kernel-wfp: Print filter weight in "ipsecdump filters"
[strongswan.git] / src / libcharon / plugins / kernel_wfp / ipsecdump.c
1 /*
2 * Copyright (C) 2013 Martin Willi
3 * Copyright (C) 2013 revosec AG
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License as published by the
7 * Free Software Foundation; either version 2 of the License, or (at your
8 * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 * for more details.
14 */
15
16 /* Windows 7, for some fwpmu.h functionality */
17 #define _WIN32_WINNT 0x0601
18
19 #include "kernel_wfp_compat.h"
20
21 #include <library.h>
22
23 ENUM(auth_type_names, IPSEC_AUTH_MD5, IPSEC_AUTH_AES_256,
24 "MD5",
25 "SHA1",
26 "SHA256",
27 "AES128",
28 "AES192",
29 "AES256",
30 );
31
32 ENUM(auth_config_names, 0, 5,
33 "HMAC96",
34 "HMAC96",
35 "HMAC128",
36 "GMAC",
37 "GMAC",
38 "GMAC",
39 );
40
41 ENUM(cipher_type_names, IPSEC_CIPHER_TYPE_DES, IPSEC_CIPHER_TYPE_AES_256,
42 "DES",
43 "3DES",
44 "AES128",
45 "AES192",
46 "AES256",
47 );
48
49 ENUM(cipher_config_names, 1, 8,
50 "CBC",
51 "CBC",
52 "CBC",
53 "CBC",
54 "CBC",
55 "GCM",
56 "GCM",
57 "GCM",
58 );
59
60 ENUM(match_type_names, FWP_MATCH_EQUAL, FWP_MATCH_NOT_EQUAL,
61 "equals",
62 "greater",
63 "less than",
64 "greater or equal than",
65 "less or equal than",
66 "in range",
67 "has all flags set",
68 "has any flags set",
69 "has none flags set",
70 "equals case insensitive",
71 "not equal",
72 );
73
74 ENUM(traffic_type_names, IPSEC_TRAFFIC_TYPE_TRANSPORT, IPSEC_TRAFFIC_TYPE_TUNNEL,
75 "Transport",
76 "Tunnel",
77 );
78
79 /**
80 * Print a GUID to a static buffer
81 */
82 static char *guid2string(GUID *guid)
83 {
84 static char buf[64];
85
86 snprintf(buf, sizeof(buf),
87 "%08x,%04x,%04x%02x,%02x,%02x,%02x,%02x,%02x,%02x,%02x",
88 guid->Data1, guid->Data2, guid->Data3,
89 guid->Data4[0], guid->Data4[1], guid->Data4[2], guid->Data4[3],
90 guid->Data4[4], guid->Data4[5], guid->Data4[6], guid->Data4[7]);
91
92 return buf;
93 }
94
95 const GUID FWPM_CONDITION_IP_SOURCE_ADDRESS = {
96 0xae96897e, 0x2e94, 0x4bc9, { 0xb3,0x13,0xb2,0x7e,0xe8,0x0e,0x57,0x4d }
97 };
98 const GUID FWPM_CONDITION_IP_DESTINATION_ADDRESS = {
99 0x2d79133b, 0xb390, 0x45c6, { 0x86,0x99,0xac,0xac,0xea,0xaf,0xed,0x33 }
100 };
101
102 /**
103 * Convert filter condition key GUID to some known strings
104 */
105 static char* cond2name(GUID *guid, bool *address)
106 {
107 struct {
108 GUID guid;
109 char *name;
110 bool address;
111 } map[] = {
112 { FWPM_CONDITION_IP_LOCAL_ADDRESS, "local address", TRUE},
113 { FWPM_CONDITION_IP_REMOTE_ADDRESS, "remote address", TRUE},
114 { FWPM_CONDITION_IP_SOURCE_ADDRESS, "source address", TRUE},
115 { FWPM_CONDITION_IP_DESTINATION_ADDRESS, "destination address", TRUE},
116 { FWPM_CONDITION_IP_LOCAL_PORT, "local port", FALSE},
117 { FWPM_CONDITION_IP_REMOTE_PORT, "remote port", FALSE},
118 { FWPM_CONDITION_IP_PROTOCOL, "protocol", FALSE},
119 { FWPM_CONDITION_ICMP_CODE, "icmp code", FALSE},
120 { FWPM_CONDITION_ICMP_TYPE, "icmp type", FALSE},
121 };
122 int i;
123
124 for (i = 0; i < countof(map); i++)
125 {
126 if (memeq(&map[i].guid, guid, sizeof(GUID)))
127 {
128 *address = map[i].address;
129 return map[i].name;
130 }
131 }
132 *address = FALSE;
133 return guid2string(guid);
134 }
135
136 /**
137 * Print a host from raw data and IP version
138 */
139 static void print_host(FWP_IP_VERSION version, void *data)
140 {
141 host_t *host = NULL;
142 UINT32 ints[4];
143
144 switch (version)
145 {
146 case FWP_IP_VERSION_V4:
147 ints[0] = untoh32(data);
148 host = host_create_from_chunk(AF_INET, chunk_from_thing(ints[0]), 0);
149 break;
150 case FWP_IP_VERSION_V6:
151 ints[3] = untoh32(data);
152 ints[2] = untoh32(data + 4);
153 ints[1] = untoh32(data + 8);
154 ints[0] = untoh32(data + 12);
155 host = host_create_from_chunk(AF_INET6, chunk_from_thing(ints), 0);
156 break;
157 default:
158 break;
159 }
160 if (host)
161 {
162 printf("%H", host);
163 host->destroy(host);
164 }
165 }
166
167 /**
168 * Print IPSEC_SA_AUTH_INFORMATION0
169 */
170 static void print_auth(IPSEC_SA_AUTH_INFORMATION0 *a)
171 {
172 printf("%N-%N",
173 auth_type_names, a->authTransform.authTransformId.authType,
174 auth_config_names, a->authTransform.authTransformId.authConfig);
175 }
176
177 /**
178 * Print IPSEC_SA_CIPHER_INFORMATION0
179 */
180 static void print_cipher(IPSEC_SA_CIPHER_INFORMATION0 *c)
181 {
182 printf("%N-%N",
183 cipher_type_names, c->cipherTransform.cipherTransformId.cipherType,
184 cipher_config_names, c->cipherTransform.cipherTransformId.cipherConfig);
185 }
186
187 /**
188 * Print IPsec SA transform
189 */
190 static void list_sa(HANDLE engine, IPSEC_SA0 *sa)
191 {
192 printf(" SPI 0x%08x\n", sa->spi);
193 switch (sa->saTransformType)
194 {
195 case IPSEC_TRANSFORM_AH:
196 printf(" AH: ");
197 print_auth(sa->ahInformation);
198 break;
199 case IPSEC_TRANSFORM_ESP_AUTH:
200 printf(" ESP: ");
201 print_auth(sa->espAuthInformation);
202 break;
203 case IPSEC_TRANSFORM_ESP_CIPHER:
204 printf(" ESP: ");
205 print_cipher(sa->espCipherInformation);
206 break;
207 case IPSEC_TRANSFORM_ESP_AUTH_AND_CIPHER:
208 printf(" ESP: ");
209 print_auth(&sa->espAuthAndCipherInformation->saAuthInformation);
210 printf(", ");
211 print_cipher(&sa->espAuthAndCipherInformation->saCipherInformation);
212 break;
213 default:
214 printf(" (Transform %d)", sa->saTransformType);
215 break;
216 }
217 printf("\n");
218 }
219
220 /**
221 * List a filter condition value, optionally as IP address
222 */
223 static void print_value(FWP_CONDITION_VALUE0 *value, bool address)
224 {
225 chunk_t chunk;
226
227 switch (value->type)
228 {
229 case FWP_EMPTY:
230 printf("empty");
231 break;
232 case FWP_UINT8:
233 printf("%u", value->uint8);
234 break;
235 case FWP_UINT16:
236 printf("%u", value->uint16);
237 break;
238 case FWP_UINT32:
239 if (address)
240 {
241 print_host(FWP_IP_VERSION_V4, &value->uint32);
242 }
243 else
244 {
245 printf("%u", value->uint32);
246 }
247 break;
248 case FWP_UINT64:
249 printf("%llu", value->uint64);
250 break;
251 case FWP_INT8:
252 printf("%d", value->int8);
253 break;
254 case FWP_INT16:
255 printf("%d", value->int16);
256 break;
257 case FWP_INT32:
258 printf("%d", value->int32);
259 break;
260 case FWP_INT64:
261 printf("%lld", value->int64);
262 break;
263 case FWP_FLOAT:
264 printf("%f", value->float32);
265 break;
266 case FWP_DOUBLE:
267 printf("%lf", value->double64);
268 break;
269 case FWP_BYTE_ARRAY16_TYPE:
270 if (address)
271 {
272 print_host(FWP_IP_VERSION_V6, value->byteArray16);
273 }
274 else
275 {
276 chunk = chunk_create((u_char*)value->byteArray16, 16);
277 printf("%#B", &chunk);
278 }
279 break;
280 case FWP_BYTE_BLOB_TYPE:
281 chunk = chunk_create(value->byteBlob->data, value->byteBlob->size);
282 printf("%#B", &chunk);
283 break;
284 case FWP_V4_ADDR_MASK:
285 print_host(FWP_IP_VERSION_V4, &value->v4AddrMask->addr);
286 printf("/");
287 print_host(FWP_IP_VERSION_V4, &value->v4AddrMask->mask);
288 break;
289 case FWP_V6_ADDR_MASK:
290 print_host(FWP_IP_VERSION_V6, &value->v6AddrMask->addr);
291 printf("/%u", &value->v6AddrMask->prefixLength);
292 break;
293 case FWP_RANGE_TYPE:
294 print_value((FWP_CONDITION_VALUE0*)&value->rangeValue->valueLow,
295 address);
296 printf(" - ");
297 print_value((FWP_CONDITION_VALUE0*)&value->rangeValue->valueHigh,
298 address);
299 break;
300 default:
301 printf("(unsupported)");
302 break;
303 }
304 }
305
306 /**
307 * List a filter condition
308 */
309 static void list_cond(HANDLE engine, FWPM_FILTER_CONDITION0 *cond)
310 {
311 bool address;
312
313 printf(" '%s' %N '", cond2name(&cond->fieldKey, &address),
314 match_type_names, cond->matchType);
315 print_value(&cond->conditionValue, address);
316 printf("'\n");
317 }
318
319 /**
320 * Print IPsec SA details
321 */
322 static void list_details(HANDLE engine, IPSEC_SA_DETAILS1 *details)
323 {
324 int i;
325
326 printf(" %sbound SA: ",
327 details->saDirection == FWP_DIRECTION_INBOUND ? "In" : "Out");
328 print_host(details->traffic.ipVersion, &details->traffic.localV4Address);
329 printf(" %s ", details->saDirection == FWP_DIRECTION_INBOUND ? "<-" : "->");
330 print_host(details->traffic.ipVersion, &details->traffic.remoteV4Address);
331 printf("\n %N, flags: 0x%06x, lifetime: %us\n",
332 traffic_type_names, details->traffic.trafficType,
333 details->saBundle.flags, details->saBundle.lifetime.lifetimeSeconds);
334 if (details->udpEncapsulation)
335 {
336 printf(" UDP encap ports %u - %u\n",
337 details->udpEncapsulation->localUdpEncapPort,
338 details->udpEncapsulation->remoteUdpEncapPort);
339 }
340 for (i = 0; i < details->saBundle.numSAs; i++)
341 {
342 list_sa(engine, &details->saBundle.saList[i]);
343 }
344 printf(" Filter ID %llu\n", details->transportFilter->filterId);
345 for (i = 0; i < details->transportFilter->numFilterConditions; i++)
346 {
347 list_cond(engine, &details->transportFilter->filterCondition[i]);
348 }
349 }
350
351 /**
352 * List installed SA contexts
353 */
354 static bool list_contexts(HANDLE engine)
355 {
356 HANDLE handle;
357 UINT32 returned;
358 DWORD res;
359 IPSEC_SA_CONTEXT1 **entries;
360
361 res = IPsecSaContextCreateEnumHandle0(engine, NULL, &handle);
362 if (res != ERROR_SUCCESS)
363 {
364 fprintf(stderr, "IPsecSaContextCreateEnumHandle0(): 0x%08x\n", res);
365 return FALSE;
366 }
367
368 while (TRUE)
369 {
370 res = IPsecSaContextEnum1(engine, handle, 1, &entries, &returned);
371 if (res != ERROR_SUCCESS)
372 {
373 fprintf(stderr, "IPsecSaContextEnum1(): 0x%08x\n", res);
374 IPsecSaContextDestroyEnumHandle0(engine, handle);
375 return FALSE;
376 }
377 if (returned == 0)
378 {
379 break;
380 }
381
382 printf("SA context %llu:\n", entries[0]->saContextId);
383 list_details(engine, entries[0]->inboundSa);
384 list_details(engine, entries[0]->outboundSa);
385
386 FwpmFreeMemory0((void**)&entries);
387 }
388 IPsecSaContextDestroyEnumHandle0(engine, handle);
389 return TRUE;
390 }
391
392 const GUID FWPM_LAYER_IPSEC_KM_DEMUX_V4 = {
393 0xf02b1526, 0xa459, 0x4a51, { 0xb9, 0xe3, 0x75, 0x9d, 0xe5, 0x2b, 0x9d, 0x2c }
394 };
395 const GUID FWPM_LAYER_IPSEC_KM_DEMUX_V6 = {
396 0x2f755cf6, 0x2fd4, 0x4e88, { 0xb3, 0xe4, 0xa9, 0x1b, 0xca, 0x49, 0x52, 0x35 }
397 };
398 const GUID FWPM_LAYER_IPSEC_V4 = {
399 0xeda65c74, 0x610d, 0x4bc5, { 0x94, 0x8f, 0x3c, 0x4f, 0x89, 0x55, 0x68, 0x67 }
400 };
401 const GUID FWPM_LAYER_IPSEC_V6 = {
402 0x13c48442, 0x8d87, 0x4261, { 0x9a, 0x29, 0x59, 0xd2, 0xab, 0xc3, 0x48, 0xb4 }
403 };
404 const GUID FWPM_LAYER_IKEEXT_V4 = {
405 0xb14b7bdb, 0xdbbd, 0x473e, { 0xbe, 0xd4, 0x8b, 0x47, 0x08, 0xd4, 0xf2, 0x70 }
406 };
407 const GUID FWPM_LAYER_IKEEXT_V6 = {
408 0xb64786b3, 0xf687, 0x4eb9, { 0x89, 0xd2, 0x8e, 0xf3, 0x2a, 0xcd, 0xab, 0xe2 }
409 };
410 const GUID FWPM_LAYER_INBOUND_IPPACKET_V4 = {
411 0xc86fd1bf, 0x21cd, 0x497e, { 0xa0, 0xbb, 0x17, 0x42, 0x5c, 0x88, 0x5c, 0x58 }
412 };
413 const GUID FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD = {
414 0xb5a230d0, 0xa8c0, 0x44f2, { 0x91, 0x6e, 0x99, 0x1b, 0x53, 0xde, 0xd1, 0xf7 }
415 };
416 const GUID FWPM_LAYER_INBOUND_IPPACKET_V6 = {
417 0xf52032cb, 0x991c, 0x46e7, { 0x97, 0x1d, 0x26, 0x01, 0x45, 0x9a, 0x91, 0xca }
418 };
419 const GUID FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD = {
420 0xbb24c279, 0x93b4, 0x47a2, { 0x83, 0xad, 0xae, 0x16, 0x98, 0xb5, 0x08, 0x85 }
421 };
422 const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V4 = {
423 0x1e5c9fae, 0x8a84, 0x4135, { 0xa3, 0x31, 0x95, 0x0b, 0x54, 0x22, 0x9e, 0xcd }
424 };
425 const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD = {
426 0x08e4bcb5, 0xb647, 0x48f3, { 0x95, 0x3c, 0xe5, 0xdd, 0xbd, 0x03, 0x93, 0x7e }
427 };
428 const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V6 = {
429 0xa3b3ab6b, 0x3564, 0x488c, { 0x91, 0x17, 0xf3, 0x4e, 0x82, 0x14, 0x27, 0x63 }
430 };
431 const GUID FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD = {
432 0x9513d7c4, 0xa934, 0x49dc, { 0x91, 0xa7, 0x6c, 0xcb, 0x80, 0xcc, 0x02, 0xe3 }
433 };
434 const GUID FWPM_LAYER_IPFORWARD_V4 = {
435 0xa82acc24, 0x4ee1, 0x4ee1, { 0xb4, 0x65, 0xfd, 0x1d, 0x25, 0xcb, 0x10, 0xa4 }
436 };
437 const GUID FWPM_LAYER_IPFORWARD_V4_DISCARD = {
438 0x9e9ea773, 0x2fae, 0x4210, { 0x8f, 0x17, 0x34, 0x12, 0x9e, 0xf3, 0x69, 0xeb }
439 };
440 const GUID FWPM_LAYER_IPFORWARD_V6 = {
441 0x7b964818, 0x19c7, 0x493a, { 0xb7, 0x1f, 0x83, 0x2c, 0x36, 0x84, 0xd2, 0x8c }
442 };
443 const GUID FWPM_LAYER_IPFORWARD_V6_DISCARD = {
444 0x31524a5d, 0x1dfe, 0x472f, { 0xbb, 0x93, 0x51, 0x8e, 0xe9, 0x45, 0xd8, 0xa2 }
445 };
446 const GUID FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD = {
447 0xac4a9833, 0xf69d, 0x4648, { 0xb2, 0x61, 0x6d, 0xc8, 0x48, 0x35, 0xef, 0x39 }
448 };
449 const GUID FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD = {
450 0x2a6ff955, 0x3b2b, 0x49d2, { 0x98, 0x48, 0xad, 0x9d, 0x72, 0xdc, 0xaa, 0xb7 }
451 };
452 const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD = {
453 0xc5f10551, 0xbdb0, 0x43d7, { 0xa3, 0x13, 0x50, 0xe2, 0x11, 0xf4, 0xd6, 0x8a }
454 };
455 const GUID FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD = {
456 0xf433df69, 0xccbd, 0x482e, { 0xb9, 0xb2, 0x57, 0x16, 0x56, 0x58, 0xc3, 0xb3 }
457 };
458
459 /**
460 * Convert filter layer GUID to name
461 */
462 static char* layer2name(GUID *guid)
463 {
464 struct {
465 GUID guid;
466 char *name;
467 } map[] = {
468 { FWPM_LAYER_IPSEC_KM_DEMUX_V4, "IPsec KM demux v4" },
469 { FWPM_LAYER_IPSEC_KM_DEMUX_V6, "IPsec KM demux v6" },
470 { FWPM_LAYER_IPSEC_V4, "IPsec v4" },
471 { FWPM_LAYER_IPSEC_V6, "IPsec v6" },
472 { FWPM_LAYER_IKEEXT_V4, "IKE ext v4" },
473 { FWPM_LAYER_IKEEXT_V6, "IKE ext v6" },
474 { FWPM_LAYER_INBOUND_IPPACKET_V4, "inbound v4" },
475 { FWPM_LAYER_INBOUND_IPPACKET_V4_DISCARD, "inbound v4 dsc" },
476 { FWPM_LAYER_INBOUND_IPPACKET_V6, "inbound v6" },
477 { FWPM_LAYER_INBOUND_IPPACKET_V6_DISCARD, "inbound v6 dsc" },
478 { FWPM_LAYER_OUTBOUND_IPPACKET_V4, "outbound v4" },
479 { FWPM_LAYER_OUTBOUND_IPPACKET_V4_DISCARD, "outbound v4 dsc" },
480 { FWPM_LAYER_OUTBOUND_IPPACKET_V6, "outbound v6" },
481 { FWPM_LAYER_OUTBOUND_IPPACKET_V6_DISCARD, "outbound v6 dsc" },
482 { FWPM_LAYER_IPFORWARD_V4, "forward v4" },
483 { FWPM_LAYER_IPFORWARD_V4_DISCARD, "forward v4 dsc" },
484 { FWPM_LAYER_IPFORWARD_V6, "forward v6" },
485 { FWPM_LAYER_IPFORWARD_V6_DISCARD, "forward v6 discard" },
486 { FWPM_LAYER_INBOUND_TRANSPORT_V4, "inbound transport v4" },
487 { FWPM_LAYER_INBOUND_TRANSPORT_V4_DISCARD, "inbound transport v4 dsc" },
488 { FWPM_LAYER_INBOUND_TRANSPORT_V6, "inbound transport v6" },
489 { FWPM_LAYER_INBOUND_TRANSPORT_V6_DISCARD, "inbound v6 transport dsc" },
490 { FWPM_LAYER_OUTBOUND_TRANSPORT_V4, "outbound transport v4" },
491 { FWPM_LAYER_OUTBOUND_TRANSPORT_V4_DISCARD, "outbound transport v4 dsc" },
492 { FWPM_LAYER_OUTBOUND_TRANSPORT_V6, "outbound transport v6" },
493 { FWPM_LAYER_OUTBOUND_TRANSPORT_V6_DISCARD, "outbound transport v6 dsc" },
494 };
495 int i;
496
497 for (i = 0; i < countof(map); i++)
498 {
499 if (memeq(&map[i].guid, guid, sizeof(GUID)))
500 {
501 return map[i].name;
502 }
503 }
504 return NULL;
505 }
506
507 const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4 = {
508 0x191a8a46, 0x0bf8, 0x46cf, { 0xb0,0x45,0x4b,0x45,0xdf,0xa6,0xa3,0x24 }
509 };
510 const GUID FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6 = {
511 0x80c342e3, 0x1e53, 0x4d6f, { 0x9b,0x44,0x03,0xdf,0x5a,0xee,0xe1,0x54 }
512 };
513 const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4 = {
514 0x70a4196c, 0x835b, 0x4fb0, { 0x98,0xe8,0x07,0x5f,0x4d,0x97,0x7d,0x46 }
515 };
516 const GUID FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6 = {
517 0xf1835363, 0xa6a5, 0x4e62, { 0xb1,0x80,0x23,0xdb,0x78,0x9d,0x8d,0xa6 }
518 };
519 const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4 = {
520 0x28829633, 0xc4f0, 0x4e66, { 0x87,0x3f,0x84,0x4d,0xb2,0xa8,0x99,0xc7 }
521 };
522 const GUID FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6 = {
523 0xaf50bec2, 0xc686, 0x429a, { 0x88,0x4d,0xb7,0x44,0x43,0xe7,0xb0,0xb4 }
524 };
525 const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4 = {
526 0xfb532136, 0x15cb, 0x440b, { 0x93,0x7c,0x17,0x17,0xca,0x32,0x0c,0x40 }
527 };
528 const GUID FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6 = {
529 0xdae640cc, 0xe021, 0x4bee, { 0x9e,0xb6,0xa4,0x8b,0x27,0x5c,0x8c,0x1d }
530 };
531
532 /**
533 * Convert filter callout GUID to name
534 */
535 static char* callout2name(GUID *guid)
536 {
537 struct {
538 GUID guid;
539 char *name;
540 } map[] = {
541 { FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V4, "inbound transport v4" },
542 { FWPM_CALLOUT_IPSEC_INBOUND_TRANSPORT_V6, "inbound transport v6" },
543 { FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V4, "outbound transport v4" },
544 { FWPM_CALLOUT_IPSEC_OUTBOUND_TRANSPORT_V6, "outbound transport v6" },
545 { FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V4, "inbound tunnel v4" },
546 { FWPM_CALLOUT_IPSEC_INBOUND_TUNNEL_V6, "inbound tunnel v6" },
547 { FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V4, "outbound tunnel v4" },
548 { FWPM_CALLOUT_IPSEC_OUTBOUND_TUNNEL_V6, "outbound tunnel v6" },
549 { FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V4, "forward in tunnel v4" },
550 { FWPM_CALLOUT_IPSEC_FORWARD_INBOUND_TUNNEL_V6, "forward in tunnel v6" },
551 { FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V4, "forward out tunnel v4" },
552 { FWPM_CALLOUT_IPSEC_FORWARD_OUTBOUND_TUNNEL_V6, "forward out tunnel v6" },
553 };
554 int i;
555
556 for (i = 0; i < countof(map); i++)
557 {
558 if (memeq(&map[i].guid, guid, sizeof(GUID)))
559 {
560 return map[i].name;
561 }
562 }
563 return guid2string(guid);
564 }
565
566 /**
567 * Print display data with description
568 */
569 static void print_display_data(FWPM_DISPLAY_DATA0 *data)
570 {
571 char buf[128];
572
573 buf[0] = '\0';
574 if (data->name)
575 {
576 wcstombs(buf, data->name, sizeof(buf));
577 }
578 printf("%s", buf);
579 if (data->description)
580 {
581 buf[0] = '\0';
582 wcstombs(buf, data->description, sizeof(buf));
583 if (strlen(buf))
584 {
585 printf(" (%s)", buf);
586 }
587 }
588 }
589
590 /**
591 * List installed firewall filters
592 */
593 static bool list_filters(HANDLE engine)
594 {
595 HANDLE handle;
596 UINT32 returned;
597 DWORD res;
598 FWPM_FILTER0 **entries;
599 char *layer;
600 int i;
601
602 res = FwpmFilterCreateEnumHandle0(engine, NULL, &handle);
603 if (res != ERROR_SUCCESS)
604 {
605 fprintf(stderr, "FwpmFilterCreateEnumHandle0(): 0x%08x\n", res);
606 return FALSE;
607 }
608
609 while (TRUE)
610 {
611 res = FwpmFilterEnum0(engine, handle, 1, &entries, &returned);
612 if (res != ERROR_SUCCESS)
613 {
614 fprintf(stderr, "FwpmFilterEnum0(): 0x%08x\n", res);
615 FwpmFilterDestroyEnumHandle0(engine, handle);
616 return FALSE;
617 }
618 if (returned == 0)
619 {
620 break;
621 }
622
623 layer = layer2name(&entries[0]->layerKey);
624 if (layer)
625 {
626 printf("Filter ID %llu, '", entries[0]->filterId);
627 print_display_data(&entries[0]->displayData);
628 printf("'\n");
629 printf(" %s, ", layer);
630 if (entries[0]->effectiveWeight.type == FWP_UINT64)
631 {
632 printf("weight %016llx, ", *entries[0]->effectiveWeight.uint64);
633 }
634
635 switch (entries[0]->action.type)
636 {
637 case FWP_ACTION_BLOCK:
638 printf("block\n");
639 break;
640 case FWP_ACTION_PERMIT:
641 printf("permit\n");
642 break;
643 case FWP_ACTION_CALLOUT_TERMINATING:
644 printf("callout terminating: %s\n",
645 callout2name(&entries[0]->action.calloutKey));
646 break;
647 case FWP_ACTION_CALLOUT_INSPECTION:
648 printf("callout inspection: %s\n",
649 callout2name(&entries[0]->action.calloutKey));
650 break;
651 case FWP_ACTION_CALLOUT_UNKNOWN:
652 printf("callout unknown: %s\n",
653 callout2name(&entries[0]->action.calloutKey));
654 break;
655 default:
656 printf("(unknown action)\n");
657 break;
658 }
659 for (i = 0; i < entries[0]->numFilterConditions; i++)
660 {
661 list_cond(engine, &entries[0]->filterCondition[i]);
662 }
663 }
664 FwpmFreeMemory0((void**)&entries);
665 }
666 FwpmFilterDestroyEnumHandle0(engine, handle);
667 return TRUE;
668 }
669
670 /**
671 * ipsecdump main()
672 */
673 int main(int argc, char *argv[])
674 {
675 FWPM_SESSION0 session = {
676 .displayData = {
677 .name = L"ipsecdump",
678 .description = L"strongSwan SAD/SPD dumper",
679 },
680 };
681 HANDLE engine;
682 DWORD res;
683 int code;
684
685 library_init(NULL, "ipsecdump");
686 atexit(library_deinit);
687
688 res = FwpmEngineOpen0(NULL, RPC_C_AUTHN_WINNT, NULL, &session, &engine);
689 if (res != ERROR_SUCCESS)
690 {
691 fprintf(stderr, "FwpmEngineOpen(): 0x%08x\n", res);
692 return 2;
693 }
694 if (argc > 1 && streq(argv[1], "filters"))
695 {
696 code = list_filters(engine) ? 0 : 1;
697 }
698 else
699 {
700 code = list_contexts(engine) ? 0 : 1;
701 }
702 FwpmEngineClose0(engine);
703 return code;
704 }