void bootp(Req*);
void byteopt(Req*, int, uchar);
void dhcp(Req*);
-void fatal(int, char*, ...);
void hexopt(Req*, int, char*);
void logdhcp(Req*);
void logdhcpout(Req *, char *);
void termopt(Req*);
int validip(uchar*);
void vectoropt(Req*, int, uchar*, int);
-void warning(int, char*, ...);
void
timestamp(char *tag)
fmtinstall('I', eipfmt);
fmtinstall('V', eipfmt);
fmtinstall('M', eipfmt);
+ fmtinstall('H', encodefmt);
+
ARGBEGIN {
case '6':
v6opts = 1;
if(!debug)
switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
case -1:
- fatal(1, "fork");
+ fatal("fork: %r");
case 0:
break;
default:
}
if (chdir(TFTP) < 0)
- warning(1, "can't change directory to %s", TFTP);
+ warning("can't change directory to %s: %r", TFTP);
fd = openlisten(net);
for(;;){
r.fd = fd;
n = readlast(r.fd, r.buf, sizeof(r.buf));
if(n < Udphdrsize)
- fatal(1, "error reading requests");
+ fatal("error reading requests: %r");
start = nsec()/1000;
op = optbuf;
*op = 0;
proto(&r, n);
- if(r.id != nil)
- free(r.id);
}
}
void
proto(Req *rp, int n)
{
- char buf[64];
-
now = time(0);
rp->e = rp->buf + n;
return;
if(rp->bp->op != Bootrequest){
- warning(0, "not bootrequest");
+ warning("not bootrequest");
+ return;
+ }
+
+ if(!isv4(rp->up->laddr))
return;
+
+ ipifcs = readipifc(net, ipifcs, -1);
+ if((rp->ifc = findifc(rp->up->ifcaddr)) == nil){
+ warning("no interface");
+ return;
+ }
+ if(validip(rp->giaddr)){
+ /* info about gateway */
+ if(lookupip(rp->giaddr, nil, nil, &rp->gii, 1) < 0){
+ warning("unknown gateway %I", rp->giaddr);
+ return;
+ }
+ rp->gii.ifc = nil;
+ } else {
+ /* no gateway, directly connected */
+ if(ipcmp(rp->up->laddr, IPv4bcast) != 0 && localonifc(rp->up->laddr, rp->ifc) == nil){
+ warning("wrong network %I->%I on %s",
+ rp->up->raddr, rp->up->laddr, rp->ifc->dev);
+ return;
+ }
+ memset(&rp->gii, 0, sizeof(rp->gii));
+ rp->gii.ifc = rp->ifc;
}
if(rp->e < (uchar*)rp->bp->sname){
- warning(0, "packet too short");
+ warning("packet too short");
return;
}
if(rp->e >= rp->bp->optdata){
* which could be a mistake.
*/
if(rp->id == nil){
- if(rp->bp->hlen > Maxhwlen){
- warning(0, "hlen %d", rp->bp->hlen);
- return;
- }
- if(memcmp(zeros, rp->bp->chaddr, rp->bp->hlen) == 0){
- warning(0, "no chaddr");
- return;
- }
- sprint(buf, "hwa%2.2ux_", rp->bp->htype);
- rp->id = tohex(buf, rp->bp->chaddr, rp->bp->hlen);
- }
+ static char hwaid[Maxstr];
- ipifcs = readipifc(net, ipifcs, -1);
- rp->ifc = findifc(rp->up->ifcaddr);
- if(rp->ifc == nil){
- warning(0, "no interface");
- return;
- }
-
- if(validip(rp->giaddr)){
- /* info about gateway */
- if(lookupip(rp->giaddr, &rp->gii, 1) < 0){
- warning(0, "lookupip failed");
+ if(rp->bp->hlen > Maxhwlen || memcmp(zeros, rp->bp->chaddr, rp->bp->hlen) == 0){
+ warning("no chaddr");
return;
}
- rp->gii.ifc = nil;
- } else {
- /* no gateway, directly connected */
- memset(&rp->gii, 0, sizeof(rp->gii));
- rp->gii.ifc = rp->ifc;
+ snprint(hwaid, sizeof(hwaid), "hwa%2.2ux_%.*lH", rp->bp->htype, rp->bp->hlen, rp->bp->chaddr);
+ rp->id = hwaid;
}
/* info about target system */
}
}
if(b == nil){
- warning(0, "!Discover(%s via %I): no binding %I",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Discover(%s via %I on %s): no binding %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip);
return;
}
mkoffer(b, rp->id, rp->leasetime);
/* check for hard assignment */
if(rp->staticbinding){
if(findifc(rp->server) != rp->ifc) {
- warning(0, "!Request(%s via %I): for server %I not me",
- rp->id, rp->gii.ipaddr, rp->server);
+ warning("!Request(%s via %I on %s): for server %I not me",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->server);
} else
sendack(rp, rp->ii.ipaddr,
(staticlease > minlease? staticlease:
/* if we don't have an offer, nak */
if(b == nil){
- warning(0, "!Request(%s via %I): no offer",
- rp->id, rp->gii.ipaddr);
+ warning("!Request(%s via %I on %s): no offer",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev);
if(findifc(rp->server) == rp->ifc)
sendnak(rp, rp->server, "no offer for you");
return;
/* if not for me, retract offer */
if(findifc(rp->server) != rp->ifc){
b->expoffer = 0;
- warning(0, "!Request(%s via %I): for server %I not me",
- rp->id, rp->gii.ipaddr, rp->server);
+ warning("!Request(%s via %I on %s): for server %I not me",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->server);
return;
}
* client really shouldn't be specifying this when selecting
*/
if(validip(rp->ip) && ipcmp(rp->ip, b->ip) != 0){
- warning(0, "!Request(%s via %I): requests %I, not %I",
- rp->id, rp->gii.ipaddr, rp->ip, b->ip);
+ warning("!Request(%s via %I on %s): requests %I, not %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip, b->ip);
sendnak(rp, rp->ip, "bad ip address option");
return;
}
if(commitbinding(b) < 0){
- warning(0, "!Request(%s via %I): can't commit %I",
- rp->id, rp->gii.ipaddr, b->ip);
+ warning("!Request(%s via %I on %s): can't commit %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, b->ip);
sendnak(rp, b->ip, "can't commit binding");
return;
}
/* check for hard assignment */
if(rp->staticbinding){
if(ipcmp(rp->ip, rp->ii.ipaddr) != 0){
- warning(0, "!Request(%s via %I): %I not valid for %E",
- rp->id, rp->gii.ipaddr, rp->ip, rp->bp->chaddr);
+ warning("!Request(%s via %I on %s): %I not valid for %E",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip, rp->bp->chaddr);
sendnak(rp, rp->ip, "not valid");
} else
sendack(rp, rp->ip, (staticlease > minlease?
/* make sure the network makes sense */
if(!samenet(rp->ip, &rp->gii)){
- warning(0, "!Request(%s via %I): bad forward of %I",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Request(%s via %I on %s): bad forward of %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip);
return;
}
b = iptobinding(rp->ip, 0);
if(b == nil){
- warning(0, "!Request(%s via %I): no binding for %I",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Request(%s via %I on %s): no binding for %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip);
return;
}
if(ipcmp(rp->ip, b->ip) != 0 || now > b->lease){
- warning(0, "!Request(%s via %I): %I not valid",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Request(%s via %I on %s): %I not valid",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip);
sendnak(rp, rp->ip, "not valid");
return;
}
/* check for hard assignment */
if(rp->staticbinding){
if(ipcmp(rp->ciaddr, rp->ii.ipaddr) != 0){
- warning(0, "!Request(%s via %I): %I not valid",
- rp->id, rp->gii.ipaddr, rp->ciaddr);
+ warning("!Request(%s via %I on %s): %I not valid",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ciaddr);
sendnak(rp, rp->ciaddr, "not valid");
} else
sendack(rp, rp->ciaddr, (staticlease > minlease?
/* make sure the network makes sense */
if(!samenet(rp->ciaddr, &rp->gii)){
- warning(0, "!Request(%s via %I): bad forward of %I",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Request(%s via %I on %s): bad forward of %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ciaddr);
return;
}
b = iptobinding(rp->ciaddr, 0);
if(b == nil){
- warning(0, "!Request(%s via %I): no binding for %I",
- rp->id, rp->ciaddr, rp->ciaddr);
+ warning("!Request(%s via %I on %s): no binding for %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ciaddr);
return;
}
if(ipcmp(rp->ciaddr, b->ip) != 0){
- warning(0, "!Request(%s via %I): %I not valid",
- rp->id, rp->gii.ipaddr, rp->ciaddr);
+ warning("!Request(%s via %I on %s): %I not valid",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ciaddr);
sendnak(rp, rp->ciaddr, "invalid ip address");
return;
}
mkoffer(b, rp->id, rp->leasetime);
if(commitbinding(b) < 0){
- warning(0, "!Request(%s via %I): can't commit %I",
- rp->id, rp->gii.ipaddr, b->ip);
+ warning("!Request(%s via %I on %s): can't commit %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, b->ip);
sendnak(rp, b->ip, "can't commit binding");
return;
}
b = idtooffer(rp->id, &rp->gii);
if(b == nil){
- warning(0, "!Decline(%s via %I): no binding",
- rp->id, rp->gii.ipaddr);
+ warning("!Decline(%s via %I on %s): no binding",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev);
return;
}
b = idtobinding(rp->id, &rp->gii, 0);
if(b == nil){
- warning(0, "!Release(%s via %I): no binding",
- rp->id, rp->gii.ipaddr);
+ warning("!Release(%s via %I on %s): no binding",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev);
return;
}
if(strcmp(rp->id, b->boundto) != 0){
- warning(0, "!Release(%s via %I): invalid release of %I",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Release(%s via %I on %s): invalid release of %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip);
return;
}
- warning(0, "Release(%s via %I): releasing %I", b->boundto, rp->gii.ipaddr, b->ip);
+ warning("Release(%s via %I on %s): releasing %I",
+ b->boundto, rp->gii.ipaddr, rp->ifc->dev, b->ip);
if(releasebinding(b, rp->id) < 0)
- warning(0, "release: couldn't release");
+ warning("release: couldn't release");
}
void
b = iptobinding(rp->ciaddr, 0);
if(b == nil){
- warning(0, "!Inform(%s via %I): no binding for %I",
- rp->id, rp->gii.ipaddr, rp->ip);
+ warning("!Inform(%s via %I on %s): no binding for %I",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev, rp->ip);
return;
}
sendack(rp, b->ip, 0, 0);
} else {
ipmove(up->raddr, ip);
if(bp->htype == 1)
- arpenter(up->raddr, bp->chaddr, up->ifcaddr);
+ arpenter(up->raddr, bp->chaddr, up->laddr);
hnputs(up->rport, 68);
}
*/
n = rp->p - rp->buf;
if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
- warning(0, "offer: write failed: %r");
+ warning("offer: write failed: %r");
}
void
} else {
ipmove(up->raddr, ip);
if(bp->htype == 1)
- arpenter(up->raddr, bp->chaddr, up->ifcaddr);
+ arpenter(up->raddr, bp->chaddr, up->laddr);
hnputs(up->rport, 68);
}
*/
n = rp->p - rp->buf;
if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
- warning(0, "ack: write failed: %r");
+ warning("ack: write failed: %r");
}
void
*/
n = rp->p - rp->buf;
if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
- warning(0, "nak: write failed: %r");
+ warning("nak: write failed: %r");
}
void
ushort flags;
Info *iip;
- warning(0, "bootp %s %I->%I from %s via %I, file %s",
+ warning("bootp %s %I->%I from %s via %I on %s, file %s",
rp->genrequest? "generic": (rp->p9request? "p9": ""),
rp->up->raddr, rp->up->laddr,
- rp->id, rp->gii.ipaddr,
+ rp->id, rp->gii.ipaddr, rp->ifc->dev,
rp->bp->file);
if(nobootp)
iip = &rp->ii;
if(rp->staticbinding == 0){
- warning(0, "bootp from unknown %s via %I", rp->id, rp->gii.ipaddr);
+ warning("bootp from unknown %s via %I on %s",
+ rp->id, rp->gii.ipaddr, rp->ifc->dev);
return;
}
if(*bp->sname){
if(strcmp(bp->sname, mysysname) != 0){
bp->sname[20] = 0;
- warning(0, "bootp for server %s", bp->sname);
+ warning("bootp for server %s", bp->sname);
return;
}
} else
else if(*bp->sname) /* if we were asked, respond no matter what */
bp->file[0] = '\0';
else {
- warning(0, "no bootfile for %I", iip->ipaddr);
+ warning("no bootfile for %I", iip->ipaddr);
return;
}
}
/* ignore if the file is unreadable */
if((!rp->genrequest) && bp->file[0] && access(bp->file, 4) < 0){
- warning(0, "inaccessible bootfile1 %s", bp->file);
+ warning("inaccessible bootfile1 %s", bp->file);
return;
}
bp->op = Bootreply;
v6tov4(bp->yiaddr, iip->ipaddr);
if(rp->p9request){
- warning(0, "p9bootp: %I", iip->ipaddr);
+ warning("p9bootp: %I", iip->ipaddr);
memmove(bp->optmagic, plan9opt, 4);
rp->p += sprint((char*)rp->p, "%V %I %I %I",
iip->ipmask+IPv4off, iip->fsip, iip->auip, iip->gwip);
sprint(optbuf, "%s", (char*)(bp->optmagic));
} else if(rp->genrequest){
- warning(0, "genericbootp: %I", iip->ipaddr);
+ warning("genericbootp: %I", iip->ipaddr);
memmove(bp->optmagic, genericopt, 4);
miscoptions(rp, iip->ipaddr);
termopt(rp);
} else if(iip->vendor[0] != 0) {
- warning(0, "bootp vendor field: %s", iip->vendor);
+ warning("bootp vendor field: %s", iip->vendor);
memset(rp->p, 0, 128-4);
rp->p += sprint((char*)bp->optmagic, "%s", iip->vendor);
} else {
} else {
v4tov6(up->raddr, bp->yiaddr);
if(bp->htype == 1)
- arpenter(up->raddr, bp->chaddr, up->ifcaddr);
+ arpenter(up->raddr, bp->chaddr, up->laddr);
hnputs(up->rport, 68);
}
*/
n = rp->p - rp->buf;
if(!ismuted(rp) && write(rp->fd, rp->buf, n) != n)
- warning(0, "bootp: write failed: %r");
+ warning("bootp: write failed: %r");
- warning(0, "bootp via %I: file %s xid(%ux)flag(%ux)ci(%V)gi(%V)yi(%V)si(%V) %s",
+ warning("bootp via %I: file %s xid(%ux)flag(%ux)ci(%V)gi(%V)yi(%V)si(%V) %s",
up->raddr, bp->file, nhgetl(bp->xid), nhgets(bp->flags),
bp->ciaddr, bp->giaddr, bp->yiaddr, bp->siaddr,
optbuf);
case ODclientid:
if(n <= 1)
break;
- rp->id = toid( o, n);
+ rp->id = toid(o, n);
break;
case ODparams:
if(n > sizeof(rp->requested))
maskopt(rp, OBmask, rp->ii.ipmask);
else if(validip(rp->gii.ipmask))
maskopt(rp, OBmask, rp->gii.ipmask);
- else if((lifc = findlifc(ip, rp->ifc)) != nil)
+ else if((lifc = localonifc(ip, rp->ifc)) != nil)
maskopt(rp, OBmask, lifc->mask);
if(validip(rp->ii.gwip)){
sprint(data, "%s/udp!*!bootp", net);
cfd = announce(data, devdir);
if(cfd < 0)
- fatal(1, "can't announce");
+ fatal("can't announce: %r");
if(fprint(cfd, "headers") < 0)
- fatal(1, "can't set header mode");
+ fatal("can't set header mode: %r");
sprint(data, "%s/data", devdir);
fd = open(data, ORDWR);
if(fd < 0)
- fatal(1, "open udp data");
+ fatal("open udp data: %r");
return fd;
}
void
-fatal(int syserr, char *fmt, ...)
+fatal(char *fmt, ...)
{
char buf[Maxloglen];
va_list arg;
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
- if(syserr)
- syslog(1, blog, "%s: %r", buf);
- else
- syslog(1, blog, "%s", buf);
+ syslog(1, blog, "%s", buf);
exits(buf);
}
void
-warning(int syserr, char *fmt, ...)
+warning(char *fmt, ...)
{
char buf[Maxloglen];
va_list arg;
va_start(arg, fmt);
vseprint(buf, buf+sizeof(buf), fmt, arg);
va_end(arg);
- if(syserr){
- syslog(0, blog, "%s: %r", buf);
- if(debug)
- fprint(2, "%s: %r\n", buf);
- } else {
- syslog(0, blog, "%s", buf);
- if(debug)
- fprint(2, "%s\n", buf);
- }
+ syslog(0, blog, "%s", buf);
+ if(debug)
+ fprint(2, "%s\n", buf);
}
char*
return;
if (!isv4(ip)) {
if (debug)
- warning(0, "not a v4 %s server: %I", optname[t], ip);
+ warning("not a v4 %s server: %I", optname[t], ip);
return;
}
*rp->p++ = t;
v4s++;
if (v4s <= 0) {
if (debug)
- warning(0, "no v4 %s servers", optname[t]);
+ warning("no v4 %s servers", optname[t]);
return;
}
*rp->p++ = t;
}
void
-arpenter(uchar *ip, uchar *ether, uchar *ifcaddr)
+arpenter(uchar *ip, uchar *mac, uchar *src)
{
- int f;
char buf[256];
+ int fd, n;
- sprint(buf, "%s/arp", net);
- f = open(buf, OWRITE);
- if(f < 0){
- syslog(debug, blog, "open %s: %r", buf);
+ snprint(buf, sizeof buf, "%s/arp", net);
+ if((fd = open(buf, OWRITE)) < 0){
+ warning("couldn't open %s: %r", buf);
return;
}
- fprint(f, "add ether %I %E %I", ip, ether, ifcaddr);
- close(f);
+ n = snprint(buf, sizeof buf, "add ether %I %E %I\n", ip, mac, src);
+ if(write(fd, buf, n) != n)
+ warning("arpenter: %s: %r", buf);
+ close(fd);
}
char *dhcpmsgname[] =