Imported Upstream version 2.88
[platform/upstream/dnsmasq.git] / src / rfc2131.c
1 /* dnsmasq is Copyright (c) 2000-2022 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 #define option_len(opt) ((int)(((unsigned char *)(opt))[1]))
22 #define option_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[2u+(unsigned int)(i)]))
23
24 #ifdef HAVE_SCRIPT
25 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt);
26 #endif
27
28 static int sanitise(unsigned char *opt, char *buf);
29 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback);
30 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt);
31 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val);
32 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, 
33                               int opt, const char *string, int null_term);
34 static struct in_addr option_addr(unsigned char *opt);
35 static unsigned int option_uint(unsigned char *opt, int offset, int size);
36 static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
37                        int mac_len, char *interface, char *string, char *err, u32 xid);
38 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize);
39 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize);
40 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end);
41 static void clear_packet(struct dhcp_packet *mess, unsigned char *end);
42 static int in_list(unsigned char *list, int opt);
43 static void do_options(struct dhcp_context *context,
44                        struct dhcp_packet *mess,
45                        unsigned char *end,
46                        unsigned char *req_options,
47                        char *hostname, 
48                        char *domain,
49                        struct dhcp_netid *netid,
50                        struct in_addr subnet_addr, 
51                        unsigned char fqdn_flags,
52                        int null_term, int pxe_arch,
53                        unsigned char *uuid,
54                        int vendor_class_len,
55                        time_t now,
56                        unsigned int lease_time,
57                        unsigned short fuzz,
58                        const char *pxevendor);
59
60
61 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt); 
62 static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag, struct dhcp_packet *mess, unsigned char *end, int null_term);
63 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor);
64 static int prune_vendor_opts(struct dhcp_netid *netid);
65 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now);
66 struct dhcp_boot *find_boot(struct dhcp_netid *netid);
67 static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe);
68 static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid);
69 static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor);
70
71 size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
72                   size_t sz, time_t now, int unicast_dest, int loopback,
73                   int *is_inform, int pxe, struct in_addr fallback, time_t recvtime)
74 {
75   unsigned char *opt, *clid = NULL;
76   struct dhcp_lease *ltmp, *lease = NULL;
77   struct dhcp_vendor *vendor;
78   struct dhcp_mac *mac;
79   struct dhcp_netid_list *id_list;
80   int clid_len = 0, ignore = 0, do_classes = 0, rapid_commit = 0, selecting = 0, pxearch = -1;
81   const char *pxevendor = NULL;
82   struct dhcp_packet *mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
83   unsigned char *end = (unsigned char *)(mess + 1); 
84   unsigned char *real_end = (unsigned char *)(mess + 1); 
85   char *hostname = NULL, *offer_hostname = NULL, *client_hostname = NULL, *domain = NULL;
86   int hostname_auth = 0, borken_opt = 0;
87   unsigned char *req_options = NULL;
88   char *message = NULL;
89   unsigned int time;
90   struct dhcp_config *config;
91   struct dhcp_netid *netid, *tagif_netid;
92   struct in_addr subnet_addr, override;
93   unsigned short fuzz = 0;
94   unsigned int mess_type = 0;
95   unsigned char fqdn_flags = 0;
96   unsigned char *agent_id = NULL, *uuid = NULL;
97   unsigned char *emac = NULL;
98   int vendor_class_len = 0, emac_len = 0;
99   struct dhcp_netid known_id, iface_id, cpewan_id;
100   struct dhcp_opt *o;
101   unsigned char pxe_uuid[17];
102   unsigned char *oui = NULL, *serial = NULL;
103 #ifdef HAVE_SCRIPT
104   unsigned char *class = NULL;
105 #endif
106
107   subnet_addr.s_addr = override.s_addr = 0;
108
109   /* set tag with name == interface */
110   iface_id.net = iface_name;
111   iface_id.next = NULL;
112   netid = &iface_id; 
113   
114   if (mess->op != BOOTREQUEST || mess->hlen > DHCP_CHADDR_MAX)
115     return 0;
116    
117   if (mess->htype == 0 && mess->hlen != 0)
118     return 0;
119
120   /* check for DHCP rather than BOOTP */
121   if ((opt = option_find(mess, sz, OPTION_MESSAGE_TYPE, 1)))
122     {
123       u32 cookie = htonl(DHCP_COOKIE);
124       
125       /* only insist on a cookie for DHCP. */
126       if (memcmp(mess->options, &cookie, sizeof(u32)) != 0)
127         return 0;
128       
129       mess_type = option_uint(opt, 0, 1);
130       
131       /* two things to note here: expand_buf may move the packet,
132          so reassign mess from daemon->packet. Also, the size
133          sent includes the IP and UDP headers, hence the magic "-28" */
134       if ((opt = option_find(mess, sz, OPTION_MAXMESSAGE, 2)))
135         {
136           size_t size = (size_t)option_uint(opt, 0, 2) - 28;
137           
138           if (size > DHCP_PACKET_MAX)
139             size = DHCP_PACKET_MAX;
140           else if (size < sizeof(struct dhcp_packet))
141             size = sizeof(struct dhcp_packet);
142           
143           if (expand_buf(&daemon->dhcp_packet, size))
144             {
145               mess = (struct dhcp_packet *)daemon->dhcp_packet.iov_base;
146               real_end = end = ((unsigned char *)mess) + size;
147             }
148         }
149
150       /* Some buggy clients set ciaddr when they shouldn't, so clear that here since
151          it can affect the context-determination code. */
152       if ((option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ) || mess_type == DHCPDISCOVER))
153         mess->ciaddr.s_addr = 0;
154
155       /* search for device identity from CPEWAN devices, we pass this through to the script */
156       if ((opt = option_find(mess, sz, OPTION_VENDOR_IDENT_OPT, 5)))
157         {
158           unsigned  int elen, offset, len = option_len(opt);
159           
160           for (offset = 0; offset < (len - 5); offset += elen + 5)
161             {
162               elen = option_uint(opt, offset + 4 , 1);
163               if (option_uint(opt, offset, 4) == BRDBAND_FORUM_IANA && offset + elen + 5 <= len)
164                 {
165                   unsigned char *x = option_ptr(opt, offset + 5);
166                   unsigned char *y = option_ptr(opt, offset + elen + 5);
167                   oui = option_find1(x, y, 1, 1);
168                   serial = option_find1(x, y, 2, 1);
169 #ifdef HAVE_SCRIPT
170                   class = option_find1(x, y, 3, 1);               
171 #endif
172                   /* If TR069-id is present set the tag "cpewan-id" to facilitate echoing 
173                      the gateway id back. Note that the device class is optional */
174                   if (oui && serial)
175                     {
176                       cpewan_id.net = "cpewan-id";
177                       cpewan_id.next = netid;
178                       netid = &cpewan_id;
179                     }
180                   break;
181                 }
182             }
183         }
184       
185       if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
186         {
187           /* Any agent-id needs to be copied back out, verbatim, as the last option
188              in the packet. Here, we shift it to the very end of the buffer, if it doesn't
189              get overwritten, then it will be shuffled back at the end of processing.
190              Note that the incoming options must not be overwritten here, so there has to 
191              be enough free space at the end of the packet to copy the option. */
192           unsigned char *sopt;
193           unsigned int total = option_len(opt) + 2;
194           unsigned char *last_opt = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + sz,
195                                                  OPTION_END, 0);
196           if (last_opt && last_opt < end - total)
197             {
198               end -= total;
199               agent_id = end;
200               memcpy(agent_id, opt, total);
201             }
202
203           /* look for RFC3527 Link selection sub-option */
204           if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBNET_SELECT, INADDRSZ)))
205             subnet_addr = option_addr(sopt);
206
207           /* look for RFC5107 server-identifier-override */
208           if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SERVER_OR, INADDRSZ)))
209             override = option_addr(sopt);
210           
211           /* if a circuit-id or remote-is option is provided, exact-match to options. */ 
212           for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
213             {
214               int search;
215               
216               if (vendor->match_type == MATCH_CIRCUIT)
217                 search = SUBOPT_CIRCUIT_ID;
218               else if (vendor->match_type == MATCH_REMOTE)
219                 search = SUBOPT_REMOTE_ID;
220               else if (vendor->match_type == MATCH_SUBSCRIBER)
221                 search = SUBOPT_SUBSCR_ID;
222               else 
223                 continue;
224
225               if ((sopt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), search, 1)) &&
226                   vendor->len == option_len(sopt) &&
227                   memcmp(option_ptr(sopt, 0), vendor->data, vendor->len) == 0)
228                 {
229                   vendor->netid.next = netid;
230                   netid = &vendor->netid;
231                 } 
232             }
233         }
234
235       /* Check for RFC3011 subnet selector - only if RFC3527 one not present */
236       if (subnet_addr.s_addr == 0 && (opt = option_find(mess, sz, OPTION_SUBNET_SELECT, INADDRSZ)))
237         subnet_addr = option_addr(opt);
238       
239       /* If there is no client identifier option, use the hardware address */
240       if (!option_bool(OPT_IGNORE_CLID) && (opt = option_find(mess, sz, OPTION_CLIENT_ID, 1)))
241         {
242           clid_len = option_len(opt);
243           clid = option_ptr(opt, 0);
244         }
245
246       /* do we have a lease in store? */
247       lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, clid, clid_len);
248
249       /* If this request is missing a clid, but we've seen one before, 
250          use it again for option matching etc. */
251       if (lease && !clid && lease->clid)
252         {
253           clid_len = lease->clid_len;
254           clid = lease->clid;
255         }
256
257       /* find mac to use for logging and hashing */
258       emac = extended_hwaddr(mess->htype, mess->hlen, mess->chaddr, clid_len, clid, &emac_len);
259     }
260   
261   for (mac = daemon->dhcp_macs; mac; mac = mac->next)
262     if (mac->hwaddr_len == mess->hlen &&
263         (mac->hwaddr_type == mess->htype || mac->hwaddr_type == 0) &&
264         memcmp_masked(mac->hwaddr, mess->chaddr, mess->hlen, mac->mask))
265       {
266         mac->netid.next = netid;
267         netid = &mac->netid;
268       }
269   
270   /* Determine network for this packet. Our caller will have already linked all the 
271      contexts which match the addresses of the receiving interface but if the 
272      machine has an address already, or came via a relay, or we have a subnet selector, 
273      we search again. If we don't have have a giaddr or explicit subnet selector, 
274      use the ciaddr. This is necessary because a  machine which got a lease via a 
275      relay won't use the relay to renew. If matching a ciaddr fails but we have a context 
276      from the physical network, continue using that to allow correct DHCPNAK generation later. */
277   if (mess->giaddr.s_addr || subnet_addr.s_addr || mess->ciaddr.s_addr)
278     {
279       struct dhcp_context *context_tmp, *context_new = NULL;
280       struct shared_network *share = NULL;
281       struct in_addr addr;
282       int force = 0, via_relay = 0;
283       
284       if (subnet_addr.s_addr)
285         {
286           addr = subnet_addr;
287           force = 1;
288         }
289       else if (mess->giaddr.s_addr)
290         {
291           addr = mess->giaddr;
292           force = 1;
293           via_relay = 1;
294         }
295       else
296         {
297           /* If ciaddr is in the hardware derived set of contexts, leave that unchanged */
298           addr = mess->ciaddr;
299           for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
300             if (context_tmp->netmask.s_addr && 
301                 is_same_net(addr, context_tmp->start, context_tmp->netmask) &&
302                 is_same_net(addr, context_tmp->end, context_tmp->netmask))
303               {
304                 context_new = context;
305                 break;
306               }
307         } 
308                 
309       if (!context_new)
310         {
311           for (context_tmp = daemon->dhcp; context_tmp; context_tmp = context_tmp->next)
312             {
313               struct in_addr netmask = context_tmp->netmask;
314               
315               /* guess the netmask for relayed networks */
316               if (!(context_tmp->flags & CONTEXT_NETMASK) && context_tmp->netmask.s_addr == 0)
317                 {
318                   if (IN_CLASSA(ntohl(context_tmp->start.s_addr)) && IN_CLASSA(ntohl(context_tmp->end.s_addr)))
319                     netmask.s_addr = htonl(0xff000000);
320                   else if (IN_CLASSB(ntohl(context_tmp->start.s_addr)) && IN_CLASSB(ntohl(context_tmp->end.s_addr)))
321                     netmask.s_addr = htonl(0xffff0000);
322                   else if (IN_CLASSC(ntohl(context_tmp->start.s_addr)) && IN_CLASSC(ntohl(context_tmp->end.s_addr)))
323                     netmask.s_addr = htonl(0xffffff00); 
324                 }
325
326               /* check to see is a context is OK because of a shared address on
327                  the relayed subnet. */
328               if (via_relay)
329                 for (share = daemon->shared_networks; share; share = share->next)
330                   {
331 #ifdef HAVE_DHCP6
332                     if (share->shared_addr.s_addr == 0)
333                       continue;
334 #endif
335                     if (share->if_index != 0 ||
336                         share->match_addr.s_addr != mess->giaddr.s_addr)
337                       continue;
338                     
339                     if (netmask.s_addr != 0  && 
340                         is_same_net(share->shared_addr, context_tmp->start, netmask) &&
341                         is_same_net(share->shared_addr, context_tmp->end, netmask))
342                       break;
343                   }
344               
345               /* This section fills in context mainly when a client which is on a remote (relayed)
346                  network renews a lease without using the relay, after dnsmasq has restarted. */
347               if (share ||
348                   (netmask.s_addr != 0  && 
349                    is_same_net(addr, context_tmp->start, netmask) &&
350                    is_same_net(addr, context_tmp->end, netmask)))
351                 {
352                   context_tmp->netmask = netmask;
353                   if (context_tmp->local.s_addr == 0)
354                     context_tmp->local = fallback;
355                   if (context_tmp->router.s_addr == 0 && !share)
356                     context_tmp->router = mess->giaddr;
357                   
358                   /* fill in missing broadcast addresses for relayed ranges */
359                   if (!(context_tmp->flags & CONTEXT_BRDCAST) && context_tmp->broadcast.s_addr == 0 )
360                     context_tmp->broadcast.s_addr = context_tmp->start.s_addr | ~context_tmp->netmask.s_addr;
361                   
362                   context_tmp->current = context_new;
363                   context_new = context_tmp;
364                 }
365               
366             }
367         }
368           
369       if (context_new || force)
370         context = context_new; 
371     }
372   
373   if (!context)
374     {
375       const char *via;
376       if (subnet_addr.s_addr)
377         {
378           via = _("with subnet selector");
379           inet_ntop(AF_INET, &subnet_addr, daemon->addrbuff, ADDRSTRLEN);
380         }
381       else
382         {
383           via = _("via");
384           if (mess->giaddr.s_addr)
385             inet_ntop(AF_INET, &mess->giaddr, daemon->addrbuff, ADDRSTRLEN);
386           else
387             safe_strncpy(daemon->addrbuff, iface_name, ADDRSTRLEN);
388         }
389       my_syslog(MS_DHCP | LOG_WARNING, _("no address range available for DHCP request %s %s"),
390                 via, daemon->addrbuff);
391       return 0;
392     }
393
394   if (option_bool(OPT_LOG_OPTS))
395     {
396       struct dhcp_context *context_tmp;
397       for (context_tmp = context; context_tmp; context_tmp = context_tmp->current)
398         {
399           inet_ntop(AF_INET, &context_tmp->start, daemon->namebuff, MAXDNAME);
400           if (context_tmp->flags & (CONTEXT_STATIC | CONTEXT_PROXY))
401             {
402               inet_ntop(AF_INET, &context_tmp->netmask, daemon->addrbuff, ADDRSTRLEN);
403               my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP subnet: %s/%s"),
404                         ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
405             }
406           else
407             {
408               inet_ntop(AF_INET, &context_tmp->end, daemon->addrbuff, ADDRSTRLEN);
409               my_syslog(MS_DHCP | LOG_INFO, _("%u available DHCP range: %s -- %s"),
410                         ntohl(mess->xid), daemon->namebuff, daemon->addrbuff);
411             }
412         }
413     }
414   
415   /* dhcp-match. If we have hex-and-wildcards, look for a left-anchored match.
416      Otherwise assume the option is an array, and look for a matching element. 
417      If no data given, existence of the option is enough. This code handles 
418      rfc3925 V-I classes too. */
419   for (o = daemon->dhcp_match; o; o = o->next)
420     {
421       unsigned int len, elen, match = 0;
422       size_t offset, o2;
423
424       if (o->flags & DHOPT_RFC3925)
425         {
426           if (!(opt = option_find(mess, sz, OPTION_VENDOR_IDENT, 5)))
427             continue;
428           
429           for (offset = 0; offset < (option_len(opt) - 5u); offset += len + 5)
430             {
431               len = option_uint(opt, offset + 4 , 1);
432               /* Need to take care that bad data can't run us off the end of the packet */
433               if ((offset + len + 5 <= (unsigned)(option_len(opt))) &&
434                   (option_uint(opt, offset, 4) == (unsigned int)o->u.encap))
435                 for (o2 = offset + 5; o2 < offset + len + 5; o2 += elen + 1)
436                   { 
437                     elen = option_uint(opt, o2, 1);
438                     if ((o2 + elen + 1 <= (unsigned)option_len(opt)) &&
439                         (match = match_bytes(o, option_ptr(opt, o2 + 1), elen)))
440                       break;
441                   }
442               if (match) 
443                 break;
444             }     
445         }
446       else
447         {
448           if (!(opt = option_find(mess, sz, o->opt, 1)))
449             continue;
450           
451           match = match_bytes(o, option_ptr(opt, 0), option_len(opt));
452         } 
453
454       if (match)
455         {
456           o->netid->next = netid;
457           netid = o->netid;
458         }
459     }
460         
461   /* user-class options are, according to RFC3004, supposed to contain
462      a set of counted strings. Here we check that this is so (by seeing
463      if the counts are consistent with the overall option length) and if
464      so zero the counts so that we don't get spurious matches between 
465      the vendor string and the counts. If the lengths don't add up, we
466      assume that the option is a single string and non RFC3004 compliant 
467      and just do the substring match. dhclient provides these broken options.
468      The code, later, which sends user-class data to the lease-change script
469      relies on the transformation done here.
470   */
471
472   if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
473     {
474       unsigned char *ucp = option_ptr(opt, 0);
475       int tmp, j;
476       for (j = 0; j < option_len(opt); j += ucp[j] + 1);
477       if (j == option_len(opt))
478         for (j = 0; j < option_len(opt); j = tmp)
479           {
480             tmp = j + ucp[j] + 1;
481             ucp[j] = 0;
482           }
483     }
484     
485   for (vendor = daemon->dhcp_vendors; vendor; vendor = vendor->next)
486     {
487       int mopt;
488       
489       if (vendor->match_type == MATCH_VENDOR)
490         mopt = OPTION_VENDOR_ID;
491       else if (vendor->match_type == MATCH_USER)
492         mopt = OPTION_USER_CLASS; 
493       else
494         continue;
495
496       if ((opt = option_find(mess, sz, mopt, 1)))
497         {
498           int i;
499           for (i = 0; i <= (option_len(opt) - vendor->len); i++)
500             if (memcmp(vendor->data, option_ptr(opt, i), vendor->len) == 0)
501               {
502                 vendor->netid.next = netid;
503                 netid = &vendor->netid;
504                 break;
505               }
506         }
507     }
508
509   /* mark vendor-encapsulated options which match the client-supplied vendor class,
510      save client-supplied vendor class */
511   if ((opt = option_find(mess, sz, OPTION_VENDOR_ID, 1)))
512     {
513       memcpy(daemon->dhcp_buff3, option_ptr(opt, 0), option_len(opt));
514       vendor_class_len = option_len(opt);
515     }
516   match_vendor_opts(opt, daemon->dhcp_opts);
517   
518   if (option_bool(OPT_LOG_OPTS))
519     {
520       if (sanitise(opt, daemon->namebuff))
521         my_syslog(MS_DHCP | LOG_INFO, _("%u vendor class: %s"), ntohl(mess->xid), daemon->namebuff);
522       if (sanitise(option_find(mess, sz, OPTION_USER_CLASS, 1), daemon->namebuff))
523         my_syslog(MS_DHCP | LOG_INFO, _("%u user class: %s"), ntohl(mess->xid), daemon->namebuff);
524     }
525
526   mess->op = BOOTREPLY;
527   
528   config = find_config(daemon->dhcp_conf, context, clid, clid_len, 
529                        mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid));
530
531   /* set "known" tag for known hosts */
532   if (config)
533     {
534       known_id.net = "known";
535       known_id.next = netid;
536       netid = &known_id;
537     }
538   else if (find_config(daemon->dhcp_conf, NULL, clid, clid_len, 
539                        mess->chaddr, mess->hlen, mess->htype, NULL, run_tag_if(netid)))
540     {
541       known_id.net = "known-othernet";
542       known_id.next = netid;
543       netid = &known_id;
544     }
545   
546   if (mess_type == 0 && !pxe)
547     {
548       /* BOOTP request */
549       struct dhcp_netid id, bootp_id;
550       struct in_addr *logaddr = NULL;
551
552       /* must have a MAC addr for bootp */
553       if (mess->htype == 0 || mess->hlen == 0 || (context->flags & CONTEXT_PROXY))
554         return 0;
555       
556       if (have_config(config, CONFIG_DISABLE))
557         message = _("disabled");
558
559       end = mess->options + 64; /* BOOTP vend area is only 64 bytes */
560             
561       if (have_config(config, CONFIG_NAME))
562         {
563           hostname = config->hostname;
564           domain = config->domain;
565         }
566
567       if (config)
568         {
569           struct dhcp_netid_list *list;
570
571           for (list = config->netid; list; list = list->next)
572             {
573               list->list->next = netid;
574               netid = list->list;
575             }
576         }
577
578       /* Match incoming filename field as a netid. */
579       if (mess->file[0])
580         {
581           memcpy(daemon->dhcp_buff2, mess->file, sizeof(mess->file));
582           daemon->dhcp_buff2[sizeof(mess->file) + 1] = 0; /* ensure zero term. */
583           id.net = (char *)daemon->dhcp_buff2;
584           id.next = netid;
585           netid = &id;
586         }
587
588       /* Add "bootp" as a tag to allow different options, address ranges etc
589          for BOOTP clients */
590       bootp_id.net = "bootp";
591       bootp_id.next = netid;
592       netid = &bootp_id;
593       
594       tagif_netid = run_tag_if(netid);
595
596       for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
597         if (match_netid(id_list->list, tagif_netid, 0))
598           message = _("ignored");
599       
600       if (!message)
601         {
602           int nailed = 0;
603
604           if (have_config(config, CONFIG_ADDR))
605             {
606               nailed = 1;
607               logaddr = &config->addr;
608               mess->yiaddr = config->addr;
609               if ((lease = lease_find_by_addr(config->addr)) &&
610                   (lease->hwaddr_len != mess->hlen ||
611                    lease->hwaddr_type != mess->htype ||
612                    memcmp(lease->hwaddr, mess->chaddr, lease->hwaddr_len) != 0))
613                 message = _("address in use");
614             }
615           else
616             {
617               if (!(lease = lease_find_by_client(mess->chaddr, mess->hlen, mess->htype, NULL, 0)) ||
618                   !address_available(context, lease->addr, tagif_netid))
619                 {
620                    if (lease)
621                      {
622                        /* lease exists, wrong network. */
623                        lease_prune(lease, now);
624                        lease = NULL;
625                      }
626                    if (!address_allocate(context, &mess->yiaddr, mess->chaddr, mess->hlen, tagif_netid, now, loopback))
627                      message = _("no address available");
628                 }
629               else
630                 mess->yiaddr = lease->addr;
631             }
632           
633           if (!message && !(context = narrow_context(context, mess->yiaddr, netid)))
634             message = _("wrong network");
635           else if (context->netid.net)
636             {
637               context->netid.next = netid;
638               tagif_netid = run_tag_if(&context->netid);
639             }
640
641           log_tags(tagif_netid, ntohl(mess->xid));
642             
643           if (!message && !nailed)
644             {
645               for (id_list = daemon->bootp_dynamic; id_list; id_list = id_list->next)
646                 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
647                   break;
648               if (!id_list)
649                 message = _("no address configured");
650             }
651
652           if (!message && 
653               !lease && 
654               (!(lease = lease4_allocate(mess->yiaddr))))
655             message = _("no leases left");
656           
657           if (!message)
658             {
659               logaddr = &mess->yiaddr;
660                 
661               lease_set_hwaddr(lease, mess->chaddr, NULL, mess->hlen, mess->htype, 0, now, 1);
662               if (hostname)
663                 lease_set_hostname(lease, hostname, 1, get_domain(lease->addr), domain); 
664               /* infinite lease unless nailed in dhcp-host line. */
665               lease_set_expires(lease,  
666                                 have_config(config, CONFIG_TIME) ? config->lease_time : 0xffffffff, 
667                                 now); 
668               lease_set_interface(lease, int_index, now);
669               
670               clear_packet(mess, end);
671               do_options(context, mess, end, NULL, hostname, get_domain(mess->yiaddr), 
672                          netid, subnet_addr, 0, 0, -1, NULL, vendor_class_len, now, 0xffffffff, 0, NULL);
673             }
674         }
675       
676       daemon->metrics[METRIC_BOOTP]++;
677       log_packet("BOOTP", logaddr, mess->chaddr, mess->hlen, iface_name, NULL, message, mess->xid);
678       
679       return message ? 0 : dhcp_packet_size(mess, agent_id, real_end);
680     }
681       
682   if ((opt = option_find(mess, sz, OPTION_CLIENT_FQDN, 3)))
683     {
684       /* http://tools.ietf.org/wg/dhc/draft-ietf-dhc-fqdn-option/draft-ietf-dhc-fqdn-option-10.txt */
685       int len = option_len(opt);
686       char *pq = daemon->dhcp_buff;
687       unsigned char *pp, *op = option_ptr(opt, 0);
688       
689       fqdn_flags = *op;
690       len -= 3;
691       op += 3;
692       pp = op;
693       
694       /* NB, the following always sets at least one bit */
695       if (option_bool(OPT_FQDN_UPDATE))
696         {
697           if (fqdn_flags & 0x01)
698             {
699               fqdn_flags |= 0x02; /* set O */
700               fqdn_flags &= ~0x01; /* clear S */
701             }
702           fqdn_flags |= 0x08; /* set N */
703         }
704       else 
705         {
706           if (!(fqdn_flags & 0x01))
707             fqdn_flags |= 0x03; /* set S and O */
708           fqdn_flags &= ~0x08; /* clear N */
709         }
710       
711       if (fqdn_flags & 0x04)
712         while (*op != 0 && ((op + (*op)) - pp) < len)
713           {
714             memcpy(pq, op+1, *op);
715             pq += *op;
716             op += (*op)+1;
717             *(pq++) = '.';
718           }
719       else
720         {
721           memcpy(pq, op, len);
722           if (len > 0 && op[len-1] == 0)
723             borken_opt = 1;
724           pq += len + 1;
725         }
726       
727       if (pq != daemon->dhcp_buff)
728         pq--;
729       
730       *pq = 0;
731       
732       if (legal_hostname(daemon->dhcp_buff))
733         offer_hostname = client_hostname = daemon->dhcp_buff;
734     }
735   else if ((opt = option_find(mess, sz, OPTION_HOSTNAME, 1)))
736     {
737       int len = option_len(opt);
738       memcpy(daemon->dhcp_buff, option_ptr(opt, 0), len);
739       /* Microsoft clients are broken, and need zero-terminated strings
740          in options. We detect this state here, and do the same in
741          any options we send */
742       if (len > 0 && daemon->dhcp_buff[len-1] == 0)
743         borken_opt = 1;
744       else
745         daemon->dhcp_buff[len] = 0;
746       if (legal_hostname(daemon->dhcp_buff))
747         client_hostname = daemon->dhcp_buff;
748     }
749
750   if (client_hostname)
751     {
752       struct dhcp_match_name *m;
753       size_t nl = strlen(client_hostname);
754       
755       if (option_bool(OPT_LOG_OPTS))
756         my_syslog(MS_DHCP | LOG_INFO, _("%u client provides name: %s"), ntohl(mess->xid), client_hostname);
757       for (m = daemon->dhcp_name_match; m; m = m->next)
758         {
759           size_t ml = strlen(m->name);
760           char save = 0;
761           
762           if (nl < ml)
763             continue;
764           if (nl > ml)
765             {
766               save = client_hostname[ml];
767               client_hostname[ml] = 0;
768             }
769           
770           if (hostname_isequal(client_hostname, m->name) &&
771               (save == 0 || m->wildcard))
772             {
773               m->netid->next = netid;
774               netid = m->netid;
775             }
776           
777           if (save != 0)
778             client_hostname[ml] = save;
779         }
780     }
781   
782   if (have_config(config, CONFIG_NAME))
783     {
784       hostname = config->hostname;
785       domain = config->domain;
786       hostname_auth = 1;
787       /* be careful not to send an OFFER with a hostname not matching the DISCOVER. */
788       if (fqdn_flags != 0 || !client_hostname || hostname_isequal(hostname, client_hostname))
789         offer_hostname = hostname;
790     }
791   else if (client_hostname)
792     {
793       domain = strip_hostname(client_hostname);
794       
795       if (strlen(client_hostname) != 0)
796         {
797           hostname = client_hostname;
798           
799           if (!config)
800             {
801               /* Search again now we have a hostname. 
802                  Only accept configs without CLID and HWADDR here, (they won't match)
803                  to avoid impersonation by name. */
804               struct dhcp_config *new = find_config(daemon->dhcp_conf, context, NULL, 0,
805                                                     mess->chaddr, mess->hlen, 
806                                                     mess->htype, hostname, run_tag_if(netid));
807               if (new && !have_config(new, CONFIG_CLID) && !new->hwaddr)
808                 {
809                   config = new;
810                   /* set "known" tag for known hosts */
811                   known_id.net = "known";
812                   known_id.next = netid;
813                   netid = &known_id;
814                 }
815             }
816         }
817     }
818   
819   if (config)
820     {
821       struct dhcp_netid_list *list;
822       
823       for (list = config->netid; list; list = list->next)
824         {
825           list->list->next = netid;
826           netid = list->list;
827         }
828     }
829   
830   tagif_netid = run_tag_if(netid);
831   
832   /* if all the netids in the ignore list are present, ignore this client */
833   for (id_list = daemon->dhcp_ignore; id_list; id_list = id_list->next)
834     if (match_netid(id_list->list, tagif_netid, 0))
835       ignore = 1;
836
837   /* If configured, we can override the server-id to be the address of the relay, 
838      so that all traffic goes via the relay and can pick up agent-id info. This can be
839      configured for all relays, or by address. */
840   if (daemon->override && mess->giaddr.s_addr != 0 && override.s_addr == 0)
841     {
842       if (!daemon->override_relays)
843         override = mess->giaddr;
844       else
845         {
846           struct addr_list *l;
847           for (l = daemon->override_relays; l; l = l->next)
848             if (l->addr.s_addr == mess->giaddr.s_addr)
849               break;
850           if (l)
851             override = mess->giaddr;
852         }
853     }
854
855   /* Can have setting to ignore the client ID for a particular MAC address or hostname */
856   if (have_config(config, CONFIG_NOCLID))
857     clid = NULL;
858           
859   /* Check if client is PXE client. */
860   if (daemon->enable_pxe &&
861       is_pxe_client(mess, sz, &pxevendor))
862     {
863       if ((opt = option_find(mess, sz, OPTION_PXE_UUID, 17)))
864         {
865           memcpy(pxe_uuid, option_ptr(opt, 0), 17);
866           uuid = pxe_uuid;
867         }
868
869       /* Check if this is really a PXE bootserver request, and handle specially if so. */
870       if ((mess_type == DHCPREQUEST || mess_type == DHCPINFORM) &&
871           (opt = option_find(mess, sz, OPTION_VENDOR_CLASS_OPT, 1)) &&
872           (opt = option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_PXE_BOOT_ITEM, 4)))
873         {
874           struct pxe_service *service;
875           int type = option_uint(opt, 0, 2);
876           int layer = option_uint(opt, 2, 2);
877           unsigned char save71[4];
878           struct dhcp_opt opt71;
879
880           if (ignore)
881             return 0;
882
883           if (layer & 0x8000)
884             {
885               my_syslog(MS_DHCP | LOG_ERR, _("PXE BIS not supported"));
886               return 0;
887             }
888
889           memcpy(save71, option_ptr(opt, 0), 4);
890           
891           for (service = daemon->pxe_services; service; service = service->next)
892             if (service->type == type)
893               break;
894           
895           for (; context; context = context->current)
896             if (match_netid(context->filter, tagif_netid, 1) &&
897                 is_same_net(mess->ciaddr, context->start, context->netmask))
898               break;
899           
900           if (!service || !service->basename || !context)
901             return 0;
902                   
903           clear_packet(mess, end);
904           
905           mess->yiaddr = mess->ciaddr;
906           mess->ciaddr.s_addr = 0;
907           if (service->sname)
908             mess->siaddr = a_record_from_hosts(service->sname, now);
909           else if (service->server.s_addr != 0)
910             mess->siaddr = service->server; 
911           else
912             mess->siaddr = context->local; 
913           
914           if (strchr(service->basename, '.'))
915             snprintf((char *)mess->file, sizeof(mess->file),
916                 "%s", service->basename);
917           else
918             snprintf((char *)mess->file, sizeof(mess->file),
919                 "%s.%d", service->basename, layer);
920           
921           option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
922           option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(context->local.s_addr));
923           pxe_misc(mess, end, uuid, pxevendor);
924           
925           prune_vendor_opts(tagif_netid);
926           opt71.val = save71;
927           opt71.opt = SUBOPT_PXE_BOOT_ITEM;
928           opt71.len = 4;
929           opt71.flags = DHOPT_VENDOR_MATCH;
930           opt71.netid = NULL;
931           opt71.next = daemon->dhcp_opts;
932           do_encap_opts(&opt71, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
933           
934           log_packet("PXE", &mess->yiaddr, emac, emac_len, iface_name, (char *)mess->file, NULL, mess->xid);
935           log_tags(tagif_netid, ntohl(mess->xid));
936           return dhcp_packet_size(mess, agent_id, real_end);      
937         }
938       
939       if ((opt = option_find(mess, sz, OPTION_ARCH, 2)))
940         {
941           pxearch = option_uint(opt, 0, 2);
942
943           /* proxy DHCP here. */
944           if ((mess_type == DHCPDISCOVER || (pxe && mess_type == DHCPREQUEST)))
945             {
946               struct dhcp_context *tmp;
947               int workaround = 0;
948               
949               for (tmp = context; tmp; tmp = tmp->current)
950                 if ((tmp->flags & CONTEXT_PROXY) &&
951                     match_netid(tmp->filter, tagif_netid, 1))
952                   break;
953               
954               if (tmp)
955                 {
956                   struct dhcp_boot *boot;
957                   int redirect4011 = 0;
958
959                   if (tmp->netid.net)
960                     {
961                       tmp->netid.next = netid;
962                       tagif_netid = run_tag_if(&tmp->netid);
963                     }
964                   
965                   boot = find_boot(tagif_netid);
966                   
967                   mess->yiaddr.s_addr = 0;
968                   if  (mess_type == DHCPDISCOVER || mess->ciaddr.s_addr == 0)
969                     {
970                       mess->ciaddr.s_addr = 0;
971                       mess->flags |= htons(0x8000); /* broadcast */
972                     }
973                   
974                   clear_packet(mess, end);
975                   
976                   /* Redirect EFI clients to port 4011 */
977                   if (pxearch >= 6)
978                     {
979                       redirect4011 = 1;
980                       mess->siaddr = tmp->local;
981                     }
982                   
983                   /* Returns true if only one matching service is available. On port 4011, 
984                      it also inserts the boot file and server name. */
985                   workaround = pxe_uefi_workaround(pxearch, tagif_netid, mess, tmp->local, now, pxe);
986                   
987                   if (!workaround && boot)
988                     {
989                       /* Provide the bootfile here, for iPXE, and in case we have no menu items
990                          and set discovery_control = 8 */
991                       if (boot->next_server.s_addr) 
992                         mess->siaddr = boot->next_server;
993                       else if (boot->tftp_sname) 
994                         mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
995                       
996                       if (boot->file)
997                         safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
998                     }
999                   
1000                   option_put(mess, end, OPTION_MESSAGE_TYPE, 1, 
1001                              mess_type == DHCPDISCOVER ? DHCPOFFER : DHCPACK);
1002                   option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, htonl(tmp->local.s_addr));
1003                   pxe_misc(mess, end, uuid, pxevendor);
1004                   prune_vendor_opts(tagif_netid);
1005                   if ((pxe && !workaround) || !redirect4011)
1006                     do_encap_opts(pxe_opts(pxearch, tagif_netid, tmp->local, now), OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, 0);
1007             
1008                   daemon->metrics[METRIC_PXE]++;
1009                   log_packet("PXE", NULL, emac, emac_len, iface_name, ignore ? "proxy-ignored" : "proxy", NULL, mess->xid);
1010                   log_tags(tagif_netid, ntohl(mess->xid));
1011                   if (!ignore)
1012                     apply_delay(mess->xid, recvtime, tagif_netid);
1013                   return ignore ? 0 : dhcp_packet_size(mess, agent_id, real_end);         
1014                 }
1015             }
1016         }
1017     }
1018
1019   /* if we're just a proxy server, go no further */
1020   if ((context->flags & CONTEXT_PROXY) || pxe)
1021     return 0;
1022   
1023   if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
1024     {
1025       req_options = (unsigned char *)daemon->dhcp_buff2;
1026       memcpy(req_options, option_ptr(opt, 0), option_len(opt));
1027       req_options[option_len(opt)] = OPTION_END;
1028     }
1029   
1030   switch (mess_type)
1031     {
1032     case DHCPDECLINE:
1033       if (!(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
1034           option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
1035         return 0;
1036       
1037       /* sanitise any message. Paranoid? Moi? */
1038       sanitise(option_find(mess, sz, OPTION_MESSAGE, 1), daemon->dhcp_buff);
1039       
1040       if (!(opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1041         return 0;
1042       
1043       daemon->metrics[METRIC_DHCPDECLINE]++;
1044       log_packet("DHCPDECLINE", option_ptr(opt, 0), emac, emac_len, iface_name, NULL, daemon->dhcp_buff, mess->xid);
1045       
1046       if (lease && lease->addr.s_addr == option_addr(opt).s_addr)
1047         lease_prune(lease, now);
1048       
1049       if (have_config(config, CONFIG_ADDR) && 
1050           config->addr.s_addr == option_addr(opt).s_addr)
1051         {
1052           prettyprint_time(daemon->dhcp_buff, DECLINE_BACKOFF);
1053           inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
1054           my_syslog(MS_DHCP | LOG_WARNING, _("disabling DHCP static address %s for %s"), 
1055                     daemon->addrbuff, daemon->dhcp_buff);
1056           config->flags |= CONFIG_DECLINED;
1057           config->decline_time = now;
1058         }
1059       else
1060         /* make sure this host gets a different address next time. */
1061         for (; context; context = context->current)
1062           context->addr_epoch++;
1063       
1064       return 0;
1065
1066     case DHCPRELEASE:
1067       if (!(context = narrow_context(context, mess->ciaddr, tagif_netid)) ||
1068           !(opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)) ||
1069           option_addr(opt).s_addr != server_id(context, override, fallback).s_addr)
1070         return 0;
1071       
1072       if (lease && lease->addr.s_addr == mess->ciaddr.s_addr)
1073         lease_prune(lease, now);
1074       else
1075         message = _("unknown lease");
1076
1077       daemon->metrics[METRIC_DHCPRELEASE]++;
1078       log_packet("DHCPRELEASE", &mess->ciaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
1079         
1080       return 0;
1081       
1082     case DHCPDISCOVER:
1083       if (ignore || have_config(config, CONFIG_DISABLE))
1084         {
1085           if (option_bool(OPT_QUIET_DHCP))
1086             return 0;
1087           message = _("ignored");
1088           opt = NULL;
1089         }
1090       else 
1091         {
1092           struct in_addr addr, conf;
1093           
1094           addr.s_addr = conf.s_addr = 0;
1095
1096           if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))      
1097             addr = option_addr(opt);
1098           
1099           if (have_config(config, CONFIG_ADDR))
1100             {
1101               inet_ntop(AF_INET, &config->addr, daemon->addrbuff, ADDRSTRLEN);
1102               
1103               if ((ltmp = lease_find_by_addr(config->addr)) && 
1104                   ltmp != lease &&
1105                   !config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1106                 {
1107                   int len;
1108                   unsigned char *mac = extended_hwaddr(ltmp->hwaddr_type, ltmp->hwaddr_len,
1109                                                        ltmp->hwaddr, ltmp->clid_len, ltmp->clid, &len);
1110                   my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is leased to %s"),
1111                             daemon->addrbuff, print_mac(daemon->namebuff, mac, len));
1112                 }
1113               else
1114                 {
1115                   struct dhcp_context *tmp;
1116                   for (tmp = context; tmp; tmp = tmp->current)
1117                     if (context->router.s_addr == config->addr.s_addr)
1118                       break;
1119                   if (tmp)
1120                     my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it is in use by the server or relay"), daemon->addrbuff);
1121                   else if (have_config(config, CONFIG_DECLINED) &&
1122                            difftime(now, config->decline_time) < (float)DECLINE_BACKOFF)
1123                     my_syslog(MS_DHCP | LOG_WARNING, _("not using configured address %s because it was previously declined"), daemon->addrbuff);
1124                   else
1125                     conf = config->addr;
1126                 }
1127             }
1128           
1129           if (conf.s_addr)
1130             mess->yiaddr = conf;
1131           else if (lease && 
1132                    address_available(context, lease->addr, tagif_netid) && 
1133                    !config_find_by_address(daemon->dhcp_conf, lease->addr))
1134             mess->yiaddr = lease->addr;
1135           else if (opt && address_available(context, addr, tagif_netid) && !lease_find_by_addr(addr) && 
1136                    !config_find_by_address(daemon->dhcp_conf, addr) && do_icmp_ping(now, addr, 0, loopback))
1137             mess->yiaddr = addr;
1138           else if (emac_len == 0)
1139             message = _("no unique-id");
1140           else if (!address_allocate(context, &mess->yiaddr, emac, emac_len, tagif_netid, now, loopback))
1141             message = _("no address available");      
1142         }
1143       
1144       daemon->metrics[METRIC_DHCPDISCOVER]++;
1145       log_packet("DHCPDISCOVER", opt ? option_ptr(opt, 0) : NULL, emac, emac_len, iface_name, NULL, message, mess->xid); 
1146
1147       if (message || !(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1148         return 0;
1149
1150       if (context->netid.net)
1151         {
1152           context->netid.next = netid;
1153           tagif_netid = run_tag_if(&context->netid);
1154         }
1155
1156       apply_delay(mess->xid, recvtime, tagif_netid);
1157
1158       if (option_bool(OPT_RAPID_COMMIT) && option_find(mess, sz, OPTION_RAPID_COMMIT, 0))
1159         {
1160           rapid_commit = 1;
1161           /* If a lease exists for this host and another address, squash it. */
1162           if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1163             {
1164               lease_prune(lease, now);
1165               lease = NULL;
1166             }
1167           goto rapid_commit;
1168         }
1169       
1170       log_tags(tagif_netid, ntohl(mess->xid));
1171
1172       daemon->metrics[METRIC_DHCPOFFER]++;
1173       log_packet("DHCPOFFER" , &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1174       
1175       time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1176       clear_packet(mess, end);
1177       option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPOFFER);
1178       option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1179       option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1180       /* T1 and T2 are required in DHCPOFFER by HP's wacky Jetdirect client. */
1181       do_options(context, mess, end, req_options, offer_hostname, get_domain(mess->yiaddr), 
1182                  netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
1183       
1184       return dhcp_packet_size(mess, agent_id, real_end);
1185         
1186
1187     case DHCPREQUEST:
1188       if (ignore || have_config(config, CONFIG_DISABLE))
1189         return 0;
1190       if ((opt = option_find(mess, sz, OPTION_REQUESTED_IP, INADDRSZ)))
1191         {
1192           /* SELECTING  or INIT_REBOOT */
1193           mess->yiaddr = option_addr(opt);
1194           
1195           /* send vendor and user class info for new or recreated lease */
1196           do_classes = 1;
1197           
1198           if ((opt = option_find(mess, sz, OPTION_SERVER_IDENTIFIER, INADDRSZ)))
1199             {
1200               /* SELECTING */
1201               selecting = 1;
1202               
1203               if (override.s_addr != 0)
1204                 {
1205                   if (option_addr(opt).s_addr != override.s_addr)
1206                     return 0;
1207                 }
1208               else 
1209                 {
1210                   for (; context; context = context->current)
1211                     if (context->local.s_addr == option_addr(opt).s_addr)
1212                       break;
1213                   
1214                   if (!context)
1215                     {
1216                       /* Handle very strange configs where clients have more than one route to the server.
1217                          If a clients idea of its server-id matches any of our DHCP interfaces, we let it pass.
1218                          Have to set override to make sure we echo back the correct server-id */
1219                       struct irec *intr;
1220                       
1221                       enumerate_interfaces(0);
1222
1223                       for (intr = daemon->interfaces; intr; intr = intr->next)
1224                         if (intr->addr.sa.sa_family == AF_INET &&
1225                             intr->addr.in.sin_addr.s_addr == option_addr(opt).s_addr &&
1226                             intr->tftp_ok)
1227                           break;
1228
1229                       if (intr)
1230                         override = intr->addr.in.sin_addr;
1231                       else
1232                         {
1233                           /* In auth mode, a REQUEST sent to the wrong server
1234                              should be faulted, so that the client establishes 
1235                              communication with us, otherwise, silently ignore. */
1236                           if (!option_bool(OPT_AUTHORITATIVE))
1237                             return 0;
1238                           message = _("wrong server-ID");
1239                         }
1240                     }
1241                 }
1242
1243               /* If a lease exists for this host and another address, squash it. */
1244               if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1245                 {
1246                   lease_prune(lease, now);
1247                   lease = NULL;
1248                 }
1249             }
1250           else
1251             {
1252               /* INIT-REBOOT */
1253               if (!lease && !option_bool(OPT_AUTHORITATIVE))
1254                 return 0;
1255               
1256               if (lease && lease->addr.s_addr != mess->yiaddr.s_addr)
1257                 message = _("wrong address");
1258             }
1259         }
1260       else
1261         {
1262           /* RENEWING or REBINDING */ 
1263           /* Check existing lease for this address.
1264              We allow it to be missing if dhcp-authoritative mode
1265              as long as we can allocate the lease now - checked below.
1266              This makes for a smooth recovery from a lost lease DB */
1267           if ((lease && mess->ciaddr.s_addr != lease->addr.s_addr) ||
1268               (!lease && !option_bool(OPT_AUTHORITATIVE)))
1269             {
1270               /* A client rebinding will broadcast the request, so we may see it even 
1271                  if the lease is held by another server. Just ignore it in that case. 
1272                  If the request is unicast to us, then somethings wrong, NAK */
1273               if (!unicast_dest)
1274                 return 0;
1275               message = _("lease not found");
1276               /* ensure we broadcast NAK */
1277               unicast_dest = 0;
1278             }
1279
1280           /* desynchronise renewals */
1281           fuzz = rand16();
1282           mess->yiaddr = mess->ciaddr;
1283         }
1284
1285       daemon->metrics[METRIC_DHCPREQUEST]++;
1286       log_packet("DHCPREQUEST", &mess->yiaddr, emac, emac_len, iface_name, NULL, NULL, mess->xid);
1287       
1288     rapid_commit:
1289       if (!message)
1290         {
1291           struct dhcp_config *addr_config;
1292           struct dhcp_context *tmp = NULL;
1293           
1294           if (have_config(config, CONFIG_ADDR))
1295             for (tmp = context; tmp; tmp = tmp->current)
1296               if (context->router.s_addr == config->addr.s_addr)
1297                 break;
1298           
1299           if (!(context = narrow_context(context, mess->yiaddr, tagif_netid)))
1300             {
1301               /* If a machine moves networks whilst it has a lease, we catch that here. */
1302               message = _("wrong network");
1303               /* ensure we broadcast NAK */
1304               unicast_dest = 0;
1305             }
1306           
1307           /* Check for renewal of a lease which is outside the allowed range. */
1308           else if (!address_available(context, mess->yiaddr, tagif_netid) &&
1309                    (!have_config(config, CONFIG_ADDR) || config->addr.s_addr != mess->yiaddr.s_addr))
1310             message = _("address not available");
1311           
1312           /* Check if a new static address has been configured. Be very sure that
1313              when the client does DISCOVER, it will get the static address, otherwise
1314              an endless protocol loop will ensue. */
1315           else if (!tmp && !selecting &&
1316                    have_config(config, CONFIG_ADDR) && 
1317                    (!have_config(config, CONFIG_DECLINED) ||
1318                     difftime(now, config->decline_time) > (float)DECLINE_BACKOFF) &&
1319                    config->addr.s_addr != mess->yiaddr.s_addr &&
1320                    (!(ltmp = lease_find_by_addr(config->addr)) || ltmp == lease))
1321             message = _("static lease available");
1322
1323           /* Check to see if the address is reserved as a static address for another host */
1324           else if ((addr_config = config_find_by_address(daemon->dhcp_conf, mess->yiaddr)) && addr_config != config)
1325             message = _("address reserved");
1326
1327           else if (!lease && (ltmp = lease_find_by_addr(mess->yiaddr)))
1328             {
1329               /* If a host is configured with more than one MAC address, it's OK to 'nix 
1330                  a lease from one of it's MACs to give the address to another. */
1331               if (config && config_has_mac(config, ltmp->hwaddr, ltmp->hwaddr_len, ltmp->hwaddr_type))
1332                 {
1333                   inet_ntop(AF_INET, &ltmp->addr, daemon->addrbuff, ADDRSTRLEN);
1334                   my_syslog(MS_DHCP | LOG_INFO, _("abandoning lease to %s of %s"),
1335                             print_mac(daemon->namebuff, ltmp->hwaddr, ltmp->hwaddr_len), 
1336                             daemon->addrbuff);
1337                   lease = ltmp;
1338                 }
1339               else
1340                 message = _("address in use");
1341             }
1342
1343           if (!message)
1344             {
1345               if (emac_len == 0)
1346                 message = _("no unique-id");
1347               
1348               else if (!lease)
1349                 {            
1350                   if ((lease = lease4_allocate(mess->yiaddr)))
1351                     do_classes = 1;
1352                   else
1353                     message = _("no leases left");
1354                 }
1355             }
1356         }
1357
1358       if (message)
1359         {
1360           daemon->metrics[rapid_commit ? METRIC_NOANSWER : METRIC_DHCPNAK]++;
1361           log_packet(rapid_commit ? "NOANSWER" : "DHCPNAK", &mess->yiaddr, emac, emac_len, iface_name, NULL, message, mess->xid);
1362
1363           /* rapid commit case: lease allocate failed but don't send DHCPNAK */
1364           if (rapid_commit)
1365             return 0;
1366           
1367           mess->yiaddr.s_addr = 0;
1368           clear_packet(mess, end);
1369           option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPNAK);
1370           option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1371           option_put_string(mess, end, OPTION_MESSAGE, message, borken_opt);
1372           /* This fixes a problem with the DHCP spec, broadcasting a NAK to a host on 
1373              a distant subnet which unicast a REQ to us won't work. */
1374           if (!unicast_dest || mess->giaddr.s_addr != 0 || 
1375               mess->ciaddr.s_addr == 0 || is_same_net(context->local, mess->ciaddr, context->netmask))
1376             {
1377               mess->flags |= htons(0x8000); /* broadcast */
1378               mess->ciaddr.s_addr = 0;
1379             }
1380         }
1381       else
1382         {
1383           if (context->netid.net)
1384             {
1385               context->netid.next = netid;
1386               tagif_netid = run_tag_if( &context->netid);
1387             }
1388
1389           log_tags(tagif_netid, ntohl(mess->xid));
1390           
1391           if (do_classes)
1392             {
1393               /* pick up INIT-REBOOT events. */
1394               lease->flags |= LEASE_CHANGED;
1395
1396 #ifdef HAVE_SCRIPT
1397               if (daemon->lease_change_command)
1398                 {
1399                   struct dhcp_netid *n;
1400                   
1401                   if (mess->giaddr.s_addr)
1402                     lease->giaddr = mess->giaddr;
1403                   
1404                   free(lease->extradata);
1405                   lease->extradata = NULL;
1406                   lease->extradata_size = lease->extradata_len = 0;
1407                   
1408                   add_extradata_opt(lease, option_find(mess, sz, OPTION_VENDOR_ID, 1));
1409                   add_extradata_opt(lease, option_find(mess, sz, OPTION_HOSTNAME, 1));
1410                   add_extradata_opt(lease, oui);
1411                   add_extradata_opt(lease, serial);
1412                   add_extradata_opt(lease, class);
1413
1414                   if ((opt = option_find(mess, sz, OPTION_AGENT_ID, 1)))
1415                     {
1416                       add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_CIRCUIT_ID, 1));
1417                       add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_SUBSCR_ID, 1));
1418                       add_extradata_opt(lease, option_find1(option_ptr(opt, 0), option_ptr(opt, option_len(opt)), SUBOPT_REMOTE_ID, 1));
1419                     }
1420                   else
1421                     {
1422                       add_extradata_opt(lease, NULL);
1423                       add_extradata_opt(lease, NULL);
1424                       add_extradata_opt(lease, NULL);
1425                     }
1426
1427                   /* DNSMASQ_REQUESTED_OPTIONS */
1428                   if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 1)))
1429                     {
1430                       int i, len = option_len(opt);
1431                       unsigned char *rop = option_ptr(opt, 0);
1432                       
1433                       for (i = 0; i < len; i++)
1434                         lease_add_extradata(lease, (unsigned char *)daemon->namebuff,
1435                                             sprintf(daemon->namebuff, "%u", rop[i]), (i + 1) == len ? 0 : ',');
1436                     }
1437                   else
1438                     lease_add_extradata(lease, NULL, 0, 0);
1439                   
1440                   add_extradata_opt(lease, option_find(mess, sz, OPTION_MUD_URL_V4, 1));
1441                   
1442                   /* space-concat tag set */
1443                   if (!tagif_netid)
1444                     add_extradata_opt(lease, NULL);
1445                   else
1446                     for (n = tagif_netid; n; n = n->next)
1447                       {
1448                         struct dhcp_netid *n1;
1449                         /* kill dupes */
1450                         for (n1 = n->next; n1; n1 = n1->next)
1451                           if (strcmp(n->net, n1->net) == 0)
1452                             break;
1453                         if (!n1)
1454                           lease_add_extradata(lease, (unsigned char *)n->net, strlen(n->net), n->next ? ' ' : 0); 
1455                       }
1456                   
1457                   if ((opt = option_find(mess, sz, OPTION_USER_CLASS, 1)))
1458                     {
1459                       int len = option_len(opt);
1460                       unsigned char *ucp = option_ptr(opt, 0);
1461                       /* If the user-class option started as counted strings, the first byte will be zero. */
1462                       if (len != 0 && ucp[0] == 0)
1463                         ucp++, len--;
1464                       lease_add_extradata(lease, ucp, len, -1);
1465                     }
1466                 }
1467 #endif
1468             }
1469           
1470           if (!hostname_auth && (client_hostname = host_from_dns(mess->yiaddr)))
1471             {
1472               domain = get_domain(mess->yiaddr);
1473               hostname = client_hostname;
1474               hostname_auth = 1;
1475             }
1476           
1477           time = calc_time(context, config, option_find(mess, sz, OPTION_LEASE_TIME, 4));
1478           lease_set_hwaddr(lease, mess->chaddr, clid, mess->hlen, mess->htype, clid_len, now, do_classes);
1479           
1480           /* if all the netids in the ignore_name list are present, ignore client-supplied name */
1481           if (!hostname_auth)
1482             {
1483               for (id_list = daemon->dhcp_ignore_names; id_list; id_list = id_list->next)
1484                 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1485                   break;
1486               if (id_list)
1487                 hostname = NULL;
1488             }
1489           
1490           /* Last ditch, if configured, generate hostname from mac address */
1491           if (!hostname && emac_len != 0)
1492             {
1493               for (id_list = daemon->dhcp_gen_names; id_list; id_list = id_list->next)
1494                 if ((!id_list->list) || match_netid(id_list->list, tagif_netid, 0))
1495                   break;
1496               if (id_list)
1497                 {
1498                   int i;
1499
1500                   hostname = daemon->dhcp_buff;
1501                   /* buffer is 256 bytes, 3 bytes per octet */
1502                   for (i = 0; (i < emac_len) && (i < 80); i++)
1503                     hostname += sprintf(hostname, "%.2x%s", emac[i], (i == emac_len - 1) ? "" : "-");
1504                   hostname = daemon->dhcp_buff;
1505                 }
1506             }
1507
1508           if (hostname)
1509             lease_set_hostname(lease, hostname, hostname_auth, get_domain(lease->addr), domain);
1510           
1511           lease_set_expires(lease, time, now);
1512           lease_set_interface(lease, int_index, now);
1513
1514           if (override.s_addr != 0)
1515             lease->override = override;
1516           else
1517             override = lease->override;
1518
1519           daemon->metrics[METRIC_DHCPACK]++;
1520           log_packet("DHCPACK", &mess->yiaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);  
1521
1522           clear_packet(mess, end);
1523           option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1524           option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1525           option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1526           if (rapid_commit)
1527              option_put(mess, end, OPTION_RAPID_COMMIT, 0, 0);
1528            do_options(context, mess, end, req_options, hostname, get_domain(mess->yiaddr), 
1529                      netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, time, fuzz, pxevendor);
1530         }
1531
1532       return dhcp_packet_size(mess, agent_id, real_end); 
1533       
1534     case DHCPINFORM:
1535       if (ignore || have_config(config, CONFIG_DISABLE))
1536         message = _("ignored");
1537       
1538       daemon->metrics[METRIC_DHCPINFORM]++;
1539       log_packet("DHCPINFORM", &mess->ciaddr, emac, emac_len, iface_name, message, NULL, mess->xid);
1540      
1541       if (message || mess->ciaddr.s_addr == 0)
1542         return 0;
1543
1544       /* For DHCPINFORM only, cope without a valid context */
1545       context = narrow_context(context, mess->ciaddr, tagif_netid);
1546       
1547       /* Find a least based on IP address if we didn't
1548          get one from MAC address/client-d */
1549       if (!lease &&
1550           (lease = lease_find_by_addr(mess->ciaddr)) && 
1551           lease->hostname)
1552         hostname = lease->hostname;
1553       
1554       if (!hostname)
1555         hostname = host_from_dns(mess->ciaddr);
1556       
1557       if (context && context->netid.net)
1558         {
1559           context->netid.next = netid;
1560           tagif_netid = run_tag_if(&context->netid);
1561         }
1562
1563       log_tags(tagif_netid, ntohl(mess->xid));
1564       
1565       daemon->metrics[METRIC_DHCPACK]++;
1566       log_packet("DHCPACK", &mess->ciaddr, emac, emac_len, iface_name, hostname, NULL, mess->xid);
1567       
1568       if (lease)
1569         {
1570           lease_set_interface(lease, int_index, now);
1571           if (override.s_addr != 0)
1572             lease->override = override;
1573           else
1574             override = lease->override;
1575         }
1576
1577       clear_packet(mess, end);
1578       option_put(mess, end, OPTION_MESSAGE_TYPE, 1, DHCPACK);
1579       option_put(mess, end, OPTION_SERVER_IDENTIFIER, INADDRSZ, ntohl(server_id(context, override, fallback).s_addr));
1580      
1581       /* RFC 2131 says that DHCPINFORM shouldn't include lease-time parameters, but 
1582          we supply a utility which makes DHCPINFORM requests to get this information.
1583          Only include lease time if OPTION_LEASE_TIME is in the parameter request list,
1584          which won't be true for ordinary clients, but will be true for the 
1585          dhcp_lease_time utility. */
1586       if (lease && in_list(req_options, OPTION_LEASE_TIME))
1587         {
1588           if (lease->expires == 0)
1589             time = 0xffffffff;
1590           else
1591             time = (unsigned int)difftime(lease->expires, now);
1592           option_put(mess, end, OPTION_LEASE_TIME, 4, time);
1593         }
1594
1595       do_options(context, mess, end, req_options, hostname, get_domain(mess->ciaddr),
1596                  netid, subnet_addr, fqdn_flags, borken_opt, pxearch, uuid, vendor_class_len, now, 0xffffffff, 0, pxevendor);
1597       
1598       *is_inform = 1; /* handle reply differently */
1599       return dhcp_packet_size(mess, agent_id, real_end); 
1600     }
1601   
1602   return 0;
1603 }
1604
1605 /* find a good value to use as MAC address for logging and address-allocation hashing.
1606    This is normally just the chaddr field from the DHCP packet,
1607    but eg Firewire will have hlen == 0 and use the client-id instead. 
1608    This could be anything, but will normally be EUI64 for Firewire.
1609    We assume that if the first byte of the client-id equals the htype byte
1610    then the client-id is using the usual encoding and use the rest of the 
1611    client-id: if not we can use the whole client-id. This should give
1612    sane MAC address logs. */
1613 unsigned char *extended_hwaddr(int hwtype, int hwlen, unsigned char *hwaddr, 
1614                                       int clid_len, unsigned char *clid, int *len_out)
1615 {
1616   if (hwlen == 0 && clid && clid_len > 3)
1617     {
1618       if (clid[0]  == hwtype)
1619         {
1620           *len_out = clid_len - 1 ;
1621           return clid + 1;
1622         }
1623
1624 #if defined(ARPHRD_EUI64) && defined(ARPHRD_IEEE1394)
1625       if (clid[0] ==  ARPHRD_EUI64 && hwtype == ARPHRD_IEEE1394)
1626         {
1627           *len_out = clid_len - 1 ;
1628           return clid + 1;
1629         }
1630 #endif
1631       
1632       *len_out = clid_len;
1633       return clid;
1634     }
1635   
1636   *len_out = hwlen;
1637   return hwaddr;
1638 }
1639
1640 static unsigned int calc_time(struct dhcp_context *context, struct dhcp_config *config, unsigned char *opt)
1641 {
1642   unsigned int time = have_config(config, CONFIG_TIME) ? config->lease_time : context->lease_time;
1643   
1644   if (opt)
1645     { 
1646       unsigned int req_time = option_uint(opt, 0, 4);
1647       if (req_time < 120 )
1648         req_time = 120; /* sanity */
1649       if (time == 0xffffffff || (req_time != 0xffffffff && req_time < time))
1650         time = req_time;
1651     }
1652
1653   return time;
1654 }
1655
1656 static struct in_addr server_id(struct dhcp_context *context, struct in_addr override, struct in_addr fallback)
1657 {
1658   if (override.s_addr != 0)
1659     return override;
1660   else if (context && context->local.s_addr != 0)
1661     return context->local;
1662   else
1663     return fallback;
1664 }
1665
1666 static int sanitise(unsigned char *opt, char *buf)
1667 {
1668   char *p;
1669   int i;
1670   
1671   *buf = 0;
1672   
1673   if (!opt)
1674     return 0;
1675
1676   p = option_ptr(opt, 0);
1677
1678   for (i = option_len(opt); i > 0; i--)
1679     {
1680       char c = *p++;
1681       if (isprint((int)c))
1682         *buf++ = c;
1683     }
1684   *buf = 0; /* add terminator */
1685   
1686   return 1;
1687 }
1688
1689 #ifdef HAVE_SCRIPT
1690 static void add_extradata_opt(struct dhcp_lease *lease, unsigned char *opt)
1691 {
1692   if (!opt)
1693     lease_add_extradata(lease, NULL, 0, 0);
1694   else
1695     lease_add_extradata(lease, option_ptr(opt, 0), option_len(opt), 0); 
1696 }
1697 #endif
1698
1699 static void log_packet(char *type, void *addr, unsigned char *ext_mac, 
1700                        int mac_len, char *interface, char *string, char *err, u32 xid)
1701 {
1702   if (!err && !option_bool(OPT_LOG_OPTS) && option_bool(OPT_QUIET_DHCP))
1703     return;
1704   
1705   daemon->addrbuff[0] = 0;
1706   if (addr)
1707     inet_ntop(AF_INET, addr, daemon->addrbuff, ADDRSTRLEN);
1708   
1709   print_mac(daemon->namebuff, ext_mac, mac_len);
1710   
1711   if (option_bool(OPT_LOG_OPTS))
1712     my_syslog(MS_DHCP | LOG_INFO, "%u %s(%s) %s%s%s %s%s",
1713               ntohl(xid), 
1714               type,
1715               interface, 
1716               daemon->addrbuff,
1717               addr ? " " : "",
1718               daemon->namebuff,
1719               string ? string : "",
1720               err ? err : "");
1721   else
1722     my_syslog(MS_DHCP | LOG_INFO, "%s(%s) %s%s%s %s%s",
1723               type,
1724               interface, 
1725               daemon->addrbuff,
1726               addr ? " " : "",
1727               daemon->namebuff,
1728               string ? string : "",
1729               err ? err : "");
1730   
1731 #ifdef HAVE_UBUS
1732   if (!strcmp(type, "DHCPACK"))
1733     ubus_event_bcast("dhcp.ack", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
1734   else if (!strcmp(type, "DHCPRELEASE"))
1735     ubus_event_bcast("dhcp.release", daemon->namebuff, addr ? daemon->addrbuff : NULL, string, interface);
1736 #endif
1737 }
1738
1739 static void log_options(unsigned char *start, u32 xid)
1740 {
1741   while (*start != OPTION_END)
1742     {
1743       char *optname = option_string(AF_INET, start[0], option_ptr(start, 0), option_len(start), daemon->namebuff, MAXDNAME);
1744       
1745       my_syslog(MS_DHCP | LOG_INFO, "%u sent size:%3d option:%3d %s  %s", 
1746                 ntohl(xid), option_len(start), start[0], optname, daemon->namebuff);
1747       start += start[1] + 2;
1748     }
1749 }
1750
1751 static unsigned char *option_find1(unsigned char *p, unsigned char *end, int opt, int minsize)
1752 {
1753   while (1) 
1754     {
1755       if (p >= end)
1756         return NULL;
1757       else if (*p == OPTION_END)
1758         return opt == OPTION_END ? p : NULL;
1759       else if (*p == OPTION_PAD)
1760         p++;
1761       else 
1762         { 
1763           int opt_len;
1764           if (p > end - 2)
1765             return NULL; /* malformed packet */
1766           opt_len = option_len(p);
1767           if (p > end - (2 + opt_len))
1768             return NULL; /* malformed packet */
1769           if (*p == opt && opt_len >= minsize)
1770             return p;
1771           p += opt_len + 2;
1772         }
1773     }
1774 }
1775  
1776 static unsigned char *option_find(struct dhcp_packet *mess, size_t size, int opt_type, int minsize)
1777 {
1778   unsigned char *ret, *overload;
1779   
1780   /* skip over DHCP cookie; */
1781   if ((ret = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, opt_type, minsize)))
1782     return ret;
1783
1784   /* look for overload option. */
1785   if (!(overload = option_find1(&mess->options[0] + sizeof(u32), ((unsigned char *)mess) + size, OPTION_OVERLOAD, 1)))
1786     return NULL;
1787   
1788   /* Can we look in filename area ? */
1789   if ((overload[2] & 1) &&
1790       (ret = option_find1(&mess->file[0], &mess->file[128], opt_type, minsize)))
1791     return ret;
1792
1793   /* finally try sname area */
1794   if ((overload[2] & 2) &&
1795       (ret = option_find1(&mess->sname[0], &mess->sname[64], opt_type, minsize)))
1796     return ret;
1797
1798   return NULL;
1799 }
1800
1801 static struct in_addr option_addr(unsigned char *opt)
1802 {
1803    /* this worries about unaligned data in the option. */
1804   /* struct in_addr is network byte order */
1805   struct in_addr ret;
1806
1807   memcpy(&ret, option_ptr(opt, 0), INADDRSZ);
1808
1809   return ret;
1810 }
1811
1812 static unsigned int option_uint(unsigned char *opt, int offset, int size)
1813 {
1814   /* this worries about unaligned data and byte order */
1815   unsigned int ret = 0;
1816   int i;
1817   unsigned char *p = option_ptr(opt, offset);
1818   
1819   for (i = 0; i < size; i++)
1820     ret = (ret << 8) | *p++;
1821
1822   return ret;
1823 }
1824
1825 static unsigned char *dhcp_skip_opts(unsigned char *start)
1826 {
1827   while (*start != 0)
1828     start += start[1] + 2;
1829   return start;
1830 }
1831
1832 /* only for use when building packet: doesn't check for bad data. */ 
1833 static unsigned char *find_overload(struct dhcp_packet *mess)
1834 {
1835   unsigned char *p = &mess->options[0] + sizeof(u32);
1836   
1837   while (*p != 0)
1838     {
1839       if (*p == OPTION_OVERLOAD)
1840         return p;
1841       p += p[1] + 2;
1842     }
1843   return NULL;
1844 }
1845
1846 static size_t dhcp_packet_size(struct dhcp_packet *mess, unsigned char *agent_id, unsigned char *real_end)
1847 {
1848   unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1849   unsigned char *overload;
1850   size_t ret;
1851   
1852   /* move agent_id back down to the end of the packet */
1853   if (agent_id)
1854     {
1855       memmove(p, agent_id, real_end - agent_id);
1856       p += real_end - agent_id;
1857       memset(p, 0, real_end - p); /* in case of overlap */
1858     }
1859   
1860   /* add END options to the regions. */
1861   overload = find_overload(mess);
1862   
1863   if (overload && (option_uint(overload, 0, 1) & 1))
1864     {
1865       *dhcp_skip_opts(mess->file) = OPTION_END;
1866       if (option_bool(OPT_LOG_OPTS))
1867         log_options(mess->file, mess->xid);
1868     }
1869   else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->file) != 0)
1870     my_syslog(MS_DHCP | LOG_INFO, _("%u bootfile name: %s"), ntohl(mess->xid), (char *)mess->file);
1871   
1872   if (overload && (option_uint(overload, 0, 1) & 2))
1873     {
1874       *dhcp_skip_opts(mess->sname) = OPTION_END;
1875       if (option_bool(OPT_LOG_OPTS))
1876         log_options(mess->sname, mess->xid);
1877     }
1878   else if (option_bool(OPT_LOG_OPTS) && strlen((char *)mess->sname) != 0)
1879     my_syslog(MS_DHCP | LOG_INFO, _("%u server name: %s"), ntohl(mess->xid), (char *)mess->sname);
1880
1881
1882   *p++ = OPTION_END;
1883   
1884   if (option_bool(OPT_LOG_OPTS))
1885     {
1886       if (mess->siaddr.s_addr != 0)
1887         {
1888           inet_ntop(AF_INET, &mess->siaddr, daemon->addrbuff, ADDRSTRLEN);
1889           my_syslog(MS_DHCP | LOG_INFO, _("%u next server: %s"), ntohl(mess->xid), daemon->addrbuff);
1890         }
1891       
1892       if ((mess->flags & htons(0x8000)) && mess->ciaddr.s_addr == 0)
1893         my_syslog(MS_DHCP | LOG_INFO, _("%u broadcast response"), ntohl(mess->xid));
1894       
1895       log_options(&mess->options[0] + sizeof(u32), mess->xid);
1896     } 
1897   
1898   ret = (size_t)(p - (unsigned char *)mess);
1899   
1900   if (ret < MIN_PACKETSZ)
1901     ret = MIN_PACKETSZ;
1902   
1903   return ret;
1904 }
1905
1906 static unsigned char *free_space(struct dhcp_packet *mess, unsigned char *end, int opt, int len)
1907 {
1908   unsigned char *p = dhcp_skip_opts(&mess->options[0] + sizeof(u32));
1909   
1910   if (p + len + 3 >= end)
1911     /* not enough space in options area, try and use overload, if poss */
1912     {
1913       unsigned char *overload;
1914       
1915       if (!(overload = find_overload(mess)) &&
1916           (mess->file[0] == 0 || mess->sname[0] == 0))
1917         {
1918           /* attempt to overload fname and sname areas, we've reserved space for the
1919              overflow option previuously. */
1920           overload = p;
1921           *(p++) = OPTION_OVERLOAD;
1922           *(p++) = 1;
1923         }
1924       
1925       p = NULL;
1926       
1927       /* using filename field ? */
1928       if (overload)
1929         {
1930           if (mess->file[0] == 0)
1931             overload[2] |= 1;
1932           
1933           if (overload[2] & 1)
1934             {
1935               p = dhcp_skip_opts(mess->file);
1936               if (p + len + 3 >= mess->file + sizeof(mess->file))
1937                 p = NULL;
1938             }
1939           
1940           if (!p)
1941             {
1942               /* try to bring sname into play (it may be already) */
1943               if (mess->sname[0] == 0)
1944                 overload[2] |= 2;
1945               
1946               if (overload[2] & 2)
1947                 {
1948                   p = dhcp_skip_opts(mess->sname);
1949                   if (p + len + 3 >= mess->sname + sizeof(mess->sname))
1950                     p = NULL;
1951                 }
1952             }
1953         }
1954       
1955       if (!p)
1956         my_syslog(MS_DHCP | LOG_WARNING, _("cannot send DHCP/BOOTP option %d: no space left in packet"), opt);
1957     }
1958  
1959   if (p)
1960     {
1961       *(p++) = opt;
1962       *(p++) = len;
1963     }
1964
1965   return p;
1966 }
1967               
1968 static void option_put(struct dhcp_packet *mess, unsigned char *end, int opt, int len, unsigned int val)
1969 {
1970   int i;
1971   unsigned char *p = free_space(mess, end, opt, len);
1972   
1973   if (p) 
1974     for (i = 0; i < len; i++)
1975       *(p++) = val >> (8 * (len - (i + 1)));
1976 }
1977
1978 static void option_put_string(struct dhcp_packet *mess, unsigned char *end, int opt, 
1979                               const char *string, int null_term)
1980 {
1981   unsigned char *p;
1982   size_t len = strlen(string);
1983
1984   if (null_term && len != 255)
1985     len++;
1986
1987   if ((p = free_space(mess, end, opt, len)))
1988     memcpy(p, string, len);
1989 }
1990
1991 /* return length, note this only does the data part */
1992 static int do_opt(struct dhcp_opt *opt, unsigned char *p, struct dhcp_context *context, int null_term)
1993 {
1994   int len = opt->len;
1995   
1996   if ((opt->flags & DHOPT_STRING) && null_term && len != 255)
1997     len++;
1998
1999   if (p && len != 0)
2000     {
2001       if (context && (opt->flags & DHOPT_ADDR))
2002         {
2003           int j;
2004           struct in_addr *a = (struct in_addr *)opt->val;
2005           for (j = 0; j < opt->len; j+=INADDRSZ, a++)
2006             {
2007               /* zero means "self" (but not in vendorclass options.) */
2008               if (a->s_addr == 0)
2009                 memcpy(p, &context->local, INADDRSZ);
2010               else
2011                 memcpy(p, a, INADDRSZ);
2012               p += INADDRSZ;
2013             }
2014         }
2015       else
2016         /* empty string may be extended to "\0" by null_term */
2017         memcpy(p, opt->val ? opt->val : (unsigned char *)"", len);
2018     }  
2019   return len;
2020 }
2021
2022 static int in_list(unsigned char *list, int opt)
2023 {
2024   int i;
2025
2026    /* If no requested options, send everything, not nothing. */
2027   if (!list)
2028     return 1;
2029   
2030   for (i = 0; list[i] != OPTION_END; i++)
2031     if (opt == list[i])
2032       return 1;
2033
2034   return 0;
2035 }
2036
2037 static struct dhcp_opt *option_find2(int opt)
2038 {
2039   struct dhcp_opt *opts;
2040   
2041   for (opts = daemon->dhcp_opts; opts; opts = opts->next)
2042     if (opts->opt == opt && (opts->flags & DHOPT_TAGOK))
2043       return opts;
2044   
2045   return NULL;
2046 }
2047
2048 /* mark vendor-encapsulated options which match the client-supplied  or
2049    config-supplied vendor class */
2050 static void match_vendor_opts(unsigned char *opt, struct dhcp_opt *dopt)
2051 {
2052   for (; dopt; dopt = dopt->next)
2053     {
2054       dopt->flags &= ~DHOPT_VENDOR_MATCH;
2055       if (opt && (dopt->flags & DHOPT_VENDOR))
2056         {
2057           const struct dhcp_pxe_vendor *pv;
2058           struct dhcp_pxe_vendor dummy_vendor = {
2059             .data = (char *)dopt->u.vendor_class,
2060             .next = NULL,
2061           };
2062           if (dopt->flags & DHOPT_VENDOR_PXE)
2063             pv = daemon->dhcp_pxe_vendors;
2064           else
2065             pv = &dummy_vendor;
2066           for (; pv; pv = pv->next)
2067             {
2068               int i, len = 0, matched = 0;
2069               if (pv->data)
2070                 len = strlen(pv->data);
2071               for (i = 0; i <= (option_len(opt) - len); i++)
2072                 if (len == 0 || memcmp(pv->data, option_ptr(opt, i), len) == 0)
2073                   {
2074                     matched = 1;
2075                     break;
2076                   }
2077               if (matched)
2078                 {
2079                   dopt->flags |= DHOPT_VENDOR_MATCH;
2080                   break;
2081                 }
2082             }
2083         }
2084     }
2085 }
2086
2087 static int do_encap_opts(struct dhcp_opt *opt, int encap, int flag,  
2088                          struct dhcp_packet *mess, unsigned char *end, int null_term)
2089 {
2090   int len, enc_len, ret = 0;
2091   struct dhcp_opt *start;
2092   unsigned char *p;
2093     
2094   /* find size in advance */
2095   for (enc_len = 0, start = opt; opt; opt = opt->next)
2096     if (opt->flags & flag)
2097       {
2098         int new = do_opt(opt, NULL, NULL, null_term) + 2;
2099         ret  = 1;
2100         if (enc_len + new <= 255)
2101           enc_len += new;
2102         else
2103           {
2104             p = free_space(mess, end, encap, enc_len);
2105             for (; start && start != opt; start = start->next)
2106               if (p && (start->flags & flag))
2107                 {
2108                   len = do_opt(start, p + 2, NULL, null_term);
2109                   *(p++) = start->opt;
2110                   *(p++) = len;
2111                   p += len;
2112                 }
2113             enc_len = new;
2114             start = opt;
2115           }
2116       }
2117   
2118   if (enc_len != 0 &&
2119       (p = free_space(mess, end, encap, enc_len + 1)))
2120     {
2121       for (; start; start = start->next)
2122         if (start->flags & flag)
2123           {
2124             len = do_opt(start, p + 2, NULL, null_term);
2125             *(p++) = start->opt;
2126             *(p++) = len;
2127             p += len;
2128           }
2129       *p = OPTION_END;
2130     }
2131
2132   return ret;
2133 }
2134
2135 static void pxe_misc(struct dhcp_packet *mess, unsigned char *end, unsigned char *uuid, const char *pxevendor)
2136 {
2137   unsigned char *p;
2138
2139   if (!pxevendor)
2140     pxevendor="PXEClient";
2141   option_put_string(mess, end, OPTION_VENDOR_ID, pxevendor, 0);
2142   if (uuid && (p = free_space(mess, end, OPTION_PXE_UUID, 17)))
2143     memcpy(p, uuid, 17);
2144 }
2145
2146 static int prune_vendor_opts(struct dhcp_netid *netid)
2147 {
2148   int force = 0;
2149   struct dhcp_opt *opt;
2150
2151   /* prune vendor-encapsulated options based on netid, and look if we're forcing them to be sent */
2152   for (opt = daemon->dhcp_opts; opt; opt = opt->next)
2153     if (opt->flags & DHOPT_VENDOR_MATCH)
2154       {
2155         if (!match_netid(opt->netid, netid, 1))
2156           opt->flags &= ~DHOPT_VENDOR_MATCH;
2157         else if (opt->flags & DHOPT_FORCE)
2158           force = 1;
2159       }
2160   return force;
2161 }
2162
2163
2164 /* Many UEFI PXE implementations have badly broken menu code.
2165    If there's exactly one relevant menu item, we abandon the menu system,
2166    and jamb the data direct into the DHCP file, siaddr and sname fields.
2167    Note that in this case, we have to assume that layer zero would be requested
2168    by the client PXE stack. */
2169 static int pxe_uefi_workaround(int pxe_arch, struct dhcp_netid *netid, struct dhcp_packet *mess, struct in_addr local, time_t now, int pxe)
2170 {
2171   struct pxe_service *service, *found;
2172
2173   /* Only workaround UEFI archs. */
2174   if (pxe_arch < 6)
2175     return 0;
2176   
2177   for (found = NULL, service = daemon->pxe_services; service; service = service->next)
2178     if (pxe_arch == service->CSA && service->basename && match_netid(service->netid, netid, 1))
2179       {
2180         if (found)
2181           return 0; /* More than one relevant menu item */
2182           
2183         found = service;
2184       }
2185
2186   if (!found)
2187     return 0; /* No relevant menu items. */
2188   
2189   if (!pxe)
2190      return 1;
2191   
2192   if (found->sname)
2193     {
2194       mess->siaddr = a_record_from_hosts(found->sname, now);
2195       snprintf((char *)mess->sname, sizeof(mess->sname), "%s", found->sname);
2196     }
2197   else 
2198     {
2199       if (found->server.s_addr != 0)
2200         mess->siaddr = found->server; 
2201       else
2202         mess->siaddr = local;
2203   
2204       inet_ntop(AF_INET, &mess->siaddr, (char *)mess->sname, INET_ADDRSTRLEN);
2205     }
2206   
2207   if (found->basename)
2208     snprintf((char *)mess->file, sizeof(mess->file), 
2209              strchr(found->basename, '.') ? "%s" : "%s.0", found->basename);
2210   
2211   return 1;
2212 }
2213
2214 static struct dhcp_opt *pxe_opts(int pxe_arch, struct dhcp_netid *netid, struct in_addr local, time_t now)
2215 {
2216 #define NUM_OPTS 4  
2217
2218   unsigned  char *p, *q;
2219   struct pxe_service *service;
2220   static struct dhcp_opt *o, *ret;
2221   int i, j = NUM_OPTS - 1;
2222   struct in_addr boot_server;
2223   
2224   /* We pass back references to these, hence they are declared static */
2225   static unsigned char discovery_control;
2226   static unsigned char fake_prompt[] = { 0, 'P', 'X', 'E' }; 
2227   static struct dhcp_opt *fake_opts = NULL;
2228   
2229   /* Disable multicast, since we don't support it, and broadcast
2230      unless we need it */
2231   discovery_control = 3;
2232   
2233   ret = daemon->dhcp_opts;
2234   
2235   if (!fake_opts && !(fake_opts = whine_malloc(NUM_OPTS * sizeof(struct dhcp_opt))))
2236     return ret;
2237
2238   for (i = 0; i < NUM_OPTS; i++)
2239     {
2240       fake_opts[i].flags = DHOPT_VENDOR_MATCH;
2241       fake_opts[i].netid = NULL;
2242       fake_opts[i].next = i == (NUM_OPTS - 1) ? ret : &fake_opts[i+1];
2243     }
2244   
2245   /* create the data for the PXE_MENU and PXE_SERVERS options. */
2246   p = (unsigned char *)daemon->dhcp_buff;
2247   q = (unsigned char *)daemon->dhcp_buff3;
2248
2249   for (i = 0, service = daemon->pxe_services; service; service = service->next)
2250     if (pxe_arch == service->CSA && match_netid(service->netid, netid, 1))
2251       {
2252         size_t len = strlen(service->menu);
2253         /* opt 43 max size is 255. encapsulated option has type and length
2254            bytes, so its max size is 253. */
2255         if (p - (unsigned char *)daemon->dhcp_buff + len + 3 < 253)
2256           {
2257             *(p++) = service->type >> 8;
2258             *(p++) = service->type;
2259             *(p++) = len;
2260             memcpy(p, service->menu, len);
2261             p += len;
2262             i++;
2263           }
2264         else
2265           {
2266           toobig:
2267             my_syslog(MS_DHCP | LOG_ERR, _("PXE menu too large"));
2268             return daemon->dhcp_opts;
2269           }
2270         
2271         boot_server = service->basename ? local : 
2272           (service->sname ? a_record_from_hosts(service->sname, now) : service->server);
2273         
2274         if (boot_server.s_addr != 0)
2275           {
2276             if (q - (unsigned char *)daemon->dhcp_buff3 + 3 + INADDRSZ >= 253)
2277               goto toobig;
2278             
2279             /* Boot service with known address - give it */
2280             *(q++) = service->type >> 8;
2281             *(q++) = service->type;
2282             *(q++) = 1;
2283             /* dest misaligned */
2284             memcpy(q, &boot_server.s_addr, INADDRSZ);
2285             q += INADDRSZ;
2286           }
2287         else if (service->type != 0)
2288           /* We don't know the server for a service type, so we'll
2289              allow the client to broadcast for it */
2290           discovery_control = 2;
2291       }
2292
2293   /* if no prompt, wait forever if there's a choice */
2294   fake_prompt[0] = (i > 1) ? 255 : 0;
2295   
2296   if (i == 0)
2297     discovery_control = 8; /* no menu - just use use mess->filename */
2298   else
2299     {
2300       ret = &fake_opts[j--];
2301       ret->len = p - (unsigned char *)daemon->dhcp_buff;
2302       ret->val = (unsigned char *)daemon->dhcp_buff;
2303       ret->opt = SUBOPT_PXE_MENU;
2304
2305       if (q - (unsigned char *)daemon->dhcp_buff3 != 0)
2306         {
2307           ret = &fake_opts[j--]; 
2308           ret->len = q - (unsigned char *)daemon->dhcp_buff3;
2309           ret->val = (unsigned char *)daemon->dhcp_buff3;
2310           ret->opt = SUBOPT_PXE_SERVERS;
2311         }
2312     }
2313
2314   for (o = daemon->dhcp_opts; o; o = o->next)
2315     if ((o->flags & DHOPT_VENDOR_MATCH) && o->opt == SUBOPT_PXE_MENU_PROMPT)
2316       break;
2317   
2318   if (!o)
2319     {
2320       ret = &fake_opts[j--]; 
2321       ret->len = sizeof(fake_prompt);
2322       ret->val = fake_prompt;
2323       ret->opt = SUBOPT_PXE_MENU_PROMPT;
2324     }
2325   
2326   ret = &fake_opts[j--]; 
2327   ret->len = 1;
2328   ret->opt = SUBOPT_PXE_DISCOVERY;
2329   ret->val= &discovery_control;
2330  
2331   return ret;
2332 }
2333   
2334 static void clear_packet(struct dhcp_packet *mess, unsigned char *end)
2335 {
2336   memset(mess->sname, 0, sizeof(mess->sname));
2337   memset(mess->file, 0, sizeof(mess->file));
2338   memset(&mess->options[0] + sizeof(u32), 0, end - (&mess->options[0] + sizeof(u32)));
2339   mess->siaddr.s_addr = 0;
2340 }
2341
2342 struct dhcp_boot *find_boot(struct dhcp_netid *netid)
2343 {
2344   struct dhcp_boot *boot;
2345
2346   /* decide which dhcp-boot option we're using */
2347   for (boot = daemon->boot_config; boot; boot = boot->next)
2348     if (match_netid(boot->netid, netid, 0))
2349       break;
2350   if (!boot)
2351     /* No match, look for one without a netid */
2352     for (boot = daemon->boot_config; boot; boot = boot->next)
2353       if (match_netid(boot->netid, netid, 1))
2354         break;
2355
2356   return boot;
2357 }
2358
2359 static int is_pxe_client(struct dhcp_packet *mess, size_t sz, const char **pxe_vendor)
2360 {
2361   const unsigned char *opt = NULL;
2362   ssize_t conf_len = 0;
2363   const struct dhcp_pxe_vendor *conf = daemon->dhcp_pxe_vendors;
2364   opt = option_find(mess, sz, OPTION_VENDOR_ID, 0);
2365   if (!opt) 
2366     return 0;
2367   for (; conf; conf = conf->next)
2368     {
2369       conf_len = strlen(conf->data);
2370       if (option_len(opt) < conf_len)
2371         continue;
2372       if (strncmp(option_ptr(opt, 0), conf->data, conf_len) == 0)
2373         {
2374           if (pxe_vendor)
2375             *pxe_vendor = conf->data;
2376           return 1;
2377         }
2378     }
2379   return 0;
2380 }
2381
2382 static void do_options(struct dhcp_context *context,
2383                        struct dhcp_packet *mess,
2384                        unsigned char *end, 
2385                        unsigned char *req_options,
2386                        char *hostname, 
2387                        char *domain,
2388                        struct dhcp_netid *netid,
2389                        struct in_addr subnet_addr,
2390                        unsigned char fqdn_flags,
2391                        int null_term, int pxe_arch,
2392                        unsigned char *uuid,
2393                        int vendor_class_len,
2394                        time_t now,
2395                        unsigned int lease_time,
2396                        unsigned short fuzz,
2397                        const char *pxevendor)
2398 {
2399   struct dhcp_opt *opt, *config_opts = daemon->dhcp_opts;
2400   struct dhcp_boot *boot;
2401   unsigned char *p;
2402   int i, len, force_encap = 0;
2403   unsigned char f0 = 0, s0 = 0;
2404   int done_file = 0, done_server = 0;
2405   int done_vendor_class = 0;
2406   struct dhcp_netid *tagif;
2407   struct dhcp_netid_list *id_list;
2408
2409   /* filter options based on tags, those we want get DHOPT_TAGOK bit set */
2410   if (context)
2411     context->netid.next = NULL;
2412   tagif = option_filter(netid, context && context->netid.net ? &context->netid : NULL, config_opts);
2413         
2414   /* logging */
2415   if (option_bool(OPT_LOG_OPTS) && req_options)
2416     {
2417       char *q = daemon->namebuff;
2418       for (i = 0; req_options[i] != OPTION_END; i++)
2419         {
2420           char *s = option_string(AF_INET, req_options[i], NULL, 0, NULL, 0);
2421           q += snprintf(q, MAXDNAME - (q - daemon->namebuff),
2422                         "%d%s%s%s", 
2423                         req_options[i],
2424                         strlen(s) != 0 ? ":" : "",
2425                         s, 
2426                         req_options[i+1] == OPTION_END ? "" : ", ");
2427           if (req_options[i+1] == OPTION_END || (q - daemon->namebuff) > 40)
2428             {
2429               q = daemon->namebuff;
2430               my_syslog(MS_DHCP | LOG_INFO, _("%u requested options: %s"), ntohl(mess->xid), daemon->namebuff);
2431             }
2432         }
2433     }
2434       
2435   for (id_list = daemon->force_broadcast; id_list; id_list = id_list->next)
2436     if ((!id_list->list) || match_netid(id_list->list, netid, 0))
2437       break;
2438   if (id_list)
2439     mess->flags |= htons(0x8000); /* force broadcast */
2440   
2441   if (context)
2442     mess->siaddr = context->local;
2443   
2444   /* See if we can send the boot stuff as options.
2445      To do this we need a requested option list, BOOTP
2446      and very old DHCP clients won't have this, we also 
2447      provide a manual option to disable it.
2448      Some PXE ROMs have bugs (surprise!) and need zero-terminated 
2449      names, so we always send those.  */
2450   if ((boot = find_boot(tagif)))
2451     {
2452       if (boot->sname)
2453         {         
2454           if (!option_bool(OPT_NO_OVERRIDE) &&
2455               req_options && 
2456               in_list(req_options, OPTION_SNAME))
2457             option_put_string(mess, end, OPTION_SNAME, boot->sname, 1);
2458           else
2459             safe_strncpy((char *)mess->sname, boot->sname, sizeof(mess->sname));
2460         }
2461       
2462       if (boot->file)
2463         {
2464           if (!option_bool(OPT_NO_OVERRIDE) &&
2465               req_options && 
2466               in_list(req_options, OPTION_FILENAME))
2467             option_put_string(mess, end, OPTION_FILENAME, boot->file, 1);
2468           else
2469             safe_strncpy((char *)mess->file, boot->file, sizeof(mess->file));
2470         }
2471       
2472       if (boot->next_server.s_addr) 
2473         mess->siaddr = boot->next_server;
2474       else if (boot->tftp_sname)
2475         mess->siaddr = a_record_from_hosts(boot->tftp_sname, now);
2476     }
2477   else
2478     /* Use the values of the relevant options if no dhcp-boot given and
2479        they're not explicitly asked for as options. OPTION_END is used
2480        as an internal way to specify siaddr without using dhcp-boot, for use in
2481        dhcp-optsfile. */
2482     {
2483       if ((!req_options || !in_list(req_options, OPTION_FILENAME)) &&
2484           (opt = option_find2(OPTION_FILENAME)) && !(opt->flags & DHOPT_FORCE))
2485         {
2486           safe_strncpy((char *)mess->file, (char *)opt->val, sizeof(mess->file));
2487           done_file = 1;
2488         }
2489       
2490       if ((!req_options || !in_list(req_options, OPTION_SNAME)) &&
2491           (opt = option_find2(OPTION_SNAME)) && !(opt->flags & DHOPT_FORCE))
2492         {
2493           safe_strncpy((char *)mess->sname, (char *)opt->val, sizeof(mess->sname));
2494           done_server = 1;
2495         }
2496       
2497       if ((opt = option_find2(OPTION_END)))
2498         mess->siaddr.s_addr = ((struct in_addr *)opt->val)->s_addr;     
2499     }
2500         
2501   /* We don't want to do option-overload for BOOTP, so make the file and sname
2502      fields look like they are in use, even when they aren't. This gets restored
2503      at the end of this function. */
2504
2505   if (!req_options || option_bool(OPT_NO_OVERRIDE))
2506     {
2507       f0 = mess->file[0];
2508       mess->file[0] = 1;
2509       s0 = mess->sname[0];
2510       mess->sname[0] = 1;
2511     }
2512       
2513   /* At this point, if mess->sname or mess->file are zeroed, they are available
2514      for option overload, reserve space for the overload option. */
2515   if (mess->file[0] == 0 || mess->sname[0] == 0)
2516     end -= 3;
2517
2518   /* rfc3011 says this doesn't need to be in the requested options list. */
2519   if (subnet_addr.s_addr)
2520     option_put(mess, end, OPTION_SUBNET_SELECT, INADDRSZ, ntohl(subnet_addr.s_addr));
2521    
2522   if (lease_time != 0xffffffff)
2523     { 
2524       unsigned int t1val = lease_time/2; 
2525       unsigned int t2val = (lease_time*7)/8;
2526       unsigned int hval;
2527       
2528       /* If set by user, sanity check, so not longer than lease. */
2529       if ((opt = option_find2(OPTION_T1)))
2530         {
2531           hval = ntohl(*((unsigned int *)opt->val));
2532           if (hval < lease_time && hval > 2)
2533             t1val = hval;
2534         }
2535
2536        if ((opt = option_find2(OPTION_T2)))
2537         {
2538           hval = ntohl(*((unsigned int *)opt->val));
2539           if (hval < lease_time && hval > 2)
2540             t2val = hval;
2541         }
2542           
2543        /* ensure T1 is still < T2 */
2544        if (t2val <= t1val)
2545          t1val = t2val - 1; 
2546
2547        while (fuzz > (t1val/8))
2548          fuzz = fuzz/2;
2549          
2550        t1val -= fuzz;
2551        t2val -= fuzz;
2552        
2553        option_put(mess, end, OPTION_T1, 4, t1val);
2554        option_put(mess, end, OPTION_T2, 4, t2val);
2555     }
2556
2557   /* replies to DHCPINFORM may not have a valid context */
2558   if (context)
2559     {
2560       if (!option_find2(OPTION_NETMASK))
2561         option_put(mess, end, OPTION_NETMASK, INADDRSZ, ntohl(context->netmask.s_addr));
2562   
2563       /* May not have a "guessed" broadcast address if we got no packets via a relay
2564          from this net yet (ie just unicast renewals after a restart */
2565       if (context->broadcast.s_addr &&
2566           !option_find2(OPTION_BROADCAST))
2567         option_put(mess, end, OPTION_BROADCAST, INADDRSZ, ntohl(context->broadcast.s_addr));
2568       
2569       /* Same comments as broadcast apply, and also may not be able to get a sensible
2570          default when using subnet select.  User must configure by steam in that case. */
2571       if (context->router.s_addr &&
2572           in_list(req_options, OPTION_ROUTER) &&
2573           !option_find2(OPTION_ROUTER))
2574         option_put(mess, end, OPTION_ROUTER, INADDRSZ, ntohl(context->router.s_addr));
2575       
2576       if (daemon->port == NAMESERVER_PORT &&
2577           in_list(req_options, OPTION_DNSSERVER) &&
2578           !option_find2(OPTION_DNSSERVER))
2579         option_put(mess, end, OPTION_DNSSERVER, INADDRSZ, ntohl(context->local.s_addr));
2580     }
2581
2582   if (domain && in_list(req_options, OPTION_DOMAINNAME) && 
2583       !option_find2(OPTION_DOMAINNAME))
2584     option_put_string(mess, end, OPTION_DOMAINNAME, domain, null_term);
2585  
2586   /* Note that we ignore attempts to set the fqdn using --dhc-option=81,<name> */
2587   if (hostname)
2588     {
2589       if (in_list(req_options, OPTION_HOSTNAME) &&
2590           !option_find2(OPTION_HOSTNAME))
2591         option_put_string(mess, end, OPTION_HOSTNAME, hostname, null_term);
2592       
2593       if (fqdn_flags != 0)
2594         {
2595           len = strlen(hostname) + 3;
2596           
2597           if (fqdn_flags & 0x04)
2598             len += 2;
2599           else if (null_term)
2600             len++;
2601
2602           if (domain)
2603             len += strlen(domain) + 1;
2604           else if (fqdn_flags & 0x04)
2605             len--;
2606
2607           if ((p = free_space(mess, end, OPTION_CLIENT_FQDN, len)))
2608             {
2609               *(p++) = fqdn_flags & 0x0f; /* MBZ bits to zero */ 
2610               *(p++) = 255;
2611               *(p++) = 255;
2612
2613               if (fqdn_flags & 0x04)
2614                 {
2615                   p = do_rfc1035_name(p, hostname, NULL);
2616                   if (domain)
2617                     {
2618                       p = do_rfc1035_name(p, domain, NULL);
2619                       *p++ = 0;
2620                     }
2621                 }
2622               else
2623                 {
2624                   memcpy(p, hostname, strlen(hostname));
2625                   p += strlen(hostname);
2626                   if (domain)
2627                     {
2628                       *(p++) = '.';
2629                       memcpy(p, domain, strlen(domain));
2630                       p += strlen(domain);
2631                     }
2632                   if (null_term)
2633                     *(p++) = 0;
2634                 }
2635             }
2636         }
2637     }      
2638
2639   for (opt = config_opts; opt; opt = opt->next)
2640     {
2641       int optno = opt->opt;
2642
2643       /* netids match and not encapsulated? */
2644       if (!(opt->flags & DHOPT_TAGOK))
2645         continue;
2646       
2647       /* was it asked for, or are we sending it anyway? */
2648       if (!(opt->flags & DHOPT_FORCE) && !in_list(req_options, optno))
2649         continue;
2650       
2651       /* prohibit some used-internally options. T1 and T2 already handled. */
2652       if (optno == OPTION_CLIENT_FQDN ||
2653           optno == OPTION_MAXMESSAGE ||
2654           optno == OPTION_OVERLOAD ||
2655           optno == OPTION_PAD ||
2656           optno == OPTION_END ||
2657           optno == OPTION_T1 ||
2658           optno == OPTION_T2)
2659         continue;
2660
2661       if (optno == OPTION_SNAME && done_server)
2662         continue;
2663
2664       if (optno == OPTION_FILENAME && done_file)
2665         continue;
2666       
2667       /* For the options we have default values on
2668          dhc-option=<optionno> means "don't include this option"
2669          not "include a zero-length option" */
2670       if (opt->len == 0 && 
2671           (optno == OPTION_NETMASK ||
2672            optno == OPTION_BROADCAST ||
2673            optno == OPTION_ROUTER ||
2674            optno == OPTION_DNSSERVER || 
2675            optno == OPTION_DOMAINNAME ||
2676            optno == OPTION_HOSTNAME))
2677         continue;
2678
2679       /* vendor-class comes from elsewhere for PXE */
2680       if (pxe_arch != -1 && optno == OPTION_VENDOR_ID)
2681         continue;
2682       
2683       /* always force null-term for filename and servername - buggy PXE again. */
2684       len = do_opt(opt, NULL, context, 
2685                    (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2686
2687       if ((p = free_space(mess, end, optno, len)))
2688         {
2689           do_opt(opt, p, context, 
2690                  (optno == OPTION_SNAME || optno == OPTION_FILENAME) ? 1 : null_term);
2691           
2692           /* If we send a vendor-id, revisit which vendor-ops we consider 
2693              it appropriate to send. */
2694           if (optno == OPTION_VENDOR_ID)
2695             {
2696               match_vendor_opts(p - 2, config_opts);
2697               done_vendor_class = 1;
2698             }
2699         }  
2700     }
2701
2702   /* Now send options to be encapsulated in arbitrary options, 
2703      eg dhcp-option=encap:172,17,.......
2704      Also handle vendor-identifying vendor-encapsulated options,
2705      dhcp-option = vi-encap:13,17,.......
2706      The may be more that one "outer" to do, so group
2707      all the options which match each outer in turn. */
2708   for (opt = config_opts; opt; opt = opt->next)
2709     opt->flags &= ~DHOPT_ENCAP_DONE;
2710   
2711   for (opt = config_opts; opt; opt = opt->next)
2712     {
2713       int flags;
2714       
2715       if ((flags = (opt->flags & (DHOPT_ENCAPSULATE | DHOPT_RFC3925))))
2716         {
2717           int found = 0;
2718           struct dhcp_opt *o;
2719
2720           if (opt->flags & DHOPT_ENCAP_DONE)
2721             continue;
2722
2723           for (len = 0, o = config_opts; o; o = o->next)
2724             {
2725               int outer = flags & DHOPT_ENCAPSULATE ? o->u.encap : OPTION_VENDOR_IDENT_OPT;
2726
2727               o->flags &= ~DHOPT_ENCAP_MATCH;
2728               
2729               if (!(o->flags & flags) || opt->u.encap != o->u.encap)
2730                 continue;
2731               
2732               o->flags |= DHOPT_ENCAP_DONE;
2733               if (match_netid(o->netid, tagif, 1) &&
2734                   ((o->flags & DHOPT_FORCE) || in_list(req_options, outer)))
2735                 {
2736                   o->flags |= DHOPT_ENCAP_MATCH;
2737                   found = 1;
2738                   len += do_opt(o, NULL, NULL, 0) + 2;
2739                 }
2740             } 
2741           
2742           if (found)
2743             { 
2744               if (flags & DHOPT_ENCAPSULATE)
2745                 do_encap_opts(config_opts, opt->u.encap, DHOPT_ENCAP_MATCH, mess, end, null_term);
2746               else if (len > 250)
2747                 my_syslog(MS_DHCP | LOG_WARNING, _("cannot send RFC3925 option: too many options for enterprise number %d"), opt->u.encap);
2748               else if ((p = free_space(mess, end,  OPTION_VENDOR_IDENT_OPT, len + 5)))
2749                 {
2750                   int swap_ent = htonl(opt->u.encap);
2751                   memcpy(p, &swap_ent, 4);
2752                   p += 4;
2753                   *(p++) = len;
2754                   for (o = config_opts; o; o = o->next)
2755                     if (o->flags & DHOPT_ENCAP_MATCH)
2756                       {
2757                         len = do_opt(o, p + 2, NULL, 0);
2758                         *(p++) = o->opt;
2759                         *(p++) = len;
2760                         p += len;
2761                       }     
2762                 }
2763             }
2764         }
2765     }      
2766
2767   force_encap = prune_vendor_opts(tagif);
2768   
2769   if (context && pxe_arch != -1)
2770     {
2771       pxe_misc(mess, end, uuid, pxevendor);
2772       if (!pxe_uefi_workaround(pxe_arch, tagif, mess, context->local, now, 0))
2773         config_opts = pxe_opts(pxe_arch, tagif, context->local, now);
2774     }
2775
2776   if ((force_encap || in_list(req_options, OPTION_VENDOR_CLASS_OPT)) &&
2777       do_encap_opts(config_opts, OPTION_VENDOR_CLASS_OPT, DHOPT_VENDOR_MATCH, mess, end, null_term) && 
2778       pxe_arch == -1 && !done_vendor_class && vendor_class_len != 0 &&
2779       (p = free_space(mess, end, OPTION_VENDOR_ID, vendor_class_len)))
2780     /* If we send vendor encapsulated options, and haven't already sent option 60,
2781        echo back the value we got from the client. */
2782     memcpy(p, daemon->dhcp_buff3, vendor_class_len);        
2783    
2784    /* restore BOOTP anti-overload hack */
2785   if (!req_options || option_bool(OPT_NO_OVERRIDE))
2786     {
2787       mess->file[0] = f0;
2788       mess->sname[0] = s0;
2789     }
2790 }
2791
2792 static void apply_delay(u32 xid, time_t recvtime, struct dhcp_netid *netid)
2793 {
2794   struct delay_config *delay_conf;
2795   
2796   /* Decide which delay_config option we're using */
2797   for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
2798     if (match_netid(delay_conf->netid, netid, 0))
2799       break;
2800   
2801   if (!delay_conf)
2802     /* No match, look for one without a netid */
2803     for (delay_conf = daemon->delay_conf; delay_conf; delay_conf = delay_conf->next)
2804       if (match_netid(delay_conf->netid, netid, 1))
2805         break;
2806
2807   if (delay_conf)
2808     {
2809       if (!option_bool(OPT_QUIET_DHCP))
2810         my_syslog(MS_DHCP | LOG_INFO, _("%u reply delay: %d"), ntohl(xid), delay_conf->delay);
2811       delay_dhcp(recvtime, delay_conf->delay, -1, 0, 0);
2812     }
2813 }
2814
2815 #endif /* HAVE_DHCP */