1 #include <u.h> 2 #include <libc.h> 3 #include <bio.h> 4 #include <ip.h> 5 #include <ndb.h> 6 #include "arp.h" 7 8 typedef struct Rarp Rarp; 9 10 struct Rarp 11 { 12 uchar edst[6]; 13 uchar esrc[6]; 14 uchar type[2]; 15 uchar hrd[2]; 16 uchar pro[2]; 17 uchar hln; 18 uchar pln; 19 uchar op[2]; 20 uchar sha[6]; 21 uchar spa[4]; 22 uchar tha[6]; 23 uchar tpa[4]; 24 }; 25 26 uchar myip[IPaddrlen]; 27 uchar myether[6]; 28 char rlog[] = "ipboot"; 29 char *device = "ether0"; 30 int debug; 31 Ndb *db; 32 33 char* lookup(char*, char*, char*, char*, int); 34 35 void 36 error(char *s) 37 { 38 syslog(1, rlog, "error %s: %r", s); 39 exits(s); 40 } 41 42 char net[32]; 43 44 void 45 usage(void) 46 { 47 fprint(2, "usage: %s [-e device] [-x netmtpt] [-f ndb-file] [-d]\n", argv0); 48 exits("usage"); 49 } 50 51 void 52 main(int argc, char *argv[]) 53 { 54 int edata, ectl; 55 uchar buf[2048]; 56 long n; 57 Rarp *rp; 58 char ebuf[16]; 59 char ipbuf[64]; 60 char file[128]; 61 int arp; 62 char *p, *ndbfile; 63 64 ndbfile = nil; 65 setnetmtpt(net, sizeof(net), nil); 66 ARGBEGIN{ 67 case 'e': 68 p = ARGF(); 69 if(p == nil) 70 usage(); 71 device = p; 72 break; 73 case 'd': 74 debug = 1; 75 break; 76 case 'f': 77 p = ARGF(); 78 if(p == nil) 79 usage(); 80 ndbfile = p; 81 break; 82 case 'x': 83 p = ARGF(); 84 if(p == nil) 85 usage(); 86 setnetmtpt(net, sizeof(net), p); 87 break; 88 }ARGEND 89 USED(argc, argv); 90 91 fmtinstall('E', eipfmt); 92 fmtinstall('I', eipfmt); 93 fmtinstall('V', eipfmt); 94 95 db = ndbopen(ndbfile); 96 if(db == 0) 97 error("can't open the database"); 98 99 edata = dial(netmkaddr("0x8035", device, 0), 0, 0, &ectl); 100 if(edata < 0) 101 error("can't open ethernet"); 102 103 if(myipaddr(myip, net) < 0) 104 error("can't get my ip address"); 105 sprint(ebuf, "%s/%s", net, device); 106 if(myetheraddr(myether, ebuf) < 0) 107 error("can't get my ether address"); 108 109 snprint(file, sizeof(file), "%s/arp", net); 110 if((arp = open(file, ORDWR)) < 0) 111 fprint(2, "rarpd: can't open %s\n", file); 112 113 switch(rfork(RFNOTEG|RFPROC|RFFDG)) { 114 case -1: 115 error("fork"); 116 case 0: 117 break; 118 default: 119 exits(0); 120 } 121 122 for(;;){ 123 n = read(edata, buf, sizeof(buf)); 124 if(n <= 0) 125 error("reading"); 126 if(n < sizeof(Rarp)){ 127 syslog(debug, rlog, "bad packet size %ld", n); 128 continue; 129 } 130 rp = (Rarp*)buf; 131 if(rp->op[0]!=0 && rp->op[1]!=3){ 132 syslog(debug, rlog, "bad op %d %d %E", 133 rp->op[1], rp->op[0], rp->esrc); 134 continue; 135 } 136 137 if(debug) 138 syslog(debug, rlog, "rcv se %E si %V te %E ti %V", 139 rp->sha, rp->spa, rp->tha, rp->tpa); 140 141 sprint(ebuf, "%E", rp->tha); 142 if(lookup("ether", ebuf, "ip", ipbuf, sizeof ipbuf) == nil){ 143 syslog(debug, rlog, "client lookup failed: %s", ebuf); 144 continue; 145 } 146 v4parseip(rp->tpa, ipbuf); 147 148 memmove(rp->sha, myether, sizeof(rp->sha)); 149 v6tov4(rp->spa, myip); 150 151 rp->op[0] = 0; 152 rp->op[1] = 4; 153 memmove(rp->edst, rp->esrc, sizeof(rp->edst)); 154 155 if(debug) 156 syslog(debug, rlog, "send se %E si %V te %E ti %V", 157 rp->sha, rp->spa, rp->tha, rp->tpa); 158 159 if(write(edata, buf, 60) != 60) 160 error("write failed"); 161 162 if(arp < 0) 163 continue; 164 if(fprint(arp, "add %E %V", rp->esrc, rp->tpa) < 0) 165 fprint(2, "can't write arp entry\n"); 166 } 167 } 168 169 char* 170 lookup(char *sattr, char *sval, char *tattr, char *tval, int len) 171 { 172 static Ndb *db; 173 char *attrs[1]; 174 Ndbtuple *t; 175 176 if(db == nil) 177 db = ndbopen(0); 178 if(db == nil) 179 return nil; 180 181 if(sattr == nil) 182 sattr = ipattr(sval); 183 184 attrs[0] = tattr; 185 t = ndbipinfo(db, sattr, sval, attrs, 1); 186 if(t == nil) 187 return nil; 188 strncpy(tval, t->val, len); 189 tval[len-1] = 0; 190 ndbfree(t); 191 return tval; 192 } 193