📄 clnp_input.c
字号:
* * NOTES: * TODO: I would like to make seg_part a pointer into the mbuf, but * will it be correctly aligned? */clnp_input(m, shp)struct mbuf *m; /* ptr to first mbuf of pkt */struct snpa_hdr *shp; /* subnetwork header */{ register struct clnp_fixed *clnp; /* ptr to fixed part of header */ struct sockaddr_iso source; /* source address of pkt */ struct sockaddr_iso target; /* destination address of pkt */#define src source.siso_addr#define dst target.siso_addr caddr_t hoff; /* current offset in packet */ caddr_t hend; /* address of end of header info */ struct clnp_segment seg_part; /* segment part of hdr */ int seg_off=0; /* offset of segment part of hdr */ int seg_len;/* length of packet data&hdr in bytes */ struct clnp_optidx oidx, *oidxp = NULL; /* option index */ extern int iso_systype; /* used by ESIS config resp */ extern struct sockaddr_iso blank_siso; /* used for initializing */ int need_afrin = 0; /* true if congestion experienced */ /* which means you need afrin nose */ /* spray. How clever! */ IFDEBUG(D_INPUT) printf( "clnp_input: proccessing dg; First mbuf m_len %d, m_type x%x, %s\n", m->m_len, m->m_type, IS_CLUSTER(m) ? "cluster" : "normal"); ENDDEBUG need_afrin = 0; /* * If no iso addresses have been set, there is nothing * to do with the packet. */ if (iso_ifaddr == NULL) { clnp_discard(m, ADDR_DESTUNREACH); return; } INCSTAT(cns_total); clnp = mtod(m, struct clnp_fixed *); IFDEBUG(D_DUMPIN) struct mbuf *mhead; int total_len = 0; printf("clnp_input: clnp header:\n"); dump_buf(mtod(m, caddr_t), clnp->cnf_hdr_len); printf("clnp_input: mbuf chain:\n"); for (mhead = m; mhead != NULL; mhead=mhead->m_next) { printf("m x%x, len %d\n", mhead, mhead->m_len); total_len += mhead->m_len; } printf("clnp_input: total length of mbuf chain %d:\n", total_len); ENDDEBUG /* * Compute checksum (if necessary) and drop packet if * checksum does not match */ if (CKSUM_REQUIRED(clnp) && iso_check_csum(m, (int)clnp->cnf_hdr_len)) { INCSTAT(cns_badcsum); clnp_discard(m, GEN_BADCSUM); return; } if (clnp->cnf_vers != ISO8473_V1) { INCSTAT(cns_badvers); clnp_discard(m, DISC_UNSUPPVERS); return; } /* check mbuf data length: clnp_data_ck will free mbuf upon error */ CTOH(clnp->cnf_seglen_msb, clnp->cnf_seglen_lsb, seg_len); if ((m = clnp_data_ck(m, seg_len)) == 0) return; clnp = mtod(m, struct clnp_fixed *); hend = (caddr_t)clnp + clnp->cnf_hdr_len; /* * extract the source and destination address * drop packet on failure */ source = target = blank_siso; hoff = (caddr_t)clnp + sizeof(struct clnp_fixed); CLNP_EXTRACT_ADDR(dst, hoff, hend); if (hoff == (caddr_t)0) { INCSTAT(cns_badaddr); clnp_discard(m, GEN_INCOMPLETE); return; } CLNP_EXTRACT_ADDR(src, hoff, hend); if (hoff == (caddr_t)0) { INCSTAT(cns_badaddr); clnp_discard(m, GEN_INCOMPLETE); return; } IFDEBUG(D_INPUT) printf("clnp_input: from %s", clnp_iso_addrp(&src)); printf(" to %s\n", clnp_iso_addrp(&dst)); ENDDEBUG /* * extract the segmentation information, if it is present. * drop packet on failure */ if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && (clnp->cnf_type & CNF_SEG_OK)) { if (hoff + sizeof(struct clnp_segment) > hend) { INCSTAT(cns_noseg); clnp_discard(m, GEN_INCOMPLETE); return; } else { (void) bcopy(hoff, (caddr_t)&seg_part, sizeof(struct clnp_segment)); /* make sure segmentation fields are in host order */ seg_part.cng_id = ntohs(seg_part.cng_id); seg_part.cng_off = ntohs(seg_part.cng_off); seg_part.cng_tot_len = ntohs(seg_part.cng_tot_len); seg_off = hoff - (caddr_t)clnp; hoff += sizeof(struct clnp_segment); } } /* * process options if present. If clnp_opt_sanity returns * false (indicating an error was found in the options) or * an unsupported option was found * then drop packet and emit an ER. */ if (hoff < hend) { int errcode; oidxp = &oidx; errcode = clnp_opt_sanity(m, hoff, hend-hoff, oidxp); /* we do not support security */ if ((errcode == 0) && (oidxp->cni_securep)) errcode = DISC_UNSUPPSECURE; /* the er option is valid with ER pdus only */ if ((errcode == 0) && (oidxp->cni_er_reason != ER_INVALREAS) && ((clnp->cnf_type & CNF_TYPE) != CLNP_ER)) errcode = DISC_UNSUPPOPT;#ifdef DECBIT /* check if the congestion experienced bit is set */ if (oidxp->cni_qos_formatp) { caddr_t qosp = CLNP_OFFTOOPT(m, oidxp->cni_qos_formatp); u_char qos = *qosp; need_afrin = ((qos & (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)) == (CLNPOVAL_GLOBAL|CLNPOVAL_CONGESTED)); if (need_afrin) INCSTAT(cns_congest_rcvd); }#endif /* DECBIT */ if (errcode != 0) { clnp_discard(m, (char)errcode); IFDEBUG(D_INPUT) printf("clnp_input: dropped (err x%x) due to bad options\n", errcode); ENDDEBUG return; } } /* * check if this packet is for us. if not, then forward */ if (clnp_ours(&dst) == 0) { IFDEBUG(D_INPUT) printf("clnp_input: forwarding packet not for us\n"); ENDDEBUG clnp_forward(m, seg_len, &dst, oidxp, seg_off, shp); return; } /* * ESIS Configuration Response Function * * If the packet received was sent to the multicast address * all end systems, then send an esh to the source */ if ((shp->snh_flags & M_MCAST) && (iso_systype == SNPA_ES)) { extern short esis_holding_time; esis_shoutput(shp->snh_ifp, ESIS_ESH, esis_holding_time, shp->snh_shost, 6, &dst); } /* * If this is a fragment, then try to reassemble it. If clnp_reass * returns non NULL, the packet has been reassembled, and should * be give to TP. Otherwise the fragment has been delt with * by the reassembly code (either stored or deleted). In either case * we should have nothing more to do with it. */ if (((clnp->cnf_type & CNF_TYPE) != CLNP_ER) && (clnp->cnf_type & CNF_SEG_OK) && (seg_len != seg_part.cng_tot_len)) { struct mbuf *m0; if ((m0 = clnp_reass(m, &src, &dst, &seg_part)) != NULL) { m = m0; clnp = mtod(m, struct clnp_fixed *); INCSTAT(cns_reassembled); } else { return; } } /* * give the packet to the higher layer * * Note: the total length of packet * is the total length field of the segmentation part, * or, if absent, the segment length field of the * header. */ INCSTAT(cns_delivered); switch (clnp->cnf_type & CNF_TYPE) { case CLNP_ER: /* * This ER must have the er option. * If the option is not present, discard datagram. */ if (oidxp == NULL || oidxp->cni_er_reason == ER_INVALREAS) { clnp_discard(m, GEN_HDRSYNTAX); } else { clnp_er_input(m, &src, oidxp->cni_er_reason); } break; case CLNP_DT: (*isosw[clnp_protox[ISOPROTO_TP]].pr_input)(m, &source, &target, clnp->cnf_hdr_len, need_afrin); break; case CLNP_RAW: case CLNP_ECR: IFDEBUG(D_INPUT) printf("clnp_input: raw input of %d bytes\n", clnp->cnf_type & CNF_SEG_OK ? seg_part.cng_tot_len : seg_len); ENDDEBUG (*isosw[clnp_protox[ISOPROTO_RAW]].pr_input)(m, &source, &target, clnp->cnf_hdr_len); break; case CLNP_EC: IFDEBUG(D_INPUT) printf("clnp_input: echoing packet\n"); ENDDEBUG (void)clnp_echoreply(m, (clnp->cnf_type & CNF_SEG_OK ? (int)seg_part.cng_tot_len : seg_len), &source, &target, oidxp); break; default: printf("clnp_input: unknown clnp pkt type %d\n", clnp->cnf_type & CNF_TYPE); clnp_stat.cns_delivered--; clnp_stat.cns_noproto++; clnp_discard(m, GEN_HDRSYNTAX); break; }}#endif /* ISO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -