You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
527 lines
15 KiB
527 lines
15 KiB
/* |
|
* Copyright (c) 2001,2002 Florian Schulze. |
|
* All rights reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
* are met: |
|
* |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* 3. Neither the name of the authors nor the names of the contributors |
|
* may be used to endorse or promote products derived from this software |
|
* without specific prior written permission. |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
* SUCH DAMAGE. |
|
* |
|
* pktif.c - This file is part of lwIPtest |
|
* |
|
**************************************************************************** |
|
* |
|
* This file is derived from an example in lwIP with the following license: |
|
* |
|
* Copyright (c) 2001, Swedish Institute of Computer Science. |
|
* All rights reserved. |
|
* |
|
* Redistribution and use in source and binary forms, with or without |
|
* modification, are permitted provided that the following conditions |
|
* are met: |
|
* 1. Redistributions of source code must retain the above copyright |
|
* notice, this list of conditions and the following disclaimer. |
|
* 2. Redistributions in binary form must reproduce the above copyright |
|
* notice, this list of conditions and the following disclaimer in the |
|
* documentation and/or other materials provided with the distribution. |
|
* 3. Neither the name of the Institute nor the names of its contributors |
|
* may be used to endorse or promote products derived from this software |
|
* without specific prior written permission. |
|
* |
|
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND |
|
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
|
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE |
|
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
|
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY |
|
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF |
|
* SUCH DAMAGE. |
|
* |
|
*/ |
|
|
|
#define WIN32_LEAN_AND_MEAN |
|
#include <stdlib.h> |
|
#include <stdio.h> |
|
#include <windows.h> |
|
#include <packet32.h> |
|
#include <ntddndis.h> |
|
|
|
#include "lwip/debug.h" |
|
|
|
#include "lwip/opt.h" |
|
#include "lwip/def.h" |
|
#include "lwip/mem.h" |
|
#include "lwip/pbuf.h" |
|
#include "lwip/stats.h" |
|
#include "lwip/sys.h" |
|
#include "lwip/ip.h" |
|
|
|
#include "netif/etharp.h" |
|
#include "netif/tcpdump.h" |
|
|
|
#undef NETIF_DEBUG |
|
|
|
/* Define those to better describe your network interface. */ |
|
#define IFNAME0 'p' |
|
#define IFNAME1 'k' |
|
|
|
struct ethernetif { |
|
struct eth_addr *ethaddr; |
|
/* Add whatever per-interface state that is needed here. */ |
|
}; |
|
|
|
static const struct eth_addr ethbroadcast = {{0xff,0xff,0xff,0xff,0xff,0xff}}; |
|
|
|
/* Forward declarations. */ |
|
static void ethernetif_input(struct netif *netif); |
|
static err_t ethernetif_output(struct netif *netif, struct pbuf *p, |
|
struct ip_addr *ipaddr); |
|
|
|
static struct netif *pktif_netif; |
|
|
|
LPADAPTER lpAdapter; |
|
LPPACKET lpPacket; |
|
char buffer[256000]; // buffer to hold the data coming from the driver |
|
unsigned char *cur_packet; |
|
int cur_length; |
|
|
|
struct eth_addr ethaddr; |
|
|
|
/*-----------------------------------------------------------------------------------*/ |
|
int init_adapter(void) |
|
{ |
|
#define Max_Num_Adapter 10 |
|
|
|
char AdapterList[Max_Num_Adapter][1024]; |
|
|
|
int i; |
|
DWORD dwVersion; |
|
DWORD dwWindowsMajorVersion; |
|
|
|
//unicode strings (winnt) |
|
WCHAR AdapterName[8192]; // string that contains a list of the network adapters |
|
WCHAR *temp,*temp1; |
|
|
|
//ascii strings (win95) |
|
char AdapterNamea[8192]; // string that contains a list of the network adapters |
|
char *tempa,*temp1a; |
|
|
|
int AdapterNum=0; |
|
ULONG AdapterLength; |
|
|
|
PPACKET_OID_DATA ppacket_oid_data; |
|
|
|
BOOLEAN result; |
|
|
|
// obtain the name of the adapters installed on this machine |
|
AdapterLength=4096; |
|
|
|
memset(AdapterList,0,sizeof(AdapterList)); |
|
|
|
i=0; |
|
|
|
// the data returned by PacketGetAdapterNames is different in Win95 and in WinNT. |
|
// We have to check the os on which we are running |
|
dwVersion=GetVersion(); |
|
dwWindowsMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion))); |
|
if (!(dwVersion >= 0x80000000 && dwWindowsMajorVersion >= 4)) |
|
{ // Windows NT |
|
if(PacketGetAdapterNames(AdapterName,&AdapterLength)==FALSE){ |
|
printf("Unable to retrieve the list of the adapters!\n"); |
|
return -1; |
|
} |
|
temp=AdapterName; |
|
temp1=AdapterName; |
|
while ((*temp!='\0')||(*(temp-1)!='\0')) |
|
{ |
|
if (*temp=='\0') |
|
{ |
|
memcpy(AdapterList[i],temp1,(temp-temp1)*2); |
|
temp1=temp+1; |
|
i++; |
|
} |
|
|
|
temp++; |
|
} |
|
|
|
AdapterNum=i; |
|
} |
|
|
|
else //windows 95 |
|
{ |
|
if(PacketGetAdapterNames(AdapterNamea,&AdapterLength)==FALSE){ |
|
printf("Unable to retrieve the list of the adapters!\n"); |
|
return -1; |
|
} |
|
tempa=AdapterNamea; |
|
temp1a=AdapterNamea; |
|
|
|
while ((*tempa!='\0')||(*(tempa-1)!='\0')) |
|
{ |
|
if (*tempa=='\0') |
|
{ |
|
memcpy(AdapterList[i],temp1a,tempa-temp1a); |
|
temp1a=tempa+1; |
|
i++; |
|
} |
|
tempa++; |
|
} |
|
|
|
AdapterNum=i; |
|
} |
|
|
|
if (AdapterNum<=0) |
|
return -1; |
|
|
|
ppacket_oid_data=malloc(sizeof(PACKET_OID_DATA)+6); |
|
lpAdapter=PacketOpenAdapter(AdapterList[0]); |
|
if (!lpAdapter || (lpAdapter->hFile == INVALID_HANDLE_VALUE)) |
|
return -1; |
|
ppacket_oid_data->Oid=OID_802_3_PERMANENT_ADDRESS; |
|
ppacket_oid_data->Length=6; |
|
if (!PacketRequest(lpAdapter,FALSE,ppacket_oid_data)) |
|
return -1; |
|
memcpy(ppacket_oid_data->Data,ðaddr,6); |
|
free(ppacket_oid_data); |
|
PacketSetBuff(lpAdapter,512000); |
|
PacketSetReadTimeout(lpAdapter,1); |
|
PacketSetHwFilter(lpAdapter,NDIS_PACKET_TYPE_ALL_LOCAL); |
|
if((lpPacket = PacketAllocatePacket())==NULL){ |
|
return (-1); |
|
} |
|
PacketInitPacket(lpPacket,(char*)buffer,256000); |
|
|
|
return 0; |
|
} |
|
|
|
void shutdown_adapter(void) |
|
{ |
|
struct ethernetif *ethernetif; |
|
|
|
ethernetif = pktif_netif->state; |
|
|
|
PacketFreePacket(lpPacket); |
|
PacketCloseAdapter(lpAdapter); |
|
} |
|
|
|
static void open_adapter(struct ethernetif *ethernetif) |
|
{ |
|
memcpy(ðaddr,ethernetif->ethaddr,6); |
|
} |
|
|
|
/*-----------------------------------------------------------------------------------*/ |
|
static void |
|
low_level_init(struct netif *netif) |
|
{ |
|
struct ethernetif *ethernetif; |
|
|
|
ethernetif = netif->state; |
|
|
|
open_adapter(ethernetif); |
|
|
|
#ifdef NETIF_DEBUG |
|
DEBUGF(NETIF_DEBUG, ("pktif: eth_addr %02X%02X%02X%02X%02X%02X\n",ethernetif->ethaddr->addr[0],ethernetif->ethaddr->addr[1],ethernetif->ethaddr->addr[2],ethernetif->ethaddr->addr[3],ethernetif->ethaddr->addr[4],ethernetif->ethaddr->addr[5])); |
|
#endif /* NETIF_DEBUG */ |
|
/* Do whatever else is needed to initialize interface. */ |
|
|
|
pktif_netif=netif; |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
/* |
|
* low_level_output(): |
|
* |
|
* Should do the actual transmission of the packet. The packet is |
|
* contained in the pbuf that is passed to the function. This pbuf |
|
* might be chained. |
|
* |
|
*/ |
|
/*-----------------------------------------------------------------------------------*/ |
|
|
|
static err_t |
|
low_level_output(struct netif *ethernetif, struct pbuf *p) |
|
{ |
|
struct pbuf *q; |
|
unsigned char buffer[1600]; |
|
unsigned char *ptr; |
|
LPPACKET lpPacket; |
|
|
|
/* initiate transfer(); */ |
|
if (p->tot_len>=1600) |
|
return ERR_BUF; |
|
if((lpPacket = PacketAllocatePacket())==NULL) |
|
return ERR_BUF; |
|
PacketInitPacket(lpPacket,buffer,p->tot_len); |
|
ptr=buffer; |
|
for(q = p; q != NULL; q = q->next) { |
|
/* Send the data from the pbuf to the interface, one pbuf at a |
|
time. The size of the data in each pbuf is kept in the ->len |
|
variable. */ |
|
/* send data from(q->payload, q->len); */ |
|
#ifdef NETIF_DEBUG |
|
DEBUGF(NETIF_DEBUG, ("netif: send ptr %p q->payload %p q->len %i q->next %p\n", ptr, q->payload, (int)q->len, q->next)); |
|
#endif |
|
bcopy(q->payload,ptr,q->len); |
|
ptr+=q->len; |
|
} |
|
|
|
/* signal that packet should be sent(); */ |
|
|
|
if (!PacketSendPacket(lpAdapter,lpPacket,TRUE)) |
|
return ERR_BUF; |
|
PacketFreePacket(lpPacket); |
|
|
|
#ifdef LINK_STATS |
|
stats.link.xmit++; |
|
#endif /* LINK_STATS */ |
|
return ERR_OK; |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
/* |
|
* low_level_input(): |
|
* |
|
* Should allocate a pbuf and transfer the bytes of the incoming |
|
* packet from the interface into the pbuf. |
|
* |
|
*/ |
|
/*-----------------------------------------------------------------------------------*/ |
|
static struct pbuf * |
|
low_level_input(struct netif *ethernetif) |
|
{ |
|
struct pbuf *p, *q; |
|
int start, length; |
|
|
|
/* Obtain the size of the packet and put it into the "len" |
|
variable. */ |
|
length = cur_length; |
|
if (length<=0) |
|
return NULL; |
|
|
|
/* We allocate a pbuf chain of pbufs from the pool. */ |
|
p = pbuf_alloc(PBUF_LINK, (u16_t)length, PBUF_POOL); |
|
#ifdef NETIF_DEBUG |
|
DEBUGF(NETIF_DEBUG, ("netif: recv length %i p->tot_len %i\n", length, (int)p->tot_len)); |
|
#endif |
|
|
|
if(p != NULL) { |
|
/* We iterate over the pbuf chain until we have read the entire |
|
packet into the pbuf. */ |
|
start=0; |
|
for(q = p; q != NULL; q = q->next) { |
|
/* Read enough bytes to fill this pbuf in the chain. The |
|
avaliable data in the pbuf is given by the q->len |
|
variable. */ |
|
/* read data into(q->payload, q->len); */ |
|
#ifdef NETIF_DEBUG |
|
DEBUGF(NETIF_DEBUG, ("netif: recv start %i length %i q->payload %p q->len %i q->next %p\n", start, length, q->payload, (int)q->len, q->next)); |
|
#endif |
|
bcopy(&cur_packet[start],q->payload,q->len); |
|
start+=q->len; |
|
length-=q->len; |
|
if (length<=0) |
|
break; |
|
} |
|
/* acknowledge that packet has been read(); */ |
|
cur_length=0; |
|
#ifdef LINK_STATS |
|
stats.link.recv++; |
|
#endif /* LINK_STATS */ |
|
} else { |
|
/* drop packet(); */ |
|
cur_length=0; |
|
#ifdef LINK_STATS |
|
stats.link.memerr++; |
|
stats.link.drop++; |
|
#endif /* LINK_STATS */ |
|
} |
|
|
|
return p; |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
/* |
|
* ethernetif_output(): |
|
* |
|
* This function is called by the TCP/IP stack when an IP packet |
|
* should be sent. It calls the function called low_level_output() to |
|
* do the actuall transmission of the packet. |
|
* |
|
*/ |
|
/*-----------------------------------------------------------------------------------*/ |
|
static err_t |
|
ethernetif_output(struct netif *netif, struct pbuf *p, |
|
struct ip_addr *ipaddr) |
|
{ |
|
p = etharp_output(netif, ipaddr, p); |
|
if(p != NULL) { |
|
return low_level_output(netif, p); |
|
} |
|
return ERR_OK; |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
/* |
|
* ethernetif_input(): |
|
* |
|
* This function should be called when a packet is ready to be read |
|
* from the interface. It uses the function low_level_input() that |
|
* should handle the actual reception of bytes from the network |
|
* interface. |
|
* |
|
*/ |
|
/*-----------------------------------------------------------------------------------*/ |
|
static void |
|
ethernetif_input(struct netif *netif) |
|
{ |
|
struct ethernetif *ethernetif; |
|
struct eth_hdr *ethhdr; |
|
struct pbuf *p; |
|
|
|
|
|
ethernetif = netif->state; |
|
|
|
p = low_level_input(netif); |
|
|
|
if(p != NULL) { |
|
|
|
#ifdef LINK_STATS |
|
stats.link.recv++; |
|
#endif /* LINK_STATS */ |
|
|
|
ethhdr = p->payload; |
|
|
|
switch(htons(ethhdr->type)) { |
|
case ETHTYPE_IP: |
|
etharp_ip_input(netif, p); |
|
pbuf_header(p, -14); |
|
//if(ip_lookup(p->payload, netif)) { |
|
netif->input(p, netif); |
|
//} |
|
break; |
|
case ETHTYPE_ARP: |
|
p = etharp_arp_input(netif, ethernetif->ethaddr, p); |
|
if(p != NULL) { |
|
low_level_output(netif, p); |
|
pbuf_free(p); |
|
} |
|
break; |
|
default: |
|
pbuf_free(p); |
|
break; |
|
} |
|
} |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
static void |
|
arp_timer(void *arg) |
|
{ |
|
etharp_tmr(); |
|
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL); |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
/* |
|
* ethernetif_init(): |
|
* |
|
* Should be called at the beginning of the program to set up the |
|
* network interface. It calls the function low_level_init() to do the |
|
* actual setup of the hardware. |
|
* |
|
*/ |
|
/*-----------------------------------------------------------------------------------*/ |
|
void |
|
ethernetif_init(struct netif *netif) |
|
{ |
|
struct ethernetif *ethernetif; |
|
|
|
ethernetif = mem_malloc(sizeof(struct ethernetif)); |
|
netif->state = ethernetif; |
|
netif->name[0] = IFNAME0; |
|
netif->name[1] = IFNAME1; |
|
netif->output = ethernetif_output; |
|
|
|
ethernetif->ethaddr = (struct eth_addr *)&(netif->hwaddr[0]); |
|
|
|
low_level_init(netif); |
|
etharp_init(); |
|
|
|
sys_timeout(ARP_TMR_INTERVAL, (sys_timeout_handler)arp_timer, NULL); |
|
} |
|
/*-----------------------------------------------------------------------------------*/ |
|
/* |
|
* pktif_update(): |
|
* |
|
* Needs to be called periodically to get new packets. This could |
|
* be done inside a thread. |
|
*/ |
|
/*-----------------------------------------------------------------------------------*/ |
|
static void ProcessPackets(LPPACKET lpPacket) |
|
{ |
|
|
|
ULONG ulLines, ulBytesReceived; |
|
char *base; |
|
char *buf; |
|
u_int off=0; |
|
u_int tlen,tlen1; |
|
struct bpf_hdr *hdr; |
|
struct ethernetif *ethernetif; |
|
|
|
ethernetif = pktif_netif->state; |
|
|
|
ulBytesReceived = lpPacket->ulBytesReceived; |
|
|
|
buf = lpPacket->Buffer; |
|
|
|
off=0; |
|
|
|
while(off<ulBytesReceived) |
|
{ |
|
//if(kbhit())return; |
|
hdr=(struct bpf_hdr *)(buf+off); |
|
tlen1=hdr->bh_datalen; |
|
cur_length=tlen1; |
|
tlen=hdr->bh_caplen; |
|
off+=hdr->bh_hdrlen; |
|
|
|
ulLines = (tlen + 15) / 16; |
|
if (ulLines > 5) ulLines=5; |
|
|
|
base =(char*)(buf+off); |
|
cur_packet=base; |
|
off=Packet_WORDALIGN(off+tlen); |
|
|
|
ethernetif_input(pktif_netif); |
|
} |
|
} |
|
|
|
void update_adapter(void) |
|
{ |
|
struct ethernetif *ethernetif; |
|
|
|
ethernetif = pktif_netif->state; |
|
|
|
if(PacketReceivePacket(lpAdapter,lpPacket,TRUE)==TRUE) |
|
ProcessPackets(lpPacket); |
|
cur_length=0; |
|
cur_packet=NULL; |
|
} |
|
|
|
|