treewide: align syslog tracing
[oweals/odhcpd.git] / src / dhcpv4.c
index b803359360618ccd103b2bc1c92128a4f7e5c43c..4a74b8a983b300894b179f2cea1b37e4fddeb60e 100644 (file)
 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info);
 static int setup_dhcpv4_addresses(struct interface *iface);
 static void update_static_assignments(struct interface *iface);
+static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr);
 static void valid_until_cb(struct uloop_timeout *event);
 static void handle_addrlist_change(struct interface *iface);
 static void free_dhcpv4_assignment(struct dhcpv4_assignment *a);
 static void dhcpv4_fr_start(struct dhcpv4_assignment *a);
+static void dhcpv4_fr_rand_delay(struct dhcpv4_assignment *a);
 static void dhcpv4_fr_stop(struct dhcpv4_assignment *a);
 static void handle_dhcpv4(void *addr, void *data, size_t len,
                struct interface *iface, void *dest_addr);
@@ -113,7 +115,7 @@ int dhcpv4_setup_interface(struct interface *iface, bool enable)
                }
 
                if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_PKTINFO,
-                                       &val, sizeof(val))) {
+                                       &val, sizeof(val)) < 0) {
                        syslog(LOG_ERR, "setsockopt(IP_PKTINFO): %m");
                        ret = -1;
                        goto out;
@@ -121,7 +123,7 @@ int dhcpv4_setup_interface(struct interface *iface, bool enable)
 
                val = IPTOS_PREC_INTERNETCONTROL;
                if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_TOS,
-                                       &val, sizeof(val))) {
+                                       &val, sizeof(val)) < 0) {
                        syslog(LOG_ERR, "setsockopt(IP_TOS): %m");
                        ret = -1;
                        goto out;
@@ -129,20 +131,21 @@ int dhcpv4_setup_interface(struct interface *iface, bool enable)
 
                val = IP_PMTUDISC_DONT;
                if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_MTU_DISCOVER,
-                                       &val, sizeof(val))) {
+                                       &val, sizeof(val)) < 0) {
                        syslog(LOG_ERR, "setsockopt(IP_MTU_DISCOVER): %m");
                        ret = -1;
                        goto out;
                }
 
                if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE,
-                                       iface->ifname, strlen(iface->ifname))) {
+                                       iface->ifname, strlen(iface->ifname)) < 0) {
                        syslog(LOG_ERR, "setsockopt(SO_BINDTODEVICE): %m");
                        ret = -1;
                        goto out;
                }
 
-               if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr*)&bind_addr, sizeof(bind_addr))) {
+               if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr*)&bind_addr,
+                                       sizeof(bind_addr)) < 0) {
                        syslog(LOG_ERR, "bind(): %m");
                        ret = -1;
                        goto out;
@@ -226,12 +229,12 @@ static int setup_dhcpv4_addresses(struct interface *iface)
        if (iface->dhcpv4_start.s_addr & htonl(0xffff0000) ||
            iface->dhcpv4_end.s_addr & htonl(0xffff0000) ||
            ntohl(iface->dhcpv4_start.s_addr) > ntohl(iface->dhcpv4_end.s_addr)) {
-               syslog(LOG_ERR, "invalid DHCP range for %s", iface->name);
+               syslog(LOG_ERR, "Invalid DHCP range for %s", iface->name);
                return -1;
        }
 
        if (!iface->addr4_len) {
-               syslog(LOG_WARNING, "no network(s) available on %s", iface->name);
+               syslog(LOG_WARNING, "No network(s) available on %s", iface->name);
                return -1;
        }
 
@@ -242,6 +245,9 @@ static int setup_dhcpv4_addresses(struct interface *iface)
                struct in_addr *addr = &iface->addr4[i].addr.in;
                struct in_addr mask;
 
+               if (addr_is_fr_ip(iface, addr))
+                       continue;
+
                odhcpd_bitlen2netmask(false, iface->addr4[i].prefix, &mask);
                if ((start & ntohl(~mask.s_addr)) == start &&
                            (end & ntohl(~mask.s_addr)) == end) {
@@ -258,7 +264,7 @@ static int setup_dhcpv4_addresses(struct interface *iface)
 
        /* Don't allocate IP range for subnets bigger than 28 */
        if (iface->addr4[0].prefix > 28) {
-               syslog(LOG_WARNING, "auto allocation of DHCP range fails on %s", iface->name);
+               syslog(LOG_WARNING, "Auto allocation of DHCP range fails on %s", iface->name);
                return -1;
        }
 
@@ -315,8 +321,7 @@ static void update_static_assignments(struct interface *iface)
                        /* Construct entry */
                        a = calloc(1, sizeof(*a));
                        if (!a) {
-                               syslog(LOG_ERR, "Calloc failed for static lease on interface %s",
-                                       iface->ifname);
+                               syslog(LOG_ERR, "Calloc failed for static lease on %s", iface->name);
                                continue;
                        }
                        memcpy(a->hwaddr, lease->mac.ether_addr_octet, sizeof(a->hwaddr));
@@ -368,6 +373,18 @@ static void decr_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct interface *iface)
        *ptr = NULL;
 }
 
+static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr)
+{
+       struct odhcpd_ref_ip *p;
+
+       list_for_each_entry(p, &iface->dhcpv4_fr_ips, head) {
+               if (addr->s_addr == p->addr.addr.in.s_addr)
+                       return true;
+       }
+
+       return false;
+}
+
 static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *addr,
                                uint32_t mask)
 {
@@ -437,14 +454,14 @@ static void handle_addrlist_change(struct interface *iface)
        a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head);
 
        if (netlink_setup_addr(&a->addr, iface->ifindex, false, true)) {
-               syslog(LOG_ERR, "Failed to add ip address");
+               syslog(LOG_ERR, "Failed to add ip address on %s", iface->name);
                return;
        }
 
        list_for_each_entry(c, &iface->dhcpv4_assignments, head) {
                if ((c->flags & OAF_BOUND) && c->fr_ip && !c->fr_cnt) {
                        if (c->accept_fr_nonce || iface->dhcpv4_forcereconf)
-                               dhcpv4_fr_start(c);
+                               dhcpv4_fr_rand_delay(c);
                        else
                                dhcpv4_fr_stop(c);
                }
@@ -583,14 +600,13 @@ static void dhcpv4_fr_send(struct dhcpv4_assignment *a)
        dest.sin_port = htons(DHCPV4_CLIENT_PORT);
        dest.sin_addr.s_addr = a->addr;
 
-       syslog(LOG_WARNING, "sending %s to %02x:%02x:%02x:%02x:%02x:%02x - %s",
-                       dhcpv4_msg_to_string(msg),
-                       a->hwaddr[0], a->hwaddr[1], a->hwaddr[2],
-                       a->hwaddr[3], a->hwaddr[4], a->hwaddr[5],
-                       inet_ntoa(dest.sin_addr));
-
-       sendto(iface->dhcpv4_event.uloop.fd, &fr_msg, sizeof(fr_msg),
-                       MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest));
+       if (sendto(iface->dhcpv4_event.uloop.fd, &fr_msg, sizeof(fr_msg),
+                       MSG_DONTWAIT, (struct sockaddr*)&dest, sizeof(dest)) < 0)
+               syslog(LOG_ERR, "Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(msg),
+                       odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr));
+       else
+               syslog(LOG_WARNING, "Sent %s to %s - %s", dhcpv4_msg_to_string(msg),
+                       odhcpd_print_mac(a->hwaddr, sizeof(a->hwaddr)), inet_ntoa(dest.sin_addr));
 }
 
 static void dhcpv4_fr_timer(struct uloop_timeout *event)
@@ -614,6 +630,28 @@ static void dhcpv4_fr_start(struct dhcpv4_assignment *a)
        dhcpv4_fr_send(a);
 }
 
+static void dhcpv4_fr_delay_timer(struct uloop_timeout *event)
+{
+       struct dhcpv4_assignment *a = container_of(event, struct dhcpv4_assignment, fr_timer);
+       struct interface *iface = a->iface;
+
+       (iface->dhcpv4_event.uloop.fd == -1 ? dhcpv4_fr_rand_delay(a) : dhcpv4_fr_start(a));
+}
+
+static void dhcpv4_fr_rand_delay(struct dhcpv4_assignment *a)
+{
+#define MIN_DELAY   500
+#define MAX_FUZZ    500
+       int msecs;
+
+       odhcpd_urandom(&msecs, sizeof(msecs));
+
+       msecs = labs(msecs)%MAX_FUZZ + MIN_DELAY;
+
+       uloop_timeout_set(&a->fr_timer, msecs);
+       a->fr_timer.cb = dhcpv4_fr_delay_timer;
+}
+
 static void dhcpv4_fr_stop(struct dhcpv4_assignment *a)
 {
        uloop_timeout_cancel(&a->fr_timer);
@@ -622,7 +660,7 @@ static void dhcpv4_fr_stop(struct dhcpv4_assignment *a)
        a->fr_timer.cb = NULL;
 }
 
-// Handler for DHCPv4 messages
+/* Handler for DHCPv4 messages */
 static void handle_dhcpv4(void *addr, void *data, size_t len,
                struct interface *iface, _unused void *dest_addr)
 {
@@ -635,7 +673,7 @@ static void handle_dhcpv4(void *addr, void *data, size_t len,
                return;
 
 
-       syslog(LOG_NOTICE, "Got DHCPv4 request");
+       syslog(LOG_NOTICE, "Got DHCPv4 request on %s", iface->name);
 
        if (!iface->dhcpv4_start_ip.s_addr && !iface->dhcpv4_end_ip.s_addr) {
                syslog(LOG_WARNING, "No DHCP range available on %s", iface->name);
@@ -761,10 +799,8 @@ static void handle_dhcpv4(void *addr, void *data, size_t len,
                        req->ciaddr.s_addr = INADDR_ANY;
        }
 
-       syslog(LOG_WARNING, "received %s from %02x:%02x:%02x:%02x:%02x:%02x",
-                       dhcpv4_msg_to_string(reqmsg),
-                       req->chaddr[0],req->chaddr[1],req->chaddr[2],
-                       req->chaddr[3],req->chaddr[4],req->chaddr[5]);
+       syslog(LOG_WARNING, "Received %s from %s on %s", dhcpv4_msg_to_string(reqmsg),
+                       odhcpd_print_mac(req->chaddr, req->hlen), iface->name);
 
 #ifdef WITH_UBUS
        if (reqmsg == DHCPV4_MSG_RELEASE)
@@ -891,37 +927,36 @@ static void handle_dhcpv4(void *addr, void *data, size_t len,
                dest.sin_addr.s_addr = INADDR_BROADCAST;
                dest.sin_port = htons(DHCPV4_CLIENT_PORT);
        } else {
+               struct arpreq arp = {.arp_flags = ATF_COM};
+
                /*
                 * send reply to the newly (in this proccess) allocated IP
                 */
                dest.sin_addr = reply.yiaddr;
                dest.sin_port = htons(DHCPV4_CLIENT_PORT);
 
-               struct arpreq arp = {.arp_flags = ATF_COM};
                memcpy(arp.arp_ha.sa_data, req->chaddr, 6);
                memcpy(&arp.arp_pa, &dest, sizeof(arp.arp_pa));
                memcpy(arp.arp_dev, iface->ifname, sizeof(arp.arp_dev));
-               ioctl(sock, SIOCSARP, &arp);
+
+               if (ioctl(sock, SIOCSARP, &arp) < 0)
+                       syslog(LOG_ERR, "ioctl(SIOCSARP): %m");
        }
 
-       if (dest.sin_addr.s_addr == INADDR_BROADCAST)
-               /* reply goes to IP broadcast -> MAC broadcast */
-               syslog(LOG_WARNING, "sending %s to ff:ff:ff:ff:ff:ff - %s",
-                               dhcpv4_msg_to_string(msg),
-                               inet_ntoa(dest.sin_addr));
+       if (sendto(sock, &reply, sizeof(reply), MSG_DONTWAIT,
+                       (struct sockaddr*)&dest, sizeof(dest)) < 0)
+               syslog(LOG_ERR, "Failed to send %s to %s - %s: %m",
+                       dhcpv4_msg_to_string(msg),
+                       dest.sin_addr.s_addr == INADDR_BROADCAST ?
+                       "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen),
+                       inet_ntoa(dest.sin_addr));
        else
-               /*
-                * reply is send directly to IP,
-                * MAC is assumed to be the same as the request
-                */
-               syslog(LOG_WARNING, "sending %s to %02x:%02x:%02x:%02x:%02x:%02x - %s",
-                               dhcpv4_msg_to_string(msg),
-                               req->chaddr[0],req->chaddr[1],req->chaddr[2],
-                               req->chaddr[3],req->chaddr[4],req->chaddr[5],
-                               inet_ntoa(dest.sin_addr));
+               syslog(LOG_ERR, "Sent %s to %s - %s",
+                       dhcpv4_msg_to_string(msg),
+                       dest.sin_addr.s_addr == INADDR_BROADCAST ?
+                       "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen),
+                       inet_ntoa(dest.sin_addr));
 
-       sendto(sock, &reply, sizeof(reply), MSG_DONTWAIT,
-                       (struct sockaddr*)&dest, sizeof(dest));
 
 #ifdef WITH_UBUS
        if (msg == DHCPV4_MSG_ACK)
@@ -937,11 +972,11 @@ static bool dhcpv4_assign(struct interface *iface,
        uint32_t end = ntohl(iface->dhcpv4_end_ip.s_addr);
        uint32_t count = end - start + 1;
 
-       // try to assign the IP the client asked for
+       /* try to assign the IP the client asked for */
        if (start <= ntohl(raddr) && ntohl(raddr) <= end &&
                        !find_assignment_by_addr(iface, raddr)) {
                assign->addr = raddr;
-               syslog(LOG_INFO, "assigning the IP the client asked for: %u.%u.%u.%u",
+               syslog(LOG_INFO, "Assigning the IP the client asked for: %u.%u.%u.%u",
                                ((uint8_t *)&assign->addr)[0],
                                ((uint8_t *)&assign->addr)[1],
                                ((uint8_t *)&assign->addr)[2],
@@ -949,10 +984,10 @@ static bool dhcpv4_assign(struct interface *iface,
                return true;
        }
 
-       // Seed RNG with checksum of hwaddress
+       /* Seed RNG with checksum of hwaddress */
        uint32_t seed = 0;
        for (size_t i = 0; i < sizeof(assign->hwaddr); ++i) {
-               // Knuth's multiplicative method
+               /* Knuth's multiplicative method */
                uint8_t o = assign->hwaddr[i];
                seed += (o*2654435761) % UINT32_MAX;
        }
@@ -963,7 +998,7 @@ static bool dhcpv4_assign(struct interface *iface,
 
        if (list_empty(&iface->dhcpv4_assignments)) {
                assign->addr = htonl(try);
-               syslog(LOG_INFO, "assigning mapped IP (empty list): %u.%u.%u.%u",
+               syslog(LOG_INFO, "Assigning mapped IP (empty list): %u.%u.%u.%u",
                                ((uint8_t *)&assign->addr)[0],
                                ((uint8_t *)&assign->addr)[1],
                                ((uint8_t *)&assign->addr)[2],
@@ -975,7 +1010,7 @@ static bool dhcpv4_assign(struct interface *iface,
                if (!find_assignment_by_addr(iface, htonl(try))) {
                        /* test was successful: IP address is not assigned, assign it */
                        assign->addr = htonl(try);
-                       syslog(LOG_DEBUG, "assigning mapped IP: %u.%u.%u.%u (try %u of %u)",
+                       syslog(LOG_DEBUG, "Assigning mapped IP: %u.%u.%u.%u (try %u of %u)",
                                        ((uint8_t *)&assign->addr)[0],
                                        ((uint8_t *)&assign->addr)[1],
                                        ((uint8_t *)&assign->addr)[2],
@@ -986,7 +1021,7 @@ static bool dhcpv4_assign(struct interface *iface,
                try = (((try - start) + 1) % count) + start;
        }
 
-       syslog(LOG_WARNING, "can't assign any IP address -> address space is full");
+       syslog(LOG_WARNING, "Can't assign any IP address -> address space is full");
        return false;
 }
 
@@ -1059,6 +1094,11 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface,
                                        if (a->hostname) {
                                                memcpy(a->hostname, hostname, hostname_len);
                                                a->hostname[hostname_len] = 0;
+
+                                               if (odhcpd_valid_hostname(a->hostname))
+                                                       a->flags &= ~OAF_BROKEN_HOSTNAME;
+                                               else
+                                                       a->flags |= OAF_BROKEN_HOSTNAME;
                                        }
                                }