eec47f1b026e225eafb77399f29c0b8f5de03a67
[freeradius.git] / src / modules / proto_dhcp / dhcp.c
1 /*
2  * dhcp.c       Functions to send/receive dhcp packets.
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2008 The FreeRADIUS server project
21  * Copyright 2008 Alan DeKok <aland@deployingradius.com>
22  */
23
24 RCSID("$Id$")
25
26 #include <freeradius-devel/libradius.h>
27 #include <freeradius-devel/udpfromto.h>
28 #include <freeradius-devel/dhcp.h>
29
30 #ifndef __MINGW32__
31 #include <sys/ioctl.h>
32 #endif
33
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
36 #endif
37 #ifdef HAVE_SYS_TYPES_H
38 #include <sys/types.h>
39 #endif
40
41 #ifndef __MINGW32__
42 #include <net/if_arp.h>
43 #endif
44
45 #define DHCP_CHADDR_LEN (16)
46 #define DHCP_SNAME_LEN  (64)
47 #define DHCP_FILE_LEN   (128)
48 #define DHCP_VEND_LEN   (308)
49 #define DHCP_OPTION_MAGIC_NUMBER (0x63825363)
50
51 #ifndef INADDR_BROADCAST
52 #define INADDR_BROADCAST INADDR_NONE
53 #endif
54
55 /* @todo: this is a hack */
56 #  define DEBUG                 if (fr_debug_flag && fr_log_fp) fr_printf_log
57 #  define debug_pair(vp)        do { if (fr_debug_flag && fr_log_fp) { \
58                                         vp_print(fr_log_fp, vp); \
59                                      } \
60                                 } while(0)
61
62 typedef struct dhcp_packet_t {
63         uint8_t         opcode;
64         uint8_t         htype;
65         uint8_t         hlen;
66         uint8_t         hops;
67         uint32_t        xid;    /* 4 */
68         uint16_t        secs;   /* 8 */
69         uint16_t        flags;
70         uint32_t        ciaddr; /* 12 */
71         uint32_t        yiaddr; /* 16 */
72         uint32_t        siaddr; /* 20 */
73         uint32_t        giaddr; /* 24 */
74         uint8_t         chaddr[DHCP_CHADDR_LEN]; /* 28 */
75         uint8_t         sname[DHCP_SNAME_LEN]; /* 44 */
76         uint8_t         file[DHCP_FILE_LEN]; /* 108 */
77         uint32_t        option_format; /* 236 */
78         uint8_t         options[DHCP_VEND_LEN];
79 } dhcp_packet_t;
80
81 typedef struct dhcp_option_t {
82         uint8_t         code;
83         uint8_t         length;
84 } dhcp_option_t;
85
86 /*
87  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        DISCOVER
88  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         OFFER
89  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        REQUEST
90  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         ACK
91  */
92 static char const *dhcp_header_names[] = {
93         "DHCP-Opcode",
94         "DHCP-Hardware-Type",
95         "DHCP-Hardware-Address-Length",
96         "DHCP-Hop-Count",
97         "DHCP-Transaction-Id",
98         "DHCP-Number-of-Seconds",
99         "DHCP-Flags",
100         "DHCP-Client-IP-Address",
101         "DHCP-Your-IP-Address",
102         "DHCP-Server-IP-Address",
103         "DHCP-Gateway-IP-Address",
104         "DHCP-Client-Hardware-Address",
105         "DHCP-Server-Host-Name",
106         "DHCP-Boot-Filename",
107
108         NULL
109 };
110
111 static char const *dhcp_message_types[] = {
112         "invalid",
113         "DHCP-Discover",
114         "DHCP-Offer",
115         "DHCP-Request",
116         "DHCP-Decline",
117         "DHCP-Ack",
118         "DHCP-NAK",
119         "DHCP-Release",
120         "DHCP-Inform",
121         "DHCP-Force-Renew",
122 };
123
124 static int dhcp_header_sizes[] = {
125         1, 1, 1, 1,
126         4, 2, 2, 4,
127         4, 4, 4,
128         DHCP_CHADDR_LEN,
129         DHCP_SNAME_LEN,
130         DHCP_FILE_LEN
131 };
132
133
134 /*
135  *      Some clients silently ignore responses less than 300 bytes.
136  */
137 #define MIN_PACKET_SIZE (244)
138 #define DEFAULT_PACKET_SIZE (300)
139 #define MAX_PACKET_SIZE (1500 - 40)
140
141 #define DHCP_OPTION_FIELD (0)
142 #define DHCP_FILE_FIELD   (1)
143 #define DHCP_SNAME_FIELD  (2)
144
145 static uint8_t *dhcp_get_option(dhcp_packet_t *packet, size_t packet_size,
146                                 unsigned int option)
147 {
148         int overload = 0;
149         int field = DHCP_OPTION_FIELD;
150         size_t where, size;
151         uint8_t *data;
152
153         where = 0;
154         size = packet_size - offsetof(dhcp_packet_t, options);
155         data = &packet->options[where];
156
157         while (where < size) {
158                 if (data[0] == 0) { /* padding */
159                         where++;
160                         continue;
161                 }
162
163                 if (data[0] == 255) { /* end of options */
164                         if ((field == DHCP_OPTION_FIELD) &&
165                             (overload & DHCP_FILE_FIELD)) {
166                                 data = packet->file;
167                                 where = 0;
168                                 size = sizeof(packet->file);
169                                 field = DHCP_FILE_FIELD;
170                                 continue;
171
172                         } else if ((field == DHCP_FILE_FIELD) &&
173                                    (overload & DHCP_SNAME_FIELD)) {
174                                 data = packet->sname;
175                                 where = 0;
176                                 size = sizeof(packet->sname);
177                                 field = DHCP_SNAME_FIELD;
178                                 continue;
179                         }
180
181                         return NULL;
182                 }
183
184                 /*
185                  *      We MUST have a real option here.
186                  */
187                 if ((where + 2) > size) {
188                         fr_strerror_printf("Options overflow field at %u",
189                                            (unsigned int) (data - (uint8_t *) packet));
190                         return NULL;
191                 }
192
193                 if ((where + 2 + data[1]) > size) {
194                         fr_strerror_printf("Option length overflows field at %u",
195                                            (unsigned int) (data - (uint8_t *) packet));
196                         return NULL;
197                 }
198
199                 if (data[0] == option) return data;
200
201                 if (data[0] == 52) { /* overload sname and/or file */
202                         overload = data[3];
203                 }
204
205                 where += data[1] + 2;
206                 data += data[1] + 2;
207         }
208
209         return NULL;
210 }
211
212 /*
213  *      DHCPv4 is only for IPv4.  Broadcast only works if udpfromto is
214  *      defined.
215  */
216 RADIUS_PACKET *fr_dhcp_recv(int sockfd)
217 {
218         uint32_t                magic;
219         struct sockaddr_storage src;
220         struct sockaddr_storage dst;
221         socklen_t               sizeof_src;
222         socklen_t               sizeof_dst;
223         RADIUS_PACKET           *packet;
224         uint16_t                port;
225         uint8_t                 *code;
226         ssize_t                 data_len;
227
228         packet = rad_alloc(NULL, false);
229         if (!packet) {
230                 fr_strerror_printf("Failed allocating packet");
231                 return NULL;
232         }
233
234         packet->data = talloc_zero_array(packet, uint8_t, MAX_PACKET_SIZE);
235         if (!packet->data) {
236                 fr_strerror_printf("Out of memory");
237                 rad_free(&packet);
238                 return NULL;
239         }
240
241         packet->sockfd = sockfd;
242         sizeof_src = sizeof(src);
243 #ifdef WITH_UDPFROMTO
244         sizeof_dst = sizeof(dst);
245         data_len = recvfromto(sockfd, packet->data, MAX_PACKET_SIZE, 0,
246                               (struct sockaddr *)&src, &sizeof_src,
247                               (struct sockaddr *)&dst, &sizeof_dst);
248 #else
249         data_len = recvfrom(sockfd, packet->data, MAX_PACKET_SIZE, 0,
250                             (struct sockaddr *)&src, &sizeof_src);
251 #endif
252
253         if (data_len <= 0) {
254                 fr_strerror_printf("Failed reading DHCP socket: %s", fr_syserror(errno));
255                 rad_free(&packet);
256                 return NULL;
257         }
258
259         packet->data_len = data_len;
260         if (packet->data_len < MIN_PACKET_SIZE) {
261                 fr_strerror_printf("DHCP packet is too small (%zu < %d)",
262                                    packet->data_len, MIN_PACKET_SIZE);
263                 rad_free(&packet);
264                 return NULL;
265         }
266
267         if (packet->data_len > MAX_PACKET_SIZE) {
268                 fr_strerror_printf("DHCP packet is too large (%zx > %d)",
269                                    packet->data_len, MAX_PACKET_SIZE);
270                 rad_free(&packet);
271                 return NULL;
272         }
273
274         if (packet->data[1] != 1) {
275                 fr_strerror_printf("DHCP can only receive ethernet requests, not type %02x",
276                       packet->data[1]);
277                 rad_free(&packet);
278                 return NULL;
279         }
280
281         if (packet->data[2] != 6) {
282                 fr_strerror_printf("Ethernet HW length is wrong length %d",
283                         packet->data[2]);
284                 rad_free(&packet);
285                 return NULL;
286         }
287
288         memcpy(&magic, packet->data + 236, 4);
289         magic = ntohl(magic);
290         if (magic != DHCP_OPTION_MAGIC_NUMBER) {
291                 fr_strerror_printf("Cannot do BOOTP");
292                 rad_free(&packet);
293                 return NULL;
294         }
295
296         /*
297          *      Create unique keys for the packet.
298          */
299         memcpy(&magic, packet->data + 4, 4);
300         packet->id = ntohl(magic);
301
302         code = dhcp_get_option((dhcp_packet_t *) packet->data,
303                                packet->data_len, 53);
304         if (!code) {
305                 fr_strerror_printf("No message-type option was found in the packet");
306                 rad_free(&packet);
307                 return NULL;
308         }
309
310         if ((code[1] < 1) || (code[2] == 0) || (code[2] > 8)) {
311                 fr_strerror_printf("Unknown value for message-type option");
312                 rad_free(&packet);
313                 return NULL;
314         }
315
316         packet->code = code[2] | PW_DHCP_OFFSET;
317
318         /*
319          *      Create a unique vector from the MAC address and the
320          *      DHCP opcode.  This is a hack for the RADIUS
321          *      infrastructure in the rest of the server.
322          *
323          *      Note: packet->data[2] == 6, which is smaller than
324          *      sizeof(packet->vector)
325          *
326          *      FIXME:  Look for client-identifier in packet,
327          *      and use that, too?
328          */
329         memset(packet->vector, 0, sizeof(packet->vector));
330         memcpy(packet->vector, packet->data + 28, packet->data[2]);
331         packet->vector[packet->data[2]] = packet->code & 0xff;
332
333         /*
334          *      FIXME: for DISCOVER / REQUEST: src_port == dst_port + 1
335          *      FIXME: for OFFER / ACK       : src_port = dst_port - 1
336          */
337
338         /*
339          *      Unique keys are xid, client mac, and client ID?
340          */
341
342         /*
343          *      FIXME: More checks, like DHCP packet type?
344          */
345
346         sizeof_dst = sizeof(dst);
347
348 #ifndef WITH_UDPFROMTO
349         /*
350          *      This should never fail...
351          */
352         if (getsockname(sockfd, (struct sockaddr *) &dst, &sizeof_dst) < 0) {
353                 fr_strerror_printf("getsockname failed: %s", fr_syserror(errno));
354                 rad_free(&packet);
355                 return NULL;
356         }
357 #endif
358
359         fr_sockaddr2ipaddr(&dst, sizeof_dst, &packet->dst_ipaddr, &port);
360         packet->dst_port = port;
361
362         fr_sockaddr2ipaddr(&src, sizeof_src, &packet->src_ipaddr, &port);
363         packet->src_port = port;
364
365         if (fr_debug_flag > 1) {
366                 char type_buf[64];
367                 char const *name = type_buf;
368                 char src_ip_buf[256], dst_ip_buf[256];
369
370                 if ((packet->code >= PW_DHCP_DISCOVER) &&
371                     (packet->code <= PW_DHCP_INFORM)) {
372                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
373                 } else {
374                         snprintf(type_buf, sizeof(type_buf), "%d",
375                                  packet->code - PW_DHCP_OFFSET);
376                 }
377
378                 DEBUG("Received %s of Id %08x from %s:%d to %s:%d\n",
379                        name, (unsigned int) packet->id,
380                        inet_ntop(packet->src_ipaddr.af,
381                                  &packet->src_ipaddr.ipaddr,
382                                  src_ip_buf, sizeof(src_ip_buf)),
383                        packet->src_port,
384                        inet_ntop(packet->dst_ipaddr.af,
385                                  &packet->dst_ipaddr.ipaddr,
386                                  dst_ip_buf, sizeof(dst_ip_buf)),
387                        packet->dst_port);
388         }
389
390         return packet;
391 }
392
393
394 /*
395  *      Send a DHCP packet.
396  */
397 int fr_dhcp_send(RADIUS_PACKET *packet)
398 {
399         struct sockaddr_storage dst;
400         socklen_t               sizeof_dst;
401 #ifdef WITH_UDPFROMTO
402         struct sockaddr_storage src;
403         socklen_t               sizeof_src;
404
405         fr_ipaddr2sockaddr(&packet->src_ipaddr, packet->src_port,
406             &src, &sizeof_src);
407 #endif
408
409         fr_ipaddr2sockaddr(&packet->dst_ipaddr, packet->dst_port,
410                            &dst, &sizeof_dst);
411
412         if (packet->data_len == 0) {
413                 fr_strerror_printf("No data to send");
414                 return -1;
415         }
416
417         if (fr_debug_flag > 1) {
418                 char type_buf[64];
419                 char const *name = type_buf;
420 #ifdef WITH_UDPFROMTO
421                 char src_ip_buf[INET6_ADDRSTRLEN];
422 #endif
423                 char dst_ip_buf[INET6_ADDRSTRLEN];
424
425                 if ((packet->code >= PW_DHCP_DISCOVER) &&
426                     (packet->code <= PW_DHCP_INFORM)) {
427                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
428                 } else {
429                         snprintf(type_buf, sizeof(type_buf), "%d",
430                             packet->code - PW_DHCP_OFFSET);
431                 }
432
433                 DEBUG(
434 #ifdef WITH_UDPFROMTO
435                 "Sending %s Id %08x from %s:%d to %s:%d\n",
436 #else
437                 "Sending %s Id %08x to %s:%d\n",
438 #endif
439                    name, (unsigned int) packet->id,
440 #ifdef WITH_UDPFROMTO
441                    inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, src_ip_buf, sizeof(src_ip_buf)),
442                    packet->src_port,
443 #endif
444                    inet_ntop(packet->dst_ipaddr.af, &packet->dst_ipaddr.ipaddr, dst_ip_buf, sizeof(dst_ip_buf)),
445                    packet->dst_port);
446         }
447
448 #ifndef WITH_UDPFROMTO
449         /*
450          *      Assume that the packet is encoded before sending it.
451          */
452         return sendto(packet->sockfd, packet->data, packet->data_len, 0,
453                       (struct sockaddr *)&dst, sizeof_dst);
454 #else
455
456         return sendfromto(packet->sockfd, packet->data, packet->data_len, 0,
457                           (struct sockaddr *)&src, sizeof_src,
458                           (struct sockaddr *)&dst, sizeof_dst);
459 #endif
460 }
461
462 static int fr_dhcp_attr2vp(RADIUS_PACKET *packet, VALUE_PAIR *vp, uint8_t const *p, size_t alen);
463
464 static int fr_dhcp_decode_suboption(RADIUS_PACKET *packet, VALUE_PAIR *tlv, uint8_t const *data, size_t data_len)
465 {
466         uint8_t const *p, *q;
467         VALUE_PAIR *head, *vp;
468         vp_cursor_t cursor;
469
470         /*
471          *      Take a pass at parsing it.
472          */
473         p = data;
474         q = data + data_len;
475         while (p < q) {
476                 /*
477                  *      The RFC 3046 is very specific about not allowing termination
478                  *      with a 255 sub-option. But vendors are stupid, so allow it
479                  *      and the 0 padding sub-option.
480                  *      This requirement really should be a SHOULD anyway...
481                  */
482                 if (*p == 0) {
483                         p++;
484                         continue;
485                 }
486                 if (*p == 255) {
487                         q--;
488                         break;
489                 }
490
491                 /*
492                  *      Check if reading length would take us past the end of the buffer
493                  */
494                 if (++p >= q) goto malformed;
495                 p += p[0];
496
497                 /*
498                  *      Check if length > the length of the buffer we have left
499                  */
500                 if (p >= q) goto malformed;
501                 p++;
502         }
503
504         /*
505          *      Got here... must be well formed.
506          */
507         head = NULL;
508         fr_cursor_init(&cursor, &head);
509
510         p = data;
511         while (p < q) {
512                 vp = paircreate(packet, tlv->da->attr | (p[0] << 8), DHCP_MAGIC_VENDOR);
513                 if (!vp) {
514                         pairfree(&head);
515                         goto malformed;
516                 }
517
518                 if (fr_dhcp_attr2vp(packet, vp, p + 2, p[1]) < 0) {
519                         pairfree(&head);
520                         goto malformed;
521                 }
522
523                 fr_cursor_insert(&cursor, vp);
524                 p += 2 + p[1];
525         }
526
527         /*
528          *      The caller allocated TLV, so we need to copy the FIRST
529          *      attribute over top of that.
530          *
531          *      This is a pretty awful hack, but we should be able to
532          *      clean it up when we get nested VPs so lets leave it for
533          *      now.
534          */
535         if (head) {
536                 /* Cleanup any old TLV data */
537                 talloc_free(tlv->vp_tlv);
538
539                 /* @fixme fragile */
540                 memcpy(tlv, head, sizeof(*tlv));
541
542                 /* If the VP has a talloced value we need to reparent it to the original TLV attribute */
543                 switch (head->da->type) {
544                         case PW_TYPE_STRING:
545                         case PW_TYPE_OCTETS:
546                         case PW_TYPE_TLV:
547                                 (void) talloc_steal(tlv, head->data.ptr);
548
549                         default:
550                                 break;
551                 }
552                 tlv->next = head->next;
553                 talloc_free(head);
554         }
555
556         return 0;
557
558 malformed:
559         tlv->vp_tlv = talloc_array(tlv, uint8_t, data_len);
560         if (!tlv->vp_tlv) {
561                 fr_strerror_printf("No memory");
562                 return -1;
563         }
564         memcpy(tlv->vp_tlv, data, data_len);
565         tlv->length = data_len;
566
567         return 0;
568 }
569
570
571 /*
572  *      Decode ONE value into a VP
573  */
574 static int fr_dhcp_attr2vp(RADIUS_PACKET *packet, VALUE_PAIR *vp, uint8_t const *p, size_t alen)
575 {
576         char *q;
577
578         switch (vp->da->type) {
579         case PW_TYPE_BYTE:
580                 if (alen != 1) goto raw;
581                 vp->vp_byte = p[0];
582                 break;
583
584         case PW_TYPE_SHORT:
585                 if (alen != 2) goto raw;
586                 memcpy(&vp->vp_short, p, 2);
587                 vp->vp_short = ntohs(vp->vp_short);
588                 break;
589
590         case PW_TYPE_INTEGER:
591                 if (alen != 4) goto raw;
592                 memcpy(&vp->vp_integer, p, 4);
593                 vp->vp_integer = ntohl(vp->vp_integer);
594                 break;
595
596         case PW_TYPE_IPV4_ADDR:
597                 if (alen != 4) goto raw;
598                 /*
599                  *      Keep value in Network Order!
600                  */
601                 memcpy(&vp->vp_ipaddr, p , 4);
602                 vp->length = 4;
603                 break;
604
605         case PW_TYPE_STRING:
606                 vp->vp_strvalue = q = talloc_array(vp, char, alen + 1);
607                 vp->type = VT_DATA;
608                 memcpy(q, p , alen);
609                 q[alen] = '\0';
610                 break;
611
612         case PW_TYPE_ETHERNET:
613                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
614                 vp->length = sizeof(vp->vp_ether);
615                 break;
616
617         /*
618          *      Value doesn't match up with attribute type, overwrite the
619          *      vp's original DICT_ATTR with an unknown one.
620          */
621         raw:
622                 if (pair2unknown(vp) < 0) return -1;
623
624         case PW_TYPE_OCTETS:
625                 if (alen > 255) return -1;
626                 pairmemcpy(vp, p, alen);
627                 break;
628
629         /*
630          *      For option 82 et al...
631          */
632         case PW_TYPE_TLV:
633                 return fr_dhcp_decode_suboption(packet, vp, p, alen);
634
635         default:
636                 fr_strerror_printf("Internal sanity check %d %d", vp->da->type, __LINE__);
637                 return -1;
638         } /* switch over type */
639
640         vp->length = alen;
641         return 0;
642 }
643
644 ssize_t fr_dhcp_decode_options(RADIUS_PACKET *packet,
645                                uint8_t const *data, size_t len, VALUE_PAIR **head)
646 {
647         int i;
648         VALUE_PAIR *vp;
649         vp_cursor_t cursor;
650         uint8_t const *p, *next;
651         next = data;
652
653         *head = NULL;
654         fr_cursor_init(&cursor, head);
655
656         /*
657          *      FIXME: This should also check sname && file fields.
658          *      See the dhcp_get_option() function above.
659          */
660         while (next < (data + len)) {
661                 int num_entries, alen;
662                 DICT_ATTR const *da;
663
664                 p = next;
665
666                 if (*p == 0) {          /* 0x00 - Padding option */
667                         next++;
668                         continue;
669                 }
670                 if (*p == 255) break;   /* 0xff - End of options signifier */
671
672                 if ((p + 2) > (data + len)) break;
673
674                 next = p + 2 + p[1];
675
676                 da = dict_attrbyvalue(p[0], DHCP_MAGIC_VENDOR);
677                 if (!da) {
678                         fr_strerror_printf("Attribute not in our dictionary: %u", p[0]);
679                         continue;
680                 }
681
682                 vp = NULL;
683                 num_entries = 1;
684                 alen = p[1];
685                 p += 2;
686
687                 /*
688                  *      Could be an array of bytes, integers, etc.
689                  */
690                 if (da->flags.array) {
691                         switch (da->type) {
692                         case PW_TYPE_BYTE:
693                                 num_entries = alen;
694                                 alen = 1;
695                                 break;
696
697                         case PW_TYPE_SHORT: /* ignore any trailing data */
698                                 num_entries = alen >> 1;
699                                 alen = 2;
700                                 break;
701
702                         case PW_TYPE_IPV4_ADDR:
703                         case PW_TYPE_INTEGER:
704                         case PW_TYPE_DATE: /* ignore any trailing data */
705                                 num_entries = alen >> 2;
706                                 alen = 4;
707                                 break;
708
709                         default:
710
711                                 break; /* really an internal sanity failure */
712                         }
713                 }
714
715                 /*
716                  *      Loop over all of the entries, building VPs
717                  */
718                 for (i = 0; i < num_entries; i++) {
719                         vp = pairmake(packet, NULL, da->name, NULL, T_OP_ADD);
720                         if (!vp) {
721                                 fr_strerror_printf("Cannot build attribute %s", fr_strerror());
722                                 pairfree(head);
723                                 return -1;
724                         }
725
726                         if (fr_dhcp_attr2vp(packet, vp, p, alen) < 0) {
727                                 pairfree(&vp);
728                                 pairfree(head);
729                                 return -1;
730                         }
731
732                         fr_cursor_insert(&cursor, vp);
733
734                         for (vp = fr_cursor_current(&cursor);
735                              vp;
736                              vp = fr_cursor_next(&cursor)) {
737                                 debug_pair(vp);
738                         }
739                         p += alen;
740                 } /* loop over array entries */
741         } /* loop over the entire packet */
742
743         return next - data;
744 }
745
746 int fr_dhcp_decode(RADIUS_PACKET *packet)
747 {
748         size_t i;
749         uint8_t *p;
750         uint32_t giaddr;
751         vp_cursor_t cursor;
752         VALUE_PAIR *head = NULL, *vp;
753         VALUE_PAIR *maxms, *mtu;
754
755         fr_cursor_init(&cursor, &head);
756         p = packet->data;
757
758         if ((fr_debug_flag > 2) && fr_log_fp) {
759                 for (i = 0; i < packet->data_len; i++) {
760                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
761                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
762                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
763                 }
764                 fprintf(fr_log_fp, "\n");
765         }
766
767         if (packet->data[1] != 1) {
768                 fr_strerror_printf("Packet is not Ethernet: %u",
769                       packet->data[1]);
770                 return -1;
771         }
772
773         /*
774          *      Decode the header.
775          */
776         for (i = 0; i < 14; i++) {
777                 char *q;
778
779                 vp = pairmake(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
780                 if (!vp) {
781                         char buffer[256];
782                         strlcpy(buffer, fr_strerror(), sizeof(buffer));
783                         fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
784                         pairfree(&head);
785                         return -1;
786                 }
787
788                 /*
789                  *      If chaddr does != 6 bytes it's probably not ethernet, and we should store
790                  *      it as an opaque type (octets).
791                  */
792                 if ((i == 11) && (packet->data[1] == 1) && (packet->data[2] != sizeof(vp->vp_ether))) {
793                         DICT_ATTR const *da = dict_attrunknown(vp->da->attr, vp->da->vendor, true);
794                         if (!da) {
795                                 return -1;
796                         }
797                         vp->da = da;
798                 }
799
800                 switch (vp->da->type) {
801                 case PW_TYPE_BYTE:
802                         vp->vp_byte = p[0];
803                         vp->length = 1;
804                         break;
805
806                 case PW_TYPE_SHORT:
807                         vp->vp_short = (p[0] << 8) | p[1];
808                         vp->length = 2;
809                         break;
810
811                 case PW_TYPE_INTEGER:
812                         memcpy(&vp->vp_integer, p, 4);
813                         vp->vp_integer = ntohl(vp->vp_integer);
814                         vp->length = 4;
815                         break;
816
817                 case PW_TYPE_IPV4_ADDR:
818                         memcpy(&vp->vp_ipaddr, p, 4);
819                         vp->length = 4;
820                         break;
821
822                 case PW_TYPE_STRING:
823                         vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
824                         vp->type = VT_DATA;
825                         memcpy(q, p, dhcp_header_sizes[i]);
826                         q[dhcp_header_sizes[i]] = '\0';
827                         vp->length = strlen(vp->vp_strvalue);
828                         if (vp->length == 0) {
829                                 pairfree(&vp);
830                         }
831                         break;
832
833                 case PW_TYPE_OCTETS:
834                         pairmemcpy(vp, p, packet->data[2]);
835                         break;
836
837                 case PW_TYPE_ETHERNET:
838                         memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
839                         vp->length = sizeof(vp->vp_ether);
840                         break;
841
842                 default:
843                         fr_strerror_printf("BAD TYPE %d", vp->da->type);
844                         pairfree(&vp);
845                         break;
846                 }
847                 p += dhcp_header_sizes[i];
848
849                 if (!vp) continue;
850
851                 debug_pair(vp);
852                 fr_cursor_insert(&cursor, vp);
853         }
854
855         /*
856          *      Loop over the options.
857          */
858
859         /*
860          *      Nothing uses tail after this call, if it does in the future
861          *      it'll need to find the new tail...
862          */
863         {
864                 VALUE_PAIR *options = NULL;
865
866                 if (fr_dhcp_decode_options(packet,
867                                            packet->data + 240, packet->data_len - 240,
868                                            &options) < 0) {
869                         return -1;
870                 }
871
872                 if (options) {
873                         fr_cursor_insert(&cursor, options);
874                 }
875         }
876
877         /*
878          *      If DHCP request, set ciaddr to zero.
879          */
880
881         /*
882          *      Set broadcast flag for broken vendors, but only if
883          *      giaddr isn't set.
884          */
885         memcpy(&giaddr, packet->data + 24, sizeof(giaddr));
886         if (giaddr == htonl(INADDR_ANY)) {
887                 /*
888                  *      DHCP Opcode is request
889                  */
890                 vp = pairfind(head, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
891                 if (vp && vp->vp_integer == 3) {
892                         /*
893                          *      Vendor is "MSFT 98"
894                          */
895                         vp = pairfind(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
896                         if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
897                                 vp = pairfind(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
898
899                                 /*
900                                  *      Reply should be broadcast.
901                                  */
902                                 if (vp) vp->vp_integer |= 0x8000;
903                                 packet->data[10] |= 0x80;
904                         }
905                 }
906         }
907
908         /*
909          *      FIXME: Nuke attributes that aren't used in the normal
910          *      header for discover/requests.
911          */
912         packet->vps = head;
913
914         /*
915          *      Client can request a LARGER size, but not a smaller
916          *      one.  They also cannot request a size larger than MTU.
917          */
918         maxms = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
919         mtu = pairfind(packet->vps, 26, DHCP_MAGIC_VENDOR, TAG_ANY);
920
921         if (mtu && (mtu->vp_integer < DEFAULT_PACKET_SIZE)) {
922                 fr_strerror_printf("DHCP Fatal: Client says MTU is smaller than minimum permitted by the specification");
923                 return -1;
924         }
925
926         if (maxms && (maxms->vp_integer < DEFAULT_PACKET_SIZE)) {
927                 fr_strerror_printf("DHCP WARNING: Client says maximum message size is smaller than minimum permitted by the specification: fixing it");
928                 maxms->vp_integer = DEFAULT_PACKET_SIZE;
929         }
930
931         if (maxms && mtu && (maxms->vp_integer > mtu->vp_integer)) {
932                 fr_strerror_printf("DHCP WARNING: Client says MTU is smaller than maximum message size: fixing it");
933                 maxms->vp_integer = mtu->vp_integer;
934         }
935
936         if (fr_debug_flag) fflush(stdout);
937
938         return 0;
939 }
940
941
942 int8_t fr_dhcp_attr_cmp(void const *a, void const *b)
943 {
944         VALUE_PAIR const *my_a = a;
945         VALUE_PAIR const *my_b = b;
946
947         VERIFY_VP(my_a);
948         VERIFY_VP(my_b);
949
950         /*
951          *      DHCP-Message-Type is first, for simplicity.
952          */
953         if ((my_a->da->attr == 53) && (my_b->da->attr != 53)) return -1;
954
955         /*
956          *      Relay-Agent is last
957          */
958         if ((my_a->da->attr == 82) && (my_b->da->attr != 82)) return 1;
959
960         if (my_a->da->attr < my_b->da->attr) return -1;
961         if (my_a->da->attr > my_b->da->attr) return 1;
962
963         return 0;
964 }
965
966 /** Write DHCP option value into buffer
967  *
968  * Does not include DHCP option length or number.
969  *
970  * @param out where to write the DHCP option.
971  * @param outlen length of output buffer.
972  * @param vp option to encode.
973  * @return the length of data writen, -1 if out of buffer, -2 if unsupported type.
974  */
975 static ssize_t fr_dhcp_vp2attr(uint8_t *out, size_t outlen, VALUE_PAIR *vp)
976 {
977         uint32_t lvalue;
978         uint8_t *p = out;
979
980         if (outlen < vp->length) {
981                 return -1;
982         }
983
984         switch (vp->da->type) {
985         case PW_TYPE_BYTE:
986                 *p = vp->vp_byte;
987                 break;
988
989         case PW_TYPE_SHORT:
990                 p[0] = (vp->vp_short >> 8) & 0xff;
991                 p[1] = vp->vp_short & 0xff;
992                 break;
993
994         case PW_TYPE_INTEGER:
995                 lvalue = htonl(vp->vp_integer);
996                 memcpy(p, &lvalue, 4);
997                 break;
998
999         case PW_TYPE_IPV4_ADDR:
1000                 memcpy(p, &vp->vp_ipaddr, 4);
1001                 break;
1002
1003         case PW_TYPE_ETHERNET:
1004                 memcpy(p, &vp->vp_ether, 6);
1005                 break;
1006
1007         case PW_TYPE_STRING:
1008                 memcpy(p, vp->vp_strvalue, vp->length);
1009                 break;
1010
1011         case PW_TYPE_TLV:       /* FIXME: split it on 255? */
1012                 memcpy(p, vp->vp_tlv, vp->length);
1013                 break;
1014
1015         case PW_TYPE_OCTETS:
1016                 memcpy(p, vp->vp_octets, vp->length);
1017                 break;
1018
1019         default:
1020                 fr_strerror_printf("Unsupported option type %d", vp->da->type);
1021                 return -2;
1022         }
1023
1024         return vp->length;
1025 }
1026
1027 /** Create a new TLV attribute from multiple sub options
1028  *
1029  * @param[in,out] ctx to allocate new attribute in.
1030  * @param[in,out] cursor should be set to the start of the list of TLV attributes.
1031  *   Will be advanced to the first non-TLV attribute.
1032  * @return attribute holding the concatenation of the values of the sub options.
1033  */
1034 static VALUE_PAIR *fr_dhcp_vp2suboption(TALLOC_CTX *ctx, vp_cursor_t *cursor)
1035 {
1036         ssize_t length;
1037         unsigned int parent;    /* Parent attribute of suboption */
1038         uint8_t attr = 0;
1039         uint8_t *p, *opt_len = NULL;
1040         vp_cursor_t to_pack;
1041         VALUE_PAIR *vp, *tlv;
1042
1043 #define SUBOPTION_PARENT(_x) (_x & 0xffff00ff)
1044 #define SUBOPTION_ATTR(_x) ((_x & 0xff00) >> 8)
1045
1046         vp = fr_cursor_current(cursor);
1047         if (!vp) return NULL;
1048
1049         parent = SUBOPTION_PARENT(vp->da->attr);
1050         tlv = paircreate(ctx, parent, DHCP_MAGIC_VENDOR);
1051         if (!tlv) return NULL;
1052
1053         fr_cursor_copy(&to_pack, cursor);
1054
1055         /*
1056          *  Loop over TLVs to determine how much memory we need to allocate
1057          *
1058          *  We advanced the cursor we were passed, so if we fail encoding,
1059          *  the cursor is at the right position for the next potentially
1060          *  encodable attr.
1061          */
1062         for (vp = fr_cursor_current(cursor);
1063              vp && vp->da->flags.is_tlv && !vp->da->flags.extended && (SUBOPTION_PARENT(vp->da->attr) == parent);
1064              vp = fr_cursor_next(cursor)) {
1065                 /*
1066                  *  If it's not an array type or is an array type, but is not the same
1067                  *  as the previous attribute, we add 2 for the additional sub-option
1068                  *  header bytes.
1069                  */
1070                 if (!vp->da->flags.array || (SUBOPTION_ATTR(vp->da->attr) != attr)) {
1071                         attr = SUBOPTION_ATTR(vp->da->attr);
1072                         tlv->length += 2;
1073                 }
1074                 tlv->length += vp->length;
1075         }
1076
1077         tlv->vp_tlv = talloc_array(tlv, uint8_t, tlv->length);
1078         if (!tlv->vp_tlv) {
1079                 talloc_free(tlv);
1080                 return NULL;
1081         }
1082         p = tlv->vp_tlv;
1083
1084         attr = 0;
1085         for (vp = fr_cursor_current(&to_pack);
1086              vp && vp->da->flags.is_tlv && !vp->da->flags.extended && (SUBOPTION_PARENT(vp->da->attr) == parent);
1087              vp = fr_cursor_next(&to_pack)) {
1088                 if (SUBOPTION_ATTR(vp->da->attr) == 0) {
1089                         fr_strerror_printf("Invalid attribute number 0");
1090                         return NULL;
1091                 }
1092
1093                 /* Don't write out the header, were packing array options */
1094                 if (!vp->da->flags.array || (attr != SUBOPTION_ATTR(vp->da->attr))) {
1095                         attr = SUBOPTION_ATTR(vp->da->attr);
1096                         *p++ = attr;
1097                         opt_len = p++;
1098                 }
1099
1100                 length = fr_dhcp_vp2attr(p, (tlv->vp_tlv + tlv->length) - p, vp);
1101                 if ((length < 0) || (length > 255)) {
1102                         talloc_free(tlv);
1103                         return NULL;
1104                 }
1105
1106                 fr_assert(opt_len);
1107                 *opt_len += length;
1108                 p += length;
1109         };
1110
1111         return tlv;
1112 }
1113
1114 /** Encode a DHCP option and any sub-options.
1115  *
1116  * @param out Where to write encoded DHCP attributes.
1117  * @param outlen Length of out buffer.
1118  * @param ctx to use for any allocated memory.
1119  * @param cursor with current VP set to the option to be encoded. Will be advanced to the next option to encode.
1120  * @return > 0 length of data written, < 0 error, 0 not valid option (skipping).
1121  */
1122 ssize_t fr_dhcp_encode_option(uint8_t *out, size_t outlen, TALLOC_CTX *ctx, vp_cursor_t *cursor)
1123 {
1124         VALUE_PAIR *vp;
1125         DICT_ATTR const *previous;
1126         uint8_t *opt_len, *p = out;
1127         size_t freespace = outlen;
1128         ssize_t len;
1129
1130         vp = fr_cursor_current(cursor);
1131         if (!vp) return -1;
1132
1133         if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
1134         if (vp->da->attr == 53) goto next; /* already done */
1135         if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
1136
1137         if (vp->da->flags.extended) {
1138         next:
1139                 fr_strerror_printf("Attribute \"%s\" is not a DHCP option", vp->da->name);
1140                 fr_cursor_next(cursor);
1141                 return 0;
1142         }
1143
1144         /* Write out the option number */
1145         *(p++) = vp->da->attr & 0xff;
1146
1147         /* Pointer to the length field of the option */
1148         opt_len = p++;
1149
1150         /* Zero out the option's length field */
1151         *opt_len = 0;
1152
1153         /* We just consumed two bytes for the header */
1154         freespace -= 2;
1155
1156         /* DHCP options with the same number get coalesced into a single option */
1157         do {
1158                 VALUE_PAIR *tlv = NULL;
1159
1160                 /* Sub option */
1161                 if (vp->da->flags.is_tlv) {
1162                         /*
1163                          *  Coalesce TLVs into one sub-option.
1164                          *  Cursor will be advanced to next non-TLV attribute.
1165                          */
1166                         tlv = vp = fr_dhcp_vp2suboption(ctx, cursor);
1167
1168                         /*
1169                          *  Skip if there's an issue coalescing the sub-options.
1170                          *  Cursor will still have been advanced to next non-TLV attribute.
1171                          */
1172                         if (!tlv) return 0;
1173                 /*
1174                  *  If not calling fr_dhcp_vp2suboption() advance the cursor, so fr_cursor_current()
1175                  *  returns the next attribute.
1176                  */
1177                 } else {
1178                         fr_cursor_next(cursor);
1179                 }
1180
1181                 if ((*opt_len + vp->length) > 255) {
1182                         fr_strerror_printf("Skipping \"%s\": Option splitting not supported "
1183                                            "(option > 255 bytes)", vp->da->name);
1184                         talloc_free(tlv);
1185                         return 0;
1186                 }
1187
1188                 len = fr_dhcp_vp2attr(p, freespace, vp);
1189                 talloc_free(tlv);
1190                 if (len < 0) {
1191                         /* Failed encoding option */
1192                         return len;
1193                 }
1194
1195                 p += len;
1196                 *opt_len += len;
1197                 freespace -= len;
1198
1199                 previous = vp->da;
1200         } while ((vp = fr_cursor_current(cursor)) && (previous == vp->da) && vp->da->flags.array);
1201
1202         return p - out;
1203 }
1204
1205 int fr_dhcp_encode(RADIUS_PACKET *packet)
1206 {
1207         unsigned int i;
1208         uint8_t *p;
1209         vp_cursor_t cursor;
1210         VALUE_PAIR *vp;
1211         uint32_t lvalue;
1212         size_t dhcp_size;
1213         ssize_t len;
1214 #ifndef NDEBUG
1215         char const *name;
1216 #  ifdef WITH_UDPFROMTO
1217         char src_ip_buf[256];
1218 #  endif
1219         char dst_ip_buf[256];
1220 #endif
1221
1222         if (packet->data) return 0;
1223
1224         packet->data_len = MAX_PACKET_SIZE;
1225         packet->data = talloc_zero_array(packet, uint8_t, packet->data_len);
1226
1227         /* XXX Ugly ... should be set by the caller */
1228         if (packet->code == 0) packet->code = PW_DHCP_NAK;
1229
1230 #ifndef NDEBUG
1231         if ((packet->code >= PW_DHCP_DISCOVER) &&
1232             (packet->code <= PW_DHCP_INFORM)) {
1233                 name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
1234         } else {
1235                 name = "?Unknown?";
1236         }
1237
1238         DEBUG(
1239 #  ifdef WITH_UDPFROMTO
1240               "Encoding %s of id %08x from %s:%d to %s:%d\n",
1241 #  else
1242               "Encoding %s of id %08x to %s:%d\n",
1243 #  endif
1244               name, (unsigned int) packet->id,
1245 #  ifdef WITH_UDPFROMTO
1246               inet_ntop(packet->src_ipaddr.af,
1247                         &packet->src_ipaddr.ipaddr,
1248                         src_ip_buf, sizeof(src_ip_buf)),
1249               packet->src_port,
1250 #  endif
1251               inet_ntop(packet->dst_ipaddr.af,
1252                         &packet->dst_ipaddr.ipaddr,
1253                      dst_ip_buf, sizeof(dst_ip_buf)),
1254               packet->dst_port);
1255 #endif
1256
1257         p = packet->data;
1258
1259         /*
1260          *      @todo: Make this work again.
1261          */
1262 #if 0
1263         mms = DEFAULT_PACKET_SIZE; /* maximum message size */
1264
1265         /*
1266          *      Clients can request a LARGER size, but not a
1267          *      smaller one.  They also cannot request a size
1268          *      larger than MTU.
1269          */
1270
1271         /* DHCP-DHCP-Maximum-Msg-Size */
1272         vp = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1273         if (vp && (vp->vp_integer > mms)) {
1274                 mms = vp->vp_integer;
1275
1276                 if (mms > MAX_PACKET_SIZE) mms = MAX_PACKET_SIZE;
1277         }
1278 #endif
1279
1280         vp = pairfind(packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1281         if (vp) {
1282                 *p++ = vp->vp_integer & 0xff;
1283         } else {
1284                 *p++ = 1;       /* client message */
1285         }
1286
1287         /* DHCP-Hardware-Type */
1288         if ((vp = pairfind(packet->vps, 257, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1289                 *p++ = vp->vp_integer & 0xFF;
1290         } else {
1291                 *p++ = 1;               /* hardware type = ethernet */
1292         }
1293
1294         /* DHCP-Hardware-Address-Length */
1295         if ((vp = pairfind(packet->vps, 258, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1296                 *p++ = vp->vp_integer & 0xFF;
1297         } else {
1298                 *p++ = 6;               /* 6 bytes of ethernet */
1299         }
1300
1301         /* DHCP-Hop-Count */
1302         if ((vp = pairfind(packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1303                 *p = vp->vp_integer & 0xff;
1304         }
1305         p++;
1306
1307         /* DHCP-Transaction-Id */
1308         if ((vp = pairfind(packet->vps, 260, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1309                 lvalue = htonl(vp->vp_integer);
1310         } else {
1311                 lvalue = fr_rand();
1312         }
1313         memcpy(p, &lvalue, 4);
1314         p += 4;
1315
1316         /* DHCP-Number-of-Seconds */
1317         if ((vp = pairfind(packet->vps, 261, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1318                 lvalue = htonl(vp->vp_integer);
1319                 memcpy(p, &lvalue, 2);
1320         }
1321         p += 2;
1322
1323         /* DHCP-Flags */
1324         if ((vp = pairfind(packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1325                 lvalue = htons(vp->vp_integer);
1326                 memcpy(p, &lvalue, 2);
1327         }
1328         p += 2;
1329
1330         /* DHCP-Client-IP-Address */
1331         if ((vp = pairfind(packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1332                 memcpy(p, &vp->vp_ipaddr, 4);
1333         }
1334         p += 4;
1335
1336         /* DHCP-Your-IP-address */
1337         if ((vp = pairfind(packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1338                 lvalue = vp->vp_ipaddr;
1339         } else {
1340                 lvalue = htonl(INADDR_ANY);
1341         }
1342         memcpy(p, &lvalue, 4);
1343         p += 4;
1344
1345         /* DHCP-Server-IP-Address */
1346         vp = pairfind(packet->vps, 265, DHCP_MAGIC_VENDOR, TAG_ANY);
1347
1348         /* DHCP-DHCP-Server-Identifier */
1349         if (!vp && (vp = pairfind(packet->vps, 54, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1350                 lvalue = vp->vp_ipaddr;
1351         } else {
1352                 lvalue = htonl(INADDR_ANY);
1353         }
1354         memcpy(p, &lvalue, 4);
1355         p += 4;
1356
1357         /*
1358          *      DHCP-Gateway-IP-Address
1359          */
1360         if ((vp = pairfind(packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1361                 lvalue = vp->vp_ipaddr;
1362         } else {
1363                 lvalue = htonl(INADDR_ANY);
1364         }
1365         memcpy(p, &lvalue, 4);
1366         p += 4;
1367
1368         /* DHCP-Client-Hardware-Address */
1369         if ((vp = pairfind(packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1370                 if (vp->length == sizeof(vp->vp_ether)) {
1371                         memcpy(p, vp->vp_ether, vp->length);
1372                 } /* else ignore it */
1373         }
1374         p += DHCP_CHADDR_LEN;
1375
1376         /* DHCP-Server-Host-Name */
1377         if ((vp = pairfind(packet->vps, 268, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1378                 if (vp->length > DHCP_SNAME_LEN) {
1379                         memcpy(p, vp->vp_strvalue, DHCP_SNAME_LEN);
1380                 } else {
1381                         memcpy(p, vp->vp_strvalue, vp->length);
1382                 }
1383         }
1384         p += DHCP_SNAME_LEN;
1385
1386         /*
1387          *      Copy over DHCP-Boot-Filename.
1388          *
1389          *      FIXME: This copy should be delayed until AFTER the options
1390          *      have been processed.  If there are too many options for
1391          *      the packet, then they go into the sname && filename fields.
1392          *      When that happens, the boot filename is passed as an option,
1393          *      instead of being placed verbatim in the filename field.
1394          */
1395
1396         /* DHCP-Boot-Filename */
1397         vp = pairfind(packet->vps, 269, DHCP_MAGIC_VENDOR, TAG_ANY);
1398         if (vp) {
1399                 if (vp->length > DHCP_FILE_LEN) {
1400                         memcpy(p, vp->vp_strvalue, DHCP_FILE_LEN);
1401                 } else {
1402                         memcpy(p, vp->vp_strvalue, vp->length);
1403                 }
1404         }
1405         p += DHCP_FILE_LEN;
1406
1407         /* DHCP magic number */
1408         lvalue = htonl(DHCP_OPTION_MAGIC_NUMBER);
1409         memcpy(p, &lvalue, 4);
1410         p += 4;
1411
1412         /*
1413          *      Print the header.
1414          */
1415         if (fr_debug_flag > 1) {
1416                 uint8_t *pp = p;
1417
1418                 p = packet->data;
1419
1420                 for (i = 0; i < 14; i++) {
1421                         char *q;
1422
1423                         vp = pairmake(packet, NULL,
1424                                       dhcp_header_names[i], NULL, T_OP_EQ);
1425                         if (!vp) {
1426                                 char buffer[256];
1427                                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1428                                 fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1429                                 return -1;
1430                         }
1431
1432                         switch (vp->da->type) {
1433                         case PW_TYPE_BYTE:
1434                                 vp->vp_byte = p[0];
1435                                 break;
1436
1437                         case PW_TYPE_SHORT:
1438                                 vp->vp_short = (p[0] << 8) | p[1];
1439                                 break;
1440
1441                         case PW_TYPE_INTEGER:
1442                                 memcpy(&vp->vp_integer, p, 4);
1443                                 vp->vp_integer = ntohl(vp->vp_integer);
1444                                 break;
1445
1446                         case PW_TYPE_IPV4_ADDR:
1447                                 memcpy(&vp->vp_ipaddr, p, 4);
1448                                 break;
1449
1450                         case PW_TYPE_STRING:
1451                                 vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
1452                                 vp->type = VT_DATA;
1453                                 memcpy(q, p, dhcp_header_sizes[i]);
1454                                 q[dhcp_header_sizes[i]] = '\0';
1455                                 vp->length = strlen(vp->vp_strvalue);
1456                                 break;
1457
1458                         case PW_TYPE_OCTETS: /* only for Client HW Address */
1459                                 pairmemcpy(vp, p, packet->data[2]);
1460                                 break;
1461
1462                         case PW_TYPE_ETHERNET: /* only for Client HW Address */
1463                                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1464                                 break;
1465
1466                         default:
1467                                 fr_strerror_printf("Internal sanity check failed %d %d", vp->da->type, __LINE__);
1468                                 pairfree(&vp);
1469                                 break;
1470                         }
1471
1472                         p += dhcp_header_sizes[i];
1473
1474                         debug_pair(vp);
1475                         pairfree(&vp);
1476                 }
1477
1478                 /*
1479                  *      Jump over DHCP magic number, response, etc.
1480                  */
1481                 p = pp;
1482         }
1483
1484         p[0] = 0x35;            /* DHCP-Message-Type */
1485         p[1] = 1;
1486         p[2] = packet->code - PW_DHCP_OFFSET;
1487         p += 3;
1488
1489
1490         /*
1491          *  Pre-sort attributes into contiguous blocks so that fr_dhcp_encode_option
1492          *  operates correctly. This changes the order of the list, but never mind...
1493          */
1494         pairsort(&packet->vps, fr_dhcp_attr_cmp);
1495         fr_cursor_init(&cursor, &packet->vps);
1496
1497         /*
1498          *  Each call to fr_dhcp_encode_option will encode one complete DHCP option,
1499          *  and sub options.
1500          */
1501         while ((vp = fr_cursor_current(&cursor))) {
1502                 len = fr_dhcp_encode_option(p, packet->data_len - (p - packet->data), packet, &cursor);
1503                 if (len < 0) break;
1504                 if (len > 0) debug_pair(vp);
1505                 p += len;
1506         };
1507
1508         p[0] = 0xff;            /* end of option option */
1509         p[1] = 0x00;
1510         p += 2;
1511         dhcp_size = p - packet->data;
1512
1513         /*
1514          *      FIXME: if (dhcp_size > mms),
1515          *        then we put the extra options into the "sname" and "file"
1516          *        fields, AND set the "end option option" in the "options"
1517          *        field.  We also set the "overload option",
1518          *        and put options into the "file" field, followed by
1519          *        the "sname" field.  Where each option is completely
1520          *        enclosed in the "file" and/or "sname" field, AND
1521          *        followed by the "end of option", and MUST be followed
1522          *        by padding option.
1523          *
1524          *      Yuck.  That sucks...
1525          */
1526         packet->data_len = dhcp_size;
1527
1528         if (packet->data_len < DEFAULT_PACKET_SIZE) {
1529                 memset(packet->data + packet->data_len, 0,
1530                        DEFAULT_PACKET_SIZE - packet->data_len);
1531                 packet->data_len = DEFAULT_PACKET_SIZE;
1532         }
1533
1534         if ((fr_debug_flag > 2) && fr_log_fp) {
1535                 fprintf(fr_log_fp, "DHCP Sending %zu bytes\n", packet->data_len);
1536                 for (i = 0; i < packet->data_len; i++) {
1537                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", i);
1538                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1539                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1540                 }
1541                 fprintf(fr_log_fp, "\n");
1542         }
1543
1544         return 0;
1545 }
1546
1547 #ifdef SIOCSARP
1548 int fr_dhcp_add_arp_entry(int fd, char const *interface,
1549                           VALUE_PAIR *macaddr, VALUE_PAIR *ip)
1550 {
1551         struct sockaddr_in *sin;
1552         struct arpreq req;
1553
1554         if (!interface) {
1555                 fr_strerror_printf("No interface specified.  Cannot update ARP table");
1556                 return -1;
1557         }
1558
1559         if (!fr_assert(macaddr) ||
1560             !fr_assert((macaddr->da->type == PW_TYPE_ETHERNET) || (macaddr->da->type == PW_TYPE_OCTETS))) {
1561                 fr_strerror_printf("Wrong VP type (%s) for chaddr",
1562                                    fr_int2str(dict_attr_types, macaddr->da->type, "<invalid>"));
1563                 return -1;
1564         }
1565
1566         if (macaddr->length > sizeof(req.arp_ha.sa_data)) {
1567                 fr_strerror_printf("arp sa_data field too small (%zu octets) to contain chaddr (%zu octets)",
1568                                    sizeof(req.arp_ha.sa_data), macaddr->length);
1569                 return -1;
1570         }
1571
1572         memset(&req, 0, sizeof(req));
1573         sin = (struct sockaddr_in *) &req.arp_pa;
1574         sin->sin_family = AF_INET;
1575         sin->sin_addr.s_addr = ip->vp_ipaddr;
1576
1577         strlcpy(req.arp_dev, interface, sizeof(req.arp_dev));
1578
1579         if (macaddr->da->type == PW_TYPE_ETHERNET) {
1580                 memcpy(&req.arp_ha.sa_data, &macaddr->vp_ether, sizeof(macaddr->vp_ether));
1581         } else {
1582                 memcpy(&req.arp_ha.sa_data, macaddr->vp_octets, macaddr->length);
1583         }
1584
1585         req.arp_flags = ATF_COM;
1586         if (ioctl(fd, SIOCSARP, &req) < 0) {
1587                 fr_strerror_printf("Failed to add entry in ARP cache: %s (%d)", fr_syserror(errno), errno);
1588                 return -1;
1589         }
1590
1591         return 0;
1592 }
1593 #else
1594 int fr_dhcp_add_arp_entry(UNUSED int fd, UNUSED char const *interface,
1595                           UNUSED VALUE_PAIR *macaddr, UNUSED VALUE_PAIR *ip)
1596 {
1597         fr_strerror_printf("Adding ARP entry is unsupported on this system");
1598         return -1;
1599 }
1600 #endif