Ескертпе
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Жүйеге кіруді немесе каталогтарды өзгертуді байқап көруге болады.
Бұл бетке кіру үшін қатынас шегін айқындау қажет. Каталогтарды өзгертуді байқап көруге болады.
Функция CreateUnicastIpAddressEntry добавляет новую запись одноадресного IP-адреса на локальном компьютере.
Синтаксис
IPHLPAPI_DLL_LINKAGE _NETIOAPI_SUCCESS_ NETIOAPI_API CreateUnicastIpAddressEntry(
[in] const MIB_UNICASTIPADDRESS_ROW *Row
);
Параметры
[in] Row
Указатель на запись структуры MIB_UNICASTIPADDRESS_ROW для записи одноадресного IP-адреса.
Возвращаемое значение
Если функция выполняется успешно, возвращаемое значение будет NO_ERROR.
Если функция завершается сбоем, возвращаемое значение представляет собой один из следующих кодов ошибок.
| Код возврата | Описание |
|---|---|
|
Отказано в доступе". Эта ошибка возвращается при нескольких условиях, которые включают следующее: у пользователя отсутствуют необходимые права администратора на локальном компьютере или приложение не выполняется в расширенной оболочке в качестве встроенного администратора (администратора запуска от имени). |
|
В функцию передан недопустимый параметр. Эта ошибка возвращается, если в параметре Row передается указатель NULL, члену AddressMIB_UNICASTIPADDRESS_ROW, на который указывает параметр Row, не задан допустимый адрес IPv4 или IPv6 одноадресной рассылки, или оба элемента InterfaceLuid и InterfaceIndexMIB_UNICASTIPADDRESS_ROW, на которые указывает параметр Row, были не указаны.
Эта ошибка также возвращается для других ошибок в значениях, заданных для членов структуры MIB_UNICASTIPADDRESS_ROW . К этим ошибкам относятся следующие: если элемент ValidLifetime меньше элемента PreferredLifetime , Значение , если элемент PrefixOrigin имеет значение IpPrefixOriginUnchanged , а SuffixOrigin — не ipSuffixOriginUnchanged, если для элемента PrefixOrigin не задано значение IpPrefixOriginUnchanged , а для SuffixOrigin задано значение IpSuffixOriginUnchanged, если prefixOrigin Для элемента не задано значение из перечисления NL_PREFIX_ORIGIN , если для элемента SuffixOrigin не задано значение из перечисления NL_SUFFIX_ORIGIN или если для элемента OnLinkPrefixLength задано значение, превышающее длину IP-адреса, в битах (32 для IPv4-адреса одноадресной рассылки или 128 для одноадресного IPv6-адреса). |
|
Не удалось найти указанный интерфейс. Эта ошибка возвращается, если не удалось найти сетевой интерфейс, заданный элементом InterfaceLuid или InterfaceIndexMIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row . |
|
Запрос не поддерживается. Эта ошибка возвращается, если на локальном компьютере нет стека IPv4 и в элементе AddressMIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row , указан IPv4-адрес. Эта ошибка также возвращается, если на локальном компьютере нет стека IPv6 и в элементе Address был указан IPv6-адрес. |
|
Объект уже существует. Эта ошибка возвращается, если элемент AddressMIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row , является дубликатом существующего одноадресного IP-адреса в интерфейсе, указанном элементом InterfaceLuid или InterfaceIndexMIB_UNICASTIPADDRESS_ROW. |
|
Используйте FormatMessage , чтобы получить строку сообщения для возвращенной ошибки. |
Комментарии
Функция CreateUnicastIpAddressEntry определена в Windows Vista и более поздних версиях.
Функция CreateUnicastIpAddressEntry используется для добавления новой записи одноадресной рассылки IP-адреса на локальном компьютере. Ip-адрес одноадресной рассылки, добавленный функцией CreateUnicastIpAddressEntry , не является постоянным. IP-адрес существует только до тех пор, пока существует объект адаптера. Перезагрузка компьютера приводит к удалению IP-адреса, как и при сбросе сетевого интерфейса вручную карта (NIC). Кроме того, некоторые события PnP могут уничтожить адрес.
Чтобы создать IPv4-адрес, который сохраняется, можно использовать метод EnableStatic класса Win32_NetworkAdapterConfiguration в элементах управления инструментария управления Windows (WMI). Команду netsh также можно использовать для создания постоянного адреса IPv4 или IPv6.
Дополнительные сведения см. в документации по Netsh.exe документации по сокетам Windows.
Функция InitializeUnicastIpAddressEntry должна использоваться для инициализации элементов записи структуры MIB_UNICASTIPADDRESS_ROW значениями по умолчанию. Затем приложение может изменить члены в MIB_UNICASTIPADDRESS_ROW записи, которую оно хочет изменить, а затем вызвать функцию CreateUnicastIpAddressEntry .
Элемент Address в структуре MIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row , должен быть инициализирован допустимым адресом IPv4 или IPv6 одноадресной рассылки. Элемент si_family структуры SOCKADDR_INET в элементе Address должен быть инициализирован для AF_INET или AF_INET6, а соответствующий элемент Ipv4 или Ipv6 структуры SOCKADDR_INET должен иметь допустимый IP-адрес одноадресной рассылки. Кроме того, по крайней мере один из следующих элементов в структуре MIB_UNICASTIPADDRESS_ROW , указываемой на параметр Row , должен быть инициализирован в интерфейсе: InterfaceLuid или InterfaceIndex.
Поля используются в указанном выше порядке. Поэтому если указан InterfaceLuid , то этот элемент используется для определения интерфейса, к которому добавляется одноадресный IP-адрес. Если для элемента InterfaceLuid не задано значение (значения этого элемента были равны нулю), то для определения интерфейса используется элемент InterfaceIndex .
Если элемент OnLinkPrefixLengthMIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row , имеет значение 255, то CreateUnicastIpAddressEntry добавит новый одноадресный IP-адрес с набором элементов OnLinkPrefixLength , равным длине IP-адреса. Поэтому для одноадресного IPv4-адреса OnLinkPrefixLength имеет значение 32, а OnLinkPrefixLength — 128 для одноадресного IPv6-адреса. Если это приведет к неправильной маске подсети для IPv4-адреса или неправильному префиксу ссылки для IPv6-адреса, приложение должно задать для этого элемента правильное значение перед вызовом CreateUnicastIpAddressEntry.
Если ip-адрес одноадресной рассылки создается с неправильно заданным элементом OnLinkPrefixLength , ip-адрес можно изменить, вызвав Метод SetUnicastIpAddressEntry с правильным значением элемента OnLinkPrefixLength .
Элементы DadState, ScopeId и CreationTimeStampструктуры MIB_UNICASTIPADDRESS_ROW , на которую указывает Строка , игнорируются при вызове функции CreateUnicastIpAddressEntry . Эти элементы задаются сетевым стеком. Элемент ScopeId автоматически определяется интерфейсом, в который добавляется адрес. Начиная с Windows 10, если для dadState задано значение IpDadStatePreferred в структуре MIB_UNICASTIPADDRESS_ROW при вызове Метода CreateUnicastIpAddressEntry, стек установит начальное состояние DAD адреса на "предпочтительное", а не "предварительное" и выполнит оптимистичный DAD для адреса.
Функция CreateUnicastIpAddressEntry завершится ошибкой , если одноадресный IP-адрес, переданный в элементе AddressMIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row , является дубликатом существующего одноадресного IP-адреса в интерфейсе. Обратите внимание, что IP-адрес замыкания на себя можно добавить в интерфейс замыкания на себя только с помощью функции CreateUnicastIpAddressEntry .
Ip-адрес одноадресной рассылки, переданный в элементе AddressMIB_UNICASTIPADDRESS_ROW , на который указывает параметр Row , нельзя использовать сразу. IP-адрес можно использовать после успешного завершения процесса обнаружения повторяющихся адресов. Процесс обнаружения повторяющихся адресов может занять несколько секунд, так как необходимо отправлять IP-пакеты и ожидать потенциальных ответов. Для IPv6 процесс обнаружения повторяющихся адресов обычно занимает около секунды. Для IPv4 процесс обнаружения повторяющихся адресов обычно занимает около трех секунд.
Если приложению необходимо знать, когда IP-адрес можно использовать после вызова функции CreateUnicastIpAddressEntry , можно использовать два метода. Один из методов использует опрос и функцию GetUnicastIpAddressEntry . Второй метод вызывает одну из функций уведомлений NotifyAddrChange, NotifyIpInterfaceChange или NotifyUnicastIpAddressChange , чтобы настроить асинхронное уведомление об изменении адреса.
Следующий метод описывает, как использовать GetUnicastIpAddressEntry и опрос. После успешного возврата функции CreateUnicastIpAddressEntry приостановите работу на одну-три секунды (в зависимости от того, создается ли IPv6- или IPv4-адрес), чтобы предоставить время для успешного завершения процесса обнаружения адресов дублирования. Затем вызовите функцию GetUnicastIpAddressEntry , чтобы получить обновленную структуру MIB_UNICASTIPADDRESS_ROW и проверить значение элемента DadState . Если для элемента DadState задано значение IpDadStatePreferred, IP-адрес теперь можно использовать. Если для элемента DadState задано значение IpDadStateTentative, обнаружение повторяющихся адресов еще не завершено. В этом случае вызывайте функцию GetUnicastIpAddressEntry каждые полсекунды, пока член DadState по-прежнему имеет значение IpDadStateTentative. Если значение элемента DadState возвращает значение, отличное от IpDadStatePreferred или IpDadStateTentative, обнаружение повторяющихся адресов завершилось ошибкой и IP-адрес недоступен.
Следующий метод описывает, как использовать соответствующую функцию уведомления. После успешного возврата функции CreateUnicastIpAddressEntry вызовите функцию NotifyUnicastIpAddressChange , чтобы зарегистрироваться для уведомления об изменениях ip-адресов одноадресной рассылки IPv6 или IPv4 в зависимости от типа создаваемого IP-адреса. При получении уведомления о создаваемом IP-адресе вызовите функцию GetUnicastIpAddressEntry , чтобы получить элемент DadState . Если для элемента DadState задано значение IpDadStatePreferred, IP-адрес теперь можно использовать. Если для элемента DadState задано значение IpDadStateTentative, обнаружение повторяющихся адресов еще не завершено и приложению необходимо дождаться будущих уведомлений. Если значение элемента DadState возвращает значение, отличное от IpDadStatePreferred или IpDadStateTentative, обнаружение повторяющихся адресов завершилось ошибкой и IP-адрес недоступен.
Если во время процесса обнаружения повторяющихся адресов носитель отключается, а затем повторно подключается, процесс обнаружения повторяющихся адресов перезапускается. Таким образом, время завершения процесса может превысить обычное значение 1 секунды для IPv6 или 3 секунды для IPv4.
Функция CreateUnicastIpAddressEntry может вызываться только пользователем, вошедшего в систему как член группы Администраторы. Если метод CreateUnicastIpAddressEntry вызывается пользователем, не входящий в группу Администраторы, вызов функции завершится ошибкой и возвращается ERROR_ACCESS_DENIED. Эта функция также может завершиться ошибкой из-за контроля учетных записей (UAC) в Windows Vista и более поздних версиях. Если приложение, содержащее эту функцию, выполняется пользователем, вошедшего в систему как участник группы администраторов, отличный от встроенного администратора, этот вызов завершится ошибкой, если приложение не было отмечено в файле манифеста параметром requestedExecutionLevel , для которого задано значение requireAdministrator. Если в приложении отсутствует этот файл манифеста, пользователь, вошедший в систему как член группы администраторов, отличный от встроенного администратора, должен выполнять приложение в расширенной оболочке в качестве встроенного администратора (администратора запуска от имени) для успешного выполнения этой функции.
Примеры
В следующем примере показано, как использовать функцию CreateUnicastIpAddressEntry для добавления новой записи одноадресного IP-адреса на локальном компьютере.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <windows.h>
#include <winsock2.h>
#include <ws2ipdef.h>
#include <iphlpapi.h>
#include <stdio.h>
#include <stdlib.h>
// Need to link with Iphlpapi.lib and Ws2_32.lib
#pragma comment(lib, "iphlpapi.lib")
#pragma comment(lib, "ws2_32.lib")
HANDLE gCallbackComplete;
HANDLE gNotifyEvent;
void CALLBACK CallCompleted (VOID *callerContext,
PMIB_UNICASTIPADDRESS_ROW row,
MIB_NOTIFICATION_TYPE notificationType);
int main(int argc, char **argv) {
// Declare and initialize variables
unsigned long ipAddress = INADDR_NONE;
unsigned long ipMask = INADDR_NONE;
DWORD dwRetVal = 0;
DWORD dwSize = 0;
unsigned long status = 0;
DWORD lastError = 0;
SOCKADDR_IN localAddress;
NET_LUID interfaceLuid;
PMIB_IPINTERFACE_TABLE pipTable = NULL;
MIB_UNICASTIPADDRESS_ROW ipRow;
// Validate the parameters
if (argc != 3) {
printf("usage: %s IPv4address IPv4mask\n", argv[0]);
exit(1);
}
ipAddress = inet_addr(argv[1]);
if (ipAddress == INADDR_NONE) {
printf("usage: %s IPv4address IPv4mask\n", argv[0]);
exit(1);
}
ipMask = inet_addr(argv[2]);
if (ipMask == INADDR_NONE) {
printf("usage: %s IPv4address IPv4mask\n", argv[0]);
exit(1);
}
status = GetIpInterfaceTable( AF_INET, &pipTable );
if( status != NO_ERROR )
{
printf("GetIpInterfaceTable returned error: %ld\n",
status);
exit(1);
}
// Use loopback interface
interfaceLuid = pipTable->Table[0].InterfaceLuid;
localAddress.sin_family = AF_INET;
localAddress.sin_addr.S_un.S_addr = ipAddress;
FreeMibTable(pipTable);
pipTable = NULL;
// Initialize the row
InitializeUnicastIpAddressEntry( &ipRow );
ipRow.InterfaceLuid = interfaceLuid;
ipRow.Address.Ipv4 = localAddress;
// Create a Handle to be notified of IP address changes
gCallbackComplete = CreateEvent(NULL, FALSE, FALSE, NULL);
if (gCallbackComplete == NULL) {
printf("CreateEvent failed with error: %d\n", GetLastError() );
exit(1);
}
// Use NotifyUnicastIpAddressChange to determine when the address is ready
NotifyUnicastIpAddressChange(AF_INET, &CallCompleted, NULL, FALSE, &gNotifyEvent);
status = CreateUnicastIpAddressEntry(&ipRow);
if(status != NO_ERROR)
{
CancelMibChangeNotify2(gNotifyEvent);
switch(status)
{
case ERROR_INVALID_PARAMETER:
printf("Error: CreateUnicastIpAddressEntry returned ERROR_INVALID_PARAMETER\n");
break;
case ERROR_NOT_FOUND:
printf("Error: CreateUnicastIpAddressEntry returned ERROR_NOT_FOUND\n");
break;
case ERROR_NOT_SUPPORTED:
printf("Error: CreateUnicastIpAddressEntry returned ERROR_NOT_SUPPORTED\n");
break;
case ERROR_OBJECT_ALREADY_EXISTS:
printf("Error: CreateUnicastIpAddressEntry returned ERROR_OBJECT_ALREADY_EXISTS\n");
break;
default:
//NOTE: Is this case needed? If not, we can remove the ErrorExit() function
printf("CreateUnicastIpAddressEntry returned error: %d\n", status);
break;
}
exit (status);
}
else
printf("CreateUnicastIpAddressEntry succeeded\n");
// Set timeout to 6 seconds
status = WaitForSingleObject(gCallbackComplete, 6000);
if(status != WAIT_OBJECT_0)
{
CancelMibChangeNotify2(gNotifyEvent);
CancelMibChangeNotify2(gCallbackComplete);
switch(status)
{
case WAIT_ABANDONED:
printf("Wait on event was abandoned\n");
break;
case WAIT_TIMEOUT:
printf("Wait on event timed out\n");
break;
default:
printf("Wait on event exited with status %d\n", status);
break;
}
return status;
}
printf("Task completed successfully\n");
CancelMibChangeNotify2(gNotifyEvent);
CancelMibChangeNotify2(gCallbackComplete);
exit (0);
}
void CALLBACK CallCompleted(PVOID callerContext, PMIB_UNICASTIPADDRESS_ROW row, MIB_NOTIFICATION_TYPE notificationType)
{
ADDRESS_FAMILY addressFamily;
SOCKADDR_IN sockv4addr;
struct in_addr ipv4addr;
// Ensure that this is the correct notification before setting gCallbackComplete
// NOTE: Is there a stronger way to do this?
if(notificationType == MibAddInstance) {
printf("NotifyUnicastIpAddressChange received an Add instance\n");
addressFamily = (ADDRESS_FAMILY) row->Address.si_family;
switch (addressFamily) {
case AF_INET:
printf("\tAddressFamily: AF_INET\n");
break;
case AF_INET6:
printf("\tAddressFamily: AF_INET6\n");
break;
default:
printf("\tAddressFamily: %d\n", addressFamily);
break;
}
if (addressFamily == AF_INET) {
sockv4addr = row->Address.Ipv4;
ipv4addr = sockv4addr.sin_addr;
printf("IPv4 address: %s\n", inet_ntoa(ipv4addr) );
}
if (callerContext != NULL)
printf("Received a CallerContext value\n");
SetEvent(gCallbackComplete);
}
return;
}
Требования
| Требование | Значение |
|---|---|
| Минимальная версия клиента | Windows Vista [только классические приложения] |
| Минимальная версия сервера | Windows Server 2008 [только классические приложения] |
| Целевая платформа | Windows |
| Header | netioapi.h (включая Iphlpapi.h) |
| Библиотека | Iphlpapi.lib |
| DLL | Iphlpapi.dll |
См. также раздел
Справочник по вспомогательным функциям IP