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>
6
* dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
8
* This is free software; you can redistribute it and/or modify it
9
* under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful, but
14
* WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
* See the GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23
#include <sys/types.h>
24
#include <sys/socket.h>
26
#include <sys/ioctl.h>
28
#include <sys/utsname.h>
30
#include <net/if_arp.h>
32
#include <net/if_packet.h>
34
#include <linux/if_packet.h>
36
#include <net/route.h>
49
#include "pathnames.h"
52
extern char *ProgramName;
53
extern char *IfName,*IfNameExt;
54
extern int IfName_len,IfNameExt_len;
55
extern char *HostName;
56
extern unsigned char *ClassID;
57
extern int ClassID_len;
58
extern unsigned char *ClientID;
59
extern int ClientID_len;
62
extern unsigned LeaseTime;
63
extern int SetDomainName;
64
extern int SetHostName;
65
extern int SendSecondDiscover;
66
extern unsigned short ip_id;
67
extern void *(*currState)();
68
extern time_t TimeOut;
69
extern unsigned nleaseTime;
70
extern struct in_addr inform_ipaddr;
71
extern int DoCheckSum;
73
extern int resolv_renamed,yp_renamed,ntp_renamed;
74
extern int InitialHostName_len,InitialDomainName_len;
75
extern char *InitialHostName,*InitialDomainName;
78
extern unsigned char ClientMACaddr[ETH_ALEN];
79
extern int ClientMACaddr_ind;
88
int deleteDhcpCache();
89
void execute_on_change(char *prm);
95
dhcpOptions DhcpOptions;
96
dhcpInterface DhcpIface;
97
udpipMessage UdpIpMsgSend,UdpIpMsgRecv;
99
unsigned char ClientHwAddr[ETH_ALEN];
101
const struct ip *ipSend=(struct ip *)((struct udpiphdr *)UdpIpMsgSend.udpipmsg)->ip;
102
const struct ip *ipRecv=(struct ip *)((struct udpiphdr *)UdpIpMsgRecv.udpipmsg)->ip;
103
const dhcpMessage *DhcpMsgSend = (dhcpMessage *)&UdpIpMsgSend.udpipmsg[sizeof(udpiphdr)];
104
dhcpMessage *DhcpMsgRecv = (dhcpMessage *)&UdpIpMsgRecv.udpipmsg[sizeof(udpiphdr)];
106
static short int saved_if_flags = 0;
108
/*****************************************************************************/
109
/* Decode an RFC3397 DNS search order option into a space
110
seperated string. Returns length of string (including
111
terminating zero) or zero on error. out may be NULL
112
to just determine output length. */
114
static unsigned int decodeSearch(u_char *p, int len, u_char *out)
117
unsigned int count = 0, l, hops;
125
unsigned int label_type = l & 0xc0;
126
if (label_type == 0x80 || label_type == 0x40)
128
else if (label_type == 0xc0) /* pointer */
133
/* save source of first jump. */
146
/* straightforward name segment, add with '.' */
158
/* change last dot to space */
166
/* change last space to zero terminator */
173
int parseDhcpMsgRecv() /* this routine parses dhcp message received */
178
register u_char *p = DhcpMsgRecv->options+4;
179
unsigned char *end = DhcpMsgRecv->options+sizeof(DhcpMsgRecv->options);
181
/* Force T1 and T2 to 0: either new values will be in message, or they
182
will need to be recalculated from lease time */
183
if ( DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] > 0 )
184
memset(DhcpOptions.val[dhcpT1value],0,DhcpOptions.len[dhcpT1value]);
185
if ( DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] > 0 )
186
memset(DhcpOptions.val[dhcpT2value],0,DhcpOptions.len[dhcpT2value]);
190
case endOption: goto swend;
191
case padOption: p++; break;
196
if (p + 2 + p[1] >= end)
197
goto swend; /* corrupt packet */
199
if (len = decodeSearch(p+2, p[1], NULL))
201
if ( DhcpOptions.val[*p] )
202
free(DhcpOptions.val[*p]);
203
DhcpOptions.val[*p] = malloc(len);
204
DhcpOptions.len[*p] = len;
205
decodeSearch(p+2, p[1], DhcpOptions.val[*p]);
214
if (p + 2 + p[1] >= end)
215
goto swend; /* corrupt packet */
217
if ( DhcpOptions.len[*p] == p[1] )
218
memcpy(DhcpOptions.val[*p],p+2,p[1]);
221
DhcpOptions.len[*p] = p[1];
222
if ( DhcpOptions.val[*p] )
223
free(DhcpOptions.val[*p]);
226
DhcpOptions.val[*p] = malloc(p[1]+1);
227
memset(DhcpOptions.val[*p],0,p[1]+1);
228
memcpy(DhcpOptions.val[*p],p+2,p[1]);
235
fprintf(stderr,"parseDhcpMsgRecv: %d options received:\n",DhcpOptions.num);
237
if ( DhcpOptions.val[i] )
240
case 1: /* subnet mask */
241
case 3: /* routers on subnet */
242
case 4: /* time servers */
243
case 5: /* name servers */
244
case 6: /* dns servers */
245
case 28:/* broadcast addr */
246
case 33:/* staticRoute */
247
case 41:/* NIS servers */
248
case 42:/* NTP servers */
249
case 50:/* dhcpRequestdIPaddr */
250
case 54:/* dhcpServerIdentifier */
251
for (j=0;j<DhcpOptions.len[i];j+=4)
252
fprintf(stderr,"i=%-2d len=%-2d option = %u.%u.%u.%u\n",
253
i,DhcpOptions.len[i],
254
((unsigned char *)DhcpOptions.val[i])[0+j],
255
((unsigned char *)DhcpOptions.val[i])[1+j],
256
((unsigned char *)DhcpOptions.val[i])[2+j],
257
((unsigned char *)DhcpOptions.val[i])[3+j]);
259
case 2: /* time offset */
260
case 51:/* dhcpAddrLeaseTime */
261
case 57:/* dhcpMaxMsgSize */
262
case 58:/* dhcpT1value */
263
case 59:/* dhcpT2value */
264
fprintf(stderr,"i=%-2d len=%-2d option = %d\n",
265
i,DhcpOptions.len[i],
266
ntohl(*(int *)DhcpOptions.val[i]));
268
case 23:/* defaultIPTTL */
269
case 29:/* performMaskdiscovery */
270
case 31:/* performRouterdiscovery */
271
case 53:/* dhcpMessageType */
272
fprintf(stderr,"i=%-2d len=%-2d option = %u\n",
273
i,DhcpOptions.len[i],*(unsigned char *)DhcpOptions.val[i]);
276
fprintf(stderr,"i=%-2d len=%-2d option = \"%s\"\n",
277
i,DhcpOptions.len[i],(char *)DhcpOptions.val[i]);
280
DhcpMsgRecv->yiaddr = %u.%u.%u.%u\n\
281
DhcpMsgRecv->siaddr = %u.%u.%u.%u\n\
282
DhcpMsgRecv->giaddr = %u.%u.%u.%u\n\
283
DhcpMsgRecv->sname = \"%s\"\n\
284
ServerHardwareAddr = %02X.%02X.%02X.%02X.%02X.%02X\n",
285
((unsigned char *)&DhcpMsgRecv->yiaddr)[0],
286
((unsigned char *)&DhcpMsgRecv->yiaddr)[1],
287
((unsigned char *)&DhcpMsgRecv->yiaddr)[2],
288
((unsigned char *)&DhcpMsgRecv->yiaddr)[3],
289
((unsigned char *)&DhcpMsgRecv->siaddr)[0],
290
((unsigned char *)&DhcpMsgRecv->siaddr)[1],
291
((unsigned char *)&DhcpMsgRecv->siaddr)[2],
292
((unsigned char *)&DhcpMsgRecv->siaddr)[3],
293
((unsigned char *)&DhcpMsgRecv->giaddr)[0],
294
((unsigned char *)&DhcpMsgRecv->giaddr)[1],
295
((unsigned char *)&DhcpMsgRecv->giaddr)[2],
296
((unsigned char *)&DhcpMsgRecv->giaddr)[3],
298
UdpIpMsgRecv.ethhdr.ether_shost[0],
299
UdpIpMsgRecv.ethhdr.ether_shost[1],
300
UdpIpMsgRecv.ethhdr.ether_shost[2],
301
UdpIpMsgRecv.ethhdr.ether_shost[3],
302
UdpIpMsgRecv.ethhdr.ether_shost[4],
303
UdpIpMsgRecv.ethhdr.ether_shost[5]);
305
if ( ! DhcpMsgRecv->yiaddr ) DhcpMsgRecv->yiaddr=DhcpMsgSend->ciaddr;
306
if ( ! DhcpOptions.val[dhcpServerIdentifier] ) /* did not get dhcpServerIdentifier */
307
{ /* make it the same as IP address of the sender */
308
DhcpOptions.val[dhcpServerIdentifier] = malloc(4);
309
memcpy(DhcpOptions.val[dhcpServerIdentifier],&ipRecv->ip_src.s_addr,4);
310
DhcpOptions.len[dhcpServerIdentifier] = 4;
314
"dhcpServerIdentifier option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
315
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
316
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
317
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
318
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
320
if ( ! DhcpOptions.val[dns] ) /* did not get DNS */
321
{ /* make it the same as dhcpServerIdentifier */
322
DhcpOptions.val[dns] = malloc(4);
323
memcpy(DhcpOptions.val[dns],DhcpOptions.val[dhcpServerIdentifier],4);
324
DhcpOptions.len[dns] = 4;
328
"dns option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
329
((unsigned char *)DhcpOptions.val[dns])[0],
330
((unsigned char *)DhcpOptions.val[dns])[1],
331
((unsigned char *)DhcpOptions.val[dns])[2],
332
((unsigned char *)DhcpOptions.val[dns])[3]);
334
if ( ! DhcpOptions.val[subnetMask] ) /* did not get subnetMask */
336
DhcpOptions.val[subnetMask] = malloc(4);
337
((unsigned char *)DhcpOptions.val[subnetMask])[0] = 255;
339
if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 128 )
341
if ( IN_CLASSA(ntohl(DhcpMsgRecv->yiaddr)) )
344
((unsigned char *)DhcpOptions.val[subnetMask])[1] = 0; /* class A */
345
((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;
346
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0;
350
((unsigned char *)DhcpOptions.val[subnetMask])[1] = 255;
352
if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 192 )
354
if ( IN_CLASSB(ntohl(DhcpMsgRecv->yiaddr)) )
357
((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;/* class B */
358
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0;
362
((unsigned char *)DhcpOptions.val[subnetMask])[2] = 255;
363
if ( IN_CLASSC(ntohl(DhcpMsgRecv->yiaddr)) )
364
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0; /* class C */
366
((unsigned char *)DhcpOptions.val[subnetMask])[3] = 255;
369
DhcpOptions.len[subnetMask] = 4;
373
"subnetMask option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
374
((unsigned char *)DhcpOptions.val[subnetMask])[0],
375
((unsigned char *)DhcpOptions.val[subnetMask])[1],
376
((unsigned char *)DhcpOptions.val[subnetMask])[2],
377
((unsigned char *)DhcpOptions.val[subnetMask])[3]);
379
if ( ! DhcpOptions.val[broadcastAddr] ) /* did not get broadcastAddr */
381
int br = DhcpMsgRecv->yiaddr | ~*((int *)DhcpOptions.val[subnetMask]);
382
DhcpOptions.val[broadcastAddr] = malloc(4);
383
memcpy(DhcpOptions.val[broadcastAddr],&br,4);
384
DhcpOptions.len[broadcastAddr] = 4;
388
"broadcastAddr option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
389
((unsigned char *)DhcpOptions.val[broadcastAddr])[0],
390
((unsigned char *)DhcpOptions.val[broadcastAddr])[1],
391
((unsigned char *)DhcpOptions.val[broadcastAddr])[2],
392
((unsigned char *)DhcpOptions.val[broadcastAddr])[3]);
395
if ( ! DhcpOptions.val[routersOnSubnet] )
397
DhcpOptions.val[routersOnSubnet] = malloc(4);
398
if ( DhcpMsgRecv->giaddr )
399
memcpy(DhcpOptions.val[routersOnSubnet],&DhcpMsgRecv->giaddr,4);
401
memcpy(DhcpOptions.val[routersOnSubnet],DhcpOptions.val[dhcpServerIdentifier],4);
402
DhcpOptions.len[routersOnSubnet] = 4;
406
"routersOnSubnet option is missing in DHCP server response. Assuming %u.%u.%u.%u\n",
407
((unsigned char *)DhcpOptions.val[routersOnSubnet])[0],
408
((unsigned char *)DhcpOptions.val[routersOnSubnet])[1],
409
((unsigned char *)DhcpOptions.val[routersOnSubnet])[2],
410
((unsigned char *)DhcpOptions.val[routersOnSubnet])[3]);
413
if ( DhcpOptions.val[dhcpIPaddrLeaseTime] && DhcpOptions.len[dhcpIPaddrLeaseTime] == 4 )
415
if ( *(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime] == 0 )
417
memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
419
syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime=0 in DHCP server response. Assuming %u sec\n",LeaseTime);
423
syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime=%u in DHCP server response.\n",
424
ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]));
426
else /* did not get dhcpIPaddrLeaseTime */
428
DhcpOptions.val[dhcpIPaddrLeaseTime] = malloc(4);
429
memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
430
DhcpOptions.len[dhcpIPaddrLeaseTime] = 4;
433
syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime option is missing in DHCP server response. Assuming %u sec\n",LeaseTime);
435
if ( DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] == 4 )
437
if ( *(unsigned int *)DhcpOptions.val[dhcpT1value] == 0 )
439
unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
441
memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
442
DhcpOptions.len[dhcpT1value] = 4;
444
syslog(LOG_DEBUG,"dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2);
447
else /* did not get T1 */
449
unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
451
DhcpOptions.val[dhcpT1value] = malloc(4);
452
memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
453
DhcpOptions.len[dhcpT1value] = 4;
456
syslog(LOG_DEBUG,"dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2);
458
if ( DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] == 4 )
460
if ( *(unsigned int *)DhcpOptions.val[dhcpT2value] == 0 )
462
unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
464
memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
465
DhcpOptions.len[dhcpT2value] = 4;
467
syslog(LOG_DEBUG,"dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2);
470
else /* did not get T2 */
472
unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
474
DhcpOptions.val[dhcpT2value] = malloc(4);
475
memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
476
DhcpOptions.len[dhcpT2value] = 4;
479
syslog(LOG_DEBUG,"dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2);
481
if ( DhcpOptions.val[dhcpMessageType] )
482
return *(unsigned char *)DhcpOptions.val[dhcpMessageType];
485
/*****************************************************************************/
488
struct utsname sname;
489
if ( uname(&sname) ) syslog(LOG_ERR,"classIDsetup: uname: %m\n");
490
DhcpIface.class_len=snprintf(DhcpIface.class_id,CLASS_ID_MAX_LEN,
491
"%s %s %s",sname.sysname,sname.release,sname.machine);
493
/*****************************************************************************/
496
unsigned char *c = DhcpIface.client_id;
497
*c++ = dhcpClientIdentifier;
500
*c++ = ClientID_len + 1; /* 1 for the field below */
501
*c++ = 0; /* type: string */
502
memcpy(c,ClientID,ClientID_len);
503
DhcpIface.client_len = ClientID_len + 3;
506
*c++ = ETH_ALEN + 1; /* length: 6 (MAC Addr) + 1 (# field) */
507
*c++ = (TokenRingIf) ? ARPHRD_IEEE802_TR : ARPHRD_ETHER; /* type: Ethernet address */
509
memcpy(c,DhcpIface.chaddr,ETH_ALEN);
511
memcpy(c,ClientHwAddr,ETH_ALEN);
513
DhcpIface.client_len = ETH_ALEN + 3;
515
/*****************************************************************************/
516
void releaseDhcpOptions()
520
if ( DhcpOptions.val[i] ) free(DhcpOptions.val[i]);
521
memset(&DhcpOptions,0,sizeof(dhcpOptions));
523
/*****************************************************************************/
525
static void dumpframe(const char *title, struct packed_ether_header *frame)
530
printf("%s:", title);
531
dp = (unsigned char *)frame;
532
for (i = 0; i < 32; i++)
536
printf("0x%02X ", *dp++);
540
/*****************************************************************************/
541
/***** convert ethernet and token-ring frames *****/
542
int eth2tr(struct packed_ether_header *frame, int datalen)
544
struct trh_hdr *phdr;
546
char trheader[sizeof(struct trh_hdr) - sizeof(phdr->rseg) + sizeof(struct trllc)];
550
dumpframe("eth2tr: Incoming eth frame", frame);
552
memset(trheader, 0, sizeof(trheader));
553
phdr = (struct trh_hdr *)trheader;
555
phdr->fc = LLC_FRAME;
556
memcpy(phdr->daddr, frame->ether_dhost, TR_ALEN);
557
memcpy(phdr->saddr, frame->ether_shost, TR_ALEN);
558
if (phdr->daddr[0] & 0x80)
559
{ /* Destination is a broadcast */
560
phdr->rcf = sizeof(phdr->rcf) | htons(TR_RCF_BROADCAST | 0x70); /* Unlimited frame length */
561
pllc = (struct trllc *)&phdr->rseg[0];
562
phdr->saddr[0] |= TR_RII; /* Set source-route indicator */
563
len = sizeof(trheader);
567
pllc = (struct trllc *)&phdr->rcf;
568
len = sizeof(trheader) - sizeof(phdr->rcf);
570
pllc->dsap = EXTENDED_SAP;
571
pllc->ssap = EXTENDED_SAP;
573
pllc->protid[0] = pllc->protid[1] = pllc->protid[2] = 0;
574
pllc->ethertype = frame->ether_type;
575
memmove((char *)(frame + 1) + (len - sizeof(struct packed_ether_header)),
576
frame + 1, datalen); /* Make room for larger TR header */
577
memcpy(frame, trheader, len); /* Install TR header */
579
dumpframe("eth2tr: Outgoing tr frame", frame);
581
return len + datalen;
583
/*****************************************************************************/
584
int tr2eth(struct packed_ether_header *frame)
591
dumpframe("tr2eth: Incoming tr frame", frame);
593
hdr = *((struct trh_hdr *)frame);
594
if (hdr.saddr[0] & TR_RII)
597
hlen = hdr.rcf & ntohs(TR_RCF_LEN_MASK);
599
printf("rcf = 0x%X SR len %d\n", hdr.rcf, hlen);
601
if (hlen < sizeof(hdr.rcf) || (hlen & 1))
603
hdr.saddr[0] &= ~TR_RII;
605
pllc = (struct trllc *)(((__u8 *)frame) + sizeof(struct trh_hdr) - TR_MAXRIFLEN + hlen);
606
if (pllc->dsap != EXTENDED_SAP || pllc->llc != UI_CMD)
609
goto fake_rif; /* Bug in 2.2.3 kernel */
611
printf("corrupted TR-IP packet of ui=0x%x and dsap 0x%x discarded\n",
612
pllc->llc,pllc->dsap);
616
memcpy(frame->ether_dhost, hdr.daddr, ETH_ALEN);
617
memcpy(frame->ether_shost, hdr.saddr, ETH_ALEN);
618
frame->ether_type = pllc->ethertype;
619
memmove(frame + 1, pllc + 1, IPPACKET_SIZE); /* Move data portion: Overlapping buffer */
621
dumpframe("tr2eth: Outgoing eth frame", frame);
625
/*****************************************************************************/
626
/* Subtract the `struct timeval' values X and Y,
627
storing the result in RESULT.
628
Return 1 if the difference is negative, otherwise 0. */
629
static int timeval_subtract(result,x,y)
630
struct timeval *result,*x,*y;
632
/* Perform the carry for the later subtraction by updating Y. */
633
if (x->tv_usec < y->tv_usec) {
634
int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
635
y->tv_usec -= 1000000 * nsec;
638
if (x->tv_usec - y->tv_usec > 1000000) {
639
int nsec = (x->tv_usec - y->tv_usec) / 1000000;
640
y->tv_usec += 1000000 * nsec;
644
/* Compute the time remaining to wait.
645
`tv_usec' is certainly positive. */
646
result->tv_sec = x->tv_sec - y->tv_sec;
647
result->tv_usec = x->tv_usec - y->tv_usec;
649
/* Return 1 if result is negative. */
650
return x->tv_sec < y->tv_sec;
652
/*****************************************************************************/
653
int dhcpSendAndRecv(xid,msg,buildUdpIpMsg)
655
void (*buildUdpIpMsg)(unsigned);
657
struct sockaddr addr;
658
struct timeval begin, current, diff;
659
int i,len,o,timeout=0;
661
const struct udphdr *udpRecv;
662
int j=DHCP_INITIAL_RTO/2;
669
if (j > DHCP_MAX_RTO) j = DHCP_MAX_RTO;
670
memset(&addr,0,sizeof(struct sockaddr));
671
memcpy(addr.sa_data,IfName,IfName_len);
673
if ( TokenRingIf ) /* Here we convert a Eth frame into an TR frame */
674
len = eth2tr(&UdpIpMsgSend.ethhdr,sizeof(udpiphdr)+sizeof(dhcpMessage));
676
len = sizeof(struct packed_ether_header)+sizeof(udpiphdr)+sizeof(dhcpMessage);
677
if ( sendto(dhcpSocket,&UdpIpMsgSend,len,0,
678
&addr,sizeof(struct sockaddr)) == -1 )
680
syslog(LOG_ERR,"sendto: %m\n");
683
gettimeofday(&begin, NULL);
686
while ( peekfd(dhcpSocket,j+i%200000) );
689
struct ip ipRecv_local;
691
memset(&UdpIpMsgRecv,0,sizeof(udpipMessage));
692
o=sizeof(struct sockaddr);
693
len=recvfrom(dhcpSocket,&UdpIpMsgRecv,sizeof(udpipMessage),0,
694
(struct sockaddr *)&addr,&o);
697
syslog(LOG_ERR,"recvfrom: %m\n");
701
{ /* Here we convert a TR frame into an Eth frame */
702
if ( tr2eth(&UdpIpMsgRecv.ethhdr) ) continue;
704
gettimeofday(¤t, NULL);
705
timeval_subtract(&diff, ¤t, &begin);
706
timeout = j - diff.tv_sec*1000000 - diff.tv_usec + random()%200000;
707
if ( UdpIpMsgRecv.ethhdr.ether_type != htons(ETHERTYPE_IP) )
709
tmp_ip = UdpIpMsgRecv.udpipmsg;
710
for (i=0;i<sizeof(struct ip)-2;i+=2)
711
if ( ( UdpIpMsgRecv.udpipmsg[i] == 0x45 ) &&
712
( UdpIpMsgRecv.udpipmsg[i+1] == 0x00 ) )
714
tmp_ip=&(UdpIpMsgRecv.udpipmsg[i]);
717
/* Use local copy because ipRecv is not aligned. */
718
memcpy(&ipRecv_local,((struct udpiphdr *)tmp_ip)->ip,sizeof(struct ip));
719
udpRecv=(struct udphdr *)((char*)(((struct udpiphdr*)tmp_ip)->ip)+sizeof(struct ip));
720
if ( ipRecv_local.ip_p != IPPROTO_UDP ) continue;
723
if ( udpRecv->uh_dport != htons(DHCP_CLIENT_PORT) ) continue;
725
len-=sizeof(struct packed_ether_header);
726
i=(int )ntohs(ipRecv_local.ip_len);
729
if ( DebugFlag ) syslog(LOG_DEBUG,
730
"corrupted IP packet of size=%d and ip_len=%d discarded\n",
734
len=i-(ipRecv_local.ip_hl<<2);
735
i=(int )ntohs(udpRecv->uh_ulen);
738
if ( DebugFlag ) syslog(LOG_DEBUG,
739
"corrupted UDP msg of size=%d and uh_ulen=%d discarded\n",
745
len=udpipchk((udpiphdr *)tmp_ip);
751
case -1: syslog(LOG_DEBUG,
752
"corrupted IP packet with ip_len=%d discarded\n",
753
(int )ntohs(ipRecv_local.ip_len));
755
case -2: syslog(LOG_DEBUG,
756
"corrupted UDP msg with uh_ulen=%d discarded\n",
757
(int )ntohs(udpRecv->uh_ulen));
763
DhcpMsgRecv=(dhcpMessage *)&tmp_ip[(ipRecv_local.ip_hl<<2)+sizeof(struct udphdr)];
764
if ( DhcpMsgRecv->xid != xid ) continue;
765
if ( DhcpMsgRecv->htype != ARPHRD_ETHER &&
766
DhcpMsgRecv->htype != (char)ARPHRD_IEEE802_TR )
769
syslog(LOG_DEBUG,"wrong msg htype 0x%X discarded\n",DhcpMsgRecv->htype);
772
if ( DhcpMsgRecv->op != DHCP_BOOTREPLY ) continue;
773
while ( udpFooSocket > 0 &&
774
recvfrom(udpFooSocket,(void *)foobuf,sizeof(foobuf),0,NULL,NULL) != -1 );
775
if ( parseDhcpMsgRecv() == msg ) return 0;
776
if ( DhcpOptions.val[dhcpMessageType] )
777
if ( *(unsigned char *)DhcpOptions.val[dhcpMessageType] == DHCP_NAK )
779
if ( DhcpOptions.val[dhcpMsg] )
781
"DHCP_NAK server response received: %s\n",
782
(char *)DhcpOptions.val[dhcpMsg]);
785
"DHCP_NAK server response received\n");
789
while ( timeout > 0 && peekfd(dhcpSocket, timeout) == 0 );
794
/*****************************************************************************/
800
struct sockaddr_pkt sap;
801
struct sockaddr_in clientAddr;
802
memset(&ifr,0,sizeof(struct ifreq));
803
memcpy(ifr.ifr_name,IfName,IfName_len);
804
#ifdef OLD_LINUX_VERSION
805
dhcpSocket = socket(AF_INET,SOCK_PACKET,htons(ETH_P_ALL));
807
dhcpSocket = socket(AF_PACKET,SOCK_PACKET,htons(ETH_P_ALL));
809
if ( dhcpSocket == -1 )
811
syslog(LOG_ERR,"dhcpStart: socket: %m\n");
815
if ( ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr) )
817
syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n");
820
if ( ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER && ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR )
822
syslog(LOG_ERR,"dhcpStart: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name);
825
if ( ifr.ifr_hwaddr.sa_family == ARPHRD_IEEE802_TR )
829
syslog(LOG_DEBUG,"found NIC of link layer type %d\n",ifr.ifr_hwaddr.sa_family);
831
if ( setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1 )
833
syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
836
if ( ioctl(dhcpSocket,SIOCGIFFLAGS,&ifr) )
838
syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFFLAGS: %m\n");
841
saved_if_flags = ifr.ifr_flags;
842
ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING;
843
if ( ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
845
syslog(LOG_ERR,"dhcpStart: ioctl SIOCSIFFLAGS: %m\n");
848
memset(&sap,0,sizeof(sap));
854
syslog(LOG_WARNING,"dhcpStart: retrying MAC address request "
855
"(returned %02x:%02x:%02x:%02x:%02x:%02x)",
856
ClientHwAddr[0],ClientHwAddr[1],ClientHwAddr[2],
857
ClientHwAddr[3],ClientHwAddr[4],ClientHwAddr[5]);
858
if ( ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr) )
860
syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n");
863
if ( ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER && ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR )
865
syslog(LOG_ERR,"dhcpStart: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name);
868
if ( setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1 )
870
syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
873
ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING;
874
if ( ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
876
syslog(LOG_ERR,"dhcpStart: ioctl SIOCSIFFLAGS: %m\n");
879
memset(&sap,0,sizeof(sap));
880
sap.spkt_protocol = htons(ETH_P_ALL);
881
memcpy(sap.spkt_device,IfName,IfName_len);
882
#ifdef OLD_LINUX_VERSION
883
sap.spkt_family = AF_INET;
885
sap.spkt_family = AF_PACKET;
887
if ( bind(dhcpSocket,(void*)&sap,sizeof(struct sockaddr)) == -1 )
888
syslog(LOG_ERR,"dhcpStart: bind: %m\n");
890
memcpy(ClientHwAddr,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
892
fprintf(stdout,"dhcpcd: MAC address = %02x:%02x:%02x:%02x:%02x:%02x\n",
893
ClientHwAddr[0], ClientHwAddr[1], ClientHwAddr[2],
894
ClientHwAddr[3], ClientHwAddr[4], ClientHwAddr[5]);
896
while ( !ClientHwAddr[0] &&
904
i=time(NULL)+ClientHwAddr[5]+4*ClientHwAddr[4]+8*ClientHwAddr[3]+
905
16*ClientHwAddr[2]+32*ClientHwAddr[1]+64*ClientHwAddr[0];
909
udpFooSocket = socket(AF_INET,SOCK_DGRAM,0);
910
if ( udpFooSocket == -1 )
912
syslog(LOG_ERR,"dhcpStart: socket: %m\n");
915
if ( setsockopt(udpFooSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) )
916
syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
917
memset(&clientAddr.sin_addr,0,sizeof(&clientAddr.sin_addr));
918
clientAddr.sin_family = AF_INET;
919
clientAddr.sin_port = htons(DHCP_CLIENT_PORT);
920
if ( bind(udpFooSocket,(struct sockaddr *)&clientAddr,sizeof(clientAddr)) )
922
if ( errno != EADDRINUSE )
923
syslog(LOG_ERR,"dhcpStart: bind: %m\n");
928
if ( fcntl(udpFooSocket,F_SETFL,O_NONBLOCK) == -1 )
930
syslog(LOG_ERR,"dhcpStart: fcntl: %m\n");
936
/*****************************************************************************/
937
void classclientsetup()
941
memcpy(DhcpIface.class_id,ClassID,ClassID_len);
942
DhcpIface.class_len=ClassID_len;
948
/*****************************************************************************/
951
if ( sigsetjmp(env,0xffff) )
954
syslog(LOG_DEBUG,"timed out waiting for DHCP_ACK response\n");
960
memset(&DhcpOptions,0,sizeof(DhcpOptions));
961
memset(&DhcpIface,0,sizeof(dhcpInterface));
962
if ( readDhcpCache() )
965
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
966
memset(&DhcpIface,0,sizeof(dhcpInterface));
967
memset(&ifr,0,sizeof(struct ifreq));
968
#ifdef OLD_LINUX_VERSION
969
memcpy(ifr.ifr_name,IfName,IfName_len);
971
memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
973
p->sin_family = AF_INET;
974
if ( ioctl(dhcpSocket,SIOCGIFADDR,&ifr) == 0 )
975
DhcpIface.ciaddr=p->sin_addr.s_addr;
977
if ( ClientMACaddr_ind )
978
memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
980
memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
987
if ( ClientMACaddr_ind )
988
memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
990
memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
992
return dhcpRequest(random(),&buildDhcpReboot);
994
/*****************************************************************************/
997
releaseDhcpOptions();
1000
fprintf(stderr,"ClassID = \"%s\"\n\
1001
ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n",
1003
DhcpIface.client_id[0],DhcpIface.client_id[1],DhcpIface.client_id[2],
1004
DhcpIface.client_id[3],DhcpIface.client_id[4],DhcpIface.client_id[5],
1005
DhcpIface.client_id[6],DhcpIface.client_id[7],DhcpIface.client_id[8]);
1008
if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting DHCP_DISCOVER\n");
1009
if ( dhcpSendAndRecv(random(),DHCP_OFFER,&buildDhcpDiscover) )
1014
if ( SendSecondDiscover )
1016
if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting second DHCP_DISCOVER\n");
1017
dhcpSendAndRecv(DhcpMsgRecv->xid,DHCP_OFFER,&buildDhcpDiscover);
1019
prev_ip_addr = DhcpIface.ciaddr;
1020
DhcpIface.ciaddr = DhcpMsgRecv->yiaddr;
1021
memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4);
1022
memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN);
1023
DhcpIface.xid = DhcpMsgRecv->xid;
1024
/* DHCP_OFFER received */
1026
syslog(LOG_DEBUG,"DHCP_OFFER received from %s (%u.%u.%u.%u)\n",
1028
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1029
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1030
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1031
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1033
return dhcpRequest(DhcpIface.xid,&buildDhcpRequest);
1035
/*****************************************************************************/
1036
void *dhcpRequest(xid,buildDhcpMsg)
1038
void (*buildDhcpMsg)(unsigned);
1040
/* send the message and read and parse replies into DhcpOptions */
1042
syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n",
1043
((unsigned char *)&DhcpIface.ciaddr)[0],
1044
((unsigned char *)&DhcpIface.ciaddr)[1],
1045
((unsigned char *)&DhcpIface.ciaddr)[2],
1046
((unsigned char *)&DhcpIface.ciaddr)[3]);
1047
if ( dhcpSendAndRecv(xid,DHCP_ACK,buildDhcpMsg) ) return &dhcpInit;
1048
ReqSentTime=time(NULL);
1049
if ( DebugFlag ) syslog(LOG_DEBUG,
1050
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1051
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1052
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1053
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1054
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1056
/* check if the offered IP address already in use */
1059
if ( DebugFlag ) syslog(LOG_DEBUG,
1060
"requested %u.%u.%u.%u address is in use\n",
1061
((unsigned char *)&DhcpIface.ciaddr)[0],
1062
((unsigned char *)&DhcpIface.ciaddr)[1],
1063
((unsigned char *)&DhcpIface.ciaddr)[2],
1064
((unsigned char *)&DhcpIface.ciaddr)[3]);
1066
DhcpIface.ciaddr = 0;
1069
if ( DebugFlag ) syslog(LOG_DEBUG,
1070
"verified %u.%u.%u.%u address is not in use\n",
1071
((unsigned char *)&DhcpIface.ciaddr)[0],
1072
((unsigned char *)&DhcpIface.ciaddr)[1],
1073
((unsigned char *)&DhcpIface.ciaddr)[2],
1074
((unsigned char *)&DhcpIface.ciaddr)[3]);
1082
/* Successfull ACK: Use the fields obtained for future requests */
1083
memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4);
1084
memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN);
1088
/*****************************************************************************/
1092
if ( sigsetjmp(env,0xffff) ) return &dhcpRenew;
1093
i=ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT1value])-time(NULL);
1099
sleep(ntohl(*(u_int *)DhcpOptions.val[dhcpT1value]));
1102
/*****************************************************************************/
1106
if ( sigsetjmp(env,0xffff) ) return &dhcpRebind;
1107
i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT2value])-time(NULL);
1114
syslog(LOG_DEBUG,"sending DHCP_REQUEST for %u.%u.%u.%u to %u.%u.%u.%u\n",
1115
((unsigned char *)&DhcpIface.ciaddr)[0],
1116
((unsigned char *)&DhcpIface.ciaddr)[1],
1117
((unsigned char *)&DhcpIface.ciaddr)[2],
1118
((unsigned char *)&DhcpIface.ciaddr)[3],
1119
((unsigned char *)&DhcpIface.siaddr)[0],
1120
((unsigned char *)&DhcpIface.siaddr)[1],
1121
((unsigned char *)&DhcpIface.siaddr)[2],
1122
((unsigned char *)&DhcpIface.siaddr)[3]);
1123
if ( dhcpSendAndRecv(random(),DHCP_ACK,&buildDhcpRenew) ) return &dhcpRebind;
1124
ReqSentTime=time(NULL);
1125
if ( DebugFlag ) syslog(LOG_DEBUG,
1126
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1127
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1128
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1129
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1130
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1133
/*****************************************************************************/
1137
if ( sigsetjmp(env,0xffff) ) return &dhcpStop;
1138
i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime])-time(NULL);
1145
syslog(LOG_DEBUG,"broadcasting DHCP_REQUEST for %u.%u.%u.%u\n",
1146
((unsigned char *)&DhcpIface.ciaddr)[0],
1147
((unsigned char *)&DhcpIface.ciaddr)[1],
1148
((unsigned char *)&DhcpIface.ciaddr)[2],
1149
((unsigned char *)&DhcpIface.ciaddr)[3]);
1150
if ( dhcpSendAndRecv(random(),DHCP_ACK,&buildDhcpRebind) ) return &dhcpStop;
1151
ReqSentTime=time(NULL);
1152
if ( DebugFlag ) syslog(LOG_DEBUG,
1153
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1154
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1155
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1156
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1157
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1159
/* Successfull ACK: Use the fields obtained for future requests */
1160
memcpy(&DhcpIface.siaddr,DhcpOptions.val[dhcpServerIdentifier],4);
1161
memcpy(DhcpIface.shaddr,UdpIpMsgRecv.ethhdr.ether_shost,ETH_ALEN);
1165
/*****************************************************************************/
1168
struct sockaddr addr;
1170
if ( DhcpIface.ciaddr == 0 ) return &dhcpInit;
1172
buildDhcpRelease(random());
1174
memset(&addr,0,sizeof(struct sockaddr));
1175
memcpy(addr.sa_data,IfName,IfName_len);
1177
syslog(LOG_DEBUG,"sending DHCP_RELEASE for %u.%u.%u.%u to %u.%u.%u.%u\n",
1178
((unsigned char *)&DhcpIface.ciaddr)[0],
1179
((unsigned char *)&DhcpIface.ciaddr)[1],
1180
((unsigned char *)&DhcpIface.ciaddr)[2],
1181
((unsigned char *)&DhcpIface.ciaddr)[3],
1182
((unsigned char *)&DhcpIface.siaddr)[0],
1183
((unsigned char *)&DhcpIface.siaddr)[1],
1184
((unsigned char *)&DhcpIface.siaddr)[2],
1185
((unsigned char *)&DhcpIface.siaddr)[3]);
1186
if ( sendto(dhcpSocket,&UdpIpMsgSend,sizeof(struct packed_ether_header)+
1187
sizeof(udpiphdr)+sizeof(dhcpMessage),0,
1188
&addr,sizeof(struct sockaddr)) == -1 )
1189
syslog(LOG_ERR,"dhcpRelease: sendto: %m\n");
1190
arpRelease(); /* clear ARP cache entries for client IP addr */
1193
sethostname(InitialHostName,InitialHostName_len);
1195
fprintf(stdout,"dhcpcd: your hostname = %s\n",InitialHostName);
1197
if ( SetDomainName )
1199
setdomainname(InitialDomainName,InitialDomainName_len);
1201
fprintf(stdout,"dhcpcd: your domainname = %s\n",InitialDomainName);
1206
/*****************************************************************************/
1210
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
1212
releaseDhcpOptions();
1213
if ( TestCase ) goto tsc;
1214
memset(&ifr,0,sizeof(struct ifreq));
1215
#ifdef OLD_LINUX_VERSION
1216
memcpy(ifr.ifr_name,IfName,IfName_len);
1218
memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
1220
p->sin_family = AF_INET;
1221
p->sin_addr.s_addr = 0;
1222
#ifndef OLD_LINUX_VERSION
1223
if ( ioctl(dhcpSocket,SIOCSIFADDR,&ifr) == -1 )
1224
syslog(LOG_ERR,"dhcpStop: ioctl SIOCSIFADDR: %m\n");
1226
ifr.ifr_flags = saved_if_flags & ~IFF_UP;
1227
if ( (IfName_len==IfNameExt_len) && ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
1228
syslog(LOG_ERR,"dhcpStop: ioctl SIOCSIFFLAGS: %m\n");
1231
if ( resolv_renamed )
1232
rename(""RESOLV_CONF".sv",RESOLV_CONF);
1234
rename(""NIS_CONF".sv",NIS_CONF);
1236
rename(""NTP_CONF".sv",NTP_CONF);
1237
execute_on_change("down");
1240
/*****************************************************************************/
1244
struct sockaddr addr;
1245
memset(&UdpIpMsgSend,0,sizeof(udpipMessage));
1246
memcpy(UdpIpMsgSend.ethhdr.ether_dhost,MAC_BCAST_ADDR,ETH_ALEN);
1247
memcpy(UdpIpMsgSend.ethhdr.ether_shost,ClientHwAddr,ETH_ALEN);
1248
UdpIpMsgSend.ethhdr.ether_type = htons(ETHERTYPE_IP);
1249
buildDhcpDecline(random());
1250
udpipgen((udpiphdr *)&UdpIpMsgSend.udpipmsg,0,INADDR_BROADCAST,
1251
htons(DHCP_CLIENT_PORT),htons(DHCP_SERVER_PORT),sizeof(dhcpMessage));
1252
memset(&addr,0,sizeof(struct sockaddr));
1253
memcpy(addr.sa_data,IfName,IfName_len);
1254
if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting DHCP_DECLINE\n");
1255
if ( sendto(dhcpSocket,&UdpIpMsgSend,sizeof(struct packed_ether_header)+
1256
sizeof(udpiphdr)+sizeof(dhcpMessage),0,
1257
&addr,sizeof(struct sockaddr)) == -1 )
1258
syslog(LOG_ERR,"dhcpDecline: sendto: %m\n");
1262
/*****************************************************************************/
1266
memset(&DhcpOptions,0,sizeof(DhcpOptions));
1267
memset(&DhcpIface,0,sizeof(dhcpInterface));
1268
if ( ! inform_ipaddr.s_addr )
1271
struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);
1272
memset(&ifr,0,sizeof(struct ifreq));
1273
#ifdef OLD_LINUX_VERSION
1274
memcpy(ifr.ifr_name,IfName,IfName_len);
1276
memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
1278
p->sin_family = AF_INET;
1279
if ( ioctl(dhcpSocket,SIOCGIFADDR,&ifr) == 0 )
1280
inform_ipaddr.s_addr=p->sin_addr.s_addr;
1281
if ( ! inform_ipaddr.s_addr )
1283
if ( readDhcpCache() )
1285
syslog(LOG_ERR,"dhcpInform: no IP address given\n");
1289
inform_ipaddr.s_addr=DhcpIface.ciaddr;
1293
if ( ! DhcpIface.ciaddr )
1295
if ( ClientMACaddr_ind )
1296
memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
1298
memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
1301
DhcpIface.ciaddr=inform_ipaddr.s_addr;
1302
if ( ! DhcpIface.class_len )
1306
memcpy(DhcpIface.class_id,ClassID,ClassID_len);
1307
DhcpIface.class_len=ClassID_len;
1312
if ( ! DhcpIface.client_len ) clientIDsetup();
1313
if ( sigsetjmp(env,0xffff) )
1316
syslog(LOG_DEBUG,"timed out waiting for DHCP_ACK response\n");
1320
syslog(LOG_DEBUG,"broadcasting DHCP_INFORM for %u.%u.%u.%u\n",
1321
((unsigned char *)&DhcpIface.ciaddr)[0],
1322
((unsigned char *)&DhcpIface.ciaddr)[1],
1323
((unsigned char *)&DhcpIface.ciaddr)[2],
1324
((unsigned char *)&DhcpIface.ciaddr)[3]);
1325
if ( dhcpSendAndRecv(random(),DHCP_ACK,buildDhcpInform) ) return 0;
1326
if ( DebugFlag ) syslog(LOG_DEBUG,
1327
"DHCP_ACK received from %s (%u.%u.%u.%u)\n",DhcpMsgRecv->sname,
1328
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[0],
1329
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[1],
1330
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[2],
1331
((unsigned char *)DhcpOptions.val[dhcpServerIdentifier])[3]);
1333
/* check if the offered IP address already in use */
1336
if ( DebugFlag ) syslog(LOG_DEBUG,
1337
"requested %u.%u.%u.%u address is in use\n",
1338
((unsigned char *)&DhcpIface.ciaddr)[0],
1339
((unsigned char *)&DhcpIface.ciaddr)[1],
1340
((unsigned char *)&DhcpIface.ciaddr)[2],
1341
((unsigned char *)&DhcpIface.ciaddr)[3]);
1345
if ( DebugFlag ) syslog(LOG_DEBUG,
1346
"verified %u.%u.%u.%u address is not in use\n",
1347
((unsigned char *)&DhcpIface.ciaddr)[0],
1348
((unsigned char *)&DhcpIface.ciaddr)[1],
1349
((unsigned char *)&DhcpIface.ciaddr)[2],
1350
((unsigned char *)&DhcpIface.ciaddr)[3]);
1352
if ( dhcpConfig() ) return 0;