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[4]; 27 uchar myether[6]; 28 char rlog[] = "ipboot"; 29 char *device = "ether"; 30 int debug; 31 Ndb *db; 32 33 void 34 error(char *s) 35 { 36 syslog(1, rlog, "error %s: %r", s); 37 exits(s); 38 } 39 40 void 41 main(int argc, char *argv[]) 42 { 43 int edata, ectl; 44 uchar buf[2048]; 45 long n; 46 Rarp *rp; 47 char ebuf[Ndbvlen]; 48 Arpentry entry; 49 int arp; 50 Ipinfo info; 51 52 ARGBEGIN{ 53 case 'e': 54 device = ARGF(); 55 break; 56 case 'd': 57 debug = 1; 58 break; 59 }ARGEND 60 USED(argc, argv); 61 62 fmtinstall('E', eipconv); 63 fmtinstall('I', eipconv); 64 65 db = ndbopen(0); 66 if(db == 0) 67 error("can't open the database"); 68 69 edata = dial(netmkaddr("0x8035", device, 0), 0, 0, &ectl); 70 if(edata < 0) 71 error("can't open ethernet"); 72 73 if(myipaddr(myip, "/net/udp") < 0) 74 error("can't get my ip address"); 75 sprint(ebuf, "/net/%s", device); 76 if(myetheraddr(myether, ebuf) < 0) 77 error("can't get my ether address"); 78 79 if((arp = open("/net/arp/data", ORDWR)) < 0) 80 if((arp = open("#a/arp/data", ORDWR)) < 0) 81 fprint(2, "rarpd: can't open /net/arp/data\n"); 82 83 switch(rfork(RFNOTEG|RFPROC|RFFDG)) { 84 case -1: 85 error("fork"); 86 case 0: 87 break; 88 default: 89 exits(0); 90 } 91 92 for(;;){ 93 n = read(edata, buf, sizeof(buf)); 94 if(n <= 0) 95 error("reading"); 96 if(n < sizeof(Rarp)){ 97 syslog(debug, rlog, "bad packet size %d", n); 98 continue; 99 } 100 rp = (Rarp*)buf; 101 if(rp->op[0]!=0 && rp->op[1]!=3){ 102 syslog(debug, rlog, "bad op %d %d %E", 103 rp->op[1], rp->op[0], rp->esrc); 104 continue; 105 } 106 107 if(debug) 108 syslog(debug, rlog, "rcv se %E si %I te %E ti %I", 109 rp->sha, rp->spa, rp->tha, rp->tpa); 110 111 sprint(ebuf, "%E", rp->tha); 112 if(ipinfo(db, ebuf , 0, 0, &info) < 0){ 113 syslog(debug, rlog, "client lookup failed: %s", ebuf); 114 continue; 115 } 116 117 memmove(rp->sha, myether, sizeof(rp->sha)); 118 memmove(rp->spa, myip, sizeof(rp->spa)); 119 120 rp->op[0] = 0; 121 rp->op[1] = 4; 122 memmove(rp->edst, rp->esrc, sizeof(rp->edst)); 123 memmove(rp->tpa, info.ipaddr, sizeof(rp->tpa)); 124 125 if(debug) 126 syslog(debug, rlog, "send se %E si %I te %E ti %I", 127 rp->sha, rp->spa, rp->tha, rp->tpa); 128 129 if(write(edata, buf, 42) != 42) 130 error("write failed"); 131 132 if(arp < 0) 133 continue; 134 memmove(entry.etaddr, rp->esrc, sizeof(entry.etaddr)); 135 memmove(entry.ipaddr, rp->tpa, sizeof(entry.ipaddr)); 136 if(write(arp, &entry, sizeof(entry)) < 0) 137 perror("write arp entry"); 138 } 139 } 140