|
|
1.1 ! root 1: /*********************************************************** ! 2: Copyright IBM Corporation 1987 ! 3: ! 4: All Rights Reserved ! 5: ! 6: Permission to use, copy, modify, and distribute this software and its ! 7: documentation for any purpose and without fee is hereby granted, ! 8: provided that the above copyright notice appear in all copies and that ! 9: both that copyright notice and this permission notice appear in ! 10: supporting documentation, and that the name of IBM not be ! 11: used in advertising or publicity pertaining to distribution of the ! 12: software without specific, written prior permission. ! 13: ! 14: IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ! 15: ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL ! 16: IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ! 17: ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, ! 18: WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ! 19: ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS ! 20: SOFTWARE. ! 21: ! 22: ******************************************************************/ ! 23: ! 24: /* ! 25: * ARGO Project, Computer Sciences Dept., University of Wisconsin - Madison ! 26: */ ! 27: /* $Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $ */ ! 28: /* $Source: /var/src/sys/netiso/RCS/clnp_input.c,v $ */ ! 29: /* @(#)clnp_input.c 7.12 (Berkeley) 6/20/90 */ ! 30: ! 31: #ifndef lint ! 32: static char *rcsid = "$Header: /var/src/sys/netiso/RCS/clnp_input.c,v 5.1 89/02/09 16:20:32 hagens Exp $"; ! 33: #endif lint ! 34: ! 35: #include "types.h" ! 36: #include "param.h" ! 37: #include "mbuf.h" ! 38: #include "domain.h" ! 39: #include "protosw.h" ! 40: #include "socket.h" ! 41: #include "socketvar.h" ! 42: #include "errno.h" ! 43: #include "time.h" ! 44: ! 45: #include "../net/if.h" ! 46: #include "../net/if_types.h" ! 47: #include "../net/route.h" ! 48: ! 49: #include "iso.h" ! 50: #include "iso_var.h" ! 51: #include "iso_snpac.h" ! 52: #include "clnp.h" ! 53: #include "clnl.h" ! 54: #include "esis.h" ! 55: #include "../netinet/in_systm.h" ! 56: #include "../netinet/ip.h" ! 57: #include "../netinet/if_ether.h" ! 58: #include "eonvar.h" ! 59: #include "clnp_stat.h" ! 60: #include "argo_debug.h" ! 61: ! 62: #ifdef ISO ! 63: u_char clnp_protox[ISOPROTO_MAX]; ! 64: struct clnl_protosw clnl_protox[256]; ! 65: int clnpqmaxlen = IFQ_MAXLEN; /* RAH? why is this a variable */ ! 66: struct mbuf *clnp_data_ck(); ! 67: ! 68: int clnp_input(); ! 69: ! 70: int esis_input(); ! 71: ! 72: #ifdef ISO_X25ESIS ! 73: int x25esis_input(); ! 74: #endif ISO_X25ESIS ! 75: ! 76: /* ! 77: * FUNCTION: clnp_init ! 78: * ! 79: * PURPOSE: clnp initialization. Fill in clnp switch tables. ! 80: * ! 81: * RETURNS: none ! 82: * ! 83: * SIDE EFFECTS: fills in clnp_protox table with correct offsets into ! 84: * the isosw table. ! 85: * ! 86: * NOTES: ! 87: */ ! 88: clnp_init() ! 89: { ! 90: register struct protosw *pr; ! 91: ! 92: /* ! 93: * CLNP protox initialization ! 94: */ ! 95: if ((pr = pffindproto(PF_ISO, ISOPROTO_RAW, SOCK_RAW)) == 0) ! 96: printf("clnl_init: no raw CLNP\n"); ! 97: else ! 98: clnp_protox[ISOPROTO_RAW] = pr - isosw; ! 99: ! 100: if ((pr = pffindproto(PF_ISO, ISOPROTO_TP, SOCK_SEQPACKET)) == 0) ! 101: printf("clnl_init: no tp/clnp\n"); ! 102: else ! 103: clnp_protox[ISOPROTO_TP] = pr - isosw; ! 104: ! 105: /* ! 106: * CLNL protox initialization ! 107: */ ! 108: clnl_protox[ISO8473_CLNP].clnl_input = clnp_input; ! 109: ! 110: clnlintrq.ifq_maxlen = clnpqmaxlen; ! 111: } ! 112: ! 113: /* ! 114: * FUNCTION: clnlintr ! 115: * ! 116: * PURPOSE: Process a packet on the clnl input queue ! 117: * ! 118: * RETURNS: nothing. ! 119: * ! 120: * SIDE EFFECTS: ! 121: * ! 122: * NOTES: ! 123: */ ! 124: clnlintr() ! 125: { ! 126: register struct mbuf *m; /* ptr to first mbuf of pkt */ ! 127: register struct clnl_fixed *clnl; /* ptr to fixed part of clnl hdr */ ! 128: int s; /* save and restore priority */ ! 129: struct clnl_protosw *clnlsw;/* ptr to protocol switch */ ! 130: struct snpa_hdr sh; /* subnetwork hdr */ ! 131: ! 132: /* ! 133: * Get next datagram off clnl input queue ! 134: */ ! 135: next: ! 136: s = splimp(); ! 137: /* IF_DEQUEUESNPAHDR(&clnlintrq, m, sh);*/ ! 138: IF_DEQUEUE(&clnlintrq, m); ! 139: splx(s); ! 140: ! 141: ! 142: if (m == 0) /* nothing to do */ ! 143: return; ! 144: if ((m->m_flags & M_PKTHDR) == 0 || m->m_pkthdr.rcvif == 0) { ! 145: m_freem(m); ! 146: goto next; ! 147: } else { ! 148: register struct ifaddr *ifa; ! 149: for (ifa = m->m_pkthdr.rcvif->if_addrlist; ifa; ifa = ifa->ifa_next) ! 150: if (ifa->ifa_addr->sa_family == AF_ISO) ! 151: break; ! 152: if (ifa == 0) { ! 153: m_freem(m); ! 154: goto next; ! 155: } ! 156: } ! 157: bzero((caddr_t)&sh, sizeof(sh)); ! 158: sh.snh_flags = m->m_flags & (M_MCAST|M_BCAST); ! 159: switch((sh.snh_ifp = m->m_pkthdr.rcvif)->if_type) { ! 160: extern int ether_output(); ! 161: case IFT_EON: ! 162: bcopy(mtod(m, caddr_t), (caddr_t)sh.snh_dhost, sizeof(u_long)); ! 163: bcopy(sizeof(u_long) + mtod(m, caddr_t), ! 164: (caddr_t)sh.snh_shost, sizeof(u_long)); ! 165: sh.snh_dhost[4] = mtod(m, u_char *)[sizeof(struct ip) + ! 166: _offsetof(struct eon_hdr, eonh_class)]; ! 167: m->m_data += EONIPLEN; ! 168: m->m_len -= EONIPLEN; ! 169: m->m_pkthdr.len -= EONIPLEN; ! 170: break; ! 171: ! 172: default: ! 173: if (sh.snh_ifp->if_output == ether_output) { ! 174: bcopy((caddr_t)(mtod(m, struct ether_header *)->ether_dhost), ! 175: (caddr_t)sh.snh_dhost, 2*sizeof(sh.snh_dhost)); ! 176: m->m_data += sizeof (struct ether_header); ! 177: m->m_len -= sizeof (struct ether_header); ! 178: m->m_pkthdr.len -= sizeof (struct ether_header); ! 179: } ! 180: } ! 181: IFDEBUG(D_INPUT) ! 182: int i; ! 183: printf("clnlintr: src:"); ! 184: for (i=0; i<6; i++) ! 185: printf("%x%c", sh.snh_shost[i] & 0xff, (i<5) ? ':' : ' '); ! 186: printf(" dst:"); ! 187: for (i=0; i<6; i++) ! 188: printf("%x%c", sh.snh_dhost[i] & 0xff, (i<5) ? ':' : ' '); ! 189: printf("\n"); ! 190: ENDDEBUG ! 191: ! 192: /* ! 193: * Get the fixed part of the clnl header into the first mbuf. ! 194: * Drop the packet if this fails. ! 195: * Do not call m_pullup if we have a cluster mbuf or the ! 196: * data is not there. ! 197: */ ! 198: if ((IS_CLUSTER(m) || (m->m_len < sizeof(struct clnl_fixed))) && ! 199: ((m = m_pullup(m, sizeof(struct clnl_fixed))) == 0)) { ! 200: INCSTAT(cns_toosmall); /* TODO: use clnl stats */ ! 201: goto next; /* m_pullup discards mbuf */ ! 202: } ! 203: ! 204: clnl = mtod(m, struct clnl_fixed *); ! 205: ! 206: /* ! 207: * Drop packet if the length of the header is not reasonable. ! 208: */ ! 209: if ((clnl->cnf_hdr_len < CLNP_HDR_MIN) || ! 210: (clnl->cnf_hdr_len > CLNP_HDR_MAX)) { ! 211: INCSTAT(cns_badhlen); /* TODO: use clnl stats */ ! 212: m_freem(m); ! 213: goto next; ! 214: } ! 215: ! 216: /* ! 217: * If the header is not contained in this mbuf, make it so. ! 218: * Drop packet if this fails. ! 219: * Note: m_pullup will allocate a cluster mbuf if necessary ! 220: */ ! 221: if (clnl->cnf_hdr_len > m->m_len) { ! 222: if ((m = m_pullup(m, (int)clnl->cnf_hdr_len)) == 0) { ! 223: INCSTAT(cns_badhlen); /* TODO: use clnl stats */ ! 224: goto next; /* m_pullup discards mbuf */ ! 225: } ! 226: clnl = mtod(m, struct clnl_fixed *); ! 227: } ! 228: ! 229: clnlsw = &clnl_protox[clnl->cnf_proto_id]; ! 230: ! 231: ! 232: if (clnlsw->clnl_input) ! 233: (*clnlsw->clnl_input) (m, &sh); ! 234: else ! 235: m_freem(m); ! 236: ! 237: goto next; ! 238: } ! 239: ! 240: /* ! 241: * FUNCTION: clnp_input ! 242: * ! 243: * PURPOSE: process an incoming clnp packet ! 244: * ! 245: * RETURNS: nothing ! 246: * ! 247: * SIDE EFFECTS: increments fields of clnp_stat structure. ! 248: * ! 249: * NOTES: ! 250: * TODO: I would like to make seg_part a pointer into the mbuf, but ! 251: * will it be correctly aligned? ! 252: */ ! 253: clnp_input(m, shp) ! 254: struct mbuf *m; /* ptr to first mbuf of pkt */ ! 255: struct snpa_hdr *shp; /* subnetwork header */ ! 256: { ! 257: register struct clnp_fixed *clnp; /* ptr to fixed part of header */ ! 258: struct sockaddr_iso source; /* source address of pkt */ ! 259: struct sockaddr_iso target; /* destination address of pkt */ ! 260: #define src source.siso_addr ! 261: #define dst target.siso_addr ! 262: caddr_t hoff; /* current offset in packet */ ! 263: caddr_t hend; /* address of end of header info */ ! 264: struct clnp_segment seg_part; /* segment part of hdr */ ! 265: int seg_off=0; /* offset of segment part of hdr */ ! 266: int seg_len;/* length of packet data&hdr in bytes */ ! 267: struct clnp_optidx oidx, *oidxp = NULL; /* option index */ ! 268: extern int iso_systype; /* used by ESIS config resp */ ! 269: extern struct sockaddr_iso blank_siso; /* used for initializing */ ! 270: int need_afrin = 0; ! 271: /* true if congestion experienced */ ! 272: /* which means you need afrin nose */ ! 273: /* spray. How clever! */ ! 274: ! 275: IFDEBUG(D_INPUT) ! 276: printf( ! 277: "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", ! 278: m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); ! 279: ENDDEBUG ! 280: need_afrin = 0; ! 281: ! 282: /* ! 283: * If no iso addresses have been set, there is nothing ! 284: * to do with the packet. ! 285: */ ! 286: if (iso_ifaddr == NULL) { ! 287: clnp_discard(m, ADDR_DESTUNREACH); ! 288: return; ! 289: } ! 290: ! 291: INCSTAT(cns_total); ! 292: clnp = mtod(m, struct clnp_fixed *); ! 293: ! 294: IFDEBUG(D_DUMPIN) ! 295: struct mbuf *mhead; ! 296: int total_len = 0; ! 297: printf("clnp_input: clnp header:\n"); ! 298: dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); ! 299: printf("clnp_input: mbuf chain:\n"); ! 300: for (mhead = m; mhead != NULL; mhead=mhead->m_next) { ! 301: printf("m x%x, len %d\n", mhead, mhead->m_len); ! 302: total_len += mhead->m_len; ! 303: } ! 304: printf("clnp_input: total length of mbuf chain %d:\n", total_len); ! 305: ENDDEBUG ! 306: ! 307: /* ! 308: * Compute checksum (if necessary) and drop packet if ! 309: * checksum does not match ! 310: */ ! 311: if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { ! 312: INCSTAT(cns_badcsum); ! 313: clnp_discard(m, GEN_BADCSUM); ! 314: return; ! 315: } ! 316: ! 317: if (clnp->cnf_vers != ISO8473_V1) { ! 318: INCSTAT(cns_badvers); ! 319: clnp_discard(m, DISC_UNSUPPVERS); ! 320: return; ! 321: } ! 322: ! 323: ! 324: /* check mbuf data length: clnp_data_ck will free mbuf upon error */ ! 325: CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); ! 326: if ((m = clnp_data_ck(m, seg_len)) == 0) ! 327: return; ! 328: ! 329: clnp = mtod(m, struct clnp_fixed *); ! 330: hend = (caddr_t)clnp + clnp->cnf_hdr_len; ! 331: ! 332: /* ! 333: * extract the source and destination address ! 334: * drop packet on failure ! 335: */ ! 336: source = target = blank_siso; ! 337: ! 338: hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); ! 339: CLNP_EXTRACT_ADDR(dst, hoff, hend); ! 340: if (hoff == (caddr_t)0) { ! 341: INCSTAT(cns_badaddr); ! 342: clnp_discard(m, GEN_INCOMPLETE); ! 343: return; ! 344: } ! 345: CLNP_EXTRACT_ADDR(src, hoff, hend); ! 346: if (hoff == (caddr_t)0) { ! 347: INCSTAT(cns_badaddr); ! 348: clnp_discard(m, GEN_INCOMPLETE); ! 349: return; ! 350: } ! 351: ! 352: IFDEBUG(D_INPUT) ! 353: printf("clnp_input: from %s", clnp_iso_addrp(&src)); ! 354: printf(" to %s\n", clnp_iso_addrp(&dst)); ! 355: ENDDEBUG ! 356: ! 357: /* ! 358: * extract the segmentation information, if it is present. ! 359: * drop packet on failure ! 360: */ ! 361: if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && ! 362: (clnp->cnf_type & CNF_SEG_OK)) { ! 363: if (hoff + sizeof(struct clnp_segment) > hend) { ! 364: INCSTAT(cns_noseg); ! 365: clnp_discard(m, GEN_INCOMPLETE); ! 366: return; ! 367: } else { ! 368: (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); ! 369: /* make sure segmentation fields are in host order */ ! 370: seg_part.cng_id = ntohs(seg_part.cng_id); ! 371: seg_part.cng_off = ntohs(seg_part.cng_off); ! 372: seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); ! 373: seg_off = hoff - (caddr_t)clnp; ! 374: hoff += sizeof(struct clnp_segment); ! 375: } ! 376: } ! 377: ! 378: /* ! 379: * process options if present. If clnp_opt_sanity returns ! 380: * false (indicating an error was found in the options) or ! 381: * an unsupported option was found ! 382: * then drop packet and emit an ER. ! 383: */ ! 384: if (hoff < hend) { ! 385: int errcode; ! 386: ! 387: oidxp = &oidx; ! 388: errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); ! 389: ! 390: /* we do not support security */ ! 391: if ((errcode == 0) && (oidxp->cni_securep)) ! 392: errcode = DISC_UNSUPPSECURE; ! 393: ! 394: /* the er option is valid with ER pdus only */ ! 395: if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && ! 396: ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) ! 397: errcode = DISC_UNSUPPOPT; ! 398: ! 399: #ifdef DECBIT ! 400: /* check if the congestion experienced bit is set */ ! 401: if (oidxp->cni_qos_formatp) { ! 402: caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); ! 403: u_char qos = *qosp; ! 404: ! 405: need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == ! 406: (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); ! 407: if (need_afrin) ! 408: INCSTAT(cns_congest_rcvd); ! 409: } ! 410: #endif DECBIT ! 411: ! 412: if (errcode != 0) { ! 413: clnp_discard(m, (char)errcode); ! 414: IFDEBUG(D_INPUT) ! 415: printf("clnp_input: dropped (err x%x) due to bad options\n", ! 416: errcode); ! 417: ENDDEBUG ! 418: return; ! 419: } ! 420: } ! 421: ! 422: /* ! 423: * check if this packet is for us. if not, then forward ! 424: */ ! 425: if (clnp_ours(&dst) == 0) { ! 426: IFDEBUG(D_INPUT) ! 427: printf("clnp_input: forwarding packet not for us\n"); ! 428: ENDDEBUG ! 429: clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); ! 430: return; ! 431: } ! 432: ! 433: /* ! 434: * ESIS Configuration Response Function ! 435: * ! 436: * If the packet received was sent to the multicast address ! 437: * all end systems, then send an esh to the source ! 438: */ ! 439: if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { ! 440: extern short esis_holding_time; ! 441: ! 442: esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, ! 443: shp->snh_shost, 6, &dst); ! 444: } ! 445: ! 446: /* ! 447: * If this is a fragment, then try to reassemble it. If clnp_reass ! 448: * returns non NULL, the packet has been reassembled, and should ! 449: * be give to TP. Otherwise the fragment has been delt with ! 450: * by the reassembly code (either stored or deleted). In either case ! 451: * we should have nothing more to do with it. ! 452: */ ! 453: if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && ! 454: (clnp->cnf_type & CNF_SEG_OK) && ! 455: (seg_len != seg_part.cng_tot_len)) { ! 456: struct mbuf *m0; ! 457: ! 458: if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { ! 459: m = m0; ! 460: clnp = mtod(m, struct clnp_fixed *); ! 461: INCSTAT(cns_reassembled); ! 462: } else { ! 463: return; ! 464: } ! 465: } ! 466: ! 467: /* ! 468: * give the packet to the higher layer ! 469: * ! 470: * Note: the total length of packet ! 471: * is the total length field of the segmentation part, ! 472: * or, if absent, the segment length field of the ! 473: * header. ! 474: */ ! 475: INCSTAT(cns_delivered); ! 476: switch (clnp->cnf_type & CNF_TYPE) { ! 477: case CLNP_ER: ! 478: /* ! 479: * This ER must have the er option. ! 480: * If the option is not present, discard datagram. ! 481: */ ! 482: if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { ! 483: clnp_discard(m, GEN_HDRSYNTAX); ! 484: } else { ! 485: clnp_er_input(m, &src, oidxp->cni_er_reason); ! 486: } ! 487: break; ! 488: ! 489: case CLNP_DT: ! 490: (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target, ! 491: clnp->cnf_hdr_len, need_afrin); ! 492: break; ! 493: ! 494: case CLNP_RAW: ! 495: case CLNP_ECR: ! 496: IFDEBUG(D_INPUT) ! 497: printf("clnp_input: raw input of %d bytes\n", ! 498: clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); ! 499: ENDDEBUG ! 500: (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target, ! 501: clnp->cnf_hdr_len); ! 502: break; ! 503: ! 504: case CLNP_EC: ! 505: IFDEBUG(D_INPUT) ! 506: printf("clnp_input: echoing packet\n"); ! 507: ENDDEBUG ! 508: /* ! 509: * Switch the source and destination address, ! 510: */ ! 511: hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); ! 512: CLNP_INSERT_ADDR(hoff, src); ! 513: CLNP_INSERT_ADDR(hoff, dst); ! 514: clnp->cnf_type &= ~CNF_TYPE; ! 515: clnp->cnf_type |= CLNP_ECR; ! 516: ! 517: /* ! 518: * Forward back to sender ! 519: */ ! 520: clnp_forward(m, (int) ! 521: (clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len), ! 522: &src, oidxp, seg_off, 0); ! 523: break; ! 524: ! 525: default: ! 526: printf("clnp_input: unknown clnp pkt type %d\n", ! 527: clnp->cnf_type & CNF_TYPE); ! 528: clnp_stat.cns_delivered--; ! 529: clnp_stat.cns_noproto++; ! 530: clnp_discard(m, GEN_HDRSYNTAX); ! 531: break; ! 532: } ! 533: } ! 534: #endif ISO
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.