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