/* * lookup an ip address */ static int getipaddr(Ndb *db, char *name, uchar *to, Ipinfo *iip) { Ndbtuple *t, *nt; char buf[Ndbvlen]; uchar subnet[IPaddrlen]; Ndbs s; char *attr; attr = ipattr(name); if(strcmp(attr, "ip") == 0){ parseip(to, name); return 1; } t = ndbgetval(db, &s, attr, name, "ip", buf); if(t){ /* first look for match on same subnet */ for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ip") != 0) continue; parseip(to, nt->val); maskip(to, iip->ipmask, subnet); if(memcmp(subnet, iip->ipnet, sizeof(subnet)) == 0) return 1; } /* otherwise, just take what we have */ ndbfree(t); parseip(to, buf); return 1; } return 0; }
/* notify a slave that an area has changed. */ static void send_notify(char *slave, RR *soa, Request *req) { int i, len, n, reqno, status, fd; char *err; uchar ibuf[Maxudp+Udphdrsize], obuf[Maxudp+Udphdrsize]; RR *rp; Udphdr *up = (Udphdr*)obuf; DNSmsg repmsg; /* create the request */ reqno = rand(); n = mkreq(soa->owner, Cin, obuf, Fauth | Onotify, reqno); /* get an address */ if(strcmp(ipattr(slave), "ip") == 0) { if (parseip(up->raddr, slave) == -1) dnslog("bad address %s to notify", slave); } else { rp = dnresolve(slave, Cin, Ta, req, nil, 0, 1, 1, &status); if(rp == nil) rp = dnresolve(slave, Cin, Taaaa, req, nil, 0, 1, 1, &status); if(rp == nil) return; parseip(up->raddr, rp->ip->name); rrfreelist(rp); /* was rrfree */ } fd = udpport(nil); if(fd < 0) return; /* send 3 times or until we get anything back */ n += Udphdrsize; for(i = 0; i < 3; i++, freeanswers(&repmsg)){ dnslog("sending %d byte notify to %s/%I.%d about %s", n, slave, up->raddr, nhgets(up->rport), soa->owner->name); memset(&repmsg, 0, sizeof repmsg); if(write(fd, obuf, n) != n) break; alarm(2*1000); len = read(fd, ibuf, sizeof ibuf); alarm(0); if(len <= Udphdrsize) continue; err = convM2DNS(&ibuf[Udphdrsize], len, &repmsg, nil); if(err != nil) { free(err); continue; } if(repmsg.id == reqno && (repmsg.flags & Omask) == Onotify) break; } if (i < 3) freeanswers(&repmsg); close(fd); }
/* * compile WORD = WORD, becomes a single node with a subop */ void compile_cmp(char *proto, Filter *f, Field *fld) { uint8_t x[IPaddrlen]; char *v; if(f->op != '=') sysfatal("internal error: compile_cmp %s: not a cmp", proto); for(; fld->name != nil; fld++){ if(strcmp(f->l->s, fld->name) == 0){ f->op = WORD; f->subop = fld->subop; switch(fld->ftype){ case Fnum: f->ulv = atoi(f->r->s); break; case Fether: v = csgetvalue(nil, "sys", (char*)f->r->s, "ether", 0); if(v){ parseether(f->a, v); free(v); } else parseether(f->a, f->r->s); break; case Fv4ip: v = csgetvalue(nil, "sys", (char*)f->r->s, "ip", 0); if(v){ f->ulv = parseip(x, v); free(v); }else f->ulv = parseip(x, f->r->s); break; case Fv6ip: v = csgetvalue(nil, "sys", (char*)f->r->s, "ipv6", 0); if(v){ parseip(f->a, v); free(v); }else parseip(f->a, f->r->s); break; case Fba: parseba(f->a, f->r->s); break; default: sysfatal("internal error: compile_cmp %s: %d", proto, fld->ftype); } f->l = f->r = nil; return; } } sysfatal("unknown %s field in: %s = %s", proto, f->l->s, f->r->s); }
/* * called to bind an IP ifc to an ethernet device * called with ifc wlock'd */ static void pppbind(Ipifc * ifc, int argc, char **argv) { PPP *ppp; Ipaddr ipaddr, remip; int mtu, framing; char *chapname, *secret; if (argc < 3) error(Ebadarg); ipmove(ipaddr, IPnoaddr); ipmove(remip, IPnoaddr); mtu = Defmtu; framing = 1; chapname = nil; secret = nil; switch (argc) { default: case 9: if (argv[8][0] != '-') secret = argv[8]; case 8: if (argv[7][0] != '-') chapname = argv[7]; case 7: if (argv[6][0] != '-') framing = strtoul(argv[6], 0, 0); case 6: if (argv[5][0] != '-') mtu = strtoul(argv[5], 0, 0); case 5: if (argv[4][0] != '-') parseip(remip, argv[4]); case 4: if (argv[3][0] != '-') parseip(ipaddr, argv[3]); case 3: break; } ppp = smalloc(sizeof(*ppp)); ppp->ifc = ifc; ppp->f = ifc->conv->p->f; ifc->arg = ppp; if (waserror()) { pppunbind(ifc); nexterror(); } if (pppopen(ppp, argv[2], ipaddr, remip, mtu, framing, chapname, secret) == nil) error("ppp open failed"); poperror(); ktask("pppreader", pppreader, ifc); }
int parseipmask(char *ip, char *mask, uchar *pip, uchar *pmask) { int v, v0; v = parseip(ip, pip); v0 = parseip(mask, pmask); if (v == -1 || v0 == -1 || v != v0) return -1; return v; }
/* * hack to allow ip v4 masks to be entered in the old * style */ uint32_t parseipmask(uint8_t * to, char *from) { uint32_t x; int i; uint8_t *p; if (*from == '/') { /* as a number of prefix bits */ i = atoi(from + 1); if (i < 0) i = 0; if (i > 128) i = 128; memset(to, 0, IPaddrlen); for (p = to; i >= 8; i -= 8) *p++ = 0xff; if (i > 0) *p = ~((1 << (8 - i)) - 1); x = nhgetl(to + IPv4off); } else { /* as a straight bit mask */ x = parseip(to, from); if (memcmp(to, v4prefix, IPv4off) == 0) memset(to, 0xff, IPv4off); } return x; }
char* rudpctl(Conv *c, char **f, int n) { Rudpcb *ucb; uint8_t ip[IPaddrlen]; int x; ucb = (Rudpcb*)c->ptcl; if(n < 1) return rudpunknown; if(strcmp(f[0], "headers") == 0){ ucb->headers = 7; /* new headers format */ return nil; } else if(strcmp(f[0], "hangup") == 0){ if(n < 3) return "bad syntax"; if (parseip(ip, f[1]) == -1) return Ebadip; x = atoi(f[2]); qlock(&ucb->ql); relforget(c, ip, x, 1); qunlock(&ucb->ql); return nil; } else if(strcmp(f[0], "randdrop") == 0){ x = 10; /* default is 10% */ if(n > 1) x = atoi(f[1]); if(x > 100 || x < 0) return "illegal rudp drop rate"; ucb->randdrop = x; return nil; } return rudpunknown; }
static void netndb(char *attr, uchar *ip) { int fd, n, c; char buf[1024]; char *p; ipmove(ip, IPnoaddr); snprint(buf, sizeof(buf), "%s/ndb", mpoint); fd = open(buf, OREAD); if(fd < 0) return; n = read(fd, buf, sizeof(buf)-1); close(fd); if(n <= 0) return; buf[n] = 0; n = strlen(attr); for(p = buf; ; p++){ p = strstr(p, attr); if(p == nil) break; c = *(p-1); if(*(p + n) == '=' && (p == buf || c == '\n' || c == ' ' || c == '\t')){ p += n+1; if (parseip(ip, p) == -1) fprint(2, "netndb: can't parse ip %s\n", p); return; } } return; }
int nbnameresolve(NbName nbname, uchar *ipaddr) { ulong r, ttl; char name[NETPATHLEN]; NbName copy; Ndbtuple *t; /* for now, just use dns */ if (nbremotenametablefind(nbname, ipaddr)) { //print("%B found in cache\n", nbname); return 1; } if (nbnsfindname(nil, nbname, ipaddr, &ttl) == 0) { nbremotenametableadd(nbname, ipaddr, ttl); return 1; } nbnamecpy(copy, nbname); copy[NbNameLen - 1] = 0; nbmkstringfromname(name, sizeof(name), copy); t = dnsquery("/net", name, "ip"); if (t == nil) return 0; r = parseip(ipaddr, t->line->val); ndbfree(t); return r != -1; }
void netlogctl(Fs *f, char* s, int n) { int i, set; Netlogflag *fp; Cmdbuf *cb; Cmdtab *ct; cb = parsecmd(s, n); if(waserror()){ free(cb); nexterror(); } if(cb->nf < 2) error(Ebadnetctl); ct = lookupcmd(cb, routecmd, nelem(routecmd)); SET(set); switch(ct->index){ case CMset: set = 1; break; case CMclear: set = 0; break; case CMonly: parseip(f->alog->iponly, cb->f[1]); if(ipcmp(f->alog->iponly, IPnoaddr) == 0) f->alog->iponlyset = 0; else f->alog->iponlyset = 1; free(cb); poperror(); return; default: cmderror(cb, "unknown netlog control message"); } for(i = 1; i < cb->nf; i++){ for(fp = flags; fp->name; fp++) if(strcmp(fp->name, cb->f[i]) == 0) break; if(fp->name == nil) continue; if(set) f->alog->logmask |= fp->mask; else f->alog->logmask &= ~fp->mask; } free(cb); poperror(); }
char *ipifcaddpref6(struct Ipifc *ifc, char **argv, int argc) { uint8_t onlink = 1; uint8_t autoflag = 1; uint64_t validlt = UINT64_MAX; uint64_t preflt = UINT64_MAX; uint64_t origint = NOW / 10 ^ 3; uint8_t prefix[IPaddrlen]; int plen = 64; struct Iplifc *lifc; char addr[40], preflen[6]; char *params[3]; switch (argc) { case 7: preflt = atoi(argv[6]); /* fall through */ case 6: validlt = atoi(argv[5]); /* fall through */ case 5: autoflag = atoi(argv[4]); /* fall through */ case 4: onlink = atoi(argv[3]); /* fall through */ case 3: plen = atoi(argv[2]); case 2: break; default: return Ebadarg; } if ((parseip(prefix, argv[1]) != 6) || (validlt < preflt) || (plen < 0) || (plen > 64) || (islinklocal(prefix)) ) return Ebadarg; lifc = kzmalloc(sizeof(struct Iplifc), 0); lifc->onlink = (onlink != 0); lifc->autoflag = (autoflag != 0); lifc->validlt = validlt; lifc->preflt = preflt; lifc->origint = origint; if (ifc->m->pref2addr != NULL) ifc->m->pref2addr(prefix, ifc->mac); else return Ebadarg; snprintf(addr, sizeof(addr), "%I", prefix); snprintf(preflen, sizeof(preflen), "/%d", plen); params[0] = "add"; params[1] = addr; params[2] = preflen; return ipifcadd(ifc, params, 3, 0, lifc); }
static void parsenetwork(const char *parameter, u_int32_t *network) { if (!parseip(parameter, network)) #ifdef XTABLES_VERSION xtables_error(PARAMETER_PROBLEM, "account: wrong ip in network"); #else exit_error(PARAMETER_PROBLEM, "account: wrong ip in network"); #endif }
void netlogctl(struct Fs *f, char *s, int n) { ERRSTACK(1); int i, set = 0; Netlogflag *fp; struct cmdbuf *cb; struct cmdtab *ct; cb = parsecmd(s, n); if (waserror()) { kfree(cb); nexterror(); } if (cb->nf < 2) error(EINVAL, ERROR_FIXME); ct = lookupcmd(cb, routecmd, ARRAY_SIZE(routecmd)); switch (ct->index) { case CMset: set = 1; break; case CMclear: set = 0; break; case CMonly: parseip(f->alog->iponly, cb->f[1]); if (ipcmp(f->alog->iponly, IPnoaddr) == 0) f->alog->iponlyset = 0; else f->alog->iponlyset = 1; kfree(cb); poperror(); return; default: cmderror(cb, "unknown ip control message"); } for (i = 1; i < cb->nf; i++) { for (fp = flags; fp->name; fp++) if (strcmp(fp->name, cb->f[i]) == 0) break; if (fp->name == NULL) continue; if (set) f->alog->logmask |= fp->mask; else f->alog->logmask &= ~fp->mask; } kfree(cb); poperror(); }
static ulong lookuphost(char *s) { char to[4]; ulong ip; memset(to, 0, sizeof to); parseip(to, s); ip = nhgetl(to); if(ip != 0) return ip; if((s = hostlookup(s)) == nil) return 0; parseip(to, s); ip = nhgetl(to); free(s); return ip; }
/* * read (recipient, sender's DNS) pairs from /mail/lib/senders. * Only allow mail to recipient from any of sender's IPs. * A recipient not mentioned in the file is always permitted. */ static int senderok(char *rcpt) { int mentioned = 0, matched = 0; uchar dnsip[IPaddrlen]; Sender *snd; Ndbtuple *nt, *next, *first; rdsenders(); for (snd = sendlist; snd != nil; snd = snd->next) { if (strcmp(rcpt, snd->rcpt) != 0) continue; /* * see if this domain's ips match nci->rsys. * if not, perhaps a later entry's domain will. */ mentioned = 1; if (parseip(dnsip, snd->domain) != -1 && memcmp(rsysip, dnsip, IPaddrlen) == 0) return 1; /* * NB: nt->line links form a circular list(!). * we need to make one complete pass over it to free it all. */ first = nt = dnsquery(nci->root, snd->domain, "ip"); if (first == nil) continue; do { if (strcmp(nt->attr, "ip") == 0 && parseip(dnsip, nt->val) != -1 && memcmp(rsysip, dnsip, IPaddrlen) == 0) matched = 1; next = nt->line; free(nt); nt = next; } while (nt != first); } if (matched) return 1; else return !mentioned; }
/* * set a local address and port from a string of the form * [address!]port[!r] */ char* setladdrport(Conv* c, char* str, int announcing) { char *p; char *rv; ushort lport; uchar addr[IPaddrlen]; /* * ignore restricted part if it exists. it's * meaningless on local ports. */ p = strchr(str, '!'); if(p != nil){ *p++ = 0; if(strcmp(p, "r") == 0) p = nil; } c->lport = 0; if(p == nil){ if(announcing) ipmove(c->laddr, IPnoaddr); else setladdr(c); p = str; } else { if(strcmp(str, "*") == 0) ipmove(c->laddr, IPnoaddr); else { if(parseip(addr, str) == -1) return Ebadip; if(ipforme(c->p->f, addr)) ipmove(c->laddr, addr); else return "not a local IP address"; } } /* one process can get all connections */ if(announcing && strcmp(p, "*") == 0){ if(!iseve()) error(Eperm); return setluniqueport(c, 0); } lport = atoi(p); if(lport <= 0) rv = setlport(c); else rv = setluniqueport(c, lport); return rv; }
static char* espconnect(Conv *c, char **argv, int argc) { char *p, *pp, *e = nil; uint32_t spi; Espcb *ecb = (Espcb*)c->ptcl; switch(argc) { default: e = "bad args to connect"; break; case 2: p = strchr(argv[1], '!'); if(p == nil){ e = "malformed address"; break; } *p++ = 0; if (parseip(c->raddr, argv[1]) == -1) { e = Ebadip; break; } findlocalip(c->p->f, c->laddr, c->raddr); ecb->incoming = 0; ecb->seq = 0; if(strcmp(p, "*") == 0) { qlock(c->p); for(;;) { spi = nrand(1<<16) + 256; if(convlookup(c->p, spi) == nil) break; } qunlock(c->p); ecb->spi = spi; ecb->incoming = 1; qhangup(c->wq, nil); } else { spi = strtoul(p, &pp, 10); if(pp == p) { e = "malformed address"; break; } ecb->spi = spi; qhangup(c->rq, nil); } nullespinit(ecb, "null", nil, 0); nullahinit(ecb, "null", nil, 0); } Fsconnected(c, e); return e; }
/* * return the ip addresses for a type of server for system ip */ int lookupserver(char *attr, uchar **ipaddrs, Ndbtuple *t) { Ndbtuple *nt; int rv = 0; for(nt = t; rv < 2 && nt != nil; nt = nt->entry) if(strcmp(nt->attr, attr) == 0){ parseip(ipaddrs[rv], nt->val); rv++; } return rv; }
/* * remove an address from an interface. * called with c->car locked */ char* ipifcrem(Ipifc *ifc, char **argv, int argc) { char *rv; uint8_t ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen]; Iplifc *lifc; if(argc < 3) return Ebadarg; if (parseip(ip, argv[1]) == -1) return Ebadip; parseipmask(mask, argv[2]); if(argc < 4) maskip(ip, mask, rem); else if (parseip(rem, argv[3]) == -1) return Ebadip; wlock(ifc); /* * find address on this interface and remove from chain. * for pt to pt we actually specify the remote address as the * addresss to remove. */ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next) { if (memcmp(ip, lifc->local, IPaddrlen) == 0 && memcmp(mask, lifc->mask, IPaddrlen) == 0 && memcmp(rem, lifc->remote, IPaddrlen) == 0) break; } rv = ipifcremlifc(ifc, lifc); wunlock(ifc); return rv; }
/* * set a local address and port from a string of the form * [address!]port[!r] */ static void setladdrport(Conv *c, char *str, int announcing) { char *p; int lport; /* * ignore restricted part if it exists. it's * meaningless on local ports. */ p = strchr(str, '!'); if(p != nil){ *p++ = 0; if(strcmp(p, "r") == 0) p = nil; } c->lport = 0; if(p == nil){ if(announcing) ipmove(c->laddr, IPnoaddr); else if(0) setladdr(c); p = str; } else { if(strcmp(str, "*") == 0) ipmove(c->laddr, IPnoaddr); else if(parseip(c->laddr, str) == 0) error("invalid IP address"); } if(announcing && strcmp(p, "*") == 0){ if(!iseve()) error(Eperm); c->lport = 0; setlport(c); return; } lport = portno(p); if(lport <= 0) c->lport = 0; else c->lport = lport; setlport(c); }
int parsecidr(char *cidr, uchar *ip, uchar *mask) { char *p; int v; p = strchr(cidr, '/'); // *p++ = '\0'; v = parseip(cidr, ip); if (v == -1) return -1; if (parsecmask(v, p+1, mask) == -1) return -1; return v; }
static char* setraddrport(Conv *c, char *str) { char *p, addr[4]; p = strchr(str, '!'); if(p == 0) return "malformed address"; *p++ = 0; parseip(addr, str); c->raddr = nhgetl((uchar*)addr); c->rport = atoi(p); p = strchr(p, '!'); if(p) { if(strcmp(p, "!r") == 0) c->restricted = 1; } return 0; }
static void netenv(char *attr, uchar *ip) { int fd, n; char buf[128]; ipmove(ip, IPnoaddr); snprint(buf, sizeof(buf), "#e/%s", attr); fd = open(buf, OREAD); if(fd < 0) return; n = read(fd, buf, sizeof(buf)-1); if(n <= 0) return; buf[n] = 0; if (parseip(ip, buf) == -1) fprint(2, "netenv: can't parse ip %s\n", buf); }
static char* setraddrport(Conv *c, char *str) { char *p; p = strchr(str, '!'); if(p == nil) return "malformed address"; *p++ = 0; if(parseip(c->raddr, str) == 0) return "invalid IP address"; c->rport = portno(p); p = strchr(p, '!'); if(p){ if(strstr(p, "!r") != nil) c->restricted = 1; } return nil; }
int netlookup(char *name, uint32_t *ip) { struct hostent *he; if(parseip(name, ip) >= 0) return 0; /* BUG - Name resolution blocks. Need a non-blocking DNS. */ taskstate("netlookup"); if((he = gethostbyname(name)) != 0){ *ip = *(uint32_t*)he->h_addr; taskstate("netlookup succeeded"); return 0; } taskstate("netlookup failed"); return -1; }
static void recursesubnet(Ndb *db, uchar *addr, uchar *mask, char *attr, char *name, char *name1) { Ndbs s; Ndbtuple *t, *nt; uchar submask[IPaddrlen], net[IPaddrlen]; char ip[Ndbvlen]; int found; maskip(addr, mask, net); sprint(ip, "%I", net); t = ndbsearch(db, &s, "ip", ip); if(t == 0) return; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, "ipmask") == 0){ parseip(submask, nt->val); if(memcmp(submask, mask, IPaddrlen) != 0) recursesubnet(db, addr, submask, attr, name, name1); break; } } if(name[0] == 0){ found = 0; for(nt = t; nt; nt = nt->entry){ if(strcmp(nt->attr, attr) == 0){ if(found){ strcpy(name, nt->val); name1[0] = 0; found = 1; } else { strcpy(name1, nt->val); break; } } } } ndbfree(t); }
/* * parseipv4, parseipv6, parseip, * ip4str, ip6str, ipstr */ int testips(void) { char ip[LenStr]; uchar pip[V6]; int i, v; Z(ip); Z(pip); for (i = 0; ips[i].ip; i++) { v = parseip(ips[i].ip, pip); if (v != ips[i].v) fprintf(stderr, "testparse: %d != %d\n", ips[i].v, v); else if (v != -1) if (strcmp(ips[i].rip, ipstr(v, pip, ip)) != 0) fprintf(stderr, "testparse: %s != %s\n", ips[i].rip, ip); } return 0; }
static void setladdrport(Conv *c, char *str) { char *p, addr[4]; p = strchr(str, '!'); if(p == 0) { p = str; c->laddr = 0; } else { *p++ = 0; parseip(addr, str); c->laddr = nhgetl((uchar*)addr); } if(*p == '*') c->lport = 0; else c->lport = atoi(p); setlport(c); }
/* * convert address into a reverse lookup address */ static void mkptrname(char *ip, char *rip, int rlen) { uchar a[IPaddrlen]; char *p, *e; int i; if(cistrstr(ip, "in-addr.arpa") || cistrstr(ip, "ip6.arpa") || parseip(a, ip) == -1) snprint(rip, rlen, "%s", ip); else if(isv4(a)) snprint(rip, rlen, "%ud.%ud.%ud.%ud.in-addr.arpa", a[15], a[14], a[13], a[12]); else { p = rip; e = rip + rlen; for(i = 15; i >= 0; i--) { p = seprint(p, e, "%ux.", a[i]&0xf); p = seprint(p, e, "%ux.", a[i]>>4); } seprint(p, e, "ip6.arpa"); } }
/* * hack to allow ip v4 masks to be entered in the old * style */ int64_t parseipmask(uint8_t *to, char *from) { int i, w; int64_t x; uint8_t *p; if(*from == '/'){ /* as a number of prefix bits */ i = atoi(from+1); if(i < 0) i = 0; if(i > 128) i = 128; w = i; memset(to, 0, IPaddrlen); for(p = to; i >= 8; i -= 8) *p++ = 0xff; if(i > 0) *p = ~((1<<(8-i))-1); x = nhgetl(to+IPv4off); /* * identify as ipv6 if the mask is inexpressible as a v4 mask * (because it has too few mask bits). Arguably, we could * always return 6 here. */ if (w < 8*(IPaddrlen-IPv4addrlen)) return 6; } else { /* as a straight v4 bit mask */ x = parseip(to, from); if (x != -1) x = (uint32_t)nhgetl(to + IPv4off); if(memcmp(to, v4prefix, IPv4off) == 0) memset(to, 0xff, IPv4off); } return x; }