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;
|