📄 windrv.c
字号:
/*
* FILENAME: windrv.c
*
* Copyright 2001 By InterNiche Technologies Inc. All rights reserved
*
*
* MODULE: WIN32
*
* ROUTINES: wd_prep(), wd_init(), wd_pkt_send(), wd_close(),
* ROUTINES: select_ndis(), packet_task(), packet_init(), packet_chk(),
* ROUTINES: PacketDemuxwCopy(), wd_reg_type(), wd_stats(),
*
* PORTABLE: no
*/
/* windrv.c
*
*
* This file implements an interface to PACKET.LIB which layers on top
* of Microsoft NDIS drivers. PACKET.LIB was obtained from the winpcap
* website.
*
*/
/* Disable warnings */
#pragma warning(disable: 4244 4310 4115)
#define _WINSOCKAPI_ 1 /* and keep winsock out of this... */
#include <windows.h>
#include <stdio.h>
#include <string.h>
#undef FAR
#include "ipport.h" /* interniche files */
#ifdef WIN2K /* If this is a Windows 2000 driver */
#include "q.h"
#include "netbuf.h"
#include "net.h"
#include "ether.h"
#include "arp.h"
#include "ip.h"
#include "nvparms.h"
#include "task.h"
#include "packet32.h"
#define IPRINTF /* dprintf */ /* printf messages for debugging */
#define RXPKTSIZE 1536
/* in this file */
int wd_init(int iface); /* net initialization file */
int wd_pkt_send(struct netbuf *); /* send packet on media */
int wd_close(int iface); /* net close routine */
int wd_reg_type(unshort type, struct net*); /* register a MAC type */
void wd_stats(void * pio, int iface);
char * select_ndis(int * index_to_set);
#ifdef SUPERLOOP
int packet_init_done = FALSE;
#endif /* SUPERLOOP */
/* we use an array of these to build a list of NDIS devices in the
* system and present it to the console user. These do NOT map to
* nets[] indexes!!
*/
struct ndis_name {
int selection; /* 0 for first, etc... */
char description[200]; /* descriptive name from registry */
LPADAPTER lpAdapter; /* Adapter object */
LPPACKET packet; /* packet structure */
};
#define MAX_NDIS 10
struct ndis_name ndnames[MAX_NDIS];
#define MAXTYPES 10 /* usually use 2 - IP and ARP */
/* these structs contain the NDIS specific information for the stack
* to work with an NDIS device via Packet.DLL. These DO map to nets[]
* indexes, e.g. nets[2] corresponds to ndms[2]
*/
struct ndis_mac
{
HANDLE fd;
int nic_index; /* index into ndnames[] */
u_char macaddr[6];
u_short types[MAXTYPES]; /* e.g. 0x0800 for IP, 0x0806 for ARP */
};
/* Ndis_mac structures and their pointers */
struct ndis_mac ndms[MAXNETS];
struct ndis_mac * ndmacs[MAXNETS];
PACKET_OID_DATA oid_data;
struct ndis_stats
{
u_long sends_done;
u_long sends_started;
u_long sends_delayed;
u_long receives; /* total windrv layer receives */
u_long rx_delayed; /* received via overlapped call */
u_long rx_ioctl; /* received via IoControl call */
u_long bad_ips; /* receive with dest IP != us or bcast */
u_long last_bad; /* address in last bad_ips */
u_long resets;
u_long no_rxbuf; /* failed to get a free buffer for RX */
u_long missed_posts; /* times we missed an RX post */
u_long rxcopy; /* times we copied a receive to a little buffer */
} nstat;
struct ndis_stats ndstats[MAX_NDIS];
NET ndis_ifp;
struct bpf_stat adapter_stats;
#ifdef INICHE_TASKS
struct task * tk_ndis;
#else
int packet_init(void);
int packet_chk(void);
#endif
char rcvbuf[512000]; /* Packet.dll interface reads into this buffer */
/* Internal routines to deal with Packet.dll */
int packet_task(int parm);
void PrintPackets(LPPACKET lpPacket);
void PacketDemux(LPPACKET lpPacket, struct ndis_mac * nd);
void PacketDemuxwCopy(LPPACKET lpPacket, struct ndis_mac * nd);
extern DWORD dwVersion;
extern DWORD dwWindowsMajorVersion;
/* FUNCTION: wd_prep()
*
* PARAM1: int iface
*
* RETURNS:
*
* Prepare the interfaces and select NDIS interface to use
*/
int
wd_prep(int iface)
{
struct net * ifp;
struct ndis_mac * nmp;
char * errmsg;
int nic=0; /* selected ndnames[] index */
int j=0;
if (iface >= MAXNETS)
{
dprintf("wd_prep: MAXNETS\n");
return iface;
}
ifp = nets[iface];
nmp = ndmacs[iface] = &ndms[iface];
/* figure out which NDIS device to use */
errmsg = select_ndis(&nic);
if (errmsg)
{
dprintf("NDIS selection: %s\n", errmsg);
return iface;
}
Printu_Net("Using NDIS ethernet device %s\n", ndnames[nic].description);
nmp->nic_index = nic;
dprintf("Mac Address: ");
for (j=0; j < 6; j++)
{
dprintf("%x ", oid_data.Data[j]);
ndmacs[iface]->macaddr[j] = oid_data.Data[j];
}
dprintf ("\n");
/* set up an InterNiche net structure for a static interface */
ifp->n_lnh = ETHHDR_SIZE; /* space reserved for ethernet header */
#ifdef IEEE_802_3
ifp->n_lnh += sizeof(struct snap_hdr); /* Add IEEE bloat */
#endif
ifp->n_hal = 6; /* hardware address length */
ifp->n_mtu = 1514; /* max frame size */
ifp->n_haddr = (char*)&nmp->macaddr[0];
ifp->n_flags = (NF_NBPROT | NF_BCAST); /* driver capability flags */
ifp->mib.ifAdminStatus = 2; /* status = down */
ifp->mib.ifOperStatus = 2; /* will be set up in init() */
ifp->mib.ifLastChange = cticks * (100/TPS);
ifp->mib.ifType = ETHERNET;
ifp->mib.ifDescr = (u_char*)"Windows 2000/95/98 NDIS ethernet Hook";
ifp->mib.ifPhysAddress = &nmp->macaddr[0];
/* install our virtual driver routines */
ifp->n_init = wd_init;
ifp->pkt_send = wd_pkt_send;
ifp->n_close = wd_close;
ifp->n_reg_type = wd_reg_type;
ifp->n_stats = wd_stats;
/* set a custom name for ndis device */
ifp->name[0] = 'n';
ifp->name[1] = 'd';
ifp->name[2] = '0';
/* search the NV parameters for iface setup for our name. If this
* fails we just default to what's already in the ifp.
*/
#ifdef INCLUDE_NVPARMS
if_configbyname(ifp);
#endif
ifp->n_local = (void*)nmp; /* attach ndis pointer to iface */
ndis_ifp = ifp; /* save for task */
IPRINTF("[wd_prep done] ");
return (iface + 1); /* OK return */
}
/* FUNCTION: wd_init()
*
* PARAM1: int iface
*
* RETURNS:
*
* Start a NicheTask thread and mark the interfaces UP
*/
int
wd_init(int iface)
{
struct ndis_mac * nmp;
NET ifp;
#ifdef INICHE_TASKS
/* start a NichTask thread to manage the Packet.DLL IO */
tk_ndis = tk_new(tk_cur, packet_task, 8192, "NDIS", 0);
if (!tk_ndis)
{
dprintf("can't fork NDIS task");
return ENP_RESOURCE;
}
#else
packet_init();
#endif
nmp = ndmacs[iface];
if (nmp == NULL)
{
dtrap();
return ENP_LOGIC;
}
ifp = nets[iface];
/* The interface(s) or adapter(s) were opened and initialized in wd_prep logic */
/* This code sets the admin and operational status as UP */
ifp->n_mib->ifAdminStatus = 1; /* Admin status UP */
ifp->n_mib->ifOperStatus = 1; /* mark as really UP */
return 0;
}
/* FUNCTION: wd_pkt_send()
*
* PARAM1: struct netbuf * pkt
*
* RETURNS: 0 if successful, else -1
*
* Send the packet via Packet.DLL
*/
int
wd_pkt_send(struct netbuf * pkt)
{
struct ndis_mac * nmp;
struct ndis_name * ndname;
/* Send the packet using PacketSendPacket */
nmp = (struct ndis_mac *)pkt->net->n_local; /* get struct */
ndname = &ndnames[nmp->nic_index];
PacketInitPacket(ndname->packet, (char *)pkt->nb_prot + ETHHDR_BIAS,pkt->nb_plen);
if ((PacketSendPacket(ndname->lpAdapter, ndname->packet, TRUE)) == FALSE)
{
dprintf("Unable to send packet\n");
return -1;
}
nstat.sends_done++;
pk_free(pkt);
return 0;
}
/* FUNCTION: wd_close()
*
* PARAM1: int iface
*
* RETURNS:
*/
int
wd_close(int iface)
{
NET ifp;
struct ndis_mac * nd;
ifp = nets[iface];
nd = &ndms[iface];
if (!ifp || !(ifp->n_mib) || (ifp->n_mib->ifAdminStatus == 2))
return 0;
ifp->n_mib->ifAdminStatus = 2; /* Admin status DOWN */
#ifdef INICHE_TASKS
tk_kill(tk_ndis); /* done with the NDIS task... */
tk_ndis = NULL;
#endif
PacketCloseAdapter(ndnames[nd->nic_index].lpAdapter);
return 0;
}
extern int kbhit(void);
extern int getch(void);
/* FUNCTION: select_ndis()
*
* PARAM1: int * nic
*
* RETURNS:
*/
char *
select_ndis(int * nic)
{
ULONG NameLength = 1024;
/* unicode strings (winnt) */
static WCHAR AdapterNames[1024];
WCHAR *tmp; WCHAR *tmp1;
/* ascii strings (win95) */
static char AdapterNamesa[1024];
char * tmpa, * tmp1a;
int ethernets=0; int i =0; int j = 0;
int namelen = 0;
NetType type;
DWORD dwErrorCode;
LPADAPTER lpAdapter;
/*
* The data returned by PacketGetAdapterNames is different in Win95 and
* in WinNT/Win2000. We have to check the os on which we are running
*/
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4))
{
/* Windows NT/2000 Version */
PacketGetAdapterNames ((PTSTR) AdapterNames,(PULONG)&NameLength);
tmp = AdapterNames;
tmp1 = AdapterNames;
while ((*tmp != '\0') || (*(tmp-1) != '\0'))
{
if (*tmp == '\0')
{
namelen = (tmp-tmp1)*2;
for (j=0; j < namelen; j++)
{
ndnames[i].description[j] = *(char *)tmp1;
(char *)tmp1++;
}
/* If the ascii name indicates it's one of those stupid "NdisWan"
* things then skip it. It's not Etherent and the system will
* crash (blue-screen of death) if we try to use it.
*/
if(strstr(ndnames[i].description, "Packet_NdisWan"))
{
tmp1 = ++tmp;
continue;
}
ndnames[i].selection = i;
tmp1 = tmp+1;
i++;
}
tmp++;
}
}
else
{
/* Windows 95/98 Version */
PacketGetAdapterNames (AdapterNamesa, &NameLength);
tmpa = AdapterNamesa;
tmp1a = AdapterNamesa;
while ((*tmpa != '\0') || (*(tmp1a) != '\0'))
{
if (*tmpa == '\0')
{
if(strstr(tmpa, "Packet_NdisWan"))
continue;
namelen = (tmpa-tmp1a)*2;
for (j=0; j < namelen; j++)
{
ndnames[i].description[j] = *(char *)tmp1a;
(char *)tmp1a++;
}
ndnames[i].selection = i;
tmp1a = tmpa+1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -