summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias Schiffer <mschiffer@universe-factory.net>2015-03-22 03:10:55 +0100
committerMatthias Schiffer <mschiffer@universe-factory.net>2015-03-22 03:10:55 +0100
commitf6e36cf6d78ce8c5bed2e6d698928a89a9fbcc6f (patch)
tree69e2df2be718d891e68196052443c93ebcc74056
parent2e715f6c73505b8721d3d48e7c93598448699075 (diff)
downloadfastd-f6e36cf6d78ce8c5bed2e6d698928a89a9fbcc6f.tar
fastd-f6e36cf6d78ce8c5bed2e6d698928a89a9fbcc6f.zip
First work towards multi-interface support
-rw-r--r--src/fastd.c27
-rw-r--r--src/fastd.h22
-rw-r--r--src/peer.c2
-rw-r--r--src/peer.h2
-rw-r--r--src/poll.c6
-rw-r--r--src/receive.c2
-rw-r--r--src/shell.c22
-rw-r--r--src/shell.h1
-rw-r--r--src/tuntap.c132
-rw-r--r--src/types.h1
10 files changed, 121 insertions, 96 deletions
diff --git a/src/fastd.c b/src/fastd.c
index 52bbf9c..228d65e 100644
--- a/src/fastd.c
+++ b/src/fastd.c
@@ -211,13 +211,19 @@ static inline void on_pre_up(void) {
}
/** Calls the on-up command */
-static inline void on_up(void) {
- fastd_shell_command_exec(&conf.on_up, NULL);
+static inline void on_up(fastd_iface_t *iface) {
+ fastd_shell_env_t *env = fastd_shell_env_alloc();
+ fastd_shell_env_set_iface(env, iface);
+ fastd_shell_command_exec(&conf.on_up, env);
+ fastd_shell_env_free(env);
}
/** Calls the on-down command */
-static inline void on_down(void) {
- fastd_shell_command_exec(&conf.on_down, NULL);
+static inline void on_down(fastd_iface_t *iface) {
+ fastd_shell_env_t *env = fastd_shell_env_alloc();
+ fastd_shell_env_set_iface(env, iface);
+ fastd_shell_command_exec(&conf.on_down, env);
+ fastd_shell_env_free(env);
}
/** Calls the on-post-down command */
@@ -520,7 +526,7 @@ static inline void init(int argc, char *argv[]) {
on_pre_up();
- fastd_tuntap_open();
+ ctx.iface = fastd_tuntap_open(NULL);
/* change groups before trying to write the PID file as they can be relevant for file access */
set_groups();
@@ -541,7 +547,7 @@ static inline void init(int argc, char *argv[]) {
if (conf.drop_caps == DROP_CAPS_EARLY)
drop_caps();
- on_up();
+ on_up(ctx.iface);
if (conf.drop_caps == DROP_CAPS_ON)
drop_caps();
@@ -632,17 +638,17 @@ static void delete_peers(void) {
Performs cleanup of resources used by fastd
Besides running the on-down scripts and closing the TUN/TAP interface, this
- also frees all memory allocatedby fastd to make debugging memory leaks with
+ also frees all memory allocated by fastd to make debugging memory leaks with
valgrind as easy as possible.
*/
static inline void cleanup(void) {
pr_info("terminating fastd");
- on_down();
-
delete_peers();
- fastd_tuntap_close();
+ on_down(ctx.iface);
+ fastd_tuntap_close(ctx.iface);
+
fastd_status_close();
close_sockets();
fastd_poll_free();
@@ -658,7 +664,6 @@ static inline void cleanup(void) {
VECTOR_FREE(ctx.eth_addrs);
free(ctx.protocol_state);
- free(ctx.ifname);
#ifdef ENABLE_OPENSSL
CONF_modules_free();
diff --git a/src/fastd.h b/src/fastd.h
index ba6acfb..5e81890 100644
--- a/src/fastd.h
+++ b/src/fastd.h
@@ -154,6 +154,13 @@ struct fastd_socket {
fastd_peer_t *peer; /**< If the socket belongs to a single peer (as it was create dynamically when sending a handshake), contains that peer */
};
+/** A TUN/TAP interface */
+struct fastd_iface {
+ fastd_poll_fd_t fd; /**< The file descriptor of the tunnel interface */
+ char *name; /**< The interface name */
+ fastd_peer_t *peer; /**< The peer associated with the interface (if any) */
+};
+
/** Type of a traffic stat counter */
typedef enum fastd_stat_type {
@@ -261,16 +268,17 @@ struct fastd_config {
bool verify_config; /**< Does basic verification of the configuration and exits */
};
+
/** The dynamic state of \em fastd */
struct fastd_context {
bool log_initialized; /**< true if the logging facilities have been properly initialized */
- char *ifname; /**< The actual interface name */
-
int64_t started; /**< The timestamp when fastd was started */
int64_t now; /**< The current monotonous timestamp in microseconds after an arbitrary point in time */
+ fastd_iface_t *iface; /**< The default tunnel interface */
+
uint64_t next_peer_id; /**< An monotonously increasing ID peers are identified with in some components */
VECTOR(fastd_peer_t *) peers; /**< The currectly active peers */
@@ -305,8 +313,6 @@ struct fastd_context {
pthread_attr_t detached_thread; /**< pthread_attr_t for creating detached threads */
- fastd_poll_fd_t tunfd; /**< The file descriptor of the tunnel interface */
-
#ifdef __ANDROID__
int android_ctrl_sock_fd; /**< The unix domain socket for communicating with Android GUI */
#endif
@@ -362,10 +368,10 @@ bool fastd_android_protect_socket(int fd);
void fastd_resolve_peer(fastd_peer_t *peer, fastd_remote_t *remote);
-void fastd_tuntap_open(void);
-void fastd_tuntap_handle(void);
-void fastd_tuntap_write(fastd_buffer_t buffer);
-void fastd_tuntap_close(void);
+fastd_iface_t * fastd_tuntap_open(fastd_peer_t *peer);
+void fastd_tuntap_handle(fastd_iface_t *iface);
+void fastd_tuntap_write(fastd_iface_t *iface, fastd_buffer_t buffer);
+void fastd_tuntap_close(fastd_iface_t *iface);
void fastd_cap_init(void);
void fastd_cap_drop(void);
diff --git a/src/peer.c b/src/peer.c
index 5ac517c..417e213 100644
--- a/src/peer.c
+++ b/src/peer.c
@@ -44,6 +44,8 @@ void fastd_peer_set_shell_env(fastd_shell_env_t *env, const fastd_peer_t *peer,
fastd_shell_env_set(env, "PEER_NAME", peer ? peer->name : NULL);
+ fastd_shell_env_set_iface(env, peer->iface ?: ctx.iface);
+
switch(local_addr ? local_addr->sa.sa_family : AF_UNSPEC) {
case AF_INET:
inet_ntop(AF_INET, &local_addr->in.sin_addr, buf, sizeof(buf));
diff --git a/src/peer.h b/src/peer.h
index 348b256..631957e 100644
--- a/src/peer.h
+++ b/src/peer.h
@@ -72,6 +72,8 @@ struct fastd_peer {
fastd_protocol_key_t *key; /**< The peer's public key */
fastd_protocol_peer_state_t *protocol_state; /**< Protocol-specific peer state */
+ fastd_iface_t *iface; /**< The interface this peer is associated with */
+
/* Starting here, more dynamic fields follow: */
/** The socket used by the peer. This can either be a common bound socket or a
diff --git a/src/poll.c b/src/poll.c
index 6c83f97..dbb3c18 100644
--- a/src/poll.c
+++ b/src/poll.c
@@ -82,8 +82,12 @@ static inline void handle_fd(fastd_poll_fd_t *fd, bool input, bool error) {
#endif
case POLL_TYPE_IFACE:
+ {
+ fastd_iface_t *iface = container_of(fd, fastd_iface_t, fd);
+
if (input)
- fastd_tuntap_handle();
+ fastd_tuntap_handle(iface);
+ }
break;
case POLL_TYPE_SOCKET:
diff --git a/src/receive.c b/src/receive.c
index 8bb926c..a19039e 100644
--- a/src/receive.c
+++ b/src/receive.c
@@ -306,7 +306,7 @@ void fastd_handle_receive(fastd_peer_t *peer, fastd_buffer_t buffer, bool reorde
if (reordered)
fastd_stats_add(peer, STAT_RX_REORDERED, buffer.len);
- fastd_tuntap_write(buffer);
+ fastd_tuntap_write(peer->iface ?: ctx.iface, buffer);
if (conf.mode == MODE_TAP && conf.forward) {
fastd_send_data(buffer, peer);
diff --git a/src/shell.c b/src/shell.c
index 90102a2..3a617be 100644
--- a/src/shell.c
+++ b/src/shell.c
@@ -75,6 +75,13 @@ void fastd_shell_env_free(fastd_shell_env_t *env) {
free(env);
}
+void fastd_shell_env_set_iface(fastd_shell_env_t *env, const fastd_iface_t *iface) {
+ if (iface)
+ fastd_shell_env_set(env, "INTERFACE", iface->name);
+ else
+ fastd_shell_env_set(env, "INTERFACE", NULL);
+}
+
/** Applies a shell environment to the current process */
static void shell_command_setenv(pid_t pid, const fastd_shell_env_t *env) {
char buf[20];
@@ -84,21 +91,6 @@ static void shell_command_setenv(pid_t pid, const fastd_shell_env_t *env) {
snprintf(buf, sizeof(buf), "%u", (unsigned)pid);
setenv("FASTD_PID", buf, 1);
- if (ctx.ifname) {
- setenv("INTERFACE", ctx.ifname, 1);
- }
- else if (conf.ifname) {
- char ifname[IF_NAMESIZE];
-
- strncpy(ifname, conf.ifname, sizeof(ifname)-1);
- ifname[sizeof(ifname)-1] = 0;
-
- setenv("INTERFACE", ifname, 1);
- }
- else {
- unsetenv("INTERFACE");
- }
-
snprintf(buf, sizeof(buf), "%u", conf.mtu);
setenv("INTERFACE_MTU", buf, 1);
diff --git a/src/shell.h b/src/shell.h
index d39bcef..57b09e6 100644
--- a/src/shell.h
+++ b/src/shell.h
@@ -71,6 +71,7 @@ static inline bool fastd_shell_command_isset(const fastd_shell_command_t *comman
fastd_shell_env_t * fastd_shell_env_alloc(void);
void fastd_shell_env_set(fastd_shell_env_t *env, const char *key, const char *value);
+void fastd_shell_env_set_iface(fastd_shell_env_t *env, const fastd_iface_t *iface);
void fastd_shell_env_free(fastd_shell_env_t *env);
bool fastd_shell_command_exec_sync(const fastd_shell_command_t *command, const fastd_shell_env_t *env, int *ret);
diff --git a/src/tuntap.c b/src/tuntap.c
index 591f8d4..a303d20 100644
--- a/src/tuntap.c
+++ b/src/tuntap.c
@@ -66,13 +66,13 @@ static const bool multiaf_tun = true;
#ifdef __linux__
/** Opens the TUN/TAP device helper shared by Android and Linux targets */
-static void tuntap_open_linux(const char * dev_name) {
+static void tuntap_open_linux(fastd_iface_t *iface, const char *dev_name) {
pr_debug("initializing tun/tap device...");
struct ifreq ifr = {};
- ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(dev_name, O_RDWR|O_NONBLOCK));
- if (ctx.tunfd.fd < 0)
+ iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(dev_name, O_RDWR|O_NONBLOCK));
+ if (iface->fd.fd < 0)
exit_errno("could not open tun/tap device file");
if (conf.ifname)
@@ -92,10 +92,10 @@ static void tuntap_open_linux(const char * dev_name) {
}
ifr.ifr_flags |= IFF_NO_PI;
- if (ioctl(ctx.tunfd.fd, TUNSETIFF, &ifr) < 0)
+ if (ioctl(iface->fd.fd, TUNSETIFF, &ifr) < 0)
exit_errno("TUNSETIFF ioctl failed");
- ctx.ifname = 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);
if (ctl_sock < 0)
@@ -113,7 +113,7 @@ static void tuntap_open_linux(const char * dev_name) {
if (close(ctl_sock))
pr_error_errno("close");
- fastd_poll_fd_register(&ctx.tunfd);
+ fastd_poll_fd_register(&iface->fd);
pr_debug("tun/tap device initialized.");
}
@@ -123,7 +123,7 @@ static void tuntap_open_linux(const char * dev_name) {
#if defined(__ANDROID__)
/** Opens the TUN/TAP device */
-void fastd_tuntap_open(void) {
+static void tuntap_open(fastd_iface_t *iface) {
pr_debug("initializing tun device...");
if (conf.android_integration) {
@@ -132,38 +132,38 @@ void fastd_tuntap_open(void) {
}
pr_debug("using android TUN fd");
- ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, fastd_android_receive_tunfd());
+ iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, fastd_android_receive_tunfd());
fastd_android_send_pid();
- fastd_poll_fd_register(&ctx.tunfd);
+ fastd_poll_fd_register(&iface->fd);
pr_debug("tun device initialized.");
} else {
/* this requires root on Android */
- tuntap_open_linux("/dev/tun");
+ tuntap_open_linux(iface, "/dev/tun");
}
}
#elif defined(__linux__)
/** Opens the TUN/TAP device */
-void fastd_tuntap_open(void) {
- tuntap_open_linux("/dev/net/tun");
+static void tuntap_open(fastd_iface_t *iface) {
+ tuntap_open_linux(iface, "/dev/net/tun");
}
#elif defined(__FreeBSD__) || defined(__OpenBSD__)
/** Sets the MTU of the TUN/TAP device */
-static void set_tun_mtu(void) {
+static void set_tun_mtu(fastd_iface_t *iface) {
struct tuninfo tuninfo;
- if (ioctl(ctx.tunfd.fd, TUNGIFINFO, &tuninfo) < 0)
+ if (ioctl(iface->fd.fd, TUNGIFINFO, &tuninfo) < 0)
exit_errno("TUNGIFINFO ioctl failed");
tuninfo.mtu = conf.mtu;
- if (ioctl(ctx.tunfd.fd, TUNSIFINFO, &tuninfo) < 0)
+ if (ioctl(iface->fd.fd, TUNSIFINFO, &tuninfo) < 0)
exit_errno("TUNSIFINFO ioctl failed");
}
@@ -171,42 +171,42 @@ static void set_tun_mtu(void) {
#ifdef __FreeBSD__
/** Sets the MTU of the TAP device */
-static void set_tap_mtu(void) {
+static void set_tap_mtu(fastd_iface_t *iface) {
struct tapinfo tapinfo;
- if (ioctl(ctx.tunfd.fd, TAPGIFINFO, &tapinfo) < 0)
+ if (ioctl(iface->fd.fd, TAPGIFINFO, &tapinfo) < 0)
exit_errno("TAPGIFINFO ioctl failed");
tapinfo.mtu = conf.mtu;
- if (ioctl(ctx.tunfd.fd, TAPSIFINFO, &tapinfo) < 0)
+ if (ioctl(iface->fd.fd, TAPSIFINFO, &tapinfo) < 0)
exit_errno("TAPSIFINFO ioctl failed");
}
/** Sets up the TUN device */
-static void setup_tun(void) {
+static void setup_tun(fastd_iface_t *iface) {
int one = 1;
- if (ioctl(ctx.tunfd.fd, TUNSIFHEAD, &one) < 0)
+ if (ioctl(iface->fd.fd, TUNSIFHEAD, &one) < 0)
exit_errno("TUNSIFHEAD ioctl failed");
- set_tun_mtu();
+ set_tun_mtu(iface);
}
/** Sets up the TAP device */
-static void setup_tap(void) {
+static void setup_tap(fastd_iface_t *iface) {
struct ifreq ifr = {};
- if (ioctl(ctx.tunfd.fd, TAPGIFNAME, &ifr) < 0)
+ if (ioctl(iface->fd.fd, TAPGIFNAME, &ifr) < 0)
exit_errno("TAPGIFNAME ioctl failed");
- free(ctx.ifname);
- ctx.ifname = fastd_strndup(ifr.ifr_name, IFNAMSIZ-1);
+ free(iface->name);
+ iface->name = fastd_strndup(ifr.ifr_name, IFNAMSIZ-1);
- set_tap_mtu();
+ set_tap_mtu(iface);
}
/** Opens the TUN/TAP device */
-void fastd_tuntap_open(void) {
+static void tuntap_open(fastd_iface_t *iface) {
pr_debug("initializing tun/tap device...");
char ifname[5+IFNAMSIZ] = "/dev/";
@@ -235,41 +235,41 @@ void fastd_tuntap_open(void) {
strncat(ifname, type, IFNAMSIZ-1);
}
- ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
- if (ctx.tunfd.fd < 0)
+ iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
+ if (iface->fd.fd < 0)
exit_errno("could not open tun/tap device file");
- if (!(ctx.ifname = fdevname_r(ctx.tunfd.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");
switch (conf.mode) {
case MODE_TAP:
- setup_tap();
+ setup_tap(iface);
break;
case MODE_TUN:
- setup_tun();
+ setup_tun(iface);
break;
default:
exit_bug("invalid mode");
}
- fastd_poll_fd_register(&ctx.tunfd);
+ fastd_poll_fd_register(&iface->fd);
pr_debug("tun/tap device initialized.");
}
#else /* __OpenBSD__ */
-static void set_link0(bool set) {
+static void set_link0(fastd_iface_t *iface, bool set) {
struct ifreq ifr = {};
int ctl_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ctl_sock < 0)
exit_errno("socket");
- strncpy(ifr.ifr_name, ctx.ifname, IFNAMSIZ-1);
+ strncpy(ifr.ifr_name, iface->name, IFNAMSIZ-1);
if (ioctl(ctl_sock, SIOCGIFFLAGS, &ifr) < 0)
exit_errno("SIOCGIFFLAGS ioctl failed");
@@ -286,19 +286,19 @@ static void set_link0(bool set) {
}
/** Sets up the TUN device */
-static void setup_tun(void) {
- set_link0(false);
- set_tun_mtu();
+static void setup_tun(fastd_iface_t *iface) {
+ set_link0(iface, false);
+ set_tun_mtu(iface);
}
/** Sets up the TAP device */
-static void setup_tap(void) {
- set_link0(true);
- set_tun_mtu();
+static void setup_tap(fastd_iface_t *iface) {
+ set_link0(iface, true);
+ set_tun_mtu(iface);
}
/** Opens the TUN/TAP device */
-void fastd_tuntap_open(void) {
+static void tuntap_open(fastd_iface_t *iface) {
char ifname[5+IFNAMSIZ] = "/dev/";
if (!conf.ifname)
exit_error("config error: no interface name given.");
@@ -309,26 +309,26 @@ void fastd_tuntap_open(void) {
pr_debug("initializing tun device...");
- ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
- if (ctx.tunfd.fd < 0)
+ iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
+ if (iface->fd.fd < 0)
exit_errno("could not open tun device file");
- ctx.ifname = fastd_strndup(conf.ifname, IFNAMSIZ-1);
+ iface->name = fastd_strndup(conf.ifname, IFNAMSIZ-1);
switch (conf.mode) {
case MODE_TAP:
- setup_tap();
+ setup_tap(iface);
break;
case MODE_TUN:
- setup_tun();
+ setup_tun(iface);
break;
default:
exit_bug("invalid mode");
}
- fastd_poll_fd_register(&ctx.tunfd);
+ fastd_poll_fd_register(&iface->fd);
pr_debug("tun device initialized.");
}
@@ -338,7 +338,7 @@ void fastd_tuntap_open(void) {
#elif __APPLE__
/** Opens the TUN/TAP device */
-void fastd_tuntap_open(void) {
+static void tuntap_open(fastd_iface_t *iface) {
const char *devtype;
switch (conf.mode) {
case MODE_TAP:
@@ -363,11 +363,11 @@ void fastd_tuntap_open(void) {
pr_debug("initializing tun device...");
- ctx.tunfd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
- if (ctx.tunfd.fd < 0)
+ iface->fd = FASTD_POLL_FD(POLL_TYPE_IFACE, open(ifname, O_RDWR|O_NONBLOCK));
+ if (iface->fd.fd < 0)
exit_errno("could not open tun device file");
- ctx.ifname = fastd_strndup(conf.ifname, IFNAMSIZ-1);
+ iface->name = fastd_strndup(conf.ifname, IFNAMSIZ-1);
int ctl_sock = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (ctl_sock < 0)
@@ -382,7 +382,7 @@ void fastd_tuntap_open(void) {
if (close(ctl_sock))
pr_error_errno("close");
- fastd_poll_fd_register(&ctx.tunfd);
+ fastd_poll_fd_register(&iface->fd);
pr_debug("tun device initialized.");
}
@@ -395,7 +395,7 @@ void fastd_tuntap_open(void) {
/** Reads a packet from the TUN/TAP device */
-void fastd_tuntap_handle(void) {
+void fastd_tuntap_handle(fastd_iface_t *iface) {
size_t max_len = fastd_max_payload();
fastd_buffer_t buffer;
@@ -404,7 +404,7 @@ void fastd_tuntap_handle(void) {
else
buffer = fastd_buffer_alloc(max_len, conf.min_encrypt_head_space, conf.min_encrypt_tail_space);
- ssize_t len = read(ctx.tunfd.fd, buffer.data, max_len);
+ ssize_t len = read(iface->fd.fd, buffer.data, max_len);
if (len < 0)
exit_errno("read");
@@ -413,11 +413,11 @@ void fastd_tuntap_handle(void) {
if (multiaf_tun && conf.mode == MODE_TUN)
fastd_buffer_push_head(&buffer, 4);
- fastd_send_data(buffer, NULL);
+ fastd_send_data(buffer, iface->peer);
}
/** Writes a packet to the TUN/TAP device */
-void fastd_tuntap_write(fastd_buffer_t buffer) {
+void fastd_tuntap_write(fastd_iface_t *iface, fastd_buffer_t buffer) {
if (multiaf_tun && conf.mode == MODE_TUN) {
uint8_t version = *((uint8_t *)buffer.data) >> 4;
uint32_t af;
@@ -440,12 +440,24 @@ void fastd_tuntap_write(fastd_buffer_t buffer) {
memcpy(buffer.data, &af, 4);
}
- if (write(ctx.tunfd.fd, buffer.data, buffer.len) < 0)
+ if (write(iface->fd.fd, buffer.data, buffer.len) < 0)
pr_debug2_errno("write");
}
+fastd_iface_t * fastd_tuntap_open(fastd_peer_t *peer) {
+ fastd_iface_t *iface = fastd_new(fastd_iface_t);
+ iface->peer = peer;
+
+ tuntap_open(iface);
+
+ return iface;
+}
+
/** Closes the TUN/TAP device */
-void fastd_tuntap_close(void) {
- if (!fastd_poll_fd_close(&ctx.tunfd))
+void fastd_tuntap_close(fastd_iface_t *iface) {
+ if (!fastd_poll_fd_close(&iface->fd))
pr_warn_errno("closing tun/tap: close");
+
+ free(iface->name);
+ free(iface);
}
diff --git a/src/types.h b/src/types.h
index 2a854c2..dbb4d3c 100644
--- a/src/types.h
+++ b/src/types.h
@@ -94,6 +94,7 @@ typedef struct fastd_poll_fd fastd_poll_fd_t;
typedef union fastd_peer_address fastd_peer_address_t;
typedef struct fastd_bind_address fastd_bind_address_t;
+typedef struct fastd_iface fastd_iface_t;
typedef struct fastd_socket fastd_socket_t;
typedef struct fastd_peer_group fastd_peer_group_t;
typedef struct fastd_eth_addr fastd_eth_addr_t;