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