]> The Tcpdump Group git mirrors - libpcap/blobdiff - pcap-dos.c
pcap_create_interface() needs the interface name on Linux.
[libpcap] / pcap-dos.c
index 26a925b372095cfdf8e3cc0b47ffc7abadbd1060..ea6b225a23efaa6bacb607223955262ce968cdcb 100644 (file)
@@ -1,11 +1,9 @@
 /*
  *  This file is part of DOS-libpcap
- *  Ported to DOS/DOSX by G. Vanem <giva@bgnett.no>
+ *  Ported to DOS/DOSX by G. Vanem <gvanem@yahoo.no>
  *
  *  pcap-dos.c: Interface to PKTDRVR, NDIS2 and 32-bit pmode
  *              network drivers.
- *
- * @(#) $Header: /tcpdump/master/libpcap/pcap-dos.c,v 1.1 2004-12-18 08:52:10 guy Exp $ (LBL)
  */
 
 #include <stdio.h>
@@ -97,9 +95,10 @@ static volatile BOOL exc_occured = 0;
 
 static struct device *handle_to_device [20];
 
+static int  pcap_activate_dos (pcap_t *p);
 static int  pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback,
                            u_char *data);
-static void pcap_close_dos (pcap_t *p);
+static void pcap_cleanup_dos (pcap_t *p);
 static int  pcap_stats_dos (pcap_t *p, struct pcap_stat *ps);
 static int  pcap_sendpacket_dos (pcap_t *p, const void *buf, size_t len);
 static int  pcap_setfilter_dos (pcap_t *p, struct bpf_program *fp);
@@ -143,57 +142,74 @@ static struct device *get_device (int fd)
 }
 
 /*
- * Open MAC-driver with name 'device_name' for live capture of
- * network packets.
+ * Private data for capturing on MS-DOS.
  */
-pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,
-                        int timeout_ms, char *errbuf)
-{ 
-  struct pcap *pcap;
+struct pcap_dos {
+       void (*wait_proc)(void); /* call proc while waiting */
+       struct pcap_stat stat;
+};
 
-  if (snaplen < ETH_MIN)
-      snaplen = ETH_MIN;
+pcap_t *pcap_create_interface (const char *device _U_, char *ebuf)
+{
+       pcap_t *p;
 
-  if (snaplen > ETH_MAX)   /* silently accept and truncate large MTUs */
-      snaplen = ETH_MAX;
+       p = pcap_create_common(ebuf, sizeof (struct pcap_dos));
+       if (p == NULL)
+               return (NULL);
 
-  pcap = calloc (sizeof(*pcap), 1);
-  if (!pcap)
-  {
-    strcpy (errbuf, "Not enough memory (pcap)");
-    return (NULL);
+       p->activate_op = pcap_activate_dos;
+       return (p);
+}
+
+/*
+ * Open MAC-driver with name 'device_name' for live capture of
+ * network packets.
+ */
+static int pcap_activate_dos (pcap_t *pcap)
+{
+  if (pcap->opt.rfmon) {
+    /*
+     * No monitor mode on DOS.
+     */
+    return (PCAP_ERROR_RFMON_NOTSUP);
   }
 
-  pcap->snapshot          = max (ETH_MIN+8, snaplen);
+  if (pcap->snapshot < ETH_MIN+8)
+      pcap->snapshot = ETH_MIN+8;
+
+  if (pcap->snapshot > ETH_MAX)   /* silently accept and truncate large MTUs */
+      pcap->snapshot = ETH_MAX;
+
   pcap->linktype          = DLT_EN10MB;  /* !! */
-  pcap->inter_packet_wait = timeout_ms;
-  pcap->close_op          = pcap_close_dos;
+  pcap->cleanup_op        = pcap_cleanup_dos;
   pcap->read_op           = pcap_read_dos;
   pcap->stats_op          = pcap_stats_dos;
   pcap->inject_op         = pcap_sendpacket_dos;
   pcap->setfilter_op      = pcap_setfilter_dos;
+  pcap->setdirection_op   = NULL;  /* Not implemented.*/
   pcap->fd                = ++ref_count;
 
+  pcap->bufsize = ETH_MAX+100;     /* add some margin */
+  pcap->buffer = calloc (pcap->bufsize, 1);
+
   if (pcap->fd == 1)  /* first time we're called */
   {
-    if (!init_watt32(pcap, device_name, errbuf) ||
-        !first_init(device_name, errbuf, promisc))
+    if (!init_watt32(pcap, pcap->opt.device, pcap->errbuf) ||
+        !first_init(pcap->opt.device, pcap->errbuf, pcap->opt.promisc))
     {
-      free (pcap);
-      return (NULL);
-    } 
+      return (PCAP_ERROR);
+    }
     atexit (close_driver);
   }
-  else if (stricmp(active_dev->name,device_name))
+  else if (stricmp(active_dev->name,pcap->opt.device))
   {
-    snprintf (errbuf, PCAP_ERRBUF_SIZE,
-              "Cannot use different devices simultaneously "
-              "(`%s' vs. `%s')", active_dev->name, device_name);
-    free (pcap);
-    pcap = NULL;
+    pcap_snprintf (pcap->errbuf, PCAP_ERRBUF_SIZE,
+                   "Cannot use different devices simultaneously "
+                   "(`%s' vs. `%s')", active_dev->name, pcap->opt.device);
+    return (PCAP_ERROR);
   }
   handle_to_device [pcap->fd-1] = active_dev;
-  return (pcap);
+  return (0);
 }
 
 /*
@@ -203,16 +219,15 @@ pcap_t *pcap_open_live (const char *device_name, int snaplen, int promisc,
 static int
 pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
 {
+  struct pcap_dos *pd = p->priv;
   struct pcap_pkthdr pcap;
-  struct bpf_insn   *fcode = p->fcode.bf_insns;
-  struct timeval     now, expiry;
-  BYTE  *rx_buf;
+  struct timeval     now, expiry = { 0,0 };
   int    rx_len = 0;
 
-  if (p->inter_packet_wait > 0)
+  if (p->opt.timeout > 0)
   {
     gettimeofday2 (&now, NULL);
-    expiry.tv_usec = now.tv_usec + 1000UL * p->inter_packet_wait;
+    expiry.tv_usec = now.tv_usec + 1000UL * p->opt.timeout;
     expiry.tv_sec  = now.tv_sec;
     while (expiry.tv_usec >= 1000000L)
     {
@@ -238,13 +253,11 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
     if (dev->peek_rx_buf)
     {
       PCAP_ASSERT (dev->release_rx_buf);
-      rx_len = (*dev->peek_rx_buf) (&rx_buf);
+      rx_len = (*dev->peek_rx_buf) (&p->buffer);
     }
     else
     {
-      BYTE buf [ETH_MAX+100]; /* add some margin */
-      rx_len = (*dev->copy_rx_buf) (buf, p->snapshot);
-      rx_buf = buf;
+      rx_len = (*dev->copy_rx_buf) (p->buffer, p->snapshot);
     }
 
     if (rx_len > 0)  /* got a packet */
@@ -257,7 +270,7 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
       pcap.len    = rx_len;
 
       if (callback &&
-          (!fcode || bpf_filter(fcode, rx_buf, pcap.len, pcap.caplen)))
+          (!p->fcode.bf_insns || bpf_filter(p->fcode.bf_insns, p->buffer, pcap.len, pcap.caplen)))
       {
         filter_count++;
 
@@ -265,11 +278,11 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
          * capture.
          */
         gettimeofday2 (&pcap.ts, NULL);
-        (*callback) (data, &pcap, rx_buf);
+        (*callback) (data, &pcap, p->buffer);
       }
 
       if (dev->release_rx_buf)
-        (*dev->release_rx_buf) (rx_buf);
+        (*dev->release_rx_buf) (p->buffer);
 
       if (pcap_pkt_debug > 0)
       {
@@ -281,10 +294,22 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
       return (1);
     }
 
-    /* If not to wait for a packet or pcap_close() called from
+    /* Has "pcap_breakloop()" been called?
+     */
+    if (p->break_loop) {
+      /*
+       * Yes - clear the flag that indicates that it
+       * has, and return -2 to indicate that we were
+       * told to break out of the loop.
+       */
+      p->break_loop = 0;
+      return (-2);
+    }
+
+    /* If not to wait for a packet or pcap_cleanup_dos() called from
      * e.g. SIGINT handler, exit loop now.
      */
-    if (p->inter_packet_wait <= 0 || (volatile int)p->fd <= 0)
+    if (p->opt.timeout <= 0 || (volatile int)p->fd <= 0)
        break;
 
     gettimeofday2 (&now, NULL);
@@ -296,13 +321,13 @@ pcap_read_one (pcap_t *p, pcap_handler callback, u_char *data)
     kbhit();    /* a real CPU hog */
 #endif
 
-    if (p->wait_proc)
-      (*p->wait_proc)();     /* call yield func */
+    if (pd->wait_proc)
+      (*pd->wait_proc)();     /* call yield func */
   }
 
   if (rx_len < 0)            /* receive error */
   {
-    p->md.stat.ps_drop++;
+    pd->stat.ps_drop++;
 #ifdef USE_32BIT_DRIVERS
     if (pcap_pkt_debug > 1)
        printk ("pkt-err %s\n", pktInfo.error);
@@ -317,7 +342,7 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
 {
   int rc, num = 0;
 
-  while (num <= cnt || (cnt < 0))
+  while (num <= cnt || PACKET_COUNT_IS_UNLIMITED(cnt))
   {
     if (p->fd <= 0)
        return (-1);
@@ -337,6 +362,7 @@ pcap_read_dos (pcap_t *p, int cnt, pcap_handler callback, u_char *data)
 static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
 {
   struct net_device_stats *stats;
+  struct pcap_dos         *pd;
   struct device           *dev = p ? get_device(p->fd) : NULL;
 
   if (!dev)
@@ -353,12 +379,13 @@ static int pcap_stats_dos (pcap_t *p, struct pcap_stat *ps)
 
   FLUSHK();
 
-  p->md.stat.ps_recv   = stats->rx_packets;
-  p->md.stat.ps_drop  += stats->rx_missed_errors;
-  p->md.stat.ps_ifdrop = stats->rx_dropped +  /* queue full */
+  pd = p->priv;
+  pd->stat.ps_recv   = stats->rx_packets;
+  pd->stat.ps_drop  += stats->rx_missed_errors;
+  pd->stat.ps_ifdrop = stats->rx_dropped +  /* queue full */
                          stats->rx_errors;    /* HW errors */
   if (ps)
-     *ps = p->md.stat;
+     *ps = pd->stat;
 
   return (0);
 }
@@ -383,7 +410,7 @@ int pcap_stats_ex (pcap_t *p, struct pcap_stat_ex *se)
     strlcpy (p->errbuf, "pktdrvr doesn't have detailed statistics",
              PCAP_ERRBUF_SIZE);
     return (-1);
-  }             
+  }
   memcpy (se, (*dev->get_stats)(dev), sizeof(*se));
   return (0);
 }
@@ -420,12 +447,15 @@ u_long pcap_filter_packets (void)
 /*
  * Close pcap device. Not called for offline captures.
  */
-static void pcap_close_dos (pcap_t *p)
+static void pcap_cleanup_dos (pcap_t *p)
 {
-  if (p && !exc_occured)
+  struct pcap_dos *pd;
+
+  if (!exc_occured)
   {
+    pd = p->priv;
     if (pcap_stats(p,NULL) < 0)
-       p->md.stat.ps_drop = 0;
+       pd->stat.ps_drop = 0;
     if (!get_device(p->fd))
        return;
 
@@ -474,47 +504,52 @@ char *pcap_lookupdev (char *ebuf)
 int pcap_lookupnet (const char *device, bpf_u_int32 *localnet,
                     bpf_u_int32 *netmask, char *errbuf)
 {
+  DWORD mask, net;
+
   if (!_watt_is_init)
   {
-    strcpy (errbuf, "pcap_open_offline() or pcap_open_live() must be "
+    strcpy (errbuf, "pcap_open_offline() or pcap_activate() must be "
                     "called first");
     return (-1);
   }
 
-  *netmask  = _w32_sin_mask;
-  *localnet = my_ip_addr & *netmask;
-  if (*localnet == 0)
+  mask  = _w32_sin_mask;
+  net = my_ip_addr & mask;
+  if (net == 0)
   {
     if (IN_CLASSA(*netmask))
-       *localnet = IN_CLASSA_NET;
+       net = IN_CLASSA_NET;
     else if (IN_CLASSB(*netmask))
-       *localnet = IN_CLASSB_NET;
+       net = IN_CLASSB_NET;
     else if (IN_CLASSC(*netmask))
-       *localnet = IN_CLASSC_NET;
+       net = IN_CLASSC_NET;
     else
     {
-      sprintf (errbuf, "inet class for 0x%lx unknown", *netmask);
+      pcap_snprintf (errbuf, PCAP_ERRBUF_SIZE, "inet class for 0x%lx unknown", mask);
       return (-1);
     }
   }
+  *localnet = htonl (net);
+  *netmask = htonl (mask);
+
   ARGSUSED (device);
   return (0);
-}      
+}
 
 /*
  * Get a list of all interfaces that are present and that we probe okay.
  * Returns -1 on error, 0 otherwise.
- * The list, as returned through "alldevsp", may be null if no interfaces
+ * The list, as returned through "alldevsp", may be NULL if no interfaces
  * were up and could be opened.
  */
-int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
+int pcap_platform_finddevs  (pcap_if_t **alldevsp, char *errbuf)
 {
   struct device     *dev;
-  struct sockaddr_ll sa_ll_1, sa_ll_2;
+  struct sockaddr_in sa_ll_1, sa_ll_2;
   struct sockaddr   *addr, *netmask, *broadaddr, *dstaddr;
   pcap_if_t *devlist = NULL;
   int       ret = 0;
-  size_t    addr_size = sizeof(struct sockaddr_ll);
+  size_t    addr_size = sizeof(*addr);
 
   for (dev = (struct device*)dev_base; dev; dev = dev->next)
   {
@@ -529,14 +564,14 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
 
     memset (&sa_ll_1, 0, sizeof(sa_ll_1));
     memset (&sa_ll_2, 0, sizeof(sa_ll_2));
-    sa_ll_1.sll_family = AF_PACKET;
-    sa_ll_2.sll_family = AF_PACKET;
+    sa_ll_1.sin_family = AF_INET;
+    sa_ll_2.sin_family = AF_INET;
 
     addr      = (struct sockaddr*) &sa_ll_1;
     netmask   = (struct sockaddr*) &sa_ll_1;
     dstaddr   = (struct sockaddr*) &sa_ll_1;
     broadaddr = (struct sockaddr*) &sa_ll_2;
-    memset (&sa_ll_2.sll_addr, 0xFF, sizeof(sa_ll_2.sll_addr));
+    memset (&sa_ll_2.sin_addr, 0xFF, sizeof(sa_ll_2.sin_addr));
 
     if (pcap_add_if(&devlist, dev->name, dev->flags,
                     dev->long_name, errbuf) < 0)
@@ -544,13 +579,15 @@ int pcap_findalldevs (pcap_if_t **alldevsp, char *errbuf)
       ret = -1;
       break;
     }
-    if (add_addr_to_iflist(&devlist,dev->name, dev->flags, addr, addr_size,
+#if 0   /* Pkt drivers should have no addresses */
+    if (add_addr_to_iflist(&devlist, dev->name, dev->flags, addr, addr_size,
                            netmask, addr_size, broadaddr, addr_size,
                            dstaddr, addr_size, errbuf) < 0)
     {
       ret = -1;
       break;
     }
+#endif
   }
 
   if (devlist && ret < 0)
@@ -586,8 +623,10 @@ void pcap_set_wait (pcap_t *p, void (*yield)(void), int wait)
 {
   if (p)
   {
-    p->wait_proc         = yield;
-    p->inter_packet_wait = wait;
+    struct pcap_dos *pd = p->priv;
+
+    pd->wait_proc  = yield;
+    p->opt.timeout = wait;
   }
 }
 
@@ -612,7 +651,7 @@ open_driver (const char *dev_name, char *ebuf, int promisc)
 
       if (!(*dev->probe)(dev))    /* call the xx_probe() function */
       {
-        sprintf (ebuf, "failed to detect device `%s'", dev_name);
+        pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to detect device `%s'", dev_name);
         return (NULL);
       }
       probed_dev = dev;  /* device is probed okay and may be used */
@@ -634,7 +673,7 @@ open_driver (const char *dev_name, char *ebuf, int promisc)
 
     if (!(*dev->open)(dev))
     {
-      sprintf (ebuf, "failed to activate device `%s'", dev_name);
+      pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "failed to activate device `%s'", dev_name);
       if (pktInfo.error && !strncmp(dev->name,"pkt",3))
       {
         strcat (ebuf, ": ");
@@ -656,14 +695,14 @@ open_driver (const char *dev_name, char *ebuf, int promisc)
    */
   if (!dev)
   {
-    sprintf (ebuf, "device `%s' not supported", dev_name);
+    pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not supported", dev_name);
     return (NULL);
   }
 
 not_probed:
   if (!probed_dev)
   {
-    sprintf (ebuf, "device `%s' not probed", dev_name);
+    pcap_snprintf (ebuf, PCAP_ERRBUF_SIZE, "device `%s' not probed", dev_name);
     return (NULL);
   }
   return (dev);
@@ -733,13 +772,13 @@ static void exc_handler (int sig)
          fprintf (stderr, "Catching signal %d.\n", sig);
   }
   exc_occured = 1;
-  pcap_close_dos (NULL);
+  close_driver();
 }
 #endif  /* __DJGPP__ */
 
 
 /*
- * Open the pcap device for the first client calling pcap_open_live()
+ * Open the pcap device for the first client calling pcap_activate()
  */
 static int first_init (const char *name, char *ebuf, int promisc)
 {
@@ -910,7 +949,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
   if (_watt_is_init)
      sock_exit();
 
-  env = getenv ("PCAP_DEBUG");
+  env = getenv ("PCAP_TRACE");
   if (env && atoi(env) > 0 &&
       pcap_pkt_debug < 0)   /* if not already set */
   {
@@ -937,7 +976,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
    *            have default values. Should be taken from another
    *            ini-file/environment in any case (ref. tcpdump.ini)
    */
-  _watt_is_init = 1;  
+  _watt_is_init = 1;
 
   if (!using_pktdrv || !has_ip_addr)  /* for now .... */
   {
@@ -950,7 +989,7 @@ static int init_watt32 (struct pcap *pcap, const char *dev_name, char *err_buf)
   }
   else if (rc && using_pktdrv)
   {
-    sprintf (err_buf, "sock_init() failed, code %d", rc);
+    pcap_snprintf (err_buf, PCAP_ERRBUF_SIZE, "sock_init() failed, code %d", rc);
     return (0);
   }
 
@@ -990,7 +1029,7 @@ int EISA_bus = 0;  /* Where is natural place for this? */
  * Application config hooks to set various driver parameters.
  */
 
-static struct config_table debug_tab[] = {
+static const struct config_table debug_tab[] = {
             { "PKT.DEBUG",       ARG_ATOI,   &pcap_pkt_debug    },
             { "PKT.VECTOR",      ARG_ATOX_W, NULL               },
             { "NDIS.DEBUG",      ARG_ATOI,   NULL               },
@@ -1030,9 +1069,9 @@ static struct config_table debug_tab[] = {
  * pcap_config_hook() is an extension to application's config
  * handling. Uses Watt-32's config-table function.
  */
-int pcap_config_hook (const char *name, const char *value)
+int pcap_config_hook (const char *keyword, const char *value)
 {
-  return parse_config_table (debug_tab, NULL, name, value);
+  return parse_config_table (debug_tab, NULL, keyword, value);
 }
 
 /*
@@ -1069,7 +1108,7 @@ static int pkt_open (struct device *dev)
 
   if (!PktInitDriver(mode))
      return (0);
+
   PktResetStatistics (pktInfo.handle);
   PktQueueBusy (FALSE);
   return (1);
@@ -1267,7 +1306,7 @@ struct device rtl8139_dev LOCKED_VAR = {
               0,0,0,0,0,0,
               &cs89_dev,
               rtl8139_probe     /* dev->probe routine */
-            };            
+            };
 
 /*
  * Dequeue routine is called by polling.