Rename librad_* to fr_*
[freeradius.git] / src / lib / dhcp.c
1 /*
2  * dhcp.c       Functions to send/receive dhcp packets.
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program 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
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; 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 #ifdef WITH_DHCP
32 #define DHCP_CHADDR_LEN (16)
33 #define DHCP_SNAME_LEN  (64)
34 #define DHCP_FILE_LEN   (128)
35 #define DHCP_VEND_LEN   (308)
36 #define DHCP_OPTION_MAGIC_NUMBER (0x63825363)
37
38 typedef struct dhcp_packet_t {
39         uint8_t         opcode;
40         uint8_t         htype;
41         uint8_t         hlen;
42         uint8_t         hops;
43         uint32_t        xid;    /* 4 */
44         uint16_t        secs;   /* 8 */
45         uint16_t        flags;
46         uint32_t        ciaddr; /* 12 */
47         uint32_t        yiaddr; /* 16 */
48         uint32_t        siaddr; /* 20 */
49         uint32_t        giaddr; /* 24 */
50         uint8_t         chaddr[DHCP_CHADDR_LEN]; /* 28 */
51         char            sname[DHCP_SNAME_LEN]; /* 44 */
52         char            file[DHCP_FILE_LEN]; /* 108 */
53         uint32_t        option_format; /* 236 */
54         uint8_t         options[DHCP_VEND_LEN];
55 } dhcp_packet_t;
56
57 /*
58  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        DISCOVER
59  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         OFFER
60  *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        REQUEST
61  *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         ACK
62  */
63 static const char *dhcp_header_names[] = {
64         "DHCP-Opcode",
65         "DHCP-Hardware-Type",
66         "DHCP-Hardware-Address-Length",
67         "DHCP-Hop-Count",
68         "DHCP-Transaction-Id",
69         "DHCP-Number-of-Seconds",
70         "DHCP-Flags",
71         "DHCP-Client-IP-Address",
72         "DHCP-Your-IP-Address",
73         "DHCP-Server-IP-Address",
74         "DHCP-Gateway-IP-Address",
75         "DHCP-Client-Hardware-Address",
76         "DHCP-Server-Host-Name",
77         "DHCP-Boot-Filename",
78
79         NULL
80 };
81
82 static const char *dhcp_message_types[] = {
83         "invalid",
84         "DHCP-Discover",
85         "DHCP-Offer",
86         "DHCP-Request",
87         "DHCP-Decline",
88         "DHCP-Ack",
89         "DHCP-NAK",
90         "DHCP-Release",
91         "DHCP-Inform",
92         "DHCP-Force-Renew",
93 };
94
95 static int dhcp_header_sizes[] = {
96         1, 1, 1, 1,
97         4, 2, 2, 4,
98         4, 4, 4,
99         DHCP_CHADDR_LEN,
100         DHCP_SNAME_LEN,
101         DHCP_FILE_LEN
102 };
103
104
105 /*
106  *      Some clients silently ignore responses less than 300 bytes.
107  */
108 #define MIN_PACKET_SIZE (244)
109 #define DEFAULT_PACKET_SIZE (300)
110 #define MAX_PACKET_SIZE (1500 - 40)
111
112 /*
113  *      DHCPv4 is only for IPv4.  Broadcast only works if udpfromto is
114  *      defined.
115  */
116 RADIUS_PACKET *fr_dhcp_recv(int sockfd)
117 {
118         uint32_t                magic;
119         struct sockaddr_storage src;
120         struct sockaddr_storage dst;
121         socklen_t               sizeof_src;
122         socklen_t               sizeof_dst;
123         RADIUS_PACKET           *packet;
124         int port;
125
126         packet = rad_alloc(0);
127         if (!packet) return NULL;
128         memset(packet, 0, sizeof(packet));
129
130         packet->data = malloc(MAX_PACKET_SIZE);
131         if (!packet->data) {
132                 rad_free(&packet);
133                 return NULL;
134         }
135
136         packet->sockfd = sockfd;
137         sizeof_src = sizeof(src);
138         packet->data_len = recvfrom(sockfd, packet->data, MAX_PACKET_SIZE, 0,
139                                     (struct sockaddr *)&src, &sizeof_src);
140         if (packet->data_len <= 0) {
141                 fprintf(stderr, "Failed reading DHCP socket: %s", strerror(errno));
142                 rad_free(&packet);
143                 return NULL;
144         }
145
146         if (packet->data_len < MIN_PACKET_SIZE) {
147                 fprintf(stderr, "DHCP packet is too small (%d < %d)",
148                       packet->data_len, MIN_PACKET_SIZE);
149                 rad_free(&packet);
150                 return NULL;
151         }
152
153         if (packet->data[0] != 1) {
154                 fprintf(stderr, "Cannot receive DHCP server messages");
155                 rad_free(&packet);
156                 return NULL;
157         }
158
159         if (packet->data[1] != 1) {
160                 fprintf(stderr, "DHCP can only receive ethernet requests, not type %02x",
161                       packet->data[1]);
162                 rad_free(&packet);
163                 return NULL;
164         }
165
166         if (packet->data[2] != 6) {
167                 fprintf(stderr, "Ethernet HW length is wrong length %d\n",
168                         packet->data[2]);
169                 rad_free(&packet);
170                 return NULL;
171         }
172
173         memcpy(&magic, packet->data + 236, 4);
174         magic = ntohl(magic);
175         if (magic != DHCP_OPTION_MAGIC_NUMBER) {
176                 fprintf(stderr, "Cannot do BOOTP\n");
177                 rad_free(&packet);
178                 return NULL;
179         }
180
181         /*
182          *      Create unique keys for the packet.
183          */
184         memcpy(&magic, packet->data + 4, 4);
185         packet->id = ntohl(magic);
186
187         /*
188          *      Check that it's a known packet type.
189          */
190         if ((packet->data[240] != 53) ||
191             (packet->data[241] != 1) ||
192             (packet->data[242] == 0) ||
193             (packet->data[242] > 8)) {
194                 fprintf(stderr, "Unknown, or badly formatted DHCP packet\n");
195                 rad_free(&packet);
196                 return NULL;
197         }
198
199         /*
200          *      Create a unique vector from the MAC address and the
201          *      DHCP opcode.  This is a hack for the RADIUS
202          *      infrastructure in the rest of the server.
203          *
204          *      Note: packet->data[2] == 6, which is smaller than
205          *      sizeof(packet->vector)
206          *
207          *      FIXME:  Look for client-identifier in packet,
208          *      and use that, too?
209          */
210         memset(packet->vector, 0, sizeof(packet->vector));
211         memcpy(packet->vector, packet->data + 28, packet->data[2]);
212         packet->vector[packet->data[2]] = packet->data[242];
213
214         /*
215          *      FIXME: for DISCOVER / REQUEST: src_port == dst_port + 1
216          *      FIXME: for OFFER / ACK       : src_port = dst_port - 1
217          */
218
219         packet->code = PW_DHCP_OFFSET | packet->data[242];
220
221         /*
222          *      Unique keys are xid, client mac, and client ID?
223          */
224
225         /*
226          *      FIXME: More checks, like DHCP packet type?
227          */
228
229         sizeof_dst = sizeof(dst);
230         /*
231          *      This should never fail...
232          */
233         getsockname(sockfd, (struct sockaddr *) &dst, &sizeof_dst);
234         
235         fr_sockaddr2ipaddr(&src, sizeof_src, &packet->src_ipaddr, &port);
236         packet->src_port = port;
237
238         fr_sockaddr2ipaddr(&dst, sizeof_dst, &packet->dst_ipaddr, &port);
239         packet->dst_port = port;
240
241         if (fr_debug_flag > 1) {
242                 char type_buf[64];
243                 const char *name = type_buf;
244                 char src_ip_buf[256], dst_ip_buf[256];
245                 
246                 if ((packet->code >= PW_DHCP_DISCOVER) &&
247                     (packet->code <= PW_DHCP_INFORM)) {
248                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
249                 } else {
250                         snprintf(type_buf, sizeof(type_buf), "%d",
251                                  packet->code - PW_DHCP_OFFSET);
252                 }
253
254                 printf("Received %s of id %u from %s:%d to %s:%d\n",
255                        name, (unsigned int) packet->id,
256                        inet_ntop(packet->src_ipaddr.af,
257                                  &packet->src_ipaddr.ipaddr,
258                                  src_ip_buf, sizeof(src_ip_buf)),
259                        packet->src_port,
260                        inet_ntop(packet->dst_ipaddr.af,
261                                  &packet->dst_ipaddr.ipaddr,
262                                  dst_ip_buf, sizeof(dst_ip_buf)),
263                        packet->dst_port);
264                 fflush(stdout);
265         }
266
267         return packet;
268 }
269
270
271 /*
272  *      Send a DHCP packet.
273  */
274 int fr_dhcp_send(RADIUS_PACKET *packet)
275 {
276         struct sockaddr_storage dst;
277         struct sockaddr_storage src;
278         socklen_t               sizeof_dst;
279         socklen_t               sizeof_src;
280
281         fr_ipaddr2sockaddr(&packet->dst_ipaddr, packet->dst_port,
282                            &dst, &sizeof_dst);
283
284         /*
285          *      Currently unused...
286          */
287         fr_ipaddr2sockaddr(&packet->src_ipaddr, packet->src_port,
288                            &src, &sizeof_src);
289
290         /*
291          *      Assume that the packet is encoded before sending it.
292          */
293         return sendto(packet->sockfd, packet->data, packet->data_len, 0,
294                       (struct sockaddr *)&dst, sizeof_dst);
295 }
296
297
298 int fr_dhcp_decode(RADIUS_PACKET *packet)
299 {
300         int i;
301         ssize_t total;
302         uint8_t *p;
303         uint32_t giaddr;
304         VALUE_PAIR *head, *vp, **tail;
305         VALUE_PAIR *maxms, *mtu;
306         char buffer[2048];
307
308         head = NULL;
309         tail = &head;
310         p = packet->data;
311         
312         if ((fr_debug_flag > 2) && fr_log_fp) {
313                 for (i = 0; i < packet->data_len; i++) {
314                         if ((i & 0x0f) == 0x00) fprintf(stderr, "%d: ", i);
315                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
316                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
317                 }
318                 fprintf(fr_log_fp, "\n");
319         }
320
321         if (packet->data[1] != 1) {
322                 fprintf(stderr, "Packet is not Ethernet: %u\n",
323                       packet->data[1]);
324                 return -1;
325         }
326
327         /*
328          *      Decode the header.
329          */
330         for (i = 0; i < 14; i++) {
331                 vp = pairmake(dhcp_header_names[i], NULL, T_OP_EQ);
332                 if (!vp) {
333                         fprintf(stderr, "Parse error %s\n", fr_strerror);
334                         pairfree(&head);
335                         return -1;
336                 }
337
338
339                 if ((i == 11) && 
340                     (packet->data[1] == 1) &&
341                     (packet->data[2] == 6)) {
342                         vp->type = PW_TYPE_ETHERNET;
343                 }
344
345                 switch (vp->type) {
346                 case PW_TYPE_BYTE:
347                         vp->vp_integer = p[0];
348                         vp->length = 1;
349                         break;
350                         
351                 case PW_TYPE_SHORT:
352                         vp->vp_integer = (p[0] << 8) | p[1];
353                         vp->length = 2;
354                         break;
355                         
356                 case PW_TYPE_INTEGER:
357                         memcpy(&vp->vp_integer, p, 4);
358                         vp->vp_integer = ntohl(vp->vp_integer);
359                         vp->length = 4;
360                         break;
361                         
362                 case PW_TYPE_IPADDR:
363                         memcpy(&vp->vp_ipaddr, p, 4);
364                         vp->length = 4;
365                         break;
366                         
367                 case PW_TYPE_STRING:
368                         memcpy(vp->vp_strvalue, p, dhcp_header_sizes[i]);
369                         vp->vp_strvalue[dhcp_header_sizes[i]] = '\0';
370                         vp->length = strlen(vp->vp_strvalue);
371                         if (vp->length == 0) {
372                                 pairfree(&vp);
373                         }
374                         break;
375                         
376                 case PW_TYPE_OCTETS:
377                         memcpy(vp->vp_octets, p, packet->data[2]);
378                         vp->length = packet->data[2];
379                         break;
380                         
381                 case PW_TYPE_ETHERNET:
382                         memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
383                         vp->length = sizeof(vp->vp_ether);
384                         break;
385                         
386                 default:
387                         fprintf(stderr, "BAD TYPE %d\n", vp->type);
388                         pairfree(&vp);
389                         break;
390                 }
391                 p += dhcp_header_sizes[i];
392
393                 if (!vp) continue;
394                 
395                 if (fr_debug_flag > 1) {
396                         vp_prints(buffer, sizeof(buffer), vp);
397                         fprintf(stderr, "\t%s\n", buffer);
398                 }
399                 *tail = vp;
400                 tail = &vp->next;
401         }
402         
403         /*
404          *      Loop over the options.
405          */
406         p = packet->data + 240;
407         total = packet->data_len - 240;
408
409         while (total > 0) {
410                 int num_entries, alen;
411                 DICT_ATTR *da;
412
413                 if (*p == 0) break;
414                 if (*p == 255) break; /* end of options signifier */
415
416                 if (p[1] >= 253) {
417                         fprintf(stderr, "Attribute too long %u %u\n",
418                               p[0], p[1]);
419                         goto do_next;
420                 }
421                                 
422                 da = dict_attrbyvalue(DHCP2ATTR(p[0]));
423                 if (!da) {
424                         fprintf(stderr, "Attribute not in our dictionary: %u\n",
425                               p[0]);
426                 do_next:
427                         total -= 2;
428                         total -= p[1];
429                         p += p[1];
430                         p += 2;
431                         continue;
432                 }
433
434                 vp = NULL;
435                 num_entries = 1;
436                 alen = p[1];
437                 p += 2;
438
439                 if (da->flags.array) {
440                         switch (da->type) {
441                         case PW_TYPE_BYTE:
442                                 num_entries = alen;
443                                 alen = 1;
444                                 break;
445
446                         case PW_TYPE_SHORT:
447                                 if ((alen & 0x01) != 0) goto raw;
448                                 num_entries = alen / 2;
449                                 alen = 2;
450                                 break;
451
452                         case PW_TYPE_IPADDR:
453                         case PW_TYPE_INTEGER:
454                         case PW_TYPE_DATE:
455                                 if ((alen & 0x03) != 0) goto raw;
456                                 num_entries = alen / 4;
457                                 alen = 4;
458                                 break;
459
460                         default:
461                                 break; /* really an internal sanity failure */
462                         }
463                 } else {
464                         num_entries = 1;
465
466                         switch (da->type) {
467                         case PW_TYPE_BYTE:
468                                 if (alen != 1) goto raw;
469                                 break;
470
471                         case PW_TYPE_SHORT:
472                                 if (alen != 2) goto raw;
473                                 break;
474
475                         case PW_TYPE_IPADDR:
476                         case PW_TYPE_INTEGER:
477                         case PW_TYPE_DATE:
478                                 if (alen != 4) goto raw;
479                                 break;
480
481                         default:
482                                 break;
483                         }
484                 }
485
486                 for (i = 0; i < num_entries; i++) {
487                         vp = pairmake(da->name, NULL, T_OP_EQ);
488                         if (!vp) {
489                                 fprintf(stderr, "Cannot build attribute %s\n",
490                                         fr_strerror);
491                                 pairfree(&head);
492                                 return -1;
493                         }
494
495                         /*
496                          *      Hacks for ease of use.
497                          */
498                         if ((da->attr == DHCP2ATTR(0x3d)) &&
499                             !da->flags.array &&
500                             (alen == 7) && (*p == 1) && (num_entries == 1)) {
501                                 vp->type = PW_TYPE_ETHERNET;
502                                 memcpy(vp->vp_octets, p + 1, 6);
503                         } else
504
505                                 switch (vp->type) {
506                                 case PW_TYPE_BYTE:
507                                         vp->vp_integer = p[0];
508                                         break;
509                                 
510                                 case PW_TYPE_SHORT:
511                                         vp->vp_integer = (p[0] << 8) | p[1];
512                                         break;
513
514                                 case PW_TYPE_INTEGER:
515                                         memcpy(&vp->vp_integer, p, 4);
516                                         vp->vp_integer = ntohl(vp->vp_integer);
517                                         break;
518
519                                 case PW_TYPE_IPADDR:
520                                         memcpy(&vp->vp_ipaddr, p , 4);
521                                         vp->length = 4;
522                                         break;
523
524                                 case PW_TYPE_STRING:
525                                         memcpy(vp->vp_strvalue, p , alen);
526                                         vp->vp_strvalue[alen] = '\0';
527                                         break;
528
529                                 raw:
530                                         vp = pairmake(da->name, NULL, T_OP_EQ);
531                                         if (!vp) {
532                                                 fprintf(stderr, "Cannot build attribute %s\n", fr_strerror);
533                                                 pairfree(&head);
534                                                 return -1;
535                                         }
536
537                                         vp->type = PW_TYPE_OCTETS;
538                                 
539                                 case PW_TYPE_OCTETS:
540                                         memcpy(vp->vp_octets, p, alen);
541                                         break;
542                                 
543                                 default:
544                                         fprintf(stderr, "Internal sanity check %d %d\n", vp->type, __LINE__);
545                                         pairfree(&vp);
546                                         break;
547                                 } /* switch over type */
548                                 
549                         vp->length = alen;
550
551                         if (fr_debug_flag > 1) {
552                                 vp_prints(buffer, sizeof(buffer), vp);
553                                 fprintf(stderr, "\t%s\n", buffer);
554                         }
555
556                         *tail = vp;
557                         tail = &vp->next;
558                         p += alen;
559                 } /* loop over array entries */
560                 
561                 total -= 2;
562                 total -= (alen * num_entries);
563         }
564
565         /*
566          *      If DHCP request, set ciaddr to zero.
567          */
568
569         /*
570          *      Set broadcast flag for broken vendors, but only if
571          *      giaddr isn't set.
572          */
573         memcpy(&giaddr, packet->data + 24, sizeof(giaddr));
574         if (giaddr == htonl(INADDR_ANY)) {
575                 /*
576                  *      DHCP Opcode is request
577                  */
578                 vp = pairfind(head, DHCP2ATTR(256));
579                 if (vp && vp->lvalue == 3) {
580                         /*
581                          *      Vendor is "MSFT 98"
582                          */
583                         vp = pairfind(head, DHCP2ATTR(63));
584                         if (vp && (strcmp(vp->vp_strvalue, "MSFT 98") == 0)) {
585                                 vp = pairfind(head, DHCP2ATTR(262));
586
587                                 /*
588                                  *      Reply should be broadcast.
589                                  */
590                                 if (vp) vp->lvalue |= 0x8000;
591                                 packet->data[10] |= 0x80;                       
592                         }
593                 }
594         }
595
596         /*
597          *      FIXME: Nuke attributes that aren't used in the normal
598          *      header for discover/requests.
599          */
600         packet->vps = head;
601
602         /*
603          *      Client can request a LARGER size, but not a smaller
604          *      one.  They also cannot request a size larger than MTU.
605          */
606         maxms = pairfind(packet->vps, DHCP2ATTR(57));
607         mtu = pairfind(packet->vps, DHCP2ATTR(26));
608
609         if (mtu && (mtu->vp_integer < DEFAULT_PACKET_SIZE)) {
610                 fprintf(stderr, "DHCP Fatal: Client says MTU is smaller than minimum permitted by the specification.");
611                 return -1;
612         }
613
614         if (maxms && (maxms->vp_integer < DEFAULT_PACKET_SIZE)) {
615                 fprintf(stderr, "DHCP WARNING: Client says maximum message size is smaller than minimum permitted by the specification: fixing it");
616                 maxms->vp_integer = DEFAULT_PACKET_SIZE;
617         }
618
619         if (maxms && mtu && (maxms->vp_integer > mtu->vp_integer)) {
620                 fprintf(stderr, "DHCP WARNING: Client says MTU is smaller than maximum message size: fixing it");
621                 maxms->vp_integer = mtu->vp_integer;
622         }
623
624         if (fr_debug_flag) fflush(stdout);
625
626         return 0;
627 }
628
629
630 static int attr_cmp(const void *one, const void *two)
631 {
632         const VALUE_PAIR * const *a = one;
633         const VALUE_PAIR * const *b = two;
634
635         /*
636          *      DHCP-Message-Type is first, for simplicity.
637          */
638         if (((*a)->attribute == DHCP2ATTR(53)) &&
639             (*b)->attribute != DHCP2ATTR(53)) return -1;
640
641         /*
642          *      Relay-Agent is last
643          */
644         if (((*a)->attribute == DHCP2ATTR(82)) &&
645             (*b)->attribute != DHCP2ATTR(82)) return +1;
646
647         return ((*a)->attribute - (*b)->attribute);
648 }
649
650
651 static size_t fr_dhcp_vp2attr(VALUE_PAIR *vp, uint8_t *p, size_t room)
652 {
653         size_t length;
654         uint32_t lvalue;
655
656         /*
657          *      FIXME: Check room!
658          */
659         room = room;            /* -Wunused */
660
661         /*
662          *      Search for all attributes of the same
663          *      type, and pack them into the same
664          *      attribute.
665          */
666         switch (vp->type) {
667         case PW_TYPE_BYTE:
668                 length = 1;
669                 *p = vp->vp_integer & 0xff;
670                 break;
671                 
672         case PW_TYPE_SHORT:
673                 length = 2;
674                 p[0] = (vp->vp_integer >> 8) & 0xff;
675                 p[1] = vp->vp_integer & 0xff;
676                 break;
677                 
678         case PW_TYPE_INTEGER:
679                 length = 4;
680                 lvalue = htonl(vp->vp_integer);
681                 memcpy(p, &lvalue, 4);
682                 break;
683                 
684         case PW_TYPE_IPADDR:
685                 length = 4;
686                 memcpy(p, &vp->vp_ipaddr, 4);
687                 break;
688                 
689         case PW_TYPE_ETHERNET:
690                 length = 6;
691                 memcpy(p, &vp->vp_ether, 6);
692                 break;
693                 
694         case PW_TYPE_STRING:
695                 memcpy(p, vp->vp_strvalue, vp->length);
696                 length = vp->length;
697                 break;
698                 
699         case PW_TYPE_OCTETS:
700                 memcpy(p, vp->vp_octets, vp->length);
701                 length = vp->length;
702                 break;
703                 
704         default:
705                 fprintf(stderr, "BAD TYPE2 %d\n", vp->type);
706                 length = 0;
707                 break;
708         }
709
710         return length;
711 }
712
713 int fr_dhcp_encode(RADIUS_PACKET *packet, RADIUS_PACKET *original)
714 {
715         int i, num_vps;
716         uint8_t *p;
717         VALUE_PAIR *vp;
718         uint32_t lvalue, mms;
719         size_t dhcp_size, length;
720         dhcp_packet_t *dhcp;
721         char buffer[1024];
722
723         if (packet->data) return 0;
724
725         packet->data = malloc(MAX_PACKET_SIZE);
726         if (!packet->data) return -1;
727
728         packet->data_len = MAX_PACKET_SIZE;
729
730         if (packet->code == 0) packet->code = PW_DHCP_NAK;
731
732         /*
733          *      FIXME: allow it to send client packets.
734          */
735         if (!original) {
736                 fr_strerror_printf("Need original to send response!");
737                 return -1;
738         }
739
740         if (fr_debug_flag > 1) {
741                 char type_buf[64];
742                 const char *name = type_buf;
743                 char src_ip_buf[256], dst_ip_buf[256];
744                 
745                 if ((packet->code >= PW_DHCP_DISCOVER) &&
746                     (packet->code <= PW_DHCP_INFORM)) {
747                         name = dhcp_message_types[packet->code - PW_DHCP_OFFSET];
748                 } else {
749                         snprintf(type_buf, sizeof(type_buf), "%d",
750                                  packet->code - PW_DHCP_OFFSET);
751                 }
752
753                 printf("Sending %s of id %u from %s:%d to %s:%d\n",
754                        name, (unsigned int) packet->id,
755                        inet_ntop(packet->src_ipaddr.af,
756                                  &packet->src_ipaddr.ipaddr,
757                                  src_ip_buf, sizeof(src_ip_buf)),
758                        packet->src_port,
759                        inet_ntop(packet->dst_ipaddr.af,
760                                  &packet->dst_ipaddr.ipaddr,
761                                  dst_ip_buf, sizeof(dst_ip_buf)),
762                        packet->dst_port);
763                 fflush(stdout);
764         }
765
766         p = packet->data;
767
768         mms = DEFAULT_PACKET_SIZE; /* maximum message size */
769
770         /*
771          *      Client can request a LARGER size, but not a smaller
772          *      one.  They also cannot request a size larger than MTU.
773          */
774         vp = pairfind(original->vps, DHCP2ATTR(57));
775         if (vp && (vp->vp_integer > mms)) {
776                 mms = vp->vp_integer;
777                 
778                 if (mms > MAX_PACKET_SIZE) mms = MAX_PACKET_SIZE;
779         }
780
781         /*
782          *      RFC 3118: Authentication option.
783          */
784         vp = pairfind(packet->vps, DHCP2ATTR(90));
785         if (vp) {
786                 if (vp->length < 2) {
787                         memset(vp->vp_octets + vp->length, 0,
788                                2 - vp->length);
789                         vp->length = 2;
790                 }
791
792                 if (vp->length < 3) {
793                         struct timeval tv;
794
795                         gettimeofday(&tv, NULL);
796                         vp->vp_octets[2] = 0;
797                         timeval2ntp(&tv, vp->vp_octets + 3);
798                         vp->length = 3 + 8;
799                 }
800
801                 /*
802                  *      Configuration token (clear-text token)
803                  */
804                 if (vp->vp_octets[0] == 0) {
805                         VALUE_PAIR *pass;
806                         vp->vp_octets[1] = 0;
807
808                         pass = pairfind(packet->vps, PW_CLEARTEXT_PASSWORD);
809                         if (pass) {
810                                 length = pass->length;
811                                 if ((length + 11) > sizeof(vp->vp_octets)) {
812                                         length -= ((length + 11) - sizeof(vp->vp_octets));
813                                 }
814                                 memcpy(vp->vp_octets + 11, pass->vp_strvalue,
815                                        length);
816                                 vp->length = length + 11;
817                         } else {
818                                 vp->length = 11 + 8;
819                                 memset(vp->vp_octets + 11, 8, 0);
820                                 vp->length = 11 + 8;
821                         }
822                 } else {        /* we don't support this type! */
823                         fprintf(stderr, "DHCP-Authentication %d unsupported\n",
824                                 vp->vp_octets[0]);
825                 }
826         }
827
828         if (!original) {
829                 *p++ = 1;       /* client message */
830         } else {
831                 *p++ = 2;       /* server message */
832         }
833         *p++ = 1;               /* hardware type = ethernet */
834         *p++ = original->data[2];
835         *p++ = 0;               /* hops */
836
837         if (!original) {        /* Xid */
838                 lvalue = fr_rand();
839                 memcpy(p, &lvalue, 4);
840         } else {
841                 memcpy(p, original->data + 4, 4);
842         }
843         p += 4;
844
845         memset(p, 0, 2);        /* secs are zero */
846         p += 2;
847
848         memcpy(p, original->data + 10, 6); /* copy flags && ciaddr */
849
850         /*
851          *      Allow the admin to set the broadcast flag.
852          */
853         vp = pairfind(packet->vps, DHCP2ATTR(262));
854         if (vp) {
855                 p[0] |= (vp->vp_integer & 0xff00) >> 8;
856                 p[1] |= (vp->vp_integer & 0xff);
857         }
858
859         p += 6;
860
861         /*
862          *      Set client IP address.
863          */
864         vp = pairfind(packet->vps, DHCP2ATTR(264)); /* Your IP address */
865         if (vp) {
866                 lvalue = vp->vp_ipaddr;
867         } else {
868                 lvalue = htonl(INADDR_ANY);
869         }
870         memcpy(p, &lvalue, 4);  /* your IP address */
871         p += 4;
872
873         memset(p, 0, 4);        /* siaddr is zero */
874         p += 4;
875
876         memcpy(p, original->data + 24, 4); /* copy gateway IP address */
877         p += 4;
878
879         memcpy(p, original->data + 28, DHCP_CHADDR_LEN);
880         p += DHCP_CHADDR_LEN;
881
882         memset(p, 0, 192);      /* bootp legacy */
883         p += 192;
884
885         lvalue = htonl(DHCP_OPTION_MAGIC_NUMBER); /* DHCP magic number */
886         memcpy(p, &lvalue, 4);
887         p += 4;
888
889         /*
890          *      Print the header.
891          */
892         if (fr_debug_flag > 1) {
893                 uint8_t *pp = p;
894
895                 p = packet->data;
896
897                 for (i = 0; i < 14; i++) {
898                         vp = pairmake(dhcp_header_names[i], NULL, T_OP_EQ);
899                         if (!vp) {
900                                 fprintf(stderr, "Parse error %s\n", fr_strerror);
901                                 return -1;
902                         }
903                         
904                         switch (vp->type) {
905                         case PW_TYPE_BYTE:
906                                 vp->vp_integer = p[0];
907                                 vp->length = 1;
908                                 break;
909                                 
910                         case PW_TYPE_SHORT:
911                                 vp->vp_integer = (p[0] << 8) | p[1];
912                                 vp->length = 2;
913                                 break;
914                                 
915                         case PW_TYPE_INTEGER:
916                                 memcpy(&vp->vp_integer, p, 4);
917                                 vp->vp_integer = ntohl(vp->vp_integer);
918                                 vp->length = 4;
919                                 break;
920                                 
921                         case PW_TYPE_IPADDR:
922                                 memcpy(&vp->vp_ipaddr, p, 4);
923                                 vp->length = 4;
924                                 break;
925                                 
926                         case PW_TYPE_STRING:
927                                 memcpy(vp->vp_strvalue, p, dhcp_header_sizes[i]);
928                                 vp->vp_strvalue[dhcp_header_sizes[i]] = '\0';
929                                 vp->length = strlen(vp->vp_strvalue);
930                                 break;
931                                 
932                         case PW_TYPE_OCTETS: /* only for Client HW Address */
933                                 memcpy(vp->vp_octets, p, packet->data[2]);
934                                 vp->length = packet->data[2];
935                                 break;
936                                 
937                         case PW_TYPE_ETHERNET: /* only for Client HW Address */
938                                 memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
939                                 vp->length = sizeof(vp->vp_ether);
940                                 break;
941                                 
942                         default:
943                                 fprintf(stderr, "Internal sanity check failed %d %d\n", vp->type, __LINE__);
944                                 pairfree(&vp);
945                                 break;
946                         }
947                         
948                         p += dhcp_header_sizes[i];
949                         
950                         vp_prints(buffer, sizeof(buffer), vp);
951                         fprintf(stderr, "\t%s\n", buffer);
952                         pairfree(&vp);
953                 }
954
955                 /*
956                  *      Jump over DHCP magic number, response, etc.
957                  */
958                 p = pp;
959         }
960
961         /*
962          *      Before packing the attributes, re-order them so that
963          *      the array ones are all contiguous.  This simplifies
964          *      the later code.
965          */
966         num_vps = 0;
967         for (vp = packet->vps; vp != NULL; vp = vp->next) {
968                 num_vps++;
969         }
970         if (num_vps > 1) {
971                 VALUE_PAIR **array, **last;
972
973                 array = malloc(num_vps * sizeof(VALUE_PAIR *));
974                 
975                 i = 0;
976                 for (vp = packet->vps; vp != NULL; vp = vp->next) {
977                         array[i++] = vp;
978                 }
979                 
980                 /*
981                  *      Sort the attributes.
982                  */
983                 qsort(array, (size_t) num_vps, sizeof(VALUE_PAIR *),
984                       attr_cmp);
985                 
986                 last = &packet->vps;
987                 for (i = 0; i < num_vps; i++) {
988                         *last = array[i];
989                         array[i]->next = NULL;
990                         last = &(array[i]->next);
991                 }
992                 free(array);
993         }
994
995         p[0] = 0x35;            /* DHCP-Message-Type */
996         p[1] = 1;
997         p[2] = packet->code - PW_DHCP_OFFSET;
998         p += 3;
999
1000         /*
1001          *      Pack in the attributes.
1002          */
1003         vp = packet->vps;
1004         while (vp) {
1005                 int num_entries = 1;
1006                 
1007                 VALUE_PAIR *same;
1008                 uint8_t *plength, *pattr;
1009
1010                 if (!IS_DHCP_ATTR(vp)) goto next;
1011                 if (((vp->attribute & 0xffff) > 255) &&
1012                     (DHCP_BASE_ATTR(vp->attribute) != PW_DHCP_OPTION_82)) goto next;
1013
1014                 length = vp->length;
1015
1016                 for (same = vp->next; same != NULL; same = same->next) {
1017                         if (same->attribute != vp->attribute) break;
1018                         num_entries++;
1019                 }
1020
1021                 /*
1022                  *      For client-identifier
1023                  */
1024                 if ((vp->type == PW_TYPE_ETHERNET) &&
1025                     (vp->length == 6) &&
1026                     (num_entries == 1)) {
1027                         vp->type = PW_TYPE_OCTETS;
1028                         memmove(vp->vp_octets + 1, vp->vp_octets, 6);
1029                         vp->vp_octets[0] = 1;
1030                 }
1031
1032                 pattr = p;
1033                 *(p++) = vp->attribute & 0xff;
1034                 plength = p;
1035                 *(p++) = 0;     /* header isn't included in attr length */
1036
1037                 if (DHCP_BASE_ATTR(vp->attribute) == PW_DHCP_OPTION_82) {
1038                         *(p++) = DHCP_UNPACK_OPTION1(vp->attribute);
1039                         *(p++) = 0;
1040                         *plength = 2;
1041                 }
1042
1043                 for (i = 0; i < num_entries; i++) {
1044                         if (fr_debug_flag > 1) {
1045                                 vp_prints(buffer, sizeof(buffer), vp);
1046                                 fprintf(stderr, "\t%s\n", buffer);
1047                         }
1048
1049                         length = fr_dhcp_vp2attr(vp, p, 0);
1050
1051                         /*
1052                          *      This will never happen due to FreeRADIUS
1053                          *      limitations: sizeof(vp->vp_octets) < 255
1054                          */
1055                         if (length > 255) {
1056                                 fprintf(stderr, "WARNING Ignoring too long attribute %s!\n", vp->name);
1057                                 break;
1058                         }
1059
1060                         /*
1061                          *      More than one attribute of the same type
1062                          *      in a row: they are packed together
1063                          *      into the same TLV.  If we overflow,
1064                          *      go bananas!
1065                          */
1066                         if ((*plength + length) > 255) {
1067                                 fprintf(stderr, "WARNING Ignoring too long attribute %s!\n", vp->name);
1068                                 break;
1069                         }
1070                         
1071                         *plength += length;
1072                         p += length;
1073
1074                         if (vp->next &&
1075                             (vp->next->attribute == vp->attribute))
1076                                 vp = vp->next;
1077                 } /* loop over num_entries */
1078
1079                 if (DHCP_BASE_ATTR(vp->attribute) == PW_DHCP_OPTION_82) {
1080                         plength[2] = plength[0] - 2;
1081                 }
1082
1083         next:
1084                 vp = vp->next;
1085         }
1086
1087         p[0] = 0xff;            /* end of option option */
1088         p[1] = 0x00;
1089         p += 2;
1090         dhcp_size = p - packet->data;
1091
1092         /*
1093          *      FIXME: if (dhcp_size > mms),
1094          *        then we put the extra options into the "sname" and "file"
1095          *        fields, AND set the "end option option" in the "options"
1096          *        field.  We also set the "overload option",
1097          *        and put options into the "file" field, followed by
1098          *        the "sname" field.  Where each option is completely
1099          *        enclosed in the "file" and/or "sname" field, AND
1100          *        followed by the "end of option", and MUST be followed
1101          *        by padding option.
1102          *
1103          *      Yuck.  That sucks...
1104          */
1105         packet->data_len = dhcp_size;
1106
1107         packet->dst_ipaddr.af = AF_INET;
1108         packet->src_ipaddr.af = AF_INET;
1109
1110         packet->dst_port = original->src_port;
1111         packet->src_port = original->dst_port;
1112
1113         /*
1114          *      Note that for DHCP, we NEVER send the response to the
1115          *      source IP address of the request.  It may have
1116          *      traversed multiple relays, and we need to send the request
1117          *      to the relay closest to the client.
1118          *
1119          *      if giaddr, send to giaddr.
1120          *      if NAK, send broadcast packet
1121          *      if ciaddr, unicast to ciaddr
1122          *      if flags & 0x8000, broadcast (client request)
1123          *      if sent from 0.0.0.0, broadcast response
1124          *      unicast to client yiaddr
1125          */
1126
1127         /*
1128          *      FIXME: alignment issues.  We likely don't want to
1129          *      de-reference the packet structure directly..
1130          */
1131         dhcp = (dhcp_packet_t *) original->data;
1132
1133         if (dhcp->giaddr != htonl(INADDR_ANY)) {
1134                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->giaddr;
1135
1136                 /*
1137                  *      Gateways send FROM 68 to 67, and we
1138                  *      respond FROM 67 to 67... not to 68.
1139                  */
1140                 packet->dst_port = original->dst_port;
1141
1142         } else if (packet->code == PW_DHCP_NAK) {
1143                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
1144                 
1145         } else if (dhcp->ciaddr != htonl(INADDR_ANY)) {
1146                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->ciaddr;
1147
1148         } else if ((dhcp->flags & 0x8000) != 0) {
1149                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
1150
1151         } else if (packet->dst_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY)) {
1152                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
1153
1154         } else {
1155                 packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->yiaddr;
1156         }
1157
1158         /*
1159          *      FIXME: This may set it to broadcast, which we don't
1160          *      want.  Instead, set it to the real address of the
1161          *      socket.
1162          */
1163         packet->src_ipaddr = original->dst_ipaddr;
1164
1165         packet->sockfd = original->sockfd;
1166
1167         if (packet->data_len < DEFAULT_PACKET_SIZE) {
1168                 memset(packet->data + packet->data_len, 0,
1169                        DEFAULT_PACKET_SIZE - packet->data_len);
1170                 packet->data_len = DEFAULT_PACKET_SIZE;
1171         }
1172
1173         if ((fr_debug_flag > 2) && fr_log_fp) {
1174                 for (i = 0; i < packet->data_len; i++) {
1175                         if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", i);
1176                         fprintf(fr_log_fp, "%02x ", packet->data[i]);
1177                         if ((i & 0x0f) == 0x0f) fprintf(fr_log_fp, "\n");
1178                 }
1179                 fprintf(fr_log_fp, "\n");
1180         }
1181
1182         return 0;
1183 }
1184 #endif /* WITH_DHCP */