summaryrefslogtreecommitdiff
path: root/libnet/src/libnet_link_win32.c
diff options
context:
space:
mode:
Diffstat (limited to 'libnet/src/libnet_link_win32.c')
-rw-r--r--libnet/src/libnet_link_win32.c346
1 files changed, 346 insertions, 0 deletions
diff --git a/libnet/src/libnet_link_win32.c b/libnet/src/libnet_link_win32.c
new file mode 100644
index 0000000..ef70dfe
--- /dev/null
+++ b/libnet/src/libnet_link_win32.c
@@ -0,0 +1,346 @@
+/*
+ * $Id: libnet_link_win32.c,v 1.16 2004/02/18 18:19:00 mike Exp $
+ *
+ * libnet
+ * libnet_link_win32.c - low-level win32 libwpcap routines
+ *
+ * Copyright (c) 2001 - 2002 Don Bowman <don@sandvine.com>
+ * Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
+ * Copyright (c) 2002 Roberto Larcher <roberto.larcher@libero.it>
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ */
+
+#if (HAVE_CONFIG_H)
+#include "../include/config.h"
+#endif
+#include <winsock2.h>
+#include <iphlpapi.h> // From the Microsoft Platform SDK
+#include "../include/win32/libnet.h"
+#include <assert.h>
+#include <Packet32.h>
+#include <Ntddndis.h>
+#include "iprtrmib.h"
+
+int
+libnet_open_link(libnet_t *l)
+{
+ DWORD dwErrorCode;
+ NetType IFType;
+
+ if (l == NULL)
+ {
+ return (-1);
+ }
+
+ if (l->device == NULL)
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): NULL device\n", __func__);
+ return (-1);
+ }
+
+ l->lpAdapter = 0;
+
+ /* open adapter */
+ l->lpAdapter = PacketOpenAdapter(l->device);
+ if (!l->lpAdapter || (l->lpAdapter->hFile == INVALID_HANDLE_VALUE))
+ {
+ dwErrorCode=GetLastError();
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): unable to open the driver, error Code : %lx\n",
+ __func__, dwErrorCode);
+ return (-1);
+ }
+
+ /* increase the send buffer */
+ PacketSetBuff(l->lpAdapter, 512000);
+
+ /*
+ * Assign link type and offset.
+ */
+ if (PacketGetNetType(l->lpAdapter, &IFType))
+ {
+ switch(IFType.LinkType)
+ {
+ case NdisMedium802_3:
+ l->link_type = DLT_EN10MB;
+ l->link_offset = LIBNET_ETH_H;
+ break;
+ case NdisMedium802_5:
+ l->link_type = DLT_IEEE802;
+ l->link_offset = LIBNET_TOKEN_RING_H;
+ break;
+ case NdisMediumFddi:
+ l->link_type = DLT_FDDI;
+ l->link_offset = 0x15;
+ break;
+ case NdisMediumWan:
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s():, WinPcap has disabled support for Network type (%d)\n",
+ __func__, IFType.LinkType);
+ return (-1);
+ break;
+ case NdisMediumAtm:
+ l->link_type = DLT_ATM_RFC1483;
+ break;
+ case NdisMediumArcnet878_2:
+ l->link_type = DLT_ARCNET;
+ break;
+ default:
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): network type (%d) is not supported\n",
+ __func__, IFType.LinkType);
+ return (-1);
+ break;
+ }
+ }
+ else
+ {
+ dwErrorCode=GetLastError();
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): unable to determine the network type, error Code : %lx\n",
+ __func__, dwErrorCode);
+ return (-1);
+ }
+ return (1);
+}
+
+int
+libnet_close_link_interface(libnet_t *l)
+{
+ if (l->lpAdapter)
+ {
+ PacketSetHwFilter(l->lpAdapter, NDIS_PACKET_TYPE_ALL_LOCAL);
+ PacketCloseAdapter(l->lpAdapter);
+ }
+ return (1);
+}
+
+int
+libnet_write_link(libnet_t *l, u_int8_t *packet, u_int32_t size)
+{
+ LPPACKET lpPacket;
+ DWORD BytesTransfered;
+
+ BytesTransfered = -1;
+
+ if ((lpPacket = PacketAllocatePacket()) == NULL)
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): failed to allocate the LPPACKET structure\n", __func__);
+ return (-1);
+ }
+ PacketInitPacket(lpPacket, packet, size);
+
+ /* PacketSendPacket returns a BOOLEAN */
+ if(PacketSendPacket(l->lpAdapter, lpPacket, TRUE))
+ {
+ BytesTransfered = size;
+ }
+
+ PacketFreePacket(lpPacket);
+ return (BytesTransfered);
+ }
+
+struct libnet_ether_addr *
+libnet_get_hwaddr(libnet_t *l)
+{
+ /* This implementation is not-reentrant. */
+ static struct libnet_ether_addr *mac;
+
+ ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1);
+ PPACKET_OID_DATA OidData;
+
+ int i = 0;
+
+ if (l == NULL)
+ {
+ return (NULL);
+ }
+
+ if (l->device == NULL)
+ {
+ if (libnet_select_device(l) == -1)
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): can't figure out a device to use\n", __func__);
+ return (NULL);
+ }
+ }
+
+ mac = (struct libnet_ether_addr *)calloc(1,sizeof(struct libnet_ether_addr));
+ if (mac == NULL)
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): calloc error\n", __func__);
+ return (NULL);
+ }
+
+ OidData = (struct _PACKET_OID_DATA *) malloc(IoCtlBufferLength);
+
+ if (OidData == NULL)
+ {
+ snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
+ "%s(): OidData is NULL\n", __func__);
+ return(NULL);
+ }
+
+ if (l->link_type == DLT_IEEE802)
+ {
+ OidData->Oid = OID_802_5_CURRENT_ADDRESS;
+ }
+ else
+ {
+ OidData->Oid = OID_802_3_CURRENT_ADDRESS;
+ }
+
+ OidData->Length = 6;
+ if((PacketRequest(l->lpAdapter, FALSE, OidData)) == FALSE)
+ {
+ memset(mac, 0, 6);
+ }
+ else
+ {
+ for (i = 0; i < 6; i++)
+ {
+ mac->ether_addr_octet[i] = OidData->Data[i];
+ }
+ }
+ free(OidData);
+ return(mac);
+}
+
+struct hostent *gethostbyname2(const int8_t *name, int af)
+{
+ // XXX not implemented
+ return(NULL);
+}
+
+BYTE *
+libnet_win32_get_remote_mac(libnet_t *l, DWORD DestIP)
+{
+ HRESULT hr;
+ ULONG pulMac[6];
+ ULONG ulLen = 6;
+ static PBYTE pbHexMac;
+ PIP_ADAPTER_INFO pinfo = NULL;
+ DWORD dwSize = 0;
+ struct sockaddr_in sin;
+ static BYTE bcastmac[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
+
+ BYTE *MAC = libnet_win32_read_arp_table(DestIP);
+
+ if (MAC==NULL)
+ {
+ memset(pulMac, 0xff, sizeof (pulMac));
+ memset(&sin, 0, sizeof(sin));
+
+ if((hr = SendARP (DestIP, 0, pulMac, &ulLen)) != NO_ERROR)
+ {
+ *(int32_t *)&sin.sin_addr = DestIP;
+ GetAdaptersInfo(NULL, &dwSize);
+ pinfo = (PIP_ADAPTER_INFO)GlobalAlloc(GPTR, dwSize);
+ GetAdaptersInfo(pinfo, &dwSize);
+ if(pinfo != NULL)
+ {
+ DestIP = inet_addr(pinfo->GatewayList.IpAddress.String);
+ memset (pulMac, 0xff, sizeof (pulMac));
+ ulLen = 6;
+ if((hr = SendARP (DestIP, 0, pulMac, &ulLen)) != NO_ERROR)
+ {
+ GlobalFree(pinfo);
+ return(bcastmac);
+ }
+ }
+ else
+ {
+ GlobalFree(pinfo);
+ return(bcastmac); /* ff:ff:ff:ff:ff:ff */
+ }
+ }
+
+ pbHexMac = (PBYTE) pulMac;
+
+ return (pbHexMac);
+ }
+ else
+ {
+ return (MAC);
+ }
+}
+
+BYTE * libnet_win32_read_arp_table(DWORD DestIP)
+{
+ static BYTE buffMAC[6];
+ BOOL fOrder=TRUE;
+ BYTE *MAC=NULL;
+ DWORD status, i, ci;
+
+ PMIB_IPNETTABLE pIpNetTable = NULL;
+ DWORD Size = 0;
+
+ memset(buffMAC, 0, sizeof(buffMAC));
+
+ if((status = GetIpNetTable(pIpNetTable, &Size, fOrder)) == ERROR_INSUFFICIENT_BUFFER)
+ {
+ pIpNetTable = (PMIB_IPNETTABLE) malloc(Size);
+ assert(pIpNetTable);
+ status = GetIpNetTable(pIpNetTable, &Size, fOrder);
+ }
+
+ if(status == NO_ERROR)
+ {
+ // set current interface
+ ci = pIpNetTable->table[0].dwIndex;
+
+ for (i = 0; i < pIpNetTable->dwNumEntries; ++i)
+ {
+ if (pIpNetTable->table[i].dwIndex != ci)
+ ci = pIpNetTable->table[i].dwIndex;
+
+ if(pIpNetTable->table[i].dwAddr == DestIP) // found IP in arp cache
+ {
+ memcpy(buffMAC, pIpNetTable->table[i].bPhysAddr, sizeof(buffMAC));
+ free(pIpNetTable);
+ return buffMAC;
+ }
+ }
+
+ if (pIpNetTable)
+ free (pIpNetTable);
+ return(NULL);
+ }
+ else
+ {
+ if (pIpNetTable)
+ {
+ free (pIpNetTable);
+ }
+ MAC=NULL;
+ }
+ return(NULL);
+}
+
+/* EOF */