* Generate IPv6 header and pass packet to ip6_output. Tack on options user * may have setup with control call. */
| 389 | * may have setup with control call. |
| 390 | */ |
| 391 | int |
| 392 | rip6_output(struct mbuf *m, struct socket *so, ...) |
| 393 | { |
| 394 | struct epoch_tracker et; |
| 395 | struct mbuf *control; |
| 396 | struct m_tag *mtag; |
| 397 | struct sockaddr_in6 *dstsock; |
| 398 | struct ip6_hdr *ip6; |
| 399 | struct inpcb *inp; |
| 400 | u_int plen = m->m_pkthdr.len; |
| 401 | int error = 0; |
| 402 | struct ip6_pktopts opt, *optp; |
| 403 | struct ifnet *oifp = NULL; |
| 404 | int type = 0, code = 0; /* for ICMPv6 output statistics only */ |
| 405 | int scope_ambiguous = 0; |
| 406 | int use_defzone = 0; |
| 407 | int hlim = 0; |
| 408 | struct in6_addr in6a; |
| 409 | va_list ap; |
| 410 | |
| 411 | va_start(ap, so); |
| 412 | dstsock = va_arg(ap, struct sockaddr_in6 *); |
| 413 | control = va_arg(ap, struct mbuf *); |
| 414 | va_end(ap); |
| 415 | |
| 416 | inp = sotoinpcb(so); |
| 417 | INP_WLOCK(inp); |
| 418 | |
| 419 | if (control != NULL) { |
| 420 | if ((error = ip6_setpktopts(control, &opt, |
| 421 | inp->in6p_outputopts, so->so_cred, |
| 422 | so->so_proto->pr_protocol)) != 0) { |
| 423 | goto bad; |
| 424 | } |
| 425 | optp = &opt; |
| 426 | } else |
| 427 | optp = inp->in6p_outputopts; |
| 428 | |
| 429 | /* |
| 430 | * Check and convert scope zone ID into internal form. |
| 431 | * |
| 432 | * XXX: we may still need to determine the zone later. |
| 433 | */ |
| 434 | if (!(so->so_state & SS_ISCONNECTED)) { |
| 435 | if (!optp || !optp->ip6po_pktinfo || |
| 436 | !optp->ip6po_pktinfo->ipi6_ifindex) |
| 437 | use_defzone = V_ip6_use_defzone; |
| 438 | if (dstsock->sin6_scope_id == 0 && !use_defzone) |
| 439 | scope_ambiguous = 1; |
| 440 | if ((error = sa6_embedscope(dstsock, use_defzone)) != 0) |
| 441 | goto bad; |
| 442 | } |
| 443 | |
| 444 | /* |
| 445 | * For an ICMPv6 packet, we should know its type and code to update |
| 446 | * statistics. |
| 447 | */ |
| 448 | if (so->so_proto->pr_protocol == IPPROTO_ICMPV6) { |
no test coverage detected