Coverage Report

Created: 2025-12-27 06:42

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/dnsmasq/src/dhcp.c
Line
Count
Source
1
/* dnsmasq is Copyright (c) 2000-2025 Simon Kelley
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 dated June, 1991, or
6
   (at your option) version 3 dated 29 June, 2007.
7
 
8
   This program is distributed in the hope that it will be useful,
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
   GNU General Public License for more details.
12
     
13
   You should have received a copy of the GNU General Public License
14
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
*/
16
17
#include "dnsmasq.h"
18
19
#ifdef HAVE_DHCP
20
21
struct iface_param {
22
  struct dhcp_context *current;
23
  int ind;
24
};
25
26
struct match_param {
27
  int ind, matched;
28
  struct in_addr netmask, broadcast, addr;
29
};
30
31
static int complete_context(struct in_addr local, int if_index, char *label,
32
          struct in_addr netmask, struct in_addr broadcast, void *vparam);
33
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
34
            struct in_addr netmask, struct in_addr broadcast, void *vparam);
35
36
static int make_fd(int port)
37
0
{
38
0
  int fd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
39
0
  struct sockaddr_in saddr;
40
0
  int oneopt = 1;
41
0
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
42
0
  int mtu = IP_PMTUDISC_DONT;
43
0
#endif
44
0
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
45
0
  int tos = IPTOS_CLASS_CS6;
46
0
#endif
47
48
0
  if (fd == -1)
49
0
    die (_("cannot create DHCP socket: %s"), NULL, EC_BADNET);
50
  
51
0
  if (!fix_fd(fd) ||
52
0
#if defined(IP_MTU_DISCOVER) && defined(IP_PMTUDISC_DONT)
53
0
      setsockopt(fd, IPPROTO_IP, IP_MTU_DISCOVER, &mtu, sizeof(mtu)) == -1 ||
54
0
#endif
55
0
#if defined(IP_TOS) && defined(IPTOS_CLASS_CS6)
56
0
      setsockopt(fd, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) == -1 ||
57
0
#endif
58
0
#if defined(HAVE_LINUX_NETWORK)
59
0
      setsockopt(fd, IPPROTO_IP, IP_PKTINFO, &oneopt, sizeof(oneopt)) == -1 ||
60
#else
61
      setsockopt(fd, IPPROTO_IP, IP_RECVIF, &oneopt, sizeof(oneopt)) == -1 ||
62
#endif
63
0
      setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &oneopt, sizeof(oneopt)) == -1)  
64
0
    die(_("failed to set options on DHCP socket: %s"), NULL, EC_BADNET);
65
  
66
  /* When bind-interfaces is set, there might be more than one dnsmasq
67
     instance binding port 67. That's OK if they serve different networks.
68
     Need to set REUSEADDR|REUSEPORT to make this possible.
69
     Handle the case that REUSEPORT is defined, but the kernel doesn't 
70
     support it. This handles the introduction of REUSEPORT on Linux. */
71
0
  if (option_bool(OPT_NOWILD) || option_bool(OPT_CLEVERBIND))
72
0
    {
73
0
      int rc = 0;
74
75
0
#ifdef SO_REUSEPORT
76
0
      if ((rc = setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, &oneopt, sizeof(oneopt))) == -1 && 
77
0
    errno == ENOPROTOOPT)
78
0
  rc = 0;
79
0
#endif
80
      
81
0
      if (rc != -1)
82
0
  rc = setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &oneopt, sizeof(oneopt));
83
      
84
0
      if (rc == -1)
85
0
  die(_("failed to set SO_REUSE{ADDR|PORT} on DHCP socket: %s"), NULL, EC_BADNET);
86
0
    }
87
  
88
0
  memset(&saddr, 0, sizeof(saddr));
89
0
  saddr.sin_family = AF_INET;
90
0
  saddr.sin_port = htons(port);
91
0
  saddr.sin_addr.s_addr = INADDR_ANY;
92
#ifdef HAVE_SOCKADDR_SA_LEN
93
  saddr.sin_len = sizeof(struct sockaddr_in);
94
#endif
95
96
0
  if (bind(fd, (struct sockaddr *)&saddr, sizeof(struct sockaddr_in)))
97
0
    die(_("failed to bind DHCP server socket: %s"), NULL, EC_BADNET);
98
99
0
  return fd;
100
0
}
101
102
void dhcp_init(void)
103
0
{
104
#if defined(HAVE_BSD_NETWORK)
105
  int oneopt = 1;
106
#endif
107
108
0
  daemon->dhcpfd = make_fd(daemon->dhcp_server_port);
109
0
  if (daemon->enable_pxe)
110
0
    daemon->pxefd = make_fd(PXE_PORT);
111
0
  else
112
0
    daemon->pxefd = -1;
113
114
#if defined(HAVE_BSD_NETWORK)
115
  /* When we're not using capabilities, we need to do this here before
116
     we drop root. Also, set buffer size small, to avoid wasting
117
     kernel buffers */
118
  
119
  if (option_bool(OPT_NO_PING))
120
    daemon->dhcp_icmp_fd = -1;
121
  else if ((daemon->dhcp_icmp_fd = make_icmp_sock()) == -1 ||
122
     setsockopt(daemon->dhcp_icmp_fd, SOL_SOCKET, SO_RCVBUF, &oneopt, sizeof(oneopt)) == -1 )
123
    die(_("cannot create ICMP raw socket: %s."), NULL, EC_BADNET);
124
  
125
  /* Make BPF raw send socket */
126
  init_bpf();
127
#endif  
128
0
}
129
130
void dhcp_packet(time_t now, int pxe_fd)
131
0
{
132
0
  int fd = pxe_fd ? daemon->pxefd : daemon->dhcpfd;
133
0
  struct dhcp_packet *mess;
134
0
  struct dhcp_context *context;
135
0
  struct dhcp_relay *relay;
136
0
  int is_relay_reply = 0, is_relay_use_source = 0;
137
0
  struct iname *tmp;
138
0
  struct ifreq ifr;
139
0
  struct msghdr msg;
140
0
  struct sockaddr_in dest;
141
0
  struct cmsghdr *cmptr;
142
0
  struct iovec iov;
143
0
  ssize_t sz; 
144
0
  int iface_index = 0, unicast_dest = 0, is_inform = 0, loopback = 0;
145
0
  int rcvd_iface_index, relay_index;
146
0
  struct in_addr iface_addr;
147
0
  struct iface_param parm;
148
0
  time_t recvtime = now;
149
0
#ifdef HAVE_LINUX_NETWORK
150
0
  struct arpreq arp_req;
151
0
  struct timeval tv;
152
0
  struct in_addr dst_addr;
153
0
#endif
154
  
155
0
  union {
156
0
    struct cmsghdr align; /* this ensures alignment */
157
0
#if defined(HAVE_LINUX_NETWORK)
158
0
    char control[CMSG_SPACE(sizeof(struct in_pktinfo))];
159
#elif defined(HAVE_SOLARIS_NETWORK)
160
    char control[CMSG_SPACE(sizeof(unsigned int))];
161
#elif defined(HAVE_BSD_NETWORK) 
162
    char control[CMSG_SPACE(sizeof(struct sockaddr_dl))];
163
#endif
164
0
  } control_u;
165
0
  struct dhcp_bridge *bridge, *alias;
166
167
0
  msg.msg_controllen = sizeof(control_u);
168
0
  msg.msg_control = control_u.control;
169
0
  msg.msg_name = &dest;
170
0
  msg.msg_namelen = sizeof(dest);
171
0
  msg.msg_iov = &daemon->dhcp_packet;
172
0
  msg.msg_iovlen = 1;
173
  
174
0
  if ((sz = recv_dhcp_packet(fd, &msg)) == -1 || 
175
0
      (sz < (ssize_t)(sizeof(*mess) - sizeof(mess->options)))) 
176
0
    return;
177
  
178
0
#if defined (HAVE_LINUX_NETWORK)
179
0
  if (ioctl(fd, SIOCGSTAMP, &tv) == 0)
180
0
    recvtime = tv.tv_sec;
181
182
0
  dst_addr.s_addr = 0;
183
  
184
0
  if (msg.msg_controllen >= sizeof(struct cmsghdr))
185
0
    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
186
0
      if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_PKTINFO)
187
0
  {
188
0
    union {
189
0
      unsigned char *c;
190
0
      struct in_pktinfo *p;
191
0
    } p;
192
0
    p.c = CMSG_DATA(cmptr);
193
0
    iface_index = p.p->ipi_ifindex;
194
0
    dst_addr = p.p->ipi_addr; 
195
0
    if (dst_addr.s_addr != INADDR_BROADCAST)
196
0
      unicast_dest = 1;
197
0
  }
198
199
#elif defined(HAVE_BSD_NETWORK) 
200
  if (msg.msg_controllen >= sizeof(struct cmsghdr))
201
    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
202
      if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
203
        {
204
    union {
205
            unsigned char *c;
206
            struct sockaddr_dl *s;
207
          } p;
208
    p.c = CMSG_DATA(cmptr);
209
    iface_index = p.s->sdl_index;
210
  }
211
  
212
#elif defined(HAVE_SOLARIS_NETWORK) 
213
  if (msg.msg_controllen >= sizeof(struct cmsghdr))
214
    for (cmptr = CMSG_FIRSTHDR(&msg); cmptr; cmptr = CMSG_NXTHDR(&msg, cmptr))
215
      if (cmptr->cmsg_level == IPPROTO_IP && cmptr->cmsg_type == IP_RECVIF)
216
  {
217
    union {
218
      unsigned char *c;
219
      unsigned int *i;
220
    } p;
221
    p.c = CMSG_DATA(cmptr);
222
    iface_index = *(p.i);
223
  }
224
#endif
225
226
0
#ifdef HAVE_DUMPFILE
227
0
  union mysockaddr *sockp = NULL;
228
  
229
0
#  ifdef HAVE_LINUX_NETWORK
230
0
  union mysockaddr tosock;
231
  
232
0
  sockp = &tosock;
233
0
  tosock.in.sin_port = htons(daemon->dhcp_server_port);
234
0
  tosock.in.sin_addr = dst_addr;
235
0
  tosock.sa.sa_family = AF_INET;
236
#    ifdef HAVE_SOCKADDR_SA_LEN
237
  tosock.in.sin_len = sizeof(struct sockaddr_in);
238
#    endif
239
0
#  endif
240
  
241
0
  dump_packet_udp(DUMP_DHCP, (void *)daemon->dhcp_packet.iov_base, sz, (union mysockaddr *)&dest, sockp, -1);
242
0
#endif
243
    
244
0
  if (!indextoname(daemon->dhcpfd, iface_index, ifr.ifr_name) ||
245
0
      ioctl(daemon->dhcpfd, SIOCGIFFLAGS, &ifr) != 0)
246
0
    return;
247
  
248
0
  mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
249
  
250
  /* Non-standard extension:
251
     If giaddr == 255.255.255.255 we reply to the source
252
     address in the request packet header. This makes
253
     stand-alone leasequery clients easier, as they
254
     can leave source address determination to the kernel.
255
     In this case, set a flag and clear giaddr here,
256
     to avoid massive relay confusion. */
257
0
  if (mess->giaddr.s_addr == INADDR_BROADCAST)
258
0
    {
259
0
      mess->giaddr.s_addr = 0;
260
0
      is_relay_use_source = 1;
261
0
    }
262
  
263
0
  loopback = !mess->giaddr.s_addr && (ifr.ifr_flags & IFF_LOOPBACK);
264
  
265
0
#ifdef HAVE_LINUX_NETWORK
266
  /* ARP fiddling uses original interface even if we pretend to use a different one. */
267
0
  safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
268
0
#endif 
269
270
  /* If the interface on which the DHCP request was received is an
271
     alias of some other interface (as specified by the
272
     --bridge-interface option), change ifr.ifr_name so that we look
273
     for DHCP contexts associated with the aliased interface instead
274
     of with the aliasing one. */
275
0
  rcvd_iface_index = iface_index;
276
0
  for (bridge = daemon->bridges; bridge; bridge = bridge->next)
277
0
    {
278
0
      for (alias = bridge->alias; alias; alias = alias->next)
279
0
  if (wildcard_matchn(alias->iface, ifr.ifr_name, IF_NAMESIZE))
280
0
    {
281
0
      if (!(iface_index = if_nametoindex(bridge->iface)))
282
0
        {
283
0
    my_syslog(MS_DHCP | LOG_WARNING,
284
0
        _("unknown interface %s in bridge-interface"),
285
0
        bridge->iface);
286
0
    return;
287
0
        }
288
0
      else 
289
0
        {
290
0
    safe_strncpy(ifr.ifr_name,  bridge->iface, sizeof(ifr.ifr_name));
291
0
    break;
292
0
        }
293
0
    }
294
      
295
0
      if (alias)
296
0
  break;
297
0
    }
298
299
#ifdef MSG_BCAST
300
  /* OpenBSD tells us when a packet was broadcast */
301
  if (!(msg.msg_flags & MSG_BCAST))
302
    unicast_dest = 1;
303
#endif
304
  
305
0
  if ((relay_index = relay_reply4((struct dhcp_packet *)daemon->dhcp_packet.iov_base, (size_t)sz, ifr.ifr_name)))
306
0
    {
307
      /* Reply from server, using us as relay. */
308
0
      rcvd_iface_index = relay_index;
309
0
      if (!indextoname(daemon->dhcpfd, rcvd_iface_index, ifr.ifr_name))
310
0
  return;
311
0
      is_relay_reply = 1; 
312
0
      iov.iov_len = sz;
313
0
#ifdef HAVE_LINUX_NETWORK
314
0
      safe_strncpy(arp_req.arp_dev, ifr.ifr_name, sizeof(arp_req.arp_dev));
315
0
#endif 
316
0
    }
317
0
  else
318
0
    {
319
0
      ifr.ifr_addr.sa_family = AF_INET;
320
0
      if (ioctl(daemon->dhcpfd, SIOCGIFADDR, &ifr) != -1 )
321
0
  iface_addr = ((struct sockaddr_in *) &ifr.ifr_addr)->sin_addr;
322
0
      else
323
0
  {
324
0
    if (iface_check(AF_INET, NULL, ifr.ifr_name, NULL))
325
0
      my_syslog(MS_DHCP | LOG_WARNING, _("DHCP packet received on %s which has no address"), ifr.ifr_name);
326
0
    return;
327
0
  }
328
      
329
0
      for (tmp = daemon->dhcp_except; tmp; tmp = tmp->next)
330
0
  if (tmp->name && (tmp->flags & INAME_4) && wildcard_match(tmp->name, ifr.ifr_name))
331
0
    return;
332
      
333
      /* unlinked contexts are marked by context->current == context */
334
0
      for (context = daemon->dhcp; context; context = context->next)
335
0
  context->current = context;
336
337
0
      for (relay = daemon->relay4; relay; relay = relay->next)
338
0
  relay->matchcount = 0;
339
      
340
0
      parm.current = NULL;
341
0
      parm.ind = iface_index;
342
      
343
0
      if (!iface_check(AF_INET, (union all_addr *)&iface_addr, ifr.ifr_name, NULL))
344
0
  {
345
    /* If we failed to match the primary address of the interface, see if we've got a --listen-address
346
       for a secondary */
347
0
    struct match_param match;
348
    
349
0
    match.matched = 0;
350
0
    match.ind = iface_index;
351
    
352
0
    if (!daemon->if_addrs ||
353
0
        !iface_enumerate(AF_INET, &match, (callback_t){.af_inet=check_listen_addrs}) ||
354
0
        !match.matched)
355
0
      return;
356
    
357
0
    iface_addr = match.addr;
358
    /* make sure secondary address gets priority in case
359
       there is more than one address on the interface in the same subnet */
360
0
    complete_context(match.addr, iface_index, NULL, match.netmask, match.broadcast, &parm);
361
0
  }    
362
            
363
0
      if (!iface_enumerate(AF_INET, &parm, (callback_t){.af_inet=complete_context}))
364
0
  return;
365
366
0
      relay_upstream4(iface_addr, iface_index, mess, (size_t)sz, unicast_dest);
367
       
368
      /* May have configured relay, but not DHCP server */
369
0
      if (!daemon->dhcp)
370
0
  return;
371
372
0
      lease_prune(NULL, now); /* lose any expired leases */
373
0
      iov.iov_len = dhcp_reply(parm.current, ifr.ifr_name, iface_index, (size_t)sz, now, unicast_dest,
374
0
             loopback, &is_inform, pxe_fd, iface_addr, recvtime,
375
0
             is_relay_use_source ? dest.sin_addr : mess->giaddr);
376
0
      lease_update_file(now);
377
0
      lease_update_dns(0);
378
      
379
0
      if (iov.iov_len == 0)
380
0
  return;
381
0
    }
382
383
0
  msg.msg_name = &dest;
384
0
  msg.msg_namelen = sizeof(dest);
385
0
  msg.msg_control = NULL;
386
0
  msg.msg_controllen = 0;
387
0
  msg.msg_iov = &iov;
388
0
  iov.iov_base = daemon->dhcp_packet.iov_base;
389
  
390
  /* packet buffer may have moved */
391
0
  mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
392
  
393
#ifdef HAVE_SOCKADDR_SA_LEN
394
  dest.sin_len = sizeof(struct sockaddr_in);
395
#endif
396
  
397
0
  if (pxe_fd)
398
0
    { 
399
0
      if (mess->ciaddr.s_addr != 0)
400
0
  dest.sin_addr = mess->ciaddr;
401
0
    }
402
0
  if ((is_relay_use_source || mess->giaddr.s_addr) && !is_relay_reply)
403
0
    {
404
      /* Send to BOOTP relay. */
405
0
      if (is_relay_use_source)
406
  /* restore as-received value */
407
0
  mess->giaddr.s_addr = INADDR_BROADCAST;
408
0
      else
409
0
  {
410
0
    dest.sin_addr = mess->giaddr;
411
0
    dest.sin_port = htons(daemon->dhcp_server_port);
412
0
  }
413
0
    }
414
0
  else if (mess->ciaddr.s_addr)
415
0
    {
416
      /* If the client's idea of its own address tallys with
417
   the source address in the request packet, we believe the
418
   source port too, and send back to that.  If we're replying 
419
   to a DHCPINFORM, trust the source address always. */
420
0
      if ((!is_inform && dest.sin_addr.s_addr != mess->ciaddr.s_addr) ||
421
0
    dest.sin_port == 0 || dest.sin_addr.s_addr == 0 || is_relay_reply)
422
0
  {
423
0
    dest.sin_port = htons(daemon->dhcp_client_port); 
424
0
    dest.sin_addr = mess->ciaddr;
425
0
  }
426
0
    } 
427
0
#if defined(HAVE_LINUX_NETWORK)
428
0
  else
429
0
    {
430
      /* fill cmsg for outbound interface (both broadcast & unicast) */
431
0
      struct in_pktinfo *pkt;
432
0
      msg.msg_control = control_u.control;
433
0
      msg.msg_controllen = sizeof(control_u);
434
435
      /* alignment padding passed to the kernel should not be uninitialised. */
436
0
      memset(&control_u, 0, sizeof(control_u));
437
438
0
      cmptr = CMSG_FIRSTHDR(&msg);
439
0
      pkt = (struct in_pktinfo *)CMSG_DATA(cmptr);
440
0
      pkt->ipi_ifindex = rcvd_iface_index;
441
0
      pkt->ipi_spec_dst.s_addr = 0;
442
0
      msg.msg_controllen = CMSG_SPACE(sizeof(struct in_pktinfo));
443
0
      cmptr->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
444
0
      cmptr->cmsg_level = IPPROTO_IP;
445
0
      cmptr->cmsg_type = IP_PKTINFO;
446
447
0
      if ((ntohs(mess->flags) & 0x8000) || mess->hlen == 0 ||
448
0
         mess->hlen > sizeof(ifr.ifr_addr.sa_data) || mess->htype == 0)
449
0
        {
450
          /* broadcast to 255.255.255.255 (or mac address invalid) */
451
0
          dest.sin_addr.s_addr = INADDR_BROADCAST;
452
0
          dest.sin_port = htons(daemon->dhcp_client_port);
453
0
        }
454
0
      else
455
0
        {
456
          /* unicast to unconfigured client. Inject mac address direct into ARP cache.
457
          struct sockaddr limits size to 14 bytes. */
458
0
          dest.sin_addr = mess->yiaddr;
459
0
          dest.sin_port = htons(daemon->dhcp_client_port);
460
0
          memcpy(&arp_req.arp_pa, &dest, sizeof(struct sockaddr_in));
461
0
          arp_req.arp_ha.sa_family = mess->htype;
462
0
          memcpy(arp_req.arp_ha.sa_data, mess->chaddr, mess->hlen);
463
          /* interface name already copied in */
464
0
          arp_req.arp_flags = ATF_COM;
465
0
          if (ioctl(daemon->dhcpfd, SIOCSARP, &arp_req) == -1)
466
0
            my_syslog(MS_DHCP | LOG_ERR, _("ARP-cache injection failed: %s"), strerror(errno));
467
0
        }
468
0
    }
469
#elif defined(HAVE_SOLARIS_NETWORK)
470
  else if ((ntohs(mess->flags) & 0x8000) || mess->hlen != ETHER_ADDR_LEN || mess->htype != ARPHRD_ETHER)
471
    {
472
      /* broadcast to 255.255.255.255 (or mac address invalid) */
473
      dest.sin_addr.s_addr = INADDR_BROADCAST;
474
      dest.sin_port = htons(daemon->dhcp_client_port);
475
      /* note that we don't specify the interface here: that's done by the
476
   IP_BOUND_IF sockopt lower down. */
477
    }
478
  else
479
    {
480
      /* unicast to unconfigured client. Inject mac address direct into ARP cache. 
481
   Note that this only works for ethernet on solaris, because we use SIOCSARP
482
   and not SIOCSXARP, which would be perfect, except that it returns ENXIO 
483
   mysteriously. Bah. Fall back to broadcast for other net types. */
484
      struct arpreq req;
485
      dest.sin_addr = mess->yiaddr;
486
      dest.sin_port = htons(daemon->dhcp_client_port);
487
      *((struct sockaddr_in *)&req.arp_pa) = dest;
488
      req.arp_ha.sa_family = AF_UNSPEC;
489
      memcpy(req.arp_ha.sa_data, mess->chaddr, mess->hlen);
490
      req.arp_flags = ATF_COM;
491
      ioctl(daemon->dhcpfd, SIOCSARP, &req);
492
    }
493
#elif defined(HAVE_BSD_NETWORK)
494
  else 
495
    {
496
#ifdef HAVE_DUMPFILE
497
      if (ntohs(mess->flags) & 0x8000)
498
        dest.sin_addr.s_addr = INADDR_BROADCAST;
499
      else
500
        dest.sin_addr = mess->yiaddr;
501
      dest.sin_port = htons(daemon->dhcp_client_port);
502
      
503
      dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
504
          (union mysockaddr *)&dest, fd);
505
#endif
506
      
507
      send_via_bpf(mess, iov.iov_len, iface_addr, &ifr);
508
      return;
509
    }
510
#endif
511
   
512
#ifdef HAVE_SOLARIS_NETWORK
513
  setsockopt(fd, IPPROTO_IP, IP_BOUND_IF, &iface_index, sizeof(iface_index));
514
#endif
515
516
0
#ifdef HAVE_DUMPFILE
517
0
  dump_packet_udp(DUMP_DHCP, (void *)iov.iov_base, iov.iov_len, NULL,
518
0
      (union mysockaddr *)&dest, fd);
519
0
#endif
520
  
521
0
  while(retry_send(sendmsg(fd, &msg, 0)));
522
523
  /* This can fail when, eg, iptables DROPS destination 255.255.255.255 */
524
0
  if (errno != 0)
525
0
    {
526
0
      inet_ntop(AF_INET, &dest.sin_addr, daemon->addrbuff, ADDRSTRLEN);
527
0
      my_syslog(MS_DHCP | LOG_WARNING, _("Error sending DHCP packet to %s: %s"),
528
0
    daemon->addrbuff, strerror(errno));
529
0
    }
530
0
}
531
532
/* check against secondary interface addresses */
533
static int check_listen_addrs(struct in_addr local, int if_index, char *label,
534
            struct in_addr netmask, struct in_addr broadcast, void *vparam)
535
0
{
536
0
  struct match_param *param = vparam;
537
0
  struct iname *tmp;
538
539
0
  (void) label;
540
541
0
  if (if_index == param->ind)
542
0
    {
543
0
      for (tmp = daemon->if_addrs; tmp; tmp = tmp->next)
544
0
  if ( tmp->addr.sa.sa_family == AF_INET &&
545
0
       tmp->addr.in.sin_addr.s_addr == local.s_addr)
546
0
    {
547
0
      param->matched = 1;
548
0
      param->addr = local;
549
0
      param->netmask = netmask;
550
0
      param->broadcast = broadcast;
551
0
      break;
552
0
    }
553
0
    }
554
  
555
0
  return 1;
556
0
}
557
558
/* This is a complex routine: it gets called with each (address,netmask,broadcast) triple 
559
   of each interface (and any relay address) and does the  following things:
560
561
   1) Discards stuff for interfaces other than the one on which a DHCP packet just arrived.
562
   2) Fills in any netmask and broadcast addresses which have not been explicitly configured.
563
   3) Fills in local (this host) and router (this host or relay) addresses.
564
   4) Links contexts which are valid for hosts directly connected to the arrival interface on ->current.
565
566
   Note that the current chain may be superseded later for configured hosts or those coming via gateways. */
567
568
static void guess_range_netmask(struct in_addr addr, struct in_addr netmask)
569
0
{
570
0
  struct dhcp_context *context;
571
572
0
  for (context = daemon->dhcp; context; context = context->next)
573
0
    if (!(context->flags & CONTEXT_NETMASK) &&
574
0
  (is_same_net(addr, context->start, netmask) ||
575
0
   is_same_net(addr, context->end, netmask)))
576
0
      { 
577
0
  if (context->netmask.s_addr != netmask.s_addr &&
578
0
      !(is_same_net(addr, context->start, netmask) &&
579
0
        is_same_net(addr, context->end, netmask)))
580
0
    {
581
0
      inet_ntop(AF_INET, &context->start, daemon->dhcp_buff, DHCP_BUFF_SZ);
582
0
      inet_ntop(AF_INET, &context->end, daemon->dhcp_buff2, DHCP_BUFF_SZ);
583
0
      inet_ntop(AF_INET, &netmask, daemon->addrbuff, ADDRSTRLEN);
584
0
      my_syslog(MS_DHCP | LOG_WARNING, _("DHCP range %s -- %s is not consistent with netmask %s"),
585
0
          daemon->dhcp_buff, daemon->dhcp_buff2, daemon->addrbuff);
586
0
    } 
587
0
  context->netmask = netmask;
588
0
      }
589
0
}
590
591
static int complete_context(struct in_addr local, int if_index, char *label,
592
          struct in_addr netmask, struct in_addr broadcast, void *vparam)
593
0
{
594
0
  struct dhcp_context *context;
595
0
  struct dhcp_relay *relay;
596
0
  struct iface_param *param = vparam;
597
0
  struct shared_network *share;
598
  
599
0
  (void)label;
600
601
0
  for (share = daemon->shared_networks; share; share = share->next)
602
0
    {
603
      
604
0
#ifdef HAVE_DHCP6
605
0
      if (share->shared_addr.s_addr == 0)
606
0
  continue;
607
0
#endif
608
      
609
0
      if (share->if_index != 0)
610
0
  {
611
0
    if (share->if_index != if_index)
612
0
      continue;
613
0
  }
614
0
      else
615
0
  {
616
0
    if (share->match_addr.s_addr != local.s_addr)
617
0
      continue;
618
0
  }
619
620
0
      for (context = daemon->dhcp; context; context = context->next)
621
0
  {
622
0
    if (context->netmask.s_addr != 0 &&
623
0
        is_same_net(share->shared_addr, context->start, context->netmask) &&
624
0
        is_same_net(share->shared_addr, context->end, context->netmask))
625
0
      {
626
        /* link it onto the current chain if we've not seen it before */
627
0
        if (context->current == context)
628
0
    {
629
      /* For a shared network, we have no way to guess what the default route should be. */
630
0
      context->router.s_addr = 0;
631
0
      context->local = local; /* Use configured address for Server Identifier */
632
0
      context->current = param->current;
633
0
      param->current = context;
634
0
    }
635
        
636
0
        if (!(context->flags & CONTEXT_BRDCAST))
637
0
    context->broadcast.s_addr  = context->start.s_addr | ~context->netmask.s_addr;
638
0
      }   
639
0
  }
640
0
    }
641
642
0
  guess_range_netmask(local, netmask);
643
  
644
0
  for (context = daemon->dhcp; context; context = context->next)
645
0
    {
646
0
      if (context->netmask.s_addr != 0 &&
647
0
    is_same_net(local, context->start, context->netmask) &&
648
0
    is_same_net(local, context->end, context->netmask))
649
0
  {
650
    /* link it onto the current chain if we've not seen it before */
651
0
    if (if_index == param->ind && context->current == context)
652
0
      {
653
0
        context->router = local;
654
0
        context->local = local;
655
0
        context->current = param->current;
656
0
        param->current = context;
657
0
      }
658
    
659
0
    if (!(context->flags & CONTEXT_BRDCAST))
660
0
      {
661
0
        if (is_same_net(broadcast, context->start, context->netmask))
662
0
    context->broadcast = broadcast;
663
0
        else 
664
0
    context->broadcast.s_addr  = context->start.s_addr | ~context->netmask.s_addr;
665
0
      }
666
0
  }   
667
0
    }
668
669
0
  for (relay = daemon->relay4; relay; relay = relay->next)
670
0
    if (!relay->split_mode && relay->local.addr4.s_addr == local.s_addr)
671
0
      {
672
0
  if (if_index == param->ind)
673
0
    relay->iface_index = if_index;
674
  
675
  /* More than one interface with the relay address breaks things. */
676
0
  if (relay->matchcount++ == 1 && !relay->warned)
677
0
    {
678
0
      relay->warned = 1;
679
0
      inet_ntop(AF_INET, &local, daemon->addrbuff, ADDRSTRLEN);
680
0
      my_syslog(MS_DHCP | LOG_WARNING, _("DHCP relay address %s appears on more than one interface"), daemon->addrbuff);
681
0
    }
682
0
      }
683
  
684
0
  return 1;
685
0
}
686
    
687
struct dhcp_context *address_available(struct dhcp_context *context, 
688
               struct in_addr taddr,
689
               struct dhcp_netid *netids)
690
0
{
691
  /* Check is an address is OK for this network, check all
692
     possible ranges. Make sure that the address isn't in use
693
     by the server itself. */
694
  
695
0
  unsigned int start, end, addr = ntohl(taddr.s_addr);
696
0
  struct dhcp_context *tmp;
697
698
0
  for (tmp = context; tmp; tmp = tmp->current)
699
0
    if (taddr.s_addr == tmp->router.s_addr)
700
0
      return NULL;
701
  
702
0
  for (tmp = context; tmp; tmp = tmp->current)
703
0
    {
704
0
      start = ntohl(tmp->start.s_addr);
705
0
      end = ntohl(tmp->end.s_addr);
706
707
0
      if (!(tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY)) &&
708
0
    addr >= start &&
709
0
    addr <= end &&
710
0
    match_netid(tmp->filter, netids, 1))
711
0
  return tmp;
712
0
    }
713
714
0
  return NULL;
715
0
}
716
717
struct dhcp_context *narrow_context(struct dhcp_context *context, 
718
            struct in_addr taddr,
719
            struct dhcp_netid *netids)
720
0
{
721
  /* We start of with a set of possible contexts, all on the current physical interface.
722
     These are chained on ->current.
723
     Here we have an address, and return the actual context corresponding to that
724
     address. Note that none may fit, if the address came a dhcp-host and is outside
725
     any dhcp-range. In that case we return a static range if possible, or failing that,
726
     any context on the correct subnet. (If there's more than one, this is a dodgy 
727
     configuration: maybe there should be a warning.) */
728
  
729
0
  struct dhcp_context *tmp;
730
731
0
  if (!(tmp = address_available(context, taddr, netids)))
732
0
    {
733
0
      for (tmp = context; tmp; tmp = tmp->current)
734
0
  if (match_netid(tmp->filter, netids, 1) &&
735
0
      is_same_net(taddr, tmp->start, tmp->netmask) && 
736
0
      (tmp->flags & CONTEXT_STATIC))
737
0
    break;
738
      
739
0
      if (!tmp)
740
0
  for (tmp = context; tmp; tmp = tmp->current)
741
0
    if (match_netid(tmp->filter, netids, 1) &&
742
0
        is_same_net(taddr, tmp->start, tmp->netmask) &&
743
0
        !(tmp->flags & CONTEXT_PROXY))
744
0
      break;
745
0
    }
746
  
747
  /* Only one context allowed now */
748
0
  if (tmp)
749
0
    tmp->current = NULL;
750
  
751
0
  return tmp;
752
0
}
753
754
struct dhcp_config *config_find_by_address(struct dhcp_config *configs, struct in_addr addr)
755
0
{
756
0
  struct dhcp_config *config;
757
  
758
0
  for (config = configs; config; config = config->next)
759
0
    if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
760
0
      return config;
761
762
0
  return NULL;
763
0
}
764
765
/* Check if and address is in use by sending ICMP ping.
766
   This wrapper handles a cache and load-limiting.
767
   Return is NULL is address in use, or a pointer to a cache entry
768
   recording that it isn't. */
769
struct ping_result *do_icmp_ping(time_t now, struct in_addr addr, unsigned int hash, int loopback)
770
0
{
771
0
  static struct ping_result dummy;
772
0
  struct ping_result *r, *victim = NULL;
773
0
  int count, max = (int)(0.6 * (((float)PING_CACHE_TIME)/
774
0
        ((float)PING_WAIT)));
775
776
  /* check if we failed to ping addr sometime in the last
777
     PING_CACHE_TIME seconds. If so, assume the same situation still exists.
778
     This avoids problems when a stupid client bangs
779
     on us repeatedly. As a final check, if we did more
780
     than 60% of the possible ping checks in the last 
781
     PING_CACHE_TIME, we are in high-load mode, so don't do any more. */
782
0
  for (count = 0, r = daemon->ping_results; r; r = r->next)
783
0
    if (difftime(now, r->time) >  (float)PING_CACHE_TIME)
784
0
      victim = r; /* old record */
785
0
    else 
786
0
      {
787
0
  count++;
788
0
  if (r->addr.s_addr == addr.s_addr)
789
0
    return r;
790
0
      }
791
  
792
  /* didn't find cached entry */
793
0
  if ((count >= max) || option_bool(OPT_NO_PING) || loopback)
794
0
    {
795
      /* overloaded, or configured not to check, loopback interface, return "not in use" */
796
0
      dummy.hash = hash;
797
0
      return &dummy;
798
0
    }
799
0
  else if (icmp_ping(addr))
800
0
    return NULL; /* address in use. */
801
0
  else
802
0
    {
803
      /* at this point victim may hold an expired record */
804
0
      if (!victim)
805
0
  {
806
0
    if ((victim = whine_malloc(sizeof(struct ping_result))))
807
0
      {
808
0
        victim->next = daemon->ping_results;
809
0
        daemon->ping_results = victim;
810
0
      }
811
0
  }
812
      
813
      /* record that this address is OK for 30s 
814
   without more ping checks */
815
0
      if (victim)
816
0
  {
817
0
    victim->addr = addr;
818
0
    victim->time = now;
819
0
    victim->hash = hash;
820
0
  }
821
0
      return victim;
822
0
    }
823
0
}
824
825
int address_allocate(struct dhcp_context *context,
826
         struct in_addr *addrp, unsigned char *hwaddr, int hw_len, 
827
         struct dhcp_netid *netids, time_t now, int loopback)   
828
0
{
829
  /* Find a free address: exclude anything in use and anything allocated to
830
     a particular hwaddr/clientid/hostname in our configuration.
831
     Try to return from contexts which match netids first. */
832
833
0
  struct in_addr start, addr;
834
0
  struct dhcp_context *c, *d;
835
0
  int i, pass;
836
0
  unsigned int j; 
837
838
  /* hash hwaddr: use the SDBM hashing algorithm.  Seems to give good
839
     dispersal even with similarly-valued "strings". */ 
840
0
  for (j = 0, i = 0; i < hw_len; i++)
841
0
    j = hwaddr[i] + (j << 6) + (j << 16) - j;
842
843
  /* j == 0 is marker */
844
0
  if (j == 0)
845
0
    j = 1;
846
  
847
0
  for (pass = 0; pass <= 1; pass++)
848
0
    for (c = context; c; c = c->current)
849
0
      if (c->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
850
0
  continue;
851
0
      else if (!match_netid(c->filter, netids, pass))
852
0
  continue;
853
0
      else
854
0
  {
855
0
    if (option_bool(OPT_CONSEC_ADDR))
856
      /* seed is largest extant lease addr in this context */
857
0
      start = lease_find_max_addr(c);
858
0
    else
859
      /* pick a seed based on hwaddr */
860
0
      start.s_addr = htonl(ntohl(c->start.s_addr) + 
861
0
         ((j + c->addr_epoch) % (1 + ntohl(c->end.s_addr) - ntohl(c->start.s_addr))));
862
863
    /* iterate until we find a free address. */
864
0
    addr = start;
865
    
866
0
    do {
867
      /* eliminate addresses in use by the server. */
868
0
      for (d = context; d; d = d->current)
869
0
        if (addr.s_addr == d->router.s_addr)
870
0
    break;
871
872
      /* Addresses which end in .255 and .0 are broken in Windows even when using 
873
         supernetting. ie dhcp-range=192.168.0.1,192.168.1.254,255,255,254.0
874
         then 192.168.0.255 is a valid IP address, but not for Windows as it's
875
         in the class C range. See  KB281579. We therefore don't allocate these 
876
         addresses to avoid hard-to-diagnose problems. Thanks Bill. */      
877
0
      if (!d &&
878
0
    !lease_find_by_addr(addr) && 
879
0
    !config_find_by_address(daemon->dhcp_conf, addr) &&
880
0
    (!IN_CLASSC(ntohl(addr.s_addr)) || 
881
0
     ((ntohl(addr.s_addr) & 0xff) != 0xff && ((ntohl(addr.s_addr) & 0xff) != 0x0))))
882
0
        {
883
    /* in consec-ip mode, skip addresses equal to
884
       the number of addresses rejected by clients. This
885
       should avoid the same client being offered the same
886
       address after it has rjected it. */
887
0
    if (option_bool(OPT_CONSEC_ADDR) && c->addr_epoch)
888
0
      c->addr_epoch--;
889
0
    else
890
0
      {
891
0
        struct ping_result *r;
892
        
893
0
        if ((r = do_icmp_ping(now, addr, j, loopback)))
894
0
          {
895
      /* consec-ip mode: we offered this address for another client
896
         (different hash) recently, don't offer it to this one. */
897
0
      if (!option_bool(OPT_CONSEC_ADDR) || r->hash == j)
898
0
        {
899
0
          *addrp = addr;
900
0
          return 1;
901
0
        }
902
0
          }
903
0
        else
904
0
          {
905
      /* address in use: perturb address selection so that we are
906
         less likely to try this address again. */
907
0
      if (!option_bool(OPT_CONSEC_ADDR))
908
0
        c->addr_epoch++;
909
0
          }
910
0
      }
911
0
        }
912
      
913
0
      addr.s_addr = htonl(ntohl(addr.s_addr) + 1);
914
      
915
0
      if (addr.s_addr == htonl(ntohl(c->end.s_addr) + 1))
916
0
        addr = c->start;
917
      
918
0
    } while (addr.s_addr != start.s_addr);
919
0
  }
920
921
0
  return 0;
922
0
}
923
924
void dhcp_read_ethers(void)
925
0
{
926
0
  FILE *f = fopen(ETHERSFILE, "r");
927
0
  unsigned int flags;
928
0
  char *buff = daemon->namebuff;
929
0
  char *ip, *cp;
930
0
  struct in_addr addr;
931
0
  unsigned char hwaddr[ETHER_ADDR_LEN];
932
0
  struct dhcp_config **up, *tmp;
933
0
  struct dhcp_config *config;
934
0
  int count = 0, lineno = 0;
935
936
0
  addr.s_addr = 0; /* eliminate warning */
937
  
938
0
  if (!f)
939
0
    {
940
0
      my_syslog(MS_DHCP | LOG_ERR, _("failed to read %s: %s"), ETHERSFILE, strerror(errno));
941
0
      return;
942
0
    }
943
944
  /* This can be called again on SIGHUP, so remove entries created last time round. */
945
0
  for (up = &daemon->dhcp_conf, config = daemon->dhcp_conf; config; config = tmp)
946
0
    {
947
0
      tmp = config->next;
948
0
      if (config->flags & CONFIG_FROM_ETHERS)
949
0
  {
950
0
    *up = tmp;
951
    /* cannot have a clid */
952
0
    if (config->flags & CONFIG_NAME)
953
0
      free(config->hostname);
954
0
    free(config->hwaddr);
955
0
    free(config);
956
0
  }
957
0
      else
958
0
  up = &config->next;
959
0
    }
960
961
0
  while (fgets(buff, MAXDNAME, f))
962
0
    {
963
0
      char *host = NULL;
964
      
965
0
      lineno++;
966
      
967
0
      while (strlen(buff) > 0 && isspace((unsigned char)buff[strlen(buff)-1]))
968
0
  buff[strlen(buff)-1] = 0;
969
      
970
0
      if ((*buff == '#') || (*buff == '+') || (*buff == 0))
971
0
  continue;
972
      
973
0
      for (ip = buff; *ip && !isspace((unsigned char)*ip); ip++);
974
0
      for(; *ip && isspace((unsigned char)*ip); ip++)
975
0
  *ip = 0;
976
0
      if (!*ip || parse_hex(buff, hwaddr, ETHER_ADDR_LEN, NULL, NULL) != ETHER_ADDR_LEN)
977
0
  {
978
0
    my_syslog(MS_DHCP | LOG_ERR, _("bad line at %s line %d"), ETHERSFILE, lineno); 
979
0
    continue;
980
0
  }
981
      
982
      /* check for name or dotted-quad */
983
0
      for (cp = ip; *cp; cp++)
984
0
  if (!(*cp == '.' || (*cp >='0' && *cp <= '9')))
985
0
    break;
986
      
987
0
      if (!*cp)
988
0
  {
989
0
    if (inet_pton(AF_INET, ip, &addr.s_addr) < 1)
990
0
      {
991
0
        my_syslog(MS_DHCP | LOG_ERR, _("bad address at %s line %d"), ETHERSFILE, lineno); 
992
0
        continue;
993
0
      }
994
995
0
    flags = CONFIG_ADDR;
996
    
997
0
    for (config = daemon->dhcp_conf; config; config = config->next)
998
0
      if ((config->flags & CONFIG_ADDR) && config->addr.s_addr == addr.s_addr)
999
0
        break;
1000
0
  }
1001
0
      else 
1002
0
  {
1003
0
    int nomem;
1004
0
    if (!(host = canonicalise(ip, &nomem)) || !legal_hostname(host))
1005
0
      {
1006
0
        if (!nomem)
1007
0
    my_syslog(MS_DHCP | LOG_ERR, _("bad name at %s line %d"), ETHERSFILE, lineno); 
1008
0
        free(host);
1009
0
        continue;
1010
0
      }
1011
        
1012
0
    flags = CONFIG_NAME;
1013
1014
0
    for (config = daemon->dhcp_conf; config; config = config->next)
1015
0
      if ((config->flags & CONFIG_NAME) && hostname_isequal(config->hostname, host))
1016
0
        break;
1017
0
  }
1018
1019
0
      if (config && (config->flags & CONFIG_FROM_ETHERS))
1020
0
  {
1021
0
    my_syslog(MS_DHCP | LOG_ERR, _("ignoring %s line %d, duplicate name or IP address"), ETHERSFILE, lineno); 
1022
0
    continue;
1023
0
  }
1024
  
1025
0
      if (!config)
1026
0
  { 
1027
0
    for (config = daemon->dhcp_conf; config; config = config->next)
1028
0
      {
1029
0
        struct hwaddr_config *conf_addr = config->hwaddr;
1030
0
        if (conf_addr && 
1031
0
      conf_addr->next == NULL && 
1032
0
      conf_addr->wildcard_mask == 0 &&
1033
0
      conf_addr->hwaddr_len == ETHER_ADDR_LEN &&
1034
0
      (conf_addr->hwaddr_type == ARPHRD_ETHER || conf_addr->hwaddr_type == 0) &&
1035
0
      memcmp(conf_addr->hwaddr, hwaddr, ETHER_ADDR_LEN) == 0)
1036
0
    break;
1037
0
      }
1038
    
1039
0
    if (!config)
1040
0
      {
1041
0
        if (!(config = whine_malloc(sizeof(struct dhcp_config))))
1042
0
    continue;
1043
0
        config->flags = CONFIG_FROM_ETHERS;
1044
0
        config->hwaddr = NULL;
1045
0
        config->domain = NULL;
1046
0
        config->netid = NULL;
1047
0
        config->next = daemon->dhcp_conf;
1048
0
        daemon->dhcp_conf = config;
1049
0
      }
1050
    
1051
0
    config->flags |= flags;
1052
    
1053
0
    if (flags & CONFIG_NAME)
1054
0
      {
1055
0
        config->hostname = host;
1056
0
        host = NULL;
1057
0
      }
1058
    
1059
0
    if (flags & CONFIG_ADDR)
1060
0
      config->addr = addr;
1061
0
  }
1062
      
1063
0
      config->flags |= CONFIG_NOCLID;
1064
0
      if (!config->hwaddr)
1065
0
  config->hwaddr = whine_malloc(sizeof(struct hwaddr_config));
1066
0
      if (config->hwaddr)
1067
0
  {
1068
0
    memcpy(config->hwaddr->hwaddr, hwaddr, ETHER_ADDR_LEN);
1069
0
    config->hwaddr->hwaddr_len = ETHER_ADDR_LEN;
1070
0
    config->hwaddr->hwaddr_type = ARPHRD_ETHER;
1071
0
    config->hwaddr->wildcard_mask = 0;
1072
0
    config->hwaddr->next = NULL;
1073
0
  }
1074
0
      count++;
1075
      
1076
0
      free(host);
1077
1078
0
    }
1079
  
1080
0
  fclose(f);
1081
1082
0
  my_syslog(MS_DHCP | LOG_INFO, _("read %s - %d addresses"), ETHERSFILE, count);
1083
0
}
1084
1085
1086
/* If we've not found a hostname any other way, try and see if there's one in /etc/hosts
1087
   for this address. If it has a domain part, that must match the set domain and
1088
   it gets stripped. The set of legal domain names is bigger than the set of legal hostnames
1089
   so check here that the domain name is legal as a hostname. 
1090
   NOTE: we're only allowed to overwrite daemon->dhcp_buff if we succeed. */
1091
char *host_from_dns(struct in_addr addr)
1092
0
{
1093
0
  struct crec *lookup;
1094
1095
0
  if (daemon->port == 0)
1096
0
    return NULL; /* DNS disabled. */
1097
  
1098
0
  lookup = cache_find_by_addr(NULL, (union all_addr *)&addr, 0, F_IPV4);
1099
1100
0
  if (lookup && (lookup->flags & F_HOSTS))
1101
0
    {
1102
0
      char *dot, *hostname = cache_get_name(lookup);
1103
0
      dot = strchr(hostname, '.');
1104
      
1105
0
      if (dot && strlen(dot+1) != 0)
1106
0
  {
1107
0
    char *d2 = get_domain(addr);
1108
0
    if (!d2 || !hostname_isequal(dot+1, d2))
1109
0
      return NULL; /* wrong domain */
1110
0
  }
1111
1112
0
      if (!legal_hostname(hostname))
1113
0
  return NULL;
1114
      
1115
0
      safe_strncpy(daemon->dhcp_buff, hostname, 256);
1116
0
      strip_hostname(daemon->dhcp_buff);
1117
1118
0
      return daemon->dhcp_buff;
1119
0
    }
1120
  
1121
0
  return NULL;
1122
0
}
1123
1124
#endif