2f405aacc93f096215c7afb75042060a6f62be8d
[olsrd.git] / src / net.c
1
2 /*
3  * OLSR ad-hoc routing table management protocol
4  * Copyright (C) 2003 Andreas T√łnnesen (andreto@ifi.uio.no)
5  *
6  * This file is part of the olsr.org OLSR daemon.
7  *
8  * olsr.org is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * olsr.org is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with olsr.org; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  * 
22  * 
23  * $Id: net.c,v 1.13 2004/09/25 11:13:28 kattemat Exp $
24  *
25  */
26
27 #include "net.h"
28 #include "olsr.h"
29 #include <stdlib.h>
30
31 #ifdef WIN32
32 #define perror(x) WinSockPError(x)
33 void
34 WinSockPError(char *);
35 #endif
36
37 #warning HEAPS of changes in net.c!!!
38
39 static char out_buffer[MAXMESSAGESIZE+1];
40 static char fwd_buffer[MAXMESSAGESIZE+1];
41
42 static union olsr_packet *outmsg = (union olsr_packet *)out_buffer;
43 static union olsr_packet *fwdmsg = (union olsr_packet *)fwd_buffer;
44
45 static int outputsize = 0;      /* current size of the output buffer */
46 static int fwdsize = 0;         /* current size of the forward buffer */
47
48 static int netbuffer_reserved = 0;  /* plugins can reserve bufferspace */
49
50
51 /* Default max OLSR packet size */
52 static int maxmessagesize = MAXMESSAGESIZE - OLSR_HEADERSIZE - UDP_IP_HDRSIZE;
53
54
55 void
56 init_net()
57 {
58   ptf_list = NULL;
59
60   return;
61 }
62
63 int
64 net_set_maxmsgsize(olsr_u16_t new_size)
65 {
66
67   if(new_size > (MAXMESSAGESIZE - OLSR_HEADERSIZE - UDP_IP_HDRSIZE - netbuffer_reserved))
68     return -1;
69
70   else
71     maxmessagesize = new_size - netbuffer_reserved;
72
73   olsr_printf(1, "Not outputbuffer maxsize set to %d(%d bytes reserved)\n", 
74               maxmessagesize, 
75               netbuffer_reserved);
76   return maxmessagesize;
77 }
78
79
80 int
81 net_reserve_bufferspace(olsr_u16_t size)
82 {
83
84   if((netbuffer_reserved + size) > maxmessagesize)
85     return -1;
86
87   else
88     {
89       netbuffer_reserved += size;
90       maxmessagesize -= netbuffer_reserved;
91     }
92
93   olsr_printf(1, "Netbuffer reserved %d bytes - new maxsize %d\n", 
94               netbuffer_reserved, 
95               maxmessagesize);
96   return maxmessagesize;
97 }
98
99
100 inline olsr_u16_t
101 net_get_maxmsgsize()
102 {
103   return maxmessagesize;
104 }
105
106
107 inline olsr_u16_t
108 net_fwd_pending()
109 {
110   return fwdsize;
111 }
112
113
114 inline olsr_u16_t
115 net_output_pending()
116 {
117   return outputsize;
118 }
119
120 /**
121  * Add data to the buffer that is to be transmitted
122  *
123  * @return 0 if there was not enough room in buffer
124  */
125 int
126 net_outbuffer_push(olsr_u8_t *data, olsr_u16_t size)
127 {
128
129   if((outputsize + size) > maxmessagesize)
130     return 0;
131
132   memcpy(&out_buffer[outputsize + OLSR_HEADERSIZE], data, size);
133   outputsize += size;
134
135   return 1;
136 }
137
138
139 /**
140  * Add data to the buffer that is to be transmitted
141  *
142  * @return 0 if there was not enough room in buffer
143  */
144 int
145 net_outbuffer_push_reserved(olsr_u8_t *data, olsr_u16_t size)
146 {
147
148   if((outputsize + size) > (maxmessagesize + netbuffer_reserved))
149     return 0;
150
151   memcpy(&out_buffer[outputsize + OLSR_HEADERSIZE], data, size);
152   outputsize += size;
153
154   return 1;
155 }
156
157
158
159 /**
160  * Add data to the buffer that is to be transmitted
161  *
162  * @return 0 if there was not enough room in buffer
163  */
164 inline int
165 net_outbuffer_bytes_left()
166 {
167   return (maxmessagesize - outputsize);
168 }
169
170
171 /**
172  * Add data to the buffer that is to be forwarded
173  *
174  * @return 0 if there was not enough room in buffer
175  */
176 int
177 net_fwdbuffer_push(olsr_u8_t *data, olsr_u16_t size)
178 {
179
180   if((fwdsize + size) > maxmessagesize)
181     return 0;
182
183   memcpy(&fwd_buffer[fwdsize + OLSR_HEADERSIZE], data, size);
184   fwdsize += size;
185
186   return 1;
187 }
188
189
190 /**
191  * Add data to the buffer that is to be forwarded
192  *
193  * @return 0 if there was not enough room in buffer
194  */
195 int
196 net_fwdbuffer_push_reserved(olsr_u8_t *data, olsr_u16_t size)
197 {
198
199   if((fwdsize + size) > (maxmessagesize + netbuffer_reserved))
200     return 0;
201
202   memcpy(&fwd_buffer[fwdsize + OLSR_HEADERSIZE], data, size);
203   fwdsize += size;
204
205   return 1;
206 }
207
208
209
210 /**
211  *Sends a packet on a given interface.
212  *
213  *@param ifp the interface to send on.
214  *
215  *@return negative on error
216  */
217 int
218 net_output(struct interface *ifp)
219 {
220   struct sockaddr_in *sin;  
221   struct sockaddr_in dst;
222   struct sockaddr_in6 *sin6;  
223   struct sockaddr_in6 dst6;
224   struct ptf *tmp_ptf_list;
225   int i, x;
226
227   sin = NULL;
228   sin6 = NULL;
229
230   if(outputsize <= 0)
231     return -1;
232
233   outputsize += OLSR_HEADERSIZE;
234   /* Add the Packet seqno */
235   outmsg->v4.olsr_seqno = htons(ifp->olsr_seqnum++);
236   /* Set the packetlength */
237   outmsg->v4.olsr_packlen = htons(outputsize);
238
239   if(ipversion == AF_INET)
240     {
241       /* IP version 4 */
242       sin = (struct sockaddr_in *)&ifp->int_broadaddr;
243
244       /* Copy sin */
245       dst = *sin;
246       sin = &dst;
247
248       /* Set user defined broadcastaddr */
249       if(bcast_set)
250         memcpy(&dst.sin_addr.s_addr, &bcastaddr.sin_addr, sizeof(olsr_u32_t));
251
252       if (sin->sin_port == 0)
253         sin->sin_port = olsr_udp_port;
254     }
255   else
256     {
257       /* IP version 6 */
258       sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
259       /* Copy sin */
260       dst6 = *sin6;
261       sin6 = &dst6;
262     }
263
264   /*
265    *if the '-disp- option was given
266    *we print her decimal contetnt of the packets
267    */
268   /*
269   if(disp_pack_out)
270     {
271       switch(out_buffer[4])
272         {
273         case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
274         case(TC_MESSAGE):printf("\n\tTC ");break;
275         case(MID_MESSAGE):printf("\n\tMID ");break;
276         case(HNA_MESSAGE):printf("\n\tHNA ");break;
277         }
278       if(ipversion == AF_INET)
279         printf("to %s size: %d\n\t", ip_to_string(&sin->sin_addr.s_addr), outputsize);
280       else
281         printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), outputsize);
282
283       x = 0;
284
285       for(i = 0; i < outputsize;i++)
286         {
287           if(x == 4)
288             {
289               x = 0;
290               printf("\n\t");
291             }
292           x++;
293           if(ipversion == AF_INET)
294             printf(" %3i", (u_char) out_buffer[i]);
295           else
296             printf(" %2x", (u_char) out_buffer[i]);
297         }
298       
299       printf("\n");
300     }
301   */
302
303   /*
304    *Call possible packet transform functions registered by plugins  
305    */
306   tmp_ptf_list = ptf_list;
307   while(tmp_ptf_list != NULL)
308     {
309       tmp_ptf_list->function(out_buffer, &outputsize);
310       tmp_ptf_list = tmp_ptf_list->next;
311     }
312
313   /*
314    *if the '-disp- option was given
315    *we print her decimal contetnt of the packets
316    */
317   if(disp_pack_out)
318     {
319       switch(out_buffer[4])
320         {
321         case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
322         case(TC_MESSAGE):printf("\n\tTC ");break;
323         case(MID_MESSAGE):printf("\n\tMID ");break;
324         case(HNA_MESSAGE):printf("\n\tHNA ");break;
325         default:printf("\n\tTYPE: %d ", out_buffer[4]); break;
326         }
327       if(ipversion == AF_INET)
328         printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), outputsize);
329       else
330         printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), outputsize);
331
332       x = 0;
333
334       for(i = 0; i < outputsize;i++)
335         {
336           if(x == 4)
337             {
338               x = 0;
339               printf("\n\t");
340             }
341           x++;
342           if(ipversion == AF_INET)
343             printf(" %3i", (u_char) out_buffer[i]);
344           else
345             printf(" %2x", (u_char) out_buffer[i]);
346         }
347       
348       printf("\n");
349     }
350
351   /*
352    *packet points to the same memory area as the *msg pointer
353    *used when building packets.
354    */
355   
356   if(ipversion == AF_INET)
357     {
358       /* IP version 4 */
359       if(sendto(ifp->olsr_socket, out_buffer, outputsize, MSG_DONTROUTE, (struct sockaddr *)sin, sizeof (*sin)) < 0)
360         {
361           perror("sendto(v4)");
362           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
363           outputsize = 0;
364           return -1;
365         }
366     }
367   else
368     {
369       /* IP version 6 */
370       if(sendto(ifp->olsr_socket, out_buffer, outputsize, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof (*sin6)) < 0)
371         {
372           perror("sendto(v6)");
373           olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
374           fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
375           fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), sizeof(*sin6));
376           fprintf(stderr, "Outputsize: %d\n", outputsize);
377           outputsize = 0;
378           return -1;
379         }
380     }
381   
382   outputsize = 0;
383
384   return 1;
385 }
386
387
388
389
390
391
392 /**
393  *Forward a message on all interfaces
394  *
395  *@return negative on error
396  */
397 int
398 net_forward()
399 {
400   struct sockaddr_in *sin;  
401   struct sockaddr_in dst;
402   struct sockaddr_in6 *sin6;  
403   struct sockaddr_in6 dst6;
404   struct interface *ifn;
405   struct ptf *tmp_ptf_list;
406   int i, x;
407   
408   sin = NULL;
409   sin6 = NULL;
410   
411   for (ifn = ifnet; ifn; ifn = ifn->int_next) 
412     {
413       
414       fwdsize += OLSR_HEADERSIZE;      
415       /* Add the Packet seqno */
416       fwdmsg->v4.olsr_seqno = htons(ifn->olsr_seqnum++);
417       /* Set the packetlength */
418       fwdmsg->v4.olsr_packlen = htons(fwdsize);
419
420       if(ipversion == AF_INET)
421         {
422           /* IP version 4 */
423           sin = (struct sockaddr_in *)&ifn->int_broadaddr;
424           
425           /* Copy sin */
426           dst = *sin;
427           sin = &dst;
428
429           /* Set user defined broadcastaddr */
430           if(bcast_set)
431             memcpy(&dst.sin_addr.s_addr, &bcastaddr.sin_addr, sizeof(olsr_u32_t));
432           
433           if (sin->sin_port == 0)
434             sin->sin_port = olsr_udp_port;
435         }
436       else
437         {
438           /* IP version 6 */
439           sin6 = (struct sockaddr_in6 *)&ifn->int6_multaddr;
440           /* Copy sin */
441           dst6 = *sin6;
442           sin6 = &dst6;
443         }
444
445       /*
446        *if the '-disp- option was given
447        *we print her decimal contetnt of the packets
448        */
449       if(disp_pack_out)
450         {
451           if(ipversion == AF_INET)
452             printf("FORWARDING to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), fwdsize);
453           else
454             printf("FORWARDING to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), fwdsize);
455           
456           x = 0;
457           
458           for(i = 0; i < fwdsize;i++)
459             {
460               if(x == 4)
461                 {
462                   x = 0;
463                   printf("\n\t");
464                 }
465               x++;
466               if(ipversion == AF_INET)
467                 printf(" %3i", (u_char) fwd_buffer[i]);
468               else
469                 printf(" %2x", (u_char) fwd_buffer[i]);
470             }
471           
472           printf("\n");
473         }
474   
475       
476       /*
477        *Call possible packet transform functions registered by plugins  
478        */
479       tmp_ptf_list = ptf_list;
480       while(tmp_ptf_list != NULL)
481         {
482           tmp_ptf_list->function(fwd_buffer, &fwdsize);
483           tmp_ptf_list = tmp_ptf_list->next;
484         }
485
486
487       if(ipversion == AF_INET)
488         {
489           /* IP version 4 */
490           if(sendto(ifn->olsr_socket, fwd_buffer, fwdsize, MSG_DONTROUTE, (struct sockaddr *)sin, sizeof (*sin)) < 0)
491             {
492               perror("sendto(v4)");
493               olsr_syslog(OLSR_LOG_ERR, "OLSR: forward sendto IPv4 %m");
494               return -1;
495             }
496         }
497       else
498         {
499           /* IP version 6 */
500           if(sendto(ifn->olsr_socket, fwd_buffer, fwdsize, MSG_DONTROUTE, (struct sockaddr *)sin6, sizeof (*sin6)) < 0)
501             {
502               perror("sendto(v6)");
503               olsr_syslog(OLSR_LOG_ERR, "OLSR: forward sendto IPv6 %m");
504               fprintf(stderr, "Socket: %d interface: %d\n", ifn->olsr_socket, ifn->if_nr);
505               fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), sizeof(*sin6));
506               fprintf(stderr, "Outputsize: %d\n", fwdsize);
507               return -1;
508             }
509         }
510
511     }      
512   return 1;
513 }
514
515 /*
516  * Add a packet transform function
517  */
518 int
519 add_ptf(int (*f)(char *, int *))
520 {
521
522   struct ptf *new_ptf;
523
524   new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
525
526   new_ptf->next = ptf_list;
527   new_ptf->function = f;
528
529   ptf_list = new_ptf;
530
531   return 1;
532 }
533
534 /*
535  * Remove a packet transform function
536  */
537 int
538 del_ptf(int (*f)(char *, int *))
539 {
540   struct ptf *tmp_ptf, *prev;
541
542   tmp_ptf = ptf_list;
543   prev = NULL;
544
545   while(tmp_ptf)
546     {
547       if(tmp_ptf->function == f)
548         {
549           /* Remove entry */
550           if(prev == NULL)
551             {
552               ptf_list = tmp_ptf->next;
553               free(tmp_ptf);
554             }
555           else
556             {
557               prev->next = tmp_ptf->next;
558               free(tmp_ptf);
559             }
560           return 1;
561         }
562       prev = tmp_ptf;
563       tmp_ptf = tmp_ptf->next;
564     }
565
566   return 0;
567 }
568
569
570 int
571 join_mcast(struct interface *ifs, int sock)
572 {
573   /* See linux/in6.h */
574
575   struct ipv6_mreq mcastreq;
576
577   COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
578   mcastreq.ipv6mr_interface = ifs->if_index;
579
580   olsr_printf(3, "Interface %s joining multicast %s...",        ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr));
581   /* Send multicast */
582   if(setsockopt(sock, 
583                 IPPROTO_IPV6, 
584                 IPV6_ADD_MEMBERSHIP, 
585                 (char *)&mcastreq, 
586                 sizeof(struct ipv6_mreq)) 
587      < 0)
588     {
589       perror("Join multicast");
590       return -1;
591     }
592
593
594   /* Join reciever group */
595   if(setsockopt(sock, 
596                 IPPROTO_IPV6, 
597                 IPV6_JOIN_GROUP, 
598                 (char *)&mcastreq, 
599                 sizeof(struct ipv6_mreq)) 
600      < 0)
601     {
602       perror("Join multicast send");
603       return -1;
604     }
605
606   
607   if(setsockopt(sock, 
608                 IPPROTO_IPV6, 
609                 IPV6_MULTICAST_IF, 
610                 (char *)&mcastreq.ipv6mr_interface, 
611                 sizeof(mcastreq.ipv6mr_interface)) 
612      < 0)
613     {
614       perror("Set multicast if");
615       return -1;
616     }
617
618
619   olsr_printf(3, "OK\n");
620   return 0;
621 }
622
623
624 /**
625  * Create a IPv6 netmask based on a prefix length
626  *
627  */
628 int
629 olsr_prefix_to_netmask(union olsr_ip_addr *adr, olsr_u16_t prefix)
630 {
631   int p, i;
632
633   if(adr == NULL)
634     return 0;
635
636   p = prefix;
637   i = 0;
638
639   memset(adr, 0, ipsize);
640
641   for(;p > 0; p -= 8)
642     {
643       adr->v6.s6_addr[i] = (p < 8) ? 0xff ^ (0xff << p) : 0xff;
644       i++;
645     }
646
647 #ifdef DEBUG
648   olsr_printf(3, "Prefix %d = Netmask: %s\n", prefix, olsr_ip_to_string(adr));
649 #endif
650
651   return 1;
652 }
653
654
655
656 /**
657  * Calculate prefix length based on a netmask
658  *
659  */
660 olsr_u16_t
661 olsr_netmask_to_prefix(union olsr_ip_addr *adr)
662 {
663   olsr_u16_t prefix;
664   int i, tmp;
665
666   prefix = 0;
667
668   memset(adr, 0, ipsize);
669
670   for(i = 0; i < 16; i++)
671     {
672       if(adr->v6.s6_addr[i] == 0xff)
673         {
674           prefix += 8;
675         }
676       else
677         {
678           for(tmp = adr->v6.s6_addr[i];
679               tmp > 0;
680               tmp = tmp >> 1)
681             prefix++;
682         }
683     }
684
685 #ifdef DEBUG
686   olsr_printf(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(adr), prefix);
687 #endif
688
689   return prefix;
690 }
691
692
693
694 /**
695  *Converts a sockaddr struct to a string representing
696  *the IP address from the sockaddr struct
697  *
698  *<b>NON REENTRANT!!!!</b>
699  *
700  *@param address_to_convert the sockaddr struct to "convert"
701  *@return a char pointer to the string containing the IP
702  */
703 char *
704 sockaddr_to_string(struct sockaddr *address_to_convert)
705 {
706   struct sockaddr_in           *address;
707   
708   address=(struct sockaddr_in *)address_to_convert; 
709   return(inet_ntoa(address->sin_addr));
710   
711 }
712
713
714 /**
715  *Converts the 32bit olsr_u32_t datatype to
716  *a char array.
717  *
718  *<b>NON REENTRANT!!!!</b>
719  *
720  *@param address the olsr_u32_t to "convert"
721  *@return a char pointer to the string containing the IP
722  */
723
724 char *
725 ip_to_string(olsr_u32_t *address)
726 {
727
728   struct in_addr in;
729   in.s_addr=*address;
730   return(inet_ntoa(in));
731   
732 }
733
734
735
736
737 /**
738  *Converts the 32bit olsr_u32_t datatype to
739  *a char array.
740  *
741  *<b>NON REENTRANT!!!!</b>
742  *
743  *@param addr6 the address to "convert"
744  *@return a char pointer to the string containing the IP
745  */
746
747 char *
748 ip6_to_string(struct in6_addr *addr6)
749 {
750   return (char *)inet_ntop(AF_INET6, addr6, ipv6_buf, sizeof(ipv6_buf));
751 }
752
753
754 char *
755 olsr_ip_to_string(union olsr_ip_addr *addr)
756 {
757
758   char *ret;
759   struct in_addr in;
760   
761   if(ipversion == AF_INET)
762     {
763       in.s_addr=addr->v4;
764       ret = inet_ntoa(in);
765     }
766   else
767     {
768       /* IPv6 */
769       ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));
770     }
771
772   return ret;
773 }