Annotation of embedaddon/libnet/src/libnet_link_win32.c, revision 1.1.1.3
1.1 misho 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:
1.1.1.3 ! misho 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:
1.1 misho 36: #include <winsock2.h>
1.1.1.2 misho 37: #include <iphlpapi.h> /* From the Microsoft Platform SDK */
1.1.1.3 ! misho 38: #include <iprtrmib.h>
1.1 misho 39: #include <assert.h>
1.1.1.3 ! misho 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
1.1 misho 105:
106: int
107: libnet_open_link(libnet_t *l)
108: {
109: DWORD dwErrorCode;
110: NetType IFType;
111:
112: if (l == NULL)
1.1.1.3 ! misho 113: {
1.1 misho 114: return (-1);
1.1.1.3 ! misho 115: }
1.1 misho 116:
117: if (l->device == NULL)
118: {
119: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho 120: "%s(): NULL device", __func__);
1.1 misho 121: return (-1);
122: }
123:
124: l->lpAdapter = 0;
125:
126: /* open adapter */
1.1.1.3 ! misho 127: l->lpAdapter = PacketOpenAdapter(l->device);
1.1 misho 128: if (!l->lpAdapter || (l->lpAdapter->hFile == INVALID_HANDLE_VALUE))
129: {
130: dwErrorCode=GetLastError();
131: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho 132: "%s(): unable to open the driver, error Code : %lx",
! 133: __func__, dwErrorCode);
1.1 misho 134: return (-1);
135: }
1.1.1.3 ! misho 136:
1.1 misho 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: {
1.1.1.3 ! misho 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;
1.1 misho 177: }
178: }
179: else
180: {
181: dwErrorCode=GetLastError();
182: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho 183: "%s(): unable to determine the network type, error Code : %lx",
! 184: __func__, dwErrorCode);
1.1 misho 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
1.1.1.3 ! misho 202: libnet_write_link(libnet_t *l, const uint8_t *data, uint32_t size)
1.1 misho 203: {
1.1.1.3 ! misho 204: PACKET pkt;
! 205: DWORD BytesTransfered = -1;
1.1 misho 206:
1.1.1.3 ! misho 207: /* Packet* arguments aren't const, but aren't actually modified.
! 208: */
! 209: PacketInitPacket(&pkt, (PVOID)data, size);
1.1 misho 210:
1.1.1.3 ! misho 211: if (PacketSendPacket(l->lpAdapter, &pkt, TRUE))
! 212: BytesTransfered = size;
1.1 misho 213:
214: return (BytesTransfered);
215: }
216:
217: struct libnet_ether_addr *
218: libnet_get_hwaddr(libnet_t *l)
219: {
1.1.1.3 ! misho 220: struct libnet_ether_addr *mac = &l->link_addr;
1.1 misho 221: ULONG IoCtlBufferLength = (sizeof(PACKET_OID_DATA) + sizeof(ULONG) - 1);
1.1.1.3 ! misho 222: PPACKET_OID_DATA OidData;
1.1 misho 223:
1.1.1.3 ! misho 224: int i = 0;
! 225:
! 226: if (l == NULL)
! 227: {
1.1 misho 228: return (NULL);
1.1.1.3 ! misho 229: }
1.1 misho 230:
1.1.1.3 ! misho 231: if (l->device == NULL)
! 232: {
1.1 misho 233: if (libnet_select_device(l) == -1)
1.1.1.3 ! misho 234: {
1.1 misho 235: snprintf(l->err_buf, LIBNET_ERRBUF_SIZE,
1.1.1.3 ! misho 236: "%s(): can't figure out a device to use", __func__);
1.1 misho 237: return (NULL);
238: }
239: }
240:
1.1.1.3 ! misho 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: }
1.1 misho 248:
1.1.1.3 ! misho 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: }
1.1 misho 257:
1.1.1.3 ! misho 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);
1.1 misho 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);
1.1.1.3 ! misho 288:
1.1 misho 289: if (MAC==NULL)
290: {
291: memset(pulMac, 0xff, sizeof (pulMac));
292: memset(&sin, 0, sizeof(sin));
1.1.1.3 ! misho 293:
1.1 misho 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: }
1.1.1.3 ! misho 317:
1.1 misho 318: pbHexMac = (PBYTE) pulMac;
319:
320: return (pbHexMac);
321: }
322: else
323: {
324: return (MAC);
325: }
326: }
327:
1.1.1.3 ! misho 328: BYTE *libnet_win32_read_arp_table(DWORD DestIP)
1.1 misho 329: {
1.1.1.3 ! misho 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)
1.1 misho 340: {
1.1.1.3 ! misho 341: pIpNetTable = alloca(Size);
1.1 misho 342: status = GetIpNetTable(pIpNetTable, &Size, fOrder);
343: }
344:
1.1.1.3 ! misho 345: if (status == NO_ERROR)
1.1 misho 346: {
1.1.1.3 ! misho 347: DWORD i, ci = pIpNetTable->table[0].dwIndex; /* set current interface */
! 348:
! 349: for (i = 0; i < pIpNetTable->dwNumEntries; ++i)
1.1 misho 350: {
1.1.1.3 ! misho 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: }
1.1 misho 359: }
360: }
1.1.1.3 ! misho 361:
1.1 misho 362: return(NULL);
363: }
364:
1.1.1.3 ! misho 365: /**
! 366: * Local Variables:
! 367: * indent-tabs-mode: nil
! 368: * c-file-style: "stroustrup"
! 369: * End:
! 370: */
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>