1: /* dispatch.c
2:
3: Network input dispatcher... */
4:
5: /*
6: * Copyright (c) 2004-2009,2011 by Internet Systems Consortium, Inc. ("ISC")
7: * Copyright (c) 1995-2003 by Internet Software Consortium
8: *
9: * Permission to use, copy, modify, and distribute this software for any
10: * purpose with or without fee is hereby granted, provided that the above
11: * copyright notice and this permission notice appear in all copies.
12: *
13: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
14: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
15: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
16: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
17: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
18: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
19: * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
20: *
21: * Internet Systems Consortium, Inc.
22: * 950 Charter Street
23: * Redwood City, CA 94063
24: * <info@isc.org>
25: * https://www.isc.org/
26: *
27: * This software has been written for Internet Systems Consortium
28: * by Ted Lemon in cooperation with Vixie Enterprises and Nominum, Inc.
29: * To learn more about Internet Systems Consortium, see
30: * ``https://www.isc.org/''. To learn more about Vixie Enterprises,
31: * see ``http://www.vix.com''. To learn more about Nominum, Inc., see
32: * ``http://www.nominum.com''.
33: */
34:
35: #include "dhcpd.h"
36:
37: struct timeout *timeouts;
38: static struct timeout *free_timeouts;
39:
40: void set_time(TIME t)
41: {
42: /* Do any outstanding timeouts. */
43: if (cur_tv . tv_sec != t) {
44: cur_tv . tv_sec = t;
45: cur_tv . tv_usec = 0;
46: process_outstanding_timeouts ((struct timeval *)0);
47: }
48: }
49:
50: struct timeval *process_outstanding_timeouts (struct timeval *tvp)
51: {
52: /* Call any expired timeouts, and then if there's
53: still a timeout registered, time out the select
54: call then. */
55: another:
56: if (timeouts) {
57: struct timeout *t;
58: if ((timeouts -> when . tv_sec < cur_tv . tv_sec) ||
59: ((timeouts -> when . tv_sec == cur_tv . tv_sec) &&
60: (timeouts -> when . tv_usec <= cur_tv . tv_usec))) {
61: t = timeouts;
62: timeouts = timeouts -> next;
63: (*(t -> func)) (t -> what);
64: if (t -> unref)
65: (*t -> unref) (&t -> what, MDL);
66: t -> next = free_timeouts;
67: free_timeouts = t;
68: goto another;
69: }
70: if (tvp) {
71: tvp -> tv_sec = timeouts -> when . tv_sec;
72: tvp -> tv_usec = timeouts -> when . tv_usec;
73: }
74: return tvp;
75: } else
76: return (struct timeval *)0;
77: }
78:
79: /* Wait for packets to come in using select(). When one does, call
80: receive_packet to receive the packet and possibly strip hardware
81: addressing information from it, and then call through the
82: bootp_packet_handler hook to try to do something with it. */
83:
84: void dispatch ()
85: {
86: struct timeval tv, *tvp;
87: isc_result_t status;
88:
89: /* Wait for a packet or a timeout... XXX */
90: do {
91: tvp = process_outstanding_timeouts (&tv);
92: status = omapi_one_dispatch (0, tvp);
93: } while (status == ISC_R_TIMEDOUT || status == ISC_R_SUCCESS);
94: log_fatal ("omapi_one_dispatch failed: %s -- exiting.",
95: isc_result_totext (status));
96: }
97:
98: void add_timeout (when, where, what, ref, unref)
99: struct timeval *when;
100: void (*where) (void *);
101: void *what;
102: tvref_t ref;
103: tvunref_t unref;
104: {
105: struct timeout *t, *q;
106:
107: /* See if this timeout supersedes an existing timeout. */
108: t = (struct timeout *)0;
109: for (q = timeouts; q; q = q -> next) {
110: if ((where == NULL || q -> func == where) &&
111: q -> what == what) {
112: if (t)
113: t -> next = q -> next;
114: else
115: timeouts = q -> next;
116: break;
117: }
118: t = q;
119: }
120:
121: /* If we didn't supersede a timeout, allocate a timeout
122: structure now. */
123: if (!q) {
124: if (free_timeouts) {
125: q = free_timeouts;
126: free_timeouts = q -> next;
127: } else {
128: q = ((struct timeout *)
129: dmalloc (sizeof (struct timeout), MDL));
130: if (!q)
131: log_fatal ("add_timeout: no memory!");
132: }
133: memset (q, 0, sizeof *q);
134: q -> func = where;
135: q -> ref = ref;
136: q -> unref = unref;
137: if (q -> ref)
138: (*q -> ref)(&q -> what, what, MDL);
139: else
140: q -> what = what;
141: }
142:
143: q -> when . tv_sec = when -> tv_sec;
144: q -> when . tv_usec = when -> tv_usec;
145:
146: /* Now sort this timeout into the timeout list. */
147:
148: /* Beginning of list? */
149: if (!timeouts || (timeouts -> when . tv_sec > q -> when . tv_sec) ||
150: ((timeouts -> when . tv_sec == q -> when . tv_sec) &&
151: (timeouts -> when . tv_usec > q -> when . tv_usec))) {
152: q -> next = timeouts;
153: timeouts = q;
154: return;
155: }
156:
157: /* Middle of list? */
158: for (t = timeouts; t -> next; t = t -> next) {
159: if ((t -> next -> when . tv_sec > q -> when . tv_sec) ||
160: ((t -> next -> when . tv_sec == q -> when . tv_sec) &&
161: (t -> next -> when . tv_usec > q -> when . tv_usec))) {
162: q -> next = t -> next;
163: t -> next = q;
164: return;
165: }
166: }
167:
168: /* End of list. */
169: t -> next = q;
170: q -> next = (struct timeout *)0;
171: }
172:
173: void cancel_timeout (where, what)
174: void (*where) (void *);
175: void *what;
176: {
177: struct timeout *t, *q;
178:
179: /* Look for this timeout on the list, and unlink it if we find it. */
180: t = (struct timeout *)0;
181: for (q = timeouts; q; q = q -> next) {
182: if (q -> func == where && q -> what == what) {
183: if (t)
184: t -> next = q -> next;
185: else
186: timeouts = q -> next;
187: break;
188: }
189: t = q;
190: }
191:
192: /* If we found the timeout, put it on the free list. */
193: if (q) {
194: if (q -> unref)
195: (*q -> unref) (&q -> what, MDL);
196: q -> next = free_timeouts;
197: free_timeouts = q;
198: }
199: }
200:
201: #if defined (DEBUG_MEMORY_LEAKAGE_ON_EXIT)
202: void cancel_all_timeouts ()
203: {
204: struct timeout *t, *n;
205: for (t = timeouts; t; t = n) {
206: n = t -> next;
207: if (t -> unref && t -> what)
208: (*t -> unref) (&t -> what, MDL);
209: t -> next = free_timeouts;
210: free_timeouts = t;
211: }
212: }
213:
214: void relinquish_timeouts ()
215: {
216: struct timeout *t, *n;
217: for (t = free_timeouts; t; t = n) {
218: n = t -> next;
219: dfree (t, MDL);
220: }
221: }
222: #endif
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>