/* * 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 #include #include #include #include #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(offbh_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; }