15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * QEMU System Emulator 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (c) 2003-2008 Fabrice Bellard 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Permission is hereby granted, free of charge, to any person obtaining a copy 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of this software and associated documentation files (the "Software"), to deal 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * in the Software without restriction, including without limitation the rights 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * copies of the Software, and to permit persons to whom the Software is 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * furnished to do so, subject to the following conditions: 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * The above copyright notice and this permission notice shall be included in 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * all copies or substantial portions of the Software. 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * THE SOFTWARE. 235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <unistd.h> 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <fcntl.h> 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <signal.h> 275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <time.h> 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <errno.h> 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/time.h> 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <zlib.h> 315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 322c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner/* Needed early for CONFIG_BSD etc. */ 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "config-host.h" 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/times.h> 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/wait.h> 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <termios.h> 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/mman.h> 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ioctl.h> 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/resource.h> 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/socket.h> 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h> 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h> 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __NetBSD__ 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if_tap.h> 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__ 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/if_tun.h> 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <arpa/inet.h> 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <dirent.h> 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netdb.h> 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/select.h> 552c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#ifdef CONFIG_BSD 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h> 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__FreeBSD__) || defined(__DragonFly__) 585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libutil.h> 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <util.h> 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined (__GLIBC__) && defined (__FreeBSD_kernel__) 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <freebsd/stdlib.h> 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __linux__ 665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <pty.h> 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <malloc.h> 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/rtc.h> 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* For the benefit of older linux systems which don't supply it, 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner we use a local copy of hpet.h. */ 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* #include <linux/hpet.h> */ 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hpet.h" 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/ppdev.h> 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <linux/parport.h> 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __sun__ 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/stat.h> 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/ethernet.h> 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/sockio.h> 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/arp.h> 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in.h> 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/in_systm.h> 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/ip.h> 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/ip_icmp.h> // must come after ip.h 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/udp.h> 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <netinet/tcp.h> 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <net/if.h> 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <syslog.h> 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <stropts.h> 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(__OpenBSD__) 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <util.h> 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_VDE) 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <libvdeplug.h> 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <windows.h> 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <malloc.h> 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <sys/timeb.h> 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include <mmsystem.h> 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define getopt_long_only getopt_long 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define memalign(align, size) malloc(size) 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "net.h" 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "monitor.h" 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sysemu.h" 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-timer.h" 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-char.h" 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "audio/audio.h" 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu_socket.h" 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-log.h" 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_SLIRP) 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "libslirp.h" 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic VLANState *first_vlan; 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/***********************************************************/ 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* network device redirectors */ 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(DEBUG_NET) || defined(DEBUG_SLIRP) 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void hex_dump(FILE *f, const uint8_t *buf, int size) 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len, i, j, c; 1375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(i=0;i<size;i+=16) { 1395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = size - i; 1405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len > 16) 1415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = 16; 1425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, "%08x ", i); 1435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(j=0;j<16;j++) { 1445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (j < len) 1455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, " %02x", buf[i+j]); 1465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 1475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, " "); 1485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, " "); 1505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(j=0;j<len;j++) { 1515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner c = buf[i+j]; 1525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (c < ' ' || c > '~') 1535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner c = '.'; 1545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, "%c", c); 1555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, "\n"); 1575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int parse_macaddr(uint8_t *macaddr, const char *p) 1625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 1645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *last_char; 1655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner long int offset; 1665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner errno = 0; 1685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner offset = strtol(p, &last_char, 0); 1695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (0 == errno && '\0' == *last_char && 1705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner offset >= 0 && offset <= 0xFFFFFF) { 1715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[3] = (offset & 0xFF0000) >> 16; 1725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[4] = (offset & 0xFF00) >> 8; 1735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[5] = offset & 0xFF; 1745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(i = 0; i < 6; i++) { 1775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[i] = strtol(p, (char **)&p, 16); 1785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (i == 5) { 1795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (*p != '\0') 1805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 1825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (*p != ':' && *p != '-') 1835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p++; 1855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 1885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 1915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int get_str_sep(char *buf, int buf_size, const char **pp, int sep) 1945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p, *p1; 1965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len; 1975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = *pp; 1985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p1 = strchr(p, sep); 1995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!p1) 2005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = p1 - p; 2025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p1++; 2035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (buf_size > 0) { 2045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (len > buf_size - 1) 2055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = buf_size - 1; 2065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(buf, p, len); 2075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf[len] = '\0'; 2085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *pp = p1; 2105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 2115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint parse_host_src_port(struct sockaddr_in *haddr, 2145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in *saddr, 2155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *input_str) 2165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *str = strdup(input_str); 2185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *host_str = str; 2195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *src_str; 2205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *src_str2; 2215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *ptr; 2225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* 2245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Chop off any extra arguments at the end of the string which 2255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * would start with a comma, then fill in the src port information 2265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * if it was provided else use the "any address" and "any port". 2275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 2285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((ptr = strchr(str,','))) 2295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *ptr = '\0'; 2305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((src_str = strchr(input_str,'@'))) { 2325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *src_str = '\0'; 2335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner src_str++; 2345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parse_host_port(haddr, host_str) < 0) 2375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 2385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner src_str2 = src_str; 2405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!src_str || *src_str == '\0') 2415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner src_str2 = ":0"; 2425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parse_host_port(saddr, src_str2) < 0) 2445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 2455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(str); 2475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return(0); 2485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerfail: 2505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(str); 2515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint parse_host_port(struct sockaddr_in *saddr, const char *str) 2555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[512]; 2575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct hostent *he; 2585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p, *r; 2595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int port; 2605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = str; 2625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) 2635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr->sin_family = AF_INET; 2655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (buf[0] == '\0') { 2665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr->sin_addr.s_addr = 0; 2675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (qemu_isdigit(buf[0])) { 2695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!inet_aton(buf, &saddr->sin_addr)) 2705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 2725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((he = gethostbyname(buf)) == NULL) 2735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return - 1; 2745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr->sin_addr = *(struct in_addr *)he->h_addr; 2755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 2775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner port = strtol(p, (char **)&r, 0); 2785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (r == p) 2795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 2805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner saddr->sin_port = htons(port); 2815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 2825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if !defined(_WIN32) && 0 2855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int parse_unix_path(struct sockaddr_un *uaddr, const char *str) 2865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 2875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p; 2885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len; 2895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = MIN(108, strlen(str)); 2915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = strchr(str, ','); 2925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (p) 2935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = MIN(len, p - str); 2945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(uaddr, 0, sizeof(*uaddr)); 2965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 2975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uaddr->sun_family = AF_UNIX; 2985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(uaddr->sun_path, str, len); 2995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 3015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 3035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_format_nic_info_str(VLANClientState *vc, uint8_t macaddr[6]) 3055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(vc->info_str, sizeof(vc->info_str), 3075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "model=%s,macaddr=%02x:%02x:%02x:%02x:%02x:%02x", 3085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->model, 3095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[0], macaddr[1], macaddr[2], 3105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[3], macaddr[4], macaddr[5]); 3115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic char *assign_name(VLANClientState *vc1, const char *model) 3145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 3165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[256]; 3175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int id = 0; 3185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vlan = first_vlan; vlan; vlan = vlan->next) { 3205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 3215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vc = vlan->first_client; vc; vc = vc->next) 3235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc != vc1 && strcmp(vc->model, model) == 0) 3245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner id++; 3255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(buf, sizeof(buf), "%s.%d", model, id); 3285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return strdup(buf); 3305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerVLANClientState *qemu_new_vlan_client(VLANState *vlan, 3335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 3345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 3355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCanReceive *can_receive, 3365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetReceive *receive, 3375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetReceiveIOV *receive_iov, 3385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetCleanup *cleanup, 3395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner void *opaque) 3405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc, **pvc; 3425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc = qemu_mallocz(sizeof(VLANClientState)); 3435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->model = strdup(model); 3445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (name) 3455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->name = strdup(name); 3465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 3475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->name = assign_name(vc, model); 3485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->can_receive = can_receive; 3495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->receive = receive; 3505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->receive_iov = receive_iov; 3515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->cleanup = cleanup; 3525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->opaque = opaque; 3535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->vlan = vlan; 3545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->next = NULL; 3565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pvc = &vlan->first_client; 3575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (*pvc != NULL) 3585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pvc = &(*pvc)->next; 3595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *pvc = vc; 3605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vc; 3615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_del_vlan_client(VLANClientState *vc) 3645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState **pvc = &vc->vlan->first_client; 3665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (*pvc != NULL) 3685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (*pvc == vc) { 3695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *pvc = vc->next; 3705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc->cleanup) { 3715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->cleanup(vc); 3725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 3735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(vc->name); 3745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(vc->model); 3755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(vc); 3765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 3775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 3785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pvc = &(*pvc)->next; 3795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerVLANClientState *qemu_find_vlan_client(VLANState *vlan, void *opaque) 3825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState **pvc = &vlan->first_client; 3845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (*pvc != NULL) 3865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((*pvc)->opaque == opaque) 3875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return *pvc; 3885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 3895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pvc = &(*pvc)->next; 3905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 3925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 3935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint qemu_can_send_packet(VLANClientState *sender) 3955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 3965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan = sender->vlan; 3975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 3985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 3995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vc = vlan->first_client; vc != NULL; vc = vc->next) { 4005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc == sender) { 4015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 4025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* no can_receive() handler, they can always receive */ 4055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vc->can_receive || vc->can_receive(vc)) { 4065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 4075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 4105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int 4135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerqemu_deliver_packet(VLANClientState *sender, const uint8_t *buf, int size) 4145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 4165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret = -1; 4175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sender->vlan->delivering = 1; 4195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) { 4215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssize_t len; 4225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc == sender) { 4245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 4255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc->link_down) { 4285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = size; 4295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 4305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = vc->receive(vc, buf, size); 4335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = (ret >= 0) ? ret : len; 4355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sender->vlan->delivering = 0; 4385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 4405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_flush_queued_packets(VLANClientState *vc) 4435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANPacket *packet; 4455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while ((packet = vc->vlan->send_queue) != NULL) { 4475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 4485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->vlan->send_queue = packet->next; 4505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = qemu_deliver_packet(packet->sender, packet->data, packet->size); 4525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == 0 && packet->sent_cb != NULL) { 4535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->next = vc->vlan->send_queue; 4545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->vlan->send_queue = packet; 4555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 4565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (packet->sent_cb) 4595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->sent_cb(packet->sender); 4605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(packet); 4625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void qemu_enqueue_packet(VLANClientState *sender, 4665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const uint8_t *buf, int size, 4675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetPacketSent *sent_cb) 4685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANPacket *packet; 4705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet = qemu_malloc(sizeof(VLANPacket) + size); 4725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->next = sender->vlan->send_queue; 4735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->sender = sender; 4745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->size = size; 4755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->sent_cb = sent_cb; 4765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(packet->data, buf, size); 4775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sender->vlan->send_queue = packet; 4785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 4795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerssize_t qemu_send_packet_async(VLANClientState *sender, 4815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const uint8_t *buf, int size, 4825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetPacketSent *sent_cb) 4835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 4845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 4855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sender->link_down) { 4875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 4885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_NET 4915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("vlan %d send:\n", sender->vlan->id); 4925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hex_dump(stdout, buf, size); 4935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 4945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 4955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sender->vlan->delivering) { 4965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_enqueue_packet(sender, buf, size, NULL); 4975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 4985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 4995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = qemu_deliver_packet(sender, buf, size); 5015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == 0 && sent_cb != NULL) { 5025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_enqueue_packet(sender, buf, size, sent_cb); 5035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 5045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_flush_queued_packets(sender); 5075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 5095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size) 5125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_send_packet_async(vc, buf, size, NULL); 5145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t vc_sendv_compat(VLANClientState *vc, const struct iovec *iov, 5175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int iovcnt) 5185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buffer[4096]; 5205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t offset = 0; 5215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 5225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < iovcnt; i++) { 5245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t len; 5255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = MIN(sizeof(buffer) - offset, iov[i].iov_len); 5275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(buffer + offset, iov[i].iov_base, len); 5285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner offset += len; 5295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vc->receive(vc, buffer, offset); 5325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t calc_iov_length(const struct iovec *iov, int iovcnt) 5355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t offset = 0; 5375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 5385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < iovcnt; i++) 5405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner offset += iov[i].iov_len; 5415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return offset; 5425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int qemu_deliver_packet_iov(VLANClientState *sender, 5455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const struct iovec *iov, int iovcnt) 5465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 5485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret = -1; 5495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sender->vlan->delivering = 1; 5515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vc = sender->vlan->first_client; vc != NULL; vc = vc->next) { 5535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssize_t len; 5545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc == sender) { 5565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc->link_down) { 5605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = calc_iov_length(iov, iovcnt); 5615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 5625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc->receive_iov) { 5655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = vc->receive_iov(vc, iov, iovcnt); 5665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 5675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = vc_sendv_compat(vc, iov, iovcnt); 5685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = (ret >= 0) ? ret : len; 5715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 5725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sender->vlan->delivering = 0; 5745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 5765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 5775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t qemu_enqueue_packet_iov(VLANClientState *sender, 5795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const struct iovec *iov, int iovcnt, 5805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetPacketSent *sent_cb) 5815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 5825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANPacket *packet; 5835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t max_len = 0; 5845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 5855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner max_len = calc_iov_length(iov, iovcnt); 5875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet = qemu_malloc(sizeof(VLANPacket) + max_len); 5895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->next = sender->vlan->send_queue; 5905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->sender = sender; 5915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->sent_cb = sent_cb; 5925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->size = 0; 5935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < iovcnt; i++) { 5955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size_t len = iov[i].iov_len; 5965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 5975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(packet->data + packet->size, iov[i].iov_base, len); 5985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner packet->size += len; 5995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sender->vlan->send_queue = packet; 6025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return packet->size; 6045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerssize_t qemu_sendv_packet_async(VLANClientState *sender, 6075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const struct iovec *iov, int iovcnt, 6085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetPacketSent *sent_cb) 6095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ret; 6115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sender->link_down) { 6135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return calc_iov_length(iov, iovcnt); 6145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (sender->vlan->delivering) { 6175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_enqueue_packet_iov(sender, iov, iovcnt, NULL); 6185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = qemu_deliver_packet_iov(sender, iov, iovcnt); 6215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret == 0 && sent_cb != NULL) { 6225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_enqueue_packet_iov(sender, iov, iovcnt, sent_cb); 6235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 6245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_flush_queued_packets(sender); 6275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 6295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerssize_t 6325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerqemu_sendv_packet(VLANClientState *vc, const struct iovec *iov, int iovcnt) 6335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_sendv_packet_async(vc, iov, iovcnt, NULL); 6355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void config_error(Monitor *mon, const char *fmt, ...) 6385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner va_list ap; 6405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner va_start(ap, fmt); 6425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (mon) { 6435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_vprintf(mon, fmt, ap); 6445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 6455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: "); 6465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vfprintf(stderr, fmt, ap); 6475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 6485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 6495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner va_end(ap); 6505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_SLIRP) 6535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* slirp network adapter */ 6555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct slirp_config_str { 6575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct slirp_config_str *next; 6585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *str; 6595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 6605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int slirp_inited; 6625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic struct slirp_config_str *slirp_redirs; 6635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 6645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic const char *slirp_smb_export; 6655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic VLANClientState *slirp_vc; 6675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 6695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_smb(const char *exported_dir); 6705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_redirection(Monitor *mon, const char *redir_str); 6725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_can_output(void) 6745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return !slirp_vc || qemu_can_send_packet(slirp_vc); 6765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid slirp_output(const uint8_t *pkt, int pkt_len) 6795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_SLIRP 6815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("slirp output:\n"); 6825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hex_dump(stdout, pkt, pkt_len); 6835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 6845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!slirp_vc) 6855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 6865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_send_packet(slirp_vc, pkt, pkt_len); 6875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint slirp_is_inited(void) 6905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return slirp_inited; 6925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 6935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 6945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t slirp_receive(VLANClientState *vc, const uint8_t *buf, size_t size) 6955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 6965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef DEBUG_SLIRP 6975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner printf("slirp input:\n"); 6985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hex_dump(stdout, buf, size); 6995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 7005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_input(buf, size); 7015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 7025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int slirp_in_use; 7055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_slirp_cleanup(VLANClientState *vc) 7075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_in_use = 0; 7095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_slirp_init(VLANState *vlan, const char *model, const char *name, 7125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int restricted, const char *ip) 7135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_in_use) { 7155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* slirp only supports a single instance so far */ 7165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 7175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!slirp_inited) { 7195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_inited = 1; 7205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_init(restricted, ip); 7215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (slirp_redirs) { 7235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct slirp_config_str *config = slirp_redirs; 7245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_redirection(NULL, config->str); 7265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_redirs = config->next; 7275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(config); 7285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 7305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_smb_export) { 7315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_smb(slirp_smb_export); 7325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 7345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 7355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_vc = qemu_new_vlan_client(vlan, model, name, NULL, slirp_receive, 7375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL, net_slirp_cleanup, NULL); 7385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_vc->info_str[0] = '\0'; 7395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_in_use = 1; 7405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 7415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_slirp_redir_print(void *opaque, int is_udp, 7445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct in_addr *laddr, u_int lport, 7455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct in_addr *faddr, u_int fport) 7465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner Monitor *mon = (Monitor *)opaque; 7485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t h_addr; 7495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t g_addr; 7505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[16]; 7515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner h_addr = ntohl(faddr->s_addr); 7535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner g_addr = ntohl(laddr->s_addr); 7545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " %s |", is_udp ? "udp" : "tcp" ); 7565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(buf, 15, "%d.%d.%d.%d", (h_addr >> 24) & 0xff, 7575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (h_addr >> 16) & 0xff, 7585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (h_addr >> 8) & 0xff, 7595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (h_addr) & 0xff); 7605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " %15s |", buf); 7615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " %5d |", fport); 7625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(buf, 15, "%d.%d.%d.%d", (g_addr >> 24) & 0xff, 7645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (g_addr >> 16) & 0xff, 7655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (g_addr >> 8) & 0xff, 7665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (g_addr) & 0xff); 7675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " %15s |", buf); 7685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " %5d\n", lport); 7695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_slirp_redir_list(Monitor *mon) 7735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!mon) 7755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " Prot | Host Addr | HPort | Guest Addr | GPort\n"); 7785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " | | | | \n"); 7795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_redir_loop(net_slirp_redir_print, mon); 7805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 7815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_slirp_redir_rm(Monitor *mon, const char *port_str) 7835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 7845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int host_port; 7855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[256] = ""; 7865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p = port_str; 7875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int is_udp = 0; 7885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int n; 7895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!mon) 7915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 7925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!port_str || !port_str[0]) 7945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 7955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner get_str_sep(buf, sizeof(buf), &p, ':'); 7975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 7985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(buf, "tcp") || buf[0] == '\0') { 7995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is_udp = 0; 8005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (!strcmp(buf, "udp")) { 8015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is_udp = 1; 8025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 8035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner host_port = atoi(p); 8075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner n = slirp_redir_rm(is_udp, host_port); 8095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "removed %d redirections to %s port %d\n", n, 8115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is_udp ? "udp" : "tcp", host_port); 8125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail_syntax: 8155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "invalid format\n"); 8165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_redirection(Monitor *mon, const char *redir_str) 8195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct in_addr guest_addr; 8215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int host_port, guest_port; 8225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p; 8235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[256], *r; 8245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int is_udp; 8255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = redir_str; 8275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { 8285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(buf, "tcp") || buf[0] == '\0') { 8315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is_udp = 0; 8325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (!strcmp(buf, "udp")) { 8335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner is_udp = 1; 8345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 8355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { 8395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner host_port = strtol(buf, &r, 0); 8425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (r == buf) { 8435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) { 8475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (buf[0] == '\0') { 8505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(buf, sizeof(buf), "10.0.2.15"); 8515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!inet_aton(buf, &guest_addr)) { 8535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner guest_port = strtol(p, &r, 0); 8575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (r == p) { 8585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail_syntax; 8595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_redir(is_udp, host_port, guest_addr, guest_port) < 0) { 8625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "could not set up redirection '%s'\n", redir_str); 8635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fail_syntax: 8675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid redirection format '%s'\n", redir_str); 8685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_slirp_redir(Monitor *mon, const char *redir_str, const char *redir_opt2) 8715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 8725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct slirp_config_str *config; 8735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!slirp_inited) { 8755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (mon) { 8765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "user mode network stack not in use\n"); 8775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 8785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config = qemu_malloc(sizeof(*config)); 8795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config->str = redir_str; 8805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config->next = slirp_redirs; 8815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_redirs = config; 8825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(redir_str, "remove")) { 8875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner net_slirp_redir_rm(mon, redir_opt2); 8885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(redir_str, "list")) { 8925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner net_slirp_redir_list(mon); 8935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 8945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 8955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_redirection(mon, redir_str); 8975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 8985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 8995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifndef _WIN32 9005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic char smb_dir[1024]; 9025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void erase_dir(char *dir_name) 9045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DIR *d; 9065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct dirent *de; 9075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char filename[1024]; 9085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* erase all the files in the directory */ 9105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((d = opendir(dir_name)) != NULL) { 9115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(;;) { 9125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner de = readdir(d); 9135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!de) 9145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 9155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(de->d_name, ".") != 0 && 9165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strcmp(de->d_name, "..") != 0) { 9175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(filename, sizeof(filename), "%s/%s", 9185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner smb_dir, de->d_name); 9195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (unlink(filename) != 0) /* is it a directory? */ 9205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner erase_dir(filename); 9215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closedir(d); 9245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner rmdir(dir_name); 9255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* automatic user mode samba server configuration */ 9295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void smb_exit(void) 9305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner erase_dir(smb_dir); 9325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void slirp_smb(const char *exported_dir) 9355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char smb_conf[1024]; 9375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char smb_cmdline[1024]; 9385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner FILE *f; 9395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* XXX: better tmp dir construction */ 9415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(smb_dir, sizeof(smb_dir), "/tmp/qemu-smb.%ld", (long)getpid()); 9425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (mkdir(smb_dir, 0700) < 0) { 9435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: could not create samba server dir '%s'\n", smb_dir); 9445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 9455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(smb_conf, sizeof(smb_conf), "%s/%s", smb_dir, "smb.conf"); 9475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner f = fopen(smb_conf, "w"); 9495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!f) { 9505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: could not create samba server configuration file '%s'\n", smb_conf); 9515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 9525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(f, 9545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "[global]\n" 9555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "private dir=%s\n" 9565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "smb ports=0\n" 9575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "socket address=127.0.0.1\n" 9585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "pid directory=%s\n" 9595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "lock directory=%s\n" 9605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "log file=%s/log.smbd\n" 9615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "smb passwd file=%s/smbpasswd\n" 9625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "security = share\n" 9635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "[qemu]\n" 9645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "path=%s\n" 9655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "read only=no\n" 9665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "guest ok=yes\n", 9675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner smb_dir, 9685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner smb_dir, 9695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner smb_dir, 9705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner smb_dir, 9715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner smb_dir, 9725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exported_dir 9735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ); 9745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fclose(f); 9755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner atexit(smb_exit); 9765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(smb_cmdline, sizeof(smb_cmdline), "%s -s %s", 9785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner SMBD_COMMAND, smb_conf); 9795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_add_exec(0, smb_cmdline, 4, 139); 9815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* automatic user mode samba server configuration */ 9845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_slirp_smb(const char *exported_dir) 9855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 9865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_smb_export) { 9875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "-smb given twice\n"); 9885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(1); 9895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_smb_export = exported_dir; 9915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (slirp_inited) { 9925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_smb(exported_dir); 9935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 9945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 9955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* !defined(_WIN32) */ 9975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 9985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_info_slirp(Monitor *mon) 9995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_stats(); 10015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct VMChannel { 10045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner CharDriverState *hd; 10055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int port; 10065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 10075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int vmchannel_can_read(void *opaque) 10095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct VMChannel *vmc = (struct VMChannel*)opaque; 10115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return slirp_socket_can_recv(4, vmc->port); 10125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vmchannel_read(void *opaque, const uint8_t *buf, int size) 10155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct VMChannel *vmc = (struct VMChannel*)opaque; 10175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_socket_recv(4, vmc->port, buf, size); 10185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* CONFIG_SLIRP */ 10215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if !defined(_WIN32) 10235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct TAPState { 10255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 10265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 10275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char down_script[1024]; 10285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char down_script_arg[128]; 10295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buf[4096]; 10305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} TAPState; 10315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int launch_script(const char *setup_script, const char *ifname, int fd); 10335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t tap_receive_iov(VLANClientState *vc, const struct iovec *iov, 10355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int iovcnt) 10365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s = vc->opaque; 10385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssize_t len; 10395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 10415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = writev(s->fd, iov, iovcnt); 10425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (len == -1 && (errno == EINTR || errno == EAGAIN)); 10435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len; 10455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t tap_receive(VLANClientState *vc, const uint8_t *buf, size_t size) 10485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s = vc->opaque; 10505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssize_t len; 10515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 10535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = write(s->fd, buf, size); 10545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (len == -1 && (errno == EINTR || errno == EAGAIN)); 10555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return len; 10575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_can_send(void *opaque) 10605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s = opaque; 10625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return qemu_can_send_packet(s->vc); 10645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef __sun__ 10675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) 10685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct strbuf sbuf; 10705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int f = 0; 10715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbuf.maxlen = maxlen; 10735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sbuf.buf = (char *)buf; 10745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return getmsg(tapfd, NULL, &sbuf, &f) >= 0 ? sbuf.len : -1; 10765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 10785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t tap_read_packet(int tapfd, uint8_t *buf, int maxlen) 10795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return read(tapfd, buf, maxlen); 10815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 10835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_send(void *opaque); 10855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_send_completed(VLANClientState *vc) 10875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s = vc->opaque; 10895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, tap_can_send, tap_send, NULL, s); 10915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 10925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_send(void *opaque) 10945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 10955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s = opaque; 10965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size; 10975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 10985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 10995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = tap_read_packet(s->fd, s->buf, sizeof(s->buf)); 11005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size <= 0) { 11015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 11025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = qemu_send_packet_async(s->vc, s->buf, size, tap_send_completed); 11055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size == 0) { 11065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, NULL, NULL, NULL, NULL); 11075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (size > 0); 11095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void tap_cleanup(VLANClientState *vc) 11125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s = vc->opaque; 11145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->down_script[0]) 11165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner launch_script(s->down_script, s->down_script_arg, s->fd); 11175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 11195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 11205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 11215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* fd support */ 11245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic TAPState *net_tap_fd_init(VLANState *vlan, 11265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 11275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 11285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd) 11295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s; 11315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(TAPState)); 11335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 11345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->vc = qemu_new_vlan_client(vlan, model, name, NULL, tap_receive, 11355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner tap_receive_iov, tap_cleanup, s); 11365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler2(s->fd, tap_can_send, tap_send, NULL, s); 11375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), "fd=%d", fd); 11385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s; 11395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11412c538c86c15d597cc875dc926e4e39285c5625dfDavid 'Digit' Turner#if defined (CONFIG_BSD) || defined (__FreeBSD_kernel__) 11425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_open(char *ifname, int ifname_size) 11435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 11455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *dev; 11465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct stat s; 11475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(fd = open("/dev/tap", O_RDWR)); 11495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) { 11505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "warning: could not open /dev/tap: no virtual network emulation\n"); 11515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 11525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fstat(fd, &s); 11555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dev = devname(s.st_rdev, S_IFCHR); 11565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifname, ifname_size, dev); 11575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fcntl(fd, F_SETFL, O_NONBLOCK); 11595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return fd; 11605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 11615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined(__sun__) 11625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define TUNNEWPPA (('T'<<16) | 0x0001) 11635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 11645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Allocate TAP device, returns opened fd. 11655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Stores dev name in the first arg(must be large enough). 11665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 11675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_alloc(char *dev, size_t dev_size) 11685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 11695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int tap_fd, if_fd, ppa = -1; 11705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static int ip_fd = 0; 11715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *ptr; 11725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static int arp_fd = 0; 11745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int ip_muxid, arp_muxid; 11755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct strioctl strioc_if, strioc_ppa; 11765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int link_type = I_PLINK;; 11775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct lifreq ifr; 11785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char actual_name[32] = ""; 11795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&ifr, 0x0, sizeof(ifr)); 11815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if( *dev ){ 11835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ptr = dev; 11845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while( *ptr && !qemu_isdigit((int)*ptr) ) ptr++; 11855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ppa = atoi(ptr); 11865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Check if IP device was opened */ 11895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if( ip_fd ) 11905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(ip_fd); 11915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(ip_fd = open("/dev/udp", O_RDWR, 0)); 11935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ip_fd < 0) { 11945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog(LOG_ERR, "Can't open /dev/ip (actually /dev/udp)"); 11955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 11965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 11975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 11985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(tap_fd = open("/dev/tap", O_RDWR, 0)); 11995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (tap_fd < 0) { 12005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog(LOG_ERR, "Can't open /dev/tap"); 12015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 12025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Assign a new PPA and get its unit number. */ 12055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_ppa.ic_cmd = TUNNEWPPA; 12065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_ppa.ic_timout = 0; 12075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_ppa.ic_len = sizeof(ppa); 12085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_ppa.ic_dp = (char *)&ppa; 12095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((ppa = ioctl (tap_fd, I_STR, &strioc_ppa)) < 0) 12105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't assign new interface"); 12115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(if_fd = open("/dev/tap", O_RDWR, 0)); 12135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (if_fd < 0) { 12145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog(LOG_ERR, "Can't open /dev/tap (2)"); 12155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 12165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(ioctl(if_fd, I_PUSH, "ip") < 0){ 12185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog(LOG_ERR, "Can't push IP module"); 12195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 12205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) < 0) 12235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog(LOG_ERR, "Can't get flags\n"); 12245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf (actual_name, 32, "tap%d", ppa); 12265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name); 12275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifr.lifr_ppa = ppa; 12295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Assign ppa according to the unit number returned by tun device */ 12305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl (if_fd, SIOCSLIFNAME, &ifr) < 0) 12325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't set PPA %d", ppa); 12335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(if_fd, SIOCGLIFFLAGS, &ifr) <0) 12345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't get flags\n"); 12355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Push arp module to if_fd */ 12365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl (if_fd, I_PUSH, "arp") < 0) 12375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't push ARP module (2)"); 12385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Push arp module to ip_fd */ 12405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl (ip_fd, I_POP, NULL) < 0) 12415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "I_POP failed\n"); 12425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl (ip_fd, I_PUSH, "arp") < 0) 12435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't push ARP module (3)\n"); 12445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Open arp_fd */ 12455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(arp_fd = open ("/dev/tap", O_RDWR, 0)); 12465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (arp_fd < 0) 12475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't open %s\n", "/dev/tap"); 12485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Set ifname to arp */ 12505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_if.ic_cmd = SIOCSLIFNAME; 12515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_if.ic_timout = 0; 12525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_if.ic_len = sizeof(ifr); 12535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strioc_if.ic_dp = (char *)𝔦 12545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl(arp_fd, I_STR, &strioc_if) < 0){ 12555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't set ifname to arp\n"); 12565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if((ip_muxid = ioctl(ip_fd, I_LINK, if_fd)) < 0){ 12595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog(LOG_ERR, "Can't link TAP device to IP"); 12605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 12615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((arp_muxid = ioctl (ip_fd, link_type, arp_fd)) < 0) 12645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't link TAP device to ARP"); 12655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close (if_fd); 12675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&ifr, 0x0, sizeof(ifr)); 12695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifr.lifr_name, sizeof(ifr.lifr_name), actual_name); 12705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifr.lifr_ip_muxid = ip_muxid; 12715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifr.lifr_arp_muxid = arp_muxid; 12725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ioctl (ip_fd, SIOCSLIFMUXID, &ifr) < 0) 12745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner { 12755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl (ip_fd, I_PUNLINK , arp_muxid); 12765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ioctl (ip_fd, I_PUNLINK, ip_muxid); 12775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner syslog (LOG_ERR, "Can't set multiplexor id"); 12785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(dev, dev_size, "tap%d", ppa); 12815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return tap_fd; 12825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 12835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 12845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_open(char *ifname, int ifname_size) 12855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 12865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char dev[10]=""; 12875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 12885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if( (fd = tap_alloc(dev, sizeof(dev))) < 0 ){ 12895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Cannot allocate TAP device\n"); 12905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 12915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 12925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifname, ifname_size, dev); 12935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fcntl(fd, F_SETFL, O_NONBLOCK); 12945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return fd; 12955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 12965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined (_AIX) 12975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_open(char *ifname, int ifname_size) 12985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 12995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf (stderr, "no tap on AIX\n"); 13005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 13015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 13025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 13035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int tap_open(char *ifname, int ifname_size) 13045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 13055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ifreq ifr; 13065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, ret; 13075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(fd = open("/dev/net/tun", O_RDWR)); 13095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) { 13105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "warning: could not open /dev/net/tun: no virtual network emulation\n"); 13115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 13125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memset(&ifr, 0, sizeof(ifr)); 13145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifr.ifr_flags = IFF_TAP | IFF_NO_PI; 13155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ifname[0] != '\0') 13165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); 13175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 13185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); 13195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = ioctl(fd, TUNSETIFF, (void *) &ifr); 13205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret != 0) { 13215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); 13225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd); 13235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 13245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifname, ifname_size, ifr.ifr_name); 13265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fcntl(fd, F_SETFL, O_NONBLOCK); 13275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return fd; 13285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 13295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 13305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int launch_script(const char *setup_script, const char *ifname, int fd) 13325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 13335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sigset_t oldmask, mask; 13345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int pid, status; 13355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *args[3]; 13365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char **parg; 13375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sigemptyset(&mask); 13395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sigaddset(&mask, SIGCHLD); 13405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sigprocmask(SIG_BLOCK, &mask, &oldmask); 13415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* try to launch network script */ 13435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pid = fork(); 13445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (pid == 0) { 13455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int open_max = sysconf(_SC_OPEN_MAX), i; 13465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < open_max; i++) { 13485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (i != STDIN_FILENO && 13495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner i != STDOUT_FILENO && 13505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner i != STDERR_FILENO && 13515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner i != fd) { 13525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(i); 13535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner parg = args; 13565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *parg++ = (char *)setup_script; 13575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *parg++ = (char *)ifname; 13585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *parg++ = NULL; 13595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner execv(setup_script, args); 13604a2c9dd7630ce51a660e1aa14e10bc6fbc4621c4Iliyan Malchev exit(1); 13615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (pid > 0) { 13625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (waitpid(pid, &status, 0) != pid) { 13635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* loop */ 13645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sigprocmask(SIG_SETMASK, &oldmask, NULL); 13665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 13685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 13695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "%s: could not launch network script\n", setup_script); 13725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 13735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 13745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_tap_init(VLANState *vlan, const char *model, 13765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, const char *ifname1, 13775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *setup_script, const char *down_script) 13785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 13795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TAPState *s; 13805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 13815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char ifname[128]; 13825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ifname1 != NULL) 13845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(ifname, sizeof(ifname), ifname1); 13855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 13865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifname[0] = '\0'; 13875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner TFR(fd = tap_open(ifname, sizeof(ifname))); 13885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) 13895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 13905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 13915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!setup_script || !strcmp(setup_script, "no")) 13925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner setup_script = ""; 13935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (setup_script[0] != '\0') { 13945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (launch_script(setup_script, ifname, fd)) 13955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 13965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 13975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = net_tap_fd_init(vlan, model, name, fd); 13985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), 13995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "ifname=%s,script=%s,downscript=%s", 14005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifname, setup_script, down_script); 14015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (down_script && strcmp(down_script, "no")) { 14025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->down_script, sizeof(s->down_script), "%s", down_script); 14035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->down_script_arg, sizeof(s->down_script_arg), "%s", ifname); 14045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 14065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif /* !_WIN32 */ 14095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if defined(CONFIG_VDE) 14115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct VDEState { 14125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 14135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VDECONN *vde; 14145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} VDEState; 14155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vde_to_qemu(void *opaque) 14175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VDEState *s = opaque; 14195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buf[4096]; 14205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size; 14215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = vde_recv(s->vde, (char *)buf, sizeof(buf), 0); 14235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size > 0) { 14245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_send_packet(s->vc, buf, size); 14255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t vde_receive(VLANClientState *vc, const uint8_t *buf, size_t size) 14295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VDEState *s = vc->opaque; 14315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ssize_t ret; 14325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner do { 14345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = vde_send(s->vde, (const char *)buf, size, 0); 14355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } while (ret < 0 && errno == EINTR); 14365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 14385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void vde_cleanup(VLANClientState *vc) 14415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VDEState *s = vc->opaque; 14435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(vde_datafd(s->vde), NULL, NULL, NULL); 14445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_close(s->vde); 14455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 14465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_vde_init(VLANState *vlan, const char *model, 14495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, const char *sock, 14505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int port, const char *group, int mode) 14515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VDEState *s; 14535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *init_group = strlen(group) ? (char *)group : NULL; 14545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *init_sock = strlen(sock) ? (char *)sock : NULL; 14555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct vde_open_args args = { 14575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .port = port, 14585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .group = init_group, 14595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner .mode = mode, 14605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 14615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(VDEState)); 14635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->vde = vde_open(init_sock, (char *)"QEMU", &args); 14645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s->vde){ 14655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free(s); 14665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 14675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 14685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->vc = qemu_new_vlan_client(vlan, model, name, NULL, vde_receive, 14695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL, vde_cleanup, s); 14705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(vde_datafd(s->vde), vde_to_qemu, NULL, s); 14715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), "sock=%s,fd=%d", 14725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner sock, vde_datafd(s->vde)); 14735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 14745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 14755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 14765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* network connection */ 14785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct NetSocketState { 14795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 14805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 14815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int state; /* 0 = getting length, 1 = getting data */ 14825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned int index; 14835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned int packet_len; 14845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buf[4096]; 14855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in dgram_dst; /* contains inet host and port destination iff connectionless (SOCK_DGRAM) */ 14865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} NetSocketState; 14875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct NetSocketListenState { 14895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 14905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *model; 14915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *name; 14925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 14935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} NetSocketListenState; 14945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 14955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* XXX: we consider we can send the whole packet without blocking */ 14965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t net_socket_receive(VLANClientState *vc, const uint8_t *buf, size_t size) 14975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 14985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s = vc->opaque; 14995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t len; 15005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = htonl(size); 15015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner send_all(s->fd, (const uint8_t *)&len, sizeof(len)); 15035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return send_all(s->fd, buf, size); 15045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t net_socket_receive_dgram(VLANClientState *vc, const uint8_t *buf, size_t size) 15075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s = vc->opaque; 15095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return sendto(s->fd, (const void *)buf, size, 0, 15115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (struct sockaddr *)&s->dgram_dst, sizeof(s->dgram_dst)); 15125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_socket_send(void *opaque) 15155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s = opaque; 15175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size, err; 15185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner unsigned l; 15195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t buf1[4096]; 15205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const uint8_t *buf; 15215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = recv(s->fd, (void *)buf1, sizeof(buf1), 0); 15235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size < 0) { 15245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner err = socket_error(); 15255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (err != EWOULDBLOCK) 15265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto eoc; 15275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (size == 0) { 15285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* end of connection */ 15295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner eoc: 15305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 15315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(s->fd); 15325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 15335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf = buf1; 15355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (size > 0) { 15365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* reassemble a packet from the network */ 15375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(s->state) { 15385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 0: 15395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l = 4 - s->index; 15405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (l > size) 15415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l = size; 15425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(s->buf + s->index, buf, l); 15435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += l; 15445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size -= l; 15455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->index += l; 15465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->index == 4) { 15475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* got length */ 15485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->packet_len = ntohl(*(uint32_t *)s->buf); 15495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->index = 0; 15505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = 1; 15515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case 1: 15545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l = s->packet_len - s->index; 15555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (l > size) 15565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner l = size; 15575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->index + l <= sizeof(s->buf)) { 15585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner memcpy(s->buf + s->index, buf, l); 15595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 15605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "serious error: oversized packet received," 15615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "connection terminated.\n"); 15625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = 0; 15635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto eoc; 15645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->index += l; 15675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner buf += l; 15685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size -= l; 15695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->index >= s->packet_len) { 15705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_send_packet(s->vc, s->buf, s->packet_len); 15715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->index = 0; 15725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->state = 0; 15735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 15755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_socket_send_dgram(void *opaque) 15805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s = opaque; 15825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int size; 15835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner size = recv(s->fd, (void *)s->buf, sizeof(s->buf), 0); 15855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size < 0) 15865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 15875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (size == 0) { 15885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* end of connection */ 15895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 15905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 15915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 15925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_send_packet(s->vc, s->buf, size); 15935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 15945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 15955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_socket_mcast_create(struct sockaddr_in *mcastaddr) 15965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 15975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct ip_mreq imr; 15985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 15995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int val, ret; 16005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!IN_MULTICAST(ntohl(mcastaddr->sin_addr.s_addr))) { 16015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: error: specified mcastaddr \"%s\" (0x%08x) does not contain a multicast address\n", 16025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_ntoa(mcastaddr->sin_addr), 16035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (int)ntohl(mcastaddr->sin_addr.s_addr)); 16045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 16055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = socket(PF_INET, SOCK_DGRAM, 0); 16085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) { 16095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("socket(PF_INET, SOCK_DGRAM)"); 16105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 16115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner val = 1; 16145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret=setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, 16155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (const char *)&val, sizeof(val)); 16165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 16175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("setsockopt(SOL_SOCKET, SO_REUSEADDR)"); 16185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 16195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = bind(fd, (struct sockaddr *)mcastaddr, sizeof(*mcastaddr)); 16225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 16235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("bind"); 16245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 16255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Add host to multicast group */ 16285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner imr.imr_multiaddr = mcastaddr->sin_addr; 16295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner imr.imr_interface.s_addr = htonl(INADDR_ANY); 16305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, 16325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (const char *)&imr, sizeof(struct ip_mreq)); 16335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 16345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("setsockopt(IP_ADD_MEMBERSHIP)"); 16355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 16365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Force mcast msgs to loopback (eg. several QEMUs in same host */ 16395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner val = 1; 16405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret=setsockopt(fd, IPPROTO_IP, IP_MULTICAST_LOOP, 16415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (const char *)&val, sizeof(val)); 16425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 16435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("setsockopt(SOL_IP, IP_MULTICAST_LOOP)"); 16445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto fail; 16455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nonblock(fd); 16485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return fd; 16495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerfail: 16505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd >= 0) 16515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(fd); 16525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 16535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_socket_cleanup(VLANClientState *vc) 16565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s = vc->opaque; 16585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, NULL, NULL); 16595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 16605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 16615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 16625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, 16645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 16655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 16665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, int is_connected) 16675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 16685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in saddr; 16695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int newfd; 16705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t saddr_len; 16715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s; 16725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* fd passed: multicast: "learn" dgram_dst address from bound address and save it 16745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Because this may be "shared" socket from a "master" process, datagrams would be recv() 16755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * by ONLY ONE process: we must "clone" this dgram socket --jjo 16765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 16775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_connected) { 16795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (getsockname(fd, (struct sockaddr *) &saddr, &saddr_len) == 0) { 16805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* must be bound */ 16815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (saddr.sin_addr.s_addr==0) { 16825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: error: init_dgram: fd=%d unbound, cannot setup multicast dst addr\n", 16835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd); 16845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 16855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* clone dgram socket */ 16875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner newfd = net_socket_mcast_create(&saddr); 16885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (newfd < 0) { 16895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* error already reported by net_socket_mcast_create() */ 16905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(fd); 16915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 16925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 16935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* clone newfd to fd, close newfd */ 16945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner dup2(newfd, fd); 16955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(newfd); 16965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 16975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 16985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: error: init_dgram: fd=%d failed getsockname(): %s\n", 16995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd, strerror(errno)); 17005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 17015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(NetSocketState)); 17055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 17065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->vc = qemu_new_vlan_client(vlan, model, name, NULL, net_socket_receive_dgram, 17085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL, net_socket_cleanup, s); 17095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s); 17105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* mcast: save bound address as dst */ 17125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_connected) s->dgram_dst=saddr; 17135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), 17155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "socket: fd=%d (%s mcast=%s:%d)", 17165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd, is_connected? "cloned" : "", 17175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 17185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s; 17195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_socket_connect(void *opaque) 17225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s = opaque; 17245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, net_socket_send, NULL, s); 17255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic NetSocketState *net_socket_fd_init_stream(VLANState *vlan, 17285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 17295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 17305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, int is_connected) 17315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s; 17335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(NetSocketState)); 17345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 17355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->vc = qemu_new_vlan_client(vlan, model, name, NULL, net_socket_receive, 17365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL, net_socket_cleanup, s); 17375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), 17385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "socket: fd=%d", fd); 17395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (is_connected) { 17405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner net_socket_connect(s); 17415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 17425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s); 17435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return s; 17455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic NetSocketState *net_socket_fd_init(VLANState *vlan, 17485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, const char *name, 17495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, int is_connected) 17505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int so_type=-1, optlen=sizeof(so_type); 17525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&so_type, 17545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner (socklen_t *)&optlen)< 0) { 17555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: error: getsockopt(SO_TYPE) for fd=%d failed\n", fd); 17565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 17575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(so_type) { 17595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case SOCK_DGRAM: 17605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return net_socket_fd_init_dgram(vlan, model, name, fd, is_connected); 17615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case SOCK_STREAM: 17625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); 17635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner default: 17645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* who knows ... this could be a eg. a pty, do warn and continue as stream */ 17655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: warning: socket type=%d for fd=%d is not SOCK_DGRAM or SOCK_STREAM\n", so_type, fd); 17665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return net_socket_fd_init_stream(vlan, model, name, fd, is_connected); 17675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return NULL; 17695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_socket_accept(void *opaque) 17725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 17735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketListenState *s = opaque; 17745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s1; 17755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in saddr; 17765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socklen_t len; 17775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 17785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(;;) { 17805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = sizeof(saddr); 17815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = accept(s->fd, (struct sockaddr *)&saddr, &len); 17825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0 && errno != EINTR) { 17835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 17845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (fd >= 0) { 17855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 17865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s1 = net_socket_fd_init(s->vlan, s->model, s->name, fd, 1); 17895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s1) { 17905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(fd); 17915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 17925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s1->vc->info_str, sizeof(s1->vc->info_str), 17935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "socket: connection from %s:%d", 17945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 17955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 17965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 17975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 17985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_socket_listen_init(VLANState *vlan, 17995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 18005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 18015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *host_str) 18025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketListenState *s; 18045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, val, ret; 18055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in saddr; 18065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parse_host_port(&saddr, host_str) < 0) 18085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_mallocz(sizeof(NetSocketListenState)); 18115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = socket(PF_INET, SOCK_STREAM, 0); 18135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) { 18145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("socket"); 18155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nonblock(fd); 18185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* allow fast reuse */ 18205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner val = 1; 18215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (const char *)&val, sizeof(val)); 18225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); 18245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 18255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("bind"); 18265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = listen(fd, 0); 18295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 18305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("listen"); 18315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->vlan = vlan; 18345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->model = strdup(model); 18355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->name = name ? strdup(name) : NULL; 18365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = fd; 18375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_set_fd_handler(fd, net_socket_accept, NULL, s); 18385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 18395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_socket_connect_init(VLANState *vlan, 18425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 18435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 18445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *host_str) 18455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s; 18475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd, connected, ret, err; 18485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in saddr; 18495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parse_host_port(&saddr, host_str) < 0) 18515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = socket(PF_INET, SOCK_STREAM, 0); 18545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) { 18555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("socket"); 18565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner socket_set_nonblock(fd); 18595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner connected = 0; 18615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(;;) { 18625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); 18635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 18645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner err = socket_error(); 18655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (err == EINTR || err == EWOULDBLOCK) { 18665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (err == EINPROGRESS) { 18675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 18695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (err == WSAEALREADY) { 18705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 18725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 18735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner perror("connect"); 18745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner closesocket(fd); 18755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 18785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner connected = 1; 18795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 18805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 18825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = net_socket_fd_init(vlan, model, name, fd, connected); 18835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s) 18845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 18855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), 18865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "socket: connect to %s:%d", 18875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 18885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 18895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 18905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 18915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_socket_mcast_init(VLANState *vlan, 18925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *model, 18935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, 18945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *host_str) 18955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 18965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NetSocketState *s; 18975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 18985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct sockaddr_in saddr; 18995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parse_host_port(&saddr, host_str) < 0) 19015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 19025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = net_socket_mcast_create(&saddr); 19055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (fd < 0) 19065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 19075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = net_socket_fd_init(vlan, model, name, fd, 0); 19095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!s) 19105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 19115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->dgram_dst = saddr; 19135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->vc->info_str, sizeof(s->vc->info_str), 19155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "socket: mcast=%s:%d", 19165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); 19175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 19185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnertypedef struct DumpState { 19225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *pcap_vc; 19235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 19245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int pcap_caplen; 19255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} DumpState; 19265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#define PCAP_MAGIC 0xa1b2c3d4 19285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct pcap_file_hdr { 19305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t magic; 19315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t version_major; 19325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint16_t version_minor; 19335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int32_t thiszone; 19345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t sigfigs; 19355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t snaplen; 19365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t linktype; 19375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 19385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstruct pcap_sf_pkthdr { 19405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct { 19415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int32_t tv_sec; 19425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int32_t tv_usec; 19435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } ts; 19445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t caplen; 19455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint32_t len; 19465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner}; 19475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic ssize_t dump_receive(VLANClientState *vc, const uint8_t *buf, size_t size) 19495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DumpState *s = vc->opaque; 19515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct pcap_sf_pkthdr hdr; 19525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int64_t ts; 19535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int caplen; 19545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* Early return in case of previous error. */ 19565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd < 0) { 19575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 19585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1960a7fb77d6eca56e61e94f62e7deb4120b60b1e919David 'Digit' Turner ts = muldiv64(qemu_get_clock(vm_clock), 1000000, get_ticks_per_sec()); 19615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner caplen = size > s->pcap_caplen ? s->pcap_caplen : size; 19625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.ts.tv_sec = ts / 1000000; 19645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.ts.tv_usec = ts % 1000000; 19655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.caplen = caplen; 19665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.len = size; 19675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (write(s->fd, &hdr, sizeof(hdr)) != sizeof(hdr) || 19685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner write(s->fd, buf, caplen) != caplen) { 19695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_log("-net dump write error - stop dump\n"); 19705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 19715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = -1; 19725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return size; 19755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic void net_dump_cleanup(VLANClientState *vc) 19785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DumpState *s = vc->opaque; 19805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 19825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 19835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 19845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_dump_init(Monitor *mon, VLANState *vlan, const char *device, 19865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *name, const char *filename, int len) 19875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 19885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct pcap_file_hdr hdr; 19895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner DumpState *s; 19905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s = qemu_malloc(sizeof(DumpState)); 19925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->fd = open(filename, O_CREAT | O_WRONLY, 0644); 19945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (s->fd < 0) { 19955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "-net dump: can't open %s\n", filename); 19965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 19975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 19985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 19995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->pcap_caplen = len; 20005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.magic = PCAP_MAGIC; 20025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.version_major = 2; 20035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.version_minor = 4; 20045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.thiszone = 0; 20055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.sigfigs = 0; 20065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.snaplen = s->pcap_caplen; 20075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner hdr.linktype = 1; 20085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (write(s->fd, &hdr, sizeof(hdr)) < sizeof(hdr)) { 20105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "-net dump write error: %s\n", strerror(errno)); 20115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner close(s->fd); 20125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(s); 20135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 20145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner s->pcap_vc = qemu_new_vlan_client(vlan, device, name, NULL, dump_receive, NULL, 20175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner net_dump_cleanup, s); 20185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(s->pcap_vc->info_str, sizeof(s->pcap_vc->info_str), 20195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "dump to %s (len=%d)", filename, len); 20205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 20215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* find or alloc a new VLAN */ 20245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' TurnerVLANState *qemu_find_vlan(int id) 20255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState **pvlan, *vlan; 20275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { 20285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vlan->id == id) 20295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vlan; 20305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan = qemu_mallocz(sizeof(VLANState)); 20325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->id = id; 20335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->next = NULL; 20345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pvlan = &first_vlan; 20355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (*pvlan != NULL) 20365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pvlan = &(*pvlan)->next; 20375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *pvlan = vlan; 20385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return vlan; 20395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int nic_get_free_idx(void) 20425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int index; 20445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (index = 0; index < MAX_NICS; index++) 20465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!nd_table[index].used) 20475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return index; 20485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 20495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_check_nic_model(NICInfo *nd, const char *model) 20525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *models[2]; 20545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner models[0] = model; 20565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner models[1] = NULL; 20575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_check_nic_model_list(nd, models, model); 20595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid qemu_check_nic_model_list(NICInfo *nd, const char * const *models, 20625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *default_model) 20635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i, exit_status = 0; 20655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!nd->model) 20675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->model = strdup(default_model); 20685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(nd->model, "?") != 0) { 20705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0 ; models[i]; i++) 20715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(nd->model, models[i]) == 0) 20725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 20735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: Unsupported NIC model: %s\n", nd->model); 20755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit_status = 1; 20765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "qemu: Supported NIC models: "); 20795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0 ; models[i]; i++) 20805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "%s%c", models[i], models[i+1] ? ',' : '\n'); 20815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(exit_status); 20835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 20845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint net_client_init(Monitor *mon, const char *device, const char *p) 20865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 20875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const fd_params[] = { 20885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "fd", NULL 20895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 20905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char buf[1024]; 20915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int vlan_id, ret; 20925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 20935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *name = NULL; 20945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 20955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan_id = 0; 20965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "vlan", p)) { 20975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan_id = strtol(buf, NULL, 0); 20985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 20995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan = qemu_find_vlan(vlan_id); 21005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "name", p)) { 21025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner name = qemu_strdup(buf); 21035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "nic")) { 21055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const nic_params[] = { 21065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "macaddr", "model", NULL 21075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 21085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NICInfo *nd; 21095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner uint8_t *macaddr; 21105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int idx = nic_get_free_idx(); 21115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(buf, sizeof(buf), nic_params, p) < 0) { 21135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p); 21145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 21155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 21165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (idx == -1 || nb_nics >= MAX_NICS) { 21185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "Too Many NICs\n"); 21195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 21205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 21215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd = &nd_table[idx]; 21235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr = nd->macaddr; 21245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[0] = 0x52; 21255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[1] = 0x54; 21265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[2] = 0x00; 21275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[3] = 0x12; 21285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[4] = 0x34; 21295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner macaddr[5] = 0x56 + idx; 21305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "macaddr", p)) { 21325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (parse_macaddr(macaddr, buf) < 0) { 21335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid syntax for ethernet address\n"); 21345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 21355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 21365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "model", p)) { 21395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->model = strdup(buf); 21405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->vlan = vlan; 21425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->name = name; 21435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->used = 1; 21445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner name = NULL; 21455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nb_nics++; 21465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->nb_guest_devs++; 21475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = idx; 21485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 21495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "none")) { 21505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (*p != '\0') { 21515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "'none' takes no parameters\n"); 21525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 21535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 21545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* does nothing. It is needed to signal that no network cards 21565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner are wanted */ 21575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = 0; 21585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 21595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_SLIRP 21605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "user")) { 21615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const slirp_params[] = { 21625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "hostname", "restrict", "ip", NULL 21635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 21645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int restricted = 0; 21655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *ip = NULL; 21665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(buf, sizeof(buf), slirp_params, p) < 0) { 21685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p); 21695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 21705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 21715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "hostname", p)) { 21735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(slirp_hostname, sizeof(slirp_hostname), buf); 21745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "restrict", p)) { 21765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner restricted = (buf[0] == 'y') ? 1 : 0; 21775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "ip", p)) { 21795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ip = qemu_strdup(buf); 21805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->nb_host_devs++; 21825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_slirp_init(vlan, device, name, restricted, ip); 21835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(ip); 21845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (!strcmp(device, "channel")) { 21855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner long port; 21865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char name[20], *devname; 21875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner struct VMChannel *vmc; 21885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 21895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner port = strtol(p, &devname, 10); 21905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner devname++; 21915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (port < 1 || port > 65535) { 21925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "vmchannel wrong port number\n"); 21935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 21945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 21955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 21965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vmc = malloc(sizeof(struct VMChannel)); 21975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(name, 20, "vmchannel%ld", port); 21985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vmc->hd = qemu_chr_open(name, devname, NULL); 21995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vmc->hd) { 22005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "could not open vmchannel device '%s'\n", 22015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner devname); 22025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vmc->port = port; 22065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner slirp_add_exec(3, vmc->hd, 4, port); 22075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_chr_add_handlers(vmc->hd, vmchannel_can_read, vmchannel_read, 22085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner NULL, vmc); 22095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = 0; 22105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 22115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 22125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef _WIN32 22135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "tap")) { 22145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const tap_params[] = { 22155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "ifname", NULL 22165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 22175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char ifname[64]; 22185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 22195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(buf, sizeof(buf), tap_params, p) < 0) { 22205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p); 22215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) { 22255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "tap: no interface name\n"); 22265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->nb_host_devs++; 22305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = tap_win32_init(vlan, device, name, ifname); 22315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 22325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#elif defined (_AIX) 22335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#else 22345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "tap")) { 22355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char ifname[64], chkbuf[64]; 22365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char setup_script[1024], down_script[1024]; 22375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 22385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->nb_host_devs++; 22395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { 22405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { 22415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); 22425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = strtol(buf, NULL, 0); 22465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fcntl(fd, F_SETFL, O_NONBLOCK); 22475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner net_tap_fd_init(vlan, device, name, fd); 22485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = 0; 22495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 22505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const tap_params[] = { 22515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "ifname", "script", "downscript", NULL 22525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 22535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(chkbuf, sizeof(chkbuf), tap_params, p) < 0) { 22545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); 22555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(ifname, sizeof(ifname), "ifname", p) <= 0) { 22595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ifname[0] = '\0'; 22605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) { 22625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT); 22635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(down_script, sizeof(down_script), "downscript", p) == 0) { 22655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner pstrcpy(down_script, sizeof(down_script), DEFAULT_NETWORK_DOWN_SCRIPT); 22665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_tap_init(vlan, device, name, ifname, setup_script, down_script); 22685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 22705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 22715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "socket")) { 22725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char chkbuf[64]; 22735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { 22745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int fd; 22755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(chkbuf, sizeof(chkbuf), fd_params, p) < 0) { 22765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); 22775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fd = strtol(buf, NULL, 0); 22815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (net_socket_fd_init(vlan, device, name, fd, 1)) 22835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = 0; 22845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { 22855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const listen_params[] = { 22865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "listen", NULL 22875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 22885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(chkbuf, sizeof(chkbuf), listen_params, p) < 0) { 22895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); 22905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 22915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 22925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 22935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_socket_listen_init(vlan, device, name, buf); 22945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (get_param_value(buf, sizeof(buf), "connect", p) > 0) { 22955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const connect_params[] = { 22965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "connect", NULL 22975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 22985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(chkbuf, sizeof(chkbuf), connect_params, p) < 0) { 22995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); 23005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 23015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 23025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_socket_connect_init(vlan, device, name, buf); 23045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else if (get_param_value(buf, sizeof(buf), "mcast", p) > 0) { 23055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const mcast_params[] = { 23065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "mcast", NULL 23075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 23085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(chkbuf, sizeof(chkbuf), mcast_params, p) < 0) { 23095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", chkbuf, p); 23105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 23115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 23125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_socket_mcast_init(vlan, device, name, buf); 23145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "Unknown socket options: %s\n", p); 23165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 23175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 23185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->nb_host_devs++; 23205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 23215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VDE 23225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "vde")) { 23235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner static const char * const vde_params[] = { 23245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "vlan", "name", "sock", "port", "group", "mode", NULL 23255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 23265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char vde_sock[1024], vde_group[512]; 23275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int vde_port, vde_mode; 23285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 23295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (check_params(buf, sizeof(buf), vde_params, p) < 0) { 23305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "invalid parameter '%s' in '%s'\n", buf, p); 23315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 23325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 23335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->nb_host_devs++; 23355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(vde_sock, sizeof(vde_sock), "sock", p) <= 0) { 23365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_sock[0] = '\0'; 23375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "port", p) > 0) { 23395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_port = strtol(buf, NULL, 10); 23405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_port = 0; 23425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(vde_group, sizeof(vde_group), "group", p) <= 0) { 23445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_group[0] = '\0'; 23455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "mode", p) > 0) { 23475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_mode = strtol(buf, NULL, 8); 23485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vde_mode = 0700; 23505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_vde_init(vlan, device, name, vde_sock, vde_port, vde_group, vde_mode); 23525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else 23535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 23545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(device, "dump")) { 23555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int len = 65536; 23565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 23575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (get_param_value(buf, sizeof(buf), "len", p) > 0) { 23585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner len = strtol(buf, NULL, 0); 23595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!get_param_value(buf, sizeof(buf), "file", p)) { 23615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner snprintf(buf, sizeof(buf), "qemu-vlan%d.pcap", vlan_id); 23625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = net_dump_init(mon, vlan, device, name, buf, len); 23645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } else { 23655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "Unknown network device: %s\n", device); 23665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ret = -1; 23675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto out; 23685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (ret < 0) { 23705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner config_error(mon, "Could not initialize device '%s'\n", device); 23715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 23725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerout: 23735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_free(name); 23745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return ret; 23755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 23765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 23775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_client_uninit(NICInfo *nd) 23785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 23795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->vlan->nb_guest_devs--; 23805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nb_nics--; 23815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner nd->used = 0; 23825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner free((void *)nd->model); 23835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 23845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 23855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerstatic int net_host_check_device(const char *device) 23865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 23875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner int i; 23885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *valid_param_list[] = { "tap", "socket", "dump" 23895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_SLIRP 23905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ,"user" 23915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 23925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#ifdef CONFIG_VDE 23935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner ,"vde" 23945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 23955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner }; 23965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (i = 0; i < sizeof(valid_param_list) / sizeof(char *); i++) { 23975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strncmp(valid_param_list[i], device, 23985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner strlen(valid_param_list[i]))) 23995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 24005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 24035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 24045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_host_device_add(Monitor *mon, const char *device, const char *opts) 24065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 24075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!net_host_check_device(device)) { 24085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "invalid host network device %s\n", device); 24095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 24105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (net_client_init(mon, device, opts ? opts : "") < 0) { 24125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "adding host network device %s failed\n", device); 24135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 24155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_host_device_remove(Monitor *mon, int vlan_id, const char *device) 24175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 24185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 24195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 24205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan = qemu_find_vlan(vlan_id); 24225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vc = vlan->first_client; vc != NULL; vc = vc->next) { 24245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!strcmp(vc->name, device)) { 24255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 24265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vc) { 24305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "can't find device %s\n", device); 24315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 24325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!net_host_check_device(vc->model)) { 24345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "invalid host network device %s\n", device); 24355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return; 24365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_del_vlan_client(vc); 24385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 24395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint net_client_parse(const char *str) 24415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 24425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner const char *p; 24435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char *q; 24445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner char device[64]; 24455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p = str; 24475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner q = device; 24485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (*p != '\0' && *p != ',') { 24495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if ((q - device) < sizeof(device) - 1) 24505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q++ = *p; 24515d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p++; 24525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner *q = '\0'; 24545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (*p == ',') 24555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner p++; 24565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return net_client_init(NULL, device, p); 24585d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 24595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid do_info_network(Monitor *mon) 24615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 24625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 24635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc; 24645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { 24665d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "VLAN %d devices:\n", vlan->id); 24675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(vc = vlan->first_client; vc != NULL; vc = vc->next) 24685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, " %s: %s\n", vc->name, vc->info_str); 24695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 24715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint do_set_link(Monitor *mon, const char *name, const char *up_or_down) 24735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 24745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 24755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc = NULL; 24765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vlan = first_vlan; vlan != NULL; vlan = vlan->next) 24785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for (vc = vlan->first_client; vc != NULL; vc = vc->next) 24795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(vc->name, name) == 0) 24805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner goto done; 24815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerdone: 24825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (!vc) { 24845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "could not find network device '%s'", name); 24855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 24865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 24875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(up_or_down, "up") == 0) 24895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->link_down = 0; 24905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strcmp(up_or_down, "down") == 0) 24915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->link_down = 1; 24925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 24935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner monitor_printf(mon, "invalid link status '%s'; only 'up' or 'down' " 24945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "valid\n", up_or_down); 24955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vc->link_status_changed) 24975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc->link_status_changed(vc); 24985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 24995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 25005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 25015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_cleanup(void) 25035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 25045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 25055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* close network clients */ 25075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { 25085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *vc = vlan->first_client; 25095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner while (vc) { 25115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANClientState *next = vc->next; 25125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_del_vlan_client(vc); 25145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vc = next; 25165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 25175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 25185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 25195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid net_client_check(void) 25215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 25225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner VLANState *vlan; 25235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 25245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { 25255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vlan->nb_guest_devs == 0 && vlan->nb_host_devs == 0) 25265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner continue; 25275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vlan->nb_guest_devs == 0) 25285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Warning: vlan %d with no nics\n", vlan->id); 25295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (vlan->nb_host_devs == 0) 25305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, 25315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "Warning: vlan %d is not connected to host network\n", 25325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vlan->id); 25335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 25345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 2535