52 #define _snprintf StringCbPrintfA
67 static const char *StripPcapPrefix(
const char *pcap_dev)
69 return strchr(pcap_dev,
'{');
77 uint32_t Win32GetAdaptersAddresses(IP_ADAPTER_ADDRESSES **pif_info_list)
80 IP_ADAPTER_ADDRESSES *if_info_list;
83 err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, NULL, &size);
84 if (err != ERROR_BUFFER_OVERFLOW) {
87 if_info_list =
SCMalloc((
size_t)size);
88 if (if_info_list == NULL) {
89 return ERROR_NOT_ENOUGH_MEMORY;
91 err = GetAdaptersAddresses(AF_UNSPEC, 0, NULL, if_info_list, &size);
92 if (err != NO_ERROR) {
97 *pif_info_list = if_info_list;
101 uint32_t Win32FindAdapterAddresses(IP_ADAPTER_ADDRESSES *if_info_list,
102 const char *adapter_name,
103 IP_ADAPTER_ADDRESSES **pif_info)
105 DWORD ret = NO_ERROR;
106 adapter_name = StripPcapPrefix(adapter_name);
109 for (IP_ADAPTER_ADDRESSES *current = if_info_list; current != NULL;
110 current = current->Next) {
113 if (strncmp(adapter_name, current->AdapterName, strlen(adapter_name)) ==
121 if (*pif_info == NULL) {
122 ret = ERROR_NOT_FOUND;
128 #if NTDDI_VERSION < NTDDI_VISTA
130 int GetIfaceMTUWin32(
const char *pcap_dev) {
return 0; }
131 int GetGlobalMTUWin32(
void) {
return 0; }
133 int GetIfaceOffloadingWin32(
const char *ifname,
int csum,
int other)
135 SCLogWarning(
"Suricata not targeted for Windows Vista or "
136 "higher. Network offload interrogation not "
140 int DisableIfaceOffloadingWin32(
LiveDevice *ldev,
int csum,
int other)
142 SCLogWarning(
"Suricata not targeted for Windows Vista or "
143 "higher. Network offload interrogation not "
147 int RestoreIfaceOffloadingWin32(
LiveDevice *ldev)
149 SCLogWarning(
"Suricata not targeted for Windows Vista or "
150 "higher. Network offload interrogation not "
157 static HMODULE wmiutils_dll = NULL;
162 static HMODULE WmiUtils(
void)
164 if (wmiutils_dll == NULL) {
166 LoadLibraryA(
"C:\\Windows\\System32\\wbem\\wmiutils.dll");
175 static BSTR utob(uint64_t ui)
178 _ui64tow(ui, buf, 10);
179 return SysAllocString(buf);
188 const char *Win32GetErrorString(DWORD error_code, HMODULE ext_module)
190 char *error_string = NULL;
193 FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS;
194 if (ext_module != NULL) {
195 flags |= FORMAT_MESSAGE_FROM_HMODULE;
197 flags |= FORMAT_MESSAGE_FROM_SYSTEM;
200 FormatMessageA(
flags, ext_module, error_code, 0, (LPTSTR)&error_string, 0,
203 if (error_string == NULL) {
207 error_string[strlen(error_string) - 2] = 0;
216 static void _Win32HResultLog(
SCLogLevel level, HRESULT hr,
const char *file,
217 const char *
function,
const int line)
219 const char *err_str = Win32GetErrorString(hr, WmiUtils());
220 SCLog(level, file,
function, line,
"HRESULT: %s (0x%08" PRIx32
")", err_str,
222 LocalFree((LPVOID)err_str);
225 #define Win32HResultLogDebug(hr) \
226 _Win32HResultLog(SC_LOG_DEBUG, (hr), __FILE__, __FUNCTION__, __LINE__)
228 #define Win32HResultLogDebug(hr)
234 #define WbemLogDebug(hr) (_WbemLogDebug)((hr), __FILE__, __FUNCTION__, __LINE__)
236 static void _WbemLogDebug(HRESULT hr,
const char *file,
const char *
function,
240 IErrorInfo *err_info;
241 BSTR err_description;
242 char *err_description_mb = NULL;
244 _Win32HResultLog(
SC_LOG_DEBUG, hr, file,
function, line);
246 GetErrorInfo(0, &err_info);
248 err_info->lpVtbl->GetDescription(err_info, &err_description))) {
253 err_description_mb =
SCMalloc(SysStringLen(err_description) + 1);
255 if (err_description_mb == NULL) {
261 err_description_mb[SysStringLen(err_description)] = 0;
262 wcstombs(err_description_mb, err_description,
263 SysStringLen(err_description));
270 SCFree(err_description_mb);
271 SysFreeString(err_description);
278 int GetIfaceMTUWin32(
const char *pcap_dev)
280 DWORD err = NO_ERROR;
284 IP_ADAPTER_ADDRESSES *if_info_list = NULL, *if_info = NULL;
285 err = Win32GetAdaptersAddresses(&if_info_list);
286 if (err != NO_ERROR) {
290 err = Win32FindAdapterAddresses(if_info_list, pcap_dev, &if_info);
291 if (err != NO_ERROR) {
302 const char *errbuf = Win32GetErrorString(err, WmiUtils());
303 SCLogWarning(
"Failure when trying to get MTU via syscall for '%s': %s "
305 pcap_dev, errbuf, (uint32_t)err);
306 LocalFree((LPVOID)errbuf);
308 SCLogInfo(
"Found an MTU of %d for '%s'", mtu, pcap_dev);
317 int GetGlobalMTUWin32(
void)
321 DWORD err = NO_ERROR;
322 IP_ADAPTER_ADDRESSES *if_info_list = NULL;
325 err = Win32GetAdaptersAddresses(&if_info_list);
326 if (err != NO_ERROR) {
331 IP_ADAPTER_ADDRESSES *if_info = NULL;
332 for (if_info = if_info_list; if_info != NULL; if_info = if_info->Next) {
334 if (if_info->Mtu == (uint32_t)-1) {
339 mtu = max(mtu, if_info->Mtu);
344 SCLogInfo(
"Found a global MTU of %" PRIu32, mtu);
350 const char *errbuf = NULL;
351 FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |
352 FORMAT_MESSAGE_IGNORE_INSERTS,
353 NULL, err, 0, (LPTSTR)&errbuf, 0, NULL);
355 SCLogWarning(
"Failure when trying to get global MTU via syscall: %s (%" PRId32
")", errbuf,
361 #define ReleaseObject(objptr) \
363 if ((objptr) != NULL) { \
364 (objptr)->lpVtbl->Release(objptr); \
369 typedef enum Win32TcpOffloadFlags_ {
370 WIN32_TCP_OFFLOAD_FLAG_NONE = 0,
371 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX = 1,
372 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX = 1 << 1,
373 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX = 1 << 2,
374 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX = 1 << 3,
375 WIN32_TCP_OFFLOAD_FLAG_LSOV1_IP4 = 1 << 4,
376 WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP4 = 1 << 5,
377 WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP6 = 1 << 6,
380 WIN32_TCP_OFFLOAD_FLAG_CSUM = WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX |
381 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX |
382 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX |
383 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX,
384 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4 = WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX |
385 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX,
386 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6 = WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX |
387 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX,
388 WIN32_TCP_OFFLOAD_FLAG_LSO = WIN32_TCP_OFFLOAD_FLAG_LSOV1_IP4 |
389 WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP4 |
390 WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP6,
391 } Win32TcpOffloadFlags;
393 typedef struct ComInstance_ {
394 IWbemLocator *locator;
395 IWbemServices *services;
401 static HRESULT ComInstanceInit(ComInstance *instance, LPCWSTR resource)
405 instance->locator = NULL;
406 instance->services = NULL;
408 BSTR resource_bstr = SysAllocString(resource);
409 if (resource_bstr == NULL) {
410 hr = HRESULT_FROM_WIN32(E_OUTOFMEMORY);
416 hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
422 SCLogWarning(
"COM CoInitializeEx failed: 0x%" PRIx32, (uint32_t)hr);
425 hr = CoInitializeSecurity(
426 NULL, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_DEFAULT,
427 RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
429 SCLogWarning(
"COM CoInitializeSecurity failed: 0x%" PRIx32, (uint32_t)hr);
435 hr = CoCreateInstance(&CLSID_WbemLocator, NULL, CLSCTX_INPROC_SERVER,
436 &IID_IWbemLocator, (LPVOID *)&instance->locator);
438 SCLogWarning(
"COM CoCreateInstance failed: 0x%" PRIx32, (uint32_t)hr);
441 hr = instance->locator->lpVtbl->ConnectServer(
442 instance->locator, resource_bstr, NULL, NULL, NULL, 0, NULL, NULL,
443 &instance->services);
445 SCLogWarning(
"COM ConnectServer failed: 0x%" PRIx32, (uint32_t)hr);
450 SysFreeString(resource_bstr);
458 static void ComInstanceRelease(ComInstance *instance)
460 if (instance == NULL) {
463 ReleaseObject(instance->services);
464 ReleaseObject(instance->locator);
470 static HRESULT GetWbemClass(ComInstance *instance, LPCWSTR name,
471 IWbemClassObject **p_class)
473 HRESULT hr = WBEM_S_NO_ERROR;
474 BSTR name_bstr = NULL;
476 if (instance == NULL || name == NULL || p_class == NULL ||
478 hr = HRESULT_FROM_WIN32(E_INVALIDARG);
479 Win32HResultLogDebug(hr);
484 name_bstr = SysAllocString(name);
485 if (name_bstr == NULL) {
486 hr = HRESULT_FROM_WIN32(E_OUTOFMEMORY);
492 hr = instance->services->lpVtbl->GetObject(instance->services, name_bstr,
493 WBEM_FLAG_RETURN_WBEM_COMPLETE,
494 NULL, p_class, NULL);
497 SCLogWarning(
"WMI GetObject failed: 0x%" PRIx32, (uint32_t)hr);
502 SysFreeString(name_bstr);
510 static HRESULT GetWbemClassInstance(ComInstance *instance, LPCWSTR name,
511 IWbemClassObject **p_instance)
513 HRESULT hr = WBEM_S_NO_ERROR;
515 IWbemClassObject *
class = NULL;
517 hr = GetWbemClass(instance, name, &
class);
518 if (hr != WBEM_S_NO_ERROR) {
522 hr =
class->lpVtbl->SpawnInstance(
class, 0, p_instance);
523 if (hr != WBEM_S_NO_ERROR) {
525 SCLogWarning(
"WMI SpawnInstance failed: 0x%" PRIx32, (uint32_t)hr);
533 typedef struct WbemMethod_ {
534 ComInstance *com_instance;
538 IWbemClassObject *in_params, *out_params;
544 static HRESULT GetWbemMethod(ComInstance *com_instance, LPCWSTR class_name,
545 LPCWSTR method_name, WbemMethod *method)
548 IWbemClassObject *
class = NULL;
550 method->com_instance = com_instance;
552 BSTR class_name_bstr = SysAllocString(class_name);
553 if (class_name_bstr == NULL) {
554 hr = HRESULT_FROM_WIN32(E_OUTOFMEMORY);
558 method->method_name = SysAllocString(method_name);
559 if (method->method_name == NULL) {
560 hr = HRESULT_FROM_WIN32(E_OUTOFMEMORY);
566 hr = GetWbemClass(com_instance, class_name, &
class);
567 if (hr != WBEM_S_NO_ERROR) {
572 hr =
class->lpVtbl->GetMethod(
class, method_name, 0, &method->in_params,
573 &method->out_params);
574 if (hr != WBEM_S_NO_ERROR) {
576 SCLogWarning(
"WMI GetMethod failed: 0x%" PRIx32, (uint32_t)hr);
581 ReleaseObject(
class);
583 SysFreeString(class_name_bstr);
591 static void WbemMethodRelease(WbemMethod *method)
593 if (method == NULL) {
596 ReleaseObject(method->in_params);
597 ReleaseObject(method->out_params);
599 SysFreeString(method->method_name);
602 typedef struct WbemMethodCall_ {
607 IWbemClassObject *in_params;
613 static HRESULT GetWbemMethodCall(WbemMethod *method, LPCWSTR instance_path,
614 WbemMethodCall *call)
618 call->method = method;
619 call->instance_path = SysAllocString(instance_path);
620 if (call->instance_path == NULL) {
621 hr = HRESULT_FROM_WIN32(E_OUTOFMEMORY);
622 SCLogWarning(
"Failed to allocate BSTR: 0x%" PRIx32, (uint32_t)hr);
627 hr = method->in_params->lpVtbl->SpawnInstance(method->in_params, 0,
631 SCLogWarning(
"WMI SpawnInstance failed on in_params: 0x%" PRIx32, (uint32_t)hr);
642 static void WbemMethodCallRelease(WbemMethodCall *call)
647 ReleaseObject(call->in_params);
649 SysFreeString(call->instance_path);
655 static HRESULT WbemMethodCallExec(WbemMethodCall *call,
656 IWbemClassObject **p_out_params)
660 hr = call->method->com_instance->services->lpVtbl->ExecMethod(
661 call->method->com_instance->services, call->instance_path,
662 call->method->method_name, 0, NULL, call->in_params, p_out_params,
664 if (hr != WBEM_S_NO_ERROR) {
666 SCLogDebug(
"WMI ExecMethod failed: 0x%" PRIx32, (uint32_t)hr);
677 static HRESULT WbemGetSubObject(IWbemClassObject *
object, LPCWSTR property_name,
678 IWbemClassObject **sub_object)
683 VariantInit(&out_var);
684 hr =
object->lpVtbl->Get(
object, property_name, 0, &out_var, NULL, NULL);
685 if (hr != WBEM_S_NO_ERROR) {
689 IUnknown *unknown = V_UNKNOWN(&out_var);
690 hr = unknown->lpVtbl->QueryInterface(unknown, &IID_IWbemClassObject,
691 (
void **)sub_object);
693 SCLogWarning(
"WMI QueryInterface (IWbemClassObject) failed: 0x%" PRIx32, (uint32_t)hr);
698 VariantClear(&out_var);
705 static HRESULT GetEncapsulation(IWbemClassObject *
object, LPCWSTR category,
706 LPCWSTR subcategory, ULONG *encapsulation)
708 HRESULT hr = WBEM_S_NO_ERROR;
710 IWbemClassObject *category_object = NULL;
711 IWbemClassObject *subcategory_object = NULL;
714 VariantInit(&out_var);
717 hr = WbemGetSubObject(
object, category, &category_object);
718 if (hr != WBEM_S_NO_ERROR) {
723 hr = WbemGetSubObject(category_object, subcategory, &subcategory_object);
724 if (hr != WBEM_S_NO_ERROR) {
727 hr = subcategory_object->lpVtbl->Get(subcategory_object, L
"Encapsulation",
728 0, &out_var, NULL, NULL);
729 if (hr != WBEM_S_NO_ERROR) {
732 *encapsulation = V_UI4(&out_var);
735 VariantClear(&out_var);
736 ReleaseObject(subcategory_object);
737 ReleaseObject(category_object);
741 static HRESULT GetIUnknown(IWbemClassObject *
object, IUnknown **p_unknown)
743 HRESULT hr = WBEM_S_NO_ERROR;
745 if (
object == NULL || p_unknown == NULL || *p_unknown != NULL) {
746 hr = HRESULT_FROM_WIN32(E_INVALIDARG);
747 Win32HResultLogDebug(hr);
751 hr =
object->lpVtbl->QueryInterface(
object, &IID_IUnknown,
754 SCLogWarning(
"WMI QueryInterface (IUnknown) failed: 0x%" PRIx32, (uint32_t)hr);
762 static HRESULT BuildNdisObjectHeader(ComInstance *instance, uint8_t
type,
763 uint8_t revision, uint16_t size,
764 IWbemClassObject **p_ndis_object_header)
766 HRESULT hr = WBEM_S_NO_ERROR;
768 if (instance == NULL || p_ndis_object_header == NULL ||
769 *p_ndis_object_header != NULL) {
771 hr = HRESULT_FROM_WIN32(E_INVALIDARG);
772 Win32HResultLogDebug(hr);
777 hr = GetWbemClassInstance(instance, L
"MSNdis_ObjectHeader",
778 p_ndis_object_header);
779 if (hr != WBEM_S_NO_ERROR) {
783 VARIANT param_variant;
784 VariantInit(¶m_variant);
785 IWbemClassObject *ndis_object_header = *p_ndis_object_header;
788 V_VT(¶m_variant) = VT_UI1;
789 V_UI1(¶m_variant) =
type;
790 hr = ndis_object_header->lpVtbl->Put(ndis_object_header, L
"Type", 0,
792 VariantClear(¶m_variant);
793 if (hr != WBEM_S_NO_ERROR) {
798 V_VT(¶m_variant) = VT_UI1;
799 V_UI1(¶m_variant) = revision;
800 hr = ndis_object_header->lpVtbl->Put(ndis_object_header, L
"Revision", 0,
802 VariantClear(¶m_variant);
803 if (hr != WBEM_S_NO_ERROR) {
810 V_VT(¶m_variant) = VT_I4;
811 V_I4(¶m_variant) = size;
812 hr = ndis_object_header->lpVtbl->Put(ndis_object_header, L
"Size", 0,
814 VariantClear(¶m_variant);
815 if (hr != WBEM_S_NO_ERROR) {
824 static HRESULT BuildNdisWmiMethodHeader(ComInstance *instance,
825 uint64_t net_luid, uint32_t port_number,
826 uint64_t request_id, uint32_t timeout,
827 IWbemClassObject **p_ndis_method_header)
829 HRESULT hr = WBEM_S_NO_ERROR;
831 IWbemClassObject *ndis_object_header = NULL;
833 if (instance == NULL || p_ndis_method_header == NULL ||
834 *p_ndis_method_header != NULL) {
836 hr = HRESULT_FROM_WIN32(E_INVALIDARG);
837 Win32HResultLogDebug(hr);
842 hr = GetWbemClassInstance(instance, L
"MSNdis_WmiMethodHeader",
843 p_ndis_method_header);
844 if (hr != WBEM_S_NO_ERROR) {
848 VARIANT param_variant;
849 VariantInit(¶m_variant);
852 hr = BuildNdisObjectHeader(instance, NDIS_WMI_OBJECT_TYPE_METHOD,
853 NDIS_WMI_METHOD_HEADER_REVISION_1, 0xFFFF,
854 &ndis_object_header);
855 if (hr != WBEM_S_NO_ERROR) {
858 V_VT(¶m_variant) = VT_UNKNOWN;
859 V_UNKNOWN(¶m_variant) = NULL;
860 hr = GetIUnknown(ndis_object_header, &V_UNKNOWN(¶m_variant));
861 if (hr != WBEM_S_NO_ERROR) {
865 IWbemClassObject *ndis_method_header = *p_ndis_method_header;
868 hr = ndis_method_header->lpVtbl->Put(ndis_method_header, L
"Header", 0,
870 VariantClear(¶m_variant);
871 if (hr != WBEM_S_NO_ERROR) {
876 V_VT(¶m_variant) = VT_BSTR;
877 V_BSTR(¶m_variant) = utob(net_luid);
878 hr = ndis_method_header->lpVtbl->Put(ndis_method_header, L
"NetLuid", 0,
880 VariantClear(¶m_variant);
881 if (hr != WBEM_S_NO_ERROR) {
886 V_VT(¶m_variant) = VT_BSTR;
887 V_BSTR(¶m_variant) = utob((uint64_t)port_number);
888 hr = ndis_method_header->lpVtbl->Put(ndis_method_header, L
"PortNumber", 0,
890 VariantClear(¶m_variant);
891 if (hr != WBEM_S_NO_ERROR) {
896 V_VT(¶m_variant) = VT_BSTR;
897 V_BSTR(¶m_variant) = utob(request_id);
898 hr = ndis_method_header->lpVtbl->Put(ndis_method_header, L
"RequestId", 0,
900 VariantClear(¶m_variant);
901 if (hr != WBEM_S_NO_ERROR) {
906 V_VT(¶m_variant) = VT_BSTR;
907 V_BSTR(¶m_variant) = utob((uint64_t)timeout);
908 hr = ndis_method_header->lpVtbl->Put(ndis_method_header, L
"Timeout", 0,
910 VariantClear(¶m_variant);
911 if (hr != WBEM_S_NO_ERROR) {
916 V_VT(¶m_variant) = VT_BSTR;
917 V_BSTR(¶m_variant) = utob((uint64_t)0);
918 hr = ndis_method_header->lpVtbl->Put(ndis_method_header, L
"Padding", 0,
920 VariantClear(¶m_variant);
921 if (hr != WBEM_S_NO_ERROR) {
927 ReleaseObject(ndis_object_header);
935 static HRESULT GetNdisOffload(LPCWSTR if_description, uint32_t *offload_flags)
939 ComInstance instance = {};
940 WbemMethod method = {};
941 WbemMethodCall call = {};
943 IWbemClassObject *ndis_method_header = NULL;
944 IWbemClassObject *out_params = NULL;
945 IWbemClassObject *ndis_offload = NULL;
947 if (if_description == NULL) {
949 hr = HRESULT_FROM_WIN32(E_INVALIDARG);
953 LPCWSTR class_name = L
"MSNdis_TcpOffloadCurrentConfig";
954 LPCWSTR instance_name_fmt = L
"%s=\"%s\"";
955 size_t n_chars = wcslen(class_name) + wcslen(if_description) +
956 wcslen(instance_name_fmt);
957 LPWSTR instance_name =
SCMalloc((n_chars + 1) *
sizeof(
wchar_t));
958 if (instance_name == NULL) {
959 SCLogWarning(
"Failed to allocate buffer for instance path");
962 instance_name[n_chars] = 0;
963 hr = StringCchPrintfW(instance_name, n_chars, instance_name_fmt, class_name,
966 SCLogWarning(
"Failed to format WMI class instance name: 0x%" PRIx32, (uint32_t)hr);
970 LPCWSTR method_name = L
"WmiQueryCurrentOffloadConfig";
973 hr = ComInstanceInit(&instance, L
"ROOT\\WMI");
979 hr = GetWbemMethod(&instance, class_name, method_name, &method);
985 hr = GetWbemMethodCall(&method, instance_name, &call);
992 VARIANT param_variant;
993 VariantInit(¶m_variant);
996 hr = BuildNdisWmiMethodHeader(&instance, 0, 0, 0, 5, &ndis_method_header);
997 if (hr != WBEM_S_NO_ERROR) {
1000 V_VT(¶m_variant) = VT_UNKNOWN;
1001 V_UNKNOWN(¶m_variant) = NULL;
1002 hr = GetIUnknown(ndis_method_header, &V_UNKNOWN(¶m_variant));
1003 if (hr != WBEM_S_NO_ERROR) {
1008 hr = call.in_params->lpVtbl->Put(call.in_params, L
"Header", 0,
1010 VariantClear(¶m_variant);
1011 if (hr != WBEM_S_NO_ERROR) {
1017 hr = WbemMethodCallExec(&call, &out_params);
1019 size_t if_description_len = wcslen(if_description);
1020 char *if_description_ansi =
SCMalloc(if_description_len + 1);
1021 if (if_description_ansi == NULL) {
1022 SCLogWarning(
"Failed to allocate buffer for interface description");
1025 if_description_ansi[if_description_len] = 0;
1026 wcstombs(if_description_ansi, if_description, if_description_len);
1027 SCLogInfo(
"Obtaining offload state failed, device \"%s\" may not "
1028 "support offload. Error: 0x%" PRIx32,
1029 if_description_ansi, (uint32_t)hr);
1030 SCFree(if_description_ansi);
1031 Win32HResultLogDebug(hr);
1036 hr = WbemGetSubObject(out_params, L
"Offload", &ndis_offload);
1037 if (hr != WBEM_S_NO_ERROR) {
1040 ULONG encapsulation = 0;
1043 hr = GetEncapsulation(ndis_offload, L
"Checksum", L
"IPv4Receive",
1045 if (hr != WBEM_S_NO_ERROR) {
1049 if (encapsulation != 0) {
1050 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX;
1052 hr = GetEncapsulation(ndis_offload, L
"Checksum", L
"IPv4Transmit",
1054 if (hr != WBEM_S_NO_ERROR) {
1058 if (encapsulation != 0) {
1059 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX;
1061 hr = GetEncapsulation(ndis_offload, L
"Checksum", L
"IPv6Receive",
1063 if (hr != WBEM_S_NO_ERROR) {
1067 if (encapsulation != 0) {
1068 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX;
1070 hr = GetEncapsulation(ndis_offload, L
"Checksum", L
"IPv6Transmit",
1072 if (hr != WBEM_S_NO_ERROR) {
1076 if (encapsulation != 0) {
1077 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX;
1081 hr = GetEncapsulation(ndis_offload, L
"LsoV1", L
"WmiIPv4", &encapsulation);
1082 if (hr != WBEM_S_NO_ERROR) {
1086 if (encapsulation != 0) {
1087 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_LSOV1_IP4;
1091 hr = GetEncapsulation(ndis_offload, L
"LsoV2", L
"WmiIPv4", &encapsulation);
1092 if (hr != WBEM_S_NO_ERROR) {
1096 if (encapsulation != 0) {
1097 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP4;
1099 hr = GetEncapsulation(ndis_offload, L
"LsoV2", L
"WmiIPv6", &encapsulation);
1100 if (hr != WBEM_S_NO_ERROR) {
1104 if (encapsulation != 0) {
1105 *offload_flags |= WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP6;
1109 ReleaseObject(ndis_method_header);
1110 ReleaseObject(ndis_offload);
1111 ReleaseObject(out_params);
1113 WbemMethodCallRelease(&call);
1114 WbemMethodRelease(&method);
1115 ComInstanceRelease(&instance);
1120 int GetIfaceOffloadingWin32(
const char *pcap_dev,
int csum,
int other)
1122 SCLogDebug(
"Querying offloading for device %s", pcap_dev);
1124 DWORD err = NO_ERROR;
1126 uint32_t offload_flags = 0;
1129 IP_ADAPTER_ADDRESSES *if_info_list = NULL, *if_info = NULL;
1130 err = Win32GetAdaptersAddresses(&if_info_list);
1131 if (err != NO_ERROR) {
1135 err = Win32FindAdapterAddresses(if_info_list, pcap_dev, &if_info);
1136 if (err != NO_ERROR) {
1140 LPWSTR if_description = if_info->Description;
1143 err = GetNdisOffload(if_description, &offload_flags);
1147 }
else if (offload_flags != 0) {
1149 if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM) != 0) {
1154 if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSO) != 0) {
1161 SCLogPerf(
"NIC offloading on %s: Checksum IPv4 Rx: %d Tx: %d IPv6 "
1162 "Rx: %d Tx: %d LSOv1 IPv4: %d LSOv2 IPv4: %d IPv6: %d",
1164 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX) != 0,
1165 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX) != 0,
1166 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX) != 0,
1167 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX) != 0,
1168 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV1_IP4) != 0,
1169 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP4) != 0,
1170 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP6) != 0);
1172 SCLogWarning(
"NIC offloading on %s: Checksum IPv4 Rx: %d Tx: %d IPv6 "
1173 "Rx: %d Tx: %d LSOv1 IPv4: %d LSOv2 IPv4: %d IPv6: %d",
1174 pcap_dev, (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX) != 0,
1175 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX) != 0,
1176 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX) != 0,
1177 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX) != 0,
1178 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV1_IP4) != 0,
1179 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP4) != 0,
1180 (offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP6) != 0);
1185 const char *err_str = Win32GetErrorString(err, WmiUtils());
1186 SCLogWarning(
"Failure when trying to get feature via syscall for '%s': "
1187 "%s (0x%08" PRIx32
")",
1188 pcap_dev, err_str, (uint32_t)err);
1189 LocalFree((LPVOID)err_str);
1198 BuildNdisTcpOffloadParameters(ComInstance *instance, uint32_t offload_flags,
1200 IWbemClassObject **p_ndis_tcp_offload_parameters)
1202 HRESULT hr = WBEM_S_NO_ERROR;
1204 IWbemClassObject *ndis_object_header = NULL;
1206 if (instance == NULL || p_ndis_tcp_offload_parameters == NULL ||
1207 *p_ndis_tcp_offload_parameters != NULL) {
1209 hr = HRESULT_FROM_WIN32(E_INVALIDARG);
1210 Win32HResultLogDebug(hr);
1215 hr = GetWbemClassInstance(instance, L
"MSNdis_TcpOffloadParameters",
1216 p_ndis_tcp_offload_parameters);
1217 if (hr != WBEM_S_NO_ERROR) {
1221 VARIANT param_variant;
1222 VariantInit(¶m_variant);
1225 hr = BuildNdisObjectHeader(instance, NDIS_OBJECT_TYPE_DEFAULT,
1226 NDIS_OFFLOAD_PARAMETERS_REVISION_1,
1227 NDIS_SIZEOF_OFFLOAD_PARAMETERS_REVISION_1,
1228 &ndis_object_header);
1229 if (hr != WBEM_S_NO_ERROR) {
1232 V_VT(¶m_variant) = VT_UNKNOWN;
1233 V_UNKNOWN(¶m_variant) = NULL;
1234 hr = GetIUnknown(ndis_object_header, &V_UNKNOWN(¶m_variant));
1235 if (hr != WBEM_S_NO_ERROR) {
1239 IWbemClassObject *ndis_tcp_offload_parameters =
1240 *p_ndis_tcp_offload_parameters;
1243 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1244 ndis_tcp_offload_parameters, L
"Header", 0, ¶m_variant, 0);
1245 VariantClear(¶m_variant);
1246 if (hr != WBEM_S_NO_ERROR) {
1247 Win32HResultLogDebug(hr);
1252 V_VT(¶m_variant) = VT_BSTR;
1253 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_NO_CHANGE);
1254 if (!enable && (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4) != 0) {
1256 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED);
1257 }
else if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4) ==
1258 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4) {
1260 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED);
1261 }
else if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4RX) != 0) {
1263 V_BSTR(¶m_variant) =
1264 utob(NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED);
1265 }
else if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP4TX) != 0) {
1267 V_BSTR(¶m_variant) =
1268 utob(NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED);
1270 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1271 ndis_tcp_offload_parameters, L
"IPv4Checksum", 0, ¶m_variant, 0);
1272 if (hr != WBEM_S_NO_ERROR) {
1276 hr = ndis_tcp_offload_parameters->lpVtbl->Put(ndis_tcp_offload_parameters,
1277 L
"TCPIPv4Checksum", 0,
1279 if (hr != WBEM_S_NO_ERROR) {
1283 hr = ndis_tcp_offload_parameters->lpVtbl->Put(ndis_tcp_offload_parameters,
1284 L
"UDPIPv4Checksum", 0,
1286 if (hr != WBEM_S_NO_ERROR) {
1290 VariantClear(¶m_variant);
1293 V_VT(¶m_variant) = VT_BSTR;
1294 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_NO_CHANGE);
1295 if (!enable && (offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6) != 0) {
1297 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_TX_RX_DISABLED);
1298 }
else if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6) ==
1299 WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6) {
1301 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_TX_RX_ENABLED);
1302 }
else if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6RX) != 0) {
1304 V_BSTR(¶m_variant) =
1305 utob(NDIS_OFFLOAD_PARAMETERS_RX_ENABLED_TX_DISABLED);
1306 }
else if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_CSUM_IP6TX) != 0) {
1308 V_BSTR(¶m_variant) =
1309 utob(NDIS_OFFLOAD_PARAMETERS_TX_ENABLED_RX_DISABLED);
1311 hr = ndis_tcp_offload_parameters->lpVtbl->Put(ndis_tcp_offload_parameters,
1312 L
"TCPIPv6Checksum", 0,
1314 if (hr != WBEM_S_NO_ERROR) {
1318 hr = ndis_tcp_offload_parameters->lpVtbl->Put(ndis_tcp_offload_parameters,
1319 L
"UDPIPv6Checksum", 0,
1321 if (hr != WBEM_S_NO_ERROR) {
1325 VariantClear(¶m_variant);
1328 V_VT(¶m_variant) = VT_BSTR;
1329 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_NO_CHANGE);
1330 if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV1_IP4) != 0) {
1332 V_BSTR(¶m_variant) =
1333 utob(NDIS_OFFLOAD_PARAMETERS_LSOV1_ENABLED);
1335 V_BSTR(¶m_variant) =
1336 utob(NDIS_OFFLOAD_PARAMETERS_LSOV1_DISABLED);
1339 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1340 ndis_tcp_offload_parameters, L
"LsoV1", 0, ¶m_variant, 0);
1341 if (hr != WBEM_S_NO_ERROR) {
1345 VariantClear(¶m_variant);
1348 V_VT(¶m_variant) = VT_BSTR;
1349 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_NO_CHANGE);
1350 if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP4) != 0) {
1352 V_BSTR(¶m_variant) =
1353 utob(NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED);
1355 V_BSTR(¶m_variant) =
1356 utob(NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED);
1359 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1360 ndis_tcp_offload_parameters, L
"LsoV2IPv4", 0, ¶m_variant, 0);
1361 if (hr != WBEM_S_NO_ERROR) {
1365 VariantClear(¶m_variant);
1368 V_VT(¶m_variant) = VT_BSTR;
1369 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_NO_CHANGE);
1370 if ((offload_flags & WIN32_TCP_OFFLOAD_FLAG_LSOV2_IP6) != 0) {
1372 V_BSTR(¶m_variant) =
1373 utob(NDIS_OFFLOAD_PARAMETERS_LSOV2_ENABLED);
1375 V_BSTR(¶m_variant) =
1376 utob(NDIS_OFFLOAD_PARAMETERS_LSOV2_DISABLED);
1379 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1380 ndis_tcp_offload_parameters, L
"LsoV2IPv6", 0, ¶m_variant, 0);
1381 if (hr != WBEM_S_NO_ERROR) {
1385 VariantClear(¶m_variant);
1388 V_VT(¶m_variant) = VT_BSTR;
1389 V_BSTR(¶m_variant) = utob(NDIS_OFFLOAD_PARAMETERS_NO_CHANGE);
1390 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1391 ndis_tcp_offload_parameters, L
"IPSec", 0, ¶m_variant, 0);
1392 if (hr != WBEM_S_NO_ERROR) {
1396 hr = ndis_tcp_offload_parameters->lpVtbl->Put(ndis_tcp_offload_parameters,
1397 L
"TcpConnectionIPv4", 0,
1399 if (hr != WBEM_S_NO_ERROR) {
1403 hr = ndis_tcp_offload_parameters->lpVtbl->Put(ndis_tcp_offload_parameters,
1404 L
"TcpConnectionIPv6", 0,
1406 if (hr != WBEM_S_NO_ERROR) {
1410 hr = ndis_tcp_offload_parameters->lpVtbl->Put(
1411 ndis_tcp_offload_parameters, L
"Flags", 0, ¶m_variant, 0);
1412 if (hr != WBEM_S_NO_ERROR) {
1419 VariantClear(¶m_variant);
1424 static HRESULT SetNdisOffload(LPCWSTR if_description, uint32_t offload_flags,
1429 ComInstance instance = {};
1430 WbemMethod method = {};
1431 WbemMethodCall call = {};
1434 IWbemClassObject *ndis_method_header = NULL;
1436 IWbemClassObject *ndis_tcp_offload_parameters = NULL;
1438 if (if_description == NULL) {
1440 return E_INVALIDARG;
1443 LPCWSTR class_name = L
"MSNdis_SetTcpOffloadParameters";
1444 LPCWSTR instance_name_fmt = L
"%s=\"%s\"";
1445 size_t n_chars = wcslen(class_name) + wcslen(if_description) +
1446 wcslen(instance_name_fmt);
1447 LPWSTR instance_name =
SCMalloc((n_chars + 1) *
sizeof(
wchar_t));
1448 if (instance_name == NULL) {
1449 SCLogWarning(
"Failed to allocate buffer for instance path");
1452 instance_name[n_chars] = 0;
1453 hr = StringCchPrintfW(instance_name, n_chars, instance_name_fmt, class_name,
1456 SCLogWarning(
"Failed to format WMI class instance name: 0x%" PRIx32, (uint32_t)hr);
1461 LPCWSTR method_name = L
"WmiSetTcpOffloadParameters";
1464 hr = ComInstanceInit(&instance, L
"ROOT\\WMI");
1470 hr = GetWbemMethod(&instance, class_name, method_name, &method);
1476 hr = GetWbemMethodCall(&method, instance_name, &call);
1483 VARIANT param_variant;
1484 VariantInit(¶m_variant);
1487 hr = BuildNdisWmiMethodHeader(&instance, 0, 0, 0, 5, &ndis_method_header);
1488 if (hr != WBEM_S_NO_ERROR) {
1492 V_VT(¶m_variant) = VT_UNKNOWN;
1493 V_UNKNOWN(¶m_variant) = NULL;
1494 hr = GetIUnknown(ndis_method_header, &V_UNKNOWN(¶m_variant));
1495 if (hr != WBEM_S_NO_ERROR) {
1498 hr = call.in_params->lpVtbl->Put(call.in_params, L
"MethodHeader", 0,
1500 VariantClear(¶m_variant);
1501 if (hr != WBEM_S_NO_ERROR) {
1502 Win32HResultLogDebug(hr);
1507 hr = BuildNdisTcpOffloadParameters(&instance, offload_flags, enable,
1508 &ndis_tcp_offload_parameters);
1509 if (hr != WBEM_S_NO_ERROR) {
1513 V_VT(¶m_variant) = VT_UNKNOWN;
1514 V_UNKNOWN(¶m_variant) = NULL;
1515 hr = GetIUnknown(ndis_tcp_offload_parameters, &V_UNKNOWN(¶m_variant));
1516 if (hr != WBEM_S_NO_ERROR) {
1519 hr = call.in_params->lpVtbl->Put(call.in_params, L
"TcpOffloadParameters", 0,
1521 VariantClear(¶m_variant);
1522 if (hr != WBEM_S_NO_ERROR) {
1523 Win32HResultLogDebug(hr);
1528 hr = WbemMethodCallExec(&call, NULL);
1530 Win32HResultLogDebug(hr);
1535 ReleaseObject(ndis_tcp_offload_parameters);
1536 ReleaseObject(ndis_method_header);
1538 WbemMethodCallRelease(&call);
1539 WbemMethodRelease(&method);
1540 ComInstanceRelease(&instance);
1545 int DisableIfaceOffloadingWin32(
LiveDevice *ldev,
int csum,
int other)
1547 SCLogDebug(
"Disabling offloading for device %s", ldev->
dev);
1550 DWORD err = NO_ERROR;
1551 uint32_t offload_flags = 0;
1558 IP_ADAPTER_ADDRESSES *if_info_list = NULL, *if_info = NULL;
1559 err = Win32GetAdaptersAddresses(&if_info_list);
1560 if (err != NO_ERROR) {
1564 err = Win32FindAdapterAddresses(if_info_list, ldev->
dev, &if_info);
1565 if (err != NO_ERROR) {
1569 LPWSTR if_description = if_info->Description;
1571 err = GetNdisOffload(if_description, &offload_flags);
1578 offload_flags &= ~WIN32_TCP_OFFLOAD_FLAG_CSUM;
1581 offload_flags &= ~WIN32_TCP_OFFLOAD_FLAG_LSO;
1584 err = SetNdisOffload(if_description, offload_flags, 0);
1596 int RestoreIfaceOffloadingWin32(
LiveDevice *ldev)
1601 DWORD err = NO_ERROR;
1608 IP_ADAPTER_ADDRESSES *if_info_list = NULL, *if_info = NULL;
1609 err = Win32GetAdaptersAddresses(&if_info_list);
1610 if (err != NO_ERROR) {
1614 err = Win32FindAdapterAddresses(if_info_list, ldev->
dev, &if_info);
1615 if (err != NO_ERROR) {
1619 LPWSTR if_description = if_info->Description;
1621 err = SetNdisOffload(if_description, ldev->
offload_orig, 1);
1636 static int Win32TestStripPcapPrefix(
void)
1640 const char *name1 =
"\\Device\\NPF_{D4A32435-1BA7-4008-93A6-1518AA4BBD9B}";
1641 const char *expect_name1 =
"{D4A32435-1BA7-4008-93A6-1518AA4BBD9B}";
1643 const char *name2 =
"{D4A32435-1BA7-4008-93A6-1518AA4BBD9B}";
1644 const char *expect_name2 =
"{D4A32435-1BA7-4008-93A6-1518AA4BBD9B}";
1646 result &= (strncmp(expect_name1, StripPcapPrefix(name1),
1647 strlen(expect_name1)) == 0);
1649 result &= (strncmp(expect_name2, StripPcapPrefix(name2),
1650 strlen(expect_name2)) == 0);
1656 void Win32SyscallRegisterTests(
void)
1659 UtRegisterTest(
"Win32TestStripPcapPrefix", Win32TestStripPcapPrefix);