static void ipifcregisterproxy(Fs *f, Ipifc *ifc, uint8_t *ip) { Conv **cp, **e; Ipifc *nifc; Iplifc *lifc; Medium *m; uint8_t net[IPaddrlen]; /* register the address on any network that will proxy for us */ e = &f->ipifc->conv[f->ipifc->nc]; if(!isv4(ip)) { /* V6 */ for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc) continue; rlock(nifc); m = nifc->medium; if(m == nil || m->addmulti == nil) { runlock(nifc); continue; } for(lifc = nifc->lifc; lifc; lifc = lifc->next){ maskip(ip, lifc->mask, net); if(ipcmp(net, lifc->remote) == 0) { /* add solicited-node multicast addr */ ipv62smcast(net, ip); addselfcache(f, nifc, lifc, net, Rmulti); arpenter(f, V6, ip, nifc->mac, 6, 0); // (*m->addmulti)(nifc, net, ip); break; } } runlock(nifc); } } else { /* V4 */ for(cp = f->ipifc->conv; cp < e; cp++){ if(*cp == nil || (nifc = (Ipifc*)(*cp)->ptcl) == ifc) continue; rlock(nifc); m = nifc->medium; if(m == nil || m->areg == nil){ runlock(nifc); continue; } for(lifc = nifc->lifc; lifc; lifc = lifc->next){ maskip(ip, lifc->mask, net); if(ipcmp(net, lifc->remote) == 0){ (*m->areg)(nifc, ip); break; } } runlock(nifc); } } }
/* * find first ip addr suitable for proto and * that isn't the friggin loopback address. * deprecate link-local and multicast addresses. */ static int myipvnaddr(uint8_t *ip, struct proto *proto, char *net) { int ipisv4, wantv4; struct ipifc *nifc; struct iplifc *lifc; uint8_t mynet[IPaddrlen], linklocal[IPaddrlen]; static struct ipifc *ifc; ipmove(linklocal, IPnoaddr); wantv4 = proto->version == 4; ifc = readipifc(net, ifc, -1); for(nifc = ifc; nifc; nifc = nifc->next) for(lifc = nifc->lifc; lifc; lifc = lifc->next){ maskip(lifc->ip, loopbackmask, mynet); if(ipcmp(mynet, loopbacknet) == 0) continue; if(ISIPV6MCAST(lifc->ip) || ISIPV6LINKLOCAL(lifc->ip)) { ipmove(linklocal, lifc->ip); continue; } ipisv4 = isv4(lifc->ip) != 0; if(ipcmp(lifc->ip, IPnoaddr) != 0 && wantv4 == ipisv4){ ipmove(ip, lifc->ip); return 0; } } /* no global unicast addrs found, fall back to link-local, if any */ ipmove(ip, linklocal); return ipcmp(ip, IPnoaddr) == 0? -1: 0; }
/* * 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; }
// find first ip addr that isn't the friggin loopback address // unless there are no others int myipaddr(uchar *ip, char *net) { Ipifc *nifc; Iplifc *lifc; static Ipifc *ifc; uchar mynet[IPaddrlen]; ifc = readipifc(net, ifc, -1); for(nifc = ifc; nifc; nifc = nifc->next) for(lifc = nifc->lifc; lifc; lifc = lifc->next){ /* unspecified */ if(ipcmp(lifc->ip, IPnoaddr) == 0) continue; /* ipv6 loopback */ if(ipcmp(lifc->ip, loopback6) == 0) continue; /* ipv4 loopback */ maskip(lifc->ip, loopbackmask, mynet); if(ipcmp(mynet, loopbacknet) == 0) continue; ipmove(ip, lifc->ip); return 0; } ipmove(ip, IPnoaddr); return -1; }
/* * find the ifc on same net as the remote system. If none, * return NULL. */ struct Ipifc *findipifc(struct Fs *f, uint8_t * remote, int type) { struct Ipifc *ifc, *x; struct Iplifc *lifc; struct conv **cp, **e; uint8_t gnet[IPaddrlen]; uint8_t xmask[IPaddrlen]; x = NULL; memset(xmask, 0, IPaddrlen); /* find most specific match */ e = &f->ipifc->conv[f->ipifc->nc]; for (cp = f->ipifc->conv; cp < e; cp++) { if (*cp == 0) continue; ifc = (struct Ipifc *)(*cp)->ptcl; for (lifc = ifc->lifc; lifc; lifc = lifc->next) { maskip(remote, lifc->mask, gnet); if (ipcmp(gnet, lifc->net) == 0) { if (x == NULL || ipcmp(lifc->mask, xmask) > 0) { x = ifc; ipmove(xmask, lifc->mask); } } } } if (x != NULL) return x; /* for now for broadcast and multicast, just use first interface */ if (type & (Rbcast | Rmulti)) { for (cp = f->ipifc->conv; cp < e; cp++) { if (*cp == 0) continue; ifc = (struct Ipifc *)(*cp)->ptcl; if (ifc->lifc != NULL) return ifc; } } return NULL; }
Iplifc* findlifc(uchar *ip) { uchar x[IPaddrlen]; Ipifc *ifc; Iplifc *lifc; for(ifc = ipifcs; ifc; ifc = ifc->next){ for(lifc = ifc->lifc; lifc != nil; lifc = lifc->next){ if(lifc->net[0] == 0) continue; maskip(ip, lifc->mask, x); if(memcmp(x, lifc->net, IPaddrlen) == 0) return lifc; } } return nil; }
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); }
/* * See if we're proxying for this address on this interface */ int ipproxyifc(Fs *f, Ipifc *ifc, uint8_t *ip) { Route *r; uint8_t net[IPaddrlen]; Iplifc *lifc; /* see if this is a direct connected pt to pt address */ r = v6lookup(f, ip, nil); if(r == nil || (r->type & (Rifc|Rproxy)) != (Rifc|Rproxy)) return 0; /* see if this is on the right interface */ for(lifc = ifc->lifc; lifc; lifc = lifc->next){ maskip(ip, lifc->mask, net); if(ipcmp(net, lifc->remote) == 0) return 1; } return 0; }
/* * 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; }
/* * lookup a subnet and fill in anything we can */ static void recursesubnet(Ndb *db, uint8_t *mask, Ipinfo *iip, char *fs, char *gw, char *au) { Ndbs s; Ndbtuple *t; uint8_t submask[IPaddrlen]; char ip[Ndbvlen]; memmove(iip->ipmask, mask, 4); maskip(iip->ipaddr, iip->ipmask, iip->ipnet); sprint(ip, "%I", iip->ipnet); t = ndbsearch(db, &s, "ip", ip); print("%s->", ip); if(t){ /* look for a further subnet */ if(lookval(t, s.t, "ipmask", ip)){ parseip(submask, ip); /* recurse only if it has changed */ if(!equivip(submask, mask)) recursesubnet(db, submask, iip, fs, gw, au); } /* fill in what we don't have */ if(gw[0] == 0) lookval(t, s.t, "ipgw", gw); if(fs[0] == 0) lookval(t, s.t, "fs", fs); if(au[0] == 0) lookval(t, s.t, "auth", au); ndbfree(t); } }
/* * add an address to an interface. */ char* ipifcadd(Ipifc *ifc, char **argv, int argc, int tentative, Iplifc *lifcp) { int i, type, mtu, sendnbrdisc = 0; uint8_t ip[IPaddrlen], mask[IPaddrlen], rem[IPaddrlen]; uint8_t bcast[IPaddrlen], net[IPaddrlen]; Iplifc *lifc, **l; Fs *f; if(ifc->medium == nil) return "ipifc not yet bound to device"; f = ifc->conv->p->f; type = Rifc; memset(ip, 0, IPaddrlen); memset(mask, 0, IPaddrlen); memset(rem, 0, IPaddrlen); switch(argc){ case 6: if(strcmp(argv[5], "proxy") == 0) type |= Rproxy; /* fall through */ case 5: mtu = strtoul(argv[4], 0, 0); if(mtu >= ifc->medium->mintu && mtu <= ifc->medium->maxtu) ifc->maxtu = mtu; /* fall through */ case 4: if (parseip(ip, argv[1]) == -1 || parseip(rem, argv[3]) == -1) return Ebadip; parseipmask(mask, argv[2]); maskip(rem, mask, net); break; case 3: if (parseip(ip, argv[1]) == -1) return Ebadip; parseipmask(mask, argv[2]); maskip(ip, mask, rem); maskip(rem, mask, net); break; case 2: if (parseip(ip, argv[1]) == -1) return Ebadip; memmove(mask, defmask(ip), IPaddrlen); maskip(ip, mask, rem); maskip(rem, mask, net); break; default: return Ebadarg; } if(isv4(ip)) tentative = 0; wlock(ifc); /* ignore if this is already a local address for this ifc */ for(lifc = ifc->lifc; lifc; lifc = lifc->next) { if(ipcmp(lifc->local, ip) == 0) { if(lifc->tentative != tentative) lifc->tentative = tentative; if(lifcp) { lifc->onlink = lifcp->onlink; lifc->autoflag = lifcp->autoflag; lifc->validlt = lifcp->validlt; lifc->preflt = lifcp->preflt; lifc->origint = lifcp->origint; } goto out; } } /* add the address to the list of logical ifc's for this ifc */ lifc = smalloc(sizeof(Iplifc)); ipmove(lifc->local, ip); ipmove(lifc->mask, mask); ipmove(lifc->remote, rem); ipmove(lifc->net, net); lifc->tentative = tentative; if(lifcp) { lifc->onlink = lifcp->onlink; lifc->autoflag = lifcp->autoflag; lifc->validlt = lifcp->validlt; lifc->preflt = lifcp->preflt; lifc->origint = lifcp->origint; } else { /* default values */ lifc->onlink = lifc->autoflag = 1; lifc->validlt = lifc->preflt = ~0L; lifc->origint = NOW / 1000; } lifc->next = nil; for(l = &ifc->lifc; *l; l = &(*l)->next) ; *l = lifc; /* check for point-to-point interface */ if(ipcmp(ip, v6loopback)) /* skip v6 loopback, it's a special address */ if(ipcmp(mask, IPallbits) == 0) type |= Rptpt; /* add local routes */ if(isv4(ip)) v4addroute(f, tifc, rem+IPv4off, mask+IPv4off, rem+IPv4off, type); else v6addroute(f, tifc, rem, mask, rem, type); addselfcache(f, ifc, lifc, ip, Runi); if((type & (Rproxy|Rptpt)) == (Rproxy|Rptpt)){ ipifcregisterproxy(f, ifc, rem); goto out; } if(isv4(ip) || ipcmp(ip, IPnoaddr) == 0) { /* add subnet directed broadcast address to the self cache */ for(i = 0; i < IPaddrlen; i++) bcast[i] = (ip[i] & mask[i]) | ~mask[i]; addselfcache(f, ifc, lifc, bcast, Rbcast); /* add subnet directed network address to the self cache */ for(i = 0; i < IPaddrlen; i++) bcast[i] = (ip[i] & mask[i]) & mask[i]; addselfcache(f, ifc, lifc, bcast, Rbcast); /* add network directed broadcast address to the self cache */ memmove(mask, defmask(ip), IPaddrlen); for(i = 0; i < IPaddrlen; i++) bcast[i] = (ip[i] & mask[i]) | ~mask[i]; addselfcache(f, ifc, lifc, bcast, Rbcast); /* add network directed network address to the self cache */ memmove(mask, defmask(ip), IPaddrlen); for(i = 0; i < IPaddrlen; i++) bcast[i] = (ip[i] & mask[i]) & mask[i]; addselfcache(f, ifc, lifc, bcast, Rbcast); addselfcache(f, ifc, lifc, IPv4bcast, Rbcast); } else { if(ipcmp(ip, v6loopback) == 0) { /* add node-local mcast address */ addselfcache(f, ifc, lifc, v6allnodesN, Rmulti); /* add route for all node multicast */ v6addroute(f, tifc, v6allnodesN, v6allnodesNmask, v6allnodesN, Rmulti); } /* add all nodes multicast address */ addselfcache(f, ifc, lifc, v6allnodesL, Rmulti); /* add route for all nodes multicast */ v6addroute(f, tifc, v6allnodesL, v6allnodesLmask, v6allnodesL, Rmulti); /* add solicited-node multicast address */ ipv62smcast(bcast, ip); addselfcache(f, ifc, lifc, bcast, Rmulti); sendnbrdisc = 1; } /* register the address on this network for address resolution */ if(isv4(ip) && ifc->medium->areg != nil) (*ifc->medium->areg)(ifc, ip); out: wunlock(ifc); if(tentative && sendnbrdisc) icmpns(f, 0, SRC_UNSPEC, ip, TARG_MULTI, ifc->mac); return nil; }
/* * find the local address 'closest' to the remote system, copy it to * local and return the ifc for that address */ void findlocalip(Fs *f, uint8_t *local, uint8_t *remote) { int version, atype = unspecifiedv6, atypel = unknownv6; int atyper, deprecated; uint8_t gate[IPaddrlen], gnet[IPaddrlen]; Ipifc *ifc; Iplifc *lifc; Route *r; USED(atype); USED(atypel); qlock(f->ipifc); r = v6lookup(f, remote, nil); version = (memcmp(remote, v4prefix, IPv4off) == 0)? V4: V6; if(r != nil){ ifc = r->ifc; if(r->type & Rv4) v4tov6(gate, r->v4.gate); else { ipmove(gate, r->v6.gate); ipmove(local, v6Unspecified); } switch(version) { case V4: /* find ifc address closest to the gateway to use */ for(lifc = ifc->lifc; lifc; lifc = lifc->next){ maskip(gate, lifc->mask, gnet); if(ipcmp(gnet, lifc->net) == 0){ ipmove(local, lifc->local); goto out; } } break; case V6: /* find ifc address with scope matching the destination */ atyper = v6addrtype(remote); deprecated = 0; for(lifc = ifc->lifc; lifc; lifc = lifc->next){ atypel = v6addrtype(lifc->local); /* prefer appropriate scope */ if(atypel > atype && atype < atyper || atypel < atype && atype > atyper){ ipmove(local, lifc->local); deprecated = !v6addrcurr(lifc); atype = atypel; } else if(atypel == atype){ /* avoid deprecated addresses */ if(deprecated && v6addrcurr(lifc)){ ipmove(local, lifc->local); atype = atypel; deprecated = 0; } } if(atype == atyper && !deprecated) goto out; } if(atype >= atyper) goto out; break; default: panic("findlocalip: version %d", version); } } switch(version){ case V4: findprimaryipv4(f, local); break; case V6: findprimaryipv6(f, local); break; default: panic("findlocalip2: version %d", version); } out: qunlock(f->ipifc); }
static void ipifcregisterproxy(struct Fs *f, struct Ipifc *ifc, uint8_t * ip) { struct conv **cp, **e; struct Ipifc *nifc; struct Iplifc *lifc; struct medium *m; uint8_t net[IPaddrlen]; /* register the address on any network that will proxy for us */ e = &f->ipifc->conv[f->ipifc->nc]; if (!isv4(ip)) { // V6 for (cp = f->ipifc->conv; cp < e; cp++) { if (*cp == NULL) continue; nifc = (struct Ipifc *)(*cp)->ptcl; if (nifc == ifc) continue; rlock(&nifc->rwlock); m = nifc->m; if (m == NULL || m->addmulti == NULL) { runlock(&nifc->rwlock); continue; } for (lifc = nifc->lifc; lifc; lifc = lifc->next) { maskip(ip, lifc->mask, net); if (ipcmp(net, lifc->remote) == 0) { /* add solicited-node multicast address */ ipv62smcast(net, ip); addselfcache(f, nifc, lifc, net, Rmulti); arpenter(f, V6, ip, nifc->mac, 6, 0); //(*m->addmulti)(nifc, net, ip); break; } } runlock(&nifc->rwlock); } return; } else { // V4 for (cp = f->ipifc->conv; cp < e; cp++) { if (*cp == NULL) continue; nifc = (struct Ipifc *)(*cp)->ptcl; if (nifc == ifc) continue; rlock(&nifc->rwlock); m = nifc->m; if (m == NULL || m->areg == NULL) { runlock(&nifc->rwlock); continue; } for (lifc = nifc->lifc; lifc; lifc = lifc->next) { maskip(ip, lifc->mask, net); if (ipcmp(net, lifc->remote) == 0) { (*m->areg) (nifc, ip); break; } } runlock(&nifc->rwlock); } } }
/* * find the local address 'closest' to the remote system, copy it to * local and return the ifc for that address */ void findlocalip(struct Fs *f, uint8_t * local, uint8_t * remote) { struct Ipifc *ifc; struct Iplifc *lifc; struct route *r; uint8_t gate[IPaddrlen]; uint8_t gnet[IPaddrlen]; int version; int atype = unspecifiedv6, atypel = unknownv6; qlock(&f->ipifc->qlock); r = v6lookup(f, remote, NULL); version = isv4(remote) ? V4 : V6; if (r != NULL) { ifc = r->rt.ifc; if (r->rt.type & Rv4) v4tov6(gate, r->v4.gate); else { ipmove(gate, r->v6.gate); ipmove(local, v6Unspecified); } /* find ifc address closest to the gateway to use */ switch (version) { case V4: for (lifc = ifc->lifc; lifc; lifc = lifc->next) { maskip(gate, lifc->mask, gnet); if (ipcmp(gnet, lifc->net) == 0) { ipmove(local, lifc->local); goto out; } } break; case V6: for (lifc = ifc->lifc; lifc; lifc = lifc->next) { atypel = v6addrtype(lifc->local); maskip(gate, lifc->mask, gnet); if (ipcmp(gnet, lifc->net) == 0) if (atypel > atype) if (v6addrcurr(lifc)) { ipmove(local, lifc->local); atype = atypel; if (atype == globalv6) break; } } if (atype > unspecifiedv6) goto out; break; default: panic("findlocalip: version %d", version); } } switch (version) { case V4: findprimaryipv4(f, local); break; case V6: findprimaryipv6(f, local); break; default: panic("findlocalip2: version %d", version); } out: qunlock(&f->ipifc->qlock); }
/* * lookup (and translate) an ip destination */ static struct ndbtuple *iplookup(struct network *np, char *host, char *serv, int nolookup) { char *attr, *dnsname; struct ndbtuple *t, *nt; struct ndbs s; char ts[Maxservice]; char dollar[Maxhost]; uint8_t ip[IPaddrlen]; uint8_t net[IPaddrlen]; uint8_t tnet[IPaddrlen]; struct ipifc *ifc; struct iplifc *lifc; /* * 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", NULL); 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 */ spinlock_lock(&ipifclock); for (ifc = ipifcs; ifc != NULL; ifc = ifc->next) { for (lifc = ifc->lifc; lifc != NULL; 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); spinlock_unlock(&ipifclock); return t; } } } } spinlock_unlock(&ipifclock); return t; }
/* * do an ipinfo with defaults */ int lookupip(uchar *ipaddr, Info *iip, int gate) { char ip[32]; Ndbtuple *t, *nt; char *attrs[32], **p; if(opendb() == nil){ warning(1, "can't open db"); return -1; } p = attrs; *p++ = "ip"; *p++ = "ipmask"; *p++ = "@ipgw"; if(!gate){ *p++ = "bootf"; *p++ = "bootf2"; *p++ = "@tftp"; *p++ = "@tftp2"; *p++ = "rootpath"; *p++ = "dhcp"; *p++ = "vendorclass"; *p++ = "ether"; *p++ = "dom"; *p++ = "@fs"; *p++ = "@auth"; } *p = 0; memset(iip, 0, sizeof(*iip)); snprint(ip, sizeof(ip), "%I", ipaddr); t = ndbipinfo(db, "ip", ip, attrs, p - attrs); if(t == nil) return -1; for(nt = t; nt != nil; nt = nt->entry){ if(strcmp(nt->attr, "ip") == 0) setipaddr(iip->ipaddr, nt->val); else if(strcmp(nt->attr, "ipmask") == 0) setipmask(iip->ipmask, nt->val); else if(strcmp(nt->attr, "fs") == 0) setipaddr(iip->fsip, nt->val); else if(strcmp(nt->attr, "auth") == 0) setipaddr(iip->auip, nt->val); else if(strcmp(nt->attr, "tftp") == 0) setipaddr(iip->tftp, nt->val); else if(strcmp(nt->attr, "tftp2") == 0) setipaddr(iip->tftp2, nt->val); else if(strcmp(nt->attr, "ipgw") == 0) setipaddr(iip->gwip, nt->val); else if(strcmp(nt->attr, "ether") == 0){ /* * this is probably wrong for machines with multiple * ethers. bootp or dhcp requests could come from any * of the ethers listed in the ndb entry. */ if(memcmp(iip->etheraddr, noetheraddr, 6) == 0) parseether(iip->etheraddr, nt->val); iip->indb = 1; } else if(strcmp(nt->attr, "dhcp") == 0){ if(iip->dhcpgroup[0] == 0) strcpy(iip->dhcpgroup, nt->val); } else if(strcmp(nt->attr, "bootf") == 0){ if(iip->bootf[0] == 0) strcpy(iip->bootf, nt->val); } else if(strcmp(nt->attr, "bootf2") == 0){ if(iip->bootf2[0] == 0) strcpy(iip->bootf2, nt->val); } else if(strcmp(nt->attr, "vendor") == 0){ if(iip->vendor[0] == 0) strcpy(iip->vendor, nt->val); } else if(strcmp(nt->attr, "dom") == 0){ if(iip->domain[0] == 0) strcpy(iip->domain, nt->val); } else if(strcmp(nt->attr, "rootpath") == 0){ if(iip->rootpath[0] == 0) strcpy(iip->rootpath, nt->val); } } ndbfree(t); maskip(iip->ipaddr, iip->ipmask, iip->ipnet); return 0; }