/* * Ip input routine. Checksum and byte swap header. If fragmented * try to reassemble. Process options. Pass to next level. */ void ip_input(struct mbuf *m) { struct ip *ip = NULL; struct in_ifaddr *ia; struct ifaddr *ifa; int hlen = 0, len; int downmatch; int checkif; int srcrt = 0; MCLAIM(m, &ip_rx_mowner); KASSERT((m->m_flags & M_PKTHDR) != 0); /* * If no IP addresses have been set yet but the interfaces * are receiving, can't do anything with incoming packets yet. */ if (TAILQ_FIRST(&in_ifaddrhead) == 0) goto bad; IP_STATINC(IP_STAT_TOTAL); /* * If the IP header is not aligned, slurp it up into a new * mbuf with space for link headers, in the event we forward * it. Otherwise, if it is aligned, make sure the entire * base IP header is in the first mbuf of the chain. */ if (IP_HDR_ALIGNED_P(mtod(m, void *)) == 0) { if ((m = m_copyup(m, sizeof(struct ip), (max_linkhdr + 3) & ~3)) == NULL) { /* XXXJRT new stat, please */ IP_STATINC(IP_STAT_TOOSMALL); return; } } else if (__predict_false(m->m_len < sizeof (struct ip))) {
/* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. */ int ip_output(struct mbuf *m0, ...) { struct rtentry *rt; struct ip *ip; struct ifnet *ifp; struct mbuf *m = m0; int hlen = sizeof (struct ip); int len, error = 0; struct route iproute; const struct sockaddr_in *dst; struct in_ifaddr *ia; struct ifaddr *xifa; struct mbuf *opt; struct route *ro; int flags, sw_csum; u_long mtu; struct ip_moptions *imo; struct socket *so; va_list ap; struct secpolicy *sp = NULL; bool natt_frag = false; bool __unused done = false; union { struct sockaddr dst; struct sockaddr_in dst4; } u; struct sockaddr *rdst = &u.dst; /* real IP destination, as opposed * to the nexthop */ len = 0; va_start(ap, m0); opt = va_arg(ap, struct mbuf *); ro = va_arg(ap, struct route *); flags = va_arg(ap, int); imo = va_arg(ap, struct ip_moptions *); so = va_arg(ap, struct socket *); va_end(ap); MCLAIM(m, &ip_tx_mowner); KASSERT((m->m_flags & M_PKTHDR) != 0); KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_TCPv6|M_CSUM_UDPv6)) == 0); KASSERT((m->m_pkthdr.csum_flags & (M_CSUM_TCPv4|M_CSUM_UDPv4)) != (M_CSUM_TCPv4|M_CSUM_UDPv4)); if (opt) { m = ip_insertoptions(m, opt, &len); if (len >= sizeof(struct ip)) hlen = len; } ip = mtod(m, struct ip *); /* * Fill in IP header. */ if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { ip->ip_v = IPVERSION; ip->ip_off = htons(0); /* ip->ip_id filled in after we find out source ia */ ip->ip_hl = hlen >> 2; IP_STATINC(IP_STAT_LOCALOUT); } else {