Fix LGPL text broken by 1af9582b2
[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 #include <freeradius-devel/net.h>
30
31 #ifndef __MINGW32__
32 #include <sys/ioctl.h>
33 #endif
34
35 #ifdef HAVE_SYS_SOCKET_H
36 #include <sys/socket.h>
37 #endif
38 #ifdef HAVE_SYS_TYPES_H
39 #include <sys/types.h>
40 #endif
41
42 #ifndef __MINGW32__
43 #include <net/if_arp.h>
44 #endif
45
46 #define DHCP_CHADDR_LEN (16)
47 #define DHCP_SNAME_LEN  (64)
48 #define DHCP_FILE_LEN   (128)
49 #define DHCP_VEND_LEN   (308)
50 #define DHCP_OPTION_MAGIC_NUMBER (0x63825363)
51
52 #ifndef INADDR_BROADCAST
53 #define INADDR_BROADCAST INADDR_NONE
54 #endif
55
56 /* @todo: this is a hack */
57 #  define DEBUG                 if (fr_debug_lvl && fr_log_fp) fr_printf_log
58 #  define debug_pair(vp)        do { if (fr_debug_lvl && fr_log_fp) { \
59                                         vp_print(fr_log_fp, vp); \
60                                      } \
61                                 } while(0)
62
63 #ifdef HAVE_LINUX_IF_PACKET_H
64 #define ETH_HDR_SIZE   14
65 #define IP_HDR_SIZE    20
66 #define UDP_HDR_SIZE   8
67 #define ETH_ADDR_LEN   6
68 #define ETH_TYPE_IP    0x0800
69 #define ETH_P_ALL      0x0003
70
71 static uint8_t eth_bcast[ETH_ADDR_LEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
72
73 /* Discard raw packets which we are not interested in. Allow to trace why we discard. */
74 #define DISCARD_RP(...) { \
75         if (fr_debug_lvl > 2) { \
76                 fprintf(stdout, "dhcpclient: discarding received packet: "); \
77                 fprintf(stdout, ## __VA_ARGS__); \
78                 fprintf(stdout, "\n"); \
79         } \
80         rad_free(&packet); \
81         return NULL; \
82 }
83 #endif
84
85 typedef struct dhcp_packet_t {
86         uint8_t         opcode;
87         uint8_t         htype;
88         uint8_t         hlen;
89         uint8_t         hops;
90         uint32_t        xid;    /* 4 */
91         uint16_t        secs;   /* 8 */
92         uint16_t        flags;
93         uint32_t        ciaddr; /* 12 */
94         uint32_t        yiaddr; /* 16 */
95         uint32_t        siaddr; /* 20 */
96         uint32_t        giaddr; /* 24 */
97         uint8_t         chaddr[DHCP_CHADDR_LEN]; /* 28 */
98         uint8_t         sname[DHCP_SNAME_LEN]; /* 44 */
99         uint8_t         file[DHCP_FILE_LEN]; /* 108 */
100         uint32_t        option_format; /* 236 */
101         uint8_t         options[DHCP_VEND_LEN];
102 } dhcp_packet_t;
103
104 typedef struct dhcp_option_t {
105         uint8_t         code;
106         uint8_t         length;
107 } dhcp_option_t;
108
109 /*
110  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        DISCOVER
111  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         OFFER
112  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        REQUEST
113  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         ACK
114  */
115 static char const *dhcp_header_names[] = {
116         "DHCP-Opcode",
117         "DHCP-Hardware-Type",
118         "DHCP-Hardware-Address-Length",
119         "DHCP-Hop-Count",
120         "DHCP-Transaction-Id",
121         "DHCP-Number-of-Seconds",
122         "DHCP-Flags",
123         "DHCP-Client-IP-Address",
124         "DHCP-Your-IP-Address",
125         "DHCP-Server-IP-Address",
126         "DHCP-Gateway-IP-Address",
127         "DHCP-Client-Hardware-Address",
128         "DHCP-Server-Host-Name",
129         "DHCP-Boot-Filename",
130
131         NULL
132 };
133
134 static char const *dhcp_message_types[] = {
135         "invalid",
136         "DHCP-Discover",
137         "DHCP-Offer",
138         "DHCP-Request",
139         "DHCP-Decline",
140         "DHCP-Ack",
141         "DHCP-NAK",
142         "DHCP-Release",
143         "DHCP-Inform",
144         "DHCP-Force-Renew",
145 };
146
147 static int dhcp_header_sizes[] = {
148         1, 1, 1, 1,
149         4, 2, 2, 4,
150         4, 4, 4,
151         DHCP_CHADDR_LEN,
152         DHCP_SNAME_LEN,
153         DHCP_FILE_LEN
154 };
155
156
157 /*
158  *      Some clients silently ignore responses less than 300 bytes.
159  */
160 #define MIN_PACKET_SIZE (244)
161 #define DEFAULT_PACKET_SIZE (300)
162 #define MAX_PACKET_SIZE (1500 - 40)
163
164 #define DHCP_OPTION_FIELD (0)
165 #define DHCP_FILE_FIELD   (1)
166 #define DHCP_SNAME_FIELD  (2)
167
168 static uint8_t *dhcp_get_option(dhcp_packet_t *packet, size_t packet_size,
169                                 unsigned int option)
170 {
171         int overload = 0;
172         int field = DHCP_OPTION_FIELD;
173         size_t where, size;
174         uint8_t *data;
175
176         where = 0;
177         size = packet_size - offsetof(dhcp_packet_t, options);
178         data = &packet->options[where];
179
180         while (where < size) {
181                 if (data[0] == 0) { /* padding */
182                         where++;
183                         continue;
184                 }
185
186                 if (data[0] == 255) { /* end of options */
187                         if ((field == DHCP_OPTION_FIELD) &&
188                             (overload & DHCP_FILE_FIELD)) {
189                                 data = packet->file;
190                                 where = 0;
191                                 size = sizeof(packet->file);
192                                 field = DHCP_FILE_FIELD;
193                                 continue;
194
195                         } else if ((field == DHCP_FILE_FIELD) &&
196                                    (overload & DHCP_SNAME_FIELD)) {
197                                 data = packet->sname;
198                                 where = 0;
199                                 size = sizeof(packet->sname);
200                                 field = DHCP_SNAME_FIELD;
201                                 continue;
202                         }
203
204                         return NULL;
205                 }
206
207                 /*
208                  *      We MUST have a real option here.
209                  */
210                 if ((where + 2) > size) {
211                         fr_strerror_printf("Options overflow field at %u",
212                                            (unsigned int) (data - (uint8_t *) packet));
213                         return NULL;
214                 }
215
216                 if ((where + 2 + data[1]) > size) {
217                         fr_strerror_printf("Option length overflows field at %u",
218                                            (unsigned int) (data - (uint8_t *) packet));
219                         return NULL;
220                 }
221
222                 if (data[0] == option) return data;
223
224                 if (data[0] == 52) { /* overload sname and/or file */
225                         overload = data[3];
226                 }
227
228                 where += data[1] + 2;
229                 data += data[1] + 2;
230         }
231
232         return NULL;
233 }
234
235 /*
236  *      DHCPv4 is only for IPv4.  Broadcast only works if udpfromto is
237  *      defined.
238  */
239 RADIUS_PACKET *fr_dhcp_recv(int sockfd)
240 {
241         uint32_t                magic;
242         struct sockaddr_storage src;
243         struct sockaddr_storage dst;
244         socklen_t               sizeof_src;
245         socklen_t               sizeof_dst;
246         RADIUS_PACKET           *packet;
247         uint16_t                port;
248         uint8_t                 *code;
249         ssize_t                 data_len;
250
251         packet = rad_alloc(NULL, false);
252         if (!packet) {
253                 fr_strerror_printf("Failed allocating packet");
254                 return NULL;
255         }
256
257         packet->data = talloc_zero_array(packet, uint8_t, MAX_PACKET_SIZE);
258         if (!packet->data) {
259                 fr_strerror_printf("Out of memory");
260                 rad_free(&packet);
261                 return NULL;
262         }
263
264         packet->sockfd = sockfd;
265         sizeof_src = sizeof(src);
266 #ifdef WITH_UDPFROMTO
267         sizeof_dst = sizeof(dst);
268         data_len = recvfromto(sockfd, packet->data, MAX_PACKET_SIZE, 0,
269                               (struct sockaddr *)&src, &sizeof_src,
270                               (struct sockaddr *)&dst, &sizeof_dst);
271 #else
272         data_len = recvfrom(sockfd, packet->data, MAX_PACKET_SIZE, 0,
273                             (struct sockaddr *)&src, &sizeof_src);
274 #endif
275
276         if (data_len <= 0) {
277                 fr_strerror_printf("Failed reading DHCP socket: %s", fr_syserror(errno));
278                 rad_free(&packet);
279                 return NULL;
280         }
281
282         packet->data_len = data_len;
283         if (packet->data_len < MIN_PACKET_SIZE) {
284                 fr_strerror_printf("DHCP packet is too small (%zu < %d)",
285                                    packet->data_len, MIN_PACKET_SIZE);
286                 rad_free(&packet);
287                 return NULL;
288         }
289
290         if (packet->data_len > MAX_PACKET_SIZE) {
291                 fr_strerror_printf("DHCP packet is too large (%zx > %d)",
292                                    packet->data_len, MAX_PACKET_SIZE);
293                 rad_free(&packet);
294                 return NULL;
295         }
296
297         if (packet->data[1] != 1) {
298                 fr_strerror_printf("DHCP can only receive ethernet requests, not type %02x",
299                       packet->data[1]);
300                 rad_free(&packet);
301                 return NULL;
302         }
303
304         if (packet->data[2] != 6) {
305                 fr_strerror_printf("Ethernet HW length is wrong length %d",
306                         packet->data[2]);
307                 rad_free(&packet);
308                 return NULL;
309         }
310
311         memcpy(&magic, packet->data + 236, 4);
312         magic = ntohl(magic);
313         if (magic != DHCP_OPTION_MAGIC_NUMBER) {
314                 fr_strerror_printf("Cannot do BOOTP");
315                 rad_free(&packet);
316                 return NULL;
317         }
318
319         /*
320          *      Create unique keys for the packet.
321          */
322         memcpy(&magic, packet->data + 4, 4);
323         packet->id = ntohl(magic);
324
325         code = dhcp_get_option((dhcp_packet_t *) packet->data,
326                                packet->data_len, 53);
327         if (!code) {
328                 fr_strerror_printf("No message-type option was found in the packet");
329                 rad_free(&packet);
330                 return NULL;
331         }
332
333         if ((code[1] < 1) || (code[2] == 0) || (code[2] > 8)) {
334                 fr_strerror_printf("Unknown value for message-type option");
335                 rad_free(&packet);
336                 return NULL;
337         }
338
339         packet->code = code[2] | PW_DHCP_OFFSET;
340
341         /*
342          *      Create a unique vector from the MAC address and the
343          *      DHCP opcode.  This is a hack for the RADIUS
344          *      infrastructure in the rest of the server.
345          *
346          *      Note: packet->data[2] == 6, which is smaller than
347          *      sizeof(packet->vector)
348          *
349          *      FIXME:  Look for client-identifier in packet,
350          *      and use that, too?
351          */
352         memset(packet->vector, 0, sizeof(packet->vector));
353         memcpy(packet->vector, packet->data + 28, packet->data[2]);
354         packet->vector[packet->data[2]] = packet->code & 0xff;
355
356         /*
357          *      FIXME: for DISCOVER / REQUEST: src_port == dst_port + 1
358          *      FIXME: for OFFER / ACK       : src_port = dst_port - 1
359          */
360
361         /*
362          *      Unique keys are xid, client mac, and client ID?
363          */
364
365         /*
366          *      FIXME: More checks, like DHCP packet type?
367          */
368
369         sizeof_dst = sizeof(dst);
370
371 #ifndef WITH_UDPFROMTO
372         /*
373          *      This should never fail...
374          */
375         if (getsockname(sockfd, (struct sockaddr *) &dst, &sizeof_dst) < 0) {
376                 fr_strerror_printf("getsockname failed: %s", fr_syserror(errno));
377                 rad_free(&packet);
378                 return NULL;
379         }
380 #endif
381
382         fr_sockaddr2ipaddr(&dst, sizeof_dst, &packet->dst_ipaddr, &port);
383         packet->dst_port = port;
384
385         fr_sockaddr2ipaddr(&src, sizeof_src, &packet->src_ipaddr, &port);
386         packet->src_port = port;
387
388         if (fr_debug_lvl > 1) {
389                 char type_buf[64];
390                 char const *name = type_buf;
391                 char src_ip_buf[256], dst_ip_buf[256];
392
393                 if ((packet->code >= PW_DHCP_DISCOVER) &&
394                     (packet->code <= PW_DHCP_INFORM)) {
395                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
396                 } else {
397                         snprintf(type_buf, sizeof(type_buf), "%d",
398                                  packet->code - PW_DHCP_OFFSET);
399                 }
400
401                 DEBUG("Received %s of Id %08x from %s:%d to %s:%d\n",
402                        name, (unsigned int) packet->id,
403                        inet_ntop(packet->src_ipaddr.af,
404                                  &packet->src_ipaddr.ipaddr,
405                                  src_ip_buf, sizeof(src_ip_buf)),
406                        packet->src_port,
407                        inet_ntop(packet->dst_ipaddr.af,
408                                  &packet->dst_ipaddr.ipaddr,
409                                  dst_ip_buf, sizeof(dst_ip_buf)),
410                        packet->dst_port);
411         }
412
413         return packet;
414 }
415
416
417 /*
418  *      Send a DHCP packet.
419  */
420 int fr_dhcp_send(RADIUS_PACKET *packet)
421 {
422         struct sockaddr_storage dst;
423         socklen_t               sizeof_dst;
424 #ifdef WITH_UDPFROMTO
425         struct sockaddr_storage src;
426         socklen_t               sizeof_src;
427
428         fr_ipaddr2sockaddr(&packet->src_ipaddr, packet->src_port,
429             &src, &sizeof_src);
430 #endif
431
432         fr_ipaddr2sockaddr(&packet->dst_ipaddr, packet->dst_port,
433                            &dst, &sizeof_dst);
434
435         if (packet->data_len == 0) {
436                 fr_strerror_printf("No data to send");
437                 return -1;
438         }
439
440         if (fr_debug_lvl > 1) {
441                 char type_buf[64];
442                 char const *name = type_buf;
443 #ifdef WITH_UDPFROMTO
444                 char src_ip_buf[INET6_ADDRSTRLEN];
445 #endif
446                 char dst_ip_buf[INET6_ADDRSTRLEN];
447
448                 if ((packet->code >= PW_DHCP_DISCOVER) &&
449                     (packet->code <= PW_DHCP_INFORM)) {
450                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
451                 } else {
452                         snprintf(type_buf, sizeof(type_buf), "%d",
453                             packet->code - PW_DHCP_OFFSET);
454                 }
455
456                 DEBUG(
457 #ifdef WITH_UDPFROMTO
458                 "Sending %s Id %08x from %s:%d to %s:%d\n",
459 #else
460                 "Sending %s Id %08x to %s:%d\n",
461 #endif
462                    name, (unsigned int) packet->id,
463 #ifdef WITH_UDPFROMTO
464                    inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, src_ip_buf, sizeof(src_ip_buf)),
465                    packet->src_port,
466 #endif
467                    inet_ntop(packet->dst_ipaddr.af, &packet->dst_ipaddr.ipaddr, dst_ip_buf, sizeof(dst_ip_buf)),
468                    packet->dst_port);
469         }
470
471 #ifndef WITH_UDPFROMTO
472         /*
473          *      Assume that the packet is encoded before sending it.
474          */
475         return sendto(packet->sockfd, packet->data, packet->data_len, 0,
476                       (struct sockaddr *)&dst, sizeof_dst);
477 #else
478
479         return sendfromto(packet->sockfd, packet->data, packet->data_len, 0,
480                           (struct sockaddr *)&src, sizeof_src,
481                           (struct sockaddr *)&dst, sizeof_dst);
482 #endif
483 }
484
485 static int fr_dhcp_attr2vp(TALLOC_CTX *ctx, VALUE_PAIR **vp_p, uint8_t const *p, size_t alen);
486
487 /** Returns the number of array members for arrays with fixed element sizes
488  *
489  */
490 static int fr_dhcp_array_members(size_t *len, DICT_ATTR const *da)
491 {
492         int num_entries = 1;
493
494         /*
495          *      Could be an array of bytes, integers, etc.
496          */
497         if (da->flags.array) switch (da->type) {
498         case PW_TYPE_BYTE:
499                 num_entries = *len;
500                 *len = 1;
501                 break;
502
503         case PW_TYPE_SHORT: /* ignore any trailing data */
504                 num_entries = *len >> 1;
505                 *len = 2;
506                 break;
507
508         case PW_TYPE_IPV4_ADDR:
509         case PW_TYPE_INTEGER:
510         case PW_TYPE_DATE: /* ignore any trailing data */
511                 num_entries = *len >> 2;
512                 *len = 4;
513                 break;
514
515         case PW_TYPE_IPV6_ADDR:
516                 num_entries = *len >> 4;
517                 *len = 16;
518                 break;
519
520         default:
521                 break;
522         }
523
524         return num_entries;
525 }
526
527 /** RFC 4243 Vendor Specific Suboptions
528  *
529  * Vendor specific suboptions are in the format.
530  @verbatim
531       0                   1                   2                   3
532       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
533      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
534      |                     Enterprise Number 0                       |
535      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
536      |    Len 0      |                                               /
537      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
538      /                      Suboption Data 0                         /
539      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
540      |                     Enterprise Number n                       |
541      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
542      |    Len n      |                                               /
543      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
544      /                      Suboption Data n                         /
545      +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
546  @endverbatim
547  *
548  * So although the vendor is identified, the format of the data isn't specified
549  * so we can't actually resolve the suboption to an attribute.
550  *
551  * To get around that, we create an attribute with a vendor matching the
552  * enterprise number, and attr 0.
553  *
554  * How the suboption data is then processed, is dependent on what type
555  * \<iana\>.0 is defined as in the dictionary.
556  *
557  * @param[in,out] tlv to decode. *tlv will be set to the head of the list of suboptions and original will be freed.
558  * @param[in] ctx context to alloc new attributes in.
559  * @param[in] data to parse.
560  * @param[in] len length of data to parse.
561  */
562 static int fr_dhcp_decode_vsa(TALLOC_CTX *ctx, VALUE_PAIR **tlv, uint8_t const *data, size_t len)
563 {
564         uint8_t const *p, *q;
565         vp_cursor_t cursor;
566
567         VALUE_PAIR *head;
568
569         if (len < 4) goto malformed;
570
571         p = data;
572         q = p + len;
573         while (p < q) {
574                 if (p + 5 >= q) goto malformed;
575                 p += sizeof(uint32_t);
576                 p += p[0];
577
578                 /*
579                  *      Check if length > the length of the buffer we have left
580                  */
581                 if (p >= q) goto malformed;
582                 p++;
583         }
584
585         head = NULL;
586         fr_cursor_init(&cursor, &head);
587
588         /*
589          *      Now we know its sane, start decoding!
590          */
591         p = data;
592         while (p < q) {
593                 uint32_t vendor;
594                 DICT_ATTR const *da;
595                 VALUE_PAIR *vp;
596
597                 vendor = ntohl(*((uint32_t const *) p));
598                 /*
599                  *      This is pretty much all we can do.  RFC 4243 doesn't specify
600                  *      an attribute field, so it's up to vendors to figure out how
601                  *      they want to encode their attributes.
602                  */
603                 da = dict_attrbyvalue(0, vendor);
604                 if (!da) {
605                         da = dict_unknown_afrom_fields(ctx, 0, vendor);
606                         if (!da) {
607                                 pairfree(&head);
608                                 goto malformed;
609                         }
610                 }
611                 vp = pairalloc(ctx, da);
612                 if (!vp) {
613                         pairfree(&head);
614                         return -1;
615                 }
616                 vp->op = T_OP_ADD;
617                 pairsteal(ctx, vp); /* for unknown attributes hack */
618
619                 if (fr_dhcp_attr2vp(ctx, &vp, p + 5, p[4]) < 0) {
620                         dict_attr_free(&da);
621                         pairfree(&head);
622                         return -1;
623                 }
624
625                 fr_cursor_merge(&cursor, vp);
626                 dict_attr_free(&da); /* for unknown attributes hack */
627
628                 p += 4 + 1 + p[4];      /* vendor id (4) + len (1) + vsa len (n) */
629         }
630
631         /*
632          *      The caller allocated TLV, if decoding it generated additional
633          *      attributes, we now need to free it, and write the HEAD of our
634          *      new list of attributes in its place.
635          */
636         if (head) {
637                 vp_cursor_t tlv_cursor;
638
639                 /*
640                  *      Free the old TLV attribute
641                  */
642                 TALLOC_FREE(*tlv);
643
644                 /*
645                  *      Cursor not necessary but means we don't have to set
646                  *      ->next directly.
647                  */
648                 fr_cursor_init(&tlv_cursor, tlv);
649                 fr_cursor_merge(&tlv_cursor, head);
650         }
651
652         return 0;
653
654 malformed:
655         (*tlv)->vp_tlv = talloc_array(*tlv, uint8_t, len);
656         if (!(*tlv)->vp_tlv) {
657                 fr_strerror_printf("No memory");
658                 return -1;
659         }
660         memcpy((*tlv)->vp_tlv, data, len);
661         (*tlv)->vp_length = len;
662
663         return 0;
664 }
665
666 /** Decode DHCP suboptions
667  *
668  * @param[in,out] tlv to decode. *tlv will be set to the head of the list of suboptions and original will be freed.
669  * @param[in] ctx context to alloc new attributes in.
670  * @param[in] data to parse.
671  * @param[in] len length of data to parse.
672  */
673 static int fr_dhcp_decode_suboption(TALLOC_CTX *ctx, VALUE_PAIR **tlv, uint8_t const *data, size_t len)
674 {
675         uint8_t const *p, *q;
676         VALUE_PAIR *head, *vp;
677         vp_cursor_t cursor;
678
679         /*
680          *      TLV must already point to a VALUE_PAIR.
681          */
682         VERIFY_VP(*tlv);
683
684         /*
685          *      Take a pass at parsing it.
686          */
687         p = data;
688         q = data + len;
689         while (p < q) {
690                 /*
691                  *      RFC 3046 is very specific about not allowing termination
692                  *      with a 255 sub-option. But it's required for decoding
693                  *      option 43, and vendors will probably screw it up
694                  *      anyway.
695                  */
696                 if (*p == 0) {
697                         p++;
698                         continue;
699                 }
700                 if (*p == 255) {
701                         q--;
702                         break;
703                 }
704
705                 /*
706                  *      Check if reading length would take us past the end of the buffer
707                  */
708                 if (++p >= q) goto malformed;
709                 p += p[0];
710
711                 /*
712                  *      Check if length > the length of the buffer we have left
713                  */
714                 if (p >= q) goto malformed;
715                 p++;
716         }
717
718         /*
719          *      Got here... must be well formed.
720          */
721         head = NULL;
722         fr_cursor_init(&cursor, &head);
723
724         p = data;
725         while (p < q) {
726                 uint8_t const   *a_p;
727                 size_t          a_len;
728                 int             num_entries, i;
729
730                 DICT_ATTR const *da;
731                 uint32_t        attr;
732
733                 /*
734                  *      The initial OID string looks like:
735                  *      <iana>.0
736                  *
737                  *      If <iana>.0 is type TLV then we attempt to decode its contents as more
738                  *      DHCP suboptions, which gives us:
739                  *      <iana>.<attr>
740                  *
741                  *      If <iana>.0 is not defined in the dictionary or is type octets, we leave
742                  *      the attribute as is.
743                  */
744                 attr = (*tlv)->da->attr ? ((*tlv)->da->attr | (p[0] << 8)) : p[0];
745
746                 /*
747                  *      Use the vendor of the parent TLV which is not necessarily
748                  *      DHCP_MAGIC_VENDOR.
749                  *
750                  *      Note: This does not deal with dictionary numbering clashes. If
751                  *      the vendor uses different numbers for DHCP suboptions and RADIUS
752                  *      attributes then it's time to break out %{hex:} and regular
753                  *      expressions.
754                  */
755                 da = dict_attrbyvalue(attr, (*tlv)->da->vendor);
756                 if (!da) {
757                         da = dict_unknown_afrom_fields(ctx, attr, (*tlv)->da->vendor);
758                         if (!da) {
759                                 pairfree(&head);
760                                 return -1;
761                         }
762                 }
763
764                 a_len = p[1];
765                 a_p = p + 2;
766                 num_entries = fr_dhcp_array_members(&a_len, da);
767                 for (i = 0; i < num_entries; i++) {
768                         vp = pairalloc(ctx, da);
769                         if (!vp) {
770                                 pairfree(&head);
771                                 return -1;
772                         }
773                         vp->op = T_OP_ADD;
774                         pairsteal(ctx, vp); /* for unknown attributes hack */
775
776                         if (fr_dhcp_attr2vp(ctx, &vp, a_p, a_len) < 0) {
777                                 dict_attr_free(&da);
778                                 pairfree(&head);
779                                 goto malformed;
780                         }
781                         fr_cursor_merge(&cursor, vp);
782
783                         a_p += a_len;
784                 }
785
786                 dict_attr_free(&da); /* for unknown attributes hack */
787
788                 p += 2 + p[1];  /* code (1) + len (1) + suboption len (n)*/
789         }
790
791         /*
792          *      The caller allocated a TLV, if decoding it generated
793          *      additional attributes, we now need to free it, and write
794          *      the HEAD of our new list of attributes in its place.
795          */
796         if (head) {
797                 vp_cursor_t tlv_cursor;
798
799                 /*
800                  *      Free the old TLV attribute
801                  */
802                 TALLOC_FREE(*tlv);
803
804                 /*
805                  *      Cursor not necessary but means we don't have to set
806                  *      ->next directly.
807                  */
808                 fr_cursor_init(&tlv_cursor, tlv);
809                 fr_cursor_merge(&tlv_cursor, head);
810         }
811
812         return 0;
813
814 malformed:
815         (*tlv)->vp_tlv = talloc_array(*tlv, uint8_t, len);
816         if (!(*tlv)->vp_tlv) {
817                 fr_strerror_printf("No memory");
818                 return -1;
819         }
820         memcpy((*tlv)->vp_tlv, data, len);
821         (*tlv)->vp_length = len;
822
823         return 0;
824 }
825
826 /*
827  *      Decode ONE value into a VP
828  */
829 static int fr_dhcp_attr2vp(TALLOC_CTX *ctx, VALUE_PAIR **vp_p, uint8_t const *data, size_t len)
830 {
831         VALUE_PAIR *vp = *vp_p;
832         VERIFY_VP(vp);
833
834         switch (vp->da->type) {
835         case PW_TYPE_BYTE:
836                 if (len != 1) goto raw;
837                 vp->vp_byte = data[0];
838                 break;
839
840         case PW_TYPE_SHORT:
841                 if (len != 2) goto raw;
842                 memcpy(&vp->vp_short, data, 2);
843                 vp->vp_short = ntohs(vp->vp_short);
844                 break;
845
846         case PW_TYPE_INTEGER:
847                 if (len != 4) goto raw;
848                 memcpy(&vp->vp_integer, data, 4);
849                 vp->vp_integer = ntohl(vp->vp_integer);
850                 break;
851
852         case PW_TYPE_IPV4_ADDR:
853                 if (len != 4) goto raw;
854                 /*
855                  *      Keep value in Network Order!
856                  */
857                 memcpy(&vp->vp_ipaddr, data, 4);
858                 vp->vp_length = 4;
859                 break;
860
861         /*
862          *      In DHCPv4, string options which can also be arrays,
863          *      have their values '\0' delimited.
864          */
865         case PW_TYPE_STRING:
866         {
867                 uint8_t const *p;
868                 uint8_t const *q, *end;
869                 vp_cursor_t cursor;
870
871                 p = data;
872                 q = end = data + len;
873
874                 if (!vp->da->flags.array) {
875                         pairbstrncpy(vp, (char const *)p, q - p);
876                         break;
877                 }
878
879                 /*
880                  *      Initialise the cursor as we may be inserting
881                  *      multiple additional VPs
882                  */
883                 fr_cursor_init(&cursor, vp_p);
884                 for (;;) {
885                         q = memchr(p, '\0', q - p);
886                         /* Malformed but recoverable */
887                         if (!q) q = end;
888
889                         pairbstrncpy(vp, (char const *)p, q - p);
890                         p = q + 1;
891
892                         /* Need another VP for the next round */
893                         if (p < end) {
894                                 vp = pairalloc(ctx, vp->da);
895                                 if (!vp) {
896                                         pairfree(vp_p);
897                                         return -1;
898                                 }
899                                 fr_cursor_insert(&cursor, vp);
900                                 continue;
901                         }
902                         break;
903                 }
904         }
905                 break;
906
907         case PW_TYPE_ETHERNET:
908                 memcpy(vp->vp_ether, data, sizeof(vp->vp_ether));
909                 vp->vp_length = sizeof(vp->vp_ether);
910                 break;
911
912         /*
913          *      Value doesn't match up with attribute type, overwrite the
914          *      vp's original DICT_ATTR with an unknown one.
915          */
916         raw:
917                 if (pair2unknown(vp) < 0) return -1;
918
919         case PW_TYPE_OCTETS:
920                 if (len > 255) return -1;
921                 pairmemcpy(vp, data, len);
922                 break;
923
924         /*
925          *      For option 82 et al...
926          */
927         case PW_TYPE_TLV:
928                 return fr_dhcp_decode_suboption(ctx, vp_p, data, len);
929
930         /*
931          *      For option 82.9
932          */
933         case PW_TYPE_VSA:
934                 return fr_dhcp_decode_vsa(ctx, vp_p, data, len);
935
936         default:
937                 fr_strerror_printf("Internal sanity check %d %d", vp->da->type, __LINE__);
938                 return -1;
939         } /* switch over type */
940
941         vp->vp_length = len;
942         return 0;
943 }
944
945 /** Decode DHCP options
946  *
947  * @param[in,out] out Where to write the decoded options.
948  * @param[in] ctx context to alloc new attributes in.
949  * @param[in] data to parse.
950  * @param[in] len of data to parse.
951  */
952 ssize_t fr_dhcp_decode_options(TALLOC_CTX *ctx, VALUE_PAIR **out, uint8_t const *data, size_t len)
953 {
954         VALUE_PAIR *vp;
955         vp_cursor_t cursor;
956         uint8_t const *p, *q;
957
958         *out = NULL;
959         fr_cursor_init(&cursor, out);
960
961         /*
962          *      FIXME: This should also check sname && file fields.
963          *      See the dhcp_get_option() function above.
964          */
965         p = data;
966         q = data + len;
967         while (p < q) {
968                 uint8_t const   *a_p;
969                 size_t          a_len;
970                 int             num_entries, i;
971
972                 DICT_ATTR const *da;
973
974                 if (*p == 0) {          /* 0x00 - Padding option */
975                         p++;
976                         continue;
977                 }
978
979                 if (*p == 255) {        /* 0xff - End of options signifier */
980                         break;
981                 }
982
983                 if ((p + 2) > q) break;
984
985                 a_len = p[1];
986                 a_p = p + 2;
987
988                 /*
989                  *      Unknown attribute, create an octets type
990                  *      attribute with the contents of the sub-option.
991                  */
992                 da = dict_attrbyvalue(p[0], DHCP_MAGIC_VENDOR);
993                 if (!da) {
994                         da = dict_unknown_afrom_fields(ctx, p[0], DHCP_MAGIC_VENDOR);
995                         if (!da) {
996                                 pairfree(out);
997                                 return -1;
998                         }
999                         vp = pairalloc(ctx, da);
1000                         if (!vp) {
1001                                 pairfree(out);
1002                                 return -1;
1003                         }
1004                         pairmemcpy(vp, a_p, a_len);
1005                         fr_cursor_insert(&cursor, vp);
1006
1007                         goto next;
1008                 }
1009
1010                 /*
1011                  *      Array type sub-option create a new VALUE_PAIR
1012                  *      for each array element.
1013                  */
1014                 num_entries = fr_dhcp_array_members(&a_len, da);
1015                 for (i = 0; i < num_entries; i++) {
1016                         vp = pairalloc(ctx, da);
1017                         if (!vp) {
1018                                 pairfree(out);
1019                                 return -1;
1020                         }
1021                         vp->op = T_OP_ADD;
1022
1023                         if (fr_dhcp_attr2vp(ctx, &vp, a_p, a_len) < 0) {
1024                                 pairfree(&vp);
1025                                 pairfree(out);
1026                                 return -1;
1027                         }
1028                         fr_cursor_merge(&cursor, vp);
1029                         a_p += a_len;
1030                 } /* loop over array entries */
1031         next:
1032                 p += 2 + p[1];  /* code (1) + len (1) + option len (n)*/
1033         } /* loop over the entire packet */
1034
1035         return p - data;
1036 }
1037
1038 int fr_dhcp_decode(RADIUS_PACKET *packet)
1039 {
1040         size_t i;
1041         uint8_t *p;
1042         uint32_t giaddr;
1043         vp_cursor_t cursor;
1044         VALUE_PAIR *head = NULL, *vp;
1045         VALUE_PAIR *maxms, *mtu;
1046
1047         fr_cursor_init(&cursor, &head);
1048         p = packet->data;
1049
1050         if ((fr_debug_lvl > 2) && fr_log_fp) {
1051                 for (i = 0; i < packet->data_len; i++) {
1052                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
1053                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1054                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1055                 }
1056                 fprintf(fr_log_fp, "\n");
1057         }
1058
1059         if (packet->data[1] != 1) {
1060                 fr_strerror_printf("Packet is not Ethernet: %u",
1061                       packet->data[1]);
1062                 return -1;
1063         }
1064
1065         /*
1066          *      Decode the header.
1067          */
1068         for (i = 0; i < 14; i++) {
1069                 char *q;
1070
1071                 vp = pairmake(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
1072                 if (!vp) {
1073                         char buffer[256];
1074                         strlcpy(buffer, fr_strerror(), sizeof(buffer));
1075                         fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1076                         pairfree(&head);
1077                         return -1;
1078                 }
1079
1080                 /*
1081                  *      If chaddr does != 6 bytes it's probably not ethernet, and we should store
1082                  *      it as an opaque type (octets).
1083                  */
1084                 if ((i == 11) && (packet->data[1] == 1) && (packet->data[2] != sizeof(vp->vp_ether))) {
1085                         DICT_ATTR const *da = dict_unknown_afrom_fields(packet, vp->da->attr, vp->da->vendor);
1086                         if (!da) {
1087                                 return -1;
1088                         }
1089                         vp->da = da;
1090                 }
1091
1092                 switch (vp->da->type) {
1093                 case PW_TYPE_BYTE:
1094                         vp->vp_byte = p[0];
1095                         vp->vp_length = 1;
1096                         break;
1097
1098                 case PW_TYPE_SHORT:
1099                         vp->vp_short = (p[0] << 8) | p[1];
1100                         vp->vp_length = 2;
1101                         break;
1102
1103                 case PW_TYPE_INTEGER:
1104                         memcpy(&vp->vp_integer, p, 4);
1105                         vp->vp_integer = ntohl(vp->vp_integer);
1106                         vp->vp_length = 4;
1107                         break;
1108
1109                 case PW_TYPE_IPV4_ADDR:
1110                         memcpy(&vp->vp_ipaddr, p, 4);
1111                         vp->vp_length = 4;
1112                         break;
1113
1114                 case PW_TYPE_STRING:
1115                         vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
1116                         vp->type = VT_DATA;
1117                         memcpy(q, p, dhcp_header_sizes[i]);
1118                         q[dhcp_header_sizes[i]] = '\0';
1119                         vp->vp_length = strlen(vp->vp_strvalue);
1120                         if (vp->vp_length == 0) {
1121                                 pairfree(&vp);
1122                         }
1123                         break;
1124
1125                 case PW_TYPE_OCTETS:
1126                         pairmemcpy(vp, p, packet->data[2]);
1127                         break;
1128
1129                 case PW_TYPE_ETHERNET:
1130                         memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1131                         vp->vp_length = sizeof(vp->vp_ether);
1132                         break;
1133
1134                 default:
1135                         fr_strerror_printf("BAD TYPE %d", vp->da->type);
1136                         pairfree(&vp);
1137                         break;
1138                 }
1139                 p += dhcp_header_sizes[i];
1140
1141                 if (!vp) continue;
1142
1143                 debug_pair(vp);
1144                 fr_cursor_insert(&cursor, vp);
1145         }
1146
1147         /*
1148          *      Loop over the options.
1149          */
1150
1151         /*
1152          *      Nothing uses tail after this call, if it does in the future
1153          *      it'll need to find the new tail...
1154          */
1155         {
1156                 VALUE_PAIR *options = NULL;
1157                 vp_cursor_t options_cursor;
1158
1159                 if (fr_dhcp_decode_options(packet, &options, packet->data + 240, packet->data_len - 240) < 0) {
1160                         return -1;
1161                 }
1162
1163                 if (options) {
1164                         for (vp = fr_cursor_init(&options_cursor, options);
1165                              vp;
1166                              vp = fr_cursor_next(&options_cursor)) {
1167                                 debug_pair(vp);
1168                         }
1169                         fr_cursor_merge(&cursor, options);
1170                 }
1171         }
1172
1173         /*
1174          *      If DHCP request, set ciaddr to zero.
1175          */
1176
1177         /*
1178          *      Set broadcast flag for broken vendors, but only if
1179          *      giaddr isn't set.
1180          */
1181         memcpy(&giaddr, packet->data + 24, sizeof(giaddr));
1182         if (giaddr == htonl(INADDR_ANY)) {
1183                 /*
1184                  *      DHCP Opcode is request
1185                  */
1186                 vp = pairfind(head, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1187                 if (vp && vp->vp_integer == 3) {
1188                         /*
1189                          *      Vendor is "MSFT 98"
1190                          */
1191                         vp = pairfind(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
1192                         if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
1193                                 vp = pairfind(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
1194
1195                                 /*
1196                                  *      Reply should be broadcast.
1197                                  */
1198                                 if (vp) vp->vp_integer |= 0x8000;
1199                                 packet->data[10] |= 0x80;
1200                         }
1201                 }
1202         }
1203
1204         /*
1205          *      FIXME: Nuke attributes that aren't used in the normal
1206          *      header for discover/requests.
1207          */
1208         packet->vps = head;
1209
1210         /*
1211          *      Client can request a LARGER size, but not a smaller
1212          *      one.  They also cannot request a size larger than MTU.
1213          */
1214         maxms = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1215         mtu = pairfind(packet->vps, 26, DHCP_MAGIC_VENDOR, TAG_ANY);
1216
1217         if (mtu && (mtu->vp_integer < DEFAULT_PACKET_SIZE)) {
1218                 fr_strerror_printf("DHCP Fatal: Client says MTU is smaller than minimum permitted by the specification");
1219                 return -1;
1220         }
1221
1222         if (maxms && (maxms->vp_integer < DEFAULT_PACKET_SIZE)) {
1223                 fr_strerror_printf("DHCP WARNING: Client says maximum message size is smaller than minimum permitted by the specification: fixing it");
1224                 maxms->vp_integer = DEFAULT_PACKET_SIZE;
1225         }
1226
1227         if (maxms && mtu && (maxms->vp_integer > mtu->vp_integer)) {
1228                 fr_strerror_printf("DHCP WARNING: Client says MTU is smaller than maximum message size: fixing it");
1229                 maxms->vp_integer = mtu->vp_integer;
1230         }
1231
1232         if (fr_debug_lvl) fflush(stdout);
1233
1234         return 0;
1235 }
1236
1237
1238 int8_t fr_dhcp_attr_cmp(void const *a, void const *b)
1239 {
1240         VALUE_PAIR const *my_a = a;
1241         VALUE_PAIR const *my_b = b;
1242
1243         VERIFY_VP(my_a);
1244         VERIFY_VP(my_b);
1245
1246         /*
1247          *      DHCP-Message-Type is first, for simplicity.
1248          */
1249         if ((my_a->da->attr == 53) && (my_b->da->attr != 53)) return -1;
1250
1251         /*
1252          *      Relay-Agent is last
1253          */
1254         if ((my_a->da->attr == 82) && (my_b->da->attr != 82)) return 1;
1255
1256         if (my_a->da->attr < my_b->da->attr) return -1;
1257         if (my_a->da->attr > my_b->da->attr) return 1;
1258
1259         return 0;
1260 }
1261
1262 /** Write DHCP option value into buffer
1263  *
1264  * Does not include DHCP option length or number.
1265  *
1266  * @param out where to write the DHCP option.
1267  * @param outlen length of output buffer.
1268  * @param vp option to encode.
1269  * @return the length of data writen, -1 if out of buffer, -2 if unsupported type.
1270  */
1271 static ssize_t fr_dhcp_vp2attr(uint8_t *out, size_t outlen, VALUE_PAIR *vp)
1272 {
1273         uint32_t lvalue;
1274         uint8_t *p = out;
1275
1276         if (outlen < vp->vp_length) {
1277                 return -1;
1278         }
1279
1280         switch (vp->da->type) {
1281         case PW_TYPE_BYTE:
1282                 *p = vp->vp_byte;
1283                 break;
1284
1285         case PW_TYPE_SHORT:
1286                 p[0] = (vp->vp_short >> 8) & 0xff;
1287                 p[1] = vp->vp_short & 0xff;
1288                 break;
1289
1290         case PW_TYPE_INTEGER:
1291                 lvalue = htonl(vp->vp_integer);
1292                 memcpy(p, &lvalue, 4);
1293                 break;
1294
1295         case PW_TYPE_IPV4_ADDR:
1296                 memcpy(p, &vp->vp_ipaddr, 4);
1297                 break;
1298
1299         case PW_TYPE_ETHERNET:
1300                 memcpy(p, vp->vp_ether, 6);
1301                 break;
1302
1303         case PW_TYPE_STRING:
1304                 memcpy(p, vp->vp_strvalue, vp->vp_length);
1305                 break;
1306
1307         case PW_TYPE_TLV:       /* FIXME: split it on 255? */
1308                 memcpy(p, vp->vp_tlv, vp->vp_length);
1309                 break;
1310
1311         case PW_TYPE_OCTETS:
1312                 memcpy(p, vp->vp_octets, vp->vp_length);
1313                 break;
1314
1315         default:
1316                 fr_strerror_printf("Unsupported option type %d", vp->da->type);
1317                 return -2;
1318         }
1319
1320         return vp->vp_length;
1321 }
1322
1323 /** Create a new TLV attribute from multiple sub options
1324  *
1325  * @param[in,out] ctx to allocate new attribute in.
1326  * @param[in,out] cursor should be set to the start of the list of TLV attributes.
1327  *   Will be advanced to the first non-TLV attribute.
1328  * @return attribute holding the concatenation of the values of the sub options.
1329  */
1330 static VALUE_PAIR *fr_dhcp_vp2suboption(TALLOC_CTX *ctx, vp_cursor_t *cursor)
1331 {
1332         ssize_t length;
1333         unsigned int parent;    /* Parent attribute of suboption */
1334         uint8_t attr = 0;
1335         uint8_t *p, *opt_len = NULL;
1336         vp_cursor_t to_pack;
1337         VALUE_PAIR *vp, *tlv;
1338
1339 #define SUBOPTION_PARENT(_x) (_x & 0xffff00ff)
1340 #define SUBOPTION_ATTR(_x) ((_x & 0xff00) >> 8)
1341
1342         vp = fr_cursor_current(cursor);
1343         if (!vp) return NULL;
1344
1345         parent = SUBOPTION_PARENT(vp->da->attr);
1346         tlv = paircreate(ctx, parent, DHCP_MAGIC_VENDOR);
1347         if (!tlv) return NULL;
1348
1349         fr_cursor_copy(&to_pack, cursor);
1350
1351         /*
1352          *  Loop over TLVs to determine how much memory we need to allocate
1353          *
1354          *  We advanced the cursor we were passed, so if we fail encoding,
1355          *  the cursor is at the right position for the next potentially
1356          *  encodable attr.
1357          */
1358         for (vp = fr_cursor_current(cursor);
1359              vp && vp->da->flags.is_tlv && !vp->da->flags.extended && (SUBOPTION_PARENT(vp->da->attr) == parent);
1360              vp = fr_cursor_next(cursor)) {
1361                 /*
1362                  *  If it's not an array type or is an array type, but is not the same
1363                  *  as the previous attribute, we add 2 for the additional sub-option
1364                  *  header bytes.
1365                  */
1366                 if (!vp->da->flags.array || (SUBOPTION_ATTR(vp->da->attr) != attr)) {
1367                         attr = SUBOPTION_ATTR(vp->da->attr);
1368                         tlv->vp_length += 2;
1369                 }
1370                 tlv->vp_length += vp->vp_length;
1371         }
1372
1373         tlv->vp_tlv = talloc_zero_array(tlv, uint8_t, tlv->vp_length);
1374         if (!tlv->vp_tlv) {
1375                 talloc_free(tlv);
1376                 return NULL;
1377         }
1378         p = tlv->vp_tlv;
1379
1380         attr = 0;
1381         for (vp = fr_cursor_current(&to_pack);
1382              vp && vp->da->flags.is_tlv && !vp->da->flags.extended && (SUBOPTION_PARENT(vp->da->attr) == parent);
1383              vp = fr_cursor_next(&to_pack)) {
1384                 if (SUBOPTION_ATTR(vp->da->attr) == 0) {
1385                         fr_strerror_printf("Invalid attribute number 0");
1386                         return NULL;
1387                 }
1388
1389                 /* Don't write out the header, were packing array options */
1390                 if (!vp->da->flags.array || (attr != SUBOPTION_ATTR(vp->da->attr))) {
1391                         attr = SUBOPTION_ATTR(vp->da->attr);
1392                         *p++ = attr;
1393                         opt_len = p++;
1394                 }
1395
1396                 length = fr_dhcp_vp2attr(p, (tlv->vp_tlv + tlv->vp_length) - p, vp);
1397                 if ((length < 0) || (length > 255)) {
1398                         talloc_free(tlv);
1399                         return NULL;
1400                 }
1401
1402                 fr_assert(opt_len);
1403                 *opt_len += length;
1404                 p += length;
1405         };
1406
1407         return tlv;
1408 }
1409
1410 /** Encode a DHCP option and any sub-options.
1411  *
1412  * @param out Where to write encoded DHCP attributes.
1413  * @param outlen Length of out buffer.
1414  * @param ctx to use for any allocated memory.
1415  * @param cursor with current VP set to the option to be encoded. Will be advanced to the next option to encode.
1416  * @return > 0 length of data written, < 0 error, 0 not valid option (skipping).
1417  */
1418 ssize_t fr_dhcp_encode_option(TALLOC_CTX *ctx, uint8_t *out, size_t outlen, vp_cursor_t *cursor)
1419 {
1420         VALUE_PAIR *vp;
1421         DICT_ATTR const *previous;
1422         uint8_t *opt_len, *p = out;
1423         size_t freespace = outlen;
1424         ssize_t len;
1425
1426         vp = fr_cursor_current(cursor);
1427         if (!vp) return -1;
1428
1429         if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next; /* not a DHCP option */
1430         if (vp->da->attr == 53) goto next; /* already done */
1431         if ((vp->da->attr > 255) && (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
1432
1433         if (vp->da->flags.extended) {
1434         next:
1435                 fr_strerror_printf("Attribute \"%s\" is not a DHCP option", vp->da->name);
1436                 fr_cursor_next(cursor);
1437                 return 0;
1438         }
1439
1440         /* Write out the option number */
1441         *(p++) = vp->da->attr & 0xff;
1442
1443         /* Pointer to the length field of the option */
1444         opt_len = p++;
1445
1446         /* Zero out the option's length field */
1447         *opt_len = 0;
1448
1449         /* We just consumed two bytes for the header */
1450         freespace -= 2;
1451
1452         /* DHCP options with the same number get coalesced into a single option */
1453         do {
1454                 VALUE_PAIR *tlv = NULL;
1455
1456                 /* Sub option */
1457                 if (vp->da->flags.is_tlv) {
1458                         /*
1459                          *  Coalesce TLVs into one sub-option.
1460                          *  Cursor will be advanced to next non-TLV attribute.
1461                          */
1462                         tlv = vp = fr_dhcp_vp2suboption(ctx, cursor);
1463
1464                         /*
1465                          *  Skip if there's an issue coalescing the sub-options.
1466                          *  Cursor will still have been advanced to next non-TLV attribute.
1467                          */
1468                         if (!tlv) return 0;
1469                 /*
1470                  *  If not calling fr_dhcp_vp2suboption() advance the cursor, so fr_cursor_current()
1471                  *  returns the next attribute.
1472                  */
1473                 } else {
1474                         fr_cursor_next(cursor);
1475                 }
1476
1477                 if ((*opt_len + vp->vp_length) > 255) {
1478                         fr_strerror_printf("Skipping \"%s\": Option splitting not supported "
1479                                            "(option > 255 bytes)", vp->da->name);
1480                         talloc_free(tlv);
1481                         return 0;
1482                 }
1483
1484                 len = fr_dhcp_vp2attr(p, freespace, vp);
1485                 talloc_free(tlv);
1486                 if (len < 0) {
1487                         /* Failed encoding option */
1488                         return len;
1489                 }
1490
1491                 p += len;
1492                 *opt_len += len;
1493                 freespace -= len;
1494
1495                 previous = vp->da;
1496         } while ((vp = fr_cursor_current(cursor)) && (previous == vp->da) && vp->da->flags.array);
1497
1498         return p - out;
1499 }
1500
1501 int fr_dhcp_encode(RADIUS_PACKET *packet)
1502 {
1503         unsigned int i;
1504         uint8_t *p;
1505         vp_cursor_t cursor;
1506         VALUE_PAIR *vp;
1507         uint32_t lvalue;
1508         size_t dhcp_size;
1509         ssize_t len;
1510 #ifndef NDEBUG
1511         char const *name;
1512 #  ifdef WITH_UDPFROMTO
1513         char src_ip_buf[256];
1514 #  endif
1515         char dst_ip_buf[256];
1516 #endif
1517
1518         if (packet->data) return 0;
1519
1520         packet->data_len = MAX_PACKET_SIZE;
1521         packet->data = talloc_zero_array(packet, uint8_t, packet->data_len);
1522
1523         /* XXX Ugly ... should be set by the caller */
1524         if (packet->code == 0) packet->code = PW_DHCP_NAK;
1525
1526         /* store xid */
1527         if ((vp = pairfind(packet->vps, 260, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1528                 packet->id = vp->vp_integer;
1529         } else {
1530                 packet->id = fr_rand();
1531         }
1532
1533 #ifndef NDEBUG
1534         if ((packet->code >= PW_DHCP_DISCOVER) &&
1535             (packet->code <= PW_DHCP_INFORM)) {
1536                 name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
1537         } else {
1538                 name = "?Unknown?";
1539         }
1540
1541         DEBUG(
1542 #  ifdef WITH_UDPFROMTO
1543               "Encoding %s of id %08x from %s:%d to %s:%d\n",
1544 #  else
1545               "Encoding %s of id %08x to %s:%d\n",
1546 #  endif
1547               name, (unsigned int) packet->id,
1548 #  ifdef WITH_UDPFROMTO
1549               inet_ntop(packet->src_ipaddr.af,
1550                         &packet->src_ipaddr.ipaddr,
1551                         src_ip_buf, sizeof(src_ip_buf)),
1552               packet->src_port,
1553 #  endif
1554               inet_ntop(packet->dst_ipaddr.af,
1555                         &packet->dst_ipaddr.ipaddr,
1556                      dst_ip_buf, sizeof(dst_ip_buf)),
1557               packet->dst_port);
1558 #endif
1559
1560         p = packet->data;
1561
1562         /*
1563          *      @todo: Make this work again.
1564          */
1565 #if 0
1566         mms = DEFAULT_PACKET_SIZE; /* maximum message size */
1567
1568         /*
1569          *      Clients can request a LARGER size, but not a
1570          *      smaller one.  They also cannot request a size
1571          *      larger than MTU.
1572          */
1573
1574         /* DHCP-DHCP-Maximum-Msg-Size */
1575         vp = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1576         if (vp && (vp->vp_integer > mms)) {
1577                 mms = vp->vp_integer;
1578
1579                 if (mms > MAX_PACKET_SIZE) mms = MAX_PACKET_SIZE;
1580         }
1581 #endif
1582
1583         vp = pairfind(packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1584         if (vp) {
1585                 *p++ = vp->vp_integer & 0xff;
1586         } else {
1587                 *p++ = 1;       /* client message */
1588         }
1589
1590         /* DHCP-Hardware-Type */
1591         if ((vp = pairfind(packet->vps, 257, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1592                 *p++ = vp->vp_integer & 0xFF;
1593         } else {
1594                 *p++ = 1;               /* hardware type = ethernet */
1595         }
1596
1597         /* DHCP-Hardware-Address-Length */
1598         if ((vp = pairfind(packet->vps, 258, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1599                 *p++ = vp->vp_integer & 0xFF;
1600         } else {
1601                 *p++ = 6;               /* 6 bytes of ethernet */
1602         }
1603
1604         /* DHCP-Hop-Count */
1605         if ((vp = pairfind(packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1606                 *p = vp->vp_integer & 0xff;
1607         }
1608         p++;
1609
1610         /* DHCP-Transaction-Id */
1611         lvalue = htonl(packet->id);
1612         memcpy(p, &lvalue, 4);
1613         p += 4;
1614
1615         /* DHCP-Number-of-Seconds */
1616         if ((vp = pairfind(packet->vps, 261, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1617                 lvalue = htonl(vp->vp_integer);
1618                 memcpy(p, &lvalue, 2);
1619         }
1620         p += 2;
1621
1622         /* DHCP-Flags */
1623         if ((vp = pairfind(packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1624                 lvalue = htons(vp->vp_integer);
1625                 memcpy(p, &lvalue, 2);
1626         }
1627         p += 2;
1628
1629         /* DHCP-Client-IP-Address */
1630         if ((vp = pairfind(packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1631                 memcpy(p, &vp->vp_ipaddr, 4);
1632         }
1633         p += 4;
1634
1635         /* DHCP-Your-IP-address */
1636         if ((vp = pairfind(packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1637                 lvalue = vp->vp_ipaddr;
1638         } else {
1639                 lvalue = htonl(INADDR_ANY);
1640         }
1641         memcpy(p, &lvalue, 4);
1642         p += 4;
1643
1644         /* DHCP-Server-IP-Address */
1645         vp = pairfind(packet->vps, 265, DHCP_MAGIC_VENDOR, TAG_ANY);
1646         if (vp) {
1647                 lvalue = vp->vp_ipaddr;
1648         } else {
1649                 lvalue = htonl(INADDR_ANY);
1650         }
1651         memcpy(p, &lvalue, 4);
1652         p += 4;
1653
1654         /*
1655          *      DHCP-Gateway-IP-Address
1656          */
1657         if ((vp = pairfind(packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1658                 lvalue = vp->vp_ipaddr;
1659         } else {
1660                 lvalue = htonl(INADDR_ANY);
1661         }
1662         memcpy(p, &lvalue, 4);
1663         p += 4;
1664
1665         /* DHCP-Client-Hardware-Address */
1666         if ((vp = pairfind(packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1667                 if (vp->vp_length == sizeof(vp->vp_ether)) {
1668                         memcpy(p, vp->vp_ether, vp->vp_length);
1669                 } /* else ignore it */
1670         }
1671         p += DHCP_CHADDR_LEN;
1672
1673         /* DHCP-Server-Host-Name */
1674         if ((vp = pairfind(packet->vps, 268, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1675                 if (vp->vp_length > DHCP_SNAME_LEN) {
1676                         memcpy(p, vp->vp_strvalue, DHCP_SNAME_LEN);
1677                 } else {
1678                         memcpy(p, vp->vp_strvalue, vp->vp_length);
1679                 }
1680         }
1681         p += DHCP_SNAME_LEN;
1682
1683         /*
1684          *      Copy over DHCP-Boot-Filename.
1685          *
1686          *      FIXME: This copy should be delayed until AFTER the options
1687          *      have been processed.  If there are too many options for
1688          *      the packet, then they go into the sname && filename fields.
1689          *      When that happens, the boot filename is passed as an option,
1690          *      instead of being placed verbatim in the filename field.
1691          */
1692
1693         /* DHCP-Boot-Filename */
1694         vp = pairfind(packet->vps, 269, DHCP_MAGIC_VENDOR, TAG_ANY);
1695         if (vp) {
1696                 if (vp->vp_length > DHCP_FILE_LEN) {
1697                         memcpy(p, vp->vp_strvalue, DHCP_FILE_LEN);
1698                 } else {
1699                         memcpy(p, vp->vp_strvalue, vp->vp_length);
1700                 }
1701         }
1702         p += DHCP_FILE_LEN;
1703
1704         /* DHCP magic number */
1705         lvalue = htonl(DHCP_OPTION_MAGIC_NUMBER);
1706         memcpy(p, &lvalue, 4);
1707         p += 4;
1708
1709         /*
1710          *      Print the header.
1711          */
1712         if (fr_debug_lvl > 1) {
1713                 uint8_t *pp = p;
1714
1715                 p = packet->data;
1716
1717                 for (i = 0; i < 14; i++) {
1718                         char *q;
1719
1720                         vp = pairmake(packet, NULL,
1721                                       dhcp_header_names[i], NULL, T_OP_EQ);
1722                         if (!vp) {
1723                                 char buffer[256];
1724                                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1725                                 fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1726                                 return -1;
1727                         }
1728
1729                         switch (vp->da->type) {
1730                         case PW_TYPE_BYTE:
1731                                 vp->vp_byte = p[0];
1732                                 break;
1733
1734                         case PW_TYPE_SHORT:
1735                                 vp->vp_short = (p[0] << 8) | p[1];
1736                                 break;
1737
1738                         case PW_TYPE_INTEGER:
1739                                 memcpy(&vp->vp_integer, p, 4);
1740                                 vp->vp_integer = ntohl(vp->vp_integer);
1741                                 break;
1742
1743                         case PW_TYPE_IPV4_ADDR:
1744                                 memcpy(&vp->vp_ipaddr, p, 4);
1745                                 break;
1746
1747                         case PW_TYPE_STRING:
1748                                 vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
1749                                 vp->type = VT_DATA;
1750                                 memcpy(q, p, dhcp_header_sizes[i]);
1751                                 q[dhcp_header_sizes[i]] = '\0';
1752                                 vp->vp_length = strlen(vp->vp_strvalue);
1753                                 break;
1754
1755                         case PW_TYPE_OCTETS: /* only for Client HW Address */
1756                                 pairmemcpy(vp, p, packet->data[2]);
1757                                 break;
1758
1759                         case PW_TYPE_ETHERNET: /* only for Client HW Address */
1760                                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1761                                 break;
1762
1763                         default:
1764                                 fr_strerror_printf("Internal sanity check failed %d %d", vp->da->type, __LINE__);
1765                                 pairfree(&vp);
1766                                 break;
1767                         }
1768
1769                         p += dhcp_header_sizes[i];
1770
1771                         debug_pair(vp);
1772                         pairfree(&vp);
1773                 }
1774
1775                 /*
1776                  *      Jump over DHCP magic number, response, etc.
1777                  */
1778                 p = pp;
1779         }
1780
1781         p[0] = 0x35;            /* DHCP-Message-Type */
1782         p[1] = 1;
1783         p[2] = packet->code - PW_DHCP_OFFSET;
1784         p += 3;
1785
1786
1787         /*
1788          *  Pre-sort attributes into contiguous blocks so that fr_dhcp_encode_option
1789          *  operates correctly. This changes the order of the list, but never mind...
1790          */
1791         pairsort(&packet->vps, fr_dhcp_attr_cmp);
1792         fr_cursor_init(&cursor, &packet->vps);
1793
1794         /*
1795          *  Each call to fr_dhcp_encode_option will encode one complete DHCP option,
1796          *  and sub options.
1797          */
1798         while ((vp = fr_cursor_current(&cursor))) {
1799                 len = fr_dhcp_encode_option(packet, p, packet->data_len - (p - packet->data), &cursor);
1800                 if (len < 0) break;
1801                 if (len > 0) debug_pair(vp);
1802                 p += len;
1803         };
1804
1805         p[0] = 0xff;            /* end of option option */
1806         p[1] = 0x00;
1807         p += 2;
1808         dhcp_size = p - packet->data;
1809
1810         /*
1811          *      FIXME: if (dhcp_size > mms),
1812          *        then we put the extra options into the "sname" and "file"
1813          *        fields, AND set the "end option option" in the "options"
1814          *        field.  We also set the "overload option",
1815          *        and put options into the "file" field, followed by
1816          *        the "sname" field.  Where each option is completely
1817          *        enclosed in the "file" and/or "sname" field, AND
1818          *        followed by the "end of option", and MUST be followed
1819          *        by padding option.
1820          *
1821          *      Yuck.  That sucks...
1822          */
1823         packet->data_len = dhcp_size;
1824
1825         if (packet->data_len < DEFAULT_PACKET_SIZE) {
1826                 memset(packet->data + packet->data_len, 0,
1827                        DEFAULT_PACKET_SIZE - packet->data_len);
1828                 packet->data_len = DEFAULT_PACKET_SIZE;
1829         }
1830
1831         if ((fr_debug_lvl > 2) && fr_log_fp) {
1832                 fprintf(fr_log_fp, "DHCP Sending %zu bytes\n", packet->data_len);
1833                 for (i = 0; i < packet->data_len; i++) {
1834                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
1835                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1836                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1837                 }
1838                 fprintf(fr_log_fp, "\n");
1839         }
1840
1841         return 0;
1842 }
1843
1844 #ifdef SIOCSARP
1845 int fr_dhcp_add_arp_entry(int fd, char const *interface,
1846                           VALUE_PAIR *macaddr, VALUE_PAIR *ip)
1847 {
1848         struct sockaddr_in *sin;
1849         struct arpreq req;
1850
1851         if (!interface) {
1852                 fr_strerror_printf("No interface specified.  Cannot update ARP table");
1853                 return -1;
1854         }
1855
1856         if (!fr_assert(macaddr) ||
1857             !fr_assert((macaddr->da->type == PW_TYPE_ETHERNET) || (macaddr->da->type == PW_TYPE_OCTETS))) {
1858                 fr_strerror_printf("Wrong VP type (%s) for chaddr",
1859                                    fr_int2str(dict_attr_types, macaddr->da->type, "<invalid>"));
1860                 return -1;
1861         }
1862
1863         if (macaddr->vp_length > sizeof(req.arp_ha.sa_data)) {
1864                 fr_strerror_printf("arp sa_data field too small (%zu octets) to contain chaddr (%zu octets)",
1865                                    sizeof(req.arp_ha.sa_data), macaddr->vp_length);
1866                 return -1;
1867         }
1868
1869         memset(&req, 0, sizeof(req));
1870         sin = (struct sockaddr_in *) &req.arp_pa;
1871         sin->sin_family = AF_INET;
1872         sin->sin_addr.s_addr = ip->vp_ipaddr;
1873
1874         strlcpy(req.arp_dev, interface, sizeof(req.arp_dev));
1875
1876         if (macaddr->da->type == PW_TYPE_ETHERNET) {
1877                 memcpy(&req.arp_ha.sa_data, macaddr->vp_ether, sizeof(macaddr->vp_ether));
1878         } else {
1879                 memcpy(&req.arp_ha.sa_data, macaddr->vp_octets, macaddr->vp_length);
1880         }
1881
1882         req.arp_flags = ATF_COM;
1883         if (ioctl(fd, SIOCSARP, &req) < 0) {
1884                 fr_strerror_printf("Failed to add entry in ARP cache: %s (%d)", fr_syserror(errno), errno);
1885                 return -1;
1886         }
1887
1888         return 0;
1889 }
1890 #else
1891 int fr_dhcp_add_arp_entry(UNUSED int fd, UNUSED char const *interface,
1892                           UNUSED VALUE_PAIR *macaddr, UNUSED VALUE_PAIR *ip)
1893 {
1894         fr_strerror_printf("Adding ARP entry is unsupported on this system");
1895         return -1;
1896 }
1897 #endif
1898
1899
1900 #ifdef HAVE_LINUX_IF_PACKET_H
1901 /*
1902  *      Open a packet interface raw socket.
1903  *      Bind it to the specified interface using a device independent physical layer address.
1904  */
1905 int fr_socket_packet(int iface_index, struct sockaddr_ll *p_ll)
1906 {
1907         int lsockfd;
1908
1909         /* PF_PACKET - packet interface on device level.
1910            using a raw socket allows packet data to be unchanged by the device driver.
1911          */
1912         lsockfd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
1913         if (lsockfd < 0) {
1914                 fr_strerror_printf("cannot open socket: %s", fr_syserror(errno));
1915                 return lsockfd;
1916         }
1917
1918         /* Set link layer parameters */
1919         memset(p_ll, 0, sizeof(struct sockaddr_ll));
1920
1921         p_ll->sll_family = AF_PACKET;
1922         p_ll->sll_protocol = htons(ETH_P_ALL);
1923         p_ll->sll_ifindex = iface_index;
1924         p_ll->sll_hatype = ARPHRD_ETHER;
1925         p_ll->sll_pkttype = PACKET_OTHERHOST;
1926         p_ll->sll_halen = 6;
1927
1928         if (bind(lsockfd, (struct sockaddr *)p_ll, sizeof(struct sockaddr_ll)) < 0) {
1929                 close(lsockfd);
1930                 fr_strerror_printf("cannot bind raw socket: %s", fr_syserror(errno));
1931                 return -1;
1932         }
1933
1934         return lsockfd;
1935 }
1936
1937 /*
1938  *      Encode and send a DHCP packet on a raw packet socket.
1939  */
1940 int fr_dhcp_send_raw_packet(int sockfd, struct sockaddr_ll *p_ll, RADIUS_PACKET *packet)
1941 {
1942         VALUE_PAIR *vp;
1943         u_char dhcp_packet[1518] = { 0 };
1944
1945         /* set ethernet source address to our MAC address (DHCP-Client-Hardware-Address). */
1946         u_char dhmac[ETH_ADDR_LEN] = { 0 };
1947         if ((vp = pairfind(packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1948                 if (vp->length == sizeof(vp->vp_ether)) {
1949                         memcpy(dhmac, vp->vp_ether, vp->length);
1950                 }
1951         }
1952
1953         /* fill in Ethernet layer (L2) */
1954         struct ethernet_header *ethhdr = (struct ethernet_header *)dhcp_packet;
1955         memcpy(ethhdr->ether_dst, eth_bcast, ETH_ADDR_LEN);
1956         memcpy(ethhdr->ether_src, dhmac, ETH_ADDR_LEN);
1957         ethhdr->ether_type = htons(ETH_TYPE_IP);
1958
1959         /* fill in IP layer (L3) */
1960         struct ip_header *iph = (struct ip_header *)(dhcp_packet + ETH_HDR_SIZE);
1961         iph->ip_vhl = IP_VHL(4, 5);
1962         iph->ip_tos = 0;
1963         iph->ip_len = htons(IP_HDR_SIZE +  UDP_HDR_SIZE + packet->data_len);
1964         iph->ip_id = 0;
1965         iph->ip_off = 0;
1966         iph->ip_ttl = 64;
1967         iph->ip_p = 17;
1968         iph->ip_sum = 0; /* Filled later */
1969
1970         /* saddr: Packet-Src-IP-Address (default: 0.0.0.0). */
1971         iph->ip_src.s_addr = packet->src_ipaddr.ipaddr.ip4addr.s_addr;
1972
1973         /* daddr: packet destination IP addr (should be 255.255.255.255 for broadcast). */
1974         iph->ip_dst.s_addr = packet->dst_ipaddr.ipaddr.ip4addr.s_addr;
1975
1976         /* IP header checksum */
1977         iph->ip_sum = fr_iph_checksum((uint8_t const *)iph, 5);
1978
1979         /* fill in UDP layer (L4) */
1980         udp_header_t *uh = (udp_header_t *) (dhcp_packet + ETH_HDR_SIZE + IP_HDR_SIZE);
1981
1982         uh->src = htons(68);
1983         uh->dst = htons(67);
1984         u_int16_t l4_len = (UDP_HDR_SIZE + packet->data_len);
1985         uh->len = htons(l4_len);
1986         uh->checksum = 0; /* UDP checksum will be done after dhcp header */
1987
1988         /* DHCP layer (L7) */
1989         dhcp_packet_t *dhpointer = (dhcp_packet_t *)(dhcp_packet + ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE);
1990         /* just copy what FreeRADIUS has encoded for us. */
1991         memcpy(dhpointer, packet->data, packet->data_len);
1992
1993         /* UDP checksum is done here */
1994         uh->checksum = fr_udp_checksum((uint8_t const *)(dhcp_packet + ETH_HDR_SIZE + IP_HDR_SIZE), ntohs(uh->len), uh->checksum,
1995                                         packet->src_ipaddr.ipaddr.ip4addr, packet->dst_ipaddr.ipaddr.ip4addr);
1996
1997         if (fr_debug_lvl > 1) {
1998                 char type_buf[64];
1999                 char const *name = type_buf;
2000                 char src_ip_buf[INET6_ADDRSTRLEN];
2001                 char dst_ip_buf[INET6_ADDRSTRLEN];
2002
2003                 if ((packet->code >= PW_DHCP_DISCOVER) &&
2004                     (packet->code <= PW_DHCP_INFORM)) {
2005                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
2006                 } else {
2007                         snprintf(type_buf, sizeof(type_buf), "%d",
2008                             packet->code - PW_DHCP_OFFSET);
2009                 }
2010
2011                 DEBUG(
2012                 "Sending %s Id %08x from %s:%d to %s:%d\n",
2013                    name, (unsigned int) packet->id,
2014                    inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, src_ip_buf, sizeof(src_ip_buf)), packet->src_port,
2015                    inet_ntop(packet->dst_ipaddr.af, &packet->dst_ipaddr.ipaddr, dst_ip_buf, sizeof(dst_ip_buf)), packet->dst_port);
2016         }
2017
2018         return sendto(sockfd, dhcp_packet,
2019                 (ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE + packet->data_len),
2020                 0, (struct sockaddr *) p_ll, sizeof(struct sockaddr_ll));
2021 }
2022
2023 /*
2024  *      print an ethernet address in a buffer
2025  */
2026 char * ether_addr_print(const uint8_t *addr, char *buf)
2027 {
2028         sprintf (buf, "%02x:%02x:%02x:%02x:%02x:%02x",
2029                 addr[0], addr[1], addr[2], addr[3], addr[4], addr[5]);
2030         return buf;
2031 }
2032
2033 /*
2034  *      For a client, receive a DHCP packet from a raw packet
2035  *      socket. Make sure it matches the ongoing request.
2036  *
2037  *      FIXME: split this into two, recv_raw_packet, and verify(packet, original)
2038  */
2039 RADIUS_PACKET *fr_dhcp_recv_raw_packet(int sockfd, struct sockaddr_ll *p_ll, RADIUS_PACKET *request)
2040 {
2041         VALUE_PAIR              *vp;
2042         RADIUS_PACKET           *packet;
2043         uint8_t                 *code;
2044         uint32_t                magic, xid;
2045         ssize_t                 data_len;
2046
2047         uint8_t                 *raw_packet;
2048         ethernet_header_t       *eth_hdr;
2049         struct ip_header        *ip_hdr;
2050         udp_header_t            *udp_hdr;
2051         dhcp_packet_t           *dhcp_hdr;
2052         uint16_t                udp_src_port;
2053         uint16_t                udp_dst_port;
2054         size_t                  dhcp_data_len;
2055         int                     retval;
2056         socklen_t               sock_len;
2057         fd_set                  read_fd;
2058
2059         packet = rad_alloc(NULL, false);
2060         if (!packet) {
2061                 fr_strerror_printf("Failed allocating packet");
2062                 return NULL;
2063         }
2064
2065         raw_packet = talloc_zero_array(packet, uint8_t, MAX_PACKET_SIZE);
2066         if (!raw_packet) {
2067                 fr_strerror_printf("Out of memory");
2068                 rad_free(&packet);
2069                 return NULL;
2070         }
2071
2072         packet->sockfd = sockfd;
2073
2074         /* a packet was received (but maybe it is not for us) */
2075         sock_len = sizeof(struct sockaddr_ll);
2076         data_len = recvfrom(sockfd, raw_packet, MAX_PACKET_SIZE, 0,
2077                             (struct sockaddr *)p_ll, &sock_len);
2078
2079         uint8_t data_offset = ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE; // DHCP data starts after Ethernet, IP, UDP.
2080
2081         if (data_len <= data_offset) DISCARD_RP("Payload (%d) smaller than required for layers 2+3+4", (int)data_len);
2082
2083         /* map raw packet to packet header of the different layers (Ethernet, IP, UDP) */
2084         eth_hdr = (ethernet_header_t *)raw_packet;
2085
2086         /* a. Check Ethernet layer data (L2) */
2087         if (ntohs(eth_hdr->ether_type) != ETH_TYPE_IP) DISCARD_RP("Ethernet type (%d) != IP", ntohs(eth_hdr->ether_type));
2088
2089         /* If Ethernet destination is not broadcast (ff:ff:ff:ff:ff:ff)
2090          * Check if it matches the source HW address used (DHCP-Client-Hardware-Address = 267)
2091          */
2092         if ( (memcmp(&eth_bcast, &eth_hdr->ether_dst, ETH_ADDR_LEN) != 0) &&
2093                         (vp = pairfind(request->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY)) &&
2094                         (vp->length == sizeof(vp->vp_ether)) &&
2095                         (memcmp(vp->vp_ether, &eth_hdr->ether_dst, ETH_ADDR_LEN) != 0) ) {
2096                 /* No match. */
2097                 char eth_dest[17+1];
2098                 char eth_req_src[17+1];
2099                 DISCARD_RP("Ethernet destination (%s) is not broadcast and doesn't match request source (%s)",
2100                         ether_addr_print(eth_hdr->ether_dst, eth_dest),
2101                         ether_addr_print(vp->vp_ether, eth_req_src));
2102         }
2103
2104         /*
2105          *      Ethernet is OK.  Now look at IP.
2106          */
2107         ip_hdr = (struct ip_header *)(raw_packet + ETH_HDR_SIZE);
2108
2109         /* b. Check IPv4 layer data (L3) */
2110         if (ip_hdr->ip_p != IPPROTO_UDP) DISCARD_RP("IP protocol (%d) != UDP", ip_hdr->ip_p);
2111
2112         /*
2113          *      note: checking the destination IP address is not
2114          *      useful (it would be the offered IP address - which we
2115          *      don't know beforehand, or the broadcast address).
2116          */
2117
2118         /*
2119          *      Now check UDP.
2120          */
2121         udp_hdr = (udp_header_t *)(raw_packet + ETH_HDR_SIZE + IP_HDR_SIZE);
2122
2123         /* c. Check UDP layer data (L4) */
2124         udp_src_port = ntohs(udp_hdr->src);
2125         udp_dst_port = ntohs(udp_hdr->dst);
2126
2127         /*
2128          *      A DHCP server will always respond to port 68 (to a
2129          *      client) or 67 (to a relay).  Just check that both
2130          *      ports are 67 or 68.
2131          */
2132         if (udp_src_port != 67 && udp_src_port != 68) DISCARD_RP("UDP src port (%d) != DHCP (67 or 68)", udp_src_port);
2133         if (udp_dst_port != 67 && udp_dst_port != 68) DISCARD_RP("UDP dst port (%d) != DHCP (67 or 68)", udp_dst_port);
2134
2135         /* d. Check DHCP layer data */
2136         dhcp_data_len = data_len - data_offset;
2137
2138         if (dhcp_data_len < MIN_PACKET_SIZE) DISCARD_RP("DHCP packet is too small (%d < %d)", dhcp_data_len, MIN_PACKET_SIZE);
2139         if (dhcp_data_len > MAX_PACKET_SIZE) DISCARD_RP("DHCP packet is too large (%d > %d)", dhcp_data_len, MAX_PACKET_SIZE);
2140
2141         dhcp_hdr = (dhcp_packet_t *)(raw_packet + ETH_HDR_SIZE + IP_HDR_SIZE + UDP_HDR_SIZE);
2142
2143         if (dhcp_hdr->htype != 1) DISCARD_RP("DHCP hardware type (%d) != Ethernet (1)", dhcp_hdr->htype);
2144         if (dhcp_hdr->hlen != 6) DISCARD_RP("DHCP hardware address length (%d) != 6", dhcp_hdr->hlen);
2145
2146         magic = ntohl(dhcp_hdr->option_format);
2147
2148         if (magic != DHCP_OPTION_MAGIC_NUMBER) DISCARD_RP("DHCP magic cookie (0x%04x) != DHCP (0x%04x)", magic, DHCP_OPTION_MAGIC_NUMBER);
2149
2150         /*
2151          *      Reply transaction id must match value from request.
2152          */
2153         xid = ntohl(dhcp_hdr->xid);
2154         if (xid != (uint32_t)request->id) DISCARD_RP("DHCP transaction ID (0x%04x) != xid from request (0x%04x)", xid, request->id)
2155
2156         /* all checks ok! this is a DHCP reply we're interested in. */
2157         packet->data_len = dhcp_data_len;
2158         packet->data = talloc_memdup(packet, raw_packet + data_offset, dhcp_data_len);
2159         TALLOC_FREE(raw_packet);
2160         packet->id = xid;
2161
2162         code = dhcp_get_option((dhcp_packet_t *) packet->data,
2163                                packet->data_len, 53);
2164         if (!code) {
2165                 fr_strerror_printf("No message-type option was found in the packet");
2166                 rad_free(&packet);
2167                 return NULL;
2168         }
2169
2170         if ((code[1] < 1) || (code[2] == 0) || (code[2] > 8)) {
2171                 fr_strerror_printf("Unknown value for message-type option");
2172                 rad_free(&packet);
2173                 return NULL;
2174         }
2175
2176         packet->code = code[2] | PW_DHCP_OFFSET;
2177
2178         /*
2179          *      Create a unique vector from the MAC address and the
2180          *      DHCP opcode.  This is a hack for the RADIUS
2181          *      infrastructure in the rest of the server.
2182          *
2183          *      Note: packet->data[2] == 6, which is smaller than
2184          *      sizeof(packet->vector)
2185          *
2186          *      FIXME:  Look for client-identifier in packet,
2187          *      and use that, too?
2188          */
2189         memset(packet->vector, 0, sizeof(packet->vector));
2190         memcpy(packet->vector, packet->data + 28, packet->data[2]);
2191         packet->vector[packet->data[2]] = packet->code & 0xff;
2192
2193         packet->src_port = udp_src_port;
2194         packet->dst_port = udp_dst_port;
2195
2196         packet->src_ipaddr.af = AF_INET;
2197         packet->src_ipaddr.ipaddr.ip4addr.s_addr = ip_hdr->ip_src.s_addr;
2198         packet->dst_ipaddr.af = AF_INET;
2199         packet->dst_ipaddr.ipaddr.ip4addr.s_addr = ip_hdr->ip_dst.s_addr;
2200
2201         if (fr_debug_lvl > 1) {
2202                 char type_buf[64];
2203                 char const *name = type_buf;
2204                 char src_ip_buf[256], dst_ip_buf[256];
2205
2206                 if ((packet->code >= PW_DHCP_DISCOVER) &&
2207                     (packet->code <= PW_DHCP_INFORM)) {
2208                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
2209                 } else {
2210                         snprintf(type_buf, sizeof(type_buf), "%d", packet->code - PW_DHCP_OFFSET);
2211                 }
2212
2213                 DEBUG("Received %s of Id %08x from %s:%d to %s:%d\n",
2214                        name, (unsigned int) packet->id,
2215                        inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, src_ip_buf, sizeof(src_ip_buf)),
2216                        packet->src_port,
2217                        inet_ntop(packet->dst_ipaddr.af, &packet->dst_ipaddr.ipaddr, dst_ip_buf, sizeof(dst_ip_buf)),
2218                        packet->dst_port);
2219         }
2220
2221         return packet;
2222 }
2223 #endif