Revision 7c9d8e07 vl.c
b/vl.c | ||
---|---|---|
40 | 40 |
#include <sys/socket.h> |
41 | 41 |
#include <netinet/in.h> |
42 | 42 |
#include <dirent.h> |
43 |
#include <netdb.h> |
|
43 | 44 |
#ifdef _BSD |
44 | 45 |
#include <sys/stat.h> |
45 | 46 |
#ifndef __APPLE__ |
... | ... | |
122 | 123 |
int64_t ticks_per_sec; |
123 | 124 |
int boot_device = 'c'; |
124 | 125 |
int ram_size; |
125 |
static char network_script[1024]; |
|
126 | 126 |
int pit_min_timer_count = 0; |
127 | 127 |
int nb_nics; |
128 |
NetDriverState nd_table[MAX_NICS];
|
|
128 |
NICInfo nd_table[MAX_NICS];
|
|
129 | 129 |
QEMUTimer *gui_timer; |
130 | 130 |
int vm_running; |
131 | 131 |
#ifdef HAS_AUDIO |
... | ... | |
155 | 155 |
int usb_enabled = 0; |
156 | 156 |
USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; |
157 | 157 |
USBDevice *vm_usb_hub; |
158 |
static VLANState *first_vlan; |
|
158 | 159 |
|
159 | 160 |
/***********************************************************/ |
160 | 161 |
/* x86 ISA bus support */ |
... | ... | |
1076 | 1077 |
|
1077 | 1078 |
typedef struct { |
1078 | 1079 |
int fd_in, fd_out; |
1079 |
/* for nographic stdio only */ |
|
1080 | 1080 |
IOCanRWHandler *fd_can_read; |
1081 | 1081 |
IOReadHandler *fd_read; |
1082 | 1082 |
void *fd_opaque; |
1083 |
int max_size; |
|
1083 | 1084 |
} FDCharDriver; |
1084 | 1085 |
|
1085 | 1086 |
#define STDIO_MAX_CLIENTS 2 |
... | ... | |
1113 | 1114 |
return unix_write(s->fd_out, buf, len); |
1114 | 1115 |
} |
1115 | 1116 |
|
1117 |
static int fd_chr_read_poll(void *opaque) |
|
1118 |
{ |
|
1119 |
CharDriverState *chr = opaque; |
|
1120 |
FDCharDriver *s = chr->opaque; |
|
1121 |
|
|
1122 |
s->max_size = s->fd_can_read(s->fd_opaque); |
|
1123 |
return s->max_size; |
|
1124 |
} |
|
1125 |
|
|
1126 |
static void fd_chr_read(void *opaque) |
|
1127 |
{ |
|
1128 |
CharDriverState *chr = opaque; |
|
1129 |
FDCharDriver *s = chr->opaque; |
|
1130 |
int size, len; |
|
1131 |
uint8_t buf[1024]; |
|
1132 |
|
|
1133 |
len = sizeof(buf); |
|
1134 |
if (len > s->max_size) |
|
1135 |
len = s->max_size; |
|
1136 |
if (len == 0) |
|
1137 |
return; |
|
1138 |
size = read(s->fd_in, buf, len); |
|
1139 |
if (size > 0) { |
|
1140 |
s->fd_read(s->fd_opaque, buf, size); |
|
1141 |
} |
|
1142 |
} |
|
1143 |
|
|
1116 | 1144 |
static void fd_chr_add_read_handler(CharDriverState *chr, |
1117 | 1145 |
IOCanRWHandler *fd_can_read, |
1118 | 1146 |
IOReadHandler *fd_read, void *opaque) |
... | ... | |
1120 | 1148 |
FDCharDriver *s = chr->opaque; |
1121 | 1149 |
|
1122 | 1150 |
if (s->fd_in >= 0) { |
1151 |
s->fd_can_read = fd_can_read; |
|
1152 |
s->fd_read = fd_read; |
|
1153 |
s->fd_opaque = opaque; |
|
1123 | 1154 |
if (nographic && s->fd_in == 0) { |
1124 |
s->fd_can_read = fd_can_read; |
|
1125 |
s->fd_read = fd_read; |
|
1126 |
s->fd_opaque = opaque; |
|
1127 | 1155 |
} else { |
1128 |
qemu_add_fd_read_handler(s->fd_in, fd_can_read, fd_read, opaque); |
|
1156 |
qemu_set_fd_handler2(s->fd_in, fd_chr_read_poll, |
|
1157 |
fd_chr_read, NULL, chr); |
|
1129 | 1158 |
} |
1130 | 1159 |
} |
1131 | 1160 |
} |
... | ... | |
1261 | 1290 |
} |
1262 | 1291 |
} |
1263 | 1292 |
|
1264 |
static int stdio_can_read(void *opaque)
|
|
1293 |
static int stdio_read_poll(void *opaque)
|
|
1265 | 1294 |
{ |
1266 | 1295 |
CharDriverState *chr; |
1267 | 1296 |
FDCharDriver *s; |
... | ... | |
1284 | 1313 |
} |
1285 | 1314 |
} |
1286 | 1315 |
|
1287 |
static void stdio_read(void *opaque, const uint8_t *buf, int size)
|
|
1316 |
static void stdio_read(void *opaque) |
|
1288 | 1317 |
{ |
1289 |
int i; |
|
1290 |
for(i = 0; i < size; i++) |
|
1291 |
stdio_received_byte(buf[i]); |
|
1318 |
int size; |
|
1319 |
uint8_t buf[1]; |
|
1320 |
|
|
1321 |
size = read(0, buf, 1); |
|
1322 |
if (size > 0) |
|
1323 |
stdio_received_byte(buf[0]); |
|
1292 | 1324 |
} |
1293 | 1325 |
|
1294 | 1326 |
/* init terminal so that we can grab keys */ |
... | ... | |
1337 | 1369 |
return NULL; |
1338 | 1370 |
chr = qemu_chr_open_fd(0, 1); |
1339 | 1371 |
if (stdio_nb_clients == 0) |
1340 |
qemu_add_fd_read_handler(0, stdio_can_read, stdio_read, NULL);
|
|
1372 |
qemu_set_fd_handler2(0, stdio_read_poll, stdio_read, NULL, NULL);
|
|
1341 | 1373 |
client_index = stdio_nb_clients; |
1342 | 1374 |
} else { |
1343 | 1375 |
if (stdio_nb_clients != 0) |
... | ... | |
1603 | 1635 |
} |
1604 | 1636 |
|
1605 | 1637 |
/***********************************************************/ |
1606 |
/* Linux network device redirectors */
|
|
1638 |
/* network device redirectors */ |
|
1607 | 1639 |
|
1608 | 1640 |
void hex_dump(FILE *f, const uint8_t *buf, int size) |
1609 | 1641 |
{ |
... | ... | |
1631 | 1663 |
} |
1632 | 1664 |
} |
1633 | 1665 |
|
1634 |
void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
|
|
1666 |
static int parse_macaddr(uint8_t *macaddr, const char *p)
|
|
1635 | 1667 |
{ |
1636 |
nd->send_packet(nd, buf, size); |
|
1668 |
int i; |
|
1669 |
for(i = 0; i < 6; i++) { |
|
1670 |
macaddr[i] = strtol(p, (char **)&p, 16); |
|
1671 |
if (i == 5) { |
|
1672 |
if (*p != '\0') |
|
1673 |
return -1; |
|
1674 |
} else { |
|
1675 |
if (*p != ':') |
|
1676 |
return -1; |
|
1677 |
p++; |
|
1678 |
} |
|
1679 |
} |
|
1680 |
return 0; |
|
1637 | 1681 |
} |
1638 | 1682 |
|
1639 |
void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, |
|
1640 |
IOReadHandler *fd_read, void *opaque) |
|
1683 |
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) |
|
1641 | 1684 |
{ |
1642 |
nd->add_read_packet(nd, fd_can_read, fd_read, opaque); |
|
1685 |
const char *p, *p1; |
|
1686 |
int len; |
|
1687 |
p = *pp; |
|
1688 |
p1 = strchr(p, sep); |
|
1689 |
if (!p1) |
|
1690 |
return -1; |
|
1691 |
len = p1 - p; |
|
1692 |
p1++; |
|
1693 |
if (buf_size > 0) { |
|
1694 |
if (len > buf_size - 1) |
|
1695 |
len = buf_size - 1; |
|
1696 |
memcpy(buf, p, len); |
|
1697 |
buf[len] = '\0'; |
|
1698 |
} |
|
1699 |
*pp = p1; |
|
1700 |
return 0; |
|
1643 | 1701 |
} |
1644 | 1702 |
|
1645 |
/* dummy network adapter */ |
|
1703 |
int parse_host_port(struct sockaddr_in *saddr, const char *str) |
|
1704 |
{ |
|
1705 |
char buf[512]; |
|
1706 |
struct hostent *he; |
|
1707 |
const char *p, *r; |
|
1708 |
int port; |
|
1709 |
|
|
1710 |
p = str; |
|
1711 |
if (get_str_sep(buf, sizeof(buf), &p, ':') < 0) |
|
1712 |
return -1; |
|
1713 |
saddr->sin_family = AF_INET; |
|
1714 |
if (buf[0] == '\0') { |
|
1715 |
saddr->sin_addr.s_addr = 0; |
|
1716 |
} else { |
|
1717 |
if (isdigit(buf[0])) { |
|
1718 |
if (!inet_aton(buf, &saddr->sin_addr)) |
|
1719 |
return -1; |
|
1720 |
} else { |
|
1721 |
#ifdef _WIN32 |
|
1722 |
return -1; |
|
1723 |
#else |
|
1724 |
if ((he = gethostbyname(buf)) == NULL) |
|
1725 |
return - 1; |
|
1726 |
saddr->sin_addr = *(struct in_addr *)he->h_addr; |
|
1727 |
#endif |
|
1728 |
} |
|
1729 |
} |
|
1730 |
port = strtol(p, (char **)&r, 0); |
|
1731 |
if (r == p) |
|
1732 |
return -1; |
|
1733 |
saddr->sin_port = htons(port); |
|
1734 |
return 0; |
|
1735 |
} |
|
1646 | 1736 |
|
1647 |
static void dummy_send_packet(NetDriverState *nd, const uint8_t *buf, int size) |
|
1737 |
/* find or alloc a new VLAN */ |
|
1738 |
VLANState *qemu_find_vlan(int id) |
|
1648 | 1739 |
{ |
1740 |
VLANState **pvlan, *vlan; |
|
1741 |
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { |
|
1742 |
if (vlan->id == id) |
|
1743 |
return vlan; |
|
1744 |
} |
|
1745 |
vlan = qemu_mallocz(sizeof(VLANState)); |
|
1746 |
if (!vlan) |
|
1747 |
return NULL; |
|
1748 |
vlan->id = id; |
|
1749 |
vlan->next = NULL; |
|
1750 |
pvlan = &first_vlan; |
|
1751 |
while (*pvlan != NULL) |
|
1752 |
pvlan = &(*pvlan)->next; |
|
1753 |
*pvlan = vlan; |
|
1754 |
return vlan; |
|
1649 | 1755 |
} |
1650 | 1756 |
|
1651 |
static void dummy_add_read_packet(NetDriverState *nd, |
|
1652 |
IOCanRWHandler *fd_can_read, |
|
1653 |
IOReadHandler *fd_read, void *opaque) |
|
1757 |
VLANClientState *qemu_new_vlan_client(VLANState *vlan, |
|
1758 |
IOReadHandler *fd_read, void *opaque) |
|
1654 | 1759 |
{ |
1760 |
VLANClientState *vc, **pvc; |
|
1761 |
vc = qemu_mallocz(sizeof(VLANClientState)); |
|
1762 |
if (!vc) |
|
1763 |
return NULL; |
|
1764 |
vc->fd_read = fd_read; |
|
1765 |
vc->opaque = opaque; |
|
1766 |
vc->vlan = vlan; |
|
1767 |
|
|
1768 |
vc->next = NULL; |
|
1769 |
pvc = &vlan->first_client; |
|
1770 |
while (*pvc != NULL) |
|
1771 |
pvc = &(*pvc)->next; |
|
1772 |
*pvc = vc; |
|
1773 |
return vc; |
|
1655 | 1774 |
} |
1656 | 1775 |
|
1657 |
static int net_dummy_init(NetDriverState *nd)
|
|
1776 |
void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
|
|
1658 | 1777 |
{ |
1659 |
nd->send_packet = dummy_send_packet; |
|
1660 |
nd->add_read_packet = dummy_add_read_packet; |
|
1661 |
pstrcpy(nd->ifname, sizeof(nd->ifname), "dummy"); |
|
1662 |
return 0; |
|
1778 |
VLANState *vlan = vc1->vlan; |
|
1779 |
VLANClientState *vc; |
|
1780 |
|
|
1781 |
#if 0 |
|
1782 |
printf("vlan %d send:\n", vlan->id); |
|
1783 |
hex_dump(stdout, buf, size); |
|
1784 |
#endif |
|
1785 |
for(vc = vlan->first_client; vc != NULL; vc = vc->next) { |
|
1786 |
if (vc != vc1) { |
|
1787 |
vc->fd_read(vc->opaque, buf, size); |
|
1788 |
} |
|
1789 |
} |
|
1663 | 1790 |
} |
1664 | 1791 |
|
1665 | 1792 |
#if defined(CONFIG_SLIRP) |
1666 | 1793 |
|
1667 | 1794 |
/* slirp network adapter */ |
1668 | 1795 |
|
1669 |
static void *slirp_fd_opaque; |
|
1670 |
static IOCanRWHandler *slirp_fd_can_read; |
|
1671 |
static IOReadHandler *slirp_fd_read; |
|
1672 | 1796 |
static int slirp_inited; |
1797 |
static VLANClientState *slirp_vc; |
|
1673 | 1798 |
|
1674 | 1799 |
int slirp_can_output(void) |
1675 | 1800 |
{ |
1676 |
return slirp_fd_can_read(slirp_fd_opaque);
|
|
1801 |
return 1;
|
|
1677 | 1802 |
} |
1678 | 1803 |
|
1679 | 1804 |
void slirp_output(const uint8_t *pkt, int pkt_len) |
1680 | 1805 |
{ |
1681 | 1806 |
#if 0 |
1682 |
printf("output:\n"); |
|
1807 |
printf("slirp output:\n");
|
|
1683 | 1808 |
hex_dump(stdout, pkt, pkt_len); |
1684 | 1809 |
#endif |
1685 |
slirp_fd_read(slirp_fd_opaque, pkt, pkt_len);
|
|
1810 |
qemu_send_packet(slirp_vc, pkt, pkt_len);
|
|
1686 | 1811 |
} |
1687 | 1812 |
|
1688 |
static void slirp_send_packet(NetDriverState *nd, const uint8_t *buf, int size)
|
|
1813 |
static void slirp_receive(void *opaque, const uint8_t *buf, int size)
|
|
1689 | 1814 |
{ |
1690 | 1815 |
#if 0 |
1691 |
printf("input:\n"); |
|
1816 |
printf("slirp input:\n");
|
|
1692 | 1817 |
hex_dump(stdout, buf, size); |
1693 | 1818 |
#endif |
1694 | 1819 |
slirp_input(buf, size); |
1695 | 1820 |
} |
1696 | 1821 |
|
1697 |
static void slirp_add_read_packet(NetDriverState *nd, |
|
1698 |
IOCanRWHandler *fd_can_read, |
|
1699 |
IOReadHandler *fd_read, void *opaque) |
|
1700 |
{ |
|
1701 |
slirp_fd_opaque = opaque; |
|
1702 |
slirp_fd_can_read = fd_can_read; |
|
1703 |
slirp_fd_read = fd_read; |
|
1704 |
} |
|
1705 |
|
|
1706 |
static int net_slirp_init(NetDriverState *nd) |
|
1822 |
static int net_slirp_init(VLANState *vlan) |
|
1707 | 1823 |
{ |
1708 | 1824 |
if (!slirp_inited) { |
1709 | 1825 |
slirp_inited = 1; |
1710 | 1826 |
slirp_init(); |
1711 | 1827 |
} |
1712 |
nd->send_packet = slirp_send_packet; |
|
1713 |
nd->add_read_packet = slirp_add_read_packet; |
|
1714 |
pstrcpy(nd->ifname, sizeof(nd->ifname), "slirp"); |
|
1715 |
return 0; |
|
1716 |
} |
|
1717 |
|
|
1718 |
static int get_str_sep(char *buf, int buf_size, const char **pp, int sep) |
|
1719 |
{ |
|
1720 |
const char *p, *p1; |
|
1721 |
int len; |
|
1722 |
p = *pp; |
|
1723 |
p1 = strchr(p, sep); |
|
1724 |
if (!p1) |
|
1725 |
return -1; |
|
1726 |
len = p1 - p; |
|
1727 |
p1++; |
|
1728 |
if (buf_size > 0) { |
|
1729 |
if (len > buf_size - 1) |
|
1730 |
len = buf_size - 1; |
|
1731 |
memcpy(buf, p, len); |
|
1732 |
buf[len] = '\0'; |
|
1733 |
} |
|
1734 |
*pp = p1; |
|
1828 |
slirp_vc = qemu_new_vlan_client(vlan, |
|
1829 |
slirp_receive, NULL); |
|
1830 |
snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector"); |
|
1735 | 1831 |
return 0; |
1736 | 1832 |
} |
1737 | 1833 |
|
... | ... | |
1874 | 1970 |
#endif /* CONFIG_SLIRP */ |
1875 | 1971 |
|
1876 | 1972 |
#if !defined(_WIN32) |
1973 |
|
|
1974 |
typedef struct TAPState { |
|
1975 |
VLANClientState *vc; |
|
1976 |
int fd; |
|
1977 |
} TAPState; |
|
1978 |
|
|
1979 |
static void tap_receive(void *opaque, const uint8_t *buf, int size) |
|
1980 |
{ |
|
1981 |
TAPState *s = opaque; |
|
1982 |
int ret; |
|
1983 |
for(;;) { |
|
1984 |
ret = write(s->fd, buf, size); |
|
1985 |
if (ret < 0 && (errno == EINTR || errno == EAGAIN)) { |
|
1986 |
} else { |
|
1987 |
break; |
|
1988 |
} |
|
1989 |
} |
|
1990 |
} |
|
1991 |
|
|
1992 |
static void tap_send(void *opaque) |
|
1993 |
{ |
|
1994 |
TAPState *s = opaque; |
|
1995 |
uint8_t buf[4096]; |
|
1996 |
int size; |
|
1997 |
|
|
1998 |
size = read(s->fd, buf, sizeof(buf)); |
|
1999 |
if (size > 0) { |
|
2000 |
qemu_send_packet(s->vc, buf, size); |
|
2001 |
} |
|
2002 |
} |
|
2003 |
|
|
2004 |
/* fd support */ |
|
2005 |
|
|
2006 |
static TAPState *net_tap_fd_init(VLANState *vlan, int fd) |
|
2007 |
{ |
|
2008 |
TAPState *s; |
|
2009 |
|
|
2010 |
s = qemu_mallocz(sizeof(TAPState)); |
|
2011 |
if (!s) |
|
2012 |
return NULL; |
|
2013 |
s->fd = fd; |
|
2014 |
s->vc = qemu_new_vlan_client(vlan, tap_receive, s); |
|
2015 |
qemu_set_fd_handler(s->fd, tap_send, NULL, s); |
|
2016 |
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd); |
|
2017 |
return s; |
|
2018 |
} |
|
2019 |
|
|
1877 | 2020 |
#ifdef _BSD |
1878 |
static int tun_open(char *ifname, int ifname_size)
|
|
2021 |
static int tap_open(char *ifname, int ifname_size)
|
|
1879 | 2022 |
{ |
1880 | 2023 |
int fd; |
1881 | 2024 |
char *dev; |
... | ... | |
1895 | 2038 |
return fd; |
1896 | 2039 |
} |
1897 | 2040 |
#else |
1898 |
static int tun_open(char *ifname, int ifname_size)
|
|
2041 |
static int tap_open(char *ifname, int ifname_size)
|
|
1899 | 2042 |
{ |
1900 | 2043 |
struct ifreq ifr; |
1901 | 2044 |
int fd, ret; |
... | ... | |
1907 | 2050 |
} |
1908 | 2051 |
memset(&ifr, 0, sizeof(ifr)); |
1909 | 2052 |
ifr.ifr_flags = IFF_TAP | IFF_NO_PI; |
1910 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, "tun%d"); |
|
2053 |
if (ifname[0] != '\0') |
|
2054 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, ifname); |
|
2055 |
else |
|
2056 |
pstrcpy(ifr.ifr_name, IFNAMSIZ, "tap%d"); |
|
1911 | 2057 |
ret = ioctl(fd, TUNSETIFF, (void *) &ifr); |
1912 | 2058 |
if (ret != 0) { |
1913 | 2059 |
fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); |
1914 | 2060 |
close(fd); |
1915 | 2061 |
return -1; |
1916 | 2062 |
} |
1917 |
printf("Connected to host network interface: %s\n", ifr.ifr_name); |
|
1918 | 2063 |
pstrcpy(ifname, ifname_size, ifr.ifr_name); |
1919 | 2064 |
fcntl(fd, F_SETFL, O_NONBLOCK); |
1920 | 2065 |
return fd; |
1921 | 2066 |
} |
1922 | 2067 |
#endif |
1923 | 2068 |
|
1924 |
static void tun_send_packet(NetDriverState *nd, const uint8_t *buf, int size) |
|
2069 |
static int net_tap_init(VLANState *vlan, const char *ifname1, |
|
2070 |
const char *setup_script) |
|
2071 |
{ |
|
2072 |
TAPState *s; |
|
2073 |
int pid, status, fd; |
|
2074 |
char *args[3]; |
|
2075 |
char **parg; |
|
2076 |
char ifname[128]; |
|
2077 |
|
|
2078 |
if (ifname1 != NULL) |
|
2079 |
pstrcpy(ifname, sizeof(ifname), ifname1); |
|
2080 |
else |
|
2081 |
ifname[0] = '\0'; |
|
2082 |
fd = tap_open(ifname, sizeof(ifname)); |
|
2083 |
if (fd < 0) |
|
2084 |
return -1; |
|
2085 |
|
|
2086 |
if (!setup_script) |
|
2087 |
setup_script = ""; |
|
2088 |
if (setup_script[0] != '\0') { |
|
2089 |
/* try to launch network init script */ |
|
2090 |
pid = fork(); |
|
2091 |
if (pid >= 0) { |
|
2092 |
if (pid == 0) { |
|
2093 |
parg = args; |
|
2094 |
*parg++ = (char *)setup_script; |
|
2095 |
*parg++ = ifname; |
|
2096 |
*parg++ = NULL; |
|
2097 |
execv(setup_script, args); |
|
2098 |
exit(1); |
|
2099 |
} |
|
2100 |
while (waitpid(pid, &status, 0) != pid); |
|
2101 |
if (!WIFEXITED(status) || |
|
2102 |
WEXITSTATUS(status) != 0) { |
|
2103 |
fprintf(stderr, "%s: could not launch network script\n", |
|
2104 |
setup_script); |
|
2105 |
return -1; |
|
2106 |
} |
|
2107 |
} |
|
2108 |
} |
|
2109 |
s = net_tap_fd_init(vlan, fd); |
|
2110 |
if (!s) |
|
2111 |
return -1; |
|
2112 |
snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
|
2113 |
"tap: ifname=%s setup_script=%s", ifname, setup_script); |
|
2114 |
return 0; |
|
2115 |
} |
|
2116 |
|
|
2117 |
/* network connection */ |
|
2118 |
typedef struct NetSocketState { |
|
2119 |
VLANClientState *vc; |
|
2120 |
int fd; |
|
2121 |
int state; /* 0 = getting length, 1 = getting data */ |
|
2122 |
int index; |
|
2123 |
int packet_len; |
|
2124 |
uint8_t buf[4096]; |
|
2125 |
} NetSocketState; |
|
2126 |
|
|
2127 |
typedef struct NetSocketListenState { |
|
2128 |
VLANState *vlan; |
|
2129 |
int fd; |
|
2130 |
} NetSocketListenState; |
|
2131 |
|
|
2132 |
/* XXX: we consider we can send the whole packet without blocking */ |
|
2133 |
static void net_socket_receive(void *opaque, const uint8_t *buf, int size) |
|
1925 | 2134 |
{ |
1926 |
write(nd->fd, buf, size); |
|
2135 |
NetSocketState *s = opaque; |
|
2136 |
uint32_t len; |
|
2137 |
len = htonl(size); |
|
2138 |
|
|
2139 |
unix_write(s->fd, (const uint8_t *)&len, sizeof(len)); |
|
2140 |
unix_write(s->fd, buf, size); |
|
1927 | 2141 |
} |
1928 | 2142 |
|
1929 |
static void tun_add_read_packet(NetDriverState *nd, |
|
1930 |
IOCanRWHandler *fd_can_read, |
|
1931 |
IOReadHandler *fd_read, void *opaque) |
|
2143 |
static void net_socket_send(void *opaque) |
|
1932 | 2144 |
{ |
1933 |
qemu_add_fd_read_handler(nd->fd, fd_can_read, fd_read, opaque); |
|
2145 |
NetSocketState *s = opaque; |
|
2146 |
int l, size; |
|
2147 |
uint8_t buf1[4096]; |
|
2148 |
const uint8_t *buf; |
|
2149 |
|
|
2150 |
size = read(s->fd, buf1, sizeof(buf1)); |
|
2151 |
if (size < 0) |
|
2152 |
return; |
|
2153 |
if (size == 0) { |
|
2154 |
/* end of connection */ |
|
2155 |
qemu_set_fd_handler(s->fd, NULL, NULL, NULL); |
|
2156 |
return; |
|
2157 |
} |
|
2158 |
buf = buf1; |
|
2159 |
while (size > 0) { |
|
2160 |
/* reassemble a packet from the network */ |
|
2161 |
switch(s->state) { |
|
2162 |
case 0: |
|
2163 |
l = 4 - s->index; |
|
2164 |
if (l > size) |
|
2165 |
l = size; |
|
2166 |
memcpy(s->buf + s->index, buf, l); |
|
2167 |
buf += l; |
|
2168 |
size -= l; |
|
2169 |
s->index += l; |
|
2170 |
if (s->index == 4) { |
|
2171 |
/* got length */ |
|
2172 |
s->packet_len = ntohl(*(uint32_t *)s->buf); |
|
2173 |
s->index = 0; |
|
2174 |
s->state = 1; |
|
2175 |
} |
|
2176 |
break; |
|
2177 |
case 1: |
|
2178 |
l = s->packet_len - s->index; |
|
2179 |
if (l > size) |
|
2180 |
l = size; |
|
2181 |
memcpy(s->buf + s->index, buf, l); |
|
2182 |
s->index += l; |
|
2183 |
buf += l; |
|
2184 |
size -= l; |
|
2185 |
if (s->index >= s->packet_len) { |
|
2186 |
qemu_send_packet(s->vc, s->buf, s->packet_len); |
|
2187 |
s->index = 0; |
|
2188 |
s->state = 0; |
|
2189 |
} |
|
2190 |
break; |
|
2191 |
} |
|
2192 |
} |
|
1934 | 2193 |
} |
1935 | 2194 |
|
1936 |
static int net_tun_init(NetDriverState *nd)
|
|
2195 |
static void net_socket_connect(void *opaque)
|
|
1937 | 2196 |
{ |
1938 |
int pid, status;
|
|
1939 |
char *args[3];
|
|
1940 |
char **parg;
|
|
2197 |
NetSocketState *s = opaque;
|
|
2198 |
qemu_set_fd_handler(s->fd, net_socket_send, NULL, s);
|
|
2199 |
}
|
|
1941 | 2200 |
|
1942 |
nd->fd = tun_open(nd->ifname, sizeof(nd->ifname)); |
|
1943 |
if (nd->fd < 0) |
|
1944 |
return -1; |
|
2201 |
static NetSocketState *net_socket_fd_init(VLANState *vlan, int fd, |
|
2202 |
int is_connected) |
|
2203 |
{ |
|
2204 |
NetSocketState *s; |
|
2205 |
s = qemu_mallocz(sizeof(NetSocketState)); |
|
2206 |
if (!s) |
|
2207 |
return NULL; |
|
2208 |
s->fd = fd; |
|
2209 |
s->vc = qemu_new_vlan_client(vlan, |
|
2210 |
net_socket_receive, s); |
|
2211 |
snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
|
2212 |
"socket: fd=%d", fd); |
|
2213 |
if (is_connected) { |
|
2214 |
net_socket_connect(s); |
|
2215 |
} else { |
|
2216 |
qemu_set_fd_handler(s->fd, NULL, net_socket_connect, s); |
|
2217 |
} |
|
2218 |
return s; |
|
2219 |
} |
|
1945 | 2220 |
|
1946 |
/* try to launch network init script */ |
|
1947 |
pid = fork(); |
|
1948 |
if (pid >= 0) { |
|
1949 |
if (pid == 0) { |
|
1950 |
parg = args; |
|
1951 |
*parg++ = network_script; |
|
1952 |
*parg++ = nd->ifname; |
|
1953 |
*parg++ = NULL; |
|
1954 |
execv(network_script, args); |
|
1955 |
exit(1); |
|
1956 |
} |
|
1957 |
while (waitpid(pid, &status, 0) != pid); |
|
1958 |
if (!WIFEXITED(status) || |
|
1959 |
WEXITSTATUS(status) != 0) { |
|
1960 |
fprintf(stderr, "%s: could not launch network script\n", |
|
1961 |
network_script); |
|
2221 |
static void net_socket_accept(void *opaque) |
|
2222 |
{ |
|
2223 |
NetSocketListenState *s = opaque; |
|
2224 |
NetSocketState *s1; |
|
2225 |
struct sockaddr_in saddr; |
|
2226 |
socklen_t len; |
|
2227 |
int fd; |
|
2228 |
|
|
2229 |
for(;;) { |
|
2230 |
len = sizeof(saddr); |
|
2231 |
fd = accept(s->fd, (struct sockaddr *)&saddr, &len); |
|
2232 |
if (fd < 0 && errno != EINTR) { |
|
2233 |
return; |
|
2234 |
} else if (fd >= 0) { |
|
2235 |
break; |
|
1962 | 2236 |
} |
1963 | 2237 |
} |
1964 |
nd->send_packet = tun_send_packet; |
|
1965 |
nd->add_read_packet = tun_add_read_packet; |
|
2238 |
s1 = net_socket_fd_init(s->vlan, fd, 1); |
|
2239 |
if (!s1) { |
|
2240 |
close(fd); |
|
2241 |
} else { |
|
2242 |
snprintf(s1->vc->info_str, sizeof(s1->vc->info_str), |
|
2243 |
"socket: connection from %s:%d", |
|
2244 |
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); |
|
2245 |
} |
|
2246 |
} |
|
2247 |
|
|
2248 |
static int net_socket_listen_init(VLANState *vlan, const char *host_str) |
|
2249 |
{ |
|
2250 |
NetSocketListenState *s; |
|
2251 |
int fd, val, ret; |
|
2252 |
struct sockaddr_in saddr; |
|
2253 |
|
|
2254 |
if (parse_host_port(&saddr, host_str) < 0) |
|
2255 |
return -1; |
|
2256 |
|
|
2257 |
s = qemu_mallocz(sizeof(NetSocketListenState)); |
|
2258 |
if (!s) |
|
2259 |
return -1; |
|
2260 |
|
|
2261 |
fd = socket(PF_INET, SOCK_STREAM, 0); |
|
2262 |
if (fd < 0) { |
|
2263 |
perror("socket"); |
|
2264 |
return -1; |
|
2265 |
} |
|
2266 |
fcntl(fd, F_SETFL, O_NONBLOCK); |
|
2267 |
|
|
2268 |
/* allow fast reuse */ |
|
2269 |
val = 1; |
|
2270 |
setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &val, sizeof(val)); |
|
2271 |
|
|
2272 |
ret = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr)); |
|
2273 |
if (ret < 0) { |
|
2274 |
perror("bind"); |
|
2275 |
return -1; |
|
2276 |
} |
|
2277 |
ret = listen(fd, 0); |
|
2278 |
if (ret < 0) { |
|
2279 |
perror("listen"); |
|
2280 |
return -1; |
|
2281 |
} |
|
2282 |
s->vlan = vlan; |
|
2283 |
s->fd = fd; |
|
2284 |
qemu_set_fd_handler(fd, net_socket_accept, NULL, s); |
|
1966 | 2285 |
return 0; |
1967 | 2286 |
} |
1968 | 2287 |
|
1969 |
static int net_fd_init(NetDriverState *nd, int fd)
|
|
2288 |
static int net_socket_connect_init(VLANState *vlan, const char *host_str)
|
|
1970 | 2289 |
{ |
1971 |
nd->fd = fd; |
|
1972 |
nd->send_packet = tun_send_packet; |
|
1973 |
nd->add_read_packet = tun_add_read_packet; |
|
1974 |
pstrcpy(nd->ifname, sizeof(nd->ifname), "tunfd"); |
|
2290 |
NetSocketState *s; |
|
2291 |
int fd, connected, ret; |
|
2292 |
struct sockaddr_in saddr; |
|
2293 |
|
|
2294 |
if (parse_host_port(&saddr, host_str) < 0) |
|
2295 |
return -1; |
|
2296 |
|
|
2297 |
fd = socket(PF_INET, SOCK_STREAM, 0); |
|
2298 |
if (fd < 0) { |
|
2299 |
perror("socket"); |
|
2300 |
return -1; |
|
2301 |
} |
|
2302 |
fcntl(fd, F_SETFL, O_NONBLOCK); |
|
2303 |
|
|
2304 |
connected = 0; |
|
2305 |
for(;;) { |
|
2306 |
ret = connect(fd, (struct sockaddr *)&saddr, sizeof(saddr)); |
|
2307 |
if (ret < 0) { |
|
2308 |
if (errno == EINTR || errno == EAGAIN) { |
|
2309 |
} else if (errno == EINPROGRESS) { |
|
2310 |
break; |
|
2311 |
} else { |
|
2312 |
perror("connect"); |
|
2313 |
close(fd); |
|
2314 |
return -1; |
|
2315 |
} |
|
2316 |
} else { |
|
2317 |
connected = 1; |
|
2318 |
break; |
|
2319 |
} |
|
2320 |
} |
|
2321 |
s = net_socket_fd_init(vlan, fd, connected); |
|
2322 |
if (!s) |
|
2323 |
return -1; |
|
2324 |
snprintf(s->vc->info_str, sizeof(s->vc->info_str), |
|
2325 |
"socket: connect to %s:%d", |
|
2326 |
inet_ntoa(saddr.sin_addr), ntohs(saddr.sin_port)); |
|
1975 | 2327 |
return 0; |
1976 | 2328 |
} |
1977 | 2329 |
|
1978 | 2330 |
#endif /* !_WIN32 */ |
1979 | 2331 |
|
2332 |
static int get_param_value(char *buf, int buf_size, |
|
2333 |
const char *tag, const char *str) |
|
2334 |
{ |
|
2335 |
const char *p; |
|
2336 |
char *q; |
|
2337 |
char option[128]; |
|
2338 |
|
|
2339 |
p = str; |
|
2340 |
for(;;) { |
|
2341 |
q = option; |
|
2342 |
while (*p != '\0' && *p != '=') { |
|
2343 |
if ((q - option) < sizeof(option) - 1) |
|
2344 |
*q++ = *p; |
|
2345 |
p++; |
|
2346 |
} |
|
2347 |
*q = '\0'; |
|
2348 |
if (*p != '=') |
|
2349 |
break; |
|
2350 |
p++; |
|
2351 |
if (!strcmp(tag, option)) { |
|
2352 |
q = buf; |
|
2353 |
while (*p != '\0' && *p != ',') { |
|
2354 |
if ((q - buf) < buf_size - 1) |
|
2355 |
*q++ = *p; |
|
2356 |
p++; |
|
2357 |
} |
|
2358 |
*q = '\0'; |
|
2359 |
return q - buf; |
|
2360 |
} else { |
|
2361 |
while (*p != '\0' && *p != ',') { |
|
2362 |
p++; |
|
2363 |
} |
|
2364 |
} |
|
2365 |
if (*p != ',') |
|
2366 |
break; |
|
2367 |
p++; |
|
2368 |
} |
|
2369 |
return 0; |
|
2370 |
} |
|
2371 |
|
|
2372 |
int net_client_init(const char *str) |
|
2373 |
{ |
|
2374 |
const char *p; |
|
2375 |
char *q; |
|
2376 |
char device[64]; |
|
2377 |
char buf[1024]; |
|
2378 |
int vlan_id, ret; |
|
2379 |
VLANState *vlan; |
|
2380 |
|
|
2381 |
p = str; |
|
2382 |
q = device; |
|
2383 |
while (*p != '\0' && *p != ',') { |
|
2384 |
if ((q - device) < sizeof(device) - 1) |
|
2385 |
*q++ = *p; |
|
2386 |
p++; |
|
2387 |
} |
|
2388 |
*q = '\0'; |
|
2389 |
if (*p == ',') |
|
2390 |
p++; |
|
2391 |
vlan_id = 0; |
|
2392 |
if (get_param_value(buf, sizeof(buf), "vlan", p)) { |
|
2393 |
vlan_id = strtol(buf, NULL, 0); |
|
2394 |
} |
|
2395 |
vlan = qemu_find_vlan(vlan_id); |
|
2396 |
if (!vlan) { |
|
2397 |
fprintf(stderr, "Could not create vlan %d\n", vlan_id); |
|
2398 |
return -1; |
|
2399 |
} |
|
2400 |
if (!strcmp(device, "nic")) { |
|
2401 |
NICInfo *nd; |
|
2402 |
uint8_t *macaddr; |
|
2403 |
|
|
2404 |
if (nb_nics >= MAX_NICS) { |
|
2405 |
fprintf(stderr, "Too Many NICs\n"); |
|
2406 |
return -1; |
|
2407 |
} |
|
2408 |
nd = &nd_table[nb_nics]; |
|
2409 |
macaddr = nd->macaddr; |
|
2410 |
macaddr[0] = 0x52; |
|
2411 |
macaddr[1] = 0x54; |
|
2412 |
macaddr[2] = 0x00; |
|
2413 |
macaddr[3] = 0x12; |
|
2414 |
macaddr[4] = 0x34; |
|
2415 |
macaddr[5] = 0x56 + nb_nics; |
|
2416 |
|
|
2417 |
if (get_param_value(buf, sizeof(buf), "macaddr", p)) { |
|
2418 |
if (parse_macaddr(macaddr, buf) < 0) { |
|
2419 |
fprintf(stderr, "invalid syntax for ethernet address\n"); |
|
2420 |
return -1; |
|
2421 |
} |
|
2422 |
} |
|
2423 |
nd->vlan = vlan; |
|
2424 |
nb_nics++; |
|
2425 |
ret = 0; |
|
2426 |
} else |
|
2427 |
if (!strcmp(device, "none")) { |
|
2428 |
/* does nothing. It is needed to signal that no network cards |
|
2429 |
are wanted */ |
|
2430 |
ret = 0; |
|
2431 |
} else |
|
2432 |
#ifdef CONFIG_SLIRP |
|
2433 |
if (!strcmp(device, "user")) { |
|
2434 |
ret = net_slirp_init(vlan); |
|
2435 |
} else |
|
2436 |
#endif |
|
2437 |
#ifndef _WIN32 |
|
2438 |
if (!strcmp(device, "tap")) { |
|
2439 |
char ifname[64]; |
|
2440 |
char setup_script[1024]; |
|
2441 |
int fd; |
|
2442 |
if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { |
|
2443 |
fd = strtol(buf, NULL, 0); |
|
2444 |
ret = -1; |
|
2445 |
if (net_tap_fd_init(vlan, fd)) |
|
2446 |
ret = 0; |
|
2447 |
} else { |
|
2448 |
get_param_value(ifname, sizeof(ifname), "ifname", p); |
|
2449 |
if (get_param_value(setup_script, sizeof(setup_script), "script", p) == 0) { |
|
2450 |
pstrcpy(setup_script, sizeof(setup_script), DEFAULT_NETWORK_SCRIPT); |
|
2451 |
} |
|
2452 |
ret = net_tap_init(vlan, ifname, setup_script); |
|
2453 |
} |
|
2454 |
} else |
|
2455 |
if (!strcmp(device, "socket")) { |
|
2456 |
if (get_param_value(buf, sizeof(buf), "fd", p) > 0) { |
|
2457 |
int fd; |
|
2458 |
fd = strtol(buf, NULL, 0); |
|
2459 |
ret = -1; |
|
2460 |
if (net_socket_fd_init(vlan, fd, 1)) |
|
2461 |
ret = 0; |
|
2462 |
} else if (get_param_value(buf, sizeof(buf), "listen", p) > 0) { |
|
2463 |
ret = net_socket_listen_init(vlan, buf); |
|
2464 |
} else if (get_param_value(buf, sizeof(buf), "connect", p) > 0) { |
|
2465 |
ret = net_socket_connect_init(vlan, buf); |
|
2466 |
} else { |
|
2467 |
fprintf(stderr, "Unknown socket options: %s\n", p); |
|
2468 |
return -1; |
|
2469 |
} |
|
2470 |
} else |
|
2471 |
#endif |
|
2472 |
{ |
|
2473 |
fprintf(stderr, "Unknown network device: %s\n", device); |
|
2474 |
return -1; |
|
2475 |
} |
|
2476 |
if (ret < 0) { |
|
2477 |
fprintf(stderr, "Could not initialize device '%s'\n", device); |
|
2478 |
} |
|
2479 |
|
|
2480 |
return ret; |
|
2481 |
} |
|
2482 |
|
|
2483 |
void do_info_network(void) |
|
2484 |
{ |
|
2485 |
VLANState *vlan; |
|
2486 |
VLANClientState *vc; |
|
2487 |
|
|
2488 |
for(vlan = first_vlan; vlan != NULL; vlan = vlan->next) { |
|
2489 |
term_printf("VLAN %d devices:\n", vlan->id); |
|
2490 |
for(vc = vlan->first_client; vc != NULL; vc = vc->next) |
|
2491 |
term_printf(" %s\n", vc->info_str); |
|
2492 |
} |
|
2493 |
} |
|
2494 |
|
|
1980 | 2495 |
/***********************************************************/ |
1981 | 2496 |
/* USB devices */ |
1982 | 2497 |
|
... | ... | |
2175 | 2690 |
|
2176 | 2691 |
typedef struct IOHandlerRecord { |
2177 | 2692 |
int fd; |
2178 |
IOCanRWHandler *fd_can_read; |
|
2179 |
IOReadHandler *fd_read; |
|
2693 |
IOCanRWHandler *fd_read_poll; |
|
2694 |
IOHandler *fd_read; |
|
2695 |
IOHandler *fd_write; |
|
2180 | 2696 |
void *opaque; |
2181 | 2697 |
/* temporary data */ |
2182 | 2698 |
struct pollfd *ufd; |
2183 |
int max_size; |
|
2184 | 2699 |
struct IOHandlerRecord *next; |
2185 | 2700 |
} IOHandlerRecord; |
2186 | 2701 |
|
2187 | 2702 |
static IOHandlerRecord *first_io_handler; |
2188 | 2703 |
|
2189 |
int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, |
|
2190 |
IOReadHandler *fd_read, void *opaque) |
|
2704 |
/* XXX: fd_read_poll should be suppressed, but an API change is |
|
2705 |
necessary in the character devices to suppress fd_can_read(). */ |
|
2706 |
int qemu_set_fd_handler2(int fd, |
|
2707 |
IOCanRWHandler *fd_read_poll, |
|
2708 |
IOHandler *fd_read, |
|
2709 |
IOHandler *fd_write, |
|
2710 |
void *opaque) |
|
2191 | 2711 |
{ |
2192 |
IOHandlerRecord *ioh; |
|
2712 |
IOHandlerRecord **pioh, *ioh;
|
|
2193 | 2713 |
|
2194 |
ioh = qemu_mallocz(sizeof(IOHandlerRecord)); |
|
2195 |
if (!ioh) |
|
2196 |
return -1; |
|
2197 |
ioh->fd = fd; |
|
2198 |
ioh->fd_can_read = fd_can_read; |
|
2199 |
ioh->fd_read = fd_read; |
|
2200 |
ioh->opaque = opaque; |
|
2201 |
ioh->next = first_io_handler; |
|
2202 |
first_io_handler = ioh; |
|
2714 |
if (!fd_read && !fd_write) { |
|
2715 |
pioh = &first_io_handler; |
|
2716 |
for(;;) { |
|
2717 |
ioh = *pioh; |
|
2718 |
if (ioh == NULL) |
|
2719 |
break; |
|
2720 |
if (ioh->fd == fd) { |
|
2721 |
*pioh = ioh->next; |
|
2722 |
break; |
|
2723 |
} |
|
2724 |
pioh = &ioh->next; |
|
2725 |
} |
|
2726 |
} else { |
|
2727 |
for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { |
|
2728 |
if (ioh->fd == fd) |
|
2729 |
goto found; |
|
2730 |
} |
|
2731 |
ioh = qemu_mallocz(sizeof(IOHandlerRecord)); |
|
2732 |
if (!ioh) |
|
2733 |
return -1; |
|
2734 |
ioh->next = first_io_handler; |
|
2735 |
first_io_handler = ioh; |
|
2736 |
found: |
|
2737 |
ioh->fd = fd; |
|
2738 |
ioh->fd_read_poll = fd_read_poll; |
|
2739 |
ioh->fd_read = fd_read; |
|
2740 |
ioh->fd_write = fd_write; |
|
2741 |
ioh->opaque = opaque; |
|
2742 |
} |
|
2203 | 2743 |
return 0; |
2204 | 2744 |
} |
2205 | 2745 |
|
2206 |
void qemu_del_fd_read_handler(int fd) |
|
2746 |
int qemu_set_fd_handler(int fd, |
|
2747 |
IOHandler *fd_read, |
|
2748 |
IOHandler *fd_write, |
|
2749 |
void *opaque) |
|
2207 | 2750 |
{ |
2208 |
IOHandlerRecord **pioh, *ioh; |
|
2209 |
|
|
2210 |
pioh = &first_io_handler; |
|
2211 |
for(;;) { |
|
2212 |
ioh = *pioh; |
|
2213 |
if (ioh == NULL) |
|
2214 |
break; |
|
2215 |
if (ioh->fd == fd) { |
|
2216 |
*pioh = ioh->next; |
|
2217 |
break; |
|
2218 |
} |
|
2219 |
pioh = &ioh->next; |
|
2220 |
} |
|
2751 |
return qemu_set_fd_handler2(fd, NULL, fd_read, fd_write, opaque); |
|
2221 | 2752 |
} |
2222 | 2753 |
|
2223 | 2754 |
/***********************************************************/ |
... | ... | |
3080 | 3611 |
#ifndef _WIN32 |
3081 | 3612 |
struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf; |
3082 | 3613 |
IOHandlerRecord *ioh, *ioh_next; |
3083 |
uint8_t buf[4096]; |
|
3084 |
int n, max_size; |
|
3085 | 3614 |
#endif |
3086 | 3615 |
int ret; |
3087 | 3616 |
|
... | ... | |
3093 | 3622 |
/* XXX: separate device handlers from system ones */ |
3094 | 3623 |
pf = ufds; |
3095 | 3624 |
for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { |
3096 |
if (!ioh->fd_can_read) { |
|
3097 |
max_size = 0; |
|
3098 |
pf->fd = ioh->fd; |
|
3099 |
pf->events = POLLIN; |
|
3100 |
ioh->ufd = pf; |
|
3101 |
pf++; |
|
3102 |
} else { |
|
3103 |
max_size = ioh->fd_can_read(ioh->opaque); |
|
3104 |
if (max_size > 0) { |
|
3105 |
if (max_size > sizeof(buf)) |
|
3106 |
max_size = sizeof(buf); |
|
3107 |
pf->fd = ioh->fd; |
|
3108 |
pf->events = POLLIN; |
|
3109 |
ioh->ufd = pf; |
|
3110 |
pf++; |
|
3111 |
} else { |
|
3112 |
ioh->ufd = NULL; |
|
3113 |
} |
|
3625 |
pf->events = 0; |
|
3626 |
pf->fd = ioh->fd; |
|
3627 |
if (ioh->fd_read && |
|
3628 |
(!ioh->fd_read_poll || |
|
3629 |
ioh->fd_read_poll(ioh->opaque) != 0)) { |
|
3630 |
pf->events |= POLLIN; |
|
3631 |
} |
|
3632 |
if (ioh->fd_write) { |
|
3633 |
pf->events |= POLLOUT; |
|
3114 | 3634 |
} |
3115 |
ioh->max_size = max_size; |
|
3635 |
ioh->ufd = pf; |
|
3636 |
pf++; |
|
3116 | 3637 |
} |
3117 | 3638 |
|
3118 | 3639 |
ret = poll(ufds, pf - ufds, timeout); |
... | ... | |
3121 | 3642 |
for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { |
3122 | 3643 |
ioh_next = ioh->next; |
3123 | 3644 |
pf = ioh->ufd; |
3124 |
if (pf) { |
|
3125 |
if (pf->revents & POLLIN) { |
|
3126 |
if (ioh->max_size == 0) { |
|
3127 |
/* just a read event */ |
|
3128 |
ioh->fd_read(ioh->opaque, NULL, 0); |
|
3129 |
} else { |
|
3130 |
n = read(ioh->fd, buf, ioh->max_size); |
|
3131 |
if (n >= 0) { |
|
3132 |
ioh->fd_read(ioh->opaque, buf, n); |
|
3133 |
} else if (errno != EAGAIN) { |
|
3134 |
ioh->fd_read(ioh->opaque, NULL, -errno); |
|
3135 |
} |
|
3136 |
} |
|
3137 |
} |
|
3645 |
if (pf->revents & POLLIN) { |
|
3646 |
ioh->fd_read(ioh->opaque); |
|
3647 |
} |
|
3648 |
if (pf->revents & POLLOUT) { |
|
3649 |
ioh->fd_write(ioh->opaque); |
|
3138 | 3650 |
} |
3139 | 3651 |
} |
3140 | 3652 |
} |
... | ... | |
3251 | 3763 |
#endif |
3252 | 3764 |
"\n" |
3253 | 3765 |
"Network options:\n" |
3254 |
"-nics n simulate 'n' network cards [default=1]\n" |
|
3255 |
"-macaddr addr set the mac address of the first interface\n" |
|
3256 |
"-n script set tap/tun network init script [default=%s]\n" |
|
3257 |
"-tun-fd fd use this fd as already opened tap/tun interface\n" |
|
3766 |
"-net nic[,vlan=n][,macaddr=addr]\n" |
|
3767 |
" create a new Network Interface Card and connect it to VLAN 'n'\n" |
|
3258 | 3768 |
#ifdef CONFIG_SLIRP |
3259 |
"-user-net use user mode network stack [default if no tap/tun script]\n" |
|
3260 |
"-tftp prefix allow tftp access to files starting with prefix [-user-net]\n" |
|
3769 |
"-net user[,vlan=n]\n" |
|
3770 |
" connect the user mode network stack to VLAN 'n'\n" |
|
3771 |
#endif |
|
3261 | 3772 |
#ifndef _WIN32 |
3262 |
"-smb dir allow SMB access to files in 'dir' [-user-net]\n" |
|
3773 |
"-net tap[,vlan=n][,fd=h][,ifname=name][,script=file]\n" |
|
3774 |
" connect the host TAP network interface to VLAN 'n' and use\n" |
|
3775 |
" the network script 'file' (default=%s);\n" |
|
3776 |
" use 'fd=h' to connect to an already opened TAP interface\n" |
|
3777 |
"-net socket[,vlan=n][,fd=x][,listen=[host]:port][,connect=host:port]\n" |
|
3778 |
" connect the vlan 'n' to another VLAN using a socket connection\n" |
|
3779 |
#endif |
|
3780 |
"-net none use it alone to have zero network devices; if no -net option\n" |
|
3781 |
" is provided, the default is '-net nic -net user'\n" |
|
3782 |
"\n" |
|
3783 |
#ifdef CONFIG_SLIRP |
|
3784 |
"-tftp prefix allow tftp access to files starting with prefix [-net user]\n" |
|
3785 |
#ifndef _WIN32 |
|
3786 |
"-smb dir allow SMB access to files in 'dir' [-net user]\n" |
|
3263 | 3787 |
#endif |
3264 | 3788 |
"-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" |
3265 |
" redirect TCP or UDP connections from host to guest [-user-net]\n"
|
|
3789 |
" redirect TCP or UDP connections from host to guest [-net user]\n"
|
|
3266 | 3790 |
#endif |
3267 |
"-dummy-net use dummy network stack\n" |
|
3268 | 3791 |
"\n" |
3269 | 3792 |
"Linux boot specific:\n" |
3270 | 3793 |
"-kernel bzImage use 'bzImage' as kernel image\n" |
... | ... | |
3308 | 3831 |
"qemu-fast", |
3309 | 3832 |
#endif |
3310 | 3833 |
DEFAULT_RAM_SIZE, |
3834 |
#ifndef _WIN32 |
|
3311 | 3835 |
DEFAULT_NETWORK_SCRIPT, |
3836 |
#endif |
|
3312 | 3837 |
DEFAULT_GDBSTUB_PORT, |
3313 | 3838 |
"/tmp/qemu.log"); |
3314 | 3839 |
#ifndef CONFIG_SOFTMMU |
... | ... | |
3343 | 3868 |
QEMU_OPTION_soundhw, |
3344 | 3869 |
#endif |
3345 | 3870 |
|
3346 |
QEMU_OPTION_nics, |
|
3347 |
QEMU_OPTION_macaddr, |
|
3348 |
QEMU_OPTION_n, |
|
3349 |
QEMU_OPTION_tun_fd, |
|
3350 |
QEMU_OPTION_user_net, |
|
3871 |
QEMU_OPTION_net, |
|
3351 | 3872 |
QEMU_OPTION_tftp, |
3352 | 3873 |
QEMU_OPTION_smb, |
3353 | 3874 |
QEMU_OPTION_redir, |
3354 |
QEMU_OPTION_dummy_net, |
|
3355 | 3875 |
|
3356 | 3876 |
QEMU_OPTION_kernel, |
3357 | 3877 |
QEMU_OPTION_append, |
... | ... | |
3409 | 3929 |
{ "soundhw", HAS_ARG, QEMU_OPTION_soundhw }, |
3410 | 3930 |
#endif |
3411 | 3931 |
|
3412 |
{ "nics", HAS_ARG, QEMU_OPTION_nics}, |
|
3413 |
{ "macaddr", HAS_ARG, QEMU_OPTION_macaddr}, |
|
3414 |
{ "n", HAS_ARG, QEMU_OPTION_n }, |
|
3415 |
{ "tun-fd", HAS_ARG, QEMU_OPTION_tun_fd }, |
|
3932 |
{ "net", HAS_ARG, QEMU_OPTION_net}, |
|
3416 | 3933 |
#ifdef CONFIG_SLIRP |
3417 |
{ "user-net", 0, QEMU_OPTION_user_net }, |
|
3418 | 3934 |
{ "tftp", HAS_ARG, QEMU_OPTION_tftp }, |
3419 | 3935 |
#ifndef _WIN32 |
3420 | 3936 |
{ "smb", HAS_ARG, QEMU_OPTION_smb }, |
3421 | 3937 |
#endif |
3422 | 3938 |
{ "redir", HAS_ARG, QEMU_OPTION_redir }, |
3423 | 3939 |
#endif |
3424 |
{ "dummy-net", 0, QEMU_OPTION_dummy_net }, |
|
3425 | 3940 |
|
3426 | 3941 |
{ "kernel", HAS_ARG, QEMU_OPTION_kernel }, |
3427 | 3942 |
{ "append", HAS_ARG, QEMU_OPTION_append }, |
... | ... | |
3596 | 4111 |
} |
3597 | 4112 |
#endif |
3598 | 4113 |
|
3599 |
#define NET_IF_TUN 0 |
|
3600 |
#define NET_IF_USER 1 |
|
3601 |
#define NET_IF_DUMMY 2 |
|
4114 |
#define MAX_NET_CLIENTS 32 |
|
3602 | 4115 |
|
3603 | 4116 |
int main(int argc, char **argv) |
3604 | 4117 |
{ |
... | ... | |
3614 | 4127 |
DisplayState *ds = &display_state; |
3615 | 4128 |
int cyls, heads, secs, translation; |
3616 | 4129 |
int start_emulation = 1; |
3617 |
uint8_t macaddr[6];
|
|
3618 |
int net_if_type, nb_tun_fds, tun_fds[MAX_NICS];
|
|
4130 |
char net_clients[MAX_NET_CLIENTS][256];
|
|
4131 |
int nb_net_clients;
|
|
3619 | 4132 |
int optind; |
3620 | 4133 |
const char *r, *optarg; |
3621 | 4134 |
CharDriverState *monitor_hd; |
... | ... | |
3644 | 4157 |
ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; |
3645 | 4158 |
vga_ram_size = VGA_RAM_SIZE; |
3646 | 4159 |
bios_size = BIOS_SIZE; |
3647 |
pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); |
|
3648 | 4160 |
#ifdef CONFIG_GDBSTUB |
3649 | 4161 |
use_gdbstub = 0; |
3650 | 4162 |
gdbstub_port = DEFAULT_GDBSTUB_PORT; |
... | ... | |
3674 | 4186 |
|
3675 | 4187 |
usb_devices_index = 0; |
3676 | 4188 |
|
3677 |
nb_tun_fds = 0;
|
|
3678 |
net_if_type = -1; |
|
3679 |
nb_nics = 1;
|
|
4189 |
nb_net_clients = 0;
|
|
4190 |
|
|
4191 |
nb_nics = 0;
|
|
3680 | 4192 |
/* default mac address of the first network interface */ |
3681 |
macaddr[0] = 0x52; |
|
3682 |
macaddr[1] = 0x54; |
|
3683 |
macaddr[2] = 0x00; |
|
3684 |
macaddr[3] = 0x12; |
|
3685 |
macaddr[4] = 0x34; |
|
3686 |
macaddr[5] = 0x56; |
|
3687 | 4193 |
|
3688 | 4194 |
optind = 1; |
3689 | 4195 |
for(;;) { |
... | ... | |
3797 | 4303 |
case QEMU_OPTION_append: |
3798 | 4304 |
kernel_cmdline = optarg; |
3799 | 4305 |
break; |
3800 |
case QEMU_OPTION_tun_fd: |
|
3801 |
{ |
|
3802 |
const char *p; |
|
3803 |
int fd; |
|
3804 |
net_if_type = NET_IF_TUN; |
|
3805 |
if (nb_tun_fds < MAX_NICS) { |
|
3806 |
fd = strtol(optarg, (char **)&p, 0); |
|
3807 |
if (*p != '\0') { |
|
3808 |
fprintf(stderr, "qemu: invalid fd for network interface %d\n", nb_tun_fds); |
|
3809 |
exit(1); |
|
3810 |
} |
|
3811 |
tun_fds[nb_tun_fds++] = fd; |
|
3812 |
} |
|
3813 |
} |
|
3814 |
break; |
|
3815 | 4306 |
case QEMU_OPTION_cdrom: |
3816 | 4307 |
if (cdrom_index >= 0) { |
3817 | 4308 |
hd_filename[cdrom_index] = optarg; |
... | ... | |
3838 | 4329 |
case QEMU_OPTION_no_code_copy: |
3839 | 4330 |
code_copy_enabled = 0; |
3840 | 4331 |
break; |
3841 |
case QEMU_OPTION_nics: |
|
3842 |
nb_nics = atoi(optarg); |
|
3843 |
if (nb_nics < 0 || nb_nics > MAX_NICS) { |
|
3844 |
fprintf(stderr, "qemu: invalid number of network interfaces\n"); |
|
4332 |
case QEMU_OPTION_net: |
|
4333 |
if (nb_net_clients >= MAX_NET_CLIENTS) { |
|
4334 |
fprintf(stderr, "qemu: too many network clients\n"); |
|
3845 | 4335 |
exit(1); |
3846 | 4336 |
} |
3847 |
break; |
|
3848 |
case QEMU_OPTION_macaddr: |
|
3849 |
{ |
|
3850 |
const char *p; |
|
3851 |
int i; |
|
3852 |
p = optarg; |
|
3853 |
for(i = 0; i < 6; i++) { |
|
3854 |
macaddr[i] = strtol(p, (char **)&p, 16); |
|
3855 |
if (i == 5) { |
|
3856 |
if (*p != '\0') |
|
3857 |
goto macaddr_error; |
|
3858 |
} else { |
|
3859 |
if (*p != ':') { |
|
3860 |
macaddr_error: |
|
3861 |
fprintf(stderr, "qemu: invalid syntax for ethernet address\n"); |
|
3862 |
exit(1); |
|
3863 |
} |
|
3864 |
p++; |
|
3865 |
} |
|
3866 |
} |
|
3867 |
} |
|
4337 |
pstrcpy(net_clients[nb_net_clients], |
|
4338 |
sizeof(net_clients[0]), |
|
4339 |
optarg); |
|
4340 |
nb_net_clients++; |
|
3868 | 4341 |
break; |
3869 | 4342 |
#ifdef CONFIG_SLIRP |
3870 | 4343 |
case QEMU_OPTION_tftp: |
... | ... | |
3875 | 4348 |
net_slirp_smb(optarg); |
3876 | 4349 |
break; |
3877 | 4350 |
#endif |
3878 |
case QEMU_OPTION_user_net: |
|
3879 |
net_if_type = NET_IF_USER; |
|
3880 |
break; |
|
3881 | 4351 |
case QEMU_OPTION_redir: |
3882 | 4352 |
net_slirp_redir(optarg); |
3883 | 4353 |
break; |
3884 | 4354 |
#endif |
3885 |
case QEMU_OPTION_dummy_net: |
|
3886 |
net_if_type = NET_IF_DUMMY; |
|
3887 |
break; |
|
3888 | 4355 |
#ifdef HAS_AUDIO |
3889 | 4356 |
case QEMU_OPTION_enable_audio: |
3890 | 4357 |
audio_enabled = 1; |
... | ... | |
3930 | 4397 |
cpu_set_log(mask); |
3931 | 4398 |
} |
3932 | 4399 |
break; |
3933 |
case QEMU_OPTION_n: |
|
3934 |
pstrcpy(network_script, sizeof(network_script), optarg); |
|
3935 |
break; |
|
3936 | 4400 |
#ifdef CONFIG_GDBSTUB |
3937 | 4401 |
case QEMU_OPTION_s: |
3938 | 4402 |
use_gdbstub = 1; |
... | ... | |
4076 | 4540 |
#else |
4077 | 4541 |
setvbuf(stdout, NULL, _IOLBF, 0); |
4078 | 4542 |
#endif |
4079 |
|
|
4080 |
/* init host network redirectors */
|
|
4081 |
if (net_if_type == -1) {
|
|
4082 |
net_if_type = NET_IF_TUN;
|
|
4083 |
#if defined(CONFIG_SLIRP)
|
|
4084 |
if (access(network_script, R_OK) < 0) {
|
|
4085 |
net_if_type = NET_IF_USER;
|
|
4086 |
}
|
|
4087 |
#endif
|
|
4543 |
|
|
4544 |
/* init network clients */
|
|
4545 |
if (nb_net_clients == 0) {
|
|
4546 |
/* if no clients, we use a default config */
|
|
4547 |
pstrcpy(net_clients[0], sizeof(net_clients[0]),
|
|
4548 |
"nic");
|
|
4549 |
pstrcpy(net_clients[1], sizeof(net_clients[0]),
|
|
4550 |
"user");
|
|
4551 |
nb_net_clients = 2;
|
|
4088 | 4552 |
} |
4089 | 4553 |
|
4090 |
for(i = 0; i < nb_nics; i++) { |
|
4091 |
NetDriverState *nd = &nd_table[i]; |
|
4092 |
nd->index = i; |
|
4093 |
/* init virtual mac address */ |
|
4094 |
nd->macaddr[0] = macaddr[0]; |
|
4095 |
nd->macaddr[1] = macaddr[1]; |
|
4096 |
nd->macaddr[2] = macaddr[2]; |
|
4097 |
nd->macaddr[3] = macaddr[3]; |
|
4098 |
nd->macaddr[4] = macaddr[4]; |
|
4099 |
nd->macaddr[5] = macaddr[5] + i; |
|
4100 |
switch(net_if_type) { |
|
4101 |
#if defined(CONFIG_SLIRP) |
|
4102 |
case NET_IF_USER: |
|
4103 |
net_slirp_init(nd); |
|
4104 |
break; |
|
4105 |
#endif |
|
4106 |
#if !defined(_WIN32) |
|
4107 |
case NET_IF_TUN: |
|
4108 |
if (i < nb_tun_fds) { |
|
4109 |
net_fd_init(nd, tun_fds[i]); |
|
4110 |
} else { |
|
4111 |
if (net_tun_init(nd) < 0) |
|
4112 |
net_dummy_init(nd); |
|
4113 |
} |
|
4114 |
break; |
|
4115 |
#endif |
|
4116 |
case NET_IF_DUMMY: |
|
4117 |
default: |
|
4118 |
net_dummy_init(nd); |
|
4119 |
break; |
|
4120 |
} |
|
4554 |
for(i = 0;i < nb_net_clients; i++) { |
|
4555 |
if (net_client_init(net_clients[i]) < 0) |
|
4556 |
exit(1); |
|
4121 | 4557 |
} |
4122 | 4558 |
|
4123 | 4559 |
/* init the memory */ |
Also available in: Unified diff