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