diff -ur nat64.c nat64.c --- nat64.c 2012-10-03 16:55:57.000000000 +0400 +++ nat64.c 2012-10-04 14:22:01.000000000 +0400 @@ -94,8 +94,7 @@ } __attribute__ ((__packed__)) header; struct iovec iov[2]; - header.pi.flags = 0; - header.pi.proto = htons(ETH_P_IP); + TUN_SET_PROTO(&header.pi, ETH_P_IP); header.ip4.ver_ihl = 0x45; header.ip4.tos = tos; header.ip4.length = htons(sizeof(header.ip4) + sizeof(header.icmp) + @@ -156,6 +155,7 @@ } } + static void xlate_header_4to6(struct pkt *p, struct ip6 *ip6, int payload_length) { @@ -266,8 +266,7 @@ if (dest) dest->flags |= CACHE_F_SEEN_4TO6; - header.pi.flags = 0; - header.pi.proto = htons(ETH_P_IPV6); + TUN_SET_PROTO(&header.pi, ETH_P_IPV6); if (no_frag_hdr) { iov[0].iov_base = &header; @@ -514,8 +513,7 @@ sizeof(header.ip6_em)), ip_checksum(p_em.data, p_em.data_len))); - header.pi.flags = 0; - header.pi.proto = htons(ETH_P_IPV6); + TUN_SET_PROTO(&header.pi, ETH_P_IPV6); iov[0].iov_base = &header; iov[0].iov_len = sizeof(header); @@ -566,8 +564,7 @@ } __attribute__ ((__packed__)) header; struct iovec iov[2]; - header.pi.flags = 0; - header.pi.proto = htons(ETH_P_IPV6); + TUN_SET_PROTO(&header.pi, ETH_P_IPV6); header.ip6.ver_tc_fl = htonl((0x6 << 28) | (tc << 20)); header.ip6.payload_length = htons(sizeof(header.icmp) + data_len); header.ip6.next_header = 58; @@ -588,6 +585,8 @@ if (writev(gcfg->tun_fd, iov, data_len ? 2 : 1) < 0) slog(LOG_WARNING, "error writing packet to tun device: %s\n", strerror(errno)); + + slog(LOG_WARNING, "Wrote somethinh\n"); } static void host_send_icmp6_error(uint8_t type, uint8_t code, uint32_t word, @@ -728,8 +727,7 @@ if (dest) dest->flags |= CACHE_F_SEEN_6TO4; - header.pi.flags = 0; - header.pi.proto = htons(ETH_P_IP); + TUN_SET_PROTO(&header.pi, ETH_P_IP); header.ip4.cksum = ip_checksum(&header.ip4, sizeof(header.ip4)); @@ -932,8 +930,7 @@ sizeof(header.ip4_em)), ip_checksum(p_em.data, p_em.data_len)); - header.pi.flags = 0; - header.pi.proto = htons(ETH_P_IP); + TUN_SET_PROTO(&header.pi, ETH_P_IP); iov[0].iov_base = &header; iov[0].iov_len = sizeof(header); diff -ur tayga.c tayga.c --- tayga.c 2012-10-03 16:55:57.000000000 +0400 +++ tayga.c 2012-10-04 15:13:49.000000000 +0400 @@ -84,6 +84,7 @@ } } +#ifdef __Linux__ static void tun_setup(int do_mktun, int do_rmtun) { struct ifreq ifr; @@ -161,6 +162,113 @@ slog(LOG_INFO, "Using tun device %s with MTU %d\n", gcfg->tundev, gcfg->mtu); } +#endif + +#ifdef __FreeBSD__ +static void tun_setup(int do_mktun, int do_rmtun) +{ + struct ifreq ifr; + int fd, do_rename = 0, multi_af; + char devname[64]; + + if (strncmp(gcfg->tundev, "tun", 3)) + do_rename = 1; + + if ((do_mktun || do_rmtun) && do_rename) + { + slog(LOG_CRIT, + "tunnel interface name needs to match tun[0-9]+ pattern " + "for --mktun to work\n"); + exit(1); + } + + snprintf(devname, sizeof(devname), "/dev/%s", do_rename ? "tun" : gcfg->tundev); + + gcfg->tun_fd = open(devname, O_RDWR); + if (gcfg->tun_fd < 0) { + slog(LOG_CRIT, "Unable to open %s, aborting: %s\n", + devname, strerror(errno)); + exit(1); + } + + if (do_mktun) { + slog(LOG_NOTICE, "Created persistent tun device %s\n", + gcfg->tundev); + return; + } else if (do_rmtun) { + + /* Close socket before removal */ + close(gcfg->tun_fd); + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + slog(LOG_CRIT, "Unable to create control socket, aborting: %s\n", + strerror(errno)); + exit(1); + } + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, gcfg->tundev); + if (ioctl(fd, SIOCIFDESTROY, &ifr) < 0) { + slog(LOG_CRIT, "Unable to destroy interface %s, aborting: %s\n", + gcfg->tundev, strerror(errno)); + exit(1); + } + + close(fd); + + slog(LOG_NOTICE, "Removed persistent tun device %s\n", + gcfg->tundev); + return; + } + + /* Set multi-AF mode */ + multi_af = 1; + if (ioctl(gcfg->tun_fd, TUNSIFHEAD, &multi_af) < 0) { + slog(LOG_CRIT, "Unable to set multi-AF on %s, " + "aborting: %s\n", gcfg->tundev, + strerror(errno)); + exit(1); + } + + slog(LOG_CRIT, "Multi-AF mode set on %s\n", gcfg->tundev); + + set_nonblock(gcfg->tun_fd); + + fd = socket(PF_INET, SOCK_DGRAM, 0); + if (fd < 0) { + slog(LOG_CRIT, "Unable to create socket, aborting: %s\n", + strerror(errno)); + exit(1); + } + + if (do_rename) { + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, fdevname(gcfg->tun_fd)); + ifr.ifr_data = gcfg->tundev; + if (ioctl(fd, SIOCSIFNAME, &ifr) < 0) { + slog(LOG_CRIT, "Unable to rename interface %s to %s, aborting: %s\n", + fdevname(gcfg->tun_fd), gcfg->tundev, + strerror(errno)); + exit(1); + } + } + + memset(&ifr, 0, sizeof(ifr)); + strcpy(ifr.ifr_name, gcfg->tundev); + if (ioctl(fd, SIOCGIFMTU, &ifr) < 0) { + slog(LOG_CRIT, "Unable to query MTU, aborting: %s\n", + strerror(errno)); + exit(1); + } + close(fd); + + gcfg->mtu = ifr.ifr_mtu; + + slog(LOG_INFO, "Using tun device %s with MTU %d\n", gcfg->tundev, + gcfg->mtu); +} +#endif static void signal_handler(int signal) { @@ -214,7 +322,7 @@ memset(p, 0, sizeof(struct pkt)); p->data = gcfg->recv_buf + sizeof(struct tun_pi); p->data_len = ret - sizeof(struct tun_pi); - switch (ntohs(pi->proto)) { + switch (TUN_GET_PROTO(pi)) { case ETH_P_IP: handle_ip4(p); break; diff -ur tayga.h tayga.h --- tayga.h 2012-10-03 16:55:57.000000000 +0400 +++ tayga.h 2012-10-04 14:26:09.000000000 +0400 @@ -31,14 +31,44 @@ #include #include #include +#ifdef __Linux__ #include #include #include +#endif +#ifdef __FreeBSD__ +#include +#include +#include +#include +#include +#endif + #include "list.h" #include "config.h" +#ifdef __Linux__ +#define TUN_SET_PROTO(_pi, _af) { (_pi)->flags = 0; (_pi)->proto = htons(_af); } +#define TUN_GET_PROTO(_pi) ntohs((_pi)->proto) +#endif + +#ifdef __FreeBSD__ +#define s6_addr8 __u6_addr.__u6_addr8 +#define s6_addr16 __u6_addr.__u6_addr16 +#define s6_addr32 __u6_addr.__u6_addr32 + +struct tun_pi { + int proto; +}; + +#define ETH_P_IP AF_INET +#define ETH_P_IPV6 AF_INET6 +#define TUN_SET_PROTO(_pi, _af) { (_pi)->proto = htonl(_af); } +#define TUN_GET_PROTO(_pi) ntohl((_pi)->proto) +#endif + /* Configuration knobs */ /* Number of seconds of silence before a map ages out of the cache */