]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/libndb/ndbipinfo.c
pc64: preserve reserved bits in CR0/CR4 for amd64 in mtrr setstate()
[plan9front.git] / sys / src / libndb / ndbipinfo.c
old mode 100755 (executable)
new mode 100644 (file)
index f013355..71092d4
@@ -14,7 +14,6 @@ enum
 static Ndbtuple*       filter(Ndb *db, Ndbtuple *t, Ndbtuple *f);
 static Ndbtuple*       mkfilter(int argc, char **argv);
 static int             filtercomplete(Ndbtuple *f);
-static Ndbtuple*       toipaddr(Ndb *db, Ndbtuple *t);
 static int             prefixlen(uchar *ip);
 static Ndbtuple*       subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix);
 
@@ -115,102 +114,68 @@ prefixlen(uchar *ip)
 }
 
 /*
- *  look through a containing subset
+ *  look through containing subsets
  */
 static Ndbtuple*
 subnet(Ndb *db, uchar *net, Ndbtuple *f, int prefix)
 {
        Ndbs s;
-       Ndbtuple *t, *nt, *xt;
-       char netstr[128];
+       int nprefix;
+       char netstr[64];
        uchar mask[IPaddrlen];
-       int masklen;
+       Ndbtuple *at[128+1], *nt, *xt, *t;
 
-       t = nil;
-       sprint(netstr, "%I", net);
+       memset(at, 0, sizeof(at));
+       snprint(netstr, sizeof(netstr), "%I", net);
        nt = ndbsearch(db, &s, "ip", netstr);
        while(nt != nil){
                xt = ndbfindattr(nt, nt, "ipnet");
-               if(xt){
+               if(xt != nil){
                        xt = ndbfindattr(nt, nt, "ipmask");
-                       if(xt)
-                               parseipmask(mask, xt->val);
-                       else
+                       if(xt == nil || parseipmask(mask, xt->val, isv4(net)) == -1)
                                ipmove(mask, defmask(net));
-                       masklen = prefixlen(mask);
-                       if(masklen <= prefix){
-                               t = ndbconcatenate(t, filter(db, nt, f));
+                       nprefix = prefixlen(mask);
+                       if(nprefix <= prefix && at[nprefix] == nil){
+                               /* remember containing subnet, order by prefix length */
+                               at[nprefix] = nt;
                                nt = nil;
                        }
                }
                ndbfree(nt);
                nt = ndbsnext(&s, "ip", netstr);
        }
+       /* filter subnets, longest prefix first */
+       for(t = nil; prefix >= 0; prefix--){
+               if(at[prefix] != nil)
+                       t = ndbconcatenate(t, filter(db, at[prefix], f));
+       }
        ndbsetmalloctag(t, getcallerpc(&db));
        return t;
 }
 
-/*
- *  fill in all the requested attributes for a system.
- *  if the system's entry doesn't have all required,
- *  walk through successively more inclusive networks
- *  for inherited attributes.
- */
-Ndbtuple*
-ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
+static Ndbtuple*
+netinfo(Ndb *db, Ndbtuple *t, char **alist, int n)
 {
-       Ndbtuple *t, *nt, *f;
-       Ndbs s;
-       char *ipstr;
-       uchar net[IPaddrlen], ip[IPaddrlen];
+       uchar ip[IPaddrlen], net[IPaddrlen];
        int prefix, smallestprefix, force;
-       vlong r;
+       Ndbtuple *f, *nt;
 
-       /* just in case */
-       fmtinstall('I', eipfmt);
-       fmtinstall('M', eipfmt);
+       nt = ndbfindattr(t, t, "ip");
+       if(nt == nil || parseip(ip, nt->val) == -1){
+               ndbfree(t);
+               return nil;
+       }
 
        /* get needed attributes */
        f = mkfilter(n, alist);
 
-       /*
-        *  first look for a matching entry with an ip address
-        */
-       t = nil;
-       ipstr = ndbgetvalue(db, &s, attr, val, "ip", &nt);
-       if(ipstr == nil){
-               /* none found, make one up */
-               if(strcmp(attr, "ip") != 0) {
-                       ndbfree(f);
-                       return nil;     
-               }
-               t = ndbnew("ip", val);
-               t->line = t;
-               t->entry = nil;
-               r = parseip(net, val);
-               if(r == -1)
-                       ndbfree(t);
-       } else {
-               /* found one */
-               while(nt != nil){
-                       nt = ndbreorder(nt, s.t);
-                       t = ndbconcatenate(t, nt);
-                       nt = ndbsnext(&s, attr, val);
-               }
-               r = parseip(net, ipstr);
-               free(ipstr);
-       }
-       if(r < 0){
-               ndbfree(f);
-               return nil;
-       }
-       ipmove(ip, net);
        t = filter(db, t, f);
 
        /*
         *  now go through subnets to fill in any missing attributes
         */
-       if(isv4(net)){
+       ipmove(net, ip);
+       if(isv4(ip)){
                prefix = 127;
                smallestprefix = 100;
                force = 0;
@@ -242,14 +207,58 @@ ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
         *  if there's an unfulfilled ipmask, make one up
         */
        nt = ndbfindattr(f, f, "ipmask");
-       if(nt && !(nt->ptr & Fignore)){
+       if(nt != nil && !(nt->ptr & Fignore)){
                char x[64];
 
                snprint(x, sizeof(x), "%M", defmask(ip));
-               t = ndbconcatenate(t, ndbnew("ipmask", x));
+               nt = ndbnew("ipmask", x);
+               nt->line = nt;
+               nt->entry = nil;
+               t = ndbconcatenate(t, nt);
        }
 
        ndbfree(f);
        ndbsetmalloctag(t, getcallerpc(&db));
        return t;
 }
+
+/*
+ *  fill in all the requested attributes for a system.
+ *  if the system's entry doesn't have all required,
+ *  walk through successively more inclusive networks
+ *  for inherited attributes.
+ */
+Ndbtuple*
+ndbipinfo(Ndb *db, char *attr, char *val, char **alist, int n)
+{
+       Ndbtuple *t, *nt;
+       char *ipstr;
+       Ndbs s;
+
+       /* just in case */
+       fmtinstall('I', eipfmt);
+       fmtinstall('M', eipfmt);        
+
+       /*
+        *  first look for a matching entry with an ip address
+        */
+       ipstr = ndbgetvalue(db, &s, attr, val, "ip", &nt);
+       if(ipstr == nil){
+               /* none found, make one up */
+               if(strcmp(attr, "ip") != 0)
+                       return nil;     
+               nt = ndbnew("ip", val);
+               nt->line = nt;
+               nt->entry = nil;
+               t = netinfo(db, nt, alist, n);
+       } else {
+               /* found one */
+               free(ipstr);
+               t = nil;
+               do {
+                       nt = ndbreorder(nt, s.t);
+                       t = ndbconcatenate(t, netinfo(db, nt, alist, n));
+               } while((nt = ndbsnext(&s, attr, val)) != nil);
+       }
+       return ndbdedup(t);
+}