Patch proposal: usage of netmasks in naslist config file
Maurice Makaay <[email protected]> Thu, 20 Nov 2003 17:04:21 +0100
| Newsgroups | gmane.comp.gnu.radius.bugs |
|---|---|
| Organization | InterNLnet BV |
| Message-ID | <[email protected]> |
Hi,
The naslist file can contain a "DEFAULT" entry, which will catch all
non matching NASes. This is quite handy, but we could use a bit more
control over grouping NASes. Our radius servers get requests from
a lot of different NASes, from different infrastructures. To keep the
radacct directory a bit clean, we use the nickname in the naslist to
structurize this directory (so radius requests from multiple NASses will
be logged in the same directory). However, there are so many NASes, that the
naslist file grows very large. Moreover, new NASses appear once in a while,
which means that we regularly have to add these to the naslist.
Using the attached patch, the naslist can contain not only IP-addresses but
also netmasks in CIDR notation (e.g. /32 or /24). This solves our problems.
The naslist is now very short and new NASses almost always appear in an
already defined subnet. An example naslist could be:
127.0.0.1 local true
192.168.0.0/24 private-1 true
192.168.1.0/24 private-2 true
192.168.2.5 private-2 true
172.16.0.0/24 private-3 true
172.16.10.0/24 private-3 true
It would be great if this patch could be added to gnu-radius.
Regards,
-- Maurice Makaay
P.S. The patch I sent earlier this day for SEGFAULTING on having no
nastype in a naslist entry is also included in this patch.
_______________________________________________
Bug-gnu-radius mailing list
[email protected]
http://mail.gnu.org/mailman/listinfo/bug-gnu-radius
CVS-patch-naslist-netmask
(text/plain, 3.7 KB)
Index: include/radius.h
===================================================================
RCS file: /cvsroot/radius/radius/include/radius.h,v
retrieving revision 1.67
diff -u -r1.67 radius.h
--- include/radius.h 8 Nov 2003 09:48:09 -0000 1.67
+++ include/radius.h 20 Nov 2003 15:25:46 -0000
@@ -250,6 +250,7 @@
typedef struct nas {
struct nas *next;
UINT4 ipaddr;
+ UINT4 netmask;
char longname[MAX_LONGNAME+1];
char shortname[MAX_SHORTNAME+1];
char nastype[MAX_DICTNAME+1];
@@ -377,6 +378,8 @@
int good_ipaddr(char *);
char *ip_iptostr(UINT4, char *);
UINT4 ip_strtoip(char *);
+int good_netmask(char *);
+UINT4 ip_bitstomask(int);
/* nas.c */
NAS *nas_next(NAS *p);
Index: lib/nas.c
===================================================================
RCS file: /cvsroot/radius/radius/lib/nas.c,v
retrieving revision 1.9
diff -u -r1.9 nas.c
--- lib/nas.c 8 Nov 2003 09:48:09 -0000 1.9
+++ lib/nas.c 20 Nov 2003 15:12:27 -0000
@@ -22,6 +22,7 @@
#endif
#include <radius.h>
#include <checkrad.h>
+#include <errno.h>
static NAS *naslist; /* raddb/naslist */
@@ -62,7 +63,7 @@
bzero(&nas, sizeof(nas));
STRING_COPY(nas.shortname, fv[1]);
- if (fv[2][0] == 0)
+ if (fv[2] == NULL || fv[2][0] == 0)
STRING_COPY(nas.nastype, "true");
else
STRING_COPY(nas.nastype, fv[2]);
@@ -70,8 +71,26 @@
nas.ipaddr = 0;
STRING_COPY(nas.longname, fv[0]);
} else {
- nas.ipaddr = ip_gethostaddr(fv[0]);
+ char *pipaddr, *pnetmask;
+ UINT4 netmask;
+
+ pipaddr = fv[0];
+ pnetmask = strchr(pipaddr, '/');
+ if (pnetmask) {
+ *pnetmask++ = '\0';
+ netmask = good_netmask(pnetmask);
+ if (netmask < 0) {
+ radlog_loc(L_ERR, loc,
+ _("Ignoring illegal netmask: %s"),
+ pnetmask);
+ netmask = 32;
+ }
+ } else {
+ netmask = 32;
+ }
+ nas.ipaddr = ip_gethostaddr(pipaddr);
ip_gethostname(nas.ipaddr, nas.longname, sizeof(nas.longname));
+ nas.netmask = ip_bitstomask(netmask);
}
if (fc >= 4)
nas.args = envar_parse_argcv(fc-3, &fv[3]);
@@ -130,6 +149,8 @@
defnas = nas;
else if (nas->ipaddr == ipaddr)
break;
+ else if (ip_ipinsubnet(ipaddr, nas->ipaddr, nas->netmask))
+ break;
}
return nas ? nas : defnas;
}
Index: lib/iputil.c
===================================================================
RCS file: /cvsroot/radius/radius/lib/iputil.c,v
retrieving revision 1.4
diff -u -r1.4 iputil.c
--- lib/iputil.c 8 Nov 2003 09:48:09 -0000 1.4
+++ lib/iputil.c 20 Nov 2003 15:12:27 -0000
@@ -178,4 +178,50 @@
#endif
+/*
+ * Check for valid netmask address in CIDR notation. Returns -1 on
+ * an invalid netmask format, * -2 on an out of range netmask and
+ * 0 on a valid netmask.
+ */
+int
+good_netmask(char *netmask)
+{
+ int bits;
+
+ if (*netmask == '/') netmask ++;
+
+ if (strlen(netmask) >= 1 &&
+ strlen(netmask) <= 2 &&
+ isdigit(netmask[0]) &&
+ (netmask[1] == '\0' || isdigit(netmask[1])) ) {
+
+ bits = atol(netmask);
+ if (bits < 0 || bits > 32) return -2;
+ } else {
+ return -1;
+ }
+
+ return bits;
+}
+
+/*
+ * Return a netmask in host long notation from
+ * one supplied in standard cidr bits notation.
+ */
+UINT4
+ip_bitstomask(int bits)
+{
+ UINT4 mask = htonl(bits == 0 ? 0 : (u_long)-1 << (32 - bits));
+ return mask;
+}
+
+/*
+ * Check if an IP address is inside a subnet range.
+ */
+int
+ip_ipinsubnet(UINT4 ipaddr, UINT4 subnetaddr, UINT4 mask)
+{
+ return ((ipaddr ^ subnetaddr) & mask) == 0 ? 1 : 0;
+}
+