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