mirror of https://gitee.com/openkylin/qemu.git
Avoid buffer overflow when sending slirp packets.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1744 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
parent
191abaa2f0
commit
d861b05ea3
|
@ -283,6 +283,11 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = {
|
||||||
|
|
||||||
#define MIN_BUF_SIZE 60
|
#define MIN_BUF_SIZE 60
|
||||||
|
|
||||||
|
static void lance_can_receive(void *opaque)
|
||||||
|
{
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void lance_receive(void *opaque, const uint8_t *buf, int size)
|
static void lance_receive(void *opaque, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
LANCEState *s = opaque;
|
LANCEState *s = opaque;
|
||||||
|
@ -440,7 +445,7 @@ void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr)
|
||||||
|
|
||||||
lance_reset(s);
|
lance_reset(s);
|
||||||
|
|
||||||
s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, s);
|
s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, s);
|
||||||
|
|
||||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||||
"lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
"lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
|
27
hw/ne2000.c
27
hw/ne2000.c
|
@ -200,14 +200,10 @@ static int compute_mcast_idx(const uint8_t *ep)
|
||||||
return (crc >> 26);
|
return (crc >> 26);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* return the max buffer size if the NE2000 can receive more data */
|
static int ne2000_buffer_full(NE2000State *s)
|
||||||
static int ne2000_can_receive(void *opaque)
|
|
||||||
{
|
{
|
||||||
NE2000State *s = opaque;
|
|
||||||
int avail, index, boundary;
|
int avail, index, boundary;
|
||||||
|
|
||||||
if (s->cmd & E8390_STOP)
|
|
||||||
return 0;
|
|
||||||
index = s->curpag << 8;
|
index = s->curpag << 8;
|
||||||
boundary = s->boundary << 8;
|
boundary = s->boundary << 8;
|
||||||
if (index < boundary)
|
if (index < boundary)
|
||||||
|
@ -215,8 +211,17 @@ static int ne2000_can_receive(void *opaque)
|
||||||
else
|
else
|
||||||
avail = (s->stop - s->start) - (index - boundary);
|
avail = (s->stop - s->start) - (index - boundary);
|
||||||
if (avail < (MAX_ETH_FRAME_SIZE + 4))
|
if (avail < (MAX_ETH_FRAME_SIZE + 4))
|
||||||
return 0;
|
return 1;
|
||||||
return MAX_ETH_FRAME_SIZE;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ne2000_can_receive(void *opaque)
|
||||||
|
{
|
||||||
|
NE2000State *s = opaque;
|
||||||
|
|
||||||
|
if (s->cmd & E8390_STOP)
|
||||||
|
return 1;
|
||||||
|
return !ne2000_buffer_full(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
#define MIN_BUF_SIZE 60
|
#define MIN_BUF_SIZE 60
|
||||||
|
@ -234,7 +239,7 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size)
|
||||||
printf("NE2000: received len=%d\n", size);
|
printf("NE2000: received len=%d\n", size);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!ne2000_can_receive(s))
|
if (s->cmd & E8390_STOP || ne2000_buffer_full(s))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* XXX: check this */
|
/* XXX: check this */
|
||||||
|
@ -722,7 +727,8 @@ void isa_ne2000_init(int base, int irq, NICInfo *nd)
|
||||||
|
|
||||||
ne2000_reset(s);
|
ne2000_reset(s);
|
||||||
|
|
||||||
s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s);
|
s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
|
||||||
|
ne2000_can_receive, s);
|
||||||
|
|
||||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||||
"ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
"ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
@ -791,7 +797,8 @@ void pci_ne2000_init(PCIBus *bus, NICInfo *nd)
|
||||||
s->pci_dev = (PCIDevice *)d;
|
s->pci_dev = (PCIDevice *)d;
|
||||||
memcpy(s->macaddr, nd->macaddr, 6);
|
memcpy(s->macaddr, nd->macaddr, 6);
|
||||||
ne2000_reset(s);
|
ne2000_reset(s);
|
||||||
s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s);
|
s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive,
|
||||||
|
ne2000_can_receive, s);
|
||||||
|
|
||||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||||
"ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
"ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
|
||||||
|
|
|
@ -593,6 +593,17 @@ static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset)
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int smc91c111_can_receive(void *opaque)
|
||||||
|
{
|
||||||
|
smc91c111_state *s = (smc91c111_state *)opaque;
|
||||||
|
|
||||||
|
if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
|
||||||
|
return 1;
|
||||||
|
if (s->allocated == (1 << NUM_PACKETS) - 1)
|
||||||
|
return 0;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
static void smc91c111_receive(void *opaque, const uint8_t *buf, int size)
|
static void smc91c111_receive(void *opaque, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
smc91c111_state *s = (smc91c111_state *)opaque;
|
smc91c111_state *s = (smc91c111_state *)opaque;
|
||||||
|
@ -697,6 +708,7 @@ void smc91c111_init(NICInfo *nd, uint32_t base, void *pic, int irq)
|
||||||
|
|
||||||
smc91c111_reset(s);
|
smc91c111_reset(s);
|
||||||
|
|
||||||
s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive, s);
|
s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive,
|
||||||
|
smc91c111_can_receive, s);
|
||||||
/* ??? Save/restore. */
|
/* ??? Save/restore. */
|
||||||
}
|
}
|
||||||
|
|
29
vl.c
29
vl.c
|
@ -1842,13 +1842,16 @@ VLANState *qemu_find_vlan(int id)
|
||||||
}
|
}
|
||||||
|
|
||||||
VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
||||||
IOReadHandler *fd_read, void *opaque)
|
IOReadHandler *fd_read,
|
||||||
|
IOCanRWHandler *fd_can_read,
|
||||||
|
void *opaque)
|
||||||
{
|
{
|
||||||
VLANClientState *vc, **pvc;
|
VLANClientState *vc, **pvc;
|
||||||
vc = qemu_mallocz(sizeof(VLANClientState));
|
vc = qemu_mallocz(sizeof(VLANClientState));
|
||||||
if (!vc)
|
if (!vc)
|
||||||
return NULL;
|
return NULL;
|
||||||
vc->fd_read = fd_read;
|
vc->fd_read = fd_read;
|
||||||
|
vc->fd_can_read = fd_can_read;
|
||||||
vc->opaque = opaque;
|
vc->opaque = opaque;
|
||||||
vc->vlan = vlan;
|
vc->vlan = vlan;
|
||||||
|
|
||||||
|
@ -1860,6 +1863,20 @@ VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
||||||
return vc;
|
return vc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int qemu_can_send_packet(VLANClientState *vc1)
|
||||||
|
{
|
||||||
|
VLANState *vlan = vc1->vlan;
|
||||||
|
VLANClientState *vc;
|
||||||
|
|
||||||
|
for(vc = vlan->first_client; vc != NULL; vc = vc->next) {
|
||||||
|
if (vc != vc1) {
|
||||||
|
if (vc->fd_can_read && !vc->fd_can_read(vc->opaque))
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
|
void qemu_send_packet(VLANClientState *vc1, const uint8_t *buf, int size)
|
||||||
{
|
{
|
||||||
VLANState *vlan = vc1->vlan;
|
VLANState *vlan = vc1->vlan;
|
||||||
|
@ -1885,7 +1902,7 @@ static VLANClientState *slirp_vc;
|
||||||
|
|
||||||
int slirp_can_output(void)
|
int slirp_can_output(void)
|
||||||
{
|
{
|
||||||
return 1;
|
return qemu_can_send_packet(slirp_vc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void slirp_output(const uint8_t *pkt, int pkt_len)
|
void slirp_output(const uint8_t *pkt, int pkt_len)
|
||||||
|
@ -1913,7 +1930,7 @@ static int net_slirp_init(VLANState *vlan)
|
||||||
slirp_init();
|
slirp_init();
|
||||||
}
|
}
|
||||||
slirp_vc = qemu_new_vlan_client(vlan,
|
slirp_vc = qemu_new_vlan_client(vlan,
|
||||||
slirp_receive, NULL);
|
slirp_receive, NULL, NULL);
|
||||||
snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector");
|
snprintf(slirp_vc->info_str, sizeof(slirp_vc->info_str), "user redirector");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -2098,7 +2115,7 @@ static TAPState *net_tap_fd_init(VLANState *vlan, int fd)
|
||||||
if (!s)
|
if (!s)
|
||||||
return NULL;
|
return NULL;
|
||||||
s->fd = fd;
|
s->fd = fd;
|
||||||
s->vc = qemu_new_vlan_client(vlan, tap_receive, s);
|
s->vc = qemu_new_vlan_client(vlan, tap_receive, NULL, s);
|
||||||
qemu_set_fd_handler(s->fd, tap_send, NULL, s);
|
qemu_set_fd_handler(s->fd, tap_send, NULL, s);
|
||||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd);
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str), "tap: fd=%d", fd);
|
||||||
return s;
|
return s;
|
||||||
|
@ -2412,7 +2429,7 @@ static NetSocketState *net_socket_fd_init_dgram(VLANState *vlan, int fd,
|
||||||
return NULL;
|
return NULL;
|
||||||
s->fd = fd;
|
s->fd = fd;
|
||||||
|
|
||||||
s->vc = qemu_new_vlan_client(vlan, net_socket_receive_dgram, s);
|
s->vc = qemu_new_vlan_client(vlan, net_socket_receive_dgram, NULL, s);
|
||||||
qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
|
qemu_set_fd_handler(s->fd, net_socket_send_dgram, NULL, s);
|
||||||
|
|
||||||
/* mcast: save bound address as dst */
|
/* mcast: save bound address as dst */
|
||||||
|
@ -2440,7 +2457,7 @@ static NetSocketState *net_socket_fd_init_stream(VLANState *vlan, int fd,
|
||||||
return NULL;
|
return NULL;
|
||||||
s->fd = fd;
|
s->fd = fd;
|
||||||
s->vc = qemu_new_vlan_client(vlan,
|
s->vc = qemu_new_vlan_client(vlan,
|
||||||
net_socket_receive, s);
|
net_socket_receive, NULL, s);
|
||||||
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
snprintf(s->vc->info_str, sizeof(s->vc->info_str),
|
||||||
"socket: fd=%d", fd);
|
"socket: fd=%d", fd);
|
||||||
if (is_connected) {
|
if (is_connected) {
|
||||||
|
|
9
vl.h
9
vl.h
|
@ -279,6 +279,9 @@ typedef struct VLANClientState VLANClientState;
|
||||||
|
|
||||||
struct VLANClientState {
|
struct VLANClientState {
|
||||||
IOReadHandler *fd_read;
|
IOReadHandler *fd_read;
|
||||||
|
/* Packets may still be sent if this returns zero. It's used to
|
||||||
|
rate-limit the slirp code. */
|
||||||
|
IOCanRWHandler *fd_can_read;
|
||||||
void *opaque;
|
void *opaque;
|
||||||
struct VLANClientState *next;
|
struct VLANClientState *next;
|
||||||
struct VLANState *vlan;
|
struct VLANState *vlan;
|
||||||
|
@ -293,8 +296,12 @@ typedef struct VLANState {
|
||||||
|
|
||||||
VLANState *qemu_find_vlan(int id);
|
VLANState *qemu_find_vlan(int id);
|
||||||
VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
VLANClientState *qemu_new_vlan_client(VLANState *vlan,
|
||||||
IOReadHandler *fd_read, void *opaque);
|
IOReadHandler *fd_read,
|
||||||
|
IOCanRWHandler *fd_can_read,
|
||||||
|
void *opaque);
|
||||||
|
int qemu_can_send_packet(VLANClientState *vc);
|
||||||
void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size);
|
void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size);
|
||||||
|
void qemu_handler_true(void *opaque);
|
||||||
|
|
||||||
void do_info_network(void);
|
void do_info_network(void);
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue