Exemplo n.º 1
0
/*
 * Handle MRT getsockopt commands
 */
int
ip6_mrouter_get(struct socket *so, struct sockopt *sopt)
{
	int error = 0;

	if (so != ip6_mrouter) return EACCES;

	switch (sopt->sopt_name) {
		case MRT6_PIM:
			soopt_from_kbuf(sopt, &pim6, sizeof(pim6));
			break;
	}
	return (error);
}
Exemplo n.º 2
0
/*
 * The new sockopt interface makes it possible for us to block in the
 * copyin/out step (if we take a page fault).  Taking a page fault while
 * in a critical section is probably a Bad Thing.  (Since sockets and pcbs
 * both now use TSM, there probably isn't any need for this function to 
 * run in a critical section any more.  This needs more examination.)
 */
void
tcp_ctloutput(netmsg_t msg)
{
	struct socket *so = msg->base.nm_so;
	struct sockopt *sopt = msg->ctloutput.nm_sopt;
	int	error, opt, optval;
	struct	inpcb *inp;
	struct	tcpcb *tp;

	error = 0;
	inp = so->so_pcb;
	if (inp == NULL) {
		error = ECONNRESET;
		goto done;
	}

	if (sopt->sopt_level != IPPROTO_TCP) {
#ifdef INET6
		if (INP_CHECK_SOCKAF(so, AF_INET6))
			ip6_ctloutput_dispatch(msg);
		else
#endif /* INET6 */
		ip_ctloutput(msg);
		/* msg invalid now */
		return;
	}
	tp = intotcpcb(inp);

	switch (sopt->sopt_dir) {
	case SOPT_SET:
		error = soopt_to_kbuf(sopt, &optval, sizeof optval,
				      sizeof optval);
		if (error)
			break;
		switch (sopt->sopt_name) {
		case TCP_FASTKEEP:
			if (optval > 0) {
				if ((tp->t_flags & TF_FASTKEEP) == 0) {
					tp->t_flags |= TF_FASTKEEP;
					tcp_timer_keep_activity(tp, 0);
				}
			} else {
				tp->t_flags &= ~TF_FASTKEEP;
			}
			break;
#ifdef TCP_SIGNATURE
		case TCP_SIGNATURE_ENABLE:
			if (optval > 0)
				tp->t_flags |= TF_SIGNATURE;
			else
				tp->t_flags &= ~TF_SIGNATURE;
			break;
#endif /* TCP_SIGNATURE */
		case TCP_NODELAY:
		case TCP_NOOPT:
			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;
			break;

		case TCP_NOPUSH:
			if (optval)
				tp->t_flags |= TF_NOPUSH;
			else {
				tp->t_flags &= ~TF_NOPUSH;
				error = tcp_output(tp);
			}
			break;

		case TCP_MAXSEG:
			/*
			 * Must be between 0 and maxseg.  If the requested
			 * maxseg is too small to satisfy the desired minmss,
			 * pump it up (silently so sysctl modifications of
			 * minmss do not create unexpected program failures).
			 * Handle degenerate cases.
			 */
			if (optval > 0 && optval <= tp->t_maxseg) {
				if (optval + 40 < tcp_minmss) {
					optval = tcp_minmss - 40;
					if (optval < 0)
						optval = 1;
				}
				tp->t_maxseg = optval;
			} else {
				error = EINVAL;
			}
			break;

		default:
			error = ENOPROTOOPT;
			break;
		}
		break;

	case SOPT_GET:
		switch (sopt->sopt_name) {
#ifdef TCP_SIGNATURE
		case TCP_SIGNATURE_ENABLE:
			optval = (tp->t_flags & TF_SIGNATURE) ? 1 : 0;
			break;
#endif /* TCP_SIGNATURE */
		case TCP_NODELAY:
			optval = tp->t_flags & TF_NODELAY;
			break;
		case TCP_MAXSEG:
			optval = tp->t_maxseg;
			break;
		case TCP_NOOPT:
			optval = tp->t_flags & TF_NOOPT;
			break;
		case TCP_NOPUSH:
			optval = tp->t_flags & TF_NOPUSH;
			break;
		default:
			error = ENOPROTOOPT;
			break;
		}
		if (error == 0)
			soopt_from_kbuf(sopt, &optval, sizeof optval);
		break;
	}
done:
	lwkt_replymsg(&msg->lmsg, error);
}