d31ec83b894cd36e72dd80c12c0d950b281a516f
[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.29 2005/02/08 12:55:23 kattemat Exp $
40  */
41
42 #include "net.h"
43 #include "olsr.h"
44 #include <stdlib.h>
45
46 #ifdef WIN32
47 #define perror(x) WinSockPError(x)
48 void
49 WinSockPError(char *);
50 #endif
51
52 #warning Interface configuration is now responsible for setting up outputbuffers!!
53
54 struct olsr_netbuf
55 {
56   char *buff;     /* Pointer to the allocated buffer */
57   int if_index;
58   int bufsize;    /* Size of the buffer */
59   int maxsize;    /* Max bytes of payload that can be added to the buffer */
60   int pending;    /* How much data is currently pending in the buffer */
61   int reserved;   /* Plugins can reserve space in buffers */
62 };
63
64
65 static 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
255 /**
256  *Sends a packet on a given interface.
257  *
258  *@param ifp the interface to send on.
259  *
260  *@return negative on error
261  */
262 int
263 net_output(struct interface *ifp)
264 {
265   struct sockaddr_in *sin;  
266   struct sockaddr_in dst;
267   struct sockaddr_in6 *sin6;  
268   struct sockaddr_in6 dst6;
269   struct ptf *tmp_ptf_list;
270   int i, x;
271   union olsr_packet *outmsg;
272
273   sin = NULL;
274   sin6 = NULL;
275
276   if(!netbufs[ifp->if_nr])
277     return -1;
278
279   if(!netbufs[ifp->if_nr]->pending)
280     return 0;
281
282   netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
283
284   outmsg = (union olsr_packet *)netbufs[ifp->if_nr]->buff;
285   /* Add the Packet seqno */
286   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
287   /* Set the packetlength */
288   outmsg->v4.olsr_packlen = htons(netbufs[ifp->if_nr]->pending);
289
290   if(olsr_cnf->ip_version == AF_INET)
291     {
292       /* IP version 4 */
293       sin = (struct sockaddr_in *)&ifp->int_broadaddr;
294
295       /* Copy sin */
296       dst = *sin;
297       sin = &dst;
298
299       if (sin->sin_port == 0)
300         sin->sin_port = olsr_udp_port;
301     }
302   else
303     {
304       /* IP version 6 */
305       sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
306       /* Copy sin */
307       dst6 = *sin6;
308       sin6 = &dst6;
309     }
310
311   /*
312    *Call possible packet transform functions registered by plugins  
313    */
314   tmp_ptf_list = ptf_list;
315   while(tmp_ptf_list != NULL)
316     {
317       tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
318       tmp_ptf_list = tmp_ptf_list->next;
319     }
320
321   /*
322    *if the '-disp- option was given
323    *we print her decimal contetnt of the packets
324    */
325   if(disp_pack_out)
326     {
327       switch(netbufs[ifp->if_nr]->buff[4])
328         {
329         case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
330         case(TC_MESSAGE):printf("\n\tTC ");break;
331         case(MID_MESSAGE):printf("\n\tMID ");break;
332         case(HNA_MESSAGE):printf("\n\tHNA ");break;
333         default:printf("\n\tTYPE: %d ", netbufs[ifp->if_nr]->buff[4]); break;
334         }
335       if(olsr_cnf->ip_version == AF_INET)
336         printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), netbufs[ifp->if_nr]->pending);
337       else
338         printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), netbufs[ifp->if_nr]->pending);
339
340       x = 0;
341
342       for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
343         {
344           if(x == 4)
345             {
346               x = 0;
347               printf("\n\t");
348             }
349           x++;
350           if(olsr_cnf->ip_version == AF_INET)
351             printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
352           else
353             printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
354         }
355       
356       printf("\n");
357     }
358   
359   if(olsr_cnf->ip_version == AF_INET)
360     {
361       /* IP version 4 */
362       if(sendto(ifp->olsr_socket, 
363                 netbufs[ifp->if_nr]->buff, 
364                 netbufs[ifp->if_nr]->pending, 
365                 MSG_DONTROUTE, 
366                 (struct sockaddr *)sin, 
367                 sizeof (*sin)) 
368          < 0)
369         {
370           perror("sendto(v4)");
371           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
372           netbufs[ifp->if_nr]->pending = 0;
373           return -1;
374         }
375     }
376   else
377     {
378       /* IP version 6 */
379       if(sendto(ifp->olsr_socket, 
380                 netbufs[ifp->if_nr]->buff,
381                 netbufs[ifp->if_nr]->pending, 
382                 MSG_DONTROUTE, 
383                 (struct sockaddr *)sin6, 
384                 sizeof (*sin6)) 
385          < 0)
386         {
387           perror("sendto(v6)");
388           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
389           fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
390           fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), (int)sizeof(*sin6));
391           fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
392           netbufs[ifp->if_nr]->pending = 0;
393           return -1;
394         }
395     }
396   
397   netbufs[ifp->if_nr]->pending = 0;
398
399   return 1;
400 }
401
402
403
404
405
406
407 /**
408  * Add a packet transform function. Theese are functions
409  * called just prior to sending data in a buffer.
410  *
411  * @param f the function pointer
412  *
413  * @returns 1
414  */
415 int
416 add_ptf(int (*f)(char *, int *))
417 {
418
419   struct ptf *new_ptf;
420
421   new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
422
423   new_ptf->next = ptf_list;
424   new_ptf->function = f;
425
426   ptf_list = new_ptf;
427
428   return 1;
429 }
430
431 /**
432  * Remove a packet transform function
433  *
434  * @param f the function pointer
435  *
436  * @returns 1 if a functionpointer was removed
437  *  0 if not
438  */
439 int
440 del_ptf(int (*f)(char *, int *))
441 {
442   struct ptf *tmp_ptf, *prev;
443
444   tmp_ptf = ptf_list;
445   prev = NULL;
446
447   while(tmp_ptf)
448     {
449       if(tmp_ptf->function == f)
450         {
451           /* Remove entry */
452           if(prev == NULL)
453             {
454               ptf_list = tmp_ptf->next;
455               free(tmp_ptf);
456             }
457           else
458             {
459               prev->next = tmp_ptf->next;
460               free(tmp_ptf);
461             }
462           return 1;
463         }
464       prev = tmp_ptf;
465       tmp_ptf = tmp_ptf->next;
466     }
467
468   return 0;
469 }
470
471
472 int
473 join_mcast(struct interface *ifs, int sock)
474 {
475   /* See linux/in6.h */
476
477   struct ipv6_mreq mcastreq;
478
479   COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
480   mcastreq.ipv6mr_interface = ifs->if_index;
481
482 #if !defined __FreeBSD__ && !defined __MacOSX__ && !defined __NetBSD__
483   olsr_printf(3, "Interface %s joining multicast %s...",        ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr));
484   /* Send multicast */
485   if(setsockopt(sock, 
486                 IPPROTO_IPV6, 
487                 IPV6_ADD_MEMBERSHIP, 
488                 (char *)&mcastreq, 
489                 sizeof(struct ipv6_mreq)) 
490      < 0)
491     {
492       perror("Join multicast");
493       return -1;
494     }
495 #else
496 #warning implement IPV6_ADD_MEMBERSHIP
497 #endif
498
499   /* Old libc fix */
500 #ifdef IPV6_JOIN_GROUP
501   /* Join reciever group */
502   if(setsockopt(sock, 
503                 IPPROTO_IPV6, 
504                 IPV6_JOIN_GROUP, 
505                 (char *)&mcastreq, 
506                 sizeof(struct ipv6_mreq)) 
507      < 0)
508 #else
509   /* Join reciever group */
510   if(setsockopt(sock, 
511                 IPPROTO_IPV6, 
512                 IPV6_ADD_MEMBERSHIP, 
513                 (char *)&mcastreq, 
514                 sizeof(struct ipv6_mreq)) 
515      < 0)
516 #endif 
517     {
518       perror("Join multicast send");
519       return -1;
520     }
521
522   
523   if(setsockopt(sock, 
524                 IPPROTO_IPV6, 
525                 IPV6_MULTICAST_IF, 
526                 (char *)&mcastreq.ipv6mr_interface, 
527                 sizeof(mcastreq.ipv6mr_interface)) 
528      < 0)
529     {
530       perror("Set multicast if");
531       return -1;
532     }
533
534
535   olsr_printf(3, "OK\n");
536   return 0;
537 }
538
539
540 /**
541  * Create a IPv6 netmask based on a prefix length
542  *
543  * @param allocated address to build the netmask in
544  * @param prefix the prefix length
545  *
546  * @returns 1 on success 0 on failure
547  */
548 int
549 olsr_prefix_to_netmask(union olsr_ip_addr *adr, olsr_u16_t prefix)
550 {
551   int p, i;
552
553   if(adr == NULL)
554     return 0;
555
556   p = prefix;
557   i = 0;
558
559   memset(adr, 0, ipsize);
560
561   for(;p > 0; p -= 8)
562     {
563       adr->v6.s6_addr[i] = (p < 8) ? 0xff ^ (0xff << p) : 0xff;
564       i++;
565     }
566
567 #ifdef DEBUG
568   olsr_printf(3, "Prefix %d = Netmask: %s\n", prefix, olsr_ip_to_string(adr));
569 #endif
570
571   return 1;
572 }
573
574
575
576 /**
577  * Calculate prefix length based on a netmask
578  *
579  * @param adr the address to use to calculate the prefix length
580  *
581  * @return the prefix length
582  */
583 olsr_u16_t
584 olsr_netmask_to_prefix(union olsr_ip_addr *adr)
585 {
586   olsr_u16_t prefix;
587   int i, tmp;
588
589   prefix = 0;
590
591   for(i = 0; i < 16; i++)
592     {
593       if(adr->v6.s6_addr[i] == 0xff)
594         {
595           prefix += 8;
596         }
597       else
598         {
599           for(tmp = adr->v6.s6_addr[i];
600               tmp > 0;
601               tmp = tmp >> 1)
602             prefix++;
603         }
604     }
605
606 #ifdef DEBUG
607   olsr_printf(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(adr), prefix);
608 #endif
609
610   return prefix;
611 }
612
613
614
615 /**
616  *Converts a sockaddr struct to a string representing
617  *the IP address from the sockaddr struct
618  *
619  *<b>NON REENTRANT!!!!</b>
620  *
621  *@param address_to_convert the sockaddr struct to "convert"
622  *@return a char pointer to the string containing the IP
623  */
624 char *
625 sockaddr_to_string(struct sockaddr *address_to_convert)
626 {
627   struct sockaddr_in           *address;
628   
629   address=(struct sockaddr_in *)address_to_convert; 
630   return(inet_ntoa(address->sin_addr));
631   
632 }
633
634
635 /**
636  *Converts the 32bit olsr_u32_t datatype to
637  *a char array.
638  *
639  *<b>NON REENTRANT!!!!</b>
640  *
641  *@param address the olsr_u32_t to "convert"
642  *@return a char pointer to the string containing the IP
643  */
644
645 char *
646 ip_to_string(olsr_u32_t *address)
647 {
648
649   struct in_addr in;
650   in.s_addr=*address;
651   return(inet_ntoa(in));
652   
653 }
654
655
656
657
658 /**
659  *Converts the 32bit olsr_u32_t datatype to
660  *a char array.
661  *
662  *<b>NON REENTRANT</b>
663  *
664  *@param addr6 the address to "convert"
665  *@return a char pointer to the string containing the IP
666  */
667
668 char *
669 ip6_to_string(struct in6_addr *addr6)
670 {
671   return (char *)inet_ntop(AF_INET6, addr6, ipv6_buf, sizeof(ipv6_buf));
672 }
673
674
675 char *
676 olsr_ip_to_string(union olsr_ip_addr *addr)
677 {
678   static int index = 0;
679   static char buff[4][100];
680   char *ret;
681   struct in_addr in;
682   
683   if(olsr_cnf->ip_version == AF_INET)
684     {
685       in.s_addr=addr->v4;
686       ret = inet_ntoa(in);
687     }
688   else
689     {
690       /* IPv6 */
691       ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
692     }
693
694   strncpy(buff[index], ret, 100);
695
696   ret = buff[index];
697
698   index = (index + 1) & 3;
699
700   return ret;
701 }