that _should_ be just enough to implement TUN on Solaris 2.x

sadly this is ineligble for upstream because we don't bother
to use TAP in the slightest
pull/434/head
Rick V 5 years ago
parent 9f3d0cafc4
commit 1eddba0dd3
No known key found for this signature in database
GPG Key ID: C0EDC8723FDC3465

@ -147,6 +147,10 @@ extern "C"
char if_name[IF_NAMESIZE];
#if defined(FreeBSD)
int mode;
#endif
#if defined(__sun)
int ip_fd;
char internal_name[IF_NAMESIZE];
#endif
};

@ -47,5 +47,4 @@ tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len)
*/
return -1;
}
#endif

@ -20,6 +20,7 @@
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <arpa/inet.h>
#include <net/if.h>
@ -27,13 +28,22 @@
#include <net/if_types.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/in_systm.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>
#include <fcntl.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stropts.h>
#include <unistd.h>
#include <ctype.h>
#include <stdbool.h>
#include <errno.h>
#include <alloca.h>
#include "tuntap.h"
@ -42,50 +52,270 @@
static int
tuntap_sys_create_dev(struct device *dev, int tun)
{
return -1;
int if_fd, ip_muxid, ppa = -1;
struct lifreq lifr;
struct ifreq ifr;
const char *ptr = NULL;
struct strioctl strioc_ppa;
/* improved generic TUN/TAP driver from
* http://www.whiteboard.ne.jp/~admin2/tuntap/
* has IPv6 support. Most open-source variants of
* Solaris already have this driver in their package
* repos, Oracle Solaris users need to compile/load
* manually.
*/
explicit_bzero(&lifr, sizeof lifr);
if ((dev->ip_fd = open("/dev/udp", O_RDWR, 0)) < 0)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't open /dev/udp");
return -1;
}
if ((dev->tun_fd = open("/dev/tun", O_RDWR, 0)) < 0)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't open /dev/tun");
return -1;
}
/* get unit number */
if (*dev->if_name)
{
ptr = dev->if_name;
while (*ptr && !isdigit((int) *ptr))
{
ptr++;
}
ppa = atoi(ptr);
}
/* Assign a new PPA and get its unit number. */
strioc_ppa.ic_cmd = TUNNEWPPA;
strioc_ppa.ic_timout = 0;
strioc_ppa.ic_len = sizeof(ppa);
strioc_ppa.ic_dp = (char *)&ppa;
if (*ptr == '\0') /* no number given, try dynamic */
{
bool found_one = false;
while (!found_one && ppa < 64)
{
int new_ppa = ioctl(dev->tun_fd, I_STR, &strioc_ppa);
if (new_ppa >= 0)
{
char* msg = alloca(512);
sprintf(msg, "got dynamic interface tun%i", new_ppa);
tuntap_log( TUNTAP_LOG_INFO, msg );
ppa = new_ppa;
found_one = true;
break;
}
if (errno != EEXIST)
{
tuntap_log(TUNTAP_LOG_ERR, "unexpected error trying to find free tun interface");
return -1;
}
ppa++;
}
if (!found_one)
{
tuntap_log(TUNTAP_LOG_ERR, "could not find free tun interface, give up.");
return -1;
}
}
else /* try this particular one */
{
if ((ppa = ioctl(dev->tun_fd, I_STR, &strioc_ppa)) < 0)
{
char *msg = alloca(512);
sprintf(msg, "Can't assign PPA for new interface (tun%i)", ppa);
tuntap_log(TUNTAP_LOG_ERR, msg);
return -1;
}
}
if ((if_fd = open("/dev/tun", O_RDWR, 0)) < 0)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't open /dev/tun (2)");
return -1;
}
if (ioctl(if_fd, I_PUSH, "ip") < 0)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't push IP module");
return -1;
}
/* Assign ppa according to the unit number returned by tun device */
if (ioctl(if_fd, IF_UNITSEL, (char *) &ppa) < 0)
{
char *msg = alloca(512);
sprintf(msg, "Can't set PPA %i", ppa);
tuntap_log(TUNTAP_LOG_ERR, msg);
return -1;
}
snprintf(dev->internal_name, IF_NAMESIZE, "%s%d", "tun", ppa);
if ((ip_muxid = ioctl(dev->ip_fd, I_PLINK, if_fd)) < 0)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't link tun device to IP");
return -1;
}
explicit_bzero(&lifr, sizeof lifr);
explicit_bzero(&ifr, sizeof ifr);
memcpy(lifr.lifr_name, dev->internal_name, sizeof(lifr.lifr_name));
lifr.lifr_ip_muxid = ip_muxid;
if (ioctl(dev->ip_fd, SIOCSLIFMUXID, &lifr) < 0)
{
ioctl(dev->ip_fd, I_PUNLINK, ip_muxid);
tuntap_log(TUNTAP_LOG_ERR, "Can't set multiplexor id");
return -1;
}
fcntl(dev->tun_fd, F_SETFL, O_NONBLOCK);
fcntl(dev->tun_fd, F_SETFD, FD_CLOEXEC);
fcntl(dev->ip_fd, F_SETFD, FD_CLOEXEC);
char *msg = alloca(512);
sprintf(msg, "TUN device %s opened as %s", dev->if_name, dev->internal_name);
tuntap_log(TUNTAP_LOG_INFO, msg);
(void)memcpy(ifr.ifr_name, dev->internal_name, sizeof dev->internal_name);
/* Get the interface default values */
if(ioctl(dev->ctrl_sock, SIOCGIFFLAGS, &ifr) == -1)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't get interface values");
return -1;
}
/* Save flags for tuntap_{up, down} */
dev->flags = ifr.ifr_flags;
return 0;
}
int
tuntap_sys_start(struct device *dev, int mode, int tun)
tuntap_sys_start(struct device *dev, int mode, int tun)
{
return -1;
/* Forces automatic selection of device instance
* in tuntap_sys_create_dev().
* This also clears the specified interface name.
*/
if (tun == TUNTAP_ID_ANY)
memset(&dev->if_name, '\0', sizeof dev->if_name);
if (mode == TUNTAP_MODE_TUNNEL)
{
return tuntap_sys_create_dev(dev, tun);
}
else
return -1;
/* NOTREACHED */
}
void
tuntap_sys_destroy(struct device *dev)
{
return /*-1*/;
}
struct lifreq ifr;
int
tuntap_sys_set_hwaddr(struct device *dev, struct ether_addr *eth_addr)
{
return -1;
explicit_bzero(&ifr, sizeof ifr);
strncpy(ifr.lifr_name, dev->internal_name, sizeof(ifr.lifr_name));
if (ioctl(dev->ip_fd, SIOCGLIFFLAGS, &ifr) < 0)
{
tuntap_log(TUNTAP_LOG_WARN, "Can't get iface flags");
}
if (ioctl(dev->ip_fd, SIOCGLIFMUXID, &ifr) < 0)
{
tuntap_log(TUNTAP_LOG_WARN, "Can't get multiplexor id");
}
/* we don't support TAP, and i think jaff stripped out TAP code a while
* back...
*/
if (ioctl(dev->ip_fd, I_PUNLINK, ifr.lifr_ip_muxid) < 0)
{
tuntap_log(TUNTAP_LOG_WARN, "Can't unlink interface(ip)");
}
close(dev->ip_fd);
dev->ip_fd = -1;
}
int
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t imask)
tuntap_sys_set_ipv4(struct device *dev, t_tun_in_addr *s4, uint32_t bits)
{
return -1;
struct lifreq ifr;
struct sockaddr_in mask;
(void)memset(&ifr, '\0', sizeof ifr);
(void)memcpy(ifr.lifr_name, dev->internal_name, sizeof dev->internal_name);
/* Set the IP address first */
(void)memcpy(&(((struct sockaddr_in *)&ifr.lifr_addr)->sin_addr), s4,
sizeof(struct in_addr));
ifr.lifr_addr.ss_family = AF_INET;
if(ioctl(dev->ctrl_sock, SIOCSLIFADDR, &ifr) == -1)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't set IP address");
return -1;
}
/* Reinit the struct ifr */
(void)memset(&ifr.lifr_addr, '\0', sizeof ifr.lifr_addr);
/* Then set the netmask */
(void)memset(&mask, '\0', sizeof mask);
mask.sin_family = AF_INET;
mask.sin_addr.s_addr = bits;
(void)memcpy(&ifr.lifr_addr, &mask, sizeof mask);
if(ioctl(dev->ctrl_sock, SIOCSLIFNETMASK, &ifr) == -1)
{
tuntap_log(TUNTAP_LOG_ERR, "Can't set netmask");
return -1;
}
return 0;
}
int
tuntap_sys_set_ipv6(struct device *dev, t_tun_in6_addr *s6, uint32_t imask)
{
return -1;
(void)dev;
(void)s6;
(void)imask;
tuntap_log(TUNTAP_LOG_NOTICE, "IPv6 is configured manually, this is currently unsupported");
return -1;
}
int
tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len)
tuntap_sys_set_ifname(struct device *dev, const char *ifname, size_t len)
{
return -1;
/* Not quite sure if solaris SIOCSLIFNAME work the same way as on Linux,
* given the correct parameters.
*/
(void)dev;
(void)ifname;
(void)len;
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_ifname()");
return -1;
}
int
tuntap_sys_set_descr(struct device *dev, const char *descr, size_t len)
{
(void)dev;
(void)descr;
(void)len;
return -1;
}
(void)dev;
(void)descr;
(void)len;
tuntap_log(TUNTAP_LOG_NOTICE,
"Your system does not support tuntap_set_descr()");
return -1;
}

@ -173,6 +173,10 @@ tuntap_set_ifname(struct device *dev, const char *ifname)
int
tuntap_up(struct device *dev)
{
/* On Solaris, the interface automatically comes up when an IP
* address is first assigned.
*/
#ifndef __sun
struct ifreq ifr;
(void)memset(&ifr, '\0', sizeof ifr);
@ -186,6 +190,7 @@ tuntap_up(struct device *dev)
}
dev->flags = ifr.ifr_flags;
#endif
return 0;
}

Loading…
Cancel
Save