3 * OLSR ad-hoc routing table management protocol
4 * Copyright (C) 2003 Andreas Tønnesen (andreto@ifi.uio.no)
6 * This file is part of the olsr.org OLSR daemon.
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.
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.
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
23 * $Id: net.c,v 1.14 2004/09/25 21:06:07 kattemat Exp $
32 #define perror(x) WinSockPError(x)
34 WinSockPError(char *);
37 #warning Interface configuration is now responsible for setting up outputbuffers!!
41 char *buff; /* Pointer to the allocated buffer */
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 */
50 static struct olsr_netbuf *netbufs[MAX_IFS];
63 net_add_buffer(struct interface *ifp)
65 struct olsr_netbuf *new_buf;
67 /* If a buffer already exists for this interface back off */
68 if(netbufs[ifp->if_nr])
71 new_buf = olsr_malloc(sizeof(struct olsr_netbuf), "add_netbuff1");
72 new_buf->buff = olsr_malloc(ifp->int_mtu, "add_netbuff2");
75 new_buf->bufsize = ifp->int_mtu;
76 new_buf->if_index = ifp->if_nr;
77 new_buf->maxsize = ifp->int_mtu - OLSR_HEADERSIZE;
79 new_buf->reserved = 0;
81 netbufs[ifp->if_nr] = new_buf;
88 net_remove_buffer(struct interface *ifp)
91 /* If a buffer already exists for this interface back off */
92 if(!netbufs[ifp->if_nr])
95 /* Flush pending data */
96 if(netbufs[ifp->if_nr]->pending)
99 free(netbufs[ifp->if_nr]->buff);
100 free(netbufs[ifp->if_nr]);
101 netbufs[ifp->if_nr] = NULL;
109 net_reserve_bufspace(struct interface *ifp, int size)
113 if((!netbufs[ifp->if_nr]) || (size > netbufs[ifp->if_nr]->maxsize))
116 netbufs[ifp->if_nr]->reserved = size;
117 netbufs[ifp->if_nr]->maxsize -= size;
124 net_output_pending(struct interface *ifp)
126 if(!netbufs[ifp->if_nr])
129 return netbufs[ifp->if_nr]->pending;
135 * Add data to the buffer that is to be transmitted
137 * @return 0 if there was not enough room in buffer
140 net_outbuffer_push(struct interface *ifp, olsr_u8_t *data, olsr_u16_t size)
143 if(!netbufs[ifp->if_nr])
146 if((netbufs[ifp->if_nr]->pending + size) > netbufs[ifp->if_nr]->maxsize)
149 memcpy(&netbufs[ifp->if_nr]->buff[netbufs[ifp->if_nr]->pending + OLSR_HEADERSIZE], data, size);
150 netbufs[ifp->if_nr]->pending += size;
157 * Adddata to the reserved part of the buffer that is to be transmitted
159 * @return 0 if there was not enough room in buffer
162 net_outbuffer_push_reserved(struct interface *ifp, olsr_u8_t *data, olsr_u16_t size)
165 if(!netbufs[ifp->if_nr])
168 if((netbufs[ifp->if_nr]->pending + size) > (netbufs[ifp->if_nr]->maxsize + netbufs[ifp->if_nr]->reserved))
171 memcpy(&netbufs[ifp->if_nr]->buff[netbufs[ifp->if_nr]->pending + OLSR_HEADERSIZE], data, size);
172 netbufs[ifp->if_nr]->pending += size;
179 net_outbuffer_bytes_left(struct interface *ifp)
182 if(!netbufs[ifp->if_nr])
185 return (netbufs[ifp->if_nr]->maxsize - netbufs[ifp->if_nr]->pending);
192 *Sends a packet on a given interface.
194 *@param ifp the interface to send on.
196 *@return negative on error
199 net_output(struct interface *ifp)
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;
207 union olsr_packet *outmsg;
212 if(!netbufs[ifp->if_nr])
215 if(!netbufs[ifp->if_nr]->pending)
218 netbufs[ifp->if_nr]->pending += OLSR_HEADERSIZE;
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);
226 if(ipversion == AF_INET)
229 sin = (struct sockaddr_in *)&ifp->int_broadaddr;
235 /* Set user defined broadcastaddr */
237 memcpy(&dst.sin_addr.s_addr, &bcastaddr.sin_addr, sizeof(olsr_u32_t));
239 if (sin->sin_port == 0)
240 sin->sin_port = olsr_udp_port;
245 sin6 = (struct sockaddr_in6 *)&ifp->int6_multaddr;
252 *Call possible packet transform functions registered by plugins
254 tmp_ptf_list = ptf_list;
255 while(tmp_ptf_list != NULL)
257 tmp_ptf_list->function(netbufs[ifp->if_nr]->buff, &netbufs[ifp->if_nr]->pending);
258 tmp_ptf_list = tmp_ptf_list->next;
262 *if the '-disp- option was given
263 *we print her decimal contetnt of the packets
267 switch(netbufs[ifp->if_nr]->buff[4])
269 case(HELLO_MESSAGE):printf("\n\tHELLO ");break;
270 case(TC_MESSAGE):printf("\n\tTC ");break;
271 case(MID_MESSAGE):printf("\n\tMID ");break;
272 case(HNA_MESSAGE):printf("\n\tHNA ");break;
273 default:printf("\n\tTYPE: %d ", netbufs[ifp->if_nr]->buff[4]); break;
275 if(ipversion == AF_INET)
276 printf("to %s size: %d\n\t", ip_to_string((olsr_u32_t *)&sin->sin_addr.s_addr), netbufs[ifp->if_nr]->pending);
278 printf("to %s size: %d\n\t", ip6_to_string(&sin6->sin6_addr), netbufs[ifp->if_nr]->pending);
282 for(i = 0; i < netbufs[ifp->if_nr]->pending;i++)
290 if(ipversion == AF_INET)
291 printf(" %3i", (u_char) netbufs[ifp->if_nr]->buff[i]);
293 printf(" %2x", (u_char) netbufs[ifp->if_nr]->buff[i]);
300 *packet points to the same memory area as the *msg pointer
301 *used when building packets.
304 if(ipversion == AF_INET)
307 if(sendto(ifp->olsr_socket,
308 netbufs[ifp->if_nr]->buff,
309 netbufs[ifp->if_nr]->pending,
311 (struct sockaddr *)sin,
315 perror("sendto(v4)");
316 olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv4 %m");
317 netbufs[ifp->if_nr]->pending = 0;
324 if(sendto(ifp->olsr_socket,
325 netbufs[ifp->if_nr]->buff,
326 netbufs[ifp->if_nr]->pending,
328 (struct sockaddr *)sin6,
332 perror("sendto(v6)");
333 olsr_syslog(OLSR_LOG_ERR, "OLSR: sendto IPv6 %m");
334 fprintf(stderr, "Socket: %d interface: %d\n", ifp->olsr_socket, ifp->if_nr);
335 fprintf(stderr, "To: %s (size: %d)\n", ip6_to_string(&sin6->sin6_addr), sizeof(*sin6));
336 fprintf(stderr, "Outputsize: %d\n", netbufs[ifp->if_nr]->pending);
337 netbufs[ifp->if_nr]->pending = 0;
342 netbufs[ifp->if_nr]->pending = 0;
353 * Add a packet transform function
356 add_ptf(int (*f)(char *, int *))
361 new_ptf = olsr_malloc(sizeof(struct ptf), "Add PTF");
363 new_ptf->next = ptf_list;
364 new_ptf->function = f;
372 * Remove a packet transform function
375 del_ptf(int (*f)(char *, int *))
377 struct ptf *tmp_ptf, *prev;
384 if(tmp_ptf->function == f)
389 ptf_list = tmp_ptf->next;
394 prev->next = tmp_ptf->next;
400 tmp_ptf = tmp_ptf->next;
408 join_mcast(struct interface *ifs, int sock)
410 /* See linux/in6.h */
412 struct ipv6_mreq mcastreq;
414 COPY_IP(&mcastreq.ipv6mr_multiaddr, &ifs->int6_multaddr.sin6_addr);
415 mcastreq.ipv6mr_interface = ifs->if_index;
417 olsr_printf(3, "Interface %s joining multicast %s...", ifs->int_name, olsr_ip_to_string((union olsr_ip_addr *)&ifs->int6_multaddr.sin6_addr));
423 sizeof(struct ipv6_mreq))
426 perror("Join multicast");
431 /* Join reciever group */
436 sizeof(struct ipv6_mreq))
439 perror("Join multicast send");
447 (char *)&mcastreq.ipv6mr_interface,
448 sizeof(mcastreq.ipv6mr_interface))
451 perror("Set multicast if");
456 olsr_printf(3, "OK\n");
462 * Create a IPv6 netmask based on a prefix length
466 olsr_prefix_to_netmask(union olsr_ip_addr *adr, olsr_u16_t prefix)
476 memset(adr, 0, ipsize);
480 adr->v6.s6_addr[i] = (p < 8) ? 0xff ^ (0xff << p) : 0xff;
485 olsr_printf(3, "Prefix %d = Netmask: %s\n", prefix, olsr_ip_to_string(adr));
494 * Calculate prefix length based on a netmask
498 olsr_netmask_to_prefix(union olsr_ip_addr *adr)
505 memset(adr, 0, ipsize);
507 for(i = 0; i < 16; i++)
509 if(adr->v6.s6_addr[i] == 0xff)
515 for(tmp = adr->v6.s6_addr[i];
523 olsr_printf(3, "Netmask: %s = Prefix %d\n", olsr_ip_to_string(adr), prefix);
532 *Converts a sockaddr struct to a string representing
533 *the IP address from the sockaddr struct
535 *<b>NON REENTRANT!!!!</b>
537 *@param address_to_convert the sockaddr struct to "convert"
538 *@return a char pointer to the string containing the IP
541 sockaddr_to_string(struct sockaddr *address_to_convert)
543 struct sockaddr_in *address;
545 address=(struct sockaddr_in *)address_to_convert;
546 return(inet_ntoa(address->sin_addr));
552 *Converts the 32bit olsr_u32_t datatype to
555 *<b>NON REENTRANT!!!!</b>
557 *@param address the olsr_u32_t to "convert"
558 *@return a char pointer to the string containing the IP
562 ip_to_string(olsr_u32_t *address)
567 return(inet_ntoa(in));
575 *Converts the 32bit olsr_u32_t datatype to
578 *<b>NON REENTRANT!!!!</b>
580 *@param addr6 the address to "convert"
581 *@return a char pointer to the string containing the IP
585 ip6_to_string(struct in6_addr *addr6)
587 return (char *)inet_ntop(AF_INET6, addr6, ipv6_buf, sizeof(ipv6_buf));
592 olsr_ip_to_string(union olsr_ip_addr *addr)
598 if(ipversion == AF_INET)
606 ret = (char *)inet_ntop(AF_INET6, &addr->v6, ipv6_buf, sizeof(ipv6_buf));