client machine to verify that the Cache Manager is still accessible.
The F<NetInfo> file is in ASCII format. One of the machine's IP addresses
-appears on each line, in dotted decimal format. The File Server initially
-uses the address that appears first in the list. The order of the
-remaining addresses is not significant: if an RPC to the first interface
-fails, the File Server simultaneously sends RPCs to all of the other
+appears on each line, in dotted decimal format. To match a network instead
+of an individual address, use a slash (C</>) followed a subnet length. The
+File Server initially uses the address that matches first in the list. The
+order of the remaining addresses is not significant: if an RPC to the first
+interface fails, the File Server simultaneously sends RPCs to all of the other
interfaces in the list. Whichever interface replies first is the one to
which the File Server then sends pings and RPCs to break callbacks.
machines in the cell.
The F<NetInfo> file is in ASCII format. One of the machine's IP addresses
-appears on each line, in dotted decimal format. The order of the addresses
-is not significant.
+appears on each line, in dotted decimal format. To match a network
+instead of an individual address, use a slash (C</>) followed a subnet
+length. The order of the addresses is not significant.
Optionally, the File Server can be forced to use an IP address that does
not belong to one of the server interfaces. To do this, add a line to the
=head2 FORMAT
The F<NetRestrict> file is in ASCII format. One IP address appears on each
-line, in dotted decimal format. The order of the addresses is not
-significant. There is currently no mechanism to specify a range of
-addresses or a wildcard; each IP address must be listed individually.
+line, in dotted decimal format. To specify a network instead, use a
+slash (C</>) followed by a subnet length. The order of the addresses is
+not significant.
=head2 Client NetRestrict
To display the File Server interface addresses registered in the VLDB, use
the B<vos listaddrs> command.
+=head1 EXAMPLES
+
+If the File Server should not use the IP address 192.168.1.1 on one of
+its private interfaces, then the F<NetRestrict> file should contain
+the following:
+
+ 196.168.1.1
+
+In order to prevent the usage of any 192.168/16 addresses on its local
+interfaces, the F<NetRestrict> file should contain:
+
+ 196.168.0.0/16
+
=head1 SEE ALSO
L<NetInfo(5)>,
<listitem>
<para>Using a text editor, open the <emphasis role="bold">/usr/afs/local/NetRestrict</emphasis> file. Place one IP address
- in dotted decimal format on each line. The order of the addresses is not significant. Use the value <emphasis
- role="bold">255</emphasis> as a wildcard that represents all possible addresses in that field. For example, the entry
- <computeroutput>192.12.105.255</computeroutput> indicates that the Cache Manager does not register any of the addresses in
+ in dotted decimal format on each line. The order of the addresses is not significant. Use a slash (<emphasis
+ role="bold">/</emphasis>) followed by a subnet length to represent all possible addresses in a range. For example, the entry
+ <computeroutput>192.12.105.0/24</computeroutput> indicates that the Cache Manager does not register any of the addresses in
the 192.12.105 subnet.</para>
</listitem>
<listitem>
<para>Using a text editor, open the <emphasis role="bold">/usr/vice/etc/NetRestrict</emphasis> file. Place one IP address
- in dotted decimal format on each line. The order of the addresses is not significant. Use the value <emphasis
- role="bold">255</emphasis> as a wildcard that represents all possible addresses in that field. For example, the entry
- <computeroutput>192.12.105.255</computeroutput> indicates that the Cache Manager does not register any of the addresses in
+ in dotted decimal format on each line. The order of the addresses is not significant. Use a slash (<emphasis
+ role="bold">/</emphasis>) followed by a subnet length to represent all possible addresses in a range. For example, the entry
+ <computeroutput>192.12.105.0/24</computeroutput> indicates that the Cache Manager does not register any of the addresses in
the 192.12.105 subnet.</para>
</listitem>
#include "cellconfig.h"
-#define AFS_IPINVALID 0xffffffff /* invalid IP address */
-#define AFS_IPINVALIDIGNORE 0xfffffffe /* no input given to extractAddr */
-#define MAX_NETFILE_LINE 2048 /* length of a line in the netrestrict file */
+#define AFS_IPINVALID -1 /* invalid IP address */
+#define AFS_IPINVALIDIGNORE -2 /* no input given to extractAddr */
+#define MAX_NETFILE_LINE 2048 /* length of a line in the NetRestrict file */
#define MAXIPADDRS 1024 /* from afsd.c */
static int ParseNetInfoFile_int(afs_uint32 *, afs_uint32 *, afs_uint32 *,
int, char reason[], const char *,
int);
-/*
+
+/**
* The line parameter is a pointer to a buffer containing a string of
- * bytes of the form
-** w.x.y.z # machineName
- * returns the network interface IP Address in NBO
+ * bytes of the form:
+ *
+ * w.x.y.z[/n] # machineName
+ *
+ * Returns an IPv4 address and mask in network byte order. Optionally,
+ * a '/' may be used to specify a subnet mask length.
+ *
+ * @param[in] line
+ * Pointer to a string of bytes
+ * @param[out] maxSize
+ * Length to search in line for addresses
+ * @param[out] addr
+ * IPv4 address in network byte order
+ * @param[out] mask
+ * IPv4 subnet mask in network byte order, default to 0xffffffff
+ *
+ * @return
+ * @retval 0 success
+ * @retval AFS_IPINVALID the address is invalid or parsing failed
+ * @retval AFS_IPINVALIDIGNORE blank line that can be ignored
*/
-afs_uint32
-extract_Addr(char *line, int maxSize)
+static int
+extract_Addr(char *line, int maxSize, afs_uint32 *addr, afs_uint32 *mask)
{
char bytes[4][32];
int i = 0, n = 0;
char *endPtr;
afs_uint32 val[4];
- afs_uint32 retval = 0;
+ int subnet_len = 32;
/* skip empty spaces */
while (isspace(*line) && maxSize) {
if (!maxSize || !*line)
return AFS_IPINVALIDIGNORE;
+ /* init to 0.0.0.0 for strtol() */
+ for (n = 0; n < 4; n++) {
+ bytes[n][0] = '0';
+ bytes[n][1] = '\0';
+ }
+
for (n = 0; n < 4; n++) {
- while ((*line != '.') && !isspace(*line) && maxSize) { /* extract nth byte */
+ while ((*line != '.') && !isspace(*line)
+ && (*line != '/') && maxSize) { /* extract nth byte */
if (!isdigit(*line))
return AFS_IPINVALID;
if (i > 31)
} /* while */
if (!maxSize)
return AFS_IPINVALID;
- bytes[n][i] = 0;
- i = 0, line++;
+ bytes[n][i] = '\0';
+ if (*line == '/')
+ break;
+ i = 0;
+ line++;
+ }
+
+ if (*line == '.')
+ ++line; /* single trailing . allowed */
+
+ if (*line == '/') { /* have a subnet length */
+ line++;
+ subnet_len = 0;
+ while (isdigit(*line)) {
+ subnet_len = subnet_len * 10 + (*line - '0');
+ if (subnet_len > 32)
+ return AFS_IPINVALID; /* subnet length too long */
+ ++line;
+ }
+ if (subnet_len == 0)
+ return AFS_IPINVALID; /* subnet length too short */
+ }
+
+ if (!isspace(*line) && (*line != '\0'))
+ return AFS_IPINVALID; /* improperly formed comment */
+
+ for (n = 0; n < 4; n++) {
errno = 0;
val[n] = strtol(bytes[n], &endPtr, 10);
- if ((val[n] == 0) && (errno != 0 || bytes[n] == endPtr)) /* no conversion */
+ if ((val[n] == 0) && (errno != 0 || bytes[n] == endPtr)) /* no conversion */
return AFS_IPINVALID;
- } /* for */
+ }
+
+ *mask = 0;
+ while (subnet_len--) {
+ *mask = (*mask >> 1) | 0x80000000;
+ }
- retval = (val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3];
- return htonl(retval);
+ *mask = htonl(*mask);
+ *addr = htonl((val[0] << 24) | (val[1] << 16) | (val[2] << 8) | val[3]);
+ return 0;
}
/**
char line[MAX_NETFILE_LINE];
int lineNo, usedfile = 0;
afs_uint32 i, neaddrs, nOutaddrs;
- afs_uint32 addr, eAddrs[MAXIPADDRS], eMask[MAXIPADDRS], eMtu[MAXIPADDRS];
+ afs_uint32 addr, mask, eAddrs[MAXIPADDRS], eMask[MAXIPADDRS], eMtu[MAXIPADDRS];
+ int retval;
opr_Assert(outAddrs);
opr_Assert(reason);
usedfile = 0;
while (fgets(line, MAX_NETFILE_LINE, fp) != NULL) {
lineNo++; /* input line number */
- addr = extract_Addr(line, strlen(line));
- if (addr == AFS_IPINVALID) { /* syntactically invalid */
+ retval = extract_Addr(line, strlen(line), &addr, &mask);
+ if (retval == AFS_IPINVALID) { /* syntactically invalid */
fprintf(stderr, "%s : line %d : parse error - invalid IP\n",
fileName, lineNo);
continue;
}
- if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */
+ if (retval == AFS_IPINVALIDIGNORE) { /* ignore error */
fprintf(stderr, "%s : line %d : invalid address ... ignoring\n",
fileName, lineNo);
continue;
/* Check if we need to exclude this address */
for (i = 0; i < neaddrs; i++) {
- if (eAddrs[i] && (eAddrs[i] == addr)) {
+ if (eAddrs[i] && ((eAddrs[i] & mask) == (addr & mask))) {
eAddrs[i] = 0; /* Yes - exclude it by zeroing it for now */
}
}
char line[MAX_NETFILE_LINE];
FILE *fp;
int i, existNu, count = 0;
- afs_uint32 addr;
+ afs_uint32 addr, mask;
int lineNo = 0;
int l;
+ int retval;
opr_Assert(fileName);
opr_Assert(outAddrs);
}
lineNo++; /* input line number */
- addr = extract_Addr(&line[fake], strlen(&line[fake]));
+ retval = extract_Addr(&line[fake], strlen(&line[fake]), &addr, &mask);
- if (addr == AFS_IPINVALID) { /* syntactically invalid */
+ if (retval == AFS_IPINVALID) { /* syntactically invalid */
fprintf(stderr, "afs:%s : line %d : parse error\n", fileName,
lineNo);
continue;
}
- if (addr == AFS_IPINVALIDIGNORE) { /* ignore error */
+ if (fake && ntohl(mask) != 0xffffffff) {
+ fprintf(stderr, "afs:%s : line %d : bad fake address\n", fileName,
+ lineNo);
+ continue;
+ }
+ if (retval == AFS_IPINVALIDIGNORE) { /* ignore error */
continue;
}
/* See if it is an address that really exists */
for (i = 0; i < existNu; i++) {
- if (existingAddr[i] == addr)
+ if ((existingAddr[i] & mask) == (addr & mask))
break;
}
if ((i >= existNu) && (!fake))
/* Check if it is a duplicate address we alread have */
for (l = 0; l < count; l++) {
- if (outAddrs[l] == addr)
+ if ((outAddrs[l] & mask) == (addr & mask))
break;
}
if (l < count) {
- fprintf(stderr, "afs:%x specified twice in NetInfo file\n",
- ntohl(addr));
+ fprintf(stderr, "afs:%x matched more than once in NetInfo file\n",
+ ntohl(outAddrs[l]));
continue; /* duplicate addr - ignore */
}
$(TOP_OBJDIR)/src/opr/liboafs_opr.la
LT_libs = $(LDFLAGS_roken) $(LIB_roken)
-tests all: testcellconf ktctest
+tests all: testcellconf ktctest testnetrestrict
testcellconf: testcellconf.lo
$(LT_LDRULE_static) testcellconf.lo $(LT_deps) $(LT_libs)
ktctest: ktctest.lo
$(LT_LDRULE_static) ktctest.lo $(LT_deps) $(LT_libs)
+testnetrestrict: testnetrestrict.o
+ $(AFS_LDRULE) testnetrestrict.o $(TOP_LIBDIR)/libauth.a $(TOP_LIBDIR)/libopr.a
+
clean:
$(LT_CLEAN)
$(RM) -f copyauth testcellconf ktctest setkey auth.h cellconfig.h acfg_errors.c ktc_errors.c core
--- /dev/null
+/*
+ * testnetstrict.c
+ *
+ * Utility to test NetInfo and NetRestrict parsing
+ */
+
+#include <afsconfig.h>
+#include <afs/param.h>
+#include <afs/cellconfig.h>
+
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+#include <arpa/inet.h>
+
+char *interfaceList, *filenameNetInfo, *filenameNetRestrict;
+
+int
+rx_getAllAddrMaskMtu(afs_uint32 addrBuffer[],
+ afs_uint32 maskBuffer[],
+ afs_uint32 mtuBuffer[],
+ int maxSize)
+{
+ FILE *fp;
+ int nInterfaces = 0, lineNo = 1;
+ int a[4], m[4], mtu;
+ char line[80];
+
+ fp = fopen(interfaceList, "r");
+ if (fp == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+
+ while (nInterfaces < maxSize) {
+ ++lineNo;
+ if (fgets(line, 80, fp) == NULL)
+ break;
+ if (sscanf(line, "%d.%d.%d.%d %d.%d.%d.%d %d\n",
+ &a[0], &a[1], &a[2], &a[3],
+ &m[0], &m[1], &m[2], &m[3], &mtu) == 9) {
+
+ addrBuffer[nInterfaces] = htonl(a[0] << 24 | a[1] << 16
+ | a[2] << 8 | a[3]);
+ maskBuffer[nInterfaces] = htonl(m[0] << 24 | m[1] << 16
+ | m[2] << 8 | m[3]);
+ mtuBuffer[nInterfaces] = htonl(mtu);
+ ++nInterfaces;
+ } else {
+ fprintf(stderr, "failed to parse line %d in %s\n", lineNo, interfaceList);
+ }
+ }
+ fclose(fp);
+
+ return nInterfaces;
+}
+
+#define MAXADDRS 16
+
+int
+main(int argc, char *argv[])
+{
+ afs_uint32 outAddrs[MAXADDRS], outMask[MAXADDRS], outMtu[MAXADDRS], nAddrs;
+ char reason[1024];
+ int i, retval;
+
+ if (argc < 4) {
+ fprintf(stderr, "usage: testnetrestrict <interface list> <netinfo> <netstrict>\n");
+ exit(1);
+ }
+
+ interfaceList = argv[1];
+ filenameNetInfo = argv[2];
+ filenameNetRestrict = argv[3];
+
+ reason[0] = '\0';
+ retval = afsconf_ParseNetInfoFile(outAddrs, outMask, outMtu, MAXADDRS,
+ reason, filenameNetInfo);
+
+ printf("afsconf_ParseNetInfoFile() returned %d\n", retval);
+ if (reason[0] != '\0')
+ printf("reason: %s\n", reason);
+
+ printf("final address list:\n");
+ if (retval > 0) {
+ for(i = 0; i < retval; ++i) {
+ printf("\taddress 0x%x mask 0x%x mtu %d\n",
+ ntohl(outAddrs[i]), ntohl(outMask[i]), ntohl(outMtu[i]));
+ }
+ }
+
+ reason[0] = '\0';
+ retval = afsconf_ParseNetRestrictFile(outAddrs, outMask, outMtu, MAXADDRS,
+ &nAddrs, reason, filenameNetRestrict);
+
+ printf("\nafsconf_ParseNetRestrictFile() returned %d\n", retval);
+ if (reason[0] != '\0')
+ printf("reason: %s\n", reason);
+ if (nAddrs > 0) {
+ printf("final address list:\n");
+ for(i = 0; i < nAddrs; ++i) {
+ printf("\taddress 0x%x mask 0x%x mtu %d\n",
+ ntohl(outAddrs[i]), ntohl(outMask[i]), ntohl(outMtu[i]));
+ }
+ }
+
+ reason[0] = '\0';
+ retval = afsconf_ParseNetFiles(outAddrs, outMask, outMtu, MAXADDRS,
+ reason, filenameNetInfo, filenameNetRestrict);
+
+ printf("\nafsconf_ParseNetFiles() returned %d\n", retval);
+ if (reason[0] != '\0')
+ printf("reason: %s\n", reason);
+ if (retval > 0) {
+ printf("final address list:\n");
+ for(i = 0; i < retval; ++i) {
+ printf("\taddress 0x%x mask 0x%x mtu %d\n",
+ ntohl(outAddrs[i]), ntohl(outMask[i]), ntohl(outMtu[i]));
+ }
+ }
+
+ exit(0);
+}