ISC DHCP  4.4.1
A reference DHCPv4 and DHCPv6 implementation
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
dispatch.c
Go to the documentation of this file.
1 /* dispatch.c
2 
3  I/O dispatcher. */
4 
5 /*
6  * Copyright (c) 2004-2017 by Internet Systems Consortium, Inc. ("ISC")
7  * Copyright (c) 1999-2003 by Internet Software Consortium
8  *
9  * This Source Code Form is subject to the terms of the Mozilla Public
10  * License, v. 2.0. If a copy of the MPL was not distributed with this
11  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
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  */
28 
29 #include "dhcpd.h"
30 
31 #include <omapip/omapip_p.h>
32 #include <sys/time.h>
33 
34 static omapi_io_object_t omapi_io_states;
35 struct timeval cur_tv;
36 
38 
41 OMAPI_OBJECT_ALLOC (omapi_waiter,
43 
44 void
45 register_eventhandler(struct eventqueue **queue, void (*handler)(void *))
46 {
47  struct eventqueue *t, *q;
48 
49  /* traverse to end of list */
50  t = NULL;
51  for (q = *queue ; q ; q = q->next) {
52  if (q->handler == handler)
53  return; /* handler already registered */
54  t = q;
55  }
56 
57  q = ((struct eventqueue *)dmalloc(sizeof(struct eventqueue), MDL));
58  if (!q)
59  log_fatal("register_eventhandler: no memory!");
60  memset(q, 0, sizeof *q);
61  if (t)
62  t->next = q;
63  else
64  *queue = q;
65  q->handler = handler;
66  return;
67 }
68 
69 void
70 unregister_eventhandler(struct eventqueue **queue, void (*handler)(void *))
71 {
72  struct eventqueue *t, *q;
73 
74  /* traverse to end of list */
75  t= NULL;
76  for (q = *queue ; q ; q = q->next) {
77  if (q->handler == handler) {
78  if (t)
79  t->next = q->next;
80  else
81  *queue = q->next;
82  dfree(q, MDL); /* Don't access q after this!*/
83  break;
84  }
85  t = q;
86  }
87  return;
88 }
89 
90 void
91 trigger_event(struct eventqueue **queue)
92 {
93  struct eventqueue *q;
94 
95  for (q=*queue ; q ; q=q->next) {
96  if (q->handler)
97  (*q->handler)(NULL);
98  }
99 }
100 
101 /*
102  * Callback routine to connect the omapi I/O object and socket with
103  * the isc socket code. The isc socket code will call this routine
104  * which will then call the correct local routine to process the bytes.
105  *
106  * Currently we are always willing to read more data, this should be modified
107  * so that on connections we don't read more if we already have enough.
108  *
109  * If we have more bytes to write we ask the library to call us when
110  * we can write more. If we indicate we don't have more to write we need
111  * to poke the library via isc_socket_fdwatchpoke.
112  */
113 
114 /*
115  * sockdelete indicates if we are deleting the socket or leaving it in place
116  * 1 is delete, 0 is leave in place
117  */
118 #define SOCKDELETE 1
119 int
120 omapi_iscsock_cb(isc_task_t *task,
121  isc_socket_t *socket,
122  void *cbarg,
123  int flags)
124 {
125  omapi_io_object_t *obj;
126  isc_result_t status;
127 
128  /* Get the current time... */
129  gettimeofday (&cur_tv, (struct timezone *)0);
130 
131  /* isc socket stuff */
132 #if SOCKDELETE
133  /*
134  * walk through the io states list, if our object is on there
135  * service it. if not ignore it.
136  */
137  for (obj = omapi_io_states.next; obj != NULL; obj = obj->next) {
138  if (obj == cbarg)
139  break;
140  }
141 
142  if (obj == NULL) {
143  return(0);
144  }
145 #else
146  /* Not much to be done if we have the wrong type of object. */
147  if (((omapi_object_t *)cbarg) -> type != omapi_type_io_object) {
148  log_fatal ("Incorrect object type, must be of type io_object");
149  }
150  obj = (omapi_io_object_t *)cbarg;
151 
152  /*
153  * If the object is marked as closed don't try and process
154  * anything just indicate that we don't want any more.
155  *
156  * This should be a temporary fix until we arrange to properly
157  * close the socket.
158  */
159  if (obj->closed == ISC_TRUE) {
160  return(0);
161  }
162 #endif
163 
164  if ((flags == ISC_SOCKFDWATCH_READ) &&
165  (obj->reader != NULL) &&
166  (obj->inner != NULL)) {
167  status = obj->reader(obj->inner);
168  /*
169  * If we are shutting down (basically tried to
170  * read and got no bytes) we don't need to try
171  * again.
172  */
173  if (status == ISC_R_SHUTTINGDOWN)
174  return (0);
175  /* Otherwise We always ask for more when reading */
176  return (1);
177  } else if ((flags == ISC_SOCKFDWATCH_WRITE) &&
178  (obj->writer != NULL) &&
179  (obj->inner != NULL)) {
180  status = obj->writer(obj->inner);
181  /* If the writer has more to write they should return
182  * ISC_R_INPROGRESS */
183  if (status == ISC_R_INPROGRESS) {
184  return (1);
185  }
186  }
187 
188  /*
189  * We get here if we either had an error (inconsistent
190  * structures etc) or no more to write, tell the socket
191  * lib we don't have more to do right now.
192  */
193  return (0);
194 }
195 
196 /* Register an I/O handle so that we can do asynchronous I/O on it. */
197 
199  int (*readfd) (omapi_object_t *),
200  int (*writefd) (omapi_object_t *),
201  isc_result_t (*reader)
202  (omapi_object_t *),
203  isc_result_t (*writer)
204  (omapi_object_t *),
205  isc_result_t (*reaper)
206  (omapi_object_t *))
207 {
208  isc_result_t status;
209  omapi_io_object_t *obj, *p;
210  int fd_flags = 0, fd = 0;
211 
212  /* omapi_io_states is a static object. If its reference count
213  is zero, this is the first I/O handle to be registered, so
214  we need to initialize it. Because there is no inner or outer
215  pointer on this object, and we're setting its refcnt to 1, it
216  will never be freed. */
217  if (!omapi_io_states.refcnt) {
218  omapi_io_states.refcnt = 1;
219  omapi_io_states.type = omapi_type_io_object;
220  }
221 
222  obj = (omapi_io_object_t *)0;
223  status = omapi_io_allocate (&obj, MDL);
224  if (status != ISC_R_SUCCESS)
225  return status;
226  obj->closed = ISC_FALSE; /* mark as open */
227 
228  status = omapi_object_reference (&obj -> inner, h, MDL);
229  if (status != ISC_R_SUCCESS) {
230  omapi_io_dereference (&obj, MDL);
231  return status;
232  }
233 
234  status = omapi_object_reference (&h -> outer,
235  (omapi_object_t *)obj, MDL);
236  if (status != ISC_R_SUCCESS) {
237  omapi_io_dereference (&obj, MDL);
238  return status;
239  }
240 
241  /*
242  * Attach the I/O object to the isc socket library via the
243  * fdwatch function. This allows the socket library to watch
244  * over a socket that we built. If there are both a read and
245  * a write socket we asssume they are the same socket.
246  */
247 
248  if (readfd) {
249  fd_flags |= ISC_SOCKFDWATCH_READ;
250  fd = readfd(h);
251  }
252 
253  if (writefd) {
254  fd_flags |= ISC_SOCKFDWATCH_WRITE;
255  fd = writefd(h);
256  }
257 
258  if (fd_flags != 0) {
259  status = isc_socket_fdwatchcreate(dhcp_gbl_ctx.socketmgr,
260  fd, fd_flags,
262  obj,
264  &obj->fd);
265  if (status != ISC_R_SUCCESS) {
266  log_error("Unable to register fd with library %s",
267  isc_result_totext(status));
268 
269  /*sar*/
270  /* is this the cleanup we need? */
271  omapi_object_dereference(&h->outer, MDL);
272  omapi_io_dereference (&obj, MDL);
273  return (status);
274  }
275  }
276 
277 
278  /* Find the last I/O state, if there are any. */
279  for (p = omapi_io_states.next;
280  p && p -> next; p = p -> next)
281  ;
282  if (p)
283  omapi_io_reference (&p -> next, obj, MDL);
284  else
285  omapi_io_reference (&omapi_io_states.next, obj, MDL);
286 
287  obj -> readfd = readfd;
288  obj -> writefd = writefd;
289  obj -> reader = reader;
290  obj -> writer = writer;
291  obj -> reaper = reaper;
292 
293  omapi_io_dereference(&obj, MDL);
294  return ISC_R_SUCCESS;
295 }
296 
297 /*
298  * ReRegister an I/O handle so that we can do asynchronous I/O on it.
299  * If the handle doesn't exist we call the register routine to build it.
300  * If it does exist we change the functions associated with it, and
301  * repoke the fd code to make it happy. Neither the objects nor the
302  * fd are allowed to have changed.
303  */
304 
306  int (*readfd) (omapi_object_t *),
307  int (*writefd) (omapi_object_t *),
308  isc_result_t (*reader)
309  (omapi_object_t *),
310  isc_result_t (*writer)
311  (omapi_object_t *),
312  isc_result_t (*reaper)
313  (omapi_object_t *))
314 {
315  omapi_io_object_t *obj;
316  int fd_flags = 0;
317 
318  if ((!h -> outer) || (h -> outer -> type != omapi_type_io_object)) {
319  /*
320  * If we don't have an object or if the type isn't what
321  * we expect do the normal registration (which will overwrite
322  * an incorrect type, that's what we did historically, may
323  * want to change that)
324  */
325  return (omapi_register_io_object (h, readfd, writefd,
326  reader, writer, reaper));
327  }
328 
329  /* We have an io object of the correct type, try to update it */
330  /*sar*/
331  /* Should we validate that the fd matches the previous one?
332  * It's suppossed to, that's a requirement, don't bother yet */
333 
334  obj = (omapi_io_object_t *)h->outer;
335 
336  obj->readfd = readfd;
337  obj->writefd = writefd;
338  obj->reader = reader;
339  obj->writer = writer;
340  obj->reaper = reaper;
341 
342  if (readfd) {
343  fd_flags |= ISC_SOCKFDWATCH_READ;
344  }
345 
346  if (writefd) {
347  fd_flags |= ISC_SOCKFDWATCH_WRITE;
348  }
349 
350  isc_socket_fdwatchpoke(obj->fd, fd_flags);
351 
352  return (ISC_R_SUCCESS);
353 }
354 
356 {
357  omapi_io_object_t *obj, *ph;
358 #if SOCKDELETE
359  omapi_io_object_t *p, *last;
360 #endif
361 
362  if (!h -> outer || h -> outer -> type != omapi_type_io_object)
363  return DHCP_R_INVALIDARG;
364  obj = (omapi_io_object_t *)h -> outer;
365  ph = (omapi_io_object_t *)0;
366  omapi_io_reference (&ph, obj, MDL);
367 
368 #if SOCKDELETE
369  /*
370  * For now we leave this out. We can't clean up the isc socket
371  * structure cleanly yet so we need to leave the io object in place.
372  * By leaving it on the io states list we avoid it being freed.
373  * We also mark it as closed to avoid using it.
374  */
375 
376  /* remove from the list of I/O states */
377  last = &omapi_io_states;
378  for (p = omapi_io_states.next; p; p = p -> next) {
379  if (p == obj) {
380  omapi_io_dereference (&last -> next, MDL);
381  omapi_io_reference (&last -> next, p -> next, MDL);
382  break;
383  }
384  last = p;
385  }
386  if (obj -> next)
387  omapi_io_dereference (&obj -> next, MDL);
388 #endif
389 
390  if (obj -> outer) {
391  if (obj -> outer -> inner == (omapi_object_t *)obj)
392  omapi_object_dereference (&obj -> outer -> inner,
393  MDL);
394  omapi_object_dereference (&obj -> outer, MDL);
395  }
396  omapi_object_dereference (&obj -> inner, MDL);
397  omapi_object_dereference (&h -> outer, MDL);
398 
399 #if SOCKDELETE
400  /* remove isc socket associations */
401  if (obj->fd != NULL) {
402  isc_socket_cancel(obj->fd, dhcp_gbl_ctx.task,
403  ISC_SOCKCANCEL_ALL);
404  isc_socket_detach(&obj->fd);
405  }
406 #else
407  obj->closed = ISC_TRUE;
408 #endif
409 
410  omapi_io_dereference (&ph, MDL);
411  return ISC_R_SUCCESS;
412 }
413 
414 isc_result_t omapi_dispatch (struct timeval *t)
415 {
416  return omapi_wait_for_completion ((omapi_object_t *)&omapi_io_states,
417  t);
418 }
419 
421  struct timeval *t)
422 {
423  isc_result_t status;
424  omapi_waiter_object_t *waiter;
425  omapi_object_t *inner;
426 
427  if (object) {
428  waiter = (omapi_waiter_object_t *)0;
429  status = omapi_waiter_allocate (&waiter, MDL);
430  if (status != ISC_R_SUCCESS)
431  return status;
432 
433  /* Paste the waiter object onto the inner object we're
434  waiting on. */
435  for (inner = object; inner -> inner; inner = inner -> inner)
436  ;
437 
438  status = omapi_object_reference (&waiter -> outer, inner, MDL);
439  if (status != ISC_R_SUCCESS) {
440  omapi_waiter_dereference (&waiter, MDL);
441  return status;
442  }
443 
444  status = omapi_object_reference (&inner -> inner,
445  (omapi_object_t *)waiter,
446  MDL);
447  if (status != ISC_R_SUCCESS) {
448  omapi_waiter_dereference (&waiter, MDL);
449  return status;
450  }
451  } else
452  waiter = (omapi_waiter_object_t *)0;
453 
454  do {
455  status = omapi_one_dispatch ((omapi_object_t *)waiter, t);
456  if (status != ISC_R_SUCCESS)
457  return status;
458  } while (!waiter || !waiter -> ready);
459 
460  if (waiter -> outer) {
461  if (waiter -> outer -> inner) {
462  omapi_object_dereference (&waiter -> outer -> inner,
463  MDL);
464  if (waiter -> inner)
466  (&waiter -> outer -> inner,
467  waiter -> inner, MDL);
468  }
469  omapi_object_dereference (&waiter -> outer, MDL);
470  }
471  if (waiter -> inner)
472  omapi_object_dereference (&waiter -> inner, MDL);
473 
474  status = waiter -> waitstatus;
475  omapi_waiter_dereference (&waiter, MDL);
476  return status;
477 }
478 
480  struct timeval *t)
481 {
482  fd_set r, w, x, rr, ww, xx;
483  int max = 0;
484  int count;
485  int desc;
486  struct timeval now, to;
487  omapi_io_object_t *io, *prev, *next;
488  omapi_waiter_object_t *waiter;
489  omapi_object_t *tmp = (omapi_object_t *)0;
490 
491  if (!wo || wo -> type != omapi_type_waiter)
492  waiter = (omapi_waiter_object_t *)0;
493  else
494  waiter = (omapi_waiter_object_t *)wo;
495 
496  FD_ZERO (&x);
497 
498  /* First, see if the timeout has expired, and if so return. */
499  if (t) {
500  gettimeofday (&now, (struct timezone *)0);
501  cur_tv.tv_sec = now.tv_sec;
502  cur_tv.tv_usec = now.tv_usec;
503  if (now.tv_sec > t -> tv_sec ||
504  (now.tv_sec == t -> tv_sec && now.tv_usec >= t -> tv_usec))
505  return ISC_R_TIMEDOUT;
506 
507  /* We didn't time out, so figure out how long until
508  we do. */
509  to.tv_sec = t -> tv_sec - now.tv_sec;
510  to.tv_usec = t -> tv_usec - now.tv_usec;
511  if (to.tv_usec < 0) {
512  to.tv_usec += 1000000;
513  to.tv_sec--;
514  }
515 
516  /* It is possible for the timeout to get set larger than
517  the largest time select() is willing to accept.
518  Restricting the timeout to a maximum of one day should
519  work around this. -DPN. (Ref: Bug #416) */
520  if (to.tv_sec > (60 * 60 * 24))
521  to.tv_sec = 60 * 60 * 24;
522  }
523 
524  /* If the object we're waiting on has reached completion,
525  return now. */
526  if (waiter && waiter -> ready)
527  return ISC_R_SUCCESS;
528 
529  again:
530  /* If we have no I/O state, we can't proceed. */
531  if (!(io = omapi_io_states.next))
532  return ISC_R_NOMORE;
533 
534  /* Set up the read and write masks. */
535  FD_ZERO (&r);
536  FD_ZERO (&w);
537 
538  for (; io; io = io -> next) {
539  /* Check for a read socket. If we shouldn't be
540  trying to read for this I/O object, either there
541  won't be a readfd function, or it'll return -1. */
542  if (io -> readfd && io -> inner &&
543  (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
544  FD_SET (desc, &r);
545  if (desc > max)
546  max = desc;
547  }
548 
549  /* Same deal for write fdets. */
550  if (io -> writefd && io -> inner &&
551  (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
552  FD_SET (desc, &w);
553  if (desc > max)
554  max = desc;
555  }
556  }
557 
558  /* poll if all reader are dry */
559  now.tv_sec = 0;
560  now.tv_usec = 0;
561  rr=r;
562  ww=w;
563  xx=x;
564 
565  /* poll once */
566  count = select(max + 1, &r, &w, &x, &now);
567  if (!count) {
568  /* We are dry now */
569  trigger_event(&rw_queue_empty);
570  /* Wait for a packet or a timeout... XXX */
571  r = rr;
572  w = ww;
573  x = xx;
574  count = select(max + 1, &r, &w, &x, t ? &to : NULL);
575  }
576 
577  /* Get the current time... */
578  gettimeofday (&cur_tv, (struct timezone *)0);
579 
580  /* We probably have a bad file descriptor. Figure out which one.
581  When we find it, call the reaper function on it, which will
582  maybe make it go away, and then try again. */
583  if (count < 0) {
584  struct timeval t0;
586  io = (omapi_io_object_t *)0;
587  if (omapi_io_states.next)
588  omapi_io_reference (&io, omapi_io_states.next, MDL);
589 
590  while (io) {
591  omapi_object_t *obj;
592  FD_ZERO (&r);
593  FD_ZERO (&w);
594  t0.tv_sec = t0.tv_usec = 0;
595 
596  if (io -> readfd && io -> inner &&
597  (desc = (*(io -> readfd)) (io -> inner)) >= 0) {
598  FD_SET (desc, &r);
599  count = select (desc + 1, &r, &w, &x, &t0);
600  bogon:
601  if (count < 0) {
602  log_error ("Bad descriptor %d.", desc);
603  for (obj = (omapi_object_t *)io;
604  obj -> outer;
605  obj = obj -> outer)
606  ;
607  for (; obj; obj = obj -> inner) {
608  omapi_value_t *ov;
609  int len;
610  const char *s;
611  ov = (omapi_value_t *)0;
612  omapi_get_value_str (obj,
613  (omapi_object_t *)0,
614  "name", &ov);
615  if (ov && ov -> value &&
616  (ov -> value -> type ==
618  s = (char *)
619  ov -> value -> u.buffer.value;
620  len = ov -> value -> u.buffer.len;
621  } else {
622  s = "";
623  len = 0;
624  }
625  log_error ("Object %lx %s%s%.*s",
626  (unsigned long)obj,
627  obj -> type -> name,
628  len ? " " : "",
629  len, s);
630  if (len)
632  }
633  (*(io -> reaper)) (io -> inner);
634  if (prev) {
635  omapi_io_dereference (&prev -> next, MDL);
636  if (io -> next)
637  omapi_io_reference (&prev -> next,
638  io -> next, MDL);
639  } else {
640  omapi_io_dereference
641  (&omapi_io_states.next, MDL);
642  if (io -> next)
643  omapi_io_reference
644  (&omapi_io_states.next,
645  io -> next, MDL);
646  }
647  omapi_io_dereference (&io, MDL);
648  goto again;
649  }
650  }
651 
652  FD_ZERO (&r);
653  FD_ZERO (&w);
654  t0.tv_sec = t0.tv_usec = 0;
655 
656  /* Same deal for write fdets. */
657  if (io -> writefd && io -> inner &&
658  (desc = (*(io -> writefd)) (io -> inner)) >= 0) {
659  FD_SET (desc, &w);
660  count = select (desc + 1, &r, &w, &x, &t0);
661  if (count < 0)
662  goto bogon;
663  }
664  if (prev)
665  omapi_io_dereference (&prev, MDL);
666  omapi_io_reference (&prev, io, MDL);
667  omapi_io_dereference (&io, MDL);
668  if (prev -> next)
669  omapi_io_reference (&io, prev -> next, MDL);
670  }
671  if (prev)
672  omapi_io_dereference (&prev, MDL);
673 
674  }
675 
676  for (io = omapi_io_states.next; io; io = io -> next) {
677  if (!io -> inner)
678  continue;
679  omapi_object_reference (&tmp, io -> inner, MDL);
680  /* Check for a read descriptor, and if there is one,
681  see if we got input on that socket. */
682  if (io -> readfd &&
683  (desc = (*(io -> readfd)) (tmp)) >= 0) {
684  if (FD_ISSET (desc, &r))
685  ((*(io -> reader)) (tmp));
686  }
687 
688  /* Same deal for write descriptors. */
689  if (io -> writefd &&
690  (desc = (*(io -> writefd)) (tmp)) >= 0)
691  {
692  if (FD_ISSET (desc, &w))
693  ((*(io -> writer)) (tmp));
694  }
696  }
697 
698  /* Now check for I/O handles that are no longer valid,
699  and remove them from the list. */
700  prev = NULL;
701  io = NULL;
702  if (omapi_io_states.next != NULL) {
703  omapi_io_reference(&io, omapi_io_states.next, MDL);
704  }
705  while (io != NULL) {
706  if ((io->inner == NULL) ||
707  ((io->reaper != NULL) &&
708  ((io->reaper)(io->inner) != ISC_R_SUCCESS)))
709  {
710 
711  omapi_io_object_t *tmp = NULL;
712  /* Save a reference to the next
713  pointer, if there is one. */
714  if (io->next != NULL) {
715  omapi_io_reference(&tmp, io->next, MDL);
716  omapi_io_dereference(&io->next, MDL);
717  }
718  if (prev != NULL) {
719  omapi_io_dereference(&prev->next, MDL);
720  if (tmp != NULL)
721  omapi_io_reference(&prev->next,
722  tmp, MDL);
723  } else {
724  omapi_io_dereference(&omapi_io_states.next,
725  MDL);
726  if (tmp != NULL)
727  omapi_io_reference
728  (&omapi_io_states.next,
729  tmp, MDL);
730  else
732  (omapi_object_t *)
733  &omapi_io_states,
734  "ready");
735  }
736  if (tmp != NULL)
737  omapi_io_dereference(&tmp, MDL);
738 
739  } else {
740 
741  if (prev != NULL) {
742  omapi_io_dereference(&prev, MDL);
743  }
744  omapi_io_reference(&prev, io, MDL);
745  }
746 
747  /*
748  * Equivalent to:
749  * io = io->next
750  * But using our reference counting voodoo.
751  */
752  next = NULL;
753  if (io->next != NULL) {
754  omapi_io_reference(&next, io->next, MDL);
755  }
756  omapi_io_dereference(&io, MDL);
757  if (next != NULL) {
758  omapi_io_reference(&io, next, MDL);
759  omapi_io_dereference(&next, MDL);
760  }
761  }
762  if (prev != NULL) {
763  omapi_io_dereference(&prev, MDL);
764  }
765 
766  return ISC_R_SUCCESS;
767 }
768 
770  omapi_object_t *id,
771  omapi_data_string_t *name,
772  omapi_typed_data_t *value)
773 {
774  if (h -> type != omapi_type_io_object)
775  return DHCP_R_INVALIDARG;
776 
777  if (h -> inner && h -> inner -> type -> set_value)
778  return (*(h -> inner -> type -> set_value))
779  (h -> inner, id, name, value);
780  return ISC_R_NOTFOUND;
781 }
782 
784  omapi_object_t *id,
785  omapi_data_string_t *name,
786  omapi_value_t **value)
787 {
788  if (h -> type != omapi_type_io_object)
789  return DHCP_R_INVALIDARG;
790 
791  if (h -> inner && h -> inner -> type -> get_value)
792  return (*(h -> inner -> type -> get_value))
793  (h -> inner, id, name, value);
794  return ISC_R_NOTFOUND;
795 }
796 
797 /* omapi_io_destroy (object, MDL);
798  *
799  * Find the requested IO [object] and remove it from the list of io
800  * states, causing the cleanup functions to destroy it. Note that we must
801  * hold a reference on the object while moving its ->next reference and
802  * removing the reference in the chain to the target object...otherwise it
803  * may be cleaned up from under us.
804  */
805 isc_result_t omapi_io_destroy (omapi_object_t *h, const char *file, int line)
806 {
807  omapi_io_object_t *obj = NULL, *p, *last = NULL, **holder;
808 
809  if (h -> type != omapi_type_io_object)
810  return DHCP_R_INVALIDARG;
811 
812  /* remove from the list of I/O states */
813  for (p = omapi_io_states.next; p; p = p -> next) {
814  if (p == (omapi_io_object_t *)h) {
815  omapi_io_reference (&obj, p, MDL);
816 
817  if (last)
818  holder = &last -> next;
819  else
820  holder = &omapi_io_states.next;
821 
822  omapi_io_dereference (holder, MDL);
823 
824  if (obj -> next) {
825  omapi_io_reference (holder, obj -> next, MDL);
826  omapi_io_dereference (&obj -> next, MDL);
827  }
828 
829  return omapi_io_dereference (&obj, MDL);
830  }
831  last = p;
832  }
833 
834  return ISC_R_NOTFOUND;
835 }
836 
838  const char *name, va_list ap)
839 {
840  if (h -> type != omapi_type_io_object)
841  return DHCP_R_INVALIDARG;
842 
843  if (h -> inner && h -> inner -> type -> signal_handler)
844  return (*(h -> inner -> type -> signal_handler)) (h -> inner,
845  name, ap);
846  return ISC_R_NOTFOUND;
847 }
848 
850  omapi_object_t *id,
851  omapi_object_t *i)
852 {
853  if (i -> type != omapi_type_io_object)
854  return DHCP_R_INVALIDARG;
855 
856  if (i -> inner && i -> inner -> type -> stuff_values)
857  return (*(i -> inner -> type -> stuff_values)) (c, id,
858  i -> inner);
859  return ISC_R_SUCCESS;
860 }
861 
863  const char *name, va_list ap)
864 {
865  omapi_waiter_object_t *waiter;
866 
867  if (h -> type != omapi_type_waiter)
868  return DHCP_R_INVALIDARG;
869 
870  if (!strcmp (name, "ready")) {
871  waiter = (omapi_waiter_object_t *)h;
872  waiter -> ready = 1;
873  waiter -> waitstatus = ISC_R_SUCCESS;
874  return ISC_R_SUCCESS;
875  }
876 
877  if (!strcmp(name, "status")) {
878  waiter = (omapi_waiter_object_t *)h;
879  waiter->ready = 1;
880  waiter->waitstatus = va_arg(ap, isc_result_t);
881  return ISC_R_SUCCESS;
882  }
883 
884  if (!strcmp (name, "disconnect")) {
885  waiter = (omapi_waiter_object_t *)h;
886  waiter -> ready = 1;
887  waiter -> waitstatus = DHCP_R_CONNRESET;
888  return ISC_R_SUCCESS;
889  }
890 
891  if (h -> inner && h -> inner -> type -> signal_handler)
892  return (*(h -> inner -> type -> signal_handler)) (h -> inner,
893  name, ap);
894  return ISC_R_NOTFOUND;
895 }
896 
904 isc_result_t omapi_io_state_foreach (isc_result_t (*func) (omapi_object_t *,
905  void *),
906  void *p)
907 {
908  omapi_io_object_t *io = NULL;
909  isc_result_t status;
910  omapi_io_object_t *next = NULL;
911 
912  /*
913  * This just calls func on every inner object on the list. It would
914  * be much simpler in general case, but one of the operations could be
915  * release of the objects. Therefore we need to ref count the io and
916  * io->next pointers.
917  */
918 
919  if (omapi_io_states.next) {
921  (omapi_object_t*)omapi_io_states.next,
922  MDL);
923  }
924 
925  while(io) {
926  /* If there's a next object, save it */
927  if (io->next) {
929  (omapi_object_t*)io->next, MDL);
930  }
931  if (io->inner) {
932  status = (*func) (io->inner, p);
933  if (status != ISC_R_SUCCESS) {
934  /* Something went wrong. Let's stop using io & next pointer
935  * and bail out */
937  if (next) {
939  }
940  return status;
941  }
942  }
943  /* Update the io pointer and free the next pointer */
945  if (next) {
947  (omapi_object_t*)next,
948  MDL);
950  }
951  }
952 
953  /*
954  * The only way to get here is when next is NULL. There's no need
955  * to dereference it.
956  */
957  return ISC_R_SUCCESS;
958 }
isc_boolean_t closed
Definition: omapip_p.h:211
return DHCP_R_INVALIDARG
Definition: parse.c:1222
isc_result_t omapi_reregister_io_object(omapi_object_t *, int(*)(omapi_object_t *), int(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *))
const char int line
Definition: dhcpd.h:3782
isc_result_t omapi_register_io_object(omapi_object_t *, int(*)(omapi_object_t *), int(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *), isc_result_t(*)(omapi_object_t *))
struct eventqueue * rw_queue_empty
Definition: dispatch.c:37
isc_result_t(* reader)(omapi_object_t *)
Definition: omapip_p.h:207
isc_result_t omapi_object_reference(omapi_object_t **, omapi_object_t *, const char *, int)
Definition: alloc.c:571
isc_result_t omapi_io_signal_handler(omapi_object_t *, const char *, va_list)
Definition: dispatch.c:837
#define MDL
Definition: omapip.h:567
isc_result_t omapi_dispatch(struct timeval *)
Definition: dispatch.c:414
dhcp_context_t dhcp_gbl_ctx
Definition: isclib.c:33
omapi_typed_data_t * value
Definition: omapip.h:90
isc_result_t omapi_signal_in(omapi_object_t *, const char *,...)
Definition: support.c:285
return ISC_R_SUCCESS
Definition: parse.c:1341
p
Definition: options.c:1628
int log_error(const char *,...) __attribute__((__format__(__printf__
#define OMAPI_OBJECT_ALLOC(name, stype, type)
Definition: omapip.h:160
log_fatal("no memory for uname information.")
isc_socketmgr_t * socketmgr
Definition: isclib.h:97
isc_result_t omapi_io_state_foreach(isc_result_t(*func)(omapi_object_t *, void *), void *p)
calls a given function on every object
Definition: dispatch.c:904
isc_result_t(* reaper)(omapi_object_t *)
Definition: omapip_p.h:209
struct __omapi_io_object * next
Definition: omapip_p.h:204
void(* handler)(void *)
Definition: dhcpd.h:1451
isc_result_t omapi_get_value_str(omapi_object_t *, omapi_object_t *, const char *, omapi_value_t **)
Definition: support.c:482
isc_result_t(* writer)(omapi_object_t *)
Definition: omapip_p.h:208
struct eventqueue * next
Definition: dhcpd.h:1450
if(parse_ip_addr(cfile,&match->addr))
Definition: parse.c:532
isc_result_t omapi_waiter_signal_handler(omapi_object_t *, const char *, va_list)
Definition: dispatch.c:862
isc_result_t omapi_object_dereference(omapi_object_t **, const char *, int)
Definition: alloc.c:593
void unregister_eventhandler(struct eventqueue **, void(*handler)(void *))
Definition: dispatch.c:70
isc_result_t waitstatus
Definition: omapip_p.h:224
void trigger_event(struct eventqueue **)
Definition: dispatch.c:91
void * dmalloc(size_t, const char *, int)
Definition: alloc.c:57
isc_socket_t * fd
Definition: omapip_p.h:210
isc_result_t omapi_io_stuff_values(omapi_object_t *, omapi_object_t *, omapi_object_t *)
Definition: dispatch.c:849
dfree(uname, MDL)
isc_result_t omapi_value_dereference(omapi_value_t **, const char *, int)
Definition: alloc.c:1060
struct timeval cur_tv
Definition: dispatch.c:35
void register_eventhandler(struct eventqueue **, void(*handler)(void *))
isc_result_t omapi_wait_for_completion(omapi_object_t *, struct timeval *)
Definition: dispatch.c:420
isc_task_t * task
Definition: isclib.h:96
isc_result_t omapi_unregister_io_object(omapi_object_t *)
Definition: dispatch.c:355
omapi_object_type_t * omapi_type_io_object
Definition: support.c:35
return ISC_R_NOTFOUND
Definition: parse.c:1336
isc_result_t omapi_one_dispatch(omapi_object_t *, struct timeval *)
Definition: dispatch.c:479
isc_result_t omapi_io_destroy(omapi_object_t *, const char *, int)
Definition: dispatch.c:805
int omapi_iscsock_cb(isc_task_t *task, isc_socket_t *socket, void *cbarg, int flags)
Definition: dispatch.c:120
#define DHCP_R_CONNRESET
Definition: result.h:76
isc_result_t omapi_io_set_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_typed_data_t *)
Definition: dispatch.c:769
const char * file
Definition: dhcpd.h:3782
isc_result_t omapi_io_get_value(omapi_object_t *, omapi_object_t *, omapi_data_string_t *, omapi_value_t **)
Definition: dispatch.c:783
int(* writefd)(omapi_object_t *)
Definition: omapip_p.h:206
omapi_object_type_t * omapi_type_waiter
Definition: support.c:40
int(* readfd)(omapi_object_t *)
Definition: omapip_p.h:205