ReactOS  0.4.11-dev-946-g431643b
dispatch.c
Go to the documentation of this file.
1 /* $OpenBSD: dispatch.c,v 1.31 2004/09/21 04:07:03 david 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 
42 #include <rosdhcp.h>
43 
44 //#include <sys/ioctl.h>
45 
46 //#include <net/if_media.h>
47 //#include <ifaddrs.h>
48 //#include <poll.h>
49 
50 extern SOCKET DhcpSocket;
53 struct timeout *timeouts = NULL;
54 static struct timeout *free_timeouts = NULL;
56  struct dhcp_packet *, int, unsigned int,
57  struct iaddr, struct hardware *);
58 
59 /*
60  * Wait for packets to come in using poll(). When a packet comes in,
61  * call receive_packet to receive the packet and possibly strip hardware
62  * addressing information from it, and then call through the
63  * bootp_packet_handler hook to try to do something with it.
64  */
65 void
67 {
68  int count, to_msec;
69  struct protocol *l;
70  time_t howlong, cur_time;
71  HANDLE Events[3];
72  int EventCount = 2;
73 
74  Events[0] = StartAdapterDiscovery();
75  if (!Events[0])
76  return;
77 
78  AdapterStateChangedEvent = Events[0];
79 
80  Events[1] = hStopEvent;
81  Events[2] = WSA_INVALID_EVENT;
82 
83  ApiLock();
84 
85  do {
86  /*
87  * Call any expired timeouts, and then if there's still
88  * a timeout registered, time out the select call then.
89  */
90  time(&cur_time);
91 
92  if (timeouts)
93  {
94  struct timeout *t;
95 
96  if (timeouts->when <= cur_time) {
97  t = timeouts;
98  timeouts = timeouts->next;
99  (*(t->func))(t->what);
100  t->next = free_timeouts;
101  free_timeouts = t;
102  continue;
103  }
104 
105  /*
106  * Figure timeout in milliseconds, and check for
107  * potential overflow, so we can cram into an
108  * int for poll, while not polling with a
109  * negative timeout and blocking indefinitely.
110  */
111  howlong = timeouts->when - cur_time;
112  if (howlong > INT_MAX / 1000)
113  howlong = INT_MAX / 1000;
114  to_msec = howlong * 1000;
115  }
116  else
117  {
118  to_msec = INFINITE;
119  }
120 
121  if (Events[2] == WSA_INVALID_EVENT && DhcpSocket != INVALID_SOCKET)
122  {
123  Events[2] = WSACreateEvent();
124  if (Events[2] != WSA_INVALID_EVENT)
125  {
126  count = WSAEventSelect(DhcpSocket, Events[2], FD_READ | FD_CLOSE);
127  if (count != NO_ERROR)
128  {
129  WSACloseEvent(Events[2]);
130  Events[2] = WSA_INVALID_EVENT;
131  }
132  else
133  {
134  EventCount = 3;
135  }
136  }
137  }
138  else if (Events[2] != WSA_INVALID_EVENT && DhcpSocket == INVALID_SOCKET)
139  {
140  WSACloseEvent(Events[2]);
141  Events[2] = WSA_INVALID_EVENT;
142 
143  EventCount = 2;
144  }
145 
146  ApiUnlock();
147  count = WaitForMultipleObjects(EventCount,
148  Events,
149  FALSE,
150  to_msec);
151  ApiLock();
152  if (count == WAIT_OBJECT_0)
153  {
154  /* Adapter state change */
155  continue;
156  }
157  else if (count == WAIT_OBJECT_0 + 1)
158  {
159  /* Stop event signalled */
160  break;
161  }
162  else if (count == WAIT_OBJECT_0 + 2)
163  {
164  /* Packet received */
165 
166  /* WSA events are manual reset events */
167  WSAResetEvent(Events[2]);
168  }
169  else
170  {
171  /* Timeout */
172  continue;
173  }
174 
175  for (l = protocols; l; l = l->next) {
176  struct interface_info *ip;
177  ip = l->local;
178  if (ip && (l->handler != got_one ||
179  !ip->dead)) {
180  DH_DbgPrint(MID_TRACE,("Handling %x\n", l));
181  (*(l->handler))(l);
182  }
183  }
184  } while (1);
185 
186  AdapterStateChangedEvent = NULL;
187  CloseHandle(Events[0]);
188  CloseHandle(Events[1]);
189  WSACloseEvent(Events[2]);
190 
191  ApiUnlock();
192 }
193 
194 void
196 {
197  struct sockaddr_in from;
198  struct hardware hfrom;
199  struct iaddr ifrom;
200  ssize_t result;
201  union {
202  /*
203  * Packet input buffer. Must be as large as largest
204  * possible MTU.
205  */
206  unsigned char packbuf[4095];
207  struct dhcp_packet packet;
208  } u;
209  struct interface_info *ip = l->local;
210  PDHCP_ADAPTER adapter;
211 
212  if ((result = receive_packet(ip, u.packbuf, sizeof(u), &from,
213  &hfrom)) == -1) {
214  warning("receive_packet failed on %s: %d", ip->name,
215  WSAGetLastError());
216  ip->errors++;
217  if (ip->errors > 20) {
218  /* our interface has gone away. */
219  warning("Interface %s no longer appears valid.",
220  ip->name);
221  ip->dead = 1;
222  closesocket(l->fd);
223  remove_protocol(l);
224  adapter = AdapterFindInfo(ip);
225  if (adapter) {
226  RemoveEntryList(&adapter->ListEntry);
227  free(adapter);
228  }
229  }
230  return;
231  }
232  if (result == 0)
233  return;
234 
235  if (bootp_packet_handler) {
236  ifrom.len = 4;
237  memcpy(ifrom.iabuf, &from.sin_addr, ifrom.len);
238 
239 
240  adapter = AdapterFindByHardwareAddress(u.packet.chaddr,
241  u.packet.hlen);
242 
243  if (!adapter) {
244  warning("Discarding packet with a non-matching target physical address\n");
245  return;
246  }
247 
248  (*bootp_packet_handler)(&adapter->DhclientInfo, &u.packet, result,
249  from.sin_port, ifrom, &hfrom);
250  }
251 }
252 
253 void
254 add_timeout(time_t when, void (*where)(void *), void *what)
255 {
256  struct timeout *t, *q;
257 
258  DH_DbgPrint(MID_TRACE,("Adding timeout %x %p %x\n", when, where, what));
259  /* See if this timeout supersedes an existing timeout. */
260  t = NULL;
261  for (q = timeouts; q; q = q->next) {
262  if (q->func == where && q->what == what) {
263  if (t)
264  t->next = q->next;
265  else
266  timeouts = q->next;
267  break;
268  }
269  t = q;
270  }
271 
272  /* If we didn't supersede a timeout, allocate a timeout
273  structure now. */
274  if (!q) {
275  if (free_timeouts) {
276  q = free_timeouts;
277  free_timeouts = q->next;
278  q->func = where;
279  q->what = what;
280  } else {
281  q = malloc(sizeof(struct timeout));
282  if (!q) {
283  error("Can't allocate timeout structure!");
284  return;
285  }
286  q->func = where;
287  q->what = what;
288  }
289  }
290 
291  q->when = when;
292 
293  /* Now sort this timeout into the timeout list. */
294 
295  /* Beginning of list? */
296  if (!timeouts || timeouts->when > q->when) {
297  q->next = timeouts;
298  timeouts = q;
299  return;
300  }
301 
302  /* Middle of list? */
303  for (t = timeouts; t->next; t = t->next) {
304  if (t->next->when > q->when) {
305  q->next = t->next;
306  t->next = q;
307  return;
308  }
309  }
310 
311  /* End of list. */
312  t->next = q;
313  q->next = NULL;
314 }
315 
316 void
317 cancel_timeout(void (*where)(void *), void *what)
318 {
319  struct timeout *t, *q;
320 
321  /* Look for this timeout on the list, and unlink it if we find it. */
322  t = NULL;
323  for (q = timeouts; q; q = q->next) {
324  if (q->func == where && q->what == what) {
325  if (t)
326  t->next = q->next;
327  else
328  timeouts = q->next;
329  break;
330  }
331  t = q;
332  }
333 
334  /* If we found the timeout, put it on the free list. */
335  if (q) {
336  q->next = free_timeouts;
337  free_timeouts = q;
338  }
339 }
340 
341 /* Add a protocol to the list of protocols... */
342 void
343 add_protocol(char *name, int fd, void (*handler)(struct protocol *),
344  void *local)
345 {
346  struct protocol *p;
347 
348  p = malloc(sizeof(*p));
349  if (!p)
350  error("can't allocate protocol struct for %s", name);
351 
352  p->fd = fd;
353  p->handler = handler;
354  p->local = local;
355  p->next = protocols;
356  protocols = p;
357 }
358 
359 void
361 {
362  struct protocol *p, *next, *prev;
363  struct interface_info *ip = proto->local;
364  struct timeout *t, *q, *u;
365 
366  t = NULL;
367  q = timeouts;
368  while (q != NULL)
369  {
370  /* Remove all timeouts for this protocol */
371  if (q->what == ip)
372  {
373  /* Unlink the timeout from previous */
374  if (t)
375  t->next = q->next;
376  else
377  timeouts = q->next;
378 
379  /* Advance to the next timeout */
380  u = q->next;
381 
382  /* Add it to the free list */
383  q->next = free_timeouts;
384  free_timeouts = q;
385  }
386  else
387  {
388  /* Advance to the next timeout */
389  u = q->next;
390 
391  /* Update the previous pointer */
392  t = q;
393  }
394 
395  /* Advance */
396  q = u;
397  }
398 
399  prev = NULL;
400  for (p = protocols; p; p = next) {
401  next = p->next;
402  if (p == proto) {
403  if (prev)
404  prev->next = p->next;
405  else
406  protocols = p->next;
407  free(p);
408  }
409  }
410 }
411 
412 struct protocol *
414 {
415  struct protocol *p;
416 
417  for( p = protocols; p; p = p->next ) {
418  if( p->local == (void *)info ) return p;
419  }
420 
421  return NULL;
422 }
423 
424 int
426 {
427  return (1);
428 }
#define CloseHandle
Definition: compat.h:398
#define MID_TRACE
Definition: debug.h:15
struct png_info_def **typedef void(__cdecl typeof(png_destroy_read_struct))(struct png_struct_def **
Definition: typeof.h:47
u_short sin_port
Definition: winsock.h:511
#define INT_MAX
Definition: limits.h:40
#define error(str)
Definition: mkdosfs.c:1605
char name[IFNAMSIZ]
Definition: dhcpd.h:231
int fd
Definition: dhcpd.h:254
HANDLE AdapterStateChangedEvent
Definition: dispatch.c:51
GLuint GLuint GLsizei count
Definition: gl.h:1545
#define free
Definition: debug_ros.c:5
void(* func)(void *)
Definition: dhcpd.h:248
unsigned char iabuf[16]
Definition: dhcpd.h:127
time_t cur_time
GLdouble GLdouble t
Definition: gl.h:2047
void got_one(struct protocol *l)
Definition: dispatch.c:195
static int fd
Definition: io.c:51
#define FD_READ
Definition: winsock.h:405
GLenum GLclampf GLint GLenum GLuint GLenum GLenum GLsizei GLenum const GLvoid GLfloat GLfloat GLfloat GLfloat GLclampd GLint 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 GLboolean GLboolean GLboolean GLint GLenum GLsizei const GLvoid GLenum GLint GLenum GLint GLint GLsizei GLint GLenum GLint GLint GLint GLint GLsizei GLenum GLsizei const GLuint GLboolean GLenum GLenum GLint GLsizei GLenum GLsizei GLenum const GLvoid GLboolean const GLboolean GLenum const GLdouble * u
Definition: glfuncs.h:88
Definition: dhcpd.h:245
__u16 time
Definition: mkdosfs.c:366
#define NO_ERROR
Definition: dderror.h:5
DWORD WINAPI WaitForMultipleObjects(IN DWORD nCount, IN CONST HANDLE *lpHandles, IN BOOL bWaitAll, IN DWORD dwMilliseconds)
Definition: synch.c:151
void * local
Definition: dhcpd.h:256
void remove_protocol(struct protocol *proto)
Definition: dispatch.c:360
FORCEINLINE BOOLEAN RemoveEntryList(_In_ PLIST_ENTRY Entry)
Definition: rtlfuncs.h:105
int len
Definition: dhcpd.h:126
BOOL WSAAPI WSAResetEvent(IN WSAEVENT hEvent)
Definition: event.c:53
#define WSA_INVALID_EVENT
Definition: winsock2.h:595
#define closesocket
Definition: main.c:39
void cancel_timeout(void(*where)(void *), void *what)
Definition: dispatch.c:317
HANDLE hStopEvent
Definition: dhcpcsvc.c:19
int ip[4]
Definition: rtl.c:1176
INT WSAAPI WSAEventSelect(IN SOCKET s, IN WSAEVENT hEventObject, IN LONG lNetworkEvents)
Definition: select.c:182
BOOL WSAAPI WSACloseEvent(IN WSAEVENT hEvent)
Definition: event.c:23
smooth NULL
Definition: ftsmooth.c:416
#define DH_DbgPrint(_t_, _x_)
Definition: debug.h:49
PDHCP_ADAPTER AdapterFindInfo(struct interface_info *ip)
Definition: adapter.c:541
r l[0]
Definition: byte_order.h:167
struct protocol * find_protocol_by_adapter(struct interface_info *info)
Definition: dispatch.c:413
INT WSAAPI WSAGetLastError(VOID)
Definition: dllmain.c:112
#define WAIT_OBJECT_0
Definition: winbase.h:387
#define FD_CLOSE
Definition: winsock.h:410
#define INVALID_SOCKET
Definition: winsock.h:332
Definition: dhcpd.h:61
void add_protocol(char *name, int fd, void(*handler)(struct protocol *), void *local)
Definition: dispatch.c:343
time_t when
Definition: dhcpd.h:247
HANDLE StartAdapterDiscovery(VOID)
Definition: adapter.c:471
static struct timeout * free_timeouts
Definition: dispatch.c:54
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
struct timeout * next
Definition: dhcpd.h:246
int errors
Definition: dhcpd.h:240
void(* bootp_packet_handler)(struct interface_info *, struct dhcp_packet *, int, unsigned int, struct iaddr, struct hardware *)
Definition: dispatch.c:55
Definition: dhcpd.h:125
struct interface_info DhclientInfo
Definition: rosdhcp.h:71
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
int ssize_t
Definition: rosdhcp.h:48
void dispatch(HANDLE hStopEvent)
Definition: dispatch.c:66
struct in_addr sin_addr
Definition: winsock.h:512
#define local
Definition: zutil.h:30
PDHCP_ADAPTER AdapterFindByHardwareAddress(u_int8_t haddr[16], u_int8_t hlen)
Definition: adapter.c:555
SOCKET DhcpSocket
Definition: adapter.c:3
static unsigned __int64 next
Definition: rand_nt.c:6
LIST_ENTRY ListEntry
Definition: rosdhcp.h:65
WSAEVENT WSAAPI WSACreateEvent(VOID)
Definition: event.c:42
ssize_t receive_packet(struct interface_info *ip, unsigned char *packet_data, size_t packet_len, struct sockaddr_in *dest, struct hardware *hardware)
Definition: socket.c:29
HANDLE Events[2]
Definition: schedsvc.c:40
__kernel_time_t time_t
Definition: linux.h:252
struct protocol * protocols
Definition: dispatch.c:52
struct protocol * next
Definition: dhcpd.h:253
void add_timeout(time_t when, void(*where)(void *), void *what)
Definition: dispatch.c:254
Definition: name.c:36
void(* handler)(struct protocol *)
Definition: dhcpd.h:255
int interface_link_status(char *ifname)
Definition: dispatch.c:425
#define malloc
Definition: debug_ros.c:4
VOID ApiUnlock()
Definition: api.c:26
UINT_PTR SOCKET
Definition: winsock.h:47
void * what
Definition: dhcpd.h:249
struct timeout * timeouts
Definition: dispatch.c:53
UINT(* handler)(MSIPACKAGE *)
Definition: action.c:7782
GLfloat GLfloat p
Definition: glext.h:8902
#define INFINITE
Definition: serial.h:102
GLuint64EXT * result
Definition: glext.h:11304
VOID ApiLock()
Definition: api.c:22
#define warning(s)
Definition: debug.h:71
unsigned int(__cdecl typeof(jpeg_read_scanlines))(struct jpeg_decompress_struct *
Definition: typeof.h:29