Commit b54949cb authored by Juliusz Chroboczek's avatar Juliusz Chroboczek

Initial import.

parents
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
PREFIX = /usr/local
CDEBUGFLAGS = -Os -g -Wall
DEFINES = $(PLATFORM_DEFINES)
CFLAGS = $(CDEBUGFLAGS) $(DEFINES) $(EXTRA_DEFINES)
SRCS = ariadne.c net.c kernel.c util.c destination.c neighbour.c \
route.c xroute.c message.c
OBJS = ariadne.o net.o kernel.o util.o destination.o neighbour.o \
route.o xroute.o message.o
ariadne: $(OBJS)
$(CC) $(CFLAGS) $(LDFLAGS) -o ariadne $(OBJS) $(LDLIBS)
ariadne.html: ariadne.man
groff -man -Thtml ariadne.man > ariadne.html
.PHONY: all install uninstall clean
all: ariadne
install: ariadne ariadne.man
-rm -f $(TARGET)$(PREFIX)/bin/ariadne
cp -f ariadne $(TARGET)$(PREFIX)/bin
mkdir -p $(TARGET)$(PREFIX)/man/man8
cp -f ariadne.man $(TARGET)$(PREFIX)/man/man8/ariadne.8
uninstall:
-rm -f $(TARGET)$(PREFIX)/bin/ariadne
-rm -f $(TARGET)$(PREFIX)/man/man8/ariadne.8
clean:
-rm -f ariadne ariadne.html *.o *~ core TAGS gmon.out
Ariadne
*******
Ariadne is a loop-avoiding distance-vector routing protocol roughly
based on HSDV and AODV, but with provisions for link cost estimation
and injection of external routes.
Installation
************
$ make
$ su -c 'make install'
Running Ariadne
***************
In order to run Ariadne on a node (wireless or wired), just give it an
IPv6 address, then run the routing daemon. Assuming your wireless
interface is eth1, and your IPv6 address is $IPv6, do
# ip -6 addr add $IPv6 dev eth1
# ariadne $IPv6 eth1
If your node has multiple interfaces which you want to participate in
the Ariadne netowk, just list them all:
# ariadne $IPv6 eth0 eth1 sit1
On an access point, you'll probably want to inject external routes
into the Ariadne network. First check that you have a default route
on your access point:
$ ip -6 route show default
default via ...
Then run the routing daemon as so:
# ariadne -n default 256 $IPv6 eth1
Juliusz
This diff is collapsed.
/*
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#define MAXROUTES 512
#define MAXDESTS 1024
#define MAXNEIGHBOURS 128
#define MAXNETS 8
#define MAXXROUTES 64
#define MAXMYXROUTES 8
#define MAX_BUFFERED_UPDATES 100
#define INFINITY ((unsigned short)(~0))
#undef MAX
#undef MIN
#define MAX(x,y) ((x)<=(y)?(y):(x))
#define MIN(x,y) ((x)<=(y)?(x):(y))
#if defined(__GNUC__) && (__GNUC__ >= 3)
#define ATTRIBUTE(x) __attribute__(x)
#else
#define ATTRIBUTE(x) /**/
#endif
#ifndef IF_NAMESIZE
#include <net/if.h>
#endif
#ifdef HAVE_VALGRIND
#include <valgrind/memcheck.h>
#else
#ifndef VALGRIND_MAKE_MEM_UNDEFINED
#define VALGRIND_MAKE_MEM_UNDEFINED(a, b) do {} while(0)
#endif
#ifndef VALGRIND_CHECK_MEM_IS_DEFINED
#define VALGRIND_CHECK_MEM_IS_DEFINED(a, b) do {} while(0)
#endif
#endif
struct network {
unsigned int ifindex;
int wired;
unsigned short cost;
int hello_time;
int self_update_time;
int update_time;
char ifname[IF_NAMESIZE];
int buffered;
struct timeval flush_time;
int bufsize;
unsigned char *sendbuf;
unsigned char hello_seqno;
unsigned int hello_interval;
unsigned int self_update_interval;
};
extern struct timeval now;
extern int debug;
extern int reboot_time;
extern unsigned char myid[16];
extern struct network nets[MAXNETS];
extern int numnets;
extern int protocol_port;
extern unsigned char protocol_group[16];
extern int protocol_socket;
.TH ARIADNE 1
.SH NAME
ariadne \- ad-hoc network routing daemon
.SH SYNOPSIS
.B ariadne
[
.B \-m
.I multicast-address
]
[
.B \-p
.I port
] [
.B -S
.I state-file
] [
.B \-h
.I hello-interval
] [
.B \-H
.I wired-hello-interval
] [
.B \-u
.I update-interval
] [
.B \-k
.I kernel-metric
] [
.B \-s
] [
.B \-b
] [
.B \-p
] [
.B \-d
.I level
] [
.B \-n
.I
.I prefix cost
]...
.I address
.IR interface ...
.SH DESCRIPTION
Ariadne is a loop-avoiding distance-vector routing protocol roughly
based on HSDV and AODV, but with provisions for link cost estimation
and injection of external routes.
While it is optimised for wireless mesh networks, Ariadne will also
work efficiently on classical wired networks. In the worst case, it
will generate roughly double the amount of traffic that RIPng would
generate, while never counting to infinity.
.SH OPTIONS
.TP
.BI \-m " multicast-address"
Specify the link-local multicast address to be used by the protocol.
.TP
.BI \-p " port"
Specify the UDP port number to be used by the Ariadne protocol.
.TP
.BI \-S " state-file"
Set the name of the file used for preserving long-term information
between invocations of the
.B ariadne
daemon. If this file is deleted, the daemon will run in passive mode
for 3 minutes when it is next invoked (see
.B -P
below), and other hosts might initially not accept to route to it.
The default is
.BR /var/lib/ariadne-state .
.TP
.BI \-h " hello-interval"
Specify the interval in seconds at which periodic hello packets are
sent on wireless interfaces. The default is 8.
.TP
.BI \-H " wired-hello-interval"
Specify the interval in seconds at which periodic hello packets are
sent on wired interfaces. The default is 30.
.TP
.BI \-u " update-interval"
Specify the interval in seconds at which periodic routing table dumps
are made on all interfaces. The default is either the wired hello
interval, or 150, whichever is less.
.TP
.BI \-k " kernel-metric"
Specify a value that will be added to routes' metrics before
installing them in the kernel; this is useful when a single node
participates in multiple routing protocols. The default is 0.
.TP
.B \-s
Do not perform split-horizon processing on wired interfaces.
Split-horizon is never performed on wireless interfaces.
.TP
.B \-b
Generate messages for detecting bidirectional communication failures
on wired interfaces. By default, wired interfaces are assumed to be
symmetric.
.TP
.B \-P
Run in parasitic (passive) mode. The daemon will not announce any
routes except for itself.
.TP
.BI \-d " level"
Debug level. A value of 1 requests a routing table dump at every
iteration through the daemon's main loop. A value of 2 additionally
requests tracing every message sent or received. The default is 0.
.TP
.BI \-n " network cost"
Advertise an external route for the given network with the given cost.
We suggest a cost of 256 \[mu]
.RI ( n
+ 1) for a network
.I n
hops away.
.I Network
should be either the string
.BR default ,
or a nework specification in CIDR notation
.IB prefix / length.
If
.I length
is omitted, it defaults to 128 (a host route).
.TP
.I address
The IPv6 address that the node should advertise for itself.
(Additional addresses can be advertised as external routes with a cost
of 0.)
.TP
.IR interface ...
The list of interfaces on which the protocol should operate.
.SH WIRED INTERFACES
By default, the daemon optimises traffic on wired interfaces by
sending fewer periodic hello messages, performing split-horizon
processing and not generating any reverse reachability information.
These optimisations can be disabled using the
.BR -H ,
.B -s
and
.B -b
options respectively.
No link cost estimation is performed on wired interfaces: a wired
adjacency is assumed to be up if at least one of the last three hello
messages has been received, and down otherwise.
.SH FILES
.TP
.B /var/lib/ariadne-state
The default location of the file storing long-term state.
.SH SECURITY
Ariadne is a completely insecure protocol: any attacker able to
inject IP packets with a link-local source address can disrupt the
protocol's operation.
Since Ariadne uses link-local addresses only, there is no need to
update firewalls to allow forwarding of Ariadne protocol packets. If
ingress filtering is done on a host, the protocol port should be
opened. As Ariadne uses unicast packets in some cases, just allowing
packets destined to the multicast address is not enough.
.SH BUGS
Plenty. This is experimental software, run at your own risk.
.SH SEE ALSO
.BR routed (8),
.BR route6d (8),
.BR zebra (8),
.BR ahcpd (8).
.SH AUTHOR
Juliusz Chroboczek.
/*
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "ariadne.h"
#include "util.h"
#include "destination.h"
struct destination dests[MAXDESTS];
int numdests = 0;
struct destination *
find_destination(const unsigned char *d, int create, unsigned char seqno)
{
int i;
for(i = 0; i < numdests; i++) {
if(memcmp(dests[i].address, d, 16) == 0)
return &dests[i];
}
if(!create)
return NULL;
if(i >= numdests) {
if(numdests >= MAXDESTS) {
fprintf(stderr, "Too many destinations.\n");
return NULL;
}
memcpy(dests[numdests].address, d, 16);
numdests++;
}
dests[i].seqno = seqno;
dests[i].metric = INFINITY;
return &dests[i];
}
void
update_destination(struct destination *dest,
unsigned char seqno, unsigned short metric)
{
if(seqno_compare(dest->seqno, seqno) < 0 ||
(dest->seqno == seqno && dest->metric > metric)) {
dest->time = now.tv_sec;
dest->seqno = seqno;
dest->metric = metric;
}
}
/*
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
struct destination {
unsigned char address[16];
unsigned char seqno;
unsigned short metric;
int time;
};
struct destination *find_destination(const unsigned char *d,
int create, unsigned char seqno);
void update_destination(struct destination *dest,
unsigned char seqno, unsigned short metric);
/*
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <net/route.h>
#include <net/if.h>
#include "kernel.h"
static int old_forwarding = -1;
static int old_accept_redirects = -1;
static int
read_proc(char *filename)
{
char buf[100];
int fd, rc;
fd = open(filename, O_RDONLY);
if(fd < 0)
return -1;
rc = read(fd, buf, 99);
if(rc < 0) {
int saved_errno = errno;
close(fd);
errno = saved_errno;
return -1;
}
close(fd);
if(rc == 0)
return -1;
buf[rc] = '\0';
return atoi(buf);
}
static int
write_proc(char *filename, int value)
{
char buf[100];
int fd, rc, n;
n = snprintf(buf, 100, "%d", value);
fd = open(filename, O_WRONLY);
if(fd < 0)
return -1;
rc = write(fd, buf, n);
if(rc < n) {
int saved_errno = errno;
close(fd);
errno = saved_errno;
return -1;
}
close(fd);
return 1;
}
int
kernel_setup(int setup)
{
int rc;
if(setup) {
old_forwarding = read_proc("/proc/sys/net/ipv6/conf/all/forwarding");
if(old_forwarding < 0) {
perror("Couldn't read forwarding knob.");
return -1;
}
rc = write_proc("/proc/sys/net/ipv6/conf/all/forwarding", 1);
if(rc < 0) {
perror("Couldn't write forwarding knob.");
return -1;
}
old_accept_redirects =
read_proc("/proc/sys/net/ipv6/conf/all/accept_redirects");
if(old_accept_redirects < 0) {
perror("Couldn't read accept_redirects knob.");
return -1;
}
rc = write_proc("/proc/sys/net/ipv6/conf/all/accept_redirects", 0);
if(rc < 0) {
perror("Couldn't write accept_redirects knob.");
return -1;
}
return 1;
} else {
if(old_forwarding >= 0) {
rc = write_proc("/proc/sys/net/ipv6/conf/all/forwarding",
old_forwarding);
if(rc < 0) {
perror("Couldn't write accept_redirects knob.\n");
return -1;
}
}
if(old_accept_redirects >= 0) {
rc = write_proc("/proc/sys/net/ipv6/conf/all/accept_redirects",
old_accept_redirects);
if(rc < 0) {
perror("Couldn't write accept_redirects knob.\n");
return -1;
}
}
return 1;
}
}
int
kernel_setup_interface(int setup, const char *ifname, int ifindex)
{
return 1;
}
int
kernel_interface_mtu(const char *ifname, int ifindex)
{
struct ifreq req;
int s, rc;
s = socket(PF_INET, SOCK_DGRAM, 0);
if(s < 0)
return -1;
memset(&req, 0, sizeof(req));
strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
rc = ioctl(s, SIOCGIFMTU, &req);
if(rc < 0) {
close(s);
return -1;
}
return req.ifr_mtu;
}
int
kernel_interface_wireless(const char *ifname, int ifindex)
{
#ifndef SIOCGIWNAME
#define SIOCGIWNAME 0x8B01
#endif
struct ifreq req;
int s, rc;
s = socket(PF_INET, SOCK_DGRAM, 0);
if(s < 0)
return -1;
memset(&req, 0, sizeof(req));
strncpy(req.ifr_name, ifname, sizeof(req.ifr_name));
rc = ioctl(s, SIOCGIWNAME, &req);
if(rc < 0) {
if(errno == EOPNOTSUPP || errno == EINVAL)
rc = 0;
else {
perror("ioctl(SIOCGIWNAME)");
rc = -1;
}
} else {
rc = 1;
}
close(s);
return rc;
}
static int route_socket = -1;
int
kernel_route(int add, const unsigned char *dest, unsigned short plen,
const unsigned char *gate, int ifindex, int metric)
{
struct in6_rtmsg msg;
int rc;
if(route_socket < 0) {
route_socket = socket(AF_INET6, SOCK_DGRAM, 0);
if(route_socket < 0)
return -1;
}
memset(&msg, 0, sizeof(msg));
msg.rtmsg_flags = RTF_UP;
if(plen < 128) {
msg.rtmsg_flags |= RTF_GATEWAY;
} else {
msg.rtmsg_flags |= RTF_HOST;
if(memcmp(dest, gate, 16) != 0)
msg.rtmsg_flags |= RTF_GATEWAY;
}
msg.rtmsg_metric = metric;
memcpy(&msg.rtmsg_dst, dest, sizeof(struct in6_addr));
msg.rtmsg_dst_len = plen;
memcpy(&msg.rtmsg_gateway, gate, sizeof(struct in6_addr));
msg.rtmsg_ifindex = ifindex;
rc = ioctl(route_socket, add ? SIOCADDRT : SIOCDELRT, &msg);
if(rc < 0)
return -1;
return 1;
}
/*
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
int kernel_setup(int setup);
int kernel_setup_interface(int setup, const char *ifname, int ifindex);
int kernel_interface_mtu(const char *ifname, int ifindex);
int kernel_interface_wireless(const char *ifname, int ifindex);
int kernel_route(int add, const unsigned char *dest, unsigned short plen,
const unsigned char *gate, int ifindex, int metric);
This diff is collapsed.
/*
Copyright (c) 2007 by Juliusz Chroboczek
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
extern unsigned char seqno;
extern int seqno_time;
extern int seqno_interval;
extern unsigned int jitter;
extern unsigned int update_jitter;
extern int parasitic;
extern int silent_time;
extern int broadcast_txcost;
extern int split_horizon;
extern struct timeval update_flush_time;
extern const unsigned char packet_header[4];
void parse_packet(const unsigned char *from, struct network *net,
const unsigned char *packet, int len);
void flushbuf(struct network *net);
void send_hello(struct network *net);
void send_request(struct network *net, struct destination *dest);
void send_unicast_request(struct neighbour *neigh, struct destination *dest);
void send_update(struct destination *dest, struct network *net);
void send_self_update(struct network *net);