* provide an argument to the tiems(2) call - OpenBSD seems to barf on a NULL there
[olsrd.git] / src / socket_parser.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas T√łnnesen(andreto@olsr.org)
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without 
7  * modification, are permitted provided that the following conditions 
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright 
11  *   notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright 
13  *   notice, this list of conditions and the following disclaimer in 
14  *   the documentation and/or other materials provided with the 
15  *   distribution.
16  * * Neither the name of olsr.org, olsrd nor the names of its 
17  *   contributors may be used to endorse or promote products derived 
18  *   from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Visit http://www.olsr.org for more information.
34  *
35  * If you find this software useful feel free to make a donation
36  * to the project. For more information see the website or contact
37  * the copyright holders.
38  *
39  * $Id: socket_parser.c,v 1.26 2007/05/02 08:07:11 bernd67 Exp $
40  */
41
42 #include <unistd.h>
43 #include "socket_parser.h"
44 #include "olsr.h"
45 #include "defs.h"
46 #include "log.h"
47 #include "net_os.h"
48
49 #ifdef WIN32
50 #undef EINTR
51 #define EINTR WSAEINTR
52 #undef errno
53 #define errno WSAGetLastError()
54 #undef strerror
55 #define strerror(x) StrError(x)
56 #endif
57
58
59 struct olsr_socket_entry *olsr_socket_entries;
60
61 static int hfd = 0;
62
63 static struct timeval tvp = {0, 0};
64 static fd_set ibits;
65
66 /**
67  * Add a socket and handler to the socketset
68  * beeing used in the main select(2) loop
69  * in listen_loop
70  *
71  *@param fd the socket
72  *@param pf the processing function
73  */
74 void
75 add_olsr_socket(int fd, void(*pf)(int))
76 {
77   struct olsr_socket_entry *new_entry;
78
79   if((fd == 0) || (pf == NULL))
80     {
81       fprintf(stderr, "Bogus socket entry - not registering...\n");
82       return;
83     }
84   OLSR_PRINTF(2, "Adding OLSR socket entry %d\n", fd);
85
86   new_entry = olsr_malloc(sizeof(struct olsr_socket_entry), "Socket entry");
87
88   new_entry->fd = fd;
89   new_entry->process_function = pf;
90
91   /* Queue */
92   new_entry->next = olsr_socket_entries;
93   olsr_socket_entries = new_entry;
94
95   if(fd + 1 > hfd)
96     hfd = fd + 1;
97 }
98
99 /**
100  * Remove a socket and handler to the socketset
101  * beeing used in the main select(2) loop
102  * in listen_loop
103  *
104  *@param fd the socket
105  *@param pf the processing function
106  */
107 int
108 remove_olsr_socket(int fd, void(*pf)(int))
109 {
110   struct olsr_socket_entry *entry, *prev_entry;
111
112   if((fd == 0) || (pf == NULL))
113     {
114       olsr_syslog(OLSR_LOG_ERR, "Bogus socket entry - not processing...\n");
115       return 0;
116     }
117   OLSR_PRINTF(1, "Removing OLSR socket entry %d\n", fd);
118
119   entry = olsr_socket_entries;
120   prev_entry = NULL;
121
122   while(entry)
123     {
124       if((entry->fd == fd) && (entry->process_function == pf))
125         {
126           if(prev_entry == NULL)
127             {
128               olsr_socket_entries = entry->next;
129               free(entry);
130             }
131           else
132             {
133               prev_entry->next = entry->next;
134               free(entry);
135             }
136
137           if(hfd == fd + 1)
138             {
139               /* Re-calculate highest FD */
140               entry = olsr_socket_entries;
141               hfd = 0;
142               while(entry)
143                 {
144                   if(entry->fd + 1 > hfd)
145                     hfd = entry->fd + 1;
146                   entry = entry->next;
147                 }
148             }
149           return 1;
150         }
151       prev_entry = entry;
152       entry = entry->next;
153     }
154
155   return 0;
156 }
157
158
159 void
160 poll_sockets(void)
161 {
162   int n;
163   struct olsr_socket_entry *olsr_sockets;
164   /* Global buffer for times(2) calls. Do not remopve since at least OpenBSD needs it. */
165   struct tms tms_buf;
166
167   /* If there are no registered sockets we
168    * do not call select(2)
169    */
170   if(hfd == 0)
171     return;
172   
173   FD_ZERO(&ibits);
174   
175   /* Adding file-descriptors to FD set */
176   
177   for(olsr_sockets = olsr_socket_entries; olsr_sockets; olsr_sockets = olsr_sockets->next)
178     {
179       FD_SET(olsr_sockets->fd, &ibits);      
180     }
181       
182   /* Runnig select on the FD set */
183   n = olsr_select(hfd, &ibits, 0, 0, &tvp);
184   
185   if(n == 0)
186     return;
187   /* Did somethig go wrong? */
188   if (n < 0) 
189     {
190       if(errno != EINTR) {
191         const char * const err_msg = strerror(errno);
192         olsr_syslog(OLSR_LOG_ERR, "select: %s", err_msg);
193         OLSR_PRINTF(1, "Error select: %s", err_msg);
194       }
195       return;
196     }
197
198   /* Update time since this is much used by the parsing functions */
199   gettimeofday(&now, NULL);
200   now_times = times(&tms_buf);
201
202   for(olsr_sockets = olsr_socket_entries;olsr_sockets;olsr_sockets = olsr_sockets->next)
203     {
204       if(FD_ISSET(olsr_sockets->fd, &ibits))
205           olsr_sockets->process_function(olsr_sockets->fd);
206     }   
207 }
208