| 854 | } |
| 855 | |
| 856 | static int |
| 857 | rip6_send(struct socket *so, int flags, struct mbuf *m, struct sockaddr *nam, |
| 858 | struct mbuf *control, struct thread *td) |
| 859 | { |
| 860 | struct inpcb *inp; |
| 861 | struct sockaddr_in6 tmp; |
| 862 | struct sockaddr_in6 *dst; |
| 863 | int ret; |
| 864 | |
| 865 | inp = sotoinpcb(so); |
| 866 | KASSERT(inp != NULL, ("rip6_send: inp == NULL")); |
| 867 | |
| 868 | /* Always copy sockaddr to avoid overwrites. */ |
| 869 | /* Unlocked read. */ |
| 870 | if (so->so_state & SS_ISCONNECTED) { |
| 871 | if (nam) { |
| 872 | m_freem(m); |
| 873 | return (EISCONN); |
| 874 | } |
| 875 | /* XXX */ |
| 876 | bzero(&tmp, sizeof(tmp)); |
| 877 | tmp.sin6_family = AF_INET6; |
| 878 | tmp.sin6_len = sizeof(struct sockaddr_in6); |
| 879 | INP_RLOCK(inp); |
| 880 | bcopy(&inp->in6p_faddr, &tmp.sin6_addr, |
| 881 | sizeof(struct in6_addr)); |
| 882 | INP_RUNLOCK(inp); |
| 883 | dst = &tmp; |
| 884 | } else { |
| 885 | if (nam == NULL) { |
| 886 | m_freem(m); |
| 887 | return (ENOTCONN); |
| 888 | } |
| 889 | if (nam->sa_len != sizeof(struct sockaddr_in6)) { |
| 890 | m_freem(m); |
| 891 | return (EINVAL); |
| 892 | } |
| 893 | tmp = *(struct sockaddr_in6 *)nam; |
| 894 | dst = &tmp; |
| 895 | |
| 896 | if (dst->sin6_family == AF_UNSPEC) { |
| 897 | /* |
| 898 | * XXX: we allow this case for backward |
| 899 | * compatibility to buggy applications that |
| 900 | * rely on old (and wrong) kernel behavior. |
| 901 | */ |
| 902 | log(LOG_INFO, "rip6 SEND: address family is " |
| 903 | "unspec. Assume AF_INET6\n"); |
| 904 | dst->sin6_family = AF_INET6; |
| 905 | } else if (dst->sin6_family != AF_INET6) { |
| 906 | m_freem(m); |
| 907 | return(EAFNOSUPPORT); |
| 908 | } |
| 909 | } |
| 910 | ret = rip6_output(m, so, dst, control); |
| 911 | return (ret); |
| 912 | } |
| 913 |
nothing calls this directly
no test coverage detected