| 790 | } |
| 791 | |
| 792 | static int |
| 793 | rip6_connect(struct socket *so, struct sockaddr *nam, struct thread *td) |
| 794 | { |
| 795 | struct inpcb *inp; |
| 796 | struct sockaddr_in6 *addr = (struct sockaddr_in6 *)nam; |
| 797 | struct in6_addr in6a; |
| 798 | int error = 0, scope_ambiguous = 0; |
| 799 | |
| 800 | inp = sotoinpcb(so); |
| 801 | KASSERT(inp != NULL, ("rip6_connect: inp == NULL")); |
| 802 | |
| 803 | if (nam->sa_len != sizeof(*addr)) |
| 804 | return (EINVAL); |
| 805 | if (CK_STAILQ_EMPTY(&V_ifnet)) |
| 806 | return (EADDRNOTAVAIL); |
| 807 | if (addr->sin6_family != AF_INET6) |
| 808 | return (EAFNOSUPPORT); |
| 809 | |
| 810 | /* |
| 811 | * Application should provide a proper zone ID or the use of default |
| 812 | * zone IDs should be enabled. Unfortunately, some applications do |
| 813 | * not behave as it should, so we need a workaround. Even if an |
| 814 | * appropriate ID is not determined, we'll see if we can determine |
| 815 | * the outgoing interface. If we can, determine the zone ID based on |
| 816 | * the interface below. |
| 817 | */ |
| 818 | if (addr->sin6_scope_id == 0 && !V_ip6_use_defzone) |
| 819 | scope_ambiguous = 1; |
| 820 | if ((error = sa6_embedscope(addr, V_ip6_use_defzone)) != 0) |
| 821 | return (error); |
| 822 | |
| 823 | INP_INFO_WLOCK(&V_ripcbinfo); |
| 824 | INP_WLOCK(inp); |
| 825 | /* Source address selection. XXX: need pcblookup? */ |
| 826 | error = in6_selectsrc_socket(addr, inp->in6p_outputopts, |
| 827 | inp, so->so_cred, scope_ambiguous, &in6a, NULL); |
| 828 | if (error) { |
| 829 | INP_WUNLOCK(inp); |
| 830 | INP_INFO_WUNLOCK(&V_ripcbinfo); |
| 831 | return (error); |
| 832 | } |
| 833 | |
| 834 | inp->in6p_faddr = addr->sin6_addr; |
| 835 | inp->in6p_laddr = in6a; |
| 836 | soisconnected(so); |
| 837 | INP_WUNLOCK(inp); |
| 838 | INP_INFO_WUNLOCK(&V_ripcbinfo); |
| 839 | return (0); |
| 840 | } |
| 841 | |
| 842 | static int |
| 843 | rip6_shutdown(struct socket *so) |
nothing calls this directly
no test coverage detected