odhcpd: Replace strerror(errno) with %m format
[project/odhcpd.git] / src / dhcpv4.c
index a4b6030..db5f138 100644 (file)
 #include "dhcpv4.h"
 #include "dhcpv6.h"
 
+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 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_stop(struct dhcpv4_assignment *a);
@@ -48,6 +50,7 @@ static struct dhcpv4_assignment* dhcpv4_lease(struct interface *iface,
                uint32_t *leasetime, const char *hostname, const size_t hostname_len,
                const bool accept_fr_nonce, bool *incl_fr_opt, uint32_t *fr_serverid);
 
+static struct netevent_handler dhcpv4_netevent_handler = { .cb = dhcpv4_netevent_cb, };
 static struct uloop_timeout valid_until_timeout = {.cb = valid_until_cb};
 static uint32_t serial = 0;
 
@@ -58,13 +61,15 @@ struct odhcpd_ref_ip {
 };
 
 /* Create socket and register events */
-int init_dhcpv4(void)
+int dhcpv4_init(void)
 {
        uloop_timeout_set(&valid_until_timeout, 1000);
+       netlink_add_netevent_handler(&dhcpv4_netevent_handler);
+
        return 0;
 }
 
-int setup_dhcpv4_interface(struct interface *iface, bool enable)
+int dhcpv4_setup_interface(struct interface *iface, bool enable)
 {
        if (iface->dhcpv4_event.uloop.fd > 0) {
                uloop_fd_delete(&iface->dhcpv4_event.uloop);
@@ -81,8 +86,7 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable)
 
                int sock = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
                if (sock < 0) {
-                       syslog(LOG_ERR, "Failed to create DHCPv4 server socket: %s",
-                                       strerror(errno));
+                       syslog(LOG_ERR, "Failed to create DHCPv4 server socket: %m");
                        return -1;
                }
 
@@ -105,8 +109,7 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable)
                                        {INADDR_ANY}, {0}};
 
                if (bind(sock, (struct sockaddr*)&bind_addr, sizeof(bind_addr))) {
-                       syslog(LOG_ERR, "Failed to open DHCPv4 server socket: %s",
-                                       strerror(errno));
+                       syslog(LOG_ERR, "Failed to open DHCPv4 server socket: %m");
                        return -1;
                }
 
@@ -126,6 +129,26 @@ int setup_dhcpv4_interface(struct interface *iface, bool enable)
        return 0;
 }
 
+
+static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info)
+{
+       struct interface *iface = info->iface;
+
+       if (!iface || iface->dhcpv4 == MODE_DISABLED)
+               return;
+
+       switch (event) {
+       case NETEV_IFINDEX_CHANGE:
+               dhcpv4_setup_interface(iface, true);
+               break;
+       case NETEV_ADDRLIST_CHANGE:
+               handle_addrlist_change(iface);
+               break;
+       default:
+               break;
+       }
+}
+
 static struct dhcpv4_assignment *find_assignment_by_hwaddr(struct interface *iface, const uint8_t *hwaddr)
 {
        struct dhcpv4_assignment *a;
@@ -293,7 +316,7 @@ static void decr_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct interface *iface)
        struct odhcpd_ref_ip *ip = *ptr;
 
        if (--ip->ref_cnt == 0) {
-               odhcpd_setup_addr(&ip->addr, iface, false, false);
+               netlink_setup_addr(&ip->addr, iface->ifindex, false, false);
 
                list_del(&ip->head);
                free(ip);
@@ -344,17 +367,14 @@ static void valid_until_cb(struct uloop_timeout *event)
        uloop_timeout_set(event, 1000);
 }
 
-void dhcpv4_addr_update(struct interface *iface)
+static void handle_addrlist_change(struct interface *iface)
 {
-       if (iface->dhcpv4 == MODE_DISABLED)
-               return;
-
        struct odhcpd_ipaddr ip;
        struct odhcpd_ref_ip *a;
        struct dhcpv4_assignment *c;
        uint32_t mask = iface->dhcpv4_mask.s_addr;
 
-       memset(&ip, sizeof(ip), 0);
+       memset(&ip, 0, sizeof(ip));
        ip.addr.in = iface->dhcpv4_local;
        ip.prefix = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask);
        ip.broadcast = iface->dhcpv4_bcast;
@@ -373,7 +393,7 @@ void dhcpv4_addr_update(struct interface *iface)
 
        a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head);
 
-       if (odhcpd_setup_addr(&a->addr, iface, false, true)) {
+       if (netlink_setup_addr(&a->addr, iface->ifindex, false, true)) {
                syslog(LOG_ERR, "Failed to add ip address");
                return;
        }
@@ -701,6 +721,11 @@ static void handle_dhcpv4(void *addr, void *data, size_t len,
                        req->chaddr[0],req->chaddr[1],req->chaddr[2],
                        req->chaddr[3],req->chaddr[4],req->chaddr[5]);
 
+#ifdef WITH_UBUS
+       if (reqmsg == DHCPV4_MSG_RELEASE)
+               ubus_bcast_dhcp_event("dhcp.release", req->chaddr, req->hlen,
+                                       &req->ciaddr, hostname, iface->ifname);
+#endif
        if (reqmsg == DHCPV4_MSG_DECLINE || reqmsg == DHCPV4_MSG_RELEASE)
                return;
 
@@ -850,6 +875,12 @@ static void handle_dhcpv4(void *addr, void *data, size_t len,
 
        sendto(sock, &reply, sizeof(reply), MSG_DONTWAIT,
                        (struct sockaddr*)&dest, sizeof(dest));
+
+#ifdef WITH_UBUS
+       if (msg == DHCPV4_MSG_ACK)
+               ubus_bcast_dhcp_event("dhcp.ack", req->chaddr, req->hlen, &reply.yiaddr,
+                                       hostname, iface->ifname);
+#endif
 }
 
 static bool dhcpv4_assign(struct interface *iface,