ratfs: implement ipv6 support, replace v4parsecidr() with parseipandmask()

This commit is contained in:
cinap_lenrek 2019-02-11 23:38:58 +01:00
parent 168dabc142
commit 50e617f8b6
5 changed files with 54 additions and 86 deletions

View file

@ -1,5 +1,4 @@
#include "ratfs.h" #include "ratfs.h"
#include <ip.h>
enum { enum {
ACCEPT = 0, /* verbs in control file */ ACCEPT = 0, /* verbs in control file */
@ -40,6 +39,7 @@ getconf(void)
Biobuf *bp; Biobuf *bp;
char *cp; char *cp;
Node *np, *dir, **l; Node *np, *dir, **l;
Cidraddr ip;
if(debugfd >= 0) if(debugfd >= 0)
fprint(debugfd, "loading %s\n", conffile); fprint(debugfd, "loading %s\n", conffile);
@ -76,8 +76,10 @@ getconf(void)
break; break;
if (strcmp(cp, "ournets") == 0){ if (strcmp(cp, "ournets") == 0){
for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){ for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){
if(cidrparse(&ip, cp) == -1)
continue;
np = newnode(dir, cp, Trustedperm, 0111, trustedqid++); np = newnode(dir, cp, Trustedperm, 0111, trustedqid++);
cidrparse(&np->ip, cp); np->ip = ip;
subslash(cp); subslash(cp);
np->d.name = atom(cp); np->d.name = atom(cp);
} }
@ -218,16 +220,12 @@ findkey(char *val, Keyword *p)
/* /*
* parse a cidr specification in either IP/mask or IP#mask format * parse a cidr specification in either IP/mask or IP#mask format
*/ */
void int
cidrparse(Cidraddr *cidr, char *cp) cidrparse(Cidraddr *cidr, char *cp)
{ {
uchar ip[IPaddrlen];
char *p, *slash; char buf[64], *p, *slash;
int c; int c;
ulong a, m;
uchar addr[IPv4addrlen];
uchar mask[IPv4addrlen];
char buf[64];
/* /*
* find '/' or '#' character in the cidr specification * find '/' or '#' character in the cidr specification
@ -250,25 +248,11 @@ cidrparse(Cidraddr *cidr, char *cp)
} }
*p = 0; *p = 0;
v4parsecidr(addr, mask, buf); if(parseipandmask(ip, cidr->mask, buf, slash) == -1)
a = nhgetl(addr); return -1;
m = nhgetl(mask); maskip(ip, cidr->mask, cidr->ipaddr);
/*
* if a mask isn't specified, we build a minimal mask
* instead of using the default mask for that net. in this
* case we never allow a class A mask (0xff000000).
*/
if(slash == 0){
m = 0xff000000;
p = buf;
for(p = strchr(p, '.'); p && p[1]; p = strchr(p+1, '.'))
m = (m>>8)|0xff000000;
/* force at least a class B */ return 0;
m |= 0xffff0000;
}
cidr->ipaddr = a;
cidr->mask = m;
} }
/* /*
@ -335,7 +319,9 @@ ipinsert(Node *np, char *cp)
char *tmp; char *tmp;
int i; int i;
Address *ap; Address *ap;
if(cp == 0 || *cp == 0) Cidraddr ip;
if(cp == 0 || *cp == 0 || cidrparse(&ip, cp) == -1)
return; return;
np = dirwalk("ip", np); np = dirwalk("ip", np);
@ -351,27 +337,19 @@ ipinsert(Node *np, char *cp)
} }
ap = &np->addrs[i]; /* new entry on end */ ap = &np->addrs[i]; /* new entry on end */
ap->ip = ip;
tmp = strdup(cp); tmp = strdup(cp);
if(tmp == nil) if(tmp == nil)
fatal("out of memory"); fatal("out of memory");
subslash(tmp); subslash(tmp);
ap->name = atom(tmp); ap->name = atom(tmp);
free(tmp); free(tmp);
cidrparse(&ap->ip, cp);
} }
int static int
ipcomp(void *a, void *b) ipaddrcomp(void *a, void *b)
{ {
ulong aip, bip; return ipcmp(((Address*)a)->ip.ipaddr, ((Address*)b)->ip.ipaddr);
aip = ((Address*)a)->ip.ipaddr;
bip = ((Address*)b)->ip.ipaddr;
if(aip > bip)
return 1;
if(aip < bip)
return -1;
return 0;
} }
/* /*
@ -389,7 +367,7 @@ ipsort(void)
continue; continue;
for(np = dir->children; np; np = np->sibs){ for(np = dir->children; np; np = np->sibs){
if(np->d.type == IPaddr && np->count && np->addrs) if(np->d.type == IPaddr && np->count && np->addrs)
qsort(np->addrs, np->count, sizeof(Address), ipcomp); qsort(np->addrs, np->count, sizeof(Address), ipaddrcomp);
np->baseqid = base; np->baseqid = base;
base += np->count; base += np->count;
} }

View file

@ -39,9 +39,6 @@ int trustedqid = Qtrustedfile;
char *ctlfile = CTLFILE; char *ctlfile = CTLFILE;
char *conffile = CONFFILE; char *conffile = CONFFILE;
#pragma varargck type "I" Cidraddr*
static int ipconv(Fmt*);
static void post(int, char*); static void post(int, char*);
static void setroot(void); static void setroot(void);
@ -75,7 +72,9 @@ main(int argc, char *argv[])
if(argc != 0) if(argc != 0)
usage(); usage();
fmtinstall('I', ipconv); fmtinstall('I', eipfmt);
fmtinstall('M', eipfmt);
setroot(); setroot();
getconf(); getconf();
reload(); reload();
@ -263,10 +262,10 @@ printnode(Node *np)
fprint(debugfd, "\tTrusted Child: %p", np->children); fprint(debugfd, "\tTrusted Child: %p", np->children);
break; break;
case Trustedperm: case Trustedperm:
fprint(debugfd, "\tPerm Trustedfile: %I", &np->ip); fprint(debugfd, "\tPerm Trustedfile: %I %M", np->ip.ipaddr, np->ip.mask);
break; break;
case Trustedtemp: case Trustedtemp:
fprint(debugfd, "\tTemp Trustedfile: %I", &np->ip); fprint(debugfd, "\tTemp Trustedfile: %I %M", np->ip.ipaddr, np->ip.mask);
break; break;
case Ctlfile: case Ctlfile:
fprint(debugfd, "\tCtlfile"); fprint(debugfd, "\tCtlfile");
@ -301,18 +300,3 @@ printtree(Node *np)
for (np = np->children; np; np = np->sibs) for (np = np->children; np; np = np->sibs)
printtree(np); printtree(np);
} }
static int
ipconv(Fmt *f)
{
Cidraddr *ip;
int i, j;
char *p;
ip = va_arg(f->args, Cidraddr*);
p = (char*)&ip->ipaddr;
i = 0;
for (j = ip->mask; j; j <<= 1)
i++;
return fmtprint(f, "%d.%d.%d.%d/%d", p[3]&0xff, p[2]&0xff, p[1]&0xff, p[0]&0xff, i);
}

View file

@ -1,5 +1,4 @@
#include "ratfs.h" #include "ratfs.h"
#include <ip.h>
enum { enum {
Maxdoms = 10, /* max domains in a path */ Maxdoms = 10, /* max domains in a path */
@ -9,7 +8,7 @@ enum {
static int accountmatch(char*, char**, int, char*); static int accountmatch(char*, char**, int, char*);
static Node* acctwalk(char*, Node*); static Node* acctwalk(char*, Node*);
static int dommatch(char*, char*); static int dommatch(char*, char*);
static Address* ipsearch(ulong, Address*, int); static Address* ipsearch(uchar*, Address*, int);
static Node* ipwalk(char*, Node*); static Node* ipwalk(char*, Node*);
static Node* trwalk(char*, Node*); static Node* trwalk(char*, Node*);
static int usermatch(char*, char*); static int usermatch(char*, char*);
@ -78,16 +77,17 @@ dirwalk(char *name, Node *np)
static Node* static Node*
trwalk(char *name, Node *np) trwalk(char *name, Node *np)
{ {
uchar addr[IPaddrlen], net[IPaddrlen];
Node *p; Node *p;
ulong peerip;
uchar addr[IPv4addrlen];
v4parseip(addr, name); parseip(addr, name);
peerip = nhgetl(addr);
for(p = np->children; p; p = p->sibs) for(p = np->children; p; p = p->sibs){
if((peerip&p->ip.mask) == p->ip.ipaddr) maskip(addr, p->ip.mask, net);
if(ipcmp(net, p->ip.ipaddr) == 0)
break; break;
}
return p; return p;
} }
@ -97,17 +97,15 @@ trwalk(char *name, Node *np)
static Node* static Node*
ipwalk(char *name, Node *np) ipwalk(char *name, Node *np)
{ {
uchar addr[IPaddrlen];
Address *ap; Address *ap;
ulong peerip;
uchar addr[IPv4addrlen];
v4parseip(addr, name); parseip(addr, name);
peerip = nhgetl(addr);
if(debugfd >= 0) if(debugfd >= 0)
fprint(debugfd, "%d.%d.%d.%d - ", addr[0]&0xff, addr[1]&0xff, fprint(debugfd, "%I - ", addr);
addr[2]&0xff, addr[3]&0xff);
ap = ipsearch(peerip, np->addrs, np->count); ap = ipsearch(addr, np->addrs, np->count);
if(ap == 0) if(ap == 0)
return 0; return 0;
@ -156,8 +154,9 @@ acctwalk(char *name, Node *np)
*/ */
static Address* static Address*
ipsearch(ulong addr, Address *base, int n) ipsearch(uchar *addr, Address *base, int n)
{ {
uchar net[IPaddrlen];
ulong top, bot, mid; ulong top, bot, mid;
Address *ap; Address *ap;
@ -165,11 +164,12 @@ ipsearch(ulong addr, Address *base, int n)
top = n; top = n;
for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) {
ap = &base[mid]; ap = &base[mid];
if((addr&ap->ip.mask) == ap->ip.ipaddr) maskip(addr, ap->ip.mask, net);
if(ipcmp(net, ap->ip.ipaddr) == 0)
return ap; return ap;
if(addr < ap->ip.ipaddr) if(ipcmp(addr, ap->ip.ipaddr) < 0)
top = mid; top = mid;
else if(mid != n-1 && addr >= base[mid+1].ip.ipaddr) else if(mid != n-1 && ipcmp(addr, base[mid+1].ip.ipaddr) >= 0)
bot = mid; bot = mid;
else else
break; break;

View file

@ -302,6 +302,7 @@ rcreate(Fcall *f)
{ {
Fid *fidp; Fid *fidp;
Node *np; Node *np;
Cidraddr ip;
fidp = newfid(f->fid); fidp = newfid(f->fid);
np = fidp->node; np = fidp->node;
@ -315,12 +316,16 @@ rcreate(Fcall *f)
return; return;
} }
/* Ignore the supplied mode and force it to be non-writable */ if(cidrparse(&ip, f->name) == -1){
reply(f, "bad cidr in filename");
return;
}
/* Ignore the supplied mode and force it to be non-writable */
np = newnode(np, f->name, Trustedtemp, 0444, trustedqid++); np = newnode(np, f->name, Trustedtemp, 0444, trustedqid++);
np->ip = ip;
if(trustedqid >= Qaddrfile) /* wrap QIDs */ if(trustedqid >= Qaddrfile) /* wrap QIDs */
trustedqid = Qtrustedfile; trustedqid = Qtrustedfile;
cidrparse(&np->ip, f->name);
f->qid = np->d.qid; f->qid = np->d.qid;
np->d.uid = fidp->uid; np->d.uid = fidp->uid;
np->d.gid = np->d.uid; np->d.gid = np->d.uid;

View file

@ -3,6 +3,7 @@
#include <auth.h> #include <auth.h>
#include <fcall.h> #include <fcall.h>
#include <bio.h> #include <bio.h>
#include <ip.h>
enum { enum {
MAXRPC = 8192, MAXRPC = 8192,
@ -54,8 +55,8 @@ struct Fid
struct Cidraddr struct Cidraddr
{ {
ulong ipaddr; /* CIDR base addr */ uchar ipaddr[IPaddrlen]; /* CIDR base addr */
ulong mask; /* CIDR mask */ uchar mask[IPaddrlen]; /* CIDR mask */
}; };
/* an address is either an account name (domain!user) or Ip address */ /* an address is either an account name (domain!user) or Ip address */
@ -98,7 +99,7 @@ long lastctltime;
int trustedqid; int trustedqid;
char* atom(char*); char* atom(char*);
void cidrparse(Cidraddr*, char*); int cidrparse(Cidraddr*, char*);
void cleantrusted(void); void cleantrusted(void);
Node* dirwalk(char*, Node*); Node* dirwalk(char*, Node*);
int dread(Fid*, int); int dread(Fid*, int);