/* * IP output. The packet in mbuf chain m contains a skeletal IP * header (with len, off, ttl, proto, tos, src, dst). * ip_len and ip_off are in host format. * The mbuf chain containing the packet will be freed. * The mbuf opt, if present, will not be freed. * In the IP forwarding case, the packet will arrive with options already * inserted, so must have a NULL opt pointer. */ int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp) { struct ip *ip = NULL; struct ifnet *ifp = NULL; /* keep compiler happy */ struct mbuf *m0; int hlen = sizeof (struct ip); int mtu; int n; /* scratchpad */ int error = 0; int nortfree = 0; struct sockaddr_in *dst; struct in_ifaddr *ia = NULL; int isbroadcast, sw_csum; struct route iproute; struct rtentry *rte; /* cache for ro->ro_rt */ struct in_addr odst; #ifdef IPFIREWALL_FORWARD struct m_tag *fwd_tag = NULL; #endif #ifdef IPSEC int no_route_but_check_spd = 0; #endif #ifdef PROMISCUOUS_INET struct ifl2info *l2i_tag = NULL; int ispromisc = 0; #endif M_ASSERTPKTHDR(m); if (inp != NULL) { INP_LOCK_ASSERT(inp); M_SETFIB(m, inp->inp_inc.inc_fibnum); if (inp->inp_flags & (INP_HW_FLOWID|INP_SW_FLOWID)) { m->m_pkthdr.flowid = inp->inp_flowid; m->m_flags |= M_FLOWID; } } #ifdef PROMISCUOUS_INET l2i_tag = (struct ifl2info *)m_tag_locate(m, MTAG_PROMISCINET, MTAG_PROMISCINET_L2INFO, NULL); if ((inp && (inp->inp_flags2 & INP_PROMISC)) || l2i_tag) { unsigned int fib; if (l2i_tag) { /* * This is a packet that has been turned around * after reception, such as a TCP SYN packet being * recycled as a RST, so fib comes from the mbuf, * not the (probably nonexistent) connection * context. */ fib = M_GETFIB(m); } else { fib = inp->inp_fibnum; if (0 != if_promiscinet_add_tag(m, inp->inp_l2info)) { goto bad; } } ifp = ifnet_byfib_ref(fib); if (NULL == ifp) { IPSTAT_INC(ips_noroute); error = EHOSTUNREACH; goto bad; } isbroadcast = 0; ispromisc = 1; } #endif /* PROMISCUOUS_INET */ if (ro == NULL) { ro = &iproute; bzero(ro, sizeof (*ro)); #ifdef FLOWTABLE { struct flentry *fle; /* * The flow table returns route entries valid for up to 30 * seconds; we rely on the remainder of ip_output() taking no * longer than that long for the stability of ro_rt. The * flow ID assignment must have happened before this point. */ if ((fle = flowtable_lookup_mbuf(V_ip_ft, m, AF_INET)) != NULL) { flow_to_route(fle, ro); nortfree = 1; } } #endif } if (opt) { int len = 0; m = ip_insertoptions(m, opt, &len); if (len != 0) hlen = len; /* ip->ip_hl is updated above */ } ip = mtod(m, struct ip *); /* * Fill in IP header. If we are not allowing fragmentation, * then the ip_id field is meaningless, but we don't set it * to zero. Doing so causes various problems when devices along * the path (routers, load balancers, firewalls, etc.) illegally * disable DF on our packet. Note that a 16-bit counter * will wrap around in less than 10 seconds at 100 Mbit/s on a * medium with MTU 1500. See Steven M. Bellovin, "A Technique * for Counting NATted Hosts", Proc. IMW'02, available at * <http://www.cs.columbia.edu/~smb/papers/fnat.pdf>. */ if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { ip->ip_v = IPVERSION; ip->ip_hl = hlen >> 2; ip->ip_id = ip_newid(); IPSTAT_INC(ips_localout); } else {
/* * 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. * If route ro is present and has ro_rt initialized, route lookup would be * skipped and ro->ro_rt would be used. If ro is present but ro->ro_rt is NULL, * then result of route lookup is stored in ro->ro_rt. * * In the IP forwarding case, the packet will arrive with options already * inserted, so must have a NULL opt pointer. */ int ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, struct ip_moptions *imo, struct inpcb *inp) { struct ip *ip; struct ifnet *ifp = NULL; /* keep compiler happy */ struct mbuf *m0; int hlen = sizeof (struct ip); int mtu; int n; /* scratchpad */ int error = 0; struct sockaddr_in *dst; struct in_ifaddr *ia; int isbroadcast; uint16_t ip_len, ip_off; struct route iproute; struct rtentry *rte; /* cache for ro->ro_rt */ struct in_addr odst; struct m_tag *fwd_tag = NULL; #ifdef IPSEC int no_route_but_check_spd = 0; #endif M_ASSERTPKTHDR(m); if (inp != NULL) { INP_LOCK_ASSERT(inp); M_SETFIB(m, inp->inp_inc.inc_fibnum); if (inp->inp_flags & (INP_HW_FLOWID|INP_SW_FLOWID)) { m->m_pkthdr.flowid = inp->inp_flowid; m->m_flags |= M_FLOWID; } } if (ro == NULL) { ro = &iproute; bzero(ro, sizeof (*ro)); } #ifdef FLOWTABLE if (ro->ro_rt == NULL) { struct flentry *fle; /* * The flow table returns route entries valid for up to 30 * seconds; we rely on the remainder of ip_output() taking no * longer than that long for the stability of ro_rt. The * flow ID assignment must have happened before this point. */ fle = flowtable_lookup_mbuf(V_ip_ft, m, AF_INET); if (fle != NULL) flow_to_route(fle, ro); } #endif if (opt) { int len = 0; m = ip_insertoptions(m, opt, &len); if (len != 0) hlen = len; /* ip->ip_hl is updated above */ } ip = mtod(m, struct ip *); ip_len = ntohs(ip->ip_len); ip_off = ntohs(ip->ip_off); /* * Fill in IP header. If we are not allowing fragmentation, * then the ip_id field is meaningless, but we don't set it * to zero. Doing so causes various problems when devices along * the path (routers, load balancers, firewalls, etc.) illegally * disable DF on our packet. Note that a 16-bit counter * will wrap around in less than 10 seconds at 100 Mbit/s on a * medium with MTU 1500. See Steven M. Bellovin, "A Technique * for Counting NATted Hosts", Proc. IMW'02, available at * <http://www.cs.columbia.edu/~smb/papers/fnat.pdf>. */ if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { ip->ip_v = IPVERSION; ip->ip_hl = hlen >> 2; ip->ip_id = ip_newid(); IPSTAT_INC(ips_localout); } else {