/* Copyright (C) 1998 Transarc Corporation. All rights reserved. * */ /* Functions for accessing NT system configuration information. */ #include #include #include #include #include #include #include #include #include "afsreg.h" #include "syscfg.h" static int GetInterfaceList(HKEY skey, char **list); static char *GetNextInterface(char *iflist); static int GetIP(HKEY skey, char *ifname, int *addr, int *mask); /* syscfg_GetIFInfo * * Retrieve IP addresses, subnet masks, MTU sizes, and flags for all * configured interfaces. * * Arguments: * IN/OUT: * count - in is max size of arrays. out is number of elements used. * * OUT: * addrs - array of configured IP addresses, in host order. * masks - array of subnet masks, in host order. * mtus - array of MTU sizes. * flags - array of flags. * * Return Value: * Total number of configured interfaces (>= count) or -1 on error. */ int syscfg_GetIFInfo(int *count, int *addrs, int *masks, int *mtus, int *flags) { int maxCount = *count; char *IFListBase = NULL; char *IFList, *ifname; HKEY skey; int i, n, nConfig; if (RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_IPSRV_KEY, KEY_READ, 0, &skey, NULL)) return -1; if ((nConfig = GetInterfaceList(skey, &IFListBase)) < 0) { (void) RegCloseKey(skey); return -1; } IFList = IFListBase; n = 0; while ((n < maxCount) && (ifname = GetNextInterface(IFList))) { if (GetIP(skey, ifname, &addrs[n], &masks[n]) == 0) { n++ ; } IFList = ifname; } /* And until we get mtu's and flags */ for (i = 0; i < n; i++) { mtus[i] = 1500; flags[i] = 0; } (void) RegCloseKey(skey); free(IFListBase); *count = n; return nConfig; } /* GetInterfaceList * * Get interface list; list is represented as a multistring. * Returns number of elements in interface list or -1 on error. */ static int GetInterfaceList(HKEY skey, char **list) { HKEY key; long status; char *str = NULL; int size; DWORD valType; if (RegOpenKeyAlt(skey, AFSREG_IPSRV_IFACELIST_SUBKEY, KEY_READ, 0, &key, NULL)) return -1; status = RegQueryValueAlt(key, AFSREG_IPSRV_IFACELIST_BIND_VALUE, &valType, &str, NULL); (void) RegCloseKey(key); if (status || (valType != REG_MULTI_SZ)) return -1; /* Count strings in multistring. */ size = 0; if (*str != '\0') { int i; for (i = 1; ; i++) { if (str[i] == '\0') { /* hit end of string */ size++; i++; if (str[i] == '\0') { /* hit end of multistring */ break; } } } } *list = str; return size; } /* GetNextInterface * * Parse interface list. In first call to GetNextInterface(), iflist is * the list returned by GetInterfaceList(); in successive calls, iflist is * the pointer returned by the previous call to GetNextInterface(). * * Returns pointer to next adapter name, or NULL if done. */ static char *GetNextInterface(char *iflist) { char *ifname; /* interface substrings are assumed to be of form \Device\ */ ifname = strrchr(iflist, '\\'); if (!ifname) { /* subsequent (not first) call; advance to next interface substring */ iflist += strlen(iflist) + 1; /* iflist now points to next interface or end-of-multistring char */ ifname = strrchr(iflist, '\\'); } if (ifname) { /* advance to first character of adapter name */ ifname++; } return ifname; } /* GetIP * * Get IP address associated with interface (adapter name). * Returns 0 on success and -1 on error. */ static int GetIP(HKEY skey, char *ifname, int *addr, int *mask) { HKEY key; char *s; long status; int len; char *ipStr = NULL; char *snMask = NULL; DWORD valType; len = strlen(ifname) + 1 + sizeof(AFSREG_IPSRV_ADAPTER_PARAM_SUBKEY); s = malloc(len); if (!s) return -1; sprintf(s, "%s\\%s", ifname, AFSREG_IPSRV_ADAPTER_PARAM_SUBKEY); status = RegOpenKeyAlt(skey, s, KEY_READ, 0, &key, NULL); free(s); if (status) return -1; status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_ADDR_VALUE, &valType, &ipStr, NULL); if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) { if (ipStr) free(ipStr); (void) RegCloseKey(key); return -1; } if (*ipStr != '0') { status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_MASK_VALUE, &valType, &snMask, NULL); if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) { if (snMask) free(snMask); snMask = NULL; } } else { /* adapter configured via DHCP; address/mask in alternate values */ free(ipStr); ipStr = NULL; status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_DHCPADDR_VALUE, &valType, &ipStr, NULL); if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) { if (ipStr) free(ipStr); (void) RegCloseKey(key); return -1; } status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_DHCPMASK_VALUE, &valType, &snMask, NULL); if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) { if (snMask) free(snMask); snMask = NULL; } } /* convert ip and subnet. */ *addr = (int)inet_addr(ipStr); *addr = ntohl(*addr); free(ipStr); if (snMask) { *mask = (int)inet_addr(snMask); *mask = ntohl(*mask); free(snMask); } else { *mask = 0; } (void) RegCloseKey(key); return 0; }