/* * 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); }
/* * 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); }