Need to merge suboptions list, not insert the head of it, closes #812
[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(TALLOC_CTX *ctx, VALUE_PAIR **vp_p, uint8_t const *p, size_t alen);
463
464 /** Returns the number of array members for arrays with fixed element sizes
465  *
466  */
467 static int fr_dhcp_array_members(size_t *len, DICT_ATTR const *da)
468 {
469         int num_entries = 1;
470
471         /*
472          *      Could be an array of bytes, integers, etc.
473          */
474         if (da->flags.array) switch (da->type) {
475         case PW_TYPE_BYTE:
476                 num_entries = *len;
477                 *len = 1;
478                 break;
479
480         case PW_TYPE_SHORT: /* ignore any trailing data */
481                 num_entries = *len >> 1;
482                 *len = 2;
483                 break;
484
485         case PW_TYPE_IPV4_ADDR:
486         case PW_TYPE_INTEGER:
487         case PW_TYPE_DATE: /* ignore any trailing data */
488                 num_entries = *len >> 2;
489                 *len = 4;
490                 break;
491
492         case PW_TYPE_IPV6_ADDR:
493                 num_entries = *len >> 4;
494                 *len = 16;
495                 break;
496
497         default:
498                 break;
499         }
500
501         return num_entries;
502 }
503
504 /** RFC 4243 Vendor Specific Suboptions
505  *
506  * Vendor specific suboptions are in the format.
507  @verbatim
508       0                   1                   2                   3
509       0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
510      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
511      |                     Enterprise Number 0                       |
512      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
513      |    Len 0      |                                               /
514      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
515      /                      Suboption Data 0                         /
516      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
517      |                     Enterprise Number n                       |
518      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
519      |    Len n      |                                               /
520      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
521      /                      Suboption Data n                         /
522      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
523  @endverbatim
524  *
525  * So although the vendor is identified, the format of the data isn't specified
526  * so we can't actually resolve the suboption to an attribute.
527  *
528  * To get around that, we create an attribute with a vendor matching the
529  * enterprise number, and attr 0.
530  *
531  * How the suboption data is then processed, is dependent on what type
532  * \<iana\>.0 is defined as in the dictionary.
533  *
534  * @param[in,out] tlv to decode. *tlv will be set to the head of the list of suboptions and original will be freed.
535  * @param[in] ctx context to alloc new attributes in.
536  * @param[in] data to parse.
537  * @param[in] len length of data to parse.
538  */
539 static int fr_dhcp_decode_vsa(TALLOC_CTX *ctx, VALUE_PAIR **tlv, uint8_t const *data, size_t len)
540 {
541         uint8_t const *p, *q;
542         vp_cursor_t cursor;
543
544         VALUE_PAIR *head;
545
546         if (len < 4) goto malformed;
547
548         p = data;
549         q = p + len;
550         while (p < q) {
551                 if (p + 5 >= q) goto malformed;
552                 p += sizeof(uint32_t);
553                 p += p[0];
554
555                 /*
556                  *      Check if length > the length of the buffer we have left
557                  */
558                 if (p >= q) goto malformed;
559                 p++;
560         }
561
562         head = NULL;
563         fr_cursor_init(&cursor, &head);
564
565         /*
566          *      Now we know its sane, start decoding!
567          */
568         p = data;
569         while (p < q) {
570                 uint32_t vendor;
571                 DICT_ATTR const *da;
572                 VALUE_PAIR *vp;
573
574                 vendor = ntohl(*((uint32_t const *) p));
575                 /*
576                  *      This is pretty much all we can do.  RFC 4243 doesn't specify
577                  *      an attribute field, so it's up to vendors to figure out how
578                  *      they want to encode their attributes.
579                  */
580                 da = dict_attrbyvalue(0, vendor);
581                 if (!da) {
582                         da = dict_unknown_afrom_fields(ctx, 0, vendor);
583                         if (!da) {
584                                 pairfree(&head);
585                                 goto malformed;
586                         }
587                 }
588                 vp = pairalloc(ctx, da);
589                 if (!vp) {
590                         pairfree(&head);
591                         return -1;
592                 }
593                 vp->op = T_OP_ADD;
594                 pairsteal(ctx, vp); /* for unknown attributes hack */
595
596                 if (fr_dhcp_attr2vp(ctx, &vp, p + 5, p[4]) < 0) {
597                         dict_attr_free(&da);
598                         pairfree(&head);
599                         return -1;
600                 }
601
602                 fr_cursor_merge(&cursor, vp);
603                 dict_attr_free(&da); /* for unknown attributes hack */
604
605                 p += 4 + 1 + p[4];      /* vendor id (4) + len (1) + vsa len (n) */
606         }
607
608         /*
609          *      The caller allocated TLV, if decoding it generated additional
610          *      attributes, we now need to free it, and write the HEAD of our
611          *      new list of attributes in its place.
612          */
613         if (head) {
614                 vp_cursor_t tlv_cursor;
615
616                 /*
617                  *      Free the old TLV attribute
618                  */
619                 TALLOC_FREE(*tlv);
620
621                 /*
622                  *      Cursor not necessary but means we don't have to set
623                  *      ->next directly.
624                  */
625                 fr_cursor_init(&tlv_cursor, tlv);
626                 fr_cursor_merge(&tlv_cursor, head);
627         }
628
629         return 0;
630
631 malformed:
632         (*tlv)->vp_tlv = talloc_array(*tlv, uint8_t, len);
633         if (!(*tlv)->vp_tlv) {
634                 fr_strerror_printf("No memory");
635                 return -1;
636         }
637         memcpy((*tlv)->vp_tlv, data, len);
638         (*tlv)->length = len;
639
640         return 0;
641 }
642
643 /** Decode DHCP suboptions
644  *
645  * @param[in,out] tlv to decode. *tlv will be set to the head of the list of suboptions and original will be freed.
646  * @param[in] ctx context to alloc new attributes in.
647  * @param[in] data to parse.
648  * @param[in] len length of data to parse.
649  */
650 static int fr_dhcp_decode_suboption(TALLOC_CTX *ctx, VALUE_PAIR **tlv, uint8_t const *data, size_t len)
651 {
652         uint8_t const *p, *q;
653         VALUE_PAIR *head, *vp;
654         vp_cursor_t cursor;
655
656         /*
657          *      TLV must already point to a VALUE_PAIR.
658          */
659         VERIFY_VP(*tlv);
660
661         /*
662          *      Take a pass at parsing it.
663          */
664         p = data;
665         q = data + len;
666         while (p < q) {
667                 /*
668                  *      RFC 3046 is very specific about not allowing termination
669                  *      with a 255 sub-option. But it's required for decoding
670                  *      option 43, and vendors will probably screw it up
671                  *      anyway.
672                  */
673                 if (*p == 0) {
674                         p++;
675                         continue;
676                 }
677                 if (*p == 255) {
678                         q--;
679                         break;
680                 }
681
682                 /*
683                  *      Check if reading length would take us past the end of the buffer
684                  */
685                 if (++p >= q) goto malformed;
686                 p += p[0];
687
688                 /*
689                  *      Check if length > the length of the buffer we have left
690                  */
691                 if (p >= q) goto malformed;
692                 p++;
693         }
694
695         /*
696          *      Got here... must be well formed.
697          */
698         head = NULL;
699         fr_cursor_init(&cursor, &head);
700
701         p = data;
702         while (p < q) {
703                 uint8_t const   *a_p;
704                 size_t          a_len;
705                 int             num_entries, i;
706
707                 DICT_ATTR const *da;
708                 uint32_t        attr;
709
710                 /*
711                  *      The initial OID string looks like:
712                  *      <iana>.0
713                  *
714                  *      If <iana>.0 is type TLV then we attempt to decode its contents as more
715                  *      DHCP suboptions, which gives us:
716                  *      <iana>.<attr>
717                  *
718                  *      If <iana>.0 is not defined in the dictionary or is type octets, we leave
719                  *      the attribute as is.
720                  */
721                 attr = (*tlv)->da->attr ? ((*tlv)->da->attr | (p[0] << 8)) : p[0];
722
723                 /*
724                  *      Use the vendor of the parent TLV which is not necessarily
725                  *      DHCP_MAGIC_VENDOR.
726                  *
727                  *      Note: This does not deal with dictionary numbering clashes. If
728                  *      the vendor uses different numbers for DHCP suboptions and RADIUS
729                  *      attributes then it's time to break out %{hex:} and regular
730                  *      expressions.
731                  */
732                 da = dict_attrbyvalue(attr, (*tlv)->da->vendor);
733                 if (!da) {
734                         da = dict_unknown_afrom_fields(ctx, attr, (*tlv)->da->vendor);
735                         if (!da) {
736                                 pairfree(&head);
737                                 return -1;
738                         }
739                 }
740
741                 a_len = p[1];
742                 a_p = p + 2;
743                 num_entries = fr_dhcp_array_members(&a_len, da);
744                 for (i = 0; i < num_entries; i++) {
745                         vp = pairalloc(ctx, da);
746                         if (!vp) {
747                                 pairfree(&head);
748                                 return -1;
749                         }
750                         vp->op = T_OP_ADD;
751                         pairsteal(ctx, vp); /* for unknown attributes hack */
752
753                         if (fr_dhcp_attr2vp(ctx, &vp, a_p, a_len) < 0) {
754                                 dict_attr_free(&da);
755                                 pairfree(&head);
756                                 goto malformed;
757                         }
758                         fr_cursor_merge(&cursor, vp);
759
760                         a_p += a_len;
761                 }
762
763                 dict_attr_free(&da); /* for unknown attributes hack */
764
765                 p += 2 + p[1];  /* code (1) + len (1) + suboption len (n)*/
766         }
767
768         /*
769          *      The caller allocated a TLV, if decoding it generated
770          *      additional attributes, we now need to free it, and write
771          *      the HEAD of our new list of attributes in its place.
772          */
773         if (head) {
774                 vp_cursor_t tlv_cursor;
775
776                 /*
777                  *      Free the old TLV attribute
778                  */
779                 TALLOC_FREE(*tlv);
780
781                 /*
782                  *      Cursor not necessary but means we don't have to set
783                  *      ->next directly.
784                  */
785                 fr_cursor_init(&tlv_cursor, tlv);
786                 fr_cursor_merge(&tlv_cursor, head);
787         }
788
789         return 0;
790
791 malformed:
792         (*tlv)->vp_tlv = talloc_array(*tlv, uint8_t, len);
793         if (!(*tlv)->vp_tlv) {
794                 fr_strerror_printf("No memory");
795                 return -1;
796         }
797         memcpy((*tlv)->vp_tlv, data, len);
798         (*tlv)->length = len;
799
800         return 0;
801 }
802
803 /*
804  *      Decode ONE value into a VP
805  */
806 static int fr_dhcp_attr2vp(TALLOC_CTX *ctx, VALUE_PAIR **vp_p, uint8_t const *data, size_t len)
807 {
808         VALUE_PAIR *vp = *vp_p;
809         VERIFY_VP(vp);
810
811         switch (vp->da->type) {
812         case PW_TYPE_BYTE:
813                 if (len != 1) goto raw;
814                 vp->vp_byte = data[0];
815                 break;
816
817         case PW_TYPE_SHORT:
818                 if (len != 2) goto raw;
819                 memcpy(&vp->vp_short, data, 2);
820                 vp->vp_short = ntohs(vp->vp_short);
821                 break;
822
823         case PW_TYPE_INTEGER:
824                 if (len != 4) goto raw;
825                 memcpy(&vp->vp_integer, data, 4);
826                 vp->vp_integer = ntohl(vp->vp_integer);
827                 break;
828
829         case PW_TYPE_IPV4_ADDR:
830                 if (len != 4) goto raw;
831                 /*
832                  *      Keep value in Network Order!
833                  */
834                 memcpy(&vp->vp_ipaddr, data, 4);
835                 vp->length = 4;
836                 break;
837
838         /*
839          *      In DHCPv4, string options which can also be arrays,
840          *      have their values '\0' delimited.
841          */
842         case PW_TYPE_STRING:
843         {
844                 uint8_t const *p;
845                 uint8_t const *q, *end;
846                 vp_cursor_t cursor;
847
848                 p = data;
849                 q = end = data + len;
850
851                 if (!vp->da->flags.array) {
852                         pairstrncpy(vp, (char const *)p, q - p);
853                         break;
854                 }
855
856                 /*
857                  *      Initialise the cursor as we may be inserting
858                  *      multiple additional VPs
859                  */
860                 fr_cursor_init(&cursor, vp_p);
861                 for (;;) {
862                         q = memchr(p, '\0', q - p);
863                         /* Malformed but recoverable */
864                         if (!q) q = end;
865
866                         pairstrncpy(vp, (char const *)p, q - p);
867                         p = q + 1;
868
869                         /* Need another VP for the next round */
870                         if (p < end) {
871                                 vp = pairalloc(ctx, vp->da);
872                                 if (!vp) {
873                                         pairfree(vp_p);
874                                         return -1;
875                                 }
876                                 fr_cursor_insert(&cursor, vp);
877                                 continue;
878                         }
879                         break;
880                 }
881         }
882                 break;
883
884         case PW_TYPE_ETHERNET:
885                 memcpy(vp->vp_ether, data, sizeof(vp->vp_ether));
886                 vp->length = sizeof(vp->vp_ether);
887                 break;
888
889         /*
890          *      Value doesn't match up with attribute type, overwrite the
891          *      vp's original DICT_ATTR with an unknown one.
892          */
893         raw:
894                 if (pair2unknown(vp) < 0) return -1;
895
896         case PW_TYPE_OCTETS:
897                 if (len > 255) return -1;
898                 pairmemcpy(vp, data, len);
899                 break;
900
901         /*
902          *      For option 82 et al...
903          */
904         case PW_TYPE_TLV:
905                 return fr_dhcp_decode_suboption(ctx, vp_p, data, len);
906
907         /*
908          *      For option 82.9
909          */
910         case PW_TYPE_VSA:
911                 return fr_dhcp_decode_vsa(ctx, vp_p, data, len);
912
913         default:
914                 fr_strerror_printf("Internal sanity check %d %d", vp->da->type, __LINE__);
915                 return -1;
916         } /* switch over type */
917
918         vp->length = len;
919         return 0;
920 }
921
922 /** Decode DHCP options
923  *
924  * @param[in,out] out Where to write the decoded options.
925  * @param[in] ctx context to alloc new attributes in.
926  * @param[in] data to parse.
927  * @param[in] len of data to parse.
928  */
929 ssize_t fr_dhcp_decode_options(TALLOC_CTX *ctx, VALUE_PAIR **out, uint8_t const *data, size_t len)
930 {
931         VALUE_PAIR *vp;
932         vp_cursor_t cursor;
933         uint8_t const *p, *q;
934
935         *out = NULL;
936         fr_cursor_init(&cursor, out);
937
938         /*
939          *      FIXME: This should also check sname && file fields.
940          *      See the dhcp_get_option() function above.
941          */
942         p = data;
943         q = data + len;
944         while (p < q) {
945                 uint8_t const   *a_p;
946                 size_t          a_len;
947                 int             num_entries, i;
948
949                 DICT_ATTR const *da;
950
951                 if (*p == 0) {          /* 0x00 - Padding option */
952                         p++;
953                         continue;
954                 }
955
956                 if (*p == 255) {        /* 0xff - End of options signifier */
957                         break;
958                 }
959
960                 if ((p + 2) > q) break;
961
962                 a_len = p[1];
963                 a_p = p + 2;
964
965                 /*
966                  *      Unknown attribute, create an octets type
967                  *      attribute with the contents of the sub-option.
968                  */
969                 da = dict_attrbyvalue(p[0], DHCP_MAGIC_VENDOR);
970                 if (!da) {
971                         da = dict_unknown_afrom_fields(ctx, p[0], DHCP_MAGIC_VENDOR);
972                         if (!da) {
973                                 pairfree(out);
974                                 return -1;
975                         }
976                         vp = pairalloc(ctx, da);
977                         if (!vp) {
978                                 pairfree(out);
979                                 return -1;
980                         }
981                         pairmemcpy(vp, a_p, a_len);
982                         fr_cursor_insert(&cursor, vp);
983
984                         goto next;
985                 }
986
987                 /*
988                  *      Array type sub-option create a new VALUE_PAIR
989                  *      for each array element.
990                  */
991                 num_entries = fr_dhcp_array_members(&a_len, da);
992                 for (i = 0; i < num_entries; i++) {
993                         vp = pairalloc(ctx, da);
994                         if (!vp) {
995                                 pairfree(out);
996                                 return -1;
997                         }
998                         vp->op = T_OP_ADD;
999
1000                         if (fr_dhcp_attr2vp(ctx, &vp, a_p, a_len) < 0) {
1001                                 pairfree(&vp);
1002                                 pairfree(out);
1003                                 return -1;
1004                         }
1005                         fr_cursor_merge(&cursor, vp);
1006
1007                         for (vp = fr_cursor_current(&cursor);
1008                              vp;
1009                              vp = fr_cursor_next(&cursor)) {
1010                                 debug_pair(vp);
1011                         }
1012                         a_p += a_len;
1013                 } /* loop over array entries */
1014         next:
1015                 p += 2 + p[1];  /* code (1) + len (1) + option len (n)*/
1016         } /* loop over the entire packet */
1017
1018         return p - data;
1019 }
1020
1021 int fr_dhcp_decode(RADIUS_PACKET *packet)
1022 {
1023         size_t i;
1024         uint8_t *p;
1025         uint32_t giaddr;
1026         vp_cursor_t cursor;
1027         VALUE_PAIR *head = NULL, *vp;
1028         VALUE_PAIR *maxms, *mtu;
1029
1030         fr_cursor_init(&cursor, &head);
1031         p = packet->data;
1032
1033         if ((fr_debug_flag > 2) && fr_log_fp) {
1034                 for (i = 0; i < packet->data_len; i++) {
1035                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
1036                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1037                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1038                 }
1039                 fprintf(fr_log_fp, "\n");
1040         }
1041
1042         if (packet->data[1] != 1) {
1043                 fr_strerror_printf("Packet is not Ethernet: %u",
1044                       packet->data[1]);
1045                 return -1;
1046         }
1047
1048         /*
1049          *      Decode the header.
1050          */
1051         for (i = 0; i < 14; i++) {
1052                 char *q;
1053
1054                 vp = pairmake(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
1055                 if (!vp) {
1056                         char buffer[256];
1057                         strlcpy(buffer, fr_strerror(), sizeof(buffer));
1058                         fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1059                         pairfree(&head);
1060                         return -1;
1061                 }
1062
1063                 /*
1064                  *      If chaddr does != 6 bytes it's probably not ethernet, and we should store
1065                  *      it as an opaque type (octets).
1066                  */
1067                 if ((i == 11) && (packet->data[1] == 1) && (packet->data[2] != sizeof(vp->vp_ether))) {
1068                         DICT_ATTR const *da = dict_unknown_afrom_fields(packet, vp->da->attr, vp->da->vendor);
1069                         if (!da) {
1070                                 return -1;
1071                         }
1072                         vp->da = da;
1073                 }
1074
1075                 switch (vp->da->type) {
1076                 case PW_TYPE_BYTE:
1077                         vp->vp_byte = p[0];
1078                         vp->length = 1;
1079                         break;
1080
1081                 case PW_TYPE_SHORT:
1082                         vp->vp_short = (p[0] << 8) | p[1];
1083                         vp->length = 2;
1084                         break;
1085
1086                 case PW_TYPE_INTEGER:
1087                         memcpy(&vp->vp_integer, p, 4);
1088                         vp->vp_integer = ntohl(vp->vp_integer);
1089                         vp->length = 4;
1090                         break;
1091
1092                 case PW_TYPE_IPV4_ADDR:
1093                         memcpy(&vp->vp_ipaddr, p, 4);
1094                         vp->length = 4;
1095                         break;
1096
1097                 case PW_TYPE_STRING:
1098                         vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
1099                         vp->type = VT_DATA;
1100                         memcpy(q, p, dhcp_header_sizes[i]);
1101                         q[dhcp_header_sizes[i]] = '\0';
1102                         vp->length = strlen(vp->vp_strvalue);
1103                         if (vp->length == 0) {
1104                                 pairfree(&vp);
1105                         }
1106                         break;
1107
1108                 case PW_TYPE_OCTETS:
1109                         pairmemcpy(vp, p, packet->data[2]);
1110                         break;
1111
1112                 case PW_TYPE_ETHERNET:
1113                         memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1114                         vp->length = sizeof(vp->vp_ether);
1115                         break;
1116
1117                 default:
1118                         fr_strerror_printf("BAD TYPE %d", vp->da->type);
1119                         pairfree(&vp);
1120                         break;
1121                 }
1122                 p += dhcp_header_sizes[i];
1123
1124                 if (!vp) continue;
1125
1126                 debug_pair(vp);
1127                 fr_cursor_insert(&cursor, vp);
1128         }
1129
1130         /*
1131          *      Loop over the options.
1132          */
1133
1134         /*
1135          *      Nothing uses tail after this call, if it does in the future
1136          *      it'll need to find the new tail...
1137          */
1138         {
1139                 VALUE_PAIR *options = NULL;
1140
1141                 if (fr_dhcp_decode_options(packet, &options, packet->data + 240, packet->data_len - 240) < 0) {
1142                         return -1;
1143                 }
1144
1145                 if (options) fr_cursor_merge(&cursor, options);
1146         }
1147
1148         /*
1149          *      If DHCP request, set ciaddr to zero.
1150          */
1151
1152         /*
1153          *      Set broadcast flag for broken vendors, but only if
1154          *      giaddr isn't set.
1155          */
1156         memcpy(&giaddr, packet->data + 24, sizeof(giaddr));
1157         if (giaddr == htonl(INADDR_ANY)) {
1158                 /*
1159                  *      DHCP Opcode is request
1160                  */
1161                 vp = pairfind(head, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1162                 if (vp && vp->vp_integer == 3) {
1163                         /*
1164                          *      Vendor is "MSFT 98"
1165                          */
1166                         vp = pairfind(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
1167                         if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
1168                                 vp = pairfind(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
1169
1170                                 /*
1171                                  *      Reply should be broadcast.
1172                                  */
1173                                 if (vp) vp->vp_integer |= 0x8000;
1174                                 packet->data[10] |= 0x80;
1175                         }
1176                 }
1177         }
1178
1179         /*
1180          *      FIXME: Nuke attributes that aren't used in the normal
1181          *      header for discover/requests.
1182          */
1183         packet->vps = head;
1184
1185         /*
1186          *      Client can request a LARGER size, but not a smaller
1187          *      one.  They also cannot request a size larger than MTU.
1188          */
1189         maxms = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1190         mtu = pairfind(packet->vps, 26, DHCP_MAGIC_VENDOR, TAG_ANY);
1191
1192         if (mtu && (mtu->vp_integer < DEFAULT_PACKET_SIZE)) {
1193                 fr_strerror_printf("DHCP Fatal: Client says MTU is smaller than minimum permitted by the specification");
1194                 return -1;
1195         }
1196
1197         if (maxms && (maxms->vp_integer < DEFAULT_PACKET_SIZE)) {
1198                 fr_strerror_printf("DHCP WARNING: Client says maximum message size is smaller than minimum permitted by the specification: fixing it");
1199                 maxms->vp_integer = DEFAULT_PACKET_SIZE;
1200         }
1201
1202         if (maxms && mtu && (maxms->vp_integer > mtu->vp_integer)) {
1203                 fr_strerror_printf("DHCP WARNING: Client says MTU is smaller than maximum message size: fixing it");
1204                 maxms->vp_integer = mtu->vp_integer;
1205         }
1206
1207         if (fr_debug_flag) fflush(stdout);
1208
1209         return 0;
1210 }
1211
1212
1213 int8_t fr_dhcp_attr_cmp(void const *a, void const *b)
1214 {
1215         VALUE_PAIR const *my_a = a;
1216         VALUE_PAIR const *my_b = b;
1217
1218         VERIFY_VP(my_a);
1219         VERIFY_VP(my_b);
1220
1221         /*
1222          *      DHCP-Message-Type is first, for simplicity.
1223          */
1224         if ((my_a->da->attr == 53) && (my_b->da->attr != 53)) return -1;
1225
1226         /*
1227          *      Relay-Agent is last
1228          */
1229         if ((my_a->da->attr == 82) && (my_b->da->attr != 82)) return 1;
1230
1231         if (my_a->da->attr < my_b->da->attr) return -1;
1232         if (my_a->da->attr > my_b->da->attr) return 1;
1233
1234         return 0;
1235 }
1236
1237 /** Write DHCP option value into buffer
1238  *
1239  * Does not include DHCP option length or number.
1240  *
1241  * @param out where to write the DHCP option.
1242  * @param outlen length of output buffer.
1243  * @param vp option to encode.
1244  * @return the length of data writen, -1 if out of buffer, -2 if unsupported type.
1245  */
1246 static ssize_t fr_dhcp_vp2attr(uint8_t *out, size_t outlen, VALUE_PAIR *vp)
1247 {
1248         uint32_t lvalue;
1249         uint8_t *p = out;
1250
1251         if (outlen < vp->length) {
1252                 return -1;
1253         }
1254
1255         switch (vp->da->type) {
1256         case PW_TYPE_BYTE:
1257                 *p = vp->vp_byte;
1258                 break;
1259
1260         case PW_TYPE_SHORT:
1261                 p[0] = (vp->vp_short >> 8) & 0xff;
1262                 p[1] = vp->vp_short & 0xff;
1263                 break;
1264
1265         case PW_TYPE_INTEGER:
1266                 lvalue = htonl(vp->vp_integer);
1267                 memcpy(p, &lvalue, 4);
1268                 break;
1269
1270         case PW_TYPE_IPV4_ADDR:
1271                 memcpy(p, &vp->vp_ipaddr, 4);
1272                 break;
1273
1274         case PW_TYPE_ETHERNET:
1275                 memcpy(p, &vp->vp_ether, 6);
1276                 break;
1277
1278         case PW_TYPE_STRING:
1279                 memcpy(p, vp->vp_strvalue, vp->length);
1280                 break;
1281
1282         case PW_TYPE_TLV:       /* FIXME: split it on 255? */
1283                 memcpy(p, vp->vp_tlv, vp->length);
1284                 break;
1285
1286         case PW_TYPE_OCTETS:
1287                 memcpy(p, vp->vp_octets, vp->length);
1288                 break;
1289
1290         default:
1291                 fr_strerror_printf("Unsupported option type %d", vp->da->type);
1292                 return -2;
1293         }
1294
1295         return vp->length;
1296 }
1297
1298 /** Create a new TLV attribute from multiple sub options
1299  *
1300  * @param[in,out] ctx to allocate new attribute in.
1301  * @param[in,out] cursor should be set to the start of the list of TLV attributes.
1302  *   Will be advanced to the first non-TLV attribute.
1303  * @return attribute holding the concatenation of the values of the sub options.
1304  */
1305 static VALUE_PAIR *fr_dhcp_vp2suboption(TALLOC_CTX *ctx, vp_cursor_t *cursor)
1306 {
1307         ssize_t length;
1308         unsigned int parent;    /* Parent attribute of suboption */
1309         uint8_t attr = 0;
1310         uint8_t *p, *opt_len = NULL;
1311         vp_cursor_t to_pack;
1312         VALUE_PAIR *vp, *tlv;
1313
1314 #define SUBOPTION_PARENT(_x) (_x & 0xffff00ff)
1315 #define SUBOPTION_ATTR(_x) ((_x & 0xff00) >> 8)
1316
1317         vp = fr_cursor_current(cursor);
1318         if (!vp) return NULL;
1319
1320         parent = SUBOPTION_PARENT(vp->da->attr);
1321         tlv = paircreate(ctx, parent, DHCP_MAGIC_VENDOR);
1322         if (!tlv) return NULL;
1323
1324         fr_cursor_copy(&to_pack, cursor);
1325
1326         /*
1327          *  Loop over TLVs to determine how much memory we need to allocate
1328          *
1329          *  We advanced the cursor we were passed, so if we fail encoding,
1330          *  the cursor is at the right position for the next potentially
1331          *  encodable attr.
1332          */
1333         for (vp = fr_cursor_current(cursor);
1334              vp && vp->da->flags.is_tlv && !vp->da->flags.extended && (SUBOPTION_PARENT(vp->da->attr) == parent);
1335              vp = fr_cursor_next(cursor)) {
1336                 /*
1337                  *  If it's not an array type or is an array type, but is not the same
1338                  *  as the previous attribute, we add 2 for the additional sub-option
1339                  *  header bytes.
1340                  */
1341                 if (!vp->da->flags.array || (SUBOPTION_ATTR(vp->da->attr) != attr)) {
1342                         attr = SUBOPTION_ATTR(vp->da->attr);
1343                         tlv->length += 2;
1344                 }
1345                 tlv->length += vp->length;
1346         }
1347
1348         tlv->vp_tlv = talloc_zero_array(tlv, uint8_t, tlv->length);
1349         if (!tlv->vp_tlv) {
1350                 talloc_free(tlv);
1351                 return NULL;
1352         }
1353         p = tlv->vp_tlv;
1354
1355         attr = 0;
1356         for (vp = fr_cursor_current(&to_pack);
1357              vp && vp->da->flags.is_tlv && !vp->da->flags.extended && (SUBOPTION_PARENT(vp->da->attr) == parent);
1358              vp = fr_cursor_next(&to_pack)) {
1359                 if (SUBOPTION_ATTR(vp->da->attr) == 0) {
1360                         fr_strerror_printf("Invalid attribute number 0");
1361                         return NULL;
1362                 }
1363
1364                 /* Don't write out the header, were packing array options */
1365                 if (!vp->da->flags.array || (attr != SUBOPTION_ATTR(vp->da->attr))) {
1366                         attr = SUBOPTION_ATTR(vp->da->attr);
1367                         *p++ = attr;
1368                         opt_len = p++;
1369                 }
1370
1371                 length = fr_dhcp_vp2attr(p, (tlv->vp_tlv + tlv->length) - p, vp);
1372                 if ((length < 0) || (length > 255)) {
1373                         talloc_free(tlv);
1374                         return NULL;
1375                 }
1376
1377                 fr_assert(opt_len);
1378                 *opt_len += length;
1379                 p += length;
1380         };
1381
1382         return tlv;
1383 }
1384
1385 /** Encode a DHCP option and any sub-options.
1386  *
1387  * @param out Where to write encoded DHCP attributes.
1388  * @param outlen Length of out buffer.
1389  * @param ctx to use for any allocated memory.
1390  * @param cursor with current VP set to the option to be encoded. Will be advanced to the next option to encode.
1391  * @return > 0 length of data written, < 0 error, 0 not valid option (skipping).
1392  */
1393 ssize_t fr_dhcp_encode_option(TALLOC_CTX *ctx, uint8_t *out, size_t outlen, vp_cursor_t *cursor)
1394 {
1395         VALUE_PAIR *vp;
1396         DICT_ATTR const *previous;
1397         uint8_t *opt_len, *p = out;
1398         size_t freespace = outlen;
1399         ssize_t len;
1400
1401         vp = fr_cursor_current(cursor);
1402         if (!vp) return -1;
1403
1404         if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
1405         if (vp->da->attr == 53) goto next; /* already done */
1406         if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
1407
1408         if (vp->da->flags.extended) {
1409         next:
1410                 fr_strerror_printf("Attribute \"%s\" is not a DHCP option", vp->da->name);
1411                 fr_cursor_next(cursor);
1412                 return 0;
1413         }
1414
1415         /* Write out the option number */
1416         *(p++) = vp->da->attr & 0xff;
1417
1418         /* Pointer to the length field of the option */
1419         opt_len = p++;
1420
1421         /* Zero out the option's length field */
1422         *opt_len = 0;
1423
1424         /* We just consumed two bytes for the header */
1425         freespace -= 2;
1426
1427         /* DHCP options with the same number get coalesced into a single option */
1428         do {
1429                 VALUE_PAIR *tlv = NULL;
1430
1431                 /* Sub option */
1432                 if (vp->da->flags.is_tlv) {
1433                         /*
1434                          *  Coalesce TLVs into one sub-option.
1435                          *  Cursor will be advanced to next non-TLV attribute.
1436                          */
1437                         tlv = vp = fr_dhcp_vp2suboption(ctx, cursor);
1438
1439                         /*
1440                          *  Skip if there's an issue coalescing the sub-options.
1441                          *  Cursor will still have been advanced to next non-TLV attribute.
1442                          */
1443                         if (!tlv) return 0;
1444                 /*
1445                  *  If not calling fr_dhcp_vp2suboption() advance the cursor, so fr_cursor_current()
1446                  *  returns the next attribute.
1447                  */
1448                 } else {
1449                         fr_cursor_next(cursor);
1450                 }
1451
1452                 if ((*opt_len + vp->length) > 255) {
1453                         fr_strerror_printf("Skipping \"%s\": Option splitting not supported "
1454                                            "(option > 255 bytes)", vp->da->name);
1455                         talloc_free(tlv);
1456                         return 0;
1457                 }
1458
1459                 len = fr_dhcp_vp2attr(p, freespace, vp);
1460                 talloc_free(tlv);
1461                 if (len < 0) {
1462                         /* Failed encoding option */
1463                         return len;
1464                 }
1465
1466                 p += len;
1467                 *opt_len += len;
1468                 freespace -= len;
1469
1470                 previous = vp->da;
1471         } while ((vp = fr_cursor_current(cursor)) && (previous == vp->da) && vp->da->flags.array);
1472
1473         return p - out;
1474 }
1475
1476 int fr_dhcp_encode(RADIUS_PACKET *packet)
1477 {
1478         unsigned int i;
1479         uint8_t *p;
1480         vp_cursor_t cursor;
1481         VALUE_PAIR *vp;
1482         uint32_t lvalue;
1483         size_t dhcp_size;
1484         ssize_t len;
1485 #ifndef NDEBUG
1486         char const *name;
1487 #  ifdef WITH_UDPFROMTO
1488         char src_ip_buf[256];
1489 #  endif
1490         char dst_ip_buf[256];
1491 #endif
1492
1493         if (packet->data) return 0;
1494
1495         packet->data_len = MAX_PACKET_SIZE;
1496         packet->data = talloc_zero_array(packet, uint8_t, packet->data_len);
1497
1498         /* XXX Ugly ... should be set by the caller */
1499         if (packet->code == 0) packet->code = PW_DHCP_NAK;
1500
1501         /* store xid */
1502         if ((vp = pairfind(packet->vps, 260, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1503                 packet->id = vp->vp_integer;
1504         } else {
1505                 packet->id = fr_rand();
1506         }
1507
1508 #ifndef NDEBUG
1509         if ((packet->code >= PW_DHCP_DISCOVER) &&
1510             (packet->code <= PW_DHCP_INFORM)) {
1511                 name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
1512         } else {
1513                 name = "?Unknown?";
1514         }
1515
1516         DEBUG(
1517 #  ifdef WITH_UDPFROMTO
1518               "Encoding %s of id %08x from %s:%d to %s:%d\n",
1519 #  else
1520               "Encoding %s of id %08x to %s:%d\n",
1521 #  endif
1522               name, (unsigned int) packet->id,
1523 #  ifdef WITH_UDPFROMTO
1524               inet_ntop(packet->src_ipaddr.af,
1525                         &packet->src_ipaddr.ipaddr,
1526                         src_ip_buf, sizeof(src_ip_buf)),
1527               packet->src_port,
1528 #  endif
1529               inet_ntop(packet->dst_ipaddr.af,
1530                         &packet->dst_ipaddr.ipaddr,
1531                      dst_ip_buf, sizeof(dst_ip_buf)),
1532               packet->dst_port);
1533 #endif
1534
1535         p = packet->data;
1536
1537         /*
1538          *      @todo: Make this work again.
1539          */
1540 #if 0
1541         mms = DEFAULT_PACKET_SIZE; /* maximum message size */
1542
1543         /*
1544          *      Clients can request a LARGER size, but not a
1545          *      smaller one.  They also cannot request a size
1546          *      larger than MTU.
1547          */
1548
1549         /* DHCP-DHCP-Maximum-Msg-Size */
1550         vp = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1551         if (vp && (vp->vp_integer > mms)) {
1552                 mms = vp->vp_integer;
1553
1554                 if (mms > MAX_PACKET_SIZE) mms = MAX_PACKET_SIZE;
1555         }
1556 #endif
1557
1558         vp = pairfind(packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1559         if (vp) {
1560                 *p++ = vp->vp_integer & 0xff;
1561         } else {
1562                 *p++ = 1;       /* client message */
1563         }
1564
1565         /* DHCP-Hardware-Type */
1566         if ((vp = pairfind(packet->vps, 257, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1567                 *p++ = vp->vp_integer & 0xFF;
1568         } else {
1569                 *p++ = 1;               /* hardware type = ethernet */
1570         }
1571
1572         /* DHCP-Hardware-Address-Length */
1573         if ((vp = pairfind(packet->vps, 258, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1574                 *p++ = vp->vp_integer & 0xFF;
1575         } else {
1576                 *p++ = 6;               /* 6 bytes of ethernet */
1577         }
1578
1579         /* DHCP-Hop-Count */
1580         if ((vp = pairfind(packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1581                 *p = vp->vp_integer & 0xff;
1582         }
1583         p++;
1584
1585         /* DHCP-Transaction-Id */
1586         lvalue = htonl(packet->id);
1587         memcpy(p, &lvalue, 4);
1588         p += 4;
1589
1590         /* DHCP-Number-of-Seconds */
1591         if ((vp = pairfind(packet->vps, 261, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1592                 lvalue = htonl(vp->vp_integer);
1593                 memcpy(p, &lvalue, 2);
1594         }
1595         p += 2;
1596
1597         /* DHCP-Flags */
1598         if ((vp = pairfind(packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1599                 lvalue = htons(vp->vp_integer);
1600                 memcpy(p, &lvalue, 2);
1601         }
1602         p += 2;
1603
1604         /* DHCP-Client-IP-Address */
1605         if ((vp = pairfind(packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1606                 memcpy(p, &vp->vp_ipaddr, 4);
1607         }
1608         p += 4;
1609
1610         /* DHCP-Your-IP-address */
1611         if ((vp = pairfind(packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1612                 lvalue = vp->vp_ipaddr;
1613         } else {
1614                 lvalue = htonl(INADDR_ANY);
1615         }
1616         memcpy(p, &lvalue, 4);
1617         p += 4;
1618
1619         /* DHCP-Server-IP-Address */
1620         vp = pairfind(packet->vps, 265, DHCP_MAGIC_VENDOR, TAG_ANY);
1621         if (vp) {
1622                 lvalue = vp->vp_ipaddr;
1623         } else {
1624                 lvalue = htonl(INADDR_ANY);
1625         }
1626         memcpy(p, &lvalue, 4);
1627         p += 4;
1628
1629         /*
1630          *      DHCP-Gateway-IP-Address
1631          */
1632         if ((vp = pairfind(packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1633                 lvalue = vp->vp_ipaddr;
1634         } else {
1635                 lvalue = htonl(INADDR_ANY);
1636         }
1637         memcpy(p, &lvalue, 4);
1638         p += 4;
1639
1640         /* DHCP-Client-Hardware-Address */
1641         if ((vp = pairfind(packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1642                 if (vp->length == sizeof(vp->vp_ether)) {
1643                         memcpy(p, vp->vp_ether, vp->length);
1644                 } /* else ignore it */
1645         }
1646         p += DHCP_CHADDR_LEN;
1647
1648         /* DHCP-Server-Host-Name */
1649         if ((vp = pairfind(packet->vps, 268, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1650                 if (vp->length > DHCP_SNAME_LEN) {
1651                         memcpy(p, vp->vp_strvalue, DHCP_SNAME_LEN);
1652                 } else {
1653                         memcpy(p, vp->vp_strvalue, vp->length);
1654                 }
1655         }
1656         p += DHCP_SNAME_LEN;
1657
1658         /*
1659          *      Copy over DHCP-Boot-Filename.
1660          *
1661          *      FIXME: This copy should be delayed until AFTER the options
1662          *      have been processed.  If there are too many options for
1663          *      the packet, then they go into the sname && filename fields.
1664          *      When that happens, the boot filename is passed as an option,
1665          *      instead of being placed verbatim in the filename field.
1666          */
1667
1668         /* DHCP-Boot-Filename */
1669         vp = pairfind(packet->vps, 269, DHCP_MAGIC_VENDOR, TAG_ANY);
1670         if (vp) {
1671                 if (vp->length > DHCP_FILE_LEN) {
1672                         memcpy(p, vp->vp_strvalue, DHCP_FILE_LEN);
1673                 } else {
1674                         memcpy(p, vp->vp_strvalue, vp->length);
1675                 }
1676         }
1677         p += DHCP_FILE_LEN;
1678
1679         /* DHCP magic number */
1680         lvalue = htonl(DHCP_OPTION_MAGIC_NUMBER);
1681         memcpy(p, &lvalue, 4);
1682         p += 4;
1683
1684         /*
1685          *      Print the header.
1686          */
1687         if (fr_debug_flag > 1) {
1688                 uint8_t *pp = p;
1689
1690                 p = packet->data;
1691
1692                 for (i = 0; i < 14; i++) {
1693                         char *q;
1694
1695                         vp = pairmake(packet, NULL,
1696                                       dhcp_header_names[i], NULL, T_OP_EQ);
1697                         if (!vp) {
1698                                 char buffer[256];
1699                                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1700                                 fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1701                                 return -1;
1702                         }
1703
1704                         switch (vp->da->type) {
1705                         case PW_TYPE_BYTE:
1706                                 vp->vp_byte = p[0];
1707                                 break;
1708
1709                         case PW_TYPE_SHORT:
1710                                 vp->vp_short = (p[0] << 8) | p[1];
1711                                 break;
1712
1713                         case PW_TYPE_INTEGER:
1714                                 memcpy(&vp->vp_integer, p, 4);
1715                                 vp->vp_integer = ntohl(vp->vp_integer);
1716                                 break;
1717
1718                         case PW_TYPE_IPV4_ADDR:
1719                                 memcpy(&vp->vp_ipaddr, p, 4);
1720                                 break;
1721
1722                         case PW_TYPE_STRING:
1723                                 vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
1724                                 vp->type = VT_DATA;
1725                                 memcpy(q, p, dhcp_header_sizes[i]);
1726                                 q[dhcp_header_sizes[i]] = '\0';
1727                                 vp->length = strlen(vp->vp_strvalue);
1728                                 break;
1729
1730                         case PW_TYPE_OCTETS: /* only for Client HW Address */
1731                                 pairmemcpy(vp, p, packet->data[2]);
1732                                 break;
1733
1734                         case PW_TYPE_ETHERNET: /* only for Client HW Address */
1735                                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1736                                 break;
1737
1738                         default:
1739                                 fr_strerror_printf("Internal sanity check failed %d %d", vp->da->type, __LINE__);
1740                                 pairfree(&vp);
1741                                 break;
1742                         }
1743
1744                         p += dhcp_header_sizes[i];
1745
1746                         debug_pair(vp);
1747                         pairfree(&vp);
1748                 }
1749
1750                 /*
1751                  *      Jump over DHCP magic number, response, etc.
1752                  */
1753                 p = pp;
1754         }
1755
1756         p[0] = 0x35;            /* DHCP-Message-Type */
1757         p[1] = 1;
1758         p[2] = packet->code - PW_DHCP_OFFSET;
1759         p += 3;
1760
1761
1762         /*
1763          *  Pre-sort attributes into contiguous blocks so that fr_dhcp_encode_option
1764          *  operates correctly. This changes the order of the list, but never mind...
1765          */
1766         pairsort(&packet->vps, fr_dhcp_attr_cmp);
1767         fr_cursor_init(&cursor, &packet->vps);
1768
1769         /*
1770          *  Each call to fr_dhcp_encode_option will encode one complete DHCP option,
1771          *  and sub options.
1772          */
1773         while ((vp = fr_cursor_current(&cursor))) {
1774                 len = fr_dhcp_encode_option(packet, p, packet->data_len - (p - packet->data), &cursor);
1775                 if (len < 0) break;
1776                 if (len > 0) debug_pair(vp);
1777                 p += len;
1778         };
1779
1780         p[0] = 0xff;            /* end of option option */
1781         p[1] = 0x00;
1782         p += 2;
1783         dhcp_size = p - packet->data;
1784
1785         /*
1786          *      FIXME: if (dhcp_size > mms),
1787          *        then we put the extra options into the "sname" and "file"
1788          *        fields, AND set the "end option option" in the "options"
1789          *        field.  We also set the "overload option",
1790          *        and put options into the "file" field, followed by
1791          *        the "sname" field.  Where each option is completely
1792          *        enclosed in the "file" and/or "sname" field, AND
1793          *        followed by the "end of option", and MUST be followed
1794          *        by padding option.
1795          *
1796          *      Yuck.  That sucks...
1797          */
1798         packet->data_len = dhcp_size;
1799
1800         if (packet->data_len < DEFAULT_PACKET_SIZE) {
1801                 memset(packet->data + packet->data_len, 0,
1802                        DEFAULT_PACKET_SIZE - packet->data_len);
1803                 packet->data_len = DEFAULT_PACKET_SIZE;
1804         }
1805
1806         if ((fr_debug_flag > 2) && fr_log_fp) {
1807                 fprintf(fr_log_fp, "DHCP Sending %zu bytes\n", packet->data_len);
1808                 for (i = 0; i < packet->data_len; i++) {
1809                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
1810                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1811                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1812                 }
1813                 fprintf(fr_log_fp, "\n");
1814         }
1815
1816         return 0;
1817 }
1818
1819 #ifdef SIOCSARP
1820 int fr_dhcp_add_arp_entry(int fd, char const *interface,
1821                           VALUE_PAIR *macaddr, VALUE_PAIR *ip)
1822 {
1823         struct sockaddr_in *sin;
1824         struct arpreq req;
1825
1826         if (!interface) {
1827                 fr_strerror_printf("No interface specified.  Cannot update ARP table");
1828                 return -1;
1829         }
1830
1831         if (!fr_assert(macaddr) ||
1832             !fr_assert((macaddr->da->type == PW_TYPE_ETHERNET) || (macaddr->da->type == PW_TYPE_OCTETS))) {
1833                 fr_strerror_printf("Wrong VP type (%s) for chaddr",
1834                                    fr_int2str(dict_attr_types, macaddr->da->type, "<invalid>"));
1835                 return -1;
1836         }
1837
1838         if (macaddr->length > sizeof(req.arp_ha.sa_data)) {
1839                 fr_strerror_printf("arp sa_data field too small (%zu octets) to contain chaddr (%zu octets)",
1840                                    sizeof(req.arp_ha.sa_data), macaddr->length);
1841                 return -1;
1842         }
1843
1844         memset(&req, 0, sizeof(req));
1845         sin = (struct sockaddr_in *) &req.arp_pa;
1846         sin->sin_family = AF_INET;
1847         sin->sin_addr.s_addr = ip->vp_ipaddr;
1848
1849         strlcpy(req.arp_dev, interface, sizeof(req.arp_dev));
1850
1851         if (macaddr->da->type == PW_TYPE_ETHERNET) {
1852                 memcpy(&req.arp_ha.sa_data, &macaddr->vp_ether, sizeof(macaddr->vp_ether));
1853         } else {
1854                 memcpy(&req.arp_ha.sa_data, macaddr->vp_octets, macaddr->length);
1855         }
1856
1857         req.arp_flags = ATF_COM;
1858         if (ioctl(fd, SIOCSARP, &req) < 0) {
1859                 fr_strerror_printf("Failed to add entry in ARP cache: %s (%d)", fr_syserror(errno), errno);
1860                 return -1;
1861         }
1862
1863         return 0;
1864 }
1865 #else
1866 int fr_dhcp_add_arp_entry(UNUSED int fd, UNUSED char const *interface,
1867                           UNUSED VALUE_PAIR *macaddr, UNUSED VALUE_PAIR *ip)
1868 {
1869         fr_strerror_printf("Adding ARP entry is unsupported on this system");
1870         return -1;
1871 }
1872 #endif