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