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>