The following commit has been merged in the master branch:
commit 0d7b2685cbd951ae9876934781cb829a0e1e4d12
Author: Stefan Sperling <stsp(a)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;
--
batman; test conversation