|
|
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.