2 * Copyright 2000, International Business Machines Corporation and others.
5 * This software has been released under the terms of the IBM Public
6 * License. For details, see the LICENSE file in the top-level source
7 * directory or online at http://www.openafs.org/dl/license10.html
10 /* Functions for accessing NT system configuration information. */
23 static int IsLoopback(char * guid);
27 * Retrieve IP addresses, subnet masks, MTU sizes, and flags for all
28 * configured interfaces.
32 * count - in is max size of arrays. out is number of elements used.
35 * addrs - array of configured IP addresses, in host order.
36 * masks - array of subnet masks, in host order.
37 * mtus - array of MTU sizes.
38 * flags - array of flags.
41 * Total number of configured interfaces (>= count) or -1 on error.
44 int syscfg_GetIFInfo(int *count, int *addrs, int *masks, int *mtus, int *flags)
46 PMIB_IPADDRTABLE pIpAddrTable = NULL;
52 int maxCount = *count;
54 PIP_ADAPTER_ADDRESSES pAddresses, cAddress;
55 PMIB_IPADDRTABLE pIpTbl;
62 DWORD (WINAPI *pGetAdaptersAddresses)(ULONG, DWORD, PVOID,
63 PIP_ADAPTER_ADDRESSES, PULONG) = 0;
65 hIpHlp = LoadLibrary("iphlpapi");
67 (FARPROC) pGetAdaptersAddresses = GetProcAddress(hIpHlp, "GetAdaptersAddresses");
68 if (pGetAdaptersAddresses == NULL)
72 if (pGetAdaptersAddresses == NULL)
73 return syscfg_GetIFInfo_2000(count, addrs, masks, mtus, flags);
75 /* first pass to get the required size of the IP table */
76 pIpTbl = (PMIB_IPADDRTABLE) malloc(sizeof(MIB_IPADDRTABLE));
77 outBufLen = sizeof(MIB_IPADDRTABLE);
79 dwRetVal = GetIpAddrTable(pIpTbl, &outBufLen, FALSE);
80 if (dwRetVal != ERROR_INSUFFICIENT_BUFFER) {
81 /* this should have failed with an insufficient buffer because we
82 didn't give any space to place the IP addresses */
89 /* second pass to get the actual data */
91 pIpTbl = (PMIB_IPADDRTABLE) malloc(outBufLen);
93 dwRetVal = GetIpAddrTable(pIpTbl, &outBufLen, FALSE);
94 if (dwRetVal != NO_ERROR) {
101 pAddresses = (IP_ADAPTER_ADDRESSES*) malloc(sizeof(IP_ADAPTER_ADDRESSES));
103 /* first call gets required buffer size */
104 if (pGetAdaptersAddresses(AF_INET,
108 &outBufLen) == ERROR_BUFFER_OVERFLOW)
111 pAddresses = (IP_ADAPTER_ADDRESSES*) malloc(outBufLen);
119 /* second call to get the actual data */
120 if ((dwRetVal = pGetAdaptersAddresses(AF_INET,
124 &outBufLen)) == NO_ERROR)
126 /* we have a list of addresses. go through them and figure out
128 for (cAddress = pAddresses; cAddress; cAddress = cAddress->Next) {
130 /* skip software loopback adapters */
131 if (cAddress->IfType == IF_TYPE_SOFTWARE_LOOPBACK)
134 /* also skip interfaces that are not up */
135 if (cAddress->OperStatus != 1)
138 /* starting with the AdapterName, which is actually the adapter
139 instance GUID, check if this is a MS loopback device */
140 if (IsLoopback(cAddress->AdapterName))
143 /* ok. looks good. Now fish out all the addresses from the
144 address table corresponding to the interface, and add them
146 for (i=0;i<pIpTbl->dwNumEntries;i++) {
147 if (pIpTbl->table[i].dwIndex == cAddress->IfIndex)
150 addrs[n] = ntohl(pIpTbl->table[i].dwAddr);
151 masks[n] = ntohl(pIpTbl->table[i].dwMask);
152 mtus[n] = cAddress->Mtu;
166 /* again. this is bad */
178 static int IsLoopback(char * guid)
180 int isloopback = FALSE;
184 HKEY hkDevConn = NULL;
186 HKEY hkAdapter = NULL;
188 char pnpIns[MAX_PATH];
190 char service[MAX_PATH];
194 /* Open the network adapters key */
195 if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Control\\Network\\{4D36E972-E325-11CE-BFC1-08002BE10318}", 0, KEY_READ, &hkNet)))
198 /* open the guid key */
199 if (FAILED(RegOpenKeyEx(hkNet, guid, 0, KEY_READ, &hkDev)))
202 /* then the connection */
203 if (FAILED(RegOpenKeyEx(hkDev, "Connection", 0, KEY_READ, &hkDevConn)))
206 /* and find out the plug-n-play instance ID */
208 if (FAILED(RegQueryValueEx(hkDevConn, "PnpInstanceID", NULL, NULL, pnpIns, &size)))
211 /* now look in the device ENUM */
212 if (FAILED(RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\CurrentControlSet\\Enum", 0, KEY_READ, &hkEnum)))
215 /* for the instance that we found above */
216 if (FAILED(RegOpenKeyEx(hkEnum, pnpIns, 0, KEY_READ, &hkAdapter)))
219 /* and fetch the harware ID */
221 if (FAILED(RegQueryValueEx(hkAdapter, "HardwareID", NULL, NULL, hwId, &size)))
225 if (FAILED(RegQueryValueEx(hkAdapter, "Service", NULL, NULL, service, &size)))
228 /* and see if it is the loopback adapter */
229 if (!stricmp(hwId, "*msloop") || !stricmp(service, "msloop"))
234 RegCloseKey(hkAdapter);
238 RegCloseKey(hkDevConn);
247 static int GetInterfaceList(HKEY skey, char **list);
248 static char *GetNextInterface(char *iflist);
249 static int GetIP(HKEY skey, char *ifname, int *addr, int *mask);
251 int syscfg_GetIFInfo_2000(int *count, int *addrs, int *masks, int *mtus, int *flags)
253 int maxCount = *count;
254 char *IFListBase = NULL;
255 char *IFList, *ifname;
259 if (RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_IPSRV_KEY,
260 KEY_READ, 0, &skey, NULL))
263 if ((nConfig = GetInterfaceList(skey, &IFListBase)) < 0) {
264 (void) RegCloseKey(skey);
271 while ((n < maxCount) && (ifname = GetNextInterface(IFList))) {
272 if (!IsLoopback(ifname) && GetIP(skey, ifname, &addrs[n], &masks[n]) == 0 && addrs[n] != 0) {
280 /* And until we get mtu's and flags */
281 for (i = 0; i < n; i++) {
286 (void) RegCloseKey(skey);
296 * Get interface list; list is represented as a multistring.
297 * Returns number of elements in interface list or -1 on error.
299 static int GetInterfaceList(HKEY skey, char **list)
307 if (RegOpenKeyAlt(skey, AFSREG_IPSRV_IFACELIST_SUBKEY,
308 KEY_READ, 0, &key, NULL))
311 status = RegQueryValueAlt(key, AFSREG_IPSRV_IFACELIST_BIND_VALUE,
312 &valType, &str, NULL);
313 (void) RegCloseKey(key);
314 if (status || (valType != REG_MULTI_SZ))
317 /* Count strings in multistring. */
324 if (str[i] == '\0') {
325 /* hit end of string */
328 if (str[i] == '\0') {
329 /* hit end of multistring */
342 * Parse interface list. In first call to GetNextInterface(), iflist is
343 * the list returned by GetInterfaceList(); in successive calls, iflist is
344 * the pointer returned by the previous call to GetNextInterface().
346 * Returns pointer to next adapter name, or NULL if done.
349 static char *GetNextInterface(char *iflist)
353 /* interface substrings are assumed to be of form \Device\<adapter name>
354 * \Tcpip\Parameters\Interfaces\<adapter name>
356 ifname = strrchr(iflist, '\\');
359 /* subsequent (not first) call; advance to next interface substring */
360 iflist += strlen(iflist) + 1;
361 /* iflist now points to next interface or end-of-multistring char */
362 ifname = strrchr(iflist, '\\');
366 /* advance to first character of adapter name */
376 * Get IP address associated with interface (adapter name).
377 * Returns 0 on success and -1 on error.
380 static int GetIP(HKEY skey, char *ifname, int *addr, int *mask)
393 len = strlen(ifname) + 1 + sizeof(AFSREG_IPSRV_ADAPTER_PARAM_SUBKEY);
398 sprintf(s, "%s\\%s", ifname, AFSREG_IPSRV_ADAPTER_PARAM_SUBKEY);
400 status = RegOpenKeyAlt(skey, s, KEY_READ, 0, &key, NULL);
406 dwSize = sizeof(DWORD);
407 status = RegQueryValueEx(key, "EnableDHCP", NULL,
408 &valType, &dwDHCP, &dwSize);
409 if (status || (valType != REG_DWORD))
413 status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_ADDR_VALUE,
414 &valType, &ipStr, NULL);
415 if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
416 if (ipStr) free(ipStr);
417 (void) RegCloseKey(key);
421 status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_MASK_VALUE,
422 &valType, &snMask, NULL);
423 if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
424 if (snMask) free(snMask);
428 /* adapter configured via DHCP; address/mask in alternate values */
429 dwSize = sizeof(DWORD);
430 status = RegQueryValueEx(key, "Lease", NULL,
431 &valType, &dwLease, &dwSize);
432 if (status || (valType != REG_DWORD) || dwLease == 0) {
433 (void) RegCloseKey(key);
437 status = RegQueryValueAlt(key,
438 AFSREG_IPSRV_ADAPTER_PARAM_DHCPADDR_VALUE,
439 &valType, &ipStr, NULL);
441 if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
442 if (ipStr) free(ipStr);
443 (void) RegCloseKey(key);
447 status = RegQueryValueAlt(key,
448 AFSREG_IPSRV_ADAPTER_PARAM_DHCPMASK_VALUE,
449 &valType, &snMask, NULL);
451 if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
452 if (snMask) free(snMask);
457 /* convert ip and subnet. */
458 *addr = (int)inet_addr(ipStr);
459 *addr = ntohl(*addr);
463 *mask = (int)inet_addr(snMask);
464 *mask = ntohl(*mask);
470 (void) RegCloseKey(key);