Port all olsrd 0.6.0 OS specific files and adapt them to the new interface.
[olsrd.git] / src / net_olsr.c
1
2 /*
3  * The olsr.org Optimized Link-State Routing daemon(olsrd)
4  * Copyright (c) 2004-2009, the olsr.org team - see HISTORY file
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  *
11  * * Redistributions of source code must retain the above copyright
12  *   notice, this list of conditions and the following disclaimer.
13  * * Redistributions in binary form must reproduce the above copyright
14  *   notice, this list of conditions and the following disclaimer in
15  *   the documentation and/or other materials provided with the
16  *   distribution.
17  * * Neither the name of olsr.org, olsrd nor the names of its
18  *   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 COPYRIGHT HOLDERS AND CONTRIBUTORS
22  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32  * POSSIBILITY OF SUCH DAMAGE.
33  *
34  * Visit http://www.olsr.org for more information.
35  *
36  * If you find this software useful feel free to make a donation
37  * to the project. For more information see the website or contact
38  * the copyright holders.
39  *
40  */
41
42 #include "net_olsr.h"
43 #include "ipcalc.h"
44 #include "olsr.h"
45 #include "os_net.h"
46 #include "link_set.h"
47 #include "lq_packet.h"
48 #include "olsr_logging.h"
49
50 #include <stdlib.h>
51 #include <assert.h>
52 #include <limits.h>
53 #include <errno.h>
54
55 static void olsr_add_invalid_address(const union olsr_ip_addr *);
56 static void olsr_expire_buffer_timer(void *context);
57
58 #if 0                           // WIN32
59 #define perror(x) WinSockPError(x)
60 void
61   WinSockPError(const char *);
62 #endif
63
64 /*
65  * Root of the filter set.
66  */
67 static struct avl_tree filter_tree;
68
69 /* Packet transform functions */
70
71 struct ptf {
72   packet_transform_function function;
73   struct ptf *next;
74 };
75
76 static struct ptf *ptf_list;
77
78 static const char *const deny_ipv4_defaults[] = {
79   "0.0.0.0",
80   "127.0.0.1",
81   NULL
82 };
83
84 static const char *const deny_ipv6_defaults[] = {
85   "0::0",
86   "0::1",
87   NULL
88 };
89
90 /* buffer writeback timer */
91 struct olsr_timer_info *buffer_hold_timer_info;
92
93 /*
94  * Converts each invalid IP-address from string to network byte order
95  * and adds it to the invalid list.
96  */
97 void
98 init_net(void)
99 {
100   const char *const *defaults = olsr_cnf->ip_version == AF_INET ? deny_ipv4_defaults : deny_ipv6_defaults;
101
102   /* Init filter tree */
103   avl_init(&filter_tree, avl_comp_default, false, NULL);
104
105   if (*defaults) {
106     OLSR_INFO(LOG_NETWORKING, "Initializing invalid IP list.\n");
107   }
108
109   for (; *defaults != NULL; defaults++) {
110     union olsr_ip_addr addr;
111     if (inet_pton(olsr_cnf->ip_version, *defaults, &addr) <= 0) {
112       OLSR_WARN(LOG_NETWORKING, "Error converting fixed IP %s for deny rule!!\n", *defaults);
113       continue;
114     }
115     olsr_add_invalid_address(&addr);
116   }
117
118   buffer_hold_timer_info = olsr_alloc_timerinfo("Buffer writeback", olsr_expire_buffer_timer, false);
119 }
120
121 /**
122  * Wrapper for the timer callback.
123  */
124 static void
125 olsr_expire_buffer_timer(void *context)
126 {
127   struct interface *ifn;
128
129   ifn = (struct interface *)context;
130
131   /*
132    * Clear the pointer to indicate that this timer has
133    * been expired and needs to be restarted in case there
134    * will be another message queued in the future.
135    */
136   ifn->buffer_hold_timer = NULL;
137
138   /*
139    * Do we have something to emit ?
140    */
141   if (!net_output_pending(ifn)) {
142     return;
143   }
144
145   OLSR_DEBUG(LOG_NETWORKING, "Buffer Holdtimer for %s timed out, sending data.\n", ifn->int_name);
146
147   net_output(ifn);
148 }
149
150 /*
151  * set_buffer_timer
152  *
153  * Kick a hold-down timer which defers building of a message.
154  * This has the desired effect that olsr messages get bigger.
155  */
156 void
157 set_buffer_timer(struct interface *ifn)
158 {
159
160   /*
161    * Bail if there is already a timer running.
162    */
163   if (ifn->buffer_hold_timer) {
164     return;
165   }
166
167   /*
168    * This is the first message since the last time this interface has
169    * been drained. Flush the buffer in second or so.
170    */
171   ifn->buffer_hold_timer =
172     olsr_start_timer(OLSR_BUFFER_HOLD_TIME, OLSR_BUFFER_HOLD_JITTER,
173                      ifn, buffer_hold_timer_info);
174 }
175
176 void
177 deinit_netfilters(void)
178 {
179   struct filter_entry *filter;
180   struct list_iterator iterator;
181   OLSR_FOR_ALL_FILTERS(filter, iterator) {
182     avl_delete(&filter_tree, &filter->filter_node);
183     free(filter);
184   }
185 }
186
187 /**
188  * Create an outputbuffer for the given interface. This
189  * function will allocate the needed storage according
190  * to the MTU of the interface.
191  *
192  * @param ifp the interface to create a buffer for
193  *
194  * @return 0 on success, negative if a buffer already existed
195  *  for the given interface
196  */
197 int
198 net_add_buffer(struct interface *ifp)
199 {
200   /* Can the interfaces MTU actually change? If not, we can elimiate
201    * the "bufsize" field in "struct olsr_netbuf".
202    */
203   if (ifp->netbuf.bufsize != ifp->int_mtu && ifp->netbuf.buff != NULL) {
204     free(ifp->netbuf.buff);
205     ifp->netbuf.buff = NULL;
206   }
207
208   if (ifp->netbuf.buff == NULL) {
209     ifp->netbuf.buff = olsr_malloc(ifp->int_mtu, "add_netbuff");
210   }
211
212   /* Fill struct */
213   ifp->netbuf.bufsize = ifp->int_mtu;
214   ifp->netbuf.maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
215
216   ifp->netbuf.pending = 0;
217   ifp->netbuf.reserved = 0;
218
219   return 0;
220 }
221
222 /**
223  * Remove a outputbuffer. Frees the allocated memory.
224  *
225  * @param ifp the interface corresponding to the buffer
226  * to remove
227  *
228  * @return 0 on success, negative if no buffer is found
229  */
230 void
231 net_remove_buffer(struct interface *ifp)
232 {
233   /* Flush pending data */
234   if (ifp->netbuf.pending != 0) {
235     net_output(ifp);
236   }
237   free(ifp->netbuf.buff);
238   ifp->netbuf.buff = NULL;
239 }
240
241 #if 0
242
243 /**
244  * Reserve space in a outputbuffer. This should only be needed
245  * in very special cases. This will decrease the reported size
246  * of the buffer so that there is always <i>size</i> bytes
247  * of data available in the buffer. To add data in the reserved
248  * area one must use the net_outbuffer_push_reserved function.
249  *
250  * @param ifp the interface corresponding to the buffer
251  * to reserve space on
252  * @param size the number of bytes to reserve
253  *
254  * @return 0 on success, negative if there was not enough
255  *  bytes to reserve
256  */
257 int
258 net_reserve_bufspace(struct interface *ifp, int size)
259 {
260   if (size > ifp->netbuf.maxsize) {
261     return -1;
262   }
263   ifp->netbuf.reserved = size;
264   ifp->netbuf.maxsize -= size;
265
266   return 0;
267 }
268 #endif
269
270 /**
271  * Add data to a buffer.
272  *
273  * @param ifp the interface corresponding to the buffer
274  * @param data a pointer to the data to add
275  * @param size the number of byte to copy from data
276  *
277  * @return -1 if no buffer was found, 0 if there was not
278  *  enough room in buffer or the number of bytes added on
279  *  success
280  */
281 int
282 net_outbuffer_push(struct interface *ifp, const void *data, const uint16_t size)
283 {
284   if (ifp->netbuf.pending + size > ifp->netbuf.maxsize) {
285     return 0;
286   }
287   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
288   ifp->netbuf.pending += size;
289
290   return size;
291 }
292
293 #if 0
294
295 /**
296  * Add data to the reserved part of a buffer
297  *
298  * @param ifp the interface corresponding to the buffer
299  * @param data a pointer to the data to add
300  * @param size the number of byte to copy from data
301  *
302  * @return -1 if no buffer was found, 0 if there was not
303  *  enough room in buffer or the number of bytes added on
304  *  success
305  */
306 int
307 net_outbuffer_push_reserved(struct interface *ifp, const void *data, const uint16_t size)
308 {
309   if (ifp->netbuf.pending + size > ifp->netbuf.maxsize + ifp->netbuf.reserved) {
310     return 0;
311   }
312   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
313   ifp->netbuf.pending += size;
314
315   return size;
316 }
317 #endif
318
319 /**
320  * Add a packet transform function. Theese are functions
321  * called just prior to sending data in a buffer.
322  *
323  * @param f the function pointer
324  *
325  * @returns 1
326  */
327 void
328 add_ptf(packet_transform_function f)
329 {
330   struct ptf *new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
331
332   new_ptf->function = f;
333   new_ptf->next = ptf_list;
334   ptf_list = new_ptf;
335 }
336
337 #if 0
338
339 /**
340  * Remove a packet transform function
341  *
342  * @param f the function pointer
343  *
344  * @returns 1 if a functionpointer was removed
345  *  0 if not
346  */
347 int
348 del_ptf(packet_transform_function f)
349 {
350   struct ptf *prev, *tmp_ptf;
351   for (prev = NULL, tmp_ptf = ptf_list; tmp_ptf != NULL; prev = tmp_ptf, tmp_ptf = tmp_ptf->next) {
352     if (tmp_ptf->function == f) {
353       /* Remove entry */
354       if (prev == NULL) {
355         ptf_list = tmp_ptf->next;
356       } else {
357         prev->next = tmp_ptf->next;
358       }
359       free(tmp_ptf);
360       return 1;
361     }
362   }
363   return 0;
364 }
365 #endif
366
367 /**
368  *Sends a packet on a given interface.
369  *
370  *@param ifp the interface to send on.
371  *
372  *@return negative on error
373  */
374 int
375 net_output(struct interface *ifp)
376 {
377   struct ptf *tmp_ptf;
378   struct olsr_packet *outmsg;
379   int retval;
380
381   if (ifp->netbuf.pending == 0) {
382     return 0;
383   }
384
385   ifp->netbuf.pending += OLSR_HEADERSIZE;
386
387   retval = ifp->netbuf.pending;
388
389   outmsg = (struct olsr_packet *)ifp->netbuf.buff;
390   /* Add the Packet seqno */
391   outmsg->seqno = htons(ifp->olsr_seqnum++);
392   /* Set the packetlength */
393   outmsg->size = htons(ifp->netbuf.pending);
394
395   /*
396    * Call possible packet transform functions registered by plugins
397    */
398   for (tmp_ptf = ptf_list; tmp_ptf != NULL; tmp_ptf = tmp_ptf->next) {
399     tmp_ptf->function(ifp->netbuf.buff, &ifp->netbuf.pending);
400   }
401
402   if (olsr_sendto(ifp->send_socket, ifp->netbuf.buff, ifp->netbuf.pending,
403       MSG_DONTROUTE, &ifp->int_multicast) < 0) {
404 #if !defined REMOVE_LOG_WARN
405     const int save_errno = errno;
406     struct ipaddr_str buf;
407 #endif
408     OLSR_WARN(LOG_NETWORKING, "sending %d bytes (IPv%d) to %s:%d on interface %s/%d: %s (%d)\n",
409             ifp->netbuf.pending, olsr_cnf->ip_version == AF_INET ? 4 : 6,
410             olsr_sockaddr_to_string(&buf, &ifp->int_multicast), ntohs(ifp->int_multicast.v4.sin_port),
411             ifp->int_name, ifp->if_index,
412             strerror(save_errno), save_errno);
413     retval = -1;
414   }
415
416   ifp->netbuf.pending = 0;
417   return retval;
418 }
419
420 /*
421  * Adds the given IP-address to the invalid list.
422  */
423 static void
424 olsr_add_invalid_address(const union olsr_ip_addr *addr)
425 {
426 #if !defined REMOVE_LOG_INFO
427   struct ipaddr_str buf;
428 #endif
429   struct filter_entry *filter;
430
431   /*
432    * Check first if the address already exists.
433    */
434   if (!olsr_validate_address(addr)) {
435     return;
436   }
437
438   filter = olsr_malloc(sizeof(struct filter_entry), "Add filter address");
439
440   filter->filter_addr = *addr;
441   filter->filter_node.key = &filter->filter_addr;
442   avl_insert(&filter_tree, &filter->filter_node);
443
444   OLSR_INFO(LOG_NETWORKING, "Added %s to filter set\n", olsr_ip_to_string(&buf, &filter->filter_addr));
445 }
446
447
448 bool
449 olsr_validate_address(const union olsr_ip_addr *addr)
450 {
451   if (avl_find(&filter_tree, addr)) {
452 #if !defined REMOVE_LOG_DEBUG
453     struct ipaddr_str buf;
454 #endif
455     OLSR_DEBUG(LOG_NETWORKING, "Validation of address %s failed!\n", olsr_ip_to_string(&buf, addr));
456     return false;
457   }
458   return true;
459 }
460
461 /*
462  * Local Variables:
463  * c-basic-offset: 2
464  * indent-tabs-mode: nil
465  * End:
466  */