3cde165b7f3c14c09ae06a126028faded2854aa7
[olsrd.git] / src / net.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: net.c,v 1.37 2005/03/04 21:30:16 kattemat Exp $
40  */
41
42 #include "net.h"
43 #include "log.h"
44 #include "olsr.h"
45 #include "net_os.h"
46 #include <stdlib.h>
47
48 #ifdef WIN32
49 #define perror(x) WinSockPError(x)
50 void
51 WinSockPError(char *);
52 #endif
53
54
55 /* Packet transform functions */
56
57 struct ptf
58 {
59   int (*function)(char *, int *);
60   struct ptf *next;
61 };
62
63 static struct ptf *ptf_list;
64
65 struct olsr_netbuf *netbufs[MAX_IFS];
66
67 static char ipv6_buf[100]; /* for address coversion */
68
69 /**
70  * Create a outputbuffer for the given interface. This
71  * function will allocate the needed storage according 
72  * to the MTU of the interface.
73  *
74  * @param ifp the interface to create a buffer for
75  *
76  * @return 0 on success, negative if a buffer already existed
77  *  for the given interface
78  */ 
79 int
80 net_add_buffer(struct interface *ifp)
81 {
82   struct olsr_netbuf *new_buf;
83
84   /* If a buffer already exists for this interface back off */
85   if(netbufs[ifp->if_nr])
86     return -1;
87
88   new_buf = olsr_malloc(sizeof(struct olsr_netbuf), "add_netbuff1");
89   new_buf->buff = olsr_malloc(ifp->int_mtu, "add_netbuff2");
90
91   /* Fill struct */
92   new_buf->bufsize = ifp->int_mtu;
93   new_buf->if_index = ifp->if_nr;
94   new_buf->maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
95   new_buf->pending = 0;
96   new_buf->reserved = 0;
97
98   netbufs[ifp->if_nr] = new_buf;
99
100   return 0;
101 }
102
103
104 /**
105  * Remove a outputbuffer. Frees the allocated memory.
106  *
107  * @param ifp the interface corresponding to the buffer
108  * to remove
109  *
110  * @return 0 on success, negative if no buffer is found
111  */
112 int
113 net_remove_buffer(struct interface *ifp)
114 {
115
116   /* If a buffer does no exist for this interface back off */
117   if(!netbufs[ifp->if_nr])
118     return -1;
119   
120   /* Flush pending data */
121   if(netbufs[ifp->if_nr]->pending)
122     net_output(ifp);
123
124   free(netbufs[ifp->if_nr]->buff);
125   free(netbufs[ifp->if_nr]);
126   netbufs[ifp->if_nr] = NULL;
127
128   return 0;
129 }
130
131
132
133 /**
134  * Reserve space in a outputbuffer. This should only be needed
135  * in very special cases. This will decrease the reported size
136  * of the buffer so that there is always <i>size</i> bytes
137  * of data available in the buffer. To add data in the reserved
138  * area one must use the net_outbuffer_push_reserved function.
139  *
140  * @param ifp the interface corresponding to the buffer
141  * to reserve space on
142  * @param size the number of bytes to reserve
143  *
144  * @return 0 on success, negative if there was not enough
145  *  bytes to reserve
146  */
147 int
148 net_reserve_bufspace(struct interface *ifp, int size)
149 {
150   if((!netbufs[ifp->if_nr]) || (size > netbufs[ifp->if_nr]->maxsize))
151     return -1;
152   
153   netbufs[ifp->if_nr]->reserved = size;
154   netbufs[ifp->if_nr]->maxsize -= size;
155   
156   return 0;
157 }
158
159 /**
160  * Returns the number of bytes pending in the buffer. That
161  * is the number of bytes added but not sent.
162  *
163  * @param ifp the interface corresponding to the buffer
164  *
165  * @return the number of bytes currently pending
166  */
167 olsr_u16_t
168 net_output_pending(struct interface *ifp)
169 {
170   if(!netbufs[ifp->if_nr])
171     return -1;
172
173   return netbufs[ifp->if_nr]->pending;
174 }
175
176
177
178 /**
179  * Add data to a buffer.
180  *
181  * @param ifp the interface corresponding to the buffer
182  * @param data a pointer to the data to add
183  * @param size the number of byte to copy from data
184  *
185  * @return -1 if no buffer was found, 0 if there was not 
186  *  enough room in buffer or the number of bytes added on 
187  *  success
188  */
189 int
190 net_outbuffer_push(struct interface *ifp, olsr_u8_t *data, olsr_u16_t size)
191 {
192
193   if(!netbufs[ifp->if_nr])
194     return -1;
195
196   if((netbufs[ifp->if_nr]->pending + size) > netbufs[ifp->if_nr]->maxsize)
197     return 0;
198
199   memcpy(&netbufs[ifp->if_nr]->buff[netbufs[ifp->if_nr]->pending + OLSR_HEADERSIZE], data, size);
200   netbufs[ifp->if_nr]->pending += size;
201
202   return size;
203 }
204
205
206 /**
207  * Add data to the reserved part of a buffer
208  *
209  * @param ifp the interface corresponding to the buffer
210  * @param data a pointer to the data to add
211  * @param size the number of byte to copy from data
212  *
213  * @return -1 if no buffer was found, 0 if there was not 
214  *  enough room in buffer or the number of bytes added on 
215  *  success
216  */
217 int
218 net_outbuffer_push_reserved(struct interface *ifp, olsr_u8_t *data, olsr_u16_t size)
219 {
220
221   if(!netbufs[ifp->if_nr])
222     return -1;
223
224   if((netbufs[ifp->if_nr]->pending + size) > (netbufs[ifp->if_nr]->maxsize + netbufs[ifp->if_nr]->reserved))
225     return 0;
226
227   memcpy(&netbufs[ifp->if_nr]->buff[netbufs[ifp->if_nr]->pending + OLSR_HEADERSIZE], data, size);
228   netbufs[ifp->if_nr]->pending += size;
229
230   return size;
231 }
232
233 /**
234  * Report the number of bytes currently available in the buffer
235  * (not including possible reserved bytes)
236  *
237  * @param ifp the interface corresponding to the buffer
238  *
239  * @return the number of bytes available in the buffer or
240  *  -1 if no buffer was found
241  */
242 int
243 net_outbuffer_bytes_left(struct interface *ifp)
244 {
245
246   if(!netbufs[ifp->if_nr])
247     return -1;
248
249   return (netbufs[ifp->if_nr]->maxsize - netbufs[ifp->if_nr]->pending);
250 }
251
252
253 /**
254  * Add a packet transform function. Theese are functions
255  * called just prior to sending data in a buffer.
256  *
257  * @param f the function pointer
258  *
259  * @returns 1
260  */
261 int
262 add_ptf(int (*f)(char *, int *))
263 {
264
265   struct ptf *new_ptf;
266
267   new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
268
269   new_ptf->next = ptf_list;
270   new_ptf->function = f;
271
272   ptf_list = new_ptf;
273
274   return 1;
275 }
276
277 /**
278  * Remove a packet transform function
279  *
280  * @param f the function pointer
281  *
282  * @returns 1 if a functionpointer was removed
283  *  0 if not
284  */
285 int
286 del_ptf(int (*f)(char *, int *))
287 {
288   struct ptf *tmp_ptf, *prev;
289
290   tmp_ptf = ptf_list;
291   prev = NULL;
292
293   while(tmp_ptf)
294     {
295       if(tmp_ptf->function == f)
296         {
297           /* Remove entry */
298           if(prev == NULL)
299             {
300               ptf_list = tmp_ptf->next;
301               free(tmp_ptf);
302             }
303           else
304             {
305               prev->next = tmp_ptf->next;
306               free(tmp_ptf);
307             }
308           return 1;
309         }
310       prev = tmp_ptf;
311       tmp_ptf = tmp_ptf->next;
312     }
313
314   return 0;
315 }
316
317
318
319 /**
320  *Sends a packet on a given interface.
321  *
322  *@param ifp the interface to send on.
323  *
324  *@return negative on error
325  */
326 int
327 net_output(struct interface *ifp)
328 {
329   struct sockaddr_in *sin;  
330   struct sockaddr_in dst;
331   struct sockaddr_in6 *sin6;  
332   struct sockaddr_in6 dst6;
333   struct ptf *tmp_ptf_list;
334   int i, x;
335   union olsr_packet *outmsg;
336
337   sin = NULL;
338   sin6 = NULL;
339
340   if(!netbufs[ifp->if_nr])
341     return -1;
342
343   if(!netbufs[ifp->if_nr]->pending)
344     return 0;
345
346   netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
347
348   outmsg = (union olsr_packet *)netbufs[ifp->if_nr]->buff;
349   /* Add the Packet seqno */
350   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
351   /* Set the packetlength */
352   outmsg->v4.olsr_packlen = htons(netbufs[ifp->if_nr]->pending);
353
354   if(olsr_cnf->ip_version == AF_INET)
355     {
356       /* IP version 4 */
357       sin = (struct sockaddr_in *)&ifp->int_broadaddr;
358
359       /* Copy sin */
360       dst = *sin;
361       sin = &dst;
362
363       if (sin->sin_port == 0)
364         sin->sin_port = olsr_udp_port;
365     }
366   else
367     {
368       /* IP version 6 */
369       sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
370       /* Copy sin */
371       dst6 = *sin6;
372       sin6 = &dst6;
373     }
374
375   /*
376    *Call possible packet transform functions registered by plugins  
377    */
378   tmp_ptf_list = ptf_list;
379   while(tmp_ptf_list != NULL)
380     {
381       tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
382       tmp_ptf_list = tmp_ptf_list->next;
383     }
384
385   /*
386    *if the -dispout option was given
387    *we print the contetnt of the packets
388    */
389   if(disp_pack_out)
390     {
391       switch(netbufs[ifp->if_nr]->buff[4])
392         {
393         case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
394         case(TC_MESSAGE):printf("\n\tTC ");break;
395         case(MID_MESSAGE):printf("\n\tMID ");break;
396         case(HNA_MESSAGE):printf("\n\tHNA ");break;
397         default:printf("\n\tTYPE: %d ", netbufs[ifp->if_nr]->buff[4]); break;
398         }
399       if(olsr_cnf->ip_version == AF_INET)
400         printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), netbufs[ifp->if_nr]->pending);
401       else
402         printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), netbufs[ifp->if_nr]->pending);
403
404       x = 0;
405
406       for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
407         {
408           if(x == 4)
409             {
410               x = 0;
411               printf("\n\t");
412             }
413           x++;
414           if(olsr_cnf->ip_version == AF_INET)
415             printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
416           else
417             printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
418         }
419       
420       printf("\n");
421     }
422   
423   if(olsr_cnf->ip_version == AF_INET)
424     {
425       /* IP version 4 */
426       if(olsr_sendto(ifp->olsr_socket, 
427                      netbufs[ifp->if_nr]->buff, 
428                      netbufs[ifp->if_nr]->pending, 
429                      MSG_DONTROUTE, 
430                      (struct sockaddr *)sin, 
431                      sizeof (*sin))
432          < 0)
433         {
434           perror("sendto(v4)");
435           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
436           netbufs[ifp->if_nr]->pending = 0;
437           return -1;
438         }
439     }
440   else
441     {
442       /* IP version 6 */
443       if(olsr_sendto(ifp->olsr_socket, 
444                      netbufs[ifp->if_nr]->buff,
445                      netbufs[ifp->if_nr]->pending, 
446                      MSG_DONTROUTE, 
447                      (struct sockaddr *)sin6, 
448                      sizeof (*sin6))
449          < 0)
450         {
451           perror("sendto(v6)");
452           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
453           fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
454           fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), (int)sizeof(*sin6));
455           fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
456           netbufs[ifp->if_nr]->pending = 0;
457           return -1;
458         }
459     }
460   
461   netbufs[ifp->if_nr]->pending = 0;
462
463   return 1;
464 }
465
466
467
468 /**
469  * Create a IPv6 netmask based on a prefix length
470  *
471  * @param allocated address to build the netmask in
472  * @param prefix the prefix length
473  *
474  * @returns 1 on success 0 on failure
475  */
476 int
477 olsr_prefix_to_netmask(union olsr_ip_addr *adr, olsr_u16_t prefix)
478 {
479   int p, i;
480
481   if(adr == NULL)
482     return 0;
483
484   p = prefix;
485   i = 0;
486
487   memset(adr, 0, ipsize);
488
489   for(;p > 0; p -= 8)
490     {
491       adr->v6.s6_addr[i] = (p < 8) ? 0xff ^ (0xff << p) : 0xff;
492       i++;
493     }
494
495 #ifdef DEBUG
496   OLSR_PRINTF(3, "Prefix %d = Netmask: %s\n", prefix, olsr_ip_to_string(adr))
497 #endif
498
499   return 1;
500 }
501
502
503
504 /**
505  * Calculate prefix length based on a netmask
506  *
507  * @param adr the address to use to calculate the prefix length
508  *
509  * @return the prefix length
510  */
511 olsr_u16_t
512 olsr_netmask_to_prefix(union olsr_ip_addr *adr)
513 {
514   olsr_u16_t prefix;
515   int i, tmp;
516
517   prefix = 0;
518
519   for(i = 0; i < 16; i++)
520     {
521       if(adr->v6.s6_addr[i] == 0xff)
522         {
523           prefix += 8;
524         }
525       else
526         {
527           for(tmp = adr->v6.s6_addr[i];
528               tmp > 0;
529               tmp = tmp >> 1)
530             prefix++;
531         }
532     }
533
534 #ifdef DEBUG
535   OLSR_PRINTF(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(adr), prefix)
536 #endif
537
538   return prefix;
539 }
540
541
542
543 /**
544  *Converts a sockaddr struct to a string representing
545  *the IP address from the sockaddr struct
546  *
547  *<b>NON REENTRANT!!!!</b>
548  *
549  *@param address_to_convert the sockaddr struct to "convert"
550  *@return a char pointer to the string containing the IP
551  */
552 char *
553 sockaddr_to_string(struct sockaddr *address_to_convert)
554 {
555   struct sockaddr_in           *address;
556   
557   address=(struct sockaddr_in *)address_to_convert; 
558   return(inet_ntoa(address->sin_addr));
559   
560 }
561
562
563 /**
564  *Converts the 32bit olsr_u32_t datatype to
565  *a char array.
566  *
567  *<b>NON REENTRANT!!!!</b>
568  *
569  *@param address the olsr_u32_t to "convert"
570  *@return a char pointer to the string containing the IP
571  */
572
573 char *
574 ip_to_string(olsr_u32_t *address)
575 {
576
577   struct in_addr in;
578   in.s_addr=*address;
579   return(inet_ntoa(in));
580   
581 }
582
583
584
585
586 /**
587  *Converts the 32bit olsr_u32_t datatype to
588  *a char array.
589  *
590  *<b>NON REENTRANT</b>
591  *
592  *@param addr6 the address to "convert"
593  *@return a char pointer to the string containing the IP
594  */
595
596 char *
597 ip6_to_string(struct in6_addr *addr6)
598 {
599   return (char *)inet_ntop(AF_INET6, addr6, ipv6_buf, sizeof(ipv6_buf));
600 }
601
602
603 char *
604 olsr_ip_to_string(union olsr_ip_addr *addr)
605 {
606   static int index = 0;
607   static char buff[4][100];
608   char *ret;
609   struct in_addr in;
610   
611   if(olsr_cnf->ip_version == AF_INET)
612     {
613       in.s_addr=addr->v4;
614       ret = inet_ntoa(in);
615     }
616   else
617     {
618       /* IPv6 */
619       ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
620     }
621
622   strncpy(buff[index], ret, 100);
623
624   ret = buff[index];
625
626   index = (index + 1) & 3;
627
628   return ret;
629 }