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