iface: make fastd_iface_open() gracefully (at least on Linux, for now)

This commit is contained in:
Matthias Schiffer 2015-03-23 02:39:41 +01:00
parent 0e8493ea17
commit 6dbb8e041c
3 changed files with 43 additions and 17 deletions

View file

@ -176,11 +176,12 @@ int fastd_android_receive_tunfd(void) {
int handle; int handle;
if (ancil_recv_fd(ctx.android_ctrl_sock_fd, &handle)) { if (ancil_recv_fd(ctx.android_ctrl_sock_fd, &handle)) {
exit_errno("could not receive TUN handle from Android"); pr_error("could not receive TUN handle from Android");
} else { return -1;
pr_debug("received fd: %u", handle);
} }
pr_debug("received fd: %u", handle);
return handle; return handle;
} }

View file

@ -500,8 +500,11 @@ static inline void init(int argc, char *argv[]) {
fastd_on_pre_up(); fastd_on_pre_up();
if (conf.mode == MODE_TAP) if (conf.mode == MODE_TAP) {
ctx.iface = fastd_iface_open(NULL); ctx.iface = fastd_iface_open(NULL);
if (!ctx.iface)
exit(1); /* An error message has already been printed by fastd_iface_open() */
}
/* change groups before trying to write the PID file as they can be relevant for file access */ /* change groups before trying to write the PID file as they can be relevant for file access */
set_groups(); set_groups();

View file

@ -85,16 +85,19 @@ static inline fastd_iface_type_t get_iface_type(void) {
} }
} }
static void open_iface(fastd_iface_t *iface);
#ifdef __linux__ #ifdef __linux__
/** Opens the TUN/TAP device helper shared by Android and Linux targets */ /** Opens the TUN/TAP device helper shared by Android and Linux targets */
static void open_iface_linux(fastd_iface_t *iface, const char *dev_name) { static void open_iface_linux(fastd_iface_t *iface, const char *dev_name) {
int ctl_sock = -1;
struct ifreq ifr = {}; struct ifreq ifr = {};
iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(dev_name, O_RDWR|O_NONBLOCK)); iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(dev_name, O_RDWR|O_NONBLOCK));
if (iface->fd.fd < 0) if (iface->fd.fd < 0)
exit_errno("could not open tun/tap device file"); exit_errno("could not open TUN/TAP device file");
if (conf.ifname) if (conf.ifname)
strncpy(ifr.ifr_name, conf.ifname, IFNAMSIZ-1); strncpy(ifr.ifr_name, conf.ifname, IFNAMSIZ-1);
@ -113,12 +116,14 @@ static void open_iface_linux(fastd_iface_t *iface, const char *dev_name) {
} }
ifr.ifr_flags |= IFF_NO_PI; ifr.ifr_flags |= IFF_NO_PI;
if (ioctl(iface->fd.fd, TUNSETIFF, &ifr) < 0) if (ioctl(iface->fd.fd, TUNSETIFF, &ifr) < 0) {
exit_errno("TUNSETIFF ioctl failed"); pr_error_errno("unable to open TUN/TAP interface: TUNSETIFF ioctl failed");
goto error;
}
iface->name = fastd_strndup(ifr.ifr_name, IFNAMSIZ-1); iface->name = fastd_strndup(ifr.ifr_name, IFNAMSIZ-1);
int ctl_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); ctl_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ctl_sock < 0) if (ctl_sock < 0)
exit_errno("socket"); exit_errno("socket");
@ -127,13 +132,25 @@ static void open_iface_linux(fastd_iface_t *iface, const char *dev_name) {
if (ifr.ifr_mtu != conf.mtu) { if (ifr.ifr_mtu != conf.mtu) {
ifr.ifr_mtu = conf.mtu; ifr.ifr_mtu = conf.mtu;
if (ioctl(ctl_sock, SIOCSIFMTU, &ifr) < 0) if (ioctl(ctl_sock, SIOCSIFMTU, &ifr) < 0) {
exit_errno("SIOCSIFMTU ioctl failed"); pr_error_errno("unable to set TUN/TAP interface MTU: SIOCSIFMTU ioctl failed");
goto error;
}
} }
if (close(ctl_sock)) if (close(ctl_sock))
pr_error_errno("close"); pr_error_errno("close");
return;
error:
if (ctl_sock >= 0) {
if (close(ctl_sock))
pr_error_errno("close");
}
close(iface->fd.fd);
iface->fd.fd = -1;
} }
#endif #endif
@ -247,10 +264,10 @@ static void open_iface(fastd_iface_t *iface) {
iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK)); iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
if (iface->fd.fd < 0) if (iface->fd.fd < 0)
exit_errno("could not open tun/tap device file"); exit_errno("could not open TUN/TAP device file");
if (!(iface->name = fdevname_r(iface->fd.fd, fastd_alloc(IFNAMSIZ), IFNAMSIZ))) if (!(iface->name = fdevname_r(iface->fd.fd, fastd_alloc(IFNAMSIZ), IFNAMSIZ)))
exit_errno("could not get tun/tap interface name"); exit_errno("could not get TUN/TAP interface name");
switch (get_iface_type()) { switch (get_iface_type()) {
case IFACE_TYPE_TAP: case IFACE_TYPE_TAP:
@ -383,7 +400,7 @@ static void open_iface(fastd_iface_t *iface) {
#else #else
#error unknown tun/tap implementation #error unknown TUN/TAP implementation
#endif #endif
@ -448,13 +465,18 @@ fastd_iface_t * fastd_iface_open(fastd_peer_t *peer) {
fastd_iface_t *iface = fastd_new(fastd_iface_t); fastd_iface_t *iface = fastd_new(fastd_iface_t);
iface->peer = peer; iface->peer = peer;
pr_debug("initializing tun/tap device..."); pr_debug("initializing TUN/TAP device...");
open_iface(iface); open_iface(iface);
if (iface->fd.fd < 0) {
free(iface);
return NULL;
}
if (iface->name) if (iface->name)
pr_debug("tun/tap device `%s' initialized.", iface->name); pr_debug("TUN/TAP device `%s' initialized.", iface->name);
else else
pr_debug("tun/tap device initialized."); pr_debug("TUN/TAP device initialized.");
fastd_poll_fd_register(&iface->fd); fastd_poll_fd_register(&iface->fd);
@ -464,7 +486,7 @@ fastd_iface_t * fastd_iface_open(fastd_peer_t *peer) {
/** Closes the TUN/TAP device */ /** Closes the TUN/TAP device */
void fastd_iface_close(fastd_iface_t *iface) { void fastd_iface_close(fastd_iface_t *iface) {
if (!fastd_poll_fd_close(&iface->fd)) if (!fastd_poll_fd_close(&iface->fd))
pr_warn_errno("closing tun/tap: close"); pr_warn_errno("closing TUN/TAP: close");
free(iface->name); free(iface->name);
free(iface); free(iface);