sd-dhcp-server.c revision 8de4a226c71ef43e652274b33b5d19211a44ac7b
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering This file is part of systemd.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering Copyright (C) 2013 Intel Corporation. All rights reserved.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering Copyright (C) 2014 Tom Gundersen
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering systemd is free software; you can redistribute it and/or modify it
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering under the terms of the GNU Lesser General Public License as published by
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering the Free Software Foundation; either version 2.1 of the License, or
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering (at your option) any later version.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering systemd is distributed in the hope that it will be useful, but
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering WITHOUT ANY WARRANTY; without even the implied warranty of
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering Lesser General Public License for more details.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering You should have received a copy of the GNU Lesser General Public License
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering along with systemd; If not, see <http://www.gnu.org/licenses/>.
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringsd_dhcp_server *sd_dhcp_server_ref(sd_dhcp_server *server) {
3f6fd1ba65f962702753c4ad284b588e59689a23Lennart Poettering assert_se(REFCNT_INC(server->n_ref) >= 2);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringsd_dhcp_server *sd_dhcp_server_unref(sd_dhcp_server *server) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (server && REFCNT_DEC(server->n_ref) <= 0) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint sd_dhcp_server_new(sd_dhcp_server **ret, int ifindex) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering _cleanup_dhcp_server_unref_ sd_dhcp_server *server = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint sd_dhcp_server_attach_event(sd_dhcp_server *server, sd_event *event, int priority) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint sd_dhcp_server_detach_event(sd_dhcp_server *server) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering server->event = sd_event_unref(server->event);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringsd_event *sd_dhcp_server_get_event(sd_dhcp_server *server) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint sd_dhcp_server_stop(sd_dhcp_server *server) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering sd_event_source_unref(server->receive_message);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering server->fd_raw = safe_close(server->fd_raw);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int parse_request(uint8_t code, uint8_t len, const uint8_t *option,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering req->max_optlen = be16toh(*(be16_t*)option) -
4afd3348c7506dd1d36305b7bcb9feb8952b9d6bLennart Poetteringstatic void dhcp_request_free(DHCPRequest *req) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart PoetteringDEFINE_TRIVIAL_CLEANUP_FUNC(DHCPRequest*, dhcp_request_free);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering#define _cleanup_dhcp_request_free_ _cleanup_(dhcp_request_freep)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int ensure_sane_request(DHCPRequest *req, DHCPMessage *message) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* set client id based on mac address if client did not send an explicit one */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering memcpy(&req->client_id.data[1], &message->chaddr, ETH_ALEN);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering if (req->max_optlen < DHCP_MIN_OPTIONS_SIZE)
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering _cleanup_dhcp_request_free_ DHCPRequest *req = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering type = dhcp_option_parse(message, length, parse_request, req);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* this only fails on critical errors */
72c0a2c255b172ebbb2a2b7dab7c9aec4c9582d9Lennart Poettering log_dhcp_server(server, "received message of type %d", type);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringstatic int server_receive_message(sd_event_source *s, int fd,
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering _cleanup_free_ DHCPMessage *message = NULL;
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))];
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering else if ((size_t)len < sizeof(DHCPMessage))
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering cmsg->cmsg_len == CMSG_LEN(sizeof(struct in_pktinfo))) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering struct in_pktinfo *info = (struct in_pktinfo*)CMSG_DATA(cmsg);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering /* TODO figure out if this can be done as a filter on the socket, like for IPv6 */
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering return dhcp_server_handle_message(server, message, (size_t)len);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poetteringint sd_dhcp_server_start(sd_dhcp_server *server) {
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert_return(!server->receive_message, -EBUSY);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering assert_return(server->fd_raw == -1, -EBUSY);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = socket(AF_PACKET, SOCK_DGRAM | SOCK_NONBLOCK, 0);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = dhcp_network_bind_udp_socket(INADDR_ANY, DHCP_PORT_SERVER);
b6e676ce41508e2aeea22202fc8f234126177f52Lennart Poettering r = sd_event_add_io(server->event, &server->receive_message,