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