|
|
1.1 ! root 1: /* ! 2: * ip line discipline, to be pushed on an ethernet controller. ! 3: * collects data till a delim, passes it to ip_input(). ! 4: */ ! 5: ! 6: #include "sys/param.h" ! 7: #include "sys/stream.h" ! 8: #include "sys/conf.h" ! 9: #include "sys/inet/in.h" ! 10: #include "sys/inet/ip_var.h" ! 11: #include "sys/inet/ethernet.h" ! 12: ! 13: extern struct ipif ipif[]; ! 14: extern struct ipif *ipifsort[]; ! 15: extern int ipcnt; /* number of ip's */ ! 16: extern int arpcnt; ! 17: ! 18: int ipiput(), ipisrv(), ipclose(); ! 19: long ipopen(); ! 20: int iposrv(); ! 21: static struct qinit iprinit = { ipiput, ipisrv, ipopen, ipclose, IP_MSG_LIMIT, 64}; ! 22: static struct qinit ipwinit = { putq, iposrv, ipopen, ipclose, 2*IP_MSG_LIMIT, 64 }; ! 23: struct streamtab ipstream = { &iprinit, &ipwinit }; ! 24: ! 25: long ! 26: ipopen(q, dev) ! 27: register struct queue *q; ! 28: { ! 29: static int timing; ! 30: register struct ipif *fp, *ifend; ! 31: ! 32: if (q->ptr) ! 33: return(1); ! 34: if(!timing){ ! 35: timing = 1; ! 36: ip_slowtimo(); ! 37: } ! 38: ifend = &ipif[ipcnt]; ! 39: for (fp = ipif; fp < ifend; fp++) ! 40: if (fp->queue == NULL) ! 41: break; ! 42: if (fp >= ifend) ! 43: return(0); ! 44: fp->queue = q; /* that's the RD q */ ! 45: fp->flags = IFF_UP; ! 46: fp->that = fp->thishost = 0; ! 47: fp->ipackets = fp->opackets = fp->ierrors = fp->oerrors = 0; ! 48: fp->mtu = 1500; ! 49: fp->arp = -1; ! 50: fp->dev = dev; ! 51: q->flag |= QDELIM; ! 52: WR(q)->flag |= QDELIM; ! 53: q->ptr = (caddr_t)fp; ! 54: WR(q)->ptr = (caddr_t)fp; ! 55: q->flag |= QNOENB; /* ipiput calls qenable() */ ! 56: return(1); ! 57: } ! 58: ! 59: ipclose(q) ! 60: struct queue *q; ! 61: { ! 62: register struct ipif *ifp; ! 63: ! 64: ifp = (struct ipif *)q->ptr; ! 65: ip_ifremove(ifp); ! 66: ifp->queue = 0; ! 67: ifp->flags = 0; ! 68: } ! 69: ! 70: ipisrv(q) ! 71: register struct queue *q; ! 72: { ! 73: register struct block *bp, *head, *tail; ! 74: register struct ipif *ifp; ! 75: ! 76: /* there is now a whole packet waiting ! 77: * on this queue; strip it off and pass to ip_input(). ! 78: * things other than data or delims are forwarded directly ! 79: * by ipiput(). ! 80: */ ! 81: head = tail = (struct block *) 0; ! 82: ifp = (struct ipif *)q->ptr; ! 83: while(bp = getq(q)){ ! 84: if (bp->type != M_DATA) ! 85: panic("ipisrv"); ! 86: bp->next = NULL; ! 87: if (head == NULL) ! 88: head = bp; ! 89: else ! 90: tail->next = bp; ! 91: tail = bp; ! 92: if (bp->class&S_DELIM) { ! 93: bp->class &=~ S_DELIM; ! 94: MCHECK(head); ! 95: if((ifp->flags & IFF_ARP) ! 96: && (head->wptr-head->rptr) >= sizeof(struct etherpup)){ ! 97: /* strip off ether header */ ! 98: head->rptr += sizeof(struct etherpup); ! 99: } ! 100: ip_input(head); ! 101: ifp->ipackets++; ! 102: head = tail = NULL; ! 103: } ! 104: } ! 105: if(head) ! 106: bp_putback(q, head); ! 107: } ! 108: ! 109: ! 110: ipiput(q, bp) ! 111: register struct queue *q; ! 112: register struct block *bp; ! 113: { ! 114: switch(bp->type){ ! 115: case M_DATA: ! 116: putq(q, bp); ! 117: if (bp->class&S_DELIM) ! 118: qenable(q); ! 119: break; ! 120: default: ! 121: (*q->next->qinfo->putp)(q->next, bp); ! 122: break; ! 123: } ! 124: ! 125: } ! 126: ! 127: iposrv(q) ! 128: register struct queue *q; ! 129: { ! 130: struct x{ ! 131: unsigned int in; ! 132: unsigned char en[6]; ! 133: } *xp; ! 134: register struct block *bp; ! 135: register struct ipif *ifp; ! 136: register long *intp; ! 137: ! 138: ifp = (struct ipif *)q->ptr; ! 139: while(bp = getq(q)){ ! 140: switch (bp->type) { ! 141: case M_IOCTL: ! 142: switch(stiocom(bp)){ ! 143: case IPIOARP: ! 144: ifp->flags |= IFF_ARP; ! 145: bp->type = M_IOCACK; ! 146: bp->wptr = bp->rptr; ! 147: qreply(q, bp); ! 148: break; ! 149: case IPIORESOLVE: ! 150: xp = (struct x *)(stiodata(bp)); ! 151: if (arpcnt > 0) ! 152: arp_install(xp->in, xp->en); ! 153: bp->wptr = bp->rptr; ! 154: bp->type = M_IOCACK; ! 155: qreply(q, bp); ! 156: break; ! 157: case IPIOHOST: ! 158: intp = (long *)(stiodata(bp)); ! 159: ifp->that = *intp; ! 160: ifp->flags |= IFF_HOST; ! 161: ifp->mask = 0xffffffff; ! 162: ifp->broadcast = 0; ! 163: ip_ifinsert(ifp); ! 164: bp->type = M_IOCACK; ! 165: qreply(q, bp); ! 166: ip_doroute(ifp->that, 0); ! 167: break; ! 168: case IPIOMTU: ! 169: intp = (long *)(stiodata(bp)); ! 170: ifp->mtu = *intp; ! 171: bp->type = M_IOCACK; ! 172: qreply(q, bp); ! 173: break; ! 174: case IPIONET: ! 175: intp = (long *)(stiodata(bp)); ! 176: ifp->that = *intp; ! 177: ifp->mask = IN_CLASS_NMASK(ifp->that); ! 178: ifp->broadcast = ifp->that|~ifp->mask; ! 179: ip_ifinsert(ifp); ! 180: ifp->flags &= (~IFF_HOST); ! 181: bp->type = M_IOCACK; ! 182: qreply(q, bp); ! 183: ip_doroute(ifp->that, 0); ! 184: break; ! 185: case IPIOMASK: ! 186: intp = (long *)(stiodata(bp)); ! 187: /* ! 188: * the mask has to be a superset of the class mask ! 189: */ ! 190: if((*intp&ifp->mask)==ifp->mask) ! 191: ifp->mask = *intp; ! 192: ifp->broadcast = ifp->that|~ifp->mask; ! 193: ip_ifinsert(ifp); ! 194: bp->type = M_IOCACK; ! 195: qreply(q, bp); ! 196: break; ! 197: case IPIOLOCAL: ! 198: intp = (long *)(stiodata(bp)); ! 199: ifp->thishost = *intp; ! 200: bp->type = M_IOCACK; ! 201: qreply(q, bp); ! 202: break; ! 203: default: ! 204: (*q->next->qinfo->putp)(q->next, bp); ! 205: break; ! 206: } ! 207: continue; ! 208: ! 209: default: ! 210: if (q->next->flag & QFULL) { ! 211: putbq(q, bp); ! 212: return; ! 213: } ! 214: if(bp->class&S_DELIM) ! 215: ifp->opackets++; ! 216: (*q->next->qinfo->putp)(q->next, bp); ! 217: continue; ! 218: } ! 219: } ! 220: } ! 221: ! 222: /* ! 223: * Insert an entry into ipifsort. Entries are sorted by mask length, ! 224: * longest first. ! 225: */ ! 226: ip_ifinsert(ifp) ! 227: struct ipif *ifp; ! 228: { ! 229: int s = spl6(); ! 230: register int i, j; ! 231: ! 232: /* ! 233: * First try to remove it. This may be a reordering. ! 234: */ ! 235: ip_ifremove(ifp); ! 236: ! 237: /* ! 238: * Now (re)insert it in the correct place ! 239: */ ! 240: for(i=0; i<ipcnt; i++){ ! 241: if(ipifsort[i]==ifp) ! 242: panic("ip_ifinsert duplcate"); ! 243: if(ipifsort[i]==0 || (ifp->mask & ipifsort[i]->mask)!=ifp->mask) ! 244: break; ! 245: } ! 246: if(i>=ipcnt) ! 247: panic("ip_ifinsert no room"); ! 248: for(j=ipcnt-1; j>i; j--) ! 249: ipifsort[j] = ipifsort[j-1]; ! 250: ipifsort[i] = ifp; ! 251: splx(s); ! 252: } ! 253: ! 254: /* ! 255: * Remove an entry from ipifsort. Compress list to fill gap. ! 256: * It may not already be there. ! 257: */ ! 258: ip_ifremove(ifp) ! 259: struct ipif *ifp; ! 260: { ! 261: int s = spl6(); ! 262: register int i; ! 263: ! 264: for(i=0; i<ipcnt; i++) ! 265: if(ipifsort[i]==ifp) ! 266: break; ! 267: if(i<ipcnt){ ! 268: for(; i<ipcnt-1; i++) ! 269: ipifsort[i] = ipifsort[i+1]; ! 270: ipifsort[i] = 0; ! 271: } ! 272: splx(s); ! 273: } ! 274: ! 275: /* ! 276: * Find the interface to use for sending messages to `dst'. ! 277: * ipifsort is sorted into priority order; ! 278: * first match found is best. ! 279: */ ! 280: struct ipif * ! 281: ip_ifonnetof(dst) ! 282: register unsigned long dst; ! 283: { ! 284: extern ipprintfs; ! 285: register struct ipif *ifp; ! 286: register int i; ! 287: register int Ipcnt = ipcnt; /* optimization */ ! 288: ! 289: /* ! 290: * first look for a match against addresses ! 291: */ ! 292: for(i=0; i < Ipcnt; i++){ ! 293: if((ifp = ipifsort[i])==0) ! 294: break; ! 295: if(ifp->flags & IFF_UP) ! 296: if((dst & ifp->mask) == ifp->that) ! 297: return(ifp); ! 298: } ! 299: ! 300: /* ! 301: * now try to match against the local host's addresses ! 302: */ ! 303: ifp = ip_ifwithaddr(dst); ! 304: if(ifp) ! 305: return(ifp); ! 306: ! 307: /* ! 308: * no match ! 309: */ ! 310: if(ipprintfs) ! 311: printf("ifonnetof %x?\n", dst); ! 312: return(0); ! 313: } ! 314: ! 315: /* ! 316: * return the interface for which addr is a local address. if non ! 317: * such exists, return 0. ! 318: * ! 319: * This routine assumes that ipifsort is sorted in priority order ! 320: * so that the first match found is the best match. ! 321: */ ! 322: struct ipif * ! 323: ip_ifwithaddr(addr) ! 324: register u_long addr; ! 325: { ! 326: register int i; ! 327: register u_long net, mask; ! 328: register struct ipif *ifp; ! 329: register int Ipcnt = ipcnt; /* optimization */ ! 330: ! 331: net = in_netof(addr); ! 332: for(i=0; i < Ipcnt; i++){ ! 333: if((ifp = ipifsort[i])==0) ! 334: break; ! 335: if(ifp->flags & IFF_UP) { ! 336: ! 337: /* address of this host */ ! 338: if(addr == ifp->thishost) ! 339: return(ifp); ! 340: ! 341: /* standard IP broadcast address */ ! 342: if(addr == ifp->broadcast) ! 343: return(ifp); ! 344: ! 345: /* old style BSD IP broadcast address */ ! 346: if(addr == in_netof(ifp->thishost)) ! 347: return(ifp); ! 348: ! 349: /* address on a network simulated by this node */ ! 350: if(net == ifp->thishost) ! 351: return(ifp); ! 352: ! 353: /* finally, try unsubnetted broadcast addresses */ ! 354: mask = IN_CLASS_NMASK(ifp->thishost); ! 355: if((mask&ifp->thishost | ~mask) == addr) ! 356: return(ifp); ! 357: ! 358: /* finally, try unsubnetted broadcast addresses */ ! 359: if((mask&ifp->thishost) == addr) ! 360: return(ifp); ! 361: } ! 362: } ! 363: return(0); ! 364: } ! 365: ! 366: /* ! 367: * output list bp onto interface ifp ! 368: * for better buffering, put it on ip's queue first; ! 369: * iposrv will dribble it out as there's room ! 370: */ ! 371: ip_ldout(bp, dst, ifp) ! 372: register struct block *bp; ! 373: unsigned long dst; /* host byte order */ ! 374: register struct ipif *ifp; ! 375: { ! 376: extern struct block *arp_resolve(); ! 377: register struct block *bp1; ! 378: register struct queue *q; ! 379: ! 380: if(ifp->queue == 0){ ! 381: printf("ifp but no queue in ip_ldout\n"); ! 382: bp_free(bp); ! 383: return(0); ! 384: } ! 385: q = WR(ifp->queue); ! 386: if(q->flag & QFULL){ ! 387: bp_free(bp); ! 388: ifp->oerrors++; ! 389: return(1); ! 390: } ! 391: if(arpcnt > 0 && (ifp->flags & IFF_ARP)){ ! 392: bp = arp_resolve(ifp->queue, bp, dst); ! 393: if(bp == 0) ! 394: return(1); ! 395: } ! 396: MCHECK(bp); ! 397: while(bp){ ! 398: bp1 = bp->next; ! 399: if (bp1==NULL) ! 400: bp->class |= S_DELIM; ! 401: (*q->qinfo->putp)(q, bp); ! 402: bp = bp1; ! 403: } ! 404: return(0); ! 405: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.