The following commit has been merged in the master branch: commit 0d7b2685cbd951ae9876934781cb829a0e1e4d12 Author: Stefan Sperling stsp@stsp.in-berlin.de Date: Wed Aug 30 23:39:29 2006 +0200
Initial FreeBSD support.
diff --git a/Makefile b/Makefile index 0d27d7d..b876def 100755 --- a/Makefile +++ b/Makefile @@ -20,7 +20,17 @@ CC = gcc CFLAGS = -Wall -O0 -g3 LDFLAGS = -lpthread
-batman: batman.o linux.o +UNAME=$(shell uname) + +ifeq ($(UNAME),Linux) +OS_OBJ= linux.o +endif + +ifeq ($(UNAME),FreeBSD) +OS_OBJ= freebsd.o +endif + +batman: batman.o $(OS_OBJ)
clean: rm -f batman *.o *~ diff --git a/batman.c b/batman.c index 68f56e8..cf7653e 100755 --- a/batman.c +++ b/batman.c @@ -80,7 +80,7 @@ static LIST_HEAD(gw_list); LIST_HEAD(if_list); static unsigned int next_own;
- +struct vis_if vis_if;
void usage(void) { diff --git a/linux.c b/freebsd.c old mode 100755 new mode 100644 similarity index 66% copy from linux.c copy to freebsd.c index 450cea4..05ee983 --- a/linux.c +++ b/freebsd.c @@ -18,11 +18,14 @@ */
#include <sys/types.h> +#include <sys/sysctl.h> #include <sys/socket.h> #include <sys/time.h> #include <sys/ioctl.h> -#include <arpa/inet.h> #include <net/route.h> +#include <net/if.h> +#include <netinet/in.h> +#include <arpa/inet.h> #include <stdio.h> #include <time.h> #include <string.h> @@ -31,17 +34,35 @@ #include <unistd.h> #include <signal.h> #include <stdlib.h> -#include <linux/if.h> +#include <err.h> +#include <limits.h> + +/* Resolve namespace pollution from sys/queue.h */ +#ifdef LIST_HEAD +#undef LIST_HEAD +#endif
#include "os.h" #include "batman.h" #include "list.h"
-struct vis_if vis_if; - static struct timeval start_time; static int stop;
+/* Message structure used to interface the kernel routing table. + * See route(4) for details on the message passing interface for + * manipulating the kernel routing table in FreeBSD. + * We transmit at most two addresses at once: a destination host + * and a gateway. + */ +struct rt_msg +{ + struct rt_msghdr hdr; + struct sockaddr_in dest; + struct sockaddr_in gateway; +}; + +#define SYSCTL_FORWARDING "net.inet.ip.forwarding"
static void get_time_internal(struct timeval *tv) { @@ -84,26 +105,30 @@ void output(char *format, ...)
void set_forwarding(int state) { - FILE *f; - - if((f = fopen("/proc/sys/net/ipv4/ip_forward", "w")) == NULL) - return; + /* FreeBSD allows us to set the boolean IP forwarding + * sysctl to anything. Check the value for sanity. */ + if (state < 0 || state > 1) + { + errno = EINVAL; + err(1, "set_forwarding: %i", state); + }
- fprintf(f, "%d", state); - fclose(f); + if (sysctlbyname(SYSCTL_FORWARDING, NULL, NULL, &state, sizeof(state)) == -1) + { + err(1, "Cannot enable packet forwarding"); + } }
int get_forwarding(void) { - FILE *f; - int state = 0; - - if((f = fopen("/proc/sys/net/ipv4/ip_forward", "r")) == NULL) - return 0; - - fscanf(f, "%d", &state); - fclose(f); - + int state; + size_t len; + + len = sizeof(state); + if (sysctlbyname(SYSCTL_FORWARDING, &state, &len, NULL, 0) == -1) + { + err(1, "Cannot tell if packet forwarding is enabled"); + } return state; }
@@ -114,60 +139,110 @@ void close_all_sockets()
list_for_each(if_pos, &if_list) { batman_if = list_entry(if_pos, struct batman_if, list); -// pthread_join( batman_if->listen_thread_id, NULL ); - close(batman_if->tcp_gw_sock); + close(batman_if->udp_send_sock); close(batman_if->udp_recv_sock); } - - if(vis_if.sock) - close(vis_if.sock); }
-void add_del_route(unsigned int dest, unsigned int router, int del, char *dev, int sock) +void add_del_route(unsigned int dest, unsigned int router, int del, + char *dev, int sock) { - struct rtentry route; char str1[16], str2[16]; - struct sockaddr_in *addr; + int rt_sock; + static unsigned int seq = 0; + struct rt_msg msg; + struct sockaddr_in *so_dest, *so_gateway; + struct sockaddr_in ifname; + socklen_t ifname_len; + ssize_t len; + pid_t pid; + + so_dest = NULL; + so_gateway = NULL; + + memset(&msg, 0, sizeof(struct rt_msg));
inet_ntop(AF_INET, &dest, str1, sizeof (str1)); inet_ntop(AF_INET, &router, str2, sizeof (str2));
- memset(&route, 0, sizeof (struct rtentry)); + msg.hdr.rtm_type = del ? RTM_DELETE : RTM_ADD; + msg.hdr.rtm_version = RTM_VERSION; + msg.hdr.rtm_flags = RTF_STATIC | RTF_UP | RTF_HOST; + msg.hdr.rtm_addrs = RTA_DST;
- addr = (struct sockaddr_in *)&route.rt_dst; + so_dest = &msg.dest; + so_dest->sin_family = AF_INET; + so_dest->sin_len = sizeof(struct sockaddr_in); + so_dest->sin_addr.s_addr = dest;
- addr->sin_family = AF_INET; - addr->sin_addr.s_addr = dest; + msg.hdr.rtm_msglen = sizeof(struct rt_msghdr) + + (2 * sizeof(struct sockaddr_in));
- addr = (struct sockaddr_in *)&route.rt_genmask; + msg.hdr.rtm_flags |= RTF_GATEWAY; + msg.hdr.rtm_addrs |= RTA_GATEWAY;
- addr->sin_family = AF_INET; - addr->sin_addr.s_addr = 0xffffffff; + so_gateway = &msg.gateway; + so_gateway->sin_family = AF_INET; + so_gateway->sin_len = sizeof(struct sockaddr_in);
- route.rt_flags = RTF_HOST | RTF_UP; - - if (dest != router) - { - addr = (struct sockaddr_in *)&route.rt_gateway; + if (dest != router) { + /* This is not a direct route; router is our gateway + * to the remote host. + * We essentially run 'route add <remote ip> <gateway ip> */ + so_gateway->sin_addr.s_addr = router; + } else { + /* This is a direct route to the remote host. + * We use our own IP address as gateway. + * We essentially run 'route add <remote ip> <local ip> */ + ifname_len = sizeof(struct sockaddr_in); + if (getsockname(sock, (struct sockaddr*)&ifname, &ifname_len) == -1) { + err(1, "Could not get name of interface %s", dev); + } + so_gateway->sin_addr.s_addr = ifname.sin_addr.s_addr; + }
- addr->sin_family = AF_INET; - addr->sin_addr.s_addr = router; + output("%s route to %s via %s\n", del ? "Deleting" : "Adding", str1, str2);
- route.rt_flags |= RTF_GATEWAY; + rt_sock = socket(PF_ROUTE, SOCK_RAW, AF_INET); + if (rt_sock < 0) + err(1, "Could not open socket to routing table");
- output("%s route to %s via %s\n", del ? "Deleting" : "Adding", str1, str2); - } else { - output("%s route to %s via 0.0.0.0\n", del ? "Deleting" : "Adding", str1); - } + pid = getpid(); + len = 0; + seq++;
- route.rt_metric = 1; + /* Send message */ + do { + msg.hdr.rtm_seq = seq; + len = write(rt_sock, &msg, msg.hdr.rtm_msglen); + if (len < 0) + { + warn("Error sending routing message to kernel"); + err(1, "Cannot %s route to %s", + del ? "delete" : "add", str1); + } + } while (len < msg.hdr.rtm_msglen);
- route.rt_dev = dev; + /* Get reply */ + do { + len = read(rt_sock, &msg, sizeof(struct rt_msg)); + if (len < 0) + err(1, "Error reading from routing socket"); + } while (len > 0 && (msg.hdr.rtm_seq != seq || msg.hdr.rtm_pid != pid));
- if (ioctl(sock, del ? SIOCDELRT : SIOCADDRT, &route) < 0) + /* Evaluate reply */ + if (msg.hdr.rtm_version != RTM_VERSION) + { + warn("routing message version mismatch: " + "compiled with version %i, " + "but running kernel uses version %i", RTM_VERSION, + msg.hdr.rtm_version); + } + if (msg.hdr.rtm_errno) { - fprintf(stderr, "Cannot %s route to %s via %s: %s\n", - del ? "delete" : "add", str1, str2, strerror(errno)); + errno = msg.hdr.rtm_errno; + err(1, "Cannot %s route to %s", + del ? "delete" : "add", str1); } }
@@ -291,6 +366,24 @@ int receive_packet(unsigned char *buff, int len, unsigned int *neigh, unsigned i
int send_packet(unsigned char *buff, int len, struct sockaddr_in *broad, int sock) { +//#define STSP_DEBUG +#ifdef STSP_DEBUG + struct ifreq int_req; + char str[16]; + + memset(&int_req, 0, sizeof (struct ifreq)); + strcpy(int_req.ifr_name, "wi0"); + + if (ioctl(sock, SIOCGIFADDR, &int_req) < 0) + { + fprintf(stderr, "Cannot get IP address of interface %s\n", "wi0"); + close_all_sockets(); + exit(EXIT_FAILURE); + } + + addr_to_string(((struct sockaddr_in *)&int_req.ifr_addr)->sin_addr.s_addr, str, sizeof (str)); + printf("Sending packet with source IP %s\n", str); +#endif if (sendto(sock, buff, len, 0, (struct sockaddr *)broad, sizeof (struct sockaddr_in)) < 0) { fprintf(stderr, "Cannot send packet: %s\n", strerror(errno)); @@ -305,47 +398,16 @@ static void handler(int sig) stop = 1; }
-void *gw_listen( void *arg ) { - - struct batman_if *batman_if = (struct batman_if *)arg; - struct sockaddr_in client_addr; - socklen_t sin_size = sizeof(struct sockaddr_in); - char str1[16], str2[16]; - int client_fd; - - while (!is_aborted()) { - - if ( ( client_fd = accept(batman_if->tcp_gw_sock, (struct sockaddr *)&client_addr, &sin_size) ) == -1 ) { - perror("accept"); - continue; - } - - if ( debug_level >= 0 ) { - addr_to_string(batman_if->addr.sin_addr.s_addr, str1, sizeof (str1)); - addr_to_string(client_addr.sin_addr.s_addr, str2, sizeof (str2)); - printf( "gateway: %s got connection from %s\n", str1, str2 ); - } - - close( client_fd ); - - } - - return NULL; - -} - int main(int argc, char *argv[]) { - struct in_addr tmp_ip_holder; + struct in_addr tmp_pref_gw; struct batman_if *batman_if; struct ifreq int_req; int on = 1, res, optchar, found_args = 1; char str1[16], str2[16], *dev; - unsigned int vis_server = 0;
- stop = 0; dev = NULL; - memset(&tmp_ip_holder, 0, sizeof (struct in_addr)); + memset(&tmp_pref_gw, 0, sizeof (struct in_addr));
printf( "B.A.T.M.A.N-II v%s (internal version %i)\n", VERSION, BATMAN_VERSION );
@@ -414,14 +476,14 @@ int main(int argc, char *argv[]) case 'p':
errno = 0; - if ( inet_pton(AF_INET, optarg, &tmp_ip_holder) < 1 ) { + if ( inet_pton(AF_INET, optarg, &tmp_pref_gw) < 1 ) {
printf( "Invalid preferred gateway IP specified: %s\n", optarg ); exit(EXIT_FAILURE);
}
- pref_gateway = tmp_ip_holder.s_addr; + pref_gateway = tmp_pref_gw.s_addr;
found_args += 2; break; @@ -429,14 +491,14 @@ int main(int argc, char *argv[]) case 's':
errno = 0; - if ( inet_pton(AF_INET, optarg, &tmp_ip_holder) < 1 ) { + if ( inet_pton(AF_INET, optarg, &tmp_pref_gw) < 1 ) {
- printf( "Invalid preferred visualation server IP specified: %s\n", optarg ); + printf( "Invalid preferred gateway IP specified: %s\n", optarg ); exit(EXIT_FAILURE);
}
- vis_server = tmp_ip_holder.s_addr; + pref_gateway = tmp_pref_gw.s_addr;
found_args += 2; @@ -465,16 +527,20 @@ int main(int argc, char *argv[])
if ( strlen(batman_if->dev) > IFNAMSIZ - 1 ) { fprintf(stderr, "Interface name too long: %s\n", batman_if->dev); - close_all_sockets(); exit(EXIT_FAILURE); }
- batman_if->udp_recv_sock = socket(PF_INET, SOCK_DGRAM, 0); + batman_if->udp_send_sock = socket(PF_INET, SOCK_DGRAM, 0); + if (batman_if->udp_send_sock < 0) + { + fprintf(stderr, "Cannot create send socket: %s", strerror(errno)); + exit(EXIT_FAILURE); + }
+ batman_if->udp_recv_sock = socket(PF_INET, SOCK_DGRAM, 0); if (batman_if->udp_recv_sock < 0) { - fprintf(stderr, "Cannot create socket: %s", strerror(errno)); - close_all_sockets(); + fprintf(stderr, "Cannot create receive socket: %s", strerror(errno)); exit(EXIT_FAILURE); }
@@ -503,74 +569,37 @@ int main(int argc, char *argv[]) batman_if->broad.sin_port = htons(PORT); batman_if->broad.sin_addr.s_addr = ((struct sockaddr_in *)&int_req.ifr_broadaddr)->sin_addr.s_addr;
- if (setsockopt(batman_if->udp_recv_sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (int)) < 0) + if (setsockopt(batman_if->udp_send_sock, SOL_SOCKET, SO_BROADCAST, &on, sizeof (int)) < 0) { fprintf(stderr, "Cannot enable broadcasts: %s\n", strerror(errno)); close_all_sockets(); exit(EXIT_FAILURE); }
- if (bind(batman_if->udp_recv_sock, (struct sockaddr *)&batman_if->broad, sizeof (struct sockaddr_in)) < 0) + if (bind(batman_if->udp_send_sock, (struct sockaddr *)&batman_if->addr, sizeof (struct sockaddr_in)) < 0) { - fprintf(stderr, "Cannot bind socket: %s\n", strerror(errno)); + fprintf(stderr, "Cannot bind send socket: %s\n", strerror(errno)); close_all_sockets(); exit(EXIT_FAILURE); }
- batman_if->udp_send_sock = batman_if->udp_recv_sock; + if (bind(batman_if->udp_recv_sock, (struct sockaddr *)&batman_if->broad, sizeof (struct sockaddr_in)) < 0) + { + fprintf(stderr, "Cannot bind receive socket: %s\n", strerror(errno)); + close_all_sockets(); + exit(EXIT_FAILURE); + }
addr_to_string(batman_if->addr.sin_addr.s_addr, str1, sizeof (str1)); addr_to_string(batman_if->broad.sin_addr.s_addr, str2, sizeof (str2));
printf("Using interface %s with address %s and broadcast address %s\n", batman_if->dev, str1, str2);
- if ( gateway_class != 0 ) { - - batman_if->tcp_gw_sock = socket(PF_INET, SOCK_STREAM, 0); - - if (batman_if->tcp_gw_sock < 0) { - fprintf(stderr, "Cannot create socket: %s", strerror(errno)); - close_all_sockets(); - exit(EXIT_FAILURE); - } - - if (setsockopt(batman_if->tcp_gw_sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(int)) < 0) { - printf("Cannot enable reuse of address: %s\n", strerror(errno)); - close_all_sockets(); - exit(EXIT_FAILURE); - } - - if (bind( batman_if->tcp_gw_sock, (struct sockaddr*)&batman_if->addr, sizeof(struct sockaddr_in)) < 0) { - printf("Cannot bind socket: %s\n",strerror(errno)); - close_all_sockets(); - exit(EXIT_FAILURE); - } - - if (listen( batman_if->tcp_gw_sock, 10 ) < 0) { - printf("Cannot listen socket: %s\n",strerror(errno)); - close_all_sockets(); - exit(EXIT_FAILURE); - } - - pthread_create(&batman_if->listen_thread_id, NULL, &gw_listen, batman_if); - - } - found_ifs++; found_args++;
}
- if(vis_server) - { - memset(&vis_if.addr, 0, sizeof(vis_if.addr)); - vis_if.addr.sin_family = AF_INET; - vis_if.addr.sin_port = htons(1967); - vis_if.addr.sin_addr.s_addr = vis_server; - vis_if.sock = socket( PF_INET, SOCK_DGRAM, 0); - } else - memset(&vis_if, 0, sizeof(vis_if)); -
if (found_ifs == 0) { @@ -593,13 +622,6 @@ int main(int argc, char *argv[]) return 1; }
- if ( ( routing_class == 0 ) && ( pref_gateway != 0 ) ) - { - fprintf(stderr, "Error - preferred gateway can't be set without specifying routing class !\n"); - usage(); - return 1; - } - if ( debug_level > 0 ) printf("debug level: %i\n", debug_level); if ( ( debug_level > 0 ) && ( orginator_interval != 1000 ) ) printf( "orginator interval: %i\n", orginator_interval ); if ( ( debug_level > 0 ) && ( gateway_class > 0 ) ) printf( "gateway class: %i\n", gateway_class ); @@ -609,6 +631,9 @@ int main(int argc, char *argv[]) printf( "preferred gateway: %s\n", str1 ); }
+ + stop = 0; + signal(SIGINT, handler);
gettimeofday(&start_time, NULL); @@ -619,5 +644,4 @@ int main(int argc, char *argv[])
close_all_sockets(); return res; - } diff --git a/linux.c b/linux.c index 450cea4..c9242a0 100755 --- a/linux.c +++ b/linux.c @@ -37,7 +37,7 @@ #include "batman.h" #include "list.h"
-struct vis_if vis_if; +extern struct vis_if vis_if;
static struct timeval start_time; static int stop;