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