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