|
|
1.1 ! root 1: /* ! 2: * A R P L D ! 3: * ! 4: * Generic (ethernet) address-resolution line discipline. ! 5: * Implements an LRU cache of protocol address to ethernet address mappings. ! 6: * ! 7: * ! 8: * Written by Kurt Gollhardt (Nirvonics, Inc.) ! 9: * Last update Wed Feb 12 20:43:28 1986 ! 10: * ! 11: */ ! 12: ! 13: #include "../h/param.h" ! 14: #include "../h/systm.h" ! 15: #include "../h/stream.h" ! 16: #include "../h/conf.h" ! 17: #include "../h/ioctl.h" ! 18: #include "../h/ttyld.h" ! 19: #include "../h/ethernet.h" ! 20: #include "../h/order.h" ! 21: #include "../net/arpld.h" ! 22: ! 23: #include "arp.h" ! 24: #if NARP > 0 ! 25: ! 26: #define NARPROTO (NARP * NPROTO) ! 27: ! 28: struct arp_dev Arp_dev[NARP]; ! 29: struct proto Arp_proto[NARPROTO]; ! 30: ! 31: static int hd_size = MAX_HARDSIZE, ! 32: pr_size, pr_hfirst; ! 33: ! 34: static u_char hd_sender[MAX_HARDSIZE], ! 35: hd_target[MAX_HARDSIZE], ! 36: pr_sender[MAX_PRSIZE], ! 37: pr_target[MAX_PRSIZE]; ! 38: ! 39: static unsigned arp_clock; ! 40: ! 41: static int install(), request(); ! 42: static int pack(), unpack(); ! 43: static int bcmp(); ! 44: ! 45: struct block *packet_pullup(); ! 46: ! 47: #define DEBUG ! 48: ! 49: #ifdef DEBUG ! 50: int Arpdebug = 0; ! 51: # define debug(x) if (Arpdebug) x ! 52: #else ! 53: # define debug(x) ! 54: #endif ! 55: ! 56: ! 57: #define order(x,size,hfirst) ((hfirst) ? order_hfirst(x,size) \ ! 58: : order_lfirst(x,size)) ! 59: ! 60: ! 61: arp_enable(dev, type, psize, phfirst, paddr) ! 62: dev_t dev; ! 63: u_char *paddr; ! 64: { ! 65: register struct proto *pr, *pr2; ! 66: register struct arp_dev *arpd; ! 67: register struct arp *arp; ! 68: register int i; ! 69: int ps = spl6(); ! 70: ! 71: dev = physical(dev); ! 72: ! 73: /* Find the per-device structure for the desired device */ ! 74: for (arpd = Arp_dev, i = 0; i < NARP; ++i, ++arpd) { ! 75: if (arpd->pdev == dev) ! 76: break; ! 77: } ! 78: if (i == NARP) { ! 79: printf("ARP: no arp for dev (%d,%d)\n", major(dev), minor(dev)); ! 80: goto bad; ! 81: } ! 82: if (bcmp(arpd->hdaddr, hzero, MAX_HARDSIZE)) { ! 83: printf("ARP: hardware address not set for dev (%d,%d)\n", ! 84: major(dev), minor(dev)); ! 85: goto bad; ! 86: } ! 87: ! 88: /* Find a free protocol structure for this device */ ! 89: pr = 0; ! 90: for (pr2 = &Arp_proto[NPROTO * i], i = 0; i < NPROTO; ++i, ++pr2) { ! 91: if (pr2->psize == 0) ! 92: pr = pr2; ! 93: else if (pr2->type == type) { ! 94: printf("ARP: duplicate enable - dev (%d,%d) type 0x%x\n", ! 95: major(dev), minor(dev), type); ! 96: goto bad; ! 97: } ! 98: } ! 99: if (pr == 0) { ! 100: printf("ARP: too many protocols on dev (%d,%d)\n", ! 101: major(dev), minor(dev)); ! 102: goto bad; ! 103: } ! 104: ! 105: if (psize < 1 || psize > MAX_PRSIZE) { ! 106: printf("ARP: protocol address size (%d) out of range\n", psize); ! 107: goto bad; ! 108: } ! 109: pr->ptr = arpd; ! 110: pr->type = type; ! 111: pr->psize = psize; ! 112: pr->phfirst = phfirst; ! 113: ! 114: /* Clear out the arp pairs */ ! 115: for (arp = pr->pair; arp < &pr->pair[NPAIR]; ++arp) ! 116: bcopy(pzero, arp->paddr, psize); ! 117: ! 118: /* Add our address as arp pair 0 */ ! 119: bcopy(paddr, pr->pair[0].paddr, pr->psize); ! 120: bcopy(arpd->hdaddr, pr->pair[0].hdaddr, hd_size); ! 121: ! 122: splx(ps); ! 123: ! 124: debug(printf("ARP: enabled protocol 0x%x on dev (%d,%d), channel %d\n", ! 125: type, major(dev), minor(dev), pr - Arp_proto)); ! 126: debug(printf(" my addr is")); ! 127: debug(print_addr(paddr, pr->psize)); ! 128: debug(printf(" at ethernet")); ! 129: debug(print_addr(arpd->hdaddr, hd_size)); ! 130: debug(printf(" order is %s-byte first\n", phfirst? "high" : "low")); ! 131: ! 132: return pr - Arp_proto; ! 133: ! 134: bad: ! 135: splx(ps); ! 136: return -1; ! 137: } ! 138: ! 139: arp_getaddr(i, paddr, hdaddr) ! 140: u_short i; ! 141: u_char *paddr, *hdaddr; ! 142: { ! 143: register struct proto *pr = &Arp_proto[i]; ! 144: register struct arp *arp; ! 145: int ps; ! 146: ! 147: if (i >= NARPROTO || pr->psize == 0) { ! 148: printf("ARP: getaddr on un-enabled channel %d\n", i); ! 149: return -1; ! 150: } ! 151: ! 152: debug(printf("ARP: getaddr for")); ! 153: debug(print_addr(paddr, pr->psize)); ! 154: debug(printf(" on channel %d\n", i)); ! 155: ! 156: ps = spl6(); ! 157: ! 158: for (arp = pr->pair; arp < &pr->pair[NPAIR]; ++arp) { ! 159: if (bcmp(arp->paddr, paddr, pr->psize)) { ! 160: bcopy(arp->hdaddr, hdaddr, hd_size); ! 161: arp->time = ++arp_clock; ! 162: splx(ps); ! 163: return 0; ! 164: } ! 165: } ! 166: ! 167: request(pr, paddr); ! 168: splx(ps); ! 169: return -1; ! 170: } ! 171: ! 172: struct block * ! 173: arp_resolve(i, bp, paddr) ! 174: struct block *bp; ! 175: u_char *paddr; ! 176: { ! 177: register struct block *bp1; ! 178: register struct etherpup *ep; ! 179: ! 180: if ((bp1 = allocb(sizeof(struct etherpup))) == 0) { ! 181: printf("ARP: can't alloc block for resolve\n"); ! 182: bad: ! 183: while (bp != 0) { ! 184: bp1 = bp->next; ! 185: freeb(bp); ! 186: bp = bp1; ! 187: } ! 188: return 0; ! 189: } ! 190: ! 191: ep = (struct etherpup *)bp1->wptr; ! 192: bp1->wptr += sizeof(struct etherpup); ! 193: if (arp_getaddr(i, paddr, ep->dhost) < 0) { ! 194: freeb(bp1); ! 195: goto bad; ! 196: } ! 197: ! 198: ep->type = hfirst_short(Arp_proto[i].type); ! 199: bp1->next = bp; ! 200: return bp1; ! 201: } ! 202: ! 203: arp_disable(i) ! 204: u_short i; ! 205: { ! 206: register struct proto *pr = &Arp_proto[i]; ! 207: register struct arp *arp; ! 208: ! 209: if (i >= NARPROTO || pr->psize == 0) { ! 210: printf("ARP: disable on un-enabled channel %d\n", i); ! 211: return; ! 212: } ! 213: ! 214: debug(printf("ARP: disabled channel %d\n", i)); ! 215: ! 216: pr->psize = 0; ! 217: } ! 218: ! 219: arp_broadcast(hdaddr) ! 220: u_char *hdaddr; ! 221: { ! 222: bcopy(broadaddr, hdaddr, hd_size); ! 223: } ! 224: ! 225: ! 226: static install(pr, paddr, hdaddr) ! 227: register struct proto *pr; ! 228: u_char *paddr, *hdaddr; ! 229: { ! 230: register struct arp *arp, *empty; ! 231: ! 232: debug(printf("ARP: install()\n")); ! 233: ! 234: /* Look for an arp pair for this address, or a free one, or LRU */ ! 235: for (empty = arp = pr->pair; arp < &pr->pair[NPAIR]; ++arp) { ! 236: if (bcmp(arp->paddr, paddr, pr->psize)) ! 237: break; ! 238: if (bcmp(arp->paddr, pzero, pr->psize)) ! 239: (empty = arp)->time = arp_clock + 1; ! 240: else if (arp_clock - arp->time > arp_clock - empty->time) ! 241: empty = arp; ! 242: } ! 243: ! 244: if (arp == &pr->pair[NPAIR]) ! 245: (arp = empty)->time = ++arp_clock; ! 246: ! 247: bcopy(paddr, arp->paddr, pr->psize); ! 248: bcopy(hdaddr, arp->hdaddr, hd_size); ! 249: ! 250: debug(printf("ARP: installed paddr")); ! 251: debug(print_addr(paddr, pr->psize)); ! 252: debug(printf(" at ethernet")); ! 253: debug(print_addr(hdaddr, hd_size)); ! 254: debug(printf(" on channel %d\n", pr - Arp_proto)); ! 255: ! 256: return 0; ! 257: } ! 258: ! 259: #define OUT_SIZE (sizeof(struct etherpup) + sizeof(struct ether_arp) \ ! 260: - 2*(MAX_HARDSIZE + MAX_PRSIZE) + 2*(hd_size + pr_size)) ! 261: ! 262: static request(pr, paddr) ! 263: register struct proto *pr; ! 264: u_char *paddr; ! 265: { ! 266: register struct queue *q; ! 267: register struct block *bp; ! 268: struct ether_arp *arpkt; ! 269: struct etherpup *ep; ! 270: long my_paddr, his_paddr; ! 271: ! 272: debug(printf("ARP: request()\n")); ! 273: ! 274: pr_size = pr->psize; ! 275: pr_hfirst = pr->phfirst; ! 276: ! 277: q = WR(pr->ptr->rdq); ! 278: if ((bp = allocb(OUT_SIZE)) == 0) { ! 279: printf("ARP: can't alloc block for request\n"); ! 280: return; ! 281: } ! 282: if (bp->lim - bp->wptr < OUT_SIZE) { ! 283: freeb(bp); ! 284: printf("ARP: block too small for request\n"); ! 285: return; ! 286: } ! 287: ! 288: ep = (struct etherpup *)bp->wptr; ! 289: arpkt = (struct ether_arp *)(bp->wptr + sizeof(struct etherpup)); ! 290: bp->wptr += OUT_SIZE; ! 291: ! 292: bcopy(broadaddr, ep->dhost, hd_size); ! 293: ep->type = hfirst_short(ETHERPUP_ARPTYPE); ! 294: ! 295: arpkt->arp_hrd = hfirst_short(ARPHRD_ETHER); ! 296: arpkt->arp_pro = hfirst_short(pr->type); ! 297: arpkt->arp_hln = hd_size; ! 298: arpkt->arp_pln = pr_size; ! 299: arpkt->arp_op = hfirst_short(ARPOP_REQUEST); ! 300: ! 301: bcopy(pr->pair[0].hdaddr, hd_sender, hd_size); ! 302: bcopy(pr->pair[0].paddr, pr_sender, pr_size); ! 303: bcopy(paddr, pr_target, pr_size); ! 304: bcopy(hzero, hd_target, hd_size); ! 305: pack(arpkt); ! 306: ! 307: debug(printf("ARP: sending a request for address")); ! 308: debug(print_addr(paddr, pr->psize)); ! 309: debug(printf(" on channel %d\n", pr - Arp_proto)); ! 310: ! 311: if (q->next->flag & QFULL) { ! 312: freeb(bp); ! 313: debug(printf("ARP: QFULL in request()\n")); ! 314: } else { ! 315: (*q->next->qinfo->putp)(q->next, bp); ! 316: putctl(q->next, M_DELIM); ! 317: } ! 318: } ! 319: ! 320: ! 321: int arp_open(), arp_close(), arp_iput(), arp_srv(), arp_bypass(), arp_rcvpkt(); ! 322: static struct qinit arp_rinit = { ! 323: arp_iput, arp_srv, arp_open, arp_close, 750, 250 ! 324: }; ! 325: static struct qinit arp_winit = { ! 326: arp_bypass, NULL, arp_open, arp_close, 0, 0 ! 327: }; ! 328: struct streamtab arpinfo = { &arp_rinit, &arp_winit }; ! 329: ! 330: ! 331: arp_open(q, dev) ! 332: register struct queue *q; ! 333: dev_t dev; ! 334: { ! 335: register int i; ! 336: register struct arp_dev *arpd, *narp; ! 337: ! 338: if (q->ptr) /* If this stream is already open, don't do anything */ ! 339: return 1; ! 340: ! 341: dev = physical(dev); ! 342: ! 343: /* Look for a free per-device structure */ ! 344: narp = 0; ! 345: for (arpd = Arp_dev; arpd < &Arp_dev[NARP]; ++arpd) { ! 346: if (arpd->pdev == dev) { ! 347: printf("ARP: multiple arps on device (%d,%d)\n", ! 348: major(dev), minor(dev)); ! 349: return 0; ! 350: } ! 351: if (arpd->pdev == 0) ! 352: narp = arpd; ! 353: } ! 354: if (narp == 0) ! 355: return 0; /* Open fails: no more line disciplines */ ! 356: ! 357: narp->pdev = dev; ! 358: narp->delim_count = 0; ! 359: bcopy(hzero, narp->hdaddr, MAX_HARDSIZE); ! 360: narp->rdq = q; ! 361: ! 362: q->flag |= QDELIM|QNOENB; ! 363: q->ptr = (caddr_t)narp; ! 364: return 1; ! 365: } ! 366: ! 367: arp_close(q) ! 368: register struct queue *q; ! 369: { ! 370: register struct arp_dev *arpd; ! 371: int n, i; ! 372: ! 373: arpd = (struct arp_dev *)q->ptr; ! 374: arpd->pdev = 0; ! 375: q->ptr = 0; ! 376: n = (arpd - Arp_dev) * NPROTO; ! 377: for (i = n; i < n + NPROTO; ++i) ! 378: Arp_proto[i].psize = 0; ! 379: } ! 380: ! 381: arp_bypass(q, bp) ! 382: register struct queue *q; ! 383: register struct block *bp; ! 384: { ! 385: (*q->next->qinfo->putp)(q->next, bp); ! 386: } ! 387: ! 388: arp_misc(q, bp) ! 389: struct queue *q; ! 390: struct block *bp; ! 391: { ! 392: register union stmsg *sp; ! 393: ! 394: if (bp->type == M_IOCACK) { ! 395: sp = (union stmsg *)bp->rptr; ! 396: if (sp->iocx.com == ENIOADDR) ! 397: bcopy(sp->iocx.xxx, ((struct arp_dev *)q->ptr)->hdaddr, ! 398: MAX_HARDSIZE); ! 399: } ! 400: /* Anything else, just pass on to the next guy */ ! 401: (*q->next->qinfo->putp)(q->next, bp); ! 402: } ! 403: ! 404: arp_iput(q, bp) ! 405: struct queue *q; ! 406: struct block *bp; ! 407: { ! 408: packet_putp(q, bp, &((struct arp_dev *)q->ptr)->delim_count, 0, arp_misc); ! 409: } ! 410: ! 411: arp_false(q) ! 412: struct queue *q; ! 413: { ! 414: return 0; ! 415: } ! 416: ! 417: arp_srv(q) ! 418: struct queue *q; ! 419: { ! 420: packet_srvp(q, &((struct arp_dev *)q->ptr)->delim_count, ! 421: arp_false, arp_false, arp_rcvpkt, 0); ! 422: } ! 423: ! 424: arp_rcvpkt(q, bp, partial) ! 425: register struct queue *q; ! 426: register struct block *bp; ! 427: { ! 428: register struct ether_arp *arpkt; ! 429: register struct proto *pr; ! 430: register struct etherpup *ep; ! 431: register int i, type; ! 432: short op; ! 433: int ps; ! 434: ! 435: if (partial || bp == NULL) { ! 436: free_blocks(bp); ! 437: return; ! 438: } ! 439: i = sizeof(struct etherpup) + sizeof(struct ether_arp); ! 440: if ((bp = packet_pullup(bp, i)) == 0) { ! 441: printf("ARP: bad packet\n"); ! 442: return; ! 443: } ! 444: if (bp->next) ! 445: free_blocks(bp); ! 446: ! 447: pr = &Arp_proto[((struct arp_dev *)q->ptr - Arp_dev) * NPROTO]; ! 448: arpkt = (struct ether_arp *)(bp->rptr + sizeof(struct etherpup)); ! 449: type = hfirst_short(arpkt->arp_pro); ! 450: op = hfirst_short(arpkt->arp_op); ! 451: ! 452: debug(printf("ARP: rcvd arp %s for protocol 0x%x\n", ! 453: (op == ARPOP_REQUEST ? "request" : ! 454: (op == ARPOP_REPLY ? "reply" : "(BAD)")), type)); ! 455: ! 456: ps = spl6(); ! 457: ! 458: for (i = 0; i < NPROTO; ++i, ++pr) { ! 459: if (pr->psize != 0 && pr->type == type) ! 460: break; ! 461: } ! 462: if (i == NPROTO) ! 463: goto out; /* Not one of the types we recognize */ ! 464: ! 465: pr_size = pr->psize; ! 466: pr_hfirst = pr->phfirst; ! 467: unpack(arpkt); ! 468: ! 469: if (!bcmp(pr_target, pr->pair[0].paddr, pr_size)) { ! 470: out: ! 471: splx(ps); ! 472: freeb(bp); ! 473: return; ! 474: } ! 475: if (bcmp(pr_sender, pr->pair[0].paddr, pr_size)) { ! 476: printf("ARP: someone is pretending to be me!!!\n"); ! 477: goto out; ! 478: } ! 479: if (op == ARPOP_REPLY && !bcmp(hd_target, pr->pair[0].hdaddr, hd_size)) ! 480: goto out; ! 481: ! 482: install(pr, pr_sender, hd_sender); ! 483: if (op != ARPOP_REQUEST) ! 484: goto out; ! 485: ! 486: arpkt->arp_hrd = hfirst_short(ARPHRD_ETHER); ! 487: arpkt->arp_op = hfirst_short(ARPOP_REPLY); ! 488: ! 489: debug(printf("ARP: sending reply to")); ! 490: debug(print_addr(pr_sender, pr_size)); ! 491: debug(printf(" at ethernet")); ! 492: debug(print_addr(hd_sender, hd_size)); ! 493: debug(printf(" on channel %d\n", pr - Arp_proto)); ! 494: ! 495: bcopy(pr_sender, pr_target, pr_size); ! 496: bcopy(hd_sender, hd_target, hd_size); ! 497: bcopy(pr->pair[0].paddr, pr_sender, pr_size); ! 498: bcopy(pr->pair[0].hdaddr, hd_sender, hd_size); ! 499: pack(arpkt); ! 500: ! 501: ep = (struct etherpup *)(bp->rptr += sizeof(struct etherpup) ! 502: - sizeof(struct etherpup)); ! 503: bcopy(hd_target, ep->dhost, hd_size); ! 504: ep->type = hfirst_short(ETHERPUP_ARPTYPE); ! 505: ! 506: splx(ps); ! 507: ! 508: q = WR(q); ! 509: if (q->next->flag & QFULL) { ! 510: freeb(bp); ! 511: debug(printf("ARP: QFULL on reply\n")); ! 512: } else { ! 513: (*q->next->qinfo->putp) (q->next, bp); ! 514: putctl(q->next, M_DELIM); ! 515: } ! 516: } ! 517: ! 518: ! 519: static pack(arpkt) ! 520: struct ether_arp *arpkt; ! 521: { ! 522: register u_char *p = arpkt->arp_addr; ! 523: long paddr; ! 524: ! 525: debug(printf("ARP: packing arp from")); ! 526: debug(print_addr(pr_sender, pr_size)); ! 527: debug(printf(" at")); ! 528: debug(print_addr(hd_sender, hd_size)); ! 529: debug(printf(", target is")); ! 530: debug(print_addr(pr_target, pr_size)); ! 531: debug(printf(" (at")); ! 532: debug(print_addr(hd_target, hd_size)); ! 533: debug(printf(")\n")); ! 534: ! 535: bcopy(hd_sender, p, hd_size); ! 536: paddr = order(*(long *)pr_sender, pr_size, pr_hfirst); ! 537: bcopy(&paddr, p += hd_size, pr_size); ! 538: bcopy(hd_target, p += pr_size, hd_size); ! 539: paddr = order(*(long *)pr_target, pr_size, pr_hfirst); ! 540: bcopy(&paddr, p += hd_size, pr_size); ! 541: } ! 542: ! 543: static unpack(arpkt) ! 544: struct ether_arp *arpkt; ! 545: { ! 546: register u_char *p = arpkt->arp_addr; ! 547: long paddr; ! 548: ! 549: bcopy(p, hd_sender, hd_size); ! 550: paddr = order(*(long *)(p += hd_size), pr_size, pr_hfirst); ! 551: bcopy(&paddr, pr_sender, pr_size); ! 552: bcopy(p += pr_size, hd_target, hd_size); ! 553: paddr = order(*(long *)(p += hd_size), pr_size, pr_hfirst); ! 554: bcopy(&paddr, pr_target, pr_size); ! 555: ! 556: debug(printf("ARP: unpacked arp from")); ! 557: debug(print_addr(pr_sender, pr_size)); ! 558: debug(printf(" at")); ! 559: debug(print_addr(hd_sender, hd_size)); ! 560: debug(printf(", target is")); ! 561: debug(print_addr(pr_target, pr_size)); ! 562: debug(printf(" (at")); ! 563: debug(print_addr(hd_target, hd_size)); ! 564: debug(printf(")\n")); ! 565: } ! 566: ! 567: ! 568: static bcmp(a, b, n) ! 569: register u_char *a, *b; ! 570: register int n; ! 571: { ! 572: while (n-- > 0) ! 573: if(*a++ != *b++) ! 574: return 0; ! 575: return 1; ! 576: } ! 577: ! 578: ! 579: #ifdef DEBUG ! 580: ! 581: print_addr(addr, size) ! 582: register u_char *addr; ! 583: register u_short size; ! 584: { ! 585: while (size-- > 0) ! 586: printf(" %x", *addr++); ! 587: } ! 588: ! 589: #endif DEBUG ! 590: ! 591: #endif NARP
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.