📄 cs.c
字号:
* the service '*' needs no translation. */char*ipserv(Network *np, char *name, char *buf, int blen){ char *p; int alpha = 0; int restr = 0; char port[10]; Ndbtuple *t, *nt; Ndbs s; /* '*' means any service */ if(strcmp(name, "*")==0){ strcpy(buf, name); return buf; } /* see if it's numeric or symbolic */ port[0] = 0; for(p = name; *p; p++){ if(isdigit(*p)) {} else if(isalpha(*p) || *p == '-' || *p == '$') alpha = 1; else return 0; } t = nil; p = nil; if(alpha){ p = ndbgetvalue(db, &s, np->net, name, "port", &t); if(p == nil) return 0; } else { /* look up only for tcp ports < 1024 to get the restricted * attribute */ if(atoi(name) < 1024 && strcmp(np->net, "tcp") == 0) p = ndbgetvalue(db, &s, "port", name, "port", &t); if(p == nil) p = strdup(name); } if(t){ for(nt = t; nt; nt = nt->entry) if(strcmp(nt->attr, "restricted") == 0) restr = 1; ndbfree(t); } snprint(buf, blen, "%s%s", p, restr ? "!r" : ""); free(p); return buf;}/* * lookup an ip attribute */intipattrlookup(Ndb *db, char *ipa, char *attr, char *val, int vlen){ Ndbtuple *t, *nt; char *alist[2]; alist[0] = attr; t = ndbipinfo(db, "ip", ipa, alist, 1); if(t == nil) return 0; for(nt = t; nt != nil; nt = nt->entry){ if(strcmp(nt->attr, attr) == 0){ nstrcpy(val, nt->val, vlen); ndbfree(t); return 1; } } /* we shouldn't get here */ ndbfree(t); return 0;}/* * lookup (and translate) an ip destination */Ndbtuple*iplookup(Network *np, char *host, char *serv, int nolookup){ char *attr, *dnsname; Ndbtuple *t, *nt; Ndbs s; char ts[Maxservice]; char dollar[Maxhost]; uchar ip[IPaddrlen]; uchar net[IPaddrlen]; uchar tnet[IPaddrlen]; Ipifc *ifc; Iplifc *lifc; USED(nolookup); /* * start with the service since it's the most likely to fail * and costs the least */ werrstr("can't translate address"); if(serv==0 || ipserv(np, serv, ts, sizeof ts) == 0){ werrstr("can't translate service"); return 0; } /* for dial strings with no host */ if(strcmp(host, "*") == 0) return ndbnew("ip", "*"); /* * hack till we go v6 :: = 0.0.0.0 */ if(strcmp("::", host) == 0) return ndbnew("ip", "*"); /* * '$' means the rest of the name is an attribute that we * need to search for */ if(*host == '$'){ if(ipattrlookup(db, ipaddr, host+1, dollar, sizeof dollar)) host = dollar; } /* * turn '[ip address]' into just 'ip address' */ if(*host == '[' && host[strlen(host)-1] == ']'){ host++; host[strlen(host)-1] = 0; } /* * just accept addresses */ attr = ipattr(host); if(strcmp(attr, "ip") == 0) return ndbnew("ip", host); /* * give the domain name server the first opportunity to * resolve domain names. if that fails try the database. */ t = 0; werrstr("can't translate address"); if(strcmp(attr, "dom") == 0) t = dnsiplookup(host, &s); if(t == 0) free(ndbgetvalue(db, &s, attr, host, "ip", &t)); if(t == 0){ dnsname = ndbgetvalue(db, &s, attr, host, "dom", nil); if(dnsname){ t = dnsiplookup(dnsname, &s); free(dnsname); } } if(t == 0) t = dnsiplookup(host, &s); if(t == 0) return 0; /* * reorder the tuple to have the matched line first and * save that in the request structure. */ t = reorder(t, s.t); /* * reorder according to our interfaces */ lock(&ipifclock); for(ifc = ipifcs; ifc != nil; ifc = ifc->next){ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ maskip(lifc->ip, lifc->mask, net); for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; parseip(ip, nt->val); maskip(ip, lifc->mask, tnet); if(memcmp(net, tnet, IPaddrlen) == 0){ t = reorder(t, nt); unlock(&ipifclock); return t; } } } } unlock(&ipifclock); return t;}/* * translate an ip address */char*iptrans(Ndbtuple *t, Network *np, char *serv, char *rem, int hack){ char ts[Maxservice]; char reply[Maxreply]; char x[Maxservice]; if(strcmp(t->attr, "ip") != 0) return 0; if(serv == 0 || ipserv(np, serv, ts, sizeof ts) == 0){ werrstr("can't translate service"); return 0; } if(rem != nil) snprint(x, sizeof(x), "!%s", rem); else *x = 0; if(*t->val == '*') snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, ts, x); else snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s%s", mntpt, np->net, t->val, ts, x, hack?"!fasttimeout":""); return strdup(reply);}/* * lookup a telephone number */Ndbtuple*telcolookup(Network *np, char *host, char *serv, int nolookup){ Ndbtuple *t; Ndbs s; USED(np, nolookup, serv); werrstr("can't translate address"); free(ndbgetvalue(db, &s, "sys", host, "telco", &t)); if(t == 0) return ndbnew("telco", host); return reorder(t, s.t);}/* * translate a telephone address */char*telcotrans(Ndbtuple *t, Network *np, char *serv, char *rem, int){ char reply[Maxreply]; char x[Maxservice]; if(strcmp(t->attr, "telco") != 0) return 0; if(rem != nil) snprint(x, sizeof(x), "!%s", rem); else *x = 0; if(serv) snprint(reply, sizeof(reply), "%s/%s/clone %s!%s%s", mntpt, np->net, t->val, serv, x); else snprint(reply, sizeof(reply), "%s/%s/clone %s%s", mntpt, np->net, t->val, x); return strdup(reply);}/* * reorder the tuple to put x's line first in the entry */Ndbtuple*reorder(Ndbtuple *t, Ndbtuple *x){ Ndbtuple *nt; Ndbtuple *line; /* find start of this entry's line */ for(line = x; line->entry == line->line; line = line->line) ; line = line->line; if(line == t) return t; /* already the first line */ /* remove this line and everything after it from the entry */ for(nt = t; nt->entry != line; nt = nt->entry) ; nt->entry = 0; /* make that the start of the entry */ for(nt = line; nt->entry; nt = nt->entry) ; nt->entry = t; return line;}/* * create a slave process to handle a request to avoid one request blocking * another. parent returns to job loop. */voidslave(void){ if(*isslave) return; /* we're already a slave process */ switch(rfork(RFPROC|RFNOTEG|RFMEM|RFNOWAIT)){ case -1: break; case 0: if(debug) syslog(0, logfile, "slave %d", getpid()); *isslave = 1; break; default: longjmp(masterjmp, 1); }}/* * call the dns process and have it try to translate a name */Ndbtuple*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); slave(); if(strcmp(ipattr(buf), "ip") == 0) t = dnsquery(mntpt, buf, "ptr"); else t = dnsquery(mntpt, buf, "ip"); s->t = t; if(t == nil){ rerrstr(buf, sizeof buf); if(strstr(buf, "exist")) werrstr("can't translate address: %s", buf); else if(strstr(buf, "dns failure")) werrstr("temporary problem: %s", buf); } lock(&dblock); return t;}intqmatch(Ndbtuple *t, char **attr, char **val, int n){ int i, found; Ndbtuple *nt; for(i = 1; i < n; i++){ found = 0; for(nt = t; nt; nt = nt->entry) if(strcmp(attr[i], nt->attr) == 0) if(strcmp(val[i], "*") == 0 || strcmp(val[i], nt->val) == 0){ found = 1; break; } if(found == 0) break; } return i == n;}voidqreply(Mfile *mf, Ndbtuple *t){ Ndbtuple *nt; String *s; s = s_new(); for(nt = t; mf->nreply < Nreply && nt; nt = nt->entry){ s_append(s, nt->attr); s_append(s, "="); s_append(s, nt->val); if(nt->line != nt->entry){ mf->replylen[mf->nreply] = s_len(s); mf->reply[mf->nreply++] = strdup(s_to_c(s)); s_restart(s); } else s_append(s, " "); } s_free(s);}enum{ Maxattr= 32,};/* * generic query lookup. The query is of one of the following * forms: * * attr1=val1 attr2=val2 attr3=val3 ... * * returns the matching tuple * * ipinfo attr=val attr1 attr2 attr3 ... * * is like ipinfo and returns the attr{1-n} * associated with the ip address. */char*genquery(Mfile *mf, char *query){ int i, n; char *p; char *attr[Maxattr]; char *val[Maxattr]; Ndbtuple *t; Ndbs s; n = getfields(query, attr, 32, 1, " "); if(n == 0) return "bad query"; if(strcmp(attr[0], "ipinfo") == 0) return ipinfoquery(mf, attr, n); /* parse pairs */ for(i = 0; i < n; i++){ p = strchr(attr[i], '='); if(p == 0) return "bad query"; *p++ = 0; val[i] = p; } /* give dns a chance */ if((strcmp(attr[0], "dom") == 0 || strcmp(attr[0], "ip") == 0) && val[0]){ t = dnsiplookup(val[0], &s); if(t){ if(qmatch(t, attr, val, n)){ qreply(mf, t); ndbfree(t); return 0; } ndbfree(t); } } /* first pair is always the key. It can't be a '*' */ t = ndbsearch(db, &s, attr[0], val[0]); /* search is the and of all the pairs */ while(t){ if(qmatch(t, attr, val, n)){ qreply(mf, t); ndbfree(t); return 0; } ndbfree(t); t = ndbsnext(&s, attr[0], val[0]); } return "no match";}/* * resolve an ip address */static Ndbtuple*ipresolve(char *attr, char *host){ Ndbtuple *t, *nt, **l; t = iplookup(&network[Ntcp], host, "*", 0); for(l = &t; *l != nil; ){ nt = *l; if(strcmp(nt->attr, "ip") != 0){ *l = nt->entry; nt->entry = nil; ndbfree(nt); continue; } strcpy(nt->attr, attr); l = &nt->entry; } return t;}char*ipinfoquery(Mfile *mf, char **list, int n){ int i, nresolve; int resolve[Maxattr]; Ndbtuple *t, *nt, **l; char *attr, *val; /* skip 'ipinfo' */ list++; n--; if(n < 1) return "bad query"; /* get search attribute=value, or assume ip=myipaddr */ attr = *list; if((val = strchr(attr, '=')) != nil){ *val++ = 0; list++; n--; }else{ attr = "ip"; val = ipaddr; } if(n < 1) return "bad query"; /* * don't let ndbipinfo resolve the addresses, we're * better at it. */ nresolve = 0; for(i = 0; i < n; i++) if(*list[i] == '@'){ list[i]++; resolve[i] = 1; nresolve++; } else resolve[i] = 0; t = ndbipinfo(db, attr, val, list, n); if(t == nil) return "no match"; if(nresolve != 0){ for(l = &t; *l != nil;){ nt = *l; /* already an address? */ if(strcmp(ipattr(nt->val), "ip") == 0){ l = &(*l)->entry; continue; } /* user wants it resolved? */ for(i = 0; i < n; i++) if(strcmp(list[i], nt->attr) == 0) break; if(i >= n || resolve[i] == 0){ l = &(*l)->entry; continue; } /* resolve address and replace entry */ *l = ipresolve(nt->attr, nt->val); while(*l != nil) l = &(*l)->entry; *l = nt->entry; nt->entry = nil; ndbfree(nt); } } /* make it all one line */ for(nt = t; nt != nil; nt = nt->entry){ if(nt->entry == nil) nt->line = t; else nt->line = nt->entry; } qreply(mf, t); return nil;}void*emalloc(int size){ void *x; x = malloc(size); if(x == nil) abort(); memset(x, 0, size); return x;}char*estrdup(char *s){ int size; char *p; size = strlen(s)+1; p = malloc(size); if(p == nil) abort(); memmove(p, s, size); return p;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -