FreeBSD/sys/netinet/in_mcast.c
/*
 * Return the IP multicast options in response to user getsockopt().
 */
Return the IP multicast options in response to user getsockopt().
Return the IP multicast options in response to user getsockopt () .
int
inp_getmoptions(struct inpcb *inp, struct sockopt *sopt)
{
	struct rm_priotracker	 in_ifa_tracker;
	struct ip_mreqn		 mreqn;
	struct ip_moptions	*imo;
	struct ifnet		*ifp;
	struct in_ifaddr	*ia;
	int			 error, optval;
	u_char			 coptval;
	INP_WLOCK(inp);
	imo = inp->inp_moptions;
	if (inp->inp_socket->so_proto->pr_protocol == IPPROTO_DIVERT ||
	    (inp->inp_socket->so_proto->pr_type != SOCK_RAW &&
	    inp->inp_socket->so_proto->pr_type != SOCK_DGRAM)) {
		INP_WUNLOCK(inp);
		return (EOPNOTSUPP);
	}
	error = 0;
	switch (sopt->sopt_name) {
	case IP_MULTICAST_VIF:
		if (imo != NULL)
			optval = imo->imo_multicast_vif;
		else
			optval = -1;
		INP_WUNLOCK(inp);
		error = sooptcopyout(sopt, &optval, sizeof(int));
		break;
	case IP_MULTICAST_IF:
		memset(&mreqn, 0, sizeof(struct ip_mreqn));
		if (imo != NULL) {
			ifp = imo->imo_multicast_ifp;
			if (!in_nullhost(imo->imo_multicast_addr)) {
				mreqn.imr_address = imo->imo_multicast_addr;
			} else if (ifp != NULL) {
				mreqn.imr_ifindex = ifp->if_index;
				IFP_TO_IA(ifp, ia, &in_ifa_tracker);
				if (ia != NULL) {
					mreqn.imr_address =
					    IA_SIN(ia)->sin_addr;
					ifa_free(&ia->ia_ifa);
				}
			}
		}
		INP_WUNLOCK(inp);
		if (sopt->sopt_valsize == sizeof(struct ip_mreqn)) {
			error = sooptcopyout(sopt, &mreqn,
			    sizeof(struct ip_mreqn));
		} else {
			error = sooptcopyout(sopt, &mreqn.imr_address,
			    sizeof(struct in_addr));
		}
		break;
	case IP_MULTICAST_TTL:
		if (imo == NULL)
			optval = coptval = IP_DEFAULT_MULTICAST_TTL;
		else
			optval = coptval = imo->imo_multicast_ttl;
		INP_WUNLOCK(inp);
		if (sopt->sopt_valsize == sizeof(u_char))
			error = sooptcopyout(sopt, &coptval, sizeof(u_char));
		else
			error = sooptcopyout(sopt, &optval, sizeof(int));
		break;
	case IP_MULTICAST_LOOP:
		if (imo == NULL)
			optval = coptval = IP_DEFAULT_MULTICAST_LOOP;
		else
			optval = coptval = imo->imo_multicast_loop;
		INP_WUNLOCK(inp);
		if (sopt->sopt_valsize == sizeof(u_char))
			error = sooptcopyout(sopt, &coptval, sizeof(u_char));
		else
			error = sooptcopyout(sopt, &optval, sizeof(int));
		break;
	case IP_MSFILTER:
		if (imo == NULL) {
			error = EADDRNOTAVAIL;
			INP_WUNLOCK(inp);
		} else {
			error = inp_get_source_filters(inp, sopt);
		}
		break;
	default:
		INP_WUNLOCK(inp);
		error = ENOPROTOOPT;
		break;
	}
	INP_UNLOCK_ASSERT(inp);
	return (error);
}
int inp_getmoptions ( struct inpcb * inp , struct sockopt * sopt ) { struct rm_priotracker in_ifa_tracker ; struct ip_mreqn mreqn ; struct ip_moptions * imo ; struct ifnet * ifp ; struct in_ifaddr * ia ; int error , optval ; u_char coptval ; INP_WLOCK ( inp ) ; imo = inp -> inp_moptions ; if ( inp -> inp_socket -> so_proto -> pr_protocol == IPPROTO_DIVERT || ( inp -> inp_socket -> so_proto -> pr_type != SOCK_RAW && inp -> inp_socket -> so_proto -> pr_type != SOCK_DGRAM ) ) { INP_WUNLOCK ( inp ) ; return ( EOPNOTSUPP ) ; } error = 0 ; switch ( sopt -> sopt_name ) { case IP_MULTICAST_VIF : if ( imo != NULL ) optval = imo -> imo_multicast_vif ; else optval = -1 ; INP_WUNLOCK ( inp ) ; error = sooptcopyout ( sopt , & optval , sizeof ( int ) ) ; break ; case IP_MULTICAST_IF : memset ( & mreqn , 0 , sizeof ( struct ip_mreqn ) ) ; if ( imo != NULL ) { ifp = imo -> imo_multicast_ifp ; if ( ! in_nullhost ( imo -> imo_multicast_addr ) ) { mreqn . imr_address = imo -> imo_multicast_addr ; } else if ( ifp != NULL ) { mreqn . imr_ifindex = ifp -> if_index ; IFP_TO_IA ( ifp , ia , & in_ifa_tracker ) ; if ( ia != NULL ) { mreqn . imr_address = IA_SIN ( ia ) -> sin_addr ; ifa_free ( & ia -> ia_ifa ) ; } } } INP_WUNLOCK ( inp ) ; if ( sopt -> sopt_valsize == sizeof ( struct ip_mreqn ) ) { error = sooptcopyout ( sopt , & mreqn , sizeof ( struct ip_mreqn ) ) ; } else { error = sooptcopyout ( sopt , & mreqn . imr_address , sizeof ( struct in_addr ) ) ; } break ; case IP_MULTICAST_TTL : if ( imo == NULL ) optval = coptval = IP_DEFAULT_MULTICAST_TTL ; else optval = coptval = imo -> imo_multicast_ttl ; INP_WUNLOCK ( inp ) ; if ( sopt -> sopt_valsize == sizeof ( u_char ) ) error = sooptcopyout ( sopt , & coptval , sizeof ( u_char ) ) ; else error = sooptcopyout ( sopt , & optval , sizeof ( int ) ) ; break ; case IP_MULTICAST_LOOP : if ( imo == NULL ) optval = coptval = IP_DEFAULT_MULTICAST_LOOP ; else optval = coptval = imo -> imo_multicast_loop ; INP_WUNLOCK ( inp ) ; if ( sopt -> sopt_valsize == sizeof ( u_char ) ) error = sooptcopyout ( sopt , & coptval , sizeof ( u_char ) ) ; else error = sooptcopyout ( sopt , & optval , sizeof ( int ) ) ; break ; case IP_MSFILTER : if ( imo == NULL ) { error = EADDRNOTAVAIL ; INP_WUNLOCK ( inp ) ; } else { error = inp_get_source_filters ( inp , sopt ) ; } break ; default : INP_WUNLOCK ( inp ) ; error = ENOPROTOOPT ; break ; } INP_UNLOCK_ASSERT ( inp ) ; return ( error ) ; }
Return the IP multicast options in response to user getsockopt().
Return the IP multicast options in response to user getsockopt () .
/*
	 * If socket is neither of type SOCK_RAW or SOCK_DGRAM,
	 * or is a divert socket, reject it.
	 */