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