error.c 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399
  1. /*
  2. * TAP-Windows -- A kernel driver to provide virtual tap
  3. * device functionality on Windows.
  4. *
  5. * This code was inspired by the CIPE-Win32 driver by Damion K. Wilson.
  6. *
  7. * This source code is Copyright (C) 2002-2014 OpenVPN Technologies, Inc.,
  8. * and is released under the GPL version 2 (see below).
  9. *
  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.
  13. *
  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.
  18. *
  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
  23. */
  24. #include "tap.h"
  25. //-----------------
  26. // DEBUGGING OUTPUT
  27. //-----------------
  28. const char *g_LastErrorFilename;
  29. int g_LastErrorLineNumber;
  30. #if DBG
  31. DebugOutput g_Debug;
  32. BOOLEAN
  33. NewlineExists (const char *str, int len)
  34. {
  35. while (len-- > 0)
  36. {
  37. const char c = *str++;
  38. if (c == '\n')
  39. return TRUE;
  40. else if (c == '\0')
  41. break;
  42. }
  43. return FALSE;
  44. }
  45. VOID
  46. MyDebugInit (unsigned int bufsiz)
  47. {
  48. NdisZeroMemory (&g_Debug, sizeof (g_Debug));
  49. g_Debug.text = (char *) MemAlloc (bufsiz, FALSE);
  50. if (g_Debug.text)
  51. {
  52. g_Debug.capacity = bufsiz;
  53. }
  54. }
  55. VOID
  56. MyDebugFree ()
  57. {
  58. if (g_Debug.text)
  59. {
  60. MemFree (g_Debug.text, g_Debug.capacity);
  61. }
  62. NdisZeroMemory (&g_Debug, sizeof (g_Debug));
  63. }
  64. VOID
  65. MyDebugPrint (const unsigned char* format, ...)
  66. {
  67. if (g_Debug.text && g_Debug.capacity > 0 && CAN_WE_PRINT)
  68. {
  69. BOOLEAN owned;
  70. ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
  71. if (owned)
  72. {
  73. const int remaining = (int)g_Debug.capacity - (int)g_Debug.out;
  74. if (remaining > 0)
  75. {
  76. va_list args;
  77. NTSTATUS status;
  78. char *end;
  79. #ifdef DBG_PRINT
  80. va_start (args, format);
  81. vDbgPrintEx (DPFLTR_IHVNETWORK_ID, DPFLTR_INFO_LEVEL, format, args);
  82. va_end (args);
  83. #endif
  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);
  93. va_start (args, format);
  94. vDbgPrintEx(DPFLTR_IHVDRIVER_ID , 1, format, args);
  95. va_end (args);
  96. if (status == STATUS_SUCCESS)
  97. g_Debug.out = (unsigned int) (end - g_Debug.text);
  98. else
  99. g_Debug.error = TRUE;
  100. }
  101. else
  102. g_Debug.error = TRUE;
  103. RELEASE_MUTEX (&g_Debug.lock);
  104. }
  105. else
  106. g_Debug.error = TRUE;
  107. }
  108. }
  109. BOOLEAN
  110. GetDebugLine (
  111. __in char *buf,
  112. __in const int len
  113. )
  114. {
  115. static const char *truncated = "[OUTPUT TRUNCATED]\n";
  116. BOOLEAN ret = FALSE;
  117. NdisZeroMemory (buf, len);
  118. if (g_Debug.text && g_Debug.capacity > 0)
  119. {
  120. BOOLEAN owned;
  121. ACQUIRE_MUTEX_ADAPTIVE (&g_Debug.lock, owned);
  122. if (owned)
  123. {
  124. int i = 0;
  125. if (g_Debug.error || NewlineExists (g_Debug.text + g_Debug.in, (int)g_Debug.out - (int)g_Debug.in))
  126. {
  127. while (i < (len - 1) && g_Debug.in < g_Debug.out)
  128. {
  129. const char c = g_Debug.text[g_Debug.in++];
  130. if (c == '\n')
  131. break;
  132. buf[i++] = c;
  133. }
  134. if (i < len)
  135. buf[i] = '\0';
  136. }
  137. if (!i)
  138. {
  139. if (g_Debug.in == g_Debug.out)
  140. {
  141. g_Debug.in = g_Debug.out = 0;
  142. if (g_Debug.error)
  143. {
  144. const unsigned int tlen = strlen (truncated);
  145. if (tlen < g_Debug.capacity)
  146. {
  147. NdisMoveMemory (g_Debug.text, truncated, tlen+1);
  148. g_Debug.out = tlen;
  149. }
  150. g_Debug.error = FALSE;
  151. }
  152. }
  153. }
  154. else
  155. ret = TRUE;
  156. RELEASE_MUTEX (&g_Debug.lock);
  157. }
  158. }
  159. return ret;
  160. }
  161. VOID
  162. PrMac (const MACADDR mac)
  163. {
  164. DEBUGP (("%x:%x:%x:%x:%x:%x",
  165. mac[0], mac[1], mac[2],
  166. mac[3], mac[4], mac[5]));
  167. }
  168. VOID
  169. PrIP (IPADDR ip_addr)
  170. {
  171. const unsigned char *ip = (const unsigned char *) &ip_addr;
  172. DEBUGP (("%d.%d.%d.%d",
  173. ip[0], ip[1], ip[2], ip[3]));
  174. }
  175. const char *
  176. PrIPProto (int proto)
  177. {
  178. switch (proto)
  179. {
  180. case IPPROTO_UDP:
  181. return "UDP";
  182. case IPPROTO_TCP:
  183. return "TCP";
  184. case IPPROTO_ICMP:
  185. return "ICMP";
  186. case IPPROTO_IGMP:
  187. return "IGMP";
  188. default:
  189. return "???";
  190. }
  191. }
  192. VOID
  193. DumpARP (const char *prefix, const ARP_PACKET *arp)
  194. {
  195. DEBUGP (("%s ARP src=", prefix));
  196. PrMac (arp->m_MAC_Source);
  197. DEBUGP ((" dest="));
  198. PrMac (arp->m_MAC_Destination);
  199. DEBUGP ((" OP=0x%04x",
  200. (int)ntohs(arp->m_ARP_Operation)));
  201. DEBUGP ((" M=0x%04x(%d)",
  202. (int)ntohs(arp->m_MAC_AddressType),
  203. (int)arp->m_MAC_AddressSize));
  204. DEBUGP ((" P=0x%04x(%d)",
  205. (int)ntohs(arp->m_PROTO_AddressType),
  206. (int)arp->m_PROTO_AddressSize));
  207. DEBUGP ((" MacSrc="));
  208. PrMac (arp->m_ARP_MAC_Source);
  209. DEBUGP ((" MacDest="));
  210. PrMac (arp->m_ARP_MAC_Destination);
  211. DEBUGP ((" IPSrc="));
  212. PrIP (arp->m_ARP_IP_Source);
  213. DEBUGP ((" IPDest="));
  214. PrIP (arp->m_ARP_IP_Destination);
  215. DEBUGP (("\n"));
  216. }
  217. struct ethpayload
  218. {
  219. ETH_HEADER eth;
  220. UCHAR payload[DEFAULT_PACKET_LOOKAHEAD];
  221. };
  222. #ifdef ALLOW_PACKET_DUMP
  223. VOID
  224. DumpPacket2(
  225. __in const char *prefix,
  226. __in const ETH_HEADER *eth,
  227. __in const unsigned char *data,
  228. __in unsigned int len
  229. )
  230. {
  231. struct ethpayload *ep = (struct ethpayload *) MemAlloc (sizeof (struct ethpayload), TRUE);
  232. if (ep)
  233. {
  234. if (len > DEFAULT_PACKET_LOOKAHEAD)
  235. len = DEFAULT_PACKET_LOOKAHEAD;
  236. ep->eth = *eth;
  237. NdisMoveMemory (ep->payload, data, len);
  238. DumpPacket (prefix, (unsigned char *) ep, sizeof (ETH_HEADER) + len);
  239. MemFree (ep, sizeof (struct ethpayload));
  240. }
  241. }
  242. VOID
  243. DumpPacket(
  244. __in const char *prefix,
  245. __in const unsigned char *data,
  246. __in unsigned int len
  247. )
  248. {
  249. const ETH_HEADER *eth = (const ETH_HEADER *) data;
  250. const IPHDR *ip = (const IPHDR *) (data + sizeof (ETH_HEADER));
  251. if (len < sizeof (ETH_HEADER))
  252. {
  253. DEBUGP (("%s TRUNCATED PACKET LEN=%d\n", prefix, len));
  254. return;
  255. }
  256. // ARP Packet?
  257. if (len >= sizeof (ARP_PACKET) && eth->proto == htons (ETH_P_ARP))
  258. {
  259. DumpARP (prefix, (const ARP_PACKET *) data);
  260. return;
  261. }
  262. // IPv4 packet?
  263. if (len >= (sizeof (IPHDR) + sizeof (ETH_HEADER))
  264. && eth->proto == htons (ETH_P_IP)
  265. && IPH_GET_VER (ip->version_len) == 4)
  266. {
  267. const int hlen = IPH_GET_LEN (ip->version_len);
  268. const int blen = len - sizeof (ETH_HEADER);
  269. BOOLEAN did = FALSE;
  270. DEBUGP (("%s IPv4 %s[%d]", prefix, PrIPProto (ip->protocol), len));
  271. if (!(ntohs (ip->tot_len) == blen && hlen <= blen))
  272. {
  273. DEBUGP ((" XXX"));
  274. return;
  275. }
  276. // TCP packet?
  277. if (ip->protocol == IPPROTO_TCP
  278. && blen - hlen >= (sizeof (TCPHDR)))
  279. {
  280. const TCPHDR *tcp = (TCPHDR *) (data + sizeof (ETH_HEADER) + hlen);
  281. DEBUGP ((" "));
  282. PrIP (ip->saddr);
  283. DEBUGP ((":%d", ntohs (tcp->source)));
  284. DEBUGP ((" -> "));
  285. PrIP (ip->daddr);
  286. DEBUGP ((":%d", ntohs (tcp->dest)));
  287. did = TRUE;
  288. }
  289. // UDP packet?
  290. else if ((ntohs (ip->frag_off) & IP_OFFMASK) == 0
  291. && ip->protocol == IPPROTO_UDP
  292. && blen - hlen >= (sizeof (UDPHDR)))
  293. {
  294. const UDPHDR *udp = (UDPHDR *) (data + sizeof (ETH_HEADER) + hlen);
  295. // DHCP packet?
  296. if ((udp->dest == htons (BOOTPC_PORT) || udp->dest == htons (BOOTPS_PORT))
  297. && blen - hlen >= (sizeof (UDPHDR) + sizeof (DHCP)))
  298. {
  299. const DHCP *dhcp = (DHCP *) (data
  300. + hlen
  301. + sizeof (ETH_HEADER)
  302. + sizeof (UDPHDR));
  303. int optlen = len
  304. - sizeof (ETH_HEADER)
  305. - hlen
  306. - sizeof (UDPHDR)
  307. - sizeof (DHCP);
  308. if (optlen < 0)
  309. optlen = 0;
  310. DumpDHCP (eth, ip, udp, dhcp, optlen);
  311. did = TRUE;
  312. }
  313. if (!did)
  314. {
  315. DEBUGP ((" "));
  316. PrIP (ip->saddr);
  317. DEBUGP ((":%d", ntohs (udp->source)));
  318. DEBUGP ((" -> "));
  319. PrIP (ip->daddr);
  320. DEBUGP ((":%d", ntohs (udp->dest)));
  321. did = TRUE;
  322. }
  323. }
  324. if (!did)
  325. {
  326. DEBUGP ((" ipproto=%d ", ip->protocol));
  327. PrIP (ip->saddr);
  328. DEBUGP ((" -> "));
  329. PrIP (ip->daddr);
  330. }
  331. DEBUGP (("\n"));
  332. return;
  333. }
  334. {
  335. DEBUGP (("%s ??? src=", prefix));
  336. PrMac (eth->src);
  337. DEBUGP ((" dest="));
  338. PrMac (eth->dest);
  339. DEBUGP ((" proto=0x%04x len=%d\n",
  340. (int) ntohs(eth->proto),
  341. len));
  342. }
  343. }
  344. #endif // ALLOW_PACKET_DUMP
  345. #endif