]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/ndb/cs.c
ndb/dns: various changes
[plan9front.git] / sys / src / cmd / ndb / cs.c
index 10ecee536e1fc7ebee8651af8867ea3682598a26..512f1706ab5e4c9337e6b4d5a8385669ac53998b 100644 (file)
@@ -17,6 +17,7 @@ enum
        Maxfdata=               8192,
        Maxhost=                64,             /* maximum host name size */
        Maxservice=             64,             /* maximum service name size */
+       Maxactive=              200,            /* maximum number of active slave procs */
 
        Qdir=                   0,
        Qcs=                    1,
@@ -32,7 +33,8 @@ int vers;             /* incremented each clone/attach */
 
 struct Mfile
 {
-       int             busy;
+       int             busy;   /* fid in use */
+       int             ref;    /* cleanup when drops to zero */
 
        char            *user;
        Qid             qid;
@@ -72,7 +74,7 @@ struct Job
        Fcall   request;
        Fcall   reply;
 };
-Lock   joblock;
+QLock  joblock;
 Job    *joblist;
 
 Mlist  *mlist;
@@ -82,8 +84,10 @@ int  paranoia;
 int    ipv6lookups = 1;
 jmp_buf        masterjmp;      /* return through here after a slave process has been created */
 int    *isslave;       /* *isslave non-zero means this is a slave process */
+long   active;         /* number of active slaves */
 char   *dbfile;
 Ndb    *db, *netdb;
+char   *csuser;
 
 void   rversion(Job*);
 void   rflush(Job*);
@@ -119,10 +123,8 @@ void       freejob(Job*);
 void   setext(char*, int, char*);
 void   cleanmf(Mfile*);
 
-extern void    paralloc(void);
-
-Lock   dblock;         /* mutex on database operations */
-Lock   netlock;        /* mutex for netinit() */
+QLock  dblock;         /* mutex on database operations */
+QLock  netlock;        /* mutex for netinit() */
 
 char   *logfile = "cs";
 char   *paranoiafile = "cs.paranoia";
@@ -149,25 +151,27 @@ struct Network
        Network         *next;
 };
 
-enum
-{
-       Ntcp = 0,
+enum {
+       Ntcp = 1,
 };
 
 /*
  *  net doesn't apply to (r)udp, icmp(v6), or telco (for speed).
  */
 Network network[] = {
-[Ntcp] { "tcp",        iplookup,       iptrans,        0 },
-       { "udp",        iplookup,       iptrans,        1 },
-       { "icmp",       iplookup,       iptrans,        1 },
-       { "icmpv6",     iplookup,       iptrans,        1 },
-       { "rudp",       iplookup,       iptrans,        1 },
-       { "telco",      telcolookup,    telcotrans,     1 },
+       { "il",         iplookup,       iptrans,        0, 1, },
+       { "tcp",        iplookup,       iptrans,        0, 0, },
+       { "il",         iplookup,       iptrans,        0, 0, },
+       { "udp",        iplookup,       iptrans,        1, 0, },
+       { "icmp",       iplookup,       iptrans,        1, 0, },
+       { "icmpv6",     iplookup,       iptrans,        1, 0, },
+       { "rudp",       iplookup,       iptrans,        1, 0, },
+       { "ssh",        iplookup,       iptrans,        1, 0, },
+       { "telco",      telcolookup,    telcotrans,     1, 0, },
        { 0 },
 };
 
-Lock ipifclock;
+QLock ipifclock;
 Ipifc *ipifcs;
 
 char   eaddr[16];              /* ascii ethernet address */
@@ -263,6 +267,7 @@ main(int argc, char *argv[])
        netinit(0);
 
        if(!justsetname){
+               csuser = estrdup(getuser());
                mountinit(servefile, mntpt);
                io();
        }
@@ -336,6 +341,10 @@ ndbinit(void)
        if(db == nil)
                error("can't open network database");
 
+       for(netdb = db; netdb; netdb = netdb->next)
+               if(strcmp(netdb->file, netndb) == 0)
+                       return;
+
        netdb = ndbopen(netndb);
        if(netdb != nil){
                netdb->nohash = 1;
@@ -353,7 +362,7 @@ newfid(int fid)
        for(f = mlist; f; f = f->next)
                if(f->mf.busy && f->mf.fid == fid)
                        return &f->mf;
-               else if(!ff && !f->mf.busy)
+               else if(!ff && !f->mf.busy && !f->mf.ref)
                        ff = f;
        if(ff == 0){
                ff = emalloc(sizeof *f);
@@ -371,12 +380,12 @@ newjob(void)
 {
        Job *job;
 
-       job = mallocz(sizeof(Job), 1);
-       lock(&joblock);
+       job = emalloc(sizeof *job);
+       qlock(&joblock);
        job->next = joblist;
        joblist = job;
        job->request.tag = -1;
-       unlock(&joblock);
+       qunlock(&joblock);
        return job;
 }
 
@@ -385,15 +394,15 @@ freejob(Job *job)
 {
        Job **l;
 
-       lock(&joblock);
+       qlock(&joblock);
        for(l = &joblist; *l; l = &(*l)->next){
                if((*l) == job){
                        *l = job->next;
-                       free(job);
                        break;
                }
        }
-       unlock(&joblock);
+       qunlock(&joblock);
+       free(job);
 }
 
 void
@@ -401,14 +410,14 @@ flushjob(int tag)
 {
        Job *job;
 
-       lock(&joblock);
+       qlock(&joblock);
        for(job = joblist; job; job = job->next){
                if(job->request.tag == tag && job->request.type != Tflush){
                        job->flushed = 1;
                        break;
                }
        }
-       unlock(&joblock);
+       qunlock(&joblock);
 }
 
 void
@@ -435,8 +444,10 @@ io(void)
 
        for(;;){
                n = read9pmsg(mfd[0], mdata, sizeof mdata);
-               if(n<=0)
+               if(n < 0)
                        error("mount read");
+               if(n == 0)
+                       continue;
                job = newjob();
                if(convM2S(mdata, n, &job->request) != n){
                        syslog(1, logfile, "format error %ux %ux %ux %ux %ux",
@@ -444,12 +455,11 @@ io(void)
                        freejob(job);
                        continue;
                }
-               lock(&dblock);
+               qlock(&dblock);
                mf = newfid(job->request.fid);
                if(debug)
                        syslog(0, logfile, "%F", &job->request);
 
-
                switch(job->request.type){
                default:
                        syslog(1, logfile, "unknown request type %d", job->request.type);
@@ -494,7 +504,7 @@ io(void)
                        rwstat(job, mf);
                        break;
                }
-               unlock(&dblock);
+               qunlock(&dblock);
 
                freejob(job);
 
@@ -504,6 +514,7 @@ io(void)
                if(*isslave){
                        if(debug)
                                syslog(0, logfile, "slave death %d", getpid());
+                       adec(&active);
                        _exits(0);
                }
        }
@@ -664,6 +675,8 @@ rread(Job *job, Mfile *mf)
        err = 0;
        off = job->request.offset;
        cnt = job->request.count;
+       mf->ref++;
+
        if(mf->qid.type & QTDIR){
                clock = time(0);
                if(off == 0){
@@ -682,38 +695,44 @@ rread(Job *job, Mfile *mf)
                        n = convD2M(&dir, buf, sizeof buf);
                }
                job->reply.data = (char*)buf;
-       } else {
-               for(;;){
-                       /* look for an answer at the right offset */
-                       toff = 0;
-                       for(i = 0; mf->reply[i] && i < mf->nreply; i++){
-                               n = mf->replylen[i];
-                               if(off < toff + n)
-                                       break;
-                               toff += n;
-                       }
-                       if(i < mf->nreply)
-                               break;          /* got something to return */
-
-                       /* try looking up more answers */
-                       if(lookup(mf) == 0){
-                               /* no more */
-                               n = 0;
-                               goto send;
-                       }
+               goto send;
+       }
+
+       for(;;){
+               /* look for an answer at the right offset */
+               toff = 0;
+               for(i = 0; mf->reply[i] && i < mf->nreply; i++){
+                       n = mf->replylen[i];
+                       if(off < toff + n)
+                               break;
+                       toff += n;
                }
+               if(i < mf->nreply)
+                       break;          /* got something to return */
 
-               /* give back a single reply (or part of one) */
-               job->reply.data = mf->reply[i] + (off - toff);
-               if(cnt > toff - off + n)
-                       n = toff - off + n;
-               else
-                       n = cnt;
+               /* try looking up more answers */
+               if(lookup(mf) == 0 || job->flushed){
+                       /* no more */
+                       n = 0;
+                       goto send;
+               }
        }
+
+       /* give back a single reply (or part of one) */
+       job->reply.data = mf->reply[i] + (off - toff);
+       if(cnt > toff - off + n)
+               n = toff - off + n;
+       else
+               n = cnt;
+
 send:
        job->reply.count = n;
        sendmsg(job, err);
+
+       if(--mf->ref == 0 && mf->busy == 0)
+               cleanmf(mf);
 }
+
 void
 cleanmf(Mfile *mf)
 {
@@ -764,6 +783,9 @@ rwrite(Job *job, Mfile *mf)
        }
        job->request.data[cnt] = 0;
 
+       if(strcmp(mf->user, "none") == 0 || strcmp(mf->user, csuser) != 0)
+               goto query;     /* skip special commands if not owner */
+
        /*
         *  toggle debugging
         */
@@ -810,6 +832,13 @@ rwrite(Job *job, Mfile *mf)
                goto send;
        }
 
+query:
+       if(mf->ref){
+               err = "query already in progress";
+               goto send;
+       }
+       mf->ref++;
+
        /* start transaction with a clean slate */
        cleanmf(mf);
 
@@ -818,32 +847,31 @@ rwrite(Job *job, Mfile *mf)
         */
        if(*job->request.data == '!'){
                err = genquery(mf, job->request.data+1);
-               goto send;
+               goto done;
        }
 
        if(debug)
                syslog(0, logfile, "write %s", job->request.data);
        if(paranoia)
                syslog(0, paranoiafile, "write %s by %s", job->request.data, mf->user);
-
        /*
         *  break up name
         */
        n = getfields(job->request.data, field, 4, 1, "!");
        switch(n){
        case 1:
-               mf->net = strdup("net");
-               mf->host = strdup(field[0]);
+               mf->net = estrdup("net");
+               mf->host = estrdup(field[0]);
                break;
        case 4:
-               mf->rem = strdup(field[3]);
+               mf->rem = estrdup(field[3]);
                /* fall through */
        case 3:
-               mf->serv = strdup(field[2]);
+               mf->serv = estrdup(field[2]);
                /* fall through */
        case 2:
-               mf->host = strdup(field[1]);
-               mf->net = strdup(field[0]);
+               mf->host = estrdup(field[1]);
+               mf->net = estrdup(field[0]);
                break;
        }
 
@@ -854,6 +882,11 @@ rwrite(Job *job, Mfile *mf)
                rerrstr(curerr, sizeof curerr);
                err = curerr;
        }
+
+done:
+       if(--mf->ref == 0 && mf->busy == 0)
+               cleanmf(mf);
+
 send:
        job->reply.count = cnt;
        sendmsg(job, err);
@@ -862,11 +895,12 @@ send:
 void
 rclunk(Job *job, Mfile *mf)
 {
-       cleanmf(mf);
+       if(mf->ref == 0)
+               cleanmf(mf);
        free(mf->user);
        mf->user = 0;
-       mf->busy = 0;
        mf->fid = 0;
+       mf->busy = 0;
        sendmsg(job, 0);
 }
 
@@ -929,11 +963,11 @@ sendmsg(Job *job, char *err)
                syslog(1, logfile, "sendmsg convS2M of %F returns 0", &job->reply);
                abort();
        }
-       lock(&joblock);
+       qlock(&joblock);
        if(job->flushed == 0)
                if(write(mfd[1], mdata, n)!=n)
                        error("mount write");
-       unlock(&joblock);
+       qunlock(&joblock);
        if(debug)
                syslog(0, logfile, "%F %d", &job->reply, n);
 }
@@ -1000,7 +1034,7 @@ ipid(void)
                if(p && *p){
                        attr = ipattr(p);
                        if(strcmp(attr, "ip") != 0)
-                               mysysname = strdup(p);
+                               mysysname = estrdup(p);
                }
 
                /*
@@ -1012,7 +1046,7 @@ ipid(void)
                        ndbreopen(netdb);
                        for(tt = t = ndbparse(netdb); t != nil; t = t->entry){
                                if(strcmp(t->attr, "sys") == 0){
-                                       mysysname = strdup(t->val);
+                                       mysysname = estrdup(t->val);
                                        break;
                                }
                        }
@@ -1037,7 +1071,7 @@ ipid(void)
                        }
                        for(tt = t; tt != nil; tt = tt->entry){
                                if(strcmp(tt->attr, "sys") == 0){
-                                       mysysname = strdup(tt->val);
+                                       mysysname = estrdup(tt->val);
                                        break;
                                }
                        }
@@ -1046,7 +1080,7 @@ ipid(void)
 
                /* nothing else worked, use the ip address */
                if(mysysname == 0 && isvalidip(ipa))
-                       mysysname = strdup(ipaddr);
+                       mysysname = estrdup(ipaddr);
 
 
                /* set /dev/sysname if we now know it */
@@ -1078,7 +1112,7 @@ netinit(int background)
                default:
                        return;
                }
-               lock(&netlock);
+               qlock(&netlock);
        }
 
        /* add the mounted networks to the default list */
@@ -1108,7 +1142,7 @@ netinit(int background)
                        mysysname?mysysname:"???", eaddr, ipaddr, ipa);
 
        if(background){
-               unlock(&netlock);
+               qunlock(&netlock);
                _exits(0);
        }
 }
@@ -1247,7 +1281,7 @@ lookup(Mfile *mf)
                else
                        snprint(reply, sizeof(reply), "%s/%s/clone %s",
                                mntpt, mf->net, mf->host);
-               mf->reply[0] = strdup(reply);
+               mf->reply[0] = estrdup(reply);
                mf->replylen[0] = strlen(reply);
                mf->nreply = 1;
                return 1;
@@ -1272,7 +1306,7 @@ ipserv(Network *np, char *name, char *buf, int blen)
 
        /* '*' means any service */
        if(strcmp(name, "*")==0){
-               strcpy(buf, name);
+               nstrcpy(buf, name, blen);
                return buf;
        }
 
@@ -1299,7 +1333,7 @@ ipserv(Network *np, char *name, char *buf, int blen)
                if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0)
                        p = ndbgetvalue(db, &s, "port", name, "port", &t);
                if(p == nil)
-                       p = strdup(name);
+                       p = estrdup(name);
        }
 
        if(t){
@@ -1380,6 +1414,7 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
        if(strcmp("::", host) == 0)
                return ndbnew("ip", "*");
 
+
        /*
         *  '$' means the rest of the name is an attribute that we
         *  need to search for
@@ -1392,9 +1427,15 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
        /*
         *  turn '[ip address]' into just 'ip address'
         */
-       if(*host == '[' && host[strlen(host)-1] == ']'){
-               host++;
-               host[strlen(host)-1] = 0;
+       if(*host == '['){
+               char *x;
+
+               if(host != dollar){
+                       nstrcpy(dollar, host, sizeof dollar);
+                       host = dollar;
+               }
+               if(x = strchr(++host, ']'))
+                       *x = 0;
        }
 
        /*
@@ -1435,7 +1476,7 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
        /*
         * reorder according to our interfaces
         */
-       lock(&ipifclock);
+       qlock(&ipifclock);
        for(ifc = ipifcs; ifc != nil; ifc = ifc->next){
                for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){
                        maskip(lifc->ip, lifc->mask, net);
@@ -1446,13 +1487,13 @@ iplookup(Network *np, char *host, char *serv, int nolookup)
                                maskip(ip, lifc->mask, tnet);
                                if(memcmp(net, tnet, IPaddrlen) == 0){
                                        t = reorder(t, nt);
-                                       unlock(&ipifclock);
+                                       qunlock(&ipifclock);
                                        return t;
                                }
                        }
                }
        }
-       unlock(&ipifclock);
+       qunlock(&ipifclock);
 
        return t;
 }
@@ -1486,7 +1527,7 @@ iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack)
                snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s",
                        mntpt, np->net, t->val, ts, x, hack? "!fasttimeout": "");
 
-       return strdup(reply);
+       return estrdup(reply);
 }
 
 /*
@@ -1530,7 +1571,7 @@ telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int)
        else
                snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net,
                        t->val, x);
-       return strdup(reply);
+       return estrdup(reply);
 }
 
 /*
@@ -1570,15 +1611,19 @@ slave(char *host)
 {
        if(*isslave)
                return;         /* we're already a slave process */
-
+       if(ainc(&active) >= Maxactive){
+               adec(&active);
+               return;
+       }
        switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){
        case -1:
+               adec(&active);
                break;
        case 0:
+               *isslave = 1;
                if(debug)
                        syslog(0, logfile, "slave %d", getpid());
                procsetname("%s", host);
-               *isslave = 1;
                break;
        default:
                longjmp(masterjmp, 1);
@@ -1598,7 +1643,7 @@ dnsip6lookup(char *mntpt, char *buf, Ndbtuple *t)
        /* convert ipv6 attr to ip */
        for (tt = t6; tt != nil; tt = tt->entry)
                if (strcmp(tt->attr, "ipv6") == 0)
-                       strncpy(tt->attr, "ip", sizeof tt->attr - 1);
+                       strcpy(tt->attr, "ip");
 
        if (t == nil)
                return t6;
@@ -1619,20 +1664,21 @@ dnsiplookup(char *host, Ndbs *s)
        char buf[Maxreply];
        Ndbtuple *t;
 
-       unlock(&dblock);
-
-       /* save the name before starting a slave */
-       snprint(buf, sizeof(buf), "%s", host);
-
+       qunlock(&dblock);
        slave(host);
+       if(*isslave == 0){
+               qlock(&dblock);
+               werrstr("too mutch activity");
+               return nil;
+       }
 
-       if(strcmp(ipattr(buf), "ip") == 0)
-               t = dnsquery(mntpt, buf, "ptr");
+       if(strcmp(ipattr(host), "ip") == 0)
+               t = dnsquery(mntpt, host, "ptr");
        else {
-               t = dnsquery(mntpt, buf, "ip");
+               t = dnsquery(mntpt, host, "ip");
                /* special case: query ipv6 (AAAA dns RR) too */
                if (ipv6lookups)
-                       t = dnsip6lookup(mntpt, buf, t);
+                       t = dnsip6lookup(mntpt, host, t);
        }
        s->t = t;
 
@@ -1644,7 +1690,7 @@ dnsiplookup(char *host, Ndbs *s)
                        werrstr("temporary problem: %s", buf);
        }
 
-       lock(&dblock);
+       qlock(&dblock);
        return t;
 }
 
@@ -1683,7 +1729,7 @@ qreply(Mfile *mf, Ndbtuple *t)
 
                if(nt->line != nt->entry){
                        mf->replylen[mf->nreply] = s_len(s);
-                       mf->reply[mf->nreply++] = strdup(s_to_c(s));
+                       mf->reply[mf->nreply++] = estrdup(s_to_c(s));
                        s_restart(s);
                } else
                        s_append(s, " ");
@@ -1783,7 +1829,7 @@ ipresolve(char *attr, char *host)
                        ndbfree(nt);
                        continue;
                }
-               strcpy(nt->attr, attr);
+               nstrcpy(nt->attr, attr, sizeof(nt->attr));
                l = &nt->entry;
        }
        return t;
@@ -1884,7 +1930,7 @@ emalloc(int size)
 
        x = malloc(size);
        if(x == nil)
-               abort();
+               error("out of memory");
        memset(x, 0, size);
        return x;
 }
@@ -1895,10 +1941,11 @@ estrdup(char *s)
        int size;
        char *p;
 
-       size = strlen(s)+1;
-       p = malloc(size);
+       size = strlen(s);
+       p = malloc(size+1);
        if(p == nil)
-               abort();
+               error("out of memory");
        memmove(p, s, size);
+       p[size] = 0;
        return p;
 }