📄 tp_inet.c
字号:
* * CALLED FROM: tp_emit() * * FUNCTION and ARGUMENTS: * Take a packet(m0) from tp and package it so that ip will accept it. * This means prepending space for the ip header and filling in a few * of the fields. * inp is the inpcb structure; datalen is the length of the data in the * mbuf string m0. * RETURNS: * whatever (E*) is returned form the net layer output routine. * * SIDE EFFECTS: * * NOTES: */inttpip_output(inp, m0, datalen, nochksum) struct inpcb *inp; struct mbuf *m0; int datalen; int nochksum;{ return tpip_output_dg( &inp->inp_laddr, &inp->inp_faddr, m0, datalen, &inp->inp_route, nochksum);}/* * NAME: tpip_output_dg() * * CALLED FROM: tp_error_emit() * * FUNCTION and ARGUMENTS: * This is a copy of tpip_output that takes the addresses * instead of a pcb. It's used by the tp_error_emit, when we * don't have an in_pcb with which to call the normal output rtn. * * RETURNS: ENOBUFS or whatever (E*) is * returned form the net layer output routine. * * SIDE EFFECTS: * * NOTES: *//*ARGSUSED*/inttpip_output_dg(laddr, faddr, m0, datalen, ro, nochksum) struct in_addr *laddr, *faddr; struct mbuf *m0; int datalen; struct route *ro; int nochksum;{ register struct mbuf *m; register struct ip *ip; int error; IFDEBUG(D_EMIT) printf("tpip_output_dg datalen 0x%x m0 0x%x\n", datalen, m0); ENDDEBUG MGETHDR(m, M_DONTWAIT, TPMT_IPHDR); if (m == 0) { error = ENOBUFS; goto bad; } m->m_next = m0; MH_ALIGN(m, sizeof(struct ip)); m->m_len = sizeof(struct ip); ip = mtod(m, struct ip *); bzero((caddr_t)ip, sizeof *ip); ip->ip_p = IPPROTO_TP; m->m_pkthdr.len = ip->ip_len = sizeof(struct ip) + datalen; ip->ip_ttl = MAXTTL; /* don't know why you need to set ttl; * overlay doesn't even make this available */ ip->ip_src = *laddr; ip->ip_dst = *faddr; IncStat(ts_tpdu_sent); IFDEBUG(D_EMIT) dump_mbuf(m, "tpip_output_dg before ip_output\n"); ENDDEBUG error = ip_output(m, (struct mbuf *)0, ro, IP_ALLOWBROADCAST, NULL); IFDEBUG(D_EMIT) printf("tpip_output_dg after ip_output\n"); ENDDEBUG return error;bad: m_freem(m); IncStat(ts_send_drop); return error;}/* * NAME: tpip_input() * * CALLED FROM: * ip's input routine, indirectly through the protosw. * * FUNCTION and ARGUMENTS: * Take a packet (m) from ip, strip off the ip header and give it to tp * * RETURNS: No return value. * * SIDE EFFECTS: * * NOTES: */ProtoHooktpip_input(m, iplen) struct mbuf *m; int iplen;{ struct sockaddr_in src, dst; register struct ip *ip; int s = splnet(), hdrlen; IncStat(ts_pkt_rcvd); /* * IP layer has already pulled up the IP header, * but the first byte after the IP header may not be there, * e.g. if you came in via loopback, so you have to do an * m_pullup to before you can even look to see how much you * really need. The good news is that m_pullup will round * up to almost the next mbuf's worth. */ if((m = m_pullup(m, iplen + 1)) == MNULL) goto discard; CHANGE_MTYPE(m, TPMT_DATA); /* * Now pull up the whole tp header: * Unfortunately, there may be IP options to skip past so we * just fetch it as an unsigned char. */ hdrlen = iplen + 1 + mtod(m, u_char *)[iplen]; if( m->m_len < hdrlen ) { if((m = m_pullup(m, hdrlen)) == MNULL){ IFDEBUG(D_TPINPUT) printf("tp_input, pullup 2!\n"); ENDDEBUG goto discard; } } /* * cannot use tp_inputprep() here 'cause you don't * have quite the same situation */ IFDEBUG(D_TPINPUT) dump_mbuf(m, "after tpip_input both pullups"); ENDDEBUG /* * m_pullup may have returned a different mbuf */ ip = mtod(m, struct ip *); /* * drop the ip header from the front of the mbuf * this is necessary for the tp checksum */ m->m_len -= iplen; m->m_data += iplen; src.sin_addr = *(struct in_addr *)&(ip->ip_src); src.sin_family = AF_INET; src.sin_len = sizeof(src); dst.sin_addr = *(struct in_addr *)&(ip->ip_dst); dst.sin_family = AF_INET; dst.sin_len = sizeof(dst); (void) tp_input(m, (struct sockaddr *)&src, (struct sockaddr *)&dst, 0, tpip_output_dg, 0); return 0;discard: IFDEBUG(D_TPINPUT) printf("tpip_input DISCARD\n"); ENDDEBUG IFTRACE(D_TPINPUT) tptrace(TPPTmisc, "tpip_input DISCARD m", m,0,0,0); ENDTRACE m_freem(m); IncStat(ts_recv_drop); splx(s); return 0;}#include <sys/protosw.h>#include <netinet/ip_icmp.h>extern void tp_quench();/* * NAME: tpin_quench() * * CALLED FROM: tpip_ctlinput() * * FUNCTION and ARGUMENTS: find the tpcb pointer and pass it to tp_quench * * RETURNS: Nada * * SIDE EFFECTS: * * NOTES: */voidtpin_quench(inp) struct inpcb *inp;{ tp_quench((struct tp_pcb *)inp->inp_socket->so_pcb, PRC_QUENCH);}/* * NAME: tpip_ctlinput() * * CALLED FROM: * The network layer through the protosw table. * * FUNCTION and ARGUMENTS: * When clnp gets an ICMP msg this gets called. * It either returns an error status to the user or * causes all connections on this address to be aborted * by calling the appropriate xx_notify() routine. * (cmd) is the type of ICMP error. * (sa) the address of the sender * * RETURNS: Nothing * * SIDE EFFECTS: * * NOTES: */ProtoHooktpip_ctlinput(cmd, sin) int cmd; struct sockaddr_in *sin;{ extern u_char inetctlerrmap[]; extern struct in_addr zeroin_addr; void tp_quench __P((struct inpcb *,int)); void tpin_abort __P((struct inpcb *,int)); if (sin->sin_family != AF_INET && sin->sin_family != AF_IMPLINK) return 0; if (sin->sin_addr.s_addr == INADDR_ANY) return 0; if (cmd < 0 || cmd > PRC_NCMDS) return 0; switch (cmd) { case PRC_QUENCH: in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0, zeroin_addr, 0, cmd, tp_quench); break; case PRC_ROUTEDEAD: case PRC_HOSTUNREACH: case PRC_UNREACH_NET: case PRC_IFDOWN: case PRC_HOSTDEAD: in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0, zeroin_addr, 0, cmd, in_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_TIMXCEED_REASS: case PRC_PARAMPROB: */ in_pcbnotify(&tp_inpcb, (struct sockaddr *)sin, 0, zeroin_addr, 0, cmd, tpin_abort); } return 0;}/* * NAME: tpin_abort() * * 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. * * RETURNS: Nothing * * SIDE EFFECTS: * * NOTES: */ProtoHooktpin_abort(inp) struct inpcb *inp;{ struct tp_event e; e.ev_number = ER_TPDU; e.ATTR(ER_TPDU).e_reason = ENETRESET; (void) tp_driver((struct tp_pcb *)inp->inp_ppcb, &e); return 0;}#ifdef ARGO_DEBUGdump_inaddr(addr) register struct sockaddr_in *addr;{ printf("INET: port 0x%x; addr 0x%x\n", addr->sin_port, addr->sin_addr);}#endif /* ARGO_DEBUG */#endif /* INET */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -