Remove the olsr-specific duplicated types
[olsrd.git] / src / net_olsr.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon(olsrd)
3  * Copyright (c) 2004, Andreas Tonnesen(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  */
40
41 #include "net_olsr.h"
42 #include "ipcalc.h"
43 #include "log.h"
44 #include "olsr.h"
45 #include "net_os.h"
46 #include "print_packet.h"
47 #include "link_set.h"
48 #include "lq_packet.h"
49
50 #include <stdlib.h>
51 #include <assert.h>
52 #include <limits.h>
53 #include <errno.h>
54
55 bool disp_pack_out = false;
56
57
58 #ifdef 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 /*
91  * Converts each invalid IP-address from string to network byte order
92  * and adds it to the invalid list.
93  */
94 void
95 init_net(void)
96 {
97   const char * const *defaults = olsr_cnf->ip_version == AF_INET ? deny_ipv4_defaults : deny_ipv6_defaults;
98   
99   for (; *defaults != NULL; defaults++) {
100     union olsr_ip_addr addr;
101     if (inet_pton(olsr_cnf->ip_version, *defaults, &addr) <= 0){
102       fprintf(stderr, "Error converting fixed IP %s for deny rule!!\n", *defaults);
103       continue;
104     }
105     olsr_add_invalid_address(&addr);
106   }
107   avl_init(&filter_tree, avl_comp_default);
108 }
109
110 /**
111  * Create an outputbuffer for the given interface. This
112  * function will allocate the needed storage according 
113  * to the MTU of the interface.
114  *
115  * @param ifp the interface to create a buffer for
116  *
117  * @return 0 on success, negative if a buffer already existed
118  *  for the given interface
119  */ 
120 int
121 net_add_buffer(struct interface *ifp)
122 {
123   /* Can the interfaces MTU actually change? If not, we can elimiate
124    * the "bufsize" field in "struct olsr_netbuf".
125    */
126   if (ifp->netbuf.bufsize != ifp->int_mtu && ifp->netbuf.buff != NULL) {
127     free(ifp->netbuf.buff);
128     ifp->netbuf.buff = NULL;
129   }
130   
131   if (ifp->netbuf.buff == NULL) {
132     ifp->netbuf.buff = olsr_malloc(ifp->int_mtu, "add_netbuff");
133   }
134
135   /* Fill struct */
136   ifp->netbuf.bufsize = ifp->int_mtu;
137   ifp->netbuf.maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
138
139   ifp->netbuf.pending = 0;
140   ifp->netbuf.reserved = 0;
141
142   return 0;
143 }
144
145 /**
146  * Remove a outputbuffer. Frees the allocated memory.
147  *
148  * @param ifp the interface corresponding to the buffer
149  * to remove
150  *
151  * @return 0 on success, negative if no buffer is found
152  */
153 void
154 net_remove_buffer(struct interface *ifp)
155 {
156   /* Flush pending data */
157   if (ifp->netbuf.pending != 0) {
158     net_output(ifp);
159   }
160   free(ifp->netbuf.buff);
161   ifp->netbuf.buff = NULL;
162 }
163
164 #if 0
165 /**
166  * Reserve space in a outputbuffer. This should only be needed
167  * in very special cases. This will decrease the reported size
168  * of the buffer so that there is always <i>size</i> bytes
169  * of data available in the buffer. To add data in the reserved
170  * area one must use the net_outbuffer_push_reserved function.
171  *
172  * @param ifp the interface corresponding to the buffer
173  * to reserve space on
174  * @param size the number of bytes to reserve
175  *
176  * @return 0 on success, negative if there was not enough
177  *  bytes to reserve
178  */
179 int
180 net_reserve_bufspace(struct interface *ifp, int size)
181 {
182   if (size > ifp->netbuf.maxsize) {
183     return -1;
184   }
185   ifp->netbuf.reserved = size;
186   ifp->netbuf.maxsize -= size;
187   
188   return 0;
189 }
190 #endif
191
192 /**
193  * Add data to a buffer.
194  *
195  * @param ifp the interface corresponding to the buffer
196  * @param data a pointer to the data to add
197  * @param size the number of byte to copy from data
198  *
199  * @return -1 if no buffer was found, 0 if there was not 
200  *  enough room in buffer or the number of bytes added on 
201  *  success
202  */
203 int
204 net_outbuffer_push(struct interface *ifp, const void *data, const uint16_t size)
205 {
206   if (ifp->netbuf.pending + size > ifp->netbuf.maxsize) {
207     return 0;
208   }
209   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
210   ifp->netbuf.pending += size;
211
212   return size;
213 }
214
215 #if 0
216 /**
217  * Add data to the reserved part of a buffer
218  *
219  * @param ifp the interface corresponding to the buffer
220  * @param data a pointer to the data to add
221  * @param size the number of byte to copy from data
222  *
223  * @return -1 if no buffer was found, 0 if there was not 
224  *  enough room in buffer or the number of bytes added on 
225  *  success
226  */
227 int
228 net_outbuffer_push_reserved(struct interface *ifp, const void *data, const uint16_t size)
229 {
230   if (ifp->netbuf.pending + size > ifp->netbuf.maxsize + ifp->netbuf.reserved) {
231     return 0;
232   }
233   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
234   ifp->netbuf.pending += size;
235
236   return size;
237 }
238 #endif
239
240 /**
241  * Add a packet transform function. Theese are functions
242  * called just prior to sending data in a buffer.
243  *
244  * @param f the function pointer
245  *
246  * @returns 1
247  */
248 void
249 add_ptf(packet_transform_function f)
250 {
251   struct ptf *new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
252
253   new_ptf->function = f;
254   new_ptf->next = ptf_list;
255   ptf_list = new_ptf;
256 }
257
258 /**
259  * Remove a packet transform function
260  *
261  * @param f the function pointer
262  *
263  * @returns 1 if a functionpointer was removed
264  *  0 if not
265  */
266 int
267 del_ptf(packet_transform_function f)
268 {
269   struct ptf *prev, *tmp_ptf;
270   for (prev = NULL, tmp_ptf = ptf_list;
271        tmp_ptf != NULL;
272        prev = tmp_ptf, tmp_ptf = tmp_ptf->next) {
273     if (tmp_ptf->function == f) {
274       /* Remove entry */
275       if (prev == NULL) {
276         ptf_list = tmp_ptf->next;
277       } else {
278         prev->next = tmp_ptf->next;
279       }
280       free(tmp_ptf);
281       return 1;
282     }
283   }
284   return 0;
285 }
286
287 /**
288  *Sends a packet on a given interface.
289  *
290  *@param ifp the interface to send on.
291  *
292  *@return negative on error
293  */
294 int
295 net_output(struct interface *ifp)
296 {
297   union {
298     struct sockaddr sin;
299     struct sockaddr_in sin4;
300     struct sockaddr_in6 sin6;
301   } dstaddr;
302   int dstaddr_size;
303   struct ptf *tmp_ptf;
304   union olsr_packet *outmsg;
305   int retval;
306
307   if (ifp->netbuf.pending == 0) {
308     return 0;
309   }
310
311   ifp->netbuf.pending += OLSR_HEADERSIZE;
312
313   retval = ifp->netbuf.pending;
314
315   outmsg = (union olsr_packet *)ifp->netbuf.buff;
316   /* Add the Packet seqno */
317   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
318   /* Set the packetlength */
319   outmsg->v4.olsr_packlen = htons(ifp->netbuf.pending);
320
321   if (olsr_cnf->ip_version == AF_INET) {
322     /* IP version 4 */
323
324     /* Copy sin */
325     dstaddr.sin4 = ifp->int_broadaddr;
326     if (dstaddr.sin4.sin_port == 0) {
327       dstaddr.sin4.sin_port = htons(OLSRPORT);
328     }
329     dstaddr_size = sizeof(dstaddr.sin4);
330   } else {
331     /* IP version 6 */
332     /* Copy sin */
333     dstaddr.sin6 = ifp->int6_multaddr;
334    /* No port number???? */
335     dstaddr_size = sizeof(dstaddr.sin6);
336   }
337
338   /*
339    * Call possible packet transform functions registered by plugins  
340    */
341   for (tmp_ptf = ptf_list; tmp_ptf != NULL; tmp_ptf = tmp_ptf->next) {
342     tmp_ptf->function(ifp->netbuf.buff, &ifp->netbuf.pending);
343   }
344
345   /*
346    * if the -dispout option was given
347    * we print the content of the packets
348    */
349   if (disp_pack_out) {
350     print_olsr_serialized_packet(stdout,
351                                  (union olsr_packet *)ifp->netbuf.buff, 
352                                  ifp->netbuf.pending, &ifp->ip_addr); 
353   }
354   if (olsr_sendto(ifp->olsr_socket, 
355                   ifp->netbuf.buff, 
356                   ifp->netbuf.pending, 
357                   MSG_DONTROUTE, 
358                   &dstaddr.sin,
359                   dstaddr_size) < 0) {
360     const int save_errno = errno;
361 #if 1
362     char sabuf[1024];
363     dstaddr.sin.sa_family = olsr_cnf->ip_version;
364     fprintf(stderr, "OLSR: sendto IPv%d: %s\n", olsr_cnf->ip_version == AF_INET ? 4 : 6, strerror(save_errno));
365     fprintf(stderr, "To: %s (size: %d)\n", sockaddr_to_string(sabuf, sizeof(sabuf), &dstaddr.sin, dstaddr_size), dstaddr_size);
366     fprintf(stderr, "Socket: %d interface: %d/%s\n", ifp->olsr_socket, ifp->if_index, ifp->int_name);
367     fprintf(stderr, "Outputsize: %d\n", ifp->netbuf.pending);
368 #endif
369     olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv%d: %s", olsr_cnf->ip_version == AF_INET ? 4 : 6, strerror(save_errno));
370     retval = -1;
371   }
372   
373   ifp->netbuf.pending = 0;
374
375   /*
376    * if we've just transmitted a TC message, let Dijkstra use the current
377    * link qualities for the links to our neighbours
378    */
379
380   lq_tc_pending = false;
381   return retval;
382 }
383
384 /*
385  * Adds the given IP-address to the invalid list. 
386  */
387 void
388 olsr_add_invalid_address(const union olsr_ip_addr *addr)
389 {
390   struct ipaddr_str buf;
391   struct filter_entry *filter;
392
393   /*
394    * Check first if the address already exists.
395    */
396   if (!olsr_validate_address(addr)) {
397     return;
398   }
399
400   filter = olsr_malloc(sizeof(struct filter_entry), "Add filter address");
401
402   filter->filter_addr = *addr;
403   filter->filter_node.key = &filter->filter_addr;
404   avl_insert(&filter_tree, &filter->filter_node, AVL_DUP_NO);
405
406   OLSR_PRINTF(1, "Added %s to filter set\n",
407               olsr_ip_to_string(&buf, &filter->filter_addr));
408 }
409
410
411 bool
412 olsr_validate_address(const union olsr_ip_addr *addr)
413 {
414   const struct filter_entry *filter = filter_tree2filter(avl_find(&filter_tree, addr));
415                               
416   if (filter) {
417     struct ipaddr_str buf;
418     OLSR_PRINTF(1, "Validation of address %s failed!\n",
419                 olsr_ip_to_string(&buf, addr));
420     return false;
421   }
422   return true;
423 }
424
425 /*
426  * Local Variables:
427  * c-basic-offset: 2
428  * indent-tabs-mode: nil
429  * End:
430  */