winnt-dont-display-ibm-legal-message-20040326
[openafs.git] / src / WINNT / afsreg / syscfg.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
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
8  */
9
10 /* Functions for accessing NT system configuration information. */
11
12 #include <afs/param.h>
13 #include <afs/stds.h>
14
15 #include <windows.h>
16 #include <stddef.h>
17 #include <stdlib.h>
18 #include <stdio.h>
19 #include <string.h>
20 #include <winsock2.h>
21
22 #include "afsreg.h"
23 #include "syscfg.h"
24
25 static int GetInterfaceList(HKEY skey, char **list);
26 static char *GetNextInterface(char *iflist);
27 static int GetIP(HKEY skey, char *ifname, int *addr, int *mask);
28
29
30 /* syscfg_GetIFInfo
31  *
32  * Retrieve IP addresses, subnet masks, MTU sizes, and flags for all
33  * configured interfaces.
34  *
35  * Arguments:
36  * IN/OUT:
37  *      count - in is max size of arrays. out is number of elements used.
38  *
39  * OUT:
40  *      addrs - array of configured IP addresses, in host order.
41  *      masks - array of subnet masks, in host order.
42  *      mtus  - array of MTU sizes.
43  *      flags - array of flags.
44  *
45  * Return Value:
46  *      Total number of configured interfaces (>= count) or -1 on error.
47  */
48
49 int syscfg_GetIFInfo(int *count, int *addrs, int *masks, int *mtus, int *flags)
50 {
51     int maxCount = *count;
52     char *IFListBase = NULL;
53     char *IFList, *ifname;
54     HKEY skey;
55     int i, n, nConfig;
56
57     if (RegOpenKeyAlt(AFSREG_NULL_KEY, AFSREG_IPSRV_KEY,
58                       KEY_READ, 0, &skey, NULL))
59         return -1;
60
61     if ((nConfig = GetInterfaceList(skey, &IFListBase)) < 0) {
62         (void) RegCloseKey(skey);
63         return -1;
64     }
65
66     IFList = IFListBase;
67     n = 0;
68
69     while ((n < maxCount) && (ifname = GetNextInterface(IFList))) {
70         if (GetIP(skey, ifname, &addrs[n], &masks[n]) == 0) {
71             n++ ;
72         }
73         IFList = ifname;
74     }
75
76     /* And until we get mtu's and flags */
77     for (i = 0; i < n; i++) {
78         mtus[i] = 1500;
79         flags[i] = 0;
80     }
81
82     (void) RegCloseKey(skey);
83     free(IFListBase);
84
85     *count = n;
86     return nConfig;
87 }
88
89
90 /* GetInterfaceList
91  *
92  * Get interface list; list is represented as a multistring.
93  * Returns number of elements in interface list or -1 on error.
94  */
95 static int GetInterfaceList(HKEY skey, char **list)
96 {
97     HKEY key;
98     long status;
99     char *str = NULL;
100     int size;
101     DWORD valType;
102
103     if (RegOpenKeyAlt(skey, AFSREG_IPSRV_IFACELIST_SUBKEY,
104                       KEY_READ, 0, &key, NULL))
105         return -1;
106
107     status = RegQueryValueAlt(key, AFSREG_IPSRV_IFACELIST_BIND_VALUE,
108                               &valType, &str, NULL);
109     (void) RegCloseKey(key);
110     if (status || (valType != REG_MULTI_SZ))
111         return -1;
112
113     /* Count strings in multistring. */
114     size = 0;
115
116     if (*str != '\0') {
117         int i;
118
119         for (i = 1; ; i++) {
120             if (str[i] == '\0') {
121                 /* hit end of string */
122                 size++;
123                 i++;
124                 if (str[i] == '\0') {
125                     /* hit end of multistring */
126                     break;
127                 }
128             }
129         }
130     }
131     *list = str;
132     return size;
133 }
134
135
136 /* GetNextInterface
137  *
138  * Parse interface list.  In first call to GetNextInterface(), iflist is
139  * the list returned by GetInterfaceList(); in successive calls, iflist is
140  * the pointer returned by the previous call to GetNextInterface().
141  *
142  * Returns pointer to next adapter name, or NULL if done.
143  */
144
145 static char *GetNextInterface(char *iflist)
146 {
147     char *ifname;
148
149     /* interface substrings are assumed to be of form \Device\<adapter name> */
150     ifname = strrchr(iflist, '\\');
151
152     if (!ifname) {
153         /* subsequent (not first) call; advance to next interface substring */
154         iflist += strlen(iflist) + 1;
155         /* iflist now points to next interface or end-of-multistring char */
156         ifname = strrchr(iflist, '\\');
157     }
158
159     if (ifname) {
160         /* advance to first character of adapter name */
161         ifname++;
162     }
163
164     return ifname;
165 }
166
167
168 /* GetIP
169  *
170  * Get IP address associated with interface (adapter name).
171  * Returns 0 on success and -1 on error.
172  */
173
174 static int GetIP(HKEY skey, char *ifname, int *addr, int *mask)
175 {
176     HKEY key;
177     char *s;
178     long status;
179     int len;
180     char *ipStr = NULL;
181     char *snMask = NULL;
182     DWORD valType;
183
184     len = strlen(ifname) + 1 + sizeof(AFSREG_IPSRV_ADAPTER_PARAM_SUBKEY);
185     s = malloc(len);
186     if (!s)
187         return -1;
188
189     sprintf(s, "%s\\%s", ifname, AFSREG_IPSRV_ADAPTER_PARAM_SUBKEY);
190
191     status = RegOpenKeyAlt(skey, s, KEY_READ, 0, &key, NULL);
192     free(s);
193
194     if (status)
195         return -1;
196
197     status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_ADDR_VALUE,
198                               &valType, &ipStr, NULL);
199     if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
200         if (ipStr) free(ipStr);
201         (void) RegCloseKey(key);
202         return -1;
203     }
204
205     if (*ipStr != '0') {
206         status = RegQueryValueAlt(key, AFSREG_IPSRV_ADAPTER_PARAM_MASK_VALUE,
207                                   &valType, &snMask, NULL);
208         if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
209             if (snMask) free(snMask);
210             snMask = NULL;
211         }
212     } else {
213         /* adapter configured via DHCP; address/mask in alternate values */
214         free(ipStr);
215         ipStr = NULL;
216
217         status = RegQueryValueAlt(key,
218                                   AFSREG_IPSRV_ADAPTER_PARAM_DHCPADDR_VALUE,
219                                   &valType, &ipStr, NULL);
220
221         if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
222             if (ipStr) free(ipStr);
223             (void) RegCloseKey(key);
224             return -1;
225         }
226
227         status = RegQueryValueAlt(key,
228                                   AFSREG_IPSRV_ADAPTER_PARAM_DHCPMASK_VALUE,
229                                   &valType, &snMask, NULL);
230
231         if (status || (valType != REG_SZ && valType != REG_MULTI_SZ)) {
232             if (snMask) free(snMask);
233             snMask = NULL;
234         }
235     }
236
237     /* convert ip and subnet. */
238     *addr = (int)inet_addr(ipStr);
239     *addr = ntohl(*addr);
240     free(ipStr);
241
242     if (snMask) {
243         *mask = (int)inet_addr(snMask);
244         *mask = ntohl(*mask);
245         free(snMask);
246     } else {
247         *mask = 0;
248     }
249
250     (void) RegCloseKey(key);
251
252     return 0;
253 }