193 lines
3.3 KiB
C
193 lines
3.3 KiB
C
|
#include <u.h>
|
||
|
#include <libc.h>
|
||
|
#include <bio.h>
|
||
|
#include <ip.h>
|
||
|
#include <ndb.h>
|
||
|
#include "arp.h"
|
||
|
|
||
|
typedef struct Rarp Rarp;
|
||
|
|
||
|
struct Rarp
|
||
|
{
|
||
|
uchar edst[6];
|
||
|
uchar esrc[6];
|
||
|
uchar type[2];
|
||
|
uchar hrd[2];
|
||
|
uchar pro[2];
|
||
|
uchar hln;
|
||
|
uchar pln;
|
||
|
uchar op[2];
|
||
|
uchar sha[6];
|
||
|
uchar spa[4];
|
||
|
uchar tha[6];
|
||
|
uchar tpa[4];
|
||
|
};
|
||
|
|
||
|
uchar myip[IPaddrlen];
|
||
|
uchar myether[6];
|
||
|
char rlog[] = "ipboot";
|
||
|
char *device = "ether0";
|
||
|
int debug;
|
||
|
Ndb *db;
|
||
|
|
||
|
char* lookup(char*, char*, char*, char*, int);
|
||
|
|
||
|
void
|
||
|
error(char *s)
|
||
|
{
|
||
|
syslog(1, rlog, "error %s: %r", s);
|
||
|
exits(s);
|
||
|
}
|
||
|
|
||
|
char net[32];
|
||
|
|
||
|
void
|
||
|
usage(void)
|
||
|
{
|
||
|
fprint(2, "usage: %s [-e device] [-x netmtpt] [-f ndb-file] [-d]\n", argv0);
|
||
|
exits("usage");
|
||
|
}
|
||
|
|
||
|
void
|
||
|
main(int argc, char *argv[])
|
||
|
{
|
||
|
int edata, ectl;
|
||
|
uchar buf[2048];
|
||
|
long n;
|
||
|
Rarp *rp;
|
||
|
char ebuf[16];
|
||
|
char ipbuf[64];
|
||
|
char file[128];
|
||
|
int arp;
|
||
|
char *p, *ndbfile;
|
||
|
|
||
|
ndbfile = nil;
|
||
|
setnetmtpt(net, sizeof(net), nil);
|
||
|
ARGBEGIN{
|
||
|
case 'e':
|
||
|
p = ARGF();
|
||
|
if(p == nil)
|
||
|
usage();
|
||
|
device = p;
|
||
|
break;
|
||
|
case 'd':
|
||
|
debug = 1;
|
||
|
break;
|
||
|
case 'f':
|
||
|
p = ARGF();
|
||
|
if(p == nil)
|
||
|
usage();
|
||
|
ndbfile = p;
|
||
|
break;
|
||
|
case 'x':
|
||
|
p = ARGF();
|
||
|
if(p == nil)
|
||
|
usage();
|
||
|
setnetmtpt(net, sizeof(net), p);
|
||
|
break;
|
||
|
}ARGEND
|
||
|
USED(argc, argv);
|
||
|
|
||
|
fmtinstall('E', eipfmt);
|
||
|
fmtinstall('I', eipfmt);
|
||
|
fmtinstall('V', eipfmt);
|
||
|
|
||
|
db = ndbopen(ndbfile);
|
||
|
if(db == 0)
|
||
|
error("can't open the database");
|
||
|
|
||
|
edata = dial(netmkaddr("0x8035", device, 0), 0, 0, &ectl);
|
||
|
if(edata < 0)
|
||
|
error("can't open ethernet");
|
||
|
|
||
|
if(myipaddr(myip, net) < 0)
|
||
|
error("can't get my ip address");
|
||
|
sprint(ebuf, "%s/%s", net, device);
|
||
|
if(myetheraddr(myether, ebuf) < 0)
|
||
|
error("can't get my ether address");
|
||
|
|
||
|
snprint(file, sizeof(file), "%s/arp", net);
|
||
|
if((arp = open(file, ORDWR)) < 0)
|
||
|
fprint(2, "rarpd: can't open %s\n", file);
|
||
|
|
||
|
switch(rfork(RFNOTEG|RFPROC|RFFDG)) {
|
||
|
case -1:
|
||
|
error("fork");
|
||
|
case 0:
|
||
|
break;
|
||
|
default:
|
||
|
exits(0);
|
||
|
}
|
||
|
|
||
|
for(;;){
|
||
|
n = read(edata, buf, sizeof(buf));
|
||
|
if(n <= 0)
|
||
|
error("reading");
|
||
|
if(n < sizeof(Rarp)){
|
||
|
syslog(debug, rlog, "bad packet size %ld", n);
|
||
|
continue;
|
||
|
}
|
||
|
rp = (Rarp*)buf;
|
||
|
if(rp->op[0]!=0 && rp->op[1]!=3){
|
||
|
syslog(debug, rlog, "bad op %d %d %E",
|
||
|
rp->op[1], rp->op[0], rp->esrc);
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if(debug)
|
||
|
syslog(debug, rlog, "rcv se %E si %V te %E ti %V",
|
||
|
rp->sha, rp->spa, rp->tha, rp->tpa);
|
||
|
|
||
|
sprint(ebuf, "%E", rp->tha);
|
||
|
if(lookup("ether", ebuf, "ip", ipbuf, sizeof ipbuf) == nil){
|
||
|
syslog(debug, rlog, "client lookup failed: %s", ebuf);
|
||
|
continue;
|
||
|
}
|
||
|
v4parseip(rp->tpa, ipbuf);
|
||
|
|
||
|
memmove(rp->sha, myether, sizeof(rp->sha));
|
||
|
v6tov4(rp->spa, myip);
|
||
|
|
||
|
rp->op[0] = 0;
|
||
|
rp->op[1] = 4;
|
||
|
memmove(rp->edst, rp->esrc, sizeof(rp->edst));
|
||
|
|
||
|
if(debug)
|
||
|
syslog(debug, rlog, "send se %E si %V te %E ti %V",
|
||
|
rp->sha, rp->spa, rp->tha, rp->tpa);
|
||
|
|
||
|
if(write(edata, buf, 60) != 60)
|
||
|
error("write failed");
|
||
|
|
||
|
if(arp < 0)
|
||
|
continue;
|
||
|
if(fprint(arp, "add %E %V", rp->esrc, rp->tpa) < 0)
|
||
|
fprint(2, "can't write arp entry\n");
|
||
|
}
|
||
|
}
|
||
|
|
||
|
char*
|
||
|
lookup(char *sattr, char *sval, char *tattr, char *tval, int len)
|
||
|
{
|
||
|
static Ndb *db;
|
||
|
char *attrs[1];
|
||
|
Ndbtuple *t;
|
||
|
|
||
|
if(db == nil)
|
||
|
db = ndbopen(0);
|
||
|
if(db == nil)
|
||
|
return nil;
|
||
|
|
||
|
if(sattr == nil)
|
||
|
sattr = ipattr(sval);
|
||
|
|
||
|
attrs[0] = tattr;
|
||
|
t = ndbipinfo(db, sattr, sval, attrs, 1);
|
||
|
if(t == nil)
|
||
|
return nil;
|
||
|
strncpy(tval, t->val, len);
|
||
|
tval[len-1] = 0;
|
||
|
ndbfree(t);
|
||
|
return tval;
|
||
|
}
|