version 1.183, 2009/01/15 15:29:10 |
version 1.201, 2010/10/14 03:07:51 |
|
|
/* $NetBSD$ */ |
/* $NetBSD$ */ |
|
|
/*- |
/*- |
* Copyright (c) 2002, 2007, 2008 The NetBSD Foundation, Inc. |
* Copyright (c) 2002, 2007, 2008, 2009 The NetBSD Foundation, Inc. |
* All rights reserved. |
* All rights reserved. |
* |
* |
* This code is derived from software contributed to The NetBSD Foundation |
* This code is derived from software contributed to The NetBSD Foundation |
* by Jason R. Thorpe of Wasabi Systems, Inc. |
* by Jason R. Thorpe of Wasabi Systems, Inc, and by Andrew Doran. |
* |
* |
* Redistribution and use in source and binary forms, with or without |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* modification, are permitted provided that the following conditions |
Line 95 __KERNEL_RCSID(0, "$NetBSD$"); |
|
Line 95 __KERNEL_RCSID(0, "$NetBSD$"); |
|
|
|
#ifdef COMPAT_50 |
#ifdef COMPAT_50 |
#include <compat/sys/time.h> |
#include <compat/sys/time.h> |
#define SO_OSNDTIMEO 0x1005 |
#include <compat/sys/socket.h> |
#define SO_ORCVTIMEO 0x1006 |
|
#endif |
#endif |
|
|
#include <uvm/uvm.h> |
#include <uvm/uvm.h> |
Line 152 int somaxkva = SOMAXKVA; |
|
Line 151 int somaxkva = SOMAXKVA; |
|
static int socurkva; |
static int socurkva; |
static kcondvar_t socurkva_cv; |
static kcondvar_t socurkva_cv; |
|
|
|
static kauth_listener_t socket_listener; |
|
|
#define SOCK_LOAN_CHUNK 65536 |
#define SOCK_LOAN_CHUNK 65536 |
|
|
static size_t sodopendfree(void); |
static size_t sodopendfree(void); |
Line 385 sosend_loan(struct socket *so, struct ui |
|
Line 386 sosend_loan(struct socket *so, struct ui |
|
|
|
for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE) |
for (i = 0, va = lva; i < npgs; i++, va += PAGE_SIZE) |
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]), |
pmap_kenter_pa(va, VM_PAGE_TO_PHYS(m->m_ext.ext_pgs[i]), |
VM_PROT_READ); |
VM_PROT_READ, 0); |
pmap_update(pmap_kernel()); |
pmap_update(pmap_kernel()); |
|
|
lva += (vaddr_t) iov->iov_base & PAGE_MASK; |
lva += (vaddr_t) iov->iov_base & PAGE_MASK; |
Line 429 getsombuf(struct socket *so, int type) |
|
Line 430 getsombuf(struct socket *so, int type) |
|
return m; |
return m; |
} |
} |
|
|
|
static int |
|
socket_listener_cb(kauth_cred_t cred, kauth_action_t action, void *cookie, |
|
void *arg0, void *arg1, void *arg2, void *arg3) |
|
{ |
|
int result; |
|
enum kauth_network_req req; |
|
|
|
result = KAUTH_RESULT_DEFER; |
|
req = (enum kauth_network_req)arg0; |
|
|
|
if ((action != KAUTH_NETWORK_SOCKET) && |
|
(action != KAUTH_NETWORK_BIND)) |
|
return result; |
|
|
|
switch (req) { |
|
case KAUTH_REQ_NETWORK_BIND_PORT: |
|
result = KAUTH_RESULT_ALLOW; |
|
break; |
|
|
|
case KAUTH_REQ_NETWORK_SOCKET_DROP: { |
|
/* Normal users can only drop their own connections. */ |
|
struct socket *so = (struct socket *)arg1; |
|
|
|
if (proc_uidmatch(cred, so->so_cred)) |
|
result = KAUTH_RESULT_ALLOW; |
|
|
|
break; |
|
} |
|
|
|
case KAUTH_REQ_NETWORK_SOCKET_OPEN: |
|
/* We allow "raw" routing/bluetooth sockets to anyone. */ |
|
if ((u_long)arg1 == PF_ROUTE || (u_long)arg1 == PF_BLUETOOTH) |
|
result = KAUTH_RESULT_ALLOW; |
|
else { |
|
/* Privileged, let secmodel handle this. */ |
|
if ((u_long)arg2 == SOCK_RAW) |
|
break; |
|
} |
|
|
|
result = KAUTH_RESULT_ALLOW; |
|
|
|
break; |
|
|
|
case KAUTH_REQ_NETWORK_SOCKET_CANSEE: |
|
result = KAUTH_RESULT_ALLOW; |
|
|
|
break; |
|
|
|
default: |
|
break; |
|
} |
|
|
|
return result; |
|
} |
|
|
void |
void |
soinit(void) |
soinit(void) |
{ |
{ |
|
|
|
|
callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback, |
callback_register(&vm_map_to_kernel(kernel_map)->vmk_reclaim_callback, |
&sokva_reclaimerentry, NULL, sokva_reclaim_callback); |
&sokva_reclaimerentry, NULL, sokva_reclaim_callback); |
|
|
|
socket_listener = kauth_listen_scope(KAUTH_SCOPE_NETWORK, |
|
socket_listener_cb, NULL); |
} |
} |
|
|
/* |
/* |
Line 502 socreate(int dom, struct socket **aso, i |
|
Line 561 socreate(int dom, struct socket **aso, i |
|
#endif |
#endif |
uid = kauth_cred_geteuid(l->l_cred); |
uid = kauth_cred_geteuid(l->l_cred); |
so->so_uidinfo = uid_find(uid); |
so->so_uidinfo = uid_find(uid); |
so->so_egid = kauth_cred_getegid(l->l_cred); |
|
so->so_cpid = l->l_proc->p_pid; |
so->so_cpid = l->l_proc->p_pid; |
if (lockso != NULL) { |
if (lockso != NULL) { |
/* Caller wants us to share a lock. */ |
/* Caller wants us to share a lock. */ |
Line 521 socreate(int dom, struct socket **aso, i |
|
Line 579 socreate(int dom, struct socket **aso, i |
|
sofree(so); |
sofree(so); |
return error; |
return error; |
} |
} |
|
so->so_cred = kauth_cred_dup(l->l_cred); |
sounlock(so); |
sounlock(so); |
*aso = so; |
*aso = so; |
return 0; |
return 0; |
Line 556 fsocreate(int domain, struct socket **so |
|
Line 615 fsocreate(int domain, struct socket **so |
|
} |
} |
|
|
int |
int |
|
sofamily(const struct socket *so) |
|
{ |
|
const struct protosw *pr; |
|
const struct domain *dom; |
|
|
|
if ((pr = so->so_proto) == NULL) |
|
return AF_UNSPEC; |
|
if ((dom = pr->pr_domain) == NULL) |
|
return AF_UNSPEC; |
|
return dom->dom_family; |
|
} |
|
|
|
int |
sobind(struct socket *so, struct mbuf *nam, struct lwp *l) |
sobind(struct socket *so, struct mbuf *nam, struct lwp *l) |
{ |
{ |
int error; |
int error; |
Line 681 soclose(struct socket *so) |
|
Line 753 soclose(struct socket *so) |
|
if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio) |
if ((so->so_state & SS_ISDISCONNECTING) && so->so_nbio) |
goto drop; |
goto drop; |
while (so->so_state & SS_ISCONNECTED) { |
while (so->so_state & SS_ISCONNECTED) { |
error = sowait(so, so->so_linger * hz); |
error = sowait(so, true, so->so_linger * hz); |
if (error) |
if (error) |
break; |
break; |
} |
} |
Line 697 soclose(struct socket *so) |
|
Line 769 soclose(struct socket *so) |
|
discard: |
discard: |
if (so->so_state & SS_NOFDREF) |
if (so->so_state & SS_NOFDREF) |
panic("soclose: NOFDREF"); |
panic("soclose: NOFDREF"); |
|
kauth_cred_free(so->so_cred); |
so->so_state |= SS_NOFDREF; |
so->so_state |= SS_NOFDREF; |
sofree(so); |
sofree(so); |
return (error); |
return (error); |
Line 829 sosend(struct socket *so, struct mbuf *a |
|
Line 902 sosend(struct socket *so, struct mbuf *a |
|
struct proc *p; |
struct proc *p; |
long space, len, resid, clen, mlen; |
long space, len, resid, clen, mlen; |
int error, s, dontroute, atomic; |
int error, s, dontroute, atomic; |
|
short wakeup_state = 0; |
|
|
p = l->l_proc; |
p = l->l_proc; |
sodopendfree(); |
sodopendfree(); |
Line 903 sosend(struct socket *so, struct mbuf *a |
|
Line 977 sosend(struct socket *so, struct mbuf *a |
|
goto release; |
goto release; |
} |
} |
sbunlock(&so->so_snd); |
sbunlock(&so->so_snd); |
|
if (wakeup_state & SS_RESTARTSYS) { |
|
error = ERESTART; |
|
goto out; |
|
} |
error = sbwait(&so->so_snd); |
error = sbwait(&so->so_snd); |
if (error) |
if (error) |
goto out; |
goto out; |
|
wakeup_state = so->so_state; |
goto restart; |
goto restart; |
} |
} |
|
wakeup_state = 0; |
mp = ⊤ |
mp = ⊤ |
space -= clen; |
space -= clen; |
do { |
do { |
Line 942 sosend(struct socket *so, struct mbuf *a |
|
Line 1022 sosend(struct socket *so, struct mbuf *a |
|
} |
} |
if (resid >= MINCLSIZE && space >= MCLBYTES) { |
if (resid >= MINCLSIZE && space >= MCLBYTES) { |
SOSEND_COUNTER_INCR(&sosend_copy_big); |
SOSEND_COUNTER_INCR(&sosend_copy_big); |
m_clget(m, M_WAIT); |
m_clget(m, M_DONTWAIT); |
if ((m->m_flags & M_EXT) == 0) |
if ((m->m_flags & M_EXT) == 0) |
goto nopages; |
goto nopages; |
mlen = MCLBYTES; |
mlen = MCLBYTES; |
Line 1083 soreceive(struct socket *so, struct mbuf |
|
Line 1163 soreceive(struct socket *so, struct mbuf |
|
struct mbuf *nextrecord; |
struct mbuf *nextrecord; |
int mbuf_removed = 0; |
int mbuf_removed = 0; |
const struct domain *dom; |
const struct domain *dom; |
|
short wakeup_state = 0; |
|
|
pr = so->so_proto; |
pr = so->so_proto; |
atomic = pr->pr_flags & PR_ATOMIC; |
atomic = pr->pr_flags & PR_ATOMIC; |
Line 1197 soreceive(struct socket *so, struct mbuf |
|
Line 1278 soreceive(struct socket *so, struct mbuf |
|
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1"); |
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1"); |
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); |
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1"); |
sbunlock(&so->so_rcv); |
sbunlock(&so->so_rcv); |
error = sbwait(&so->so_rcv); |
if (wakeup_state & SS_RESTARTSYS) |
|
error = ERESTART; |
|
else |
|
error = sbwait(&so->so_rcv); |
if (error != 0) { |
if (error != 0) { |
sounlock(so); |
sounlock(so); |
splx(s); |
splx(s); |
return error; |
return error; |
} |
} |
|
wakeup_state = so->so_state; |
goto restart; |
goto restart; |
} |
} |
dontblock: |
dontblock: |
Line 1341 soreceive(struct socket *so, struct mbuf |
|
Line 1426 soreceive(struct socket *so, struct mbuf |
|
panic("receive 3"); |
panic("receive 3"); |
#endif |
#endif |
so->so_state &= ~SS_RCVATMARK; |
so->so_state &= ~SS_RCVATMARK; |
|
wakeup_state = 0; |
len = uio->uio_resid; |
len = uio->uio_resid; |
if (so->so_oobmark && len > so->so_oobmark - offset) |
if (so->so_oobmark && len > so->so_oobmark - offset) |
len = so->so_oobmark - offset; |
len = so->so_oobmark - offset; |
Line 1473 soreceive(struct socket *so, struct mbuf |
|
Line 1559 soreceive(struct socket *so, struct mbuf |
|
NULL, (struct mbuf *)(long)flags, NULL, l); |
NULL, (struct mbuf *)(long)flags, NULL, l); |
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); |
SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2"); |
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); |
SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2"); |
error = sbwait(&so->so_rcv); |
if (wakeup_state & SS_RESTARTSYS) |
|
error = ERESTART; |
|
else |
|
error = sbwait(&so->so_rcv); |
if (error != 0) { |
if (error != 0) { |
sbunlock(&so->so_rcv); |
sbunlock(&so->so_rcv); |
sounlock(so); |
sounlock(so); |
Line 1482 soreceive(struct socket *so, struct mbuf |
|
Line 1571 soreceive(struct socket *so, struct mbuf |
|
} |
} |
if ((m = so->so_rcv.sb_mb) != NULL) |
if ((m = so->so_rcv.sb_mb) != NULL) |
nextrecord = m->m_nextpkt; |
nextrecord = m->m_nextpkt; |
|
wakeup_state = so->so_state; |
} |
} |
} |
} |
|
|
Line 1549 soshutdown(struct socket *so, int how) |
|
Line 1639 soshutdown(struct socket *so, int how) |
|
} |
} |
|
|
void |
void |
|
sorestart(struct socket *so) |
|
{ |
|
/* |
|
* An application has called close() on an fd on which another |
|
* of its threads has called a socket system call. |
|
* Mark this and wake everyone up, and code that would block again |
|
* instead returns ERESTART. |
|
* On system call re-entry the fd is validated and EBADF returned. |
|
* Any other fd will block again on the 2nd syscall. |
|
*/ |
|
solock(so); |
|
so->so_state |= SS_RESTARTSYS; |
|
cv_broadcast(&so->so_cv); |
|
cv_broadcast(&so->so_snd.sb_cv); |
|
cv_broadcast(&so->so_rcv.sb_cv); |
|
sounlock(so); |
|
} |
|
|
|
void |
sorflush(struct socket *so) |
sorflush(struct socket *so) |
{ |
{ |
struct sockbuf *sb, asb; |
struct sockbuf *sb, asb; |
Line 1620 sosetopt1(struct socket *so, const struc |
|
Line 1729 sosetopt1(struct socket *so, const struc |
|
case SO_REUSEPORT: |
case SO_REUSEPORT: |
case SO_OOBINLINE: |
case SO_OOBINLINE: |
case SO_TIMESTAMP: |
case SO_TIMESTAMP: |
|
#ifdef SO_OTIMESTAMP |
|
case SO_OTIMESTAMP: |
|
#endif |
error = sockopt_getint(sopt, &optval); |
error = sockopt_getint(sopt, &optval); |
solock(so); |
solock(so); |
if (error) |
if (error) |
Line 1690 sosetopt1(struct socket *so, const struc |
|
Line 1802 sosetopt1(struct socket *so, const struc |
|
case SO_ORCVTIMEO: { |
case SO_ORCVTIMEO: { |
struct timeval50 otv; |
struct timeval50 otv; |
error = sockopt_get(sopt, &otv, sizeof(otv)); |
error = sockopt_get(sopt, &otv, sizeof(otv)); |
if (error) |
if (error) { |
|
solock(so); |
break; |
break; |
|
} |
timeval50_to_timeval(&otv, &tv); |
timeval50_to_timeval(&otv, &tv); |
opt = opt == SO_OSNDTIMEO ? SO_SNDTIMEO : SO_RCVTIMEO; |
opt = opt == SO_OSNDTIMEO ? SO_SNDTIMEO : SO_RCVTIMEO; |
error = 0; |
error = 0; |
Line 1815 sogetopt1(struct socket *so, struct sock |
|
Line 1929 sogetopt1(struct socket *so, struct sock |
|
case SO_BROADCAST: |
case SO_BROADCAST: |
case SO_OOBINLINE: |
case SO_OOBINLINE: |
case SO_TIMESTAMP: |
case SO_TIMESTAMP: |
|
#ifdef SO_OTIMESTAMP |
|
case SO_OTIMESTAMP: |
|
#endif |
error = sockopt_setint(sopt, (so->so_options & opt) ? 1 : 0); |
error = sockopt_setint(sopt, (so->so_options & opt) ? 1 : 0); |
break; |
break; |
|
|
Line 2071 sohasoutofband(struct socket *so) |
|
Line 2188 sohasoutofband(struct socket *so) |
|
{ |
{ |
|
|
fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so); |
fownsignal(so->so_pgid, SIGURG, POLL_PRI, POLLPRI|POLLRDBAND, so); |
selnotify(&so->so_rcv.sb_sel, POLLPRI | POLLRDBAND, 0); |
selnotify(&so->so_rcv.sb_sel, POLLPRI | POLLRDBAND, NOTE_SUBMIT); |
} |
} |
|
|
static void |
static void |
Line 2303 sysctl_kern_somaxkva(SYSCTLFN_ARGS) |
|
Line 2420 sysctl_kern_somaxkva(SYSCTLFN_ARGS) |
|
} |
} |
|
|
static void |
static void |
sysctl_kern_somaxkva_setup() |
sysctl_kern_somaxkva_setup(void) |
{ |
{ |
|
|
KASSERT(socket_sysctllog == NULL); |
KASSERT(socket_sysctllog == NULL); |