* Sends mbuf @m to the wire via ip[6]_output(). * * Returns 0 on success or an errno value on failure. @m is always consumed. */
| 401 | * Returns 0 on success or an errno value on failure. @m is always consumed. |
| 402 | */ |
| 403 | static int |
| 404 | div_output_outbound(int family, struct socket *so, struct mbuf *m) |
| 405 | { |
| 406 | struct ip *const ip = mtod(m, struct ip *); |
| 407 | struct mbuf *options; |
| 408 | struct inpcb *inp; |
| 409 | int error; |
| 410 | |
| 411 | inp = sotoinpcb(so); |
| 412 | INP_RLOCK(inp); |
| 413 | switch (family) { |
| 414 | case AF_INET: |
| 415 | /* |
| 416 | * Don't allow both user specified and setsockopt |
| 417 | * options, and don't allow packet length sizes that |
| 418 | * will crash. |
| 419 | */ |
| 420 | if ((((ip->ip_hl << 2) != sizeof(struct ip)) && |
| 421 | inp->inp_options != NULL) || |
| 422 | ((u_short)ntohs(ip->ip_len) > m->m_pkthdr.len)) { |
| 423 | INP_RUNLOCK(inp); |
| 424 | m_freem(m); |
| 425 | return (EINVAL); |
| 426 | } |
| 427 | break; |
| 428 | #ifdef INET6 |
| 429 | case AF_INET6: |
| 430 | { |
| 431 | struct ip6_hdr *const ip6 = mtod(m, struct ip6_hdr *); |
| 432 | |
| 433 | /* Don't allow packet length sizes that will crash */ |
| 434 | if (((u_short)ntohs(ip6->ip6_plen) > m->m_pkthdr.len)) { |
| 435 | INP_RUNLOCK(inp); |
| 436 | m_freem(m); |
| 437 | return (EINVAL); |
| 438 | } |
| 439 | break; |
| 440 | } |
| 441 | #endif |
| 442 | } |
| 443 | |
| 444 | /* Send packet to output processing */ |
| 445 | KMOD_IPSTAT_INC(ips_rawout); /* XXX */ |
| 446 | |
| 447 | #ifdef MAC |
| 448 | mac_inpcb_create_mbuf(inp, m); |
| 449 | #endif |
| 450 | /* |
| 451 | * Get ready to inject the packet into ip_output(). |
| 452 | * Just in case socket options were specified on the |
| 453 | * divert socket, we duplicate them. This is done |
| 454 | * to avoid having to hold the PCB locks over the call |
| 455 | * to ip_output(), as doing this results in a number of |
| 456 | * lock ordering complexities. |
| 457 | * |
| 458 | * Note that we set the multicast options argument for |
| 459 | * ip_output() to NULL since it should be invariant that |
| 460 | * they are not present. |
no test coverage detected