/** * Open the tun device. * * @param interfaceName the interface name you *want* to use or NULL to let the kernel decide. * @param assignedInterfaceName the interface name you get. * @param log * @param eh * @return a file descriptor for the tunnel. */ void* TUNConfigurator_initTun(const char* interfaceName, char assignedInterfaceName[TUNConfigurator_IFNAMSIZ], struct Log* logger, struct Except* eh) { // Open the descriptor int tunFd = open("/dev/tun", O_RDWR); //Get the resulting device name const char* assignedDevname; assignedDevname = fdevname(tunFd); // Extract the number eg: 0 from tun0 int ppa = 0; for (uint32_t i = 0; i < strlen(assignedDevname); i++) { if (isdigit(assignedDevname[i])) { ppa = atoi(assignedDevname); } } if (tunFd < 0 || ppa < 0 ) { enum Errno err = Errno_get(); close(tunFd); char* error = NULL; if (tunFd < 0) { error = "open(\"/dev/tun\")"; } else if (ppa < 0) { error = "fdevname/getting number from fdevname"; } Except_raise(eh, TUNConfigurator_initTun_INTERNAL, error, Errno_strerror(err)); } // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0 // so we'll skip the pretty names and call everything tunX snprintf(assignedInterfaceName, TUNConfigurator_IFNAMSIZ, "tun%d", ppa); char* error = NULL; // We want to send IPv6 through our tun device, so we need to be able to specify "ethertype" int tunhead = 1; if (ioctl(tunFd,TUNSIFHEAD,&tunhead) == -1) { error = "TUNSIFHEAD"; } if (error) { enum Errno err = Errno_get(); close(tunFd); Except_raise(eh, TUNConfigurator_initTun_INTERNAL, "%s [%s]", error, Errno_strerror(err)); } intptr_t ret = (intptr_t) tunFd; return (void*) ret; }
struct Iface* TUNInterface_new(const char* interfaceName, char assignedInterfaceName[TUNInterface_IFNAMSIZ], int isTapMode, struct EventBase* base, struct Log* logger, struct Except* eh, struct Allocator* alloc) { char deviceFile[TUNInterface_IFNAMSIZ]; if (isTapMode) { Except_throw(eh, "tap mode not supported on this platform"); } // We are on FreeBSD so we just need to read /dev/tunxx to create the tun interface if (interfaceName) { snprintf(deviceFile,TUNInterface_IFNAMSIZ,"/dev/%s",interfaceName); } else { snprintf(deviceFile,TUNInterface_IFNAMSIZ,"%s","/dev/tun"); } // Open the descriptor int tunFd = open(deviceFile, O_RDWR); //Get the resulting device name const char* assignedDevname; assignedDevname = fdevname(tunFd); // Extract the number eg: 0 from tun0 int ppa = 0; for (uint32_t i = 0; i < strlen(assignedDevname); i++) { if (isdigit(assignedDevname[i])) { ppa = atoi(assignedDevname+i); break; } } if (tunFd < 0 || ppa < 0 ) { int err = errno; close(tunFd); char* error = NULL; if (tunFd < 0) { error = "open(\"/dev/tun\")"; } else if (ppa < 0) { error = "fdevname/getting number from fdevname"; } Except_throw(eh, "%s [%s]", error, strerror(err)); } // Since devices are numbered rather than named, it's not possible to have tun0 and cjdns0 // so we'll skip the pretty names and call everything tunX if (assignedInterfaceName) { snprintf(assignedInterfaceName, TUNInterface_IFNAMSIZ, "tun%d", ppa); } char* error = NULL; // We want to send IPv6 through our tun device, so we need to be able to specify "ethertype" int tunhead = 1; if (ioctl(tunFd,TUNSIFHEAD,&tunhead) == -1) { error = "TUNSIFHEAD"; } if (error) { int err = errno; close(tunFd); Except_throw(eh, "%s [%s]", error, strerror(err)); } struct Pipe* p = Pipe_forFiles(tunFd, tunFd, base, eh, alloc); struct BSDMessageTypeWrapper* bmtw = BSDMessageTypeWrapper_new(alloc, logger); Iface_plumb(&p->iface, &bmtw->wireSide); return &bmtw->inside; }