From 9e0c4e1df552fc7e4b994285065d356bca15eeff Mon Sep 17 00:00:00 2001 From: Gerhard Rieger Date: Sat, 26 Nov 2011 14:25:27 +0100 Subject: [PATCH] allow tun/tap specification without IP address --- CHANGES | 2 ++ doc/socat.yo | 13 +++++++------ xio-tun.c | 53 ++++++++++++++++++++++++++-------------------------- 3 files changed, 36 insertions(+), 32 deletions(-) diff --git a/CHANGES b/CHANGES index c3281f9..14d2b9f 100644 --- a/CHANGES +++ b/CHANGES @@ -91,6 +91,8 @@ new features: added option max-children that limits the number of concurrent child processes. Thanks to Sam Liddicott for providing the patch. + Till Maas added support for tun/tap addresses without IP address + ####################### V 1.7.1.3: security: diff --git a/doc/socat.yo b/doc/socat.yo index 82be39c..41daa68 100644 --- a/doc/socat.yo +++ b/doc/socat.yo @@ -957,12 +957,13 @@ label(ADDRESS_TCP6_LISTEN)dit(bf(tt(TCP6-LISTEN:))) Additional useful option: link(ipv6only)(OPTION_IPV6_V6ONLY)nl() Option groups: link(FD)(GROUP_FD),link(SOCKET)(GROUP_SOCKET),link(LISTEN)(GROUP_LISTEN),link(CHILD)(GROUP_CHILD),link(RANGE)(GROUP_RANGE),link(IP6)(GROUP_IP6),link(TCP)(GROUP_TCP),link(RETRY)(GROUP_RETRY) nl() -label(ADDRESS_TUN)dit(bf(tt(TUN:/))) - Creates a Linux TUN/TAP device and assignes to it the address and netmask - defined by the parameters. The resulting network interface is ready for use - by other processes; socat serves its "wire side". This address requires read - and write access to the tunnel cloning device, usually code(/dev/net/tun). - nl() +label(ADDRESS_TUN)dit(bf(tt(TUN[:/]))) + Creates a Linux TUN/TAP device and optionally assignes it the address and + netmask given by the parameters. The resulting network interface is almost + ready for use by other processes; socat serves its "wire side". This address + requires read and write access to the tunnel cloning device, usually + code(/dev/net/tun), as well as permission to set some tt(ioctl()s). + bf(Option iff-up is required to immediately activate the interface!)nl() Option groups: link(FD)(GROUP_FD),link(NAMED)(GROUP_NAMED),link(OPEN)(GROUP_OPEN),link(TUN)(GROUP_TUN) nl() Useful options: link(iff-up)(OPTION_IFF_UP), diff --git a/xio-tun.c b/xio-tun.c index 2c9fff7..d1e7b6d 100644 --- a/xio-tun.c +++ b/xio-tun.c @@ -1,5 +1,5 @@ /* source: xio-tun.c */ -/* Copyright Gerhard Rieger 2007-2009 */ +/* Copyright Gerhard Rieger 2007-2011 */ /* Published under the GNU General Public License V.2, see file COPYING */ /* this file contains the source for opening addresses of tun/tap type */ @@ -78,8 +78,8 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl char *ifaddr; int result; - if (argc != 2) { - Error2("%s: wrong number of parameters (%d instead of 1)", + if (argc > 2 || argc < 0) { + Error2("%s: wrong number of parameters (%d instead of 0 or 1)", argv[0], argc-1); } @@ -146,30 +146,31 @@ static int xioopen_tun(int argc, const char *argv[], struct opt *opts, int xiofl } /*--------------------- setting interface address and netmask ------------*/ - if ((ifaddr = strdup(argv[1])) == NULL) { - Error1("strdup(\"%s\"): out of memory", argv[1]); - return STAT_RETRYLATER; + if (argc == 2) { + if ((ifaddr = strdup(argv[1])) == NULL) { + Error1("strdup(\"%s\"): out of memory", argv[1]); + return STAT_RETRYLATER; + } + if ((result = xioparsenetwork(ifaddr, pf, &network)) != STAT_OK) { + /*! recover */ + return result; + } + socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr); + ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = + network.netaddr.ip4.sin_addr; + if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { + Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s", + sockfd, ifr.ifr_name, ifaddr, strerror(errno)); + } + ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr = + network.netmask.ip4.sin_addr; + if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { + Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s", + sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr, + ifaddr, strerror(errno)); + } + free(ifaddr); } - if ((result = xioparsenetwork(ifaddr, pf, &network)) != STAT_OK) { - /*! recover */ - return result; - } - socket_init(pf, (union sockaddr_union *)&ifr.ifr_addr); - ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr = - network.netaddr.ip4.sin_addr; - if (Ioctl(sockfd, SIOCSIFADDR, &ifr) < 0) { - Error4("ioctl(%d, SIOCSIFADDR, {\"%s\", \"%s\"}: %s", - sockfd, ifr.ifr_name, ifaddr, strerror(errno)); - } - ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr = - network.netmask.ip4.sin_addr; - if (Ioctl(sockfd, SIOCSIFNETMASK, &ifr) < 0) { - Error4("ioctl(%d, SIOCSIFNETMASK, {\"0x%08u\", \"%s\"}, %s", - sockfd, ((struct sockaddr_in *)&ifr.ifr_netmask)->sin_addr.s_addr, - ifaddr, strerror(errno)); - } - free(ifaddr); - /*--------------------- setting interface flags --------------------------*/ applyopts_single(&xfd->stream, opts, PH_FD);