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
18 #include "../afs/param.h"
19 #include "../afs/sysincludes.h"
20 #include "../afs/afsincludes.h"
23 #include <sys/types.h>
25 #include <netinet/in.h>
27 #include <sys/errno.h>
33 #define AFS_IPINVALID 0xffffffff /* invalid IP address */
34 #define AFS_IPINVALIDIGNORE 0xfffffffe /* no input given to extractAddr */
35 #define MAX_NETFILE_LINE 2048 /* length of a line in the netrestrict file */
36 #define MAXIPADDRS 1024 /* from afsd.c */
39 * The line parameter is a pointer to a buffer containing a string of
41 ** w.x.y.z # machineName
42 * returns the network interface IP Address in NBO
45 extract_Addr(line, maxSize)
55 /* skip empty spaces */
56 while ( isspace(*line) && maxSize ) {
60 /* skip empty lines */
61 if ( !maxSize || !*line ) return AFS_IPINVALIDIGNORE;
64 while ( ( *line != '.' )&&!isspace(*line) && maxSize) { /* extract nth byte */
65 if ( !isdigit(*line) ) return AFS_IPINVALID;
66 if ( i > 31 ) return AFS_IPINVALID; /* no space */
67 bytes[n][i++] = *line++;
70 if ( !maxSize ) return AFS_IPINVALID;
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];
86 /* parseNetRestrictFile()
87 * Get a list of IP addresses for this host removing any address found
88 * in the config file (fileName parameter): /usr/vice/etc/NetRestrict
89 * for clients and /usr/afs/local/NetRestrict for servers.
91 * Returns the number of valid addresses in outAddrs[] and count in
92 * nAddrs. Returns 0 on success; or 1 if the config file was not
93 * there or empty (we still return the host's IP addresses). Returns
94 * -1 on fatal failure with reason in the reason argument (so the
95 * caller can choose to ignore the entire file but should write
96 * something to a log file).
98 * All addresses should be in NBO (as returned by rx_getAllAddr() and
99 * parsed by extract_Addr().
101 int parseNetRestrictFile(outAddrs, mask, mtu, maxAddrs, nAddrs, reason, fileName)
102 afs_uint32 outAddrs[]; /* output address array */
103 afs_uint32 *mask, *mtu; /* optional mask and mtu */
104 afs_uint32 maxAddrs; /* max number of addresses */
105 afs_uint32 *nAddrs; /* number of Addresses in output array */
106 char reason[]; /* reason for failure */
107 const char *fileName; /* filename to parse */
110 char line[MAX_NETFILE_LINE];
111 int lineNo, usedfile;
112 afs_uint32 i, neaddrs, nfaddrs, nOutaddrs;
113 afs_uint32 addr, eAddrs[MAXIPADDRS], eMask[MAXIPADDRS], eMtu[MAXIPADDRS];
119 if (mask) assert(mtu);
123 for (i=0; i<maxAddrs; i++) outAddrs[i] = 0;
126 /* get all network interfaces from the kernel */
127 neaddrs = rxi_getAllAddrMaskMtu(eAddrs, eMask, eMtu, MAXIPADDRS);
129 sprintf(reason,"No existing IP interfaces found");
133 if ( (fp = fopen(fileName, "r")) == 0 ) {
134 sprintf(reason, "Could not open file %s for reading:%s",
135 fileName, strerror(errno));
139 /* For each line in the NetRestrict file */
142 while (fgets(line, MAX_NETFILE_LINE, fp) != NULL) {
143 lineNo++; /* input line number */
144 addr = extract_Addr(line, strlen(line));
145 if (addr == AFS_IPINVALID) { /* syntactically invalid */
146 fprintf(stderr,"%s : line %d : parse error - invalid IP\n", fileName, lineNo);
149 if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */
150 fprintf(stderr, "%s : line %d : invalid address ... ignoring\n",fileName, lineNo);
155 /* Check if we need to exclude this address */
156 for (i=0; i<neaddrs; i++) {
157 if (eAddrs[i] && (eAddrs[i] == addr)) {
158 eAddrs[i] = 0; /* Yes - exclude it by zeroing it for now */
166 sprintf(reason,"No valid IP addresses in %s\n",fileName);
171 /* Collect the addresses we have left to return */
173 for (i=0; i<neaddrs; i++) {
174 if (!eAddrs[i]) continue;
175 outAddrs[nOutaddrs] = eAddrs[i];
177 mask[nOutaddrs] = eMask[i];
178 mtu[nOutaddrs] = eMtu[i];
180 if (++nOutaddrs >= maxAddrs) break;
182 if (nOutaddrs == 0) {
183 sprintf(reason, "No addresses to use after parsing %s",fileName);
187 return (usedfile ? 0 : 1); /* 0=>used the file. 1=>didn't use file */
193 * this function reads in stuff from InterfaceAddr file in
194 * /usr/vice/etc ( if it exists ) and verifies the addresses
196 * 'final' contains all those addresses that are found to
197 * be valid. This function returns the number of valid
198 * interface addresses. Pulled out from afsd.c
201 ParseNetInfoFile(final, mask, mtu, max, reason, fileName)
202 afs_uint32 *final, *mask, *mtu;
203 int max; /* max number of interfaces */
205 const char *fileName;
208 afs_uint32 existingAddr[MAXIPADDRS], existingMask[MAXIPADDRS], existingMtu[MAXIPADDRS];
209 char line[MAX_NETFILE_LINE];
211 int i, existNu, count = 0;
222 /* get all network interfaces from the kernel */
223 existNu = rxi_getAllAddrMaskMtu(existingAddr,existingMask,existingMtu,MAXIPADDRS);
227 if ( (fp = fopen(fileName, "r")) == 0 ) {
228 /* If file does not exist or is not readable, then
229 * use all interface addresses.
231 sprintf(reason,"Failed to open %s(%s)\nUsing all configured addresses\n",
232 fileName, strerror(errno));
233 for ( i=0; i < existNu; i++) {
234 final[i] = existingAddr[i];
235 mask[i] = existingMask[i];
236 mtu[i] = existingMtu[i];
241 /* For each line in the NetInfo file */
242 while ( fgets(line, MAX_NETFILE_LINE, fp) != NULL ) {
243 lineNo++; /* input line number */
244 addr = extract_Addr(line, MAX_NETFILE_LINE);
246 if (addr == AFS_IPINVALID) { /* syntactically invalid */
247 fprintf(stderr,"afs:%s : line %d : parse error\n", fileName, lineNo);
250 if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */
254 /* See if it is an address that really exists */
255 for (i=0; i < existNu; i++) {
256 if (existingAddr[i] == addr) break;
258 if (i >= existNu) continue; /* not found - ignore */
260 /* Check if it is a duplicate address we alread have */
261 for (l=0; l < count; l++) {
262 if ( final[l] == addr ) break;
265 fprintf(stderr,"afs:%x specified twice in NetInfo file\n", ntohl(addr));
266 continue; /* duplicate addr - ignore */
269 if ( count == max ) { /* no more space */
270 fprintf(stderr,"afs:Too many interfaces. The current kernel configuration supports a maximum of %d interfaces\n", max);
272 final[count] = existingAddr[i];
273 mask[count] = existingMask[i];
274 mtu[count] = existingMtu[i];
279 /* in case of any error, we use all the interfaces present */
281 sprintf(reason,"Error in reading/parsing Interface file\nUsing all configured interface addresses \n");
282 for ( i=0; i < existNu; i++) {
283 final[i] = existingAddr[i];
284 mask[i] = existingMask[i];
285 mtu[i] = existingMtu[i];
295 * Given two arrays of addresses, masks and mtus find the common ones
296 * and return them in the first buffer. Return number of common
299 int filterAddrs(addr1,addr2,mask1,mask2,mtu1,mtu2,n1,n2)
300 afs_uint32 addr1[],addr2[];
301 afs_uint32 mask1[], mask2[];
302 afs_uint32 mtu1[], mtu2[];
304 afs_uint32 taddr[MAXIPADDRS];
305 afs_uint32 tmask[MAXIPADDRS];
306 afs_uint32 tmtu[MAXIPADDRS];
307 int count=0,i=0,j=0,found=0;
319 if(addr1[i]==addr2[j]) {
325 taddr[count]=addr1[i];
326 tmask[count]=mask1[i];
331 /* copy everything into addr1, mask1 and mtu1 */
332 for(i=0;i<count;i++) {
339 /* and zero out the rest */
340 for(i=count;i<n1;i++) {
351 * parse both netinfo and netrerstrict files and return the final
352 * set of IP addresses to use
354 int parseNetFiles(addrbuf, maskbuf,mtubuf,max,reason, niFileName, nrFileName)
355 afs_uint32 addrbuf[];
356 afs_uint32 maskbuf[];
358 afs_uint32 max; /* Entries in addrbuf, maskbuf and mtubuf */
360 const char *niFileName;
361 const char *nrFileName;
363 afs_uint32 addrbuf1[MAXIPADDRS],maskbuf1[MAXIPADDRS], mtubuf1[MAXIPADDRS];
364 afs_uint32 addrbuf2[MAXIPADDRS],maskbuf2[MAXIPADDRS], mtubuf2[MAXIPADDRS];
366 afs_uint32 nAddrs2=0;
369 nAddrs1 = ParseNetInfoFile(addrbuf1, maskbuf1, mtubuf1, MAXIPADDRS,reason,
371 code = parseNetRestrictFile(addrbuf2,maskbuf2,mtubuf2,
372 MAXIPADDRS,&nAddrs2,reason,
374 if ((nAddrs1 < 0) && (code)) {
378 else if ((nAddrs1 > 0) && (code)) {
379 /* netinfo succeeded and netrestrict failed */
380 for(i=0;((i<nAddrs1)&&(i<max));i++) {
381 addrbuf[i]=addrbuf1[i];
383 maskbuf[i]=maskbuf1[i];
384 mtubuf[i]=mtubuf1[i];
389 else if ((!code) && (nAddrs1 < 0)) {
390 /* netrestrict succeeded and netinfo failed */
391 for (i=0;((i<nAddrs2)&&(i<max));i++) {
392 addrbuf[i]=addrbuf2[i];
394 maskbuf[i]=maskbuf2[i];
395 mtubuf[i]=mtubuf2[i];
400 else if ((!code) && (nAddrs1 >= 0)) {
402 /* take the intersection of addrbuf1 and addrbuf2 */
403 code=filterAddrs(addrbuf1,addrbuf2,maskbuf1,maskbuf2,mtubuf1,mtubuf2,
405 for(i=0;((i<code)&&(i<max));i++) {
406 addrbuf[i]=addrbuf1[i];
408 maskbuf[i]=maskbuf1[i];
409 mtubuf[i]=mtubuf1[i];