Upgrade to OpenVPN 2.1.0
[tomato.git] / release / src / router / openvpn / tap-win32 / error.c
blob82757cce11854a1c8f00b8b18d0b1c0bbf5e3c13
1 /*
2 * TAP-Win32/TAP-Win64 -- A kernel driver to provide virtual tap
3 * device functionality on Windows.
5 * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
7 * This source code is Copyright (C) 2002-2009 OpenVPN Technologies, Inc.,
8 * and is released under the GPL version 2 (see below).
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 //-----------------
26 // DEBUGGING OUTPUT
27 //-----------------
29 const char *g_LastErrorFilename;
30 int g_LastErrorLineNumber;
32 #if DBG
34 DebugOutput g_Debug;
36 BOOLEAN
37 NewlineExists (const char *str, int len)
39 while (len-- > 0)
41 const char c = *str++;
42 if (c == '\n')
43 return TRUE;
44 else if (c == '\0')
45 break;
47 return FALSE;
50 VOID
51 MyDebugInit (unsigned int bufsiz)
53 NdisZeroMemory (&g_Debug, sizeof (g_Debug));
54 g_Debug.text = (char *) MemAlloc (bufsiz, FALSE);
55 if (g_Debug.text)
56 g_Debug.capacity = bufsiz;
59 VOID
60 MyDebugFree ()
62 if (g_Debug.text)
63 MemFree (g_Debug.text, g_Debug.capacity);
64 NdisZeroMemory (&g_Debug, sizeof (g_Debug));
67 VOID
68 MyDebugPrint (const unsigned char* format, ...)
70 if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT)
72 BOOLEAN owned;
73 ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
74 if (owned)
76 const int remaining = (int)g_Debug.capacity - (int)g_Debug.out;
78 if (remaining > 0)
80 va_list args;
81 NTSTATUS status;
82 char *end;
84 va_start (args, format);
85 status = RtlStringCchVPrintfExA (g_Debug.text + g_Debug.out,
86 remaining,
87 &end,
88 NULL,
89 STRSAFE_NO_TRUNCATION | STRSAFE_IGNORE_NULLS,
90 format,
91 args);
92 va_end (args);
94 if (status == STATUS_SUCCESS)
95 g_Debug.out = (unsigned int) (end - g_Debug.text);
96 else
97 g_Debug.error = TRUE;
99 else
100 g_Debug.error = TRUE;
102 RELEASE_MUTEX (&g_Debug.lock);
104 else
105 g_Debug.error = TRUE;
109 BOOLEAN
110 GetDebugLine (char *buf, const int len)
112 static const char *truncated = "[OUTPUT TRUNCATED]\n";
113 BOOLEAN ret = FALSE;
115 NdisZeroMemory (buf, len);
117 if (g_Debug.text && g_Debug.capacity > 0)
119 BOOLEAN owned;
120 ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
121 if (owned)
123 int i = 0;
125 if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in))
127 while (i < (len - 1) && g_Debug.in < g_Debug.out)
129 const char c = g_Debug.text[g_Debug.in++];
130 if (c == '\n')
131 break;
132 buf[i++] = c;
134 if (i < len)
135 buf[i] = '\0';
138 if (!i)
140 if (g_Debug.in == g_Debug.out)
142 g_Debug.in = g_Debug.out = 0;
143 if (g_Debug.error)
145 const unsigned int tlen = strlen (truncated);
146 if (tlen < g_Debug.capacity)
148 NdisMoveMemory (g_Debug.text, truncated, tlen+1);
149 g_Debug.out = tlen;
151 g_Debug.error = FALSE;
155 else
156 ret = TRUE;
158 RELEASE_MUTEX (&g_Debug.lock);
161 return ret;
164 VOID
165 MyAssert (const unsigned char *file, int line)
167 DEBUGP (("MYASSERT failed %s/%d\n", file, line));
168 KeBugCheckEx (0x0F00BABA,
169 (ULONG_PTR) line,
170 (ULONG_PTR) 0,
171 (ULONG_PTR) 0,
172 (ULONG_PTR) 0);
175 VOID
176 PrMac (const MACADDR mac)
178 DEBUGP (("%x:%x:%x:%x:%x:%x",
179 mac[0], mac[1], mac[2],
180 mac[3], mac[4], mac[5]));
183 VOID
184 PrIP (IPADDR ip_addr)
186 const unsigned char *ip = (const unsigned char *) &ip_addr;
188 DEBUGP (("%d.%d.%d.%d",
189 ip[0], ip[1], ip[2], ip[3]));
192 const char *
193 PrIPProto (int proto)
195 switch (proto)
197 case IPPROTO_UDP:
198 return "UDP";
199 case IPPROTO_TCP:
200 return "TCP";
201 case IPPROTO_ICMP:
202 return "ICMP";
203 case IPPROTO_IGMP:
204 return "IGMP";
205 default:
206 return "???";
210 VOID
211 DumpARP (const char *prefix, const ARP_PACKET *arp)
213 DEBUGP (("%s ARP src=", prefix));
214 PrMac (arp->m_MAC_Source);
215 DEBUGP ((" dest="));
216 PrMac (arp->m_MAC_Destination);
217 DEBUGP ((" OP=0x%04x",
218 (int)ntohs(arp->m_ARP_Operation)));
219 DEBUGP ((" M=0x%04x(%d)",
220 (int)ntohs(arp->m_MAC_AddressType),
221 (int)arp->m_MAC_AddressSize));
222 DEBUGP ((" P=0x%04x(%d)",
223 (int)ntohs(arp->m_PROTO_AddressType),
224 (int)arp->m_PROTO_AddressSize));
226 DEBUGP ((" MacSrc="));
227 PrMac (arp->m_ARP_MAC_Source);
228 DEBUGP ((" MacDest="));
229 PrMac (arp->m_ARP_MAC_Destination);
231 DEBUGP ((" IPSrc="));
232 PrIP (arp->m_ARP_IP_Source);
233 DEBUGP ((" IPDest="));
234 PrIP (arp->m_ARP_IP_Destination);
236 DEBUGP (("\n"));
239 struct ethpayload {
240 ETH_HEADER eth;
241 UCHAR payload[DEFAULT_PACKET_LOOKAHEAD];
244 VOID
245 DumpPacket2 (const char *prefix,
246 const ETH_HEADER *eth,
247 const unsigned char *data,
248 unsigned int len)
250 struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE);
251 if (ep)
253 if (len > DEFAULT_PACKET_LOOKAHEAD)
254 len = DEFAULT_PACKET_LOOKAHEAD;
255 ep->eth = *eth;
256 NdisMoveMemory (ep->payload, data, len);
257 DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len);
258 MemFree (ep, sizeof (struct ethpayload));
262 VOID
263 DumpPacket (const char *prefix,
264 const unsigned char *data,
265 unsigned int len)
267 const ETH_HEADER *eth = (const ETH_HEADER *) data;
268 const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER));
270 if (len < sizeof (ETH_HEADER))
272 DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len));
273 return;
276 // ARP Packet?
277 if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP))
279 DumpARP (prefix, (const ARP_PACKET *) data);
280 return;
283 // IPv4 packet?
284 if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER))
285 && eth->proto == htons (ETH_P_IP)
286 && IPH_GET_VER (ip->version_len) == 4)
288 const int hlen = IPH_GET_LEN (ip->version_len);
289 const int blen = len - sizeof (ETH_HEADER);
290 BOOLEAN did = FALSE;
292 DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len));
294 if (!(ntohs (ip->tot_len) == blen && hlen <= blen))
296 DEBUGP ((" XXX"));
297 return;
300 // TCP packet?
301 if (ip->protocol == IPPROTO_TCP
302 && blen - hlen >= (sizeof (TCPHDR)))
304 const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen);
305 DEBUGP ((" "));
306 PrIP (ip->saddr);
307 DEBUGP ((":%d", ntohs (tcp->source)));
308 DEBUGP ((" -> "));
309 PrIP (ip->daddr);
310 DEBUGP ((":%d", ntohs (tcp->dest)));
311 did = TRUE;
314 // UDP packet?
315 else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0
316 && ip->protocol == IPPROTO_UDP
317 && blen - hlen >= (sizeof (UDPHDR)))
319 const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen);
321 // DHCP packet?
322 if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT))
323 && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP)))
325 const DHCP *dhcp = (DHCP *) (data
326 + hlen
327 + sizeof (ETH_HEADER)
328 + sizeof (UDPHDR));
330 int optlen = len
331 - sizeof (ETH_HEADER)
332 - hlen
333 - sizeof (UDPHDR)
334 - sizeof (DHCP);
336 if (optlen < 0)
337 optlen = 0;
339 DumpDHCP (eth, ip, udp, dhcp, optlen);
340 did = TRUE;
343 if (!did)
345 DEBUGP ((" "));
346 PrIP (ip->saddr);
347 DEBUGP ((":%d", ntohs (udp->source)));
348 DEBUGP ((" -> "));
349 PrIP (ip->daddr);
350 DEBUGP ((":%d", ntohs (udp->dest)));
351 did = TRUE;
355 if (!did)
357 DEBUGP ((" ipproto=%d ", ip->protocol));
358 PrIP (ip->saddr);
359 DEBUGP ((" -> "));
360 PrIP (ip->daddr);
363 DEBUGP (("\n"));
364 return;
368 DEBUGP (("%s ??? src=", prefix));
369 PrMac (eth->src);
370 DEBUGP ((" dest="));
371 PrMac (eth->dest);
372 DEBUGP ((" proto=0x%04x len=%d\n",
373 (int) ntohs(eth->proto),
374 len));
378 #endif