📄 ip_input.c
字号:
} NTOHS(ip->ip_id); NTOHS(ip->ip_off); /* * Check that the amount of data in the buffers * is as at least much as the IP header would have us expect. * Trim mbufs if longer than we expect. * Drop packet if shorter than we expect. */ if (m->m_pkthdr.len < ip->ip_len) {#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_CRITICAL event */ WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_CRITICAL, 17, 8, ip->ip_src.s_addr, ip->ip_dst.s_addr, WV_NETEVENT_IPIN_BADMBLK, WV_NET_RECV, m->m_pkthdr.len, ip->ip_len)#endif /* INCLUDE_WVNET */#endif#ifdef VIRTUAL_STACK _ipstat.ips_tooshort++;#else ipstat.ips_tooshort++;#endif /* VIRTUAL_STACK */ goto bad; } if (m->m_pkthdr.len > ip->ip_len) { if (m->m_len == m->m_pkthdr.len) { m->m_len = ip->ip_len; m->m_pkthdr.len = ip->ip_len; } else m_adj(m, ip->ip_len - m->m_pkthdr.len); } /* IPsec filter Hook */ if (_func_ipsecFilterHook != NULL) { if (_func_ipsecFilterHook (&m, &ip, hlen) == ERROR) { goto done; /* IPsec filter hook has already freed the mbuf */ } } /* ipFilterHook example fireWall Hook processing */ if (_ipFilterHook != NULL) { /* process the packet if the hook returns other than TRUE */ if ((*_ipFilterHook) (m->m_pkthdr.rcvif, &m, &ip, hlen) == TRUE) goto done; /* the hook should free the mbuf */ } /* * Process options and, if not destined for us, * ship it on. ip_dooptions returns 1 when an * error was detected (causing an icmp message * to be sent and the original packet to be freed). */ ip_nhops = 0; /* for source routed packets */ if (hlen > sizeof (struct ip) && ip_dooptions(m)) goto done; /* * Check our list of addresses, to see if the packet is for us. */#ifdef VIRTUAL_STACK for (ia = _in_ifaddr; ia; ia = ia->ia_next) {#else for (ia = in_ifaddr; ia; ia = ia->ia_next) {#endif /* VIRTUAL_STACK */#define satosin(sa) ((struct sockaddr_in *)(sa)) /* if ip is strong ended we will accept packets on an interface * only if destination in ip hdr matches ip address on the * receiving interface and not just any interface. */ if ((ipStrongEnded == TRUE) && (ia->ia_ifp != m->m_pkthdr.rcvif)) continue; if (IA_SIN(ia)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if (#ifdef DIRECTED_BROADCAST ia->ia_ifp == m->m_pkthdr.rcvif &&#endif (ia->ia_ifp->if_flags & IFF_BROADCAST)) { u_long t; if (satosin(&ia->ia_broadaddr)->sin_addr.s_addr == ip->ip_dst.s_addr) goto ours; if (ip->ip_dst.s_addr == ia->ia_netbroadcast.s_addr) goto ours; /* * Look for all-0's host part (old broadcast addr), * either for subnet or net. */ t = ntohl(ip->ip_dst.s_addr); if (t == ia->ia_subnet) goto ours; if (t == ia->ia_net) goto ours; } } if (IN_MULTICAST(ntohl(ip->ip_dst.s_addr))) { struct in_multi *inm; if (_mCastRouteFwdHook != NULL) { /* * If we are acting as a multicast router, all * incoming multicast packets are passed to the * kernel-level multicast forwarding function. * The packet is returned (relatively) intact; if * ip_mforward() returns a non-zero value, the packet * must be discarded, else it may be accepted below. * * (The IP ident field is put in the same byte order * as expected when ip_mforward() is called from * ip_output().) */ ip->ip_id = htons(ip->ip_id); if ((*_mCastRouteFwdHook)(m, m->m_pkthdr.rcvif, ip, NULL) != 0) {#ifdef VIRTUAL_STACK _ipstat.ips_cantforward++;#else ipstat.ips_cantforward++;#endif /* VIRTUAL_STACK */ m_freem(m); goto done; } ip->ip_id = ntohs(ip->ip_id); /* * The process-level routing demon needs to receive * all multicast IGMP packets, whether or not this * host belongs to their destination groups. */ if (ip->ip_p == IPPROTO_IGMP) goto ours;#ifdef VIRTUAL_STACK _ipstat.ips_forward++;#else ipstat.ips_forward++;#endif /* VIRTUAL_STACK */ } /* * See if we belong to the destination multicast group on the * arrival interface. */ IN_LOOKUP_MULTI(ip->ip_dst, m->m_pkthdr.rcvif, inm); if (inm == NULL) {#ifdef VIRTUAL_STACK _ipstat.ips_cantforward++;#else ipstat.ips_cantforward++;#endif /* VIRTUAL_STACK */ m_freem(m); goto done; } goto ours; } if (ip->ip_dst.s_addr == (u_long)INADDR_BROADCAST) goto ours; if (ip->ip_dst.s_addr == INADDR_ANY) goto ours; /* * Not for us; forward if possible and desirable. */ if ((_ipCfgFlags & IP_DO_FORWARDING) == 0) {#ifdef VIRTUAL_STACK _ipstat.ips_cantforward++;#else ipstat.ips_cantforward++;#endif /* VIRTUAL_STACK */ m_freem(m); } else ip_forward(m, 0); goto done;ours:#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_INFO event */ WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_INFO, 6, 16, ip->ip_src.s_addr, ip->ip_dst.s_addr, WV_NETEVENT_IPIN_GOODMBLK, WV_NET_RECV, ip->ip_src.s_addr, ip->ip_dst.s_addr)#endif /* INCLUDE_WVNET */#endif /* * If offset or IP_MF are set, must reassemble. * Otherwise, nothing need be done. * (We could look in the reassembly queue to see * if the packet was previously fragmented, * but it's not worth the time; just let them time out.) */ if (ip->ip_off &~ IP_DF) { /* * Look for queue of fragments * of this datagram. */#ifdef VIRTUAL_STACK for (fp = _ipq.next; fp != &_ipq; fp = fp->next)#else for (fp = ipq.next; fp != &ipq; fp = fp->next)#endif if (ip->ip_id == fp->ipq_id && ip->ip_src.s_addr == fp->ipq_src.s_addr && ip->ip_dst.s_addr == fp->ipq_dst.s_addr && ip->ip_p == fp->ipq_p) goto found; fp = 0;found: /* * Adjust ip_len to not reflect header, * set ip_mff if more fragments are expected, * convert offset of this to bytes. */ ip->ip_len -= hlen; ((struct ipasfrag *)ip)->ipf_mff &= ~1; if (ip->ip_off & IP_MF) ((struct ipasfrag *)ip)->ipf_mff |= 1; ip->ip_off <<= 3; /* * If datagram marked as having more fragments * or if this is not the first fragment, * attempt reassembly; if it succeeds, proceed. */ if (((struct ipasfrag *)ip)->ipf_mff & 1 || ip->ip_off) {#ifdef VIRTUAL_STACK _ipstat.ips_fragments++;#else ipstat.ips_fragments++;#endif /* VIRTUAL_STACK */ if ((m = ipReAssemble (m, fp)) == NULL) goto done; ip = mtod (m, struct ip *); hlen = ip->ip_hl << 2;#ifdef VIRTUAL_STACK _ipstat.ips_reassembled++;#else ipstat.ips_reassembled++;#endif /* VIRTUAL_STACK */ } else if (fp) ip_freef(fp); } else ip->ip_len -= hlen;#ifdef FORWARD_BROADCASTS if ((m->m_flags & M_BCAST) && (proxyBroadcastHook != NULL)) (* proxyBroadcastHook) (m, m->m_pkthdr.rcvif);#endif if (_func_ipsecInput != NULL) { /* Deliver the packet to ipsec for further processing/filtering. */ if (_func_ipsecInput (&m, hlen, &ip) == ERROR) { goto done; } } /* * Switch out to protocol's input routine. */#ifdef WV_INSTRUMENTATION#ifdef INCLUDE_WVNET /* WV_NET_NOTICE event */ WV_NET_ADDRIN_EVENT_2 (NET_CORE_EVENT, WV_NET_NOTICE, 10, 14, ip->ip_src.s_addr, ip->ip_dst.s_addr, WV_NETEVENT_IPIN_FINISH, WV_NET_RECV, ip->ip_src.s_addr, ip->ip_dst.s_addr)#endif /* INCLUDE_WVNET */#endif#ifdef VIRTUAL_STACK _ipstat.ips_delivered++;#else ipstat.ips_delivered++;#endif /* VIRTUAL_STACK */ (*inetsw[ip_protox[ip->ip_p]].pr_input) (m, hlen); splx (s); return;bad: m_freem(m);done: splx (s); return; }/********************************************************************************* ipReAssemble - reassemble ip fragments** This function reassembles the ip fragments and returns the pointer to the* mbuf chain if reassembly is complete orelse returns null.** RETURNS: pMbuf/NULL** SEE ALSO: ,** NOMANUAL*/LOCAL struct mbuf * ipReAssemble ( FAST struct mbuf * pMbuf, /* pointer to mbuf chain fragment */ FAST struct ipq * pIpFragQueue /* pointer to ip fragment queue */ ) { FAST struct mbuf ** pPtrMbuf; /* pointer to ptr to mbuf */ FAST struct mbuf * pMbPktFrag = NULL; /* pointer to the packet */ FAST struct ip * pIpHdr; /* pointer to ip header */ FAST struct ipasfrag * pIpHdrFrag = NULL; /* ipfragment header */ FAST int len; FAST struct mbuf * pMbufTmp; /* pointer to mbuf */ pIpHdr = mtod (pMbuf, struct ip *); pMbuf->m_nextpkt = NULL; /* * If first fragment to arrive, create a reassembly queue. */ if (pIpFragQueue == 0) { if ((pMbufTmp = mBufClGet (M_DONTWAIT, MT_FTABLE, sizeof(struct ipq), TRUE)) == NULL) goto dropFrag; pIpFragQueue = mtod(pMbufTmp, struct ipq *);#ifdef VIRTUAL_STACK insque(pIpFragQueue, &_ipq);#else insque(pIpFragQueue, &ipq);#endif pIpFragQueue->ipq_ttl = ipfragttl; /* configuration parameter */ pIpFragQueue->ipq_p = pIpHdr->ip_p; pIpFragQueue->ipq_id = pIpHdr->ip_id; pIpFragQueue->ipq_src = ((struct ip *)pIpHdr)->ip_src; pIpFragQueue->ipq_dst = ((struct ip *)pIpHdr)->ip_dst; pIpFragQueue->pMbufHdr = pMbufTmp; /* back pointer to mbuf */ pIpFragQueue->pMbufPkt = pMbuf; /* first fragment received */ goto ipChkReAssembly; } for (pPtrMbuf = &(pIpFragQueue->pMbufPkt); *pPtrMbuf != NULL; pPtrMbuf = &(*pPtrMbuf)->m_nextpkt) { pMbPktFrag = *pPtrMbuf; pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); if ((USHORT)pIpHdr->ip_off > (USHORT)pIpHdrFrag->ip_off) { if ((len = (signed int)((USHORT)pIpHdrFrag->ip_off + pIpHdrFrag->ip_len - (USHORT)pIpHdr->ip_off)) > 0) { if (len >= pIpHdr->ip_len) goto dropFrag; /* drop the fragment */ pIpHdrFrag->ip_len -= len; m_adj(pMbPktFrag, -len); /* trim from the tail */ } if (pMbPktFrag->m_nextpkt == NULL) { /* this is the likely case most of the time */ pMbPktFrag->m_nextpkt = pMbuf; /* insert the fragment */ pMbuf->m_nextpkt = NULL; break; } } else /* if pIpHdr->ip_off <= pIpHdrFrag->ip_off */ { /* if complete overlap */ while (((USHORT)pIpHdr->ip_off + pIpHdr->ip_len) >= ((USHORT)pIpHdrFrag->ip_off + pIpHdrFrag->ip_len)) { *pPtrMbuf = (*pPtrMbuf)->m_nextpkt; pMbPktFrag->m_nextpkt = NULL; m_freem (pMbPktFrag); /* drop the fragment */ pMbPktFrag = *pPtrMbuf; if (pMbPktFrag == NULL) break; pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); } /* if partial overlap trim my data at the end*/ if ((pMbPktFrag != NULL) && ((len = (((USHORT) pIpHdr->ip_off + pIpHdr->ip_len) - (USHORT) pIpHdrFrag->ip_off)) > 0)) { pIpHdr->ip_len -= len; m_adj (pMbuf, -len); /* trim from the tail */ } pMbuf->m_nextpkt = pMbPktFrag; *pPtrMbuf = pMbuf; /* insert the current fragment */ break; } } ipChkReAssembly: len = 0; for (pMbPktFrag = pIpFragQueue->pMbufPkt; pMbPktFrag != NULL; pMbPktFrag = pMbPktFrag->m_nextpkt) { pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); if ((USHORT)pIpHdrFrag->ip_off != len) return (NULL); len += pIpHdrFrag->ip_len; } if (pIpHdrFrag->ipf_mff & 1) /* last fragment's mff bit still set */ return (NULL); /* reassemble and concatenate all fragments */ pMbuf = pIpFragQueue->pMbufPkt; pMbufTmp = pMbuf->m_nextpkt; pMbuf->m_nextpkt = NULL; while (pMbufTmp != NULL) { pMbPktFrag = pMbufTmp; pIpHdrFrag = mtod(pMbPktFrag, struct ipasfrag *); pMbPktFrag->m_data += pIpHdrFrag->ip_hl << 2; /* remove the header */ pMbPktFrag->m_len -= pIpHdrFrag->ip_hl << 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -