Boolean ssh_register_ip_notifications(SshInterceptor generic_interceptor) { SshNt6Interceptor interceptor = (SshNt6Interceptor)generic_interceptor; NTSTATUS status; interceptor->address_change_handle = NULL; interceptor->route_change_handle = NULL; status = NotifyUnicastIpAddressChange(AF_UNSPEC, ssh_address_change_notify, interceptor, TRUE, &interceptor->address_change_handle); if (status == STATUS_SUCCESS) { status = NotifyRouteChange2(AF_UNSPEC, ssh_route_change_notify, interceptor, TRUE, &interceptor->route_change_handle); } if (status != STATUS_SUCCESS) { ssh_cancel_ip_notifications(generic_interceptor); return FALSE; } return TRUE; }
int platform_notify_iface_change(reconfigure_callback_function reconfig_callback) { ULONG err; // Request callbacks when a unicast IPv4 interface address changes err = NotifyUnicastIpAddressChange(AF_INET, addr_change_callback, reconfig_callback, FALSE, ¬ification_handle); if (err != 0) { printf("Failed to register interface change callback\n"); notification_handle = INVALID_HANDLE_VALUE; return -1; } // The handle will be unregistered in platform_cleanup() return 0; }
VOID AddressDemo( VOID ) { NETIO_STATUS Status; PMIB_UNICASTIPADDRESS_TABLE UnicastTable = NULL; MIB_UNICASTIPADDRESS_ROW Row; ULONG i; IN6_ADDR Ipv6Address = {0xfe,0x3f,0,0,0,0,0,0,0,0,0,0,0,0,0x20,0x00}; HANDLE Handle; NET_IFINDEX InterfaceIndex = 0; // // Retrieve all the IP addresses. // Status = GetUnicastIpAddressTable( AF_UNSPEC, &UnicastTable); if (!WIN_SUCCESS(Status)) { printf( "GetUnicastAddressTable Failed. Error %d\n", Status); } else { printf( "GetUnicastAddressTable Succeeded.\n"); printf( "Total Number of all IP Address Entries: %d.\n", UnicastTable->NumEntries); for (i = 0; i < UnicastTable->NumEntries; i++) { printf("Address %2d: ", i); PrintIpAddress(&UnicastTable->Table[i].Address); printf("\n"); } FreeMibTable(UnicastTable); printf("\n\n"); } // // Retrieve IPv6 Only Addresses. // Status = GetUnicastIpAddressTable( AF_INET6, &UnicastTable); if (!WIN_SUCCESS(Status)) { printf( "GetUnicastAddressTable Failed. Error %d\n", Status); } else { printf( "GetUnicastAddressTable Succeeded.\n"); printf( "Total Number of IPv6 Address Entries: %d.\n", UnicastTable->NumEntries); for (i = 0; i < UnicastTable->NumEntries; i++) { printf("Address %2d: ", i); PrintIpAddress(&UnicastTable->Table[i].Address); printf("\n"); } InterfaceIndex = UnicastTable->Table[i - 1].InterfaceIndex; FreeMibTable(UnicastTable); } Status = NotifyUnicastIpAddressChange( AF_UNSPEC, //(PUNICAST_IPADDRESS_CHANGE_CALLBACK)AddressCallbackDemo, &AddressCallbackDemo, NULL, FALSE, &Handle); if (!WIN_SUCCESS(Status)) { printf( "\nRegister address change failed. Error %d\n", Status); } else { printf( "\nRegister address change succeeded.\n"); } InitializeUnicastIpAddressEntry(&Row); Row.Address.si_family = AF_INET6; INETADDR_SET_ADDRESS((PSOCKADDR)&Row.Address, (PUCHAR)&Ipv6Address); Row.InterfaceIndex = InterfaceIndex; Status = CreateUnicastIpAddressEntry(&Row); if (!WIN_SUCCESS(Status)) { printf("Create IPv6 unicast address entry failed. Error %d\n", Status); } else { printf("Create IPv6 unicast address entry succeeded.\n"); } Status = GetUnicastIpAddressEntry(&Row); if (!WIN_SUCCESS(Status)) { printf("Get IPv6 unicast address failed. Error %d\n", Status); } else { printf("Get IPv6 unicast address entry succeeded.\n"); } Row.PreferredLifetime = 500000; Status = SetUnicastIpAddressEntry(&Row); if (!WIN_SUCCESS(Status)) { printf("Set IPv6 unicast address entry failed. Error %d\n", Status); } else { printf("Set IPv6 unicast address entry succeeded.\n"); } Status = DeleteUnicastIpAddressEntry(&Row); if (!WIN_SUCCESS(Status)) { printf("Delete Ipv6 Unicast Address Failed. Error %d\n", Status); } else { printf("Delete Ipv6 Unicast Address Succeeded.\n"); } Sleep(2000); Status = CancelMibChangeNotify2(Handle); if (!WIN_SUCCESS(Status)) { printf( "Deregister address change failed. Error %d\n\n", Status); } else { printf( "Deregister address change succeeded.\n\n"); } }
_Use_decl_annotations_ NDIS_STATUS FilterAttach( NDIS_HANDLE NdisFilterHandle, NDIS_HANDLE FilterDriverContext, PNDIS_FILTER_ATTACH_PARAMETERS AttachParameters ) /*++ Routine Description: Filter attach routine. Create filter's context, allocate NetBufferLists and NetBuffer pools and any other resources, and read configuration if needed. Arguments: NdisFilterHandle - Specify a handle identifying this instance of the filter. FilterAttach should save this handle. It is a required parameter in subsequent calls to NdisFxxx functions. FilterDriverContext - Filter driver context passed to NdisFRegisterFilterDriver. AttachParameters - attach parameters Return Value: NDIS_STATUS_SUCCESS: FilterAttach successfully allocated and initialize data structures for this filter instance. NDIS_STATUS_RESOURCES: FilterAttach failed due to insufficient resources. NDIS_STATUS_FAILURE: FilterAttach could not set up this instance of this filter and it has called NdisWriteErrorLogEntry with parameters specifying the reason for failure. N.B.: FILTER can use NdisRegisterDeviceEx to create a device, so the upper layer can send Irps to the filter. --*/ { PMS_FILTER pFilter = NULL; NDIS_STATUS Status = NDIS_STATUS_SUCCESS; NTSTATUS NtStatus; NDIS_FILTER_ATTRIBUTES FilterAttributes; ULONG Size; COMPARTMENT_ID OriginalCompartmentID; OBJECT_ATTRIBUTES ObjectAttributes = {0}; const ULONG RegKeyOffset = ARRAYSIZE(L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\otlwf\\Parameters\\NdisAdapters\\") - 1; DECLARE_CONST_UNICODE_STRING(RegKeyPath, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\otlwf\\Parameters\\NdisAdapters\\{00000000-0000-0000-0000-000000000000}"); RtlCopyMemory(RegKeyPath.Buffer + RegKeyOffset, AttachParameters->BaseMiniportName->Buffer + 8, sizeof(L"{00000000-0000-0000-0000-000000000000}")); LogFuncEntry(DRIVER_DEFAULT); do { ASSERT(FilterDriverContext == (NDIS_HANDLE)FilterDriverObject); if (FilterDriverContext != (NDIS_HANDLE)FilterDriverObject) { Status = NDIS_STATUS_INVALID_PARAMETER; break; } // Verify the media type is supported. This is a last resort; the // the filter should never have been bound to an unsupported miniport // to begin with. if (AttachParameters->MiniportMediaType != NdisMediumIP) { LogError(DRIVER_DEFAULT, "Unsupported media type, 0x%x.", (ULONG)AttachParameters->MiniportMediaType); Status = NDIS_STATUS_INVALID_PARAMETER; break; } Size = sizeof(MS_FILTER) + AttachParameters->BaseMiniportInstanceName->Length; pFilter = (PMS_FILTER)FILTER_ALLOC_MEM(NdisFilterHandle, Size); if (pFilter == NULL) { LogWarning(DRIVER_DEFAULT, "Failed to allocate context structure, 0x%x bytes", Size); Status = NDIS_STATUS_RESOURCES; break; } NdisZeroMemory(pFilter, sizeof(MS_FILTER)); LogVerbose(DRIVER_DEFAULT, "Opening interface registry key %S", RegKeyPath.Buffer); InitializeObjectAttributes( &ObjectAttributes, (PUNICODE_STRING)&RegKeyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); // Open the registry key NtStatus = ZwOpenKey(&pFilter->InterfaceRegKey, KEY_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(NtStatus)) { LogError(DRIVER_DEFAULT, "ZwOpenKey failed to open %S, %!STATUS!", RegKeyPath.Buffer, NtStatus); Status = NDIS_STATUS_FAILURE; break; } // Format of "\DEVICE\{5BA90C49-0D7E-455B-8D3B-614F6714A212}" AttachParameters->BaseMiniportName->Buffer += 8; AttachParameters->BaseMiniportName->Length -= 8 * sizeof(WCHAR); NtStatus = RtlGUIDFromString(AttachParameters->BaseMiniportName, &pFilter->InterfaceGuid); AttachParameters->BaseMiniportName->Buffer -= 8; AttachParameters->BaseMiniportName->Length += 8 * sizeof(WCHAR); if (!NT_SUCCESS(NtStatus)) { LogError(DRIVER_DEFAULT, "Failed to convert FilterModuleGuidName to a GUID, %!STATUS!", NtStatus); Status = NDIS_STATUS_FAILURE; break; } pFilter->InterfaceFriendlyName.Length = pFilter->InterfaceFriendlyName.MaximumLength = AttachParameters->BaseMiniportInstanceName->Length; pFilter->InterfaceFriendlyName.Buffer = (PWSTR)((PUCHAR)pFilter + sizeof(MS_FILTER)); NdisMoveMemory(pFilter->InterfaceFriendlyName.Buffer, AttachParameters->BaseMiniportInstanceName->Buffer, pFilter->InterfaceFriendlyName.Length); pFilter->InterfaceIndex = AttachParameters->BaseMiniportIfIndex; pFilter->InterfaceLuid = AttachParameters->BaseMiniportNetLuid; pFilter->InterfaceCompartmentID = UNSPECIFIED_COMPARTMENT_ID; pFilter->FilterHandle = NdisFilterHandle; NdisZeroMemory(&FilterAttributes, sizeof(NDIS_FILTER_ATTRIBUTES)); FilterAttributes.Header.Revision = NDIS_FILTER_ATTRIBUTES_REVISION_1; FilterAttributes.Header.Size = sizeof(NDIS_FILTER_ATTRIBUTES); FilterAttributes.Header.Type = NDIS_OBJECT_TYPE_FILTER_ATTRIBUTES; FilterAttributes.Flags = 0; NDIS_DECLARE_FILTER_MODULE_CONTEXT(MS_FILTER); Status = NdisFSetAttributes(NdisFilterHandle, pFilter, &FilterAttributes); if (Status != NDIS_STATUS_SUCCESS) { LogError(DRIVER_DEFAULT, "Failed to set attributes, %!NDIS_STATUS!", Status); break; } // Filter initially in Paused state pFilter->State = FilterPaused; // Initialize rundowns to disabled with no active references pFilter->ExternalRefs.Count = EX_RUNDOWN_ACTIVE; pFilter->cmdRundown.Count = EX_RUNDOWN_ACTIVE; // Query the compartment ID for this interface to use for the IP stack pFilter->InterfaceCompartmentID = GetInterfaceCompartmentID(&pFilter->InterfaceLuid); LogVerbose(DRIVER_DEFAULT, "Interface %!GUID! is in Compartment %u", &pFilter->InterfaceGuid, (ULONG)pFilter->InterfaceCompartmentID); // Make sure we are in the right compartment (VOID)otLwfSetCompartment(pFilter, &OriginalCompartmentID); // Register for address changed notifications NtStatus = NotifyUnicastIpAddressChange( AF_INET6, otLwfAddressChangeCallback, pFilter, FALSE, &pFilter->AddressChangeHandle ); // Revert the compartment, now that we have the table otLwfRevertCompartment(OriginalCompartmentID); if (!NT_SUCCESS(NtStatus)) { LogError(DRIVER_DEFAULT, "NotifyUnicastIpAddressChange failed, %!STATUS!", NtStatus); Status = NDIS_STATUS_FAILURE; break; } // Add Filter to global list of Thread Filters NdisAcquireSpinLock(&FilterListLock); InsertTailList(&FilterModuleList, &pFilter->FilterModuleLink); NdisReleaseSpinLock(&FilterListLock); LogVerbose(DRIVER_DEFAULT, "Created Filter: %p", pFilter); } while (FALSE); // Clean up on failure if (Status != NDIS_STATUS_SUCCESS) { if (pFilter != NULL) { if (pFilter->AddressChangeHandle != NULL) { CancelMibChangeNotify2(pFilter->AddressChangeHandle); pFilter->AddressChangeHandle = NULL; } NdisFreeMemory(pFilter, 0, 0); } } LogFuncExitNDIS(DRIVER_DEFAULT, Status); return Status; }