|
|
1.1 root 1: #include <sys/param.h>
2: #include <stdio.h>
3: #include <errno.h>
4: #include <signal.h>
5: #include <sys/filio.h>
6: #include <sys/inio.h>
7: #include <sys/enio.h>
8: #include <sys/inet/ethernet.h>
9: #include <sys/inet/in.h>
10: #include "config.h"
11:
12: extern errno;
13: extern unsigned short htons();
14: extern int ip_ld;
15: extern char *optarg;
16: extern int optind;
17: char *enpr();
18:
19: /*
20: * global because we're too lazy to pass them as args
21: */
22: int debug, fool;
23: in_addr myinaddr, hisinaddr, mask, broadcast;
24: int superarp;
25: u_char myenaddr[6];
26: u_char noether[6];
27:
28: usage(name)
29: char *name;
30: {
31: fprint(2,
32: "Usage: %s [-m subnet-mask] [-s] device myinaddr hisinaddr [arp-device]\n",
33: name);
34: fprint(2,
35: " %s [-m subnet-mask] [-s] myinaddr hisinaddr\n",
36: name);
37: fprint(2,
38: " %s [-m subnet-mask] [-s] myinaddr\n",
39: name);
40: exit(1);
41: }
42:
43: main(argc, argv)
44: char *argv[];
45: {
46: char *dev, *me, *it, *arp;
47: int ipfd, enfd, x, ld;
48: int c, mtu;
49:
50: /*
51: * process arguments
52: */
53: while((c = getopt(argc, argv, "dfm:s")) != -1)
54: switch(c){
55: case 'd':
56: /*
57: * debugging
58: */
59: debug = 1;
60: break;
61: case 'f':
62: /*
63: * fool people not understanding the
64: * broadcast IP address to shut them up
65: */
66: fool = 1;
67: break;
68: case 'm':
69: /*
70: * subnet mask
71: */
72: if(strchr(optarg, '.'))
73: mask = in_aton(optarg);
74: else
75: sscanf(optarg, "%x", &mask);
76: break;
77: case 's':
78: /*
79: * answer all arp requests for this net ignoring mask
80: */
81: superarp = 1;
82: break;
83: default:
84: usage(argv[0]);
85: break;
86: }
87:
88: switch(argc-optind){
89: case 1:
90: dev = 0;
91: me = argv[optind++];
92: it = me;
93: arp = 0;
94: break;
95: case 2:
96: dev = 0;
97: me = argv[optind++];
98: it = argv[optind++];
99: arp = 0;
100: break;
101: case 3:
102: dev = argv[optind++];
103: me = argv[optind++];
104: it = argv[optind++];
105: arp = 0;
106: break;
107: case 4:
108: dev = argv[optind++];
109: me = argv[optind++];
110: it = argv[optind++];
111: arp = argv[optind++];
112: break;
113: default:
114: usage(argv[0]);
115: break;
116: }
117:
118: /*
119: * look up the addresses
120: */
121: hisinaddr = in_address(it);
122: if(hisinaddr == 0){
123: logevent("ipconfig: unknown host/net %s\n", it);
124: exit(1);
125: }
126: myinaddr = in_addronnet(me, hisinaddr, mask);
127: if(myinaddr == 0){
128: logevent("ipconfig: no host %s on same net as %s\n", me,it);
129: exit(1);
130: }
131:
132: /*
133: * push disciplines onto the right device
134: */
135: signal(SIGHUP, SIG_IGN);
136: if(dev) {
137: ipfd = open(dev, 2);
138: if(ipfd < 0){
139: perror(dev);
140: exit(1);
141: }
142: if(arp){
143: x = htons((unsigned short)ETHERPUP_IPTYPE);
144: if(ioctl(ipfd, ENIOTYPE, &x) < 0){
145: logevent("ENIOTYPE\n");
146: exit(1);
147: }
148: }
149: flavor(ipfd, myinaddr, hisinaddr, mtu);
150: } else {
151: int pfd[2];
152: if(pipe(pfd)<0){
153: logevent("pipe\n");
154: exit(1);
155: }
156: flavor(pfd[0], myinaddr, hisinaddr, mtu);
157: flavor(pfd[1], hisinaddr, myinaddr, mtu);
158: }
159:
160: /*
161: * wait for ever or do arping
162: */
163: if(arp == 0){
164: if(!debug)
165: detach("ipconfig");
166: pause(); /* forever, hopefully */
167: exit(0);
168: }
169: if(ioctl(ipfd, IPIOARP, 0) < 0){
170: logevent("IPIOARP\n");
171: exit(1);
172: }
173: enfd = open(arp, 2);
174: if(enfd < 0){
175: logevent("can't open arp device %s\n", arp);
176: exit(1);
177: }
178: if(!debug)
179: detach("ipconfig");
180: doarp(ipfd, enfd);
181: }
182:
183: flavor(ipfd, myinaddr, hisinaddr, mtu)
184: int ipfd;
185: in_addr myinaddr, hisinaddr;
186: int mtu;
187: {
188: if(ioctl(ipfd, FIOPUSHLD, &ip_ld) < 0){
189: logevent("PUSHLD\n");
190: exit(1);
191: }
192:
193: /*
194: * tell the line disciplines the identity of the ends
195: */
196: if(ioctl(ipfd, IPIOLOCAL, &myinaddr) < 0){
197: logevent("IPIOLOCAL\n");
198: exit(1);
199: }
200: if(hisinaddr!=in_netof(hisinaddr) && !mask){
201: /*
202: * host to host connection
203: */
204: ioctl(ipfd, IPIOHOST, &hisinaddr);
205: broadcast = hisinaddr;
206: } else {
207: /*
208: * host to network connection
209: */
210: mtu = 1500;
211: ioctl(ipfd, IPIOMTU, &mtu);
212: ioctl(ipfd, IPIONET, &hisinaddr);
213: if(mask) {
214: ioctl(ipfd, IPIOMASK, &mask);
215: broadcast = hisinaddr | ~mask;
216: } else {
217: broadcast = hisinaddr |
218: (IN_CLASSA(hisinaddr) ? IN_CLASSA_HOST :
219: (IN_CLASSB(hisinaddr) ? IN_CLASSB_HOST :
220: (IN_CLASSC(hisinaddr) ? IN_CLASSC_HOST :
221: 0)));
222: }
223: }
224: }
225:
226: /*
227: * Address resolution
228: */
229:
230: struct ether_arp{
231: /* driver goo */
232: struct etherpup arp_ether;
233:
234: /* arp stuff */
235: u_short arp_hrd;
236: #define ARPHRD_ETHER 1
237: u_short arp_pro;
238: u_char arp_hln;
239: u_char arp_pln;
240: u_short arp_op;
241: #define ARPOP_REQUEST 1
242: #define ARPOP_REPLY 2
243: u_char arp_sha[6]; /* sender ether addr */
244: u_char arp_spa[4]; /* sender internet addr */
245: u_char arp_tha[6]; /* target ether addr */
246: u_char arp_tpa[4]; /* target internet addr */
247: };
248:
249: u_char broadaddr[6] = {
250: 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
251: };
252:
253: /* wait for ARP requests and answers */
254: doarp(ipfd, enfd)
255: int ipfd;
256: int enfd;
257: {
258: fd_set rdfds;
259: int x;
260: char buf[2000];
261: struct goo{
262: in_addr inaddr;
263: u_char enaddr[6];
264: } goo;
265: in_addr tpa;
266:
267: x = htons((u_short)ETHERPUP_ARPTYPE);
268: if(ioctl(enfd, ENIOTYPE, &x) < 0){
269: perror("ipconfig: ENIOTYPE");
270: exit(1);
271: }
272: if(ioctl(enfd, ENIOADDR, myenaddr) < 0){
273: perror("ipconfig: ENIOADDR");
274: exit(1);
275: }
276:
277: FD_ZERO(rdfds);
278: while(1){
279: FD_SET(ipfd, rdfds);
280: FD_SET(enfd, rdfds);
281:
282: errno = 0; /* just in case */
283: if(select(20, &rdfds, 0, 2000) < 0){
284: if(errno == EINTR)
285: continue;
286: logevent("ipconfig: select error\n");
287: exit(1);
288: }
289: if(FD_ISSET(ipfd, rdfds)){
290: if(read(ipfd, &tpa, sizeof(tpa)) != sizeof(tpa))
291: logevent("ipconfig: in read\n");
292: arpwhohas(enfd, ipfd, tpa);
293: }
294: if(FD_ISSET(enfd, rdfds)){
295: if(read(enfd, buf, sizeof(buf)) <= 0)
296: logevent("ipconfig: en read\n");
297: arpinput(ipfd, enfd, buf);
298: }
299: }
300: }
301:
302: /* broadcast an arp request */
303: arpwhohas(enfd, ipfd, addr)
304: in_addr addr;
305: {
306: struct goo{
307: in_addr inaddr;
308: u_char enaddr[6];
309: } goo;
310: struct ether_arp a;
311: in_addr rddaniym;
312:
313: if(addr == myinaddr){
314: goo.inaddr = addr;
315: bcopy(myenaddr, goo.enaddr, sizeof(goo.enaddr));
316: ioctl(ipfd, IPIORESOLVE, &goo);
317: return;
318: }
319: if(addr == hisinaddr || addr == broadcast){
320: goo.inaddr = addr;
321: bcopy(broadaddr, goo.enaddr, sizeof(goo.enaddr));
322: ioctl(ipfd, IPIORESOLVE, &goo);
323: return;
324: }
325: bcopy(broadaddr, a.arp_ether.dhost, sizeof(a.arp_ether.dhost));
326: a.arp_ether.type = htons(ETHERPUP_ARPTYPE);
327:
328: a.arp_hrd = htons(ARPHRD_ETHER);
329: a.arp_pro = htons(ETHERPUP_IPTYPE);
330: a.arp_hln = sizeof(goo.enaddr);
331: a.arp_pln = sizeof(in_addr);
332: a.arp_op = htons(ARPOP_REQUEST);
333:
334: bcopy(myenaddr, a.arp_sha, sizeof(a.arp_sha));
335: rddaniym = htonl(myinaddr);
336: bcopy(&rddaniym, a.arp_spa, sizeof(a.arp_spa));
337: addr = htonl(addr);
338: bcopy(&addr, a.arp_tpa, sizeof(a.arp_tpa));
339:
340: write(enfd, &a, sizeof(a));
341: }
342:
343: /* process an arp request */
344: arpinput(ipfd, enfd, ap)
345: struct ether_arp *ap;
346: {
347: struct goo{
348: in_addr inaddr;
349: u_char enaddr[6];
350: } goo;
351: in_addr spa, tpa;
352: in_addr rddaniym;
353: int forgery = 0;
354:
355: bcopy(ap->arp_spa, &spa, sizeof(spa));
356: bcopy(ap->arp_tpa, &tpa, sizeof(tpa));
357: spa = ntohl(spa);
358: tpa = ntohl(tpa);
359:
360: if(debug){
361: print("%s from %s",
362: ap->arp_op == ntohs(ARPOP_REQUEST) ? "request" : "answer",
363: in_ntoa(spa));
364: print(" for %s\n", in_ntoa(tpa));
365: }
366:
367: if(ntohs(ap->arp_pro) != ETHERPUP_IPTYPE)
368: return;
369:
370: /* make sure noone's trying to be me */
371: if(memcmp(ap->arp_sha, myenaddr, sizeof(myenaddr)) != 0){
372: if(spa == myinaddr){
373: /*
374: * scream on the console and send out an
375: * arp packet with my correct ether addrss
376: */
377: logconsole("ipconfig: machine at ether address %s is forging my IP address\n", enpr(ap->arp_ether.shost));
378: tpa = spa;
379: bcopy(myenaddr, ap->arp_sha, sizeof(myenaddr));
380: forgery = 1;
381: }
382: }
383:
384: if(!forgery){
385: /* incorporate sender's address */
386: goo.inaddr = spa;
387: bcopy(ap->arp_sha, goo.enaddr, sizeof(goo.enaddr));
388: if(ioctl(ipfd, IPIORESOLVE, &goo) < 0)
389: logevent("ipconfig: IPIORESOLVE");
390:
391: /* send reply only to a request */
392: if(ap->arp_op != ntohs(ARPOP_REQUEST))
393: return;
394: }
395:
396: /* accept the request if
397: * (1) the target is me or
398: * (2) superarp==1 and ( the target is not on my subnet &&
399: * the target is on my net )
400: */
401: if(tpa==myinaddr || (superarp && in_netof(tpa)==in_netof(myinaddr) &&
402: in_subnetof(tpa, mask)!=in_subnetof(myinaddr, mask))){
403: if(debug)
404: print("answering %s\n", enpr(ap->arp_sha));
405: ap->arp_hrd = htons(ARPHRD_ETHER);
406: ap->arp_pro = htons(ETHERPUP_IPTYPE);
407: ap->arp_op = htons(ARPOP_REPLY);
408: rddaniym = htonl(tpa);
409: tpa = htonl(spa);
410: spa = rddaniym;
411: bcopy(&tpa, ap->arp_tpa, sizeof(ap->arp_tpa));
412: bcopy(&spa, ap->arp_spa, sizeof(ap->arp_spa));
413: bcopy(ap->arp_sha, ap->arp_tha, sizeof(ap->arp_tha));
414: bcopy(myenaddr, ap->arp_sha, sizeof(ap->arp_sha));
415: bcopy(broadaddr, ap->arp_ether.dhost, sizeof(ap->arp_ether.dhost));
416: ap->arp_ether.type = htons(ETHERPUP_ARPTYPE);
417: write(enfd, ap, sizeof(struct ether_arp));
418: } else if((tpa==hisinaddr || tpa==broadcast)){
419: /*
420: * For various reasons, some systems to not understand
421: * the correct IP address to use for broadcast. This
422: * causes them to send there future arp requests (for that
423: * address) to a non-existant ether address.
424: */
425: logevent("bozo request from %s", in_ntoa(spa));
426: fprint(2, " for %s\n", in_ntoa(tpa));
427: if(fool){
428: logevent("giving him bozoid arp response\n");
429: ap->arp_hrd = htons(ARPHRD_ETHER);
430: ap->arp_pro = htons(ETHERPUP_IPTYPE);
431: ap->arp_op = htons(ARPOP_REPLY);
432: rddaniym = htonl(tpa);
433: tpa = htonl(spa);
434: spa = rddaniym;
435: bcopy(&tpa, ap->arp_tpa, sizeof(ap->arp_tpa));
436: bcopy(&spa, ap->arp_spa, sizeof(ap->arp_spa));
437: bcopy(ap->arp_sha, ap->arp_tha, sizeof(ap->arp_tha));
438: bcopy(noether, ap->arp_sha, sizeof(ap->arp_sha));
439: bcopy(ap->arp_ether.shost, ap->arp_ether.dhost,sizeof(ap->arp_ether.dhost));
440: ap->arp_ether.type = htons(ETHERPUP_ARPTYPE);
441:
442: write(enfd, ap, sizeof(struct ether_arp));
443: }
444: }
445: }
446:
447: arppr(a)
448: struct ether_arp a;
449: {
450: in_addr spa, tpa;
451:
452: print("dhost %s\n", enpr(a.arp_ether.dhost));
453: print("shost %s\n", enpr(a.arp_ether.shost));
454: print("type %x\n", ntohs(a.arp_ether.type));
455: a.arp_hrd = ntohs(a.arp_hrd);
456: a.arp_pro = ntohs(a.arp_pro);
457: a.arp_op = ntohs(a.arp_op);
458:
459: bcopy(a.arp_spa, &spa, sizeof(spa));
460: bcopy(a.arp_tpa, &tpa, sizeof(tpa));
461: tpa = ntohl(tpa);
462: spa = ntohl(spa);
463:
464: print("hrd %d pro %x op %d spa %x tpa %x\n",
465: a.arp_hrd, a.arp_pro, a.arp_op, spa, tpa);
466: print("sha %s\n", enpr(a.arp_sha));
467: print("tha %s\n", enpr(a.arp_tha));
468: }
469:
470: char *
471: enpr(en)
472: u_char *en;
473: {
474: static char a[128];
475:
476: sprint(a, "%02x %02x %02x %02x %02x %02x", en[0], en[1], en[2],
477: en[3], en[4], en[5]);
478: return a;
479: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.