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 #include +#include 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; +} +