⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tun.c

📁 tun虚拟网卡设备源码
💻 C
📖 第 1 页 / 共 5 页
字号:
#elsevoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  ASSERT (0);}#endif#elsevoidopen_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, false, true, tt);}#endif /* HAVE_LINUX_IF_TUN_H */#ifdef TUNSETPERSISTvoidtuncfg (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, int persist_mode){  struct tuntap *tt;  ALLOC_OBJ (tt, struct tuntap);  clear_tuntap (tt);  tt->type = dev_type_enum (dev, dev_type);  open_tun (dev, dev_type, dev_node, ipv6, tt);  if (ioctl (tt->fd, TUNSETPERSIST, persist_mode) < 0)    msg (M_ERR, "Cannot ioctl TUNSETPERSIST(%d) %s", persist_mode, dev);  close_tun (tt);  msg (M_INFO, "Persist state set to: %s", (persist_mode ? "ON" : "OFF"));}#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 = &pi;      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 = &pi;      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);}static voidsolaris_close_tun (struct tuntap *tt){  if (tt)    {      if (tt->ip_fd >= 0)	{	  struct ifreq ifr;	  CLEAR (ifr);	  strncpynt (ifr.ifr_name, tt->actual_name, sizeof (ifr.ifr_name));	  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);	  tt->ip_fd = -1;	}      if (tt->fd >= 0)	{	  close (tt->fd);	  tt->fd = -1;	}    }}/* * Close TUN device.  */voidclose_tun (struct tuntap *tt){  if (tt)    {      solaris_close_tun (tt);      if (tt->actual_name)	free (tt->actual_name);            clear_tuntap (tt);      free (tt);    }}static voidsolaris_error_close (struct tuntap *tt, const struct env_set *es, const char *actual){  char command_line[256];  openvpn_snprintf (command_line, sizeof (command_line),		    IFCONFIG_PATH " %s unplumb",		    actual);  msg (M_INFO, "%s", command_line);  system_check (command_line, es, 0, "Solaris ifconfig unplumb failed");  close_tun (tt);  msg (M_FATAL, "Solaris ifconfig failed");}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);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -