~ubuntu-branches/ubuntu/saucy/bochs/saucy-proposed

« back to all changes in this revision

Viewing changes to iodev/eth_tap.cc

  • Committer: Bazaar Package Importer
  • Author(s): David Futcher
  • Date: 2009-04-30 07:46:11 UTC
  • mfrom: (1.1.11 upstream) (4.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20090430074611-6dih80a5mk2uvxhk
Tags: 2.3.7+20090416-1ubuntu1
* Merge from debian unstable (LP: #370427), remaining changes:
  - debian/patches/12_no-ssp.patch: Build bios with -fno-stack-protector
  - Add Replaces/Conflicts for bochsbios-qemu (<< 2.3.6-2)

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/////////////////////////////////////////////////////////////////////////
2
 
// $Id: eth_tap.cc,v 1.30 2008/02/15 22:05:42 sshwarts Exp $
 
2
// $Id: eth_tap.cc,v 1.35 2009/04/13 13:33:11 vruppert Exp $
3
3
/////////////////////////////////////////////////////////////////////////
4
4
//
5
5
//  Copyright (C) 2001  MandrakeSoft S.A.
22
22
//
23
23
//  You should have received a copy of the GNU Lesser General Public
24
24
//  License along with this library; if not, write to the Free Software
25
 
//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 
25
//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 
26
//
 
27
/////////////////////////////////////////////////////////////////////////
26
28
 
27
29
// eth_tap.cc  - TAP interface by Bryce Denney
28
30
//
79
81
// host, you should be able to get Bochs talking to anyone on the internet.
80
82
//
81
83
 
 
84
// Pavel Dufek (PD), CZ, 2008 - quick & dirty hack for Solaris 10 sparc tap 
 
85
// ala Qemu.
 
86
 
82
87
// Define BX_PLUGGABLE in files that can be compiled into plugins.  For
83
88
// platforms that require a special tag on exported symbols, BX_PLUGGABLE
84
89
// is used to know when we are exporting symbols and when we are importing.
91
96
 
92
97
#include "eth.h"
93
98
 
94
 
#define LOG_THIS bx_devices.pluginNE2kDevice->
 
99
#define LOG_THIS netdev->
95
100
 
96
101
#include <signal.h>
97
102
#include <sys/param.h>
114
119
#include <assert.h>
115
120
#include <fcntl.h>
116
121
#include <errno.h>
 
122
#if defined(__sun__)
 
123
// Sun/Solaris specific defines/includes
 
124
#define TUNNEWPPA       (('T'<<16) | 0x0001)
 
125
#include <stropts.h>
 
126
#endif
117
127
 
118
128
#define BX_ETH_TAP_LOGGING 0
119
129
 
123
133
class bx_tap_pktmover_c : public eth_pktmover_c {
124
134
public:
125
135
  bx_tap_pktmover_c(const char *netif, const char *macaddr,
126
 
                     eth_rx_handler_t rxh,
127
 
                     void *rxarg, char *script);
 
136
                    eth_rx_handler_t rxh,
 
137
                    bx_devmodel_c *dev, const char *script);
128
138
  void sendpkt(void *buf, unsigned io_len);
129
139
private:
130
140
  int fd;
147
157
  bx_tap_locator_c(void) : eth_locator_c("tap") {}
148
158
protected:
149
159
  eth_pktmover_c *allocate(const char *netif, const char *macaddr,
150
 
                           eth_rx_handler_t rxh,
151
 
                           void *rxarg, char *script) {
152
 
    return (new bx_tap_pktmover_c(netif, macaddr, rxh, rxarg, script));
 
160
                           eth_rx_handler_t rxh,
 
161
                           bx_devmodel_c *dev, const char *script) {
 
162
    return (new bx_tap_pktmover_c(netif, macaddr, rxh, dev, script));
153
163
  }
154
164
} bx_tap_match;
155
165
 
160
170
 
161
171
// the constructor
162
172
bx_tap_pktmover_c::bx_tap_pktmover_c(const char *netif,
163
 
                                       const char *macaddr,
164
 
                                       eth_rx_handler_t rxh,
165
 
                                       void *rxarg,
166
 
                                       char *script)
 
173
                                     const char *macaddr,
 
174
                                     eth_rx_handler_t rxh,
 
175
                                     bx_devmodel_c *dev,
 
176
                                     const char *script)
167
177
{
168
178
  int flags;
169
179
  char filename[BX_PATHNAME_LEN];
 
180
 
 
181
  this->netdev = dev;
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));
172
184
  }
173
 
  sprintf (filename, "/dev/%s", netif);
 
185
#if defined(__sun__)
 
186
  strcpy(filename,"/dev/tap"); /* PD - device on Solaris is always the same */
 
187
#else
 
188
  sprintf(filename, "/dev/%s", netif);
 
189
#endif
174
190
 
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);
179
195
  if (sock < 0) {
180
 
    BX_PANIC (("socket creation: %s", strerror(errno)));
 
196
    BX_PANIC(("socket creation: %s", strerror(errno)));
181
197
    return;
182
198
  }
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)));
188
204
    close(sock);
189
205
    return;
190
206
  }
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));
193
209
    close(sock);
194
210
    return;
195
211
  }
197
213
    BX_INFO(("turn on ARP for %s device", netif));
198
214
    ifr.ifr_flags &= ~IFF_NOARP;
199
215
    if (ioctl(sock, SIOCSIFFLAGS, &ifr) < 0) {
200
 
      BX_PANIC (("SIOCSIFFLAGS: %s", strerror(errno)));
 
216
      BX_PANIC(("SIOCSIFFLAGS: %s", strerror(errno)));
201
217
      close(sock);
202
218
      return;
203
219
    }
207
223
 
208
224
  fd = open (filename, O_RDWR);
209
225
  if (fd < 0) {
210
 
    BX_PANIC(("open failed on %s: %s", netif, strerror(errno)));
 
226
    BX_PANIC(("open failed on TAP %s: %s", netif, strerror(errno)));
211
227
    return;
212
228
  }
213
229
 
 
230
#if defined(__sun__) 
 
231
  char *ptr;       /* PD - ppa allocation ala qemu */
 
232
  char my_dev[10]; /* enough ... */
 
233
  int ppa=-1;
 
234
  struct strioctl strioc_ppa;
 
235
 
 
236
  my_dev[10-1]=0;
 
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 */
 
239
    ptr = my_dev;
 
240
    while( *ptr && !isdigit((int)*ptr) ) ptr++;
 
241
    ppa = atoi(ptr);
 
242
  }
 
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));
 
250
#endif
 
251
 
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)));
221
259
  }
222
260
 
223
 
  BX_INFO(("eth_tap: opened %s device", netif));
 
261
  BX_INFO(("tap network drive: opened %s device", netif));
224
262
 
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))
229
267
  {
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));
232
270
  }
233
271
 
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
238
276
  this->rxh   = rxh;
239
 
  this->rxarg = rxarg;
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");
254
 
  fflush (txlog_txt);
 
289
    fprintf(txlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
 
290
  fprintf(txlog_txt, "\n--\n");
 
291
  fflush(txlog_txt);
255
292
 
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");
266
 
  fflush (rxlog_txt);
 
301
    fprintf(rxlog_txt, "%02x%s", 0xff & macaddr[i], i<5?":" : "");
 
302
  fprintf(rxlog_txt, "\n--\n");
 
303
  fflush(rxlog_txt);
267
304
 
268
305
#endif
269
306
}
273
310
  Bit8u txbuf[BX_PACKET_BUFSIZE];
274
311
  txbuf[0] = 0;
275
312
  txbuf[1] = 0;
 
313
  unsigned int size;
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
 
318
     is really out */
 
319
#if defined(__sun__)
 
320
  int ret;
 
321
  for(;;) {
 
322
    ret=write(fd, txbuf, io_len);
 
323
    if (ret < 0 && (errno == EINTR || errno == EAGAIN)) {
 
324
    } else {
 
325
      size=ret;
 
326
      break;
 
327
    }
 
328
  }
 
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) {
281
 
#else
 
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) {
285
337
#endif
286
338
    BX_PANIC(("write on tap device: %s", strerror(errno)));
287
339
  } else {
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));
289
341
  }
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)
320
372
  Bit8u buf[BX_PACKET_BUFSIZE];
321
373
  Bit8u *rxbuf;
322
374
  if (fd<0) return;
 
375
#if defined(__sun__)
 
376
  struct strbuf sbuf;
 
377
  int f = 0;
 
378
  sbuf.maxlen = sizeof(buf);
 
379
  sbuf.buf = (char *)buf;
 
380
  nbytes = getmsg(fd, NULL, &sbuf, &f) >=0 ? sbuf.len : -1;
 
381
#else
323
382
  nbytes = read (fd, buf, sizeof(buf));
 
383
#endif
324
384
 
325
385
  // hack: discard first two bytes
326
 
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__)  // Should be fixed for other *BSD
 
386
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__APPLE__) || defined(__sun__) // Should be fixed for other *BSD
327
387
  rxbuf = buf;
328
388
#else
329
389
  rxbuf = buf+2;
340
400
#endif
341
401
 
342
402
  if (nbytes>0)
343
 
    BX_DEBUG (("tap read returned %d bytes", nbytes));
 
403
    BX_DEBUG(("tap read returned %d bytes", nbytes));
344
404
  if (nbytes<0) {
345
405
    if (errno != EAGAIN)
346
 
      BX_ERROR (("tap read error: %s", strerror(errno)));
 
406
      BX_ERROR(("tap read error: %s", strerror(errno)));
347
407
    return;
348
408
  }
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]);
362
422
    }
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
365
 
    fflush (rxlog);
366
 
    fflush (rxlog_txt);
 
425
    fflush(rxlog);
 
426
    fflush(rxlog_txt);
367
427
  }
368
428
#endif
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));
372
432
    nbytes = 60;
373
433
  }
374
 
  (*rxh)(rxarg, rxbuf, nbytes);
 
434
  (*rxh)(netdev, rxbuf, nbytes);
375
435
}
376
436
 
377
437
#endif /* if BX_NETWORKING && defined HAVE_ETHERTAP */