Commit 7c9d8e07e188597e570a311efc46cb1ab013e5e7
1 parent
868bfe2b
new network emulation
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1622 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
7 changed files
with
902 additions
and
419 deletions
gdbstub.c
@@ -704,19 +704,19 @@ void gdb_exit(CPUState *env, int code) | @@ -704,19 +704,19 @@ void gdb_exit(CPUState *env, int code) | ||
704 | } | 704 | } |
705 | 705 | ||
706 | #else | 706 | #else |
707 | -static int gdb_can_read(void *opaque) | ||
708 | -{ | ||
709 | - return 256; | ||
710 | -} | ||
711 | - | ||
712 | -static void gdb_read(void *opaque, const uint8_t *buf, int size) | 707 | +static void gdb_read(void *opaque) |
713 | { | 708 | { |
714 | GDBState *s = opaque; | 709 | GDBState *s = opaque; |
715 | - int i; | 710 | + int i, size; |
711 | + uint8_t buf[4096]; | ||
712 | + | ||
713 | + size = read(s->fd, buf, sizeof(buf)); | ||
714 | + if (size < 0) | ||
715 | + return; | ||
716 | if (size == 0) { | 716 | if (size == 0) { |
717 | /* end of connection */ | 717 | /* end of connection */ |
718 | qemu_del_vm_stop_handler(gdb_vm_stopped, s); | 718 | qemu_del_vm_stop_handler(gdb_vm_stopped, s); |
719 | - qemu_del_fd_read_handler(s->fd); | 719 | + qemu_set_fd_handler(s->fd, NULL, NULL, NULL); |
720 | qemu_free(s); | 720 | qemu_free(s); |
721 | vm_start(); | 721 | vm_start(); |
722 | } else { | 722 | } else { |
@@ -727,7 +727,7 @@ static void gdb_read(void *opaque, const uint8_t *buf, int size) | @@ -727,7 +727,7 @@ static void gdb_read(void *opaque, const uint8_t *buf, int size) | ||
727 | 727 | ||
728 | #endif | 728 | #endif |
729 | 729 | ||
730 | -static void gdb_accept(void *opaque, const uint8_t *buf, int size) | 730 | +static void gdb_accept(void *opaque) |
731 | { | 731 | { |
732 | GDBState *s; | 732 | GDBState *s; |
733 | struct sockaddr_in sockaddr; | 733 | struct sockaddr_in sockaddr; |
@@ -768,7 +768,7 @@ static void gdb_accept(void *opaque, const uint8_t *buf, int size) | @@ -768,7 +768,7 @@ static void gdb_accept(void *opaque, const uint8_t *buf, int size) | ||
768 | vm_stop(EXCP_INTERRUPT); | 768 | vm_stop(EXCP_INTERRUPT); |
769 | 769 | ||
770 | /* start handling I/O */ | 770 | /* start handling I/O */ |
771 | - qemu_add_fd_read_handler(s->fd, gdb_can_read, gdb_read, s); | 771 | + qemu_set_fd_handler(s->fd, gdb_read, NULL, s); |
772 | /* when the VM is stopped, the following callback is called */ | 772 | /* when the VM is stopped, the following callback is called */ |
773 | qemu_add_vm_stop_handler(gdb_vm_stopped, s); | 773 | qemu_add_vm_stop_handler(gdb_vm_stopped, s); |
774 | #endif | 774 | #endif |
@@ -815,9 +815,9 @@ int gdbserver_start(int port) | @@ -815,9 +815,9 @@ int gdbserver_start(int port) | ||
815 | return -1; | 815 | return -1; |
816 | /* accept connections */ | 816 | /* accept connections */ |
817 | #ifdef CONFIG_USER_ONLY | 817 | #ifdef CONFIG_USER_ONLY |
818 | - gdb_accept (NULL, NULL, 0); | 818 | + gdb_accept (NULL); |
819 | #else | 819 | #else |
820 | - qemu_add_fd_read_handler(gdbserver_fd, NULL, gdb_accept, NULL); | 820 | + qemu_set_fd_handler(gdbserver_fd, gdb_accept, NULL, NULL); |
821 | #endif | 821 | #endif |
822 | return 0; | 822 | return 0; |
823 | } | 823 | } |
hw/lance.c
@@ -154,7 +154,8 @@ struct lance_init_block { | @@ -154,7 +154,8 @@ struct lance_init_block { | ||
154 | #define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) | 154 | #define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) |
155 | 155 | ||
156 | typedef struct LANCEState { | 156 | typedef struct LANCEState { |
157 | - NetDriverState *nd; | 157 | + VLANClientState *vc; |
158 | + uint8_t macaddr[6]; /* init mac address */ | ||
158 | uint32_t leptr; | 159 | uint32_t leptr; |
159 | uint16_t addr; | 160 | uint16_t addr; |
160 | uint16_t regs[LE_NREGS]; | 161 | uint16_t regs[LE_NREGS]; |
@@ -169,7 +170,7 @@ static void lance_send(void *opaque); | @@ -169,7 +170,7 @@ static void lance_send(void *opaque); | ||
169 | static void lance_reset(void *opaque) | 170 | static void lance_reset(void *opaque) |
170 | { | 171 | { |
171 | LANCEState *s = opaque; | 172 | LANCEState *s = opaque; |
172 | - memcpy(s->phys, s->nd->macaddr, 6); | 173 | + memcpy(s->phys, s->macaddr, 6); |
173 | s->rxptr = 0; | 174 | s->rxptr = 0; |
174 | s->txptr = 0; | 175 | s->txptr = 0; |
175 | memset(s->regs, 0, LE_NREGS * 2); | 176 | memset(s->regs, 0, LE_NREGS * 2); |
@@ -280,31 +281,6 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = { | @@ -280,31 +281,6 @@ static CPUWriteMemoryFunc *lance_mem_write[3] = { | ||
280 | }; | 281 | }; |
281 | 282 | ||
282 | 283 | ||
283 | -/* return the max buffer size if the LANCE can receive more data */ | ||
284 | -static int lance_can_receive(void *opaque) | ||
285 | -{ | ||
286 | - LANCEState *s = opaque; | ||
287 | - uint32_t dmaptr = s->leptr + s->ledmaregs[3]; | ||
288 | - struct lance_init_block *ib; | ||
289 | - int i; | ||
290 | - uint8_t temp8; | ||
291 | - | ||
292 | - if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) | ||
293 | - return 0; | ||
294 | - | ||
295 | - ib = (void *) iommu_translate(dmaptr); | ||
296 | - | ||
297 | - for (i = 0; i < RX_RING_SIZE; i++) { | ||
298 | - cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); | ||
299 | - if (temp8 == (LE_R1_OWN)) { | ||
300 | - DPRINTF("can receive %d\n", RX_BUFF_SIZE); | ||
301 | - return RX_BUFF_SIZE; | ||
302 | - } | ||
303 | - } | ||
304 | - DPRINTF("cannot receive\n"); | ||
305 | - return 0; | ||
306 | -} | ||
307 | - | ||
308 | #define MIN_BUF_SIZE 60 | 284 | #define MIN_BUF_SIZE 60 |
309 | 285 | ||
310 | static void lance_receive(void *opaque, const uint8_t *buf, int size) | 286 | static void lance_receive(void *opaque, const uint8_t *buf, int size) |
@@ -368,7 +344,7 @@ static void lance_send(void *opaque) | @@ -368,7 +344,7 @@ static void lance_send(void *opaque) | ||
368 | temp16 = (~temp16) + 1; | 344 | temp16 = (~temp16) + 1; |
369 | cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16); | 345 | cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16); |
370 | DPRINTF("sending packet, len %d\n", temp16); | 346 | DPRINTF("sending packet, len %d\n", temp16); |
371 | - qemu_send_packet(s->nd, pkt_buf, temp16); | 347 | + qemu_send_packet(s->vc, pkt_buf, temp16); |
372 | temp8 = LE_T1_POK; | 348 | temp8 = LE_T1_POK; |
373 | cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); | 349 | cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); |
374 | s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; | 350 | s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; |
@@ -443,7 +419,7 @@ static int lance_load(QEMUFile *f, void *opaque, int version_id) | @@ -443,7 +419,7 @@ static int lance_load(QEMUFile *f, void *opaque, int version_id) | ||
443 | return 0; | 419 | return 0; |
444 | } | 420 | } |
445 | 421 | ||
446 | -void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | 422 | +void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr) |
447 | { | 423 | { |
448 | LANCEState *s; | 424 | LANCEState *s; |
449 | int lance_io_memory, ledma_io_memory; | 425 | int lance_io_memory, ledma_io_memory; |
@@ -452,7 +428,6 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | @@ -452,7 +428,6 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | ||
452 | if (!s) | 428 | if (!s) |
453 | return; | 429 | return; |
454 | 430 | ||
455 | - s->nd = nd; | ||
456 | s->irq = irq; | 431 | s->irq = irq; |
457 | 432 | ||
458 | lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); | 433 | lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); |
@@ -461,8 +436,21 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | @@ -461,8 +436,21 @@ void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr) | ||
461 | ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); | 436 | ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); |
462 | cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); | 437 | cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); |
463 | 438 | ||
439 | + memcpy(s->macaddr, nd->macaddr, 6); | ||
440 | + | ||
464 | lance_reset(s); | 441 | lance_reset(s); |
465 | - qemu_add_read_packet(nd, lance_can_receive, lance_receive, s); | 442 | + |
443 | + s->vc = qemu_new_vlan_client(nd->vlan, lance_receive, s); | ||
444 | + | ||
445 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | ||
446 | + "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | ||
447 | + s->macaddr[0], | ||
448 | + s->macaddr[1], | ||
449 | + s->macaddr[2], | ||
450 | + s->macaddr[3], | ||
451 | + s->macaddr[4], | ||
452 | + s->macaddr[5]); | ||
453 | + | ||
466 | register_savevm("lance", leaddr, 1, lance_save, lance_load, s); | 454 | register_savevm("lance", leaddr, 1, lance_save, lance_load, s); |
467 | qemu_register_reset(lance_reset, s); | 455 | qemu_register_reset(lance_reset, s); |
468 | } | 456 | } |
hw/ne2000.c
@@ -122,6 +122,7 @@ typedef struct NE2000State { | @@ -122,6 +122,7 @@ typedef struct NE2000State { | ||
122 | uint16_t rcnt; | 122 | uint16_t rcnt; |
123 | uint32_t rsar; | 123 | uint32_t rsar; |
124 | uint8_t rsr; | 124 | uint8_t rsr; |
125 | + uint8_t rxcr; | ||
125 | uint8_t isr; | 126 | uint8_t isr; |
126 | uint8_t dcfg; | 127 | uint8_t dcfg; |
127 | uint8_t imr; | 128 | uint8_t imr; |
@@ -130,7 +131,8 @@ typedef struct NE2000State { | @@ -130,7 +131,8 @@ typedef struct NE2000State { | ||
130 | uint8_t mult[8]; /* multicast mask array */ | 131 | uint8_t mult[8]; /* multicast mask array */ |
131 | int irq; | 132 | int irq; |
132 | PCIDevice *pci_dev; | 133 | PCIDevice *pci_dev; |
133 | - NetDriverState *nd; | 134 | + VLANClientState *vc; |
135 | + uint8_t macaddr[6]; | ||
134 | uint8_t mem[NE2000_MEM_SIZE]; | 136 | uint8_t mem[NE2000_MEM_SIZE]; |
135 | } NE2000State; | 137 | } NE2000State; |
136 | 138 | ||
@@ -139,7 +141,7 @@ static void ne2000_reset(NE2000State *s) | @@ -139,7 +141,7 @@ static void ne2000_reset(NE2000State *s) | ||
139 | int i; | 141 | int i; |
140 | 142 | ||
141 | s->isr = ENISR_RESET; | 143 | s->isr = ENISR_RESET; |
142 | - memcpy(s->mem, s->nd->macaddr, 6); | 144 | + memcpy(s->mem, s->macaddr, 6); |
143 | s->mem[14] = 0x57; | 145 | s->mem[14] = 0x57; |
144 | s->mem[15] = 0x57; | 146 | s->mem[15] = 0x57; |
145 | 147 | ||
@@ -167,6 +169,30 @@ static void ne2000_update_irq(NE2000State *s) | @@ -167,6 +169,30 @@ static void ne2000_update_irq(NE2000State *s) | ||
167 | } | 169 | } |
168 | } | 170 | } |
169 | 171 | ||
172 | +#define POLYNOMIAL 0x04c11db6 | ||
173 | + | ||
174 | +/* From FreeBSD */ | ||
175 | +/* XXX: optimize */ | ||
176 | +static int compute_mcast_idx(const uint8_t *ep) | ||
177 | +{ | ||
178 | + uint32_t crc; | ||
179 | + int carry, i, j; | ||
180 | + uint8_t b; | ||
181 | + | ||
182 | + crc = 0xffffffff; | ||
183 | + for (i = 0; i < 6; i++) { | ||
184 | + b = *ep++; | ||
185 | + for (j = 0; j < 8; j++) { | ||
186 | + carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01); | ||
187 | + crc <<= 1; | ||
188 | + b >>= 1; | ||
189 | + if (carry) | ||
190 | + crc = ((crc ^ POLYNOMIAL) | carry); | ||
191 | + } | ||
192 | + } | ||
193 | + return (crc >> 26); | ||
194 | +} | ||
195 | + | ||
170 | /* return the max buffer size if the NE2000 can receive more data */ | 196 | /* return the max buffer size if the NE2000 can receive more data */ |
171 | static int ne2000_can_receive(void *opaque) | 197 | static int ne2000_can_receive(void *opaque) |
172 | { | 198 | { |
@@ -192,13 +218,46 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size) | @@ -192,13 +218,46 @@ static void ne2000_receive(void *opaque, const uint8_t *buf, int size) | ||
192 | { | 218 | { |
193 | NE2000State *s = opaque; | 219 | NE2000State *s = opaque; |
194 | uint8_t *p; | 220 | uint8_t *p; |
195 | - int total_len, next, avail, len, index; | 221 | + int total_len, next, avail, len, index, mcast_idx; |
196 | uint8_t buf1[60]; | 222 | uint8_t buf1[60]; |
223 | + static const uint8_t broadcast_macaddr[6] = | ||
224 | + { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | ||
197 | 225 | ||
198 | #if defined(DEBUG_NE2000) | 226 | #if defined(DEBUG_NE2000) |
199 | printf("NE2000: received len=%d\n", size); | 227 | printf("NE2000: received len=%d\n", size); |
200 | #endif | 228 | #endif |
201 | 229 | ||
230 | + if (!ne2000_can_receive(s)) | ||
231 | + return; | ||
232 | + | ||
233 | + /* XXX: check this */ | ||
234 | + if (s->rxcr & 0x10) { | ||
235 | + /* promiscuous: receive all */ | ||
236 | + } else { | ||
237 | + if (!memcmp(buf, broadcast_macaddr, 6)) { | ||
238 | + /* broadcast address */ | ||
239 | + if (!(s->rxcr & 0x04)) | ||
240 | + return; | ||
241 | + } else if (buf[0] & 0x01) { | ||
242 | + /* multicast */ | ||
243 | + if (!(s->rxcr & 0x08)) | ||
244 | + return; | ||
245 | + mcast_idx = compute_mcast_idx(buf); | ||
246 | + if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) | ||
247 | + return; | ||
248 | + } else if (s->mem[0] == buf[0] && | ||
249 | + s->mem[2] == buf[1] && | ||
250 | + s->mem[4] == buf[2] && | ||
251 | + s->mem[6] == buf[3] && | ||
252 | + s->mem[8] == buf[4] && | ||
253 | + s->mem[10] == buf[5]) { | ||
254 | + /* match */ | ||
255 | + } else { | ||
256 | + return; | ||
257 | + } | ||
258 | + } | ||
259 | + | ||
260 | + | ||
202 | /* if too small buffer, then expand it */ | 261 | /* if too small buffer, then expand it */ |
203 | if (size < MIN_BUF_SIZE) { | 262 | if (size < MIN_BUF_SIZE) { |
204 | memcpy(buf1, buf, size); | 263 | memcpy(buf1, buf, size); |
@@ -273,7 +332,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -273,7 +332,7 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
273 | index -= NE2000_PMEM_SIZE; | 332 | index -= NE2000_PMEM_SIZE; |
274 | /* fail safe: check range on the transmitted length */ | 333 | /* fail safe: check range on the transmitted length */ |
275 | if (index + s->tcnt <= NE2000_PMEM_END) { | 334 | if (index + s->tcnt <= NE2000_PMEM_END) { |
276 | - qemu_send_packet(s->nd, s->mem + index, s->tcnt); | 335 | + qemu_send_packet(s->vc, s->mem + index, s->tcnt); |
277 | } | 336 | } |
278 | /* signal end of transfert */ | 337 | /* signal end of transfert */ |
279 | s->tsr = ENTSR_PTX; | 338 | s->tsr = ENTSR_PTX; |
@@ -320,6 +379,9 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) | @@ -320,6 +379,9 @@ static void ne2000_ioport_write(void *opaque, uint32_t addr, uint32_t val) | ||
320 | case EN0_RCNTHI: | 379 | case EN0_RCNTHI: |
321 | s->rcnt = (s->rcnt & 0x00ff) | (val << 8); | 380 | s->rcnt = (s->rcnt & 0x00ff) | (val << 8); |
322 | break; | 381 | break; |
382 | + case EN0_RXCR: | ||
383 | + s->rxcr = val; | ||
384 | + break; | ||
323 | case EN0_DCFG: | 385 | case EN0_DCFG: |
324 | s->dcfg = val; | 386 | s->dcfg = val; |
325 | break; | 387 | break; |
@@ -608,10 +670,10 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id) | @@ -608,10 +670,10 @@ static int ne2000_load(QEMUFile* f,void* opaque,int version_id) | ||
608 | return 0; | 670 | return 0; |
609 | } | 671 | } |
610 | 672 | ||
611 | -void isa_ne2000_init(int base, int irq, NetDriverState *nd) | 673 | +void isa_ne2000_init(int base, int irq, NICInfo *nd) |
612 | { | 674 | { |
613 | NE2000State *s; | 675 | NE2000State *s; |
614 | - | 676 | + |
615 | s = qemu_mallocz(sizeof(NE2000State)); | 677 | s = qemu_mallocz(sizeof(NE2000State)); |
616 | if (!s) | 678 | if (!s) |
617 | return; | 679 | return; |
@@ -627,14 +689,22 @@ void isa_ne2000_init(int base, int irq, NetDriverState *nd) | @@ -627,14 +689,22 @@ void isa_ne2000_init(int base, int irq, NetDriverState *nd) | ||
627 | register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); | 689 | register_ioport_write(base + 0x1f, 1, 1, ne2000_reset_ioport_write, s); |
628 | register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); | 690 | register_ioport_read(base + 0x1f, 1, 1, ne2000_reset_ioport_read, s); |
629 | s->irq = irq; | 691 | s->irq = irq; |
630 | - s->nd = nd; | 692 | + memcpy(s->macaddr, nd->macaddr, 6); |
631 | 693 | ||
632 | ne2000_reset(s); | 694 | ne2000_reset(s); |
633 | 695 | ||
634 | - qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); | ||
635 | - | 696 | + s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s); |
697 | + | ||
698 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | ||
699 | + "ne2000 macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | ||
700 | + s->macaddr[0], | ||
701 | + s->macaddr[1], | ||
702 | + s->macaddr[2], | ||
703 | + s->macaddr[3], | ||
704 | + s->macaddr[4], | ||
705 | + s->macaddr[5]); | ||
706 | + | ||
636 | register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); | 707 | register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); |
637 | - | ||
638 | } | 708 | } |
639 | 709 | ||
640 | /***********************************************************/ | 710 | /***********************************************************/ |
@@ -665,7 +735,7 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num, | @@ -665,7 +735,7 @@ static void ne2000_map(PCIDevice *pci_dev, int region_num, | ||
665 | register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); | 735 | register_ioport_read(addr + 0x1f, 1, 1, ne2000_reset_ioport_read, s); |
666 | } | 736 | } |
667 | 737 | ||
668 | -void pci_ne2000_init(PCIBus *bus, NetDriverState *nd) | 738 | +void pci_ne2000_init(PCIBus *bus, NICInfo *nd) |
669 | { | 739 | { |
670 | PCINE2000State *d; | 740 | PCINE2000State *d; |
671 | NE2000State *s; | 741 | NE2000State *s; |
@@ -690,10 +760,19 @@ void pci_ne2000_init(PCIBus *bus, NetDriverState *nd) | @@ -690,10 +760,19 @@ void pci_ne2000_init(PCIBus *bus, NetDriverState *nd) | ||
690 | s = &d->ne2000; | 760 | s = &d->ne2000; |
691 | s->irq = 16; // PCI interrupt | 761 | s->irq = 16; // PCI interrupt |
692 | s->pci_dev = (PCIDevice *)d; | 762 | s->pci_dev = (PCIDevice *)d; |
693 | - s->nd = nd; | 763 | + memcpy(s->macaddr, nd->macaddr, 6); |
694 | ne2000_reset(s); | 764 | ne2000_reset(s); |
695 | - qemu_add_read_packet(nd, ne2000_can_receive, ne2000_receive, s); | ||
696 | - | 765 | + s->vc = qemu_new_vlan_client(nd->vlan, ne2000_receive, s); |
766 | + | ||
767 | + snprintf(s->vc->info_str, sizeof(s->vc->info_str), | ||
768 | + "ne2000 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | ||
769 | + s->macaddr[0], | ||
770 | + s->macaddr[1], | ||
771 | + s->macaddr[2], | ||
772 | + s->macaddr[3], | ||
773 | + s->macaddr[4], | ||
774 | + s->macaddr[5]); | ||
775 | + | ||
697 | /* XXX: instance number ? */ | 776 | /* XXX: instance number ? */ |
698 | register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); | 777 | register_savevm("ne2000", 0, 1, ne2000_save, ne2000_load, s); |
699 | register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, | 778 | register_savevm("ne2000_pci", 0, 1, generic_pci_save, generic_pci_load, |
hw/parallel.c
@@ -154,27 +154,6 @@ static uint32_t parallel_ioport_read(void *opaque, uint32_t addr) | @@ -154,27 +154,6 @@ static uint32_t parallel_ioport_read(void *opaque, uint32_t addr) | ||
154 | return ret; | 154 | return ret; |
155 | } | 155 | } |
156 | 156 | ||
157 | -static int parallel_can_receive(ParallelState *s) | ||
158 | -{ | ||
159 | - return 0; | ||
160 | -} | ||
161 | - | ||
162 | -static void parallel_receive_byte(ParallelState *s, int ch) | ||
163 | -{ | ||
164 | -} | ||
165 | - | ||
166 | -static int parallel_can_receive1(void *opaque) | ||
167 | -{ | ||
168 | - ParallelState *s = opaque; | ||
169 | - return parallel_can_receive(s); | ||
170 | -} | ||
171 | - | ||
172 | -static void parallel_receive1(void *opaque, const uint8_t *buf, int size) | ||
173 | -{ | ||
174 | - ParallelState *s = opaque; | ||
175 | - parallel_receive_byte(s, buf[0]); | ||
176 | -} | ||
177 | - | ||
178 | /* If fd is zero, it means that the parallel device uses the console */ | 157 | /* If fd is zero, it means that the parallel device uses the console */ |
179 | ParallelState *parallel_init(int base, int irq, CharDriverState *chr) | 158 | ParallelState *parallel_init(int base, int irq, CharDriverState *chr) |
180 | { | 159 | { |
@@ -200,6 +179,5 @@ ParallelState *parallel_init(int base, int irq, CharDriverState *chr) | @@ -200,6 +179,5 @@ ParallelState *parallel_init(int base, int irq, CharDriverState *chr) | ||
200 | 179 | ||
201 | register_ioport_write(base, 8, 1, parallel_ioport_write, s); | 180 | register_ioport_write(base, 8, 1, parallel_ioport_write, s); |
202 | register_ioport_read(base, 8, 1, parallel_ioport_read, s); | 181 | register_ioport_read(base, 8, 1, parallel_ioport_read, s); |
203 | - qemu_chr_add_read_handler(chr, parallel_can_receive1, parallel_receive1, s); | ||
204 | return s; | 182 | return s; |
205 | } | 183 | } |
monitor.c
@@ -196,23 +196,6 @@ static void do_info_version(void) | @@ -196,23 +196,6 @@ static void do_info_version(void) | ||
196 | term_printf("%s\n", QEMU_VERSION); | 196 | term_printf("%s\n", QEMU_VERSION); |
197 | } | 197 | } |
198 | 198 | ||
199 | -static void do_info_network(void) | ||
200 | -{ | ||
201 | - int i, j; | ||
202 | - NetDriverState *nd; | ||
203 | - | ||
204 | - for(i = 0; i < nb_nics; i++) { | ||
205 | - nd = &nd_table[i]; | ||
206 | - term_printf("%d: ifname=%s macaddr=", i, nd->ifname); | ||
207 | - for(j = 0; j < 6; j++) { | ||
208 | - if (j > 0) | ||
209 | - term_printf(":"); | ||
210 | - term_printf("%02x", nd->macaddr[j]); | ||
211 | - } | ||
212 | - term_printf("\n"); | ||
213 | - } | ||
214 | -} | ||
215 | - | ||
216 | static void do_info_block(void) | 199 | static void do_info_block(void) |
217 | { | 200 | { |
218 | bdrv_info(); | 201 | bdrv_info(); |
vl.c
@@ -40,6 +40,7 @@ | @@ -40,6 +40,7 @@ | ||
40 | #include <sys/socket.h> | 40 | #include <sys/socket.h> |
41 | #include <netinet/in.h> | 41 | #include <netinet/in.h> |
42 | #include <dirent.h> | 42 | #include <dirent.h> |
43 | +#include <netdb.h> | ||
43 | #ifdef _BSD | 44 | #ifdef _BSD |
44 | #include <sys/stat.h> | 45 | #include <sys/stat.h> |
45 | #ifndef __APPLE__ | 46 | #ifndef __APPLE__ |
@@ -122,10 +123,9 @@ const char* keyboard_layout = NULL; | @@ -122,10 +123,9 @@ const char* keyboard_layout = NULL; | ||
122 | int64_t ticks_per_sec; | 123 | int64_t ticks_per_sec; |
123 | int boot_device = 'c'; | 124 | int boot_device = 'c'; |
124 | int ram_size; | 125 | int ram_size; |
125 | -static char network_script[1024]; | ||
126 | int pit_min_timer_count = 0; | 126 | int pit_min_timer_count = 0; |
127 | int nb_nics; | 127 | int nb_nics; |
128 | -NetDriverState nd_table[MAX_NICS]; | 128 | +NICInfo nd_table[MAX_NICS]; |
129 | QEMUTimer *gui_timer; | 129 | QEMUTimer *gui_timer; |
130 | int vm_running; | 130 | int vm_running; |
131 | #ifdef HAS_AUDIO | 131 | #ifdef HAS_AUDIO |
@@ -155,6 +155,7 @@ int win2k_install_hack = 0; | @@ -155,6 +155,7 @@ int win2k_install_hack = 0; | ||
155 | int usb_enabled = 0; | 155 | int usb_enabled = 0; |
156 | USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; | 156 | USBPort *vm_usb_ports[MAX_VM_USB_PORTS]; |
157 | USBDevice *vm_usb_hub; | 157 | USBDevice *vm_usb_hub; |
158 | +static VLANState *first_vlan; | ||
158 | 159 | ||
159 | /***********************************************************/ | 160 | /***********************************************************/ |
160 | /* x86 ISA bus support */ | 161 | /* x86 ISA bus support */ |
@@ -1076,10 +1077,10 @@ CharDriverState *qemu_chr_open_null(void) | @@ -1076,10 +1077,10 @@ CharDriverState *qemu_chr_open_null(void) | ||
1076 | 1077 | ||
1077 | typedef struct { | 1078 | typedef struct { |
1078 | int fd_in, fd_out; | 1079 | int fd_in, fd_out; |
1079 | - /* for nographic stdio only */ | ||
1080 | IOCanRWHandler *fd_can_read; | 1080 | IOCanRWHandler *fd_can_read; |
1081 | IOReadHandler *fd_read; | 1081 | IOReadHandler *fd_read; |
1082 | void *fd_opaque; | 1082 | void *fd_opaque; |
1083 | + int max_size; | ||
1083 | } FDCharDriver; | 1084 | } FDCharDriver; |
1084 | 1085 | ||
1085 | #define STDIO_MAX_CLIENTS 2 | 1086 | #define STDIO_MAX_CLIENTS 2 |
@@ -1113,6 +1114,33 @@ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | @@ -1113,6 +1114,33 @@ static int fd_chr_write(CharDriverState *chr, const uint8_t *buf, int len) | ||
1113 | return unix_write(s->fd_out, buf, len); | 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 | static void fd_chr_add_read_handler(CharDriverState *chr, | 1144 | static void fd_chr_add_read_handler(CharDriverState *chr, |
1117 | IOCanRWHandler *fd_can_read, | 1145 | IOCanRWHandler *fd_can_read, |
1118 | IOReadHandler *fd_read, void *opaque) | 1146 | IOReadHandler *fd_read, void *opaque) |
@@ -1120,12 +1148,13 @@ static void fd_chr_add_read_handler(CharDriverState *chr, | @@ -1120,12 +1148,13 @@ static void fd_chr_add_read_handler(CharDriverState *chr, | ||
1120 | FDCharDriver *s = chr->opaque; | 1148 | FDCharDriver *s = chr->opaque; |
1121 | 1149 | ||
1122 | if (s->fd_in >= 0) { | 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 | if (nographic && s->fd_in == 0) { | 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 | } else { | 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,7 +1290,7 @@ static void stdio_received_byte(int ch) | @@ -1261,7 +1290,7 @@ static void stdio_received_byte(int ch) | ||
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 | CharDriverState *chr; | 1295 | CharDriverState *chr; |
1267 | FDCharDriver *s; | 1296 | FDCharDriver *s; |
@@ -1284,11 +1313,14 @@ static int stdio_can_read(void *opaque) | @@ -1284,11 +1313,14 @@ static int stdio_can_read(void *opaque) | ||
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 | /* init terminal so that we can grab keys */ | 1326 | /* init terminal so that we can grab keys */ |
@@ -1337,7 +1369,7 @@ CharDriverState *qemu_chr_open_stdio(void) | @@ -1337,7 +1369,7 @@ CharDriverState *qemu_chr_open_stdio(void) | ||
1337 | return NULL; | 1369 | return NULL; |
1338 | chr = qemu_chr_open_fd(0, 1); | 1370 | chr = qemu_chr_open_fd(0, 1); |
1339 | if (stdio_nb_clients == 0) | 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 | client_index = stdio_nb_clients; | 1373 | client_index = stdio_nb_clients; |
1342 | } else { | 1374 | } else { |
1343 | if (stdio_nb_clients != 0) | 1375 | if (stdio_nb_clients != 0) |
@@ -1603,7 +1635,7 @@ CharDriverState *qemu_chr_open(const char *filename) | @@ -1603,7 +1635,7 @@ CharDriverState *qemu_chr_open(const char *filename) | ||
1603 | } | 1635 | } |
1604 | 1636 | ||
1605 | /***********************************************************/ | 1637 | /***********************************************************/ |
1606 | -/* Linux network device redirectors */ | 1638 | +/* network device redirectors */ |
1607 | 1639 | ||
1608 | void hex_dump(FILE *f, const uint8_t *buf, int size) | 1640 | void hex_dump(FILE *f, const uint8_t *buf, int size) |
1609 | { | 1641 | { |
@@ -1631,107 +1663,171 @@ void hex_dump(FILE *f, const uint8_t *buf, int size) | @@ -1631,107 +1663,171 @@ void hex_dump(FILE *f, const uint8_t *buf, int size) | ||
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 | #if defined(CONFIG_SLIRP) | 1792 | #if defined(CONFIG_SLIRP) |
1666 | 1793 | ||
1667 | /* slirp network adapter */ | 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 | static int slirp_inited; | 1796 | static int slirp_inited; |
1797 | +static VLANClientState *slirp_vc; | ||
1673 | 1798 | ||
1674 | int slirp_can_output(void) | 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 | void slirp_output(const uint8_t *pkt, int pkt_len) | 1804 | void slirp_output(const uint8_t *pkt, int pkt_len) |
1680 | { | 1805 | { |
1681 | #if 0 | 1806 | #if 0 |
1682 | - printf("output:\n"); | 1807 | + printf("slirp output:\n"); |
1683 | hex_dump(stdout, pkt, pkt_len); | 1808 | hex_dump(stdout, pkt, pkt_len); |
1684 | #endif | 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 | #if 0 | 1815 | #if 0 |
1691 | - printf("input:\n"); | 1816 | + printf("slirp input:\n"); |
1692 | hex_dump(stdout, buf, size); | 1817 | hex_dump(stdout, buf, size); |
1693 | #endif | 1818 | #endif |
1694 | slirp_input(buf, size); | 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 | if (!slirp_inited) { | 1824 | if (!slirp_inited) { |
1709 | slirp_inited = 1; | 1825 | slirp_inited = 1; |
1710 | slirp_init(); | 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 | return 0; | 1831 | return 0; |
1736 | } | 1832 | } |
1737 | 1833 | ||
@@ -1874,8 +1970,55 @@ void net_slirp_smb(const char *exported_dir) | @@ -1874,8 +1970,55 @@ void net_slirp_smb(const char *exported_dir) | ||
1874 | #endif /* CONFIG_SLIRP */ | 1970 | #endif /* CONFIG_SLIRP */ |
1875 | 1971 | ||
1876 | #if !defined(_WIN32) | 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 | #ifdef _BSD | 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 | int fd; | 2023 | int fd; |
1881 | char *dev; | 2024 | char *dev; |
@@ -1895,7 +2038,7 @@ static int tun_open(char *ifname, int ifname_size) | @@ -1895,7 +2038,7 @@ static int tun_open(char *ifname, int ifname_size) | ||
1895 | return fd; | 2038 | return fd; |
1896 | } | 2039 | } |
1897 | #else | 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 | struct ifreq ifr; | 2043 | struct ifreq ifr; |
1901 | int fd, ret; | 2044 | int fd, ret; |
@@ -1907,76 +2050,448 @@ static int tun_open(char *ifname, int ifname_size) | @@ -1907,76 +2050,448 @@ static int tun_open(char *ifname, int ifname_size) | ||
1907 | } | 2050 | } |
1908 | memset(&ifr, 0, sizeof(ifr)); | 2051 | memset(&ifr, 0, sizeof(ifr)); |
1909 | ifr.ifr_flags = IFF_TAP | IFF_NO_PI; | 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 | ret = ioctl(fd, TUNSETIFF, (void *) &ifr); | 2057 | ret = ioctl(fd, TUNSETIFF, (void *) &ifr); |
1912 | if (ret != 0) { | 2058 | if (ret != 0) { |
1913 | fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); | 2059 | fprintf(stderr, "warning: could not configure /dev/net/tun: no virtual network emulation\n"); |
1914 | close(fd); | 2060 | close(fd); |
1915 | return -1; | 2061 | return -1; |
1916 | } | 2062 | } |
1917 | - printf("Connected to host network interface: %s\n", ifr.ifr_name); | ||
1918 | pstrcpy(ifname, ifname_size, ifr.ifr_name); | 2063 | pstrcpy(ifname, ifname_size, ifr.ifr_name); |
1919 | fcntl(fd, F_SETFL, O_NONBLOCK); | 2064 | fcntl(fd, F_SETFL, O_NONBLOCK); |
1920 | return fd; | 2065 | return fd; |
1921 | } | 2066 | } |
1922 | #endif | 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 | return 0; | 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 | return 0; | 2327 | return 0; |
1976 | } | 2328 | } |
1977 | 2329 | ||
1978 | #endif /* !_WIN32 */ | 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 | /* USB devices */ | 2496 | /* USB devices */ |
1982 | 2497 | ||
@@ -2175,49 +2690,65 @@ static void host_segv_handler(int host_signum, siginfo_t *info, | @@ -2175,49 +2690,65 @@ static void host_segv_handler(int host_signum, siginfo_t *info, | ||
2175 | 2690 | ||
2176 | typedef struct IOHandlerRecord { | 2691 | typedef struct IOHandlerRecord { |
2177 | int fd; | 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 | void *opaque; | 2696 | void *opaque; |
2181 | /* temporary data */ | 2697 | /* temporary data */ |
2182 | struct pollfd *ufd; | 2698 | struct pollfd *ufd; |
2183 | - int max_size; | ||
2184 | struct IOHandlerRecord *next; | 2699 | struct IOHandlerRecord *next; |
2185 | } IOHandlerRecord; | 2700 | } IOHandlerRecord; |
2186 | 2701 | ||
2187 | static IOHandlerRecord *first_io_handler; | 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 | return 0; | 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,8 +3611,6 @@ void main_loop_wait(int timeout) | @@ -3080,8 +3611,6 @@ void main_loop_wait(int timeout) | ||
3080 | #ifndef _WIN32 | 3611 | #ifndef _WIN32 |
3081 | struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf; | 3612 | struct pollfd ufds[MAX_IO_HANDLERS + 1], *pf; |
3082 | IOHandlerRecord *ioh, *ioh_next; | 3613 | IOHandlerRecord *ioh, *ioh_next; |
3083 | - uint8_t buf[4096]; | ||
3084 | - int n, max_size; | ||
3085 | #endif | 3614 | #endif |
3086 | int ret; | 3615 | int ret; |
3087 | 3616 | ||
@@ -3093,26 +3622,18 @@ void main_loop_wait(int timeout) | @@ -3093,26 +3622,18 @@ void main_loop_wait(int timeout) | ||
3093 | /* XXX: separate device handlers from system ones */ | 3622 | /* XXX: separate device handlers from system ones */ |
3094 | pf = ufds; | 3623 | pf = ufds; |
3095 | for(ioh = first_io_handler; ioh != NULL; ioh = ioh->next) { | 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 | ret = poll(ufds, pf - ufds, timeout); | 3639 | ret = poll(ufds, pf - ufds, timeout); |
@@ -3121,20 +3642,11 @@ void main_loop_wait(int timeout) | @@ -3121,20 +3642,11 @@ void main_loop_wait(int timeout) | ||
3121 | for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { | 3642 | for(ioh = first_io_handler; ioh != NULL; ioh = ioh_next) { |
3122 | ioh_next = ioh->next; | 3643 | ioh_next = ioh->next; |
3123 | pf = ioh->ufd; | 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,20 +3763,31 @@ void help(void) | @@ -3251,20 +3763,31 @@ void help(void) | ||
3251 | #endif | 3763 | #endif |
3252 | "\n" | 3764 | "\n" |
3253 | "Network options:\n" | 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 | #ifdef CONFIG_SLIRP | 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 | #ifndef _WIN32 | 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 | #endif | 3787 | #endif |
3264 | "-redir [tcp|udp]:host-port:[guest-host]:guest-port\n" | 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 | #endif | 3790 | #endif |
3267 | - "-dummy-net use dummy network stack\n" | ||
3268 | "\n" | 3791 | "\n" |
3269 | "Linux boot specific:\n" | 3792 | "Linux boot specific:\n" |
3270 | "-kernel bzImage use 'bzImage' as kernel image\n" | 3793 | "-kernel bzImage use 'bzImage' as kernel image\n" |
@@ -3308,7 +3831,9 @@ void help(void) | @@ -3308,7 +3831,9 @@ void help(void) | ||
3308 | "qemu-fast", | 3831 | "qemu-fast", |
3309 | #endif | 3832 | #endif |
3310 | DEFAULT_RAM_SIZE, | 3833 | DEFAULT_RAM_SIZE, |
3834 | +#ifndef _WIN32 | ||
3311 | DEFAULT_NETWORK_SCRIPT, | 3835 | DEFAULT_NETWORK_SCRIPT, |
3836 | +#endif | ||
3312 | DEFAULT_GDBSTUB_PORT, | 3837 | DEFAULT_GDBSTUB_PORT, |
3313 | "/tmp/qemu.log"); | 3838 | "/tmp/qemu.log"); |
3314 | #ifndef CONFIG_SOFTMMU | 3839 | #ifndef CONFIG_SOFTMMU |
@@ -3343,15 +3868,10 @@ enum { | @@ -3343,15 +3868,10 @@ enum { | ||
3343 | QEMU_OPTION_soundhw, | 3868 | QEMU_OPTION_soundhw, |
3344 | #endif | 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 | QEMU_OPTION_tftp, | 3872 | QEMU_OPTION_tftp, |
3352 | QEMU_OPTION_smb, | 3873 | QEMU_OPTION_smb, |
3353 | QEMU_OPTION_redir, | 3874 | QEMU_OPTION_redir, |
3354 | - QEMU_OPTION_dummy_net, | ||
3355 | 3875 | ||
3356 | QEMU_OPTION_kernel, | 3876 | QEMU_OPTION_kernel, |
3357 | QEMU_OPTION_append, | 3877 | QEMU_OPTION_append, |
@@ -3409,19 +3929,14 @@ const QEMUOption qemu_options[] = { | @@ -3409,19 +3929,14 @@ const QEMUOption qemu_options[] = { | ||
3409 | { "soundhw", HAS_ARG, QEMU_OPTION_soundhw }, | 3929 | { "soundhw", HAS_ARG, QEMU_OPTION_soundhw }, |
3410 | #endif | 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 | #ifdef CONFIG_SLIRP | 3933 | #ifdef CONFIG_SLIRP |
3417 | - { "user-net", 0, QEMU_OPTION_user_net }, | ||
3418 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, | 3934 | { "tftp", HAS_ARG, QEMU_OPTION_tftp }, |
3419 | #ifndef _WIN32 | 3935 | #ifndef _WIN32 |
3420 | { "smb", HAS_ARG, QEMU_OPTION_smb }, | 3936 | { "smb", HAS_ARG, QEMU_OPTION_smb }, |
3421 | #endif | 3937 | #endif |
3422 | { "redir", HAS_ARG, QEMU_OPTION_redir }, | 3938 | { "redir", HAS_ARG, QEMU_OPTION_redir }, |
3423 | #endif | 3939 | #endif |
3424 | - { "dummy-net", 0, QEMU_OPTION_dummy_net }, | ||
3425 | 3940 | ||
3426 | { "kernel", HAS_ARG, QEMU_OPTION_kernel }, | 3941 | { "kernel", HAS_ARG, QEMU_OPTION_kernel }, |
3427 | { "append", HAS_ARG, QEMU_OPTION_append }, | 3942 | { "append", HAS_ARG, QEMU_OPTION_append }, |
@@ -3596,9 +4111,7 @@ static void select_soundhw (const char *optarg) | @@ -3596,9 +4111,7 @@ static void select_soundhw (const char *optarg) | ||
3596 | } | 4111 | } |
3597 | #endif | 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 | int main(int argc, char **argv) | 4116 | int main(int argc, char **argv) |
3604 | { | 4117 | { |
@@ -3614,8 +4127,8 @@ int main(int argc, char **argv) | @@ -3614,8 +4127,8 @@ int main(int argc, char **argv) | ||
3614 | DisplayState *ds = &display_state; | 4127 | DisplayState *ds = &display_state; |
3615 | int cyls, heads, secs, translation; | 4128 | int cyls, heads, secs, translation; |
3616 | int start_emulation = 1; | 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 | int optind; | 4132 | int optind; |
3620 | const char *r, *optarg; | 4133 | const char *r, *optarg; |
3621 | CharDriverState *monitor_hd; | 4134 | CharDriverState *monitor_hd; |
@@ -3644,7 +4157,6 @@ int main(int argc, char **argv) | @@ -3644,7 +4157,6 @@ int main(int argc, char **argv) | ||
3644 | ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; | 4157 | ram_size = DEFAULT_RAM_SIZE * 1024 * 1024; |
3645 | vga_ram_size = VGA_RAM_SIZE; | 4158 | vga_ram_size = VGA_RAM_SIZE; |
3646 | bios_size = BIOS_SIZE; | 4159 | bios_size = BIOS_SIZE; |
3647 | - pstrcpy(network_script, sizeof(network_script), DEFAULT_NETWORK_SCRIPT); | ||
3648 | #ifdef CONFIG_GDBSTUB | 4160 | #ifdef CONFIG_GDBSTUB |
3649 | use_gdbstub = 0; | 4161 | use_gdbstub = 0; |
3650 | gdbstub_port = DEFAULT_GDBSTUB_PORT; | 4162 | gdbstub_port = DEFAULT_GDBSTUB_PORT; |
@@ -3674,16 +4186,10 @@ int main(int argc, char **argv) | @@ -3674,16 +4186,10 @@ int main(int argc, char **argv) | ||
3674 | 4186 | ||
3675 | usb_devices_index = 0; | 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 | /* default mac address of the first network interface */ | 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 | optind = 1; | 4194 | optind = 1; |
3689 | for(;;) { | 4195 | for(;;) { |
@@ -3797,21 +4303,6 @@ int main(int argc, char **argv) | @@ -3797,21 +4303,6 @@ int main(int argc, char **argv) | ||
3797 | case QEMU_OPTION_append: | 4303 | case QEMU_OPTION_append: |
3798 | kernel_cmdline = optarg; | 4304 | kernel_cmdline = optarg; |
3799 | break; | 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 | case QEMU_OPTION_cdrom: | 4306 | case QEMU_OPTION_cdrom: |
3816 | if (cdrom_index >= 0) { | 4307 | if (cdrom_index >= 0) { |
3817 | hd_filename[cdrom_index] = optarg; | 4308 | hd_filename[cdrom_index] = optarg; |
@@ -3838,33 +4329,15 @@ int main(int argc, char **argv) | @@ -3838,33 +4329,15 @@ int main(int argc, char **argv) | ||
3838 | case QEMU_OPTION_no_code_copy: | 4329 | case QEMU_OPTION_no_code_copy: |
3839 | code_copy_enabled = 0; | 4330 | code_copy_enabled = 0; |
3840 | break; | 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 | exit(1); | 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 | break; | 4341 | break; |
3869 | #ifdef CONFIG_SLIRP | 4342 | #ifdef CONFIG_SLIRP |
3870 | case QEMU_OPTION_tftp: | 4343 | case QEMU_OPTION_tftp: |
@@ -3875,16 +4348,10 @@ int main(int argc, char **argv) | @@ -3875,16 +4348,10 @@ int main(int argc, char **argv) | ||
3875 | net_slirp_smb(optarg); | 4348 | net_slirp_smb(optarg); |
3876 | break; | 4349 | break; |
3877 | #endif | 4350 | #endif |
3878 | - case QEMU_OPTION_user_net: | ||
3879 | - net_if_type = NET_IF_USER; | ||
3880 | - break; | ||
3881 | case QEMU_OPTION_redir: | 4351 | case QEMU_OPTION_redir: |
3882 | net_slirp_redir(optarg); | 4352 | net_slirp_redir(optarg); |
3883 | break; | 4353 | break; |
3884 | #endif | 4354 | #endif |
3885 | - case QEMU_OPTION_dummy_net: | ||
3886 | - net_if_type = NET_IF_DUMMY; | ||
3887 | - break; | ||
3888 | #ifdef HAS_AUDIO | 4355 | #ifdef HAS_AUDIO |
3889 | case QEMU_OPTION_enable_audio: | 4356 | case QEMU_OPTION_enable_audio: |
3890 | audio_enabled = 1; | 4357 | audio_enabled = 1; |
@@ -3930,9 +4397,6 @@ int main(int argc, char **argv) | @@ -3930,9 +4397,6 @@ int main(int argc, char **argv) | ||
3930 | cpu_set_log(mask); | 4397 | cpu_set_log(mask); |
3931 | } | 4398 | } |
3932 | break; | 4399 | break; |
3933 | - case QEMU_OPTION_n: | ||
3934 | - pstrcpy(network_script, sizeof(network_script), optarg); | ||
3935 | - break; | ||
3936 | #ifdef CONFIG_GDBSTUB | 4400 | #ifdef CONFIG_GDBSTUB |
3937 | case QEMU_OPTION_s: | 4401 | case QEMU_OPTION_s: |
3938 | use_gdbstub = 1; | 4402 | use_gdbstub = 1; |
@@ -4076,48 +4540,20 @@ int main(int argc, char **argv) | @@ -4076,48 +4540,20 @@ int main(int argc, char **argv) | ||
4076 | #else | 4540 | #else |
4077 | setvbuf(stdout, NULL, _IOLBF, 0); | 4541 | setvbuf(stdout, NULL, _IOLBF, 0); |
4078 | #endif | 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 | /* init the memory */ | 4559 | /* init the memory */ |
vl.h
@@ -196,10 +196,17 @@ void kbd_put_keysym(int keysym); | @@ -196,10 +196,17 @@ void kbd_put_keysym(int keysym); | ||
196 | 196 | ||
197 | typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); | 197 | typedef void IOReadHandler(void *opaque, const uint8_t *buf, int size); |
198 | typedef int IOCanRWHandler(void *opaque); | 198 | typedef int IOCanRWHandler(void *opaque); |
199 | +typedef void IOHandler(void *opaque); | ||
199 | 200 | ||
200 | -int qemu_add_fd_read_handler(int fd, IOCanRWHandler *fd_can_read, | ||
201 | - IOReadHandler *fd_read, void *opaque); | ||
202 | -void qemu_del_fd_read_handler(int fd); | 201 | +int qemu_set_fd_handler2(int fd, |
202 | + IOCanRWHandler *fd_read_poll, | ||
203 | + IOHandler *fd_read, | ||
204 | + IOHandler *fd_write, | ||
205 | + void *opaque); | ||
206 | +int qemu_set_fd_handler(int fd, | ||
207 | + IOHandler *fd_read, | ||
208 | + IOHandler *fd_write, | ||
209 | + void *opaque); | ||
203 | 210 | ||
204 | /* character device */ | 211 | /* character device */ |
205 | 212 | ||
@@ -270,30 +277,42 @@ extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; | @@ -270,30 +277,42 @@ extern CharDriverState *serial_hds[MAX_SERIAL_PORTS]; | ||
270 | 277 | ||
271 | extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; | 278 | extern CharDriverState *parallel_hds[MAX_PARALLEL_PORTS]; |
272 | 279 | ||
273 | -/* network redirectors support */ | 280 | +/* VLANs support */ |
281 | + | ||
282 | +typedef struct VLANClientState VLANClientState; | ||
283 | + | ||
284 | +struct VLANClientState { | ||
285 | + IOReadHandler *fd_read; | ||
286 | + void *opaque; | ||
287 | + struct VLANClientState *next; | ||
288 | + struct VLANState *vlan; | ||
289 | + char info_str[256]; | ||
290 | +}; | ||
291 | + | ||
292 | +typedef struct VLANState { | ||
293 | + int id; | ||
294 | + VLANClientState *first_client; | ||
295 | + struct VLANState *next; | ||
296 | +} VLANState; | ||
297 | + | ||
298 | +VLANState *qemu_find_vlan(int id); | ||
299 | +VLANClientState *qemu_new_vlan_client(VLANState *vlan, | ||
300 | + IOReadHandler *fd_read, void *opaque); | ||
301 | +void qemu_send_packet(VLANClientState *vc, const uint8_t *buf, int size); | ||
302 | + | ||
303 | +void do_info_network(void); | ||
304 | + | ||
305 | +/* NIC info */ | ||
274 | 306 | ||
275 | #define MAX_NICS 8 | 307 | #define MAX_NICS 8 |
276 | 308 | ||
277 | -typedef struct NetDriverState { | ||
278 | - int index; /* index number in QEMU */ | 309 | +typedef struct NICInfo { |
279 | uint8_t macaddr[6]; | 310 | uint8_t macaddr[6]; |
280 | - char ifname[16]; | ||
281 | - void (*send_packet)(struct NetDriverState *nd, | ||
282 | - const uint8_t *buf, int size); | ||
283 | - void (*add_read_packet)(struct NetDriverState *nd, | ||
284 | - IOCanRWHandler *fd_can_read, | ||
285 | - IOReadHandler *fd_read, void *opaque); | ||
286 | - /* tun specific data */ | ||
287 | - int fd; | ||
288 | - /* slirp specific data */ | ||
289 | -} NetDriverState; | 311 | + VLANState *vlan; |
312 | +} NICInfo; | ||
290 | 313 | ||
291 | extern int nb_nics; | 314 | extern int nb_nics; |
292 | -extern NetDriverState nd_table[MAX_NICS]; | ||
293 | - | ||
294 | -void qemu_send_packet(NetDriverState *nd, const uint8_t *buf, int size); | ||
295 | -void qemu_add_read_packet(NetDriverState *nd, IOCanRWHandler *fd_can_read, | ||
296 | - IOReadHandler *fd_read, void *opaque); | 315 | +extern NICInfo nd_table[MAX_NICS]; |
297 | 316 | ||
298 | /* timers */ | 317 | /* timers */ |
299 | 318 | ||
@@ -692,8 +711,8 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); | @@ -692,8 +711,8 @@ int fdctrl_get_drive_type(fdctrl_t *fdctrl, int drive_num); | ||
692 | 711 | ||
693 | /* ne2000.c */ | 712 | /* ne2000.c */ |
694 | 713 | ||
695 | -void isa_ne2000_init(int base, int irq, NetDriverState *nd); | ||
696 | -void pci_ne2000_init(PCIBus *bus, NetDriverState *nd); | 714 | +void isa_ne2000_init(int base, int irq, NICInfo *nd); |
715 | +void pci_ne2000_init(PCIBus *bus, NICInfo *nd); | ||
697 | 716 | ||
698 | /* pckbd.c */ | 717 | /* pckbd.c */ |
699 | 718 | ||
@@ -781,7 +800,7 @@ void *iommu_init(uint32_t addr); | @@ -781,7 +800,7 @@ void *iommu_init(uint32_t addr); | ||
781 | uint32_t iommu_translate_local(void *opaque, uint32_t addr); | 800 | uint32_t iommu_translate_local(void *opaque, uint32_t addr); |
782 | 801 | ||
783 | /* lance.c */ | 802 | /* lance.c */ |
784 | -void lance_init(NetDriverState *nd, int irq, uint32_t leaddr, uint32_t ledaddr); | 803 | +void lance_init(NICInfo *nd, int irq, uint32_t leaddr, uint32_t ledaddr); |
785 | 804 | ||
786 | /* tcx.c */ | 805 | /* tcx.c */ |
787 | void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, | 806 | void *tcx_init(DisplayState *ds, uint32_t addr, uint8_t *vram_base, |