Merge pull request #78 from ffontaine/master
[olsrd.git] / src / net_olsr.c
1 /*
2  * The olsr.org Optimized Link-State Routing daemon (olsrd)
3  *
4  * (c) by the OLSR project
5  *
6  * See our Git repository to find out who worked on this file
7  * and thus is a copyright holder on it.
8  *
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  *   notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above copyright
18  *   notice, this list of conditions and the following disclaimer in
19  *   the documentation and/or other materials provided with the
20  *   distribution.
21  * * Neither the name of olsr.org, olsrd nor the names of its
22  *   contributors may be used to endorse or promote products derived
23  *   from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *
38  * Visit http://www.olsr.org for more information.
39  *
40  * If you find this software useful feel free to make a donation
41  * to the project. For more information see the website or contact
42  * the copyright holders.
43  *
44  */
45
46 #include "net_olsr.h"
47 #include "ipcalc.h"
48 #include "log.h"
49 #include "olsr.h"
50 #include "net_os.h"
51 #include "link_set.h"
52 #include "lq_packet.h"
53
54 #include <stdlib.h>
55 #include <assert.h>
56 #include <limits.h>
57
58 #ifdef _WIN32
59 #define perror(x) WinSockPError(x)
60 void WinSockPError(const char *);
61 #endif /* _WIN32 */
62
63 struct deny_address_entry {
64   union olsr_ip_addr addr;
65   struct deny_address_entry *next;
66 };
67
68 /* Packet transform functions */
69
70 struct ptf {
71   packet_transform_function function;
72   struct ptf *next;
73 };
74
75 static struct ptf *ptf_list;
76
77 static struct deny_address_entry *deny_entries;
78
79 static const char *const deny_ipv4_defaults[] = {
80   "0.0.0.0",
81   "127.0.0.1",
82   NULL
83 };
84
85 static const char *const deny_ipv6_defaults[] = {
86   "0::0",
87   "0::1",
88   NULL
89 };
90
91 /*
92  * Converts each invalid IP-address from string to network byte order
93  * and adds it to the invalid list.
94  *
95  * TODO: rename function
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   for (; *defaults != NULL; defaults++) {
103     union olsr_ip_addr addr;
104     if (inet_pton(olsr_cnf->ip_version, *defaults, &addr) <= 0) {
105       fprintf(stderr, "Error converting fixed IP %s for deny rule!!\n", *defaults);
106       continue;
107     }
108     olsr_add_invalid_address(&addr);
109   }
110 }
111
112 /**
113  * Create an outputbuffer for the given interface. This
114  * function will allocate the needed storage according
115  * to the MTU of the interface.
116  *
117  * @param ifp the interface to create a buffer for
118  *
119  * @return 0 on success, negative if a buffer already existed
120  *  for the given interface
121  */
122 int
123 net_add_buffer(struct interface_olsr *ifp)
124 {
125   /* Can the interfaces MTU actually change? If not, we can elimiate
126    * the "bufsize" field in "struct olsr_netbuf".
127    */
128   if (ifp->netbuf.bufsize != ifp->int_mtu && ifp->netbuf.buff != NULL) {
129     free(ifp->netbuf.buff);
130     ifp->netbuf.buff = NULL;
131   }
132
133   if (ifp->netbuf.buff == NULL) {
134     ifp->netbuf.buff = olsr_malloc(ifp->int_mtu, "add_netbuff");
135   }
136
137   /* Fill struct */
138   ifp->netbuf.bufsize = ifp->int_mtu;
139   ifp->netbuf.maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
140
141   ifp->netbuf.pending = 0;
142   ifp->netbuf.reserved = 0;
143
144   return 0;
145 }
146
147 /**
148  * Remove a outputbuffer. Frees the allocated memory.
149  *
150  * @param ifp the interface corresponding to the buffer
151  * to remove
152  *
153  * @return 0 on success, negative if no buffer is found
154  */
155 int
156 net_remove_buffer(struct interface_olsr *ifp)
157 {
158   /* Flush pending data */
159   if (ifp->netbuf.pending)
160     net_output(ifp);
161
162   free(ifp->netbuf.buff);
163   ifp->netbuf.buff = NULL;
164
165   return 0;
166 }
167
168 /**
169  * Reserve space in a outputbuffer. This should only be needed
170  * in very special cases. This will decrease the reported size
171  * of the buffer so that there is always <i>size</i> bytes
172  * of data available in the buffer. To add data in the reserved
173  * area one must use the net_outbuffer_push_reserved function.
174  *
175  * @param ifp the interface corresponding to the buffer
176  * to reserve space on
177  * @param size the number of bytes to reserve
178  *
179  * @return 0 on success, negative if there was not enough
180  *  bytes to reserve
181  */
182 int
183 net_reserve_bufspace(struct interface_olsr *ifp, int size)
184 {
185   if (size > ifp->netbuf.maxsize)
186     return -1;
187
188   ifp->netbuf.reserved = size;
189   ifp->netbuf.maxsize -= size;
190
191   return 0;
192 }
193
194 /**
195  * Returns the number of bytes pending in the buffer. That
196  * is the number of bytes added but not sent.
197  *
198  * @param ifp the interface corresponding to the buffer
199  *
200  * @return the number of bytes currently pending
201  */
202 uint16_t
203 net_output_pending(const struct interface_olsr * ifp)
204 {
205   return ifp->netbuf.pending;
206 }
207
208 /**
209  * Add data to a buffer.
210  *
211  * @param ifp the interface corresponding to the buffer
212  * @param data a pointer to the data to add
213  * @param size the number of byte to copy from data
214  *
215  * @return -1 if no buffer was found, 0 if there was not
216  *  enough room in buffer or the number of bytes added on
217  *  success
218  */
219 int
220 net_outbuffer_push(struct interface_olsr *ifp, const void *data, const uint16_t size)
221 {
222   if ((ifp->netbuf.pending + size) > ifp->netbuf.maxsize)
223     return 0;
224
225   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
226   ifp->netbuf.pending += size;
227
228   return size;
229 }
230
231 /**
232  * Add data to the reserved part of a buffer
233  *
234  * @param ifp the interface corresponding to the buffer
235  * @param data a pointer to the data to add
236  * @param size the number of byte to copy from data
237  *
238  * @return -1 if no buffer was found, 0 if there was not
239  *  enough room in buffer or the number of bytes added on
240  *  success
241  */
242 int
243 net_outbuffer_push_reserved(struct interface_olsr *ifp, const void *data, const uint16_t size)
244 {
245   if ((ifp->netbuf.pending + size) > (ifp->netbuf.maxsize + ifp->netbuf.reserved))
246     return 0;
247
248   memcpy(&ifp->netbuf.buff[ifp->netbuf.pending + OLSR_HEADERSIZE], data, size);
249   ifp->netbuf.pending += size;
250
251   return size;
252 }
253
254 /**
255  * Report the number of bytes currently available in the buffer
256  * (not including possible reserved bytes)
257  *
258  * @param ifp the interface corresponding to the buffer
259  *
260  * @return the number of bytes available in the buffer or
261  */
262 int
263 net_outbuffer_bytes_left(const struct interface_olsr *ifp)
264 {
265   /* IPv6 minimum MTU - IPv6 header - UDP header - VLAN-Tag */
266   static int MAX_REMAINING = 1280 - 40 - 8 - 4;
267   int remaining = ifp->netbuf.maxsize - ifp->netbuf.pending;
268
269   if (remaining > MAX_REMAINING) {
270     return MAX_REMAINING;
271   }
272   return remaining;
273 }
274
275 /**
276  * Add a packet transform function. Theese are functions
277  * called just prior to sending data in a buffer.
278  *
279  * @param f the function pointer
280  *
281  * @returns 1
282  */
283 int
284 add_ptf(packet_transform_function f)
285 {
286
287   struct ptf *new_ptf;
288
289   new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
290
291   new_ptf->next = ptf_list;
292   new_ptf->function = f;
293
294   ptf_list = new_ptf;
295
296   return 1;
297 }
298
299 /**
300  * Remove a packet transform function
301  *
302  * @param f the function pointer
303  *
304  * @returns 1 if a functionpointer was removed
305  *  0 if not
306  */
307 int
308 del_ptf(packet_transform_function f)
309 {
310   struct ptf *prev = NULL;
311   struct ptf *tmp_ptf = ptf_list;
312   while (tmp_ptf) {
313     if (tmp_ptf->function == f) {
314       /* Remove entry */
315       if (prev == NULL)
316         ptf_list = tmp_ptf->next;
317       else
318         prev->next = tmp_ptf->next;
319       free(tmp_ptf);
320       return 1;
321     }
322     prev = tmp_ptf;
323     tmp_ptf = tmp_ptf->next;
324   }
325
326   return 0;
327 }
328
329 /**
330  *Sends a packet on a given interface.
331  *
332  *@param ifp the interface to send on.
333  *
334  *@return negative on error
335  */
336 int
337 net_output(struct interface_olsr *ifp)
338 {
339   struct sockaddr_in *sin = NULL;
340   struct sockaddr_in6 *sin6 = NULL;
341   struct sockaddr_in dst;
342   struct sockaddr_in6 dst6;
343   struct ptf *tmp_ptf_list;
344   union olsr_packet *outmsg;
345   int retval;
346
347   if (!ifp->netbuf.pending)
348     return 0;
349
350   ifp->netbuf.pending += OLSR_HEADERSIZE;
351
352   retval = ifp->netbuf.pending;
353
354   outmsg = (union olsr_packet *)ifp->netbuf.buff;
355   /* Add the Packet seqno */
356   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
357   /* Set the packetlength */
358   outmsg->v4.olsr_packlen = htons(ifp->netbuf.pending);
359
360   if (olsr_cnf->ip_version == AF_INET) {
361     /* IP version 4 */
362     sin = (struct sockaddr_in *)&ifp->int_broadaddr;
363
364     /* Copy sin */
365     dst = *sin;
366     sin = &dst;
367
368     if (sin->sin_port == 0)
369       sin->sin_port = htons(olsr_cnf->olsrport);
370   } else {
371     /* IP version 6 */
372     sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
373     /* Copy sin */
374     dst6 = *sin6;
375     sin6 = &dst6;
376   }
377
378   /*
379    *Call possible packet transform functions registered by plugins
380    */
381   for (tmp_ptf_list = ptf_list; tmp_ptf_list != NULL; tmp_ptf_list = tmp_ptf_list->next) {
382     tmp_ptf_list->function(ifp->netbuf.buff, &ifp->netbuf.pending);
383   }
384
385   if (olsr_cnf->ip_version == AF_INET) {
386     /* IP version 4 */
387     if (olsr_sendto(ifp->send_socket, ifp->netbuf.buff, ifp->netbuf.pending, MSG_DONTROUTE, (struct sockaddr *)sin, sizeof(*sin)) <
388         0) {
389       perror("sendto(v4)");
390 #ifndef _WIN32
391       olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 '%s' on interface %s", strerror(errno), ifp->int_name);
392 #endif /* _WIN32 */
393       retval = -1;
394     }
395   } else {
396     /* IP version 6 */
397     if (olsr_sendto(ifp->send_socket, ifp->netbuf.buff, ifp->netbuf.pending, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof(*sin6))
398         < 0) {
399       struct ipaddr_str buf;
400       perror("sendto(v6)");
401 #ifndef _WIN32
402       olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 '%s' on interface %s", strerror(errno), ifp->int_name);
403 #endif /* _WIN32 */
404       fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_index);
405       fprintf(stderr, "To: %s (size: %u)\n", ip6_to_string(&buf, &sin6->sin6_addr), (unsigned int)sizeof(*sin6));
406       fprintf(stderr, "Outputsize: %d\n", ifp->netbuf.pending);
407       retval = -1;
408     }
409   }
410
411   ifp->netbuf.pending = 0;
412
413   /*
414    * if we've just transmitted a TC message, let Dijkstra use the current
415    * link qualities for the links to our neighbours
416    */
417
418   lq_tc_pending = false;
419
420   return retval;
421 }
422
423 /*
424  * Adds the given IP-address to the invalid list.
425  */
426 void
427 olsr_add_invalid_address(const union olsr_ip_addr *adr)
428 {
429   struct ipaddr_str buf;
430   struct deny_address_entry *new_entry = olsr_malloc(sizeof(struct deny_address_entry), "Add deny address");
431
432   new_entry->addr = *adr;
433   new_entry->next = deny_entries;
434   deny_entries = new_entry;
435   OLSR_PRINTF(1, "Added %s to IP deny set\n", olsr_ip_to_string(&buf, &new_entry->addr));
436 }
437
438 bool
439 olsr_validate_address(const union olsr_ip_addr *adr)
440 {
441   const struct deny_address_entry *deny_entry;
442
443   for (deny_entry = deny_entries; deny_entry != NULL; deny_entry = deny_entry->next) {
444     if (ipequal(adr, &deny_entry->addr)) {
445       struct ipaddr_str buf;
446       OLSR_PRINTF(1, "Validation of address %s failed!\n", olsr_ip_to_string(&buf, adr));
447       return false;
448     }
449     if (&deny_entry->addr == &olsr_cnf->main_addr)
450       break;
451   }
452   return true;
453 }
454
455 /*
456  * Local Variables:
457  * c-basic-offset: 2
458  * indent-tabs-mode: nil
459  * End:
460  */