void readroutes(void) { int n; char *p; Biobuf *b; char *f[6]; Route route; b = Bopen(routefile, OREAD); if(b == 0) return; while(p = Brdline(b, '\n')){ p[Blinelen(b)-1] = 0; n = getfields(p, f, 6, 1, " \t"); if(n < 5) continue; v4parseip(route.dest, f[0]); v4parseipmask(route.mask, f[1]); v4parseip(route.gate, f[2]); route.metric = Infinity; if(equivip(route.dest, ralloc.def.dest) && equivip(route.mask, ralloc.def.mask)) memmove(ralloc.def.gate, route.gate, Pasize); else if(!equivip(route.dest, route.gate) && strchr(f[3], 'i') == 0) considerroute(&route); } Bterm(b); }
/* * `from' may contain an address followed by other characters, * at least in /boot, so we permit whitespace (and more) after the address. * we do ensure that "delete" cannot be parsed as "de::". * * some callers don't check the return value for errors, so * set `to' to something distinctive in the case of a parse error. */ vlong parseip(uchar *to, char *from) { int i, elipsis = 0, v4 = 1; ulong x; char *p, *op; memset(to, 0, IPaddrlen); p = from; for(i = 0; i < IPaddrlen && ipcharok(*p); i+=2){ op = p; x = strtoul(p, &p, 16); if(*p == '.' || (*p == 0 && i == 0)){ /* ends with v4? */ if(i > IPaddrlen-4){ memset(to, 0, IPaddrlen); return -1; /* parse error */ } p = v4parseip(to+i, op); i += 4; break; } /* v6: at most 4 hex digits, followed by colon or delim */ if(x != (ushort)x || *p != ':' && !delimchar(*p)) { memset(to, 0, IPaddrlen); return -1; /* parse error */ } to[i] = x>>8; to[i+1] = x; if(*p == ':'){ v4 = 0; if(*++p == ':'){ /* :: is elided zero short(s) */ if (elipsis) { memset(to, 0, IPaddrlen); return -1; /* second :: */ } elipsis = i+2; p++; } } else if (p == op) /* strtoul made no progress? */ break; } if (p == from || !delimchar(*p)) { memset(to, 0, IPaddrlen); return -1; /* parse error */ } if(i < IPaddrlen){ memmove(&to[elipsis+IPaddrlen-i], &to[elipsis], i-elipsis); memset(&to[elipsis], 0, IPaddrlen-i); } if(v4){ to[10] = to[11] = 0xff; return nhgetl(to + IPv4off); } else return 6; }
static void process(char *ether) { uchar ethaddr[6], ipaddr[IPaddrlen], ipv4[IPv4addrlen]; if (parseether(ethaddr, ether) < 0) sysfatal("%s: not an ether address", ether); if (v4_6to4) { v4parseip(ipv4, v4_6to4); eaip26to4(ipaddr, ethaddr, ipv4); } else ea2lla(ipaddr, ethaddr); print("%I\n", ipaddr); }
/* * Walk the directory of trusted files */ static Node* trwalk(char *name, Node *np) { Node *p; ulong peerip; uchar addr[IPv4addrlen]; v4parseip(addr, name); peerip = nhgetl(addr); for(p = np->children; p; p = p->sibs) if((peerip&p->ip.mask) == p->ip.ipaddr) break; return p; }
/* * Walk a directory of IP addresses */ static Node* ipwalk(char *name, Node *np) { Address *ap; ulong peerip; uchar addr[IPv4addrlen]; v4parseip(addr, name); peerip = nhgetl(addr); 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); if(ap == 0) return 0; dummy.d.name = ap->name; return &dummy; }
/* * parse a v4 ip address/mask in cidr format */ char* v4parsecidr(uint8_t *addr, uint8_t *mask, char *from) { int i; char *p; uint8_t *a; p = v4parseip(addr, from); if(*p == '/'){ /* as a number of prefix bits */ i = strtoul(p+1, &p, 0); if(i > 32) i = 32; memset(mask, 0, IPv4addrlen); for(a = mask; i >= 8; i -= 8) *a++ = 0xff; if(i > 0) *a = ~((1<<(8-i))-1); } else memcpy(mask, defmask(addr), IPv4addrlen); return p; }
uint32_t parseip(uint8_t * to, char *from) { int i, elipsis = 0, v4 = 1; uint32_t x; char *p, *op; memset(to, 0, IPaddrlen); p = from; for (i = 0; i < 16 && *p; i += 2) { op = p; x = strtoul(p, &p, 16); if (*p == '.' || (*p == 0 && i == 0)) { p = v4parseip(to + i, op); i += 4; break; } else { to[i] = x >> 8; to[i + 1] = x; } if (*p == ':') { v4 = 0; if (*++p == ':') { elipsis = i + 2; p++; } } } if (i < 16) { memmove(&to[elipsis + 16 - i], &to[elipsis], i - elipsis); memset(&to[elipsis], 0, 16 - i); } if (v4) { to[10] = to[11] = 0xff; return nhgetl(to + 12); } else return 6; }
void main(int argc, char *argv[]) { int dobroadcast, i, n; long diff; char *p; char buf[2*1024]; uint8_t raddr[Pasize]; Bnet *bn, **l; Udphdr *up; Rip *r; Ripmsg *m; Route route; static long btime; setnetmtpt(netdir, sizeof(netdir), nil); dobroadcast = 0; ARGBEGIN{ case 'b': dobroadcast++; break; case 'd': debug++; break; case 'n': readonly++; break; case 'x': p = ARGF(); if(p == nil) usage(); setnetmtpt(netdir, sizeof(netdir), p); break; default: usage(); }ARGEND /* specific broadcast nets */ l = &bnets; while(argc > 0){ bn = (Bnet*)malloc(sizeof(Bnet)); if(bn == 0) fatal(1, "out of mem"); v4parseip(bn->addr, *argv); *l = bn; l = &bn->next; argc--; argv++; dobroadcast++; } /* command returns */ if(!debug) switch(rfork(RFNOTEG|RFPROC|RFFDG|RFNOWAIT)) { case -1: fatal(1, "fork"); case 0: break; default: exits(0); } fmtinstall('E', eipfmt); fmtinstall('V', eipfmt); snprint(routefile, sizeof(routefile), "%s/iproute", netdir); snprint(buf, sizeof(buf), "%s/iproute", netdir); now = time(0); readifcs(); readroutes(); notify(ding); ripfd = openport(); for(;;) { diff = btime - time(0); if(diff <= 0){ if(dobroadcast) broadcast(); timeoutroutes(); btime = time(0) + 2*60; diff = 2*60; } alarm(diff*1000); n = read(ripfd, buf, sizeof(buf)); alarm(0); if(n <= 0) continue; n = (n - Udphdrsize - 4) / sizeof(Rip); if(n <= 0) continue; up = (Udphdr*)buf; m = (Ripmsg*)(buf+Udphdrsize); if(m->type != Response || m->vers != Version) continue; v6tov4(raddr, up->raddr); /* ignore our own messages */ for(i = 0; i < ialloc.nifc; i++) if(equivip(ialloc.ifc[i].addr, raddr)) continue; now = time(0); for(r = m->rip; r < &m->rip[n]; r++){ memmove(route.gate, raddr, Pasize); memmove(route.mask, getmask(r->addr), Pasize); v4maskip(r->addr, route.mask, route.dest); route.metric = nhgetl(r->metric) + 1; if(route.metric < 1) continue; considerroute(&route); } } /* not reached */ }