Update to new avl/list iteration macros
[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, *iterator;
180   OLSR_FOR_ALL_FILTERS(filter, iterator) {
181     avl_delete(&filter_tree, &filter->filter_node);
182     free(filter);
183   }
184 }
185
186 /**
187  * Create an outputbuffer for the given interface. This
188  * function will allocate the needed storage according
189  * to the MTU of the interface.
190  *
191  * @param ifp the interface to create a buffer for
192  *
193  * @return 0 on success, negative if a buffer already existed
194  *  for the given interface
195  */
196 int
197 net_add_buffer(struct interface *ifp)
198 {
199   /* Can the interfaces MTU actually change? If not, we can elimiate
200    * the "bufsize" field in "struct olsr_netbuf".
201    */
202   if (ifp->netbuf.bufsize != ifp->int_mtu && ifp->netbuf.buff != NULL) {
203     free(ifp->netbuf.buff);
204     ifp->netbuf.buff = NULL;
205   }
206
207   if (ifp->netbuf.buff == NULL) {
208     ifp->netbuf.buff = olsr_malloc(ifp->int_mtu, "add_netbuff");
209   }
210
211   /* Fill struct */
212   ifp->netbuf.bufsize = ifp->int_mtu;
213   ifp->netbuf.maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
214
215   ifp->netbuf.pending = 0;
216   ifp->netbuf.reserved = 0;
217
218   return 0;
219 }
220
221 /**
222  * Remove a outputbuffer. Frees the allocated memory.
223  *
224  * @param ifp the interface corresponding to the buffer
225  * to remove
226  *
227  * @return 0 on success, negative if no buffer is found
228  */
229 void
230 net_remove_buffer(struct interface *ifp)
231 {
232   /* Flush pending data */
233   if (ifp->netbuf.pending != 0) {
234     net_output(ifp);
235   }
236   free(ifp->netbuf.buff);
237   ifp->netbuf.buff = NULL;
238 }
239
240 #if 0
241
242 /**
243  * Reserve space in a outputbuffer. This should only be needed
244  * in very special cases. This will decrease the reported size
245  * of the buffer so that there is always <i>size</i> bytes
246  * of data available in the buffer. To add data in the reserved
247  * area one must use the net_outbuffer_push_reserved function.
248  *
249  * @param ifp the interface corresponding to the buffer
250  * to reserve space on
251  * @param size the number of bytes to reserve
252  *
253  * @return 0 on success, negative if there was not enough
254  *  bytes to reserve
255  */
256 int
257 net_reserve_bufspace(struct interface *ifp, int size)
258 {
259   if (size > ifp->netbuf.maxsize) {
260     return -1;
261   }
262   ifp->netbuf.reserved = size;
263   ifp->netbuf.maxsize -= size;
264
265   return 0;
266 }
267 #endif
268
269 /**
270  * Add data to a buffer.
271  *
272  * @param ifp the interface corresponding to the buffer
273  * @param data a pointer to the data to add
274  * @param size the number of byte to copy from data
275  *
276  * @return -1 if no buffer was found, 0 if there was not
277  *  enough room in buffer or the number of bytes added on
278  *  success
279  */
280 int
281 net_outbuffer_push(struct interface *ifp, const void *data, const uint16_t size)
282 {
283   if (ifp->netbuf.pending + size > ifp->netbuf.maxsize) {
284     return 0;
285   }
286   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
287   ifp->netbuf.pending += size;
288
289   return size;
290 }
291
292 #if 0
293
294 /**
295  * Add data to the reserved part of a buffer
296  *
297  * @param ifp the interface corresponding to the buffer
298  * @param data a pointer to the data to add
299  * @param size the number of byte to copy from data
300  *
301  * @return -1 if no buffer was found, 0 if there was not
302  *  enough room in buffer or the number of bytes added on
303  *  success
304  */
305 int
306 net_outbuffer_push_reserved(struct interface *ifp, const void *data, const uint16_t size)
307 {
308   if (ifp->netbuf.pending + size > ifp->netbuf.maxsize + ifp->netbuf.reserved) {
309     return 0;
310   }
311   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
312   ifp->netbuf.pending += size;
313
314   return size;
315 }
316 #endif
317
318 /**
319  * Add a packet transform function. Theese are functions
320  * called just prior to sending data in a buffer.
321  *
322  * @param f the function pointer
323  *
324  * @returns 1
325  */
326 void
327 add_ptf(packet_transform_function f)
328 {
329   struct ptf *new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
330
331   new_ptf->function = f;
332   new_ptf->next = ptf_list;
333   ptf_list = new_ptf;
334 }
335
336 #if 0
337
338 /**
339  * Remove a packet transform function
340  *
341  * @param f the function pointer
342  *
343  * @returns 1 if a functionpointer was removed
344  *  0 if not
345  */
346 int
347 del_ptf(packet_transform_function f)
348 {
349   struct ptf *prev, *tmp_ptf;
350   for (prev = NULL, tmp_ptf = ptf_list; tmp_ptf != NULL; prev = tmp_ptf, tmp_ptf = tmp_ptf->next) {
351     if (tmp_ptf->function == f) {
352       /* Remove entry */
353       if (prev == NULL) {
354         ptf_list = tmp_ptf->next;
355       } else {
356         prev->next = tmp_ptf->next;
357       }
358       free(tmp_ptf);
359       return 1;
360     }
361   }
362   return 0;
363 }
364 #endif
365
366 /**
367  *Sends a packet on a given interface.
368  *
369  *@param ifp the interface to send on.
370  *
371  *@return negative on error
372  */
373 int
374 net_output(struct interface *ifp)
375 {
376   struct ptf *tmp_ptf;
377   struct olsr_packet *outmsg;
378   int retval;
379
380   if (ifp->netbuf.pending == 0) {
381     return 0;
382   }
383
384   ifp->netbuf.pending += OLSR_HEADERSIZE;
385
386   retval = ifp->netbuf.pending;
387
388   outmsg = (struct olsr_packet *)ifp->netbuf.buff;
389   /* Add the Packet seqno */
390   outmsg->seqno = htons(ifp->olsr_seqnum++);
391   /* Set the packetlength */
392   outmsg->size = htons(ifp->netbuf.pending);
393
394   /*
395    * Call possible packet transform functions registered by plugins
396    */
397   for (tmp_ptf = ptf_list; tmp_ptf != NULL; tmp_ptf = tmp_ptf->next) {
398     tmp_ptf->function(ifp->netbuf.buff, &ifp->netbuf.pending);
399   }
400
401   if (os_sendto(ifp->send_socket, ifp->netbuf.buff, ifp->netbuf.pending,
402       MSG_DONTROUTE, &ifp->int_multicast) < 0) {
403 #if !defined REMOVE_LOG_WARN
404     const int save_errno = errno;
405     struct ipaddr_str buf;
406 #endif
407     OLSR_WARN(LOG_NETWORKING, "sending %d bytes (IPv%d) to %s:%d on interface %s/%d: %s (%d)\n",
408             ifp->netbuf.pending, olsr_cnf->ip_version == AF_INET ? 4 : 6,
409             olsr_sockaddr_to_string(&buf, &ifp->int_multicast), ntohs(ifp->int_multicast.v4.sin_port),
410             ifp->int_name, ifp->if_index,
411             strerror(save_errno), save_errno);
412     retval = -1;
413   }
414
415   ifp->netbuf.pending = 0;
416   return retval;
417 }
418
419 /*
420  * Adds the given IP-address to the invalid list.
421  */
422 static void
423 olsr_add_invalid_address(const union olsr_ip_addr *addr)
424 {
425 #if !defined REMOVE_LOG_INFO
426   struct ipaddr_str buf;
427 #endif
428   struct filter_entry *filter;
429
430   /*
431    * Check first if the address already exists.
432    */
433   if (!olsr_validate_address(addr)) {
434     return;
435   }
436
437   filter = olsr_malloc(sizeof(struct filter_entry), "Add filter address");
438
439   filter->filter_addr = *addr;
440   filter->filter_node.key = &filter->filter_addr;
441   avl_insert(&filter_tree, &filter->filter_node);
442
443   OLSR_INFO(LOG_NETWORKING, "Added %s to filter set\n", olsr_ip_to_string(&buf, &filter->filter_addr));
444 }
445
446
447 bool
448 olsr_validate_address(const union olsr_ip_addr *addr)
449 {
450   if (avl_find(&filter_tree, addr)) {
451 #if !defined REMOVE_LOG_DEBUG
452     struct ipaddr_str buf;
453 #endif
454     OLSR_DEBUG(LOG_NETWORKING, "Validation of address %s failed!\n", olsr_ip_to_string(&buf, addr));
455     return false;
456   }
457   return true;
458 }
459
460 /*
461  * Local Variables:
462  * c-basic-offset: 2
463  * indent-tabs-mode: nil
464  * End:
465  */