?? tun.c
字號:
#endif /* TUNSETPERSIST */voidclose_tun (struct tuntap *tt){ if (tt) { close_tun_generic (tt); free (tt); }}intwrite_tun (struct tuntap* tt, uint8_t *buf, int len){#if LINUX_IPV6 if (tt->ipv6) { struct tun_pi pi; struct iphdr *iph; struct iovec vect[2]; int ret; iph = (struct iphdr *)buf; pi.flags = 0; if(iph->version == 6) pi.proto = htons(ETH_P_IPV6); else pi.proto = htons(ETH_P_IP); vect[0].iov_len = sizeof(pi); vect[0].iov_base = π vect[1].iov_len = len; vect[1].iov_base = buf; ret = writev(tt->fd, vect, 2); return(ret - sizeof(pi)); } else#endif return write (tt->fd, buf, len);}intread_tun (struct tuntap* tt, uint8_t *buf, int len){#if LINUX_IPV6 if (tt->ipv6) { struct iovec vect[2]; struct tun_pi pi; int ret; vect[0].iov_len = sizeof(pi); vect[0].iov_base = π vect[1].iov_len = len; vect[1].iov_base = buf; ret = readv(tt->fd, vect, 2); return(ret - sizeof(pi)); } else#endif return read (tt->fd, buf, len);}#elif defined(TARGET_SOLARIS)#ifndef TUNNEWPPA#error I need the symbol TUNNEWPPA from net/if_tun.h#endifvoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){ int if_fd, muxid, ppa = -1; struct ifreq ifr; const char *ptr; const char *ip_node; const char *dev_tuntap_type; int link_type; bool is_tun; ipv6_support (ipv6, false, tt); if (tt->type == DEV_TYPE_NULL) { open_null (tt); return; } if (tt->type == DEV_TYPE_TUN) { ip_node = "/dev/udp"; if (!dev_node) dev_node = "/dev/tun"; dev_tuntap_type = "tun"; link_type = I_PLINK; is_tun = true; } else if (tt->type == DEV_TYPE_TAP) { ip_node = "/dev/ip"; if (!dev_node) dev_node = "/dev/tap"; dev_tuntap_type = "tap"; link_type = I_PLINK; /* was: I_LINK */ is_tun = false; } else { msg (M_FATAL, "I don't recognize device %s as a tun or tap device", dev); } /* get unit number */ if (*dev) { ptr = dev; while (*ptr && !isdigit ((int) *ptr)) ptr++; ppa = atoi (ptr); } if ((tt->ip_fd = open (ip_node, O_RDWR, 0)) < 0) msg (M_ERR, "Can't open %s", ip_node); if ((tt->fd = open (dev_node, O_RDWR, 0)) < 0) msg (M_ERR, "Can't open %s", dev_node); /* Assign a new PPA and get its unit number. */ if ((ppa = ioctl (tt->fd, TUNNEWPPA, ppa)) < 0) msg (M_ERR, "Can't assign new interface"); if ((if_fd = open (dev_node, O_RDWR, 0)) < 0) msg (M_ERR, "Can't open %s (2)", dev_node); if (ioctl (if_fd, I_PUSH, "ip") < 0) msg (M_ERR, "Can't push IP module"); /* Assign ppa according to the unit number returned by tun device */ if (ioctl (if_fd, IF_UNITSEL, (char *) &ppa) < 0) msg (M_ERR, "Can't set PPA %d", ppa); if ((muxid = ioctl (tt->ip_fd, link_type, if_fd)) < 0) msg (M_ERR, "Can't link %s device to IP", dev_tuntap_type); close (if_fd); tt->actual_name = (char *) malloc (32); CHECK_MALLOC_RETURN (tt->actual_name); openvpn_snprintf (tt->actual_name, 32, "%s%d", dev_tuntap_type, ppa); CLEAR (ifr); strncpynt (ifr.ifr_name, tt->actual_name, sizeof (ifr.ifr_name)); ifr.ifr_ip_muxid = muxid; if (ioctl (tt->ip_fd, SIOCSIFMUXID, &ifr) < 0) { ioctl (tt->ip_fd, I_PUNLINK, muxid); msg (M_ERR, "Can't set multiplexor id"); } set_nonblock (tt->fd); set_cloexec (tt->fd); set_cloexec (tt->ip_fd); msg (M_INFO, "TUN/TAP device %s opened", tt->actual_name);}/* * Close TUN device. */voidclose_tun (struct tuntap *tt){ if (tt && tt->fd >= 0) { struct ifreq ifr; CLEAR (ifr); if (ioctl (tt->ip_fd, SIOCGIFFLAGS, &ifr) < 0) msg (M_WARN | M_ERRNO, "Can't get iface flags"); if (ioctl (tt->ip_fd, SIOCGIFMUXID, &ifr) < 0) msg (M_WARN | M_ERRNO, "Can't get multiplexor id"); if (ioctl (tt->ip_fd, I_PUNLINK, ifr.ifr_ip_muxid) < 0) msg (M_WARN | M_ERRNO, "Can't unlink interface"); close (tt->ip_fd); close (tt->fd); } if (tt) { clear_tuntap (tt); free (tt); }}intwrite_tun (struct tuntap* tt, uint8_t *buf, int len){ struct strbuf sbuf; sbuf.len = len; sbuf.buf = (char *)buf; return putmsg (tt->fd, NULL, &sbuf, 0) >= 0 ? sbuf.len : -1;}intread_tun (struct tuntap* tt, uint8_t *buf, int len){ struct strbuf sbuf; int f = 0; sbuf.maxlen = len; sbuf.buf = (char *)buf; return getmsg (tt->fd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1;}#elif defined(TARGET_OPENBSD)#if !defined(HAVE_READV) || !defined(HAVE_WRITEV)#error openbsd build requires readv & writev library functions#endif/* * OpenBSD has a slightly incompatible TUN device from * the rest of the world, in that it prepends a * uint32 to the beginning of the IP header * to designate the protocol (why not just * look at the version field in the IP header to * determine v4 or v6?). * * We strip off this field on reads and * put it back on writes. * * I have not tested TAP devices on OpenBSD, * but I have conditionalized the special * TUN handling code described above to * go away for TAP devices. */voidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){ open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); /* Enable multicast on the interface */ if (tt->fd >= 0) { struct tuninfo info; if (ioctl (tt->fd, TUNGIFINFO, &info) < 0) { msg (M_WARN | M_ERRNO, "Can't get interface info: %s", strerror(errno)); } info.flags |= IFF_MULTICAST; if (ioctl (tt->fd, TUNSIFINFO, &info) < 0) { msg (M_WARN | M_ERRNO, "Can't set interface info: %s", strerror(errno)); } }}voidclose_tun (struct tuntap* tt){ if (tt) { close_tun_generic (tt); free (tt); }}static inline intopenbsd_modify_read_write_return (int len){ if (len > 0) return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; else return len;}intwrite_tun (struct tuntap* tt, uint8_t *buf, int len){ if (tt->type == DEV_TYPE_TUN) { u_int32_t type; struct iovec iv[2]; struct ip *iph; iph = (struct ip *) buf; if (tt->ipv6 && iph->ip_v == 6) type = htonl (AF_INET6); else type = htonl (AF_INET); iv[0].iov_base = &type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = len; return openbsd_modify_read_write_return (writev (tt->fd, iv, 2)); } else return write (tt->fd, buf, len);}intread_tun (struct tuntap* tt, uint8_t *buf, int len){ if (tt->type == DEV_TYPE_TUN) { u_int32_t type; struct iovec iv[2]; iv[0].iov_base = &type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = len; return openbsd_modify_read_write_return (readv (tt->fd, iv, 2)); } else return read (tt->fd, buf, len);}#elif defined(TARGET_NETBSD)/* * NetBSD does not support IPv6 on tun out of the box, * but there exists a patch. When this patch is applied, * only two things are left to openvpn: * 1. Activate multicasting (this has already been done * before by the kernel, but we make sure that nobody * has deactivated multicasting inbetween. * 2. Deactivate "link layer mode" (otherwise NetBSD * prepends the address family to the packet, and we * would run into the same trouble as with OpenBSD. */voidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){ open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); if (tt->fd >= 0) { int i = IFF_POINTOPOINT|IFF_MULTICAST; ioctl (tt->fd, TUNSIFMODE, &i); /* multicast on */ i = 0; ioctl (tt->fd, TUNSLMODE, &i); /* link layer mode off */ }}voidclose_tun (struct tuntap *tt){ if (tt) { close_tun_generic (tt); free (tt); }}intwrite_tun (struct tuntap* tt, uint8_t *buf, int len){ return write (tt->fd, buf, len);}intread_tun (struct tuntap* tt, uint8_t *buf, int len){ return read (tt->fd, buf, len);}#elif defined(TARGET_FREEBSD)static inline intfreebsd_modify_read_write_return (int len){ if (len > 0) return len > sizeof (u_int32_t) ? len - sizeof (u_int32_t) : 0; else return len;}voidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){ open_tun_generic (dev, dev_type, dev_node, ipv6, true, true, tt); if (tt->fd >= 0) { int i = 0; /* Disable extended modes */ ioctl (tt->fd, TUNSLMODE, &i); i = 1; ioctl (tt->fd, TUNSIFHEAD, &i); }}voidclose_tun (struct tuntap *tt){ if (tt) { close_tun_generic (tt); free (tt); }}intwrite_tun (struct tuntap* tt, uint8_t *buf, int len){ if (tt->type == DEV_TYPE_TUN) { u_int32_t type; struct iovec iv[2]; struct ip *iph; iph = (struct ip *) buf; if (tt->ipv6 && iph->ip_v == 6) type = htonl (AF_INET6); else type = htonl (AF_INET); iv[0].iov_base = (char *)&type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = len; return freebsd_modify_read_write_return (writev (tt->fd, iv, 2)); } else return write (tt->fd, buf, len);}intread_tun (struct tuntap* tt, uint8_t *buf, int len){ if (tt->type == DEV_TYPE_TUN) { u_int32_t type; struct iovec iv[2]; iv[0].iov_base = (char *)&type; iv[0].iov_len = sizeof (type); iv[1].iov_base = buf; iv[1].iov_len = len; return freebsd_modify_read_write_return (readv (tt->fd, iv, 2)); } else return read (tt->fd, buf, len);}#elif defined(WIN32)inttun_read_queue (struct tuntap *tt, int maxsize){ if (tt->reads.iostate == IOSTATE_INITIAL) { DWORD len; BOOL status; int err; /* reset buf to its initial state */ tt->reads.buf = tt->reads.buf_init; len = maxsize ? maxsize : BLEN (&tt->reads.buf); ASSERT (len <= BLEN (&tt->reads.buf)); /* the overlapped read will signal this event on I/O completion */ ASSERT (ResetEvent (tt->reads.overlapped.hEvent)); status = ReadFile( tt->hand, BPTR (&tt->reads.buf), len, &tt->reads.size, &tt->reads.overlapped ); if (status) /* operation completed immediately? */ { /* since we got an immediate return, we must signal the event object ourselves */ ASSERT (SetEvent (tt->reads.overlapped.hEvent)); tt->reads.iostate = IOSTATE_IMMEDIATE_RETURN; tt->reads.status = 0; msg (D_WIN32_IO, "WIN32 I/O: TAP Read immediate return [%d,%d]", (int) len, (int) tt->reads.size); } else { err = GetLastError ();
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -