ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

dispatch.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 doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.