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