📄 tp_iso.c
字号:
}/* * CALLED FROM: * tp_emit() * FUNCTION and ARGUMENTS: * Take a packet(m0) from tp and package it so that clnp will accept it. * This means prepending space for the clnp header and filling in a few * of the fields. * isop is the isopcb structure; datalen is the length of the data in the * mbuf string m0. * RETURN VALUE: * whatever (E*) is returned form the net layer output routine. */inttpclnp_output(isop, m0, datalen, nochksum) struct isopcb *isop; struct mbuf *m0; int datalen; int nochksum;{ register struct mbuf *m = m0; IncStat(ts_tpdu_sent); IFDEBUG(D_TPISO) struct tpdu *hdr = mtod(m0, struct tpdu *); printf("abt to call clnp_output: datalen 0x%x, hdr.li 0x%x, hdr.dutype 0x%x nocsum x%x dst addr:\n", datalen, (int)hdr->tpdu_li, (int)hdr->tpdu_type, nochksum); dump_isoaddr(isop->isop_faddr); printf("\nsrc addr:\n"); dump_isoaddr(isop->isop_laddr); dump_mbuf(m0, "at tpclnp_output"); ENDDEBUG return clnp_output(m0, isop, datalen, /* flags */nochksum ? CLNP_NO_CKSUM : 0);}/* * CALLED FROM: * tp_error_emit() * FUNCTION and ARGUMENTS: * This is a copy of tpclnp_output that takes the addresses * instead of a pcb. It's used by the tp_error_emit, when we * don't have an iso_pcb with which to call the normal output rtn. * RETURN VALUE: * ENOBUFS or * whatever (E*) is returned form the net layer output routine. */inttpclnp_output_dg(laddr, faddr, m0, datalen, ro, nochksum) struct iso_addr *laddr, *faddr; struct mbuf *m0; int datalen; struct route *ro; int nochksum;{ struct isopcb tmppcb; int err; int flags; register struct mbuf *m = m0; IFDEBUG(D_TPISO) printf("tpclnp_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); ENDDEBUG /* * Fill in minimal portion of isopcb so that clnp can send the * packet. */ bzero((caddr_t)&tmppcb, sizeof(tmppcb)); tmppcb.isop_laddr = &tmppcb.isop_sladdr; tmppcb.isop_laddr->siso_addr = *laddr; tmppcb.isop_faddr = &tmppcb.isop_sfaddr; tmppcb.isop_faddr->siso_addr = *faddr; IFDEBUG(D_TPISO) printf("tpclnp_output_dg faddr: \n"); dump_isoaddr(&tmppcb.isop_sfaddr); printf("\ntpclnp_output_dg laddr: \n"); dump_isoaddr(&tmppcb.isop_sladdr); printf("\n"); ENDDEBUG /* * Do not use packet cache since this is a one shot error packet */ flags = (CLNP_NOCACHE|(nochksum?CLNP_NO_CKSUM:0)); IncStat(ts_tpdu_sent); err = clnp_output(m0, &tmppcb, datalen, flags); /* * Free route allocated by clnp (if the route was indeed allocated) */ if (tmppcb.isop_route.ro_rt) RTFREE(tmppcb.isop_route.ro_rt); return(err);}/* * CALLED FROM: * clnp's input routine, indirectly through the protosw. * FUNCTION and ARGUMENTS: * Take a packet (m) from clnp, strip off the clnp header and give it to tp * No return value. */ProtoHooktpclnp_input(m, src, dst, clnp_len, ce_bit) register struct mbuf *m; struct sockaddr_iso *src, *dst; int clnp_len, ce_bit;{ struct mbuf *tp_inputprep(); int tp_input(), cltp_input(), (*input)() = tp_input; IncStat(ts_pkt_rcvd); IFDEBUG(D_TPINPUT) printf("tpclnp_input: m 0x%x clnp_len 0x%x\n", m, clnp_len); dump_mbuf(m, "at tpclnp_input"); ENDDEBUG /* * CLNP gives us an mbuf chain WITH the clnp header pulled up, * and the length of the clnp header. * First, strip off the Clnp header. leave the mbuf there for the * pullup that follows. */ m->m_len -= clnp_len; m->m_data += clnp_len; m->m_pkthdr.len -= clnp_len; /* XXXX: should probably be in clnp_input */ switch (dst->siso_data[dst->siso_nlen - 1]) {#ifdef TUBA case ISOPROTO_TCP: return (tuba_tcpinput(m, src, dst));#endif case 0: if (m->m_len == 0 && (m = m_pullup(m, 1)) == 0) return 0; if (*(mtod(m, u_char *)) == ISO10747_IDRP) return (idrp_input(m, src, dst)); } m = tp_inputprep(m); if (m == 0) return 0; if (mtod(m, u_char *)[1] == UD_TPDU_type) input = cltp_input; IFDEBUG(D_TPINPUT) dump_mbuf(m, "after tpclnp_input both pullups"); ENDDEBUG IFDEBUG(D_TPISO) printf("calling %sinput : src 0x%x, dst 0x%x, src addr:\n", (input == tp_input ? "tp_" : "clts_"), src, dst); dump_isoaddr(src); printf(" dst addr:\n"); dump_isoaddr(dst); ENDDEBUG (void) (*input)(m, (struct sockaddr *)src, (struct sockaddr *)dst, 0, tpclnp_output_dg, ce_bit); IFDEBUG(D_QUENCH) { if(time.tv_usec & 0x4 && time.tv_usec & 0x40) { printf("tpclnp_input: FAKING %s\n", tp_stat.ts_pkt_rcvd & 0x1?"QUENCH":"QUENCH2"); if(tp_stat.ts_pkt_rcvd & 0x1) { tpclnp_ctlinput(PRC_QUENCH, &src); } else { tpclnp_ctlinput(PRC_QUENCH2, &src); } } } ENDDEBUG return 0;}ProtoHookiso_rtchange(){ return 0;}/* * CALLED FROM: * tpclnp_ctlinput() * FUNCTION and ARGUMENTS: * find the tpcb pointer and pass it to tp_quench */voidtpiso_decbit(isop) struct isopcb *isop;{ tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH2);}/* * CALLED FROM: * tpclnp_ctlinput() * FUNCTION and ARGUMENTS: * find the tpcb pointer and pass it to tp_quench */voidtpiso_quench(isop) struct isopcb *isop;{ tp_quench((struct tp_pcb *)isop->isop_socket->so_pcb, PRC_QUENCH);}/* * CALLED FROM: * The network layer through the protosw table. * FUNCTION and ARGUMENTS: * When clnp an ICMP-like msg this gets called. * It either returns an error status to the user or * it causes all connections on this address to be aborted * by calling the appropriate xx_notify() routine. * (cmd) is the type of ICMP error. * (siso) is the address of the guy who sent the ER CLNPDU */ProtoHooktpclnp_ctlinput(cmd, siso) int cmd; struct sockaddr_iso *siso;{ extern u_char inetctlerrmap[]; extern ProtoHook tpiso_abort(); extern ProtoHook iso_rtchange(); extern ProtoHook tpiso_reset(); void iso_pcbnotify(); IFDEBUG(D_TPINPUT) printf("tpclnp_ctlinput1: cmd 0x%x addr: \n", cmd); dump_isoaddr(siso); ENDDEBUG if (cmd < 0 || cmd > PRC_NCMDS) return 0; if (siso->siso_family != AF_ISO) return 0; switch (cmd) { case PRC_QUENCH2: iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_decbit); break; case PRC_QUENCH: iso_pcbnotify(&tp_isopcb, siso, 0, (int (*)())tpiso_quench); break; case PRC_TIMXCEED_REASS: case PRC_ROUTEDEAD: iso_pcbnotify(&tp_isopcb, siso, 0, tpiso_reset); break; case PRC_HOSTUNREACH: case PRC_UNREACH_NET: case PRC_IFDOWN: case PRC_HOSTDEAD: iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], iso_rtchange); break; default: /* case PRC_MSGSIZE: case PRC_UNREACH_HOST: case PRC_UNREACH_PROTOCOL: case PRC_UNREACH_PORT: case PRC_UNREACH_NEEDFRAG: case PRC_UNREACH_SRCFAIL: case PRC_REDIRECT_NET: case PRC_REDIRECT_HOST: case PRC_REDIRECT_TOSNET: case PRC_REDIRECT_TOSHOST: case PRC_TIMXCEED_INTRANS: case PRC_PARAMPROB: */ iso_pcbnotify(&tp_isopcb, siso, (int)inetctlerrmap[cmd], tpiso_abort); break; } return 0;}/* * XXX - Variant which is called by clnp_er.c with an isoaddr rather * than a sockaddr_iso. */static struct sockaddr_iso siso = {sizeof(siso), AF_ISO};tpclnp_ctlinput1(cmd, isoa) int cmd; struct iso_addr *isoa;{ bzero((caddr_t)&siso.siso_addr, sizeof(siso.siso_addr)); bcopy((caddr_t)isoa, (caddr_t)&siso.siso_addr, isoa->isoa_len); tpclnp_ctlinput(cmd, &siso);}/* * These next 2 routines are * CALLED FROM: * xxx_notify() from tp_ctlinput() when * net level gets some ICMP-equiv. type event. * FUNCTION and ARGUMENTS: * Cause the connection to be aborted with some sort of error * reason indicating that the network layer caused the abort. * Fakes an ER TPDU so we can go through the driver. * abort always aborts the TP connection. * reset may or may not, depending on the TP class that's in use. */ProtoHooktpiso_abort(isop) struct isopcb *isop;{ struct tp_event e; IFDEBUG(D_CONN) printf("tpiso_abort 0x%x\n", isop); ENDDEBUG e.ev_number = ER_TPDU; e.ATTR(ER_TPDU).e_reason = ECONNABORTED; return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e);}ProtoHooktpiso_reset(isop) struct isopcb *isop;{ struct tp_event e; e.ev_number = T_NETRESET; return tp_driver((struct tp_pcb *)isop->isop_socket->so_pcb, &e);}#endif /* ISO */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -