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.
  • Loading branch information
darconeous committed Jan 30, 2013
1 parent 092b6f3 commit a571b66
Show file tree
Hide file tree
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
Expand Up @@ -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
Expand Down
8 changes: 4 additions & 4 deletions cpu/native/net/tapdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -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);
Expand Down
177 changes: 176 additions & 1 deletion cpu/native/net/tapdev6.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -66,7 +77,7 @@
static int drop = 0;
#endif

static int fd;
static int fd = -1;

static unsigned long lasttime;

Expand Down Expand Up @@ -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)
{
Expand All @@ -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);
Expand Down Expand Up @@ -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
Expand Up @@ -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));
Expand Down

0 comments on commit a571b66

Please sign in to comment.