161
171
// the constructor
162
172
bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif,
164
eth_rx_handler_t rxh,
174
eth_rx_handler_t rxh,
169
179
char filename[BX_PATHNAME_LEN];
170
182
if (strncmp (netif, "tap", 3) != 0) {
171
BX_PANIC (("eth_tap: interface name (%s) must be tap0..tap15", netif));
183
BX_PANIC(("eth_tap: interface name (%s) must be tap0..tap15", netif));
173
sprintf (filename, "/dev/%s", netif);
186
strcpy(filename,"/dev/tap"); /* PD - device on Solaris is always the same */
188
sprintf(filename, "/dev/%s", netif);
175
191
#if defined(__linux__)
176
192
// check if the TAP devices is running, and turn on ARP. This is based
177
193
// on code from the Mac-On-Linux project. http://http://www.maconlinux.org/
178
194
int sock = socket(AF_INET, SOCK_DGRAM, 0);
180
BX_PANIC (("socket creation: %s", strerror(errno)));
196
BX_PANIC(("socket creation: %s", strerror(errno)));
183
199
struct ifreq ifr;
184
200
memset(&ifr, 0, sizeof(ifr));
185
201
strncpy(ifr.ifr_name, netif, sizeof(ifr.ifr_name));
186
202
if(ioctl(sock, SIOCGIFFLAGS, &ifr) < 0) {
187
BX_PANIC (("SIOCGIFFLAGS on %s: %s", netif, strerror(errno)));
203
BX_PANIC(("SIOCGIFFLAGS on %s: %s", netif, strerror(errno)));
191
207
if (!(ifr.ifr_flags & IFF_RUNNING)) {
192
BX_PANIC (("%s device is not running", netif));
208
BX_PANIC(("%s device is not running", netif));
208
224
fd = open (filename, O_RDWR);
210
BX_PANIC(("open failed on %s: %s", netif, strerror(errno)));
226
BX_PANIC(("open failed on TAP %s: %s", netif, strerror(errno)));
231
char *ptr; /* PD - ppa allocation ala qemu */
232
char my_dev[10]; /* enough ... */
234
struct strioctl strioc_ppa;
237
strncpy(my_dev,netif,10); /* following ptr= does not work with const char* */
238
if( *my_dev ) { /* find the ppa number X from string tapX */
240
while( *ptr && !isdigit((int)*ptr) ) ptr++;
243
/* Assign a new PPA and get its unit number. */
244
strioc_ppa.ic_cmd = TUNNEWPPA;
245
strioc_ppa.ic_timout = 0;
246
strioc_ppa.ic_len = sizeof(ppa);
247
strioc_ppa.ic_dp = (char *)&ppa;
248
if ((ppa = ioctl (fd, I_STR, &strioc_ppa)) < 0)
249
BX_PANIC(("Can't assign new interface tap%d !",ppa));
214
252
/* set O_ASYNC flag so that we can poll with read() */
215
253
if ((flags = fcntl(fd, F_GETFL)) < 0) {
216
254
BX_PANIC(("getflags on tap device: %s", strerror(errno)));
220
258
BX_PANIC(("set tap device flags: %s", strerror(errno)));
223
BX_INFO(("eth_tap: opened %s device", netif));
261
BX_INFO(("tap network drive: opened %s device", netif));
225
263
/* Execute the configuration script */
226
264
char intname[IFNAMSIZ];
227
265
strcpy(intname,netif);
228
266
if((script != NULL) && (strcmp(script, "") != 0) && (strcmp(script, "none") != 0))
230
if (execute_script(script, intname) < 0)
268
if (execute_script(this->netdev, script, intname) < 0)
231
269
BX_ERROR(("execute script '%s' on %s failed", script, intname));
234
272
// Start the rx poll
235
273
this->rx_timer_index =
236
274
bx_pc_system.register_timer(this, this->rx_timer_handler, 1000,
237
1, 1, "eth_tap"); // continuous, active
275
1, 1, "eth_tap"); // continuous, active
240
277
memcpy(&guest_macaddr[0], macaddr, 6);
241
278
#if BX_ETH_TAP_LOGGING
242
279
// eventually Bryce wants txlog to dump in pcap format so that
243
280
// tcpdump -r FILE can read it and interpret packets.
244
txlog = fopen ("ne2k-tx.log", "wb");
245
if (!txlog) BX_PANIC (("open ne2k-tx.log failed"));
246
txlog_txt = fopen ("ne2k-txdump.txt", "wb");
247
if (!txlog_txt) BX_PANIC (("open ne2k-txdump.txt failed"));
248
fprintf (txlog_txt, "tap packetmover readable log file\n");
249
fprintf (txlog_txt, "net IF = %s\n", netif);
250
fprintf (txlog_txt, "MAC address = ");
281
txlog = fopen("ne2k-tx.log", "wb");
282
if (!txlog) BX_PANIC(("open ne2k-tx.log failed"));
283
txlog_txt = fopen("ne2k-txdump.txt", "wb");
284
if (!txlog_txt) BX_PANIC(("open ne2k-txdump.txt failed"));
285
fprintf(txlog_txt, "tap packetmover readable log file\n");
286
fprintf(txlog_txt, "net IF = %s\n", netif);
287
fprintf(txlog_txt, "MAC address = ");
251
288
for (int i=0; i<6; i++)
252
fprintf (txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
253
fprintf (txlog_txt, "\n--\n");
289
fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
290
fprintf(txlog_txt, "\n--\n");
256
rxlog = fopen ("ne2k-rx.log", "wb");
257
if (!rxlog) BX_PANIC (("open ne2k-rx.log failed"));
258
rxlog_txt = fopen ("ne2k-rxdump.txt", "wb");
259
if (!rxlog_txt) BX_PANIC (("open ne2k-rxdump.txt failed"));
260
fprintf (rxlog_txt, "tap packetmover readable log file\n");
261
fprintf (rxlog_txt, "net IF = %s\n", netif);
262
fprintf (rxlog_txt, "MAC address = ");
293
rxlog = fopen("ne2k-rx.log", "wb");
294
if (!rxlog) BX_PANIC(("open ne2k-rx.log failed"));
295
rxlog_txt = fopen("ne2k-rxdump.txt", "wb");
296
if (!rxlog_txt) BX_PANIC(("open ne2k-rxdump.txt failed"));
297
fprintf(rxlog_txt, "tap packetmover readable log file\n");
298
fprintf(rxlog_txt, "net IF = %s\n", netif);
299
fprintf(rxlog_txt, "MAC address = ");
263
300
for (int i=0; i<6; i++)
264
fprintf (rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
265
fprintf (rxlog_txt, "\n--\n");
301
fprintf(rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
302
fprintf(rxlog_txt, "\n--\n");
273
310
Bit8u txbuf[BX_PACKET_BUFSIZE];
276
314
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || \
277
defined(__APPLE__) || defined(__OpenBSD__) // Should be fixed for other *BSD
315
defined(__APPLE__) || defined(__OpenBSD__) || defined(__sun__) // Should be fixed for other *BSD
278
316
memcpy(txbuf, buf, io_len);
279
unsigned int size = write(fd, txbuf, io_len);
317
/* PD - for Sun variant the retry cycle from qemu - mainly to be sure packet
322
ret=write(fd, txbuf, io_len);
323
if (ret < 0 && (errno == EINTR || errno == EAGAIN)) {
329
#else /* not defined __sun__ */
330
size = write(fd, txbuf, io_len);
331
#endif /* whole condition about defined __sun__ */
280
332
if (size != io_len) {
333
#else /* not bsd/apple/sun style */
282
334
memcpy(txbuf+2, buf, io_len);
283
unsigned int size = write(fd, txbuf, io_len+2);
335
size = write(fd, txbuf, io_len+2);
284
336
if (size != io_len+2) {
286
338
BX_PANIC(("write on tap device: %s", strerror(errno)));
288
BX_DEBUG(("wrote %d bytes + 2 byte pad on tap", io_len));
340
BX_DEBUG(("wrote %d bytes + ev. 2 byte pad on tap", io_len));
290
342
#if BX_ETH_TAP_LOGGING
291
343
BX_DEBUG(("sendpkt length %u", io_len));
294
346
int n = fwrite(buf, io_len, 1, txlog);
295
347
if (n != 1) BX_ERROR(("fwrite to txlog failed, io_len = %u", io_len));
296
348
// dump packet in hex into an ascii log file
297
fprintf(txlog_txt, "NE2K transmitting a packet, length %u\n", io_len);
349
fprintf(txlog_txt, "transmitting a packet, length %u\n", io_len);
298
350
Bit8u *charbuf = (Bit8u *)buf;
299
351
for (n=0; n<(int)io_len; n++) {
300
352
if (((n % 16) == 0) && n>0)
343
BX_DEBUG (("tap read returned %d bytes", nbytes));
403
BX_DEBUG(("tap read returned %d bytes", nbytes));
345
405
if (errno != EAGAIN)
346
BX_ERROR (("tap read error: %s", strerror(errno)));
406
BX_ERROR(("tap read error: %s", strerror(errno)));
349
409
#if BX_ETH_TAP_LOGGING
350
410
if (nbytes > 0) {
351
BX_DEBUG (("receive packet length %u", nbytes));
411
BX_DEBUG(("receive packet length %u", nbytes));
352
412
// dump raw bytes to a file, eventually dump in pcap format so that
353
413
// tcpdump -r FILE can interpret them for us.
354
int n = fwrite (rxbuf, nbytes, 1, rxlog);
355
if (n != 1) BX_ERROR (("fwrite to rxlog failed, nbytes = %d", nbytes));
414
int n = fwrite(rxbuf, nbytes, 1, rxlog);
415
if (n != 1) BX_ERROR(("fwrite to rxlog failed, nbytes = %d", nbytes));
356
416
// dump packet in hex into an ascii log file
357
fprintf (rxlog_txt, "NE2K received a packet, length %u\n", nbytes);
417
fprintf(rxlog_txt, "received a packet, length %u\n", nbytes);
358
418
for (n=0; n<nbytes; n++) {
359
419
if (((n % 16) == 0) && n>0)
360
fprintf (rxlog_txt, "\n");
361
fprintf (rxlog_txt, "%02x ", rxbuf[n]);
420
fprintf(rxlog_txt, "\n");
421
fprintf(rxlog_txt, "%02x ", rxbuf[n]);
363
fprintf (rxlog_txt, "\n--\n");
423
fprintf(rxlog_txt, "\n--\n");
364
424
// flush log so that we see the packets as they arrive w/o buffering
369
429
BX_DEBUG(("eth_tap: got packet: %d bytes, dst=%x:%x:%x:%x:%x:%x, src=%x:%x:%x:%x:%x:%x\n", nbytes, rxbuf[0], rxbuf[1], rxbuf[2], rxbuf[3], rxbuf[4], rxbuf[5], rxbuf[6], rxbuf[7], rxbuf[8], rxbuf[9], rxbuf[10], rxbuf[11]));
370
430
if (nbytes < 60) {
371
BX_INFO (("packet too short (%d), padding to 60", nbytes));
431
BX_INFO(("packet too short (%d), padding to 60", nbytes));
374
(*rxh)(rxarg, rxbuf, nbytes);
434
(*rxh)(netdev, rxbuf, nbytes);
377
437
#endif /* if BX_NETWORKING && defined HAVE_ETHERTAP */