summaryrefslogtreecommitdiff
path: root/sys/kern/uipc_socket.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/uipc_socket.c')
-rw-r--r--sys/kern/uipc_socket.c44
1 files changed, 30 insertions, 14 deletions
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 58d78fbd5d4..7d497af7426 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uipc_socket.c,v 1.238 2019/12/31 13:48:32 visa Exp $ */
+/* $OpenBSD: uipc_socket.c,v 1.239 2020/01/15 13:17:35 mpi Exp $ */
/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
/*
@@ -155,6 +155,8 @@ socreate(int dom, struct socket **aso, int type, int proto)
so->so_egid = p->p_ucred->cr_gid;
so->so_cpid = p->p_p->ps_pid;
so->so_proto = prp;
+ so->so_snd.sb_timeo_nsecs = INFSLP;
+ so->so_rcv.sb_timeo_nsecs = INFSLP;
s = solock(so);
error = (*prp->pr_attach)(so, proto);
@@ -265,6 +267,15 @@ sofree(struct socket *so, int s)
}
}
+static inline uint64_t
+solinger_nsec(struct socket *so)
+{
+ if (so->so_linger == 0)
+ return INFSLP;
+
+ return SEC_TO_NSEC(so->so_linger);
+}
+
/*
* Close a socket on last file table reference removal.
* Initiate disconnect if connected.
@@ -302,9 +313,9 @@ soclose(struct socket *so, int flags)
(flags & MSG_DONTWAIT))
goto drop;
while (so->so_state & SS_ISCONNECTED) {
- error = sosleep(so, &so->so_timeo,
+ error = sosleep_nsec(so, &so->so_timeo,
PSOCK | PCATCH, "netcls",
- so->so_linger * hz);
+ solinger_nsec(so));
if (error)
break;
}
@@ -1113,6 +1124,7 @@ sorflush(struct socket *so)
aso.so_rcv = *sb;
memset(&sb->sb_startzero, 0,
(caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero);
+ sb->sb_timeo_nsecs = INFSLP;
if (pr->pr_flags & PR_RIGHTS && pr->pr_domain->dom_dispose)
(*pr->pr_domain->dom_dispose)(aso.so_rcv.sb_mb);
sbrelease(&aso, &aso.so_rcv);
@@ -1761,22 +1773,25 @@ sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
case SO_RCVTIMEO:
{
struct timeval tv;
- int val;
+ uint64_t nsecs;
if (m == NULL || m->m_len < sizeof (tv))
return (EINVAL);
memcpy(&tv, mtod(m, struct timeval *), sizeof tv);
- val = tvtohz(&tv);
- if (val > USHRT_MAX)
+ if (!timerisvalid(&tv))
+ return (EINVAL);
+ nsecs = TIMEVAL_TO_NSEC(&tv);
+ if (nsecs == UINT64_MAX)
return (EDOM);
-
+ if (nsecs == 0)
+ nsecs = INFSLP;
switch (optname) {
case SO_SNDTIMEO:
- so->so_snd.sb_timeo = val;
+ so->so_snd.sb_timeo_nsecs = nsecs;
break;
case SO_RCVTIMEO:
- so->so_rcv.sb_timeo = val;
+ so->so_rcv.sb_timeo_nsecs = nsecs;
break;
}
break;
@@ -1910,13 +1925,14 @@ sogetopt(struct socket *so, int level, int optname, struct mbuf *m)
case SO_RCVTIMEO:
{
struct timeval tv;
- int val = (optname == SO_SNDTIMEO ?
- so->so_snd.sb_timeo : so->so_rcv.sb_timeo);
+ uint64_t nsecs = (optname == SO_SNDTIMEO ?
+ so->so_snd.sb_timeo_nsecs :
+ so->so_rcv.sb_timeo_nsecs);
m->m_len = sizeof(struct timeval);
memset(&tv, 0, sizeof(tv));
- tv.tv_sec = val / hz;
- tv.tv_usec = (val % hz) * tick;
+ if (nsecs != INFSLP)
+ NSEC_TO_TIMEVAL(nsecs, &tv);
memcpy(mtod(m, struct timeval *), &tv, sizeof tv);
break;
}
@@ -2129,7 +2145,7 @@ sobuf_print(struct sockbuf *sb,
(*pr)("\tsb_sel: ...\n");
(*pr)("\tsb_flagsintr: %d\n", sb->sb_flagsintr);
(*pr)("\tsb_flags: %i\n", sb->sb_flags);
- (*pr)("\tsb_timeo: %i\n", sb->sb_timeo);
+ (*pr)("\tsb_timeo_nsecs: %llu\n", sb->sb_timeo_nsecs);
}
void