|
|
1.1 ! root 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 "net/tap.h" ! 26: ! 27: #include <sys/stat.h> ! 28: #include <sys/ethernet.h> ! 29: #include <sys/sockio.h> ! 30: #include <netinet/arp.h> ! 31: #include <netinet/in.h> ! 32: #include <netinet/in_systm.h> ! 33: #include <netinet/ip.h> ! 34: #include <netinet/ip_icmp.h> // must come after ip.h ! 35: #include <netinet/udp.h> ! 36: #include <netinet/tcp.h> ! 37: #include <net/if.h> ! 38: #include <syslog.h> ! 39: #include <stropts.h> ! 40: ! 41: ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) ! 42: { ! 43: struct strbuf sbuf; ! 44: int f = 0; ! 45: ! 46: sbuf.maxlen = maxlen; ! 47: sbuf.buf = (char *)buf; ! 48: ! 49: return getmsg(tapfd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1; ! 50: } ! 51: ! 52: #define TUNNEWPPA (('T'<<16) | 0x0001) ! 53: /* ! 54: * Allocate TAP device, returns opened fd. ! 55: * Stores dev name in the first arg(must be large enough). ! 56: */ ! 57: static int tap_alloc(char *dev, size_t dev_size) ! 58: { ! 59: int tap_fd, if_fd, ppa = -1; ! 60: static int ip_fd = 0; ! 61: char *ptr; ! 62: ! 63: static int arp_fd = 0; ! 64: int ip_muxid, arp_muxid; ! 65: struct strioctl strioc_if, strioc_ppa; ! 66: int link_type = I_PLINK;; ! 67: struct lifreq ifr; ! 68: char actual_name[32] = ""; ! 69: ! 70: memset(&ifr, 0x0, sizeof(ifr)); ! 71: ! 72: if( *dev ){ ! 73: ptr = dev; ! 74: while( *ptr && !qemu_isdigit((int)*ptr) ) ptr++; ! 75: ppa = atoi(ptr); ! 76: } ! 77: ! 78: /* Check if IP device was opened */ ! 79: if( ip_fd ) ! 80: close(ip_fd); ! 81: ! 82: TFR(ip_fd = open("/dev/udp", O_RDWR, 0)); ! 83: if (ip_fd < 0) { ! 84: syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)"); ! 85: return -1; ! 86: } ! 87: ! 88: TFR(tap_fd = open("/dev/tap", O_RDWR, 0)); ! 89: if (tap_fd < 0) { ! 90: syslog(LOG_ERR, "Can't open /dev/tap"); ! 91: return -1; ! 92: } ! 93: ! 94: /* Assign a new PPA and get its unit number. */ ! 95: strioc_ppa.ic_cmd = TUNNEWPPA; ! 96: strioc_ppa.ic_timout = 0; ! 97: strioc_ppa.ic_len = sizeof(ppa); ! 98: strioc_ppa.ic_dp = (char *)&ppa; ! 99: if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) ! 100: syslog (LOG_ERR, "Can't assign new interface"); ! 101: ! 102: TFR(if_fd = open("/dev/tap", O_RDWR, 0)); ! 103: if (if_fd < 0) { ! 104: syslog(LOG_ERR, "Can't open /dev/tap (2)"); ! 105: return -1; ! 106: } ! 107: if(ioctl(if_fd, I_PUSH, "ip") < 0){ ! 108: syslog(LOG_ERR, "Can't push IP module"); ! 109: return -1; ! 110: } ! 111: ! 112: if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) ! 113: syslog(LOG_ERR, "Can't get flags\n"); ! 114: ! 115: snprintf (actual_name, 32, "tap%d", ppa); ! 116: pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name); ! 117: ! 118: ifr.lifr_ppa = ppa; ! 119: /* Assign ppa according to the unit number returned by tun device */ ! 120: ! 121: if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0) ! 122: syslog (LOG_ERR, "Can't set PPA %d", ppa); ! 123: if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0) ! 124: syslog (LOG_ERR, "Can't get flags\n"); ! 125: /* Push arp module to if_fd */ ! 126: if (ioctl (if_fd, I_PUSH, "arp") < 0) ! 127: syslog (LOG_ERR, "Can't push ARP module (2)"); ! 128: ! 129: /* Push arp module to ip_fd */ ! 130: if (ioctl (ip_fd, I_POP, NULL) < 0) ! 131: syslog (LOG_ERR, "I_POP failed\n"); ! 132: if (ioctl (ip_fd, I_PUSH, "arp") < 0) ! 133: syslog (LOG_ERR, "Can't push ARP module (3)\n"); ! 134: /* Open arp_fd */ ! 135: TFR(arp_fd = open ("/dev/tap", O_RDWR, 0)); ! 136: if (arp_fd < 0) ! 137: syslog (LOG_ERR, "Can't open %s\n", "/dev/tap"); ! 138: ! 139: /* Set ifname to arp */ ! 140: strioc_if.ic_cmd = SIOCSLIFNAME; ! 141: strioc_if.ic_timout = 0; ! 142: strioc_if.ic_len = sizeof(ifr); ! 143: strioc_if.ic_dp = (char *)𝔦 ! 144: if (ioctl(arp_fd, I_STR, &strioc_if) < 0){ ! 145: syslog (LOG_ERR, "Can't set ifname to arp\n"); ! 146: } ! 147: ! 148: if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){ ! 149: syslog(LOG_ERR, "Can't link TAP device to IP"); ! 150: return -1; ! 151: } ! 152: ! 153: if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0) ! 154: syslog (LOG_ERR, "Can't link TAP device to ARP"); ! 155: ! 156: close (if_fd); ! 157: ! 158: memset(&ifr, 0x0, sizeof(ifr)); ! 159: pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name); ! 160: ifr.lifr_ip_muxid = ip_muxid; ! 161: ifr.lifr_arp_muxid = arp_muxid; ! 162: ! 163: if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0) ! 164: { ! 165: ioctl (ip_fd, I_PUNLINK , arp_muxid); ! 166: ioctl (ip_fd, I_PUNLINK, ip_muxid); ! 167: syslog (LOG_ERR, "Can't set multiplexor id"); ! 168: } ! 169: ! 170: snprintf(dev, dev_size, "tap%d", ppa); ! 171: return tap_fd; ! 172: } ! 173: ! 174: int tap_open(char *ifname, int ifname_size, int *vnet_hdr, int vnet_hdr_required) ! 175: { ! 176: char dev[10]=""; ! 177: int fd; ! 178: if( (fd = tap_alloc(dev, sizeof(dev))) < 0 ){ ! 179: fprintf(stderr, "Cannot allocate TAP device\n"); ! 180: return -1; ! 181: } ! 182: pstrcpy(ifname, ifname_size, dev); ! 183: if (*vnet_hdr) { ! 184: /* Solaris doesn't have IFF_VNET_HDR */ ! 185: *vnet_hdr = 0; ! 186: ! 187: if (vnet_hdr_required && !*vnet_hdr) { ! 188: qemu_error("vnet_hdr=1 requested, but no kernel " ! 189: "support for IFF_VNET_HDR available"); ! 190: close(fd); ! 191: return -1; ! 192: } ! 193: } ! 194: fcntl(fd, F_SETFL, O_NONBLOCK); ! 195: return fd; ! 196: } ! 197: ! 198: int tap_set_sndbuf(int fd, QemuOpts *opts) ! 199: { ! 200: return 0; ! 201: } ! 202: ! 203: int tap_probe_vnet_hdr(int fd) ! 204: { ! 205: return 0; ! 206: } ! 207: ! 208: int tap_probe_has_ufo(int fd) ! 209: { ! 210: return 0; ! 211: } ! 212: ! 213: void tap_fd_set_offload(int fd, int csum, int tso4, ! 214: int tso6, int ecn, int ufo) ! 215: { ! 216: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.