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