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