Skip to content

Commit

Permalink
platform/minimal-net: Better, more seamless support for OS X.
Browse files Browse the repository at this point in the history
This patch enables automatic route setup and cleanup when
starting and stopping the minimal-net target on OS X.

Both IPv4 and IPv6 are supported.

Using the minimal-net target on OS X was absolute hell
before I came up with this patch. Now it is painless.
darconeous committed Jan 30, 2013
1 parent 092b6f3 commit a571b66
Showing 4 changed files with 191 additions and 11 deletions.
11 changes: 8 additions & 3 deletions cpu/native/Makefile.native
Original file line number Diff line number Diff line change
@@ -18,10 +18,15 @@ CFLAGSWERROR=-Werror -pedantic -std=c99 -Werror
endif
CFLAGSNO = -Wall -g -I/usr/local/include $(CFLAGSWERROR)
CFLAGS += $(CFLAGSNO) -O
ifeq ($(HOST_OS),Linux)
LDFLAGS += -Wl,-Map=contiki-$(TARGET).map,-export-dynamic

ifeq ($(shell uname),Darwin)
AROPTS = -r
LDFLAGS += -Wl,-flat_namespace
CFLAGS += -DHAVE_SNPRINTF=1 -U__ASSERT_USE_STDERR
else
LDFLAGS += -Wl
ifeq ($(HOST_OS),Linux)
LDFLAGS = -Wl,-Map=contiki-$(TARGET).map,-export-dynamic
endif
endif

### Compilation rules
8 changes: 4 additions & 4 deletions cpu/native/net/tapdev.c
Original file line number Diff line number Diff line change
@@ -81,7 +81,7 @@ static void
remove_route(void)
{
char buf[1024];
snprintf(buf, sizeof(buf), "route delete -net 172.16.0.0");
snprintf(buf, sizeof(buf), "route delete -net 172.18.0.0");
system(buf);
printf("%s\n", buf);

@@ -110,15 +110,15 @@ tapdev_init(void)
}
#endif /* Linux */

snprintf(buf, sizeof(buf), "ifconfig tap0 inet 192.168.1.1");
snprintf(buf, sizeof(buf), "ifconfig tap0 inet 172.18.0.1/16");
system(buf);
printf("%s\n", buf);
#ifdef linux
/* route add for linux */
snprintf(buf, sizeof(buf), "route add -net 172.16.0.0/16 gw 192.168.1.2");
snprintf(buf, sizeof(buf), "route add -net 172.18.0.0/16 dev tap0");
#else /* linux */
/* route add for freebsd */
snprintf(buf, sizeof(buf), "route add -net 172.16.0.0/16 192.168.1.2");
snprintf(buf, sizeof(buf), "route add -net 172.18.0.0/16 -iface tap0");
#endif /* linux */

system(buf);
177 changes: 176 additions & 1 deletion cpu/native/net/tapdev6.c
Original file line number Diff line number Diff line change
@@ -56,6 +56,17 @@
#define DEVTAP "/dev/tap0"
#endif /* linux */

#ifdef __APPLE__
#include <net/if.h>
#include <netinet/in.h>
#include <netinet6/in6_var.h>
#include <netinet6/nd6.h> // ND6_INFINITE_LIFETIME
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/errno.h>
#include <net/if_dl.h> // struct sockaddr_dl
#include <net/route.h> // AF_ROUTE things
#endif

#include "tapdev6.h"
#include "contiki-net.h"
@@ -66,7 +77,7 @@
static int drop = 0;
#endif

static int fd;
static int fd = -1;

static unsigned long lasttime;

@@ -123,6 +134,159 @@ tapdev_poll(void)
return ret;
}
/*---------------------------------------------------------------------------*/
#if defined(__APPLE__)
static int reqfd = -1, sfd = -1, interface_index;

static void
tapdev_init_darwin_routes(void)
{
struct stat st;

if(-1 == fstat(fd, &st)) {
perror("tapdev: fstat failed.");
exit(EXIT_FAILURE);
}

/************* Add address *************/

struct in6_aliasreq addreq6 = { };
reqfd = socket(AF_INET6, SOCK_DGRAM, 0);

if(-1 == fcntl(reqfd, F_SETFD, FD_CLOEXEC)) {
perror("tapdev: fcntl failed.");
exit(EXIT_FAILURE);
}

devname_r(st.st_rdev, S_IFCHR, addreq6.ifra_name,
sizeof(addreq6.ifra_name));

addreq6.ifra_addr.sin6_family = AF_INET6;
addreq6.ifra_addr.sin6_len = sizeof(addreq6.ifra_addr);
addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA);
addreq6.ifra_addr.sin6_addr.__u6_addr.__u6_addr16[7] = UIP_HTONS(0x0001);

addreq6.ifra_prefixmask.sin6_family = AF_INET6;
addreq6.ifra_prefixmask.sin6_len = sizeof(addreq6.ifra_prefixmask);
addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[0] =
UIP_HTONS(0xFFFF);
addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[1] =
UIP_HTONS(0xFFFF);
addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[2] =
UIP_HTONS(0xFFFF);
addreq6.ifra_prefixmask.sin6_addr.__u6_addr.__u6_addr16[3] =
UIP_HTONS(0xFFFF);

addreq6.ifra_lifetime.ia6t_vltime = ND6_INFINITE_LIFETIME;
addreq6.ifra_lifetime.ia6t_pltime = ND6_INFINITE_LIFETIME;
addreq6.ifra_lifetime.ia6t_expire = ND6_INFINITE_LIFETIME;
addreq6.ifra_lifetime.ia6t_preferred = ND6_INFINITE_LIFETIME;

if(-1 == ioctl(reqfd, SIOCAIFADDR_IN6, &addreq6)) {
perror("tapdev: Uable to add address, call to ioctl failed.");
exit(EXIT_FAILURE);
}

/************* Add route *************/

int s = socket(AF_ROUTE, SOCK_RAW, AF_INET6);

if(s == -1) {
perror("tapdev: Unable to add route, call to socket() failed.");

// Failing to add the route is not fatal, so just return.
return;
}

sfd = s;
interface_index = if_nametoindex(devname(st.st_rdev, S_IFCHR));

PRINTF("tapdev: if_nametoindex(devname(st.st_rdev, S_IFCHR)) = %d\n",
interface_index);
PRINTF("tapdev: devname(st.st_rdev, S_IFCHR) = %s\n",
devname(st.st_rdev, S_IFCHR));

struct {
struct rt_msghdr hdr;
struct sockaddr_in6 dst;
struct sockaddr_dl gw;
struct sockaddr_in6 mask;
} msg = {};

msg.hdr.rtm_msglen = sizeof(msg);
msg.hdr.rtm_version = RTM_VERSION;
msg.hdr.rtm_type = RTM_ADD;
msg.hdr.rtm_index = interface_index;
msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
msg.hdr.rtm_pid = getpid();
msg.hdr.rtm_seq = 0;

msg.dst.sin6_family = AF_INET6;
msg.dst.sin6_len = sizeof(msg.dst);
msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA);

msg.gw.sdl_family = AF_LINK;
msg.gw.sdl_len = sizeof(msg.gw);
msg.gw.sdl_index = interface_index;

msg.mask.sin6_family = AF_INET6;
msg.mask.sin6_len = sizeof(msg.mask);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF);

if(-1 == write(s, &msg, sizeof(msg))) {
perror("tapdev: Unable to add route, call to write() failed.");

// Failing to add the route is not fatal, so just return.
return;
}
}
/*---------------------------------------------------------------------------*/
static void
tapdev_cleanup_darwin_routes(void)
{
struct {
struct rt_msghdr hdr;
struct sockaddr_in6 dst;
struct sockaddr_dl gw;
struct sockaddr_in6 mask;
} msg = {};

msg.hdr.rtm_msglen = sizeof(msg);
msg.hdr.rtm_version = RTM_VERSION;
msg.hdr.rtm_type = RTM_DELETE;
msg.hdr.rtm_index = interface_index;
msg.hdr.rtm_flags = RTF_UP | RTF_STATIC;
msg.hdr.rtm_addrs = RTA_DST | RTA_GATEWAY | RTA_NETMASK;
msg.hdr.rtm_pid = getpid();
msg.hdr.rtm_seq = 0;

msg.dst.sin6_family = AF_INET6;
msg.dst.sin6_len = sizeof(msg.dst);
msg.dst.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xAAAA);

msg.gw.sdl_family = AF_LINK;
msg.gw.sdl_len = sizeof(msg.gw);
msg.gw.sdl_index = interface_index;

msg.mask.sin6_family = AF_INET6;
msg.mask.sin6_len = sizeof(msg.mask);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[0] = UIP_HTONS(0xFFFF);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[1] = UIP_HTONS(0xFFFF);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[2] = UIP_HTONS(0xFFFF);
msg.mask.sin6_addr.__u6_addr.__u6_addr16[3] = UIP_HTONS(0xFFFF);
if(-1 == write(sfd, &msg, sizeof(msg))) {
perror("tapdev: Unable to delete route");
exit(EXIT_FAILURE);
}

close(reqfd);
close(sfd);
}
#endif // defined(__APPLE__)
/*---------------------------------------------------------------------------*/
void
tapdev_init(void)
{
@@ -146,6 +310,10 @@ tapdev_init(void)
}
#endif /* Linux */

#ifdef __APPLE__
tapdev_init_darwin_routes();
#endif

/* Linux (ubuntu)
snprintf(buf, sizeof(buf), "ip link set tap0 up");
system(buf);
@@ -236,5 +404,12 @@ tapdev_do_send(void)
void
tapdev_exit(void)
{
PRINTF("tapdev: Closing...\n");

#ifdef __APPLE__
tapdev_cleanup_darwin_routes();
#endif

close(fd);
}
/*---------------------------------------------------------------------------*/
6 changes: 3 additions & 3 deletions platform/minimal-net/contiki-main.c
Original file line number Diff line number Diff line change
@@ -236,21 +236,21 @@ main(void)

uip_gethostaddr(&addr);
if(addr.u8[0] == 0) {
uip_ipaddr(&addr, 10,1,1,1);
uip_ipaddr(&addr, 172,18,0,2);
}
printf("IP Address: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr));
uip_sethostaddr(&addr);

uip_getnetmask(&addr);
if(addr.u8[0] == 0) {
uip_ipaddr(&addr, 255,0,0,0);
uip_ipaddr(&addr, 255,255,0,0);
uip_setnetmask(&addr);
}
printf("Subnet Mask: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr));

uip_getdraddr(&addr);
if(addr.u8[0] == 0) {
uip_ipaddr(&addr, 10,1,1,100);
uip_ipaddr(&addr, 172,18,0,1);
uip_setdraddr(&addr);
}
printf("Def. Router: %d.%d.%d.%d\n", uip_ipaddr_to_quad(&addr));

0 comments on commit a571b66

Please sign in to comment.