* Generate IP header and pass packet to ip_output. Tack on options user may * have setup with control call. */
| 446 | * have setup with control call. |
| 447 | */ |
| 448 | int |
| 449 | rip_output(struct mbuf *m, struct socket *so, ...) |
| 450 | { |
| 451 | struct epoch_tracker et; |
| 452 | struct ip *ip; |
| 453 | int error; |
| 454 | struct inpcb *inp = sotoinpcb(so); |
| 455 | va_list ap; |
| 456 | u_long dst; |
| 457 | int flags = ((so->so_options & SO_DONTROUTE) ? IP_ROUTETOIF : 0) | |
| 458 | IP_ALLOWBROADCAST; |
| 459 | int cnt, hlen; |
| 460 | u_char opttype, optlen, *cp; |
| 461 | |
| 462 | va_start(ap, so); |
| 463 | dst = va_arg(ap, u_long); |
| 464 | va_end(ap); |
| 465 | |
| 466 | /* |
| 467 | * If the user handed us a complete IP packet, use it. Otherwise, |
| 468 | * allocate an mbuf for a header and fill it in. |
| 469 | */ |
| 470 | if ((inp->inp_flags & INP_HDRINCL) == 0) { |
| 471 | if (m->m_pkthdr.len + sizeof(struct ip) > IP_MAXPACKET) { |
| 472 | m_freem(m); |
| 473 | return(EMSGSIZE); |
| 474 | } |
| 475 | M_PREPEND(m, sizeof(struct ip), M_NOWAIT); |
| 476 | if (m == NULL) |
| 477 | return(ENOBUFS); |
| 478 | |
| 479 | INP_RLOCK(inp); |
| 480 | ip = mtod(m, struct ip *); |
| 481 | ip->ip_tos = inp->inp_ip_tos; |
| 482 | if (inp->inp_flags & INP_DONTFRAG) |
| 483 | ip->ip_off = htons(IP_DF); |
| 484 | else |
| 485 | ip->ip_off = htons(0); |
| 486 | ip->ip_p = inp->inp_ip_p; |
| 487 | ip->ip_len = htons(m->m_pkthdr.len); |
| 488 | ip->ip_src = inp->inp_laddr; |
| 489 | ip->ip_dst.s_addr = dst; |
| 490 | #ifdef ROUTE_MPATH |
| 491 | if (CALC_FLOWID_OUTBOUND) { |
| 492 | uint32_t hash_type, hash_val; |
| 493 | |
| 494 | hash_val = fib4_calc_software_hash(ip->ip_src, |
| 495 | ip->ip_dst, 0, 0, ip->ip_p, &hash_type); |
| 496 | m->m_pkthdr.flowid = hash_val; |
| 497 | M_HASHTYPE_SET(m, hash_type); |
| 498 | flags |= IP_NODEFAULTFLOWID; |
| 499 | } |
| 500 | #endif |
| 501 | if (jailed(inp->inp_cred)) { |
| 502 | /* |
| 503 | * prison_local_ip4() would be good enough but would |
| 504 | * let a source of INADDR_ANY pass, which we do not |
| 505 | * want to see from jails. |
no test coverage detected