ReactOS 0.4.16-dev-1041-g8b6907f
dhclient.c
Go to the documentation of this file.
1/* $OpenBSD: dhclient.c,v 1.62 2004/12/05 18:35:51 deraadt Exp $ */
2
3/*
4 * Copyright 2004 Henning Brauer <henning@openbsd.org>
5 * Copyright (c) 1995, 1996, 1997, 1998, 1999
6 * The Internet Software Consortium. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the distribution.
17 * 3. Neither the name of The Internet Software Consortium nor the names
18 * of its contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND
22 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
23 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
24 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
25 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR
26 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
29 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
30 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 *
35 * This software has been written for the Internet Software Consortium
36 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie
37 * Enterprises. To learn more about the Internet Software Consortium,
38 * see ``http://www.vix.com/isc''. To learn more about Vixie
39 * Enterprises, see ``http://www.vix.com''.
40 *
41 * This client was substantially modified and enhanced by Elliot Poger
42 * for use on Linux while he was working on the MosquitoNet project at
43 * Stanford.
44 *
45 * The current version owes much to Elliot's Linux enhancements, but
46 * was substantially reorganized and partially rewritten by Ted Lemon
47 * so as to use the same networking framework that the Internet Software
48 * Consortium DHCP server uses. Much system-specific configuration code
49 * was moved into a shell script so that as support for more operating
50 * systems is added, it will not be necessary to port and maintain
51 * system-specific configuration code to these operating systems - instead,
52 * the shell script can invoke the native tools to accomplish the same
53 * purpose.
54 */
55
56#include <rosdhcp.h>
57
58#define PERIOD 0x2e
59#define hyphenchar(c) ((c) == 0x2d)
60#define bslashchar(c) ((c) == 0x5c)
61#define periodchar(c) ((c) == PERIOD)
62#define asterchar(c) ((c) == 0x2a)
63#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \
64 ((c) >= 0x61 && (c) <= 0x7a))
65#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
66
67#define borderchar(c) (alphachar(c) || digitchar(c))
68#define middlechar(c) (borderchar(c) || hyphenchar(c))
69#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
70
71unsigned long debug_trace_level = 0; /* DEBUG_ULTRA */
72
75
76int log_perror = 1;
78//int nullfd = -1;
79
80struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } };
83
84/*
85 * ASSERT_STATE() does nothing now; it used to be
86 * assert (state_is == state_shouldbe).
87 */
88#define ASSERT_STATE(state_is, state_shouldbe) {}
89
90#define TIME_MAX 2147483647
91
94int unknown_ok = 1;
96
97void usage(void);
98int check_option(struct client_lease *l, int option);
99int ipv4addrs(char * buf);
100int res_hnok(const char *dn);
101char *option_as_string(unsigned int code, unsigned char *data, int len);
102int fork_privchld(int, int);
103int check_arp( struct interface_info *ip, struct client_lease *lp );
104
105#define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len))
106
108
109
110int
112{
113 ApiInit();
114 AdapterInit();
115
116 tzset();
117
119 sockaddr_broadcast.sin_family = AF_INET;
121 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST;
122 inaddr_any.s_addr = INADDR_ANY;
124
125 return 1; // TRUE
126}
127
128void
130{
131 // AdapterStop();
132 // ApiFree();
133 /* FIXME: Close pipe and kill pipe thread */
134}
135
136/* XXX Implement me */
137int check_arp( struct interface_info *ip, struct client_lease *lp ) {
138 return 1;
139}
140
141/*
142 * Individual States:
143 *
144 * Each routine is called from the dhclient_state_machine() in one of
145 * these conditions:
146 * -> entering INIT state
147 * -> recvpacket_flag == 0: timeout in this state
148 * -> otherwise: received a packet in this state
149 *
150 * Return conditions as handled by dhclient_state_machine():
151 * Returns 1, sendpacket_flag = 1: send packet, reset timer.
152 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone).
153 * Returns 0: finish the nap which was interrupted for no good reason.
154 *
155 * Several per-interface variables are used to keep track of the process:
156 * active_lease: the lease that is being used on the interface
157 * (null pointer if not configured yet).
158 * offered_leases: leases corresponding to DHCPOFFER messages that have
159 * been sent to us by DHCP servers.
160 * acked_leases: leases corresponding to DHCPACK messages that have been
161 * sent to us by DHCP servers.
162 * sendpacket: DHCP packet we're trying to send.
163 * destination: IP address to send sendpacket to
164 * In addition, there are several relevant per-lease variables.
165 * T1_expiry, T2_expiry, lease_expiry: lease milestones
166 * In the active lease, these control the process of renewing the lease;
167 * In leases on the acked_leases list, this simply determines when we
168 * can no longer legitimately use the lease.
169 */
170
171void
172state_reboot(void *ipp)
173{
174 struct interface_info *ip = ipp;
176
177 /* If we don't remember an active lease, go straight to INIT. */
178 if (!ip->client->active || ip->client->active->is_bootp) {
179 state_init(ip);
180 return;
181 }
182
183 /* We are in the rebooting state. */
184 ip->client->state = S_REBOOTING;
185
186 /* make_request doesn't initialize xid because it normally comes
187 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER,
188 so pick an xid now. */
189 ip->client->xid = RtlRandom(&foo);
190
191 /* Make a DHCPREQUEST packet, and set appropriate per-interface
192 flags. */
193 make_request(ip, ip->client->active);
194 ip->client->destination = iaddr_broadcast;
195 time(&ip->client->first_sending);
196 ip->client->interval = ip->client->config->initial_interval;
197
198 /* Zap the medium list... */
199 ip->client->medium = NULL;
200
201 /* Send out the first DHCPREQUEST packet. */
203}
204
205/*
206 * Called when a lease has completely expired and we've
207 * been unable to renew it.
208 */
209void
210state_init(void *ipp)
211{
212 struct interface_info *ip = ipp;
213
215
216 /* Make a DHCPDISCOVER packet, and set appropriate per-interface
217 flags. */
218 make_discover(ip, ip->client->active);
219 ip->client->xid = ip->client->packet.xid;
220 ip->client->destination = iaddr_broadcast;
221 ip->client->state = S_SELECTING;
222 time(&ip->client->first_sending);
223 ip->client->interval = ip->client->config->initial_interval;
224
225 /* Add an immediate timeout to cause the first DHCPDISCOVER packet
226 to go out. */
228}
229
230/*
231 * state_selecting is called when one or more DHCPOFFER packets
232 * have been received and a configurable period of time has passed.
233 */
234void
236{
237 struct interface_info *ip = ipp;
238 struct client_lease *lp, *next, *picked;
240
242
243 time(&cur_time);
244
245 /* Cancel state_selecting and send_discover timeouts, since either
246 one could have got us here. */
249
250 /* We have received one or more DHCPOFFER packets. Currently,
251 the only criterion by which we judge leases is whether or
252 not we get a response when we arp for them. */
253 picked = NULL;
254 for (lp = ip->client->offered_leases; lp; lp = next) {
255 next = lp->next;
256
257 /* Check to see if we got an ARPREPLY for the address
258 in this particular lease. */
259 if (!picked) {
260 if( !check_arp(ip,lp) ) goto freeit;
261 picked = lp;
262 picked->next = NULL;
263 } else {
264freeit:
266 }
267 }
268 ip->client->offered_leases = NULL;
269
270 /* If we just tossed all the leases we were offered, go back
271 to square one. */
272 if (!picked) {
273 ip->client->state = S_INIT;
274 state_init(ip);
275 return;
276 }
277
278 /* If it was a BOOTREPLY, we can just take the address right now. */
279 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) {
280 ip->client->new = picked;
281
282 /* Make up some lease expiry times
283 XXX these should be configurable. */
284 ip->client->new->expiry = cur_time + 12000;
285 ip->client->new->renewal += cur_time + 8000;
286 ip->client->new->rebind += cur_time + 10000;
287
288 ip->client->state = S_REQUESTING;
289
290 /* Bind to the address we received. */
291 bind_lease(ip);
292 return;
293 }
294
295 /* Go to the REQUESTING state. */
296 ip->client->destination = iaddr_broadcast;
297 ip->client->state = S_REQUESTING;
298 ip->client->first_sending = cur_time;
299 ip->client->interval = ip->client->config->initial_interval;
300
301 /* Make a DHCPREQUEST packet from the lease we picked. */
302 make_request(ip, picked);
303 ip->client->xid = ip->client->packet.xid;
304
305 /* Toss the lease we picked - we'll get it back in a DHCPACK. */
306 free_client_lease(picked);
307
308 /* Add an immediate timeout to send the first DHCPREQUEST packet. */
310}
311
312/* state_requesting is called when we receive a DHCPACK message after
313 having sent out one or more DHCPREQUEST packets. */
314
315void
317{
319 struct client_lease *lease;
321
322 time(&cur_time);
323
324 /* If we're not receptive to an offer right now, or if the offer
325 has an unrecognizable transaction id, then just drop it. */
326 if (packet->interface->client->xid != packet->raw->xid ||
327 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
328 (memcmp(packet->interface->hw_address.haddr,
329 packet->raw->chaddr, packet->raw->hlen)))
330 return;
331
332 if (ip->client->state != S_REBOOTING &&
333 ip->client->state != S_REQUESTING &&
334 ip->client->state != S_RENEWING &&
335 ip->client->state != S_REBINDING)
336 return;
337
338 note("DHCPACK from %s", piaddr(packet->client_addr));
339
340 lease = packet_to_lease(packet);
341 if (!lease) {
342 note("packet_to_lease failed.");
343 return;
344 }
345
346 ip->client->new = lease;
347
348 /* Stop resending DHCPREQUEST. */
350
351 /* Figure out the lease time. */
352 if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data)
353 ip->client->new->expiry = getULong(
354 ip->client->new->options[DHO_DHCP_LEASE_TIME].data);
355 else
356 ip->client->new->expiry = DHCP_DEFAULT_LEASE_TIME;
357 /* A number that looks negative here is really just very large,
358 because the lease expiry offset is unsigned. */
359 if (ip->client->new->expiry < 0)
360 ip->client->new->expiry = TIME_MAX;
361 /* XXX should be fixed by resetting the client state */
362 if (ip->client->new->expiry < 60)
363 ip->client->new->expiry = 60;
364
365 /* Take the server-provided renewal time if there is one;
366 otherwise figure it out according to the spec. */
367 if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len)
368 ip->client->new->renewal = getULong(
369 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data);
370 else
371 ip->client->new->renewal = ip->client->new->expiry / 2;
372
373 /* Same deal with the rebind time. */
374 if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len)
375 ip->client->new->rebind = getULong(
376 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data);
377 else
378 ip->client->new->rebind = ip->client->new->renewal +
379 ip->client->new->renewal / 2 + ip->client->new->renewal / 4;
380
381#ifdef __REACTOS__
382 ip->client->new->obtained = cur_time;
383#endif
384 ip->client->new->expiry += cur_time;
385 /* Lease lengths can never be negative. */
386 if (ip->client->new->expiry < cur_time)
387 ip->client->new->expiry = TIME_MAX;
388 ip->client->new->renewal += cur_time;
389 if (ip->client->new->renewal < cur_time)
390 ip->client->new->renewal = TIME_MAX;
391 ip->client->new->rebind += cur_time;
392 if (ip->client->new->rebind < cur_time)
393 ip->client->new->rebind = TIME_MAX;
394
395 bind_lease(ip);
396}
397
398void set_name_servers( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
399 CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
400 HKEY RegKey;
401
402 strcat(Buffer, Adapter->DhclientInfo.name);
404 return;
405
406
407 if( new_lease->options[DHO_DOMAIN_NAME_SERVERS].len ) {
408
409 struct iaddr nameserver;
410 char *nsbuf;
411 int i, addrs =
412 new_lease->options[DHO_DOMAIN_NAME_SERVERS].len / sizeof(ULONG);
413
414 nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) );
415
416 if( nsbuf) {
417 nsbuf[0] = 0;
418 for( i = 0; i < addrs; i++ ) {
419 nameserver.len = sizeof(ULONG);
420 memcpy( nameserver.iabuf,
421 new_lease->options[DHO_DOMAIN_NAME_SERVERS].data +
422 (i * sizeof(ULONG)), sizeof(ULONG) );
423 strcat( nsbuf, piaddr(nameserver) );
424 if( i != addrs-1 ) strcat( nsbuf, "," );
425 }
426
427 DH_DbgPrint(MID_TRACE,("Setting DhcpNameserver: %s\n", nsbuf));
428
429 RegSetValueExA( RegKey, "DhcpNameServer", 0, REG_SZ,
430 (LPBYTE)nsbuf, strlen(nsbuf) + 1 );
431 free( nsbuf );
432 }
433
434 } else {
435 RegDeleteValueW( RegKey, L"DhcpNameServer" );
436 }
437
438 RegCloseKey( RegKey );
439
440}
441
442void
444 struct client_lease *new_lease)
445{
446 CHAR Buffer1[MAX_PATH] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
447 CHAR Buffer2[MAX_PATH] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters";
448 HKEY RegKey1, RegKey2;
449
450 strcat(Buffer1, Adapter->DhclientInfo.name);
451
452 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer1, 0, KEY_WRITE, &RegKey1 ) != ERROR_SUCCESS)
453 {
454 return;
455 }
456
457 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer2, 0, KEY_WRITE, &RegKey2 ) != ERROR_SUCCESS)
458 {
459 RegCloseKey(RegKey1);
460 return;
461 }
462
463 if (new_lease->options[DHO_DOMAIN_NAME].len)
464 {
465 DH_DbgPrint(MID_TRACE, ("Setting DhcpDomain: %s\n", new_lease->options[DHO_DOMAIN_NAME].data));
466
467 RegSetValueExA(RegKey1,
468 "DhcpDomain",
469 0,
470 REG_SZ,
471 (LPBYTE)new_lease->options[DHO_DOMAIN_NAME].data,
472 new_lease->options[DHO_DOMAIN_NAME].len);
473
474 RegSetValueExA(RegKey2,
475 "DhcpDomain",
476 0,
477 REG_SZ,
478 (LPBYTE)new_lease->options[DHO_DOMAIN_NAME].data,
479 new_lease->options[DHO_DOMAIN_NAME].len);
480 }
481 else
482 {
483 RegDeleteValueW(RegKey1, L"DhcpDomain");
484 RegDeleteValueW(RegKey2, L"DhcpDomain");
485 }
486
487 RegCloseKey(RegKey1);
488 RegCloseKey(RegKey2);
489
490}
491
492void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) {
493 CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\";
494 struct iaddr netmask;
495 HKEY hkey;
496 int i;
497 DWORD dwEnableDHCP;
498
499 strcat(Buffer, Adapter->DhclientInfo.name);
501 hkey = NULL;
502
503
504 if( Adapter->NteContext )
505 {
506 DeleteIPAddress( Adapter->NteContext );
507 Adapter->NteContext = 0;
508 }
509
510 /* Set up our default router if we got one from the DHCP server */
511 if( new_lease->options[DHO_SUBNET_MASK].len ) {
513
514 memcpy( netmask.iabuf,
515 new_lease->options[DHO_SUBNET_MASK].data,
516 new_lease->options[DHO_SUBNET_MASK].len );
518 ( *((ULONG*)new_lease->address.iabuf),
519 *((ULONG*)netmask.iabuf),
520 Adapter->IfMib.dwIndex,
521 &Adapter->NteContext,
522 &Adapter->NteInstance );
523 if (hkey) {
524 RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)piaddr(new_lease->address), strlen(piaddr(new_lease->address))+1);
525 Buffer[0] = '\0';
526 for(i = 0; i < new_lease->options[DHO_SUBNET_MASK].len; i++)
527 {
528 sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_SUBNET_MASK].data[i]);
529 if (i + 1 < new_lease->options[DHO_SUBNET_MASK].len)
530 strcat(Buffer, ".");
531 }
532 RegSetValueExA(hkey, "DhcpSubnetMask", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
533 dwEnableDHCP = 1;
534 RegSetValueExA(hkey, "EnableDHCP", 0, REG_DWORD, (LPBYTE)&dwEnableDHCP, sizeof(DWORD));
535
536 RegSetValueExA(hkey, "LeaseObtainedTime", 0, REG_DWORD, (LPBYTE)&new_lease->obtained, sizeof(DWORD));
537 RegSetValueExA(hkey, "LeaseTerminatesTime", 0, REG_DWORD, (LPBYTE)&new_lease->expiry, sizeof(DWORD));
538 RegSetValueExA(hkey, "DhcpServer", 0, REG_SZ, (LPBYTE)piaddr(new_lease->serveraddress), strlen(piaddr(new_lease->serveraddress))+1);
539 }
540
541 if( !NT_SUCCESS(Status) )
542 warning("AddIPAddress: %lx\n", Status);
543 }
544
545 if( new_lease->options[DHO_ROUTERS].len ) {
547
548 Adapter->RouterMib.dwForwardDest = 0; /* Default route */
549 Adapter->RouterMib.dwForwardMask = 0;
550 Adapter->RouterMib.dwForwardMetric1 = 1;
551 Adapter->RouterMib.dwForwardIfIndex = Adapter->IfMib.dwIndex;
552
553 if( Adapter->RouterMib.dwForwardNextHop ) {
554 /* If we set a default route before, delete it before continuing */
555 DeleteIpForwardEntry( &Adapter->RouterMib );
556 }
557
558 Adapter->RouterMib.dwForwardNextHop =
559 *((ULONG*)new_lease->options[DHO_ROUTERS].data);
560
562
563 if( !NT_SUCCESS(Status) )
564 warning("CreateIpForwardEntry: %lx\n", Status);
565
566 if (hkey) {
567 Buffer[0] = '\0';
568 for(i = 0; i < new_lease->options[DHO_ROUTERS].len; i++)
569 {
570 sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_ROUTERS].data[i]);
571 if (i + 1 < new_lease->options[DHO_ROUTERS].len)
572 strcat(Buffer, ".");
573 }
574 RegSetValueExA(hkey, "DhcpDefaultGateway", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1);
575 }
576 }
577
578 if (hkey)
579 RegCloseKey(hkey);
580}
581
582
583void
585{
586 PDHCP_ADAPTER Adapter;
587 struct client_lease *new_lease = ip->client->new;
589
590 time(&cur_time);
591
592 /* Remember the medium. */
593 ip->client->new->medium = ip->client->medium;
594
595 /* Replace the old active lease with the new one. */
596 if (ip->client->active)
597 free_client_lease(ip->client->active);
598 ip->client->active = ip->client->new;
599 ip->client->new = NULL;
600
601 /* Set up a timeout to start the renewal process. */
602 /* Timeout of zero means no timeout (some implementations seem to use
603 * one day).
604 */
605 if( ip->client->active->renewal - cur_time )
606 add_timeout(ip->client->active->renewal, state_bound, ip);
607
608 note("bound to %s -- renewal in %ld seconds.",
609 piaddr(ip->client->active->address),
610 (long int)(ip->client->active->renewal - cur_time));
611
612 ip->client->state = S_BOUND;
613
614 Adapter = AdapterFindInfo( ip );
615
616 if( Adapter ) setup_adapter( Adapter, new_lease );
617 else {
618 warning("Could not find adapter for info %p\n", ip);
619 return;
620 }
621 set_name_servers( Adapter, new_lease );
622 set_domain( Adapter, new_lease );
623}
624
625/*
626 * state_bound is called when we've successfully bound to a particular
627 * lease, but the renewal time on that lease has expired. We are
628 * expected to unicast a DHCPREQUEST to the server that gave us our
629 * original lease.
630 */
631void
632state_bound(void *ipp)
633{
634 struct interface_info *ip = ipp;
635
637
638 /* T1 has expired. */
639 make_request(ip, ip->client->active);
640 ip->client->xid = ip->client->packet.xid;
641
642 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) {
643 memcpy(ip->client->destination.iabuf, ip->client->active->
645 ip->client->destination.len = 4;
646 } else
647 ip->client->destination = iaddr_broadcast;
648
649 time(&ip->client->first_sending);
650 ip->client->interval = ip->client->config->initial_interval;
651 ip->client->state = S_RENEWING;
652
653 /* Send the first packet immediately. */
655}
656
657void
659{
660 struct iaddrlist *ap;
661
662 if (packet->raw->op != BOOTREPLY)
663 return;
664
665 /* If there's a reject list, make sure this packet's sender isn't
666 on it. */
667 for (ap = packet->interface->client->config->reject_list;
668 ap; ap = ap->next) {
669 if (addr_eq(packet->client_addr, ap->addr)) {
670 note("BOOTREPLY from %s rejected.", piaddr(ap->addr));
671 return;
672 }
673 }
675}
676
677void
679{
680 struct iaddrlist *ap;
681 void (*handler)(struct packet *);
682 char *type;
683
684 switch (packet->packet_type) {
685 case DHCPOFFER:
687 type = "DHCPOFFER";
688 break;
689 case DHCPNAK:
691 type = "DHCPNACK";
692 break;
693 case DHCPACK:
695 type = "DHCPACK";
696 break;
697 default:
698 return;
699 }
700
701 /* If there's a reject list, make sure this packet's sender isn't
702 on it. */
703 for (ap = packet->interface->client->config->reject_list;
704 ap; ap = ap->next) {
705 if (addr_eq(packet->client_addr, ap->addr)) {
706 note("%s from %s rejected.", type, piaddr(ap->addr));
707 return;
708 }
709 }
710 (*handler)(packet);
711}
712
713void
715{
717 struct client_lease *lease, *lp;
718 int i;
719 int arp_timeout_needed = 0, stop_selecting;
721 "DHCPOFFER" : "BOOTREPLY";
723
724 time(&cur_time);
725
726 /* If we're not receptive to an offer right now, or if the offer
727 has an unrecognizable transaction id, then just drop it. */
728 if (ip->client->state != S_SELECTING ||
729 packet->interface->client->xid != packet->raw->xid ||
730 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
731 (memcmp(packet->interface->hw_address.haddr,
732 packet->raw->chaddr, packet->raw->hlen)))
733 return;
734
735 note("%s from %s", name, piaddr(packet->client_addr));
736
737
738 /* If this lease doesn't supply the minimum required parameters,
739 blow it off. */
740 for (i = 0; ip->client->config->required_options[i]; i++) {
741 if (!packet->options[ip->client->config->
742 required_options[i]].len) {
743 note("%s isn't satisfactory.", name);
744 return;
745 }
746 }
747
748 /* If we've already seen this lease, don't record it again. */
749 for (lease = ip->client->offered_leases;
750 lease; lease = lease->next) {
751 if (lease->address.len == sizeof(packet->raw->yiaddr) &&
752 !memcmp(lease->address.iabuf,
753 &packet->raw->yiaddr, lease->address.len)) {
754 debug("%s already seen.", name);
755 return;
756 }
757 }
758
759 lease = packet_to_lease(packet);
760 if (!lease) {
761 note("packet_to_lease failed.");
762 return;
763 }
764
765 /* If this lease was acquired through a BOOTREPLY, record that
766 fact. */
768 lease->is_bootp = 1;
769
770 /* Record the medium under which this lease was offered. */
771 lease->medium = ip->client->medium;
772
773 /* Send out an ARP Request for the offered IP address. */
774 if( !check_arp( ip, lease ) ) {
775 note("Arp check failed\n");
776 return;
777 }
778
779 /* Figure out when we're supposed to stop selecting. */
780 stop_selecting =
781 ip->client->first_sending + ip->client->config->select_interval;
782
783 /* If this is the lease we asked for, put it at the head of the
784 list, and don't mess with the arp request timeout. */
785 if (lease->address.len == ip->client->requested_address.len &&
786 !memcmp(lease->address.iabuf,
787 ip->client->requested_address.iabuf,
788 ip->client->requested_address.len)) {
789 lease->next = ip->client->offered_leases;
790 ip->client->offered_leases = lease;
791 } else {
792 /* If we already have an offer, and arping for this
793 offer would take us past the selection timeout,
794 then don't extend the timeout - just hope for the
795 best. */
796 if (ip->client->offered_leases &&
797 (cur_time + arp_timeout_needed) > stop_selecting)
798 arp_timeout_needed = 0;
799
800 /* Put the lease at the end of the list. */
801 lease->next = NULL;
802 if (!ip->client->offered_leases)
803 ip->client->offered_leases = lease;
804 else {
805 for (lp = ip->client->offered_leases; lp->next;
806 lp = lp->next)
807 ; /* nothing */
808 lp->next = lease;
809 }
810 }
811
812 /* If we're supposed to stop selecting before we've had time
813 to wait for the ARPREPLY, add some delay to wait for
814 the ARPREPLY. */
815 if (stop_selecting - cur_time < arp_timeout_needed)
816 stop_selecting = cur_time + arp_timeout_needed;
817
818 /* If the selecting interval has expired, go immediately to
819 state_selecting(). Otherwise, time out into
820 state_selecting at the select interval. */
821 if (stop_selecting <= 0)
823 else {
824 add_timeout(stop_selecting, state_selecting, ip);
826 }
827}
828
829/* Allocate a client_lease structure and initialize it from the parameters
830 in the specified packet. */
831
832struct client_lease *
834{
835 struct client_lease *lease;
836 int i;
837
838 lease = malloc(sizeof(struct client_lease));
839
840 if (!lease) {
841 warning("dhcpoffer: no memory to record lease.");
842 return (NULL);
843 }
844
845 memset(lease, 0, sizeof(*lease));
846
847 /* Copy the lease options. */
848 for (i = 0; i < 256; i++) {
849 if (packet->options[i].len) {
850 lease->options[i].data =
851 malloc(packet->options[i].len + 1);
852 if (!lease->options[i].data) {
853 warning("dhcpoffer: no memory for option %d", i);
854 free_client_lease(lease);
855 return (NULL);
856 } else {
857 memcpy(lease->options[i].data,
858 packet->options[i].data,
859 packet->options[i].len);
860 lease->options[i].len =
861 packet->options[i].len;
862 lease->options[i].data[lease->options[i].len] =
863 0;
864 }
865 if (!check_option(lease,i)) {
866 /* ignore a bogus lease offer */
867 warning("Invalid lease option - ignoring offer");
868 free_client_lease(lease);
869 return (NULL);
870 }
871 }
872 }
873
874 lease->address.len = sizeof(packet->raw->yiaddr);
875 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len);
876#ifdef __REACTOS__
877 lease->serveraddress.len = sizeof(packet->raw->siaddr);
878 memcpy(lease->serveraddress.iabuf, &packet->raw->siaddr, lease->address.len);
879#endif
880
881 /* If the server name was filled out, copy it. */
883 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) &&
884 packet->raw->sname[0]) {
885 lease->server_name = malloc(DHCP_SNAME_LEN + 1);
886 if (!lease->server_name) {
887 warning("dhcpoffer: no memory for server name.");
888 free_client_lease(lease);
889 return (NULL);
890 }
891 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN);
892 lease->server_name[DHCP_SNAME_LEN]='\0';
893 if (!res_hnok(lease->server_name) ) {
894 warning("Bogus server name %s", lease->server_name );
895 free_client_lease(lease);
896 return (NULL);
897 }
898
899 }
900
901 /* Ditto for the filename. */
903 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) &&
904 packet->raw->file[0]) {
905 /* Don't count on the NUL terminator. */
906 lease->filename = malloc(DHCP_FILE_LEN + 1);
907 if (!lease->filename) {
908 warning("dhcpoffer: no memory for filename.");
909 free_client_lease(lease);
910 return (NULL);
911 }
912 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN);
913 lease->filename[DHCP_FILE_LEN]='\0';
914 }
915 return lease;
916}
917
918void
920{
922
923 /* If we're not receptive to an offer right now, or if the offer
924 has an unrecognizable transaction id, then just drop it. */
925 if (packet->interface->client->xid != packet->raw->xid ||
926 (packet->interface->hw_address.hlen != packet->raw->hlen) ||
927 (memcmp(packet->interface->hw_address.haddr,
928 packet->raw->chaddr, packet->raw->hlen)))
929 return;
930
931 if (ip->client->state != S_REBOOTING &&
932 ip->client->state != S_REQUESTING &&
933 ip->client->state != S_RENEWING &&
934 ip->client->state != S_REBINDING)
935 return;
936
937 note("DHCPNAK from %s", piaddr(packet->client_addr));
938
939 if (!ip->client->active) {
940 note("DHCPNAK with no active lease.\n");
941 return;
942 }
943
944 free_client_lease(ip->client->active);
945 ip->client->active = NULL;
946
947 /* Stop sending DHCPREQUEST packets... */
949
950 ip->client->state = S_INIT;
951 state_init(ip);
952}
953
954/* Send out a DHCPDISCOVER packet, and set a timeout to send out another
955 one after the right interval has expired. If we don't get an offer by
956 the time we reach the panic interval, call the panic function. */
957
958void
960{
961 struct interface_info *ip = ipp;
962 int interval, increase = 1;
964
965 DH_DbgPrint(MID_TRACE,("Doing discover on interface %p\n",ip));
966
967 time(&cur_time);
968
969 /* Figure out how long it's been since we started transmitting. */
970 interval = cur_time - ip->client->first_sending;
971
972 /* If we're past the panic timeout, call the script and tell it
973 we haven't found anything for this interface yet. */
974 if (interval > ip->client->config->timeout) {
976 ip->client->first_sending = cur_time;
977 }
978
979 /* If we're selecting media, try the whole list before doing
980 the exponential backoff, but if we've already received an
981 offer, stop looping, because we obviously have it right. */
982 if (!ip->client->offered_leases &&
983 ip->client->config->media) {
984 int fail = 0;
985
986 if (ip->client->medium) {
987 ip->client->medium = ip->client->medium->next;
988 increase = 0;
989 }
990 if (!ip->client->medium) {
991 if (fail)
992 error("No valid media types for %s!", ip->name);
993 ip->client->medium = ip->client->config->media;
994 increase = 1;
995 }
996
997 note("Trying medium \"%s\" %d", ip->client->medium->string,
998 increase);
999 /* XXX Support other media types eventually */
1000 }
1001
1002 /*
1003 * If we're supposed to increase the interval, do so. If it's
1004 * currently zero (i.e., we haven't sent any packets yet), set
1005 * it to one; otherwise, add to it a random number between zero
1006 * and two times itself. On average, this means that it will
1007 * double with every transmission.
1008 */
1009 if (increase) {
1010 if (!ip->client->interval)
1011 ip->client->interval =
1012 ip->client->config->initial_interval;
1013 else {
1014 ip->client->interval += (rand() >> 2) %
1015 (2 * ip->client->interval);
1016 }
1017
1018 /* Don't backoff past cutoff. */
1019 if (ip->client->interval >
1020 ip->client->config->backoff_cutoff)
1021 ip->client->interval =
1022 ((ip->client->config->backoff_cutoff / 2)
1023 + ((rand() >> 2) %
1024 ip->client->config->backoff_cutoff));
1025 } else if (!ip->client->interval)
1026 ip->client->interval =
1027 ip->client->config->initial_interval;
1028
1029 /* If the backoff would take us to the panic timeout, just use that
1030 as the interval. */
1031 if (cur_time + ip->client->interval >
1032 ip->client->first_sending + ip->client->config->timeout)
1033 ip->client->interval =
1034 (ip->client->first_sending +
1035 ip->client->config->timeout) - cur_time + 1;
1036
1037 /* Record the number of seconds since we started sending. */
1038 if (interval < 65536)
1039 ip->client->packet.secs = htons(interval);
1040 else
1041 ip->client->packet.secs = htons(65535);
1042 ip->client->secs = ip->client->packet.secs;
1043
1044 note("DHCPDISCOVER on %s to %s port %d interval %ld",
1045 ip->name, inet_ntoa(sockaddr_broadcast.sin_addr),
1046 ntohs(sockaddr_broadcast.sin_port), (long int)ip->client->interval);
1047
1048 /* Send out a packet. */
1049 (void)send_packet(ip, &ip->client->packet, ip->client->packet_length,
1051
1052 DH_DbgPrint(MID_TRACE,("discover timeout: now %x -> then %x\n",
1053 cur_time, cur_time + ip->client->interval));
1054
1055 add_timeout(cur_time + ip->client->interval, send_discover, ip);
1056}
1057
1058/*
1059 * state_panic gets called if we haven't received any offers in a preset
1060 * amount of time. When this happens, we try to use existing leases
1061 * that haven't yet expired, and failing that, we call the client script
1062 * and hope it can do something.
1063 */
1064void
1065state_panic(void *ipp)
1066{
1067 struct interface_info *ip = ipp;
1068 uint16_t address_low;
1069 int i;
1070 IPAddr IpAddress;
1071 ULONG Buffer[20];
1073 DWORD ret;
1074 PDHCP_ADAPTER Adapter = AdapterFindInfo(ip);
1075
1076 note("No DHCPOFFERS received.");
1077
1078 if (!Adapter->NteContext)
1079 {
1080 /* Generate an automatic private address */
1081 DbgPrint("DHCPCSVC: Failed to receive a response from a DHCP server. An automatic private address will be assigned.\n");
1082
1083 /* FIXME: The address generation code sucks */
1084 srand(0);
1085
1086 for (;;)
1087 {
1088 address_low = rand();
1089 for (i = 0; i < ip->hw_address.hlen; i++)
1090 address_low += ip->hw_address.haddr[i];
1091
1092 IpAddress = htonl(0xA9FE0000 | address_low); // 169.254.X.X
1093
1094 /* Send an ARP request to check if the IP address is already in use */
1095 BufferSize = sizeof(Buffer);
1096 ret = SendARP(IpAddress,
1097 IpAddress,
1098 Buffer,
1099 &BufferSize);
1100 DH_DbgPrint(MID_TRACE,("DHCPCSVC: SendARP returned %lu\n", ret));
1101 if (ret != 0)
1102 {
1103 /* The IP address is not in use */
1104 DH_DbgPrint(MID_TRACE,("DHCPCSVC: Using automatic private address\n"));
1105 AddIPAddress(IpAddress,
1106 htonl(0xFFFF0000), // 255.255.0.0
1107 Adapter->IfMib.dwIndex,
1108 &Adapter->NteContext,
1109 &Adapter->NteInstance);
1110 return;
1111 }
1112 }
1113 }
1114}
1115
1116void
1118{
1119 struct interface_info *ip = ipp;
1120 struct sockaddr_in destination;
1121 struct in_addr from;
1122 int interval;
1124
1125 time(&cur_time);
1126
1127 /* Figure out how long it's been since we started transmitting. */
1128 interval = cur_time - ip->client->first_sending;
1129
1130 /* If we're in the INIT-REBOOT or REQUESTING state and we're
1131 past the reboot timeout, go to INIT and see if we can
1132 DISCOVER an address... */
1133 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it
1134 means either that we're on a network with no DHCP server,
1135 or that our server is down. In the latter case, assuming
1136 that there is a backup DHCP server, DHCPDISCOVER will get
1137 us a new address, but we could also have successfully
1138 reused our old address. In the former case, we're hosed
1139 anyway. This is not a win-prone situation. */
1140 if ((ip->client->state == S_REBOOTING ||
1141 ip->client->state == S_REQUESTING) &&
1142 interval > ip->client->config->reboot_timeout) {
1143 ip->client->state = S_INIT;
1145 state_init(ip);
1146 return;
1147 }
1148
1149 /* If we're in the reboot state, make sure the media is set up
1150 correctly. */
1151 if (ip->client->state == S_REBOOTING &&
1152 !ip->client->medium &&
1153 ip->client->active->medium ) {
1154 /* If the medium we chose won't fly, go to INIT state. */
1155 /* XXX Nothing for now */
1156
1157 /* Record the medium. */
1158 ip->client->medium = ip->client->active->medium;
1159 }
1160
1161 /* If the lease has expired, relinquish the address and go back
1162 to the INIT state. */
1163 if (ip->client->state != S_REQUESTING &&
1164 cur_time > ip->client->active->expiry) {
1165 PDHCP_ADAPTER Adapter = AdapterFindInfo( ip );
1166 /* Run the client script with the new parameters. */
1167 /* No script actions necessary in the expiry case */
1168 /* Now do a preinit on the interface so that we can
1169 discover a new address. */
1170
1171 if( Adapter )
1172 {
1173 DeleteIPAddress( Adapter->NteContext );
1174 Adapter->NteContext = 0;
1175 }
1176
1177 ip->client->state = S_INIT;
1178 state_init(ip);
1179 return;
1180 }
1181
1182 /* Do the exponential backoff... */
1183 if (!ip->client->interval)
1184 ip->client->interval = ip->client->config->initial_interval;
1185 else
1186 ip->client->interval += ((rand() >> 2) %
1187 (2 * ip->client->interval));
1188
1189 /* Don't backoff past cutoff. */
1190 if (ip->client->interval >
1191 ip->client->config->backoff_cutoff)
1192 ip->client->interval =
1193 ((ip->client->config->backoff_cutoff / 2) +
1194 ((rand() >> 2) % ip->client->interval));
1195
1196 /* If the backoff would take us to the expiry time, just set the
1197 timeout to the expiry time. */
1198 if (ip->client->state != S_REQUESTING &&
1199 cur_time + ip->client->interval >
1200 ip->client->active->expiry)
1201 ip->client->interval =
1202 ip->client->active->expiry - cur_time + 1;
1203
1204 /* If the lease T2 time has elapsed, or if we're not yet bound,
1205 broadcast the DHCPREQUEST rather than unicasting. */
1206 memset(&destination, 0, sizeof(destination));
1207 if (ip->client->state == S_REQUESTING ||
1208 ip->client->state == S_REBOOTING ||
1209 cur_time > ip->client->active->rebind)
1210 destination.sin_addr.s_addr = INADDR_BROADCAST;
1211 else
1212 memcpy(&destination.sin_addr.s_addr,
1213 ip->client->destination.iabuf,
1214 sizeof(destination.sin_addr.s_addr));
1215 destination.sin_port = htons(REMOTE_PORT);
1216 destination.sin_family = AF_INET;
1217// destination.sin_len = sizeof(destination);
1218
1219 if (ip->client->state != S_REQUESTING)
1220 memcpy(&from, ip->client->active->address.iabuf,
1221 sizeof(from));
1222 else
1223 from.s_addr = INADDR_ANY;
1224
1225 /* Record the number of seconds since we started sending. */
1226 if (ip->client->state == S_REQUESTING)
1227 ip->client->packet.secs = ip->client->secs;
1228 else {
1229 if (interval < 65536)
1230 ip->client->packet.secs = htons(interval);
1231 else
1232 ip->client->packet.secs = htons(65535);
1233 }
1234
1235 note("DHCPREQUEST on %s to %s port %d", ip->name,
1236 inet_ntoa(destination.sin_addr), ntohs(destination.sin_port));
1237
1238 /* Send out a packet. */
1239 (void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
1240 from, &destination, NULL);
1241
1242 add_timeout(cur_time + ip->client->interval, send_request, ip);
1243}
1244
1245void
1247{
1248 struct interface_info *ip = ipp;
1249
1250 note("DHCPDECLINE on %s to %s port %d", ip->name,
1251 inet_ntoa(sockaddr_broadcast.sin_addr),
1252 ntohs(sockaddr_broadcast.sin_port));
1253
1254 /* Send out a packet. */
1255 (void) send_packet(ip, &ip->client->packet, ip->client->packet_length,
1257}
1258
1259void
1261{
1262 unsigned char discover = DHCPDISCOVER;
1263 struct tree_cache *options[256];
1264 struct tree_cache option_elements[256];
1265 int i;
1267
1268 memset(option_elements, 0, sizeof(option_elements));
1269 memset(options, 0, sizeof(options));
1270 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1271
1272 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */
1274 options[i] = &option_elements[i];
1275 options[i]->value = &discover;
1276 options[i]->len = sizeof(discover);
1277 options[i]->buf_size = sizeof(discover);
1278 options[i]->timeout = 0xFFFFFFFF;
1279
1280 /* Request the options we want */
1282 options[i] = &option_elements[i];
1283 options[i]->value = ip->client->config->requested_options;
1284 options[i]->len = ip->client->config->requested_option_count;
1285 options[i]->buf_size =
1286 ip->client->config->requested_option_count;
1287 options[i]->timeout = 0xFFFFFFFF;
1288
1289 /* If we had an address, try to get it again. */
1290 if (lease) {
1291 ip->client->requested_address = lease->address;
1293 options[i] = &option_elements[i];
1294 options[i]->value = lease->address.iabuf;
1295 options[i]->len = lease->address.len;
1296 options[i]->buf_size = lease->address.len;
1297 options[i]->timeout = 0xFFFFFFFF;
1298 } else
1299 ip->client->requested_address.len = 0;
1300
1301 /* Send any options requested in the config file. */
1302 for (i = 0; i < 256; i++)
1303 if (!options[i] &&
1304 ip->client->config->send_options[i].data) {
1305 options[i] = &option_elements[i];
1306 options[i]->value =
1307 ip->client->config->send_options[i].data;
1308 options[i]->len =
1309 ip->client->config->send_options[i].len;
1310 options[i]->buf_size =
1311 ip->client->config->send_options[i].len;
1312 options[i]->timeout = 0xFFFFFFFF;
1313 }
1314
1315 /* Set up the option buffer... */
1316 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1317 options);
1318 if (ip->client->packet_length < BOOTP_MIN_LEN)
1319 ip->client->packet_length = BOOTP_MIN_LEN;
1320
1321 ip->client->packet.op = BOOTREQUEST;
1322 ip->client->packet.htype = ip->hw_address.htype;
1323 ip->client->packet.hlen = ip->hw_address.hlen;
1324 ip->client->packet.hops = 0;
1325 ip->client->packet.xid = RtlRandom(&foo);
1326 ip->client->packet.secs = 0; /* filled in by send_discover. */
1327 ip->client->packet.flags = 0;
1328
1329 memset(&(ip->client->packet.ciaddr),
1330 0, sizeof(ip->client->packet.ciaddr));
1331 memset(&(ip->client->packet.yiaddr),
1332 0, sizeof(ip->client->packet.yiaddr));
1333 memset(&(ip->client->packet.siaddr),
1334 0, sizeof(ip->client->packet.siaddr));
1335 memset(&(ip->client->packet.giaddr),
1336 0, sizeof(ip->client->packet.giaddr));
1337 memcpy(ip->client->packet.chaddr,
1338 ip->hw_address.haddr, ip->hw_address.hlen);
1339}
1340
1341
1342void
1344{
1345 unsigned char request = DHCPREQUEST;
1346 struct tree_cache *options[256];
1347 struct tree_cache option_elements[256];
1348 int i;
1349
1350 memset(options, 0, sizeof(options));
1351 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1352
1353 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */
1355 options[i] = &option_elements[i];
1356 options[i]->value = &request;
1357 options[i]->len = sizeof(request);
1358 options[i]->buf_size = sizeof(request);
1359 options[i]->timeout = 0xFFFFFFFF;
1360
1361 /* Request the options we want */
1363 options[i] = &option_elements[i];
1364 options[i]->value = ip->client->config->requested_options;
1365 options[i]->len = ip->client->config->requested_option_count;
1366 options[i]->buf_size =
1367 ip->client->config->requested_option_count;
1368 options[i]->timeout = 0xFFFFFFFF;
1369
1370 /* If we are requesting an address that hasn't yet been assigned
1371 to us, use the DHCP Requested Address option. */
1372 if (ip->client->state == S_REQUESTING) {
1373 /* Send back the server identifier... */
1375 options[i] = &option_elements[i];
1376 options[i]->value = lease->options[i].data;
1377 options[i]->len = lease->options[i].len;
1378 options[i]->buf_size = lease->options[i].len;
1379 options[i]->timeout = 0xFFFFFFFF;
1380 }
1381 if (ip->client->state == S_REQUESTING ||
1382 ip->client->state == S_REBOOTING) {
1383 ip->client->requested_address = lease->address;
1385 options[i] = &option_elements[i];
1386 options[i]->value = lease->address.iabuf;
1387 options[i]->len = lease->address.len;
1388 options[i]->buf_size = lease->address.len;
1389 options[i]->timeout = 0xFFFFFFFF;
1390 } else
1391 ip->client->requested_address.len = 0;
1392
1393 /* Send any options requested in the config file. */
1394 for (i = 0; i < 256; i++)
1395 if (!options[i] &&
1396 ip->client->config->send_options[i].data) {
1397 options[i] = &option_elements[i];
1398 options[i]->value =
1399 ip->client->config->send_options[i].data;
1400 options[i]->len =
1401 ip->client->config->send_options[i].len;
1402 options[i]->buf_size =
1403 ip->client->config->send_options[i].len;
1404 options[i]->timeout = 0xFFFFFFFF;
1405 }
1406
1407 /* Set up the option buffer... */
1408 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1409 options);
1410 if (ip->client->packet_length < BOOTP_MIN_LEN)
1411 ip->client->packet_length = BOOTP_MIN_LEN;
1412
1413 ip->client->packet.op = BOOTREQUEST;
1414 ip->client->packet.htype = ip->hw_address.htype;
1415 ip->client->packet.hlen = ip->hw_address.hlen;
1416 ip->client->packet.hops = 0;
1417 ip->client->packet.xid = ip->client->xid;
1418 ip->client->packet.secs = 0; /* Filled in by send_request. */
1419
1420 /* If we own the address we're requesting, put it in ciaddr;
1421 otherwise set ciaddr to zero. */
1422 if (ip->client->state == S_BOUND ||
1423 ip->client->state == S_RENEWING ||
1424 ip->client->state == S_REBINDING) {
1425 memcpy(&ip->client->packet.ciaddr,
1426 lease->address.iabuf, lease->address.len);
1427 ip->client->packet.flags = 0;
1428 } else {
1429 memset(&ip->client->packet.ciaddr, 0,
1430 sizeof(ip->client->packet.ciaddr));
1431 ip->client->packet.flags = 0;
1432 }
1433
1434 memset(&ip->client->packet.yiaddr, 0,
1435 sizeof(ip->client->packet.yiaddr));
1436 memset(&ip->client->packet.siaddr, 0,
1437 sizeof(ip->client->packet.siaddr));
1438 memset(&ip->client->packet.giaddr, 0,
1439 sizeof(ip->client->packet.giaddr));
1440 memcpy(ip->client->packet.chaddr,
1441 ip->hw_address.haddr, ip->hw_address.hlen);
1442}
1443
1444void
1446{
1447 struct tree_cache *options[256], message_type_tree;
1448 struct tree_cache requested_address_tree;
1449 struct tree_cache server_id_tree, client_id_tree;
1450 unsigned char decline = DHCPDECLINE;
1451 int i;
1452
1453 memset(options, 0, sizeof(options));
1454 memset(&ip->client->packet, 0, sizeof(ip->client->packet));
1455
1456 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */
1458 options[i] = &message_type_tree;
1459 options[i]->value = &decline;
1460 options[i]->len = sizeof(decline);
1461 options[i]->buf_size = sizeof(decline);
1462 options[i]->timeout = 0xFFFFFFFF;
1463
1464 /* Send back the server identifier... */
1466 options[i] = &server_id_tree;
1467 options[i]->value = lease->options[i].data;
1468 options[i]->len = lease->options[i].len;
1469 options[i]->buf_size = lease->options[i].len;
1470 options[i]->timeout = 0xFFFFFFFF;
1471
1472 /* Send back the address we're declining. */
1474 options[i] = &requested_address_tree;
1475 options[i]->value = lease->address.iabuf;
1476 options[i]->len = lease->address.len;
1477 options[i]->buf_size = lease->address.len;
1478 options[i]->timeout = 0xFFFFFFFF;
1479
1480 /* Send the uid if the user supplied one. */
1482 if (ip->client->config->send_options[i].len) {
1483 options[i] = &client_id_tree;
1484 options[i]->value = ip->client->config->send_options[i].data;
1485 options[i]->len = ip->client->config->send_options[i].len;
1486 options[i]->buf_size = ip->client->config->send_options[i].len;
1487 options[i]->timeout = 0xFFFFFFFF;
1488 }
1489
1490
1491 /* Set up the option buffer... */
1492 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0,
1493 options);
1494 if (ip->client->packet_length < BOOTP_MIN_LEN)
1495 ip->client->packet_length = BOOTP_MIN_LEN;
1496
1497 ip->client->packet.op = BOOTREQUEST;
1498 ip->client->packet.htype = ip->hw_address.htype;
1499 ip->client->packet.hlen = ip->hw_address.hlen;
1500 ip->client->packet.hops = 0;
1501 ip->client->packet.xid = ip->client->xid;
1502 ip->client->packet.secs = 0; /* Filled in by send_request. */
1503 ip->client->packet.flags = 0;
1504
1505 /* ciaddr must always be zero. */
1506 memset(&ip->client->packet.ciaddr, 0,
1507 sizeof(ip->client->packet.ciaddr));
1508 memset(&ip->client->packet.yiaddr, 0,
1509 sizeof(ip->client->packet.yiaddr));
1510 memset(&ip->client->packet.siaddr, 0,
1511 sizeof(ip->client->packet.siaddr));
1512 memset(&ip->client->packet.giaddr, 0,
1513 sizeof(ip->client->packet.giaddr));
1514 memcpy(ip->client->packet.chaddr,
1515 ip->hw_address.haddr, ip->hw_address.hlen);
1516}
1517
1518void
1520{
1521 int i;
1522
1523 if (lease->server_name)
1524 free(lease->server_name);
1525 if (lease->filename)
1526 free(lease->filename);
1527 for (i = 0; i < 256; i++) {
1528 if (lease->options[i].len)
1529 free(lease->options[i].data);
1530 }
1531 free(lease);
1532}
1533
1535
1536void
1538{
1539 struct client_lease *lp;
1540
1541 if (!leaseFile) {
1543 if (!leaseFile)
1544 error("can't create %s", path_dhclient_db);
1545 } else {
1548 }
1549
1550 for (lp = ifi->client->leases; lp; lp = lp->next)
1551 write_client_lease(ifi, lp, 1);
1552 if (ifi->client->active)
1553 write_client_lease(ifi, ifi->client->active, 1);
1554
1556}
1557
1558void
1560 int rewrite)
1561{
1562 static int leases_written;
1563 struct tm *t;
1564 int i;
1565
1566 if (!rewrite) {
1567 if (leases_written++ > 20) {
1569 leases_written = 0;
1570 }
1571 }
1572
1573 /* If the lease came from the config file, we don't need to stash
1574 a copy in the lease database. */
1575 if (lease->is_static)
1576 return;
1577
1578 if (!leaseFile) { /* XXX */
1580 if (!leaseFile) {
1581 error("can't create %s", path_dhclient_db);
1582 return;
1583 }
1584 }
1585
1586 fprintf(leaseFile, "lease {\n");
1587 if (lease->is_bootp)
1588 fprintf(leaseFile, " bootp;\n");
1589 fprintf(leaseFile, " interface \"%s\";\n", ip->name);
1590 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address));
1591 if (lease->filename)
1592 fprintf(leaseFile, " filename \"%s\";\n", lease->filename);
1593 if (lease->server_name)
1594 fprintf(leaseFile, " server-name \"%s\";\n",
1595 lease->server_name);
1596 if (lease->medium)
1597 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string);
1598 for (i = 0; i < 256; i++)
1599 if (lease->options[i].len)
1600 fprintf(leaseFile, " option %s %s;\n",
1602 pretty_print_option(i, lease->options[i].data,
1603 lease->options[i].len, 1, 1));
1604
1605 t = gmtime(&lease->renewal);
1606 if (t)
1607 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n",
1608 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1609 t->tm_hour, t->tm_min, t->tm_sec);
1610 t = gmtime(&lease->rebind);
1611 if (t)
1612 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n",
1613 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1614 t->tm_hour, t->tm_min, t->tm_sec);
1615 t = gmtime(&lease->expiry);
1616 if (t)
1617 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n",
1618 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday,
1619 t->tm_hour, t->tm_min, t->tm_sec);
1620 fprintf(leaseFile, "}\n");
1622}
1623
1624void
1625priv_script_init(struct interface_info *ip, char *reason, char *medium)
1626{
1627 if (ip) {
1628 // XXX Do we need to do anything?
1629 }
1630}
1631
1632void
1634{
1635 u_int8_t dbuf[1500];
1636 int i, len = 0;
1637
1638#if 0
1639 script_set_env(ip->client, prefix, "ip_address",
1640 piaddr(lease->address));
1641#endif
1642
1643 if (lease->options[DHO_SUBNET_MASK].len &&
1644 (lease->options[DHO_SUBNET_MASK].len <
1645 sizeof(lease->address.iabuf))) {
1646 struct iaddr netmask, subnet, broadcast;
1647
1648 memcpy(netmask.iabuf, lease->options[DHO_SUBNET_MASK].data,
1649 lease->options[DHO_SUBNET_MASK].len);
1650 netmask.len = lease->options[DHO_SUBNET_MASK].len;
1651
1652 subnet = subnet_number(lease->address, netmask);
1653 if (subnet.len) {
1654#if 0
1655 script_set_env(ip->client, prefix, "network_number",
1656 piaddr(subnet));
1657#endif
1658 if (!lease->options[DHO_BROADCAST_ADDRESS].len) {
1659 broadcast = broadcast_addr(subnet, netmask);
1660 if (broadcast.len)
1661#if 0
1662 script_set_env(ip->client, prefix,
1663 "broadcast_address",
1664 piaddr(broadcast));
1665#else
1666 ;
1667#endif
1668 }
1669 }
1670 }
1671
1672#if 0
1673 if (lease->filename)
1674 script_set_env(ip->client, prefix, "filename", lease->filename);
1675 if (lease->server_name)
1676 script_set_env(ip->client, prefix, "server_name",
1677 lease->server_name);
1678#endif
1679
1680 for (i = 0; i < 256; i++) {
1681 u_int8_t *dp = NULL;
1682
1683 if (ip->client->config->defaults[i].len) {
1684 if (lease->options[i].len) {
1685 switch (
1686 ip->client->config->default_actions[i]) {
1687 case ACTION_DEFAULT:
1688 dp = lease->options[i].data;
1689 len = lease->options[i].len;
1690 break;
1691 case ACTION_SUPERSEDE:
1692supersede:
1693 dp = ip->client->
1694 config->defaults[i].data;
1695 len = ip->client->
1696 config->defaults[i].len;
1697 break;
1698 case ACTION_PREPEND:
1699 len = ip->client->
1700 config->defaults[i].len +
1701 lease->options[i].len;
1702 if (len >= sizeof(dbuf)) {
1703 warning("no space to %s %s",
1704 "prepend option",
1706 goto supersede;
1707 }
1708 dp = dbuf;
1709 memcpy(dp,
1710 ip->client->
1711 config->defaults[i].data,
1712 ip->client->
1713 config->defaults[i].len);
1714 memcpy(dp + ip->client->
1715 config->defaults[i].len,
1716 lease->options[i].data,
1717 lease->options[i].len);
1718 dp[len] = '\0';
1719 break;
1720 case ACTION_APPEND:
1721 len = ip->client->
1722 config->defaults[i].len +
1723 lease->options[i].len + 1;
1724 if (len > sizeof(dbuf)) {
1725 warning("no space to %s %s",
1726 "append option",
1728 goto supersede;
1729 }
1730 dp = dbuf;
1731 memcpy(dp,
1732 lease->options[i].data,
1733 lease->options[i].len);
1734 memcpy(dp + lease->options[i].len,
1735 ip->client->
1736 config->defaults[i].data,
1737 ip->client->
1738 config->defaults[i].len);
1739 dp[len-1] = '\0';
1740 }
1741 } else {
1742 dp = ip->client->
1743 config->defaults[i].data;
1744 len = ip->client->
1745 config->defaults[i].len;
1746 }
1747 } else if (lease->options[i].len) {
1748 len = lease->options[i].len;
1749 dp = lease->options[i].data;
1750 } else {
1751 len = 0;
1752 }
1753#if 0
1754 if (len) {
1755 char name[256];
1756
1757 if (dhcp_option_ev_name(name, sizeof(name),
1758 &dhcp_options[i]))
1759 script_set_env(ip->client, prefix, name,
1760 pretty_print_option(i, dp, len, 0, 0));
1761 }
1762#endif
1763 }
1764#if 0
1765 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry);
1766 script_set_env(ip->client, prefix, "expiry", tbuf);
1767#endif
1768}
1769
1770int
1771dhcp_option_ev_name(char *buf, size_t buflen, struct dhcp_option *option)
1772{
1773 int i;
1774
1775 for (i = 0; option->name[i]; i++) {
1776 if (i + 1 == buflen)
1777 return 0;
1778 if (option->name[i] == '-')
1779 buf[i] = '_';
1780 else
1781 buf[i] = option->name[i];
1782 }
1783
1784 buf[i] = 0;
1785 return 1;
1786}
1787
1788#if 0
1789void
1790go_daemon(void)
1791{
1792 static int state = 0;
1793
1794 if (no_daemon || state)
1795 return;
1796
1797 state = 1;
1798
1799 /* Stop logging to stderr... */
1800 log_perror = 0;
1801
1802 if (daemon(1, 0) == -1)
1803 error("daemon");
1804
1805 /* we are chrooted, daemon(3) fails to open /dev/null */
1806 if (nullfd != -1) {
1807 dup2(nullfd, STDIN_FILENO);
1808 dup2(nullfd, STDOUT_FILENO);
1809 dup2(nullfd, STDERR_FILENO);
1810 close(nullfd);
1811 nullfd = -1;
1812 }
1813}
1814#endif
1815
1816int
1818{
1819 char *opbuf;
1820 char *sbuf;
1821
1822 /* we use this, since this is what gets passed to dhclient-script */
1823
1824 opbuf = pretty_print_option(option, l->options[option].data,
1825 l->options[option].len, 0, 0);
1826
1827 sbuf = option_as_string(option, l->options[option].data,
1828 l->options[option].len);
1829
1830 switch (option) {
1831 case DHO_SUBNET_MASK:
1832 case DHO_TIME_SERVERS:
1833 case DHO_NAME_SERVERS:
1834 case DHO_ROUTERS:
1836 case DHO_LOG_SERVERS:
1837 case DHO_COOKIE_SERVERS:
1838 case DHO_LPR_SERVERS:
1841 case DHO_SWAP_SERVER:
1843 case DHO_NIS_SERVERS:
1844 case DHO_NTP_SERVERS:
1847 case DHO_FONT_SERVERS:
1849 if (!ipv4addrs(opbuf)) {
1850 warning("Invalid IP address in option(%d): %s", option, opbuf);
1851 return (0);
1852 }
1853 return (1) ;
1854 case DHO_HOST_NAME:
1855 case DHO_DOMAIN_NAME:
1856 case DHO_NIS_DOMAIN:
1857 if (!res_hnok(sbuf))
1858 warning("Bogus Host Name option %d: %s (%s)", option,
1859 sbuf, opbuf);
1860 return (1);
1861 case DHO_PAD:
1862 case DHO_TIME_OFFSET:
1863 case DHO_BOOT_SIZE:
1864 case DHO_MERIT_DUMP:
1865 case DHO_ROOT_PATH:
1867 case DHO_IP_FORWARDING:
1869 case DHO_POLICY_FILTER:
1871 case DHO_DEFAULT_IP_TTL:
1874 case DHO_INTERFACE_MTU:
1877 case DHO_MASK_SUPPLIER:
1880 case DHO_STATIC_ROUTES:
1889 case DHO_NETBIOS_SCOPE:
1896 case DHO_DHCP_MESSAGE:
1903 case DHO_END:
1904 return (1);
1905 default:
1906 warning("unknown dhcp option value 0x%x", option);
1907 return (unknown_ok);
1908 }
1909}
1910
1911int
1912res_hnok(const char *dn)
1913{
1914 int pch = PERIOD, ch = *dn++;
1915
1916 while (ch != '\0') {
1917 int nch = *dn++;
1918
1919 if (periodchar(ch)) {
1920 ;
1921 } else if (periodchar(pch)) {
1922 if (!borderchar(ch))
1923 return (0);
1924 } else if (periodchar(nch) || nch == '\0') {
1925 if (!borderchar(ch))
1926 return (0);
1927 } else {
1928 if (!middlechar(ch))
1929 return (0);
1930 }
1931 pch = ch, ch = nch;
1932 }
1933 return (1);
1934}
1935
1936/* Does buf consist only of dotted decimal ipv4 addrs?
1937 * return how many if so,
1938 * otherwise, return 0
1939 */
1940int
1942{
1943 char *tmp;
1944 struct in_addr jnk;
1945 int i = 0;
1946
1947 note("Input: %s", buf);
1948
1949 do {
1950 tmp = strtok(buf, " ");
1951 note("got %s", tmp);
1952 if( tmp && inet_aton(tmp, &jnk) ) i++;
1953 buf = NULL;
1954 } while( tmp );
1955
1956 return (i);
1957}
1958
1959
1960char *
1961option_as_string(unsigned int code, unsigned char *data, int len)
1962{
1963 static char optbuf[32768]; /* XXX */
1964 char *op = optbuf;
1965 int opleft = sizeof(optbuf);
1966 unsigned char *dp = data;
1967
1968 if (code > 255)
1969 error("option_as_string: bad code %d", code);
1970
1971 for (; dp < data + len; dp++) {
1972 if (!isascii(*dp) || !isprint(*dp)) {
1973 if (dp + 1 != data + len || *dp != 0) {
1974 _snprintf(op, opleft, "\\%03o", *dp);
1975 op += 4;
1976 opleft -= 4;
1977 }
1978 } else if (*dp == '"' || *dp == '\'' || *dp == '$' ||
1979 *dp == '`' || *dp == '\\') {
1980 *op++ = '\\';
1981 *op++ = *dp;
1982 opleft -= 2;
1983 } else {
1984 *op++ = *dp;
1985 opleft--;
1986 }
1987 }
1988 if (opleft < 1)
1989 goto toobig;
1990 *op = 0;
1991 return optbuf;
1992toobig:
1993 warning("dhcp option too large");
1994 return "<error>";
1995}
1996
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
#define isprint(c)
Definition: acclib.h:73
char * strtok(char *String, const char *Delimiters)
Definition: utclib.c:338
unsigned short int uint16_t
Definition: acefiex.h:54
#define close
Definition: acwin.h:98
CHAR FAR *WSAAPI inet_ntoa(IN IN_ADDR in)
Definition: addrconv.c:160
#define inet_aton(ap, inp)
Definition: adns_win32.h:161
static int state
Definition: maze.c:121
LONG NTSTATUS
Definition: precomp.h:26
void AdapterInit()
Definition: adapter.c:192
PDHCP_ADAPTER AdapterFindInfo(struct interface_info *ip)
Definition: adapter.c:526
VOID ApiInit()
Definition: api.c:18
void cancel_timeout(void(*where)(void *), void *what)
Definition: dispatch.c:316
void add_timeout(time_t when, void(*where)(void *), void *what)
Definition: dispatch.c:253
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *)
Definition: dispatch.c:59
char * pretty_print_option(unsigned int code, unsigned char *data, int len, int emit_commas, int emit_quotes)
Definition: options.c:396
int cons_options(struct packet *inpacket, struct dhcp_packet *outpacket, int mms, struct tree_cache **options)
Definition: options.c:199
void do_packet(struct interface_info *interface, struct dhcp_packet *packet, int len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
Definition: options.c:635
int note(char *format,...)
Definition: util.c:12
int addr_eq(struct iaddr a, struct iaddr b)
Definition: util.c:100
struct iaddr broadcast_addr(struct iaddr addr, struct iaddr mask)
Definition: util.c:167
char * piaddr(struct iaddr addr)
Definition: util.c:6
u_int32_t getULong(unsigned char *data)
Definition: util.c:96
struct iaddr subnet_number(struct iaddr addr, struct iaddr mask)
Definition: util.c:172
#define MID_TRACE
Definition: debug.h:15
#define DH_DbgPrint(_t_, _x_)
Definition: debug.h:49
#define DHO_DHCP_MESSAGE
Definition: dhcp.h:152
#define DHO_MASK_SUPPLIER
Definition: dhcp.h:126
#define DHCPREQUEST
Definition: dhcp.h:164
#define DHO_TCP_KEEPALIVE_GARBAGE
Definition: dhcp.h:135
#define DHO_DHCP_MAX_MESSAGE_SIZE
Definition: dhcp.h:153
#define DHO_ROUTER_DISCOVERY
Definition: dhcp.h:127
#define DHO_NAME_SERVERS
Definition: dhcp.h:101
#define DHO_VENDOR_ENCAPSULATED_OPTIONS
Definition: dhcp.h:139
#define DHO_PERFORM_MASK_DISCOVERY
Definition: dhcp.h:125
#define DHO_NIS_SERVERS
Definition: dhcp.h:137
#define BOOTP_MIN_LEN
Definition: dhcp.h:54
#define DHO_NON_LOCAL_SOURCE_ROUTING
Definition: dhcp.h:116
#define DHO_NTP_SERVERS
Definition: dhcp.h:138
#define DHO_MERIT_DUMP
Definition: dhcp.h:110
#define DHO_NETBIOS_NAME_SERVERS
Definition: dhcp.h:140
#define DHO_DHCP_PARAMETER_REQUEST_LIST
Definition: dhcp.h:151
#define DHO_FONT_SERVERS
Definition: dhcp.h:144
#define DHO_NETBIOS_SCOPE
Definition: dhcp.h:143
#define DHCPNAK
Definition: dhcp.h:167
#define DHCP_SNAME_LEN
Definition: dhcp.h:46
#define DHO_LOG_SERVERS
Definition: dhcp.h:103
#define DHCPACK
Definition: dhcp.h:166
#define DHCP_FILE_LEN
Definition: dhcp.h:47
#define DHO_NETBIOS_NODE_TYPE
Definition: dhcp.h:142
#define DHO_NIS_DOMAIN
Definition: dhcp.h:136
#define BOOTREPLY
Definition: dhcp.h:79
#define DHO_PAD
Definition: dhcp.h:96
#define DHO_HOST_NAME
Definition: dhcp.h:108
#define DHO_TCP_KEEPALIVE_INTERVAL
Definition: dhcp.h:134
#define DHO_BROADCAST_ADDRESS
Definition: dhcp.h:124
#define DHO_TIME_SERVERS
Definition: dhcp.h:100
#define DHO_NETBIOS_DD_SERVER
Definition: dhcp.h:141
#define DHO_IP_FORWARDING
Definition: dhcp.h:115
#define DHO_IMPRESS_SERVERS
Definition: dhcp.h:106
#define DHO_TRAILER_ENCAPSULATION
Definition: dhcp.h:130
#define DHO_PATH_MTU_PLATEAU_TABLE
Definition: dhcp.h:121
#define DHO_DHCP_USER_CLASS_ID
Definition: dhcp.h:158
#define DHO_EXTENSIONS_PATH
Definition: dhcp.h:114
#define DHO_DHCP_CLIENT_IDENTIFIER
Definition: dhcp.h:157
#define DHO_TIME_OFFSET
Definition: dhcp.h:98
#define DHO_DEFAULT_TCP_TTL
Definition: dhcp.h:133
#define DHO_DHCP_MESSAGE_TYPE
Definition: dhcp.h:149
#define DHO_INTERFACE_MTU
Definition: dhcp.h:122
#define DHO_X_DISPLAY_MANAGER
Definition: dhcp.h:145
#define DHO_POLICY_FILTER
Definition: dhcp.h:117
#define DHO_ALL_SUBNETS_LOCAL
Definition: dhcp.h:123
#define DHO_MAX_DGRAM_REASSEMBLY
Definition: dhcp.h:118
#define BOOTREQUEST
Definition: dhcp.h:78
#define DHCPDISCOVER
Definition: dhcp.h:162
#define DHO_END
Definition: dhcp.h:159
#define DHO_COOKIE_SERVERS
Definition: dhcp.h:104
#define DHO_DOMAIN_NAME
Definition: dhcp.h:111
#define DHO_DHCP_RENEWAL_TIME
Definition: dhcp.h:154
#define DHCPOFFER
Definition: dhcp.h:163
#define DHO_SWAP_SERVER
Definition: dhcp.h:112
#define DHO_DOMAIN_NAME_SERVERS
Definition: dhcp.h:102
#define DHO_DEFAULT_IP_TTL
Definition: dhcp.h:119
#define DHO_BOOT_SIZE
Definition: dhcp.h:109
#define DHO_DHCP_REBINDING_TIME
Definition: dhcp.h:155
#define DHO_DHCP_OPTION_OVERLOAD
Definition: dhcp.h:148
#define DHO_DHCP_SERVER_IDENTIFIER
Definition: dhcp.h:150
#define DHO_ROOT_PATH
Definition: dhcp.h:113
#define DHO_ARP_CACHE_TIMEOUT
Definition: dhcp.h:131
#define DHO_ROUTERS
Definition: dhcp.h:99
#define DHO_IEEE802_3_ENCAPSULATION
Definition: dhcp.h:132
#define DHO_DHCP_REQUESTED_ADDRESS
Definition: dhcp.h:146
#define DHO_DHCP_LEASE_TIME
Definition: dhcp.h:147
#define DHO_STATIC_ROUTES
Definition: dhcp.h:129
#define DHO_SUBNET_MASK
Definition: dhcp.h:97
#define DHO_DHCP_CLASS_IDENTIFIER
Definition: dhcp.h:156
#define DHO_LPR_SERVERS
Definition: dhcp.h:105
#define DHO_ROUTER_SOLICITATION_ADDRESS
Definition: dhcp.h:128
#define DHCPDECLINE
Definition: dhcp.h:165
#define DHO_PATH_MTU_AGING_TIMEOUT
Definition: dhcp.h:120
#define DHO_RESOURCE_LOCATION_SERVERS
Definition: dhcp.h:107
#define RegCloseKey(hKey)
Definition: registry.h:49
r l[0]
Definition: byte_order.h:168
Definition: bufpool.h:45
#define free
Definition: debug_ros.c:5
#define malloc
Definition: debug_ros.c:4
#define BufferSize
Definition: mmc.h:75
#define ERROR_SUCCESS
Definition: deptool.c:10
void make_request(struct interface_info *ip, struct client_lease *lease)
Definition: dhclient.c:1343
#define TIME_MAX
Definition: dhclient.c:90
int init_client(void)
Definition: dhclient.c:111
struct client_lease * packet_to_lease(struct packet *packet)
Definition: dhclient.c:833
void bootp(struct packet *packet)
Definition: dhclient.c:658
int unknown_ok
Definition: dhclient.c:94
void bind_lease(struct interface_info *ip)
Definition: dhclient.c:584
void dhcp(struct packet *packet)
Definition: dhclient.c:678
#define middlechar(c)
Definition: dhclient.c:68
char * path_dhclient_db
Definition: dhclient.c:74
int privfd
Definition: dhclient.c:77
void send_discover(void *ipp)
Definition: dhclient.c:959
void free_client_lease(struct client_lease *lease)
Definition: dhclient.c:1519
void dhcpnak(struct packet *packet)
Definition: dhclient.c:919
int dhcp_option_ev_name(char *buf, size_t buflen, struct dhcp_option *option)
Definition: dhclient.c:1771
struct iaddr iaddr_broadcast
Definition: dhclient.c:80
void write_client_lease(struct interface_info *ip, struct client_lease *lease, int rewrite)
Definition: dhclient.c:1559
struct in_addr inaddr_any
Definition: dhclient.c:81
int check_option(struct client_lease *l, int option)
Definition: dhclient.c:1817
void state_bound(void *ipp)
Definition: dhclient.c:632
int ipv4addrs(char *buf)
Definition: dhclient.c:1941
char * path_dhclient_conf
Definition: dhclient.c:73
void setup_adapter(PDHCP_ADAPTER Adapter, struct client_lease *new_lease)
Definition: dhclient.c:492
int fork_privchld(int, int)
void make_decline(struct interface_info *ip, struct client_lease *lease)
Definition: dhclient.c:1445
#define periodchar(c)
Definition: dhclient.c:61
struct sockaddr_in sockaddr_broadcast
Definition: dhclient.c:82
int no_daemon
Definition: dhclient.c:93
void state_selecting(void *ipp)
Definition: dhclient.c:235
void send_decline(void *ipp)
Definition: dhclient.c:1246
int check_arp(struct interface_info *ip, struct client_lease *lp)
Definition: dhclient.c:137
void state_reboot(void *ipp)
Definition: dhclient.c:172
void set_domain(PDHCP_ADAPTER Adapter, struct client_lease *new_lease)
Definition: dhclient.c:443
void dhcpack(struct packet *packet)
Definition: dhclient.c:316
void state_panic(void *ipp)
Definition: dhclient.c:1065
void stop_client(void)
Definition: dhclient.c:129
#define borderchar(c)
Definition: dhclient.c:67
FILE * leaseFile
Definition: dhclient.c:1534
char * option_as_string(unsigned int code, unsigned char *data, int len)
Definition: dhclient.c:1961
int log_perror
Definition: dhclient.c:76
void priv_script_init(struct interface_info *ip, char *reason, char *medium)
Definition: dhclient.c:1625
void priv_script_write_params(struct interface_info *ip, char *prefix, struct client_lease *lease)
Definition: dhclient.c:1633
time_t scripttime
Definition: dhclient.c:107
void state_init(void *ipp)
Definition: dhclient.c:210
int routefd
Definition: dhclient.c:95
int res_hnok(const char *dn)
Definition: dhclient.c:1912
int log_priority
Definition: dhclient.c:92
#define ASSERT_STATE(state_is, state_shouldbe)
Definition: dhclient.c:88
void set_name_servers(PDHCP_ADAPTER Adapter, struct client_lease *new_lease)
Definition: dhclient.c:398
void rewrite_client_leases(struct interface_info *ifi)
Definition: dhclient.c:1537
void usage(void)
void dhcpoffer(struct packet *packet)
Definition: dhclient.c:714
unsigned long debug_trace_level
Definition: dhclient.c:71
#define PERIOD
Definition: dhclient.c:58
void make_discover(struct interface_info *ip, struct client_lease *lease)
Definition: dhclient.c:1260
void go_daemon(void)
time_t cur_time
@ S_REBOOTING
Definition: dhcpd.h:171
@ S_BOUND
Definition: dhcpd.h:175
@ S_RENEWING
Definition: dhcpd.h:176
@ S_REBINDING
Definition: dhcpd.h:177
@ S_SELECTING
Definition: dhcpd.h:173
@ S_REQUESTING
Definition: dhcpd.h:174
@ S_INIT
Definition: dhcpd.h:172
#define REMOTE_PORT
Definition: dhcpd.h:113
#define _PATH_DHCLIENT_CONF
Definition: dhcpd.h:274
void script_set_env(struct client_state *, const char *, const char *, const char *)
#define NULL
Definition: types.h:112
#define NT_SUCCESS(StatCode)
Definition: apphelp.c:33
UINT op
Definition: effect.c:236
LONG WINAPI RegSetValueExA(HKEY hKey, LPCSTR lpValueName, DWORD Reserved, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
Definition: reg.c:4799
LONG WINAPI RegOpenKeyExA(_In_ HKEY hKey, _In_ LPCSTR lpSubKey, _In_ DWORD ulOptions, _In_ REGSAM samDesired, _Out_ PHKEY phkResult)
Definition: reg.c:3298
LONG WINAPI RegDeleteValueW(HKEY hKey, LPCWSTR lpValueName)
Definition: reg.c:2330
static WCHAR reason[MAX_STRING_RESOURCE_LEN]
Definition: object.c:1904
#define MAX_PATH
Definition: compat.h:34
DWORD WINAPI GetTickCount(VOID)
Definition: time.c:455
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7512
__kernel_time_t time_t
Definition: linux.h:252
#define AF_INET
Definition: tcpip.h:117
unsigned long DWORD
Definition: ntddk_ex.h:95
static void increase(int &a_)
Status
Definition: gdiplustypes.h:25
GLuint GLuint GLsizei GLenum type
Definition: gl.h:1545
GLint GLenum GLsizei GLsizei GLsizei GLint GLsizei const GLvoid * data
Definition: gl.h:1950
GLdouble GLdouble t
Definition: gl.h:2047
GLenum GLuint GLenum GLsizei const GLchar * buf
Definition: glext.h:7751
GLenum GLsizei len
Definition: glext.h:6722
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
#define DbgPrint
Definition: hal.h:12
#define isascii
Definition: ctype.h:742
_CRTIMP void __cdecl rewind(_Inout_ FILE *_File)
_Check_return_opt_ _CRTIMP int __cdecl fprintf(_Inout_ FILE *_File, _In_z_ _Printf_format_string_ const char *_Format,...)
_Check_return_opt_ _CRTIMP int __cdecl fflush(_Inout_opt_ FILE *_File)
_Check_return_ _CRTIMP FILE *__cdecl fopen(_In_z_ const char *_Filename, _In_z_ const char *_Mode)
void __cdecl srand(_In_ unsigned int _Seed)
_Check_return_ int __cdecl rand(void)
Definition: rand.c:10
DWORD WINAPI AddIPAddress(IPAddr Address, IPMask Netmask, DWORD IfIndex, PULONG NteContext, PULONG NteInstance)
Definition: iphlpapi_main.c:67
DWORD WINAPI DeleteIpForwardEntry(PMIB_IPFORWARDROW pRoute)
DWORD WINAPI CreateIpForwardEntry(PMIB_IPFORWARDROW pRoute)
DWORD WINAPI DeleteIPAddress(ULONG NTEContext)
DWORD WINAPI SendARP(IPAddr DestIP, IPAddr SrcIP, PULONG pMacAddr, PULONG PhyAddrLen)
#define debug(msg)
Definition: key_call.c:71
#define REG_SZ
Definition: layer.c:22
#define INADDR_BROADCAST
Definition: inet.h:82
#define INADDR_ANY
Definition: inet.h:80
__u16 time
Definition: mkdosfs.c:8
#define error(str)
Definition: mkdosfs.c:1605
#define pch(ap)
Definition: match.c:418
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define htons(x)
Definition: module.h:215
#define ntohs(x)
Definition: module.h:210
#define htonl(x)
Definition: module.h:214
#define sprintf(buf, format,...)
Definition: sprintf.c:55
#define STDOUT_FILENO
Definition: syshdrs.h:89
#define STDERR_FILENO
Definition: syshdrs.h:90
#define STDIN_FILENO
Definition: syshdrs.h:88
NTSYSAPI ULONG NTAPI RtlRandom(_Inout_ PULONG Seed)
#define KEY_WRITE
Definition: nt_native.h:1031
#define L(x)
Definition: ntvdm.h:50
ULONG IPAddr
Definition: pfhook.h:35
static unsigned __int64 next
Definition: rand_nt.c:6
unsigned char u_int8_t
Definition: rosdhcp.h:33
#define DHCP_DEFAULT_LEASE_TIME
Definition: rosdhcp.h:30
int nch
Definition: scanf.h:135
#define REG_DWORD
Definition: sdbapi.c:596
_Check_return_ _CRTIMP int __cdecl dup2(_In_ int _FileHandleSrc, _In_ int _FileHandleDst)
_CRTIMP struct tm *__cdecl gmtime(const time_t *_Time)
Definition: time.h:415
_CRTIMP void __cdecl tzset(void)
#define warning(s)
Definition: debug.h:83
strcat
Definition: string.h:92
#define memset(x, y, z)
Definition: compat.h:39
ssize_t send_packet(struct interface_info *ip, struct dhcp_packet *p, size_t size, struct in_addr addr, struct sockaddr_in *broadcast, struct hardware *hardware)
Definition: socket.c:9
CardRegion * from
Definition: spigame.cpp:19
ULONG NteContext
Definition: rosdhcp.h:70
ULONG NteInstance
Definition: rosdhcp.h:70
MIB_IPFORWARDROW RouterMib
Definition: rosdhcp.h:67
struct interface_info DhclientInfo
Definition: rosdhcp.h:71
MIB_IFROW IfMib
Definition: rosdhcp.h:66
DWORD dwIndex
Definition: ifmib.h:38
DWORD dwForwardNextHop
Definition: ipmib.h:74
DWORD dwForwardMetric1
Definition: ipmib.h:88
IF_INDEX dwForwardIfIndex
Definition: ipmib.h:75
DWORD dwForwardDest
Definition: ipmib.h:71
DWORD dwForwardMask
Definition: ipmib.h:72
unsigned int is_static
Definition: dhcpd.h:164
struct string_list * medium
Definition: dhcpd.h:163
struct option_data options[256]
Definition: dhcpd.h:166
struct iaddr address
Definition: dhcpd.h:156
char * filename
Definition: dhcpd.h:162
char * server_name
Definition: dhcpd.h:157
unsigned int is_bootp
Definition: dhcpd.h:165
struct client_lease * next
Definition: dhcpd.h:154
time_t renewal
Definition: dhcpd.h:155
time_t rebind
Definition: dhcpd.h:155
time_t expiry
Definition: dhcpd.h:155
Definition: inflate.c:139
Definition: dhcpd.h:125
int len
Definition: dhcpd.h:126
unsigned char iabuf[16]
Definition: dhcpd.h:127
Definition: tcpip.h:126
struct client_state * client
Definition: dhcpd.h:238
Definition: dhcpd.h:62
Definition: name.c:39
Definition: getopt.h:109
WCHAR * name
Definition: getopt.h:110
Definition: dhcpd.h:135
struct dhcp_packet * raw
Definition: dhcpd.h:136
struct interface_info * interface
Definition: dhcpd.h:142
struct option_data options[256]
Definition: dhcpd.h:144
int packet_type
Definition: dhcpd.h:138
struct iaddr client_addr
Definition: dhcpd.h:141
Definition: tftpd.h:86
struct in_addr sin_addr
Definition: winsock.h:512
short sin_family
Definition: winsock.h:510
u_short sin_port
Definition: winsock.h:511
Definition: time.h:68
struct dhcp_option dhcp_options[256]
Definition: tables.c:68
Character const *const prefix
Definition: tempnam.cpp:195
static const u8_t broadcast[6]
Definition: test_dhcp.c:23
unsigned char * LPBYTE
Definition: typedefs.h:53
uint32_t ULONG
Definition: typedefs.h:59
int ret
_In_ WDFMEMORY _Out_opt_ size_t * BufferSize
Definition: wdfmemory.h:254
void int int ULONGLONG int va_list * ap
Definition: winesup.h:36
#define HKEY_LOCAL_MACHINE
Definition: winreg.h:12
#define snprintf
Definition: wintirpc.h:48
#define _snprintf
Definition: xmlstorage.h:200
char CHAR
Definition: xmlstorage.h:175