~ubuntu-branches/ubuntu/trusty/dhcpcd/trusty-security

« back to all changes in this revision

Viewing changes to src/client.c

  • Committer: Bazaar Package Importer
  • Author(s): Simon Kelley
  • Date: 2005-09-30 02:21:51 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20050930022151-vq3xlcazj0bdpyf4
Tags: 1:2.0.0-2
Clear out /etc/dhcpc/resolv.conf and /var/lib/dhcpc/* 
during purge. (closes: #330515)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
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>
 
7
 * 
 
8
 * dhcpcd is an RFC2131 and RFC1541 compliant DHCP client daemon.
 
9
 *
 
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.
 
14
 *
 
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.
 
19
 *
 
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.
 
23
 */
 
24
 
 
25
#include <sys/types.h>
 
26
#include <sys/socket.h>
 
27
#include <sys/stat.h>
 
28
#include <sys/ioctl.h>
 
29
#include <sys/time.h>
 
30
#include <sys/utsname.h>
 
31
#include <net/if.h>
 
32
#include <net/if_arp.h>
 
33
#ifdef __GLIBC__
 
34
#include <net/if_packet.h>
 
35
#else
 
36
#include <linux/if_packet.h>
 
37
#endif
 
38
#include <net/route.h>
 
39
#include <fcntl.h>
 
40
#include <stdio.h>
 
41
#include <stdlib.h>
 
42
#include <string.h>
 
43
#include <unistd.h>
 
44
#include <syslog.h>
 
45
#include <errno.h>
 
46
#include <setjmp.h>
 
47
#include <time.h>
 
48
#include "client.h"
 
49
#include "buildmsg.h"
 
50
#include "udpipgen.h"
 
51
#include "pathnames.h"
 
52
#include "kversion.h"
 
53
 
 
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;
 
62
extern  int             DebugFlag;
 
63
extern  int             BeRFC1541;
 
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;
 
74
extern  int             TestCase;
 
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;
 
79
 
 
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];
 
86
 
 
87
#if 0
 
88
extern  unsigned char   ClientMACaddr[ETH_ALEN];
 
89
extern  int             ClientMACaddr_ind;
 
90
#endif
 
91
 
 
92
extern  int             SetFQDNHostName;
 
93
 
 
94
#ifdef ARPCHECK
 
95
int arpCheck();
 
96
#endif
 
97
int     arpRelease();
 
98
int     dhcpConfig();
 
99
int     readDhcpCache();
 
100
int     deleteDhcpCache();
 
101
void    execute_on_change(char *prm);
 
102
 
 
103
int                     dhcpSocket;
 
104
int                     udpFooSocket;
 
105
int                     prev_ip_addr;
 
106
time_t                  ReqSentTime;
 
107
dhcpOptions             DhcpOptions;
 
108
dhcpInterface           DhcpIface;
 
109
udpipMessage            UdpIpMsgSend,UdpIpMsgRecv;
 
110
jmp_buf                 env;
 
111
unsigned char           ClientHwAddr[ETH_ALEN];
 
112
 
 
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)];
 
117
 
 
118
static short int saved_if_flags = 0;
 
119
int     TokenRingIf     =       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. */
 
125
 
 
126
static unsigned int decodeSearch(u_char *p, int len, u_char *out)
 
127
{
 
128
  u_char *r, *q = p;
 
129
  unsigned int count = 0, l, hops;
 
130
 
 
131
  while (q - p < len)
 
132
    {
 
133
      r = NULL;
 
134
      hops = 0;
 
135
      while ((l = *q++))
 
136
        {
 
137
          unsigned int label_type = l & 0xc0;
 
138
          if (label_type == 0x80 || label_type == 0x40)
 
139
            return 0;
 
140
          else if (label_type == 0xc0) /* pointer */
 
141
            { 
 
142
              l = (l&0x3f) << 8;
 
143
              l |= *q++;
 
144
              
 
145
              /* save source of first jump. */
 
146
              if (!r)
 
147
                r = q;
 
148
 
 
149
              hops++;
 
150
              if (hops > 255)
 
151
                return 0;
 
152
              q = p + l;
 
153
              if (q - p >= len)
 
154
                return 0;
 
155
            }
 
156
          else 
 
157
            {
 
158
              /* straightforward name segment, add with '.' */
 
159
              count += l+1;
 
160
              if (out)
 
161
                {
 
162
                  memcpy(out, q, l);
 
163
                  out += l;
 
164
                  *out++ = '.';
 
165
                }
 
166
              q += l;
 
167
            }
 
168
        }
 
169
 
 
170
      /* change last dot to space */
 
171
      if (out)
 
172
        *(out-1) = ' ';
 
173
 
 
174
      if (r)
 
175
        q = r;
 
176
    }
 
177
 
 
178
  /* change last space to zero terminator */
 
179
  if (out)
 
180
    *(out-1) = 0;
 
181
 
 
182
  return count;  
 
183
}
 
184
 
 
185
int parseDhcpMsgRecv() /* this routine parses dhcp message received */
 
186
{
 
187
#ifdef DEBUG
 
188
  int i,j;
 
189
#endif
 
190
  register u_char *p = DhcpMsgRecv->options+4;
 
191
  unsigned char *end = DhcpMsgRecv->options+sizeof(DhcpMsgRecv->options);
 
192
 
 
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]);
 
199
  while ( p < end )
 
200
    switch ( *p )
 
201
      {
 
202
        case endOption: goto swend;
 
203
        case padOption: p++; break;
 
204
        case dnsSearchPath:
 
205
          {
 
206
            unsigned int len;
 
207
            
 
208
            if (p + 2 + p[1] >= end)
 
209
              goto swend; /* corrupt packet */
 
210
 
 
211
            if (len = decodeSearch(p+2, p[1], NULL))
 
212
              {
 
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]);
 
218
              }
 
219
            p += p[1]+2;
 
220
            break;
 
221
          }
 
222
 
 
223
        default:
 
224
          if ( p[1] )
 
225
            {
 
226
              if (p + 2 + p[1] >= end)
 
227
              goto swend; /* corrupt packet */
 
228
              
 
229
              if ( DhcpOptions.len[*p] == p[1] )
 
230
                memcpy(DhcpOptions.val[*p],p+2,p[1]);
 
231
              else
 
232
                {
 
233
                  DhcpOptions.len[*p] = p[1];
 
234
                  if ( DhcpOptions.val[*p] )
 
235
                    free(DhcpOptions.val[*p]);
 
236
                  else
 
237
                    DhcpOptions.num++;
 
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]);
 
241
                }
 
242
            }
 
243
          p+=p[1]+2;
 
244
      }
 
245
swend:
 
246
#ifdef DEBUG
 
247
  fprintf(stderr,"parseDhcpMsgRecv: %d options received:\n",DhcpOptions.num);
 
248
  for (i=1;i<255;i++)
 
249
    if ( DhcpOptions.val[i] )
 
250
      switch ( i )
 
251
        {
 
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]);
 
270
            break;
 
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]));
 
279
            break;
 
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]);
 
286
            break;
 
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);
 
294
            break;
 
295
          default:
 
296
            fprintf(stderr,"i=%-2d  len=%-2d  option = \"%s\"\n",
 
297
                i,DhcpOptions.len[i],(char *)DhcpOptions.val[i]);
 
298
        }
 
299
fprintf(stderr,"\
 
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],
 
317
DhcpMsgRecv->sname,
 
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]);
 
324
#endif
 
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;
 
331
      DhcpOptions.num++;
 
332
      if ( DebugFlag )
 
333
        syslog(LOG_DEBUG,
 
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]);
 
339
    }
 
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;
 
345
      DhcpOptions.num++;
 
346
      if ( DebugFlag )
 
347
        syslog(LOG_DEBUG,
 
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]);
 
353
    }
 
354
  if ( ! DhcpOptions.val[subnetMask] ) /* did not get subnetMask */
 
355
    {
 
356
      DhcpOptions.val[subnetMask] = malloc(4);
 
357
      ((unsigned char *)DhcpOptions.val[subnetMask])[0] = 255;
 
358
#if 0
 
359
      if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 128 )
 
360
#else
 
361
      if ( IN_CLASSA(ntohl(DhcpMsgRecv->yiaddr)) )
 
362
#endif
 
363
        {
 
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;
 
367
        }
 
368
      else
 
369
        {
 
370
          ((unsigned char *)DhcpOptions.val[subnetMask])[1] = 255;
 
371
#if 0
 
372
          if ( ((unsigned char *)&DhcpMsgRecv->yiaddr)[0] < 192 )
 
373
#else
 
374
          if ( IN_CLASSB(ntohl(DhcpMsgRecv->yiaddr)) )
 
375
#endif
 
376
            {
 
377
              ((unsigned char *)DhcpOptions.val[subnetMask])[2] = 0;/* class B */
 
378
              ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 0;
 
379
            }
 
380
          else
 
381
            {
 
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 */
 
385
              else
 
386
                ((unsigned char *)DhcpOptions.val[subnetMask])[3] = 255;
 
387
            }
 
388
        }
 
389
      DhcpOptions.len[subnetMask] = 4;
 
390
      DhcpOptions.num++;
 
391
      if ( DebugFlag )
 
392
        syslog(LOG_DEBUG,
 
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]);
 
398
    }
 
399
  if ( ! DhcpOptions.val[broadcastAddr] ) /* did not get broadcastAddr */
 
400
    {
 
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;
 
405
      DhcpOptions.num++;
 
406
      if ( DebugFlag )
 
407
        syslog(LOG_DEBUG,
 
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]);
 
413
    }
 
414
#if 0
 
415
  if ( ! DhcpOptions.val[routersOnSubnet] )
 
416
    {
 
417
      DhcpOptions.val[routersOnSubnet] = malloc(4);
 
418
      if ( DhcpMsgRecv->giaddr )
 
419
        memcpy(DhcpOptions.val[routersOnSubnet],&DhcpMsgRecv->giaddr,4);
 
420
      else
 
421
        memcpy(DhcpOptions.val[routersOnSubnet],DhcpOptions.val[dhcpServerIdentifier],4);
 
422
      DhcpOptions.len[routersOnSubnet] = 4;
 
423
      DhcpOptions.num++;
 
424
      if ( DebugFlag )
 
425
        syslog(LOG_DEBUG,
 
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]);
 
431
    }
 
432
#endif
 
433
  if ( DhcpOptions.val[dhcpIPaddrLeaseTime] && DhcpOptions.len[dhcpIPaddrLeaseTime] == 4 )
 
434
    {
 
435
      if ( *(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime] == 0 )
 
436
        {
 
437
          memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
 
438
          if ( DebugFlag )
 
439
            syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime=0 in DHCP server response. Assuming %u sec\n",LeaseTime);
 
440
        }
 
441
      else
 
442
        if ( DebugFlag )
 
443
          syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime=%u in DHCP server response.\n",
 
444
          ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]));
 
445
    }
 
446
  else /* did not get dhcpIPaddrLeaseTime */
 
447
    {
 
448
      DhcpOptions.val[dhcpIPaddrLeaseTime] = malloc(4);
 
449
      memcpy(DhcpOptions.val[dhcpIPaddrLeaseTime],&nleaseTime,4);
 
450
      DhcpOptions.len[dhcpIPaddrLeaseTime] = 4;
 
451
      DhcpOptions.num++;
 
452
      if ( DebugFlag )
 
453
        syslog(LOG_DEBUG,"dhcpIPaddrLeaseTime option is missing in DHCP server response. Assuming %u sec\n",LeaseTime);
 
454
    }
 
455
  if ( DhcpOptions.val[dhcpT1value] && DhcpOptions.len[dhcpT1value] == 4 )
 
456
    {
 
457
      if ( *(unsigned int *)DhcpOptions.val[dhcpT1value] == 0 )
 
458
        {
 
459
          unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
 
460
          int t1 = htonl(t2);
 
461
          memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
 
462
          DhcpOptions.len[dhcpT1value] = 4;
 
463
          if ( DebugFlag )
 
464
            syslog(LOG_DEBUG,"dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2);
 
465
        }
 
466
    }
 
467
  else          /* did not get T1 */
 
468
    {
 
469
      unsigned t2 = 0.5*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
 
470
      int t1 = htonl(t2);
 
471
      DhcpOptions.val[dhcpT1value] = malloc(4);
 
472
      memcpy(DhcpOptions.val[dhcpT1value],&t1,4);
 
473
      DhcpOptions.len[dhcpT1value] = 4;
 
474
      DhcpOptions.num++;
 
475
      if ( DebugFlag )
 
476
        syslog(LOG_DEBUG,"dhcpT1value is missing in DHCP server response. Assuming %u sec\n",t2);
 
477
    }
 
478
  if ( DhcpOptions.val[dhcpT2value] && DhcpOptions.len[dhcpT2value] == 4 )
 
479
    {
 
480
      if ( *(unsigned int *)DhcpOptions.val[dhcpT2value] == 0 )
 
481
        {
 
482
          unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
 
483
          int t1 = htonl(t2);
 
484
          memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
 
485
          DhcpOptions.len[dhcpT2value] = 4;
 
486
          if ( DebugFlag )
 
487
            syslog(LOG_DEBUG,"dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2);
 
488
        }
 
489
    }
 
490
  else          /* did not get T2 */
 
491
    {
 
492
      unsigned t2 = 0.875*ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime]);
 
493
      int t1 = htonl(t2);
 
494
      DhcpOptions.val[dhcpT2value] = malloc(4);
 
495
      memcpy(DhcpOptions.val[dhcpT2value],&t1,4);
 
496
      DhcpOptions.len[dhcpT2value] = 4;
 
497
      DhcpOptions.num++;
 
498
      if ( DebugFlag )
 
499
        syslog(LOG_DEBUG,"dhcpT2value is missing in DHCP server response. Assuming %u sec\n",t2);
 
500
    }
 
501
  if ( DhcpOptions.val[dhcpFQDNHostName] )
 
502
    {
 
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);
 
508
    }
 
509
  else
 
510
    {
 
511
      if ( DebugFlag && (SetFQDNHostName != FQDNdisable) )
 
512
        {
 
513
          syslog(LOG_DEBUG,"dhcpFQDNHostName is missing in DHCP server response.\n");
 
514
        }
 
515
    }
 
516
  if ( DhcpOptions.val[dhcpMessageType] )
 
517
    return *(unsigned char *)DhcpOptions.val[dhcpMessageType];
 
518
  return 0;
 
519
}
 
520
/*****************************************************************************/
 
521
void classIDsetup()
 
522
{
 
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);
 
527
}
 
528
/*****************************************************************************/
 
529
void clientIDsetup()
 
530
{
 
531
  unsigned char *c = DhcpIface.client_id;
 
532
  *c++ = dhcpClientIdentifier;
 
533
  if ( ClientID )
 
534
    {
 
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;
 
539
      return;
 
540
    }
 
541
  *c++ = ETH_ALEN + 1;          /* length: 6 (MAC Addr) + 1 (# field) */
 
542
  *c++ = (TokenRingIf) ? ARPHRD_IEEE802_TR : ARPHRD_ETHER;      /* type: Ethernet address */
 
543
#if 0
 
544
  memcpy(c,DhcpIface.chaddr,ETH_ALEN);
 
545
#else
 
546
  memcpy(c,ClientHwAddr,ETH_ALEN);
 
547
#endif
 
548
  DhcpIface.client_len = ETH_ALEN + 3;
 
549
}
 
550
/*****************************************************************************/
 
551
void releaseDhcpOptions()
 
552
{
 
553
  register int i;
 
554
  for (i=1;i<256;i++)
 
555
    if ( DhcpOptions.val[i] ) free(DhcpOptions.val[i]);
 
556
  memset(&DhcpOptions,0,sizeof(dhcpOptions));
 
557
}
 
558
/*****************************************************************************/
 
559
#ifdef DEBUG
 
560
static void dumpframe(const char *title, struct packed_ether_header *frame)
 
561
{
 
562
  int i;
 
563
  unsigned char *dp;
 
564
 
 
565
  printf("%s:", title);
 
566
  dp = (unsigned char *)frame;
 
567
  for (i = 0; i < 32; i++)
 
568
    {
 
569
      if ((i % 16) == 0)
 
570
        printf("\n");
 
571
      printf("0x%02X ", *dp++);
 
572
    }
 
573
}
 
574
#endif /* DEBUG */
 
575
/*****************************************************************************/
 
576
/***** convert ethernet and token-ring frames *****/
 
577
int eth2tr(struct packed_ether_header *frame, int datalen)
 
578
{
 
579
  struct trh_hdr *phdr;
 
580
  struct trllc *pllc;
 
581
  char trheader[sizeof(struct trh_hdr) - sizeof(phdr->rseg) + sizeof(struct trllc)];
 
582
  int len;
 
583
 
 
584
#ifdef DEBUG
 
585
  dumpframe("eth2tr: Incoming eth frame", frame);
 
586
#endif
 
587
  memset(trheader, 0, sizeof(trheader));
 
588
  phdr = (struct trh_hdr *)trheader;
 
589
  phdr->ac = AC;
 
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);
 
599
    }
 
600
  else
 
601
    {
 
602
      pllc = (struct trllc *)&phdr->rcf;
 
603
      len = sizeof(trheader) - sizeof(phdr->rcf);
 
604
    }
 
605
  pllc->dsap = EXTENDED_SAP;
 
606
  pllc->ssap = EXTENDED_SAP;
 
607
  pllc->llc = UI_CMD;
 
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 */
 
613
#ifdef DEBUG
 
614
  dumpframe("eth2tr: Outgoing tr frame", frame);
 
615
#endif
 
616
  return len + datalen;
 
617
}
 
618
/*****************************************************************************/
 
619
int tr2eth(struct packed_ether_header *frame)
 
620
{
 
621
  struct trh_hdr hdr;
 
622
  struct trllc *pllc;
 
623
  int hlen = 0;
 
624
 
 
625
#ifdef DEBUG
 
626
  dumpframe("tr2eth: Incoming tr frame", frame);
 
627
#endif
 
628
  hdr = *((struct trh_hdr *)frame);
 
629
  if (hdr.saddr[0] & TR_RII)
 
630
    {
 
631
fake_rif :
 
632
      hlen = hdr.rcf & ntohs(TR_RCF_LEN_MASK);
 
633
#ifdef DEBUG
 
634
      printf("rcf = 0x%X SR len %d\n", hdr.rcf, hlen);
 
635
#endif
 
636
      if (hlen < sizeof(hdr.rcf) || (hlen & 1))
 
637
        return 1;
 
638
      hdr.saddr[0] &= ~TR_RII;
 
639
    }
 
640
  pllc = (struct trllc *)(((__u8 *)frame) + sizeof(struct trh_hdr) - TR_MAXRIFLEN + hlen);
 
641
  if (pllc->dsap != EXTENDED_SAP || pllc->llc != UI_CMD)
 
642
    {
 
643
      if (hlen == 0)
 
644
          goto fake_rif;        /* Bug in 2.2.3 kernel */
 
645
#ifdef DEBUG
 
646
      printf("corrupted TR-IP packet of ui=0x%x and dsap 0x%x discarded\n",
 
647
        pllc->llc,pllc->dsap);
 
648
#endif
 
649
      return 1;
 
650
    }
 
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 */
 
655
#ifdef DEBUG
 
656
  dumpframe("tr2eth: Outgoing eth frame", frame);
 
657
#endif
 
658
  return 0;
 
659
}
 
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;
 
666
{
 
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;
 
671
    y->tv_sec += nsec;
 
672
  }
 
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;
 
676
    y->tv_sec -= nsec;
 
677
  }
 
678
 
 
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;
 
683
 
 
684
  /* Return 1 if result is negative. */
 
685
  return x->tv_sec < y->tv_sec;
 
686
}
 
687
/*****************************************************************************/
 
688
int dhcpSendAndRecv(xid,msg,buildUdpIpMsg)
 
689
unsigned xid,msg;
 
690
void (*buildUdpIpMsg)(unsigned);
 
691
{
 
692
  struct sockaddr addr;
 
693
  struct timeval begin, current, diff;
 
694
  int i,len,o,timeout=0;
 
695
  char foobuf[512];
 
696
  const struct udphdr *udpRecv;
 
697
  int j=DHCP_INITIAL_RTO/2;
 
698
 
 
699
  do
 
700
    {
 
701
      do
 
702
        {
 
703
          j+=j;
 
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);
 
707
          buildUdpIpMsg(xid);
 
708
          if ( TokenRingIf )      /* Here we convert a Eth frame into an TR frame */
 
709
            len = eth2tr(&UdpIpMsgSend.ethhdr,sizeof(udpiphdr)+sizeof(dhcpMessage));
 
710
          else
 
711
            len = sizeof(struct packed_ether_header)+sizeof(udpiphdr)+sizeof(dhcpMessage);
 
712
          if ( sendto(dhcpSocket,&UdpIpMsgSend,len,0,
 
713
                &addr,sizeof(struct sockaddr)) == -1 )
 
714
            {
 
715
              syslog(LOG_ERR,"sendto: %m\n");
 
716
              return -1;
 
717
            }
 
718
          gettimeofday(&begin, NULL);
 
719
          i=random();
 
720
        }
 
721
      while ( peekfd(dhcpSocket,j+i%200000) );
 
722
      do
 
723
        {
 
724
          struct ip ipRecv_local;
 
725
          char *tmp_ip;
 
726
          memset(&UdpIpMsgRecv,0,sizeof(udpipMessage));
 
727
          o=sizeof(struct sockaddr);
 
728
          len=recvfrom(dhcpSocket,&UdpIpMsgRecv,sizeof(udpipMessage),0,
 
729
                     (struct sockaddr *)&addr,&o);
 
730
          if ( len == -1 )
 
731
            {
 
732
              syslog(LOG_ERR,"recvfrom: %m\n");
 
733
              return -1;
 
734
            }
 
735
          if ( TokenRingIf )
 
736
            {    /* Here we convert a TR frame into an Eth frame */
 
737
              if ( tr2eth(&UdpIpMsgRecv.ethhdr) ) continue;
 
738
            }
 
739
          gettimeofday(&current, NULL);
 
740
          timeval_subtract(&diff, &current, &begin);
 
741
          timeout = j - diff.tv_sec*1000000 - diff.tv_usec + random()%200000;
 
742
          if ( UdpIpMsgRecv.ethhdr.ether_type != htons(ETHERTYPE_IP) )
 
743
            continue;
 
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 ) )
 
748
              {
 
749
                tmp_ip=&(UdpIpMsgRecv.udpipmsg[i]);
 
750
                break;
 
751
              }
 
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;
 
756
          if ( TokenRingIf )
 
757
            {
 
758
              if ( udpRecv->uh_dport != htons(DHCP_CLIENT_PORT) ) continue;
 
759
            }
 
760
          len-=sizeof(struct packed_ether_header);
 
761
          i=(int )ntohs(ipRecv_local.ip_len);
 
762
          if ( len < i )
 
763
            {
 
764
              if ( DebugFlag ) syslog(LOG_DEBUG,
 
765
                "corrupted IP packet of size=%d and ip_len=%d discarded\n",
 
766
                len,i);
 
767
              continue;
 
768
            }
 
769
          len=i-(ipRecv_local.ip_hl<<2);
 
770
          i=(int )ntohs(udpRecv->uh_ulen);
 
771
          if ( len < i )
 
772
            {
 
773
              if ( DebugFlag ) syslog(LOG_DEBUG,
 
774
                "corrupted UDP msg of size=%d and uh_ulen=%d discarded\n",
 
775
                len,i);
 
776
              continue;
 
777
            }
 
778
          if ( DoCheckSum )
 
779
            {
 
780
              len=udpipchk((udpiphdr *)tmp_ip);
 
781
              if ( len )
 
782
                {
 
783
                  if ( DebugFlag )
 
784
                    switch ( len )
 
785
                      {
 
786
                        case -1: syslog(LOG_DEBUG,
 
787
                          "corrupted IP packet with ip_len=%d discarded\n",
 
788
                          (int )ntohs(ipRecv_local.ip_len));
 
789
                          break;
 
790
                        case -2: syslog(LOG_DEBUG,
 
791
                          "corrupted UDP msg with uh_ulen=%d discarded\n",
 
792
                          (int )ntohs(udpRecv->uh_ulen));
 
793
                        break;
 
794
                      }
 
795
                  continue;
 
796
                }
 
797
            }
 
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 )
 
802
            {
 
803
                if ( DebugFlag )
 
804
                  syslog(LOG_DEBUG,"wrong msg htype 0x%X discarded\n",DhcpMsgRecv->htype);
 
805
                continue;
 
806
            }
 
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 )
 
813
            {
 
814
              if ( DhcpOptions.val[dhcpMsg] )
 
815
                syslog(LOG_ERR,
 
816
                "DHCP_NAK server response received: %s\n",
 
817
                (char *)DhcpOptions.val[dhcpMsg]);
 
818
              else
 
819
                syslog(LOG_ERR,
 
820
                "DHCP_NAK server response received\n");
 
821
              return 1;
 
822
            }
 
823
        }
 
824
      while ( timeout > 0 && peekfd(dhcpSocket, timeout) == 0 );
 
825
    }
 
826
  while ( 1 );
 
827
  return 1;
 
828
}
 
829
/*****************************************************************************/
 
830
void *dhcpStart()
 
831
{
 
832
  int o = 1;
 
833
  unsigned i=0;
 
834
  struct ifreq  ifr;
 
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));
 
841
#else
 
842
  dhcpSocket = socket(AF_PACKET,SOCK_PACKET,htons(ETH_P_ALL));
 
843
#endif
 
844
  if ( dhcpSocket == -1 )
 
845
    {
 
846
      syslog(LOG_ERR,"dhcpStart: socket: %m\n");
 
847
      exit(1);
 
848
    }
 
849
 
 
850
  if ( ioctl(dhcpSocket,SIOCGIFHWADDR,&ifr) )
 
851
    {
 
852
      syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n");
 
853
      exit(1);
 
854
    }
 
855
  if ( ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER && ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR )
 
856
    {
 
857
      syslog(LOG_ERR,"dhcpStart: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name);
 
858
      exit(1);
 
859
    }
 
860
  if ( ifr.ifr_hwaddr.sa_family == ARPHRD_IEEE802_TR )
 
861
    {
 
862
      TokenRingIf = 1;
 
863
      if ( DebugFlag )
 
864
        syslog(LOG_DEBUG,"found NIC of link layer type %d\n",ifr.ifr_hwaddr.sa_family);
 
865
    }
 
866
  if ( setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1 )
 
867
    {
 
868
      syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
 
869
      exit(1);
 
870
    }
 
871
  if ( ioctl(dhcpSocket,SIOCGIFFLAGS,&ifr) )  
 
872
    {  
 
873
      syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFFLAGS: %m\n");  
 
874
      exit(1);  
 
875
    }  
 
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) )
 
879
    {
 
880
      syslog(LOG_ERR,"dhcpStart: ioctl SIOCSIFFLAGS: %m\n");
 
881
      exit(1);
 
882
    }
 
883
  memset(&sap,0,sizeof(sap));
 
884
 
 
885
  do
 
886
    {
 
887
      i++;
 
888
      if ( i>1 )
 
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) )
 
894
        {
 
895
          syslog(LOG_ERR,"dhcpStart: ioctl SIOCGIFHWADDR: %m\n");
 
896
          exit(1);
 
897
        }
 
898
      if ( ifr.ifr_hwaddr.sa_family != ARPHRD_ETHER && ifr.ifr_hwaddr.sa_family != ARPHRD_IEEE802_TR )
 
899
        {
 
900
          syslog(LOG_ERR,"dhcpStart: interface %s is not Ethernet or 802.2 Token Ring\n",ifr.ifr_name);
 
901
          exit(1);
 
902
        }
 
903
      if ( setsockopt(dhcpSocket,SOL_SOCKET,SO_BROADCAST,&o,sizeof(o)) == -1 )
 
904
        {
 
905
          syslog(LOG_ERR,"dhcpStart: setsockopt: %m\n");
 
906
          exit(1);
 
907
        }
 
908
      ifr.ifr_flags = saved_if_flags | IFF_UP | IFF_BROADCAST | IFF_NOTRAILERS | IFF_RUNNING;
 
909
      if ( ioctl(dhcpSocket,SIOCSIFFLAGS,&ifr) )
 
910
        {
 
911
          syslog(LOG_ERR,"dhcpStart: ioctl SIOCSIFFLAGS: %m\n");
 
912
          exit(1);
 
913
        }
 
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;
 
919
#else
 
920
      sap.spkt_family = AF_PACKET;
 
921
#endif
 
922
      if ( bind(dhcpSocket,(void*)&sap,sizeof(struct sockaddr)) == -1 )
 
923
        syslog(LOG_ERR,"dhcpStart: bind: %m\n");
 
924
 
 
925
      memcpy(ClientHwAddr,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
 
926
      if ( DebugFlag )
 
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]);
 
930
    }
 
931
  while ( !ClientHwAddr[0] &&
 
932
          !ClientHwAddr[1] &&
 
933
          !ClientHwAddr[2] &&
 
934
          !ClientHwAddr[3] &&
 
935
          !ClientHwAddr[4] &&
 
936
          !ClientHwAddr[5] &&
 
937
           i<HWADDR_TRIES );
 
938
 
 
939
  i=time(NULL)+ClientHwAddr[5]+4*ClientHwAddr[4]+8*ClientHwAddr[3]+
 
940
  16*ClientHwAddr[2]+32*ClientHwAddr[1]+64*ClientHwAddr[0];
 
941
  srandom(i);
 
942
  ip_id=i&0xffff;
 
943
 
 
944
  udpFooSocket = socket(AF_INET,SOCK_DGRAM,0);
 
945
  if ( udpFooSocket == -1 )
 
946
    {
 
947
      syslog(LOG_ERR,"dhcpStart: socket: %m\n");
 
948
      exit(1);
 
949
    }
 
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)) )
 
956
    {
 
957
      if ( errno != EADDRINUSE )
 
958
        syslog(LOG_ERR,"dhcpStart: bind: %m\n");
 
959
      close(udpFooSocket);
 
960
      udpFooSocket = -1;
 
961
    }
 
962
  else
 
963
    if ( fcntl(udpFooSocket,F_SETFL,O_NONBLOCK) == -1 )
 
964
      {
 
965
        syslog(LOG_ERR,"dhcpStart: fcntl: %m\n");
 
966
        exit(1);
 
967
      }
 
968
 
 
969
  return &dhcpInit;
 
970
}
 
971
/*****************************************************************************/
 
972
void classclientsetup()
 
973
{
 
974
  if ( ClassID )
 
975
    {
 
976
      memcpy(DhcpIface.class_id,ClassID,ClassID_len);
 
977
      DhcpIface.class_len=ClassID_len;
 
978
    }
 
979
  else
 
980
    classIDsetup();
 
981
  clientIDsetup();
 
982
}
 
983
/*****************************************************************************/
 
984
void *dhcpReboot()
 
985
{
 
986
  if ( sigsetjmp(env,0xffff) )
 
987
    {
 
988
      if ( DebugFlag )
 
989
        syslog(LOG_DEBUG,"timed out waiting for DHCP_ACK response\n");
 
990
      if (TimeOut != 0)
 
991
        alarm(TimeOut);
 
992
      return &dhcpInit;
 
993
    }
 
994
  dhcpStart();
 
995
  memset(&DhcpOptions,0,sizeof(DhcpOptions));
 
996
  memset(&DhcpIface,0,sizeof(dhcpInterface));
 
997
  if ( readDhcpCache() )
 
998
    {
 
999
      struct ifreq      ifr;
 
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);
 
1005
#else
 
1006
      memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
 
1007
#endif
 
1008
      p->sin_family = AF_INET;
 
1009
      if ( ioctl(dhcpSocket,SIOCGIFADDR,&ifr) == 0 )
 
1010
        DhcpIface.ciaddr=p->sin_addr.s_addr;
 
1011
#if 0
 
1012
      if ( ClientMACaddr_ind )
 
1013
        memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
 
1014
      else
 
1015
        memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
 
1016
#endif
 
1017
      classclientsetup();
 
1018
      return &dhcpInit;
 
1019
    }
 
1020
  classclientsetup();
 
1021
#if 0
 
1022
  if ( ClientMACaddr_ind )
 
1023
    memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
 
1024
  else
 
1025
    memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
 
1026
#endif
 
1027
  return dhcpRequest(random(),&buildDhcpReboot);
 
1028
}
 
1029
/*****************************************************************************/
 
1030
void *dhcpInit()
 
1031
{
 
1032
  releaseDhcpOptions();
 
1033
 
 
1034
#ifdef DEBUG
 
1035
fprintf(stderr,"ClassID  = \"%s\"\n\
 
1036
ClientID = \"%u.%u.%u.%02X.%02X.%02X.%02X.%02X.%02X\"\n",
 
1037
DhcpIface.class_id,
 
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]);
 
1041
#endif
 
1042
 
 
1043
  if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting DHCP_DISCOVER\n");
 
1044
  if ( dhcpSendAndRecv(random(),DHCP_OFFER,&buildDhcpDiscover) )
 
1045
    {
 
1046
      dhcpStop();
 
1047
      return 0;
 
1048
    }
 
1049
  if ( SendSecondDiscover )
 
1050
    {
 
1051
      if ( DebugFlag ) syslog(LOG_DEBUG,"broadcasting second DHCP_DISCOVER\n");
 
1052
      dhcpSendAndRecv(DhcpMsgRecv->xid,DHCP_OFFER,&buildDhcpDiscover);
 
1053
    }
 
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 */
 
1060
  if ( DebugFlag )
 
1061
    syslog(LOG_DEBUG,"DHCP_OFFER received from %s (%u.%u.%u.%u)\n",
 
1062
    DhcpMsgRecv->sname,
 
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]);
 
1067
 
 
1068
  return dhcpRequest(DhcpIface.xid,&buildDhcpRequest);
 
1069
}
 
1070
/*****************************************************************************/
 
1071
void *dhcpRequest(xid,buildDhcpMsg)
 
1072
unsigned xid;
 
1073
void (*buildDhcpMsg)(unsigned);
 
1074
{
 
1075
/* send the message and read and parse replies into DhcpOptions */
 
1076
  if ( DebugFlag )
 
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]);
 
1090
#ifdef ARPCHECK
 
1091
/* check if the offered IP address already in use */
 
1092
  if ( arpCheck() )
 
1093
    {
 
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]);
 
1100
      dhcpDecline();
 
1101
      DhcpIface.ciaddr = 0;
 
1102
      return &dhcpInit;
 
1103
    }
 
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]);
 
1110
#endif
 
1111
  if ( dhcpConfig() )
 
1112
    {
 
1113
      dhcpStop();
 
1114
      return 0;
 
1115
    }
 
1116
 
 
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);
 
1120
 
 
1121
  return &dhcpBound;
 
1122
}
 
1123
/*****************************************************************************/
 
1124
void *dhcpBound()
 
1125
{
 
1126
  int i;
 
1127
  if ( sigsetjmp(env,0xffff) ) return &dhcpRenew;
 
1128
  i=ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT1value])-time(NULL);
 
1129
  if ( i > 0 )
 
1130
    alarm(i);
 
1131
  else
 
1132
    return &dhcpRenew;
 
1133
 
 
1134
  sleep(ntohl(*(u_int *)DhcpOptions.val[dhcpT1value]));
 
1135
  return &dhcpRenew;
 
1136
}
 
1137
/*****************************************************************************/
 
1138
void *dhcpRenew()
 
1139
{
 
1140
  int i;
 
1141
  if ( sigsetjmp(env,0xffff) ) return &dhcpRebind;
 
1142
  i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpT2value])-time(NULL);
 
1143
  if ( i > 0 )
 
1144
    alarm(i);
 
1145
  else
 
1146
    return &dhcpRebind;
 
1147
 
 
1148
  if ( DebugFlag )
 
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]);
 
1166
  return &dhcpBound;
 
1167
}
 
1168
/*****************************************************************************/
 
1169
void *dhcpRebind()
 
1170
{
 
1171
  int i;
 
1172
  if ( sigsetjmp(env,0xffff) ) return &dhcpStop;
 
1173
  i = ReqSentTime+ntohl(*(unsigned int *)DhcpOptions.val[dhcpIPaddrLeaseTime])-time(NULL);
 
1174
  if ( i > 0 )
 
1175
    alarm(i);
 
1176
  else
 
1177
    return &dhcpStop;
 
1178
 
 
1179
  if ( DebugFlag )
 
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]);
 
1193
 
 
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);
 
1197
 
 
1198
  return &dhcpBound;
 
1199
}
 
1200
/*****************************************************************************/
 
1201
void *dhcpRelease()
 
1202
{
 
1203
  struct sockaddr addr;
 
1204
  deleteDhcpCache();
 
1205
  if ( DhcpIface.ciaddr == 0 ) return &dhcpInit;
 
1206
 
 
1207
  buildDhcpRelease(random());
 
1208
 
 
1209
  memset(&addr,0,sizeof(struct sockaddr));
 
1210
  memcpy(addr.sa_data,IfName,IfName_len);
 
1211
  if ( DebugFlag )
 
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 */
 
1226
  if ( SetHostName )
 
1227
    {
 
1228
      sethostname(InitialHostName,InitialHostName_len);
 
1229
      if ( DebugFlag )
 
1230
        fprintf(stdout,"dhcpcd: your hostname = %s\n",InitialHostName);
 
1231
    }
 
1232
  if ( SetDomainName )
 
1233
    {
 
1234
      setdomainname(InitialDomainName,InitialDomainName_len);
 
1235
      if ( DebugFlag )
 
1236
        fprintf(stdout,"dhcpcd: your domainname = %s\n",InitialDomainName);
 
1237
    }
 
1238
  DhcpIface.ciaddr=0;
 
1239
  return &dhcpInit;
 
1240
}
 
1241
/*****************************************************************************/
 
1242
void *dhcpStop()
 
1243
{
 
1244
  struct ifreq ifr;
 
1245
  struct sockaddr_in    *p = (struct sockaddr_in *)&(ifr.ifr_addr);
 
1246
 
 
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);
 
1252
#else
 
1253
  memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
 
1254
#endif
 
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");
 
1260
#endif
 
1261
  if (DownIfaceOnStop)
 
1262
    {
 
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");
 
1266
    }
 
1267
tsc:
 
1268
  close(dhcpSocket);
 
1269
  if ( resolv_renamed )
 
1270
    rename(resolv_file_sv, resolv_file);
 
1271
  if ( yp_renamed )
 
1272
    rename(nis_file_sv, nis_file);
 
1273
  if ( ntp_renamed )
 
1274
    rename(ntp_file_sv, ntp_file);
 
1275
  execute_on_change("down");
 
1276
  return &dhcpStart;
 
1277
}
 
1278
/*****************************************************************************/
 
1279
#ifdef ARPCHECK
 
1280
void *dhcpDecline()
 
1281
{
 
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");
 
1297
  return &dhcpInit;
 
1298
}
 
1299
#endif
 
1300
/*****************************************************************************/
 
1301
void *dhcpInform()
 
1302
{
 
1303
  dhcpStart();
 
1304
  memset(&DhcpOptions,0,sizeof(DhcpOptions));
 
1305
  memset(&DhcpIface,0,sizeof(dhcpInterface));
 
1306
  if ( ! inform_ipaddr.s_addr )
 
1307
    {
 
1308
      struct ifreq ifr;
 
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);
 
1313
#else
 
1314
      memcpy(ifr.ifr_name,IfNameExt,IfNameExt_len);
 
1315
#endif
 
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 )
 
1320
        {
 
1321
          if ( readDhcpCache() )
 
1322
            {
 
1323
              syslog(LOG_ERR,"dhcpInform: no IP address given\n");
 
1324
              return NULL;
 
1325
            }
 
1326
          else
 
1327
            inform_ipaddr.s_addr=DhcpIface.ciaddr;
 
1328
        }
 
1329
    }
 
1330
#if 0
 
1331
  if ( ! DhcpIface.ciaddr )
 
1332
    {
 
1333
      if ( ClientMACaddr_ind )
 
1334
        memcpy(DhcpIface.chaddr,ClientMACaddr,ETH_ALEN);
 
1335
      else
 
1336
        memcpy(DhcpIface.chaddr,ClientHwAddr,ETH_ALEN);
 
1337
    }
 
1338
#endif
 
1339
  DhcpIface.ciaddr=inform_ipaddr.s_addr;
 
1340
  if ( ! DhcpIface.class_len )
 
1341
    { 
 
1342
      if ( ClassID )
 
1343
        {
 
1344
          memcpy(DhcpIface.class_id,ClassID,ClassID_len);
 
1345
          DhcpIface.class_len=ClassID_len;
 
1346
        }
 
1347
      else
 
1348
        classIDsetup();
 
1349
    }
 
1350
  if ( ! DhcpIface.client_len ) clientIDsetup();
 
1351
  if ( sigsetjmp(env,0xffff) )
 
1352
    {
 
1353
      if ( DebugFlag )
 
1354
        syslog(LOG_DEBUG,"timed out waiting for DHCP_ACK response\n");
 
1355
      return 0;
 
1356
    }
 
1357
  if ( DebugFlag )
 
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]);
 
1370
#ifdef ARPCHECK
 
1371
/* check if the offered IP address already in use */
 
1372
  if ( arpCheck() )
 
1373
    {
 
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]);
 
1380
      dhcpDecline();
 
1381
      return 0;
 
1382
    }
 
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]);
 
1389
#endif
 
1390
  if ( dhcpConfig() ) return 0;
 
1391
  exit(0);
 
1392
}