~ubuntu-branches/ubuntu/natty/freeradius/natty-updates

« back to all changes in this revision

Viewing changes to src/lib/dhcp.c

  • Committer: Bazaar Package Importer
  • Author(s): Josip Rodin
  • Date: 2009-11-23 03:57:37 UTC
  • mfrom: (1.2.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 28.
  • Revision ID: james.westby@ubuntu.com-20091123035737-zsgtzhfych8hir68
Tags: 2.1.7+dfsg-1
* Adopting the package, closes: #536623.
* New upstream version, closes: #513484.
  + Fixes the blooper in unlang evaluation logic, closes: #526175.
* Used quilt (and added README.source), and moved upstream file patching
  into debian/patches/. The source is no longer in collab-maint git
  (to make it simpler for me to finally get this out the door), but
  kept the .gitignore should we need that again.
* Dropped the dialup_admin/bin/backup_radacct patch (integrated upstream).
* Dropped the raddb/Makefile patch (problem no longer exists upstream).
* Dropped the lib/packet.c lib/radius.c main/listen.c patches (was from
  upstream 2.0.5 anyway).
* Dropped references to otp.conf, it no longer exists upstream.
  Keep removing the conffile statoverride in prerm.
* Dropped references to snmp.conf, it no longer exists upstream.
  Keep removing the conffile statoverride in prerm.
* Ship /etc/freeradius/modules/* in the freeradius package.
* Stop shipping sites-enabled symlinks in the package and instead create
  them only on initial install, thanks to Matej Vela, closes: #533396.
* Add export PATH="${PATH:+$PATH:}/usr/sbin:/sbin" to the init script
  at the request of John Morrissey, closes: #550143.
* Stop installing /var/run/freeradius in the package to silence Lintian.
  The init script already recreates it at will.
* Remove executable bit from example.pl to silence Lintian.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * dhcp.c       Functions to send/receive dhcp packets.
3
3
 *
4
 
 * Version:     $Id: dhcp.c,v 1.1 2008/04/20 14:51:25 aland Exp $
 
4
 * Version:     $Id$
5
5
 *
6
6
 *   This program is free software; you can redistribute it and/or modify
7
7
 *   it under the terms of the GNU General Public License as published by
22
22
 */
23
23
 
24
24
#include        <freeradius-devel/ident.h>
25
 
RCSID("$Id: dhcp.c,v 1.1 2008/04/20 14:51:25 aland Exp $")
 
25
RCSID("$Id$")
26
26
 
27
27
#include <freeradius-devel/libradius.h>
28
28
#include <freeradius-devel/udpfromto.h>
35
35
#define DHCP_VEND_LEN   (308)
36
36
#define DHCP_OPTION_MAGIC_NUMBER (0x63825363)
37
37
 
 
38
#ifndef INADDR_BROADCAST
 
39
#define INADDR_BROADCAST INADDR_NONE
 
40
#endif
 
41
 
38
42
typedef struct dhcp_packet_t {
39
43
        uint8_t         opcode;
40
44
        uint8_t         htype;
48
52
        uint32_t        siaddr; /* 20 */
49
53
        uint32_t        giaddr; /* 24 */
50
54
        uint8_t         chaddr[DHCP_CHADDR_LEN]; /* 28 */
51
 
        char            sname[DHCP_SNAME_LEN]; /* 44 */
52
 
        char            file[DHCP_FILE_LEN]; /* 108 */
 
55
        uint8_t         sname[DHCP_SNAME_LEN]; /* 44 */
 
56
        uint8_t         file[DHCP_FILE_LEN]; /* 108 */
53
57
        uint32_t        option_format; /* 236 */
54
58
        uint8_t         options[DHCP_VEND_LEN];
55
59
} dhcp_packet_t;
56
60
 
 
61
typedef struct dhcp_option_t {
 
62
        uint8_t         code;
 
63
        uint8_t         length;
 
64
} dhcp_option_t;
 
65
 
57
66
/*
58
67
 *      INADDR_ANY : 68 -> INADDR_BROADCAST : 67        DISCOVER
59
68
 *      INADDR_BROADCAST : 68 <- SERVER_IP : 67         OFFER
106
115
 *      Some clients silently ignore responses less than 300 bytes.
107
116
 */
108
117
#define MIN_PACKET_SIZE (244)
109
 
#define DEFAULT_PACKET_SIZE (576)
 
118
#define DEFAULT_PACKET_SIZE (300)
110
119
#define MAX_PACKET_SIZE (1500 - 40)
111
120
 
 
121
#define DHCP_OPTION_FIELD (0)
 
122
#define DHCP_FILE_FIELD   (1)
 
123
#define DHCP_SNAME_FIELD  (2)
 
124
 
 
125
static uint8_t *dhcp_get_option(dhcp_packet_t *packet, size_t packet_size,
 
126
                                unsigned int option)
 
127
                                
 
128
{
 
129
        int overload = 0;
 
130
        int field = DHCP_OPTION_FIELD;
 
131
        size_t where, size;
 
132
        uint8_t *data = packet->options;
 
133
 
 
134
        where = 0;
 
135
        size = packet_size - offsetof(dhcp_packet_t, options);
 
136
        data = &packet->options[where];
 
137
 
 
138
        while (where < size) {
 
139
                if (data[0] == 0) { /* padding */
 
140
                        where++;
 
141
                        continue;
 
142
                }
 
143
 
 
144
                if (data[0] == 255) { /* end of options */
 
145
                        if ((field == DHCP_OPTION_FIELD) &&
 
146
                            (overload & DHCP_FILE_FIELD)) {
 
147
                                data = packet->file;
 
148
                                where = 0;
 
149
                                size = sizeof(packet->file);
 
150
                                field = DHCP_FILE_FIELD;
 
151
                                continue;
 
152
 
 
153
                        } else if ((field == DHCP_FILE_FIELD) &&
 
154
                                   (overload && DHCP_SNAME_FIELD)) {
 
155
                                data = packet->sname;
 
156
                                where = 0;
 
157
                                size = sizeof(packet->sname);
 
158
                                field = DHCP_SNAME_FIELD;
 
159
                                continue;
 
160
                        }
 
161
 
 
162
                        return NULL;
 
163
                }
 
164
 
 
165
                /*
 
166
                 *      We MUST have a real option here.
 
167
                 */
 
168
                if ((where + 2) > size) {
 
169
                        fr_strerror_printf("Options overflow field at %u",
 
170
                                           data - (uint8_t *) packet);
 
171
                        return NULL;
 
172
                }
 
173
 
 
174
                if ((where + 2 + data[1]) > size) {
 
175
                        fr_strerror_printf("Option length overflows field at %u",
 
176
                                           data - (uint8_t *) packet);
 
177
                        return NULL;
 
178
                }
 
179
 
 
180
                if (data[0] == option) return data;
 
181
 
 
182
                if (data[0] == 52) { /* overload sname and/or file */
 
183
                        overload = data[3];
 
184
                }
 
185
 
 
186
                where += data[1] + 2;
 
187
                data += data[1] + 2;
 
188
        }
 
189
 
 
190
        return NULL;
 
191
}
 
192
 
112
193
/*
113
194
 *      DHCPv4 is only for IPv4.  Broadcast only works if udpfromto is
114
195
 *      defined.
118
199
        uint32_t                magic;
119
200
        struct sockaddr_storage src;
120
201
        struct sockaddr_storage dst;
121
 
        socklen_t               sizeof_src = sizeof(src);
122
 
        socklen_t               sizeof_dst = sizeof(dst);
 
202
        socklen_t               sizeof_src;
 
203
        socklen_t               sizeof_dst;
123
204
        RADIUS_PACKET           *packet;
124
 
 
125
 
        memset(&src, 0, sizeof_src);
126
 
        memset(&dst, 0, sizeof_dst);
 
205
        int port;
 
206
        uint8_t                 *code;
127
207
 
128
208
        packet = rad_alloc(0);
129
209
        if (!packet) return NULL;
136
216
        }
137
217
 
138
218
        packet->sockfd = sockfd;
 
219
        sizeof_src = sizeof(src);
 
220
#ifdef WITH_UDPFROMTO
 
221
        sizeof_dst = sizeof(dst);
 
222
        packet->data_len = recvfromto(sockfd, packet->data, MAX_PACKET_SIZE, 0,
 
223
                                      (struct sockaddr *)&src, &sizeof_src,
 
224
                                      (struct sockaddr *)&dst, &sizeof_dst);
 
225
#else
139
226
        packet->data_len = recvfrom(sockfd, packet->data, MAX_PACKET_SIZE, 0,
140
227
                                    (struct sockaddr *)&src, &sizeof_src);
 
228
#endif
 
229
 
141
230
        if (packet->data_len <= 0) {
142
231
                fprintf(stderr, "Failed reading DHCP socket: %s", strerror(errno));
143
232
                rad_free(&packet);
185
274
        memcpy(&magic, packet->data + 4, 4);
186
275
        packet->id = ntohl(magic);
187
276
 
188
 
        /*
189
 
         *      Check that it's a known packet type.
190
 
         */
191
 
        if ((packet->data[240] != 53) ||
192
 
            (packet->data[241] != 1) ||
193
 
            (packet->data[242] == 0) ||
194
 
            (packet->data[242] >= 8)) {
195
 
                fprintf(stderr, "Unknown, or badly formatted DHCP packet\n");
196
 
                rad_free(&packet);
197
 
                return NULL;
198
 
        }
 
277
        code = dhcp_get_option((dhcp_packet_t *) packet->data,
 
278
                               packet->data_len, 53);
 
279
        if (!code) {
 
280
                fr_strerror_printf("No message-type option was found in the packet");
 
281
                rad_free(&packet);
 
282
                return NULL;
 
283
        }
 
284
 
 
285
        if ((code[1] < 1) || (code[2] == 0) || (code[2] > 8)) {
 
286
                fr_strerror_printf("Unknown value for message-type option");
 
287
                rad_free(&packet);
 
288
                return NULL;
 
289
        }
 
290
 
 
291
        packet->code = code[2] | PW_DHCP_OFFSET;
199
292
 
200
293
        /*
201
294
         *      Create a unique vector from the MAC address and the
210
303
         */
211
304
        memset(packet->vector, 0, sizeof(packet->vector));
212
305
        memcpy(packet->vector, packet->data + 28, packet->data[2]);
213
 
        packet->vector[packet->data[2]] = packet->data[242];
 
306
        packet->vector[packet->data[2]] = packet->code & 0xff;
214
307
 
215
308
        /*
216
309
         *      FIXME: for DISCOVER / REQUEST: src_port == dst_port + 1
217
310
         *      FIXME: for OFFER / ACK       : src_port = dst_port - 1
218
311
         */
219
312
 
220
 
        packet->code = PW_DHCP_OFFSET | packet->data[242];
221
 
 
222
313
        /*
223
314
         *      Unique keys are xid, client mac, and client ID?
224
315
         */
227
318
         *      FIXME: More checks, like DHCP packet type?
228
319
         */
229
320
 
230
 
        {
231
 
                struct sockaddr_in      *s4;
232
 
                struct sockaddr_storage si;
233
 
                socklen_t si_len = sizeof(si);
234
 
 
235
 
                /*
236
 
                 *      This should never fail...
237
 
                 */
238
 
                getsockname(sockfd, (struct sockaddr *) &si, &si_len);
239
 
 
240
 
                s4 = (struct sockaddr_in *)&src;
241
 
                packet->src_ipaddr.af = AF_INET;
242
 
                packet->src_ipaddr.ipaddr.ip4addr = s4->sin_addr;
243
 
                packet->src_port = ntohs(s4->sin_port);
244
 
 
245
 
                s4 = (struct sockaddr_in *)&si;
246
 
                packet->dst_ipaddr.af = AF_INET;
247
 
                packet->dst_ipaddr.ipaddr.ip4addr = s4->sin_addr;
248
 
                packet->dst_port = ntohs(s4->sin_port);
249
 
        }
250
 
 
251
 
        if (librad_debug > 1) {
 
321
        sizeof_dst = sizeof(dst);
 
322
 
 
323
#ifndef WITH_UDPFROMTO
 
324
        /*
 
325
         *      This should never fail...
 
326
         */
 
327
        getsockname(sockfd, (struct sockaddr *) &dst, &sizeof_dst);
 
328
#endif
 
329
        
 
330
        fr_sockaddr2ipaddr(&dst, sizeof_dst, &packet->dst_ipaddr, &port);
 
331
        packet->dst_port = port;
 
332
 
 
333
        fr_sockaddr2ipaddr(&src, sizeof_src, &packet->src_ipaddr, &port);
 
334
        packet->src_port = port;
 
335
 
 
336
        if (fr_debug_flag > 1) {
252
337
                char type_buf[64];
253
338
                const char *name = type_buf;
254
339
                char src_ip_buf[256], dst_ip_buf[256];
261
346
                                 packet->code - PW_DHCP_OFFSET);
262
347
                }
263
348
 
264
 
                printf("Received %s of id %u from %s:%d to %s:%d\n",
 
349
                printf("Received %s of id %08x from %s:%d to %s:%d\n",
265
350
                       name, (unsigned int) packet->id,
266
351
                       inet_ntop(packet->src_ipaddr.af,
267
352
                                 &packet->src_ipaddr.ipaddr,
284
369
int fr_dhcp_send(RADIUS_PACKET *packet)
285
370
{
286
371
        struct sockaddr_storage dst;
 
372
        socklen_t               sizeof_dst;
 
373
#ifdef WITH_UDPFROMTO
287
374
        struct sockaddr_storage src;
288
 
        socklen_t               sizeof_dst = sizeof(dst);
289
 
        socklen_t               sizeof_src = sizeof(src);
290
 
 
291
 
        memset(&src, 0, sizeof(src));
292
 
        memset(&dst, 0, sizeof(dst));
293
 
 
294
 
        /*
295
 
         *      Only IPv4 is supported.
296
 
         */
297
 
        {
298
 
                struct sockaddr_in      *s4;
299
 
 
300
 
                s4 = (struct sockaddr_in *)&dst;
301
 
                sizeof_dst = sizeof(struct sockaddr_in);
302
 
 
303
 
                s4->sin_family = AF_INET;
304
 
                s4->sin_addr = packet->dst_ipaddr.ipaddr.ip4addr;
305
 
                s4->sin_port = htons(packet->dst_port);
306
 
 
307
 
                s4 = (struct sockaddr_in *)&src;
308
 
                sizeof_src = sizeof(struct sockaddr_in);
309
 
 
310
 
                s4->sin_family = AF_INET;
311
 
                s4->sin_addr = packet->src_ipaddr.ipaddr.ip4addr;
312
 
                s4->sin_port = htons(packet->src_port);
313
 
        }
314
 
 
 
375
        socklen_t               sizeof_src;
 
376
#endif
 
377
 
 
378
        fr_ipaddr2sockaddr(&packet->dst_ipaddr, packet->dst_port,
 
379
                           &dst, &sizeof_dst);
 
380
 
 
381
#ifndef WITH_UDPFROMTO
315
382
        /*
316
383
         *      Assume that the packet is encoded before sending it.
317
384
         */
318
385
        return sendto(packet->sockfd, packet->data, packet->data_len, 0,
319
386
                      (struct sockaddr *)&dst, sizeof_dst);
 
387
#else
 
388
        fr_ipaddr2sockaddr(&packet->src_ipaddr, packet->src_port,
 
389
                           &src, &sizeof_src);
 
390
 
 
391
        return sendfromto(packet->sockfd,
 
392
                          packet->data, packet->data_len, 0,
 
393
                          (struct sockaddr *)&src, sizeof_src,
 
394
                          (struct sockaddr *)&dst, sizeof_dst);
 
395
#endif
320
396
}
321
397
 
322
398
 
334
410
        tail = &head;
335
411
        p = packet->data;
336
412
        
337
 
        if ((librad_debug > 2) && fr_log_fp) {
 
413
        if ((fr_debug_flag > 2) && fr_log_fp) {
338
414
                for (i = 0; i < packet->data_len; i++) {
339
415
                        if ((i & 0x0f) == 0x00) fprintf(stderr, "%d: ", i);
340
416
                        fprintf(fr_log_fp, "%02x ", packet->data[i]);
355
431
        for (i = 0; i < 14; i++) {
356
432
                vp = pairmake(dhcp_header_names[i], NULL, T_OP_EQ);
357
433
                if (!vp) {
358
 
                        fprintf(stderr, "Parse error %s\n", librad_errstr);
 
434
                        fprintf(stderr, "Parse error %s\n", fr_strerror());
359
435
                        pairfree(&head);
360
436
                        return -1;
361
437
                }
404
480
                        break;
405
481
                        
406
482
                case PW_TYPE_ETHERNET:
407
 
                        memcpy(vp->vp_ether, p, packet->data[2]);
408
 
                        vp->length = packet->data[2];
 
483
                        memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
 
484
                        vp->length = sizeof(vp->vp_ether);
409
485
                        break;
410
486
                        
411
487
                default:
417
493
 
418
494
                if (!vp) continue;
419
495
                
420
 
                if (librad_debug > 1) {
 
496
                if (fr_debug_flag > 1) {
421
497
                        vp_prints(buffer, sizeof(buffer), vp);
422
498
                        fprintf(stderr, "\t%s\n", buffer);
423
499
                }
431
507
        p = packet->data + 240;
432
508
        total = packet->data_len - 240;
433
509
 
 
510
        /*
 
511
         *      FIXME: This should also check sname && file fields.
 
512
         *      See the dhcp_get_option() function above.
 
513
         */
434
514
        while (total > 0) {
435
515
                int num_entries, alen;
436
516
                DICT_ATTR *da;
512
592
                        vp = pairmake(da->name, NULL, T_OP_EQ);
513
593
                        if (!vp) {
514
594
                                fprintf(stderr, "Cannot build attribute %s\n",
515
 
                                        librad_errstr);
 
595
                                        fr_strerror());
516
596
                                pairfree(&head);
517
597
                                return -1;
518
598
                        }
554
634
                                raw:
555
635
                                        vp = pairmake(da->name, NULL, T_OP_EQ);
556
636
                                        if (!vp) {
557
 
                                                fprintf(stderr, "Cannot build attribute %s\n", librad_errstr);
 
637
                                                fprintf(stderr, "Cannot build attribute %s\n", fr_strerror());
558
638
                                                pairfree(&head);
559
639
                                                return -1;
560
640
                                        }
573
653
                                
574
654
                        vp->length = alen;
575
655
 
576
 
                        if (librad_debug > 1) {
 
656
                        if (fr_debug_flag > 1) {
577
657
                                vp_prints(buffer, sizeof(buffer), vp);
578
658
                                fprintf(stderr, "\t%s\n", buffer);
579
659
                        }
646
726
                maxms->vp_integer = mtu->vp_integer;
647
727
        }
648
728
 
649
 
        if (librad_debug) fflush(stdout);
 
729
        if (fr_debug_flag) fflush(stdout);
650
730
 
651
731
        return 0;
652
732
}
754
834
 
755
835
        if (packet->code == 0) packet->code = PW_DHCP_NAK;
756
836
 
757
 
        if (librad_debug > 1) {
 
837
        /*
 
838
         *      FIXME: allow it to send client packets.
 
839
         */
 
840
        if (!original) {
 
841
                fr_strerror_printf("Need original to send response!");
 
842
                return -1;
 
843
        }
 
844
 
 
845
        packet->dst_ipaddr.af = AF_INET;
 
846
        packet->src_ipaddr.af = AF_INET;
 
847
 
 
848
        packet->dst_port = original->src_port;
 
849
        packet->src_port = original->dst_port;
 
850
 
 
851
        /*
 
852
         *      Note that for DHCP, we NEVER send the response to the
 
853
         *      source IP address of the request.  It may have
 
854
         *      traversed multiple relays, and we need to send the request
 
855
         *      to the relay closest to the client.
 
856
         *
 
857
         *      if giaddr, send to giaddr.
 
858
         *      if NAK, send broadcast packet
 
859
         *      if ciaddr, unicast to ciaddr
 
860
         *      if flags & 0x8000, broadcast (client request)
 
861
         *      if sent from 0.0.0.0, broadcast response
 
862
         *      unicast to client yiaddr
 
863
         */
 
864
 
 
865
        /*
 
866
         *      FIXME: alignment issues.  We likely don't want to
 
867
         *      de-reference the packet structure directly..
 
868
         */
 
869
        dhcp = (dhcp_packet_t *) original->data;
 
870
 
 
871
        if (dhcp->giaddr != htonl(INADDR_ANY)) {
 
872
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->giaddr;
 
873
 
 
874
                if (dhcp->giaddr != htonl(INADDR_LOOPBACK)) {
 
875
                        packet->dst_port = original->dst_port;
 
876
                } else {
 
877
                        packet->dst_port = original->src_port; /* debugging */
 
878
                }
 
879
 
 
880
        } else if (packet->code == PW_DHCP_NAK) {
 
881
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
 
882
                
 
883
        } else if (dhcp->ciaddr != htonl(INADDR_ANY)) {
 
884
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->ciaddr;
 
885
 
 
886
        } else if ((dhcp->flags & 0x8000) != 0) {
 
887
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
 
888
 
 
889
        } else if (packet->dst_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY)) {
 
890
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
 
891
 
 
892
        } else if (dhcp->yiaddr != htonl(INADDR_ANY)) {
 
893
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->yiaddr;
 
894
 
 
895
        } else {
 
896
                /* leave destination IP alone. */
 
897
        }
 
898
 
 
899
        /*
 
900
         *      Rewrite the source IP to be our own, if we know it.
 
901
         */
 
902
        if (packet->src_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_BROADCAST)) {
 
903
                packet->src_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_ANY);
 
904
        }
 
905
 
 
906
        if (fr_debug_flag > 1) {
758
907
                char type_buf[64];
759
908
                const char *name = type_buf;
760
909
                char src_ip_buf[256], dst_ip_buf[256];
767
916
                                 packet->code - PW_DHCP_OFFSET);
768
917
                }
769
918
 
770
 
                printf("Sending %s of id %u from %s:%d to %s:%d\n",
 
919
                printf("Sending %s of id %08x from %s:%d to %s:%d\n",
771
920
                       name, (unsigned int) packet->id,
772
921
                       inet_ntop(packet->src_ipaddr.af,
773
922
                                 &packet->src_ipaddr.ipaddr,
833
982
                                vp->length = length + 11;
834
983
                        } else {
835
984
                                vp->length = 11 + 8;
836
 
                                memset(vp->vp_octets + 11, 8, 0);
 
985
                                memset(vp->vp_octets + 11, 0, 8);
837
986
                                vp->length = 11 + 8;
838
987
                        }
839
988
                } else {        /* we don't support this type! */
863
1012
        p += 2;
864
1013
 
865
1014
        memcpy(p, original->data + 10, 6); /* copy flags && ciaddr */
 
1015
 
 
1016
        /*
 
1017
         *      Allow the admin to set the broadcast flag.
 
1018
         */
 
1019
        vp = pairfind(packet->vps, DHCP2ATTR(262));
 
1020
        if (vp) {
 
1021
                p[0] |= (vp->vp_integer & 0xff00) >> 8;
 
1022
                p[1] |= (vp->vp_integer & 0xff);
 
1023
        }
 
1024
 
866
1025
        p += 6;
867
1026
 
868
1027
        /*
877
1036
        memcpy(p, &lvalue, 4);  /* your IP address */
878
1037
        p += 4;
879
1038
 
880
 
        memset(p, 0, 4);        /* siaddr is zero */
881
 
        p += 4;
882
 
 
883
 
        memset(p, 0, 4);        /* gateway address is zero */
884
 
        p += 4;
885
 
 
886
 
        /*
887
 
         *      FIXME: allow it to send client packets.
888
 
         */
889
 
        if (!original) {
890
 
                librad_log("Need original to send response!");
891
 
                return -1;
 
1039
        vp = pairfind(packet->vps, DHCP2ATTR(265)); /* server IP address */
 
1040
        if (!vp) vp = pairfind(packet->vps, DHCP2ATTR(54)); /* identifier */
 
1041
        if (vp) {
 
1042
                lvalue = vp->vp_ipaddr;
 
1043
        } else {
 
1044
                lvalue = htonl(INADDR_ANY);
892
1045
        }
 
1046
        memcpy(p, &lvalue, 4);  /* Server IP address */
 
1047
        p += 4;
 
1048
 
 
1049
        memcpy(p, original->data + 24, 4); /* copy gateway IP address */
 
1050
        p += 4;
893
1051
 
894
1052
        memcpy(p, original->data + 28, DHCP_CHADDR_LEN);
895
1053
        p += DHCP_CHADDR_LEN;
904
1062
        /*
905
1063
         *      Print the header.
906
1064
         */
907
 
        if (librad_debug > 1) {
 
1065
        if (fr_debug_flag > 1) {
908
1066
                uint8_t *pp = p;
909
1067
 
910
1068
                p = packet->data;
912
1070
                for (i = 0; i < 14; i++) {
913
1071
                        vp = pairmake(dhcp_header_names[i], NULL, T_OP_EQ);
914
1072
                        if (!vp) {
915
 
                                fprintf(stderr, "Parse error %s\n", librad_errstr);
 
1073
                                fprintf(stderr, "Parse error %s\n", fr_strerror());
916
1074
                                return -1;
917
1075
                        }
918
1076
                        
949
1107
                                vp->length = packet->data[2];
950
1108
                                break;
951
1109
                                
 
1110
                        case PW_TYPE_ETHERNET: /* only for Client HW Address */
 
1111
                                memcpy(vp->vp_ether, p, sizeof(vp->vp_ether));
 
1112
                                vp->length = sizeof(vp->vp_ether);
 
1113
                                break;
 
1114
                                
952
1115
                        default:
953
1116
                                fprintf(stderr, "Internal sanity check failed %d %d\n", vp->type, __LINE__);
954
1117
                                pairfree(&vp);
968
1131
                p = pp;
969
1132
        }
970
1133
 
971
 
        vp = pairfind(packet->vps, DHCP2ATTR(53));
972
 
        if (vp && (vp->vp_integer != (packet->code - PW_DHCP_OFFSET))) {
973
 
                fprintf(stderr, "Message-Type doesn't match! %d %d\n",
974
 
                        packet->code, vp->vp_integer);
975
 
        }
976
 
        pairdelete(&packet->vps, DHCP2ATTR(0x35));
977
 
 
978
1134
        /*
979
1135
         *      Before packing the attributes, re-order them so that
980
1136
         *      the array ones are all contiguous.  This simplifies
1025
1181
                uint8_t *plength, *pattr;
1026
1182
 
1027
1183
                if (!IS_DHCP_ATTR(vp)) goto next;
 
1184
                if (vp->attribute == DHCP2ATTR(53)) goto next; /* already done */
1028
1185
                if (((vp->attribute & 0xffff) > 255) &&
1029
1186
                    (DHCP_BASE_ATTR(vp->attribute) != PW_DHCP_OPTION_82)) goto next;
1030
1187
 
1058
1215
                }
1059
1216
 
1060
1217
                for (i = 0; i < num_entries; i++) {
1061
 
                        if (librad_debug > 1) {
 
1218
                        if (fr_debug_flag > 1) {
1062
1219
                                vp_prints(buffer, sizeof(buffer), vp);
1063
1220
                                fprintf(stderr, "\t%s\n", buffer);
1064
1221
                        }
1121
1278
         */
1122
1279
        packet->data_len = dhcp_size;
1123
1280
 
1124
 
        packet->dst_ipaddr.af = AF_INET;
1125
 
        packet->src_ipaddr.af = AF_INET;
1126
 
 
1127
 
        packet->dst_port = original->src_port;
1128
 
        packet->src_port = original->dst_port;
1129
 
 
1130
 
        /*
1131
 
         *      Note that for DHCP, we NEVER send the response to the
1132
 
         *      source IP address of the request.  It may have
1133
 
         *      traversed multiple relays, and we need to send the request
1134
 
         *      to the relay closest to the client.
1135
 
         *
1136
 
         *      if giaddr, send to giaddr.
1137
 
         *      if NAK, send broadcast packet
1138
 
         *      if ciaddr, unicast to ciaddr
1139
 
         *      if flags & 0x8000, broadcast (client request)
1140
 
         *      if sent from 0.0.0.0, broadcast response
1141
 
         *      unicast to client yiaddr
1142
 
         */
1143
 
 
1144
 
        /*
1145
 
         *      FIXME: alignment issues.  We likely don't want to
1146
 
         *      de-reference the packet structure directly..
1147
 
         */
1148
 
        dhcp = (dhcp_packet_t *) original->data;
1149
 
 
1150
 
        if (dhcp->giaddr != htonl(INADDR_ANY)) {
1151
 
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->giaddr;
1152
 
 
1153
 
        } else if (packet->code == PW_DHCP_NAK) {
1154
 
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
1155
 
                
1156
 
        } else if (dhcp->ciaddr != htonl(INADDR_ANY)) {
1157
 
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->ciaddr;
1158
 
 
1159
 
        } else if ((dhcp->flags & 0x8000) != 0) {
1160
 
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
1161
 
 
1162
 
        } else if (packet->dst_ipaddr.ipaddr.ip4addr.s_addr == htonl(INADDR_ANY)) {
1163
 
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = htonl(INADDR_BROADCAST);
1164
 
 
1165
 
        } else {
1166
 
                packet->dst_ipaddr.ipaddr.ip4addr.s_addr = dhcp->yiaddr;
1167
 
        }
1168
 
 
1169
1281
        /*
1170
1282
         *      FIXME: This may set it to broadcast, which we don't
1171
1283
         *      want.  Instead, set it to the real address of the
1181
1293
                packet->data_len = DEFAULT_PACKET_SIZE;
1182
1294
        }
1183
1295
 
1184
 
        if ((librad_debug > 2) && fr_log_fp) {
 
1296
        if ((fr_debug_flag > 2) && fr_log_fp) {
1185
1297
                for (i = 0; i < packet->data_len; i++) {
1186
1298
                        if ((i & 0x0f) == 0x00) fprintf(fr_log_fp, "%d: ", i);
1187
1299
                        fprintf(fr_log_fp, "%02x ", packet->data[i]);