|
|
1.1 ! root 1: /* ! 2: * C H R O U T E L D ! 3: * ! 4: * Chaosnet packet routing line discipline. ! 5: * ! 6: * ! 7: * (c) Copyright 1985 Nirvonics, Inc. ! 8: * ! 9: * Written by Kurt Gollhardt ! 10: * Last update Tue Mar 12 04:21:35 1985 ! 11: * ! 12: * This software is the property of Nirvonics, Inc. ! 13: * All rights reserved. ! 14: * ! 15: */ ! 16: ! 17: #include "chroute.h" ! 18: #if NCHROUTE > 0 ! 19: #include "../h/param.h" ! 20: #include "../h/systm.h" ! 21: #include "../h/stream.h" ! 22: #include "../h/ioctl.h" ! 23: #include "../h/ttyld.h" ! 24: #include "../h/conf.h" ! 25: #include "../h/order.h" ! 26: #include "../h/ethernet.h" ! 27: #include "../chaosld/types.h" ! 28: #include "../chaosld/constants.h" ! 29: #include "../chaosld/chrouteld.h" ! 30: ! 31: ! 32: struct chif Chif[NCHROUTE]; ! 33: struct chroute Chroute[CHNSUBNET]; ! 34: ! 35: static struct chif *primary; ! 36: ! 37: int NChropen; ! 38: int NChroute = NCHROUTE; ! 39: int NChsubnet = CHNSUBNET; ! 40: ! 41: int Chrtimer; /* Routing timer running */ ! 42: ! 43: int chroute_open(), chroute_close(), chroute_put(), chroute_srv(); ! 44: static struct qinit chroute_init = { ! 45: chroute_put, chroute_srv, chroute_open, chroute_close, 512, 64 ! 46: }; ! 47: struct streamtab chrouteinfo = { &chroute_init, &chroute_init }; ! 48: ! 49: #define DEBUG ! 50: ! 51: #ifdef DEBUG ! 52: int Chrdebug = 0; ! 53: # define debug(x) if (Chrdebug) x ! 54: #else ! 55: # define debug(x) ! 56: #endif ! 57: ! 58: static struct statxcvr zstat; ! 59: ! 60: ! 61: chroute_open(q, dev) ! 62: register struct queue *q; ! 63: dev_t dev; ! 64: { ! 65: register int i; ! 66: register struct chif *ifp; ! 67: ! 68: if (q->ptr) /* If this stream is already open, don't do anything */ ! 69: return 1; ! 70: ! 71: /* Look for a free interface structure */ ! 72: ! 73: if (NChropen++ == NCHROUTE) ! 74: return 0; /* If there are none left, the open fails */ ! 75: for (i = 0, ifp = Chif; ifp->rdq != 0; ++ifp) ! 76: ; ! 77: ! 78: ifp->rdq = q; ! 79: ifp->my_addr.ch_addr = 0; ! 80: ifp->arp = -1; ! 81: ifp->if_dev = dev; ! 82: ifp->if_cost = HIGH_COST / 4; /* We expect this to be set by an ioctl, ! 83: but just in case ... */ ! 84: ifp->if_stat = zstat; ! 85: ! 86: q->flag |= QDELIM|QNOENB; ! 87: WR(q)->flag |= QDELIM|QNOENB; ! 88: q->ptr = WR(q)->ptr = (caddr_t)ifp; ! 89: ! 90: if (!Chrtimer) ! 91: ch_rtimer(); ! 92: ! 93: return 1; ! 94: } ! 95: ! 96: ! 97: chroute_close(q) ! 98: register struct queue *q; ! 99: { ! 100: register struct chif *ifp; ! 101: ! 102: --NChropen; ! 103: ifp = (struct chif *)q->ptr; ! 104: Chroute[ifp->my_addr.ch_subnet].rt_type = CHNOPATH; ! 105: arp_disable(ifp->arp); ! 106: ifp->rdq = (struct queue *)0; ! 107: ifp->my_addr.ch_addr = 0; ! 108: if (ifp == primary) ! 109: primary = (struct chif *)0; ! 110: q->ptr = 0; ! 111: } ! 112: ! 113: ! 114: chroute_put(q, bp) ! 115: register struct queue *q; ! 116: register struct block *bp; ! 117: { ! 118: debug(printf("chroute_put(%s, %d)\n", ! 119: ((q->flag & QREADR)? "RD" : "WR"), bp->type)); ! 120: ! 121: switch (bp->type) { ! 122: case M_DATA: ! 123: putq(q, bp); ! 124: break; ! 125: case M_DELIM: ! 126: putq(q, bp); ! 127: qenable(q); ! 128: break; ! 129: case M_IOCTL: ! 130: /* Process an ioctl only if it's going towards the device */ ! 131: if (!(q->flag & QREADR) && chroute_ioctl(q, bp)) ! 132: break; ! 133: default: /* Anything else, just pass on to the next guy */ ! 134: (*q->next->qinfo->putp)(q->next, bp); ! 135: } ! 136: } ! 137: ! 138: ! 139: chroute_srv(q) ! 140: register struct queue *q; ! 141: { ! 142: register struct block *bp; ! 143: register struct chif *ifp; ! 144: register struct chroute *r; ! 145: int minsize; ! 146: ! 147: /* We have a complete packet in the queue, composed of some number ! 148: of M_DATA's followed by an M_DELIM. ! 149: We know there are no other block types, because chroute_put() ! 150: won't give us anything else. */ ! 151: ! 152: debug(printf("chroute_srv(%s)\n", ((q->flag & QREADR)? "RD" : "WR"))); ! 153: ! 154: if (bp = q->first) { ! 155: if (bp->type == M_DELIM) { ! 156: printf("chroute: delimiter without data\n"); ! 157: flush_packet(q); ! 158: return; ! 159: } ! 160: minsize = sizeof(struct pkt_header); ! 161: if (q->flag & QREADR) { ! 162: /* The packet is coming from the device */ ! 163: minsize += sizeof(struct ether_in); ! 164: } ! 165: if (block_pullup(q, minsize) == 0) { ! 166: flush_packet(q); ! 167: return; ! 168: } ! 169: if (q->flag & QREADR) { ! 170: /* Packet is from device; strip off ethernet header */ ! 171: q->first->rptr += sizeof(struct ether_in); ! 172: ifp = (struct chif *)q->ptr; ! 173: ifp->ist_rcvd++; ! 174: if (ifp->my_addr.ch_addr != 0) { ! 175: r = &Chroute[ifp->my_addr.ch_subnet]; ! 176: r->rt_type = CHDIRECT; ! 177: r->rt_cost = ifp->if_cost; ! 178: r->rt_path.ifp = ifp; ! 179: } ! 180: } ! 181: chroute_dispatch(q); ! 182: ! 183: /* See if there's another packet on the queue */ ! 184: for (bp = q->first; bp != NOBLOCK; bp = bp->next) ! 185: if (bp->type == M_DELIM) { ! 186: qenable(q); /* re-enable queue for the next packet */ ! 187: break; ! 188: } ! 189: } ! 190: } ! 191: ! 192: ! 193: /* Handle an ioctl */ ! 194: ! 195: chroute_ioctl(q, bp) ! 196: register struct queue *q; ! 197: register struct block *bp; ! 198: { ! 199: register union stmsg *sp; ! 200: register struct chif *ifp; ! 201: register struct chroute *rt; ! 202: register struct chaddr_pair *chp; ! 203: ! 204: ifp = (struct chif *)q->ptr; ! 205: sp = (union stmsg *)bp->rptr; ! 206: switch (sp->iocx.com) { ! 207: case CHIOCADDR: ! 208: bp->wptr = bp->rptr; ! 209: if (ifp->my_addr.ch_addr != 0) { ! 210: Chroute[ifp->my_addr.ch_subnet].rt_type = CHNOPATH; ! 211: arp_disable(ifp->arp); ! 212: } ! 213: ifp->my_addr.ch_addr = *(int *)(sp->iocx.xxx); ! 214: if (ifp->my_addr.ch_subnet >= CHNSUBNET ! 215: || ifp->my_addr.ch_subnet == 0) { ! 216: ifp->my_addr.ch_addr = 0; ! 217: bp->type = M_IOCNAK; ! 218: break; ! 219: } ! 220: rt = &Chroute[ifp->my_addr.ch_subnet]; ! 221: rt->rt_type = CHDIRECT; ! 222: rt->rt_cost = ifp->if_cost; ! 223: rt->rt_path.ifp = ifp; ! 224: /* Should we check if this fails? */ ! 225: ifp->arp = arp_enable(ifp->if_dev, ETHERPUP_CHAOSTYPE, ! 226: sizeof(chaddr), 0, &ifp->my_addr); ! 227: bp->type = M_IOCACK; ! 228: break; ! 229: case CRIOCOST: ! 230: ifp->if_cost = *(u_short *)(sp->iocx.xxx); ! 231: bp->wptr = bp->rptr; ! 232: bp->type = M_IOCACK; ! 233: break; ! 234: case CRIOPRIMARY: ! 235: primary = ifp; ! 236: bp->wptr = bp->rptr; ! 237: bp->type = M_IOCACK; ! 238: break; ! 239: default: ! 240: return 0; /* Let someone else deal with it */ ! 241: } ! 242: ! 243: qreply(q, bp); ! 244: return 1; ! 245: } ! 246: ! 247: ! 248: /* We've got a packet to send (or receive); send it to the right place */ ! 249: ! 250: chroute_dispatch(q) ! 251: register struct queue *q; ! 252: { ! 253: register struct block *bp; ! 254: register struct pkt_header *ph; ! 255: register struct chroute *rt; ! 256: register struct chif *ifp; ! 257: register int len, isdelim; ! 258: struct ether_out *ep; ! 259: chaddr dest; ! 260: ! 261: ph = (struct pkt_header *)q->first->rptr; ! 262: ifp = (struct chif *)q->ptr; ! 263: debug(printf("chroute_dispatch: op 0%o len %d\n", ph->ph_op, ph->ph_len)); ! 264: ! 265: if (q->flag & QREADR && ph->ph_op == RUTOP) { ! 266: if (block_pullup(q, ph->ph_len + sizeof(*ph)) == 0) { ! 267: ifp->ist_rej++; ! 268: flush_packet(q); ! 269: return; ! 270: } ! 271: chroute_rcvrut(q->first->rptr); ! 272: flush_packet(q); ! 273: return; ! 274: } ! 275: ! 276: if (primary && (ph->ph_daddr.ch_addr == primary->my_addr.ch_addr ! 277: || (q->flag & QREADR && ph->ph_daddr.ch_addr == 0))) { ! 278: ph->ph_daddr = primary->my_addr; ! 279: if (ph->ph_len > CHMAXDATA) { ! 280: ifp->ist_len++; ! 281: flush_packet(q); ! 282: return; ! 283: } ! 284: len = sizeof(struct pkt_header) + ph->ph_len; ! 285: while (bp = getq(q)) { ! 286: if (bp->type == M_DATA) { ! 287: if (bp->wptr - bp->rptr > len) ! 288: bp->wptr = bp->rptr + len; ! 289: len -= bp->wptr - bp->rptr; ! 290: if (bp->wptr <= bp->rptr) { ! 291: freeb(bp); ! 292: continue; ! 293: } ! 294: } ! 295: debug(print_buf(bp, "rcvd:")); ! 296: isdelim = (bp->type == M_DELIM); ! 297: (*primary->rdq->next->qinfo->putp)(primary->rdq->next, bp); ! 298: if (isdelim) ! 299: break; ! 300: } ! 301: if (len != 0) ! 302: ifp->ist_len++; ! 303: return; ! 304: } ! 305: ! 306: if (q->flag & QREADR) { ! 307: if (ph->ph_daddr.ch_host == 0) { ! 308: ifp->ist_rej++; ! 309: flush_packet(q); ! 310: return; ! 311: } else if (++ph->ph_fc == 0) { ! 312: /* Overforwarded packet */ ! 313: flush_packet(q); ! 314: return; ! 315: } ! 316: } ! 317: ! 318: dest = ph->ph_daddr; ! 319: if (ph->ph_daddr.ch_host == 0) ! 320: ph->ph_daddr.ch_subnet = 0; ! 321: if (dest.ch_subnet >= CHNSUBNET ! 322: || (rt = &Chroute[dest.ch_subnet])->rt_type == CHNOPATH) { ! 323: flush_packet(q); ! 324: return; ! 325: } ! 326: ! 327: if (rt->rt_type == CHFIXED || rt->rt_type == CHBRIDGE) ! 328: dest = rt->rt_path.bridge; ! 329: ifp = Chroute[dest.ch_subnet].rt_path.ifp; ! 330: ! 331: if ((bp = allocb(sizeof(struct ether_out))) == 0) { ! 332: ifp->ist_abrt++; ! 333: flush_packet(q); ! 334: return; ! 335: } ! 336: ep = (struct ether_out *)bp->wptr; ! 337: bp->wptr += sizeof(struct ether_out); ! 338: ep->type = hfirst_short(ETHERPUP_CHAOSTYPE); ! 339: ! 340: if (dest.ch_host == 0) /* If address is 0, broadcast to everyone */ ! 341: arp_broadcast(ep->dhost); ! 342: else if (arp_getaddr(ifp->arp, &dest, ep->dhost) == -1) { ! 343: ifp->ist_abrt++; ! 344: flush_packet(q); ! 345: return; ! 346: } ! 347: ! 348: do { ! 349: debug(print_buf(bp, "xmit:")); ! 350: isdelim = (bp->type == M_DELIM); ! 351: (*(WR(ifp->rdq)->next->qinfo->putp)) (WR(ifp->rdq)->next, bp); ! 352: if (isdelim) ! 353: break; ! 354: } while (bp = getq(q)); ! 355: ! 356: ifp->ist_xmit++; ! 357: } ! 358: ! 359: ! 360: /* Handle RUT (Routing) Packets */ ! 361: chroute_rcvrut(ph) ! 362: register struct pkt_header *ph; ! 363: { ! 364: register struct rut_data *rd; ! 365: register struct chroute *rt; ! 366: register int i; ! 367: ! 368: if ((i = ph->ph_saddr.ch_subnet) >= CHNSUBNET) { ! 369: printf("CHAOS: Bad subnet (%d) in RUT packet\n", i); ! 370: return; ! 371: } ! 372: if (Chroute[i].rt_type != CHDIRECT) { ! 373: printf("CHAOS: RUT packet from unconnected subnet %d\n", i); ! 374: return; ! 375: } ! 376: ! 377: debug(printf("chroute_rcvrut(%d)\n", i)); ! 378: ! 379: rd = (struct rut_data *)((char *)ph + sizeof(struct pkt_header)); ! 380: for (i = ph->ph_len; i > 0; i -= sizeof(struct rut_data), ++rd) { ! 381: if (rd->rd_subnet >= CHNSUBNET) ! 382: continue; ! 383: rt = &Chroute[rd->rd_subnet]; ! 384: switch (rt->rt_type) { ! 385: case CHBRIDGE: ! 386: if (rd->rd_cost > rt->rt_cost) ! 387: break; ! 388: case CHNOPATH: ! 389: rt->rt_cost = rd->rd_cost; ! 390: rt->rt_type = CHBRIDGE; ! 391: rt->rt_path.bridge = ph->ph_saddr; ! 392: break; ! 393: case CHDIRECT: ! 394: case CHFIXED: ! 395: break; ! 396: default: ! 397: printf("CHAOS: Bad entry in routing table, type = %d\n", ! 398: rt->rt_type); ! 399: } ! 400: } ! 401: } ! 402: ! 403: ! 404: #ifdef DEBUG ! 405: ! 406: print_buf(bp, s) ! 407: register struct block *bp; ! 408: register char *s; ! 409: { ! 410: register u_char *p; ! 411: register int i; ! 412: ! 413: printf("%s msg type %d len %d", s, bp->type, bp->wptr - bp->rptr); ! 414: for (i = 0, p = bp->rptr; p < bp->wptr; ++i, ++p) { ! 415: if ((i & 31) == 0) ! 416: printf("\n%s", s); ! 417: printf(" %x", *p); ! 418: } ! 419: printf("\n"); ! 420: } ! 421: ! 422: #endif DEBUG
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.