From 50e617f8b60b61e98538cb8ccb09958740defb9a Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Mon, 11 Feb 2019 23:38:58 +0100 Subject: [PATCH] ratfs: implement ipv6 support, replace v4parsecidr() with parseipandmask() --- sys/src/cmd/ratfs/ctlfiles.c | 60 ++++++++++++------------------------ sys/src/cmd/ratfs/main.c | 26 +++------------- sys/src/cmd/ratfs/misc.c | 38 +++++++++++------------ sys/src/cmd/ratfs/proto.c | 9 ++++-- sys/src/cmd/ratfs/ratfs.h | 7 +++-- 5 files changed, 54 insertions(+), 86 deletions(-) diff --git a/sys/src/cmd/ratfs/ctlfiles.c b/sys/src/cmd/ratfs/ctlfiles.c index a9f863029..f5e1a1965 100644 --- a/sys/src/cmd/ratfs/ctlfiles.c +++ b/sys/src/cmd/ratfs/ctlfiles.c @@ -1,5 +1,4 @@ #include "ratfs.h" -#include enum { ACCEPT = 0, /* verbs in control file */ @@ -40,6 +39,7 @@ getconf(void) Biobuf *bp; char *cp; Node *np, *dir, **l; + Cidraddr ip; if(debugfd >= 0) fprint(debugfd, "loading %s\n", conffile); @@ -76,8 +76,10 @@ getconf(void) break; if (strcmp(cp, "ournets") == 0){ for(cp += strlen(cp)+1; cp && *cp; cp += strlen(cp)+1){ + if(cidrparse(&ip, cp) == -1) + continue; np = newnode(dir, cp, Trustedperm, 0111, trustedqid++); - cidrparse(&np->ip, cp); + np->ip = ip; subslash(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 */ -void +int cidrparse(Cidraddr *cidr, char *cp) { - - char *p, *slash; + uchar ip[IPaddrlen]; + char buf[64], *p, *slash; int c; - ulong a, m; - uchar addr[IPv4addrlen]; - uchar mask[IPv4addrlen]; - char buf[64]; /* * find '/' or '#' character in the cidr specification @@ -250,25 +248,11 @@ cidrparse(Cidraddr *cidr, char *cp) } *p = 0; - v4parsecidr(addr, mask, buf); - a = nhgetl(addr); - m = nhgetl(mask); - /* - * 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; + if(parseipandmask(ip, cidr->mask, buf, slash) == -1) + return -1; + maskip(ip, cidr->mask, cidr->ipaddr); - /* force at least a class B */ - m |= 0xffff0000; - } - cidr->ipaddr = a; - cidr->mask = m; + return 0; } /* @@ -335,7 +319,9 @@ ipinsert(Node *np, char *cp) char *tmp; int i; Address *ap; - if(cp == 0 || *cp == 0) + Cidraddr ip; + + if(cp == 0 || *cp == 0 || cidrparse(&ip, cp) == -1) return; np = dirwalk("ip", np); @@ -351,27 +337,19 @@ ipinsert(Node *np, char *cp) } ap = &np->addrs[i]; /* new entry on end */ + ap->ip = ip; tmp = strdup(cp); if(tmp == nil) fatal("out of memory"); subslash(tmp); ap->name = atom(tmp); free(tmp); - cidrparse(&ap->ip, cp); } -int -ipcomp(void *a, void *b) +static int +ipaddrcomp(void *a, void *b) { - ulong aip, bip; - - aip = ((Address*)a)->ip.ipaddr; - bip = ((Address*)b)->ip.ipaddr; - if(aip > bip) - return 1; - if(aip < bip) - return -1; - return 0; + return ipcmp(((Address*)a)->ip.ipaddr, ((Address*)b)->ip.ipaddr); } /* @@ -389,7 +367,7 @@ ipsort(void) continue; for(np = dir->children; np; np = np->sibs){ 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; base += np->count; } diff --git a/sys/src/cmd/ratfs/main.c b/sys/src/cmd/ratfs/main.c index 7c83c892d..c0add934f 100644 --- a/sys/src/cmd/ratfs/main.c +++ b/sys/src/cmd/ratfs/main.c @@ -39,9 +39,6 @@ int trustedqid = Qtrustedfile; char *ctlfile = CTLFILE; char *conffile = CONFFILE; -#pragma varargck type "I" Cidraddr* - -static int ipconv(Fmt*); static void post(int, char*); static void setroot(void); @@ -75,7 +72,9 @@ main(int argc, char *argv[]) if(argc != 0) usage(); - fmtinstall('I', ipconv); + fmtinstall('I', eipfmt); + fmtinstall('M', eipfmt); + setroot(); getconf(); reload(); @@ -263,10 +262,10 @@ printnode(Node *np) fprint(debugfd, "\tTrusted Child: %p", np->children); break; case Trustedperm: - fprint(debugfd, "\tPerm Trustedfile: %I", &np->ip); + fprint(debugfd, "\tPerm Trustedfile: %I %M", np->ip.ipaddr, np->ip.mask); break; case Trustedtemp: - fprint(debugfd, "\tTemp Trustedfile: %I", &np->ip); + fprint(debugfd, "\tTemp Trustedfile: %I %M", np->ip.ipaddr, np->ip.mask); break; case Ctlfile: fprint(debugfd, "\tCtlfile"); @@ -301,18 +300,3 @@ printtree(Node *np) for (np = np->children; np; np = np->sibs) 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); -} diff --git a/sys/src/cmd/ratfs/misc.c b/sys/src/cmd/ratfs/misc.c index ae2b4bb94..cc717926b 100644 --- a/sys/src/cmd/ratfs/misc.c +++ b/sys/src/cmd/ratfs/misc.c @@ -1,5 +1,4 @@ #include "ratfs.h" -#include enum { Maxdoms = 10, /* max domains in a path */ @@ -9,7 +8,7 @@ enum { static int accountmatch(char*, char**, int, char*); static Node* acctwalk(char*, Node*); static int dommatch(char*, char*); -static Address* ipsearch(ulong, Address*, int); +static Address* ipsearch(uchar*, Address*, int); static Node* ipwalk(char*, Node*); static Node* trwalk(char*, Node*); static int usermatch(char*, char*); @@ -78,16 +77,17 @@ dirwalk(char *name, Node *np) static Node* trwalk(char *name, Node *np) { + uchar addr[IPaddrlen], net[IPaddrlen]; Node *p; - ulong peerip; - uchar addr[IPv4addrlen]; - v4parseip(addr, name); - peerip = nhgetl(addr); + parseip(addr, name); - for(p = np->children; p; p = p->sibs) - if((peerip&p->ip.mask) == p->ip.ipaddr) + for(p = np->children; p; p = p->sibs){ + maskip(addr, p->ip.mask, net); + if(ipcmp(net, p->ip.ipaddr) == 0) break; + } + return p; } @@ -97,17 +97,15 @@ trwalk(char *name, Node *np) static Node* ipwalk(char *name, Node *np) { + uchar addr[IPaddrlen]; Address *ap; - ulong peerip; - uchar addr[IPv4addrlen]; - v4parseip(addr, name); - peerip = nhgetl(addr); + parseip(addr, name); if(debugfd >= 0) - fprint(debugfd, "%d.%d.%d.%d - ", addr[0]&0xff, addr[1]&0xff, - addr[2]&0xff, addr[3]&0xff); - ap = ipsearch(peerip, np->addrs, np->count); + fprint(debugfd, "%I - ", addr); + + ap = ipsearch(addr, np->addrs, np->count); if(ap == 0) return 0; @@ -156,8 +154,9 @@ acctwalk(char *name, Node *np) */ static Address* -ipsearch(ulong addr, Address *base, int n) +ipsearch(uchar *addr, Address *base, int n) { + uchar net[IPaddrlen]; ulong top, bot, mid; Address *ap; @@ -165,11 +164,12 @@ ipsearch(ulong addr, Address *base, int n) top = n; for (mid = (bot+top)/2; mid < top; mid = (bot+top)/2) { 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; - if(addr < ap->ip.ipaddr) + if(ipcmp(addr, ap->ip.ipaddr) < 0) 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; else break; diff --git a/sys/src/cmd/ratfs/proto.c b/sys/src/cmd/ratfs/proto.c index 2613ab5b1..8ca76ef40 100644 --- a/sys/src/cmd/ratfs/proto.c +++ b/sys/src/cmd/ratfs/proto.c @@ -302,6 +302,7 @@ rcreate(Fcall *f) { Fid *fidp; Node *np; + Cidraddr ip; fidp = newfid(f->fid); np = fidp->node; @@ -315,12 +316,16 @@ rcreate(Fcall *f) 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->ip = ip; if(trustedqid >= Qaddrfile) /* wrap QIDs */ trustedqid = Qtrustedfile; - cidrparse(&np->ip, f->name); f->qid = np->d.qid; np->d.uid = fidp->uid; np->d.gid = np->d.uid; diff --git a/sys/src/cmd/ratfs/ratfs.h b/sys/src/cmd/ratfs/ratfs.h index ddf6f710c..48cabf3f6 100644 --- a/sys/src/cmd/ratfs/ratfs.h +++ b/sys/src/cmd/ratfs/ratfs.h @@ -3,6 +3,7 @@ #include #include #include +#include enum { MAXRPC = 8192, @@ -54,8 +55,8 @@ struct Fid struct Cidraddr { - ulong ipaddr; /* CIDR base addr */ - ulong mask; /* CIDR mask */ + uchar ipaddr[IPaddrlen]; /* CIDR base addr */ + uchar mask[IPaddrlen]; /* CIDR mask */ }; /* an address is either an account name (domain!user) or Ip address */ @@ -98,7 +99,7 @@ long lastctltime; int trustedqid; char* atom(char*); -void cidrparse(Cidraddr*, char*); +int cidrparse(Cidraddr*, char*); void cleantrusted(void); Node* dirwalk(char*, Node*); int dread(Fid*, int);