Fix paircursor bugs
[freeradius.git] / src / modules / proto_dhcp / dhcp.c
1 /*
2  * dhcp.c       Functions to send/receive dhcp packets.
3  *
4  * Version:     $Id$
5  *
6  *   This library is free software; you can redistribute it and/or
7  *   modify it under the terms of the GNU Lesser General Public
8  *   License as published by the Free Software Foundation; either
9  *   version 2.1 of the License, or (at your option) any later version.
10  *
11  *   This library is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  *   Lesser General Public License for more details.
15  *
16  *   You should have received a copy of the GNU Lesser General Public
17  *   License along with this library; if not, write to the Free Software
18  *   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  *
20  * Copyright 2008 The FreeRADIUS server project
21  * Copyright 2008 Alan DeKok <aland@deployingradius.com>
22  */
23
24 RCSID("$Id$")
25
26 #include <freeradius-devel/libradius.h>
27 #include <freeradius-devel/udpfromto.h>
28 #include <freeradius-devel/dhcp.h>
29
30 #ifndef __MINGW32__
31 #include <sys/ioctl.h>
32 #endif
33
34 #ifdef HAVE_SYS_SOCKET_H
35 #include <sys/socket.h>
36 #endif
37 #ifdef HAVE_SYS_TYPES_H
38 #include <sys/types.h>
39 #endif
40
41 #ifndef __MINGW32__
42 #include <net/if_arp.h>
43 #endif
44
45 #define DHCP_CHADDR_LEN (16)
46 #define DHCP_SNAME_LEN  (64)
47 #define DHCP_FILE_LEN   (128)
48 #define DHCP_VEND_LEN   (308)
49 #define DHCP_OPTION_MAGIC_NUMBER (0x63825363)
50
51 #ifndef INADDR_BROADCAST
52 #define INADDR_BROADCAST INADDR_NONE
53 #endif
54
55 /* @todo: this is a hack */
56 #  define DEBUG                 if (fr_debug_flag && fr_log_fp) fr_printf_log
57 void fr_strerror_printf(char const *fmt, ...);
58 #  define debug_pair(vp)        do { if (fr_debug_flag && fr_log_fp) { \
59                                         vp_print(fr_log_fp, vp); \
60                                      } \
61                                 } while(0)
62
63 typedef struct dhcp_packet_t {
64         uint8_t         opcode;
65         uint8_t         htype;
66         uint8_t         hlen;
67         uint8_t         hops;
68         uint32_t        xid;    /* 4 */
69         uint16_t        secs;   /* 8 */
70         uint16_t        flags;
71         uint32_t        ciaddr; /* 12 */
72         uint32_t        yiaddr; /* 16 */
73         uint32_t        siaddr; /* 20 */
74         uint32_t        giaddr; /* 24 */
75         uint8_t         chaddr[DHCP_CHADDR_LEN]; /* 28 */
76         uint8_t         sname[DHCP_SNAME_LEN]; /* 44 */
77         uint8_t         file[DHCP_FILE_LEN]; /* 108 */
78         uint32_t        option_format; /* 236 */
79         uint8_t         options[DHCP_VEND_LEN];
80 } dhcp_packet_t;
81
82 typedef struct dhcp_option_t {
83         uint8_t         code;
84         uint8_t         length;
85 } dhcp_option_t;
86
87 /*
88  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        DISCOVER
89  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         OFFER
90  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        REQUEST
91  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         ACK
92  */
93 static char const *dhcp_header_names[] = {
94         "DHCP-Opcode",
95         "DHCP-Hardware-Type",
96         "DHCP-Hardware-Address-Length",
97         "DHCP-Hop-Count",
98         "DHCP-Transaction-Id",
99         "DHCP-Number-of-Seconds",
100         "DHCP-Flags",
101         "DHCP-Client-IP-Address",
102         "DHCP-Your-IP-Address",
103         "DHCP-Server-IP-Address",
104         "DHCP-Gateway-IP-Address",
105         "DHCP-Client-Hardware-Address",
106         "DHCP-Server-Host-Name",
107         "DHCP-Boot-Filename",
108
109         NULL
110 };
111
112 static char const *dhcp_message_types[] = {
113         "invalid",
114         "DHCP-Discover",
115         "DHCP-Offer",
116         "DHCP-Request",
117         "DHCP-Decline",
118         "DHCP-Ack",
119         "DHCP-NAK",
120         "DHCP-Release",
121         "DHCP-Inform",
122         "DHCP-Force-Renew",
123 };
124
125 static int dhcp_header_sizes[] = {
126         1, 1, 1, 1,
127         4, 2, 2, 4,
128         4, 4, 4,
129         DHCP_CHADDR_LEN,
130         DHCP_SNAME_LEN,
131         DHCP_FILE_LEN
132 };
133
134
135 /*
136  *      Some clients silently ignore responses less than 300 bytes.
137  */
138 #define MIN_PACKET_SIZE (244)
139 #define DEFAULT_PACKET_SIZE (300)
140 #define MAX_PACKET_SIZE (1500 - 40)
141
142 #define DHCP_OPTION_FIELD (0)
143 #define DHCP_FILE_FIELD   (1)
144 #define DHCP_SNAME_FIELD  (2)
145
146 static uint8_t *dhcp_get_option(dhcp_packet_t *packet, size_t packet_size,
147                                 unsigned int option)
148 {
149         int overload = 0;
150         int field = DHCP_OPTION_FIELD;
151         size_t where, size;
152         uint8_t *data;
153
154         where = 0;
155         size = packet_size - offsetof(dhcp_packet_t, options);
156         data = &packet->options[where];
157
158         while (where < size) {
159                 if (data[0] == 0) { /* padding */
160                         where++;
161                         continue;
162                 }
163
164                 if (data[0] == 255) { /* end of options */
165                         if ((field == DHCP_OPTION_FIELD) &&
166                             (overload & DHCP_FILE_FIELD)) {
167                                 data = packet->file;
168                                 where = 0;
169                                 size = sizeof(packet->file);
170                                 field = DHCP_FILE_FIELD;
171                                 continue;
172
173                         } else if ((field == DHCP_FILE_FIELD) &&
174                                    (overload & DHCP_SNAME_FIELD)) {
175                                 data = packet->sname;
176                                 where = 0;
177                                 size = sizeof(packet->sname);
178                                 field = DHCP_SNAME_FIELD;
179                                 continue;
180                         }
181
182                         return NULL;
183                 }
184
185                 /*
186                  *      We MUST have a real option here.
187                  */
188                 if ((where + 2) > size) {
189                         fr_strerror_printf("Options overflow field at %u",
190                                            (unsigned int) (data - (uint8_t *) packet));
191                         return NULL;
192                 }
193
194                 if ((where + 2 + data[1]) > size) {
195                         fr_strerror_printf("Option length overflows field at %u",
196                                            (unsigned int) (data - (uint8_t *) packet));
197                         return NULL;
198                 }
199
200                 if (data[0] == option) return data;
201
202                 if (data[0] == 52) { /* overload sname and/or file */
203                         overload = data[3];
204                 }
205
206                 where += data[1] + 2;
207                 data += data[1] + 2;
208         }
209
210         return NULL;
211 }
212
213 /*
214  *      DHCPv4 is only for IPv4.  Broadcast only works if udpfromto is
215  *      defined.
216  */
217 RADIUS_PACKET *fr_dhcp_recv(int sockfd)
218 {
219         uint32_t                magic;
220         struct sockaddr_storage src;
221         struct sockaddr_storage dst;
222         socklen_t               sizeof_src;
223         socklen_t               sizeof_dst;
224         RADIUS_PACKET           *packet;
225         int port;
226         uint8_t                 *code;
227
228         packet = rad_alloc(NULL, 0);
229         if (!packet) {
230                 fr_strerror_printf("Failed allocating packet");
231                 return NULL;
232         }
233
234         packet->data = talloc_zero_array(packet, uint8_t, MAX_PACKET_SIZE);
235         if (!packet->data) {
236                 fr_strerror_printf("Out of memory");
237                 rad_free(&packet);
238                 return NULL;
239         }
240
241         packet->sockfd = sockfd;
242         sizeof_src = sizeof(src);
243 #ifdef WITH_UDPFROMTO
244         sizeof_dst = sizeof(dst);
245         packet->data_len = recvfromto(sockfd, packet->data, MAX_PACKET_SIZE, 0,
246                                       (struct sockaddr *)&src, &sizeof_src,
247                                       (struct sockaddr *)&dst, &sizeof_dst);
248 #else
249         packet->data_len = recvfrom(sockfd, packet->data, MAX_PACKET_SIZE, 0,
250                                     (struct sockaddr *)&src, &sizeof_src);
251 #endif
252
253         if (packet->data_len <= 0) {
254                 fr_strerror_printf("Failed reading DHCP socket: %s", strerror(errno));
255                 rad_free(&packet);
256                 return NULL;
257         }
258
259         if (packet->data_len < MIN_PACKET_SIZE) {
260                 fr_strerror_printf("DHCP packet is too small (%zu < %d)",
261                                    packet->data_len, MIN_PACKET_SIZE);
262                 rad_free(&packet);
263                 return NULL;
264         }
265
266         if (packet->data[1] != 1) {
267                 fr_strerror_printf("DHCP can only receive ethernet requests, not type %02x",
268                       packet->data[1]);
269                 rad_free(&packet);
270                 return NULL;
271         }
272
273         if (packet->data[2] != 6) {
274                 fr_strerror_printf("Ethernet HW length is wrong length %d",
275                         packet->data[2]);
276                 rad_free(&packet);
277                 return NULL;
278         }
279
280         memcpy(&magic, packet->data + 236, 4);
281         magic = ntohl(magic);
282         if (magic != DHCP_OPTION_MAGIC_NUMBER) {
283                 fr_strerror_printf("Cannot do BOOTP");
284                 rad_free(&packet);
285                 return NULL;
286         }
287
288         /*
289          *      Create unique keys for the packet.
290          */
291         memcpy(&magic, packet->data + 4, 4);
292         packet->id = ntohl(magic);
293
294         code = dhcp_get_option((dhcp_packet_t *) packet->data,
295                                packet->data_len, 53);
296         if (!code) {
297                 fr_strerror_printf("No message-type option was found in the packet");
298                 rad_free(&packet);
299                 return NULL;
300         }
301
302         if ((code[1] < 1) || (code[2] == 0) || (code[2] > 8)) {
303                 fr_strerror_printf("Unknown value for message-type option");
304                 rad_free(&packet);
305                 return NULL;
306         }
307
308         packet->code = code[2] | PW_DHCP_OFFSET;
309
310         /*
311          *      Create a unique vector from the MAC address and the
312          *      DHCP opcode.  This is a hack for the RADIUS
313          *      infrastructure in the rest of the server.
314          *
315          *      Note: packet->data[2] == 6, which is smaller than
316          *      sizeof(packet->vector)
317          *
318          *      FIXME:  Look for client-identifier in packet,
319          *      and use that, too?
320          */
321         memset(packet->vector, 0, sizeof(packet->vector));
322         memcpy(packet->vector, packet->data + 28, packet->data[2]);
323         packet->vector[packet->data[2]] = packet->code & 0xff;
324
325         /*
326          *      FIXME: for DISCOVER / REQUEST: src_port == dst_port + 1
327          *      FIXME: for OFFER / ACK       : src_port = dst_port - 1
328          */
329
330         /*
331          *      Unique keys are xid, client mac, and client ID?
332          */
333
334         /*
335          *      FIXME: More checks, like DHCP packet type?
336          */
337
338         sizeof_dst = sizeof(dst);
339
340 #ifndef WITH_UDPFROMTO
341         /*
342          *      This should never fail...
343          */
344         if (getsockname(sockfd, (struct sockaddr *) &dst, &sizeof_dst) < 0) {
345                 fr_strerror_printf("getsockname failed: %s", strerror(errno));
346                 rad_free(&packet);
347                 return NULL;
348         }
349 #endif
350
351         fr_sockaddr2ipaddr(&dst, sizeof_dst, &packet->dst_ipaddr, &port);
352         packet->dst_port = port;
353
354         fr_sockaddr2ipaddr(&src, sizeof_src, &packet->src_ipaddr, &port);
355         packet->src_port = port;
356
357         if (fr_debug_flag > 1) {
358                 char type_buf[64];
359                 char const *name = type_buf;
360                 char src_ip_buf[256], dst_ip_buf[256];
361
362                 if ((packet->code >= PW_DHCP_DISCOVER) &&
363                     (packet->code <= PW_DHCP_INFORM)) {
364                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
365                 } else {
366                         snprintf(type_buf, sizeof(type_buf), "%d",
367                                  packet->code - PW_DHCP_OFFSET);
368                 }
369
370                 DEBUG("Received %s of id %08x from %s:%d to %s:%d\n",
371                        name, (unsigned int) packet->id,
372                        inet_ntop(packet->src_ipaddr.af,
373                                  &packet->src_ipaddr.ipaddr,
374                                  src_ip_buf, sizeof(src_ip_buf)),
375                        packet->src_port,
376                        inet_ntop(packet->dst_ipaddr.af,
377                                  &packet->dst_ipaddr.ipaddr,
378                                  dst_ip_buf, sizeof(dst_ip_buf)),
379                        packet->dst_port);
380         }
381
382         return packet;
383 }
384
385
386 /*
387  *      Send a DHCP packet.
388  */
389 int fr_dhcp_send(RADIUS_PACKET *packet)
390 {
391         struct sockaddr_storage dst;
392         socklen_t               sizeof_dst;
393 #ifdef WITH_UDPFROMTO
394         struct sockaddr_storage src;
395         socklen_t               sizeof_src;
396
397         fr_ipaddr2sockaddr(&packet->src_ipaddr, packet->src_port,
398             &src, &sizeof_src);
399 #endif
400
401         fr_ipaddr2sockaddr(&packet->dst_ipaddr, packet->dst_port,
402                            &dst, &sizeof_dst);
403
404         if (fr_debug_flag > 1) {
405                 char type_buf[64];
406                 char const *name = type_buf;
407 #ifdef WITH_UDPFROMTO
408                 char src_ip_buf[INET6_ADDRSTRLEN];
409 #endif
410                 char dst_ip_buf[INET6_ADDRSTRLEN];
411
412                 if ((packet->code >= PW_DHCP_DISCOVER) &&
413                     (packet->code <= PW_DHCP_INFORM)) {
414                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
415                 } else {
416                         snprintf(type_buf, sizeof(type_buf), "%d",
417                             packet->code - PW_DHCP_OFFSET);
418                 }
419
420                 DEBUG(
421 #ifdef WITH_UDPFROMTO
422                 "Sending %s of id %08x from %s:%d to %s:%d\n",
423 #else
424                 "Sending %s of id %08x to %s:%d\n",
425 #endif
426                    name, (unsigned int) packet->id,
427 #ifdef WITH_UDPFROMTO
428                    inet_ntop(packet->src_ipaddr.af, &packet->src_ipaddr.ipaddr, src_ip_buf, sizeof(src_ip_buf)),
429                    packet->src_port,
430 #endif
431                    inet_ntop(packet->dst_ipaddr.af, &packet->dst_ipaddr.ipaddr, dst_ip_buf, sizeof(dst_ip_buf)),
432                    packet->dst_port);
433         }
434
435 #ifndef WITH_UDPFROMTO
436         /*
437          *      Assume that the packet is encoded before sending it.
438          */
439         return sendto(packet->sockfd, packet->data, packet->data_len, 0,
440                       (struct sockaddr *)&dst, sizeof_dst);
441 #else
442
443         return sendfromto(packet->sockfd, packet->data, packet->data_len, 0,
444                           (struct sockaddr *)&src, sizeof_src,
445                           (struct sockaddr *)&dst, sizeof_dst);
446 #endif
447 }
448
449 static int fr_dhcp_attr2vp(RADIUS_PACKET *packet, VALUE_PAIR *vp, uint8_t const *p, size_t alen);
450
451 static int decode_tlv(RADIUS_PACKET *packet, VALUE_PAIR *tlv, uint8_t const *data, size_t data_len)
452 {
453         uint8_t const *p;
454         VALUE_PAIR *head, *vp;
455         vp_cursor_t cursor;
456
457         /*
458          *      Take a pass at parsing it.
459          */
460         p = data;
461         while (p < (data + data_len)) {
462                 if ((p + 2) > (data + data_len)) goto make_tlv;
463
464                 if ((p + p[1] + 2) > (data + data_len)) goto make_tlv;
465                 p += 2 + p[1];
466         }
467
468         /*
469          *      Got here... must be well formed.
470          */
471         head = NULL;
472         paircursor(&cursor, &head);
473
474         p = data;
475         while (p < (data + data_len)) {
476                 vp = paircreate(packet, tlv->da->attr | (p[0] << 8), DHCP_MAGIC_VENDOR);
477                 if (!vp) {
478                         pairfree(&head);
479                         goto make_tlv;
480                 }
481
482                 if (fr_dhcp_attr2vp(packet, vp, p + 2, p[1]) < 0) {
483                         pairfree(&head);
484                         goto make_tlv;
485                 }
486
487                 pairinsert(&cursor, vp);
488                 p += 2 + p[1];
489         }
490
491         /*
492          *      The caller allocated TLV, so we need to copy the FIRST
493          *      attribute over top of that.
494          */
495         if (head) {
496                 memcpy(tlv, head, sizeof(*tlv));
497                 head->next = NULL;
498                 pairfree(&head);
499         }
500
501         return 0;
502
503 make_tlv:
504         tlv->vp_tlv = talloc_array(tlv, uint8_t, data_len);
505         if (!tlv->vp_tlv) {
506                 fr_strerror_printf("No memory");
507                 return -1;
508         }
509         memcpy(tlv->vp_tlv, data, data_len);
510         tlv->length = data_len;
511
512         return 0;
513 }
514
515
516 /*
517  *      Decode ONE value into a VP
518  */
519 static int fr_dhcp_attr2vp(RADIUS_PACKET *packet, VALUE_PAIR *vp, uint8_t const *p, size_t alen)
520 {
521         char *q;
522
523         switch (vp->da->type) {
524         case PW_TYPE_BYTE:
525                 if (alen != 1) goto raw;
526                 vp->vp_integer = p[0];
527                 break;
528
529         case PW_TYPE_SHORT:
530                 if (alen != 2) goto raw;
531                 memcpy(&vp->vp_integer, p, 2);
532                 vp->vp_integer = ntohs(vp->vp_integer);
533                 break;
534
535         case PW_TYPE_INTEGER:
536                 if (alen != 4) goto raw;
537                 memcpy(&vp->vp_integer, p, 4);
538                 vp->vp_integer = ntohl(vp->vp_integer);
539                 break;
540
541         case PW_TYPE_IPADDR:
542                 if (alen != 4) goto raw;
543                 /*
544                  *      Keep value in Network Order!
545                  */
546                 memcpy(&vp->vp_ipaddr, p , 4);
547                 vp->length = 4;
548                 break;
549
550         case PW_TYPE_STRING:
551                 vp->vp_strvalue = q = talloc_array(vp, char, alen + 1);
552                 vp->type = VT_DATA;
553                 memcpy(q, p , alen);
554                 q[alen] = '\0';
555                 break;
556
557         case PW_TYPE_ETHERNET:
558                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
559                 vp->length = sizeof(vp->vp_ether);
560                 break;
561
562         /*
563          *      Value doesn't match up with attribute type, overwrite the
564          *      vp's original DICT_ATTR with an unknown one.
565          */
566         raw:
567                 if (pair2unknown(vp) < 0) return -1;
568
569         case PW_TYPE_OCTETS:
570                 if (alen > 253) return -1;
571                 pairmemcpy(vp, p, alen);
572                 break;
573
574         case PW_TYPE_TLV:
575                 return decode_tlv(packet, vp, p, alen);
576
577         default:
578                 fr_strerror_printf("Internal sanity check %d %d", vp->da->type, __LINE__);
579                 return -1;
580         } /* switch over type */
581
582         vp->length = alen;
583         return 0;
584 }
585
586 ssize_t fr_dhcp_decode_options(RADIUS_PACKET *packet,
587                                uint8_t const *data, size_t len, VALUE_PAIR **head)
588 {
589         int i;
590         VALUE_PAIR *vp;
591         vp_cursor_t cursor;
592         uint8_t const *p, *next;
593         next = data;
594
595         *head = NULL;
596         paircursor(&cursor, head);
597
598         /*
599          *      FIXME: This should also check sname && file fields.
600          *      See the dhcp_get_option() function above.
601          */
602         while (next < (data + len)) {
603                 int num_entries, alen;
604                 DICT_ATTR const *da;
605
606                 p = next;
607
608                 if (*p == 0) break;
609                 if (*p == 255) break; /* end of options signifier */
610                 if ((p + 2) > (data + len)) break;
611
612                 next = p + 2 + p[1];
613
614                 if (p[1] >= 253) {
615                         fr_strerror_printf("Attribute too long %u %u",
616                                            p[0], p[1]);
617                         continue;
618                 }
619
620                 da = dict_attrbyvalue(p[0], DHCP_MAGIC_VENDOR);
621                 if (!da) {
622                         fr_strerror_printf("Attribute not in our dictionary: %u",
623                                            p[0]);
624                         continue;
625                 }
626
627                 vp = NULL;
628                 num_entries = 1;
629                 alen = p[1];
630                 p += 2;
631
632                 /*
633                  *      Could be an array of bytes, integers, etc.
634                  */
635                 if (da->flags.array) {
636                         switch (da->type) {
637                         case PW_TYPE_BYTE:
638                                 num_entries = alen;
639                                 alen = 1;
640                                 break;
641
642                         case PW_TYPE_SHORT: /* ignore any trailing data */
643                                 num_entries = alen >> 1;
644                                 alen = 2;
645                                 break;
646
647                         case PW_TYPE_IPADDR:
648                         case PW_TYPE_INTEGER:
649                         case PW_TYPE_DATE: /* ignore any trailing data */
650                                 num_entries = alen >> 2;
651                                 alen = 4;
652                                 break;
653
654                         default:
655
656                                 break; /* really an internal sanity failure */
657                         }
658                 }
659
660                 /*
661                  *      Loop over all of the entries, building VPs
662                  */
663                 for (i = 0; i < num_entries; i++) {
664                         vp = pairmake(packet, NULL, da->name, NULL, T_OP_ADD);
665                         if (!vp) {
666                                 fr_strerror_printf("Cannot build attribute %s",
667                                         fr_strerror());
668                                 pairfree(head);
669                                 return -1;
670                         }
671
672                         /*
673                          *      Hack for ease of use.
674                          */
675                         if ((da->vendor == DHCP_MAGIC_VENDOR) &&
676                             (da->attr == 61) && !da->flags.array &&
677                             (alen == 7) && (*p == 1) && (num_entries == 1)) {
678                                 pairmemcpy(vp, p + 1, 6);
679
680                         } else if (fr_dhcp_attr2vp(packet, vp, p, alen) < 0) {
681                                 pairfree(&vp);
682                                 pairfree(head);
683                                 return -1;
684                         }
685
686                         pairinsert(&cursor, vp);
687
688                         for (vp = paircurrent(&cursor);
689                              vp;
690                              vp = pairnext(&cursor)) {
691                                 debug_pair(vp);
692                         }
693                         p += alen;
694                 } /* loop over array entries */
695         } /* loop over the entire packet */
696
697         return next - data;
698 }
699
700 int fr_dhcp_decode(RADIUS_PACKET *packet)
701 {
702         size_t i;
703         uint8_t *p;
704         uint32_t giaddr;
705         vp_cursor_t cursor;
706         VALUE_PAIR *head = NULL, *vp;
707         VALUE_PAIR *maxms, *mtu;
708
709         paircursor(&cursor, &head);
710         p = packet->data;
711
712         if ((fr_debug_flag > 2) && fr_log_fp) {
713                 for (i = 0; i < packet->data_len; i++) {
714                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
715                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
716                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
717                 }
718                 fprintf(fr_log_fp, "\n");
719         }
720
721         if (packet->data[1] != 1) {
722                 fr_strerror_printf("Packet is not Ethernet: %u",
723                       packet->data[1]);
724                 return -1;
725         }
726
727         /*
728          *      Decode the header.
729          */
730         for (i = 0; i < 14; i++) {
731                 char *q;
732
733                 vp = pairmake(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
734                 if (!vp) {
735                         char buffer[256];
736                         strlcpy(buffer, fr_strerror(), sizeof(buffer));
737                         fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
738                         pairfree(&head);
739                         return -1;
740                 }
741
742                 /*
743                  *      If chaddr does != 6 bytes it's probably not ethernet, and we should store
744                  *      it as an opaque type (octets).
745                  */
746                 if ((i == 11) && (packet->data[1] == 1) && (packet->data[2] != sizeof(vp->vp_ether))) {
747                         DICT_ATTR const *da = dict_attrunknown(vp->da->attr, vp->da->vendor, true);
748                         if (!da) {
749                                 return -1;
750                         }
751                         vp->da = da;
752                 }
753
754                 switch (vp->da->type) {
755                 case PW_TYPE_BYTE:
756                         vp->vp_integer = p[0];
757                         vp->length = 1;
758                         break;
759
760                 case PW_TYPE_SHORT:
761                         vp->vp_integer = (p[0] << 8) | p[1];
762                         vp->length = 2;
763                         break;
764
765                 case PW_TYPE_INTEGER:
766                         memcpy(&vp->vp_integer, p, 4);
767                         vp->vp_integer = ntohl(vp->vp_integer);
768                         vp->length = 4;
769                         break;
770
771                 case PW_TYPE_IPADDR:
772                         memcpy(&vp->vp_ipaddr, p, 4);
773                         vp->length = 4;
774                         break;
775
776                 case PW_TYPE_STRING:
777                         vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
778                         vp->type = VT_DATA;
779                         memcpy(q, p, dhcp_header_sizes[i]);
780                         q[dhcp_header_sizes[i]] = '\0';
781                         vp->length = strlen(vp->vp_strvalue);
782                         if (vp->length == 0) {
783                                 pairfree(&vp);
784                         }
785                         break;
786
787                 case PW_TYPE_OCTETS:
788                         pairmemcpy(vp, p, packet->data[2]);
789                         break;
790
791                 case PW_TYPE_ETHERNET:
792                         memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
793                         vp->length = sizeof(vp->vp_ether);
794                         break;
795
796                 default:
797                         fr_strerror_printf("BAD TYPE %d", vp->da->type);
798                         pairfree(&vp);
799                         break;
800                 }
801                 p += dhcp_header_sizes[i];
802
803                 if (!vp) continue;
804
805                 debug_pair(vp);
806                 pairinsert(&cursor, vp);
807         }
808
809         /*
810          *      Loop over the options.
811          */
812
813         /*
814          *      Nothing uses tail after this call, if it does in the future
815          *      it'll need to find the new tail...
816          */
817         {
818                 VALUE_PAIR *options = NULL;
819
820                 if (fr_dhcp_decode_options(packet,
821                                            packet->data + 240, packet->data_len - 240,
822                                            &options) < 0) {
823                         return -1;
824                 }
825
826                 if (options) {
827                         pairinsert(&cursor, options);
828                 }
829         }
830
831         /*
832          *      If DHCP request, set ciaddr to zero.
833          */
834
835         /*
836          *      Set broadcast flag for broken vendors, but only if
837          *      giaddr isn't set.
838          */
839         memcpy(&giaddr, packet->data + 24, sizeof(giaddr));
840         if (giaddr == htonl(INADDR_ANY)) {
841                 /*
842                  *      DHCP Opcode is request
843                  */
844                 vp = pairfind(head, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
845                 if (vp && vp->vp_integer == 3) {
846                         /*
847                          *      Vendor is "MSFT 98"
848                          */
849                         vp = pairfind(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
850                         if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
851                                 vp = pairfind(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
852
853                                 /*
854                                  *      Reply should be broadcast.
855                                  */
856                                 if (vp) vp->vp_integer |= 0x8000;
857                                 packet->data[10] |= 0x80;
858                         }
859                 }
860         }
861
862         /*
863          *      FIXME: Nuke attributes that aren't used in the normal
864          *      header for discover/requests.
865          */
866         packet->vps = head;
867
868         /*
869          *      Client can request a LARGER size, but not a smaller
870          *      one.  They also cannot request a size larger than MTU.
871          */
872         maxms = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
873         mtu = pairfind(packet->vps, 26, DHCP_MAGIC_VENDOR, TAG_ANY);
874
875         if (mtu && (mtu->vp_integer < DEFAULT_PACKET_SIZE)) {
876                 fr_strerror_printf("DHCP Fatal: Client says MTU is smaller than minimum permitted by the specification.");
877                 return -1;
878         }
879
880         if (maxms && (maxms->vp_integer < DEFAULT_PACKET_SIZE)) {
881                 fr_strerror_printf("DHCP WARNING: Client says maximum message size is smaller than minimum permitted by the specification: fixing it");
882                 maxms->vp_integer = DEFAULT_PACKET_SIZE;
883         }
884
885         if (maxms && mtu && (maxms->vp_integer > mtu->vp_integer)) {
886                 fr_strerror_printf("DHCP WARNING: Client says MTU is smaller than maximum message size: fixing it");
887                 maxms->vp_integer = mtu->vp_integer;
888         }
889
890         if (fr_debug_flag) fflush(stdout);
891
892         return 0;
893 }
894
895
896 static int attr_cmp(void const *one, void const *two)
897 {
898         VALUE_PAIR const * const *a = one;
899         VALUE_PAIR const * const *b = two;
900
901         /*
902          *      DHCP-Message-Type is first, for simplicity.
903          */
904         if (((*a)->da->attr == 53) &&
905             (*b)->da->attr != 53) return -1;
906
907         /*
908          *      Relay-Agent is last
909          */
910         if (((*a)->da->attr == 82) &&
911             (*b)->da->attr != 82) return 1;
912
913         return ((*a)->da->attr - (*b)->da->attr);
914 }
915
916 /*
917  * @todo Check room!
918  */
919 static size_t fr_dhcp_vp2attr(VALUE_PAIR *vp, uint8_t *p, UNUSED size_t room)
920 {
921         size_t length;
922         uint32_t lvalue;
923
924         /*
925          *      Search for all attributes of the same
926          *      type, and pack them into the same
927          *      attribute.
928          */
929         switch (vp->da->type) {
930         case PW_TYPE_BYTE:
931                 length = 1;
932                 *p = vp->vp_integer & 0xff;
933                 break;
934
935         case PW_TYPE_SHORT:
936                 length = 2;
937                 p[0] = (vp->vp_integer >> 8) & 0xff;
938                 p[1] = vp->vp_integer & 0xff;
939                 break;
940
941         case PW_TYPE_INTEGER:
942                 length = 4;
943                 lvalue = htonl(vp->vp_integer);
944                 memcpy(p, &lvalue, 4);
945                 break;
946
947         case PW_TYPE_IPADDR:
948                 length = 4;
949                 memcpy(p, &vp->vp_ipaddr, 4);
950                 break;
951
952         case PW_TYPE_ETHERNET:
953                 length = 6;
954                 memcpy(p, &vp->vp_ether, 6);
955                 break;
956
957         case PW_TYPE_STRING:
958                 memcpy(p, vp->vp_strvalue, vp->length);
959                 length = vp->length;
960                 break;
961
962         case PW_TYPE_TLV:       /* FIXME: split it on 255? */
963                 memcpy(p, vp->vp_tlv, vp->length);
964                 length = vp->length;
965                 break;
966
967         case PW_TYPE_OCTETS:
968                 memcpy(p, vp->vp_octets, vp->length);
969                 length = vp->length;
970                 break;
971
972         default:
973                 fr_strerror_printf("BAD TYPE2 %d", vp->da->type);
974                 length = 0;
975                 break;
976         }
977
978         return length;
979 }
980
981 static VALUE_PAIR *fr_dhcp_vp2suboption(RADIUS_PACKET *packet, VALUE_PAIR *vps)
982 {
983         int length;
984         unsigned int attribute;
985         uint8_t *ptr;
986         vp_cursor_t cursor;
987         VALUE_PAIR *vp, *tlv;
988
989         attribute = vps->da->attr & 0xffff00ff;
990
991         tlv = paircreate(packet, attribute, DHCP_MAGIC_VENDOR);
992         if (!tlv) return NULL;
993
994         tlv->length = 0;
995         for (vp = paircursor(&cursor, &vps);
996              vp;
997              vp = pairnext(&cursor)) {
998                 /*
999                  *      Group the attributes ONLY until we see a
1000                  *      non-TLV attribute.
1001                  */
1002                 if (!vp->da->flags.is_tlv ||
1003                     vp->da->flags.extended ||
1004                     ((vp->da->attr & 0xffff00ff) != attribute)) {
1005                         break;
1006                 }
1007
1008                 tlv->length += vp->length + 2;
1009         }
1010
1011         if (!tlv->length) {
1012                 pairfree(&tlv);
1013                 return NULL;
1014         }
1015
1016         tlv->vp_tlv = talloc_array(tlv, uint8_t, tlv->length);
1017         if (!tlv->vp_tlv) {
1018                 pairfree(&tlv);
1019                 return NULL;
1020         }
1021
1022         ptr = tlv->vp_tlv;
1023         for (vp = paircursor(&cursor, &vps);
1024              vp;
1025              vp = pairnext(&cursor)) {
1026                 if (!vp->da->flags.is_tlv ||
1027                     vp->da->flags.extended ||
1028                     ((vp->da->attr & 0xffff00ff) != attribute)) {
1029                         break;
1030                 }
1031
1032                 length = fr_dhcp_vp2attr(vp, ptr + 2,
1033                                          tlv->vp_tlv + tlv->length - ptr);
1034                 if (length > 255) {
1035                         pairfree(&tlv);
1036                         return NULL;
1037                 }
1038
1039                 /*
1040                  *      Pack the attribute.
1041                  */
1042                 ptr[0] = (vp->da->attr & 0xff00) >> 8;
1043                 ptr[1] = length;
1044
1045                 ptr += length + 2;
1046         }
1047
1048         return tlv;
1049 }
1050
1051
1052 int fr_dhcp_encode(RADIUS_PACKET *packet)
1053 {
1054         unsigned int i, num_vps;
1055         uint8_t *p;
1056         vp_cursor_t cursor;
1057         VALUE_PAIR *vp;
1058         uint32_t lvalue;
1059         size_t dhcp_size, length;
1060 #ifndef NDEBUG
1061         char const *name;
1062 #  ifdef WITH_UDPFROMTO
1063         char src_ip_buf[256];
1064 #  endif
1065         char dst_ip_buf[256];
1066 #endif
1067
1068         if (packet->data) return 0;
1069
1070         packet->data_len = MAX_PACKET_SIZE;
1071         packet->data = talloc_zero_array(packet, uint8_t, packet->data_len);
1072
1073         /* XXX Ugly ... should be set by the caller */
1074         if (packet->code == 0) packet->code = PW_DHCP_NAK;
1075
1076 #ifndef NDEBUG
1077         if ((packet->code >= PW_DHCP_DISCOVER) &&
1078             (packet->code <= PW_DHCP_INFORM)) {
1079                 name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
1080         } else {
1081                 name = "?Unknown?";
1082         }
1083
1084         DEBUG(
1085 #ifdef WITH_UDPFROMTO
1086               "Encoding %s of id %08x from %s:%d to %s:%d\n",
1087 #else
1088               "Encoding %s of id %08x to %s:%d\n",
1089 #endif
1090               name, (unsigned int) packet->id,
1091 #ifdef WITH_UDPFROMTO
1092               inet_ntop(packet->src_ipaddr.af,
1093                         &packet->src_ipaddr.ipaddr,
1094                         src_ip_buf, sizeof(src_ip_buf)),
1095               packet->src_port,
1096 #endif
1097               inet_ntop(packet->dst_ipaddr.af,
1098                         &packet->dst_ipaddr.ipaddr,
1099                      dst_ip_buf, sizeof(dst_ip_buf)),
1100               packet->dst_port);
1101 #endif
1102
1103         p = packet->data;
1104
1105         /*
1106          *      @todo: Make this work again.
1107          */
1108 #if 0
1109         mms = DEFAULT_PACKET_SIZE; /* maximum message size */
1110
1111         /*
1112          *      Clients can request a LARGER size, but not a
1113          *      smaller one.  They also cannot request a size
1114          *      larger than MTU.
1115          */
1116
1117         /* DHCP-DHCP-Maximum-Msg-Size */
1118         vp = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1119         if (vp && (vp->vp_integer > mms)) {
1120                 mms = vp->vp_integer;
1121
1122                 if (mms > MAX_PACKET_SIZE) mms = MAX_PACKET_SIZE;
1123         }
1124 #endif
1125
1126         vp = pairfind(packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1127         if (vp) {
1128                 *p++ = vp->vp_integer & 0xff;
1129         } else {
1130                 *p++ = 1;       /* client message */
1131         }
1132
1133         /* DHCP-Hardware-Type */
1134         if ((vp = pairfind(packet->vps, 257, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1135                 *p++ = vp->vp_integer & 0xFF;
1136         } else {
1137                 *p++ = 1;               /* hardware type = ethernet */
1138         }
1139
1140         /* DHCP-Hardware-Address-Length */
1141         if ((vp = pairfind(packet->vps, 258, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1142                 *p++ = vp->vp_integer & 0xFF;
1143         } else {
1144                 *p++ = 6;               /* 6 bytes of ethernet */
1145         }
1146
1147         /* DHCP-Hop-Count */
1148         if ((vp = pairfind(packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1149                 *p = vp->vp_integer & 0xff;
1150         }
1151         p++;
1152
1153         /* DHCP-Transaction-Id */
1154         if ((vp = pairfind(packet->vps, 260, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1155                 lvalue = htonl(vp->vp_integer);
1156         } else {
1157                 lvalue = fr_rand();
1158         }
1159         memcpy(p, &lvalue, 4);
1160         p += 4;
1161
1162         /* DHCP-Number-of-Seconds */
1163         if ((vp = pairfind(packet->vps, 261, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1164                 lvalue = htonl(vp->vp_integer);
1165                 memcpy(p, &lvalue, 2);
1166         }
1167         p += 2;
1168
1169         /* DHCP-Flags */
1170         if ((vp = pairfind(packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1171                 lvalue = htons(vp->vp_integer);
1172                 memcpy(p, &lvalue, 2);
1173         }
1174         p += 2;
1175
1176         /* DHCP-Client-IP-Address */
1177         if ((vp = pairfind(packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1178                 memcpy(p, &vp->vp_ipaddr, 4);
1179         }
1180         p += 4;
1181
1182         /* DHCP-Your-IP-address */
1183         if ((vp = pairfind(packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1184                 lvalue = vp->vp_ipaddr;
1185         } else {
1186                 lvalue = htonl(INADDR_ANY);
1187         }
1188         memcpy(p, &lvalue, 4);
1189         p += 4;
1190
1191         /* DHCP-Server-IP-Address */
1192         vp = pairfind(packet->vps, 265, DHCP_MAGIC_VENDOR, TAG_ANY);
1193
1194         /* DHCP-DHCP-Server-Identifier */
1195         if (!vp && (vp = pairfind(packet->vps, 54, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1196                 lvalue = vp->vp_ipaddr;
1197         } else {
1198                 lvalue = htonl(INADDR_ANY);
1199         }
1200         memcpy(p, &lvalue, 4);
1201         p += 4;
1202
1203         /*
1204          *      DHCP-Gateway-IP-Address
1205          */
1206         if ((vp = pairfind(packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1207                 lvalue = vp->vp_ipaddr;
1208         } else {
1209                 lvalue = htonl(INADDR_ANY);
1210         }
1211         memcpy(p, &lvalue, 4);
1212         p += 4;
1213
1214         /* DHCP-Client-Hardware-Address */
1215         if ((vp = pairfind(packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1216                 if (vp->length > DHCP_CHADDR_LEN) {
1217                         memcpy(p, vp->vp_octets, DHCP_CHADDR_LEN);
1218                 } else {
1219                         memcpy(p, vp->vp_octets, vp->length);
1220                 }
1221         }
1222         p += DHCP_CHADDR_LEN;
1223
1224         /* DHCP-Server-Host-Name */
1225         if ((vp = pairfind(packet->vps, 268, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1226                 if (vp->length > DHCP_SNAME_LEN) {
1227                         memcpy(p, vp->vp_strvalue, DHCP_SNAME_LEN);
1228                 } else {
1229                         memcpy(p, vp->vp_strvalue, vp->length);
1230                 }
1231         }
1232         p += DHCP_SNAME_LEN;
1233
1234         /*
1235          *      Copy over DHCP-Boot-Filename.
1236          *
1237          *      FIXME: This copy should be delayed until AFTER the options
1238          *      have been processed.  If there are too many options for
1239          *      the packet, then they go into the sname && filename fields.
1240          *      When that happens, the boot filename is passed as an option,
1241          *      instead of being placed verbatim in the filename field.
1242          */
1243
1244         /* DHCP-Boot-Filename */
1245         if ((vp = pairfind(packet->vps, 269, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1246                 if (vp->length > DHCP_FILE_LEN) {
1247                         memcpy(p, vp->vp_strvalue, DHCP_FILE_LEN);
1248                 } else {
1249                         memcpy(p, vp->vp_strvalue, vp->length);
1250                 }
1251         }
1252         p += DHCP_FILE_LEN;
1253
1254         /* DHCP magic number */
1255         lvalue = htonl(DHCP_OPTION_MAGIC_NUMBER);
1256         memcpy(p, &lvalue, 4);
1257         p += 4;
1258
1259         /*
1260          *      Print the header.
1261          */
1262         if (fr_debug_flag > 1) {
1263                 uint8_t *pp = p;
1264
1265                 p = packet->data;
1266
1267                 for (i = 0; i < 14; i++) {
1268                         char *q;
1269
1270                         vp = pairmake(packet, NULL,
1271                                       dhcp_header_names[i], NULL, T_OP_EQ);
1272                         if (!vp) {
1273                                 char buffer[256];
1274                                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1275                                 fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1276                                 return -1;
1277                         }
1278
1279                         switch (vp->da->type) {
1280                         case PW_TYPE_BYTE:
1281                                 vp->vp_integer = p[0];
1282                                 vp->length = 1;
1283                                 break;
1284
1285                         case PW_TYPE_SHORT:
1286                                 vp->vp_integer = (p[0] << 8) | p[1];
1287                                 vp->length = 2;
1288                                 break;
1289
1290                         case PW_TYPE_INTEGER:
1291                                 memcpy(&vp->vp_integer, p, 4);
1292                                 vp->vp_integer = ntohl(vp->vp_integer);
1293                                 vp->length = 4;
1294                                 break;
1295
1296                         case PW_TYPE_IPADDR:
1297                                 memcpy(&vp->vp_ipaddr, p, 4);
1298                                 vp->length = 4;
1299                                 break;
1300
1301                         case PW_TYPE_STRING:
1302                                 vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i]);
1303                                 vp->type = VT_DATA;
1304                                 memcpy(q, p, dhcp_header_sizes[i]);
1305                                 q[dhcp_header_sizes[i]] = '\0';
1306                                 vp->length = strlen(vp->vp_strvalue);
1307                                 break;
1308
1309                         case PW_TYPE_OCTETS: /* only for Client HW Address */
1310                                 pairmemcpy(vp, p, packet->data[2]);
1311                                 break;
1312
1313                         case PW_TYPE_ETHERNET: /* only for Client HW Address */
1314                                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1315                                 vp->length = sizeof(vp->vp_ether);
1316                                 break;
1317
1318                         default:
1319                                 fr_strerror_printf("Internal sanity check failed %d %d", vp->da->type, __LINE__);
1320                                 pairfree(&vp);
1321                                 break;
1322                         }
1323
1324                         p += dhcp_header_sizes[i];
1325
1326                         debug_pair(vp);
1327                         pairfree(&vp);
1328                 }
1329
1330                 /*
1331                  *      Jump over DHCP magic number, response, etc.
1332                  */
1333                 p = pp;
1334         }
1335
1336         /*
1337          *      Before packing the attributes, re-order them so that
1338          *      the array ones are all contiguous.  This simplifies
1339          *      the later code.
1340          */
1341         num_vps = 0;
1342         for (vp = paircursor(&cursor, &packet->vps);
1343              vp;
1344              vp = pairnext(&cursor)) {
1345                 num_vps++;
1346         }
1347         if (num_vps > 1) {
1348                 VALUE_PAIR **array;
1349
1350                 array = talloc_array(packet, VALUE_PAIR*, num_vps);
1351
1352                 i = 0;
1353                 for (vp = paircursor(&cursor, &packet->vps);
1354                      vp;
1355                      vp = pairnext(&cursor)) {
1356                         array[i++] = vp;
1357                 }
1358
1359                 /*
1360                  *      Sort the attributes.
1361                  */
1362                 qsort(array, (size_t) num_vps, sizeof(VALUE_PAIR *), attr_cmp);
1363
1364                 packet->vps = NULL;
1365                 paircursor(&cursor, &packet->vps);
1366                 for (i = 0; i < num_vps; i++) {
1367                         array[i]->next = NULL;
1368                         pairinsert(&cursor, array[i]);
1369                 }
1370                 talloc_free(array);
1371         }
1372
1373         p[0] = 0x35;            /* DHCP-Message-Type */
1374         p[1] = 1;
1375         p[2] = packet->code - PW_DHCP_OFFSET;
1376         p += 3;
1377
1378         /*
1379          *      Pack in the attributes.
1380          */
1381         vp = packet->vps;
1382         while (vp) {
1383                 unsigned int num_entries = 1;
1384                 VALUE_PAIR *same;
1385                 uint8_t *plength;
1386
1387                 if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next;
1388                 if (vp->da->attr == 53) goto next; /* already done */
1389                 if ((vp->da->attr > 255) &&
1390                     (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
1391
1392                 debug_pair(vp);
1393                 if (vp->da->flags.extended) goto next;
1394
1395                 for (same = paircursor(&cursor, &vp->next);
1396                      same;
1397                      same = pairnext(&cursor)) {
1398                         if (same->da->attr != vp->da->attr) break;
1399                         num_entries++;
1400                 }
1401
1402                 /*
1403                  *      For client-identifier
1404                  * @todo What's this meant to be doing?!
1405                  */
1406 #if 0
1407                 if ((vp->da->type == PW_TYPE_ETHERNET) &&
1408                     (vp->length == 6) &&
1409                     (num_entries == 1)) {
1410                         vp->da->type = PW_TYPE_OCTETS;
1411                         memmove(vp->vp_octets + 1, vp->vp_octets, 6);
1412                         vp->vp_octets[0] = 1;
1413                 }
1414 #endif
1415                 *(p++) = vp->da->attr & 0xff;
1416                 plength = p;
1417                 *(p++) = 0;     /* header isn't included in attr length */
1418
1419                 for (i = 0; i < num_entries; i++) {
1420                         if (i != 0) debug_pair(vp);
1421
1422                         if (vp->da->flags.is_tlv) {
1423                                 VALUE_PAIR *tlv;
1424
1425                                 /*
1426                                  *      Should NOT have been encoded yet!
1427                                  */
1428                                 tlv = fr_dhcp_vp2suboption(packet, vp);
1429
1430                                 /*
1431                                  *      Ignore it if there's an issue
1432                                  *      encoding it.
1433                                  */
1434                                 if (!tlv) goto next;
1435
1436                                 tlv->next = vp->next;
1437                                 vp->next = tlv;
1438                                 vp = tlv;
1439                         }
1440
1441                         length = fr_dhcp_vp2attr(vp, p, 0);
1442
1443                         /*
1444                          *      This will never happen due to FreeRADIUS
1445                          *      limitations: sizeof(vp->vp_octets) < 255
1446                          */
1447                         if (length > 255) {
1448                                 fr_strerror_printf("WARNING Ignoring too long attribute %s!", vp->da->name);
1449                                 break;
1450                         }
1451
1452                         /*
1453                          *      More than one attribute of the same type
1454                          *      in a row: they are packed together
1455                          *      into the same TLV.  If we overflow,
1456                          *      go bananas!
1457                          */
1458                         if ((*plength + length) > 255) {
1459                                 fr_strerror_printf("WARNING Ignoring too long attribute %s!", vp->da->name);
1460                                 break;
1461                         }
1462
1463                         *plength += length;
1464                         p += length;
1465
1466                         if (vp->next &&
1467                             (vp->next->da->attr == vp->da->attr))
1468                                 vp = vp->next;
1469                 } /* loop over num_entries */
1470
1471         next:
1472                 vp = vp->next;
1473         }
1474
1475         p[0] = 0xff;            /* end of option option */
1476         p[1] = 0x00;
1477         p += 2;
1478         dhcp_size = p - packet->data;
1479
1480         /*
1481          *      FIXME: if (dhcp_size > mms),
1482          *        then we put the extra options into the "sname" and "file"
1483          *        fields, AND set the "end option option" in the "options"
1484          *        field.  We also set the "overload option",
1485          *        and put options into the "file" field, followed by
1486          *        the "sname" field.  Where each option is completely
1487          *        enclosed in the "file" and/or "sname" field, AND
1488          *        followed by the "end of option", and MUST be followed
1489          *        by padding option.
1490          *
1491          *      Yuck.  That sucks...
1492          */
1493         packet->data_len = dhcp_size;
1494
1495         if (packet->data_len < DEFAULT_PACKET_SIZE) {
1496                 memset(packet->data + packet->data_len, 0,
1497                        DEFAULT_PACKET_SIZE - packet->data_len);
1498                 packet->data_len = DEFAULT_PACKET_SIZE;
1499         }
1500
1501         if ((fr_debug_flag > 2) && fr_log_fp) {
1502                 for (i = 0; i < packet->data_len; i++) {
1503                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", i);
1504                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1505                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1506                 }
1507                 fprintf(fr_log_fp, "\n");
1508         }
1509
1510         return 0;
1511 }
1512
1513 #ifdef SIOCSARP
1514 int fr_dhcp_add_arp_entry(int fd, char const *interface,
1515                           VALUE_PAIR *macaddr, VALUE_PAIR *ip)
1516 {
1517         struct sockaddr_in *sin;
1518         struct arpreq req;
1519
1520         if (!fr_assert(macaddr) ||
1521             !fr_assert((macaddr->da->type == PW_TYPE_ETHERNET) || (macaddr->da->type == PW_TYPE_OCTETS))) {
1522                 fr_strerror_printf("Wrong VP type (%s) for chaddr",
1523                                    fr_int2str(dict_attr_types, macaddr->da->type, "<invalid>"));
1524                 return -1;
1525         }
1526
1527         if (macaddr->length > sizeof(req.arp_ha.sa_data)) {
1528                 fr_strerror_printf("arp sa_data field too small (%zu octets) to contain chaddr (%zu octets)",
1529                                    sizeof(req.arp_ha.sa_data), macaddr->length);
1530                 return -1;
1531         }
1532
1533         memset(&req, 0, sizeof(req));
1534         sin = (struct sockaddr_in *) &req.arp_pa;
1535         sin->sin_family = AF_INET;
1536         sin->sin_addr.s_addr = ip->vp_ipaddr;
1537
1538         if (interface) {
1539                 strlcpy(req.arp_dev, interface, sizeof(req.arp_dev));
1540         }
1541
1542         if (macaddr->da->type == PW_TYPE_ETHERNET) {
1543                 memcpy(&req.arp_ha.sa_data, &macaddr->vp_ether, sizeof(macaddr->vp_ether));
1544         } else {
1545                 memcpy(&req.arp_ha.sa_data, macaddr->vp_octets, macaddr->length);
1546         }
1547
1548         req.arp_flags = ATF_COM;
1549         if (ioctl(fd, SIOCSARP, &req) < 0) {
1550                 fr_strerror_printf("Failed to add entry in ARP cache: %s (%d)", strerror(errno), errno);
1551                 return -1;
1552         }
1553
1554         return 0;
1555 }
1556 #else
1557 int fr_dhcp_add_arp_entry(UNUSED int fd, UNUSED char const *interface,
1558                           UNUSED VALUE_PAIR *macaddr, UNUSED VALUE_PAIR *ip)
1559 {
1560         fr_strerror_printf("Adding ARP entry is unsupported on this system");
1561         return -1;
1562 }
1563 #endif