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