* 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
| 316 | * inserted, so must have a NULL opt pointer. |
| 317 | */ |
| 318 | int |
| 319 | ip_output(struct mbuf *m, struct mbuf *opt, struct route *ro, int flags, |
| 320 | struct ip_moptions *imo, struct inpcb *inp) |
| 321 | { |
| 322 | struct rm_priotracker in_ifa_tracker; |
| 323 | struct ip *ip; |
| 324 | struct ifnet *ifp = NULL; /* keep compiler happy */ |
| 325 | struct mbuf *m0; |
| 326 | int hlen = sizeof (struct ip); |
| 327 | int mtu = 0; |
| 328 | int error = 0; |
| 329 | int vlan_pcp = -1; |
| 330 | struct sockaddr_in *dst, sin; |
| 331 | const struct sockaddr_in *gw; |
| 332 | struct in_ifaddr *ia = NULL; |
| 333 | struct in_addr src; |
| 334 | int isbroadcast; |
| 335 | uint16_t ip_len, ip_off; |
| 336 | uint32_t fibnum; |
| 337 | #if defined(IPSEC) || defined(IPSEC_SUPPORT) |
| 338 | int no_route_but_check_spd = 0; |
| 339 | #endif |
| 340 | |
| 341 | M_ASSERTPKTHDR(m); |
| 342 | NET_EPOCH_ASSERT(); |
| 343 | |
| 344 | if (inp != NULL) { |
| 345 | INP_LOCK_ASSERT(inp); |
| 346 | M_SETFIB(m, inp->inp_inc.inc_fibnum); |
| 347 | if ((flags & IP_NODEFAULTFLOWID) == 0) { |
| 348 | m->m_pkthdr.flowid = inp->inp_flowid; |
| 349 | M_HASHTYPE_SET(m, inp->inp_flowtype); |
| 350 | } |
| 351 | if ((inp->inp_flags2 & INP_2PCP_SET) != 0) |
| 352 | vlan_pcp = (inp->inp_flags2 & INP_2PCP_MASK) >> |
| 353 | INP_2PCP_SHIFT; |
| 354 | #ifdef NUMA |
| 355 | m->m_pkthdr.numa_domain = inp->inp_numa_domain; |
| 356 | #endif |
| 357 | } |
| 358 | |
| 359 | if (opt) { |
| 360 | int len = 0; |
| 361 | m = ip_insertoptions(m, opt, &len); |
| 362 | if (len != 0) |
| 363 | hlen = len; /* ip->ip_hl is updated above */ |
| 364 | } |
| 365 | ip = mtod(m, struct ip *); |
| 366 | ip_len = ntohs(ip->ip_len); |
| 367 | ip_off = ntohs(ip->ip_off); |
| 368 | |
| 369 | if ((flags & (IP_FORWARDING|IP_RAWOUTPUT)) == 0) { |
| 370 | ip->ip_v = IPVERSION; |
| 371 | ip->ip_hl = hlen >> 2; |
| 372 | ip_fillid(ip); |
| 373 | } else { |
| 374 | /* Header already set, fetch hlen from there */ |
| 375 | hlen = ip->ip_hl << 2; |
no test coverage detected