| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 | /* *  TAP-Windows -- A kernel driver to provide virtual tap *                 device functionality on Windows. * *  This code was inspired by the CIPE-Win32 driver by Damion K. Wilson. * *  This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc., *  and is released under the GPL version 2 (see below). * *  This program is free software; you can redistribute it and/or modify *  it under the terms of the GNU General Public License version 2 *  as published by the Free Software Foundation. * *  This program is distributed in the hope that it will be useful, *  but WITHOUT ANY WARRANTY; without even the implied warranty of *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the *  GNU General Public License for more details. * *  You should have received a copy of the GNU General Public License *  along with this program (see the file COPYING included with this *  distribution); if not, write to the Free Software Foundation, Inc., *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */#include "tap.h"//-----------------// DEBUGGING OUTPUT//-----------------const char *g_LastErrorFilename;int g_LastErrorLineNumber;#if DBGDebugOutput g_Debug;BOOLEANNewlineExists (const char *str, int len){    while (len-- > 0)    {        const char c = *str++;        if (c == '\n')            return TRUE;        else if (c == '\0')            break;    }    return FALSE;}VOIDMyDebugInit (unsigned int bufsiz){    NdisZeroMemory (&g_Debug, sizeof (g_Debug));    g_Debug.text = (char *) MemAlloc (bufsiz, FALSE);    if (g_Debug.text)    {        g_Debug.capacity = bufsiz;    }}VOIDMyDebugFree (){    if (g_Debug.text)    {        MemFree (g_Debug.text, g_Debug.capacity);    }    NdisZeroMemory (&g_Debug, sizeof (g_Debug));}VOIDMyDebugPrint (const unsigned char* format, ...){    if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT)    {        BOOLEAN owned;        ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);        if (owned)        {            const int remaining = (int)g_Debug.capacity - (int)g_Debug.out;            if (remaining > 0)            {                va_list args;                NTSTATUS status;                char *end;#ifdef DBG_PRINT                va_start (args, format);                vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args);                va_end (args);#endif                va_start (args, format);                status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out,                    remaining,                    &end,                    NULL,                    STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS,                    format,                    args);                va_end (args);                va_start (args, format);                vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args);                va_end (args);                if (status == STATUS_SUCCESS)                    g_Debug.out = (unsigned int) (end - g_Debug.text);                else                    g_Debug.error = TRUE;            }            else                g_Debug.error = TRUE;            RELEASE_MUTEX (&g_Debug.lock);        }        else            g_Debug.error = TRUE;    }}BOOLEANGetDebugLine (    __in char *buf,    __in const int len    ){    static const char *truncated = "[OUTPUT TRUNCATED]\n";    BOOLEAN ret = FALSE;    NdisZeroMemory (buf, len);    if (g_Debug.text && g_Debug.capacity > 0)    {        BOOLEAN owned;        ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);        if (owned)        {            int i = 0;            if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in))            {                while (i < (len - 1) && g_Debug.in < g_Debug.out)                {                    const char c = g_Debug.text[g_Debug.in++];                    if (c == '\n')                        break;                    buf[i++] = c;                }                if (i < len)                    buf[i] = '\0';            }            if (!i)            {                if (g_Debug.in == g_Debug.out)                {                    g_Debug.in = g_Debug.out = 0;                    if (g_Debug.error)                    {                        const unsigned int tlen = strlen (truncated);                        if (tlen < g_Debug.capacity)                        {                            NdisMoveMemory (g_Debug.text, truncated, tlen+1);                            g_Debug.out = tlen;                        }                        g_Debug.error = FALSE;                    }                }            }            else                ret = TRUE;            RELEASE_MUTEX (&g_Debug.lock);        }          }    return ret;}VOIDPrMac (const MACADDR mac){  DEBUGP (("%x:%x:%x:%x:%x:%x",	    mac[0], mac[1], mac[2],	    mac[3], mac[4], mac[5]));}VOIDPrIP (IPADDR ip_addr){  const unsigned char *ip = (const unsigned char *) &ip_addr;  DEBUGP (("%d.%d.%d.%d",	    ip[0], ip[1], ip[2], ip[3]));}const char *PrIPProto (int proto){    switch (proto)    {    case IPPROTO_UDP:        return "UDP";    case IPPROTO_TCP:        return "TCP";    case IPPROTO_ICMP:        return "ICMP";    case IPPROTO_IGMP:        return "IGMP";    default:        return "???";    }}VOIDDumpARP (const char *prefix, const ARP_PACKET *arp){  DEBUGP (("%s ARP src=", prefix));  PrMac (arp->m_MAC_Source);  DEBUGP ((" dest="));  PrMac (arp->m_MAC_Destination);  DEBUGP ((" OP=0x%04x",	    (int)ntohs(arp->m_ARP_Operation)));  DEBUGP ((" M=0x%04x(%d)",	    (int)ntohs(arp->m_MAC_AddressType),	    (int)arp->m_MAC_AddressSize));  DEBUGP ((" P=0x%04x(%d)",	    (int)ntohs(arp->m_PROTO_AddressType),	    (int)arp->m_PROTO_AddressSize));  DEBUGP ((" MacSrc="));  PrMac (arp->m_ARP_MAC_Source);  DEBUGP ((" MacDest="));  PrMac (arp->m_ARP_MAC_Destination);  DEBUGP ((" IPSrc="));  PrIP (arp->m_ARP_IP_Source);  DEBUGP ((" IPDest="));  PrIP (arp->m_ARP_IP_Destination);  DEBUGP (("\n"));}struct ethpayload{  ETH_HEADER eth;  UCHAR payload[DEFAULT_PACKET_LOOKAHEAD];};#ifdef ALLOW_PACKET_DUMPVOIDDumpPacket2(    __in const char *prefix,    __in const ETH_HEADER *eth,    __in const unsigned char *data,    __in unsigned int len    ){    struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE);    if (ep)    {        if (len > DEFAULT_PACKET_LOOKAHEAD)            len = DEFAULT_PACKET_LOOKAHEAD;        ep->eth = *eth;        NdisMoveMemory (ep->payload, data, len);        DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len);        MemFree (ep, sizeof (struct ethpayload));    }}VOIDDumpPacket(    __in const char *prefix,    __in const unsigned char *data,    __in unsigned int len    ){    const ETH_HEADER *eth = (const ETH_HEADER *) data;    const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER));    if (len < sizeof (ETH_HEADER))    {        DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len));        return;    }    // ARP Packet?    if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP))    {        DumpARP (prefix, (const ARP_PACKET *) data);        return;    }    // IPv4 packet?    if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER))        && eth->proto == htons (ETH_P_IP)        && IPH_GET_VER (ip->version_len) == 4)    {        const int hlen = IPH_GET_LEN (ip->version_len);        const int blen = len - sizeof (ETH_HEADER);        BOOLEAN did = FALSE;        DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len));        if (!(ntohs (ip->tot_len) == blen && hlen <= blen))        {            DEBUGP ((" XXX"));            return;        }        // TCP packet?        if (ip->protocol == IPPROTO_TCP            && blen - hlen >= (sizeof (TCPHDR)))        {            const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen);            DEBUGP ((" "));            PrIP (ip->saddr);            DEBUGP ((":%d", ntohs (tcp->source)));            DEBUGP ((" -> "));            PrIP (ip->daddr);            DEBUGP ((":%d", ntohs (tcp->dest)));            did = TRUE;        }        // UDP packet?        else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0            && ip->protocol == IPPROTO_UDP            && blen - hlen >= (sizeof (UDPHDR)))        {            const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen);            // DHCP packet?            if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT))                && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP)))            {                const DHCP *dhcp = (DHCP *) (data                    + hlen                    + sizeof (ETH_HEADER)                    + sizeof (UDPHDR));                int optlen = len                    - sizeof (ETH_HEADER)                    - hlen                    - sizeof (UDPHDR)                    - sizeof (DHCP);                if (optlen < 0)                    optlen = 0;                DumpDHCP (eth, ip, udp, dhcp, optlen);                did = TRUE;            }            if (!did)            {                DEBUGP ((" "));                PrIP (ip->saddr);                DEBUGP ((":%d", ntohs (udp->source)));                DEBUGP ((" -> "));                PrIP (ip->daddr);                DEBUGP ((":%d", ntohs (udp->dest)));                did = TRUE;            }        }        if (!did)        {            DEBUGP ((" ipproto=%d ", ip->protocol));            PrIP (ip->saddr);            DEBUGP ((" -> "));            PrIP (ip->daddr);        }        DEBUGP (("\n"));        return;    }    {        DEBUGP (("%s ??? src=", prefix));        PrMac (eth->src);        DEBUGP ((" dest="));        PrMac (eth->dest);        DEBUGP ((" proto=0x%04x len=%d\n",            (int) ntohs(eth->proto),            len));    }}#endif // ALLOW_PACKET_DUMP#endif
 |