/[ \t]+$//
[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 = packet->options;
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[256];
409 #endif
410                 char dst_ip_buf[256];
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,
429                      &packet->src_ipaddr.ipaddr,
430                      src_ip_buf, sizeof(src_ip_buf)),
431                    packet->src_port,
432 #endif
433                    inet_ntop(packet->dst_ipaddr.af,
434                      &packet->dst_ipaddr.ipaddr,
435                      dst_ip_buf, sizeof(dst_ip_buf)),
436                    packet->dst_port);
437         }
438
439 #ifndef WITH_UDPFROMTO
440         /*
441          *      Assume that the packet is encoded before sending it.
442          */
443         return sendto(packet->sockfd, packet->data, packet->data_len, 0,
444                       (struct sockaddr *)&dst, sizeof_dst);
445 #else
446
447         return sendfromto(packet->sockfd, packet->data, packet->data_len, 0,
448                           (struct sockaddr *)&src, sizeof_src,
449                           (struct sockaddr *)&dst, sizeof_dst);
450 #endif
451 }
452
453 static int fr_dhcp_attr2vp(RADIUS_PACKET *packet, VALUE_PAIR *vp, uint8_t const *p, size_t alen);
454
455 static int decode_tlv(RADIUS_PACKET *packet, VALUE_PAIR *tlv, uint8_t const *data, size_t data_len)
456 {
457         const uint8_t *p;
458         VALUE_PAIR *head, *vp;
459         vp_cursor_t cursor;
460
461         /*
462          *      Take a pass at parsing it.
463          */
464         p = data;
465         while (p < (data + data_len)) {
466                 if ((p + 2) > (data + data_len)) goto make_tlv;
467
468                 if ((p + p[1] + 2) > (data + data_len)) goto make_tlv;
469                 p += 2 + p[1];
470         }
471
472         /*
473          *      Got here... must be well formed.
474          */
475         head = NULL;
476         paircursor(&cursor, &head);
477
478         p = data;
479         while (p < (data + data_len)) {
480                 vp = paircreate(packet, tlv->da->attr | (p[0] << 8), DHCP_MAGIC_VENDOR);
481                 if (!vp) {
482                         pairfree(&head);
483                         goto make_tlv;
484                 }
485
486                 if (fr_dhcp_attr2vp(packet, vp, p + 2, p[1]) < 0) {
487                         pairfree(&head);
488                         goto make_tlv;
489                 }
490
491                 pairinsert(&cursor, vp);
492                 p += 2 + p[1];
493         }
494
495         /*
496          *      The caller allocated TLV, so we need to copy the FIRST
497          *      attribute over top of that.
498          */
499         if (head) {
500                 memcpy(tlv, head, sizeof(*tlv));
501                 head->next = NULL;
502                 pairfree(&head);
503         }
504
505         return 0;
506
507 make_tlv:
508         tlv->vp_tlv = talloc_array(tlv, uint8_t, data_len);
509         if (!tlv->vp_tlv) {
510                 fr_strerror_printf("No memory");
511                 return -1;
512         }
513         memcpy(tlv->vp_tlv, data, data_len);
514         tlv->length = data_len;
515
516         return 0;
517 }
518
519
520 /*
521  *      Decode ONE value into a VP
522  */
523 static int fr_dhcp_attr2vp(RADIUS_PACKET *packet, VALUE_PAIR *vp, uint8_t const *p, size_t alen)
524 {
525         char *q;
526
527         switch (vp->da->type) {
528         case PW_TYPE_BYTE:
529                 if (alen != 1) goto raw;
530                 vp->vp_integer = p[0];
531                 break;
532
533         case PW_TYPE_SHORT:
534                 if (alen != 2) goto raw;
535                 memcpy(&vp->vp_integer, p, 2);
536                 vp->vp_integer = ntohs(vp->vp_integer);
537                 break;
538
539         case PW_TYPE_INTEGER:
540                 if (alen != 4) goto raw;
541                 memcpy(&vp->vp_integer, p, 4);
542                 vp->vp_integer = ntohl(vp->vp_integer);
543                 break;
544
545         case PW_TYPE_IPADDR:
546                 if (alen != 4) goto raw;
547                 /*
548                  *      Keep value in Network Order!
549                  */
550                 memcpy(&vp->vp_ipaddr, p , 4);
551                 vp->length = 4;
552                 break;
553
554         case PW_TYPE_STRING:
555                 vp->vp_strvalue = q = talloc_array(vp, char, alen + 1);
556                 vp->type = VT_DATA;
557                 memcpy(q, p , alen);
558                 q[alen] = '\0';
559                 break;
560
561         /*
562          *      Value doesn't match up with attribute type, overwrite the
563          *      vp's original DICT_ATTR with an unknown one.
564          */
565         raw:
566                 if (pair2unknown(vp) < 0) return -1;
567
568         case PW_TYPE_OCTETS:
569                 if (alen > 253) return -1;
570                 pairmemcpy(vp, p, alen);
571                 break;
572
573         case PW_TYPE_TLV:
574                 return decode_tlv(packet, vp, p, alen);
575
576         default:
577                 fr_strerror_printf("Internal sanity check %d %d", vp->da->type, __LINE__);
578                 return -1;
579         } /* switch over type */
580
581         vp->length = alen;
582         return 0;
583 }
584
585 ssize_t fr_dhcp_decode_options(RADIUS_PACKET *packet,
586                                uint8_t const *data, size_t len, VALUE_PAIR **head)
587 {
588         int i;
589         VALUE_PAIR *vp;
590         vp_cursor_t cursor;
591         uint8_t const *p, *next;
592         next = data;
593
594         *head = NULL;
595         paircursor(&cursor, head);
596
597         /*
598          *      FIXME: This should also check sname && file fields.
599          *      See the dhcp_get_option() function above.
600          */
601         while (next < (data + len)) {
602                 int num_entries, alen;
603                 const DICT_ATTR *da;
604
605                 p = next;
606
607                 if (*p == 0) break;
608                 if (*p == 255) break; /* end of options signifier */
609                 if ((p + 2) > (data + len)) break;
610
611                 next = p + 2 + p[1];
612
613                 if (p[1] >= 253) {
614                         fr_strerror_printf("Attribute too long %u %u",
615                                            p[0], p[1]);
616                         continue;
617                 }
618
619                 da = dict_attrbyvalue(p[0], DHCP_MAGIC_VENDOR);
620                 if (!da) {
621                         fr_strerror_printf("Attribute not in our dictionary: %u",
622                                            p[0]);
623                         continue;
624                 }
625
626                 vp = NULL;
627                 num_entries = 1;
628                 alen = p[1];
629                 p += 2;
630
631                 /*
632                  *      Could be an array of bytes, integers, etc.
633                  */
634                 if (da->flags.array) {
635                         switch (da->type) {
636                         case PW_TYPE_BYTE:
637                                 num_entries = alen;
638                                 alen = 1;
639                                 break;
640
641                         case PW_TYPE_SHORT: /* ignore any trailing data */
642                                 num_entries = alen >> 1;
643                                 alen = 2;
644                                 break;
645
646                         case PW_TYPE_IPADDR:
647                         case PW_TYPE_INTEGER:
648                         case PW_TYPE_DATE: /* ignore any trailing data */
649                                 num_entries = alen >> 2;
650                                 alen = 4;
651                                 break;
652
653                         default:
654
655                                 break; /* really an internal sanity failure */
656                         }
657                 }
658
659                 /*
660                  *      Loop over all of the entries, building VPs
661                  */
662                 for (i = 0; i < num_entries; i++) {
663                         vp = pairmake(packet, NULL, da->name, NULL, T_OP_ADD);
664                         if (!vp) {
665                                 fr_strerror_printf("Cannot build attribute %s",
666                                         fr_strerror());
667                                 pairfree(head);
668                                 return -1;
669                         }
670
671                         /*
672                          *      Hack for ease of use.
673                          */
674                         if ((da->vendor == DHCP_MAGIC_VENDOR) &&
675                             (da->attr == 61) && !da->flags.array &&
676                             (alen == 7) && (*p == 1) && (num_entries == 1)) {
677                                 pairmemcpy(vp, p + 1, 6);
678
679                         } else if (fr_dhcp_attr2vp(packet, vp, p, alen) < 0) {
680                                 pairfree(&vp);
681                                 pairfree(head);
682                                 return -1;
683                         }
684
685                         pairinsert(&cursor, vp);
686
687                         for (vp = paircurrent(&cursor);
688                              vp;
689                              vp = pairnext(&cursor)) {
690                                 debug_pair(vp);
691                         }
692                         p += alen;
693                 } /* loop over array entries */
694         } /* loop over the entire packet */
695
696         return next - data;
697 }
698
699 int fr_dhcp_decode(RADIUS_PACKET *packet)
700 {
701         size_t i;
702         uint8_t *p;
703         uint32_t giaddr;
704         vp_cursor_t cursor;
705         VALUE_PAIR *head = NULL, *vp;
706         VALUE_PAIR *maxms, *mtu;
707
708         paircursor(&cursor, &head);
709         p = packet->data;
710
711         if ((fr_debug_flag > 2) && fr_log_fp) {
712                 for (i = 0; i < packet->data_len; i++) {
713                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", (int) i);
714                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
715                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
716                 }
717                 fprintf(fr_log_fp, "\n");
718         }
719
720         if (packet->data[1] != 1) {
721                 fr_strerror_printf("Packet is not Ethernet: %u",
722                       packet->data[1]);
723                 return -1;
724         }
725
726         /*
727          *      Decode the header.
728          */
729         for (i = 0; i < 14; i++) {
730                 char *q;
731
732                 vp = pairmake(packet, NULL, dhcp_header_names[i], NULL, T_OP_EQ);
733                 if (!vp) {
734                         char buffer[256];
735                         strlcpy(buffer, fr_strerror(), sizeof(buffer));
736                         fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
737                         pairfree(&head);
738                         return -1;
739                 }
740
741                 if ((i == 11) &&
742                     (packet->data[1] == 1) &&
743                     (packet->data[2] != 6)) {
744                         fr_strerror_printf("chaddr of incorrect length for ethernet");
745                 }
746
747                 switch (vp->da->type) {
748                 case PW_TYPE_BYTE:
749                         vp->vp_integer = p[0];
750                         vp->length = 1;
751                         break;
752
753                 case PW_TYPE_SHORT:
754                         vp->vp_integer = (p[0] << 8) | p[1];
755                         vp->length = 2;
756                         break;
757
758                 case PW_TYPE_INTEGER:
759                         memcpy(&vp->vp_integer, p, 4);
760                         vp->vp_integer = ntohl(vp->vp_integer);
761                         vp->length = 4;
762                         break;
763
764                 case PW_TYPE_IPADDR:
765                         memcpy(&vp->vp_ipaddr, p, 4);
766                         vp->length = 4;
767                         break;
768
769                 case PW_TYPE_STRING:
770                         vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i] + 1);
771                         vp->type = VT_DATA;
772                         memcpy(q, p, dhcp_header_sizes[i]);
773                         q[dhcp_header_sizes[i]] = '\0';
774                         vp->length = strlen(vp->vp_strvalue);
775                         if (vp->length == 0) {
776                                 pairfree(&vp);
777                         }
778                         break;
779
780                 case PW_TYPE_OCTETS:
781                         pairmemcpy(vp, p, packet->data[2]);
782                         break;
783
784                 case PW_TYPE_ETHERNET:
785                         memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
786                         vp->length = sizeof(vp->vp_ether);
787                         break;
788
789                 default:
790                         fr_strerror_printf("BAD TYPE %d", vp->da->type);
791                         pairfree(&vp);
792                         break;
793                 }
794                 p += dhcp_header_sizes[i];
795
796                 if (!vp) continue;
797
798                 debug_pair(vp);
799                 pairinsert(&cursor, vp);
800         }
801
802         /*
803          *      Loop over the options.
804          */
805
806         /*
807          *      Nothing uses tail after this call, if it does in the future
808          *      it'll need to find the new tail...
809          */
810         {
811                 VALUE_PAIR *options = NULL;
812
813                 if (fr_dhcp_decode_options(packet,
814                                            packet->data + 240, packet->data_len - 240,
815                                            &options) < 0) {
816                         return -1;
817                 }
818
819                 if (options) {
820                         pairinsert(&cursor, options);
821                 }
822         }
823
824         /*
825          *      If DHCP request, set ciaddr to zero.
826          */
827
828         /*
829          *      Set broadcast flag for broken vendors, but only if
830          *      giaddr isn't set.
831          */
832         memcpy(&giaddr, packet->data + 24, sizeof(giaddr));
833         if (giaddr == htonl(INADDR_ANY)) {
834                 /*
835                  *      DHCP Opcode is request
836                  */
837                 vp = pairfind(head, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
838                 if (vp && vp->vp_integer == 3) {
839                         /*
840                          *      Vendor is "MSFT 98"
841                          */
842                         vp = pairfind(head, 63, DHCP_MAGIC_VENDOR, TAG_ANY);
843                         if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
844                                 vp = pairfind(head, 262, DHCP_MAGIC_VENDOR, TAG_ANY);
845
846                                 /*
847                                  *      Reply should be broadcast.
848                                  */
849                                 if (vp) vp->vp_integer |= 0x8000;
850                                 packet->data[10] |= 0x80;
851                         }
852                 }
853         }
854
855         /*
856          *      FIXME: Nuke attributes that aren't used in the normal
857          *      header for discover/requests.
858          */
859         packet->vps = head;
860
861         /*
862          *      Client can request a LARGER size, but not a smaller
863          *      one.  They also cannot request a size larger than MTU.
864          */
865         maxms = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
866         mtu = pairfind(packet->vps, 26, DHCP_MAGIC_VENDOR, TAG_ANY);
867
868         if (mtu && (mtu->vp_integer < DEFAULT_PACKET_SIZE)) {
869                 fr_strerror_printf("DHCP Fatal: Client says MTU is smaller than minimum permitted by the specification.");
870                 return -1;
871         }
872
873         if (maxms && (maxms->vp_integer < DEFAULT_PACKET_SIZE)) {
874                 fr_strerror_printf("DHCP WARNING: Client says maximum message size is smaller than minimum permitted by the specification: fixing it");
875                 maxms->vp_integer = DEFAULT_PACKET_SIZE;
876         }
877
878         if (maxms && mtu && (maxms->vp_integer > mtu->vp_integer)) {
879                 fr_strerror_printf("DHCP WARNING: Client says MTU is smaller than maximum message size: fixing it");
880                 maxms->vp_integer = mtu->vp_integer;
881         }
882
883         if (fr_debug_flag) fflush(stdout);
884
885         return 0;
886 }
887
888
889 static int attr_cmp(void const *one, void const *two)
890 {
891         const VALUE_PAIR * const *a = one;
892         const VALUE_PAIR * const *b = two;
893
894         /*
895          *      DHCP-Message-Type is first, for simplicity.
896          */
897         if (((*a)->da->attr == 53) &&
898             (*b)->da->attr != 53) return -1;
899
900         /*
901          *      Relay-Agent is last
902          */
903         if (((*a)->da->attr == 82) &&
904             (*b)->da->attr != 82) return 1;
905
906         return ((*a)->da->attr - (*b)->da->attr);
907 }
908
909 /*
910  * @todo Check room!
911  */
912 static size_t fr_dhcp_vp2attr(VALUE_PAIR *vp, uint8_t *p, UNUSED size_t room)
913 {
914         size_t length;
915         uint32_t lvalue;
916
917         /*
918          *      Search for all attributes of the same
919          *      type, and pack them into the same
920          *      attribute.
921          */
922         switch (vp->da->type) {
923         case PW_TYPE_BYTE:
924                 length = 1;
925                 *p = vp->vp_integer & 0xff;
926                 break;
927
928         case PW_TYPE_SHORT:
929                 length = 2;
930                 p[0] = (vp->vp_integer >> 8) & 0xff;
931                 p[1] = vp->vp_integer & 0xff;
932                 break;
933
934         case PW_TYPE_INTEGER:
935                 length = 4;
936                 lvalue = htonl(vp->vp_integer);
937                 memcpy(p, &lvalue, 4);
938                 break;
939
940         case PW_TYPE_IPADDR:
941                 length = 4;
942                 memcpy(p, &vp->vp_ipaddr, 4);
943                 break;
944
945         case PW_TYPE_ETHERNET:
946                 length = 6;
947                 memcpy(p, &vp->vp_ether, 6);
948                 break;
949
950         case PW_TYPE_STRING:
951                 memcpy(p, vp->vp_strvalue, vp->length);
952                 length = vp->length;
953                 break;
954
955         case PW_TYPE_TLV:       /* FIXME: split it on 255? */
956                 memcpy(p, vp->vp_tlv, vp->length);
957                 length = vp->length;
958                 break;
959
960         case PW_TYPE_OCTETS:
961                 memcpy(p, vp->vp_octets, vp->length);
962                 length = vp->length;
963                 break;
964
965         default:
966                 fr_strerror_printf("BAD TYPE2 %d", vp->da->type);
967                 length = 0;
968                 break;
969         }
970
971         return length;
972 }
973
974 static VALUE_PAIR *fr_dhcp_vp2suboption(RADIUS_PACKET *packet, VALUE_PAIR *vps)
975 {
976         int length;
977         unsigned int attribute;
978         uint8_t *ptr;
979         vp_cursor_t cursor;
980         VALUE_PAIR *vp, *tlv;
981
982         attribute = vps->da->attr & 0xffff00ff;
983
984         tlv = paircreate(packet, attribute, DHCP_MAGIC_VENDOR);
985         if (!tlv) return NULL;
986
987         tlv->length = 0;
988         for (vp = paircursor(&cursor, &vps);
989              vp;
990              vp = pairnext(&cursor)) {
991                 /*
992                  *      Group the attributes ONLY until we see a
993                  *      non-TLV attribute.
994                  */
995                 if (!vp->da->flags.is_tlv ||
996                     vp->da->flags.extended ||
997                     ((vp->da->attr & 0xffff00ff) != attribute)) {
998                         break;
999                 }
1000
1001                 tlv->length += vp->length + 2;
1002         }
1003
1004         if (!tlv->length) {
1005                 pairfree(&tlv);
1006                 return NULL;
1007         }
1008
1009         tlv->vp_tlv = talloc_array(tlv, uint8_t, tlv->length);
1010         if (!tlv->vp_tlv) {
1011                 pairfree(&tlv);
1012                 return NULL;
1013         }
1014
1015         ptr = tlv->vp_tlv;
1016         for (vp = paircursor(&cursor, &vps);
1017              vp;
1018              vp = pairnext(&cursor)) {
1019                 if (!vp->da->flags.is_tlv ||
1020                     vp->da->flags.extended ||
1021                     ((vp->da->attr & 0xffff00ff) != attribute)) {
1022                         break;
1023                 }
1024
1025                 length = fr_dhcp_vp2attr(vp, ptr + 2,
1026                                          tlv->vp_tlv + tlv->length - ptr);
1027                 if (length > 255) {
1028                         pairfree(&tlv);
1029                         return NULL;
1030                 }
1031
1032                 /*
1033                  *      Pack the attribute.
1034                  */
1035                 ptr[0] = (vp->da->attr & 0xff00) >> 8;
1036                 ptr[1] = length;
1037
1038                 ptr += length + 2;
1039         }
1040
1041         return tlv;
1042 }
1043
1044
1045 int fr_dhcp_encode(RADIUS_PACKET *packet)
1046 {
1047         unsigned int i, num_vps;
1048         uint8_t *p;
1049         vp_cursor_t cursor;
1050         VALUE_PAIR *vp;
1051         uint32_t lvalue, mms;
1052         size_t dhcp_size, length;
1053 #ifndef NDEBUG
1054         char const *name;
1055 #  ifdef WITH_UDPFROMTO
1056         char src_ip_buf[256];
1057 #  endif
1058         char dst_ip_buf[256];
1059 #endif
1060
1061         if (packet->data) return 0;
1062
1063         packet->data_len = MAX_PACKET_SIZE;
1064         packet->data = talloc_zero_array(packet, uint8_t, packet->data_len);
1065
1066         /* XXX Ugly ... should be set by the caller */
1067         if (packet->code == 0) packet->code = PW_DHCP_NAK;
1068
1069 #ifndef NDEBUG
1070         if ((packet->code >= PW_DHCP_DISCOVER) &&
1071             (packet->code <= PW_DHCP_INFORM)) {
1072                 name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
1073         } else {
1074                 name = "?Unknown?";
1075         }
1076
1077         DEBUG(
1078 #ifdef WITH_UDPFROMTO
1079               "Encoding %s of id %08x from %s:%d to %s:%d\n",
1080 #else
1081               "Encoding %s of id %08x to %s:%d\n",
1082 #endif
1083               name, (unsigned int) packet->id,
1084 #ifdef WITH_UDPFROMTO
1085               inet_ntop(packet->src_ipaddr.af,
1086                         &packet->src_ipaddr.ipaddr,
1087                         src_ip_buf, sizeof(src_ip_buf)),
1088               packet->src_port,
1089 #endif
1090               inet_ntop(packet->dst_ipaddr.af,
1091                         &packet->dst_ipaddr.ipaddr,
1092                      dst_ip_buf, sizeof(dst_ip_buf)),
1093               packet->dst_port);
1094 #endif
1095
1096         p = packet->data;
1097
1098         mms = DEFAULT_PACKET_SIZE; /* maximum message size */
1099
1100         /*
1101          *      Clients can request a LARGER size, but not a
1102          *      smaller one.  They also cannot request a size
1103          *      larger than MTU.
1104          */
1105
1106         /* DHCP-DHCP-Maximum-Msg-Size */
1107         vp = pairfind(packet->vps, 57, DHCP_MAGIC_VENDOR, TAG_ANY);
1108         if (vp && (vp->vp_integer > mms)) {
1109                 mms = vp->vp_integer;
1110
1111                 if (mms > MAX_PACKET_SIZE) mms = MAX_PACKET_SIZE;
1112         }
1113
1114         vp = pairfind(packet->vps, 256, DHCP_MAGIC_VENDOR, TAG_ANY);
1115         if (vp) {
1116                 *p++ = vp->vp_integer & 0xff;
1117         } else {
1118                 *p++ = 1;       /* client message */
1119         }
1120
1121         /* DHCP-Hardware-Type */
1122         if ((vp = pairfind(packet->vps, 257, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1123                 *p++ = vp->vp_integer & 0xFF;
1124         } else {
1125                 *p++ = 1;               /* hardware type = ethernet */
1126         }
1127
1128         /* DHCP-Hardware-Address-Length */
1129         if ((vp = pairfind(packet->vps, 258, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1130                 *p++ = vp->vp_integer & 0xFF;
1131         } else {
1132                 *p++ = 6;               /* 6 bytes of ethernet */
1133         }
1134
1135         /* DHCP-Hop-Count */
1136         if ((vp = pairfind(packet->vps, 259, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1137                 *p = vp->vp_integer & 0xff;
1138         }
1139         p++;
1140
1141         /* DHCP-Transaction-Id */
1142         if ((vp = pairfind(packet->vps, 260, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1143                 lvalue = htonl(vp->vp_integer);
1144         } else {
1145                 lvalue = fr_rand();
1146         }
1147         memcpy(p, &lvalue, 4);
1148         p += 4;
1149
1150         /* DHCP-Number-of-Seconds */
1151         if ((vp = pairfind(packet->vps, 261, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1152                 lvalue = htonl(vp->vp_integer);
1153                 memcpy(p, &lvalue, 2);
1154         }
1155         p += 2;
1156
1157         /* DHCP-Flags */
1158         if ((vp = pairfind(packet->vps, 262, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1159                 lvalue = htons(vp->vp_integer);
1160                 memcpy(p, &lvalue, 2);
1161         }
1162         p += 2;
1163
1164         /* DHCP-Client-IP-Address */
1165         if ((vp = pairfind(packet->vps, 263, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1166                 memcpy(p, &vp->vp_ipaddr, 4);
1167         }
1168         p += 4;
1169
1170         /* DHCP-Your-IP-address */
1171         if ((vp = pairfind(packet->vps, 264, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1172                 lvalue = vp->vp_ipaddr;
1173         } else {
1174                 lvalue = htonl(INADDR_ANY);
1175         }
1176         memcpy(p, &lvalue, 4);
1177         p += 4;
1178
1179         /* DHCP-Server-IP-Address */
1180         vp = pairfind(packet->vps, 265, DHCP_MAGIC_VENDOR, TAG_ANY);
1181
1182         /* DHCP-DHCP-Server-Identifier */
1183         if (!vp && (vp = pairfind(packet->vps, 54, 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         /*
1192          *      DHCP-Gateway-IP-Address
1193          */
1194         if ((vp = pairfind(packet->vps, 266, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1195                 lvalue = vp->vp_ipaddr;
1196         } else {
1197                 lvalue = htonl(INADDR_ANY);
1198         }
1199         memcpy(p, &lvalue, 4);
1200         p += 4;
1201
1202         /* DHCP-Client-Hardware-Address */
1203         if ((vp = pairfind(packet->vps, 267, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1204                 if (vp->length > DHCP_CHADDR_LEN) {
1205                         memcpy(p, vp->vp_octets, DHCP_CHADDR_LEN);
1206                 } else {
1207                         memcpy(p, vp->vp_octets, vp->length);
1208                 }
1209         }
1210         p += DHCP_CHADDR_LEN;
1211
1212         /* DHCP-Server-Host-Name */
1213         if ((vp = pairfind(packet->vps, 268, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1214                 if (vp->length > DHCP_SNAME_LEN) {
1215                         memcpy(p, vp->vp_strvalue, DHCP_SNAME_LEN);
1216                 } else {
1217                         memcpy(p, vp->vp_strvalue, vp->length);
1218                 }
1219         }
1220         p += DHCP_SNAME_LEN;
1221
1222         /*
1223          *      Copy over DHCP-Boot-Filename.
1224          *
1225          *      FIXME: This copy should be delayed until AFTER the options
1226          *      have been processed.  If there are too many options for
1227          *      the packet, then they go into the sname && filename fields.
1228          *      When that happens, the boot filename is passed as an option,
1229          *      instead of being placed verbatim in the filename field.
1230          */
1231
1232         /* DHCP-Boot-Filename */
1233         if ((vp = pairfind(packet->vps, 269, DHCP_MAGIC_VENDOR, TAG_ANY))) {
1234                 if (vp->length > DHCP_FILE_LEN) {
1235                         memcpy(p, vp->vp_strvalue, DHCP_FILE_LEN);
1236                 } else {
1237                         memcpy(p, vp->vp_strvalue, vp->length);
1238                 }
1239         }
1240         p += DHCP_FILE_LEN;
1241
1242         /* DHCP magic number */
1243         lvalue = htonl(DHCP_OPTION_MAGIC_NUMBER);
1244         memcpy(p, &lvalue, 4);
1245         p += 4;
1246
1247         /*
1248          *      Print the header.
1249          */
1250         if (fr_debug_flag > 1) {
1251                 uint8_t *pp = p;
1252
1253                 p = packet->data;
1254
1255                 for (i = 0; i < 14; i++) {
1256                         char *q;
1257
1258                         vp = pairmake(packet, NULL,
1259                                       dhcp_header_names[i], NULL, T_OP_EQ);
1260                         if (!vp) {
1261                                 char buffer[256];
1262                                 strlcpy(buffer, fr_strerror(), sizeof(buffer));
1263                                 fr_strerror_printf("Cannot decode packet due to internal error: %s", buffer);
1264                                 return -1;
1265                         }
1266
1267                         switch (vp->da->type) {
1268                         case PW_TYPE_BYTE:
1269                                 vp->vp_integer = p[0];
1270                                 vp->length = 1;
1271                                 break;
1272
1273                         case PW_TYPE_SHORT:
1274                                 vp->vp_integer = (p[0] << 8) | p[1];
1275                                 vp->length = 2;
1276                                 break;
1277
1278                         case PW_TYPE_INTEGER:
1279                                 memcpy(&vp->vp_integer, p, 4);
1280                                 vp->vp_integer = ntohl(vp->vp_integer);
1281                                 vp->length = 4;
1282                                 break;
1283
1284                         case PW_TYPE_IPADDR:
1285                                 memcpy(&vp->vp_ipaddr, p, 4);
1286                                 vp->length = 4;
1287                                 break;
1288
1289                         case PW_TYPE_STRING:
1290                                 vp->vp_strvalue = q = talloc_array(vp, char, dhcp_header_sizes[i]);
1291                                 vp->type = VT_DATA;
1292                                 memcpy(q, p, dhcp_header_sizes[i]);
1293                                 q[dhcp_header_sizes[i]] = '\0';
1294                                 vp->length = strlen(vp->vp_strvalue);
1295                                 break;
1296
1297                         case PW_TYPE_OCTETS: /* only for Client HW Address */
1298                                 pairmemcpy(vp, p, packet->data[2]);
1299                                 break;
1300
1301                         case PW_TYPE_ETHERNET: /* only for Client HW Address */
1302                                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
1303                                 vp->length = sizeof(vp->vp_ether);
1304                                 break;
1305
1306                         default:
1307                                 fr_strerror_printf("Internal sanity check failed %d %d", vp->da->type, __LINE__);
1308                                 pairfree(&vp);
1309                                 break;
1310                         }
1311
1312                         p += dhcp_header_sizes[i];
1313
1314                         debug_pair(vp);
1315                         pairfree(&vp);
1316                 }
1317
1318                 /*
1319                  *      Jump over DHCP magic number, response, etc.
1320                  */
1321                 p = pp;
1322         }
1323
1324         /*
1325          *      Before packing the attributes, re-order them so that
1326          *      the array ones are all contiguous.  This simplifies
1327          *      the later code.
1328          */
1329         num_vps = 0;
1330         for (vp = paircursor(&cursor, &packet->vps);
1331              vp;
1332              vp = pairnext(&cursor)) {
1333                 num_vps++;
1334         }
1335         if (num_vps > 1) {
1336                 VALUE_PAIR **array;
1337
1338                 array = talloc_array(packet, VALUE_PAIR*, num_vps);
1339
1340                 i = 0;
1341                 for (vp = paircursor(&cursor, &packet->vps);
1342                      vp;
1343                      vp = pairnext(&cursor)) {
1344                         array[i++] = vp;
1345                 }
1346
1347                 /*
1348                  *      Sort the attributes.
1349                  */
1350                 qsort(array, (size_t) num_vps, sizeof(VALUE_PAIR *), attr_cmp);
1351
1352                 paircursor(&cursor, &packet->vps);
1353                 for (i = 0; i < num_vps; i++) {
1354                         pairinsert(&cursor, array[i]->next);
1355                 }
1356                 talloc_free(array);
1357         }
1358
1359         p[0] = 0x35;            /* DHCP-Message-Type */
1360         p[1] = 1;
1361         p[2] = packet->code - PW_DHCP_OFFSET;
1362         p += 3;
1363
1364         /*
1365          *      Pack in the attributes.
1366          */
1367         vp = packet->vps;
1368         while (vp) {
1369                 unsigned int num_entries = 1;
1370                 VALUE_PAIR *same;
1371                 uint8_t *plength;
1372
1373                 if (vp->da->vendor != DHCP_MAGIC_VENDOR) goto next;
1374                 if (vp->da->attr == 53) goto next; /* already done */
1375                 if ((vp->da->attr > 255) &&
1376                     (DHCP_BASE_ATTR(vp->da->attr) != PW_DHCP_OPTION_82)) goto next;
1377
1378                 debug_pair(vp);
1379                 if (vp->da->flags.extended) goto next;
1380
1381                 length = vp->length;
1382
1383                 for (same = paircursor(&cursor, &vp->next);
1384                      same;
1385                      same = pairnext(&cursor)) {
1386                         if (same->da->attr != vp->da->attr) break;
1387                         num_entries++;
1388                 }
1389
1390                 /*
1391                  *      For client-identifier
1392                  * @todo What's this meant to be doing?!
1393                  */
1394 #if 0
1395                 if ((vp->da->type == PW_TYPE_ETHERNET) &&
1396                     (vp->length == 6) &&
1397                     (num_entries == 1)) {
1398                         vp->da->type = PW_TYPE_OCTETS;
1399                         memmove(vp->vp_octets + 1, vp->vp_octets, 6);
1400                         vp->vp_octets[0] = 1;
1401                 }
1402 #endif
1403                 *(p++) = vp->da->attr & 0xff;
1404                 plength = p;
1405                 *(p++) = 0;     /* header isn't included in attr length */
1406
1407                 for (i = 0; i < num_entries; i++) {
1408                         if (i != 0) debug_pair(vp);
1409
1410                         if (vp->da->flags.is_tlv) {
1411                                 VALUE_PAIR *tlv;
1412
1413                                 /*
1414                                  *      Should NOT have been encoded yet!
1415                                  */
1416                                 tlv = fr_dhcp_vp2suboption(packet, vp);
1417
1418                                 /*
1419                                  *      Ignore it if there's an issue
1420                                  *      encoding it.
1421                                  */
1422                                 if (!tlv) goto next;
1423
1424                                 tlv->next = vp->next;
1425                                 vp->next = tlv;
1426                                 vp = tlv;
1427                         }
1428
1429                         length = fr_dhcp_vp2attr(vp, p, 0);
1430
1431                         /*
1432                          *      This will never happen due to FreeRADIUS
1433                          *      limitations: sizeof(vp->vp_octets) < 255
1434                          */
1435                         if (length > 255) {
1436                                 fr_strerror_printf("WARNING Ignoring too long attribute %s!", vp->da->name);
1437                                 break;
1438                         }
1439
1440                         /*
1441                          *      More than one attribute of the same type
1442                          *      in a row: they are packed together
1443                          *      into the same TLV.  If we overflow,
1444                          *      go bananas!
1445                          */
1446                         if ((*plength + length) > 255) {
1447                                 fr_strerror_printf("WARNING Ignoring too long attribute %s!", vp->da->name);
1448                                 break;
1449                         }
1450
1451                         *plength += length;
1452                         p += length;
1453
1454                         if (vp->next &&
1455                             (vp->next->da->attr == vp->da->attr))
1456                                 vp = vp->next;
1457                 } /* loop over num_entries */
1458
1459         next:
1460                 vp = vp->next;
1461         }
1462
1463         p[0] = 0xff;            /* end of option option */
1464         p[1] = 0x00;
1465         p += 2;
1466         dhcp_size = p - packet->data;
1467
1468         /*
1469          *      FIXME: if (dhcp_size > mms),
1470          *        then we put the extra options into the "sname" and "file"
1471          *        fields, AND set the "end option option" in the "options"
1472          *        field.  We also set the "overload option",
1473          *        and put options into the "file" field, followed by
1474          *        the "sname" field.  Where each option is completely
1475          *        enclosed in the "file" and/or "sname" field, AND
1476          *        followed by the "end of option", and MUST be followed
1477          *        by padding option.
1478          *
1479          *      Yuck.  That sucks...
1480          */
1481         packet->data_len = dhcp_size;
1482
1483         if (packet->data_len < DEFAULT_PACKET_SIZE) {
1484                 memset(packet->data + packet->data_len, 0,
1485                        DEFAULT_PACKET_SIZE - packet->data_len);
1486                 packet->data_len = DEFAULT_PACKET_SIZE;
1487         }
1488
1489         if ((fr_debug_flag > 2) && fr_log_fp) {
1490                 for (i = 0; i < packet->data_len; i++) {
1491                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", i);
1492                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1493                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1494                 }
1495                 fprintf(fr_log_fp, "\n");
1496         }
1497
1498         return 0;
1499 }
1500
1501 #ifdef SIOCSARP
1502 int fr_dhcp_add_arp_entry(int fd, char const *interface,
1503                           VALUE_PAIR *macaddr, VALUE_PAIR *ip)
1504 {
1505         struct sockaddr_in *sin;
1506         struct arpreq req;
1507
1508         if (macaddr->length > sizeof (req.arp_ha.sa_data)) {
1509                 fr_strerror_printf("ERROR: DHCP only supports up to %zu octets "
1510                                    "for Client Hardware Address "
1511                                    "(got %zu octets)\n",
1512                                    sizeof(req.arp_ha.sa_data),
1513                                    macaddr->length);
1514                 return -1;
1515         }
1516
1517         memset(&req, 0, sizeof(req));
1518         sin = (struct sockaddr_in *) &req.arp_pa;
1519         sin->sin_family = AF_INET;
1520         sin->sin_addr.s_addr = ip->vp_ipaddr;
1521         strlcpy(req.arp_dev, interface, sizeof(req.arp_dev));
1522         memcpy(&req.arp_ha.sa_data, macaddr->vp_octets, macaddr->length);
1523
1524         req.arp_flags = ATF_COM;
1525         if (ioctl(fd, SIOCSARP, &req) < 0) {
1526                 fr_strerror_printf("DHCP: Failed to add entry in ARP cache: %s (%d)",
1527                                    strerror(errno), errno);
1528                 return -1;
1529         }
1530
1531         return 0;
1532 }
1533 #else
1534 int fr_dhcp_add_arp_entry(UNUSED int fd, UNUSED char const *interface,
1535                           UNUSED VALUE_PAIR *macaddr, UNUSED VALUE_PAIR *ip)
1536 {
1537         fr_strerror_printf("Adding ARP entry is unsupported on this system");
1538         return -1;
1539 }
1540 #endif