| 405 | } |
| 406 | |
| 407 | static int |
| 408 | stf_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, |
| 409 | struct route *ro) |
| 410 | { |
| 411 | struct stf_softc *sc; |
| 412 | const struct sockaddr_in6 *dst6; |
| 413 | struct in_addr in4; |
| 414 | const void *ptr; |
| 415 | u_int8_t tos; |
| 416 | struct ip *ip; |
| 417 | struct ip6_hdr *ip6; |
| 418 | struct in6_addr addr6, mask6; |
| 419 | int error; |
| 420 | |
| 421 | #ifdef MAC |
| 422 | error = mac_ifnet_check_transmit(ifp, m); |
| 423 | if (error) { |
| 424 | m_freem(m); |
| 425 | return (error); |
| 426 | } |
| 427 | #endif |
| 428 | |
| 429 | sc = ifp->if_softc; |
| 430 | dst6 = (const struct sockaddr_in6 *)dst; |
| 431 | |
| 432 | /* just in case */ |
| 433 | if ((ifp->if_flags & IFF_UP) == 0) { |
| 434 | m_freem(m); |
| 435 | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); |
| 436 | return ENETDOWN; |
| 437 | } |
| 438 | |
| 439 | /* |
| 440 | * If we don't have an ip4 address that match my inner ip6 address, |
| 441 | * we shouldn't generate output. Without this check, we'll end up |
| 442 | * using wrong IPv4 source. |
| 443 | */ |
| 444 | if (stf_getsrcifa6(ifp, &addr6, &mask6) != 0) { |
| 445 | m_freem(m); |
| 446 | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); |
| 447 | return ENETDOWN; |
| 448 | } |
| 449 | |
| 450 | if (m->m_len < sizeof(*ip6)) { |
| 451 | m = m_pullup(m, sizeof(*ip6)); |
| 452 | if (!m) { |
| 453 | if_inc_counter(ifp, IFCOUNTER_OERRORS, 1); |
| 454 | return ENOBUFS; |
| 455 | } |
| 456 | } |
| 457 | ip6 = mtod(m, struct ip6_hdr *); |
| 458 | tos = (ntohl(ip6->ip6_flow) >> 20) & 0xff; |
| 459 | |
| 460 | /* |
| 461 | * Pickup the right outer dst addr from the list of candidates. |
| 462 | * ip6_dst has priority as it may be able to give us shorter IPv4 hops. |
| 463 | */ |
| 464 | ptr = NULL; |
nothing calls this directly
no test coverage detected