uipc_socket.c
来自「eCos操作系统源码」· C语言 代码 · 共 1,522 行 · 第 1/3 页
C
1,522 行
error = sooptcopyin(sopt, afap, sizeof *afap, sizeof *afap); afap->af_name[sizeof(afap->af_name)-1] = '\0'; afap->af_arg[sizeof(afap->af_arg)-1] = '\0'; if (error) goto out; afp = accept_filt_get(afap->af_name); if (afp == NULL) { error = ENOENT; goto out; } MALLOC(af, struct so_accf *, sizeof(*af), M_ACCF, M_WAITOK); bzero(af, sizeof(*af)); if (afp->accf_create != NULL) { if (afap->af_name[0] != '\0') { int len = strlen(afap->af_name) + 1; MALLOC(af->so_accept_filter_str, char *, len, M_ACCF, M_WAITOK); strcpy(af->so_accept_filter_str, afap->af_name); } af->so_accept_filter_arg = afp->accf_create(so, afap->af_arg); if (af->so_accept_filter_arg == NULL) { FREE(af->so_accept_filter_str, M_ACCF); FREE(af, M_ACCF); so->so_accf = NULL; error = EINVAL; goto out; } } af->so_accept_filter = afp; so->so_accf = af; so->so_options |= SO_ACCEPTFILTER;out: if (afap != NULL) FREE(afap, M_TEMP); return (error);}#endif /* INET *//* * Perhaps this routine, and sooptcopyout(), below, ought to come in * an additional variant to handle the case where the option value needs * to be some kind of integer, but not a specific size. * In addition to their use here, these functions are also called by the * protocol-level pr_ctloutput() routines. */intsooptcopyin(sopt, buf, len, minlen) struct sockopt *sopt; void *buf; size_t len; size_t minlen;{ size_t valsize; /* * If the user gives us more than we wanted, we ignore it, * but if we don't get the minimum length the caller * wants, we return EINVAL. On success, sopt->sopt_valsize * is set to however much we actually retrieved. */ if ((valsize = sopt->sopt_valsize) < minlen) return EINVAL; if (valsize > len) sopt->sopt_valsize = valsize = len; if (sopt->sopt_p != 0) return (copyin(sopt->sopt_val, buf, valsize)); bcopy(sopt->sopt_val, buf, valsize); return 0;}intsosetopt(so, sopt) struct socket *so; struct sockopt *sopt;{ int error, optval; struct linger l; struct timeval tv; u_long val; error = 0; if (sopt->sopt_level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) return ((*so->so_proto->pr_ctloutput) (so, sopt)); error = ENOPROTOOPT; } else { switch (sopt->sopt_name) {#ifdef INET case SO_ACCEPTFILTER: error = do_setopt_accept_filter(so, sopt); if (error) goto bad; break;#endif /* INET */ case SO_LINGER: error = sooptcopyin(sopt, &l, sizeof l, sizeof l); if (error) goto bad; so->so_linger = l.l_linger; if (l.l_onoff) so->so_options |= SO_LINGER; else so->so_options &= ~SO_LINGER; break; case SO_DEBUG: case SO_KEEPALIVE: case SO_DONTROUTE: case SO_USELOOPBACK: case SO_BROADCAST: case SO_REUSEADDR: case SO_REUSEPORT: case SO_OOBINLINE: case SO_TIMESTAMP: error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) goto bad; if (optval) so->so_options |= sopt->sopt_name; else so->so_options &= ~sopt->sopt_name; break; case SO_SNDBUF: case SO_RCVBUF: case SO_SNDLOWAT: case SO_RCVLOWAT: error = sooptcopyin(sopt, &optval, sizeof optval, sizeof optval); if (error) goto bad; /* * Values < 1 make no sense for any of these * options, so disallow them. */ if (optval < 1) { error = EINVAL; goto bad; } switch (sopt->sopt_name) { case SO_SNDBUF: case SO_RCVBUF: if (sbreserve(sopt->sopt_name == SO_SNDBUF ? &so->so_snd : &so->so_rcv, (u_long)optval, so, curproc) == 0) { error = ENOBUFS; goto bad; } break; /* * Make sure the low-water is never greater than * the high-water. */ case SO_SNDLOWAT: so->so_snd.sb_lowat = (optval > so->so_snd.sb_hiwat) ? so->so_snd.sb_hiwat : optval; break; case SO_RCVLOWAT: so->so_rcv.sb_lowat = (optval > so->so_rcv.sb_hiwat) ? so->so_rcv.sb_hiwat : optval; break; } break; case SO_SNDTIMEO: case SO_RCVTIMEO: error = sooptcopyin(sopt, &tv, sizeof tv, sizeof tv); if (error) goto bad; /* assert(hz > 0); */ if (tv.tv_sec < 0 || tv.tv_sec > SHRT_MAX / hz || tv.tv_usec < 0 || tv.tv_usec >= 1000000) { error = EDOM; goto bad; } /* assert(tick > 0); */ /* assert(ULONG_MAX - SHRT_MAX >= 1000000); */ val = (u_long)(tv.tv_sec * hz) + tv.tv_usec / tick; if (val > SHRT_MAX) { error = EDOM; goto bad; } switch (sopt->sopt_name) { case SO_SNDTIMEO: so->so_snd.sb_timeo = val; break; case SO_RCVTIMEO: so->so_rcv.sb_timeo = val; break; } break; default: error = ENOPROTOOPT; break; } if (error == 0 && so->so_proto && so->so_proto->pr_ctloutput) { (void) ((*so->so_proto->pr_ctloutput) (so, sopt)); } }bad: return (error);}/* Helper routine for getsockopt */intsooptcopyout(sopt, buf, len) struct sockopt *sopt; void *buf; size_t len;{ int error; size_t valsize; error = 0; /* * Documented get behavior is that we always return a value, * possibly truncated to fit in the user's buffer. * Traditional behavior is that we always tell the user * precisely how much we copied, rather than something useful * like the total amount we had available for her. * Note that this interface is not idempotent; the entire answer must * generated ahead of time. */ valsize = min(len, sopt->sopt_valsize); sopt->sopt_valsize = valsize; if (sopt->sopt_val != 0) { if (sopt->sopt_p != 0) error = copyout(buf, sopt->sopt_val, valsize); else bcopy(buf, sopt->sopt_val, valsize); } return error;}intsogetopt(so, sopt) struct socket *so; struct sockopt *sopt;{ int error, optval; struct linger l; struct timeval tv; struct accept_filter_arg *afap; error = 0; if (sopt->sopt_level != SOL_SOCKET) { if (so->so_proto && so->so_proto->pr_ctloutput) { return ((*so->so_proto->pr_ctloutput) (so, sopt)); } else return (ENOPROTOOPT); } else { switch (sopt->sopt_name) {#ifdef INET case SO_ACCEPTFILTER: if ((so->so_options & SO_ACCEPTCONN) == 0) return (EINVAL); MALLOC(afap, struct accept_filter_arg *, sizeof(*afap), M_TEMP, M_WAITOK); bzero(afap, sizeof(*afap)); if ((so->so_options & SO_ACCEPTFILTER) != 0) { 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); } error = sooptcopyout(sopt, afap, sizeof(*afap)); FREE(afap, M_TEMP); break;#endif /* INET */ case SO_LINGER: l.l_onoff = so->so_options & SO_LINGER; l.l_linger = so->so_linger; error = sooptcopyout(sopt, &l, sizeof l); break; case SO_USELOOPBACK: case SO_DONTROUTE: case SO_DEBUG: case SO_KEEPALIVE: case SO_REUSEADDR: case SO_REUSEPORT: case SO_BROADCAST: case SO_OOBINLINE: case SO_TIMESTAMP: optval = so->so_options & sopt->sopt_name;integer: error = sooptcopyout(sopt, &optval, sizeof optval); break; case SO_TYPE: optval = so->so_type; goto integer; case SO_ERROR: optval = so->so_error; so->so_error = 0; goto integer; case SO_SNDBUF: optval = so->so_snd.sb_hiwat; goto integer; case SO_RCVBUF: optval = so->so_rcv.sb_hiwat; goto integer; case SO_SNDLOWAT: optval = so->so_snd.sb_lowat; goto integer; case SO_RCVLOWAT: optval = so->so_rcv.sb_lowat; goto integer; case SO_SNDTIMEO: case SO_RCVTIMEO: optval = (sopt->sopt_name == SO_SNDTIMEO ? so->so_snd.sb_timeo : so->so_rcv.sb_timeo); tv.tv_sec = optval / hz; tv.tv_usec = (optval % hz) * tick; error = sooptcopyout(sopt, &tv, sizeof tv); break; default: error = ENOPROTOOPT; break; } return (error); }}/* XXX; prepare mbuf for (__FreeBSD__ < 3) routines. */intsoopt_getm(struct sockopt *sopt, struct mbuf **mp){ struct mbuf *m, *m_prev; int sopt_size = sopt->sopt_valsize; MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_DATA); if (m == 0) { return ENOBUFS; } if (sopt_size > MLEN) { MCLGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_free(m); return ENOBUFS; } m->m_len = min(MCLBYTES, sopt_size); } else { m->m_len = min(MLEN, sopt_size); } sopt_size -= m->m_len; *mp = m; m_prev = m; while (sopt_size) { MGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT, MT_DATA); if (m == 0) { m_freem(*mp); return ENOBUFS; } if (sopt_size > MLEN) { MCLGET(m, sopt->sopt_p ? M_WAIT : M_DONTWAIT); if ((m->m_flags & M_EXT) == 0) { m_freem(*mp); return ENOBUFS; } m->m_len = min(MCLBYTES, sopt_size); } else { m->m_len = min(MLEN, sopt_size); } sopt_size -= m->m_len; m_prev->m_next = m; m_prev = m; } return 0;}/* XXX; copyin sopt data into mbuf chain for (__FreeBSD__ < 3) routines. */intsoopt_mcopyin(struct sockopt *sopt, struct mbuf *m){ struct mbuf *m0 = m; if (sopt->sopt_val == NULL) return 0; while (m != NULL && sopt->sopt_valsize >= m->m_len) { if (sopt->sopt_p != NULL) { int error; error = copyin(sopt->sopt_val, mtod(m, char *), m->m_len); if (error != 0) { m_freem(m0); return(error); } } else bcopy(sopt->sopt_val, mtod(m, char *), m->m_len); sopt->sopt_valsize -= m->m_len; (caddr_t)sopt->sopt_val += m->m_len; m = m->m_next; } if (m != NULL) /* should be allocated enoughly at ip6_sooptmcopyin() */ panic("ip6_sooptmcopyin"); return 0;}/* XXX; copyout mbuf chain data into soopt for (__FreeBSD__ < 3) routines. */intsoopt_mcopyout(struct sockopt *sopt, struct mbuf *m){ struct mbuf *m0 = m; size_t valsize = 0; if (sopt->sopt_val == NULL) return 0; while (m != NULL && sopt->sopt_valsize >= m->m_len) { if (sopt->sopt_p != NULL) { int error; error = copyout(mtod(m, char *), sopt->sopt_val, m->m_len); if (error != 0) { m_freem(m0); return(error); } } else bcopy(mtod(m, char *), sopt->sopt_val, m->m_len); sopt->sopt_valsize -= m->m_len; (caddr_t)sopt->sopt_val += m->m_len; valsize += m->m_len; m = m->m_next; } if (m != NULL) { /* enough soopt buffer should be given from user-land */ m_freem(m0); return(EINVAL); } sopt->sopt_valsize = valsize; return 0;}voidsohasoutofband(so) register struct socket *so;{ selwakeup(&so->so_rcv.sb_sel);}intsopoll(struct socket *so, int events, struct ucred *cred, struct proc *p){ panic("%s\n", __FUNCTION__); return 0;#if 0 // POLL int revents = 0; int s = splnet(); if (events & (POLLIN | POLLRDNORM)) if (soreadable(so)) revents |= events & (POLLIN | POLLRDNORM); if (events & (POLLOUT | POLLWRNORM)) if (sowriteable(so)) revents |= events & (POLLOUT | POLLWRNORM); if (events & (POLLPRI | POLLRDBAND)) if (so->so_oobmark || (so->so_state & SS_RCVATMARK)) revents |= events & (POLLPRI | POLLRDBAND); if (revents == 0) { if (events & (POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND)) { selrecord(p, &so->so_rcv.sb_sel); so->so_rcv.sb_flags |= SB_SEL; } if (events & (POLLOUT | POLLWRNORM)) { selrecord(p, &so->so_snd.sb_sel); so->so_snd.sb_flags |= SB_SEL; } } splx(s); return (revents);#endif // POLL}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?