Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendhclient.c
Go to the documentation of this file.
00001 /* $OpenBSD: dhclient.c,v 1.62 2004/12/05 18:35:51 deraadt Exp $ */ 00002 00003 /* 00004 * Copyright 2004 Henning Brauer <henning@openbsd.org> 00005 * Copyright (c) 1995, 1996, 1997, 1998, 1999 00006 * The Internet Software Consortium. All rights reserved. 00007 * 00008 * Redistribution and use in source and binary forms, with or without 00009 * modification, are permitted provided that the following conditions 00010 * are met: 00011 * 00012 * 1. Redistributions of source code must retain the above copyright 00013 * notice, this list of conditions and the following disclaimer. 00014 * 2. Redistributions in binary form must reproduce the above copyright 00015 * notice, this list of conditions and the following disclaimer in the 00016 * documentation and/or other materials provided with the distribution. 00017 * 3. Neither the name of The Internet Software Consortium nor the names 00018 * of its contributors may be used to endorse or promote products derived 00019 * from this software without specific prior written permission. 00020 * 00021 * THIS SOFTWARE IS PROVIDED BY THE INTERNET SOFTWARE CONSORTIUM AND 00022 * CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 00023 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 00024 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 00025 * DISCLAIMED. IN NO EVENT SHALL THE INTERNET SOFTWARE CONSORTIUM OR 00026 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 00027 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 00028 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF 00029 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 00030 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 00031 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 00032 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 00033 * SUCH DAMAGE. 00034 * 00035 * This software has been written for the Internet Software Consortium 00036 * by Ted Lemon <mellon@fugue.com> in cooperation with Vixie 00037 * Enterprises. To learn more about the Internet Software Consortium, 00038 * see ``http://www.vix.com/isc''. To learn more about Vixie 00039 * Enterprises, see ``http://www.vix.com''. 00040 * 00041 * This client was substantially modified and enhanced by Elliot Poger 00042 * for use on Linux while he was working on the MosquitoNet project at 00043 * Stanford. 00044 * 00045 * The current version owes much to Elliot's Linux enhancements, but 00046 * was substantially reorganized and partially rewritten by Ted Lemon 00047 * so as to use the same networking framework that the Internet Software 00048 * Consortium DHCP server uses. Much system-specific configuration code 00049 * was moved into a shell script so that as support for more operating 00050 * systems is added, it will not be necessary to port and maintain 00051 * system-specific configuration code to these operating systems - instead, 00052 * the shell script can invoke the native tools to accomplish the same 00053 * purpose. 00054 */ 00055 00056 #include "rosdhcp.h" 00057 00058 #define PERIOD 0x2e 00059 #define hyphenchar(c) ((c) == 0x2d) 00060 #define bslashchar(c) ((c) == 0x5c) 00061 #define periodchar(c) ((c) == PERIOD) 00062 #define asterchar(c) ((c) == 0x2a) 00063 #define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) || \ 00064 ((c) >= 0x61 && (c) <= 0x7a)) 00065 #define digitchar(c) ((c) >= 0x30 && (c) <= 0x39) 00066 00067 #define borderchar(c) (alphachar(c) || digitchar(c)) 00068 #define middlechar(c) (borderchar(c) || hyphenchar(c)) 00069 #define domainchar(c) ((c) > 0x20 && (c) < 0x7f) 00070 00071 unsigned long debug_trace_level = 0; /* DEBUG_ULTRA */ 00072 00073 char *path_dhclient_conf = _PATH_DHCLIENT_CONF; 00074 char *path_dhclient_db = NULL; 00075 00076 int log_perror = 1; 00077 int privfd; 00078 //int nullfd = -1; 00079 00080 struct iaddr iaddr_broadcast = { 4, { 255, 255, 255, 255 } }; 00081 struct in_addr inaddr_any; 00082 struct sockaddr_in sockaddr_broadcast; 00083 00084 /* 00085 * ASSERT_STATE() does nothing now; it used to be 00086 * assert (state_is == state_shouldbe). 00087 */ 00088 #define ASSERT_STATE(state_is, state_shouldbe) {} 00089 00090 #define TIME_MAX 2147483647 00091 00092 int log_priority; 00093 int no_daemon; 00094 int unknown_ok = 1; 00095 int routefd; 00096 00097 void usage(void); 00098 int check_option(struct client_lease *l, int option); 00099 int ipv4addrs(char * buf); 00100 int res_hnok(const char *dn); 00101 char *option_as_string(unsigned int code, unsigned char *data, int len); 00102 int fork_privchld(int, int); 00103 int check_arp( struct interface_info *ip, struct client_lease *lp ); 00104 00105 #define ADVANCE(x, n) (x += ROUNDUP((n)->sa_len)) 00106 00107 time_t scripttime; 00108 00109 static WCHAR ServiceName[] = L"DHCP"; 00110 00111 SERVICE_STATUS_HANDLE ServiceStatusHandle = 0; 00112 SERVICE_STATUS ServiceStatus; 00113 00114 00115 /* XXX Implement me */ 00116 int check_arp( struct interface_info *ip, struct client_lease *lp ) { 00117 return 1; 00118 } 00119 00120 00121 static VOID 00122 UpdateServiceStatus(DWORD dwState) 00123 { 00124 ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 00125 ServiceStatus.dwCurrentState = dwState; 00126 00127 ServiceStatus.dwControlsAccepted = 0; 00128 00129 ServiceStatus.dwWin32ExitCode = 0; 00130 ServiceStatus.dwServiceSpecificExitCode = 0; 00131 ServiceStatus.dwCheckPoint = 0; 00132 00133 if (dwState == SERVICE_START_PENDING || 00134 dwState == SERVICE_STOP_PENDING || 00135 dwState == SERVICE_PAUSE_PENDING || 00136 dwState == SERVICE_CONTINUE_PENDING) 00137 ServiceStatus.dwWaitHint = 10000; 00138 else 00139 ServiceStatus.dwWaitHint = 0; 00140 00141 SetServiceStatus(ServiceStatusHandle, 00142 &ServiceStatus); 00143 } 00144 00145 00146 static DWORD WINAPI 00147 ServiceControlHandler(DWORD dwControl, 00148 DWORD dwEventType, 00149 LPVOID lpEventData, 00150 LPVOID lpContext) 00151 { 00152 switch (dwControl) 00153 { 00154 case SERVICE_CONTROL_STOP: 00155 UpdateServiceStatus(SERVICE_STOP_PENDING); 00156 UpdateServiceStatus(SERVICE_STOPPED); 00157 return ERROR_SUCCESS; 00158 00159 case SERVICE_CONTROL_PAUSE: 00160 UpdateServiceStatus(SERVICE_PAUSED); 00161 return ERROR_SUCCESS; 00162 00163 case SERVICE_CONTROL_CONTINUE: 00164 UpdateServiceStatus(SERVICE_START_PENDING); 00165 UpdateServiceStatus(SERVICE_RUNNING); 00166 return ERROR_SUCCESS; 00167 00168 case SERVICE_CONTROL_INTERROGATE: 00169 SetServiceStatus(ServiceStatusHandle, 00170 &ServiceStatus); 00171 return ERROR_SUCCESS; 00172 00173 case SERVICE_CONTROL_SHUTDOWN: 00174 UpdateServiceStatus(SERVICE_STOP_PENDING); 00175 UpdateServiceStatus(SERVICE_STOPPED); 00176 return ERROR_SUCCESS; 00177 00178 default : 00179 return ERROR_CALL_NOT_IMPLEMENTED; 00180 } 00181 } 00182 00183 00184 VOID NTAPI 00185 ServiceMain(DWORD argc, LPWSTR *argv) 00186 { 00187 ServiceStatusHandle = RegisterServiceCtrlHandlerExW(ServiceName, 00188 ServiceControlHandler, 00189 NULL); 00190 if (!ServiceStatusHandle) 00191 { 00192 DbgPrint("DHCPCSVC: Unable to register service control handler (%lx)\n", GetLastError()); 00193 return; 00194 } 00195 00196 UpdateServiceStatus(SERVICE_START_PENDING); 00197 00198 ApiInit(); 00199 AdapterInit(); 00200 00201 tzset(); 00202 00203 memset(&sockaddr_broadcast, 0, sizeof(sockaddr_broadcast)); 00204 sockaddr_broadcast.sin_family = AF_INET; 00205 sockaddr_broadcast.sin_port = htons(REMOTE_PORT); 00206 sockaddr_broadcast.sin_addr.s_addr = INADDR_BROADCAST; 00207 inaddr_any.s_addr = INADDR_ANY; 00208 bootp_packet_handler = do_packet; 00209 00210 if (PipeInit() == INVALID_HANDLE_VALUE) 00211 { 00212 DbgPrint("DHCPCSVC: PipeInit() failed!\n"); 00213 AdapterStop(); 00214 ApiFree(); 00215 UpdateServiceStatus(SERVICE_STOPPED); 00216 } 00217 00218 DH_DbgPrint(MID_TRACE,("DHCP Service Started\n")); 00219 00220 UpdateServiceStatus(SERVICE_RUNNING); 00221 00222 DH_DbgPrint(MID_TRACE,("Going into dispatch()\n")); 00223 00224 DbgPrint("DHCPCSVC: DHCP service is starting up\n"); 00225 00226 dispatch(); 00227 00228 DbgPrint("DHCPCSVC: DHCP service is shutting down\n"); 00229 00230 //AdapterStop(); 00231 //ApiFree(); 00232 /* FIXME: Close pipe and kill pipe thread */ 00233 00234 UpdateServiceStatus(SERVICE_STOPPED); 00235 } 00236 00237 /* 00238 * Individual States: 00239 * 00240 * Each routine is called from the dhclient_state_machine() in one of 00241 * these conditions: 00242 * -> entering INIT state 00243 * -> recvpacket_flag == 0: timeout in this state 00244 * -> otherwise: received a packet in this state 00245 * 00246 * Return conditions as handled by dhclient_state_machine(): 00247 * Returns 1, sendpacket_flag = 1: send packet, reset timer. 00248 * Returns 1, sendpacket_flag = 0: just reset the timer (wait for a milestone). 00249 * Returns 0: finish the nap which was interrupted for no good reason. 00250 * 00251 * Several per-interface variables are used to keep track of the process: 00252 * active_lease: the lease that is being used on the interface 00253 * (null pointer if not configured yet). 00254 * offered_leases: leases corresponding to DHCPOFFER messages that have 00255 * been sent to us by DHCP servers. 00256 * acked_leases: leases corresponding to DHCPACK messages that have been 00257 * sent to us by DHCP servers. 00258 * sendpacket: DHCP packet we're trying to send. 00259 * destination: IP address to send sendpacket to 00260 * In addition, there are several relevant per-lease variables. 00261 * T1_expiry, T2_expiry, lease_expiry: lease milestones 00262 * In the active lease, these control the process of renewing the lease; 00263 * In leases on the acked_leases list, this simply determines when we 00264 * can no longer legitimately use the lease. 00265 */ 00266 00267 void 00268 state_reboot(void *ipp) 00269 { 00270 struct interface_info *ip = ipp; 00271 ULONG foo = (ULONG) GetTickCount(); 00272 00273 /* If we don't remember an active lease, go straight to INIT. */ 00274 if (!ip->client->active || ip->client->active->is_bootp) { 00275 state_init(ip); 00276 return; 00277 } 00278 00279 /* We are in the rebooting state. */ 00280 ip->client->state = S_REBOOTING; 00281 00282 /* make_request doesn't initialize xid because it normally comes 00283 from the DHCPDISCOVER, but we haven't sent a DHCPDISCOVER, 00284 so pick an xid now. */ 00285 ip->client->xid = RtlRandom(&foo); 00286 00287 /* Make a DHCPREQUEST packet, and set appropriate per-interface 00288 flags. */ 00289 make_request(ip, ip->client->active); 00290 ip->client->destination = iaddr_broadcast; 00291 time(&ip->client->first_sending); 00292 ip->client->interval = ip->client->config->initial_interval; 00293 00294 /* Zap the medium list... */ 00295 ip->client->medium = NULL; 00296 00297 /* Send out the first DHCPREQUEST packet. */ 00298 send_request(ip); 00299 } 00300 00301 /* 00302 * Called when a lease has completely expired and we've 00303 * been unable to renew it. 00304 */ 00305 void 00306 state_init(void *ipp) 00307 { 00308 struct interface_info *ip = ipp; 00309 00310 ASSERT_STATE(state, S_INIT); 00311 00312 /* Make a DHCPDISCOVER packet, and set appropriate per-interface 00313 flags. */ 00314 make_discover(ip, ip->client->active); 00315 ip->client->xid = ip->client->packet.xid; 00316 ip->client->destination = iaddr_broadcast; 00317 ip->client->state = S_SELECTING; 00318 time(&ip->client->first_sending); 00319 ip->client->interval = ip->client->config->initial_interval; 00320 00321 /* Add an immediate timeout to cause the first DHCPDISCOVER packet 00322 to go out. */ 00323 send_discover(ip); 00324 } 00325 00326 /* 00327 * state_selecting is called when one or more DHCPOFFER packets 00328 * have been received and a configurable period of time has passed. 00329 */ 00330 void 00331 state_selecting(void *ipp) 00332 { 00333 struct interface_info *ip = ipp; 00334 struct client_lease *lp, *next, *picked; 00335 time_t cur_time; 00336 00337 ASSERT_STATE(state, S_SELECTING); 00338 00339 time(&cur_time); 00340 00341 /* Cancel state_selecting and send_discover timeouts, since either 00342 one could have got us here. */ 00343 cancel_timeout(state_selecting, ip); 00344 cancel_timeout(send_discover, ip); 00345 00346 /* We have received one or more DHCPOFFER packets. Currently, 00347 the only criterion by which we judge leases is whether or 00348 not we get a response when we arp for them. */ 00349 picked = NULL; 00350 for (lp = ip->client->offered_leases; lp; lp = next) { 00351 next = lp->next; 00352 00353 /* Check to see if we got an ARPREPLY for the address 00354 in this particular lease. */ 00355 if (!picked) { 00356 if( !check_arp(ip,lp) ) goto freeit; 00357 picked = lp; 00358 picked->next = NULL; 00359 } else { 00360 freeit: 00361 free_client_lease(lp); 00362 } 00363 } 00364 ip->client->offered_leases = NULL; 00365 00366 /* If we just tossed all the leases we were offered, go back 00367 to square one. */ 00368 if (!picked) { 00369 ip->client->state = S_INIT; 00370 state_init(ip); 00371 return; 00372 } 00373 00374 /* If it was a BOOTREPLY, we can just take the address right now. */ 00375 if (!picked->options[DHO_DHCP_MESSAGE_TYPE].len) { 00376 ip->client->new = picked; 00377 00378 /* Make up some lease expiry times 00379 XXX these should be configurable. */ 00380 ip->client->new->expiry = cur_time + 12000; 00381 ip->client->new->renewal += cur_time + 8000; 00382 ip->client->new->rebind += cur_time + 10000; 00383 00384 ip->client->state = S_REQUESTING; 00385 00386 /* Bind to the address we received. */ 00387 bind_lease(ip); 00388 return; 00389 } 00390 00391 /* Go to the REQUESTING state. */ 00392 ip->client->destination = iaddr_broadcast; 00393 ip->client->state = S_REQUESTING; 00394 ip->client->first_sending = cur_time; 00395 ip->client->interval = ip->client->config->initial_interval; 00396 00397 /* Make a DHCPREQUEST packet from the lease we picked. */ 00398 make_request(ip, picked); 00399 ip->client->xid = ip->client->packet.xid; 00400 00401 /* Toss the lease we picked - we'll get it back in a DHCPACK. */ 00402 free_client_lease(picked); 00403 00404 /* Add an immediate timeout to send the first DHCPREQUEST packet. */ 00405 send_request(ip); 00406 } 00407 00408 /* state_requesting is called when we receive a DHCPACK message after 00409 having sent out one or more DHCPREQUEST packets. */ 00410 00411 void 00412 dhcpack(struct packet *packet) 00413 { 00414 struct interface_info *ip = packet->interface; 00415 struct client_lease *lease; 00416 time_t cur_time; 00417 00418 time(&cur_time); 00419 00420 /* If we're not receptive to an offer right now, or if the offer 00421 has an unrecognizable transaction id, then just drop it. */ 00422 if (packet->interface->client->xid != packet->raw->xid || 00423 (packet->interface->hw_address.hlen != packet->raw->hlen) || 00424 (memcmp(packet->interface->hw_address.haddr, 00425 packet->raw->chaddr, packet->raw->hlen))) 00426 return; 00427 00428 if (ip->client->state != S_REBOOTING && 00429 ip->client->state != S_REQUESTING && 00430 ip->client->state != S_RENEWING && 00431 ip->client->state != S_REBINDING) 00432 return; 00433 00434 note("DHCPACK from %s", piaddr(packet->client_addr)); 00435 00436 lease = packet_to_lease(packet); 00437 if (!lease) { 00438 note("packet_to_lease failed."); 00439 return; 00440 } 00441 00442 ip->client->new = lease; 00443 00444 /* Stop resending DHCPREQUEST. */ 00445 cancel_timeout(send_request, ip); 00446 00447 /* Figure out the lease time. */ 00448 if (ip->client->new->options[DHO_DHCP_LEASE_TIME].data) 00449 ip->client->new->expiry = getULong( 00450 ip->client->new->options[DHO_DHCP_LEASE_TIME].data); 00451 else 00452 ip->client->new->expiry = DHCP_DEFAULT_LEASE_TIME; 00453 /* A number that looks negative here is really just very large, 00454 because the lease expiry offset is unsigned. */ 00455 if (ip->client->new->expiry < 0) 00456 ip->client->new->expiry = TIME_MAX; 00457 /* XXX should be fixed by resetting the client state */ 00458 if (ip->client->new->expiry < 60) 00459 ip->client->new->expiry = 60; 00460 00461 /* Take the server-provided renewal time if there is one; 00462 otherwise figure it out according to the spec. */ 00463 if (ip->client->new->options[DHO_DHCP_RENEWAL_TIME].len) 00464 ip->client->new->renewal = getULong( 00465 ip->client->new->options[DHO_DHCP_RENEWAL_TIME].data); 00466 else 00467 ip->client->new->renewal = ip->client->new->expiry / 2; 00468 00469 /* Same deal with the rebind time. */ 00470 if (ip->client->new->options[DHO_DHCP_REBINDING_TIME].len) 00471 ip->client->new->rebind = getULong( 00472 ip->client->new->options[DHO_DHCP_REBINDING_TIME].data); 00473 else 00474 ip->client->new->rebind = ip->client->new->renewal + 00475 ip->client->new->renewal / 2 + ip->client->new->renewal / 4; 00476 00477 #ifdef __REACTOS__ 00478 ip->client->new->obtained = cur_time; 00479 #endif 00480 ip->client->new->expiry += cur_time; 00481 /* Lease lengths can never be negative. */ 00482 if (ip->client->new->expiry < cur_time) 00483 ip->client->new->expiry = TIME_MAX; 00484 ip->client->new->renewal += cur_time; 00485 if (ip->client->new->renewal < cur_time) 00486 ip->client->new->renewal = TIME_MAX; 00487 ip->client->new->rebind += cur_time; 00488 if (ip->client->new->rebind < cur_time) 00489 ip->client->new->rebind = TIME_MAX; 00490 00491 bind_lease(ip); 00492 } 00493 00494 void set_name_servers( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) { 00495 CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; 00496 HKEY RegKey; 00497 00498 strcat(Buffer, Adapter->DhclientInfo.name); 00499 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &RegKey ) != ERROR_SUCCESS) 00500 return; 00501 00502 00503 if( new_lease->options[DHO_DOMAIN_NAME_SERVERS].len ) { 00504 00505 struct iaddr nameserver; 00506 char *nsbuf; 00507 int i, addrs = 00508 new_lease->options[DHO_DOMAIN_NAME_SERVERS].len / sizeof(ULONG); 00509 00510 nsbuf = malloc( addrs * sizeof(IP_ADDRESS_STRING) ); 00511 00512 if( nsbuf) { 00513 nsbuf[0] = 0; 00514 for( i = 0; i < addrs; i++ ) { 00515 nameserver.len = sizeof(ULONG); 00516 memcpy( nameserver.iabuf, 00517 new_lease->options[DHO_DOMAIN_NAME_SERVERS].data + 00518 (i * sizeof(ULONG)), sizeof(ULONG) ); 00519 strcat( nsbuf, piaddr(nameserver) ); 00520 if( i != addrs-1 ) strcat( nsbuf, "," ); 00521 } 00522 00523 DH_DbgPrint(MID_TRACE,("Setting DhcpNameserver: %s\n", nsbuf)); 00524 00525 RegSetValueExA( RegKey, "DhcpNameServer", 0, REG_SZ, 00526 (LPBYTE)nsbuf, strlen(nsbuf) + 1 ); 00527 free( nsbuf ); 00528 } 00529 00530 } else { 00531 RegDeleteValueW( RegKey, L"DhcpNameServer" ); 00532 } 00533 00534 RegCloseKey( RegKey ); 00535 00536 } 00537 00538 void setup_adapter( PDHCP_ADAPTER Adapter, struct client_lease *new_lease ) { 00539 CHAR Buffer[200] = "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters\\Interfaces\\"; 00540 struct iaddr netmask; 00541 HKEY hkey; 00542 int i; 00543 DWORD dwEnableDHCP; 00544 00545 strcat(Buffer, Adapter->DhclientInfo.name); 00546 if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, Buffer, 0, KEY_WRITE, &hkey) != ERROR_SUCCESS) 00547 hkey = NULL; 00548 00549 00550 if( Adapter->NteContext ) 00551 { 00552 DeleteIPAddress( Adapter->NteContext ); 00553 Adapter->NteContext = 0; 00554 } 00555 00556 /* Set up our default router if we got one from the DHCP server */ 00557 if( new_lease->options[DHO_SUBNET_MASK].len ) { 00558 NTSTATUS Status; 00559 00560 memcpy( netmask.iabuf, 00561 new_lease->options[DHO_SUBNET_MASK].data, 00562 new_lease->options[DHO_SUBNET_MASK].len ); 00563 Status = AddIPAddress 00564 ( *((ULONG*)new_lease->address.iabuf), 00565 *((ULONG*)netmask.iabuf), 00566 Adapter->IfMib.dwIndex, 00567 &Adapter->NteContext, 00568 &Adapter->NteInstance ); 00569 if (hkey) { 00570 RegSetValueExA(hkey, "DhcpIPAddress", 0, REG_SZ, (LPBYTE)piaddr(new_lease->address), strlen(piaddr(new_lease->address))+1); 00571 Buffer[0] = '\0'; 00572 for(i = 0; i < new_lease->options[DHO_SUBNET_MASK].len; i++) 00573 { 00574 sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_SUBNET_MASK].data[i]); 00575 if (i + 1 < new_lease->options[DHO_SUBNET_MASK].len) 00576 strcat(Buffer, "."); 00577 } 00578 RegSetValueExA(hkey, "DhcpSubnetMask", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1); 00579 dwEnableDHCP = 1; 00580 RegSetValueExA(hkey, "EnableDHCP", 0, REG_DWORD, (LPBYTE)&dwEnableDHCP, sizeof(DWORD)); 00581 } 00582 00583 if( !NT_SUCCESS(Status) ) 00584 warning("AddIPAddress: %lx\n", Status); 00585 } 00586 00587 if( new_lease->options[DHO_ROUTERS].len ) { 00588 NTSTATUS Status; 00589 00590 Adapter->RouterMib.dwForwardDest = 0; /* Default route */ 00591 Adapter->RouterMib.dwForwardMask = 0; 00592 Adapter->RouterMib.dwForwardMetric1 = 1; 00593 Adapter->RouterMib.dwForwardIfIndex = Adapter->IfMib.dwIndex; 00594 00595 if( Adapter->RouterMib.dwForwardNextHop ) { 00596 /* If we set a default route before, delete it before continuing */ 00597 DeleteIpForwardEntry( &Adapter->RouterMib ); 00598 } 00599 00600 Adapter->RouterMib.dwForwardNextHop = 00601 *((ULONG*)new_lease->options[DHO_ROUTERS].data); 00602 00603 Status = CreateIpForwardEntry( &Adapter->RouterMib ); 00604 00605 if( !NT_SUCCESS(Status) ) 00606 warning("CreateIpForwardEntry: %lx\n", Status); 00607 00608 if (hkey) { 00609 Buffer[0] = '\0'; 00610 for(i = 0; i < new_lease->options[DHO_ROUTERS].len; i++) 00611 { 00612 sprintf(&Buffer[strlen(Buffer)], "%u", new_lease->options[DHO_ROUTERS].data[i]); 00613 if (i + 1 < new_lease->options[DHO_ROUTERS].len) 00614 strcat(Buffer, "."); 00615 } 00616 RegSetValueExA(hkey, "DhcpDefaultGateway", 0, REG_SZ, (LPBYTE)Buffer, strlen(Buffer)+1); 00617 } 00618 } 00619 00620 if (hkey) 00621 RegCloseKey(hkey); 00622 } 00623 00624 00625 void 00626 bind_lease(struct interface_info *ip) 00627 { 00628 PDHCP_ADAPTER Adapter; 00629 struct client_lease *new_lease = ip->client->new; 00630 time_t cur_time; 00631 00632 time(&cur_time); 00633 00634 /* Remember the medium. */ 00635 ip->client->new->medium = ip->client->medium; 00636 ip->client->active = ip->client->new; 00637 ip->client->new = NULL; 00638 00639 /* Set up a timeout to start the renewal process. */ 00640 /* Timeout of zero means no timeout (some implementations seem to use 00641 * one day). 00642 */ 00643 if( ip->client->active->renewal - cur_time ) 00644 add_timeout(ip->client->active->renewal, state_bound, ip); 00645 00646 note("bound to %s -- renewal in %ld seconds.", 00647 piaddr(ip->client->active->address), 00648 (long int)(ip->client->active->renewal - cur_time)); 00649 00650 ip->client->state = S_BOUND; 00651 00652 Adapter = AdapterFindInfo( ip ); 00653 00654 if( Adapter ) setup_adapter( Adapter, new_lease ); 00655 else { 00656 warning("Could not find adapter for info %p\n", ip); 00657 return; 00658 } 00659 set_name_servers( Adapter, new_lease ); 00660 } 00661 00662 /* 00663 * state_bound is called when we've successfully bound to a particular 00664 * lease, but the renewal time on that lease has expired. We are 00665 * expected to unicast a DHCPREQUEST to the server that gave us our 00666 * original lease. 00667 */ 00668 void 00669 state_bound(void *ipp) 00670 { 00671 struct interface_info *ip = ipp; 00672 00673 ASSERT_STATE(state, S_BOUND); 00674 00675 /* T1 has expired. */ 00676 make_request(ip, ip->client->active); 00677 ip->client->xid = ip->client->packet.xid; 00678 00679 if (ip->client->active->options[DHO_DHCP_SERVER_IDENTIFIER].len == 4) { 00680 memcpy(ip->client->destination.iabuf, ip->client->active-> 00681 options[DHO_DHCP_SERVER_IDENTIFIER].data, 4); 00682 ip->client->destination.len = 4; 00683 } else 00684 ip->client->destination = iaddr_broadcast; 00685 00686 time(&ip->client->first_sending); 00687 ip->client->interval = ip->client->config->initial_interval; 00688 ip->client->state = S_RENEWING; 00689 00690 /* Send the first packet immediately. */ 00691 send_request(ip); 00692 } 00693 00694 void 00695 bootp(struct packet *packet) 00696 { 00697 struct iaddrlist *ap; 00698 00699 if (packet->raw->op != BOOTREPLY) 00700 return; 00701 00702 /* If there's a reject list, make sure this packet's sender isn't 00703 on it. */ 00704 for (ap = packet->interface->client->config->reject_list; 00705 ap; ap = ap->next) { 00706 if (addr_eq(packet->client_addr, ap->addr)) { 00707 note("BOOTREPLY from %s rejected.", piaddr(ap->addr)); 00708 return; 00709 } 00710 } 00711 dhcpoffer(packet); 00712 } 00713 00714 void 00715 dhcp(struct packet *packet) 00716 { 00717 struct iaddrlist *ap; 00718 void (*handler)(struct packet *); 00719 char *type; 00720 00721 switch (packet->packet_type) { 00722 case DHCPOFFER: 00723 handler = dhcpoffer; 00724 type = "DHCPOFFER"; 00725 break; 00726 case DHCPNAK: 00727 handler = dhcpnak; 00728 type = "DHCPNACK"; 00729 break; 00730 case DHCPACK: 00731 handler = dhcpack; 00732 type = "DHCPACK"; 00733 break; 00734 default: 00735 return; 00736 } 00737 00738 /* If there's a reject list, make sure this packet's sender isn't 00739 on it. */ 00740 for (ap = packet->interface->client->config->reject_list; 00741 ap; ap = ap->next) { 00742 if (addr_eq(packet->client_addr, ap->addr)) { 00743 note("%s from %s rejected.", type, piaddr(ap->addr)); 00744 return; 00745 } 00746 } 00747 (*handler)(packet); 00748 } 00749 00750 void 00751 dhcpoffer(struct packet *packet) 00752 { 00753 struct interface_info *ip = packet->interface; 00754 struct client_lease *lease, *lp; 00755 int i; 00756 int arp_timeout_needed = 0, stop_selecting; 00757 char *name = packet->options[DHO_DHCP_MESSAGE_TYPE].len ? 00758 "DHCPOFFER" : "BOOTREPLY"; 00759 time_t cur_time; 00760 00761 time(&cur_time); 00762 00763 /* If we're not receptive to an offer right now, or if the offer 00764 has an unrecognizable transaction id, then just drop it. */ 00765 if (ip->client->state != S_SELECTING || 00766 packet->interface->client->xid != packet->raw->xid || 00767 (packet->interface->hw_address.hlen != packet->raw->hlen) || 00768 (memcmp(packet->interface->hw_address.haddr, 00769 packet->raw->chaddr, packet->raw->hlen))) 00770 return; 00771 00772 note("%s from %s", name, piaddr(packet->client_addr)); 00773 00774 00775 /* If this lease doesn't supply the minimum required parameters, 00776 blow it off. */ 00777 for (i = 0; ip->client->config->required_options[i]; i++) { 00778 if (!packet->options[ip->client->config-> 00779 required_options[i]].len) { 00780 note("%s isn't satisfactory.", name); 00781 return; 00782 } 00783 } 00784 00785 /* If we've already seen this lease, don't record it again. */ 00786 for (lease = ip->client->offered_leases; 00787 lease; lease = lease->next) { 00788 if (lease->address.len == sizeof(packet->raw->yiaddr) && 00789 !memcmp(lease->address.iabuf, 00790 &packet->raw->yiaddr, lease->address.len)) { 00791 debug("%s already seen.", name); 00792 return; 00793 } 00794 } 00795 00796 lease = packet_to_lease(packet); 00797 if (!lease) { 00798 note("packet_to_lease failed."); 00799 return; 00800 } 00801 00802 /* If this lease was acquired through a BOOTREPLY, record that 00803 fact. */ 00804 if (!packet->options[DHO_DHCP_MESSAGE_TYPE].len) 00805 lease->is_bootp = 1; 00806 00807 /* Record the medium under which this lease was offered. */ 00808 lease->medium = ip->client->medium; 00809 00810 /* Send out an ARP Request for the offered IP address. */ 00811 if( !check_arp( ip, lease ) ) { 00812 note("Arp check failed\n"); 00813 return; 00814 } 00815 00816 /* Figure out when we're supposed to stop selecting. */ 00817 stop_selecting = 00818 ip->client->first_sending + ip->client->config->select_interval; 00819 00820 /* If this is the lease we asked for, put it at the head of the 00821 list, and don't mess with the arp request timeout. */ 00822 if (lease->address.len == ip->client->requested_address.len && 00823 !memcmp(lease->address.iabuf, 00824 ip->client->requested_address.iabuf, 00825 ip->client->requested_address.len)) { 00826 lease->next = ip->client->offered_leases; 00827 ip->client->offered_leases = lease; 00828 } else { 00829 /* If we already have an offer, and arping for this 00830 offer would take us past the selection timeout, 00831 then don't extend the timeout - just hope for the 00832 best. */ 00833 if (ip->client->offered_leases && 00834 (cur_time + arp_timeout_needed) > stop_selecting) 00835 arp_timeout_needed = 0; 00836 00837 /* Put the lease at the end of the list. */ 00838 lease->next = NULL; 00839 if (!ip->client->offered_leases) 00840 ip->client->offered_leases = lease; 00841 else { 00842 for (lp = ip->client->offered_leases; lp->next; 00843 lp = lp->next) 00844 ; /* nothing */ 00845 lp->next = lease; 00846 } 00847 } 00848 00849 /* If we're supposed to stop selecting before we've had time 00850 to wait for the ARPREPLY, add some delay to wait for 00851 the ARPREPLY. */ 00852 if (stop_selecting - cur_time < arp_timeout_needed) 00853 stop_selecting = cur_time + arp_timeout_needed; 00854 00855 /* If the selecting interval has expired, go immediately to 00856 state_selecting(). Otherwise, time out into 00857 state_selecting at the select interval. */ 00858 if (stop_selecting <= 0) 00859 state_selecting(ip); 00860 else { 00861 add_timeout(stop_selecting, state_selecting, ip); 00862 cancel_timeout(send_discover, ip); 00863 } 00864 } 00865 00866 /* Allocate a client_lease structure and initialize it from the parameters 00867 in the specified packet. */ 00868 00869 struct client_lease * 00870 packet_to_lease(struct packet *packet) 00871 { 00872 struct client_lease *lease; 00873 int i; 00874 00875 lease = malloc(sizeof(struct client_lease)); 00876 00877 if (!lease) { 00878 warning("dhcpoffer: no memory to record lease."); 00879 return (NULL); 00880 } 00881 00882 memset(lease, 0, sizeof(*lease)); 00883 00884 /* Copy the lease options. */ 00885 for (i = 0; i < 256; i++) { 00886 if (packet->options[i].len) { 00887 lease->options[i].data = 00888 malloc(packet->options[i].len + 1); 00889 if (!lease->options[i].data) { 00890 warning("dhcpoffer: no memory for option %d", i); 00891 free_client_lease(lease); 00892 return (NULL); 00893 } else { 00894 memcpy(lease->options[i].data, 00895 packet->options[i].data, 00896 packet->options[i].len); 00897 lease->options[i].len = 00898 packet->options[i].len; 00899 lease->options[i].data[lease->options[i].len] = 00900 0; 00901 } 00902 if (!check_option(lease,i)) { 00903 /* ignore a bogus lease offer */ 00904 warning("Invalid lease option - ignoring offer"); 00905 free_client_lease(lease); 00906 return (NULL); 00907 } 00908 } 00909 } 00910 00911 lease->address.len = sizeof(packet->raw->yiaddr); 00912 memcpy(lease->address.iabuf, &packet->raw->yiaddr, lease->address.len); 00913 #ifdef __REACTOS__ 00914 lease->serveraddress.len = sizeof(packet->raw->siaddr); 00915 memcpy(lease->serveraddress.iabuf, &packet->raw->siaddr, lease->address.len); 00916 #endif 00917 00918 /* If the server name was filled out, copy it. */ 00919 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || 00920 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 2)) && 00921 packet->raw->sname[0]) { 00922 lease->server_name = malloc(DHCP_SNAME_LEN + 1); 00923 if (!lease->server_name) { 00924 warning("dhcpoffer: no memory for server name."); 00925 free_client_lease(lease); 00926 return (NULL); 00927 } 00928 memcpy(lease->server_name, packet->raw->sname, DHCP_SNAME_LEN); 00929 lease->server_name[DHCP_SNAME_LEN]='\0'; 00930 if (!res_hnok(lease->server_name) ) { 00931 warning("Bogus server name %s", lease->server_name ); 00932 free_client_lease(lease); 00933 return (NULL); 00934 } 00935 00936 } 00937 00938 /* Ditto for the filename. */ 00939 if ((!packet->options[DHO_DHCP_OPTION_OVERLOAD].len || 00940 !(packet->options[DHO_DHCP_OPTION_OVERLOAD].data[0] & 1)) && 00941 packet->raw->file[0]) { 00942 /* Don't count on the NUL terminator. */ 00943 lease->filename = malloc(DHCP_FILE_LEN + 1); 00944 if (!lease->filename) { 00945 warning("dhcpoffer: no memory for filename."); 00946 free_client_lease(lease); 00947 return (NULL); 00948 } 00949 memcpy(lease->filename, packet->raw->file, DHCP_FILE_LEN); 00950 lease->filename[DHCP_FILE_LEN]='\0'; 00951 } 00952 return lease; 00953 } 00954 00955 void 00956 dhcpnak(struct packet *packet) 00957 { 00958 struct interface_info *ip = packet->interface; 00959 00960 /* If we're not receptive to an offer right now, or if the offer 00961 has an unrecognizable transaction id, then just drop it. */ 00962 if (packet->interface->client->xid != packet->raw->xid || 00963 (packet->interface->hw_address.hlen != packet->raw->hlen) || 00964 (memcmp(packet->interface->hw_address.haddr, 00965 packet->raw->chaddr, packet->raw->hlen))) 00966 return; 00967 00968 if (ip->client->state != S_REBOOTING && 00969 ip->client->state != S_REQUESTING && 00970 ip->client->state != S_RENEWING && 00971 ip->client->state != S_REBINDING) 00972 return; 00973 00974 note("DHCPNAK from %s", piaddr(packet->client_addr)); 00975 00976 if (!ip->client->active) { 00977 note("DHCPNAK with no active lease.\n"); 00978 return; 00979 } 00980 00981 free_client_lease(ip->client->active); 00982 ip->client->active = NULL; 00983 00984 /* Stop sending DHCPREQUEST packets... */ 00985 cancel_timeout(send_request, ip); 00986 00987 ip->client->state = S_INIT; 00988 state_init(ip); 00989 } 00990 00991 /* Send out a DHCPDISCOVER packet, and set a timeout to send out another 00992 one after the right interval has expired. If we don't get an offer by 00993 the time we reach the panic interval, call the panic function. */ 00994 00995 void 00996 send_discover(void *ipp) 00997 { 00998 struct interface_info *ip = ipp; 00999 int interval, increase = 1; 01000 time_t cur_time; 01001 01002 DH_DbgPrint(MID_TRACE,("Doing discover on interface %p\n",ip)); 01003 01004 time(&cur_time); 01005 01006 /* Figure out how long it's been since we started transmitting. */ 01007 interval = cur_time - ip->client->first_sending; 01008 01009 /* If we're past the panic timeout, call the script and tell it 01010 we haven't found anything for this interface yet. */ 01011 if (interval > ip->client->config->timeout) { 01012 state_panic(ip); 01013 ip->client->first_sending = cur_time; 01014 } 01015 01016 /* If we're selecting media, try the whole list before doing 01017 the exponential backoff, but if we've already received an 01018 offer, stop looping, because we obviously have it right. */ 01019 if (!ip->client->offered_leases && 01020 ip->client->config->media) { 01021 int fail = 0; 01022 01023 if (ip->client->medium) { 01024 ip->client->medium = ip->client->medium->next; 01025 increase = 0; 01026 } 01027 if (!ip->client->medium) { 01028 if (fail) 01029 error("No valid media types for %s!", ip->name); 01030 ip->client->medium = ip->client->config->media; 01031 increase = 1; 01032 } 01033 01034 note("Trying medium \"%s\" %d", ip->client->medium->string, 01035 increase); 01036 /* XXX Support other media types eventually */ 01037 } 01038 01039 /* 01040 * If we're supposed to increase the interval, do so. If it's 01041 * currently zero (i.e., we haven't sent any packets yet), set 01042 * it to one; otherwise, add to it a random number between zero 01043 * and two times itself. On average, this means that it will 01044 * double with every transmission. 01045 */ 01046 if (increase) { 01047 if (!ip->client->interval) 01048 ip->client->interval = 01049 ip->client->config->initial_interval; 01050 else { 01051 ip->client->interval += (rand() >> 2) % 01052 (2 * ip->client->interval); 01053 } 01054 01055 /* Don't backoff past cutoff. */ 01056 if (ip->client->interval > 01057 ip->client->config->backoff_cutoff) 01058 ip->client->interval = 01059 ((ip->client->config->backoff_cutoff / 2) 01060 + ((rand() >> 2) % 01061 ip->client->config->backoff_cutoff)); 01062 } else if (!ip->client->interval) 01063 ip->client->interval = 01064 ip->client->config->initial_interval; 01065 01066 /* If the backoff would take us to the panic timeout, just use that 01067 as the interval. */ 01068 if (cur_time + ip->client->interval > 01069 ip->client->first_sending + ip->client->config->timeout) 01070 ip->client->interval = 01071 (ip->client->first_sending + 01072 ip->client->config->timeout) - cur_time + 1; 01073 01074 /* Record the number of seconds since we started sending. */ 01075 if (interval < 65536) 01076 ip->client->packet.secs = htons(interval); 01077 else 01078 ip->client->packet.secs = htons(65535); 01079 ip->client->secs = ip->client->packet.secs; 01080 01081 note("DHCPDISCOVER on %s to %s port %d interval %ld", 01082 ip->name, inet_ntoa(sockaddr_broadcast.sin_addr), 01083 ntohs(sockaddr_broadcast.sin_port), (long int)ip->client->interval); 01084 01085 /* Send out a packet. */ 01086 (void)send_packet(ip, &ip->client->packet, ip->client->packet_length, 01087 inaddr_any, &sockaddr_broadcast, NULL); 01088 01089 DH_DbgPrint(MID_TRACE,("discover timeout: now %x -> then %x\n", 01090 cur_time, cur_time + ip->client->interval)); 01091 01092 add_timeout(cur_time + ip->client->interval, send_discover, ip); 01093 } 01094 01095 /* 01096 * state_panic gets called if we haven't received any offers in a preset 01097 * amount of time. When this happens, we try to use existing leases 01098 * that haven't yet expired, and failing that, we call the client script 01099 * and hope it can do something. 01100 */ 01101 void 01102 state_panic(void *ipp) 01103 { 01104 struct interface_info *ip = ipp; 01105 PDHCP_ADAPTER Adapter = AdapterFindInfo(ip); 01106 01107 note("No DHCPOFFERS received."); 01108 01109 if (!Adapter->NteContext) 01110 { 01111 /* Generate an automatic private address */ 01112 DbgPrint("DHCPCSVC: Failed to receive a response from a DHCP server. An automatic private address will be assigned.\n"); 01113 01114 /* FIXME: The address generation code sucks */ 01115 AddIPAddress(htonl(0xA9FE0000 | (rand() % 0xFFFF)), //169.254.X.X 01116 htonl(0xFFFF0000), //255.255.0.0 01117 Adapter->IfMib.dwIndex, 01118 &Adapter->NteContext, 01119 &Adapter->NteInstance); 01120 } 01121 } 01122 01123 void 01124 send_request(void *ipp) 01125 { 01126 struct interface_info *ip = ipp; 01127 struct sockaddr_in destination; 01128 struct in_addr from; 01129 int interval; 01130 time_t cur_time; 01131 01132 time(&cur_time); 01133 01134 /* Figure out how long it's been since we started transmitting. */ 01135 interval = cur_time - ip->client->first_sending; 01136 01137 /* If we're in the INIT-REBOOT or REQUESTING state and we're 01138 past the reboot timeout, go to INIT and see if we can 01139 DISCOVER an address... */ 01140 /* XXX In the INIT-REBOOT state, if we don't get an ACK, it 01141 means either that we're on a network with no DHCP server, 01142 or that our server is down. In the latter case, assuming 01143 that there is a backup DHCP server, DHCPDISCOVER will get 01144 us a new address, but we could also have successfully 01145 reused our old address. In the former case, we're hosed 01146 anyway. This is not a win-prone situation. */ 01147 if ((ip->client->state == S_REBOOTING || 01148 ip->client->state == S_REQUESTING) && 01149 interval > ip->client->config->reboot_timeout) { 01150 ip->client->state = S_INIT; 01151 cancel_timeout(send_request, ip); 01152 state_init(ip); 01153 return; 01154 } 01155 01156 /* If we're in the reboot state, make sure the media is set up 01157 correctly. */ 01158 if (ip->client->state == S_REBOOTING && 01159 !ip->client->medium && 01160 ip->client->active->medium ) { 01161 /* If the medium we chose won't fly, go to INIT state. */ 01162 /* XXX Nothing for now */ 01163 01164 /* Record the medium. */ 01165 ip->client->medium = ip->client->active->medium; 01166 } 01167 01168 /* If the lease has expired, relinquish the address and go back 01169 to the INIT state. */ 01170 if (ip->client->state != S_REQUESTING && 01171 cur_time > ip->client->active->expiry) { 01172 PDHCP_ADAPTER Adapter = AdapterFindInfo( ip ); 01173 /* Run the client script with the new parameters. */ 01174 /* No script actions necessary in the expiry case */ 01175 /* Now do a preinit on the interface so that we can 01176 discover a new address. */ 01177 01178 if( Adapter ) 01179 { 01180 DeleteIPAddress( Adapter->NteContext ); 01181 Adapter->NteContext = 0; 01182 } 01183 01184 ip->client->state = S_INIT; 01185 state_init(ip); 01186 return; 01187 } 01188 01189 /* Do the exponential backoff... */ 01190 if (!ip->client->interval) 01191 ip->client->interval = ip->client->config->initial_interval; 01192 else 01193 ip->client->interval += ((rand() >> 2) % 01194 (2 * ip->client->interval)); 01195 01196 /* Don't backoff past cutoff. */ 01197 if (ip->client->interval > 01198 ip->client->config->backoff_cutoff) 01199 ip->client->interval = 01200 ((ip->client->config->backoff_cutoff / 2) + 01201 ((rand() >> 2) % ip->client->interval)); 01202 01203 /* If the backoff would take us to the expiry time, just set the 01204 timeout to the expiry time. */ 01205 if (ip->client->state != S_REQUESTING && 01206 cur_time + ip->client->interval > 01207 ip->client->active->expiry) 01208 ip->client->interval = 01209 ip->client->active->expiry - cur_time + 1; 01210 01211 /* If the lease T2 time has elapsed, or if we're not yet bound, 01212 broadcast the DHCPREQUEST rather than unicasting. */ 01213 memset(&destination, 0, sizeof(destination)); 01214 if (ip->client->state == S_REQUESTING || 01215 ip->client->state == S_REBOOTING || 01216 cur_time > ip->client->active->rebind) 01217 destination.sin_addr.s_addr = INADDR_BROADCAST; 01218 else 01219 memcpy(&destination.sin_addr.s_addr, 01220 ip->client->destination.iabuf, 01221 sizeof(destination.sin_addr.s_addr)); 01222 destination.sin_port = htons(REMOTE_PORT); 01223 destination.sin_family = AF_INET; 01224 // destination.sin_len = sizeof(destination); 01225 01226 if (ip->client->state != S_REQUESTING) 01227 memcpy(&from, ip->client->active->address.iabuf, 01228 sizeof(from)); 01229 else 01230 from.s_addr = INADDR_ANY; 01231 01232 /* Record the number of seconds since we started sending. */ 01233 if (ip->client->state == S_REQUESTING) 01234 ip->client->packet.secs = ip->client->secs; 01235 else { 01236 if (interval < 65536) 01237 ip->client->packet.secs = htons(interval); 01238 else 01239 ip->client->packet.secs = htons(65535); 01240 } 01241 01242 note("DHCPREQUEST on %s to %s port %d", ip->name, 01243 inet_ntoa(destination.sin_addr), ntohs(destination.sin_port)); 01244 01245 /* Send out a packet. */ 01246 (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, 01247 from, &destination, NULL); 01248 01249 add_timeout(cur_time + ip->client->interval, send_request, ip); 01250 } 01251 01252 void 01253 send_decline(void *ipp) 01254 { 01255 struct interface_info *ip = ipp; 01256 01257 note("DHCPDECLINE on %s to %s port %d", ip->name, 01258 inet_ntoa(sockaddr_broadcast.sin_addr), 01259 ntohs(sockaddr_broadcast.sin_port)); 01260 01261 /* Send out a packet. */ 01262 (void) send_packet(ip, &ip->client->packet, ip->client->packet_length, 01263 inaddr_any, &sockaddr_broadcast, NULL); 01264 } 01265 01266 void 01267 make_discover(struct interface_info *ip, struct client_lease *lease) 01268 { 01269 unsigned char discover = DHCPDISCOVER; 01270 struct tree_cache *options[256]; 01271 struct tree_cache option_elements[256]; 01272 int i; 01273 ULONG foo = (ULONG) GetTickCount(); 01274 01275 memset(option_elements, 0, sizeof(option_elements)); 01276 memset(options, 0, sizeof(options)); 01277 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 01278 01279 /* Set DHCP_MESSAGE_TYPE to DHCPDISCOVER */ 01280 i = DHO_DHCP_MESSAGE_TYPE; 01281 options[i] = &option_elements[i]; 01282 options[i]->value = &discover; 01283 options[i]->len = sizeof(discover); 01284 options[i]->buf_size = sizeof(discover); 01285 options[i]->timeout = 0xFFFFFFFF; 01286 01287 /* Request the options we want */ 01288 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 01289 options[i] = &option_elements[i]; 01290 options[i]->value = ip->client->config->requested_options; 01291 options[i]->len = ip->client->config->requested_option_count; 01292 options[i]->buf_size = 01293 ip->client->config->requested_option_count; 01294 options[i]->timeout = 0xFFFFFFFF; 01295 01296 /* If we had an address, try to get it again. */ 01297 if (lease) { 01298 ip->client->requested_address = lease->address; 01299 i = DHO_DHCP_REQUESTED_ADDRESS; 01300 options[i] = &option_elements[i]; 01301 options[i]->value = lease->address.iabuf; 01302 options[i]->len = lease->address.len; 01303 options[i]->buf_size = lease->address.len; 01304 options[i]->timeout = 0xFFFFFFFF; 01305 } else 01306 ip->client->requested_address.len = 0; 01307 01308 /* Send any options requested in the config file. */ 01309 for (i = 0; i < 256; i++) 01310 if (!options[i] && 01311 ip->client->config->send_options[i].data) { 01312 options[i] = &option_elements[i]; 01313 options[i]->value = 01314 ip->client->config->send_options[i].data; 01315 options[i]->len = 01316 ip->client->config->send_options[i].len; 01317 options[i]->buf_size = 01318 ip->client->config->send_options[i].len; 01319 options[i]->timeout = 0xFFFFFFFF; 01320 } 01321 01322 /* Set up the option buffer... */ 01323 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 01324 options, 0, 0, 0, NULL, 0); 01325 if (ip->client->packet_length < BOOTP_MIN_LEN) 01326 ip->client->packet_length = BOOTP_MIN_LEN; 01327 01328 ip->client->packet.op = BOOTREQUEST; 01329 ip->client->packet.htype = ip->hw_address.htype; 01330 ip->client->packet.hlen = ip->hw_address.hlen; 01331 ip->client->packet.hops = 0; 01332 ip->client->packet.xid = RtlRandom(&foo); 01333 ip->client->packet.secs = 0; /* filled in by send_discover. */ 01334 ip->client->packet.flags = 0; 01335 01336 memset(&(ip->client->packet.ciaddr), 01337 0, sizeof(ip->client->packet.ciaddr)); 01338 memset(&(ip->client->packet.yiaddr), 01339 0, sizeof(ip->client->packet.yiaddr)); 01340 memset(&(ip->client->packet.siaddr), 01341 0, sizeof(ip->client->packet.siaddr)); 01342 memset(&(ip->client->packet.giaddr), 01343 0, sizeof(ip->client->packet.giaddr)); 01344 memcpy(ip->client->packet.chaddr, 01345 ip->hw_address.haddr, ip->hw_address.hlen); 01346 } 01347 01348 01349 void 01350 make_request(struct interface_info *ip, struct client_lease * lease) 01351 { 01352 unsigned char request = DHCPREQUEST; 01353 struct tree_cache *options[256]; 01354 struct tree_cache option_elements[256]; 01355 int i; 01356 01357 memset(options, 0, sizeof(options)); 01358 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 01359 01360 /* Set DHCP_MESSAGE_TYPE to DHCPREQUEST */ 01361 i = DHO_DHCP_MESSAGE_TYPE; 01362 options[i] = &option_elements[i]; 01363 options[i]->value = &request; 01364 options[i]->len = sizeof(request); 01365 options[i]->buf_size = sizeof(request); 01366 options[i]->timeout = 0xFFFFFFFF; 01367 01368 /* Request the options we want */ 01369 i = DHO_DHCP_PARAMETER_REQUEST_LIST; 01370 options[i] = &option_elements[i]; 01371 options[i]->value = ip->client->config->requested_options; 01372 options[i]->len = ip->client->config->requested_option_count; 01373 options[i]->buf_size = 01374 ip->client->config->requested_option_count; 01375 options[i]->timeout = 0xFFFFFFFF; 01376 01377 /* If we are requesting an address that hasn't yet been assigned 01378 to us, use the DHCP Requested Address option. */ 01379 if (ip->client->state == S_REQUESTING) { 01380 /* Send back the server identifier... */ 01381 i = DHO_DHCP_SERVER_IDENTIFIER; 01382 options[i] = &option_elements[i]; 01383 options[i]->value = lease->options[i].data; 01384 options[i]->len = lease->options[i].len; 01385 options[i]->buf_size = lease->options[i].len; 01386 options[i]->timeout = 0xFFFFFFFF; 01387 } 01388 if (ip->client->state == S_REQUESTING || 01389 ip->client->state == S_REBOOTING) { 01390 ip->client->requested_address = lease->address; 01391 i = DHO_DHCP_REQUESTED_ADDRESS; 01392 options[i] = &option_elements[i]; 01393 options[i]->value = lease->address.iabuf; 01394 options[i]->len = lease->address.len; 01395 options[i]->buf_size = lease->address.len; 01396 options[i]->timeout = 0xFFFFFFFF; 01397 } else 01398 ip->client->requested_address.len = 0; 01399 01400 /* Send any options requested in the config file. */ 01401 for (i = 0; i < 256; i++) 01402 if (!options[i] && 01403 ip->client->config->send_options[i].data) { 01404 options[i] = &option_elements[i]; 01405 options[i]->value = 01406 ip->client->config->send_options[i].data; 01407 options[i]->len = 01408 ip->client->config->send_options[i].len; 01409 options[i]->buf_size = 01410 ip->client->config->send_options[i].len; 01411 options[i]->timeout = 0xFFFFFFFF; 01412 } 01413 01414 /* Set up the option buffer... */ 01415 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 01416 options, 0, 0, 0, NULL, 0); 01417 if (ip->client->packet_length < BOOTP_MIN_LEN) 01418 ip->client->packet_length = BOOTP_MIN_LEN; 01419 01420 ip->client->packet.op = BOOTREQUEST; 01421 ip->client->packet.htype = ip->hw_address.htype; 01422 ip->client->packet.hlen = ip->hw_address.hlen; 01423 ip->client->packet.hops = 0; 01424 ip->client->packet.xid = ip->client->xid; 01425 ip->client->packet.secs = 0; /* Filled in by send_request. */ 01426 01427 /* If we own the address we're requesting, put it in ciaddr; 01428 otherwise set ciaddr to zero. */ 01429 if (ip->client->state == S_BOUND || 01430 ip->client->state == S_RENEWING || 01431 ip->client->state == S_REBINDING) { 01432 memcpy(&ip->client->packet.ciaddr, 01433 lease->address.iabuf, lease->address.len); 01434 ip->client->packet.flags = 0; 01435 } else { 01436 memset(&ip->client->packet.ciaddr, 0, 01437 sizeof(ip->client->packet.ciaddr)); 01438 ip->client->packet.flags = 0; 01439 } 01440 01441 memset(&ip->client->packet.yiaddr, 0, 01442 sizeof(ip->client->packet.yiaddr)); 01443 memset(&ip->client->packet.siaddr, 0, 01444 sizeof(ip->client->packet.siaddr)); 01445 memset(&ip->client->packet.giaddr, 0, 01446 sizeof(ip->client->packet.giaddr)); 01447 memcpy(ip->client->packet.chaddr, 01448 ip->hw_address.haddr, ip->hw_address.hlen); 01449 } 01450 01451 void 01452 make_decline(struct interface_info *ip, struct client_lease *lease) 01453 { 01454 struct tree_cache *options[256], message_type_tree; 01455 struct tree_cache requested_address_tree; 01456 struct tree_cache server_id_tree, client_id_tree; 01457 unsigned char decline = DHCPDECLINE; 01458 int i; 01459 01460 memset(options, 0, sizeof(options)); 01461 memset(&ip->client->packet, 0, sizeof(ip->client->packet)); 01462 01463 /* Set DHCP_MESSAGE_TYPE to DHCPDECLINE */ 01464 i = DHO_DHCP_MESSAGE_TYPE; 01465 options[i] = &message_type_tree; 01466 options[i]->value = &decline; 01467 options[i]->len = sizeof(decline); 01468 options[i]->buf_size = sizeof(decline); 01469 options[i]->timeout = 0xFFFFFFFF; 01470 01471 /* Send back the server identifier... */ 01472 i = DHO_DHCP_SERVER_IDENTIFIER; 01473 options[i] = &server_id_tree; 01474 options[i]->value = lease->options[i].data; 01475 options[i]->len = lease->options[i].len; 01476 options[i]->buf_size = lease->options[i].len; 01477 options[i]->timeout = 0xFFFFFFFF; 01478 01479 /* Send back the address we're declining. */ 01480 i = DHO_DHCP_REQUESTED_ADDRESS; 01481 options[i] = &requested_address_tree; 01482 options[i]->value = lease->address.iabuf; 01483 options[i]->len = lease->address.len; 01484 options[i]->buf_size = lease->address.len; 01485 options[i]->timeout = 0xFFFFFFFF; 01486 01487 /* Send the uid if the user supplied one. */ 01488 i = DHO_DHCP_CLIENT_IDENTIFIER; 01489 if (ip->client->config->send_options[i].len) { 01490 options[i] = &client_id_tree; 01491 options[i]->value = ip->client->config->send_options[i].data; 01492 options[i]->len = ip->client->config->send_options[i].len; 01493 options[i]->buf_size = ip->client->config->send_options[i].len; 01494 options[i]->timeout = 0xFFFFFFFF; 01495 } 01496 01497 01498 /* Set up the option buffer... */ 01499 ip->client->packet_length = cons_options(NULL, &ip->client->packet, 0, 01500 options, 0, 0, 0, NULL, 0); 01501 if (ip->client->packet_length < BOOTP_MIN_LEN) 01502 ip->client->packet_length = BOOTP_MIN_LEN; 01503 01504 ip->client->packet.op = BOOTREQUEST; 01505 ip->client->packet.htype = ip->hw_address.htype; 01506 ip->client->packet.hlen = ip->hw_address.hlen; 01507 ip->client->packet.hops = 0; 01508 ip->client->packet.xid = ip->client->xid; 01509 ip->client->packet.secs = 0; /* Filled in by send_request. */ 01510 ip->client->packet.flags = 0; 01511 01512 /* ciaddr must always be zero. */ 01513 memset(&ip->client->packet.ciaddr, 0, 01514 sizeof(ip->client->packet.ciaddr)); 01515 memset(&ip->client->packet.yiaddr, 0, 01516 sizeof(ip->client->packet.yiaddr)); 01517 memset(&ip->client->packet.siaddr, 0, 01518 sizeof(ip->client->packet.siaddr)); 01519 memset(&ip->client->packet.giaddr, 0, 01520 sizeof(ip->client->packet.giaddr)); 01521 memcpy(ip->client->packet.chaddr, 01522 ip->hw_address.haddr, ip->hw_address.hlen); 01523 } 01524 01525 void 01526 free_client_lease(struct client_lease *lease) 01527 { 01528 int i; 01529 01530 if (lease->server_name) 01531 free(lease->server_name); 01532 if (lease->filename) 01533 free(lease->filename); 01534 for (i = 0; i < 256; i++) { 01535 if (lease->options[i].len) 01536 free(lease->options[i].data); 01537 } 01538 free(lease); 01539 } 01540 01541 FILE *leaseFile; 01542 01543 void 01544 rewrite_client_leases(struct interface_info *ifi) 01545 { 01546 struct client_lease *lp; 01547 01548 if (!leaseFile) { 01549 leaseFile = fopen(path_dhclient_db, "w"); 01550 if (!leaseFile) 01551 error("can't create %s", path_dhclient_db); 01552 } else { 01553 fflush(leaseFile); 01554 rewind(leaseFile); 01555 } 01556 01557 for (lp = ifi->client->leases; lp; lp = lp->next) 01558 write_client_lease(ifi, lp, 1); 01559 if (ifi->client->active) 01560 write_client_lease(ifi, ifi->client->active, 1); 01561 01562 fflush(leaseFile); 01563 } 01564 01565 void 01566 write_client_lease(struct interface_info *ip, struct client_lease *lease, 01567 int rewrite) 01568 { 01569 static int leases_written; 01570 struct tm *t; 01571 int i; 01572 01573 if (!rewrite) { 01574 if (leases_written++ > 20) { 01575 rewrite_client_leases(ip); 01576 leases_written = 0; 01577 } 01578 } 01579 01580 /* If the lease came from the config file, we don't need to stash 01581 a copy in the lease database. */ 01582 if (lease->is_static) 01583 return; 01584 01585 if (!leaseFile) { /* XXX */ 01586 leaseFile = fopen(path_dhclient_db, "w"); 01587 if (!leaseFile) { 01588 error("can't create %s", path_dhclient_db); 01589 return; 01590 } 01591 } 01592 01593 fprintf(leaseFile, "lease {\n"); 01594 if (lease->is_bootp) 01595 fprintf(leaseFile, " bootp;\n"); 01596 fprintf(leaseFile, " interface \"%s\";\n", ip->name); 01597 fprintf(leaseFile, " fixed-address %s;\n", piaddr(lease->address)); 01598 if (lease->filename) 01599 fprintf(leaseFile, " filename \"%s\";\n", lease->filename); 01600 if (lease->server_name) 01601 fprintf(leaseFile, " server-name \"%s\";\n", 01602 lease->server_name); 01603 if (lease->medium) 01604 fprintf(leaseFile, " medium \"%s\";\n", lease->medium->string); 01605 for (i = 0; i < 256; i++) 01606 if (lease->options[i].len) 01607 fprintf(leaseFile, " option %s %s;\n", 01608 dhcp_options[i].name, 01609 pretty_print_option(i, lease->options[i].data, 01610 lease->options[i].len, 1, 1)); 01611 01612 t = gmtime(&lease->renewal); 01613 if (t) 01614 fprintf(leaseFile, " renew %d %d/%d/%d %02d:%02d:%02d;\n", 01615 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 01616 t->tm_hour, t->tm_min, t->tm_sec); 01617 t = gmtime(&lease->rebind); 01618 if (t) 01619 fprintf(leaseFile, " rebind %d %d/%d/%d %02d:%02d:%02d;\n", 01620 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 01621 t->tm_hour, t->tm_min, t->tm_sec); 01622 t = gmtime(&lease->expiry); 01623 if (t) 01624 fprintf(leaseFile, " expire %d %d/%d/%d %02d:%02d:%02d;\n", 01625 t->tm_wday, t->tm_year + 1900, t->tm_mon + 1, t->tm_mday, 01626 t->tm_hour, t->tm_min, t->tm_sec); 01627 fprintf(leaseFile, "}\n"); 01628 fflush(leaseFile); 01629 } 01630 01631 void 01632 priv_script_init(struct interface_info *ip, char *reason, char *medium) 01633 { 01634 if (ip) { 01635 // XXX Do we need to do anything? 01636 } 01637 } 01638 01639 void 01640 priv_script_write_params(struct interface_info *ip, char *prefix, struct client_lease *lease) 01641 { 01642 u_int8_t dbuf[1500]; 01643 int i, len = 0; 01644 01645 #if 0 01646 script_set_env(ip->client, prefix, "ip_address", 01647 piaddr(lease->address)); 01648 #endif 01649 01650 if (lease->options[DHO_SUBNET_MASK].len && 01651 (lease->options[DHO_SUBNET_MASK].len < 01652 sizeof(lease->address.iabuf))) { 01653 struct iaddr netmask, subnet, broadcast; 01654 01655 memcpy(netmask.iabuf, lease->options[DHO_SUBNET_MASK].data, 01656 lease->options[DHO_SUBNET_MASK].len); 01657 netmask.len = lease->options[DHO_SUBNET_MASK].len; 01658 01659 subnet = subnet_number(lease->address, netmask); 01660 if (subnet.len) { 01661 #if 0 01662 script_set_env(ip->client, prefix, "network_number", 01663 piaddr(subnet)); 01664 #endif 01665 if (!lease->options[DHO_BROADCAST_ADDRESS].len) { 01666 broadcast = broadcast_addr(subnet, netmask); 01667 if (broadcast.len) 01668 #if 0 01669 script_set_env(ip->client, prefix, 01670 "broadcast_address", 01671 piaddr(broadcast)); 01672 #else 01673 ; 01674 #endif 01675 } 01676 } 01677 } 01678 01679 #if 0 01680 if (lease->filename) 01681 script_set_env(ip->client, prefix, "filename", lease->filename); 01682 if (lease->server_name) 01683 script_set_env(ip->client, prefix, "server_name", 01684 lease->server_name); 01685 #endif 01686 01687 for (i = 0; i < 256; i++) { 01688 u_int8_t *dp = NULL; 01689 01690 if (ip->client->config->defaults[i].len) { 01691 if (lease->options[i].len) { 01692 switch ( 01693 ip->client->config->default_actions[i]) { 01694 case ACTION_DEFAULT: 01695 dp = lease->options[i].data; 01696 len = lease->options[i].len; 01697 break; 01698 case ACTION_SUPERSEDE: 01699 supersede: 01700 dp = ip->client-> 01701 config->defaults[i].data; 01702 len = ip->client-> 01703 config->defaults[i].len; 01704 break; 01705 case ACTION_PREPEND: 01706 len = ip->client-> 01707 config->defaults[i].len + 01708 lease->options[i].len; 01709 if (len >= sizeof(dbuf)) { 01710 warning("no space to %s %s", 01711 "prepend option", 01712 dhcp_options[i].name); 01713 goto supersede; 01714 } 01715 dp = dbuf; 01716 memcpy(dp, 01717 ip->client-> 01718 config->defaults[i].data, 01719 ip->client-> 01720 config->defaults[i].len); 01721 memcpy(dp + ip->client-> 01722 config->defaults[i].len, 01723 lease->options[i].data, 01724 lease->options[i].len); 01725 dp[len] = '\0'; 01726 break; 01727 case ACTION_APPEND: 01728 len = ip->client-> 01729 config->defaults[i].len + 01730 lease->options[i].len + 1; 01731 if (len > sizeof(dbuf)) { 01732 warning("no space to %s %s", 01733 "append option", 01734 dhcp_options[i].name); 01735 goto supersede; 01736 } 01737 dp = dbuf; 01738 memcpy(dp, 01739 lease->options[i].data, 01740 lease->options[i].len); 01741 memcpy(dp + lease->options[i].len, 01742 ip->client-> 01743 config->defaults[i].data, 01744 ip->client-> 01745 config->defaults[i].len); 01746 dp[len-1] = '\0'; 01747 } 01748 } else { 01749 dp = ip->client-> 01750 config->defaults[i].data; 01751 len = ip->client-> 01752 config->defaults[i].len; 01753 } 01754 } else if (lease->options[i].len) { 01755 len = lease->options[i].len; 01756 dp = lease->options[i].data; 01757 } else { 01758 len = 0; 01759 } 01760 #if 0 01761 if (len) { 01762 char name[256]; 01763 01764 if (dhcp_option_ev_name(name, sizeof(name), 01765 &dhcp_options[i])) 01766 script_set_env(ip->client, prefix, name, 01767 pretty_print_option(i, dp, len, 0, 0)); 01768 } 01769 #endif 01770 } 01771 #if 0 01772 snprintf(tbuf, sizeof(tbuf), "%d", (int)lease->expiry); 01773 script_set_env(ip->client, prefix, "expiry", tbuf); 01774 #endif 01775 } 01776 01777 int 01778 dhcp_option_ev_name(char *buf, size_t buflen, struct dhcp_option *option) 01779 { 01780 int i; 01781 01782 for (i = 0; option->name[i]; i++) { 01783 if (i + 1 == buflen) 01784 return 0; 01785 if (option->name[i] == '-') 01786 buf[i] = '_'; 01787 else 01788 buf[i] = option->name[i]; 01789 } 01790 01791 buf[i] = 0; 01792 return 1; 01793 } 01794 01795 #if 0 01796 void 01797 go_daemon(void) 01798 { 01799 static int state = 0; 01800 01801 if (no_daemon || state) 01802 return; 01803 01804 state = 1; 01805 01806 /* Stop logging to stderr... */ 01807 log_perror = 0; 01808 01809 if (daemon(1, 0) == -1) 01810 error("daemon"); 01811 01812 /* we are chrooted, daemon(3) fails to open /dev/null */ 01813 if (nullfd != -1) { 01814 dup2(nullfd, STDIN_FILENO); 01815 dup2(nullfd, STDOUT_FILENO); 01816 dup2(nullfd, STDERR_FILENO); 01817 close(nullfd); 01818 nullfd = -1; 01819 } 01820 } 01821 #endif 01822 01823 int 01824 check_option(struct client_lease *l, int option) 01825 { 01826 char *opbuf; 01827 char *sbuf; 01828 01829 /* we use this, since this is what gets passed to dhclient-script */ 01830 01831 opbuf = pretty_print_option(option, l->options[option].data, 01832 l->options[option].len, 0, 0); 01833 01834 sbuf = option_as_string(option, l->options[option].data, 01835 l->options[option].len); 01836 01837 switch (option) { 01838 case DHO_SUBNET_MASK: 01839 case DHO_TIME_SERVERS: 01840 case DHO_NAME_SERVERS: 01841 case DHO_ROUTERS: 01842 case DHO_DOMAIN_NAME_SERVERS: 01843 case DHO_LOG_SERVERS: 01844 case DHO_COOKIE_SERVERS: 01845 case DHO_LPR_SERVERS: 01846 case DHO_IMPRESS_SERVERS: 01847 case DHO_RESOURCE_LOCATION_SERVERS: 01848 case DHO_SWAP_SERVER: 01849 case DHO_BROADCAST_ADDRESS: 01850 case DHO_NIS_SERVERS: 01851 case DHO_NTP_SERVERS: 01852 case DHO_NETBIOS_NAME_SERVERS: 01853 case DHO_NETBIOS_DD_SERVER: 01854 case DHO_FONT_SERVERS: 01855 case DHO_DHCP_SERVER_IDENTIFIER: 01856 if (!ipv4addrs(opbuf)) { 01857 warning("Invalid IP address in option(%d): %s", option, opbuf); 01858 return (0); 01859 } 01860 return (1) ; 01861 case DHO_HOST_NAME: 01862 case DHO_DOMAIN_NAME: 01863 case DHO_NIS_DOMAIN: 01864 if (!res_hnok(sbuf)) 01865 warning("Bogus Host Name option %d: %s (%s)", option, 01866 sbuf, opbuf); 01867 return (1); 01868 case DHO_PAD: 01869 case DHO_TIME_OFFSET: 01870 case DHO_BOOT_SIZE: 01871 case DHO_MERIT_DUMP: 01872 case DHO_ROOT_PATH: 01873 case DHO_EXTENSIONS_PATH: 01874 case DHO_IP_FORWARDING: 01875 case DHO_NON_LOCAL_SOURCE_ROUTING: 01876 case DHO_POLICY_FILTER: 01877 case DHO_MAX_DGRAM_REASSEMBLY: 01878 case DHO_DEFAULT_IP_TTL: 01879 case DHO_PATH_MTU_AGING_TIMEOUT: 01880 case DHO_PATH_MTU_PLATEAU_TABLE: 01881 case DHO_INTERFACE_MTU: 01882 case DHO_ALL_SUBNETS_LOCAL: 01883 case DHO_PERFORM_MASK_DISCOVERY: 01884 case DHO_MASK_SUPPLIER: 01885 case DHO_ROUTER_DISCOVERY: 01886 case DHO_ROUTER_SOLICITATION_ADDRESS: 01887 case DHO_STATIC_ROUTES: 01888 case DHO_TRAILER_ENCAPSULATION: 01889 case DHO_ARP_CACHE_TIMEOUT: 01890 case DHO_IEEE802_3_ENCAPSULATION: 01891 case DHO_DEFAULT_TCP_TTL: 01892 case DHO_TCP_KEEPALIVE_INTERVAL: 01893 case DHO_TCP_KEEPALIVE_GARBAGE: 01894 case DHO_VENDOR_ENCAPSULATED_OPTIONS: 01895 case DHO_NETBIOS_NODE_TYPE: 01896 case DHO_NETBIOS_SCOPE: 01897 case DHO_X_DISPLAY_MANAGER: 01898 case DHO_DHCP_REQUESTED_ADDRESS: 01899 case DHO_DHCP_LEASE_TIME: 01900 case DHO_DHCP_OPTION_OVERLOAD: 01901 case DHO_DHCP_MESSAGE_TYPE: 01902 case DHO_DHCP_PARAMETER_REQUEST_LIST: 01903 case DHO_DHCP_MESSAGE: 01904 case DHO_DHCP_MAX_MESSAGE_SIZE: 01905 case DHO_DHCP_RENEWAL_TIME: 01906 case DHO_DHCP_REBINDING_TIME: 01907 case DHO_DHCP_CLASS_IDENTIFIER: 01908 case DHO_DHCP_CLIENT_IDENTIFIER: 01909 case DHO_DHCP_USER_CLASS_ID: 01910 case DHO_END: 01911 return (1); 01912 default: 01913 warning("unknown dhcp option value 0x%x", option); 01914 return (unknown_ok); 01915 } 01916 } 01917 01918 int 01919 res_hnok(const char *dn) 01920 { 01921 int pch = PERIOD, ch = *dn++; 01922 01923 while (ch != '\0') { 01924 int nch = *dn++; 01925 01926 if (periodchar(ch)) { 01927 ; 01928 } else if (periodchar(pch)) { 01929 if (!borderchar(ch)) 01930 return (0); 01931 } else if (periodchar(nch) || nch == '\0') { 01932 if (!borderchar(ch)) 01933 return (0); 01934 } else { 01935 if (!middlechar(ch)) 01936 return (0); 01937 } 01938 pch = ch, ch = nch; 01939 } 01940 return (1); 01941 } 01942 01943 /* Does buf consist only of dotted decimal ipv4 addrs? 01944 * return how many if so, 01945 * otherwise, return 0 01946 */ 01947 int 01948 ipv4addrs(char * buf) 01949 { 01950 char *tmp; 01951 struct in_addr jnk; 01952 int i = 0; 01953 01954 note("Input: %s", buf); 01955 01956 do { 01957 tmp = strtok(buf, " "); 01958 note("got %s", tmp); 01959 if( tmp && inet_aton(tmp, &jnk) ) i++; 01960 buf = NULL; 01961 } while( tmp ); 01962 01963 return (i); 01964 } 01965 01966 01967 char * 01968 option_as_string(unsigned int code, unsigned char *data, int len) 01969 { 01970 static char optbuf[32768]; /* XXX */ 01971 char *op = optbuf; 01972 int opleft = sizeof(optbuf); 01973 unsigned char *dp = data; 01974 01975 if (code > 255) 01976 error("option_as_string: bad code %d", code); 01977 01978 for (; dp < data + len; dp++) { 01979 if (!isascii(*dp) || !isprint(*dp)) { 01980 if (dp + 1 != data + len || *dp != 0) { 01981 _snprintf(op, opleft, "\\%03o", *dp); 01982 op += 4; 01983 opleft -= 4; 01984 } 01985 } else if (*dp == '"' || *dp == '\'' || *dp == '$' || 01986 *dp == '`' || *dp == '\\') { 01987 *op++ = '\\'; 01988 *op++ = *dp; 01989 opleft -= 2; 01990 } else { 01991 *op++ = *dp; 01992 opleft--; 01993 } 01994 } 01995 if (opleft < 1) 01996 goto toobig; 01997 *op = 0; 01998 return optbuf; 01999 toobig: 02000 warning("dhcp option too large"); 02001 return "<error>"; 02002 } 02003 Generated on Sun May 27 2012 04:23:27 for ReactOS by
1.7.6.1
|