/* * Copyright (C) 2006 BATMAN contributors: * Thomas Lopatic * This program is free software; you can redistribute it and/or * modify it under the terms of version 2 of the GNU General Public * License as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA * 02110-1301, USA * */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "os.h" #include "batman-specific.h" void add_del_route( uint32_t dest, uint16_t netmask, uint32_t router, int8_t del, char *dev, int32_t sock ) { struct rtentry route; char str1[16], str2[16]; struct sockaddr_in *addr; inet_ntop(AF_INET, &dest, str1, sizeof (str1)); inet_ntop(AF_INET, &router, str2, sizeof (str2)); memset(&route, 0, sizeof (struct rtentry)); addr = (struct sockaddr_in *)&route.rt_dst; addr->sin_family = AF_INET; addr->sin_addr.s_addr = dest; addr = (struct sockaddr_in *)&route.rt_genmask; addr->sin_family = AF_INET; addr->sin_addr.s_addr = ( netmask == 32 ? 0xffffffff : htonl( ~ ( 0xffffffff >> netmask ) ) ); route.rt_flags = ( netmask == 32 ? ( RTF_HOST | RTF_UP ) : RTF_UP ); route.rt_metric = 1; if ( ( dest != router ) || ( ( dest == 0 ) && ( router == 0 ) ) ) { addr = (struct sockaddr_in *)&route.rt_gateway; addr->sin_family = AF_INET; addr->sin_addr.s_addr = router; if ( ( dest == 0 ) && ( router == 0 ) ) { route.rt_metric = 0; debug_output( 3, "%s default route via %s\n", del ? "Deleting" : "Adding", dev ); debug_output( 4, "%s default route via %s\n", del ? "Deleting" : "Adding", dev ); } else { route.rt_flags |= RTF_GATEWAY; debug_output( 3, "%s route to %s/%i via %s (%s)\n", del ? "Deleting" : "Adding", str1, netmask, str2, dev ); debug_output( 4, "%s route to %s/%i via %s (%s)\n", del ? "Deleting" : "Adding", str1, netmask, str2, dev ); } } else { debug_output( 3, "%s route to %s via 0.0.0.0 (%s)\n", del ? "Deleting" : "Adding", str1, dev ); debug_output( 4, "%s route to %s via 0.0.0.0 (%s)\n", del ? "Deleting" : "Adding", str1, dev ); } route.rt_dev = dev; if ( ioctl( sock, del ? SIOCDELRT : SIOCADDRT, &route ) < 0 ) debug_output( 0, "Error - can't %s route to %s/%i via %s: %s\n", del ? "delete" : "add", str1, netmask, str2, strerror(errno) ); } /* Probe for tun interface availability */ int8_t probe_tun() { int32_t fd; if ( ( fd = open( "/dev/net/tun", O_RDWR ) ) < 0 ) { debug_output( 0, "Error - could not open '/dev/net/tun' ! Is the tun kernel module loaded ?\n" ); return 0; } close( fd ); return 1; } int8_t del_dev_tun( int32_t fd ) { if ( ioctl( fd, TUNSETPERSIST, 0 ) < 0 ) { debug_output( 0, "Error - can't delete tun device: %s\n", strerror(errno) ); return -1; } close( fd ); return 1; } int8_t add_dev_tun( struct batman_if *batman_if, uint32_t tun_addr, char *tun_dev, size_t tun_dev_size, int32_t *fd ) { int32_t tmp_fd; struct ifreq ifr_tun, ifr_if; struct sockaddr_in addr; /* set up tunnel device */ memset( &ifr_tun, 0, sizeof(ifr_tun) ); memset( &ifr_if, 0, sizeof(ifr_if) ); ifr_tun.ifr_flags = IFF_TUN | IFF_NO_PI; if ( ( *fd = open( "/dev/net/tun", O_RDWR ) ) < 0 ) { debug_output( 0, "Error - can't create tun device (/dev/net/tun): %s\n", strerror(errno) ); return -1; } if ( ( ioctl( *fd, TUNSETIFF, (void *) &ifr_tun ) ) < 0 ) { debug_output( 0, "Error - can't create tun device (TUNSETIFF): %s\n", strerror(errno) ); close(*fd); return -1; } if ( ioctl( *fd, TUNSETPERSIST, 1 ) < 0 ) { debug_output( 0, "Error - can't create tun device (TUNSETPERSIST): %s\n", strerror(errno) ); close(*fd); return -1; } tmp_fd = socket(AF_INET, SOCK_DGRAM, 0); if ( tmp_fd < 0 ) { debug_output( 0, "Error - can't create tun device (udp socket): %s\n", strerror(errno) ); del_dev_tun( *fd ); return -1; } /* set ip of this end point of tunnel */ memset( &addr, 0, sizeof(addr) ); addr.sin_addr.s_addr = tun_addr; addr.sin_family = AF_INET; memcpy( &ifr_tun.ifr_addr, &addr, sizeof(struct sockaddr) ); if ( ioctl( tmp_fd, SIOCSIFADDR, &ifr_tun) < 0 ) { debug_output( 0, "Error - can't create tun device (SIOCSIFADDR): %s\n", strerror(errno) ); del_dev_tun( *fd ); close( tmp_fd ); return -1; } if ( ioctl( tmp_fd, SIOCGIFFLAGS, &ifr_tun) < 0 ) { debug_output( 0, "Error - can't create tun device (SIOCGIFFLAGS): %s\n", strerror(errno) ); del_dev_tun( *fd ); close( tmp_fd ); return -1; } ifr_tun.ifr_flags |= IFF_UP; ifr_tun.ifr_flags |= IFF_RUNNING; if ( ioctl( tmp_fd, SIOCSIFFLAGS, &ifr_tun) < 0 ) { debug_output( 0, "Error - can't create tun device (SIOCSIFFLAGS): %s\n", strerror(errno) ); del_dev_tun( *fd ); close( tmp_fd ); return -1; } /* get MTU from real interface */ strncpy( ifr_if.ifr_name, batman_if->dev, IFNAMSIZ - 1 ); if ( ioctl( tmp_fd, SIOCGIFMTU, &ifr_if ) < 0 ) { debug_output( 0, "Error - can't create tun device (SIOCGIFMTU): %s\n", strerror(errno) ); del_dev_tun( *fd ); close( tmp_fd ); return -1; } /* set MTU of tun interface: real MTU - 28 */ if ( ifr_if.ifr_mtu < 100 ) { debug_output( 0, "Warning - MTU smaller than 100 -> can't reduce MTU anymore\n" ); } else { ifr_tun.ifr_mtu = ifr_if.ifr_mtu - 28; if ( ioctl( tmp_fd, SIOCSIFMTU, &ifr_tun ) < 0 ) { debug_output( 0, "Error - can't create tun device (SIOCSIFMTU): %s\n", strerror(errno) ); del_dev_tun( *fd ); close( tmp_fd ); return -1; } } strncpy( tun_dev, ifr_tun.ifr_name, tun_dev_size - 1 ); close( tmp_fd ); return 1; }