2
* dhcpcd - DHCP client daemon -
3
* Copyright (C) 1996 - 1997 Yoichi Hariguchi <yoichi@fore.com>
4
* Copyright (C) January, 1998 Sergei Viznyuk <sv@phystech.com>
5
* Copyright (C) 2005 Roy Marples <uberlord@gentoo.org>
6
* Copyright (C) 2005 Simon Kelley <simon@thekelleys.org.uk>
8
* dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
10
* This is free software; you can redistribute it and/or modify it
11
* under the terms of the GNU General Public License as published by
12
* the Free Software Foundation; either version 2 of the License, or
13
* (at your option) any later version.
15
* This program is distributed in the hope that it will be useful, but
16
* WITHOUT ANY WARRANTY; without even the implied warranty of
17
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18
* See the GNU General Public License for more details.
20
* You should have received a copy of the GNU General Public License
21
* along with this program; if not, write to the Free Software
22
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25
#include <sys/types.h>
26
#include <sys/socket.h>
28
#include <sys/ioctl.h>
30
#include <sys/utsname.h>
32
#include <net/if_arp.h>
34
#include <net/if_packet.h>
36
#include <linux/if_packet.h>
38
#include <net/route.h>
51
#include "pathnames.h"
54
extern char *ProgramName;
55
extern char *IfName,*IfNameExt;
56
extern int IfName_len,IfNameExt_len;
57
extern char *HostName;
58
extern unsigned char *ClassID;
59
extern int ClassID_len;
60
extern unsigned char *ClientID;
61
extern int ClientID_len;
64
extern unsigned LeaseTime;
65
extern int SetDomainName;
66
extern int SetHostName;
67
extern int SendSecondDiscover;
68
extern unsigned short ip_id;
69
extern void *(*currState)();
70
extern time_t TimeOut;
71
extern unsigned nleaseTime;
72
extern struct in_addr inform_ipaddr;
73
extern int DoCheckSum;
75
extern int resolv_renamed,yp_renamed,ntp_renamed;
76
extern int InitialHostName_len,InitialDomainName_len;
77
extern char *InitialHostName,*InitialDomainName;
78
extern int DownIfaceOnStop;
80
extern char resolv_file[128];
81
extern char resolv_file_sv[128];
82
extern char ntp_file[128];
83
extern char ntp_file_sv[128];
84
extern char nis_file[128];
85
extern char nis_file_sv[128];
88
extern unsigned char ClientMACaddr[ETH_ALEN];
89
extern int ClientMACaddr_ind;
92
extern int SetFQDNHostName;
100
int deleteDhcpCache();
101
void execute_on_change(char *prm);
107
dhcpOptions DhcpOptions;
108
dhcpInterface DhcpIface;
109
udpipMessage UdpIpMsgSend,UdpIpMsgRecv;
111
unsigned char ClientHwAddr[ETH_ALEN];
113
const struct ip *ipSend=(struct ip *)((struct udpiphdr *)UdpIpMsgSend.udpipmsg)->ip;
114
const struct ip *ipRecv=(struct ip *)((struct udpiphdr *)UdpIpMsgRecv.udpipmsg)->ip;
115
const dhcpMessage *DhcpMsgSend = (dhcpMessage *)&UdpIpMsgSend.udpipmsg[sizeof(udpiphdr)];
116
dhcpMessage *DhcpMsgRecv = (dhcpMessage *)&UdpIpMsgRecv.udpipmsg[sizeof(udpiphdr)];
118
static short int saved_if_flags = 0;
120
/*****************************************************************************/
121
/* Decode an RFC3397 DNS search order option into a space
122
seperated string. Returns length of string (including
123
terminating zero) or zero on error. out may be NULL
124
to just determine output length. */
126
static unsigned int decodeSearch(u_char *p, int len, u_char *out)
129
unsigned int count = 0, l, hops;
137
unsigned int label_type = l & 0xc0;
138
if (label_type == 0x80 || label_type == 0x40)
140
else if (label_type == 0xc0) /* pointer */
145
/* save source of first jump. */
158
/* straightforward name segment, add with '.' */
170
/* change last dot to space */
178
/* change last space to zero terminator */
185
int parseDhcpMsgRecv() /* this routine parses dhcp message received */
190
register u_char *p = DhcpMsgRecv->options+4;
191
unsigned char *end = DhcpMsgRecv->options+sizeof(DhcpMsgRecv->options);
193
/* Force T1 and T2 to 0: either new values will be in message, or they
194
will need to be recalculated from lease time */
195
if ( DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] > 0 )
196
memset(DhcpOptions.val[dhcpT1value],0,DhcpOptions.len[dhcpT1value]);
197
if ( DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] > 0 )
198
memset(DhcpOptions.val[dhcpT2value],0,DhcpOptions.len[dhcpT2value]);
202
case endOption: goto swend;
203
case padOption: p++; break;
208
if (p + 2 + p[1] >= end)
209
goto swend; /* corrupt packet */
211
if (len = decodeSearch(p+2, p[1], NULL))
213
if ( DhcpOptions.val[*p] )
214
free(DhcpOptions.val[*p]);
215
DhcpOptions.val[*p] = malloc(len);
216
DhcpOptions.len[*p] = len;
217
decodeSearch(p+2, p[1], DhcpOptions.val[*p]);
226
if (p + 2 + p[1] >= end)
227
goto swend; /* corrupt packet */
229
if ( DhcpOptions.len[*p] == p[1] )
230
memcpy(DhcpOptions.val[*p],p+2,p[1]);
233
DhcpOptions.len[*p] = p[1];
234
if ( DhcpOptions.val[*p] )
235
free(DhcpOptions.val[*p]);
238
DhcpOptions.val[*p] = malloc(p[1]+1);
239
memset(DhcpOptions.val[*p],0,p[1]+1);
240
memcpy(DhcpOptions.val[*p],p+2,p[1]);
247
fprintf(stderr,"parseDhcpMsgRecv: %d options received:\n",DhcpOptions.num);
249
if ( DhcpOptions.val[i] )
252
case 1: /* subnet mask */
253
case 3: /* routers on subnet */
254
case 4: /* time servers */
255
case 5: /* name servers */
256
case 6: /* dns servers */
257
case 28:/* broadcast addr */
258
case 33:/* staticRoute */
259
case 41:/* NIS servers */
260
case 42:/* NTP servers */
261
case 50:/* dhcpRequestdIPaddr */
262
case 54:/* dhcpServerIdentifier */
263
for (j=0;j<DhcpOptions.len[i];j+=4)
264
fprintf(stderr,"i=%-2d len=%-2d option = %u.%u.%u.%u\n",
265
i,DhcpOptions.len[i],
266
((unsigned char *)DhcpOptions.val[i])[0+j],
267
((unsigned char *)DhcpOptions.val[i])[1+j],
268
((unsigned char *)DhcpOptions.val[i])[2+j],
269
((unsigned char *)DhcpOptions.val[i])[3+j]);
271
case 2: /* time offset */
272
case 51:/* dhcpAddrLeaseTime */
273
case 57:/* dhcpMaxMsgSize */
274
case 58:/* dhcpT1value */
275
case 59:/* dhcpT2value */
276
fprintf(stderr,"i=%-2d len=%-2d option = %d\n",
277
i,DhcpOptions.len[i],
278
ntohl(*(int *)DhcpOptions.val[i]));
280
case 23:/* defaultIPTTL */
281
case 29:/* performMaskdiscovery */
282
case 31:/* performRouterdiscovery */
283
case 53:/* dhcpMessageType */
284
fprintf(stderr,"i=%-2d len=%-2d option = %u\n",
285
i,DhcpOptions.len[i],*(unsigned char *)DhcpOptions.val[i]);
287
case 81:/* dhcpFQDNHostName */
288
fprintf(stderr,"i=%-2d len=%-2d flags = %02X rcode1 = %02X rcode2 = %02X name = \"%s\"\n",
289
i,DhcpOptions.len[i],
290
((unsigned char *)DhcpOptions.val[i])[0],
291
((unsigned char *)DhcpOptions.val[i])[1],
292
((unsigned char *)DhcpOptions.val[i])[2],
293
((char *)DhcpOptions.val[i])+3);
296
fprintf(stderr,"i=%-2d len=%-2d option = \"%s\"\n",
297
i,DhcpOptions.len[i],(char *)DhcpOptions.val[i]);
300
DhcpMsgRecv->yiaddr = %u.%u.%u.%u\n\
301
DhcpMsgRecv->siaddr = %u.%u.%u.%u\n\
302
DhcpMsgRecv->giaddr = %u.%u.%u.%u\n\
303
DhcpMsgRecv->sname = \"%s\"\n\
304
ServerHardwareAddr = %02X.%02X.%02X.%02X.%02X.%02X\n",
305
((unsigned char *)&DhcpMsgRecv->yiaddr)[0],
306
((unsigned char *)&DhcpMsgRecv->yiaddr)[1],
307
((unsigned char *)&DhcpMsgRecv->yiaddr)[2],
308
((unsigned char *)&DhcpMsgRecv->yiaddr)[3],
309
((unsigned char *)&DhcpMsgRecv->siaddr)[0],
310
((unsigned char *)&DhcpMsgRecv->siaddr)[1],
311
((unsigned char *)&DhcpMsgRecv->siaddr)[2],
312
((unsigned char *)&DhcpMsgRecv->siaddr)[3],
313
((unsigned char *)&DhcpMsgRecv->giaddr)[0],
314
((unsigned char *)&DhcpMsgRecv->giaddr)[1],
315
((unsigned char *)&DhcpMsgRecv->giaddr)[2],
316
((unsigned char *)&DhcpMsgRecv->giaddr)[3],
318
UdpIpMsgRecv.ethhdr.ether_shost[0],
319
UdpIpMsgRecv.ethhdr.ether_shost[1],
320
UdpIpMsgRecv.ethhdr.ether_shost[2],
321
UdpIpMsgRecv.ethhdr.ether_shost[3],
322
UdpIpMsgRecv.ethhdr.ether_shost[4],
323
UdpIpMsgRecv.ethhdr.ether_shost[5]);
325
if ( ! DhcpMsgRecv->yiaddr ) DhcpMsgRecv->yiaddr=DhcpMsgSend->ciaddr;
326
if ( ! DhcpOptions.val[dhcpServerIdentifier] ) /* did not get dhcpServerIdentifier */
327
{ /* make it the same as IP address of the sender */
328
DhcpOptions.val[dhcpServerIdentifier] = malloc(4);
329
memcpy(DhcpOptions.val[dhcpServerIdentifier],&ipRecv->ip_src.s_addr,4);
330
DhcpOptions.len[dhcpServerIdentifier] = 4;
334
"dhcpServerIdentifier option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
335
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
336
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
337
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
338
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
340
if ( ! DhcpOptions.val[dns] ) /* did not get DNS */
341
{ /* make it the same as dhcpServerIdentifier */
342
DhcpOptions.val[dns] = malloc(4);
343
memcpy(DhcpOptions.val[dns],DhcpOptions.val[dhcpServerIdentifier],4);
344
DhcpOptions.len[dns] = 4;
348
"dns option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
349
((unsigned char *)DhcpOptions.val[dns])[0],
350
((unsigned char *)DhcpOptions.val[dns])[1],
351
((unsigned char *)DhcpOptions.val[dns])[2],
352
((unsigned char *)DhcpOptions.val[dns])[3]);
354
if ( ! DhcpOptions.val[subnetMask] ) /* did not get subnetMask */
356
DhcpOptions.val[subnetMask] = malloc(4);
357
((unsigned char *)DhcpOptions.val[subnetMask])[0] = 255;
359
if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 128 )
361
if ( IN_CLASSA(ntohl(DhcpMsgRecv->yiaddr)) )
364
((unsigned char *)DhcpOptions.val[subnetMask])[1] = 0; /* class A */
365
((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;
366
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0;
370
((unsigned char *)DhcpOptions.val[subnetMask])[1] = 255;
372
if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 192 )
374
if ( IN_CLASSB(ntohl(DhcpMsgRecv->yiaddr)) )
377
((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;/* class B */
378
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0;
382
((unsigned char *)DhcpOptions.val[subnetMask])[2] = 255;
383
if ( IN_CLASSC(ntohl(DhcpMsgRecv->yiaddr)) )
384
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0; /* class C */
386
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 255;
389
DhcpOptions.len[subnetMask] = 4;
393
"subnetMask option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
394
((unsigned char *)DhcpOptions.val[subnetMask])[0],
395
((unsigned char *)DhcpOptions.val[subnetMask])[1],
396
((unsigned char *)DhcpOptions.val[subnetMask])[2],
397
((unsigned char *)DhcpOptions.val[subnetMask])[3]);
399
if ( ! DhcpOptions.val[broadcastAddr] ) /* did not get broadcastAddr */
401
int br = DhcpMsgRecv->yiaddr | ~*((int *)DhcpOptions.val[subnetMask]);
402
DhcpOptions.val[broadcastAddr] = malloc(4);
403
memcpy(DhcpOptions.val[broadcastAddr],&br,4);
404
DhcpOptions.len[broadcastAddr] = 4;
408
"broadcastAddr option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
409
((unsigned char *)DhcpOptions.val[broadcastAddr])[0],
410
((unsigned char *)DhcpOptions.val[broadcastAddr])[1],
411
((unsigned char *)DhcpOptions.val[broadcastAddr])[2],
412
((unsigned char *)DhcpOptions.val[broadcastAddr])[3]);
415
if ( ! DhcpOptions.val[routersOnSubnet] )
417
DhcpOptions.val[routersOnSubnet] = malloc(4);
418
if ( DhcpMsgRecv->giaddr )
419
memcpy(DhcpOptions.val[routersOnSubnet],&DhcpMsgRecv->giaddr,4);
421
memcpy(DhcpOptions.val[routersOnSubnet],DhcpOptions.val[dhcpServerIdentifier],4);
422
DhcpOptions.len[routersOnSubnet] = 4;
426
"routersOnSubnet option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
427
((unsigned char *)DhcpOptions.val[routersOnSubnet])[0],
428
((unsigned char *)DhcpOptions.val[routersOnSubnet])[1],
429
((unsigned char *)DhcpOptions.val[routersOnSubnet])[2],
430
((unsigned char *)DhcpOptions.val[routersOnSubnet])[3]);
433
if ( DhcpOptions.val[dhcpIPaddrLeaseTime] && DhcpOptions.len[dhcpIPaddrLeaseTime] == 4 )
435
if ( *(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime] == 0 )
437
memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
439
syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime=0 in DHCP server response. Assuming %u sec\n",LeaseTime);
443
syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime=%u in DHCP server response.\n",
444
ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]));
446
else /* did not get dhcpIPaddrLeaseTime */
448
DhcpOptions.val[dhcpIPaddrLeaseTime] = malloc(4);
449
memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
450
DhcpOptions.len[dhcpIPaddrLeaseTime] = 4;
453
syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime option is missing in DHCP server response. Assuming %u sec\n",LeaseTime);
455
if ( DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] == 4 )
457
if ( *(unsigned int *)DhcpOptions.val[dhcpT1value] == 0 )
459
unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
461
memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
462
DhcpOptions.len[dhcpT1value] = 4;
464
syslog(LOG_DEBUG,"dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2);
467
else /* did not get T1 */
469
unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
471
DhcpOptions.val[dhcpT1value] = malloc(4);
472
memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
473
DhcpOptions.len[dhcpT1value] = 4;
476
syslog(LOG_DEBUG,"dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2);
478
if ( DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] == 4 )
480
if ( *(unsigned int *)DhcpOptions.val[dhcpT2value] == 0 )
482
unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
484
memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
485
DhcpOptions.len[dhcpT2value] = 4;
487
syslog(LOG_DEBUG,"dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2);
490
else /* did not get T2 */
492
unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
494
DhcpOptions.val[dhcpT2value] = malloc(4);
495
memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
496
DhcpOptions.len[dhcpT2value] = 4;
499
syslog(LOG_DEBUG,"dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2);
501
if ( DhcpOptions.val[dhcpFQDNHostName] )
503
syslog(LOG_DEBUG,"dhcpFQDNHostName response flags = %02X rcode1 = %02X rcode2 = %02X name = \"%s\"\n",
504
((unsigned char *)DhcpOptions.val[dhcpFQDNHostName])[0],
505
((unsigned char *)DhcpOptions.val[dhcpFQDNHostName])[1],
506
((unsigned char *)DhcpOptions.val[dhcpFQDNHostName])[2],
507
((char *)DhcpOptions.val[dhcpFQDNHostName])+3);
511
if ( DebugFlag && (SetFQDNHostName != FQDNdisable) )
513
syslog(LOG_DEBUG,"dhcpFQDNHostName is missing in DHCP server response.\n");
516
if ( DhcpOptions.val[dhcpMessageType] )
517
return *(unsigned char *)DhcpOptions.val[dhcpMessageType];
520
/*****************************************************************************/
523
struct utsname sname;
524
if ( uname(&sname) ) syslog(LOG_ERR,"classIDsetup: uname: %m\n");
525
DhcpIface.class_len=snprintf(DhcpIface.class_id,CLASS_ID_MAX_LEN,
526
"%s %s %s",sname.sysname,sname.release,sname.machine);
528
/*****************************************************************************/
531
unsigned char *c = DhcpIface.client_id;
532
*c++ = dhcpClientIdentifier;
535
*c++ = ClientID_len + 1; /* 1 for the field below */
536
*c++ = 0; /* type: string */
537
memcpy(c,ClientID,ClientID_len);
538
DhcpIface.client_len = ClientID_len + 3;
541
*c++ = ETH_ALEN + 1; /* length: 6 (MAC Addr) + 1 (# field) */
542
*c++ = (TokenRingIf) ? ARPHRD_IEEE802_TR : ARPHRD_ETHER; /* type: Ethernet address */
544
memcpy(c,DhcpIface.chaddr,ETH_ALEN);
546
memcpy(c,ClientHwAddr,ETH_ALEN);
548
DhcpIface.client_len = ETH_ALEN + 3;
550
/*****************************************************************************/
551
void releaseDhcpOptions()
555
if ( DhcpOptions.val[i] ) free(DhcpOptions.val[i]);
556
memset(&DhcpOptions,0,sizeof(dhcpOptions));
558
/*****************************************************************************/
560
static void dumpframe(const char *title, struct packed_ether_header *frame)
565
printf("%s:", title);
566
dp = (unsigned char *)frame;
567
for (i = 0; i < 32; i++)
571
printf("0x%02X ", *dp++);
575
/*****************************************************************************/
576
/***** convert ethernet and token-ring frames *****/
577
int eth2tr(struct packed_ether_header *frame, int datalen)
579
struct trh_hdr *phdr;
581
char trheader[sizeof(struct trh_hdr) - sizeof(phdr->rseg) + sizeof(struct trllc)];
585
dumpframe("eth2tr: Incoming eth frame", frame);
587
memset(trheader, 0, sizeof(trheader));
588
phdr = (struct trh_hdr *)trheader;
590
phdr->fc = LLC_FRAME;
591
memcpy(phdr->daddr, frame->ether_dhost, TR_ALEN);
592
memcpy(phdr->saddr, frame->ether_shost, TR_ALEN);
593
if (phdr->daddr[0] & 0x80)
594
{ /* Destination is a broadcast */
595
phdr->rcf = sizeof(phdr->rcf) | htons(TR_RCF_BROADCAST | 0x70); /* Unlimited frame length */
596
pllc = (struct trllc *)&phdr->rseg[0];
597
phdr->saddr[0] |= TR_RII; /* Set source-route indicator */
598
len = sizeof(trheader);
602
pllc = (struct trllc *)&phdr->rcf;
603
len = sizeof(trheader) - sizeof(phdr->rcf);
605
pllc->dsap = EXTENDED_SAP;
606
pllc->ssap = EXTENDED_SAP;
608
pllc->protid[0] = pllc->protid[1] = pllc->protid[2] = 0;
609
pllc->ethertype = frame->ether_type;
610
memmove((char *)(frame + 1) + (len - sizeof(struct packed_ether_header)),
611
frame + 1, datalen); /* Make room for larger TR header */
612
memcpy(frame, trheader, len); /* Install TR header */
614
dumpframe("eth2tr: Outgoing tr frame", frame);
616
return len + datalen;
618
/*****************************************************************************/
619
int tr2eth(struct packed_ether_header *frame)
626
dumpframe("tr2eth: Incoming tr frame", frame);
628
hdr = *((struct trh_hdr *)frame);
629
if (hdr.saddr[0] & TR_RII)
632
hlen = hdr.rcf & ntohs(TR_RCF_LEN_MASK);
634
printf("rcf = 0x%X SR len %d\n", hdr.rcf, hlen);
636
if (hlen < sizeof(hdr.rcf) || (hlen & 1))
638
hdr.saddr[0] &= ~TR_RII;
640
pllc = (struct trllc *)(((__u8 *)frame) + sizeof(struct trh_hdr) - TR_MAXRIFLEN + hlen);
641
if (pllc->dsap != EXTENDED_SAP || pllc->llc != UI_CMD)
644
goto fake_rif; /* Bug in 2.2.3 kernel */
646
printf("corrupted TR-IP packet of ui=0x%x and dsap 0x%x discarded\n",
647
pllc->llc,pllc->dsap);
651
memcpy(frame->ether_dhost, hdr.daddr, ETH_ALEN);
652
memcpy(frame->ether_shost, hdr.saddr, ETH_ALEN);
653
frame->ether_type = pllc->ethertype;
654
memmove(frame + 1, pllc + 1, IPPACKET_SIZE); /* Move data portion: Overlapping buffer */
656
dumpframe("tr2eth: Outgoing eth frame", frame);
660
/*****************************************************************************/
661
/* Subtract the `struct timeval' values X and Y,
662
storing the result in RESULT.
663
Return 1 if the difference is negative, otherwise 0. */
664
static int timeval_subtract(result,x,y)
665
struct timeval *result,*x,*y;
667
/* Perform the carry for the later subtraction by updating Y. */
668
if (x->tv_usec < y->tv_usec) {
669
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
670
y->tv_usec -= 1000000 * nsec;
673
if (x->tv_usec - y->tv_usec > 1000000) {
674
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
675
y->tv_usec += 1000000 * nsec;
679
/* Compute the time remaining to wait.
680
`tv_usec' is certainly positive. */
681
result->tv_sec = x->tv_sec - y->tv_sec;
682
result->tv_usec = x->tv_usec - y->tv_usec;
684
/* Return 1 if result is negative. */
685
return x->tv_sec < y->tv_sec;
687
/*****************************************************************************/
688
int dhcpSendAndRecv(xid,msg,buildUdpIpMsg)
690
void (*buildUdpIpMsg)(unsigned);
692
struct sockaddr addr;
693
struct timeval begin, current, diff;
694
int i,len,o,timeout=0;
696
const struct udphdr *udpRecv;
697
int j=DHCP_INITIAL_RTO/2;
704
if (j > DHCP_MAX_RTO) j = DHCP_MAX_RTO;
705
memset(&addr,0,sizeof(struct sockaddr));
706
memcpy(addr.sa_data,IfName,IfName_len);
708
if ( TokenRingIf ) /* Here we convert a Eth frame into an TR frame */
709
len = eth2tr(&UdpIpMsgSend.ethhdr,sizeof(udpiphdr)+sizeof(dhcpMessage));
711
len = sizeof(struct packed_ether_header)+sizeof(udpiphdr)+sizeof(dhcpMessage);
712
if ( sendto(dhcpSocket,&UdpIpMsgSend,len,0,
713
&addr,sizeof(struct sockaddr)) == -1 )
715
syslog(LOG_ERR,"sendto: %m\n");
718
gettimeofday(&begin, NULL);
721
while ( peekfd(dhcpSocket,j+i%200000) );
724
struct ip ipRecv_local;
726
memset(&UdpIpMsgRecv,0,sizeof(udpipMessage));
727
o=sizeof(struct sockaddr);
728
len=recvfrom(dhcpSocket,&UdpIpMsgRecv,sizeof(udpipMessage),0,
729
(struct sockaddr *)&addr,&o);
732
syslog(LOG_ERR,"recvfrom: %m\n");
736
{ /* Here we convert a TR frame into an Eth frame */
737
if ( tr2eth(&UdpIpMsgRecv.ethhdr) ) continue;
739
gettimeofday(¤t, NULL);
740
timeval_subtract(&diff, ¤t, &begin);
741
timeout = j - diff.tv_sec*1000000 - diff.tv_usec + random()%200000;
742
if ( UdpIpMsgRecv.ethhdr.ether_type != htons(ETHERTYPE_IP) )
744
tmp_ip = UdpIpMsgRecv.udpipmsg;
745
for (i=0;i<sizeof(struct ip)-2;i+=2)
746
if ( ( UdpIpMsgRecv.udpipmsg[i] == 0x45 ) &&
747
( UdpIpMsgRecv.udpipmsg[i+1] == 0x00 ) )
749
tmp_ip=&(UdpIpMsgRecv.udpipmsg[i]);
752
/* Use local copy because ipRecv is not aligned. */
753
memcpy(&ipRecv_local,((struct udpiphdr *)tmp_ip)->ip,sizeof(struct ip));
754
udpRecv=(struct udphdr *)((char*)(((struct udpiphdr*)tmp_ip)->ip)+sizeof(struct ip));
755
if ( ipRecv_local.ip_p != IPPROTO_UDP ) continue;
758
if ( udpRecv->uh_dport != htons(DHCP_CLIENT_PORT) ) continue;
760
len-=sizeof(struct packed_ether_header);
761
i=(int )ntohs(ipRecv_local.ip_len);
764
if ( DebugFlag ) syslog(LOG_DEBUG,
765
"corrupted IP packet of size=%d and ip_len=%d discarded\n",
769
len=i-(ipRecv_local.ip_hl<<2);
770
i=(int )ntohs(udpRecv->uh_ulen);
773
if ( DebugFlag ) syslog(LOG_DEBUG,
774
"corrupted UDP msg of size=%d and uh_ulen=%d discarded\n",
780
len=udpipchk((udpiphdr *)tmp_ip);
786
case -1: syslog(LOG_DEBUG,
787
"corrupted IP packet with ip_len=%d discarded\n",
788
(int )ntohs(ipRecv_local.ip_len));
790
case -2: syslog(LOG_DEBUG,
791
"corrupted UDP msg with uh_ulen=%d discarded\n",
792
(int )ntohs(udpRecv->uh_ulen));
798
DhcpMsgRecv=(dhcpMessage *)&tmp_ip[(ipRecv_local.ip_hl<<2)+sizeof(struct udphdr)];
799
if ( DhcpMsgRecv->xid != xid ) continue;
800
if ( DhcpMsgRecv->htype != ARPHRD_ETHER &&
801
DhcpMsgRecv->htype != (char)ARPHRD_IEEE802_TR )
804
syslog(LOG_DEBUG,"wrong msg htype 0x%X discarded\n",DhcpMsgRecv->htype);
807
if ( DhcpMsgRecv->op != DHCP_BOOTREPLY ) continue;
808
while ( udpFooSocket > 0 &&
809
recvfrom(udpFooSocket,(void *)foobuf,sizeof(foobuf),0,NULL,NULL) != -1 );
810
if ( parseDhcpMsgRecv() == msg ) return 0;
811
if ( DhcpOptions.val[dhcpMessageType] )
812
if ( *(unsigned char *)DhcpOptions.val[dhcpMessageType] == DHCP_NAK )
814
if ( DhcpOptions.val[dhcpMsg] )
816
"DHCP_NAK server response received: %s\n",
817
(char *)DhcpOptions.val[dhcpMsg]);
820
"DHCP_NAK server response received\n");
824
while ( timeout > 0 && peekfd(dhcpSocket, timeout) == 0 );
829
/*****************************************************************************/
835
struct sockaddr_pkt sap;
836
struct sockaddr_in clientAddr;
837
memset(&ifr,0,sizeof(struct ifreq));
838
memcpy(ifr.ifr_name,IfName,IfName_len);
839
#ifdef OLD_LINUX_VERSION
840
dhcpSocket = socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL));
842
dhcpSocket = socket(AF_PACKET,SOCK_PACKET,htons(ETH_P_ALL));
844
if ( dhcpSocket == -1 )
846
syslog(LOG_ERR,"dhcpStart: socket: %m\n");
850
if ( ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr) )
852
syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n");
855
if ( ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER && ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR )
857
syslog(LOG_ERR,"dhcpStart: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name);
860
if ( ifr.ifr_hwaddr.sa_family == ARPHRD_IEEE802_TR )
864
syslog(LOG_DEBUG,"found NIC of link layer type %d\n",ifr.ifr_hwaddr.sa_family);
866
if ( setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1 )
868
syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
871
if ( ioctl(dhcpSocket,SIOCGIFFLAGS,&ifr) )
873
syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFFLAGS: %m\n");
876
saved_if_flags = ifr.ifr_flags;
877
ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING;
878
if ( ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
880
syslog(LOG_ERR,"dhcpStart: ioctl SIOCSIFFLAGS: %m\n");
883
memset(&sap,0,sizeof(sap));
889
syslog(LOG_WARNING,"dhcpStart: retrying MAC address request "
890
"(returned %02x:%02x:%02x:%02x:%02x:%02x)",
891
ClientHwAddr[0],ClientHwAddr[1],ClientHwAddr[2],
892
ClientHwAddr[3],ClientHwAddr[4],ClientHwAddr[5]);
893
if ( ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr) )
895
syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n");
898
if ( ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER && ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR )
900
syslog(LOG_ERR,"dhcpStart: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name);
903
if ( setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1 )
905
syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
908
ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING;
909
if ( ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
911
syslog(LOG_ERR,"dhcpStart: ioctl SIOCSIFFLAGS: %m\n");
914
memset(&sap,0,sizeof(sap));
915
sap.spkt_protocol = htons(ETH_P_ALL);
916
memcpy(sap.spkt_device,IfName,IfName_len);
917
#ifdef OLD_LINUX_VERSION
918
sap.spkt_family = AF_INET;
920
sap.spkt_family = AF_PACKET;
922
if ( bind(dhcpSocket,(void*)&sap,sizeof(struct sockaddr)) == -1 )
923
syslog(LOG_ERR,"dhcpStart: bind: %m\n");
925
memcpy(ClientHwAddr,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
927
fprintf(stdout,"dhcpcd: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n",
928
ClientHwAddr[0], ClientHwAddr[1], ClientHwAddr[2],
929
ClientHwAddr[3], ClientHwAddr[4], ClientHwAddr[5]);
931
while ( !ClientHwAddr[0] &&
939
i=time(NULL)+ClientHwAddr[5]+4*ClientHwAddr[4]+8*ClientHwAddr[3]+
940
16*ClientHwAddr[2]+32*ClientHwAddr[1]+64*ClientHwAddr[0];
944
udpFooSocket = socket(AF_INET,SOCK_DGRAM,0);
945
if ( udpFooSocket == -1 )
947
syslog(LOG_ERR,"dhcpStart: socket: %m\n");
950
if ( setsockopt(udpFooSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) )
951
syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
952
memset(&clientAddr.sin_addr,0,sizeof(&clientAddr.sin_addr));
953
clientAddr.sin_family = AF_INET;
954
clientAddr.sin_port = htons(DHCP_CLIENT_PORT);
955
if ( bind(udpFooSocket,(struct sockaddr *)&clientAddr,sizeof(clientAddr)) )
957
if ( errno != EADDRINUSE )
958
syslog(LOG_ERR,"dhcpStart: bind: %m\n");
963
if ( fcntl(udpFooSocket,F_SETFL,O_NONBLOCK) == -1 )
965
syslog(LOG_ERR,"dhcpStart: fcntl: %m\n");
971
/*****************************************************************************/
972
void classclientsetup()
976
memcpy(DhcpIface.class_id,ClassID,ClassID_len);
977
DhcpIface.class_len=ClassID_len;
983
/*****************************************************************************/
986
if ( sigsetjmp(env,0xffff) )
989
syslog(LOG_DEBUG,"timed out waiting for DHCP_ACK response\n");
995
memset(&DhcpOptions,0,sizeof(DhcpOptions));
996
memset(&DhcpIface,0,sizeof(dhcpInterface));
997
if ( readDhcpCache() )
1000
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
1001
memset(&DhcpIface,0,sizeof(dhcpInterface));
1002
memset(&ifr,0,sizeof(struct ifreq));
1003
#ifdef OLD_LINUX_VERSION
1004
memcpy(ifr.ifr_name,IfName,IfName_len);
1006
memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
1008
p->sin_family = AF_INET;
1009
if ( ioctl(dhcpSocket,SIOCGIFADDR,&ifr) == 0 )
1010
DhcpIface.ciaddr=p->sin_addr.s_addr;
1012
if ( ClientMACaddr_ind )
1013
memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
1015
memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
1022
if ( ClientMACaddr_ind )
1023
memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
1025
memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
1027
return dhcpRequest(random(),&buildDhcpReboot);
1029
/*****************************************************************************/
1032
releaseDhcpOptions();
1035
fprintf(stderr,"ClassID = \"%s\"\n\
1036
ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n",
1038
DhcpIface.client_id[0],DhcpIface.client_id[1],DhcpIface.client_id[2],
1039
DhcpIface.client_id[3],DhcpIface.client_id[4],DhcpIface.client_id[5],
1040
DhcpIface.client_id[6],DhcpIface.client_id[7],DhcpIface.client_id[8]);
1043
if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting DHCP_DISCOVER\n");
1044
if ( dhcpSendAndRecv(random(),DHCP_OFFER,&buildDhcpDiscover) )
1049
if ( SendSecondDiscover )
1051
if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting second DHCP_DISCOVER\n");
1052
dhcpSendAndRecv(DhcpMsgRecv->xid,DHCP_OFFER,&buildDhcpDiscover);
1054
prev_ip_addr = DhcpIface.ciaddr;
1055
DhcpIface.ciaddr = DhcpMsgRecv->yiaddr;
1056
memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4);
1057
memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN);
1058
DhcpIface.xid = DhcpMsgRecv->xid;
1059
/* DHCP_OFFER received */
1061
syslog(LOG_DEBUG,"DHCP_OFFER received from %s (%u.%u.%u.%u)\n",
1063
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1064
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1065
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1066
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1068
return dhcpRequest(DhcpIface.xid,&buildDhcpRequest);
1070
/*****************************************************************************/
1071
void *dhcpRequest(xid,buildDhcpMsg)
1073
void (*buildDhcpMsg)(unsigned);
1075
/* send the message and read and parse replies into DhcpOptions */
1077
syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n",
1078
((unsigned char *)&DhcpIface.ciaddr)[0],
1079
((unsigned char *)&DhcpIface.ciaddr)[1],
1080
((unsigned char *)&DhcpIface.ciaddr)[2],
1081
((unsigned char *)&DhcpIface.ciaddr)[3]);
1082
if ( dhcpSendAndRecv(xid,DHCP_ACK,buildDhcpMsg) ) return &dhcpInit;
1083
ReqSentTime=time(NULL);
1084
if ( DebugFlag ) syslog(LOG_DEBUG,
1085
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1086
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1087
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1088
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1089
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1091
/* check if the offered IP address already in use */
1094
if ( DebugFlag ) syslog(LOG_DEBUG,
1095
"requested %u.%u.%u.%u address is in use\n",
1096
((unsigned char *)&DhcpIface.ciaddr)[0],
1097
((unsigned char *)&DhcpIface.ciaddr)[1],
1098
((unsigned char *)&DhcpIface.ciaddr)[2],
1099
((unsigned char *)&DhcpIface.ciaddr)[3]);
1101
DhcpIface.ciaddr = 0;
1104
if ( DebugFlag ) syslog(LOG_DEBUG,
1105
"verified %u.%u.%u.%u address is not in use\n",
1106
((unsigned char *)&DhcpIface.ciaddr)[0],
1107
((unsigned char *)&DhcpIface.ciaddr)[1],
1108
((unsigned char *)&DhcpIface.ciaddr)[2],
1109
((unsigned char *)&DhcpIface.ciaddr)[3]);
1117
/* Successfull ACK: Use the fields obtained for future requests */
1118
memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4);
1119
memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN);
1123
/*****************************************************************************/
1127
if ( sigsetjmp(env,0xffff) ) return &dhcpRenew;
1128
i=ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT1value])-time(NULL);
1134
sleep(ntohl(*(u_int *)DhcpOptions.val[dhcpT1value]));
1137
/*****************************************************************************/
1141
if ( sigsetjmp(env,0xffff) ) return &dhcpRebind;
1142
i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT2value])-time(NULL);
1149
syslog(LOG_DEBUG,"sending DHCP_REQUEST for %u.%u.%u.%u to %u.%u.%u.%u\n",
1150
((unsigned char *)&DhcpIface.ciaddr)[0],
1151
((unsigned char *)&DhcpIface.ciaddr)[1],
1152
((unsigned char *)&DhcpIface.ciaddr)[2],
1153
((unsigned char *)&DhcpIface.ciaddr)[3],
1154
((unsigned char *)&DhcpIface.siaddr)[0],
1155
((unsigned char *)&DhcpIface.siaddr)[1],
1156
((unsigned char *)&DhcpIface.siaddr)[2],
1157
((unsigned char *)&DhcpIface.siaddr)[3]);
1158
if ( dhcpSendAndRecv(random(),DHCP_ACK,&buildDhcpRenew) ) return &dhcpRebind;
1159
ReqSentTime=time(NULL);
1160
if ( DebugFlag ) syslog(LOG_DEBUG,
1161
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1162
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1163
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1164
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1165
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1168
/*****************************************************************************/
1172
if ( sigsetjmp(env,0xffff) ) return &dhcpStop;
1173
i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime])-time(NULL);
1180
syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n",
1181
((unsigned char *)&DhcpIface.ciaddr)[0],
1182
((unsigned char *)&DhcpIface.ciaddr)[1],
1183
((unsigned char *)&DhcpIface.ciaddr)[2],
1184
((unsigned char *)&DhcpIface.ciaddr)[3]);
1185
if ( dhcpSendAndRecv(random(),DHCP_ACK,&buildDhcpRebind) ) return &dhcpStop;
1186
ReqSentTime=time(NULL);
1187
if ( DebugFlag ) syslog(LOG_DEBUG,
1188
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1189
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1190
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1191
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1192
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1194
/* Successfull ACK: Use the fields obtained for future requests */
1195
memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4);
1196
memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN);
1200
/*****************************************************************************/
1203
struct sockaddr addr;
1205
if ( DhcpIface.ciaddr == 0 ) return &dhcpInit;
1207
buildDhcpRelease(random());
1209
memset(&addr,0,sizeof(struct sockaddr));
1210
memcpy(addr.sa_data,IfName,IfName_len);
1212
syslog(LOG_DEBUG,"sending DHCP_RELEASE for %u.%u.%u.%u to %u.%u.%u.%u\n",
1213
((unsigned char *)&DhcpIface.ciaddr)[0],
1214
((unsigned char *)&DhcpIface.ciaddr)[1],
1215
((unsigned char *)&DhcpIface.ciaddr)[2],
1216
((unsigned char *)&DhcpIface.ciaddr)[3],
1217
((unsigned char *)&DhcpIface.siaddr)[0],
1218
((unsigned char *)&DhcpIface.siaddr)[1],
1219
((unsigned char *)&DhcpIface.siaddr)[2],
1220
((unsigned char *)&DhcpIface.siaddr)[3]);
1221
if ( sendto(dhcpSocket,&UdpIpMsgSend,sizeof(struct packed_ether_header)+
1222
sizeof(udpiphdr)+sizeof(dhcpMessage),0,
1223
&addr,sizeof(struct sockaddr)) == -1 )
1224
syslog(LOG_ERR,"dhcpRelease: sendto: %m\n");
1225
arpRelease(); /* clear ARP cache entries for client IP addr */
1228
sethostname(InitialHostName,InitialHostName_len);
1230
fprintf(stdout,"dhcpcd: your hostname = %s\n",InitialHostName);
1232
if ( SetDomainName )
1234
setdomainname(InitialDomainName,InitialDomainName_len);
1236
fprintf(stdout,"dhcpcd: your domainname = %s\n",InitialDomainName);
1241
/*****************************************************************************/
1245
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
1247
releaseDhcpOptions();
1248
if ( TestCase ) goto tsc;
1249
memset(&ifr,0,sizeof(struct ifreq));
1250
#ifdef OLD_LINUX_VERSION
1251
memcpy(ifr.ifr_name,IfName,IfName_len);
1253
memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
1255
p->sin_family = AF_INET;
1256
p->sin_addr.s_addr = 0;
1257
#ifndef OLD_LINUX_VERSION
1258
if ( ioctl(dhcpSocket,SIOCSIFADDR,&ifr) == -1 )
1259
syslog(LOG_ERR,"dhcpStop: ioctl SIOCSIFADDR: %m\n");
1261
if (DownIfaceOnStop)
1263
ifr.ifr_flags = saved_if_flags & ~IFF_UP;
1264
if ( (IfName_len==IfNameExt_len) && ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
1265
syslog(LOG_ERR,"dhcpStop: ioctl SIOCSIFFLAGS: %m\n");
1269
if ( resolv_renamed )
1270
rename(resolv_file_sv, resolv_file);
1272
rename(nis_file_sv, nis_file);
1274
rename(ntp_file_sv, ntp_file);
1275
execute_on_change("down");
1278
/*****************************************************************************/
1282
struct sockaddr addr;
1283
memset(&UdpIpMsgSend,0,sizeof(udpipMessage));
1284
memcpy(UdpIpMsgSend.ethhdr.ether_dhost,MAC_BCAST_ADDR,ETH_ALEN);
1285
memcpy(UdpIpMsgSend.ethhdr.ether_shost,ClientHwAddr,ETH_ALEN);
1286
UdpIpMsgSend.ethhdr.ether_type = htons(ETHERTYPE_IP);
1287
buildDhcpDecline(random());
1288
udpipgen((udpiphdr *)&UdpIpMsgSend.udpipmsg,0,INADDR_BROADCAST,
1289
htons(DHCP_CLIENT_PORT),htons(DHCP_SERVER_PORT),sizeof(dhcpMessage));
1290
memset(&addr,0,sizeof(struct sockaddr));
1291
memcpy(addr.sa_data,IfName,IfName_len);
1292
if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting DHCP_DECLINE\n");
1293
if ( sendto(dhcpSocket,&UdpIpMsgSend,sizeof(struct packed_ether_header)+
1294
sizeof(udpiphdr)+sizeof(dhcpMessage),0,
1295
&addr,sizeof(struct sockaddr)) == -1 )
1296
syslog(LOG_ERR,"dhcpDecline: sendto: %m\n");
1300
/*****************************************************************************/
1304
memset(&DhcpOptions,0,sizeof(DhcpOptions));
1305
memset(&DhcpIface,0,sizeof(dhcpInterface));
1306
if ( ! inform_ipaddr.s_addr )
1309
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
1310
memset(&ifr,0,sizeof(struct ifreq));
1311
#ifdef OLD_LINUX_VERSION
1312
memcpy(ifr.ifr_name,IfName,IfName_len);
1314
memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
1316
p->sin_family = AF_INET;
1317
if ( ioctl(dhcpSocket,SIOCGIFADDR,&ifr) == 0 )
1318
inform_ipaddr.s_addr=p->sin_addr.s_addr;
1319
if ( ! inform_ipaddr.s_addr )
1321
if ( readDhcpCache() )
1323
syslog(LOG_ERR,"dhcpInform: no IP address given\n");
1327
inform_ipaddr.s_addr=DhcpIface.ciaddr;
1331
if ( ! DhcpIface.ciaddr )
1333
if ( ClientMACaddr_ind )
1334
memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
1336
memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
1339
DhcpIface.ciaddr=inform_ipaddr.s_addr;
1340
if ( ! DhcpIface.class_len )
1344
memcpy(DhcpIface.class_id,ClassID,ClassID_len);
1345
DhcpIface.class_len=ClassID_len;
1350
if ( ! DhcpIface.client_len ) clientIDsetup();
1351
if ( sigsetjmp(env,0xffff) )
1354
syslog(LOG_DEBUG,"timed out waiting for DHCP_ACK response\n");
1358
syslog(LOG_DEBUG,"broadcasting DHCP_INFORM for %u.%u.%u.%u\n",
1359
((unsigned char *)&DhcpIface.ciaddr)[0],
1360
((unsigned char *)&DhcpIface.ciaddr)[1],
1361
((unsigned char *)&DhcpIface.ciaddr)[2],
1362
((unsigned char *)&DhcpIface.ciaddr)[3]);
1363
if ( dhcpSendAndRecv(random(),DHCP_ACK,buildDhcpInform) ) return 0;
1364
if ( DebugFlag ) syslog(LOG_DEBUG,
1365
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1366
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1367
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1368
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1369
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1371
/* check if the offered IP address already in use */
1374
if ( DebugFlag ) syslog(LOG_DEBUG,
1375
"requested %u.%u.%u.%u address is in use\n",
1376
((unsigned char *)&DhcpIface.ciaddr)[0],
1377
((unsigned char *)&DhcpIface.ciaddr)[1],
1378
((unsigned char *)&DhcpIface.ciaddr)[2],
1379
((unsigned char *)&DhcpIface.ciaddr)[3]);
1383
if ( DebugFlag ) syslog(LOG_DEBUG,
1384
"verified %u.%u.%u.%u address is not in use\n",
1385
((unsigned char *)&DhcpIface.ciaddr)[0],
1386
((unsigned char *)&DhcpIface.ciaddr)[1],
1387
((unsigned char *)&DhcpIface.ciaddr)[2],
1388
((unsigned char *)&DhcpIface.ciaddr)[3]);
1390
if ( dhcpConfig() ) return 0;