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
11 * Network utility functions
12 * Parsing NetRestrict file and filtering IP addresses
15 #include <afsconfig.h>
16 #include <afs/param.h>
24 #include <afs/dirpath.h>
26 #include "cellconfig.h"
28 #define AFS_IPINVALID 0xffffffff /* invalid IP address */
29 #define AFS_IPINVALIDIGNORE 0xfffffffe /* no input given to extractAddr */
30 #define MAX_NETFILE_LINE 2048 /* length of a line in the netrestrict file */
31 #define MAXIPADDRS 1024 /* from afsd.c */
33 static int ParseNetInfoFile_int(afs_uint32 *, afs_uint32 *, afs_uint32 *,
34 int, char reason[], const char *,
37 * The line parameter is a pointer to a buffer containing a string of
39 ** w.x.y.z # machineName
40 * returns the network interface IP Address in NBO
43 extract_Addr(char *line, int maxSize)
49 afs_uint32 retval = 0;
51 /* skip empty spaces */
52 while (isspace(*line) && maxSize) {
56 /* skip empty lines */
57 if (!maxSize || !*line)
58 return AFS_IPINVALIDIGNORE;
60 for (n = 0; n < 4; n++) {
61 while ((*line != '.') && !isspace(*line) && maxSize) { /* extract nth byte */
65 return AFS_IPINVALID; /* no space */
66 bytes[n][i++] = *line++;
74 val[n] = strtol(bytes[n], &endPtr, 10);
75 if ((val[n] == 0) && (errno != 0 || bytes[n] == endPtr)) /* no conversion */
79 retval = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
84 * Get a list of IP addresses for this host removing any address found
85 * in the config file (fileName parameter): /usr/vice/etc/NetRestrict
86 * for clients and /usr/afs/local/NetRestrict for servers.
88 * Returns the number of valid addresses in outAddrs[] and count in
89 * nAddrs. Returns 0 on success; or 1 if the config file was not
90 * there or empty (we still return the host's IP addresses). Returns
91 * -1 on fatal failure with reason in the reason argument (so the
92 * caller can choose to ignore the entire file but should write
93 * something to a log file).
95 * All addresses should be in network byte order as returned by
96 * rx_getAllAddrMaskMtu() and parsed by extract_Addr().
98 * @param[out] outAddrs
99 * All the address that are found to be valid.
100 * @param[out] outMask
101 * Optional associated netmask for address
103 * Optional associated MTU for address
104 * @param[in] maxAddres
105 * Length of the above output arrays
107 * Count of valid addresses
109 * Reason (if any) for the parsing failure
110 * @param[in] fileName
111 * Configuration file to parse
114 * 0 on success; 1 if the config file was not used; -1 on
118 parseNetRestrictFile_int(afs_uint32 outAddrs[], afs_uint32 outMask[],
119 afs_uint32 outMtu[], afs_uint32 maxAddrs,
120 afs_uint32 *nAddrs, char reason[],
121 const char *fileName, const char *fileName_ni)
124 char line[MAX_NETFILE_LINE];
125 int lineNo, usedfile = 0;
126 afs_uint32 i, neaddrs, nOutaddrs;
127 afs_uint32 addr, eAddrs[MAXIPADDRS], eMask[MAXIPADDRS], eMtu[MAXIPADDRS];
129 opr_Assert(outAddrs);
131 opr_Assert(fileName);
138 for (i = 0; i < maxAddrs; i++)
142 /* get all network interfaces from the kernel */
143 neaddrs = rx_getAllAddrMaskMtu(eAddrs, eMask, eMtu, MAXIPADDRS);
145 sprintf(reason, "No existing IP interfaces found");
149 if ((neaddrs < MAXIPADDRS) && fileName_ni)
150 i = ParseNetInfoFile_int(&(eAddrs[neaddrs]), &(eMask[neaddrs]),
151 &(eMtu[neaddrs]), MAXIPADDRS-neaddrs, reason,
157 if ((fp = fopen(fileName, "r")) == 0) {
158 sprintf(reason, "Could not open file %s for reading:%s", fileName,
163 /* For each line in the NetRestrict file */
166 while (fgets(line, MAX_NETFILE_LINE, fp) != NULL) {
167 lineNo++; /* input line number */
168 addr = extract_Addr(line, strlen(line));
169 if (addr == AFS_IPINVALID) { /* syntactically invalid */
170 fprintf(stderr, "%s : line %d : parse error - invalid IP\n",
174 if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */
175 fprintf(stderr, "%s : line %d : invalid address ... ignoring\n",
181 /* Check if we need to exclude this address */
182 for (i = 0; i < neaddrs; i++) {
183 if (eAddrs[i] && (eAddrs[i] == addr)) {
184 eAddrs[i] = 0; /* Yes - exclude it by zeroing it for now */
192 sprintf(reason, "No valid IP addresses in %s\n", fileName);
197 /* Collect the addresses we have left to return */
199 for (i = 0; i < neaddrs; i++) {
202 outAddrs[nOutaddrs] = eAddrs[i];
204 outMask[nOutaddrs] = eMask[i];
205 outMtu[nOutaddrs] = eMtu[i];
207 if (++nOutaddrs >= maxAddrs)
210 if (nOutaddrs == 0) {
211 sprintf(reason, "No addresses to use after parsing %s", fileName);
215 return (usedfile ? 0 : 1); /* 0=>used the file. 1=>didn't use file */
219 afsconf_ParseNetRestrictFile(afs_uint32 outAddrs[], afs_uint32 outMask[],
220 afs_uint32 outMtu[], afs_uint32 maxAddrs,
221 afs_uint32 * nAddrs, char reason[],
222 const char *fileName)
224 return parseNetRestrictFile_int(outAddrs, outMask, outMtu, maxAddrs, nAddrs, reason, fileName, 0);
228 * Get a list of IP addresses for this host allowing only addresses found
229 * in the config file (fileName parameter): /usr/vice/etc/NetInfo for
230 * clients and /usr/afs/local/NetInfo for servers.
232 * All addresses should be in network byte order as returned by
233 * rx_getAllAddrMaskMtu() and parsed by extract_Addr().
235 * @param[out] outAddrs
236 * All the address that are found to be valid.
237 * @param[out] outMask
238 * Associated netmask for interface
240 * Associated MTU for interface
242 * Length of the output above arrays
244 * Reason for the parsing failure
245 * @param[in] fileName
247 * @param[in] fakeonly
248 * Only return addresses if they are marked as fake
251 * The number of valid address on success or < 0 on fatal failure.
254 ParseNetInfoFile_int(afs_uint32 outAddrs[], afs_uint32 outMask[], afs_uint32 outMtu[],
255 int max, char reason[], const char *fileName,
259 afs_uint32 existingAddr[MAXIPADDRS], existingMask[MAXIPADDRS],
260 existingMtu[MAXIPADDRS];
261 char line[MAX_NETFILE_LINE];
263 int i, existNu, count = 0;
268 opr_Assert(fileName);
269 opr_Assert(outAddrs);
274 /* get all network interfaces from the kernel */
276 rx_getAllAddrMaskMtu(existingAddr, existingMask, existingMtu,
281 if ((fp = fopen(fileName, "r")) == 0) {
282 /* If file does not exist or is not readable, then
283 * use all interface addresses.
286 "Failed to open %s(%s)\nUsing all configured addresses\n",
287 fileName, strerror(errno));
288 for (i = 0; i < existNu; i++) {
289 outAddrs[i] = existingAddr[i];
290 outMask[i] = existingMask[i];
291 outMtu[i] = existingMtu[i];
296 /* For each line in the NetInfo file */
297 while (fgets(line, MAX_NETFILE_LINE, fp) != NULL) {
300 /* See if first char is an 'F' for fake */
301 /* Added to allow the fileserver to advertise fake IPS for use with
302 * the translation tables for NAT-like firewalls - defect 12462 */
303 for (fake = 0; ((fake < strlen(line)) && isspace(line[fake]));
305 if ((fake < strlen(line))
306 && ((line[fake] == 'f') || (line[fake] == 'F'))) {
312 lineNo++; /* input line number */
313 addr = extract_Addr(&line[fake], strlen(&line[fake]));
315 if (addr == AFS_IPINVALID) { /* syntactically invalid */
316 fprintf(stderr, "afs:%s : line %d : parse error\n", fileName,
320 if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */
324 /* See if it is an address that really exists */
325 for (i = 0; i < existNu; i++) {
326 if (existingAddr[i] == addr)
329 if ((i >= existNu) && (!fake))
330 continue; /* not found/fake - ignore */
332 /* Check if it is a duplicate address we alread have */
333 for (l = 0; l < count; l++) {
334 if (outAddrs[l] == addr)
338 fprintf(stderr, "afs:%x specified twice in NetInfo file\n",
340 continue; /* duplicate addr - ignore */
343 if (count > max) { /* no more space */
345 "afs:Too many interfaces. The current kernel configuration supports a maximum of %d interfaces\n",
349 fprintf(stderr, "Client (2) also has address %s\n", line);
350 outAddrs[count] = addr;
351 outMask[count] = 0xffffffff;
352 outMtu[count] = htonl(1500);
354 } else if (!fakeonly) {
355 outAddrs[count] = existingAddr[i];
356 outMask[count] = existingMask[i];
357 outMtu[count] = existingMtu[i];
362 /* in case of any error, we use all the interfaces present */
365 "Error in reading/parsing Interface file\nUsing all configured interface addresses \n");
366 for (i = 0; i < existNu; i++) {
367 outAddrs[i] = existingAddr[i];
368 outMask[i] = existingMask[i];
369 outMtu[i] = existingMtu[i];
377 afsconf_ParseNetInfoFile(afs_uint32 outAddrs[], afs_uint32 outMask[], afs_uint32 outMtu[],
378 int max, char reason[], const char *fileName)
380 return ParseNetInfoFile_int(outAddrs, outMask, outMtu, max, reason, fileName, 0);
384 * Given two arrays of addresses, masks and mtus find the common ones
385 * and return them in the first buffer. Return number of common
389 filterAddrs(afs_uint32 addr1[], afs_uint32 addr2[], afs_uint32 mask1[],
390 afs_uint32 mask2[], afs_uint32 mtu1[], afs_uint32 mtu2[], int n1,
393 afs_uint32 taddr[MAXIPADDRS];
394 afs_uint32 tmask[MAXIPADDRS];
395 afs_uint32 tmtu[MAXIPADDRS];
396 int count = 0, i = 0, j = 0, found = 0;
405 for (i = 0; i < n1; i++) {
407 for (j = 0; j < n2; j++) {
408 if (addr1[i] == addr2[j]) {
414 /* Always mask loopback address */
415 if (found && rx_IsLoopbackAddr(addr1[i]))
419 taddr[count] = addr1[i];
420 tmask[count] = mask1[i];
421 tmtu[count] = mtu1[i];
425 /* copy everything into addr1, mask1 and mtu1 */
426 for (i = 0; i < count; i++) {
433 /* and zero out the rest */
434 for (i = count; i < n1; i++) {
445 * parse both NetInfo and NetRestrict files and return the final
446 * set of IP addresses to use
448 /* max - Entries in addrbuf, maskbuf and mtubuf */
450 afsconf_ParseNetFiles(afs_uint32 addrbuf[], afs_uint32 maskbuf[],
451 afs_uint32 mtubuf[], afs_uint32 max, char reason[],
452 const char *niFileName, const char *nrFileName)
454 afs_uint32 addrbuf1[MAXIPADDRS], maskbuf1[MAXIPADDRS],
456 afs_uint32 addrbuf2[MAXIPADDRS], maskbuf2[MAXIPADDRS],
459 afs_uint32 nAddrs2 = 0;
463 afsconf_ParseNetInfoFile(addrbuf1, maskbuf1, mtubuf1, MAXIPADDRS,
466 parseNetRestrictFile_int(addrbuf2, maskbuf2, mtubuf2, MAXIPADDRS,
467 &nAddrs2, reason, nrFileName, niFileName);
468 if ((nAddrs1 < 0) && (code)) {
471 } else if ((nAddrs1 > 0) && (code)) {
472 /* NetInfo succeeded and NetRestrict failed */
473 for (i = 0; ((i < nAddrs1) && (i < max)); i++) {
474 addrbuf[i] = addrbuf1[i];
476 maskbuf[i] = maskbuf1[i];
477 mtubuf[i] = mtubuf1[i];
481 } else if ((!code) && (nAddrs1 < 0)) {
482 /* NetRestrict succeeded and NetInfo failed */
483 for (i = 0; ((i < nAddrs2) && (i < max)); i++) {
484 addrbuf[i] = addrbuf2[i];
486 maskbuf[i] = maskbuf2[i];
487 mtubuf[i] = mtubuf2[i];
491 } else if ((!code) && (nAddrs1 >= 0)) {
493 /* take the intersection of addrbuf1 and addrbuf2 */
495 filterAddrs(addrbuf1, addrbuf2, maskbuf1, maskbuf2, mtubuf1,
496 mtubuf2, nAddrs1, nAddrs2);
497 for (i = 0; ((i < code) && (i < max)); i++) {
498 addrbuf[i] = addrbuf1[i];
500 maskbuf[i] = maskbuf1[i];
501 mtubuf[i] = mtubuf1[i];