예제 #1
0
int
do_getopt_accept_filter(struct socket *so, struct sockopt *sopt)
{
	struct accept_filter_arg *afap;
	int error;

	error = 0;
	afap = malloc(sizeof(*afap), M_TEMP,
	    M_WAITOK | M_ZERO);
	SOCK_LOCK(so);
	if ((so->so_options & SO_ACCEPTCONN) == 0) {
		error = EINVAL;
		goto out;
	}
	if ((so->so_options & SO_ACCEPTFILTER) == 0) {
		error = EINVAL;
		goto out;
	}
	strcpy(afap->af_name, so->so_accf->so_accept_filter->accf_name);
	if (so->so_accf->so_accept_filter_str != NULL)
		strcpy(afap->af_arg, so->so_accf->so_accept_filter_str);
out:
	SOCK_UNLOCK(so);
	if (error == 0)
		error = sooptcopyout(sopt, afap, sizeof(*afap));
	free(afap, M_TEMP);
	return (error);
}
예제 #2
0
/*
 * Handle MRT getsockopt commands
 */
int
X_ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
{
	int error = 0;

	if (so != V_ip6_mrouter)
		return (EACCES);

	switch (sopt->sopt_name) {
		case MRT6_PIM:
			error = sooptcopyout(sopt, &V_pim6, sizeof(V_pim6));
			break;
	}
	return (error);
}
예제 #3
0
static int
tcp_ipsec_pcbctl(struct inpcb *inp, struct sockopt *sopt)
{
	struct tcpcb *tp;
	int error, optval;

	INP_WLOCK_ASSERT(inp);
	if (sopt->sopt_name != TCP_MD5SIG) {
		INP_WUNLOCK(inp);
		return (ENOPROTOOPT);
	}

	tp = intotcpcb(inp);
	if (sopt->sopt_dir == SOPT_GET) {
		optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
		INP_WUNLOCK(inp);

		/* On success return with released INP_WLOCK */
		return (sooptcopyout(sopt, &optval, sizeof(optval)));
	}

	INP_WUNLOCK(inp);

	error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
	if (error != 0)
		return (error);

	/* INP_WLOCK_RECHECK */
	INP_WLOCK(inp);
	if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
		INP_WUNLOCK(inp);
		return (ECONNRESET);
	}
	if (optval > 0)
		tp->t_flags |= TF_SIGNATURE;
	else
		tp->t_flags &= ~TF_SIGNATURE;

	/* On success return with acquired INP_WLOCK */
	return (error);
}
예제 #4
0
/*
 * Handle UDP_ENCAP socket option. Always return with released INP_WLOCK.
 */
int
udp_ipsec_pcbctl(struct inpcb *inp, struct sockopt *sopt)
{
	struct udpcb *up;
	int error, optval;

	INP_WLOCK_ASSERT(inp);
	if (sopt->sopt_name != UDP_ENCAP) {
		INP_WUNLOCK(inp);
		return (ENOPROTOOPT);
	}

	up = intoudpcb(inp);
	if (sopt->sopt_dir == SOPT_GET) {
		if (up->u_flags & UF_ESPINUDP)
			optval = UDP_ENCAP_ESPINUDP;
		else
			optval = 0;
		INP_WUNLOCK(inp);
		return (sooptcopyout(sopt, &optval, sizeof(optval)));
	}
	INP_WUNLOCK(inp);

	error = sooptcopyin(sopt, &optval, sizeof(optval), sizeof(optval));
	if (error != 0)
		return (error);

	INP_WLOCK(inp);
	switch (optval) {
	case 0:
		up->u_flags &= ~UF_ESPINUDP;
		break;
	case UDP_ENCAP_ESPINUDP:
		up->u_flags |= UF_ESPINUDP;
		break;
	default:
		error = EINVAL;
	}
	INP_WUNLOCK(inp);
	return (error);
}
예제 #5
0
int
tcp_ctloutput(struct socket *so, struct sockopt *sopt)
{
	int	error, opt, optval;
	struct	inpcb *inp;
	struct	tcpcb *tp;
	struct	tcp_info ti;

	error = 0;
	inp = sotoinpcb(so);
	KASSERT(inp != NULL, ("tcp_ctloutput: inp == NULL"));
	INP_WLOCK(inp);
	if (sopt->sopt_level != IPPROTO_TCP) {
#ifdef INET6
		if (inp->inp_vflag & INP_IPV6PROTO) {
			INP_WUNLOCK(inp);
			error = ip6_ctloutput(so, sopt);
		} else {
#endif /* INET6 */
			INP_WUNLOCK(inp);
			error = ip_ctloutput(so, sopt);
#ifdef INET6
		}
#endif
		return (error);
	}
	if (inp->inp_flags & (INP_TIMEWAIT | INP_DROPPED)) {
		INP_WUNLOCK(inp);
		return (ECONNRESET);
	}

	switch (sopt->sopt_dir) {
	case SOPT_SET:
		switch (sopt->sopt_name) {
#ifdef TCP_SIGNATURE
		case TCP_MD5SIG:
			INP_WUNLOCK(inp);
			error = sooptcopyin(sopt, &optval, sizeof optval,
			    sizeof optval);
			if (error)
				return (error);

			INP_WLOCK_RECHECK(inp);
			if (optval > 0)
				tp->t_flags |= TF_SIGNATURE;
			else
				tp->t_flags &= ~TF_SIGNATURE;
			INP_WUNLOCK(inp);
			break;
#endif /* TCP_SIGNATURE */
		case TCP_NODELAY:
		case TCP_NOOPT:
			INP_WUNLOCK(inp);
			error = sooptcopyin(sopt, &optval, sizeof optval,
			    sizeof optval);
			if (error)
				return (error);

			INP_WLOCK_RECHECK(inp);
			switch (sopt->sopt_name) {
			case TCP_NODELAY:
				opt = TF_NODELAY;
				break;
			case TCP_NOOPT:
				opt = TF_NOOPT;
				break;
			default:
				opt = 0; /* dead code to fool gcc */
				break;
			}

			if (optval)
				tp->t_flags |= opt;
			else
				tp->t_flags &= ~opt;
			INP_WUNLOCK(inp);
			break;

		case TCP_NOPUSH:
			INP_WUNLOCK(inp);
			error = sooptcopyin(sopt, &optval, sizeof optval,
			    sizeof optval);
			if (error)
				return (error);

			INP_WLOCK_RECHECK(inp);
			if (optval)
				tp->t_flags |= TF_NOPUSH;
			else {
				tp->t_flags &= ~TF_NOPUSH;
				error = tcp_output(tp);
			}
			INP_WUNLOCK(inp);
			break;

		case TCP_MAXSEG:
			INP_WUNLOCK(inp);
			error = sooptcopyin(sopt, &optval, sizeof optval,
			    sizeof optval);
			if (error)
				return (error);

			INP_WLOCK_RECHECK(inp);
			if (optval > 0 && optval <= tp->t_maxseg &&
			    optval + 40 >= V_tcp_minmss)
				tp->t_maxseg = optval;
			else
				error = EINVAL;
			INP_WUNLOCK(inp);
			break;

		case TCP_INFO:
			INP_WUNLOCK(inp);
			error = EINVAL;
			break;

		default:
			INP_WUNLOCK(inp);
			error = ENOPROTOOPT;
			break;
		}
		break;

	case SOPT_GET:
		tp = intotcpcb(inp);
		switch (sopt->sopt_name) {
#ifdef TCP_SIGNATURE
		case TCP_MD5SIG:
			optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof optval);
			break;
#endif

		case TCP_NODELAY:
			optval = tp->t_flags & TF_NODELAY;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof optval);
			break;
		case TCP_MAXSEG:
			optval = tp->t_maxseg;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof optval);
			break;
		case TCP_NOOPT:
			optval = tp->t_flags & TF_NOOPT;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof optval);
			break;
		case TCP_NOPUSH:
			optval = tp->t_flags & TF_NOPUSH;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof optval);
			break;
		case TCP_INFO:
			tcp_fill_info(tp, &ti);
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &ti, sizeof ti);
			break;
		default:
			INP_WUNLOCK(inp);
			error = ENOPROTOOPT;
			break;
		}
		break;
	}
	return (error);
}
예제 #6
0
int
udp_ctloutput(struct socket *so, struct sockopt *sopt)
{
	struct inpcb *inp;
	struct udpcb *up;
	int isudplite, error, optval;

	error = 0;
	isudplite = (so->so_proto->pr_protocol == IPPROTO_UDPLITE) ? 1 : 0;
	inp = sotoinpcb(so);
	KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
	INP_WLOCK(inp);
	if (sopt->sopt_level != so->so_proto->pr_protocol) {
#ifdef INET6
		if (INP_CHECK_SOCKAF(so, AF_INET6)) {
			INP_WUNLOCK(inp);
			error = ip6_ctloutput(so, sopt);
		}
#endif
#if defined(INET) && defined(INET6)
		else
#endif
#ifdef INET
		{
			INP_WUNLOCK(inp);
			error = ip_ctloutput(so, sopt);
		}
#endif
		return (error);
	}

	switch (sopt->sopt_dir) {
	case SOPT_SET:
		switch (sopt->sopt_name) {
		case UDP_ENCAP:
			INP_WUNLOCK(inp);
			error = sooptcopyin(sopt, &optval, sizeof optval,
					    sizeof optval);
			if (error)
				break;
			inp = sotoinpcb(so);
			KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
			INP_WLOCK(inp);
#ifdef IPSEC_NAT_T
			up = intoudpcb(inp);
			KASSERT(up != NULL, ("%s: up == NULL", __func__));
#endif
			switch (optval) {
			case 0:
				/* Clear all UDP encap. */
#ifdef IPSEC_NAT_T
				up->u_flags &= ~UF_ESPINUDP_ALL;
#endif
				break;
#ifdef IPSEC_NAT_T
			case UDP_ENCAP_ESPINUDP:
			case UDP_ENCAP_ESPINUDP_NON_IKE:
				up->u_flags &= ~UF_ESPINUDP_ALL;
				if (optval == UDP_ENCAP_ESPINUDP)
					up->u_flags |= UF_ESPINUDP;
				else if (optval == UDP_ENCAP_ESPINUDP_NON_IKE)
					up->u_flags |= UF_ESPINUDP_NON_IKE;
				break;
#endif
			default:
				error = EINVAL;
				break;
			}
			INP_WUNLOCK(inp);
			break;
		case UDPLITE_SEND_CSCOV:
		case UDPLITE_RECV_CSCOV:
			if (!isudplite) {
				INP_WUNLOCK(inp);
				error = ENOPROTOOPT;
				break;
			}
			INP_WUNLOCK(inp);
			error = sooptcopyin(sopt, &optval, sizeof(optval),
			    sizeof(optval));
			if (error != 0)
				break;
			inp = sotoinpcb(so);
			KASSERT(inp != NULL, ("%s: inp == NULL", __func__));
			INP_WLOCK(inp);
			up = intoudpcb(inp);
			KASSERT(up != NULL, ("%s: up == NULL", __func__));
			if (optval != 0 && optval < 8) {
				INP_WUNLOCK(inp);
				error = EINVAL;
				break;
			}
			if (sopt->sopt_name == UDPLITE_SEND_CSCOV)
				up->u_txcslen = optval;
			else
				up->u_rxcslen = optval;
			INP_WUNLOCK(inp);
			break;
		default:
			INP_WUNLOCK(inp);
			error = ENOPROTOOPT;
			break;
		}
		break;
	case SOPT_GET:
		switch (sopt->sopt_name) {
#ifdef IPSEC_NAT_T
		case UDP_ENCAP:
			up = intoudpcb(inp);
			KASSERT(up != NULL, ("%s: up == NULL", __func__));
			optval = up->u_flags & UF_ESPINUDP_ALL;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof optval);
			break;
#endif
		case UDPLITE_SEND_CSCOV:
		case UDPLITE_RECV_CSCOV:
			if (!isudplite) {
				INP_WUNLOCK(inp);
				error = ENOPROTOOPT;
				break;
			}
			up = intoudpcb(inp);
			KASSERT(up != NULL, ("%s: up == NULL", __func__));
			if (sopt->sopt_name == UDPLITE_SEND_CSCOV)
				optval = up->u_txcslen;
			else
				optval = up->u_rxcslen;
			INP_WUNLOCK(inp);
			error = sooptcopyout(sopt, &optval, sizeof(optval));
			break;
		default:
			INP_WUNLOCK(inp);
			error = ENOPROTOOPT;
			break;
		}
		break;
	}	
	return (error);
}
예제 #7
0
파일: l2tp_proto.c 프로젝트: TARRANUM/ppp
/* -----------------------------------------------------------------------------
This function is called by socket layer to handle get/set-socketoption
----------------------------------------------------------------------------- */
int l2tp_ctloutput(struct socket *so, struct sockopt *sopt)
{
    int		error, optval;
    u_int32_t	lval, cmd = 0;
    u_int16_t	val;
    u_char 	*addr;
		
	lck_mtx_assert(ppp_domain_mutex, LCK_MTX_ASSERT_OWNED);
    
    //IOLog("l2tp_ctloutput, so = %p\n", so);

    error = optval = 0;
    if (sopt->sopt_level != PPPPROTO_L2TP) {
        return EINVAL;
    }

    switch (sopt->sopt_dir) {
        case SOPT_SET:
            switch (sopt->sopt_name) {
                case L2TP_OPT_FLAGS:
                case L2TP_OPT_BAUDRATE:
                    if (sopt->sopt_valsize != 4)
                        error = EMSGSIZE;
                    else if ((error = sooptcopyin(sopt, &lval, 4, 4)) == 0) {
                        switch (sopt->sopt_name) {
                            case L2TP_OPT_BAUDRATE: 		cmd = L2TP_CMD_SETBAUDRATE; break;
                            case L2TP_OPT_FLAGS:			cmd = L2TP_CMD_SETFLAGS; break;
                        }
                        l2tp_rfc_command(so->so_pcb, cmd, &lval);
					}
                    break;
                case L2TP_OPT_ACCEPT:
                    if (sopt->sopt_valsize != 0)
                    	error = EMSGSIZE;
                    else
                        l2tp_rfc_command(so->so_pcb, L2TP_CMD_ACCEPT, 0);
                    break;
                case L2TP_OPT_OURADDRESS:
                case L2TP_OPT_PEERADDRESS:
                    if (sopt->sopt_valsize < sizeof(struct sockaddr))
                        error = EMSGSIZE;
                    else {
                        if ((addr = _MALLOC(sopt->sopt_valsize, M_TEMP, M_WAITOK)) == 0)
                            error = ENOMEM;
                        else {
                            if ((error = sooptcopyin(sopt, addr, sopt->sopt_valsize, sopt->sopt_valsize)) == 0)
                                error = l2tp_rfc_command(so->so_pcb, 
                                    sopt->sopt_name == L2TP_OPT_OURADDRESS ? L2TP_CMD_SETOURADDR : L2TP_CMD_SETPEERADDR,
                                    addr);
                            _FREE(addr, M_TEMP);
                        }
                    }
                    break;
                case L2TP_OPT_TUNNEL_ID:
                case L2TP_OPT_PEER_TUNNEL_ID:
                case L2TP_OPT_SESSION_ID:
                case L2TP_OPT_PEER_SESSION_ID:
                case L2TP_OPT_WINDOW:
                case L2TP_OPT_PEER_WINDOW:
                case L2TP_OPT_INITIAL_TIMEOUT:
                case L2TP_OPT_TIMEOUT_CAP:
                case L2TP_OPT_MAX_RETRIES:
                case L2TP_OPT_RELIABILITY:
                    if (sopt->sopt_valsize != 2)
                        error = EMSGSIZE;
                    else if ((error = sooptcopyin(sopt, &val, 2, 2)) == 0) {
                        switch (sopt->sopt_name) {
                            case L2TP_OPT_TUNNEL_ID: 		cmd = L2TP_CMD_SETTUNNELID; break;
                            case L2TP_OPT_PEER_TUNNEL_ID: 	cmd = L2TP_CMD_SETPEERTUNNELID; break;
                            case L2TP_OPT_SESSION_ID: 		cmd = L2TP_CMD_SETSESSIONID; break;
                            case L2TP_OPT_PEER_SESSION_ID: 	cmd = L2TP_CMD_SETPEERSESSIONID; break;
                            case L2TP_OPT_WINDOW: 		cmd = L2TP_CMD_SETWINDOW; break;
                            case L2TP_OPT_PEER_WINDOW: 		cmd = L2TP_CMD_SETPEERWINDOW; break;
                            case L2TP_OPT_INITIAL_TIMEOUT: 	cmd = L2TP_CMD_SETTIMEOUT; break;
                            case L2TP_OPT_TIMEOUT_CAP: 		cmd = L2TP_CMD_SETTIMEOUTCAP; break;
                            case L2TP_OPT_MAX_RETRIES: 		cmd = L2TP_CMD_SETMAXRETRIES; break;
                            case L2TP_OPT_RELIABILITY: 		cmd = L2TP_CMD_SETRELIABILITY; break;
                        }
                        l2tp_rfc_command(so->so_pcb, cmd, &val);
                    }
                    break;
                default:
                    error = ENOPROTOOPT;
            }
            break;

        case SOPT_GET:
            switch (sopt->sopt_name) {
                case L2TP_OPT_NEW_TUNNEL_ID:
                case L2TP_OPT_TUNNEL_ID:
                case L2TP_OPT_SESSION_ID:
                    if (sopt->sopt_valsize != 2)
                        error = EMSGSIZE;
                    else {
                        switch (sopt->sopt_name) {
                            case L2TP_OPT_NEW_TUNNEL_ID: 	cmd = L2TP_CMD_GETNEWTUNNELID; break;
                            case L2TP_OPT_TUNNEL_ID: 		cmd = L2TP_CMD_GETTUNNELID; break;
                            case L2TP_OPT_SESSION_ID: 		cmd = L2TP_CMD_GETSESSIONID; break;
                        }
                        l2tp_rfc_command(so->so_pcb, cmd, &val);
                        error = sooptcopyout(sopt, &val, 2);
                    }
                    break;
                 case L2TP_OPT_FLAGS:
                    if (sopt->sopt_valsize != 4)
                        error = EMSGSIZE;
                    else {
                        l2tp_rfc_command(so->so_pcb, L2TP_CMD_GETFLAGS, &lval);
                        error = sooptcopyout(sopt, &lval, 4);
                    }
                    break;
                case L2TP_OPT_OURADDRESS:
                case L2TP_OPT_PEERADDRESS:
                    if ((addr = _MALLOC(sopt->sopt_valsize, M_TEMP, M_WAITOK)) == 0)
                        error = ENOMEM;
                    else {
                        *addr = sopt->sopt_valsize; /* max size */
                        if ((error = l2tp_rfc_command(so->so_pcb, 
                                sopt->sopt_name == L2TP_OPT_OURADDRESS ? L2TP_CMD_GETOURADDR : L2TP_CMD_GETPEERADDR,
                                addr)) == 0) {
                            error = sooptcopyout(sopt, addr, sopt->sopt_valsize);
                            _FREE(addr, M_TEMP);
                        }
                    }
                    break;
            
                default:
                    error = ENOPROTOOPT;
                    break;
            }
            break;
    }
    return error;
}
예제 #8
0
int Lpx_USER_ctloutput( struct socket *so,
                        struct sockopt *sopt )
{
    struct lpxpcb *lpxp = sotolpxpcb(so);
    int mask, error, optval;
    short soptval;
    struct lpx ioptval;

    error = 0;
    if (lpxp == NULL)
        return (EINVAL);

    switch (sopt->sopt_dir) {
    case SOPT_GET:
        switch (sopt->sopt_name) {
        case SO_ALL_PACKETS:
            mask = LPXP_ALL_PACKETS;
            goto get_flags;

        case SO_HEADERS_ON_INPUT:
            mask = LPXP_RAWIN;
            goto get_flags;

        case SO_LPX_CHECKSUM:
            mask = LPXP_CHECKSUM;
            goto get_flags;
            
        case SO_HEADERS_ON_OUTPUT:
            mask = LPXP_RAWOUT;
        get_flags:
            soptval = lpxp->lpxp_flags & mask;
            error = sooptcopyout(sopt, &soptval, sizeof soptval);
            break;

        case SO_DEFAULT_HEADERS:
            ioptval.lpx_len = 0;
            ioptval.lpx_sum = 0;
            ioptval.lpx_tc = 0;
            ioptval.lpx_pt = lpxp->lpxp_dpt;
            ioptval.lpx_dna = lpxp->lpxp_faddr;
            ioptval.lpx_sna = lpxp->lpxp_laddr;
            error = sooptcopyout(sopt, &soptval, sizeof soptval);
            break;

        case SO_SEQNO:
            error = sooptcopyout(sopt, &lpx_pexseq, 
                         sizeof lpx_pexseq);
            lpx_pexseq++;
            break;

        default:
            error = EINVAL;
        }
        break;

    case SOPT_SET:
        switch (sopt->sopt_name) {
        case SO_ALL_PACKETS:
            mask = LPXP_ALL_PACKETS;
            goto set_head;

        case SO_HEADERS_ON_INPUT:
            mask = LPXP_RAWIN;
            goto set_head;

        case SO_LPX_CHECKSUM:
            mask = LPXP_CHECKSUM;

        case SO_HEADERS_ON_OUTPUT:
            mask = LPXP_RAWOUT;
        set_head:
            error = sooptcopyin(sopt, &optval, sizeof optval,
                        sizeof optval);
            if (error)
                break;
            if (optval)
                lpxp->lpxp_flags |= mask;
            else
                lpxp->lpxp_flags &= ~mask;
            break;

        case SO_DEFAULT_HEADERS:
            error = sooptcopyin(sopt, &ioptval, sizeof ioptval,
                        sizeof ioptval);
            if (error)
                break;
            lpxp->lpxp_dpt = ioptval.lpx_pt;
            break;
#ifdef LPXIP	/* Not supported */
        case SO_LPXIP_ROUTE:
            error = lpxip_route(so, sopt);
            break;
#endif /* LPXIP */
#ifdef IPTUNNEL
#if 0
        case SO_LPXTUNNEL_ROUTE:
            error = lpxtun_route(so, sopt);
            break;
#endif
#endif
        default:
            error = EINVAL;
        }
        break;
    }
    return (error);
}