File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / networking / tun_device.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Jun 3 09:46:44 2020 UTC (4 years, 3 months ago) by misho
Branches: strongswan, MAIN
CVS tags: v5_9_2p0, v5_8_4p7, HEAD
Strongswan

    1: /*
    2:  * Copyright (C) 2012 Tobias Brunner
    3:  * Copyright (C) 2012 Giuliano Grassi
    4:  * Copyright (C) 2012 Ralf Sager
    5:  * HSR Hochschule fuer Technik Rapperswil
    6:  * Copyright (C) 2012 Martin Willi
    7:  *
    8:  * This program is free software; you can redistribute it and/or modify it
    9:  * under the terms of the GNU General Public License as published by the
   10:  * Free Software Foundation; either version 2 of the License, or (at your
   11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
   12:  *
   13:  * This program is distributed in the hope that it will be useful, but
   14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   16:  * for more details.
   17:  */
   18: 
   19: #include "tun_device.h"
   20: 
   21: #include <utils/debug.h>
   22: #include <threading/thread.h>
   23: 
   24: #if defined(__APPLE__)
   25: #include "TargetConditionals.h"
   26: #if !TARGET_OS_OSX
   27: #define TUN_DEVICE_NOT_SUPPORTED
   28: #endif
   29: #elif !defined(__linux__) && !defined(HAVE_NET_IF_TUN_H)
   30: #define TUN_DEVICE_NOT_SUPPORTED
   31: #endif
   32: 
   33: #ifdef TUN_DEVICE_NOT_SUPPORTED
   34: 
   35: tun_device_t *tun_device_create(const char *name_tmpl)
   36: {
   37: 	DBG1(DBG_LIB, "TUN devices are not supported");
   38: 	return NULL;
   39: }
   40: 
   41: #else /* TUN devices supported */
   42: 
   43: #include <errno.h>
   44: #include <fcntl.h>
   45: #include <netinet/in.h>
   46: #include <string.h>
   47: #include <sys/ioctl.h>
   48: #include <sys/types.h>
   49: #include <sys/socket.h>
   50: #include <sys/stat.h>
   51: #include <unistd.h>
   52: #include <net/if.h>
   53: 
   54: #ifdef __APPLE__
   55: #include <net/if_utun.h>
   56: #include <netinet/in_var.h>
   57: #include <sys/kern_control.h>
   58: #elif defined(__linux__)
   59: #include <linux/types.h>
   60: #include <linux/if_tun.h>
   61: #elif __FreeBSD__ >= 10
   62: #include <net/if_tun.h>
   63: #include <net/if_var.h>
   64: #include <netinet/in_var.h>
   65: #else
   66: #include <net/if_tun.h>
   67: #endif
   68: 
   69: #define TUN_DEFAULT_MTU 1500
   70: 
   71: typedef struct private_tun_device_t private_tun_device_t;
   72: 
   73: struct private_tun_device_t {
   74: 
   75: 	/**
   76: 	 * Public interface
   77: 	 */
   78: 	tun_device_t public;
   79: 
   80: 	/**
   81: 	 * The TUN device's file descriptor
   82: 	 */
   83: 	int tunfd;
   84: 
   85: 	/**
   86: 	 * Name of the TUN device
   87: 	 */
   88: 	char if_name[IFNAMSIZ];
   89: 
   90: 	/**
   91: 	 * Socket used for ioctl() to set interface addr, ...
   92: 	 */
   93: 	int sock;
   94: 
   95: 	/**
   96: 	 * The current MTU
   97: 	 */
   98: 	int mtu;
   99: 
  100: 	/**
  101: 	 * Associated address
  102: 	 */
  103: 	host_t *address;
  104: 
  105: 	/**
  106: 	 * Netmask for address
  107: 	 */
  108: 	uint8_t netmask;
  109: };
  110: 
  111: /**
  112:  * FreeBSD 10 deprecated the SIOCSIFADDR etc. commands.
  113:  */
  114: #if __FreeBSD__ >= 10
  115: 
  116: static bool set_address_and_mask(struct in_aliasreq *ifra, host_t *addr,
  117: 								 uint8_t netmask)
  118: {
  119: 	host_t *mask;
  120: 
  121: 	memcpy(&ifra->ifra_addr, addr->get_sockaddr(addr),
  122: 		   *addr->get_sockaddr_len(addr));
  123: 	/* set the same address as destination address */
  124: 	memcpy(&ifra->ifra_dstaddr, addr->get_sockaddr(addr),
  125: 		   *addr->get_sockaddr_len(addr));
  126: 
  127: 	mask = host_create_netmask(addr->get_family(addr), netmask);
  128: 	if (!mask)
  129: 	{
  130: 		DBG1(DBG_LIB, "invalid netmask: %d", netmask);
  131: 		return FALSE;
  132: 	}
  133: 	memcpy(&ifra->ifra_mask, mask->get_sockaddr(mask),
  134: 		   *mask->get_sockaddr_len(mask));
  135: 	mask->destroy(mask);
  136: 	return TRUE;
  137: }
  138: 
  139: /**
  140:  * Set the address using the more flexible SIOCAIFADDR/SIOCDIFADDR commands
  141:  * on FreeBSD 10 an newer.
  142:  */
  143: static bool set_address_impl(private_tun_device_t *this, host_t *addr,
  144: 							 uint8_t netmask)
  145: {
  146: 	struct in_aliasreq ifra;
  147: 
  148: 	memset(&ifra, 0, sizeof(ifra));
  149: 	strncpy(ifra.ifra_name, this->if_name, IFNAMSIZ);
  150: 
  151: 	if (this->address)
  152: 	{	/* remove the existing address first */
  153: 		if (!set_address_and_mask(&ifra, this->address, this->netmask))
  154: 		{
  155: 			return FALSE;
  156: 		}
  157: 		if (ioctl(this->sock, SIOCDIFADDR, &ifra) < 0)
  158: 		{
  159: 			DBG1(DBG_LIB, "failed to remove existing address on %s: %s",
  160: 				 this->if_name, strerror(errno));
  161: 			return FALSE;
  162: 		}
  163: 	}
  164: 	if (!set_address_and_mask(&ifra, addr, netmask))
  165: 	{
  166: 		return FALSE;
  167: 	}
  168: 	if (ioctl(this->sock, SIOCAIFADDR, &ifra) < 0)
  169: 	{
  170: 		DBG1(DBG_LIB, "failed to add address on %s: %s",
  171: 			 this->if_name, strerror(errno));
  172: 		return FALSE;
  173: 	}
  174: 	return TRUE;
  175: }
  176: 
  177: #else /* __FreeBSD__ */
  178: 
  179: /**
  180:  * Set the address using the classic SIOCSIFADDR etc. commands on other systems.
  181:  */
  182: static bool set_address_impl(private_tun_device_t *this, host_t *addr,
  183: 							 uint8_t netmask)
  184: {
  185: 	struct ifreq ifr;
  186: 	host_t *mask;
  187: 
  188: 	memset(&ifr, 0, sizeof(ifr));
  189: 	strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
  190: 	memcpy(&ifr.ifr_addr, addr->get_sockaddr(addr),
  191: 		   *addr->get_sockaddr_len(addr));
  192: 
  193: 	if (ioctl(this->sock, SIOCSIFADDR, &ifr) < 0)
  194: 	{
  195: 		DBG1(DBG_LIB, "failed to set address on %s: %s",
  196: 			 this->if_name, strerror(errno));
  197: 		return FALSE;
  198: 	}
  199: #ifdef __APPLE__
  200: 	if (ioctl(this->sock, SIOCSIFDSTADDR, &ifr) < 0)
  201: 	{
  202: 		DBG1(DBG_LIB, "failed to set dest address on %s: %s",
  203: 			 this->if_name, strerror(errno));
  204: 		return FALSE;
  205: 	}
  206: #endif /* __APPLE__ */
  207: 
  208: 	mask = host_create_netmask(addr->get_family(addr), netmask);
  209: 	if (!mask)
  210: 	{
  211: 		DBG1(DBG_LIB, "invalid netmask: %d", netmask);
  212: 		return FALSE;
  213: 	}
  214: 	memcpy(&ifr.ifr_addr, mask->get_sockaddr(mask),
  215: 		   *mask->get_sockaddr_len(mask));
  216: 	mask->destroy(mask);
  217: 
  218: 	if (ioctl(this->sock, SIOCSIFNETMASK, &ifr) < 0)
  219: 	{
  220: 		DBG1(DBG_LIB, "failed to set netmask on %s: %s",
  221: 			 this->if_name, strerror(errno));
  222: 		return FALSE;
  223: 	}
  224: 	return TRUE;
  225: }
  226: 
  227: #endif /* __FreeBSD__ */
  228: 
  229: METHOD(tun_device_t, set_address, bool,
  230: 	private_tun_device_t *this, host_t *addr, uint8_t netmask)
  231: {
  232: 	if (!set_address_impl(this, addr, netmask))
  233: 	{
  234: 		return FALSE;
  235: 	}
  236: 	DESTROY_IF(this->address);
  237: 	this->address = addr->clone(addr);
  238: 	this->netmask = netmask;
  239: 	return TRUE;
  240: }
  241: 
  242: METHOD(tun_device_t, get_address, host_t*,
  243: 	private_tun_device_t *this, uint8_t *netmask)
  244: {
  245: 	if (netmask && this->address)
  246: 	{
  247: 		*netmask = this->netmask;
  248: 	}
  249: 	return this->address;
  250: }
  251: 
  252: METHOD(tun_device_t, up, bool,
  253: 	private_tun_device_t *this)
  254: {
  255: 	struct ifreq ifr;
  256: 
  257: 	memset(&ifr, 0, sizeof(ifr));
  258: 	strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
  259: 
  260: 	if (ioctl(this->sock, SIOCGIFFLAGS, &ifr) < 0)
  261: 	{
  262: 		DBG1(DBG_LIB, "failed to get interface flags for %s: %s", this->if_name,
  263: 			 strerror(errno));
  264: 		return FALSE;
  265: 	}
  266: 
  267: 	ifr.ifr_flags |= IFF_RUNNING | IFF_UP;
  268: 
  269: 	if (ioctl(this->sock, SIOCSIFFLAGS, &ifr) < 0)
  270: 	{
  271: 		DBG1(DBG_LIB, "failed to set interface flags on %s: %s", this->if_name,
  272: 			 strerror(errno));
  273: 		return FALSE;
  274: 	}
  275: 	return TRUE;
  276: }
  277: 
  278: METHOD(tun_device_t, set_mtu, bool,
  279: 	private_tun_device_t *this, int mtu)
  280: {
  281: 	struct ifreq ifr;
  282: 
  283: 	memset(&ifr, 0, sizeof(ifr));
  284: 	strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
  285: 	ifr.ifr_mtu = mtu;
  286: 
  287: 	if (ioctl(this->sock, SIOCSIFMTU, &ifr) < 0)
  288: 	{
  289: 		DBG1(DBG_LIB, "failed to set MTU on %s: %s", this->if_name,
  290: 			 strerror(errno));
  291: 		return FALSE;
  292: 	}
  293: 	this->mtu = mtu;
  294: 	return TRUE;
  295: }
  296: 
  297: METHOD(tun_device_t, get_mtu, int,
  298: 	private_tun_device_t *this)
  299: {
  300: 	struct ifreq ifr;
  301: 
  302: 	if (this->mtu > 0)
  303: 	{
  304: 		return this->mtu;
  305: 	}
  306: 
  307: 	memset(&ifr, 0, sizeof(ifr));
  308: 	strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
  309: 	this->mtu = TUN_DEFAULT_MTU;
  310: 
  311: 	if (ioctl(this->sock, SIOCGIFMTU, &ifr) == 0)
  312: 	{
  313: 		this->mtu = ifr.ifr_mtu;
  314: 	}
  315: 	return this->mtu;
  316: }
  317: 
  318: METHOD(tun_device_t, get_name, char*,
  319: 	private_tun_device_t *this)
  320: {
  321: 	return this->if_name;
  322: }
  323: 
  324: METHOD(tun_device_t, get_fd, int,
  325: 	private_tun_device_t *this)
  326: {
  327: 	return this->tunfd;
  328: }
  329: 
  330: METHOD(tun_device_t, write_packet, bool,
  331: 	private_tun_device_t *this, chunk_t packet)
  332: {
  333: 	ssize_t s;
  334: 
  335: #ifdef __APPLE__
  336: 	/* UTUN's expect the packets to be prepended by a 32-bit protocol number
  337: 	 * instead of parsing the packet again, we assume IPv4 for now */
  338: 	uint32_t proto = htonl(AF_INET);
  339: 	packet = chunk_cata("cc", chunk_from_thing(proto), packet);
  340: #endif
  341: 	s = write(this->tunfd, packet.ptr, packet.len);
  342: 	if (s < 0)
  343: 	{
  344: 		DBG1(DBG_LIB, "failed to write packet to TUN device %s: %s",
  345: 			 this->if_name, strerror(errno));
  346: 		return FALSE;
  347: 	}
  348: 	else if (s != packet.len)
  349: 	{
  350: 		return FALSE;
  351: 	}
  352: 	return TRUE;
  353: }
  354: 
  355: METHOD(tun_device_t, read_packet, bool,
  356: 	private_tun_device_t *this, chunk_t *packet)
  357: {
  358: 	chunk_t data;
  359: 	ssize_t len;
  360: 	bool old;
  361: 
  362: 	data = chunk_alloca(get_mtu(this));
  363: 
  364: 	old = thread_cancelability(TRUE);
  365: 	len = read(this->tunfd, data.ptr, data.len);
  366: 	thread_cancelability(old);
  367: 	if (len < 0)
  368: 	{
  369: 		DBG1(DBG_LIB, "reading from TUN device %s failed: %s", this->if_name,
  370: 			 strerror(errno));
  371: 		return FALSE;
  372: 	}
  373: 	data.len = len;
  374: #ifdef __APPLE__
  375: 	/* UTUN's prepend packets with a 32-bit protocol number */
  376: 	data = chunk_skip(data, sizeof(uint32_t));
  377: #endif
  378: 	*packet = chunk_clone(data);
  379: 	return TRUE;
  380: }
  381: 
  382: METHOD(tun_device_t, destroy, void,
  383: 	private_tun_device_t *this)
  384: {
  385: 	if (this->tunfd > 0)
  386: 	{
  387: 		close(this->tunfd);
  388: #ifdef __FreeBSD__
  389: 		/* tun(4) says the following: "These network interfaces persist until
  390: 		 * the if_tun.ko module is unloaded, or until removed with the
  391: 		 * ifconfig(8) command."  So simply closing the FD is not enough. */
  392: 		struct ifreq ifr;
  393: 
  394: 		memset(&ifr, 0, sizeof(ifr));
  395: 		strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
  396: 		if (ioctl(this->sock, SIOCIFDESTROY, &ifr) < 0)
  397: 		{
  398: 			DBG1(DBG_LIB, "failed to destroy %s: %s", this->if_name,
  399: 				 strerror(errno));
  400: 		}
  401: #endif /* __FreeBSD__ */
  402: 	}
  403: 	if (this->sock > 0)
  404: 	{
  405: 		close(this->sock);
  406: 	}
  407: 	DESTROY_IF(this->address);
  408: 	free(this);
  409: }
  410: 
  411: /**
  412:  * Initialize the tun device
  413:  */
  414: static bool init_tun(private_tun_device_t *this, const char *name_tmpl)
  415: {
  416: #ifdef __APPLE__
  417: 
  418: 	struct ctl_info info;
  419: 	struct sockaddr_ctl addr;
  420: 	socklen_t size = IFNAMSIZ;
  421: 
  422: 	memset(&info, 0, sizeof(info));
  423: 	memset(&addr, 0, sizeof(addr));
  424: 
  425: 	this->tunfd = socket(PF_SYSTEM, SOCK_DGRAM, SYSPROTO_CONTROL);
  426: 	if (this->tunfd < 0)
  427: 	{
  428: 		DBG1(DBG_LIB, "failed to open tundevice PF_SYSTEM socket: %s",
  429: 			 strerror(errno));
  430: 		return FALSE;
  431: 	}
  432: 
  433: 	/* get a control identifier for the utun kernel extension */
  434: 	strncpy(info.ctl_name, UTUN_CONTROL_NAME, strlen(UTUN_CONTROL_NAME));
  435: 	if (ioctl(this->tunfd, CTLIOCGINFO, &info) < 0)
  436: 	{
  437: 		DBG1(DBG_LIB, "failed to ioctl tundevice: %s", strerror(errno));
  438: 		close(this->tunfd);
  439: 		return FALSE;
  440: 	}
  441: 
  442: 	addr.sc_id = info.ctl_id;
  443: 	addr.sc_len = sizeof(addr);
  444: 	addr.sc_family = AF_SYSTEM;
  445: 	addr.ss_sysaddr = AF_SYS_CONTROL;
  446: 	/* allocate identifier dynamically */
  447: 	addr.sc_unit = 0;
  448: 
  449: 	if (connect(this->tunfd, (struct sockaddr*)&addr, sizeof(addr)) < 0)
  450: 	{
  451: 		DBG1(DBG_LIB, "failed to connect tundevice: %s", strerror(errno));
  452: 		close(this->tunfd);
  453: 		return FALSE;
  454: 	}
  455: 	if (getsockopt(this->tunfd, SYSPROTO_CONTROL, UTUN_OPT_IFNAME,
  456: 				   this->if_name, &size) < 0)
  457: 	{
  458: 		DBG1(DBG_LIB, "getting tundevice name failed: %s", strerror(errno));
  459: 		close(this->tunfd);
  460: 		return FALSE;
  461: 	}
  462: 	return TRUE;
  463: 
  464: #elif defined(IFF_TUN)
  465: 
  466: 	struct ifreq ifr;
  467: 
  468: 	strncpy(this->if_name, name_tmpl ?: "tun%d", IFNAMSIZ);
  469: 	this->if_name[IFNAMSIZ-1] = '\0';
  470: 
  471: 	this->tunfd = open("/dev/net/tun", O_RDWR);
  472: 	if (this->tunfd < 0)
  473: 	{
  474: 		DBG1(DBG_LIB, "failed to open /dev/net/tun: %s", strerror(errno));
  475: 		return FALSE;
  476: 	}
  477: 
  478: 	memset(&ifr, 0, sizeof(ifr));
  479: 
  480: 	/* TUN device, no packet info */
  481: 	ifr.ifr_flags = IFF_TUN | IFF_NO_PI;
  482: 
  483: 	strncpy(ifr.ifr_name, this->if_name, IFNAMSIZ);
  484: 	if (ioctl(this->tunfd, TUNSETIFF, (void*)&ifr) < 0)
  485: 	{
  486: 		DBG1(DBG_LIB, "failed to configure TUN device: %s", strerror(errno));
  487: 		close(this->tunfd);
  488: 		return FALSE;
  489: 	}
  490: 	strncpy(this->if_name, ifr.ifr_name, IFNAMSIZ);
  491: 	return TRUE;
  492: 
  493: #elif defined(__FreeBSD__)
  494: 
  495: 	if (name_tmpl)
  496: 	{
  497: 		DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
  498: 	}
  499: 
  500: 	this->tunfd = open("/dev/tun", O_RDWR);
  501: 	if (this->tunfd < 0)
  502: 	{
  503: 		DBG1(DBG_LIB, "failed to open /dev/tun: %s", strerror(errno));
  504: 		return FALSE;
  505: 	}
  506: 	fdevname_r(this->tunfd, this->if_name, IFNAMSIZ);
  507: 	return TRUE;
  508: 
  509: #else /* !__FreeBSD__ */
  510: 
  511: 	/* this might work on Linux with older TUN driver versions (no IFF_TUN) */
  512: 	char devname[IFNAMSIZ];
  513: 	/* the same process is allowed to open a device again, but that's not what
  514: 	 * we want (unless we previously closed a device, which we don't know at
  515: 	 * this point).  therefore, this counter is static so we don't accidentally
  516: 	 * open a device twice */
  517: 	static int i = -1;
  518: 
  519: 	if (name_tmpl)
  520: 	{
  521: 		DBG1(DBG_LIB, "arbitrary naming of TUN devices is not supported");
  522: 	}
  523: 
  524: 	for (; ++i < 256; )
  525: 	{
  526: 		snprintf(devname, IFNAMSIZ, "/dev/tun%d", i);
  527: 		this->tunfd = open(devname, O_RDWR);
  528: 		if (this->tunfd > 0)
  529: 		{	/* for ioctl(2) calls only the interface name is used */
  530: 			snprintf(this->if_name, IFNAMSIZ, "tun%d", i);
  531: 			break;
  532: 		}
  533: 		DBG1(DBG_LIB, "failed to open %s: %s", this->if_name, strerror(errno));
  534: 	}
  535: 	return this->tunfd > 0;
  536: 
  537: #endif /* !__APPLE__ */
  538: }
  539: 
  540: /*
  541:  * Described in header
  542:  */
  543: tun_device_t *tun_device_create(const char *name_tmpl)
  544: {
  545: 	private_tun_device_t *this;
  546: 
  547: 	INIT(this,
  548: 		.public = {
  549: 			.read_packet = _read_packet,
  550: 			.write_packet = _write_packet,
  551: 			.get_mtu = _get_mtu,
  552: 			.set_mtu = _set_mtu,
  553: 			.get_name = _get_name,
  554: 			.get_fd = _get_fd,
  555: 			.set_address = _set_address,
  556: 			.get_address = _get_address,
  557: 			.up = _up,
  558: 			.destroy = _destroy,
  559: 		},
  560: 		.tunfd = -1,
  561: 		.sock = -1,
  562: 	);
  563: 
  564: 	if (!init_tun(this, name_tmpl))
  565: 	{
  566: 		free(this);
  567: 		return NULL;
  568: 	}
  569: 	DBG1(DBG_LIB, "created TUN device: %s", this->if_name);
  570: 
  571: 	this->sock = socket(AF_INET, SOCK_DGRAM, 0);
  572: 	if (this->sock < 0)
  573: 	{
  574: 		DBG1(DBG_LIB, "failed to open socket to configure TUN device");
  575: 		destroy(this);
  576: 		return NULL;
  577: 	}
  578: 	return &this->public;
  579: }
  580: 
  581: #endif /* TUN devices supported */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>