File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / libnet / src / libnet_link_win32.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:11:38 2023 UTC (9 months, 1 week ago) by misho
Branches: libnet, MAIN
CVS tags: v1_2p1, HEAD
Version 1.2p1

    1: /*
    2:  *  libnet
    3:  *  libnet_link_win32.c - low-level win32 libwpcap routines
    4:  *
    5:  *  Copyright (c) 2001 - 2002 Don Bowman <don@sandvine.com>
    6:  *  Copyright (c) 1998 - 2004 Mike D. Schiffman <mike@infonexus.com>
    7:  *  Copyright (c) 2002 Roberto Larcher <roberto.larcher@libero.it>
    8:  *  All rights reserved.
    9:  *
   10:  * Redistribution and use in source and binary forms, with or without
   11:  * modification, are permitted provided that the following conditions
   12:  * are met:
   13:  * 1. Redistributions of source code must retain the above copyright
   14:  *    notice, this list of conditions and the following disclaimer.
   15:  * 2. Redistributions in binary form must reproduce the above copyright
   16:  *    notice, this list of conditions and the following disclaimer in the
   17:  *    documentation and/or other materials provided with the distribution.
   18:  *
   19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   20:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   21:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   22:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   23:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   24:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   25:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   26:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   27:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   28:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   29:  * SUCH DAMAGE.
   30:  *
   31:  */
   32: 
   33: /* Libnet's unnamespaced ICMP6_ macros stomp on the enumerated versions of
   34:    these names in the MS headers, so pre-include this header. */
   35: 
   36: #include <winsock2.h>
   37: #include <iphlpapi.h> /* From the Microsoft Platform SDK */
   38: #include <iprtrmib.h>
   39: #include <assert.h>
   40: 
   41: #include "common.h"
   42: 
   43: /*
   44:  * These are the types that are the same on all platforms, and that
   45:  * have been defined by <net/bpf.h> for ages.
   46:  */
   47: 
   48: #ifndef DLT_NULL
   49: #define DLT_NULL	0	/* BSD loopback encapsulation */
   50: #endif
   51: 
   52: #ifndef DLT_EN10MB
   53: #define DLT_EN10MB	1	/* Ethernet (10Mb) */
   54: #endif
   55: 
   56: #ifndef DLT_EN3MB
   57: #define DLT_EN3MB	2	/* Experimental Ethernet (3Mb) */
   58: #endif
   59: 
   60: #ifndef DLT_AX25
   61: #define DLT_AX25	3	/* Amateur Radio AX.25 */
   62: #endif
   63: 
   64: #ifndef DLT_PRONET
   65: #define DLT_PRONET	4	/* Proteon ProNET Token Ring */
   66: #endif
   67: 
   68: #ifndef DLT_CHAOS
   69: #define DLT_CHAOS	5	/* Chaos */
   70: #endif
   71: 
   72: #ifndef DLT_IEEE802
   73: #define DLT_IEEE802	6	/* 802.5 Token Ring */
   74: #endif
   75: 
   76: #ifndef DLT_ARCNET
   77: #define DLT_ARCNET	7	/* ARCNET, with BSD-style header */
   78: #endif
   79: 
   80: #ifndef DLT_SLIP
   81: #define DLT_SLIP	8	/* Serial Line IP */
   82: #endif
   83: 
   84: #ifndef DLT_PPP
   85: #define DLT_PPP		9	/* Point-to-point Protocol */
   86: #endif
   87: 
   88: #ifndef DLT_FDDI
   89: #define DLT_FDDI	10	/* FDDI */
   90: #endif
   91: 
   92: /*
   93:  * These are types that are different on some platforms, and that
   94:  * have been defined by <net/bpf.h> for ages.  We use #ifdefs to
   95:  * detect the BSDs that define them differently from the traditional
   96:  * libpcap <net/bpf.h>
   97:  *
   98:  * XXX - DLT_ATM_RFC1483 is 13 in BSD/OS, and DLT_RAW is 14 in BSD/OS,
   99:  * but I don't know what the right #define is for BSD/OS.
  100:  */
  101: 
  102: #ifndef DLT_ATM_RFC1483
  103: #define DLT_ATM_RFC1483	11	/* LLC-encapsulated ATM */
  104: #endif
  105: 
  106: int
  107: libnet_open_link(libnet_t *l)
  108: {
  109:     DWORD dwErrorCode;
  110:     NetType IFType;
  111: 
  112:     if (l == NULL)
  113:     {
  114:         return (-1);
  115:     }
  116: 
  117:     if (l->device == NULL)
  118:     {
  119:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  120:                  "%s(): NULL device", __func__);
  121:         return (-1);
  122:     }
  123: 
  124:     l->lpAdapter = 0;
  125: 
  126:     /* open adapter */
  127:     l->lpAdapter = PacketOpenAdapter(l->device);
  128:     if (!l->lpAdapter || (l->lpAdapter->hFile == INVALID_HANDLE_VALUE))
  129:     {
  130:         dwErrorCode=GetLastError();
  131:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  132:                  "%s(): unable to open the driver, error Code : %lx",
  133:                  __func__, dwErrorCode);
  134:         return (-1);
  135:     }
  136: 
  137:     /* increase the send buffer */
  138:     PacketSetBuff(l->lpAdapter, 512000);
  139: 
  140:     /*
  141:      *  Assign link type and offset.
  142:      */
  143:     if (PacketGetNetType(l->lpAdapter, &IFType))
  144:     {
  145:         switch(IFType.LinkType)
  146:         {
  147:         case NdisMedium802_3:
  148:             l->link_type = DLT_EN10MB;
  149:             l->link_offset = LIBNET_ETH_H;
  150:             break;
  151:         case NdisMedium802_5:
  152:             l->link_type = DLT_IEEE802;
  153:             l->link_offset = LIBNET_TOKEN_RING_H;
  154:             break;
  155:         case NdisMediumFddi:
  156:             l->link_type = DLT_FDDI;
  157:             l->link_offset = 0x15;
  158:             break;
  159:         case NdisMediumWan:
  160:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  161:                      "%s():, WinPcap has disabled support for Network type (%d)",
  162:                      __func__, IFType.LinkType);
  163:             return (-1);
  164:             break;
  165:         case NdisMediumAtm:
  166:             l->link_type = DLT_ATM_RFC1483;
  167:             break;
  168:         case NdisMediumArcnet878_2:
  169:             l->link_type = DLT_ARCNET;
  170:             break;
  171:         default:
  172:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  173:                      "%s(): network type (%d) is not supported",
  174:                      __func__, IFType.LinkType);
  175:             return (-1);
  176:             break;
  177:         }
  178:     }
  179:     else
  180:     {
  181:         dwErrorCode=GetLastError();
  182:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  183:                  "%s(): unable to determine the network type, error Code : %lx",
  184:                  __func__, dwErrorCode);
  185:         return (-1);
  186:     }
  187:     return (1);
  188: }
  189: 
  190: int
  191: libnet_close_link_interface(libnet_t *l)
  192: {
  193:     if (l->lpAdapter)
  194:     {
  195:         PacketSetHwFilter(l->lpAdapter, NDIS_PACKET_TYPE_ALL_LOCAL);
  196:         PacketCloseAdapter(l->lpAdapter);
  197:     }
  198:     return (1);
  199: }
  200: 
  201: int
  202: libnet_write_link(libnet_t *l, const uint8_t *data, uint32_t size)
  203: {
  204:     PACKET pkt;
  205:     DWORD  BytesTransfered = -1;
  206: 
  207:     /* Packet* arguments aren't const, but aren't actually modified.
  208:      */
  209:     PacketInitPacket(&pkt, (PVOID)data, size);
  210: 
  211:     if (PacketSendPacket(l->lpAdapter, &pkt, TRUE))
  212:        BytesTransfered = size;
  213: 
  214:     return (BytesTransfered);
  215:  }
  216: 
  217: struct libnet_ether_addr *
  218: libnet_get_hwaddr(libnet_t *l)
  219: {
  220:     struct libnet_ether_addr *mac = &l->link_addr;
  221:     ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1);
  222:     PPACKET_OID_DATA OidData;
  223: 
  224:     int i = 0;
  225: 
  226:     if (l == NULL)
  227:     {
  228:         return (NULL);
  229:     }
  230: 
  231:     if (l->device == NULL)
  232:     {
  233:         if (libnet_select_device(l) == -1)
  234:         {
  235:             snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  236:                      "%s(): can't figure out a device to use", __func__);
  237:             return (NULL);
  238:         }
  239:     }
  240: 
  241:     OidData = (struct _PACKET_OID_DATA *)malloc(IoCtlBufferLength);
  242:     if (OidData == NULL)
  243:     {
  244:         snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
  245:                  "%s(): OidData is NULL", __func__);
  246:         return(NULL);
  247:     }
  248: 
  249:     if (l->link_type == DLT_IEEE802)
  250:     {
  251:         OidData->Oid = OID_802_5_CURRENT_ADDRESS;
  252:     }
  253:     else
  254:     {
  255:         OidData->Oid = OID_802_3_CURRENT_ADDRESS;
  256:     }
  257: 
  258:     OidData->Length = 6;
  259:     if ((PacketRequest(l->lpAdapter, FALSE, OidData)) == FALSE)
  260:     {
  261:         memset(mac, 0, 6);
  262:     }
  263:     else
  264:     {
  265:         for (i = 0; i < 6; i++)
  266:         {
  267:             mac->ether_addr_octet[i] = OidData->Data[i];
  268:         }
  269:     }
  270:     free(OidData);
  271:     return(mac);
  272: }
  273: 
  274: 
  275: BYTE *
  276: libnet_win32_get_remote_mac(libnet_t *l, DWORD DestIP)
  277: {
  278: 	HRESULT hr;
  279:     ULONG   pulMac[6];
  280:     ULONG   ulLen = 6;
  281: 	static PBYTE pbHexMac;
  282: 	PIP_ADAPTER_INFO pinfo = NULL;
  283: 	DWORD dwSize = 0;
  284: 	struct sockaddr_in sin;
  285: 	static BYTE bcastmac[]= {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
  286: 
  287: 	BYTE *MAC = libnet_win32_read_arp_table(DestIP);
  288: 
  289: 	if (MAC==NULL)
  290: 	{
  291: 		memset(pulMac, 0xff, sizeof (pulMac));
  292: 		memset(&sin, 0, sizeof(sin));
  293: 
  294: 		if((hr = SendARP (DestIP, 0, pulMac, &ulLen)) != NO_ERROR)
  295: 		{
  296: 			*(int32_t *)&sin.sin_addr = DestIP;
  297: 			GetAdaptersInfo(NULL, &dwSize);
  298: 			pinfo = (PIP_ADAPTER_INFO)GlobalAlloc(GPTR, dwSize);
  299: 			GetAdaptersInfo(pinfo, &dwSize);
  300: 			if(pinfo != NULL)
  301: 			{
  302: 				DestIP = inet_addr(pinfo->GatewayList.IpAddress.String);
  303: 				memset (pulMac, 0xff, sizeof (pulMac));
  304: 				ulLen = 6;
  305: 				if((hr = SendARP (DestIP, 0, pulMac, &ulLen)) != NO_ERROR)
  306: 				{
  307: 					GlobalFree(pinfo);
  308: 					return(bcastmac);
  309: 				}
  310: 			}
  311: 			else
  312: 			{
  313: 				GlobalFree(pinfo);
  314: 				return(bcastmac); /* ff:ff:ff:ff:ff:ff */
  315: 			}
  316: 		}
  317: 
  318: 		pbHexMac = (PBYTE) pulMac;
  319: 
  320: 		return (pbHexMac);
  321: 	}
  322: 	else
  323: 	{
  324: 		return (MAC);
  325: 	}
  326: }
  327: 
  328: BYTE *libnet_win32_read_arp_table(DWORD DestIP)
  329: {
  330:     static BYTE buffMAC[6];
  331:     BOOL fOrder = TRUE;
  332:     DWORD status;
  333: 
  334:     MIB_IPNETTABLE *pIpNetTable = NULL;
  335:     DWORD Size = 0;
  336: 
  337:     memset(buffMAC, 0, sizeof(buffMAC));
  338:     status = GetIpNetTable(NULL, &Size, fOrder);
  339:     if (status == ERROR_INSUFFICIENT_BUFFER)
  340:     {
  341:         pIpNetTable = alloca(Size);
  342:         status = GetIpNetTable(pIpNetTable, &Size, fOrder);
  343:     }
  344: 
  345:     if (status == NO_ERROR)
  346:     {
  347:         DWORD i, ci = pIpNetTable->table[0].dwIndex;  /* set current interface */
  348: 
  349:         for (i = 0; i < pIpNetTable->dwNumEntries; ++i)
  350:         {
  351:             if (pIpNetTable->table[i].dwIndex != ci)
  352:                 ci = pIpNetTable->table[i].dwIndex;
  353: 
  354:             if(pIpNetTable->table[i].dwAddr == DestIP) /* found IP in arp cache */
  355:             {
  356:                 memcpy(buffMAC, pIpNetTable->table[i].bPhysAddr, sizeof(buffMAC));
  357:                 return buffMAC;
  358:             }
  359:         }
  360:     }
  361: 
  362:     return(NULL);
  363: }
  364: 
  365: /**
  366:  * Local Variables:
  367:  *  indent-tabs-mode: nil
  368:  *  c-file-style: "stroustrup"
  369:  * End:
  370:  */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>