qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

tap-bsd.c (6423B)


      1 /*
      2  * QEMU System Emulator
      3  *
      4  * Copyright (c) 2003-2008 Fabrice Bellard
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and associated documentation files (the "Software"), to deal
      8  * in the Software without restriction, including without limitation the rights
      9  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     10  * copies of the Software, and to permit persons to whom the Software is
     11  * furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included in
     14  * all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     21  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     22  * THE SOFTWARE.
     23  */
     24 
     25 #include "qemu/osdep.h"
     26 #include "qapi/error.h"
     27 #include "tap_int.h"
     28 #include "qemu/cutils.h"
     29 #include "qemu/error-report.h"
     30 
     31 #if defined(__NetBSD__) || defined(__FreeBSD__)
     32 #include <sys/ioctl.h>
     33 #include <net/if.h>
     34 #include <net/if_tap.h>
     35 #endif
     36 
     37 #ifndef __FreeBSD__
     38 int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
     39              int vnet_hdr_required, int mq_required, Error **errp)
     40 {
     41     int fd;
     42 #ifdef TAPGIFNAME
     43     struct ifreq ifr;
     44 #else
     45     char *dev;
     46     struct stat s;
     47 #endif
     48 
     49     /* if no ifname is given, always start the search from tap0/tun0. */
     50     int i;
     51     char dname[100];
     52 
     53     for (i = 0; i < 10; i++) {
     54         if (*ifname) {
     55             snprintf(dname, sizeof dname, "/dev/%s", ifname);
     56         } else {
     57             snprintf(dname, sizeof dname, "/dev/tap%d", i);
     58         }
     59         TFR(fd = open(dname, O_RDWR));
     60         if (fd >= 0) {
     61             break;
     62         }
     63         else if (errno == ENXIO || errno == ENOENT) {
     64             break;
     65         }
     66         if (*ifname) {
     67             break;
     68         }
     69     }
     70     if (fd < 0) {
     71         error_setg_errno(errp, errno, "could not open %s", dname);
     72         return -1;
     73     }
     74 
     75 #ifdef TAPGIFNAME
     76     if (ioctl(fd, TAPGIFNAME, (void *)&ifr) < 0) {
     77         error_setg_errno(errp, errno, "could not get tap name");
     78         return -1;
     79     }
     80     pstrcpy(ifname, ifname_size, ifr.ifr_name);
     81 #else
     82     if (fstat(fd, &s) < 0) {
     83         error_setg_errno(errp, errno, "could not stat %s", dname);
     84         return -1;
     85     }
     86     dev = devname(s.st_rdev, S_IFCHR);
     87     pstrcpy(ifname, ifname_size, dev);
     88 #endif
     89 
     90     if (*vnet_hdr) {
     91         /* BSD doesn't have IFF_VNET_HDR */
     92         *vnet_hdr = 0;
     93 
     94         if (vnet_hdr_required && !*vnet_hdr) {
     95             error_setg(errp, "vnet_hdr=1 requested, but no kernel "
     96                        "support for IFF_VNET_HDR available");
     97             close(fd);
     98             return -1;
     99         }
    100     }
    101     g_unix_set_fd_nonblocking(fd, true, NULL);
    102     return fd;
    103 }
    104 
    105 #else /* __FreeBSD__ */
    106 
    107 #define PATH_NET_TAP "/dev/tap"
    108 
    109 static int tap_open_clone(char *ifname, int ifname_size, Error **errp)
    110 {
    111     int fd, s, ret;
    112     struct ifreq ifr;
    113 
    114     TFR(fd = open(PATH_NET_TAP, O_RDWR));
    115     if (fd < 0) {
    116         error_setg_errno(errp, errno, "could not open %s", PATH_NET_TAP);
    117         return -1;
    118     }
    119 
    120     memset(&ifr, 0, sizeof(ifr));
    121 
    122     ret = ioctl(fd, TAPGIFNAME, (void *)&ifr);
    123     if (ret < 0) {
    124         error_setg_errno(errp, errno, "could not get tap interface name");
    125         close(fd);
    126         return -1;
    127     }
    128 
    129     if (ifname[0] != '\0') {
    130         /* User requested the interface to have a specific name */
    131         s = socket(AF_LOCAL, SOCK_DGRAM, 0);
    132         if (s < 0) {
    133             error_setg_errno(errp, errno,
    134                              "could not open socket to set interface name");
    135             close(fd);
    136             return -1;
    137         }
    138         ifr.ifr_data = ifname;
    139         ret = ioctl(s, SIOCSIFNAME, (void *)&ifr);
    140         close(s);
    141         if (ret < 0) {
    142             error_setg(errp, "could not set tap interface name");
    143             close(fd);
    144             return -1;
    145         }
    146     } else {
    147         pstrcpy(ifname, ifname_size, ifr.ifr_name);
    148     }
    149 
    150     return fd;
    151 }
    152 
    153 int tap_open(char *ifname, int ifname_size, int *vnet_hdr,
    154              int vnet_hdr_required, int mq_required, Error **errp)
    155 {
    156     int fd = -1;
    157 
    158     /* If the specified tap device already exists just use it. */
    159     if (ifname[0] != '\0') {
    160         char dname[100];
    161         snprintf(dname, sizeof dname, "/dev/%s", ifname);
    162         TFR(fd = open(dname, O_RDWR));
    163         if (fd < 0 && errno != ENOENT) {
    164             error_setg_errno(errp, errno, "could not open %s", dname);
    165             return -1;
    166         }
    167     }
    168 
    169     if (fd < 0) {
    170         /* Tap device not specified or does not exist. */
    171         if ((fd = tap_open_clone(ifname, ifname_size, errp)) < 0) {
    172             return -1;
    173         }
    174     }
    175 
    176     if (*vnet_hdr) {
    177         /* BSD doesn't have IFF_VNET_HDR */
    178         *vnet_hdr = 0;
    179 
    180         if (vnet_hdr_required && !*vnet_hdr) {
    181             error_setg(errp, "vnet_hdr=1 requested, but no kernel "
    182                        "support for IFF_VNET_HDR available");
    183             goto error;
    184         }
    185     }
    186     if (mq_required) {
    187         error_setg(errp, "mq_required requested, but no kernel support"
    188                    " for IFF_MULTI_QUEUE available");
    189         goto error;
    190     }
    191 
    192     g_unix_set_fd_nonblocking(fd, true, NULL);
    193     return fd;
    194 
    195 error:
    196     close(fd);
    197     return -1;
    198 }
    199 #endif /* __FreeBSD__ */
    200 
    201 void tap_set_sndbuf(int fd, const NetdevTapOptions *tap, Error **errp)
    202 {
    203 }
    204 
    205 int tap_probe_vnet_hdr(int fd, Error **errp)
    206 {
    207     return 0;
    208 }
    209 
    210 int tap_probe_has_ufo(int fd)
    211 {
    212     return 0;
    213 }
    214 
    215 int tap_probe_vnet_hdr_len(int fd, int len)
    216 {
    217     return 0;
    218 }
    219 
    220 void tap_fd_set_vnet_hdr_len(int fd, int len)
    221 {
    222 }
    223 
    224 int tap_fd_set_vnet_le(int fd, int is_le)
    225 {
    226     return -EINVAL;
    227 }
    228 
    229 int tap_fd_set_vnet_be(int fd, int is_be)
    230 {
    231     return -EINVAL;
    232 }
    233 
    234 void tap_fd_set_offload(int fd, int csum, int tso4,
    235                         int tso6, int ecn, int ufo)
    236 {
    237 }
    238 
    239 int tap_fd_enable(int fd)
    240 {
    241     return -1;
    242 }
    243 
    244 int tap_fd_disable(int fd)
    245 {
    246     return -1;
    247 }
    248 
    249 int tap_fd_get_ifname(int fd, char *ifname)
    250 {
    251     return -1;
    252 }
    253 
    254 int tap_fd_set_steering_ebpf(int fd, int prog_fd)
    255 {
    256     return -1;
    257 }