tun.c

来自「OpenVPN -- A Secure tunneling daemon」· C语言 代码 · 共 811 行 · 第 1/2 页

C
811
字号
      /*       * Figure out if tun or tap device       */      if (is_dev_type (dev, dev_type, "tun"))	{	  ifr.ifr_flags |= IFF_TUN;	}      else if (is_dev_type (dev, dev_type, "tap"))	{	  ifr.ifr_flags |= IFF_TAP;	}      else	{	  msg (M_FATAL, "I don't recognize device %s as a tun or tap device",	       dev);	}      /*       * Set an explicit name, if --dev is not tun or tap       */      if (strcmp(dev, "tun") && strcmp(dev, "tap"))	strncpynt (ifr.ifr_name, dev, IFNAMSIZ);      /*       * Use special ioctl that configures tun/tap device with the parms       * we set in ifr       */      if (ioctl (tt->fd, TUNSETIFF, (void *) &ifr) < 0)	{	  msg (M_WARN | M_ERRNO, "Note: Cannot ioctl TUNSETIFF %s", dev);	  goto linux_2_2_fallback;	}      set_nonblock (tt->fd);      set_cloexec (tt->fd);      msg (M_INFO, "TUN/TAP device %s opened", ifr.ifr_name);      strncpynt (tt->actual, ifr.ifr_name, sizeof (tt->actual));    }  return; linux_2_2_fallback:  msg (M_INFO, "Note: Attempting fallback to kernel 2.2 TUN/TAP interface");  close_tun_generic (tt);  open_tun_generic (dev, dev_node, ipv6, false, true, tt);}#elsevoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  open_tun_generic (dev, 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;  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){  close_tun_generic (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;  clear_tuntap (tt);  ipv6_support (ipv6, false, tt);  if (!strcmp(dev, "null"))    {      open_null (tt);      return;    }  if (is_dev_type (dev, 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 (is_dev_type (dev, 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);  openvpn_snprintf (tt->actual, sizeof (tt->actual),		    "%s%d", dev_tuntap_type, ppa);  CLEAR (ifr);  strncpynt (ifr.ifr_name, tt->actual, 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);}/* * Close TUN device.  */voidclose_tun (struct tuntap* tt){  if (tt->fd >= 0)    {      struct ifreq ifr;      CLEAR (ifr);      strncpynt (ifr.ifr_name, tt->actual, 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);      close (tt->fd);    }  clear_tuntap (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#endifvoidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  open_tun_generic (dev, dev_node, ipv6, false, true, tt);}voidclose_tun (struct tuntap* tt){  close_tun_generic (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){  u_int32_t type = htonl (AF_INET);  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 (writev (tt->fd, iv, 2));}intread_tun (struct tuntap* tt, uint8_t *buf, int len){  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));}#elif defined(TARGET_FREEBSD)voidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  open_tun_generic (dev, dev_node, ipv6, false, true, tt);  if (tt->fd >= 0)    {      int i = 0;      /* Disable extended modes */      ioctl (tt->fd, TUNSLMODE, &i);      ioctl (tt->fd, TUNSIFHEAD, &i);    }}voidclose_tun (struct tuntap* tt){  close_tun_generic (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);}#else /* generic */voidopen_tun (const char *dev, const char *dev_type, const char *dev_node, bool ipv6, struct tuntap *tt){  open_tun_generic (dev, dev_node, ipv6, false, true, tt);}voidclose_tun (struct tuntap* tt){  close_tun_generic (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);}#endif

⌨️ 快捷键说明

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