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>