|
|
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: ! 128: /* ! 129: * set our many broadcast addresses ! 130: */ ! 131: static ! 132: setbcast(ifp) ! 133: struct ipif *ifp; ! 134: { ! 135: int i; ! 136: ! 137: /* official style */ ! 138: ifp->bcast[0] = ifp->that|~ifp->mask; /* subnet */ ! 139: ifp->bcast[1] = ifp->that|~IN_CLASS_NMASK(ifp->that); /* net */ ! 140: ifp->bcast[2] = 0xffffffff; /* undirected */ ! 141: ! 142: /* old BSD style */ ! 143: ifp->bcast[3] = ifp->that&ifp->mask; /* subnet */ ! 144: ifp->bcast[4] = ifp->that&IN_CLASS_NMASK(ifp->that); /* net */ ! 145: ifp->bcast[5] = 0; /* undirected */ ! 146: ! 147: if(ifp->flags & IFF_HOST) ! 148: for(i = 0; i < 6; i++) ! 149: ifp->bcast[i] = 0; ! 150: } ! 151: ! 152: iposrv(q) ! 153: register struct queue *q; ! 154: { ! 155: struct x{ ! 156: unsigned int in; ! 157: unsigned char en[6]; ! 158: } *xp; ! 159: register struct block *bp; ! 160: register struct ipif *ifp; ! 161: register long *intp; ! 162: ! 163: ifp = (struct ipif *)q->ptr; ! 164: while(bp = getq(q)){ ! 165: switch (bp->type) { ! 166: case M_IOCTL: ! 167: switch(stiocom(bp)){ ! 168: case IPIOARP: ! 169: ifp->flags |= IFF_ARP; ! 170: bp->type = M_IOCACK; ! 171: bp->wptr = bp->rptr; ! 172: qreply(q, bp); ! 173: break; ! 174: case IPIORESOLVE: ! 175: xp = (struct x *)(stiodata(bp)); ! 176: if (arpcnt > 0) ! 177: arp_install(xp->in, xp->en); ! 178: bp->wptr = bp->rptr; ! 179: bp->type = M_IOCACK; ! 180: qreply(q, bp); ! 181: break; ! 182: case IPIOHOST: ! 183: intp = (long *)(stiodata(bp)); ! 184: ifp->that = *intp; ! 185: ifp->flags |= IFF_HOST; ! 186: ifp->mask = 0xffffffff; ! 187: setbcast(ifp); ! 188: ip_ifinsert(ifp); ! 189: bp->type = M_IOCACK; ! 190: qreply(q, bp); ! 191: ip_doroute(ifp->that, 0); ! 192: break; ! 193: case IPIOMTU: ! 194: intp = (long *)(stiodata(bp)); ! 195: ifp->mtu = *intp; ! 196: bp->type = M_IOCACK; ! 197: qreply(q, bp); ! 198: break; ! 199: case IPIONET: ! 200: intp = (long *)(stiodata(bp)); ! 201: ifp->that = *intp; ! 202: ifp->mask = IN_CLASS_NMASK(ifp->that); ! 203: setbcast(ifp); ! 204: ip_ifinsert(ifp); ! 205: ifp->flags &= (~IFF_HOST); ! 206: bp->type = M_IOCACK; ! 207: qreply(q, bp); ! 208: ip_doroute(ifp->that, 0); ! 209: break; ! 210: case IPIOMASK: ! 211: intp = (long *)(stiodata(bp)); ! 212: /* ! 213: * the mask has to be a superset of the class mask ! 214: */ ! 215: if((*intp&ifp->mask)==ifp->mask) ! 216: ifp->mask = *intp; ! 217: setbcast(ifp); ! 218: ip_ifinsert(ifp); ! 219: bp->type = M_IOCACK; ! 220: qreply(q, bp); ! 221: break; ! 222: case IPIOLOCAL: ! 223: intp = (long *)(stiodata(bp)); ! 224: ifp->thishost = *intp; ! 225: setbcast(ifp); ! 226: bp->type = M_IOCACK; ! 227: qreply(q, bp); ! 228: break; ! 229: default: ! 230: (*q->next->qinfo->putp)(q->next, bp); ! 231: break; ! 232: } ! 233: continue; ! 234: ! 235: default: ! 236: if (q->next->flag & QFULL) { ! 237: putbq(q, bp); ! 238: return; ! 239: } ! 240: if(bp->class&S_DELIM) ! 241: ifp->opackets++; ! 242: (*q->next->qinfo->putp)(q->next, bp); ! 243: continue; ! 244: } ! 245: } ! 246: } ! 247: ! 248: /* ! 249: * Insert an entry into ipifsort. Entries are sorted by mask length, ! 250: * longest first. ! 251: */ ! 252: ip_ifinsert(ifp) ! 253: struct ipif *ifp; ! 254: { ! 255: int s = spl6(); ! 256: register int i, j; ! 257: ! 258: /* ! 259: * First try to remove it. This may be a reordering. ! 260: */ ! 261: ip_ifremove(ifp); ! 262: ! 263: /* ! 264: * Now (re)insert it in the correct place ! 265: */ ! 266: for(i=0; i<ipcnt; i++){ ! 267: if(ipifsort[i]==ifp) ! 268: panic("ip_ifinsert duplcate"); ! 269: if(ipifsort[i]==0 || (ifp->mask & ipifsort[i]->mask)!=ifp->mask) ! 270: break; ! 271: } ! 272: if(i>=ipcnt) ! 273: panic("ip_ifinsert no room"); ! 274: for(j=ipcnt-1; j>i; j--) ! 275: ipifsort[j] = ipifsort[j-1]; ! 276: ipifsort[i] = ifp; ! 277: splx(s); ! 278: } ! 279: ! 280: /* ! 281: * Remove an entry from ipifsort. Compress list to fill gap. ! 282: * It may not already be there. ! 283: */ ! 284: ip_ifremove(ifp) ! 285: struct ipif *ifp; ! 286: { ! 287: int s = spl6(); ! 288: register int i; ! 289: ! 290: for(i=0; i<ipcnt; i++) ! 291: if(ipifsort[i]==ifp) ! 292: break; ! 293: if(i<ipcnt){ ! 294: for(; i<ipcnt-1; i++) ! 295: ipifsort[i] = ipifsort[i+1]; ! 296: ipifsort[i] = 0; ! 297: } ! 298: splx(s); ! 299: } ! 300: ! 301: /* ! 302: * Find the interface to use for sending messages to `dst'. ! 303: * ipifsort is sorted into priority order; ! 304: * first match found is best. ! 305: */ ! 306: struct ipif * ! 307: ip_ifonnetof(dst) ! 308: register unsigned long dst; ! 309: { ! 310: extern ipprintfs; ! 311: register struct ipif *ifp; ! 312: register int i; ! 313: register int Ipcnt = ipcnt; /* optimization */ ! 314: ! 315: /* ! 316: * first look for a match against addresses ! 317: */ ! 318: for(i=0; i < Ipcnt; i++){ ! 319: if((ifp = ipifsort[i])==0) ! 320: break; ! 321: if(ifp->flags & IFF_UP) ! 322: if((dst & ifp->mask) == ifp->that) ! 323: return(ifp); ! 324: } ! 325: ! 326: /* ! 327: * now try to match against the local host's addresses ! 328: */ ! 329: ifp = ip_ifwithaddr(dst); ! 330: if(ifp) ! 331: return(ifp); ! 332: ! 333: /* ! 334: * no match ! 335: */ ! 336: if(ipprintfs) ! 337: printf("ifonnetof %x?\n", dst); ! 338: return(0); ! 339: } ! 340: ! 341: /* ! 342: * return the interface for which addr is a local address. if non ! 343: * such exists, return 0. ! 344: * ! 345: * This routine assumes that ipifsort is sorted in priority order ! 346: * so that the first match found is the best match. ! 347: */ ! 348: struct ipif * ! 349: ip_ifwithaddr(addr) ! 350: register u_long addr; ! 351: { ! 352: register int i, j; ! 353: register u_long net, mask; ! 354: register struct ipif *ifp; ! 355: register int Ipcnt = ipcnt; /* optimization */ ! 356: ! 357: net = in_netof(addr); ! 358: for(i=0; i < Ipcnt; i++){ ! 359: if((ifp = ipifsort[i])==0) ! 360: break; ! 361: if(ifp->flags & IFF_UP) { ! 362: ! 363: /* address of this host */ ! 364: if(addr == ifp->thishost) ! 365: return(ifp); ! 366: ! 367: for(j = 0; j < 6; j++) ! 368: if(addr == ifp->bcast[j]) ! 369: return(ifp); ! 370: ! 371: /* address on a network simulated by this node */ ! 372: if(net == ifp->thishost) ! 373: return(ifp); ! 374: } ! 375: } ! 376: return(0); ! 377: } ! 378: ! 379: /* ! 380: * output list bp onto interface ifp ! 381: * for better buffering, put it on ip's queue first; ! 382: * iposrv will dribble it out as there's room ! 383: */ ! 384: ip_ldout(bp, dst, ifp) ! 385: register struct block *bp; ! 386: unsigned long dst; /* host byte order */ ! 387: register struct ipif *ifp; ! 388: { ! 389: extern struct block *arp_resolve(); ! 390: register struct block *bp1; ! 391: register struct queue *q; ! 392: ! 393: if(ifp->queue == 0){ ! 394: printf("ifp but no queue in ip_ldout\n"); ! 395: bp_free(bp); ! 396: return(0); ! 397: } ! 398: q = WR(ifp->queue); ! 399: if(q->flag & QFULL){ ! 400: bp_free(bp); ! 401: ifp->oerrors++; ! 402: return(1); ! 403: } ! 404: if(arpcnt > 0 && (ifp->flags & IFF_ARP)){ ! 405: bp = arp_resolve(ifp->queue, bp, dst); ! 406: if(bp == 0) ! 407: return(1); ! 408: } ! 409: MCHECK(bp); ! 410: while(bp){ ! 411: bp1 = bp->next; ! 412: if (bp1==NULL) ! 413: bp->class |= S_DELIM; ! 414: (*q->qinfo->putp)(q, bp); ! 415: bp = bp1; ! 416: } ! 417: return(0); ! 418: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.