xref: /plan9/sys/src/cmd/ip/rarpd.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
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