|
|
1.1 root 1: #include <u.h>
2: #include <libc.h>
3: #include "../port/bootp.h"
4: #include "../port/arp.h"
5: #include "../boot/boot.h"
6:
7: /*
8: * il
9: */
10: uchar fsip[4];
11: uchar auip[4];
12: uchar gwip[4];
13: uchar ipmask[4];
14: uchar ipaddr[4]; /* our ip address */
15: uchar eaddr[6]; /* our ether address */
16: uchar bcast[6]; /* our ether broadcast address */
17: uchar ipnet[4]; /* our ip network number */
18:
19: static void arp(uchar*);
20: static int arplisten(void);
21: static ushort nhgets(uchar*);
22: static void hnputs(uchar*, ushort);
23: static void parseip(uchar*, char*);
24: static int myetheraddr(uchar*, char*);
25: static int parseether(uchar*, char*);
26: static int mygetfields(char*, char**, int);
27: static char* fmtaddr(uchar*);
28: static void maskip(uchar*, uchar*, uchar*);
29: static int equivip(uchar*, uchar*);
30: static void etheripconfig(Method*);
31: static int ipdial(int*, char*, uchar*, int);
32: static void catchint(void*, char*);
33:
34: uchar classmask[4][4] = {
35: 0xff, 0x00, 0x00, 0x00,
36: 0xff, 0x00, 0x00, 0x00,
37: 0xff, 0xff, 0x00, 0x00,
38: 0xff, 0xff, 0xff, 0x00,
39: };
40:
41: void
42: configtcp(Method *mp)
43: {
44: etheripconfig(mp);
45: }
46:
47: int
48: authtcp(void)
49: {
50: return -1;
51: }
52:
53: int
54: connecttcp(void)
55: {
56: int fd[2], rv;
57:
58: rv = ipdial(fd, "#Itcp/tcp", fsip, 564);
59: if(cpuflag)
60: sendmsg(fd[0], "push reboot");
61: sendmsg(fd[0], "push fcall");
62: if(rv >= 0)
63: close(fd[0]);
64: return fd[1];
65: }
66:
67: void
68: configil(Method *mp)
69: {
70: etheripconfig(mp);
71: }
72:
73: int
74: authil(void)
75: {
76: int fd[2];
77:
78: if(auip[0] == 0 || ipdial(fd, "#Iil/il", auip, 566) < 0)
79: return -1;
80: close(fd[0]);
81: return fd[1];
82: }
83:
84: int
85: connectil(void)
86: {
87: int fd[2], rv;
88:
89: rv = ipdial(fd, "#Iil/il", fsip, 17008);
90: if(cpuflag)
91: sendmsg(fd[0], "push reboot");
92: if(rv >= 0)
93: close(fd[0]);
94: return fd[1];
95: }
96:
97: static void
98: etheripconfig(Method *mp)
99: {
100: int efd[2];
101:
102: /* configure/open ip */
103: myetheraddr(eaddr, "#l/ether");
104: /*print("my etheraddr is %2.2ux%2.2ux%2.2ux%2.2ux%2.2ux%2.2ux\n", eaddr[0], eaddr[1],
105: eaddr[2], eaddr[3], eaddr[4], eaddr[5]);/**/
106: if(plumb("#l/ether", "0x800", efd, 0) < 0)
107: fatal("opening ip ether");
108:
109: sendmsg(efd[0], "push arp");
110: sendmsg(efd[0], "push internet");
111: sendmsg(efd[0], "push permanent");
112:
113: /* do a bootp to find fs, auth server, & gateway */
114: bootp(mp, efd[0], 0);
115:
116: /* done with the mux */
117: close(efd[0]);
118: close(efd[1]);
119: }
120:
121: /*
122: * configure ip. use bootp to get ip address, net mask, file server ip address,
123: * authentication server ip address and gateway ip address.
124: */
125: void
126: bootp(Method *mp, int muxctlfd, uchar *useipaddr)
127: {
128: int fd;
129: int ufd[2];
130: int n;
131: int tries;
132: Bootp req, *rp;
133: char *field[4];
134: char buf[1600];
135: char buf2[64];
136: uchar ipbcast[4]; /* ip broadcast address for bootp */
137:
138: /* determine bootp broadcast address from specified file system address */
139: if(*sys){
140: parseip(fsip, sys);
141: parseip(gwip, sys);
142: memmove(ipmask, classmask[fsip[0]>>6], sizeof(ipmask));
143: for(n = 0; n < sizeof(ipbcast); n++)
144: ipbcast[n] = (ipmask[n] & fsip[n]) | ((~ipmask[n])&0xff);
145: sprint(buf2, "%s!67", fmtaddr(ipbcast));
146: } else {
147: memmove(ipmask, classmask[3], sizeof(ipmask));
148: strcpy(buf2, "255.255.255.255!67");
149: }
150:
151: memset(bcast, 0xff, sizeof(bcast)); /* ether broadcast address */
152:
153: /* open a udp connection for bootp and fill in a packet */
154: if(plumb("#Iudp/udp", buf2, ufd, "68") < 0)
155: fatal("opening bootp udp");
156: close(ufd[0]);
157: memset(&req, 0, sizeof(req));
158: req.op = Bootrequest;
159: req.htype = 1; /* ethernet */
160: req.hlen = 6; /* ethernet */
161: memmove(req.chaddr, eaddr, sizeof(req.chaddr));
162: if(useipaddr != 0)
163: memmove(req.ciaddr, useipaddr, sizeof(req.ciaddr));
164: memset(req.file, 0, sizeof(req.file));
165: strcpy(req.vend, "p9 ");
166:
167: /* broadcast bootp's till we get a reply, or 3 times around the loop */
168: notify(catchint);
169: tries = 0;
170: field[0] = 0;
171: for(rp = 0; rp == 0 && tries++ < 10;){
172: alarm(1000);
173: if(write(ufd[1], &req, sizeof(req)) < 0)
174: fatal("sending bootp");
175: for(;;){
176: rp = 0;
177: memset(buf, 0, sizeof(buf));
178: n = read(ufd[1], buf, sizeof(buf));
179: if(n <= 0)
180: break;
181: rp = (Bootp*)buf;
182: memset(field, 0, sizeof field);
183: if(memcmp(req.chaddr, rp->chaddr, 6) == 0
184: && rp->htype == 1
185: && rp->hlen == 6
186: && mygetfields(rp->vend+4, field, 4) == 4){
187: if(strncmp(rp->vend, "p9 ", 4) == 0){
188: memmove(ipaddr, rp->yiaddr, sizeof(ipaddr));
189: parseip(ipmask, field[0]);
190: if(*sys == 0){
191: strcpy(sys, field[1]);
192: parseip(fsip, field[1]);
193: }
194: parseip(auip, field[2]);
195: parseip(gwip, field[3]);
196: maskip(ipaddr, ipmask, ipnet);
197: if(bootfile[0] == 0){
198: strncpy(bootfile, rp->file,
199: 3*NAMELEN);
200: bootfile[3*NAMELEN-1] = 0;
201: }
202: break;
203: }
204: }
205: }
206: alarm(0);
207: }
208: close(ufd[1]);
209:
210: if(field[0])
211: /*print("I am %s sub %s fs %s au %s gw %s\n",
212: fmtaddr(ipaddr), field[0], sys, field[2], field[3])/**/;
213: else {
214: errstr(buf); /* Clear timeout error from alarm */
215:
216: if(readfile("#e/ipaddr", buf2, sizeof(buf2)) < 0)
217: strcpy(buf2, "");
218: outin(0, "My IP address", buf2, sizeof(buf2));
219: parseip(ipaddr, buf2);
220:
221: if(readfile("#e/ipmask", buf2, sizeof(buf2)) < 0)
222: strcpy(buf2, "");
223: outin(0, "My IP mask", buf2, sizeof(buf2));
224: parseip(ipmask, buf2);
225: maskip(ipaddr, ipmask, ipnet);
226:
227: if(readfile("#e/ipgw", buf2, sizeof(buf2)) < 0)
228: strcpy(buf2, "");
229: outin(0, "My IP gateway", buf2, sizeof(buf2));
230: parseip(gwip, buf2);
231:
232: if(*sys)
233: strcpy(buf2, sys);
234: else {
235: if(readfile("#e/fs", buf2, sizeof(buf2)) < 0)
236: strcpy(buf2, "");
237: outin(0, "filesystem IP address", buf2, sizeof(buf2));
238: }
239: parseip(fsip, buf2);
240:
241: if(readfile("#e/auth", buf2, sizeof(buf2)) < 0)
242: strcpy(buf2, "0.0.0.0");
243: outin(0, "authentication server IP address", buf2, sizeof(buf2));
244: parseip(auip, buf2);
245: }
246:
247: if(auip[0] == 0 && auip[1] == 0)
248: mp->auth = 0;
249:
250: /* set our ip address and mask */
251: n = sprint(buf2, "setip %s ", fmtaddr(ipaddr));
252: sprint(buf2+n, "%s", fmtaddr(ipmask));
253: sendmsg(muxctlfd, buf2);
254:
255: /* specify a routing gateway */
256: if(*gwip){
257: sprint(buf2, "add 0.0.0.0 0.0.0.0 %s", fmtaddr(gwip));
258: fd = open("#P/iproute", OWRITE);
259: if(fd < 0)
260: fatal("opening iproute");
261: if(sendmsg(fd, buf2) < 0)
262: print("%s failed\n", buf2);
263: close(fd);
264: }
265: }
266:
267: static int
268: ipdial(int *ifd, char *dev, uchar *ip, int service)
269: {
270: uchar tmp[4];
271: char buf[64];
272: int arpnotefd;
273:
274: /* start a process to answer arps */
275: arpnotefd = arplisten();
276:
277: /* arp for first hop */
278: maskip(ip, ipmask, tmp);
279: if(equivip(tmp, ipnet))
280: arp(ip);
281: else
282: arp(gwip);
283:
284: /* make the call */
285: sprint(buf, "%s!%d", fmtaddr(ip), service);
286: if(plumb(dev, buf, ifd, 0) < 0){
287: fprint(2, "error dialing %s\n", buf);
288: ifd[1] = -1;
289: }
290:
291: fprint(arpnotefd, "kill");
292:
293: return ifd[1];
294: }
295:
296: /* send an arprequest, wait for a reply */
297: static void
298: arp(uchar *addr)
299: {
300: int afd[2];
301: int arpdev;
302: int n;
303: Arpentry entry;
304: Arppkt req, *rp;
305: char buf[1600];
306:
307: if(plumb("#l/ether", "0x806", afd, 0) < 0)
308: fatal("opening ip ether");
309: close(afd[0]);
310: arpdev = open("#a/arp/data", OWRITE);
311: if(arpdev < 0)
312: fatal("opening arp/data");
313:
314: /* arp for the file server or the gateway */
315: memset(&req, 0, sizeof(req));
316: memmove(req.tpa, addr, sizeof(req.tpa));
317: memset(req.d, 0xff, sizeof(req.d));
318: memmove(req.spa, ipaddr, sizeof(ipaddr));
319: memmove(req.sha, eaddr, sizeof(eaddr));
320: hnputs(req.type, ET_ARP);
321: hnputs(req.hrd, 1);
322: hnputs(req.pro, 0x800);
323: req.hln = sizeof(req.sha);
324: req.pln = sizeof(req.spa);
325: hnputs(req.op, ARP_REQUEST);
326: for(rp = 0; rp == 0;){
327: if(write(afd[1], &req, sizeof(req)) < 0)
328: fatal("sending arpreq");
329: alarm(1000);
330: for(;;){
331: rp = 0;
332: memset(buf, 0, sizeof(buf));
333: n = read(afd[1], buf, sizeof(buf));
334: if(n <= 0)
335: break;
336: rp = (Arppkt*)buf;
337: if(nhgets(rp->op) != ARP_REPLY)
338: continue;
339: memcpy(entry.etaddr, rp->sha, sizeof(entry.etaddr));
340: memcpy(entry.ipaddr, rp->spa, sizeof(entry.ipaddr));
341: if(write(arpdev, &entry, sizeof(entry)) < 0)
342: warning("write arp entry");
343: print("arp: rcvd for %s\n", fmtaddr(rp->spa));/**/
344: if(equivip(rp->spa, addr))
345: break;
346: }
347: alarm(0);
348: }
349:
350: close(arpdev);
351: close(afd[1]);
352: }
353:
354: /*
355: * fork a process to answer arp requests for us. since
356: * we will kill it after changing user id, we need to open the
357: * note process here. arplisten returns the fd of the open note
358: * process.
359: */
360: static int
361: arplisten(void)
362: {
363: int afd[2];
364: int n;
365: int pid;
366: Arppkt reply, *rp;
367: char buf[1600];
368:
369: alarm(0);
370: notify(catchint);
371:
372: switch(pid = fork()){
373: case -1:
374: fatal("forking arplisten");
375: case 0:
376: break;
377: default:
378: sprint(buf, "#p/%d/note", pid);
379: return open(buf, OWRITE);
380: }
381:
382: if(plumb("#l/ether", "0x806", afd, 0) < 0)
383: fatal("opening ip ether");
384:
385: for(;;){
386: memset(buf, 0, sizeof(buf));
387: n = read(afd[1], buf, sizeof(buf));
388: if(n < 0)
389: break;
390: if(n == 0)
391: continue;
392: rp = (Arppkt*)buf;
393: if(nhgets(rp->op) != ARP_REQUEST)
394: continue;
395: if(memcmp(rp->tpa, ipaddr, sizeof(ipaddr)) != 0)
396: continue;
397:
398: memset(&reply, 0, sizeof(reply));
399: hnputs(reply.type, ET_ARP);
400: hnputs(reply.hrd, 1);
401: hnputs(reply.pro, 0x800);
402: reply.hln = sizeof(reply.sha);
403: reply.pln = sizeof(reply.spa);
404: hnputs(reply.op, ARP_REPLY);
405: memmove(reply.tha, rp->sha, sizeof(reply.tha));
406: memmove(reply.tpa, rp->spa, sizeof(reply.tpa));
407: memmove(reply.sha, eaddr, sizeof(eaddr));
408: memmove(reply.spa, ipaddr, sizeof(ipaddr));
409: memmove(reply.d, rp->s, sizeof(rp->s));
410: print("arplisten: reply to %s\n", fmtaddr(reply.tpa));/**/
411: if(write(afd[1], &reply, ARPSIZE) < 0)
412: warning("write arp reply");
413: }
414: exits(0);
415: return 0; /* not reached */
416: }
417:
418: static ushort
419: nhgets(uchar *val)
420: {
421: return (val[0]<<8) | val[1];
422: }
423:
424: static void
425: hnputs(uchar *ptr, ushort val)
426: {
427: ptr[0] = val>>8;
428: ptr[1] = val;
429: }
430:
431: int
432: myipaddr(uchar *to, char *dev)
433: {
434: char buf[256];
435: int n, fd, clone;
436: char *ptr;
437:
438: /* Opening clone ensures the 0 connection exists */
439: sprint(buf, "%s/clone", dev);
440: clone = open(buf, OREAD);
441: if(clone < 0)
442: return -1;
443:
444: sprint(buf, "%s/0/local", dev);
445: fd = open(buf, OREAD);
446: close(clone);
447: if(fd < 0)
448: return -1;
449: n = read(fd, buf, sizeof(buf)-1);
450: close(fd);
451: if(n <= 0)
452: return -1;
453: buf[n] = 0;
454:
455: ptr = strchr(buf, ' ');
456: if(ptr)
457: *ptr = 0;
458:
459: parseip(to, buf);
460: return 0;
461: }
462:
463: #define CLASS(p) ((*(uchar*)(p))>>6)
464: static void
465: parseip(uchar *to, char *from)
466: {
467: int i;
468: char *p;
469:
470: p = from;
471: memset(to, 0, 4);
472: for(i = 0; i < 4 && *p; i++){
473: to[i] = strtoul(p, &p, 0);
474: if(*p == '.')
475: p++;
476: }
477:
478: switch(CLASS(to)){
479: case 0: /* class A - 1 byte net */
480: case 1:
481: if(i == 3){
482: to[3] = to[2];
483: to[2] = to[1];
484: to[1] = 0;
485: } else if (i == 2){
486: to[3] = to[1];
487: to[1] = 0;
488: }
489: break;
490: case 2: /* class B - 2 byte net */
491: if(i == 3){
492: to[3] = to[2];
493: to[2] = 0;
494: }
495: break;
496: }
497: }
498:
499: static int
500: myetheraddr(uchar *to, char *dev)
501: {
502: char buf[256];
503: int n, fd;
504: char *ptr;
505:
506: sprint(buf, "%s/1/stats", dev);
507: fd = open(buf, OREAD);
508: if(fd < 0)
509: return -1;
510: n = read(fd, buf, sizeof(buf)-1);
511: close(fd);
512: if(n <= 0)
513: return -1;
514: buf[n] = 0;
515:
516: ptr = strstr(buf, "addr: ");
517: if(!ptr)
518: return -1;
519: ptr += 6;
520:
521: parseether(to, ptr);
522: return 0;
523: }
524:
525: static int
526: parseether(uchar *to, char *from)
527: {
528: char nip[4];
529: char *p;
530: int i;
531:
532: p = from;
533: for(i = 0; i < 6; i++){
534: if(*p == 0)
535: return -1;
536: nip[0] = *p++;
537: if(*p == 0)
538: return -1;
539: nip[1] = *p++;
540: nip[2] = 0;
541: to[i] = strtoul(nip, 0, 16);
542: if(*p == ':')
543: p++;
544: }
545: return 0;
546: }
547:
548: static int
549: mygetfields(char *lp, char **fields, int n)
550: {
551: int i;
552:
553: for(i=0; lp && *lp && i<n; i++){
554: while(*lp == ' ' || *lp == '\t')
555: *lp++=0;
556: if(*lp == 0)
557: break;
558: fields[i]=lp;
559: while(*lp && *lp != ' ' && *lp != '\t')
560: lp++;
561: }
562: return i;
563: }
564:
565: static char*
566: fmtaddr(uchar *a)
567: {
568: static char buf[32];
569:
570: sprint(buf, "%d.%d.%d.%d", a[0], a[1], a[2], a[3]);
571: return buf;
572: }
573:
574: static void
575: catchint(void *a, char *note)
576: {
577: USED(a);
578: if(strstr(note, "alarm"))
579: noted(NCONT);
580: else
581: noted(NDFLT);
582: }
583:
584: static void
585: maskip(uchar *a, uchar *m, uchar *n)
586: {
587: int i;
588:
589: for(i = 0; i < 4; i++)
590: n[i] = a[i] & m[i];
591: }
592:
593: static int
594: equivip(uchar *a, uchar *b)
595: {
596: int i;
597:
598: for(i = 0; i < 4; i++)
599: if(a[i] != b[i])
600: return 0;
601: return 1;
602: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.