• source navigation  • diff markup  • identifier search  • freetext search  • 

Sources/odhcpd/src/dhcpv4.c

  1 /**
  2  * Copyright (C) 2012-2013 Steven Barth <steven@midlink.org>
  3  * Copyright (C) 2016 Hans Dedecker <dedeckeh@gmail.com>
  4  *
  5  * This program is free software; you can redistribute it and/or modify
  6  * it under the terms of the GNU General Public License v2 as published by
  7  * the Free Software Foundation.
  8  *
  9  * This program is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12  * GNU General Public License for more details.
 13  *
 14  *
 15  */
 16 
 17 #include <time.h>
 18 #include <errno.h>
 19 #include <fcntl.h>
 20 #include <unistd.h>
 21 #include <stddef.h>
 22 #include <stdlib.h>
 23 #include <resolv.h>
 24 #include <limits.h>
 25 #include <alloca.h>
 26 #include <net/if.h>
 27 #include <net/if_arp.h>
 28 #include <netinet/ip.h>
 29 #include <sys/ioctl.h>
 30 #include <sys/timerfd.h>
 31 #include <arpa/inet.h>
 32 
 33 #include <libubox/md5.h>
 34 
 35 #include "odhcpd.h"
 36 #include "dhcpv4.h"
 37 #include "dhcpv6.h"
 38 
 39 #define MAX_PREFIX_LEN 28
 40 
 41 static uint32_t serial = 0;
 42 
 43 struct odhcpd_ref_ip {
 44         struct list_head head;
 45         int ref_cnt;
 46         struct odhcpd_ipaddr addr;
 47 };
 48 
 49 static void inc_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct odhcpd_ref_ip *ip)
 50 {
 51         *ptr = ip;
 52         ip->ref_cnt++;
 53 }
 54 
 55 static void decr_ref_cnt_ip(struct odhcpd_ref_ip **ptr, struct interface *iface)
 56 {
 57         struct odhcpd_ref_ip *ip = *ptr;
 58 
 59         if (--ip->ref_cnt == 0) {
 60                 netlink_setup_addr(&ip->addr, iface->ifindex, false, false);
 61 
 62                 list_del(&ip->head);
 63                 free(ip);
 64         }
 65 
 66         *ptr = NULL;
 67 }
 68 
 69 static bool addr_is_fr_ip(struct interface *iface, struct in_addr *addr)
 70 {
 71         struct odhcpd_ref_ip *p;
 72 
 73         list_for_each_entry(p, &iface->dhcpv4_fr_ips, head) {
 74                 if (addr->s_addr == p->addr.addr.in.s_addr)
 75                         return true;
 76         }
 77 
 78         return false;
 79 }
 80 
 81 static bool leases_require_fr(struct interface *iface, struct odhcpd_ipaddr *addr,
 82                               uint32_t mask)
 83 {
 84         struct dhcpv4_lease *lease = NULL;
 85         struct odhcpd_ref_ip *fr_ip = NULL;
 86 
 87         list_for_each_entry(lease, &iface->dhcpv4_leases, head) {
 88                 if ((lease->accept_fr_nonce || iface->dhcpv4_forcereconf) &&
 89                     !lease->fr_ip &&
 90                     ((lease->addr & mask) == (addr->addr.in.s_addr & mask))) {
 91                         if (!fr_ip) {
 92                                 fr_ip = calloc(1, sizeof(*fr_ip));
 93                                 if (!fr_ip)
 94                                         break;
 95 
 96                                 list_add(&fr_ip->head, &iface->dhcpv4_fr_ips);
 97                                 fr_ip->addr = *addr;
 98                         }
 99                         inc_ref_cnt_ip(&lease->fr_ip, fr_ip);
100                 }
101         }
102 
103         return fr_ip ? true : false;
104 }
105 
106 static const char *dhcpv4_msg_to_string(uint8_t req_msg)
107 {
108         static const char *dhcpv4_msg_names[] = {
109                 [DHCPV4_MSG_DISCOVER]           = "DHCPV4_MSG_DISCOVER",
110                 [DHCPV4_MSG_OFFER]              = "DHCPV4_MSG_OFFER",
111                 [DHCPV4_MSG_REQUEST]            = "DHCPV4_MSG_REQUEST",
112                 [DHCPV4_MSG_DECLINE]            = "DHCPV4_MSG_DECLINE",
113                 [DHCPV4_MSG_ACK]                = "DHCPV4_MSG_ACK",
114                 [DHCPV4_MSG_NAK]                = "DHCPV4_MSG_NAK",
115                 [DHCPV4_MSG_RELEASE]            = "DHCPV4_MSG_RELEASE",
116                 [DHCPV4_MSG_INFORM]             = "DHCPV4_MSG_INFORM",
117                 [DHCPV4_MSG_FORCERENEW]         = "DHCPV4_MSG_FORCERENEW",
118                 [DHCPV4_MSG_LEASEQUERY]         = "DHCPV4_MSG_LEASEQUERY",
119                 [DHCPV4_MSG_LEASEUNASSIGNED]    = "DHCPV4_MSG_LEASEUNASSIGNED",
120                 [DHCPV4_MSG_LEASEUNKNOWN]       = "DHCPV4_MSG_LEASEUNKNOWN",
121                 [DHCPV4_MSG_LEASEACTIVE]        = "DHCPV4_MSG_LEASEACTIVE",
122                 [DHCPV4_MSG_BULKLEASEQUERY]     = "DHCPV4_MSG_BULKLEASEQUERY",
123                 [DHCPV4_MSG_LEASEQUERYDONE]     = "DHCPV4_MSG_LEASEQUERYDONE",
124                 [DHCPV4_MSG_ACTIVELEASEQUERY]   = "DHCPV4_MSG_ACTIVELEASEQUERY",
125                 [DHCPV4_MSG_LEASEQUERYSTATUS]   = "DHCPV4_MSG_LEASEQUERYSTATUS",
126                 [DHCPV4_MSG_TLS]                = "DHCPV4_MSG_TLS",
127         };
128 
129         if (req_msg >= ARRAY_SIZE(dhcpv4_msg_names))
130                 return "UNKNOWN";
131         return dhcpv4_msg_names[req_msg];
132 }
133 
134 static ssize_t dhcpv4_send_reply(struct iovec *iov, size_t iov_len,
135                                  struct sockaddr *dest, socklen_t dest_len,
136                                  void *opaque)
137 {
138         int *sock = opaque;
139         struct msghdr msg = {
140                 .msg_name = dest,
141                 .msg_namelen = dest_len,
142                 .msg_iov = iov,
143                 .msg_iovlen = iov_len,
144         };
145 
146         return sendmsg(*sock, &msg, MSG_DONTWAIT);
147 }
148 
149 static void dhcpv4_add_padding(struct iovec *iov, size_t iovlen)
150 {
151         // Theoretical max padding = vendor-specific area, RFC951, ยง3
152         static uint8_t padding[64] = { 0 };
153         size_t len = 0;
154 
155         if (!iov || !iovlen)
156                 return;
157 
158         iov[iovlen - 1].iov_base = padding;
159         iov[iovlen - 1].iov_len = 0;
160 
161         for (size_t i = 0; i < iovlen; i++)
162                 len += iov[i].iov_len;
163 
164         if (len < DHCPV4_MIN_PACKET_SIZE)
165                 iov[iovlen - 1].iov_len = DHCPV4_MIN_PACKET_SIZE - len;
166 }
167 
168 enum {
169         IOV_FR_HEADER = 0,
170         IOV_FR_MESSAGE,
171         IOV_FR_AUTH,
172         IOV_FR_AUTH_BODY,
173         IOV_FR_SERVERID,
174         IOV_FR_END,
175         IOV_FR_PADDING,
176         IOV_FR_TOTAL
177 };
178 
179 static void dhcpv4_fr_send(struct dhcpv4_lease *lease)
180 {
181         struct dhcpv4_message fr = {
182                 .op = DHCPV4_OP_BOOTREPLY,
183                 .htype = ARPHRD_ETHER,
184                 .hlen = ETH_ALEN,
185                 .hops = 0,
186                 .xid = 0,
187                 .secs = 0,
188                 .flags = 0,
189                 .ciaddr = { INADDR_ANY },
190                 .yiaddr = { INADDR_ANY },
191                 .siaddr = { INADDR_ANY },
192                 .giaddr = { INADDR_ANY },
193                 .chaddr = { 0 },
194                 .sname = { 0 },
195                 .file = { 0 },
196                 .cookie = htonl(DHCPV4_MAGIC_COOKIE),
197         };
198         struct dhcpv4_option_u8 fr_msg = {
199                 .code = DHCPV4_OPT_MESSAGE,
200                 .len = sizeof(uint8_t),
201                 .data = DHCPV4_MSG_FORCERENEW,
202         };
203         struct dhcpv4_auth_forcerenew fr_auth_body = {
204                 .protocol = DHCPV4_AUTH_PROTO_RKAP,
205                 .algorithm = DHCPV4_AUTH_ALG_HMAC_MD5,
206                 .rdm = DHCPV4_AUTH_RDM_MONOTONIC,
207                 .type = DHCPV4_AUTH_RKAP_AI_TYPE_MD5_DIGEST,
208                 .key = { 0 },
209         };
210         struct dhcpv4_option fr_auth = {
211                 .code = DHCPV4_OPT_AUTHENTICATION,
212                 .len = sizeof(fr_auth_body),
213         };
214         struct dhcpv4_option_u32 fr_serverid = {
215                 .code = DHCPV4_OPT_SERVERID,
216                 .len = sizeof(struct in_addr),
217                 .data = lease->fr_ip->addr.addr.in.s_addr,
218         };
219         uint8_t fr_end = DHCPV4_OPT_END;
220 
221         struct iovec iov[IOV_FR_TOTAL] = {
222                 [IOV_FR_HEADER]         = { &fr, sizeof(fr) },
223                 [IOV_FR_MESSAGE]        = { &fr_msg, sizeof(fr_msg) },
224                 [IOV_FR_AUTH]           = { &fr_auth, 0 },
225                 [IOV_FR_AUTH_BODY]      = { &fr_auth_body, 0 },
226                 [IOV_FR_SERVERID]       = { &fr_serverid, 0 },
227                 [IOV_FR_END]            = { &fr_end, sizeof(fr_end) },
228                 [IOV_FR_PADDING]        = { NULL, 0 },
229         };
230 
231         struct sockaddr_in dest = {
232                 .sin_family = AF_INET,
233                 .sin_port = htons(DHCPV4_CLIENT_PORT),
234                 .sin_addr = { lease->addr },
235         };
236 
237         odhcpd_urandom(&fr.xid, sizeof(fr.xid));
238         memcpy(fr.chaddr, lease->hwaddr, fr.hlen);
239 
240         if (lease->accept_fr_nonce) {
241                 uint8_t secretbytes[64] = { 0 };
242                 md5_ctx_t md5;
243 
244                 fr_auth_body.replay[0] = htonl(time(NULL));
245                 fr_auth_body.replay[1] = htonl(++serial);
246                 iov[IOV_FR_AUTH].iov_len = sizeof(fr_auth);
247                 iov[IOV_FR_AUTH_BODY].iov_len = sizeof(fr_auth_body);
248                 dhcpv4_add_padding(iov, ARRAY_SIZE(iov));
249 
250                 memcpy(secretbytes, lease->key, sizeof(lease->key));
251                 for (size_t i = 0; i < sizeof(secretbytes); ++i)
252                         secretbytes[i] ^= 0x36;
253 
254                 md5_begin(&md5);
255                 md5_hash(secretbytes, sizeof(secretbytes), &md5);
256                 for (size_t i = 0; i < ARRAY_SIZE(iov); i++)
257                         md5_hash(iov[i].iov_base, iov[i].iov_len, &md5);
258                 md5_end(fr_auth_body.key, &md5);
259 
260                 for (size_t i = 0; i < sizeof(secretbytes); ++i) {
261                         secretbytes[i] ^= 0x36;
262                         secretbytes[i] ^= 0x5c;
263                 }
264 
265                 md5_begin(&md5);
266                 md5_hash(secretbytes, sizeof(secretbytes), &md5);
267                 md5_hash(fr_auth_body.key, sizeof(fr_auth_body.key), &md5);
268                 md5_end(fr_auth_body.key, &md5);
269         } else {
270                 iov[IOV_FR_SERVERID].iov_len = sizeof(fr_serverid);
271                 dhcpv4_add_padding(iov, ARRAY_SIZE(iov));
272         }
273 
274         if (dhcpv4_send_reply(iov, ARRAY_SIZE(iov), (struct sockaddr *)&dest, sizeof(dest),
275                               &lease->iface->dhcpv4_event.uloop.fd) < 0)
276                 error("Failed to send %s to %s - %s: %m", dhcpv4_msg_to_string(fr_msg.data),
277                       odhcpd_print_mac(lease->hwaddr, sizeof(lease->hwaddr)), inet_ntoa(dest.sin_addr));
278         else
279                 debug("Sent %s to %s - %s", dhcpv4_msg_to_string(fr_msg.data),
280                       odhcpd_print_mac(lease->hwaddr, sizeof(lease->hwaddr)), inet_ntoa(dest.sin_addr));
281 }
282 
283 static void dhcpv4_fr_stop(struct dhcpv4_lease *lease)
284 {
285         uloop_timeout_cancel(&lease->fr_timer);
286         decr_ref_cnt_ip(&lease->fr_ip, lease->iface);
287         lease->fr_cnt = 0;
288         lease->fr_timer.cb = NULL;
289 }
290 
291 static void dhcpv4_fr_timer(struct uloop_timeout *event)
292 {
293         struct dhcpv4_lease *lease = container_of(event, struct dhcpv4_lease, fr_timer);
294 
295         if (lease->fr_cnt > 0 && lease->fr_cnt < 8) {
296                 dhcpv4_fr_send(lease);
297                 uloop_timeout_set(&lease->fr_timer, 1000 << lease->fr_cnt);
298                 lease->fr_cnt++;
299         } else
300                 dhcpv4_fr_stop(lease);
301 }
302 
303 static void dhcpv4_fr_start(struct dhcpv4_lease *lease)
304 {
305         uloop_timeout_set(&lease->fr_timer, 1000 << lease->fr_cnt);
306         lease->fr_timer.cb = dhcpv4_fr_timer;
307         lease->fr_cnt++;
308 
309         dhcpv4_fr_send(lease);
310 }
311 
312 static void dhcpv4_fr_rand_delay(struct dhcpv4_lease *lease);
313 
314 static void dhcpv4_fr_delay_timer(struct uloop_timeout *event)
315 {
316         struct dhcpv4_lease *lease = container_of(event, struct dhcpv4_lease, fr_timer);
317         struct interface *iface = lease->iface;
318 
319         (iface->dhcpv4_event.uloop.fd == -1 ? dhcpv4_fr_rand_delay(lease) : dhcpv4_fr_start(lease));
320 }
321 
322 static void dhcpv4_fr_rand_delay(struct dhcpv4_lease *lease)
323 {
324         int msecs;
325 
326         odhcpd_urandom(&msecs, sizeof(msecs));
327 
328         msecs = abs(msecs) % DHCPV4_FR_MAX_FUZZ + DHCPV4_FR_MIN_DELAY;
329 
330         uloop_timeout_set(&lease->fr_timer, msecs);
331         lease->fr_timer.cb = dhcpv4_fr_delay_timer;
332 }
333 
334 void dhcpv4_free_lease(struct dhcpv4_lease *lease)
335 {
336         if (lease->fr_ip)
337                 dhcpv4_fr_stop(lease);
338 
339         list_del(&lease->head);
340         if (lease->lease_cfg)
341                 lease->lease_cfg->dhcpv4_lease = NULL;
342 
343         free(lease->hostname);
344         free(lease);
345 }
346 
347 static struct dhcpv4_lease *
348 dhcpv4_alloc_lease(struct interface *iface, const uint8_t *hwaddr, size_t hwaddr_len)
349 {
350         struct dhcpv4_lease *lease;
351 
352         if (!iface || !hwaddr || hwaddr_len == 0 || hwaddr_len > sizeof(lease->hwaddr))
353                 return NULL;
354 
355         lease = calloc(1, sizeof(*lease));
356         if (!lease)
357                 return NULL;
358 
359         INIT_LIST_HEAD(&lease->head);
360 
361         lease->hwaddr_len = hwaddr_len;
362         memcpy(lease->hwaddr, hwaddr, hwaddr_len);
363         lease->iface = iface;
364 
365         return lease;
366 }
367 
368 static bool dhcpv4_insert_lease(struct list_head *list, struct dhcpv4_lease *lease,
369                                 uint32_t addr)
370 {
371         uint32_t h_addr = ntohl(addr);
372         struct dhcpv4_lease *c;
373 
374         list_for_each_entry(c, list, head) {
375                 uint32_t c_addr = ntohl(c->addr);
376 
377                 if (c_addr == h_addr)
378                         return false;
379 
380                 if (c_addr > h_addr)
381                         break;
382         }
383 
384         /* Insert new node before c (might match list head) */
385         lease->addr = addr;
386         list_add_tail(&lease->head, &c->head);
387 
388         return true;
389 }
390 
391 static bool dhcpv4_assign(struct interface *iface, struct dhcpv4_lease *lease,
392                           uint32_t raddr)
393 {
394         uint32_t start = ntohl(iface->dhcpv4_start_ip.s_addr);
395         uint32_t end = ntohl(iface->dhcpv4_end_ip.s_addr);
396         uint32_t count = end - start + 1;
397         uint32_t seed = 0;
398         char ipv4_str[INET_ADDRSTRLEN];
399 
400         /* Preconfigured IP address by static lease */
401         if (lease->addr) {
402                 if (!dhcpv4_insert_lease(&iface->dhcpv4_leases, lease, lease->addr)) {
403                         error("The static IP address is already assigned: %s",
404                               inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str)));
405                         return false;
406                 }
407 
408                 debug("Assigned static IP address: %s",
409                       inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str)));
410                 return true;
411         }
412 
413         /* The client asked for a specific address, let's try... */
414         if (ntohl(raddr) < start || ntohl(raddr) > end) {
415                 debug("The requested IP address is outside the pool: %s",
416                       inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str)));
417         } else if (config_find_lease_cfg_by_ipaddr(raddr)) {
418                 debug("The requested IP address is statically assigned: %s",
419                       inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str)));
420         } else if (!dhcpv4_insert_lease(&iface->dhcpv4_leases, lease, raddr)) {
421                 debug("The requested IP address is already assigned: %s",
422                       inet_ntop(AF_INET, &raddr, ipv4_str, sizeof(ipv4_str)));
423         } else {
424                 debug("Assigned the requested IP address: %s",
425                       inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str)));
426                 return true;
427         }
428 
429         /* Ok, we'll have to pick an address for the client... */
430         for (size_t i = 0; i < sizeof(lease->hwaddr); ++i) {
431                 /* ...hash the hwaddr (Knuth's multiplicative method)... */
432                 uint8_t o = lease->hwaddr[i];
433                 seed += (o * 2654435761) % UINT32_MAX;
434         }
435 
436         /* ...use it to seed the RNG... */
437         srand(seed);
438 
439         /* ...and try a bunch of times to assign a randomly chosen address */
440         for (uint32_t i = 0, try = (((uint32_t)rand()) % count) + start; i < count;
441              ++i, try = (((try - start) + 1) % count) + start) {
442                 uint32_t n_try = htonl(try);
443 
444                 if (config_find_lease_cfg_by_ipaddr(n_try))
445                         continue;
446 
447                 if (dhcpv4_insert_lease(&iface->dhcpv4_leases, lease, n_try)) {
448                         debug("Assigned IP adress from pool: %s (succeeded on attempt %u of %u)",
449                               inet_ntop(AF_INET, &lease->addr, ipv4_str, sizeof(ipv4_str)),
450                               i + 1, count);
451                         return true;
452                 }
453         }
454 
455         warn("Can't assign any IP address -> address space is full");
456 
457         return false;
458 }
459 
460 static struct dhcpv4_lease *find_lease_by_hwaddr(struct interface *iface, const uint8_t *hwaddr)
461 {
462         struct dhcpv4_lease *lease;
463 
464         list_for_each_entry(lease, &iface->dhcpv4_leases, head)
465                 if (!memcmp(lease->hwaddr, hwaddr, 6))
466                         return lease;
467 
468         return NULL;
469 }
470 
471 static struct dhcpv4_lease *
472 dhcpv4_lease(struct interface *iface, enum dhcpv4_msg req_msg, const uint8_t *req_mac,
473              const uint32_t req_addr, uint32_t *req_leasetime, const char *req_hostname,
474              const size_t req_hostname_len, const bool req_accept_fr, bool *reply_incl_fr,
475              uint32_t *fr_serverid)
476 {
477         struct dhcpv4_lease *lease = find_lease_by_hwaddr(iface, req_mac);
478         struct lease_cfg *lease_cfg = config_find_lease_cfg_by_mac(req_mac);
479         time_t now = odhcpd_time();
480 
481         /*
482          * If we found a static lease cfg, but no old assignment for this
483          * hwaddr, we need to clear out any old assignments given to other
484          * hwaddrs in order to take over the IP address.
485          */
486         if (lease_cfg && !lease && (req_msg == DHCPV4_MSG_DISCOVER || req_msg == DHCPV4_MSG_REQUEST)) {
487                 if (lease_cfg->dhcpv4_lease)
488                         dhcpv4_free_lease(lease_cfg->dhcpv4_lease);
489         }
490 
491         if (lease_cfg && lease && lease->lease_cfg != lease_cfg) {
492                 dhcpv4_free_lease(lease);
493                 lease = NULL;
494         }
495 
496         if (lease && (lease->flags & OAF_BOUND) && lease->fr_ip) {
497                 *fr_serverid = lease->fr_ip->addr.addr.in.s_addr;
498                 dhcpv4_fr_stop(lease);
499         }
500 
501         switch (req_msg) {
502         case DHCPV4_MSG_RELEASE:
503                 if (!lease)
504                         return NULL;
505 
506                 ubus_bcast_dhcp_event("dhcp.release", req_mac,
507                                       (struct in_addr *)&lease->addr,
508                                       lease->hostname, iface->ifname);
509                 dhcpv4_free_lease(lease);
510                 lease = NULL;
511                 break;
512 
513         case DHCPV4_MSG_DECLINE:
514                 if (!lease)
515                         return NULL;
516 
517                 lease->flags &= ~OAF_BOUND;
518 
519                 if (!(lease->flags & OAF_STATIC) || lease->lease_cfg->ipaddr != lease->addr) {
520                         memset(lease->hwaddr, 0, sizeof(lease->hwaddr));
521                         lease->valid_until = now + 3600; /* Block address for 1h */
522                 } else
523                         lease->valid_until = now - 1;
524                 break;
525 
526         case DHCPV4_MSG_DISCOVER:
527                 _fallthrough;
528 
529         case DHCPV4_MSG_REQUEST:
530                 if (!lease && iface->no_dynamic_dhcp && !lease_cfg)
531                         return NULL;
532 
533                 /* Old lease, but with an address that is out-of-scope? */
534                 if (lease && ((lease->addr & iface->dhcpv4_mask.s_addr) !=
535                      (iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr)) &&
536                     !(lease->flags & OAF_STATIC)) {
537                         /* Try to reassign to an address that is in-scope */
538                         list_del_init(&lease->head);
539                         lease->addr = INADDR_ANY;
540                         if (!dhcpv4_assign(iface, lease, req_addr)) {
541                                 dhcpv4_free_lease(lease);
542                                 lease = NULL;
543                                 break;
544                         }
545                 }
546 
547                 if (!lease) {
548                         /* Create new binding */
549                         lease = dhcpv4_alloc_lease(iface, req_mac, ETH_ALEN);
550                         if (!lease) {
551                                 warn("Failed to allocate memory for DHCPv4 lease on interface %s", iface->ifname);
552                                 return NULL;
553                         }
554 
555                         /* static lease => infinite (0), else a placeholder */
556                         lease->valid_until = lease_cfg ? 0 : now;
557                         lease->addr = lease_cfg ? lease_cfg->ipaddr : INADDR_ANY;
558 
559                         if (!dhcpv4_assign(iface, lease, req_addr)) {
560                                 dhcpv4_free_lease(lease);
561                                 return NULL;
562                         }
563 
564                         if (lease_cfg) {
565                                 lease->flags |= OAF_STATIC;
566 
567                                 if (lease_cfg->hostname)
568                                         lease->hostname = strdup(lease_cfg->hostname);
569 
570                                 lease_cfg->dhcpv4_lease = lease;
571                                 lease->lease_cfg = lease_cfg;
572                         }
573                 }
574 
575                 /* See if we need to clamp the requested leasetime */
576                 uint32_t max_leasetime;
577                 if (lease->lease_cfg && lease->lease_cfg->leasetime)
578                         max_leasetime = lease->lease_cfg->leasetime;
579                 else
580                         max_leasetime = iface->dhcp_leasetime;
581 
582                 if ((*req_leasetime == 0) || (max_leasetime < *req_leasetime))
583                         *req_leasetime = max_leasetime;
584 
585                 if (req_msg == DHCPV4_MSG_DISCOVER) {
586                         lease->flags &= ~OAF_BOUND;
587                         *reply_incl_fr = req_accept_fr;
588                         lease->valid_until = now;
589                         break;
590                 }
591 
592                 if ((!(lease->flags & OAF_STATIC) || !lease->hostname) && req_hostname_len > 0) {
593                         char *new_name = realloc(lease->hostname, req_hostname_len + 1);
594                         if (new_name) {
595                                 lease->hostname = new_name;
596                                 memcpy(lease->hostname, req_hostname, req_hostname_len);
597                                 lease->hostname[req_hostname_len] = 0;
598 
599                                 if (odhcpd_valid_hostname(lease->hostname))
600                                         lease->flags &= ~OAF_BROKEN_HOSTNAME;
601                                 else
602                                         lease->flags |= OAF_BROKEN_HOSTNAME;
603                         }
604                 }
605 
606                 *reply_incl_fr = false;
607                 if (!(lease->flags & OAF_BOUND)) {
608                         /* This is the client's first request for the address */
609                         if (req_accept_fr) {
610                                 lease->accept_fr_nonce = true;
611                                 *reply_incl_fr = true;
612                                 odhcpd_urandom(lease->key, sizeof(lease->key));
613                         }
614                         lease->flags |= OAF_BOUND;
615                 }
616 
617                 if (*req_leasetime == UINT32_MAX)
618                         lease->valid_until = 0;
619                 else
620                         lease->valid_until = (time_t)(now + *req_leasetime);
621                 break;
622 
623         default:
624                 return NULL;
625         }
626 
627         dhcpv6_ia_write_statefile();
628         return lease;
629 }
630 
631 static void dhcpv4_set_dest_addr(const struct interface *iface,
632                                  uint8_t reply_msg,
633                                  const struct dhcpv4_message *req,
634                                  const struct dhcpv4_message *reply,
635                                  const struct sockaddr_in *src,
636                                  struct sockaddr_in *dest)
637 {
638         *dest = *src;
639 
640         //struct sockaddr_in dest = *((struct sockaddr_in*)addr);
641         if (req->giaddr.s_addr) {
642                 /*
643                  * relay agent is configured, send reply to the agent
644                  */
645                 dest->sin_addr = req->giaddr;
646                 dest->sin_port = htons(DHCPV4_SERVER_PORT);
647 
648         } else if (req->ciaddr.s_addr && req->ciaddr.s_addr != dest->sin_addr.s_addr) {
649                 /*
650                  * client has existing configuration (ciaddr is set) AND this
651                  * address is not the address it used for the dhcp message
652                  */
653                 dest->sin_addr = req->ciaddr;
654                 dest->sin_port = htons(DHCPV4_CLIENT_PORT);
655 
656         } else if (ntohs(req->flags) & DHCPV4_FLAG_BROADCAST ||
657                    req->hlen != reply->hlen || !reply->yiaddr.s_addr) {
658                 /*
659                  * client requests a broadcast reply OR we can't offer an IP
660                  */
661                 dest->sin_addr.s_addr = INADDR_BROADCAST;
662                 dest->sin_port = htons(DHCPV4_CLIENT_PORT);
663 
664         } else if (!req->ciaddr.s_addr && reply_msg == DHCPV4_MSG_NAK) {
665                 /*
666                  * client has no previous configuration -> no IP, so we need to
667                  * reply with a broadcast packet
668                  */
669                 dest->sin_addr.s_addr = INADDR_BROADCAST;
670                 dest->sin_port = htons(DHCPV4_CLIENT_PORT);
671 
672         } else {
673                 /*
674                  * send reply to the newly allocated IP
675                  */
676                 dest->sin_addr = reply->yiaddr;
677                 dest->sin_port = htons(DHCPV4_CLIENT_PORT);
678 
679                 if (!(iface->ifflags & IFF_NOARP)) {
680                         struct arpreq arp = { .arp_flags = ATF_COM };
681 
682                         memcpy(arp.arp_ha.sa_data, req->chaddr, 6);
683                         memcpy(&arp.arp_pa, dest, sizeof(arp.arp_pa));
684                         memcpy(arp.arp_dev, iface->ifname, sizeof(arp.arp_dev));
685 
686                         if (ioctl(iface->dhcpv4_event.uloop.fd, SIOCSARP, &arp) < 0)
687                                 error("ioctl(SIOCSARP): %m");
688                 }
689         }
690 }
691 
692 enum {
693         IOV_HEADER = 0,
694         IOV_MESSAGE,
695         IOV_SERVERID,
696         IOV_NETMASK,
697         IOV_ROUTER,
698         IOV_ROUTER_ADDR,
699         IOV_DNSSERVER,
700         IOV_DNSSERVER_ADDR,
701         IOV_HOSTNAME,
702         IOV_HOSTNAME_NAME,
703         IOV_MTU,
704         IOV_BROADCAST,
705         IOV_NTP,
706         IOV_NTP_ADDR,
707         IOV_LEASETIME,
708         IOV_RENEW,
709         IOV_REBIND,
710         IOV_AUTH,
711         IOV_AUTH_BODY,
712         IOV_SRCH_DOMAIN,
713         IOV_SRCH_DOMAIN_NAME,
714         IOV_FR_NONCE_CAP,
715         IOV_DNR,
716         IOV_DNR_BODY,
717         IOV_END,
718         IOV_PADDING,
719         IOV_TOTAL
720 };
721 
722 void dhcpv4_handle_msg(void *src_addr, void *data, size_t len,
723                 struct interface *iface, _unused void *our_dest_addr,
724                 send_reply_cb_t send_reply, void *opaque)
725 {
726         /* Request variables */
727         struct dhcpv4_message *req = data;
728         uint8_t req_msg = DHCPV4_MSG_REQUEST;
729         uint8_t *req_opts = NULL;
730         size_t req_opts_len = 0;
731         uint32_t req_addr = INADDR_ANY;
732         uint32_t req_leasetime = 0;
733         char *req_hostname = NULL;
734         size_t req_hostname_len = 0;
735         bool req_accept_fr = false;
736 
737         /* Reply variables */
738         struct dhcpv4_message reply = {
739                 .op = DHCPV4_OP_BOOTREPLY,
740                 .htype = ARPHRD_ETHER,
741                 .hlen = ETH_ALEN,
742                 .hops = 0,
743                 .xid = req->xid,
744                 .secs = 0,
745                 .flags = req->flags,
746                 .ciaddr = { INADDR_ANY },
747                 .yiaddr = { INADDR_ANY },
748                 .siaddr = iface->dhcpv4_local,
749                 .giaddr = req->giaddr,
750                 .chaddr = { 0 },
751                 .sname = { 0 },
752                 .file = { 0 },
753                 .cookie = htonl(DHCPV4_MAGIC_COOKIE),
754         };
755         struct dhcpv4_option_u8 reply_msg = {
756                 .code = DHCPV4_OPT_MESSAGE,
757                 .len = sizeof(uint8_t),
758                 .data = DHCPV4_MSG_ACK,
759         };
760         struct dhcpv4_option_u32 reply_serverid = {
761                 .code = DHCPV4_OPT_SERVERID,
762                 .len = sizeof(struct in_addr),
763                 .data = iface->dhcpv4_local.s_addr,
764         };
765         struct dhcpv4_option_u32 reply_netmask = {
766                 .code = DHCPV4_OPT_NETMASK,
767                 .len = sizeof(uint32_t),
768         };
769         struct dhcpv4_option reply_router = {
770                 .code = DHCPV4_OPT_ROUTER,
771         };
772         struct dhcpv4_option reply_dnsserver = {
773                 .code = DHCPV4_OPT_DNSSERVER,
774         };
775         struct dhcpv4_option reply_hostname = {
776                 .code = DHCPV4_OPT_HOSTNAME,
777         };
778         struct dhcpv4_option_u16 reply_mtu = {
779                 .code = DHCPV4_OPT_MTU,
780                 .len = sizeof(uint16_t),
781         };
782         struct dhcpv4_option_u32 reply_broadcast = {
783                 .code = DHCPV4_OPT_BROADCAST,
784                 .len = sizeof(uint32_t),
785         };
786         struct dhcpv4_option reply_ntp = {
787                 .code = DHCPV4_OPT_NTPSERVER,
788                 .len = iface->dhcpv4_ntp_cnt * sizeof(*iface->dhcpv4_ntp),
789         };
790         struct dhcpv4_option_u32 reply_leasetime = {
791                 .code = DHCPV4_OPT_LEASETIME,
792                 .len = sizeof(uint32_t),
793         };
794         struct dhcpv4_option_u32 reply_renew = {
795                 .code = DHCPV4_OPT_RENEW,
796                 .len = sizeof(uint32_t),
797         };
798         struct dhcpv4_option_u32 reply_rebind = {
799                 .code = DHCPV4_OPT_REBIND,
800                 .len = sizeof(uint32_t),
801         };
802         struct dhcpv4_auth_forcerenew reply_auth_body = {
803                 .protocol = DHCPV4_AUTH_PROTO_RKAP,
804                 .algorithm = DHCPV4_AUTH_ALG_HMAC_MD5,
805                 .rdm = DHCPV4_AUTH_RDM_MONOTONIC,
806                 .type = DHCPV4_AUTH_RKAP_AI_TYPE_KEY,
807                 .key = { 0 },
808         };
809         struct dhcpv4_option reply_auth = {
810                 .code = DHCPV4_OPT_AUTHENTICATION,
811                 .len = sizeof(reply_auth_body),
812         };
813         struct dhcpv4_option reply_srch_domain = {
814                 .code = DHCPV4_OPT_SEARCH_DOMAIN,
815         };
816         struct dhcpv4_option_u8 reply_fr_nonce_cap = {
817                 .code = DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE,
818                 .len = sizeof(uint8_t),
819                 .data = 1,
820         };
821         struct dhcpv4_option reply_dnr = {
822                 .code = DHCPV4_OPT_DNR,
823         };
824         uint8_t reply_end = DHCPV4_OPT_END;
825 
826         struct iovec iov[IOV_TOTAL] = {
827                 [IOV_HEADER]            = { &reply, sizeof(reply) },
828                 [IOV_MESSAGE]           = { &reply_msg, sizeof(reply_msg) },
829                 [IOV_SERVERID]          = { &reply_serverid, sizeof(reply_serverid) },
830                 [IOV_NETMASK]           = { &reply_netmask, 0 },
831                 [IOV_ROUTER]            = { &reply_router, 0 },
832                 [IOV_ROUTER_ADDR]       = { NULL, 0 },
833                 [IOV_DNSSERVER]         = { &reply_dnsserver, 0 },
834                 [IOV_DNSSERVER_ADDR]    = { NULL, 0 },
835                 [IOV_HOSTNAME]          = { &reply_hostname, 0 },
836                 [IOV_HOSTNAME_NAME]     = { NULL, 0 },
837                 [IOV_MTU]               = { &reply_mtu, 0 },
838                 [IOV_BROADCAST]         = { &reply_broadcast, 0 },
839                 [IOV_NTP]               = { &reply_ntp, 0 },
840                 [IOV_NTP_ADDR]          = { iface->dhcpv4_ntp, 0 },
841                 [IOV_LEASETIME]         = { &reply_leasetime, 0 },
842                 [IOV_RENEW]             = { &reply_renew, 0 },
843                 [IOV_REBIND]            = { &reply_rebind, 0 },
844                 [IOV_AUTH]              = { &reply_auth, 0 },
845                 [IOV_AUTH_BODY]         = { &reply_auth_body, 0 },
846                 [IOV_SRCH_DOMAIN]       = { &reply_srch_domain, 0 },
847                 [IOV_SRCH_DOMAIN_NAME]  = { NULL, 0 },
848                 [IOV_FR_NONCE_CAP]      = { &reply_fr_nonce_cap, 0 },
849                 [IOV_DNR]               = { &reply_dnr, 0 },
850                 [IOV_DNR_BODY]          = { NULL, 0 },
851                 [IOV_END]               = { &reply_end, sizeof(reply_end) },
852                 [IOV_PADDING]           = { NULL, 0 },
853         };
854 
855         /* Options which *might* be included in the reply unrequested */
856         uint8_t std_opts[] = {
857                 DHCPV4_OPT_NETMASK,
858                 DHCPV4_OPT_ROUTER,
859                 DHCPV4_OPT_DNSSERVER,
860                 DHCPV4_OPT_HOSTNAME,
861                 DHCPV4_OPT_MTU,
862                 DHCPV4_OPT_BROADCAST,
863                 DHCPV4_OPT_LEASETIME,
864                 DHCPV4_OPT_RENEW,
865                 DHCPV4_OPT_REBIND,
866                 DHCPV4_OPT_AUTHENTICATION,
867                 DHCPV4_OPT_SEARCH_DOMAIN,
868                 DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE,
869         };
870 
871         /* Misc */
872         struct sockaddr_in dest_addr;
873         bool reply_incl_fr = false;
874         struct dhcpv4_lease *lease = NULL;
875         uint32_t fr_serverid = INADDR_ANY;
876 
877         if (iface->dhcpv4 == MODE_DISABLED)
878                 return;
879 
880         /* FIXME: would checking the magic cookie value here break any clients? */
881 
882         if (len < offsetof(struct dhcpv4_message, options) ||
883             req->op != DHCPV4_OP_BOOTREQUEST ||
884             req->htype != ARPHRD_ETHER ||
885             req->hlen != ETH_ALEN)
886                 return;
887 
888         debug("Got DHCPv4 request on %s", iface->name);
889 
890         if (!iface->dhcpv4_start_ip.s_addr && !iface->dhcpv4_end_ip.s_addr) {
891                 warn("No DHCP range available on %s", iface->name);
892                 return;
893         }
894 
895         struct dhcpv4_option *opt;
896         dhcpv4_for_each_option(req->options, (uint8_t *)data + len, opt) {
897                 switch (opt->code) {
898                 case DHCPV4_OPT_PAD:
899                         break;
900                 case DHCPV4_OPT_HOSTNAME:
901                         req_hostname = (char *)opt->data;
902                         req_hostname_len = opt->len;
903                         break;
904                 case DHCPV4_OPT_IPADDRESS:
905                         if (opt->len == 4)
906                                 memcpy(&req_addr, opt->data, 4);
907                         break;
908                 case DHCPV4_OPT_MESSAGE:
909                         if (opt->len == 1)
910                                 req_msg = opt->data[0];
911                         break;
912                 case DHCPV4_OPT_SERVERID:
913                         if (opt->len == 4 && memcmp(opt->data, &iface->dhcpv4_local, 4))
914                                 return;
915                         break;
916                 case DHCPV4_OPT_REQOPTS:
917                         if (opt->len > 0) {
918                                 req_opts = opt->data;
919                                 req_opts_len = opt->len;
920                         }
921                         break;
922                 case DHCPV4_OPT_USER_CLASS:
923                         if (iface->filter_class) {
924                                 uint8_t *c = opt->data, *cend = &opt->data[opt->len];
925                                 for (; c < cend && &c[*c] < cend; c = &c[1 + *c]) {
926                                         size_t elen = strlen(iface->filter_class);
927                                         if (*c == elen && !memcmp(&c[1], iface->filter_class, elen))
928                                                 return; // Ignore from homenet
929                                 }
930                         }
931                         break;
932                 case DHCPV4_OPT_LEASETIME:
933                         if (opt->len == 4) {
934                                 memcpy(&req_leasetime, opt->data, 4);
935                                 req_leasetime = ntohl(req_leasetime);
936                         }
937                         break;
938                 case DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE:
939                         for (uint8_t i = 0; i < opt->len; i++) {
940                                 if (opt->data[i] == 1) {
941                                         req_accept_fr = true;
942                                         break;
943                                 }
944                         }
945                         break;
946                 }
947         }
948 
949         info("Received %s from %s on %s", dhcpv4_msg_to_string(req_msg),
950              odhcpd_print_mac(req->chaddr, req->hlen), iface->name);
951 
952         switch (req_msg) {
953         case DHCPV4_MSG_INFORM:
954                 break;
955         case DHCPV4_MSG_DECLINE:
956                 _fallthrough;
957         case DHCPV4_MSG_RELEASE:
958                 dhcpv4_lease(iface, req_msg, req->chaddr, req_addr,
959                              &req_leasetime, req_hostname, req_hostname_len,
960                              req_accept_fr, &reply_incl_fr, &fr_serverid);
961                 return;
962         case DHCPV4_MSG_DISCOVER:
963                 _fallthrough;
964         case DHCPV4_MSG_REQUEST:
965                 lease = dhcpv4_lease(iface, req_msg, req->chaddr, req_addr,
966                                      &req_leasetime, req_hostname, req_hostname_len,
967                                      req_accept_fr, &reply_incl_fr, &fr_serverid);
968                 break;
969         default:
970                 return;
971         }
972 
973         /* We are at the point where we know the client expects a reply */
974         switch (req_msg) {
975         case DHCPV4_MSG_DISCOVER:
976                 if (!lease)
977                         return;
978                 reply_msg.data = DHCPV4_MSG_OFFER;
979                 break;
980 
981         case DHCPV4_MSG_REQUEST:
982                 if (!lease) {
983                         reply_msg.data = DHCPV4_MSG_NAK;
984                         break;
985                 }
986 
987                 if ((req_addr && req_addr != lease->addr) ||
988                     (req->ciaddr.s_addr && req->ciaddr.s_addr != lease->addr)) {
989                         reply_msg.data = DHCPV4_MSG_NAK;
990                         /*
991                          * DHCP client requested an IP which we can't offer to him. Probably the
992                          * client changed the network or the network has been changed. The reply
993                          * type is set to DHCPV4_MSG_NAK, because the client should not use that IP.
994                          *
995                          * For modern devices we build an answer that includes a valid IP, like
996                          * a DHCPV4_MSG_ACK. The client will use that IP and doesn't need to
997                          * perform additional DHCP round trips.
998                          *
999                          * Buggy clients do serverid checking in nack messages; therefore set the
1000                          * serverid in nack messages triggered by a previous force renew equal to
1001                          * the server id in use at that time by the server
1002                          *
1003                          */
1004                         if (fr_serverid)
1005                                 reply_serverid.data = fr_serverid;
1006 
1007                         if (req->ciaddr.s_addr &&
1008                             ((iface->dhcpv4_start_ip.s_addr & iface->dhcpv4_mask.s_addr) !=
1009                              (req->ciaddr.s_addr & iface->dhcpv4_mask.s_addr)))
1010                                 req->ciaddr.s_addr = INADDR_ANY;
1011                 }
1012                 break;
1013         }
1014 
1015         /* Note: each option might get called more than once */
1016         for (size_t i = 0; i < sizeof(std_opts) + req_opts_len; i++) {
1017                 uint8_t opt = i < sizeof(std_opts) ? std_opts[i] : req_opts[i - sizeof(std_opts)];
1018 
1019                 switch (opt) {
1020                 case DHCPV4_OPT_NETMASK:
1021                         if (!lease)
1022                                 break;
1023                         reply_netmask.data = iface->dhcpv4_mask.s_addr;
1024                         iov[IOV_NETMASK].iov_len = sizeof(reply_netmask);
1025                         break;
1026 
1027                 case DHCPV4_OPT_ROUTER:
1028                         iov[IOV_ROUTER].iov_len = sizeof(reply_router);
1029                         if (iface->dhcpv4_router_cnt) {
1030                                 reply_router.len = iface->dhcpv4_router_cnt * sizeof(*iface->dhcpv4_router);
1031                                 iov[IOV_ROUTER_ADDR].iov_base = iface->dhcpv4_router;
1032                         } else {
1033                                 reply_router.len = sizeof(iface->dhcpv4_local);
1034                                 iov[IOV_ROUTER_ADDR].iov_base = &iface->dhcpv4_local;
1035                         }
1036                         iov[IOV_ROUTER_ADDR].iov_len = reply_router.len;
1037                         break;
1038 
1039                 case DHCPV4_OPT_DNSSERVER:
1040                         iov[IOV_DNSSERVER].iov_len = sizeof(reply_dnsserver);
1041                         if (iface->dhcpv4_dns_cnt) {
1042                                 reply_dnsserver.len = iface->dhcpv4_dns_cnt * sizeof(*iface->dhcpv4_dns);
1043                                 iov[IOV_DNSSERVER_ADDR].iov_base = iface->dhcpv4_dns;
1044                         } else {
1045                                 reply_dnsserver.len = sizeof(iface->dhcpv4_local);
1046                                 iov[IOV_DNSSERVER_ADDR].iov_base = &iface->dhcpv4_local;
1047                         }
1048                         iov[IOV_DNSSERVER_ADDR].iov_len = reply_dnsserver.len;
1049                         break;
1050 
1051                 case DHCPV4_OPT_HOSTNAME:
1052                         if (!lease || !lease->hostname)
1053                                 break;
1054                         reply_hostname.len = strlen(lease->hostname);
1055                         iov[IOV_HOSTNAME].iov_len = sizeof(reply_hostname);
1056                         iov[IOV_HOSTNAME_NAME].iov_base = lease->hostname;
1057                         iov[IOV_HOSTNAME_NAME].iov_len = reply_hostname.len;
1058                         break;
1059 
1060                 case DHCPV4_OPT_MTU:
1061                         if (iov[IOV_MTU].iov_len)
1062                                 break;
1063 
1064                         struct ifreq ifr = { .ifr_name = { 0x0, } };
1065 
1066                         strncpy(ifr.ifr_name, iface->ifname, sizeof(ifr.ifr_name) - 1);
1067                         if (!ioctl(iface->dhcpv4_event.uloop.fd, SIOCGIFMTU, &ifr)) {
1068                                 reply_mtu.data = htons(ifr.ifr_mtu);
1069                                 iov[IOV_MTU].iov_len = sizeof(reply_mtu);
1070                         }
1071                         break;
1072 
1073                 case DHCPV4_OPT_BROADCAST:
1074                         if (!lease || iface->dhcpv4_bcast.s_addr == INADDR_ANY)
1075                                 break;
1076                         reply_broadcast.data = iface->dhcpv4_bcast.s_addr;
1077                         iov[IOV_BROADCAST].iov_len = sizeof(reply_broadcast);
1078                         break;
1079 
1080                 case DHCPV4_OPT_NTPSERVER:
1081                         if (!lease)
1082                                 break;
1083                         iov[IOV_NTP].iov_len = sizeof(reply_ntp);
1084                         iov[IOV_NTP_ADDR].iov_len = iface->dhcpv4_ntp_cnt * sizeof(*iface->dhcpv4_ntp);
1085                         break;
1086 
1087                 case DHCPV4_OPT_LEASETIME:
1088                         if (!lease)
1089                                 break;
1090                         reply_leasetime.data = htonl(req_leasetime);
1091                         iov[IOV_LEASETIME].iov_len = sizeof(reply_leasetime);
1092                         break;
1093 
1094                 case DHCPV4_OPT_RENEW:
1095                         if (!lease || req_leasetime == UINT32_MAX)
1096                                 break;
1097                         reply_renew.data = htonl(500 * req_leasetime / 1000);
1098                         iov[IOV_RENEW].iov_len = sizeof(reply_renew);
1099                         break;
1100 
1101                 case DHCPV4_OPT_REBIND:
1102                         if (!lease || req_leasetime == UINT32_MAX)
1103                                 break;
1104                         reply_rebind.data = htonl(875 * req_leasetime / 1000);
1105                         iov[IOV_REBIND].iov_len = sizeof(reply_rebind);
1106                         break;
1107 
1108                 case DHCPV4_OPT_AUTHENTICATION:
1109                         if (!lease || !reply_incl_fr || req_msg != DHCPV4_MSG_REQUEST)
1110                                 break;
1111 
1112                         memcpy(reply_auth_body.key, lease->key, sizeof(reply_auth_body.key));
1113                         reply_auth_body.replay[0] = htonl(time(NULL));
1114                         reply_auth_body.replay[1] = htonl(++serial);
1115                         iov[IOV_AUTH].iov_len = sizeof(reply_auth);
1116                         iov[IOV_AUTH_BODY].iov_len = sizeof(reply_auth_body);
1117                         break;
1118 
1119                 case DHCPV4_OPT_SEARCH_DOMAIN:
1120                         if (iov[IOV_SRCH_DOMAIN].iov_len || iface->search_len > UINT8_MAX)
1121                                 break;
1122 
1123                         if (iface->search) {
1124                                 reply_srch_domain.len = iface->search_len;
1125                                 iov[IOV_SRCH_DOMAIN].iov_len = sizeof(reply_srch_domain);
1126                                 iov[IOV_SRCH_DOMAIN_NAME].iov_base = iface->search;
1127                                 iov[IOV_SRCH_DOMAIN_NAME].iov_len = iface->search_len;
1128                         } else if (!res_init() && _res.dnsrch[0] && _res.dnsrch[0][0]) {
1129                                 int len;
1130 
1131                                 if (!iov[IOV_SRCH_DOMAIN_NAME].iov_base)
1132                                         iov[IOV_SRCH_DOMAIN_NAME].iov_base = alloca(DNS_MAX_NAME_LEN);
1133 
1134                                 len = dn_comp(_res.dnsrch[0],
1135                                               iov[IOV_SRCH_DOMAIN_NAME].iov_base,
1136                                               DNS_MAX_NAME_LEN, NULL, NULL);
1137                                 if (len < 0)
1138                                         break;
1139 
1140                                 reply_srch_domain.len = len;
1141                                 iov[IOV_SRCH_DOMAIN].iov_len = sizeof(reply_srch_domain);
1142                                 iov[IOV_SRCH_DOMAIN_NAME].iov_len = len;
1143                         }
1144                         break;
1145 
1146                 case DHCPV4_OPT_FORCERENEW_NONCE_CAPABLE:
1147                         if (!lease || !reply_incl_fr || req_msg == DHCPV4_MSG_REQUEST)
1148                                 break;
1149 
1150                         iov[IOV_FR_NONCE_CAP].iov_len = sizeof(reply_fr_nonce_cap);
1151                         break;
1152 
1153                 case DHCPV4_OPT_DNR:
1154                         struct dhcpv4_dnr *dnrs;
1155                         size_t dnrs_len = 0;
1156 
1157                         if (!lease || reply_dnr.len > 0)
1158                                 break;
1159 
1160                         for (size_t i = 0; i < iface->dnr_cnt; i++) {
1161                                 struct dnr_options *dnr = &iface->dnr[i];
1162 
1163                                 if (dnr->addr4_cnt == 0 && dnr->addr6_cnt > 0)
1164                                         continue;
1165 
1166                                 dnrs_len += sizeof(struct dhcpv4_dnr);
1167                                 dnrs_len += dnr->adn_len;
1168 
1169                                 if (dnr->addr4_cnt > 0 || dnr->svc_len > 0) {
1170                                         dnrs_len += sizeof(uint8_t);
1171                                         dnrs_len += dnr->addr4_cnt * sizeof(*dnr->addr4);
1172                                         dnrs_len += dnr->svc_len;
1173                                 }
1174                         }
1175 
1176                         if (dnrs_len > UINT8_MAX)
1177                                 break;
1178 
1179                         dnrs = alloca(dnrs_len);
1180                         uint8_t *pos = (uint8_t *)dnrs;
1181 
1182                         for (size_t i = 0; i < iface->dnr_cnt; i++) {
1183                                 struct dnr_options *dnr = &iface->dnr[i];
1184                                 struct dhcpv4_dnr *d4dnr = (struct dhcpv4_dnr *)pos;
1185                                 uint16_t d4dnr_len = sizeof(uint16_t) + sizeof(uint8_t) + dnr->adn_len;
1186                                 uint16_t d4dnr_priority_be = htons(dnr->priority);
1187                                 uint16_t d4dnr_len_be;
1188 
1189                                 if (dnr->addr4_cnt == 0 && dnr->addr6_cnt > 0)
1190                                         continue;
1191 
1192                                 /* memcpy as the struct is unaligned */
1193                                 memcpy(&d4dnr->priority, &d4dnr_priority_be, sizeof(d4dnr_priority_be));
1194 
1195                                 d4dnr->adn_len = dnr->adn_len;
1196                                 pos = d4dnr->body;
1197                                 memcpy(pos, dnr->adn, dnr->adn_len);
1198                                 pos += dnr->adn_len;
1199 
1200                                 if (dnr->addr4_cnt > 0 || dnr->svc_len > 0) {
1201                                         uint8_t addr4_len = dnr->addr4_cnt * sizeof(*dnr->addr4);
1202 
1203                                         *(pos++) = addr4_len;
1204                                         memcpy(pos, dnr->addr4, addr4_len);
1205                                         pos += addr4_len;
1206                                         memcpy(pos, dnr->svc, dnr->svc_len);
1207                                         pos += dnr->svc_len;
1208 
1209                                         d4dnr_len += sizeof(addr4_len) + addr4_len + dnr->svc_len;
1210                                 }
1211 
1212                                 d4dnr_len_be = htons(d4dnr_len);
1213                                 memcpy(&d4dnr->len, &d4dnr_len_be, sizeof(d4dnr_len_be));
1214                         }
1215 
1216                         reply_dnr.len = dnrs_len;
1217                         iov[IOV_DNR].iov_len = sizeof(reply_dnr);
1218                         iov[IOV_DNR_BODY].iov_base = dnrs;
1219                         iov[IOV_DNR_BODY].iov_len = dnrs_len;
1220                         break;
1221                 }
1222         }
1223 
1224         if (lease)
1225                 reply.yiaddr.s_addr = lease->addr;
1226 
1227         memcpy(reply.chaddr, req->chaddr, sizeof(reply.chaddr));
1228         dhcpv4_set_dest_addr(iface, reply_msg.data, req, &reply, src_addr, &dest_addr);
1229         dhcpv4_add_padding(iov, ARRAY_SIZE(iov));
1230 
1231         if (send_reply(iov, ARRAY_SIZE(iov), (struct sockaddr *)&dest_addr, sizeof(dest_addr), opaque) < 0)
1232                 error("Failed to send %s to %s - %s: %m",
1233                       dhcpv4_msg_to_string(reply_msg.data),
1234                       dest_addr.sin_addr.s_addr == INADDR_BROADCAST ?
1235                       "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen),
1236                       inet_ntoa(dest_addr.sin_addr));
1237         else
1238                 error("Sent %s to %s - %s",
1239                       dhcpv4_msg_to_string(reply_msg.data),
1240                       dest_addr.sin_addr.s_addr == INADDR_BROADCAST ?
1241                       "ff:ff:ff:ff:ff:ff": odhcpd_print_mac(req->chaddr, req->hlen),
1242                       inet_ntoa(dest_addr.sin_addr));
1243 
1244         if (reply_msg.data == DHCPV4_MSG_ACK && lease)
1245                 ubus_bcast_dhcp_event("dhcp.ack", req->chaddr,
1246                                       (struct in_addr *)&lease->addr,
1247                                       lease->hostname, iface->ifname);
1248 }
1249 
1250 /* Handler for DHCPv4 messages */
1251 static void dhcpv4_handle_dgram(void *addr, void *data, size_t len,
1252                                 struct interface *iface, _unused void *dest_addr)
1253 {
1254         int sock = iface->dhcpv4_event.uloop.fd;
1255 
1256         dhcpv4_handle_msg(addr, data, len, iface, dest_addr, dhcpv4_send_reply, &sock);
1257 }
1258 
1259 static int dhcpv4_setup_addresses(struct interface *iface)
1260 {
1261         iface->dhcpv4_start_ip.s_addr = INADDR_ANY;
1262         iface->dhcpv4_end_ip.s_addr = INADDR_ANY;
1263         iface->dhcpv4_local.s_addr = INADDR_ANY;
1264         iface->dhcpv4_bcast.s_addr = INADDR_ANY;
1265         iface->dhcpv4_mask.s_addr = INADDR_ANY;
1266 
1267         /* Sanity checks */
1268         if (iface->dhcpv4_start.s_addr & htonl(0xffff0000) ||
1269             iface->dhcpv4_end.s_addr & htonl(0xffff0000) ||
1270             ntohl(iface->dhcpv4_start.s_addr) > ntohl(iface->dhcpv4_end.s_addr)) {
1271                 warn("Invalid DHCP range for %s", iface->name);
1272                 return -1;
1273         }
1274 
1275         if (!iface->addr4_len) {
1276                 warn("No network(s) available on %s", iface->name);
1277                 return -1;
1278         }
1279 
1280         uint32_t start = ntohl(iface->dhcpv4_start.s_addr);
1281         uint32_t end = ntohl(iface->dhcpv4_end.s_addr);
1282 
1283         for (size_t i = 0; i < iface->addr4_len && start && end; i++) {
1284                 struct in_addr *addr = &iface->addr4[i].addr.in;
1285                 struct in_addr mask;
1286 
1287                 if (addr_is_fr_ip(iface, addr))
1288                         continue;
1289 
1290                 odhcpd_bitlen2netmask(false, iface->addr4[i].prefix, &mask);
1291                 if ((start & ntohl(~mask.s_addr)) == start &&
1292                                 (end & ntohl(~mask.s_addr)) == end &&
1293                                 end < ntohl(~mask.s_addr)) {    /* Exclude broadcast address */
1294                         iface->dhcpv4_start_ip.s_addr = htonl(start) |
1295                                                         (addr->s_addr & mask.s_addr);
1296                         iface->dhcpv4_end_ip.s_addr = htonl(end) |
1297                                                         (addr->s_addr & mask.s_addr);
1298                         iface->dhcpv4_local = *addr;
1299                         iface->dhcpv4_bcast = iface->addr4[i].broadcast;
1300                         iface->dhcpv4_mask = mask;
1301                         return 0;
1302                 }
1303         }
1304 
1305         /* Don't allocate IP range for subnets smaller than /28 */
1306         if (iface->addr4[0].prefix > MAX_PREFIX_LEN) {
1307                 warn("Auto allocation of DHCP range fails on %s (prefix length must be < %d).",
1308                      iface->name, MAX_PREFIX_LEN + 1);
1309                 return -1;
1310         }
1311 
1312         iface->dhcpv4_local = iface->addr4[0].addr.in;
1313         iface->dhcpv4_bcast = iface->addr4[0].broadcast;
1314         odhcpd_bitlen2netmask(false, iface->addr4[0].prefix, &iface->dhcpv4_mask);
1315         end = start = iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr;
1316 
1317         /* Auto allocate ranges */
1318         if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff00) {           /* /24, 150 of 256, [100..249] */
1319                 iface->dhcpv4_start_ip.s_addr = start | htonl(100);
1320                 iface->dhcpv4_end_ip.s_addr = end | htonl(100 + 150 - 1);
1321         } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffff80) {    /* /25, 100 of 128, [20..119] */
1322                 iface->dhcpv4_start_ip.s_addr = start | htonl(20);
1323                 iface->dhcpv4_end_ip.s_addr = end | htonl(20 + 100 - 1);
1324         } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffc0) {    /* /26, 50 of 64, [10..59] */
1325                 iface->dhcpv4_start_ip.s_addr = start | htonl(10);
1326                 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 50 - 1);
1327         } else if (ntohl(iface->dhcpv4_mask.s_addr) <= 0xffffffe0) {    /* /27, 20 of 32, [10..29] */
1328                 iface->dhcpv4_start_ip.s_addr = start | htonl(10);
1329                 iface->dhcpv4_end_ip.s_addr = end | htonl(10 + 20 - 1);
1330         } else {                                                        /* /28, 10 of 16, [3..12] */
1331                 iface->dhcpv4_start_ip.s_addr = start | htonl(3);
1332                 iface->dhcpv4_end_ip.s_addr = end | htonl(3 + 10 - 1);
1333         }
1334 
1335         return 0;
1336 }
1337 
1338 int dhcpv4_setup_interface(struct interface *iface, bool enable)
1339 {
1340         int ret = 0;
1341         struct sockaddr_in bind_addr = {
1342                 .sin_family = AF_INET,
1343                 .sin_port = htons(DHCPV4_SERVER_PORT),
1344                 .sin_addr = { INADDR_ANY },
1345         };
1346         int val = 1;
1347 
1348         if (iface->dhcpv4_event.uloop.fd >= 0) {
1349                 uloop_fd_delete(&iface->dhcpv4_event.uloop);
1350                 close(iface->dhcpv4_event.uloop.fd);
1351                 iface->dhcpv4_event.uloop.fd = -1;
1352         }
1353 
1354         if (!enable || iface->dhcpv4 == MODE_DISABLED) {
1355                 while (!list_empty(&iface->dhcpv4_leases))
1356                         dhcpv4_free_lease(list_first_entry(&iface->dhcpv4_leases,
1357                                                            struct dhcpv4_lease, head));
1358                 return 0;
1359         }
1360 
1361         iface->dhcpv4_event.uloop.fd = socket(AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP);
1362         if (iface->dhcpv4_event.uloop.fd < 0) {
1363                 error("socket(AF_INET): %m");
1364                 ret = -1;
1365                 goto out;
1366         }
1367 
1368         /* Basic IPv4 configuration */
1369         if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_REUSEADDR,
1370                        &val, sizeof(val)) < 0) {
1371                 error("setsockopt(SO_REUSEADDR): %m");
1372                 ret = -1;
1373                 goto out;
1374         }
1375 
1376         if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BROADCAST,
1377                        &val, sizeof(val)) < 0) {
1378                 error("setsockopt(SO_BROADCAST): %m");
1379                 ret = -1;
1380                 goto out;
1381         }
1382 
1383         if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_PKTINFO,
1384                        &val, sizeof(val)) < 0) {
1385                 error("setsockopt(IP_PKTINFO): %m");
1386                 ret = -1;
1387                 goto out;
1388         }
1389 
1390         val = IPTOS_PREC_INTERNETCONTROL;
1391         if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_TOS, &val,
1392                        sizeof(val)) < 0) {
1393                 error("setsockopt(IP_TOS): %m");
1394                 ret = -1;
1395                 goto out;
1396         }
1397 
1398         val = IP_PMTUDISC_DONT;
1399         if (setsockopt(iface->dhcpv4_event.uloop.fd, IPPROTO_IP, IP_MTU_DISCOVER,
1400                        &val, sizeof(val)) < 0) {
1401                 error("setsockopt(IP_MTU_DISCOVER): %m");
1402                 ret = -1;
1403                 goto out;
1404         }
1405 
1406         if (setsockopt(iface->dhcpv4_event.uloop.fd, SOL_SOCKET, SO_BINDTODEVICE,
1407                        iface->ifname, strlen(iface->ifname)) < 0) {
1408                 error("setsockopt(SO_BINDTODEVICE): %m");
1409                 ret = -1;
1410                 goto out;
1411         }
1412 
1413         if (bind(iface->dhcpv4_event.uloop.fd, (struct sockaddr *)&bind_addr,
1414                  sizeof(bind_addr)) < 0) {
1415                 error("bind(): %m");
1416                 ret = -1;
1417                 goto out;
1418         }
1419 
1420         if (dhcpv4_setup_addresses(iface) < 0) {
1421                 ret = -1;
1422                 goto out;
1423         }
1424 
1425         iface->dhcpv4_event.handle_dgram = dhcpv4_handle_dgram;
1426         odhcpd_register(&iface->dhcpv4_event);
1427 
1428 out:
1429         if (ret < 0 && iface->dhcpv4_event.uloop.fd >= 0) {
1430                 close(iface->dhcpv4_event.uloop.fd);
1431                 iface->dhcpv4_event.uloop.fd = -1;
1432         }
1433 
1434         return ret;
1435 }
1436 
1437 static void dhcpv4_addrlist_change(struct interface *iface)
1438 {
1439         struct odhcpd_ipaddr ip;
1440         struct odhcpd_ref_ip *a;
1441         struct dhcpv4_lease *lease;
1442         uint32_t mask = iface->dhcpv4_mask.s_addr;
1443 
1444         memset(&ip, 0, sizeof(ip));
1445         ip.addr.in = iface->dhcpv4_local;
1446         ip.prefix = odhcpd_netmask2bitlen(false, &iface->dhcpv4_mask);
1447         ip.broadcast = iface->dhcpv4_bcast;
1448 
1449         dhcpv4_setup_addresses(iface);
1450 
1451         if ((ip.addr.in.s_addr & mask) ==
1452             (iface->dhcpv4_local.s_addr & iface->dhcpv4_mask.s_addr))
1453                 return;
1454 
1455         if (ip.addr.in.s_addr && !leases_require_fr(iface, &ip, mask))
1456                 return;
1457 
1458         if (iface->dhcpv4_local.s_addr == INADDR_ANY || list_empty(&iface->dhcpv4_fr_ips))
1459                 return;
1460 
1461         a = list_first_entry(&iface->dhcpv4_fr_ips, struct odhcpd_ref_ip, head);
1462 
1463         if (netlink_setup_addr(&a->addr, iface->ifindex, false, true)) {
1464                 warn("Failed to add ip address on %s", iface->name);
1465                 return;
1466         }
1467 
1468         list_for_each_entry(lease, &iface->dhcpv4_leases, head) {
1469                 if ((lease->flags & OAF_BOUND) && lease->fr_ip && !lease->fr_cnt) {
1470                         if (lease->accept_fr_nonce || iface->dhcpv4_forcereconf)
1471                                 dhcpv4_fr_rand_delay(lease);
1472                         else
1473                                 dhcpv4_fr_stop(lease);
1474                 }
1475         }
1476 }
1477 
1478 static void dhcpv4_netevent_cb(unsigned long event, struct netevent_handler_info *info)
1479 {
1480         struct interface *iface = info->iface;
1481 
1482         if (!iface || iface->dhcpv4 == MODE_DISABLED)
1483                 return;
1484 
1485         switch (event) {
1486         case NETEV_IFINDEX_CHANGE:
1487                 dhcpv4_setup_interface(iface, true);
1488                 break;
1489         case NETEV_ADDRLIST_CHANGE:
1490                 dhcpv4_addrlist_change(iface);
1491                 break;
1492         default:
1493                 break;
1494         }
1495 }
1496 
1497 static void dhcpv4_valid_until_cb(struct uloop_timeout *event)
1498 {
1499         struct interface *iface;
1500         time_t now = odhcpd_time();
1501 
1502         avl_for_each_element(&interfaces, iface, avl) {
1503                 struct dhcpv4_lease *lease, *tmp;
1504 
1505                 if (iface->dhcpv4 != MODE_SERVER)
1506                         continue;
1507 
1508                 list_for_each_entry_safe(lease, tmp, &iface->dhcpv4_leases, head) {
1509                         if (!INFINITE_VALID(lease->valid_until) && lease->valid_until < now) {
1510                                 ubus_bcast_dhcp_event("dhcp.expire", lease->hwaddr,
1511                                                       (struct in_addr *)&lease->addr,
1512                                                       lease->hostname, iface->ifname);
1513                                 dhcpv4_free_lease(lease);
1514                         }
1515                 }
1516         }
1517         uloop_timeout_set(event, 1000);
1518 }
1519 
1520 /* Create socket and register events */
1521 int dhcpv4_init(void)
1522 {
1523         static struct netevent_handler dhcpv4_netevent_handler = { .cb = dhcpv4_netevent_cb };
1524         static struct uloop_timeout valid_until_timeout = { .cb = dhcpv4_valid_until_cb };
1525 
1526         uloop_timeout_set(&valid_until_timeout, 1000);
1527         netlink_add_netevent_handler(&dhcpv4_netevent_handler);
1528 
1529         return 0;
1530 }
1531 

This page was automatically generated by LXR 0.3.1.  •  OpenWrt