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