merge
This commit is contained in:
commit
8f91d94d19
18 changed files with 2077 additions and 1891 deletions
|
@ -88,8 +88,8 @@ enum {
|
||||||
V6nd_home = 8,
|
V6nd_home = 8,
|
||||||
V6nd_srcaddrs = 9, /* rfc3122 */
|
V6nd_srcaddrs = 9, /* rfc3122 */
|
||||||
V6nd_ip = 17,
|
V6nd_ip = 17,
|
||||||
/* /lib/rfc/drafts/draft-jeong-dnsop-ipv6-dns-discovery-12.txt */
|
V6nd_rdns = 25, /* rfc6106 */
|
||||||
V6nd_rdns = 25,
|
V6nd_rdnssl = 31,
|
||||||
/* plan 9 extensions */
|
/* plan 9 extensions */
|
||||||
V6nd_9fs = 250,
|
V6nd_9fs = 250,
|
||||||
V6nd_9auth = 251,
|
V6nd_9auth = 251,
|
||||||
|
|
979
sys/src/cmd/ip/ipconfig/dhcp.c
Normal file
979
sys/src/cmd/ip/ipconfig/dhcp.c
Normal file
|
@ -0,0 +1,979 @@
|
||||||
|
/*
|
||||||
|
* ipconfig - configure parameters of an ip stack
|
||||||
|
*/
|
||||||
|
#include <u.h>
|
||||||
|
#include <libc.h>
|
||||||
|
#include <bio.h>
|
||||||
|
#include <ip.h>
|
||||||
|
#include <ndb.h>
|
||||||
|
#include "ipconfig.h"
|
||||||
|
#include "../dhcp.h"
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
Taddr,
|
||||||
|
Taddrs,
|
||||||
|
Tstr,
|
||||||
|
Tbyte,
|
||||||
|
Tulong,
|
||||||
|
Tvec,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct Option Option;
|
||||||
|
struct Option
|
||||||
|
{
|
||||||
|
char *name;
|
||||||
|
int type;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* I was too lazy to look up the types for each of these
|
||||||
|
* options. If someone feels like it, please mail me a
|
||||||
|
* corrected array -- presotto
|
||||||
|
*/
|
||||||
|
static Option option[256] =
|
||||||
|
{
|
||||||
|
[OBmask] { "ipmask", Taddr },
|
||||||
|
[OBtimeoff] { "timeoff", Tulong },
|
||||||
|
[OBrouter] { "ipgw", Taddrs },
|
||||||
|
[OBtimeserver] { "time", Taddrs },
|
||||||
|
[OBnameserver] { "name", Taddrs },
|
||||||
|
[OBdnserver] { "dns", Taddrs },
|
||||||
|
[OBlogserver] { "log", Taddrs },
|
||||||
|
[OBcookieserver] { "cookie", Taddrs },
|
||||||
|
[OBlprserver] { "lpr", Taddrs },
|
||||||
|
[OBimpressserver] { "impress", Taddrs },
|
||||||
|
[OBrlserver] { "rl", Taddrs },
|
||||||
|
[OBhostname] { "sys", Tstr },
|
||||||
|
[OBbflen] { "bflen", Tulong },
|
||||||
|
[OBdumpfile] { "dumpfile", Tstr },
|
||||||
|
[OBdomainname] { "dom", Tstr },
|
||||||
|
[OBswapserver] { "swap", Taddrs },
|
||||||
|
[OBrootpath] { "rootpath", Tstr },
|
||||||
|
[OBextpath] { "extpath", Tstr },
|
||||||
|
[OBipforward] { "ipforward", Taddrs },
|
||||||
|
[OBnonlocal] { "nonlocal", Taddrs },
|
||||||
|
[OBpolicyfilter] { "policyfilter", Taddrs },
|
||||||
|
[OBmaxdatagram] { "maxdatagram", Tulong },
|
||||||
|
[OBttl] { "ttl", Tulong },
|
||||||
|
[OBpathtimeout] { "pathtimeout", Taddrs },
|
||||||
|
[OBpathplateau] { "pathplateau", Taddrs },
|
||||||
|
[OBmtu] { "mtu", Tulong },
|
||||||
|
[OBsubnetslocal] { "subnetslocal", Taddrs },
|
||||||
|
[OBbaddr] { "baddr", Taddrs },
|
||||||
|
[OBdiscovermask] { "discovermask", Taddrs },
|
||||||
|
[OBsupplymask] { "supplymask", Taddrs },
|
||||||
|
[OBdiscoverrouter] { "discoverrouter", Taddrs },
|
||||||
|
[OBrsserver] { "rs", Taddrs },
|
||||||
|
[OBstaticroutes] { "staticroutes", Taddrs },
|
||||||
|
[OBtrailerencap] { "trailerencap", Taddrs },
|
||||||
|
[OBarptimeout] { "arptimeout", Tulong },
|
||||||
|
[OBetherencap] { "etherencap", Taddrs },
|
||||||
|
[OBtcpttl] { "tcpttl", Tulong },
|
||||||
|
[OBtcpka] { "tcpka", Tulong },
|
||||||
|
[OBtcpkag] { "tcpkag", Tulong },
|
||||||
|
[OBnisdomain] { "nisdomain", Tstr },
|
||||||
|
[OBniserver] { "ni", Taddrs },
|
||||||
|
[OBntpserver] { "ntp", Taddrs },
|
||||||
|
[OBnetbiosns] { "netbiosns", Taddrs },
|
||||||
|
[OBnetbiosdds] { "netbiosdds", Taddrs },
|
||||||
|
[OBnetbiostype] { "netbiostype", Taddrs },
|
||||||
|
[OBnetbiosscope] { "netbiosscope", Taddrs },
|
||||||
|
[OBxfontserver] { "xfont", Taddrs },
|
||||||
|
[OBxdispmanager] { "xdispmanager", Taddrs },
|
||||||
|
[OBnisplusdomain] { "nisplusdomain", Tstr },
|
||||||
|
[OBnisplusserver] { "nisplus", Taddrs },
|
||||||
|
[OBhomeagent] { "homeagent", Taddrs },
|
||||||
|
[OBsmtpserver] { "smtp", Taddrs },
|
||||||
|
[OBpop3server] { "pop3", Taddrs },
|
||||||
|
[OBnntpserver] { "nntp", Taddrs },
|
||||||
|
[OBwwwserver] { "www", Taddrs },
|
||||||
|
[OBfingerserver] { "finger", Taddrs },
|
||||||
|
[OBircserver] { "irc", Taddrs },
|
||||||
|
[OBstserver] { "st", Taddrs },
|
||||||
|
[OBstdaserver] { "stdar", Taddrs },
|
||||||
|
|
||||||
|
[ODipaddr] { "ipaddr", Taddr },
|
||||||
|
[ODlease] { "lease", Tulong },
|
||||||
|
[ODoverload] { "overload", Taddr },
|
||||||
|
[ODtype] { "type", Tbyte },
|
||||||
|
[ODserverid] { "serverid", Taddr },
|
||||||
|
[ODparams] { "params", Tvec },
|
||||||
|
[ODmessage] { "message", Tstr },
|
||||||
|
[ODmaxmsg] { "maxmsg", Tulong },
|
||||||
|
[ODrenewaltime] { "renewaltime", Tulong },
|
||||||
|
[ODrebindingtime] { "rebindingtime", Tulong },
|
||||||
|
[ODvendorclass] { "vendorclass", Tvec },
|
||||||
|
[ODclientid] { "clientid", Tvec },
|
||||||
|
[ODtftpserver] { "tftp", Taddr },
|
||||||
|
[ODbootfile] { "bootfile", Tstr },
|
||||||
|
};
|
||||||
|
|
||||||
|
static uchar defrequested[] = {
|
||||||
|
OBmask, OBrouter, OBdnserver, OBhostname, OBdomainname, OBntpserver,
|
||||||
|
};
|
||||||
|
|
||||||
|
static uchar requested[256];
|
||||||
|
static int nrequested;
|
||||||
|
|
||||||
|
static char optmagic[4] = { 0x63, 0x82, 0x53, 0x63 };
|
||||||
|
|
||||||
|
static int openlisten(void);
|
||||||
|
|
||||||
|
static void dhcprecv(void);
|
||||||
|
static void dhcpsend(int);
|
||||||
|
static void dhcptimer(void);
|
||||||
|
|
||||||
|
static uchar* optaddaddr(uchar*, int, uchar*);
|
||||||
|
static uchar* optaddbyte(uchar*, int, int);
|
||||||
|
static uchar* optaddstr(uchar*, int, char*);
|
||||||
|
static uchar* optadd(uchar*, int, void*, int);
|
||||||
|
static uchar* optaddulong(uchar*, int, ulong);
|
||||||
|
static uchar* optaddvec(uchar*, int, uchar*, int);
|
||||||
|
static int optgetaddrs(uchar*, int, uchar*, int);
|
||||||
|
static int optgetp9addrs(uchar*, int, uchar*, int);
|
||||||
|
static int optgetaddr(uchar*, int, uchar*);
|
||||||
|
static int optgetbyte(uchar*, int);
|
||||||
|
static int optgetstr(uchar*, int, char*, int);
|
||||||
|
static uchar* optget(uchar*, int, int*);
|
||||||
|
static ulong optgetulong(uchar*, int);
|
||||||
|
static int optgetvec(uchar*, int, uchar*, int);
|
||||||
|
static char* optgetx(uchar*, uchar);
|
||||||
|
|
||||||
|
static void getoptions(uchar*);
|
||||||
|
static int parseoptions(uchar *p, int n);
|
||||||
|
static Bootp* parsebootp(uchar*, int);
|
||||||
|
|
||||||
|
void
|
||||||
|
dhcpinit(void)
|
||||||
|
{
|
||||||
|
/* init set of requested dhcp parameters with the default */
|
||||||
|
nrequested = sizeof defrequested;
|
||||||
|
memcpy(requested, defrequested, nrequested);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
dhcpquery(int needconfig, int startstate)
|
||||||
|
{
|
||||||
|
if(needconfig)
|
||||||
|
fprint(conf.cfd, "add %I %I", IPnoaddr, IPnoaddr);
|
||||||
|
|
||||||
|
conf.fd = openlisten();
|
||||||
|
if(conf.fd < 0){
|
||||||
|
conf.state = Sinit;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
notify(catch);
|
||||||
|
|
||||||
|
conf.xid = lrand();
|
||||||
|
conf.starttime = time(0);
|
||||||
|
conf.state = startstate;
|
||||||
|
switch(startstate){
|
||||||
|
case Sselecting:
|
||||||
|
conf.offered = 0;
|
||||||
|
dhcpsend(Discover);
|
||||||
|
break;
|
||||||
|
case Srenewing:
|
||||||
|
dhcpsend(Request);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
sysfatal("internal error 0");
|
||||||
|
}
|
||||||
|
conf.resend = 0;
|
||||||
|
conf.timeout = time(0) + 4;
|
||||||
|
|
||||||
|
while(conf.state != Sbound && conf.state != Sinit){
|
||||||
|
dhcprecv();
|
||||||
|
dhcptimer();
|
||||||
|
}
|
||||||
|
close(conf.fd);
|
||||||
|
|
||||||
|
if(needconfig)
|
||||||
|
fprint(conf.cfd, "remove %I %I", IPnoaddr, IPnoaddr);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
enum {
|
||||||
|
/*
|
||||||
|
* was an hour, needs to be less for the ARM/GS1 until the timer
|
||||||
|
* code has been cleaned up (pb).
|
||||||
|
*/
|
||||||
|
Maxsleep = 450,
|
||||||
|
};
|
||||||
|
|
||||||
|
void
|
||||||
|
dhcpwatch(int needconfig)
|
||||||
|
{
|
||||||
|
ulong secs, s, t;
|
||||||
|
|
||||||
|
if(nodhcpwatch)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(rfork(RFPROC|RFFDG|RFNOWAIT|RFNOTEG)){
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
case 0:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dolog = 1; /* log, don't print */
|
||||||
|
procsetname("dhcpwatch on %s", conf.dev);
|
||||||
|
/* keep trying to renew the lease */
|
||||||
|
for(;;){
|
||||||
|
secs = conf.lease/2;
|
||||||
|
if(secs < 5)
|
||||||
|
secs = 5;
|
||||||
|
|
||||||
|
/* avoid overflows */
|
||||||
|
for(s = secs; s > 0; s -= t){
|
||||||
|
if(s > Maxsleep)
|
||||||
|
t = Maxsleep;
|
||||||
|
else
|
||||||
|
t = s;
|
||||||
|
sleep(t*1000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conf.lease > 0){
|
||||||
|
/*
|
||||||
|
* during boot, the starttime can be bogus so avoid
|
||||||
|
* spurious ipunconfig's
|
||||||
|
*/
|
||||||
|
t = time(0) - conf.starttime;
|
||||||
|
if(t > (3*secs)/2)
|
||||||
|
t = secs;
|
||||||
|
if(t >= conf.lease){
|
||||||
|
conf.lease = 0;
|
||||||
|
if(!noconfig){
|
||||||
|
ipunconfig();
|
||||||
|
needconfig = 1;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
conf.lease -= t;
|
||||||
|
}
|
||||||
|
dhcpquery(needconfig, needconfig? Sselecting: Srenewing);
|
||||||
|
|
||||||
|
if(needconfig && conf.state == Sbound){
|
||||||
|
if(ip4cfg() < 0)
|
||||||
|
sysfatal("can't start ip: %r");
|
||||||
|
needconfig = 0;
|
||||||
|
/*
|
||||||
|
* leave everything we've learned somewhere that
|
||||||
|
* other procs can find it.
|
||||||
|
*/
|
||||||
|
if(beprimary)
|
||||||
|
putndb();
|
||||||
|
refresh();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dhcptimer(void)
|
||||||
|
{
|
||||||
|
ulong now;
|
||||||
|
|
||||||
|
now = time(0);
|
||||||
|
if(now < conf.timeout)
|
||||||
|
return;
|
||||||
|
|
||||||
|
switch(conf.state) {
|
||||||
|
default:
|
||||||
|
sysfatal("dhcptimer: unknown state %d", conf.state);
|
||||||
|
case Sinit:
|
||||||
|
case Sbound:
|
||||||
|
break;
|
||||||
|
case Sselecting:
|
||||||
|
case Srequesting:
|
||||||
|
case Srebinding:
|
||||||
|
dhcpsend(conf.state == Sselecting? Discover: Request);
|
||||||
|
conf.timeout = now + 4;
|
||||||
|
if(++conf.resend > 5)
|
||||||
|
conf.state = Sinit;
|
||||||
|
break;
|
||||||
|
case Srenewing:
|
||||||
|
dhcpsend(Request);
|
||||||
|
conf.timeout = now + 1;
|
||||||
|
if(++conf.resend > 3) {
|
||||||
|
conf.state = Srebinding;
|
||||||
|
conf.resend = 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dhcpsend(int type)
|
||||||
|
{
|
||||||
|
Bootp bp;
|
||||||
|
uchar *p;
|
||||||
|
int n;
|
||||||
|
uchar vendor[64];
|
||||||
|
Udphdr *up = (Udphdr*)bp.udphdr;
|
||||||
|
|
||||||
|
memset(&bp, 0, sizeof bp);
|
||||||
|
|
||||||
|
hnputs(up->rport, 67);
|
||||||
|
bp.op = Bootrequest;
|
||||||
|
hnputl(bp.xid, conf.xid);
|
||||||
|
hnputs(bp.secs, time(0)-conf.starttime);
|
||||||
|
hnputs(bp.flags, 0);
|
||||||
|
memmove(bp.optmagic, optmagic, 4);
|
||||||
|
if(conf.hwatype >= 0 && conf.hwalen < sizeof bp.chaddr){
|
||||||
|
memmove(bp.chaddr, conf.hwa, conf.hwalen);
|
||||||
|
bp.hlen = conf.hwalen;
|
||||||
|
bp.htype = conf.hwatype;
|
||||||
|
}
|
||||||
|
p = bp.optdata;
|
||||||
|
p = optaddbyte(p, ODtype, type);
|
||||||
|
p = optadd(p, ODclientid, conf.cid, conf.cidlen);
|
||||||
|
switch(type) {
|
||||||
|
default:
|
||||||
|
sysfatal("dhcpsend: unknown message type: %d", type);
|
||||||
|
case Discover:
|
||||||
|
ipmove(up->raddr, IPv4bcast); /* broadcast */
|
||||||
|
if(*conf.hostname && sendhostname)
|
||||||
|
p = optaddstr(p, OBhostname, conf.hostname);
|
||||||
|
if(plan9){
|
||||||
|
n = snprint((char*)vendor, sizeof vendor,
|
||||||
|
"plan9_%s", conf.cputype);
|
||||||
|
p = optaddvec(p, ODvendorclass, vendor, n);
|
||||||
|
}
|
||||||
|
p = optaddvec(p, ODparams, requested, nrequested);
|
||||||
|
if(validip(conf.laddr))
|
||||||
|
p = optaddaddr(p, ODipaddr, conf.laddr);
|
||||||
|
break;
|
||||||
|
case Request:
|
||||||
|
switch(conf.state){
|
||||||
|
case Srenewing:
|
||||||
|
ipmove(up->raddr, conf.server);
|
||||||
|
v6tov4(bp.ciaddr, conf.laddr);
|
||||||
|
break;
|
||||||
|
case Srebinding:
|
||||||
|
ipmove(up->raddr, IPv4bcast); /* broadcast */
|
||||||
|
v6tov4(bp.ciaddr, conf.laddr);
|
||||||
|
break;
|
||||||
|
case Srequesting:
|
||||||
|
ipmove(up->raddr, IPv4bcast); /* broadcast */
|
||||||
|
p = optaddaddr(p, ODipaddr, conf.laddr);
|
||||||
|
p = optaddaddr(p, ODserverid, conf.server);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
p = optaddulong(p, ODlease, conf.offered);
|
||||||
|
if(plan9){
|
||||||
|
n = snprint((char*)vendor, sizeof vendor,
|
||||||
|
"plan9_%s", conf.cputype);
|
||||||
|
p = optaddvec(p, ODvendorclass, vendor, n);
|
||||||
|
}
|
||||||
|
p = optaddvec(p, ODparams, requested, nrequested);
|
||||||
|
if(*conf.hostname && sendhostname)
|
||||||
|
p = optaddstr(p, OBhostname, conf.hostname);
|
||||||
|
break;
|
||||||
|
case Release:
|
||||||
|
ipmove(up->raddr, conf.server);
|
||||||
|
v6tov4(bp.ciaddr, conf.laddr);
|
||||||
|
p = optaddaddr(p, ODipaddr, conf.laddr);
|
||||||
|
p = optaddaddr(p, ODserverid, conf.server);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*p++ = OBend;
|
||||||
|
|
||||||
|
n = p - (uchar*)&bp;
|
||||||
|
USED(n);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We use a maximum size DHCP packet to survive the
|
||||||
|
* All_Aboard NAT package from Internet Share. It
|
||||||
|
* always replies to DHCP requests with a packet of the
|
||||||
|
* same size, so if the request is too short the reply
|
||||||
|
* is truncated.
|
||||||
|
*/
|
||||||
|
if(write(conf.fd, &bp, sizeof bp) != sizeof bp)
|
||||||
|
warning("dhcpsend: write failed: %r");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dhcprecv(void)
|
||||||
|
{
|
||||||
|
int i, n, type;
|
||||||
|
ulong lease;
|
||||||
|
char err[ERRMAX];
|
||||||
|
uchar buf[8000], vopts[256], taddr[IPaddrlen];
|
||||||
|
Bootp *bp;
|
||||||
|
|
||||||
|
memset(buf, 0, sizeof buf);
|
||||||
|
alarm(1000);
|
||||||
|
n = read(conf.fd, buf, sizeof buf);
|
||||||
|
alarm(0);
|
||||||
|
|
||||||
|
if(n < 0){
|
||||||
|
rerrstr(err, sizeof err);
|
||||||
|
if(strstr(err, "interrupt") == nil)
|
||||||
|
warning("dhcprecv: bad read: %s", err);
|
||||||
|
else
|
||||||
|
DEBUG("dhcprecv: read timed out");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bp = parsebootp(buf, n);
|
||||||
|
if(bp == 0) {
|
||||||
|
DEBUG("parsebootp failed: dropping packet");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
type = optgetbyte(bp->optdata, ODtype);
|
||||||
|
switch(type) {
|
||||||
|
default:
|
||||||
|
warning("dhcprecv: unknown type: %d", type);
|
||||||
|
break;
|
||||||
|
case Offer:
|
||||||
|
DEBUG("got offer from %V ", bp->siaddr);
|
||||||
|
if(conf.state != Sselecting)
|
||||||
|
break;
|
||||||
|
lease = optgetulong(bp->optdata, ODlease);
|
||||||
|
if(lease == 0){
|
||||||
|
/*
|
||||||
|
* The All_Aboard NAT package from Internet Share
|
||||||
|
* doesn't give a lease time, so we have to assume one.
|
||||||
|
*/
|
||||||
|
warning("Offer with %lud lease, using %d", lease, MinLease);
|
||||||
|
lease = MinLease;
|
||||||
|
}
|
||||||
|
DEBUG("lease=%lud ", lease);
|
||||||
|
if(!optgetaddr(bp->optdata, ODserverid, conf.server)) {
|
||||||
|
warning("Offer from server with invalid serverid");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
v4tov6(conf.laddr, bp->yiaddr);
|
||||||
|
memmove(conf.sname, bp->sname, sizeof conf.sname);
|
||||||
|
conf.sname[sizeof conf.sname-1] = 0;
|
||||||
|
DEBUG("server=%I sname=%s", conf.server, conf.sname);
|
||||||
|
conf.offered = lease;
|
||||||
|
conf.state = Srequesting;
|
||||||
|
dhcpsend(Request);
|
||||||
|
conf.resend = 0;
|
||||||
|
conf.timeout = time(0) + 4;
|
||||||
|
break;
|
||||||
|
case Ack:
|
||||||
|
DEBUG("got ack from %V ", bp->siaddr);
|
||||||
|
if (conf.state != Srequesting && conf.state != Srenewing &&
|
||||||
|
conf.state != Srebinding)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* ignore a bad lease */
|
||||||
|
lease = optgetulong(bp->optdata, ODlease);
|
||||||
|
if(lease == 0){
|
||||||
|
/*
|
||||||
|
* The All_Aboard NAT package from Internet Share
|
||||||
|
* doesn't give a lease time, so we have to assume one.
|
||||||
|
*/
|
||||||
|
warning("Ack with %lud lease, using %d", lease, MinLease);
|
||||||
|
lease = MinLease;
|
||||||
|
}
|
||||||
|
DEBUG("lease=%lud ", lease);
|
||||||
|
|
||||||
|
/* address and mask */
|
||||||
|
if(!validip(conf.laddr) || !Oflag)
|
||||||
|
v4tov6(conf.laddr, bp->yiaddr);
|
||||||
|
if(!validip(conf.mask) || !Oflag){
|
||||||
|
if(!optgetaddr(bp->optdata, OBmask, conf.mask))
|
||||||
|
ipmove(conf.mask, IPnoaddr);
|
||||||
|
if(ipcmp(conf.mask, IPv4bcast) == 0)
|
||||||
|
ipmove(conf.mask, IPnoaddr);
|
||||||
|
}
|
||||||
|
DEBUG("ipaddr=%I ipmask=%M ", conf.laddr, conf.mask);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* get a router address either from the router option
|
||||||
|
* or from the router that forwarded the dhcp packet
|
||||||
|
*/
|
||||||
|
if(validip(conf.gaddr) && Oflag) {
|
||||||
|
DEBUG("ipgw=%I ", conf.gaddr);
|
||||||
|
} else if(optgetaddr(bp->optdata, OBrouter, conf.gaddr)){
|
||||||
|
DEBUG("ipgw=%I ", conf.gaddr);
|
||||||
|
} else if(memcmp(bp->giaddr, IPnoaddr+IPv4off, IPv4addrlen)!=0){
|
||||||
|
v4tov6(conf.gaddr, bp->giaddr);
|
||||||
|
DEBUG("giaddr=%I ", conf.gaddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* get dns servers */
|
||||||
|
memset(conf.dns, 0, sizeof conf.dns);
|
||||||
|
n = optgetaddrs(bp->optdata, OBdnserver, conf.dns,
|
||||||
|
sizeof conf.dns/IPaddrlen);
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
DEBUG("dns=%I ", conf.dns + i*IPaddrlen);
|
||||||
|
|
||||||
|
/* get ntp servers */
|
||||||
|
memset(conf.ntp, 0, sizeof conf.ntp);
|
||||||
|
n = optgetaddrs(bp->optdata, OBntpserver, conf.ntp,
|
||||||
|
sizeof conf.ntp/IPaddrlen);
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
DEBUG("ntp=%I ", conf.ntp + i*IPaddrlen);
|
||||||
|
|
||||||
|
/* get names */
|
||||||
|
optgetstr(bp->optdata, OBhostname,
|
||||||
|
conf.hostname, sizeof conf.hostname);
|
||||||
|
optgetstr(bp->optdata, OBdomainname,
|
||||||
|
conf.domainname, sizeof conf.domainname);
|
||||||
|
|
||||||
|
/* get anything else we asked for */
|
||||||
|
getoptions(bp->optdata);
|
||||||
|
|
||||||
|
/* get plan9-specific options */
|
||||||
|
n = optgetvec(bp->optdata, OBvendorinfo, vopts, sizeof vopts-1);
|
||||||
|
if(n > 0 && parseoptions(vopts, n) == 0){
|
||||||
|
if(validip(conf.fs) && Oflag)
|
||||||
|
n = 1;
|
||||||
|
else {
|
||||||
|
n = optgetp9addrs(vopts, OP9fs, conf.fs, 2);
|
||||||
|
if (n == 0)
|
||||||
|
n = optgetaddrs(vopts, OP9fsv4,
|
||||||
|
conf.fs, 2);
|
||||||
|
}
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
DEBUG("fs=%I ", conf.fs + i*IPaddrlen);
|
||||||
|
|
||||||
|
if(validip(conf.auth) && Oflag)
|
||||||
|
n = 1;
|
||||||
|
else {
|
||||||
|
n = optgetp9addrs(vopts, OP9auth, conf.auth, 2);
|
||||||
|
if (n == 0)
|
||||||
|
n = optgetaddrs(vopts, OP9authv4,
|
||||||
|
conf.auth, 2);
|
||||||
|
}
|
||||||
|
for(i = 0; i < n; i++)
|
||||||
|
DEBUG("auth=%I ", conf.auth + i*IPaddrlen);
|
||||||
|
|
||||||
|
n = optgetp9addrs(vopts, OP9ipaddr, taddr, 1);
|
||||||
|
if (n > 0)
|
||||||
|
memmove(conf.laddr, taddr, IPaddrlen);
|
||||||
|
n = optgetp9addrs(vopts, OP9ipmask, taddr, 1);
|
||||||
|
if (n > 0)
|
||||||
|
memmove(conf.mask, taddr, IPaddrlen);
|
||||||
|
n = optgetp9addrs(vopts, OP9ipgw, taddr, 1);
|
||||||
|
if (n > 0)
|
||||||
|
memmove(conf.gaddr, taddr, IPaddrlen);
|
||||||
|
DEBUG("new ipaddr=%I new ipmask=%M new ipgw=%I",
|
||||||
|
conf.laddr, conf.mask, conf.gaddr);
|
||||||
|
}
|
||||||
|
conf.lease = lease;
|
||||||
|
conf.state = Sbound;
|
||||||
|
DEBUG("server=%I sname=%s", conf.server, conf.sname);
|
||||||
|
break;
|
||||||
|
case Nak:
|
||||||
|
conf.state = Sinit;
|
||||||
|
warning("recved dhcpnak on %s", conf.mpoint);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
openlisten(void)
|
||||||
|
{
|
||||||
|
int n, fd, cfd;
|
||||||
|
char data[128], devdir[40];
|
||||||
|
|
||||||
|
if (validip(conf.laddr) &&
|
||||||
|
(conf.state == Srenewing || conf.state == Srebinding))
|
||||||
|
sprint(data, "%s/udp!%I!68", conf.mpoint, conf.laddr);
|
||||||
|
else
|
||||||
|
sprint(data, "%s/udp!*!68", conf.mpoint);
|
||||||
|
for (n = 0; (cfd = announce(data, devdir)) < 0; n++) {
|
||||||
|
if(!noconfig)
|
||||||
|
sysfatal("can't announce for dhcp: %r");
|
||||||
|
|
||||||
|
/* might be another client - wait and try again */
|
||||||
|
warning("can't announce %s: %r", data);
|
||||||
|
sleep(jitter());
|
||||||
|
if(n > 10)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(fprint(cfd, "headers") < 0)
|
||||||
|
sysfatal("can't set header mode: %r");
|
||||||
|
|
||||||
|
sprint(data, "%s/data", devdir);
|
||||||
|
fd = open(data, ORDWR);
|
||||||
|
if(fd < 0)
|
||||||
|
sysfatal("open %s: %r", data);
|
||||||
|
close(cfd);
|
||||||
|
return fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar*
|
||||||
|
optadd(uchar *p, int op, void *d, int n)
|
||||||
|
{
|
||||||
|
p[0] = op;
|
||||||
|
p[1] = n;
|
||||||
|
memmove(p+2, d, n);
|
||||||
|
return p+n+2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar*
|
||||||
|
optaddbyte(uchar *p, int op, int b)
|
||||||
|
{
|
||||||
|
p[0] = op;
|
||||||
|
p[1] = 1;
|
||||||
|
p[2] = b;
|
||||||
|
return p+3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar*
|
||||||
|
optaddulong(uchar *p, int op, ulong x)
|
||||||
|
{
|
||||||
|
p[0] = op;
|
||||||
|
p[1] = 4;
|
||||||
|
hnputl(p+2, x);
|
||||||
|
return p+6;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar *
|
||||||
|
optaddaddr(uchar *p, int op, uchar *ip)
|
||||||
|
{
|
||||||
|
p[0] = op;
|
||||||
|
p[1] = 4;
|
||||||
|
v6tov4(p+2, ip);
|
||||||
|
return p+6;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* add dhcp option op with value v of length n to dhcp option array p */
|
||||||
|
static uchar *
|
||||||
|
optaddvec(uchar *p, int op, uchar *v, int n)
|
||||||
|
{
|
||||||
|
p[0] = op;
|
||||||
|
p[1] = n;
|
||||||
|
memmove(p+2, v, n);
|
||||||
|
return p+2+n;
|
||||||
|
}
|
||||||
|
|
||||||
|
static uchar *
|
||||||
|
optaddstr(uchar *p, int op, char *v)
|
||||||
|
{
|
||||||
|
int n;
|
||||||
|
|
||||||
|
n = strlen(v);
|
||||||
|
p[0] = op;
|
||||||
|
p[1] = n;
|
||||||
|
memmove(p+2, v, n);
|
||||||
|
return p+2+n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* parse p, looking for option `op'. if non-nil, np points to minimum length.
|
||||||
|
* return nil if option is too small, else ptr to opt, and
|
||||||
|
* store actual length via np if non-nil.
|
||||||
|
*/
|
||||||
|
static uchar*
|
||||||
|
optget(uchar *p, int op, int *np)
|
||||||
|
{
|
||||||
|
int len, code;
|
||||||
|
|
||||||
|
while ((code = *p++) != OBend) {
|
||||||
|
if(code == OBpad)
|
||||||
|
continue;
|
||||||
|
len = *p++;
|
||||||
|
if(code != op) {
|
||||||
|
p += len;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(np != nil){
|
||||||
|
if(*np > len) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
*np = len;
|
||||||
|
}
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optgetbyte(uchar *p, int op)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 1;
|
||||||
|
p = optget(p, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
return *p;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ulong
|
||||||
|
optgetulong(uchar *p, int op)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 4;
|
||||||
|
p = optget(p, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
return nhgetl(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optgetaddr(uchar *p, int op, uchar *ip)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 4;
|
||||||
|
p = optget(p, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
v4tov6(ip, p);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expect at most n addresses; ip[] only has room for that many */
|
||||||
|
static int
|
||||||
|
optgetaddrs(uchar *p, int op, uchar *ip, int n)
|
||||||
|
{
|
||||||
|
int len, i;
|
||||||
|
|
||||||
|
len = 4;
|
||||||
|
p = optget(p, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
len /= IPv4addrlen;
|
||||||
|
if(len > n)
|
||||||
|
len = n;
|
||||||
|
for(i = 0; i < len; i++)
|
||||||
|
v4tov6(&ip[i*IPaddrlen], &p[i*IPv4addrlen]);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* expect at most n addresses; ip[] only has room for that many */
|
||||||
|
static int
|
||||||
|
optgetp9addrs(uchar *ap, int op, uchar *ip, int n)
|
||||||
|
{
|
||||||
|
int len, i, slen, addrs;
|
||||||
|
char *p;
|
||||||
|
|
||||||
|
len = 1; /* minimum bytes needed */
|
||||||
|
p = (char *)optget(ap, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
addrs = *p++; /* first byte is address count */
|
||||||
|
for (i = 0; i < n && i < addrs && len > 0; i++) {
|
||||||
|
slen = strlen(p) + 1;
|
||||||
|
if (parseip(&ip[i*IPaddrlen], p) == -1)
|
||||||
|
fprint(2, "%s: bad address %s\n", argv0, p);
|
||||||
|
DEBUG("got plan 9 option %d addr %I (%s)",
|
||||||
|
op, &ip[i*IPaddrlen], p);
|
||||||
|
p += slen;
|
||||||
|
len -= slen;
|
||||||
|
}
|
||||||
|
return addrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optgetvec(uchar *p, int op, uchar *v, int n)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 1;
|
||||||
|
p = optget(p, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
if(len > n)
|
||||||
|
len = n;
|
||||||
|
memmove(v, p, len);
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
optgetstr(uchar *p, int op, char *s, int n)
|
||||||
|
{
|
||||||
|
int len;
|
||||||
|
|
||||||
|
len = 1;
|
||||||
|
p = optget(p, op, &len);
|
||||||
|
if(p == nil)
|
||||||
|
return 0;
|
||||||
|
if(len >= n)
|
||||||
|
len = n-1;
|
||||||
|
memmove(s, p, len);
|
||||||
|
s[len] = 0;
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
addoption(char *opt)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
Option *o;
|
||||||
|
|
||||||
|
if(opt == nil)
|
||||||
|
return -1;
|
||||||
|
for(o = option; o < &option[nelem(option)]; o++)
|
||||||
|
if(o->name && strcmp(opt, o->name) == 0){
|
||||||
|
i = o - option;
|
||||||
|
if(memchr(requested, i, nrequested) == 0 &&
|
||||||
|
nrequested < nelem(requested))
|
||||||
|
requested[nrequested++] = i;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
optgetx(uchar *p, uchar opt)
|
||||||
|
{
|
||||||
|
int i, n;
|
||||||
|
ulong x;
|
||||||
|
char *s, *ns;
|
||||||
|
char str[256];
|
||||||
|
uchar ip[IPaddrlen], ips[16*IPaddrlen], vec[256];
|
||||||
|
Option *o;
|
||||||
|
|
||||||
|
o = &option[opt];
|
||||||
|
if(o->name == nil)
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
s = nil;
|
||||||
|
switch(o->type){
|
||||||
|
case Taddr:
|
||||||
|
if(optgetaddr(p, opt, ip))
|
||||||
|
s = smprint("%s=%I", o->name, ip);
|
||||||
|
break;
|
||||||
|
case Taddrs:
|
||||||
|
n = optgetaddrs(p, opt, ips, 16);
|
||||||
|
if(n > 0)
|
||||||
|
s = smprint("%s=%I", o->name, ips);
|
||||||
|
for(i = 1; i < n; i++){
|
||||||
|
ns = smprint("%s %s=%I", s, o->name, &ips[i*IPaddrlen]);
|
||||||
|
free(s);
|
||||||
|
s = ns;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case Tulong:
|
||||||
|
x = optgetulong(p, opt);
|
||||||
|
if(x != 0)
|
||||||
|
s = smprint("%s=%lud", o->name, x);
|
||||||
|
break;
|
||||||
|
case Tbyte:
|
||||||
|
x = optgetbyte(p, opt);
|
||||||
|
if(x != 0)
|
||||||
|
s = smprint("%s=%lud", o->name, x);
|
||||||
|
break;
|
||||||
|
case Tstr:
|
||||||
|
if(optgetstr(p, opt, str, sizeof str))
|
||||||
|
s = smprint("%s=%s", o->name, str);
|
||||||
|
break;
|
||||||
|
case Tvec:
|
||||||
|
n = optgetvec(p, opt, vec, sizeof vec);
|
||||||
|
if(n > 0)
|
||||||
|
/* what's %H? it's not installed */
|
||||||
|
s = smprint("%s=%.*H", o->name, n, vec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
getoptions(uchar *p)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
char *s, *t;
|
||||||
|
|
||||||
|
for(i = nelem(defrequested); i < nrequested; i++){
|
||||||
|
s = optgetx(p, requested[i]);
|
||||||
|
if(s != nil)
|
||||||
|
DEBUG("%s ", s);
|
||||||
|
if(ndboptions == nil)
|
||||||
|
ndboptions = smprint("\t%s", s);
|
||||||
|
else{
|
||||||
|
t = ndboptions;
|
||||||
|
ndboptions = smprint("\t%s%s", s, ndboptions);
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
free(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sanity check options area
|
||||||
|
* - options don't overflow packet
|
||||||
|
* - options end with an OBend
|
||||||
|
*/
|
||||||
|
static int
|
||||||
|
parseoptions(uchar *p, int n)
|
||||||
|
{
|
||||||
|
int code, len, nin = n;
|
||||||
|
|
||||||
|
while (n > 0) {
|
||||||
|
code = *p++;
|
||||||
|
n--;
|
||||||
|
if(code == OBend)
|
||||||
|
return 0;
|
||||||
|
if(code == OBpad)
|
||||||
|
continue;
|
||||||
|
if(n == 0) {
|
||||||
|
warning("parseoptions: bad option: 0x%ux: truncated: "
|
||||||
|
"opt length = %d", code, nin);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
len = *p++;
|
||||||
|
n--;
|
||||||
|
DEBUG("parseoptions: %s(%d) len %d, bytes left %d",
|
||||||
|
option[code].name, code, len, n);
|
||||||
|
if(len > n) {
|
||||||
|
warning("parseoptions: bad option: 0x%ux: %d > %d: "
|
||||||
|
"opt length = %d", code, len, n, nin);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
p += len;
|
||||||
|
n -= len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* make sure packet ends with an OBend after all the optget code */
|
||||||
|
*p = OBend;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* sanity check received packet:
|
||||||
|
* - magic is dhcp magic
|
||||||
|
* - options don't overflow packet
|
||||||
|
*/
|
||||||
|
static Bootp*
|
||||||
|
parsebootp(uchar *p, int n)
|
||||||
|
{
|
||||||
|
Bootp *bp;
|
||||||
|
|
||||||
|
bp = (Bootp*)p;
|
||||||
|
if(n < bp->optmagic - p) {
|
||||||
|
warning("parsebootp: short bootp packet");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(conf.xid != nhgetl(bp->xid)) /* not meant for us */
|
||||||
|
return nil;
|
||||||
|
|
||||||
|
if(bp->op != Bootreply) {
|
||||||
|
warning("parsebootp: bad op %d", bp->op);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
n -= bp->optmagic - p;
|
||||||
|
p = bp->optmagic;
|
||||||
|
|
||||||
|
if(n < 4) {
|
||||||
|
warning("parsebootp: no option data");
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
if(memcmp(optmagic, p, 4) != 0) {
|
||||||
|
warning("parsebootp: bad opt magic %ux %ux %ux %ux",
|
||||||
|
p[0], p[1], p[2], p[3]);
|
||||||
|
return nil;
|
||||||
|
}
|
||||||
|
p += 4;
|
||||||
|
n -= 4;
|
||||||
|
DEBUG("parsebootp: new packet");
|
||||||
|
if(parseoptions(p, n) < 0)
|
||||||
|
return nil;
|
||||||
|
return bp;
|
||||||
|
}
|
||||||
|
|
|
@ -1,3 +1,23 @@
|
||||||
|
/* possible verbs */
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
/* commands */
|
||||||
|
Vadd,
|
||||||
|
Vremove,
|
||||||
|
Vunbind,
|
||||||
|
Vaddpref6,
|
||||||
|
Vra6,
|
||||||
|
|
||||||
|
/* media */
|
||||||
|
Vether,
|
||||||
|
Vgbe,
|
||||||
|
Vppp,
|
||||||
|
Vloopback,
|
||||||
|
Vtorus,
|
||||||
|
Vtree,
|
||||||
|
Vpkt,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct Conf Conf;
|
typedef struct Conf Conf;
|
||||||
typedef struct Ctl Ctl;
|
typedef struct Ctl Ctl;
|
||||||
|
|
||||||
|
@ -22,7 +42,7 @@ struct Conf
|
||||||
uchar laddr[IPaddrlen];
|
uchar laddr[IPaddrlen];
|
||||||
uchar mask[IPaddrlen];
|
uchar mask[IPaddrlen];
|
||||||
uchar raddr[IPaddrlen];
|
uchar raddr[IPaddrlen];
|
||||||
uchar dns[2*IPaddrlen];
|
uchar dns[8*IPaddrlen];
|
||||||
uchar fs[2*IPaddrlen];
|
uchar fs[2*IPaddrlen];
|
||||||
uchar auth[2*IPaddrlen];
|
uchar auth[2*IPaddrlen];
|
||||||
uchar ntp[2*IPaddrlen];
|
uchar ntp[2*IPaddrlen];
|
||||||
|
@ -60,12 +80,15 @@ struct Conf
|
||||||
int ttl; /* default 0 (unspecified) */
|
int ttl; /* default 0 (unspecified) */
|
||||||
|
|
||||||
/* prefix related */
|
/* prefix related */
|
||||||
|
uchar lladdr[IPaddrlen];
|
||||||
uchar v6pref[IPaddrlen];
|
uchar v6pref[IPaddrlen];
|
||||||
int prefixlen;
|
int prefixlen;
|
||||||
uchar onlink; /* flag: address is `on-link' */
|
uchar onlink; /* flag: address is `on-link' */
|
||||||
uchar autoflag; /* flag: autonomous */
|
uchar autoflag; /* flag: autonomous */
|
||||||
ulong validlt; /* valid lifetime (seconds) */
|
ulong validlt; /* valid lifetime (seconds) */
|
||||||
ulong preflt; /* preferred lifetime (seconds) */
|
ulong preflt; /* preferred lifetime (seconds) */
|
||||||
|
|
||||||
|
char dnsdomain[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Ctl
|
struct Ctl
|
||||||
|
@ -74,152 +97,60 @@ struct Ctl
|
||||||
char *ctl;
|
char *ctl;
|
||||||
};
|
};
|
||||||
|
|
||||||
extern Ctl *firstctl, **ctll;
|
|
||||||
|
|
||||||
extern Conf conf;
|
|
||||||
|
|
||||||
extern int noconfig;
|
|
||||||
extern int ipv6auto;
|
|
||||||
extern int debug;
|
|
||||||
extern int dodhcp;
|
|
||||||
extern int dolog;
|
|
||||||
extern int plan9;
|
|
||||||
extern int dupl_disc;
|
|
||||||
|
|
||||||
extern Conf conf;
|
extern Conf conf;
|
||||||
extern int myifc;
|
extern int myifc;
|
||||||
extern char *vs;
|
extern int beprimary;
|
||||||
|
extern int noconfig;
|
||||||
|
|
||||||
|
extern int debug;
|
||||||
|
extern int dolog;
|
||||||
|
|
||||||
|
extern int plan9;
|
||||||
|
extern int Oflag;
|
||||||
|
|
||||||
|
extern int dupl_disc;
|
||||||
|
|
||||||
|
extern int nodhcpwatch;
|
||||||
|
extern int sendhostname;
|
||||||
|
extern char *ndboptions;
|
||||||
|
|
||||||
|
void usage(void);
|
||||||
|
int ip4cfg(void);
|
||||||
|
void ipunconfig(void);
|
||||||
|
|
||||||
void adddefroute(uchar*, uchar*, uchar*, uchar*);
|
void adddefroute(uchar*, uchar*, uchar*, uchar*);
|
||||||
void removedefroute(int, uchar*, uchar*);
|
void removedefroute(int, uchar*, uchar*);
|
||||||
|
|
||||||
void doadd(int);
|
|
||||||
void doremove(void);
|
|
||||||
void dounbind(void);
|
|
||||||
int isether(void);
|
|
||||||
long jitter(void);
|
long jitter(void);
|
||||||
void mklladdr(void);
|
|
||||||
void procsetname(char *fmt, ...);
|
void procsetname(char *fmt, ...);
|
||||||
|
void catch(void*, char*);
|
||||||
|
int countaddrs(uchar *a, int len);
|
||||||
|
void addaddrs(uchar *to, int nto, uchar *from, int nfrom);
|
||||||
|
void addnames(char *d, char *s, int len);
|
||||||
|
Ndb* opendatabase(void);
|
||||||
|
void ndb2conf(Ndb *db, uchar *ip);
|
||||||
|
void putndb(void);
|
||||||
void refresh(void);
|
void refresh(void);
|
||||||
ulong randint(ulong low, ulong hi);
|
ulong randint(ulong low, ulong hi);
|
||||||
int validip(uchar*);
|
int validip(uchar*);
|
||||||
void warning(char *fmt, ...);
|
void warning(char *fmt, ...);
|
||||||
|
#define DEBUG if(debug)warning
|
||||||
|
|
||||||
|
/*
|
||||||
|
* DHCP
|
||||||
|
*/
|
||||||
|
void dhcpinit(void);
|
||||||
|
void dhcpquery(int, int);
|
||||||
|
void dhcpwatch(int);
|
||||||
|
int addoption(char*);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* IPv6
|
* IPv6
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void doipv6(int);
|
|
||||||
void v6paraminit(Conf*);
|
void v6paraminit(Conf*);
|
||||||
|
void parse6pref(int argc, char **argv);
|
||||||
typedef struct Headers Headers;
|
void parse6ra(int argc, char **argv);
|
||||||
typedef struct Ip4hdr Ip4hdr;
|
void doipv6(int);
|
||||||
typedef struct Lladdropt Lladdropt;
|
|
||||||
typedef struct Mtuopt Mtuopt;
|
|
||||||
typedef struct Prefixopt Prefixopt;
|
|
||||||
typedef struct Routeradv Routeradv;
|
|
||||||
typedef struct Routersol Routersol;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
IsRouter = 1,
|
|
||||||
IsHostRecv = 2,
|
|
||||||
IsHostNoRecv = 3,
|
|
||||||
|
|
||||||
MAClen = 6,
|
|
||||||
|
|
||||||
IPv4 = 4,
|
|
||||||
IPv6 = 6,
|
|
||||||
Defmtu = 1400,
|
|
||||||
|
|
||||||
IP_HOPBYHOP = 0,
|
|
||||||
ICMPv4 = 1,
|
|
||||||
IP_IGMPPROTO = 2,
|
|
||||||
IP_TCPPROTO = 6,
|
|
||||||
IP_UDPPROTO = 17,
|
|
||||||
IP_ILPROTO = 40,
|
|
||||||
IP_v6ROUTE = 43,
|
|
||||||
IP_v6FRAG = 44,
|
|
||||||
IP_IPsecESP = 50,
|
|
||||||
IP_IPsecAH = 51,
|
|
||||||
IP_v6NOMORE = 59,
|
|
||||||
ICMP6_RS = 133,
|
|
||||||
ICMP6_RA = 134,
|
|
||||||
|
|
||||||
IP_IN_IP = 41,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
MFMASK = 1 << 7,
|
|
||||||
OCMASK = 1 << 6,
|
|
||||||
OLMASK = 1 << 7,
|
|
||||||
AFMASK = 1 << 6,
|
|
||||||
RFMASK = 1 << 5,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
MAXTTL = 255,
|
|
||||||
D64HLEN = IPV6HDR_LEN - IPV4HDR_LEN,
|
|
||||||
IP_MAX = 32*1024,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Headers {
|
|
||||||
uchar dst[IPaddrlen];
|
|
||||||
uchar src[IPaddrlen];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Routersol {
|
|
||||||
uchar vcf[4]; /* version:4, traffic class:8, flow label:20 */
|
|
||||||
uchar ploadlen[2]; /* payload length: packet length - 40 */
|
|
||||||
uchar proto; /* next header type */
|
|
||||||
uchar ttl; /* hop limit */
|
|
||||||
uchar src[IPaddrlen];
|
|
||||||
uchar dst[IPaddrlen];
|
|
||||||
uchar type;
|
|
||||||
uchar code;
|
|
||||||
uchar cksum[2];
|
|
||||||
uchar res[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Routeradv {
|
|
||||||
uchar vcf[4]; /* version:4, traffic class:8, flow label:20 */
|
|
||||||
uchar ploadlen[2]; /* payload length: packet length - 40 */
|
|
||||||
uchar proto; /* next header type */
|
|
||||||
uchar ttl; /* hop limit */
|
|
||||||
uchar src[IPaddrlen];
|
|
||||||
uchar dst[IPaddrlen];
|
|
||||||
uchar type;
|
|
||||||
uchar code;
|
|
||||||
uchar cksum[2];
|
|
||||||
uchar cttl;
|
|
||||||
uchar mor;
|
|
||||||
uchar routerlt[2];
|
|
||||||
uchar rchbltime[4];
|
|
||||||
uchar rxmtimer[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Lladdropt {
|
|
||||||
uchar type;
|
|
||||||
uchar len;
|
|
||||||
uchar lladdr[MAClen];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Prefixopt {
|
|
||||||
uchar type;
|
|
||||||
uchar len;
|
|
||||||
uchar plen;
|
|
||||||
uchar lar;
|
|
||||||
uchar validlt[4];
|
|
||||||
uchar preflt[4];
|
|
||||||
uchar reserv[4];
|
|
||||||
uchar pref[IPaddrlen];
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Mtuopt {
|
|
||||||
uchar type;
|
|
||||||
uchar len;
|
|
||||||
uchar reserv[2];
|
|
||||||
uchar mtu[4];
|
|
||||||
};
|
|
||||||
|
|
||||||
void ea2lla(uchar *lla, uchar *ea);
|
void ea2lla(uchar *lla, uchar *ea);
|
||||||
void ipv62smcast(uchar *smcast, uchar *a);
|
int findllip(uchar *ip, Ipifc *ifc);
|
||||||
|
int ip6cfg(void);
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -4,6 +4,7 @@ TARG=ipconfig\
|
||||||
|
|
||||||
OFILES=\
|
OFILES=\
|
||||||
main.$O\
|
main.$O\
|
||||||
|
dhcp.$O\
|
||||||
ipv6.$O\
|
ipv6.$O\
|
||||||
ppp.$O\
|
ppp.$O\
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
#include <ip.h>
|
#include <ip.h>
|
||||||
#include <bio.h>
|
#include <bio.h>
|
||||||
#include <ndb.h>
|
#include <ndb.h>
|
||||||
#include "../dhcp.h"
|
|
||||||
#include "ipconfig.h"
|
#include "ipconfig.h"
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -1510,19 +1510,6 @@ setdefroute(char *net, Ipaddr gate)
|
||||||
close(fd);
|
close(fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum
|
|
||||||
{
|
|
||||||
Mofd= 32,
|
|
||||||
};
|
|
||||||
struct
|
|
||||||
{
|
|
||||||
Lock;
|
|
||||||
|
|
||||||
int fd[Mofd];
|
|
||||||
int cfd[Mofd];
|
|
||||||
int n;
|
|
||||||
} old;
|
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
ipopen(PPP *ppp)
|
ipopen(PPP *ppp)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1386,6 +1386,20 @@ isv4str(char *s)
|
||||||
return parseip(ip, s) != -1 && isv4(ip);
|
return parseip(ip, s) != -1 && isv4(ip);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Ndbtuple*
|
||||||
|
ndbline(Ndbtuple *t)
|
||||||
|
{
|
||||||
|
Ndbtuple *nt;
|
||||||
|
|
||||||
|
for(nt = t; nt != nil; nt = nt->entry){
|
||||||
|
if(nt->entry == nil)
|
||||||
|
nt->line = t;
|
||||||
|
else
|
||||||
|
nt->line = nt->entry;
|
||||||
|
}
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* lookup an ip destination
|
* lookup an ip destination
|
||||||
*/
|
*/
|
||||||
|
@ -1410,20 +1424,20 @@ iplookuphost(Network *np, char *host)
|
||||||
|
|
||||||
/* for dial strings with no host */
|
/* for dial strings with no host */
|
||||||
if(strcmp(host, "*") == 0)
|
if(strcmp(host, "*") == 0)
|
||||||
return ndbnew("ip", "*");
|
return ndbline(ndbnew("ip", "*"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* hack till we go v6 :: = 0.0.0.0
|
* hack till we go v6 :: = 0.0.0.0
|
||||||
*/
|
*/
|
||||||
if(strcmp("::", host) == 0)
|
if(strcmp("::", host) == 0)
|
||||||
return ndbnew("ip", "*");
|
return ndbline(ndbnew("ip", "*"));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* just accept addresses
|
* just accept addresses
|
||||||
*/
|
*/
|
||||||
attr = ipattr(host);
|
attr = ipattr(host);
|
||||||
if(strcmp(attr, "ip") == 0)
|
if(strcmp(attr, "ip") == 0)
|
||||||
return ndbnew("ip", host);
|
return ndbline(ndbnew("ip", host));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* give the domain name server the first opportunity to
|
* give the domain name server the first opportunity to
|
||||||
|
@ -1627,14 +1641,8 @@ dnsip6lookup(char *mntpt, char *buf, Ndbtuple *t)
|
||||||
if (strcmp(tt->attr, "ipv6") == 0)
|
if (strcmp(tt->attr, "ipv6") == 0)
|
||||||
strcpy(tt->attr, "ip");
|
strcpy(tt->attr, "ip");
|
||||||
|
|
||||||
if (t == nil)
|
|
||||||
return t6;
|
|
||||||
|
|
||||||
/* append t6 list to t list */
|
/* append t6 list to t list */
|
||||||
for (tt = t; tt->entry != nil; tt = tt->entry)
|
return ndbconcatenate(t, t6);
|
||||||
;
|
|
||||||
tt->entry = t6;
|
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1911,12 +1919,7 @@ ipinfoquery(Mfile *mf, char **list, int n)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* make it all one line */
|
/* make it all one line */
|
||||||
for(nt = t; nt != nil; nt = nt->entry){
|
t = ndbline(t);
|
||||||
if(nt->entry == nil)
|
|
||||||
nt->line = t;
|
|
||||||
else
|
|
||||||
nt->line = nt->entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
qreply(mf, t);
|
qreply(mf, t);
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ usage(void)
|
||||||
void
|
void
|
||||||
query(char *addr)
|
query(char *addr)
|
||||||
{
|
{
|
||||||
char buf[8192];
|
char buf[8192+1];
|
||||||
int fd, n;
|
int fd, n;
|
||||||
|
|
||||||
fd = open(server, ORDWR);
|
fd = open(server, ORDWR);
|
||||||
|
@ -31,8 +31,10 @@ query(char *addr)
|
||||||
}
|
}
|
||||||
if(!statusonly){
|
if(!statusonly){
|
||||||
seek(fd, 0, 0);
|
seek(fd, 0, 0);
|
||||||
while((n = read(fd, buf, sizeof(buf))) > 0)
|
while((n = read(fd, buf, sizeof(buf)-1)) > 0){
|
||||||
|
buf[n++] = '\n';
|
||||||
write(1, buf, n);
|
write(1, buf, n);
|
||||||
|
}
|
||||||
write(1, "\n", 1);
|
write(1, "\n", 1);
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
|
@ -14,15 +14,12 @@ char*
|
||||||
csgetvalue(char *netroot, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
csgetvalue(char *netroot, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
||||||
{
|
{
|
||||||
Ndbtuple *t, *first, *last;
|
Ndbtuple *t, *first, *last;
|
||||||
int n, linefound;
|
|
||||||
char line[1024];
|
char line[1024];
|
||||||
int fd;
|
int fd, n;
|
||||||
int oops = 0;
|
|
||||||
char *rv;
|
char *rv;
|
||||||
|
|
||||||
if(pp)
|
if(pp != nil)
|
||||||
*pp = nil;
|
*pp = nil;
|
||||||
rv = nil;
|
|
||||||
|
|
||||||
if(netroot)
|
if(netroot)
|
||||||
snprint(line, sizeof(line), "%s/cs", netroot);
|
snprint(line, sizeof(line), "%s/cs", netroot);
|
||||||
|
@ -30,17 +27,17 @@ csgetvalue(char *netroot, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
||||||
strcpy(line, "/net/cs");
|
strcpy(line, "/net/cs");
|
||||||
fd = open(line, ORDWR);
|
fd = open(line, ORDWR);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return 0;
|
return nil;
|
||||||
seek(fd, 0, 0);
|
seek(fd, 0, 0);
|
||||||
snprint(line, sizeof(line), "!%s=%s %s=*", attr, val, rattr);
|
snprint(line, sizeof(line), "!%s=%s %s=*", attr, val, rattr);
|
||||||
if(write(fd, line, strlen(line)) < 0){
|
if(write(fd, line, strlen(line)) < 0){
|
||||||
close(fd);
|
close(fd);
|
||||||
return 0;
|
return nil;
|
||||||
}
|
}
|
||||||
seek(fd, 0, 0);
|
seek(fd, 0, 0);
|
||||||
|
|
||||||
first = last = 0;
|
rv = nil;
|
||||||
linefound = 0;
|
first = last = nil;
|
||||||
for(;;){
|
for(;;){
|
||||||
n = read(fd, line, sizeof(line)-2);
|
n = read(fd, line, sizeof(line)-2);
|
||||||
if(n <= 0)
|
if(n <= 0)
|
||||||
|
@ -49,35 +46,22 @@ csgetvalue(char *netroot, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
||||||
line[n+1] = 0;
|
line[n+1] = 0;
|
||||||
|
|
||||||
t = _ndbparseline(line);
|
t = _ndbparseline(line);
|
||||||
if(t == 0)
|
if(t == nil)
|
||||||
continue;
|
continue;
|
||||||
if(first)
|
if(first != nil)
|
||||||
last->entry = t;
|
last->entry = t;
|
||||||
else
|
else
|
||||||
first = t;
|
first = t;
|
||||||
|
do {
|
||||||
last = t;
|
last = t;
|
||||||
|
if(rv == nil && strcmp(rattr, t->attr) == 0)
|
||||||
while(last->entry)
|
|
||||||
last = last->entry;
|
|
||||||
|
|
||||||
for(; t; t = t->entry){
|
|
||||||
if(linefound == 0){
|
|
||||||
if(strcmp(rattr, t->attr) == 0){
|
|
||||||
linefound = 1;
|
|
||||||
rv = strdup(t->val);
|
rv = strdup(t->val);
|
||||||
}
|
t = t->entry;
|
||||||
}
|
} while(t != nil);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if(oops){
|
if(pp != nil){
|
||||||
werrstr("buffer too short");
|
|
||||||
ndbfree(first);
|
|
||||||
return nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(pp){
|
|
||||||
setmalloctag(first, getcallerpc(&netroot));
|
setmalloctag(first, getcallerpc(&netroot));
|
||||||
*pp = first;
|
*pp = first;
|
||||||
} else
|
} else
|
||||||
|
|
|
@ -129,17 +129,14 @@ doquery(int fd, char *dn, char *type)
|
||||||
|
|
||||||
t = _ndbparseline(buf);
|
t = _ndbparseline(buf);
|
||||||
if(t != nil){
|
if(t != nil){
|
||||||
if(first)
|
if(first != nil)
|
||||||
last->entry = t;
|
last->entry = t;
|
||||||
else
|
else
|
||||||
first = t;
|
first = t;
|
||||||
last = t;
|
last = t;
|
||||||
|
while(last->entry != nil)
|
||||||
while(last->entry)
|
|
||||||
last = last->entry;
|
last = last->entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ndbsetmalloctag(first, getcallerpc(&fd));
|
|
||||||
return first;
|
return first;
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,5 @@ ndbdiscard(Ndbtuple *t, Ndbtuple *a)
|
||||||
a->entry = nil;
|
a->entry = nil;
|
||||||
ndbfree(a);
|
ndbfree(a);
|
||||||
|
|
||||||
ndbsetmalloctag(t, getcallerpc(&t));
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
@ -71,6 +71,6 @@ ndbnew(char *attr, char *val)
|
||||||
void
|
void
|
||||||
ndbsetmalloctag(Ndbtuple *t, uintptr tag)
|
ndbsetmalloctag(Ndbtuple *t, uintptr tag)
|
||||||
{
|
{
|
||||||
for(; t; t=t->entry)
|
for(; t != nil; t=t->entry)
|
||||||
setmalloctag(t, tag);
|
setmalloctag(t, tag);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
* search for a tuple that has the given 'attr=val' and also 'rattr=x'.
|
* search for a tuple that has the given 'attr=val' and also 'rattr=x'.
|
||||||
* copy 'x' into 'buf' and return the whole tuple.
|
* copy 'x' into 'buf' and return the whole tuple.
|
||||||
*
|
*
|
||||||
* return 0 if not found.
|
* return nil if not found.
|
||||||
*/
|
*/
|
||||||
char*
|
char*
|
||||||
ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
||||||
|
@ -21,11 +21,9 @@ ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
||||||
if(pp)
|
if(pp)
|
||||||
*pp = nil;
|
*pp = nil;
|
||||||
t = ndbsearch(db, s, attr, val);
|
t = ndbsearch(db, s, attr, val);
|
||||||
while(t){
|
while(t != nil){
|
||||||
/* first look on same line (closer binding) */
|
nt = ndbfindattr(t, s->t, rattr);
|
||||||
nt = s->t;
|
if(nt != nil){
|
||||||
for(;;){
|
|
||||||
if(strcmp(rattr, nt->attr) == 0){
|
|
||||||
rv = strdup(nt->val);
|
rv = strdup(nt->val);
|
||||||
if(pp != nil)
|
if(pp != nil)
|
||||||
*pp = t;
|
*pp = t;
|
||||||
|
@ -33,21 +31,6 @@ ndbgetvalue(Ndb *db, Ndbs *s, char *attr, char *val, char *rattr, Ndbtuple **pp)
|
||||||
ndbfree(t);
|
ndbfree(t);
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
nt = nt->line;
|
|
||||||
if(nt == s->t)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
/* search whole tuple */
|
|
||||||
for(nt = t; nt; nt = nt->entry){
|
|
||||||
if(strcmp(rattr, nt->attr) == 0){
|
|
||||||
rv = strdup(nt->val);
|
|
||||||
if(pp != nil)
|
|
||||||
*pp = t;
|
|
||||||
else
|
|
||||||
ndbfree(t);
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ndbfree(t);
|
ndbfree(t);
|
||||||
t = ndbsnext(s, attr, val);
|
t = ndbsnext(s, attr, val);
|
||||||
}
|
}
|
||||||
|
|
|
@ -123,26 +123,22 @@ ndbsearch(Ndb *db, Ndbs *s, char *attr, char *val)
|
||||||
memset(s, 0, sizeof(*s));
|
memset(s, 0, sizeof(*s));
|
||||||
if(_ndbcachesearch(db, s, attr, val, &t) == 0){
|
if(_ndbcachesearch(db, s, attr, val, &t) == 0){
|
||||||
/* found in cache */
|
/* found in cache */
|
||||||
if(t != nil){
|
if(t != nil)
|
||||||
ndbsetmalloctag(t, getcallerpc(&db));
|
goto out;
|
||||||
return t; /* answer from this file */
|
|
||||||
}
|
|
||||||
if(db->next == nil)
|
if(db->next == nil)
|
||||||
return nil;
|
return nil;
|
||||||
t = ndbsearch(db->next, s, attr, val);
|
t = ndbsearch(db->next, s, attr, val);
|
||||||
ndbsetmalloctag(t, getcallerpc(&db));
|
goto out;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s->db = db;
|
s->db = db;
|
||||||
s->hf = hf;
|
s->hf = hf;
|
||||||
if(s->hf){
|
if(s->hf != nil){
|
||||||
s->ptr = ndbhash(val, s->hf->hlen)*NDBPLEN;
|
s->ptr = ndbhash(val, s->hf->hlen)*NDBPLEN;
|
||||||
p = hfread(s->hf, s->ptr+NDBHLEN, NDBPLEN);
|
p = hfread(s->hf, s->ptr+NDBHLEN, NDBPLEN);
|
||||||
if(p == 0){
|
if(p == nil){
|
||||||
t = _ndbcacheadd(db, s, attr, val, nil);
|
t = _ndbcacheadd(db, s, attr, val, nil);
|
||||||
ndbsetmalloctag(t, getcallerpc(&db));
|
goto out;
|
||||||
return t;
|
|
||||||
}
|
}
|
||||||
s->ptr = NDBGETP(p);
|
s->ptr = NDBGETP(p);
|
||||||
s->type = Cptr1;
|
s->type = Cptr1;
|
||||||
|
@ -153,17 +149,17 @@ ndbsearch(Ndb *db, Ndbs *s, char *attr, char *val)
|
||||||
/* advance search to next db file */
|
/* advance search to next db file */
|
||||||
s->ptr = NDBNAP;
|
s->ptr = NDBNAP;
|
||||||
_ndbcacheadd(db, s, attr, val, nil);
|
_ndbcacheadd(db, s, attr, val, nil);
|
||||||
if(db->next == 0)
|
if(db->next == nil)
|
||||||
return nil;
|
return nil;
|
||||||
t = ndbsearch(db->next, s, attr, val);
|
t = ndbsearch(db->next, s, attr, val);
|
||||||
ndbsetmalloctag(t, getcallerpc(&db));
|
goto out;
|
||||||
return t;
|
|
||||||
} else {
|
} else {
|
||||||
s->ptr = 0;
|
s->ptr = 0;
|
||||||
s->type = Dptr;
|
s->type = Dptr;
|
||||||
}
|
}
|
||||||
t = ndbsnext(s, attr, val);
|
t = ndbsnext(s, attr, val);
|
||||||
_ndbcacheadd(db, s, attr, val, (t != nil && s->db == db)?t:nil);
|
_ndbcacheadd(db, s, attr, val, (t != nil && s->db == db)?t:nil);
|
||||||
|
out:
|
||||||
ndbsetmalloctag(t, getcallerpc(&db));
|
ndbsetmalloctag(t, getcallerpc(&db));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
@ -173,7 +169,7 @@ match(Ndbtuple *t, char *attr, char *val)
|
||||||
{
|
{
|
||||||
Ndbtuple *nt;
|
Ndbtuple *nt;
|
||||||
|
|
||||||
for(nt = t; nt; nt = nt->entry)
|
for(nt = t; nt != nil; nt = nt->entry)
|
||||||
if(strcmp(attr, nt->attr) == 0
|
if(strcmp(attr, nt->attr) == 0
|
||||||
&& strcmp(val, nt->val) == 0)
|
&& strcmp(val, nt->val) == 0)
|
||||||
return nt;
|
return nt;
|
||||||
|
@ -200,12 +196,10 @@ ndbsnext(Ndbs *s, char *attr, char *val)
|
||||||
break;
|
break;
|
||||||
t = ndbparse(db);
|
t = ndbparse(db);
|
||||||
s->ptr = Boffset(&db->b);
|
s->ptr = Boffset(&db->b);
|
||||||
if(t == 0)
|
if(t == nil)
|
||||||
break;
|
break;
|
||||||
if(s->t = match(t, attr, val)){
|
if((s->t = match(t, attr, val)) != nil)
|
||||||
ndbsetmalloctag(t, getcallerpc(&s));
|
goto out;
|
||||||
return t;
|
|
||||||
}
|
|
||||||
ndbfree(t);
|
ndbfree(t);
|
||||||
} else if(s->type == Cptr){
|
} else if(s->type == Cptr){
|
||||||
if(Bseek(&db->b, s->ptr, 0) < 0)
|
if(Bseek(&db->b, s->ptr, 0) < 0)
|
||||||
|
@ -213,18 +207,16 @@ ndbsnext(Ndbs *s, char *attr, char *val)
|
||||||
s->ptr = s->ptr1;
|
s->ptr = s->ptr1;
|
||||||
s->type = Cptr1;
|
s->type = Cptr1;
|
||||||
t = ndbparse(db);
|
t = ndbparse(db);
|
||||||
if(t == 0)
|
if(t == nil)
|
||||||
break;
|
break;
|
||||||
if(s->t = match(t, attr, val)){
|
if((s->t = match(t, attr, val)) != nil)
|
||||||
ndbsetmalloctag(t, getcallerpc(&s));
|
goto out;
|
||||||
return t;
|
|
||||||
}
|
|
||||||
ndbfree(t);
|
ndbfree(t);
|
||||||
} else if(s->type == Cptr1){
|
} else if(s->type == Cptr1){
|
||||||
if(s->ptr & NDBCHAIN){ /* hash chain continuation */
|
if(s->ptr & NDBCHAIN){ /* hash chain continuation */
|
||||||
s->ptr &= ~NDBCHAIN;
|
s->ptr &= ~NDBCHAIN;
|
||||||
p = hfread(s->hf, s->ptr+NDBHLEN, 2*NDBPLEN);
|
p = hfread(s->hf, s->ptr+NDBHLEN, 2*NDBPLEN);
|
||||||
if(p == 0)
|
if(p == nil)
|
||||||
break;
|
break;
|
||||||
s->ptr = NDBGETP(p);
|
s->ptr = NDBGETP(p);
|
||||||
s->ptr1 = NDBGETP(p+NDBPLEN);
|
s->ptr1 = NDBGETP(p+NDBPLEN);
|
||||||
|
@ -234,12 +226,10 @@ ndbsnext(Ndbs *s, char *attr, char *val)
|
||||||
break;
|
break;
|
||||||
s->ptr = NDBNAP;
|
s->ptr = NDBNAP;
|
||||||
t = ndbparse(db);
|
t = ndbparse(db);
|
||||||
if(t == 0)
|
if(t == nil)
|
||||||
break;
|
break;
|
||||||
if(s->t = match(t, attr, val)){
|
if((s->t = match(t, attr, val)) != nil)
|
||||||
ndbsetmalloctag(t, getcallerpc(&s));
|
goto out;
|
||||||
return t;
|
|
||||||
}
|
|
||||||
ndbfree(t);
|
ndbfree(t);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -247,14 +237,14 @@ ndbsnext(Ndbs *s, char *attr, char *val)
|
||||||
}
|
}
|
||||||
|
|
||||||
nextfile:
|
nextfile:
|
||||||
|
|
||||||
/* nothing left to search? */
|
/* nothing left to search? */
|
||||||
s->ptr = NDBNAP;
|
s->ptr = NDBNAP;
|
||||||
if(db->next == 0)
|
if(db->next == nil)
|
||||||
return 0;
|
return nil;
|
||||||
|
|
||||||
/* advance search to next db file */
|
/* advance search to next db file */
|
||||||
t = ndbsearch(db->next, s, attr, val);
|
t = ndbsearch(db->next, s, attr, val);
|
||||||
|
out:
|
||||||
ndbsetmalloctag(t, getcallerpc(&s));
|
ndbsetmalloctag(t, getcallerpc(&s));
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,9 +30,9 @@ ndbparse(Ndb *db)
|
||||||
Ndbtuple *first, *last;
|
Ndbtuple *first, *last;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
first = last = 0;
|
first = last = nil;
|
||||||
for(;;){
|
for(;;){
|
||||||
if((line = Brdline(&db->b, '\n')) == 0)
|
if((line = Brdline(&db->b, '\n')) == nil)
|
||||||
break;
|
break;
|
||||||
len = Blinelen(&db->b);
|
len = Blinelen(&db->b);
|
||||||
if(line[len-1] != '\n')
|
if(line[len-1] != '\n')
|
||||||
|
@ -42,15 +42,15 @@ ndbparse(Ndb *db)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
t = _ndbparseline(line);
|
t = _ndbparseline(line);
|
||||||
if(t == 0)
|
if(t == nil)
|
||||||
continue;
|
continue;
|
||||||
setmalloctag(t, getcallerpc(&db));
|
setmalloctag(t, getcallerpc(&db));
|
||||||
if(first)
|
if(first != nil)
|
||||||
last->entry = t;
|
last->entry = t;
|
||||||
else
|
else
|
||||||
first = t;
|
first = t;
|
||||||
last = t;
|
last = t;
|
||||||
while(last->entry)
|
while(last->entry != nil)
|
||||||
last = last->entry;
|
last = last->entry;
|
||||||
}
|
}
|
||||||
ndbsetmalloctag(first, getcallerpc(&db));
|
ndbsetmalloctag(first, getcallerpc(&db));
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <ndb.h>
|
#include <ndb.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* reorder the tuple to put x's line first in the entry and x fitst in its line
|
* reorder the tuple to put x's line first in the entry and x first in its line
|
||||||
*/
|
*/
|
||||||
Ndbtuple*
|
Ndbtuple*
|
||||||
ndbreorder(Ndbtuple *t, Ndbtuple *x)
|
ndbreorder(Ndbtuple *t, Ndbtuple *x)
|
||||||
|
|
Loading…
Reference in a new issue