LCOV - code coverage report
Current view: top level - network/netdev - tuntap.c (source / functions) Hit Total Coverage
Test: main_coverage.info Lines: 0 71 0.0 %
Date: 2019-08-22 15:41:25 Functions: 0 5 0.0 %

          Line data    Source code
       1             : /* SPDX-License-Identifier: LGPL-2.1+ */
       2             : 
       3             : #include <errno.h>
       4             : #include <fcntl.h>
       5             : #include <net/if.h>
       6             : #include <netinet/if_ether.h>
       7             : #include <sys/ioctl.h>
       8             : #include <sys/stat.h>
       9             : #include <sys/types.h>
      10             : #include <linux/if_tun.h>
      11             : 
      12             : #include "alloc-util.h"
      13             : #include "fd-util.h"
      14             : #include "netdev/tuntap.h"
      15             : #include "user-util.h"
      16             : 
      17             : #define TUN_DEV "/dev/net/tun"
      18             : 
      19           0 : static int netdev_fill_tuntap_message(NetDev *netdev, struct ifreq *ifr) {
      20             :         TunTap *t;
      21             : 
      22           0 :         assert(netdev);
      23           0 :         assert(netdev->ifname);
      24           0 :         assert(ifr);
      25             : 
      26           0 :         if (netdev->kind == NETDEV_KIND_TAP) {
      27           0 :                 t = TAP(netdev);
      28           0 :                 ifr->ifr_flags |= IFF_TAP;
      29             :         } else {
      30           0 :                 t = TUN(netdev);
      31           0 :                 ifr->ifr_flags |= IFF_TUN;
      32             :         }
      33             : 
      34           0 :         if (!t->packet_info)
      35           0 :                 ifr->ifr_flags |= IFF_NO_PI;
      36             : 
      37           0 :         if (t->multi_queue)
      38           0 :                 ifr->ifr_flags |= IFF_MULTI_QUEUE;
      39             : 
      40           0 :         if (t->vnet_hdr)
      41           0 :                 ifr->ifr_flags |= IFF_VNET_HDR;
      42             : 
      43           0 :         strncpy(ifr->ifr_name, netdev->ifname, IFNAMSIZ-1);
      44             : 
      45           0 :         return 0;
      46             : }
      47             : 
      48           0 : static int netdev_tuntap_add(NetDev *netdev, struct ifreq *ifr) {
      49           0 :         _cleanup_close_ int fd;
      50           0 :         TunTap *t = NULL;
      51             :         const char *user;
      52             :         const char *group;
      53             :         uid_t uid;
      54             :         gid_t gid;
      55             :         int r;
      56             : 
      57           0 :         assert(netdev);
      58           0 :         assert(ifr);
      59             : 
      60           0 :         fd = open(TUN_DEV, O_RDWR|O_CLOEXEC);
      61           0 :         if (fd < 0)
      62           0 :                 return log_netdev_error_errno(netdev, -errno,  "Failed to open tun dev: %m");
      63             : 
      64           0 :         if (ioctl(fd, TUNSETIFF, ifr) < 0)
      65           0 :                 return log_netdev_error_errno(netdev, -errno, "TUNSETIFF failed on tun dev: %m");
      66             : 
      67           0 :         if (netdev->kind == NETDEV_KIND_TAP)
      68           0 :                 t = TAP(netdev);
      69             :         else
      70           0 :                 t = TUN(netdev);
      71             : 
      72           0 :         assert(t);
      73             : 
      74           0 :         if (t->user_name) {
      75           0 :                 user = t->user_name;
      76             : 
      77           0 :                 r = get_user_creds(&user, &uid, NULL, NULL, NULL, USER_CREDS_ALLOW_MISSING);
      78           0 :                 if (r < 0)
      79           0 :                         return log_netdev_error_errno(netdev, r, "Cannot resolve user name %s: %m", t->user_name);
      80             : 
      81           0 :                 if (ioctl(fd, TUNSETOWNER, uid) < 0)
      82           0 :                         return log_netdev_error_errno(netdev, -errno, "TUNSETOWNER failed on tun dev: %m");
      83             :         }
      84             : 
      85           0 :         if (t->group_name) {
      86           0 :                 group = t->group_name;
      87             : 
      88           0 :                 r = get_group_creds(&group, &gid, USER_CREDS_ALLOW_MISSING);
      89           0 :                 if (r < 0)
      90           0 :                         return log_netdev_error_errno(netdev, r, "Cannot resolve group name %s: %m", t->group_name);
      91             : 
      92           0 :                 if (ioctl(fd, TUNSETGROUP, gid) < 0)
      93           0 :                         return log_netdev_error_errno(netdev, -errno, "TUNSETGROUP failed on tun dev: %m");
      94             : 
      95             :         }
      96             : 
      97           0 :         if (ioctl(fd, TUNSETPERSIST, 1) < 0)
      98           0 :                 return log_netdev_error_errno(netdev, -errno, "TUNSETPERSIST failed on tun dev: %m");
      99             : 
     100           0 :         return 0;
     101             : }
     102             : 
     103           0 : static int netdev_create_tuntap(NetDev *netdev) {
     104           0 :         struct ifreq ifr = {};
     105             :         int r;
     106             : 
     107           0 :         r = netdev_fill_tuntap_message(netdev, &ifr);
     108           0 :         if (r < 0)
     109           0 :                 return r;
     110             : 
     111           0 :         return netdev_tuntap_add(netdev, &ifr);
     112             : }
     113             : 
     114           0 : static void tuntap_done(NetDev *netdev) {
     115           0 :         TunTap *t = NULL;
     116             : 
     117           0 :         assert(netdev);
     118             : 
     119           0 :         if (netdev->kind == NETDEV_KIND_TUN)
     120           0 :                 t = TUN(netdev);
     121             :         else
     122           0 :                 t = TAP(netdev);
     123             : 
     124           0 :         assert(t);
     125             : 
     126           0 :         t->user_name = mfree(t->user_name);
     127           0 :         t->group_name = mfree(t->group_name);
     128           0 : }
     129             : 
     130           0 : static int tuntap_verify(NetDev *netdev, const char *filename) {
     131           0 :         assert(netdev);
     132             : 
     133           0 :         if (netdev->mtu != 0)
     134           0 :                 log_netdev_warning(netdev,
     135             :                                    "MTUBytes= configured for %s device in %s will be ignored.\n"
     136             :                                    "Please set it in the corresponding .network file.",
     137             :                                    netdev_kind_to_string(netdev->kind), filename);
     138             : 
     139           0 :         if (netdev->mac)
     140           0 :                 log_netdev_warning(netdev,
     141             :                                    "MACAddress= configured for %s device in %s will be ignored.\n"
     142             :                                    "Please set it in the corresponding .network file.",
     143             :                                    netdev_kind_to_string(netdev->kind), filename);
     144             : 
     145           0 :         return 0;
     146             : }
     147             : 
     148             : const NetDevVTable tun_vtable = {
     149             :         .object_size = sizeof(TunTap),
     150             :         .sections = "Match\0NetDev\0Tun\0",
     151             :         .config_verify = tuntap_verify,
     152             :         .done = tuntap_done,
     153             :         .create = netdev_create_tuntap,
     154             :         .create_type = NETDEV_CREATE_INDEPENDENT,
     155             : };
     156             : 
     157             : const NetDevVTable tap_vtable = {
     158             :         .object_size = sizeof(TunTap),
     159             :         .sections = "Match\0NetDev\0Tap\0",
     160             :         .config_verify = tuntap_verify,
     161             :         .done = tuntap_done,
     162             :         .create = netdev_create_tuntap,
     163             :         .create_type = NETDEV_CREATE_INDEPENDENT,
     164             : };

Generated by: LCOV version 1.14