⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pktdrvr.c

📁 Windows XP下的抓包程序实现
💻 C
📖 第 1 页 / 共 3 页
字号:
  {
    if (rxOutOfs != rxInOfs)
    {
      RX_ELEMENT far *head = (RX_ELEMENT far*) MK_FP (_DS,rxOutOfs);
      int  size, len = max;

      if (CheckElement(head))
      {
        size = min (head->firstCount, sizeof(RX_ELEMENT));
        len  = min (size, max);
        _fmemcpy (buf, &head->destin, len);
      }
      else
        size = -1;

      rxOutOfs += sizeof (RX_ELEMENT);
      if (rxOutOfs > LAST_RX_BUF)
          rxOutOfs = FIRST_RX_BUF;
      return (size);
    }
    return (0);
  }

  PUBLIC void PktQueueBusy (BOOL busy)
  {
    rxOutOfs = busy ? (rxInOfs + sizeof(RX_ELEMENT)) : rxInOfs;
    if (rxOutOfs > LAST_RX_BUF)
        rxOutOfs = FIRST_RX_BUF;
    pktDrop = 0L;
  }

  PUBLIC WORD PktBuffersUsed (void)
  {
    WORD inOfs  = rxInOfs;
    WORD outOfs = rxOutOfs;

    if (inOfs >= outOfs)
       return ((inOfs - outOfs) / sizeof(RX_ELEMENT));
    return (NUM_RX_BUF - (outOfs - inOfs) / sizeof(RX_ELEMENT));
  }

  PUBLIC DWORD PktRxDropped (void)
  {
    return (pktDrop);
  }
#endif

/**************************************************************************/

LOCAL __inline void PktFreeMem (void)
{
#if (DOSX & PHARLAP)
  if (realSeg)
  {
    _dx_real_free (realSeg);
    realSeg = 0;
  }
#elif (DOSX & DJGPP)
  if (rm_mem.rm_segment)
  {
    unsigned ofs;  /* clear the DOS-mem to prevent further upcalls */

    for (ofs = 0; ofs < 16 * rm_mem.size / 4; ofs += 4)
       _farpokel (_dos_ds, realBase + ofs, 0);
    _go32_dpmi_free_dos_memory (&rm_mem);
    rm_mem.rm_segment = 0;
  }
#elif (DOSX & DOS4GW)
  if (rm_base_sel)
  {
    dpmi_real_free (rm_base_sel);
    rm_base_sel = 0;
  }
#endif
}

/**************************************************************************/

PUBLIC BOOL PktExitDriver (void)
{           
  if (pktInfo.handle)
  {
    if (!PktSetReceiverMode(PDRX_BROADCAST))
       PUTS ("Error restoring receiver mode.");

    if (!PktReleaseHandle(pktInfo.handle))
       PUTS ("Error releasing PKT-DRVR handle.");

    PktFreeMem();
    pktInfo.handle = 0;
  }

  if (pcap_pkt_debug >= 1)
     printf ("Internal stats: too-small %lu, too-large %lu, bad-sync %lu, "
             "wrong-handle %lu\n",
             intStat.tooSmall, intStat.tooLarge,
             intStat.badSync, intStat.wrongHandle);
  return (TRUE);
}

#if (DOSX & (DJGPP|DOS4GW))
static void dump_pkt_stub (void)
{
  int i;

  fprintf (stderr, "PktReceiver %lu, pkt_stub[PktReceiver] =\n",
           PktReceiver);
  for (i = 0; i < 15; i++)
      fprintf (stderr, "%02X, ", real_stub_array[i+PktReceiver]);
  fputs ("\n", stderr);
}
#endif

/*
 * Front end initialization routine
 */
PUBLIC BOOL PktInitDriver (PKT_RX_MODE mode)
{
  PKT_RX_MODE rxMode;
  BOOL   writeInfo = (pcap_pkt_debug >= 3);

  pktInfo.quiet = (pcap_pkt_debug < 3);

#if (DOSX & PHARLAP) && defined(__HIGHC__)
  if (_mwenv != 2)
  {
    fprintf (stderr, "Only Pharlap DOS extender supported.\n");
    return (FALSE);
  }
#endif

#if (DOSX & PHARLAP) && defined(__WATCOMC__)
  if (_Extender != 1)
  {
    fprintf (stderr, "Only DOS4GW style extenders supported.\n");
    return (FALSE);
  }
#endif

  if (!PktSearchDriver())
  {
    PUTS ("Packet driver not found.");
    PktFreeMem();
    return (FALSE);
  }

  if (!PktGetDriverInfo())
  {
    PUTS ("Error getting pkt-drvr information.");
    PktFreeMem();
    return (FALSE);
  }

#if (DOSX & PHARLAP)
  if (RealCopy((ULONG)&rxOutOfs, (ULONG)&pktRxEnd,
               &realBase, &protBase, (USHORT*)&realSeg))
  {
    rxOutOfsFp  = (WORD _far *) (protBase + (WORD) &rxOutOfs);
    rxInOfsFp   = (WORD _far *) (protBase + (WORD) &rxInOfs);
    *rxOutOfsFp = FIRST_RX_BUF;
    *rxInOfsFp  = FIRST_RX_BUF;
  }
  else
  {
    PUTS ("Cannot allocate real-mode stub.");
    return (FALSE);
  }

#elif (DOSX & (DJGPP|DOS4GW))
  if (sizeof(real_stub_array) > 0xFFFF)
  {
    fprintf (stderr, "`real_stub_array[]' too big.\n");
    return (FALSE);
  }
#if (DOSX & DJGPP)
  rm_mem.size = (sizeof(real_stub_array) + 15) / 16;

  if (_go32_dpmi_allocate_dos_memory(&rm_mem) || rm_mem.rm_offset != 0)
  {
    PUTS ("real-mode init failed.");
    return (FALSE);
  }
  realBase = (rm_mem.rm_segment << 4);
  dosmemput (&real_stub_array, sizeof(real_stub_array), realBase);
  _farpokel (_dos_ds, realBase+rxOutOfs, FIRST_RX_BUF);
  _farpokel (_dos_ds, realBase+rxInOfs,  FIRST_RX_BUF);

#elif (DOSX & DOS4GW)
  rm_base_seg = dpmi_real_malloc (sizeof(real_stub_array), &rm_base_sel);
  if (!rm_base_seg)
  {
    PUTS ("real-mode init failed.");
    return (FALSE);
  }
  realBase = (rm_base_seg << 4);
  memcpy ((void*)realBase, &real_stub_array, sizeof(real_stub_array));
  *(WORD*) (realBase+rxOutOfs) = FIRST_RX_BUF;
  *(WORD*) (realBase+rxInOfs)  = FIRST_RX_BUF;

#endif
  {
    int pushf = PktReceiver;

    while (real_stub_array[pushf++] != 0x9C &&    /* pushf */
           real_stub_array[pushf]   != 0xFA)      /* cli   */
    {
      if (++para_skip > 16)
      {
        fprintf (stderr, "Something wrong with `pkt_stub.inc'.\n");
        para_skip = 0;
        dump_pkt_stub();
        return (FALSE);
      }
    }
    if (*(WORD*)(real_stub_array + offsetof(PktRealStub,_dummy)) != 0xB800)
    {
      fprintf (stderr, "`real_stub_array[]' is misaligned.\n");
      return (FALSE);
    }
  }

  if (pcap_pkt_debug > 2)
      dump_pkt_stub();

#else
  rxOutOfs = FIRST_RX_BUF;
  rxInOfs  = FIRST_RX_BUF;
#endif

  if (!PktSetAccess())
  {
    PUTS ("Error setting pkt-drvr access.");
    PktFreeMem();
    return (FALSE);
  }

  if (!PktGetAddress(&myAddress))
  {
    PUTS ("Error fetching adapter address.");
    PktFreeMem();
    return (FALSE);
  }

  if (!PktSetReceiverMode(mode))
  {
    PUTS ("Error setting receiver mode.");
    PktFreeMem();
    return (FALSE);
  }

  if (!PktGetReceiverMode(&rxMode))
  {
    PUTS ("Error getting receiver mode.");
    PktFreeMem();
    return (FALSE);
  }

  if (writeInfo)
     printf ("Pkt-driver information:\n"
             "  Version  : %d.%d\n"
             "  Name     : %.15s\n"
             "  Class    : %u (%s)\n"
             "  Type     : %u\n"
             "  Number   : %u\n"
             "  Funcs    : %u\n"
             "  Intr     : %Xh\n"
             "  Handle   : %u\n"
             "  Extended : %s\n"
             "  Hi-perf  : %s\n"
             "  RX mode  : %s\n"
             "  Eth-addr : %02X:%02X:%02X:%02X:%02X:%02X\n",

             pktInfo.majVer, pktInfo.minVer, pktInfo.name,
             pktInfo.class,  PktGetClassName(pktInfo.class),
             pktInfo.type,   pktInfo.number,
             pktInfo.funcs,  pktInfo.intr,   pktInfo.handle,
             pktInfo.funcs == 2 || pktInfo.funcs == 6 ? "Yes" : "No",
             pktInfo.funcs == 5 || pktInfo.funcs == 6 ? "Yes" : "No",
             PktRXmodeStr(rxMode),
             myAddress[0], myAddress[1], myAddress[2],
             myAddress[3], myAddress[4], myAddress[5]);

#if defined(DEBUG) && (DOSX & PHARLAP)
  if (writeInfo)
  {
    DWORD    rAdr = realBase + (WORD)&PktReceiver;
    unsigned sel, ofs;

    printf ("\nReceiver at   %04X:%04X\n", RP_SEG(rAdr),    RP_OFF(rAdr));
    printf ("Realbase    = %04X:%04X\n",   RP_SEG(realBase),RP_OFF(realBase));

    sel = _FP_SEG (protBase);
    ofs = _FP_OFF (protBase);
    printf ("Protbase    = %04X:%08X\n", sel,ofs);
    printf ("RealSeg     = %04X\n", realSeg);

    sel = _FP_SEG (rxOutOfsFp);
    ofs = _FP_OFF (rxOutOfsFp);
    printf ("rxOutOfsFp  = %04X:%08X\n", sel,ofs);

    sel = _FP_SEG (rxInOfsFp);
    ofs = _FP_OFF (rxInOfsFp);
    printf ("rxInOfsFp   = %04X:%08X\n", sel,ofs);

    printf ("Ready: *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
            *rxOutOfsFp, *rxInOfsFp);

    PktQueueBusy (TRUE);
    printf ("Busy:  *rxOutOfsFp = %04X *rxInOfsFp = %04X\n",
            *rxOutOfsFp, *rxInOfsFp);
  }
#endif

  memset (&pktStat, 0, sizeof(pktStat));  /* clear statistics */
  PktQueueBusy (TRUE);
  return (TRUE);
}


/*
 * DPMI functions only for Watcom + DOS4GW extenders
 */
#if (DOSX & DOS4GW)
LOCAL DWORD dpmi_get_real_vector (int intr)
{
  union REGS r;

  r.x.eax = 0x200;
  r.x.ebx = (DWORD) intr;
  int386 (0x31, &r, &r);
  return ((r.w.cx << 4) + r.w.dx);
}

LOCAL WORD dpmi_real_malloc (int size, WORD *selector)
{
  union REGS r;

  r.x.eax = 0x0100;             /* DPMI allocate DOS memory */
  r.x.ebx = (size + 15) / 16;   /* Number of paragraphs requested */
  int386 (0x31, &r, &r);
  if (r.w.cflag & 1)
     return (0);

  *selector = r.w.dx;
  return (r.w.ax);              /* Return segment address */
}

LOCAL void dpmi_real_free (WORD selector)
{
  union REGS r;

  r.x.eax = 0x101;              /* DPMI free DOS memory */
  r.x.ebx = selector;           /* Selector to free */
  int386 (0x31, &r, &r);
}
#endif


#if defined(DOSX) && (DOSX & PHARLAP)
/*
 * Description:
 *     This routine allocates conventional memory for the specified block
 *     of code (which must be within the first 64K of the protected mode
 *     program segment) and copies the code to it.
 *
 *     The caller should free up the conventional memory block when it
 *     is done with the conventional memory.
 *
 *     NOTE THIS ROUTINE REQUIRES 386|DOS-EXTENDER 3.0 OR LATER.
 *
 * Calling arguments:
 *     start_offs      start of real mode code in program segment
 *     end_offs        1 byte past end of real mode code in program segment
 *     real_basep      returned;  real mode ptr to use as a base for the
 *                        real mode code (eg, to get the real mode FAR
 *                        addr of a function foo(), take
 *                        real_basep + (ULONG) foo).
 *                        This pointer is constructed such that
 *                        offsets within the real mode segment are
 *                        the same as the link-time offsets in the
 *                        protected mode program segment
 *     prot_basep      returned;  prot mode ptr to use as a base for getting
 *                        to the conventional memory, also constructed
 *                        so that adding the prot mode offset of a
 *                        function or variable to the base gets you a
 *                        ptr to the function or variable in the
 *                        conventional memory block.
 *     rmem_adrp       returned;  real mode para addr of allocated
 *                        conventional memory block, to be used to free
 *                        up the conventional memory when done.  DO NOT
 *                        USE THIS TO CONSTRUCT A REAL MODE PTR, USE
 *                        REAL_BASEP INSTEAD SO THAT OFFSETS WORK OUT
 *                        CORRECTLY.
 *
 * Returned values:
 *     0      if error
 *     1      if success
 */
int RealCopy (ULONG    start_offs,
              ULONG    end_offs,
              REALPTR *real_basep,
              FARPTR  *prot_basep,
              USHORT  *rmem_adrp)
{
  ULONG   rm_base;    /* base real mode para addr for accessing */
                      /* allocated conventional memory          */
  UCHAR  *source;     /* source pointer for copy                */
  FARPTR  destin;     /* destination pointer for copy           */
  ULONG   len;        /* number of bytes to copy                */
  ULONG   temp;
  USHORT  stemp;

  /* First check for valid inputs
   */
  if (start_offs >= end_offs || end_offs > 0x10000)
     return (FALSE);

  /* Round start_offs down to a paragraph (16-byte) boundary so we can set up
   * the real mode pointer easily. Round up end_offs to make sure we allocate
   * enough paragraphs
   */
  start_offs &= ~15;
  end_offs = (15 + (end_offs << 4)) >> 4;

  /* Allocate the conventional memory for our real mode code.  Remember to
   * round byte count UP to 16-byte paragraph size.  We alloc it
   * above the DOS data buffer so both the DOS data buffer and the appl
   * conventional mem block can still be resized.
   *
   * First just try to alloc it;  if we can't get it, shrink the appl mem
   * block down to the minimum, try to alloc the memory again, then grow the
   * appl mem block back to the maximum.  (Don't try to shrink the DOS data
   * buffer to free conventional memory;  it wouldn't be good for this routine
   * to have the possible side effect of making file I/O run slower.)
   */
  len = ((end_offs - start_offs) + 15) >> 4;
  if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
  {
    if (_dx_cmem_usage(0, 0, &temp, &temp) != _DOSE_NONE)
       return (FALSE);

    if (_dx_real_above(len, rmem_adrp, &stemp) != _DOSE_NONE)
       *rmem_adrp = 0;

    if (_dx_cmem_usage(0, 1, &temp, &temp) != _DOSE_NONE)
    {
      if (*rmem_adrp != 0)
         _dx_real_free (*rmem_adrp);
      return (FALSE);
    }

    if (*rmem_adrp == 0)
       return (FALSE);
  }

  /* Construct real mode & protected mode pointers to access the allocated
   * memory.  Note we know start_offs is aligned on a paragraph (16-byte)
   * boundary, because we rounded it down.
   *
   * We make the offsets come out rights by backing off the real mode selector
   * by start_offs.
   */
  rm_base = ((ULONG) *rmem_adrp) - (start_offs >> 4);
  RP_SET (*real_basep, 0, rm_base);
  FP_SET (*prot_basep, rm_base << 4, SS_DOSMEM);

  /* Copy the real mode code/data to the allocated memory
   */
  source = (UCHAR *) start_offs;
  destin = *prot_basep;
  FP_SET (destin, FP_OFF(*prot_basep) + start_offs, FP_SEL(*prot_basep));
  len = end_offs - start_offs;
  WriteFarMem (destin, source, len);

  return (TRUE);
}
#endif /* DOSX && (DOSX & PHARLAP) */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -