Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygendispatch.c
Go to the documentation of this file.
00001 /* $OpenBSD: dispatch.c,v 1.31 2004/09/21 04:07:03 david 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 00042 #include "rosdhcp.h" 00043 00044 //#include <sys/ioctl.h> 00045 00046 //#include <net/if_media.h> 00047 //#include <ifaddrs.h> 00048 //#include <poll.h> 00049 00050 extern SOCKET DhcpSocket; 00051 HANDLE AdapterStateChangedEvent = NULL; 00052 struct protocol *protocols = NULL; 00053 struct timeout *timeouts = NULL; 00054 static struct timeout *free_timeouts = NULL; 00055 void (*bootp_packet_handler)(struct interface_info *, 00056 struct dhcp_packet *, int, unsigned int, 00057 struct iaddr, struct hardware *); 00058 00059 /* 00060 * Wait for packets to come in using poll(). When a packet comes in, 00061 * call receive_packet to receive the packet and possibly strip hardware 00062 * addressing information from it, and then call through the 00063 * bootp_packet_handler hook to try to do something with it. 00064 */ 00065 void 00066 dispatch(void) 00067 { 00068 int count, to_msec; 00069 struct protocol *l; 00070 time_t howlong, cur_time; 00071 HANDLE Events[2]; 00072 int EventCount = 1; 00073 00074 Events[0] = StartAdapterDiscovery(); 00075 if (!Events[0]) 00076 return; 00077 AdapterStateChangedEvent = Events[0]; 00078 00079 Events[1] = WSA_INVALID_EVENT; 00080 00081 ApiLock(); 00082 00083 do { 00084 /* 00085 * Call any expired timeouts, and then if there's still 00086 * a timeout registered, time out the select call then. 00087 */ 00088 time(&cur_time); 00089 00090 if (timeouts) 00091 { 00092 struct timeout *t; 00093 00094 if (timeouts->when <= cur_time) { 00095 t = timeouts; 00096 timeouts = timeouts->next; 00097 (*(t->func))(t->what); 00098 t->next = free_timeouts; 00099 free_timeouts = t; 00100 continue; 00101 } 00102 00103 /* 00104 * Figure timeout in milliseconds, and check for 00105 * potential overflow, so we can cram into an 00106 * int for poll, while not polling with a 00107 * negative timeout and blocking indefinitely. 00108 */ 00109 howlong = timeouts->when - cur_time; 00110 if (howlong > INT_MAX / 1000) 00111 howlong = INT_MAX / 1000; 00112 to_msec = howlong * 1000; 00113 } 00114 else 00115 { 00116 to_msec = INFINITE; 00117 } 00118 00119 if (Events[1] == WSA_INVALID_EVENT && DhcpSocket != INVALID_SOCKET) 00120 { 00121 Events[1] = WSACreateEvent(); 00122 if (Events[1] != WSA_INVALID_EVENT) 00123 { 00124 count = WSAEventSelect(DhcpSocket, Events[1], FD_READ | FD_CLOSE); 00125 if (count != NO_ERROR) 00126 { 00127 WSACloseEvent(Events[1]); 00128 Events[1] = WSA_INVALID_EVENT; 00129 } 00130 else 00131 { 00132 EventCount = 2; 00133 } 00134 } 00135 } 00136 else if (Events[1] != WSA_INVALID_EVENT && DhcpSocket == INVALID_SOCKET) 00137 { 00138 WSACloseEvent(Events[1]); 00139 Events[1] = WSA_INVALID_EVENT; 00140 00141 EventCount = 1; 00142 } 00143 00144 ApiUnlock(); 00145 count = WaitForMultipleObjects(EventCount, 00146 Events, 00147 FALSE, 00148 to_msec); 00149 ApiLock(); 00150 if (count == WAIT_OBJECT_0) 00151 { 00152 /* Adapter state change */ 00153 continue; 00154 } 00155 else if (count == WAIT_OBJECT_0 + 1) 00156 { 00157 /* Packet received */ 00158 00159 /* WSA events are manual reset events */ 00160 WSAResetEvent(Events[1]); 00161 } 00162 else 00163 { 00164 /* Timeout */ 00165 continue; 00166 } 00167 00168 for (l = protocols; l; l = l->next) { 00169 struct interface_info *ip; 00170 ip = l->local; 00171 if (ip && (l->handler != got_one || 00172 !ip->dead)) { 00173 DH_DbgPrint(MID_TRACE,("Handling %x\n", l)); 00174 (*(l->handler))(l); 00175 } 00176 } 00177 } while (1); 00178 00179 AdapterStateChangedEvent = NULL; 00180 CloseHandle(Events[0]); 00181 WSACloseEvent(Events[1]); 00182 00183 ApiUnlock(); 00184 } 00185 00186 void 00187 got_one(struct protocol *l) 00188 { 00189 struct sockaddr_in from; 00190 struct hardware hfrom; 00191 struct iaddr ifrom; 00192 ssize_t result; 00193 union { 00194 /* 00195 * Packet input buffer. Must be as large as largest 00196 * possible MTU. 00197 */ 00198 unsigned char packbuf[4095]; 00199 struct dhcp_packet packet; 00200 } u; 00201 struct interface_info *ip = l->local; 00202 PDHCP_ADAPTER adapter; 00203 00204 if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from, 00205 &hfrom)) == -1) { 00206 warning("receive_packet failed on %s: %d", ip->name, 00207 WSAGetLastError()); 00208 ip->errors++; 00209 if (ip->errors > 20) { 00210 /* our interface has gone away. */ 00211 warning("Interface %s no longer appears valid.", 00212 ip->name); 00213 ip->dead = 1; 00214 closesocket(l->fd); 00215 remove_protocol(l); 00216 adapter = AdapterFindInfo(ip); 00217 if (adapter) { 00218 RemoveEntryList(&adapter->ListEntry); 00219 free(adapter); 00220 } 00221 } 00222 return; 00223 } 00224 if (result == 0) 00225 return; 00226 00227 if (bootp_packet_handler) { 00228 ifrom.len = 4; 00229 memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len); 00230 00231 00232 adapter = AdapterFindByHardwareAddress(u.packet.chaddr, 00233 u.packet.hlen); 00234 00235 if (!adapter) { 00236 warning("Discarding packet with a non-matching target physical address\n"); 00237 return; 00238 } 00239 00240 (*bootp_packet_handler)(&adapter->DhclientInfo, &u.packet, result, 00241 from.sin_port, ifrom, &hfrom); 00242 } 00243 } 00244 00245 void 00246 add_timeout(time_t when, void (*where)(void *), void *what) 00247 { 00248 struct timeout *t, *q; 00249 00250 DH_DbgPrint(MID_TRACE,("Adding timeout %x %p %x\n", when, where, what)); 00251 /* See if this timeout supersedes an existing timeout. */ 00252 t = NULL; 00253 for (q = timeouts; q; q = q->next) { 00254 if (q->func == where && q->what == what) { 00255 if (t) 00256 t->next = q->next; 00257 else 00258 timeouts = q->next; 00259 break; 00260 } 00261 t = q; 00262 } 00263 00264 /* If we didn't supersede a timeout, allocate a timeout 00265 structure now. */ 00266 if (!q) { 00267 if (free_timeouts) { 00268 q = free_timeouts; 00269 free_timeouts = q->next; 00270 q->func = where; 00271 q->what = what; 00272 } else { 00273 q = malloc(sizeof(struct timeout)); 00274 if (!q) { 00275 error("Can't allocate timeout structure!"); 00276 return; 00277 } 00278 q->func = where; 00279 q->what = what; 00280 } 00281 } 00282 00283 q->when = when; 00284 00285 /* Now sort this timeout into the timeout list. */ 00286 00287 /* Beginning of list? */ 00288 if (!timeouts || timeouts->when > q->when) { 00289 q->next = timeouts; 00290 timeouts = q; 00291 return; 00292 } 00293 00294 /* Middle of list? */ 00295 for (t = timeouts; t->next; t = t->next) { 00296 if (t->next->when > q->when) { 00297 q->next = t->next; 00298 t->next = q; 00299 return; 00300 } 00301 } 00302 00303 /* End of list. */ 00304 t->next = q; 00305 q->next = NULL; 00306 } 00307 00308 void 00309 cancel_timeout(void (*where)(void *), void *what) 00310 { 00311 struct timeout *t, *q; 00312 00313 /* Look for this timeout on the list, and unlink it if we find it. */ 00314 t = NULL; 00315 for (q = timeouts; q; q = q->next) { 00316 if (q->func == where && q->what == what) { 00317 if (t) 00318 t->next = q->next; 00319 else 00320 timeouts = q->next; 00321 break; 00322 } 00323 t = q; 00324 } 00325 00326 /* If we found the timeout, put it on the free list. */ 00327 if (q) { 00328 q->next = free_timeouts; 00329 free_timeouts = q; 00330 } 00331 } 00332 00333 /* Add a protocol to the list of protocols... */ 00334 void 00335 add_protocol(char *name, int fd, void (*handler)(struct protocol *), 00336 void *local) 00337 { 00338 struct protocol *p; 00339 00340 p = malloc(sizeof(*p)); 00341 if (!p) 00342 error("can't allocate protocol struct for %s", name); 00343 00344 p->fd = fd; 00345 p->handler = handler; 00346 p->local = local; 00347 p->next = protocols; 00348 protocols = p; 00349 } 00350 00351 void 00352 remove_protocol(struct protocol *proto) 00353 { 00354 struct protocol *p, *next, *prev; 00355 struct interface_info *ip = proto->local; 00356 struct timeout *t, *q, *u; 00357 00358 t = NULL; 00359 q = timeouts; 00360 while (q != NULL) 00361 { 00362 /* Remove all timeouts for this protocol */ 00363 if (q->what == ip) 00364 { 00365 /* Unlink the timeout from previous */ 00366 if (t) 00367 t->next = q->next; 00368 else 00369 timeouts = q->next; 00370 00371 /* Advance to the next timeout */ 00372 u = q->next; 00373 00374 /* Add it to the free list */ 00375 q->next = free_timeouts; 00376 free_timeouts = q; 00377 } 00378 else 00379 { 00380 /* Advance to the next timeout */ 00381 u = q->next; 00382 00383 /* Update the previous pointer */ 00384 t = q; 00385 } 00386 00387 /* Advance */ 00388 q = u; 00389 } 00390 00391 prev = NULL; 00392 for (p = protocols; p; p = next) { 00393 next = p->next; 00394 if (p == proto) { 00395 if (prev) 00396 prev->next = p->next; 00397 else 00398 protocols = p->next; 00399 free(p); 00400 } 00401 } 00402 } 00403 00404 struct protocol * 00405 find_protocol_by_adapter(struct interface_info *info) 00406 { 00407 struct protocol *p; 00408 00409 for( p = protocols; p; p = p->next ) { 00410 if( p->local == (void *)info ) return p; 00411 } 00412 00413 return NULL; 00414 } 00415 00416 int 00417 interface_link_status(char *ifname) 00418 { 00419 return (1); 00420 } Generated on Sat May 26 2012 04:19:00 for ReactOS by
1.7.6.1
|