Bug Summary

File:kern/uipc_socket.c
Warning:line 429, column 7
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name uipc_socket.c -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -ffreestanding -mcmodel=kernel -target-cpu x86-64 -target-feature +retpoline-indirect-calls -target-feature +retpoline-indirect-branches -target-feature -sse2 -target-feature -sse -target-feature -3dnow -target-feature -mmx -target-feature +save-args -disable-red-zone -no-implicit-float -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -nostdsysteminc -nobuiltininc -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/sys -I /usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -I /usr/src/sys/arch -I /usr/src/sys/dev/pci/drm/include -I /usr/src/sys/dev/pci/drm/include/uapi -I /usr/src/sys/dev/pci/drm/amd/include/asic_reg -I /usr/src/sys/dev/pci/drm/amd/include -I /usr/src/sys/dev/pci/drm/amd/amdgpu -I /usr/src/sys/dev/pci/drm/amd/display -I /usr/src/sys/dev/pci/drm/amd/display/include -I /usr/src/sys/dev/pci/drm/amd/display/dc -I /usr/src/sys/dev/pci/drm/amd/display/amdgpu_dm -I /usr/src/sys/dev/pci/drm/amd/pm/inc -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu11 -I /usr/src/sys/dev/pci/drm/amd/pm/swsmu/smu12 -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/hwmgr -I /usr/src/sys/dev/pci/drm/amd/pm/powerplay/smumgr -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc -I /usr/src/sys/dev/pci/drm/amd/display/dc/inc/hw -I /usr/src/sys/dev/pci/drm/amd/display/dc/clk_mgr -I /usr/src/sys/dev/pci/drm/amd/display/modules/inc -I /usr/src/sys/dev/pci/drm/amd/display/modules/hdcp -I /usr/src/sys/dev/pci/drm/amd/display/dmub/inc -I /usr/src/sys/dev/pci/drm/i915 -D DDB -D DIAGNOSTIC -D KTRACE -D ACCOUNTING -D KMEMSTATS -D PTRACE -D POOL_DEBUG -D CRYPTO -D SYSVMSG -D SYSVSEM -D SYSVSHM -D UVM_SWAP_ENCRYPT -D FFS -D FFS2 -D FFS_SOFTUPDATES -D UFS_DIRHASH -D QUOTA -D EXT2FS -D MFS -D NFSCLIENT -D NFSSERVER -D CD9660 -D UDF -D MSDOSFS -D FIFO -D FUSE -D SOCKET_SPLICE -D TCP_ECN -D TCP_SIGNATURE -D INET6 -D IPSEC -D PPP_BSDCOMP -D PPP_DEFLATE -D PIPEX -D MROUTING -D MPLS -D BOOT_CONFIG -D USER_PCICONF -D APERTURE -D MTRR -D NTFS -D HIBERNATE -D PCIVERBOSE -D USBVERBOSE -D WSDISPLAY_COMPAT_USL -D WSDISPLAY_COMPAT_RAWKBD -D WSDISPLAY_DEFAULTSCREENS=6 -D X86EMU -D ONEWIREVERBOSE -D MULTIPROCESSOR -D MAXUSERS=80 -D _KERNEL -D CONFIG_DRM_AMD_DC_DCN3_0 -O2 -Wno-pointer-sign -Wno-address-of-packed-member -Wno-constant-conversion -Wno-unused-but-set-variable -Wno-gnu-folding-constant -fdebug-compilation-dir=/usr/src/sys/arch/amd64/compile/GENERIC.MP/obj -ferror-limit 19 -fwrapv -D_RET_PROTECTOR -ret-protector -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -o /usr/obj/sys/arch/amd64/compile/GENERIC.MP/scan-build/2022-01-12-131800-47421-1 -x c /usr/src/sys/kern/uipc_socket.c
1/* $OpenBSD: uipc_socket.c,v 1.271 2021/12/24 06:50:16 visa Exp $ */
2/* $NetBSD: uipc_socket.c,v 1.21 1996/02/04 02:17:52 christos Exp $ */
3
4/*
5 * Copyright (c) 1982, 1986, 1988, 1990, 1993
6 * The Regents of the University of California. All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
16 * 3. Neither the name of the University nor the names of its contributors
17 * may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * @(#)uipc_socket.c 8.3 (Berkeley) 4/15/94
33 */
34
35#include <sys/param.h>
36#include <sys/systm.h>
37#include <sys/proc.h>
38#include <sys/file.h>
39#include <sys/filedesc.h>
40#include <sys/malloc.h>
41#include <sys/mbuf.h>
42#include <sys/domain.h>
43#include <sys/kernel.h>
44#include <sys/event.h>
45#include <sys/protosw.h>
46#include <sys/socket.h>
47#include <sys/unpcb.h>
48#include <sys/socketvar.h>
49#include <sys/signalvar.h>
50#include <net/if.h>
51#include <sys/pool.h>
52#include <sys/atomic.h>
53#include <sys/rwlock.h>
54#include <sys/time.h>
55
56#ifdef DDB1
57#include <machine/db_machdep.h>
58#endif
59
60void sbsync(struct sockbuf *, struct mbuf *);
61
62int sosplice(struct socket *, int, off_t, struct timeval *);
63void sounsplice(struct socket *, struct socket *, int);
64void soidle(void *);
65void sotask(void *);
66void soreaper(void *);
67void soput(void *);
68int somove(struct socket *, int);
69void sorflush(struct socket *);
70
71void filt_sordetach(struct knote *kn);
72int filt_soread(struct knote *kn, long hint);
73int filt_soreadmodify(struct kevent *kev, struct knote *kn);
74int filt_soreadprocess(struct knote *kn, struct kevent *kev);
75int filt_soread_common(struct knote *kn, struct socket *so);
76void filt_sowdetach(struct knote *kn);
77int filt_sowrite(struct knote *kn, long hint);
78int filt_sowritemodify(struct kevent *kev, struct knote *kn);
79int filt_sowriteprocess(struct knote *kn, struct kevent *kev);
80int filt_sowrite_common(struct knote *kn, struct socket *so);
81int filt_soexcept(struct knote *kn, long hint);
82int filt_soexceptmodify(struct kevent *kev, struct knote *kn);
83int filt_soexceptprocess(struct knote *kn, struct kevent *kev);
84int filt_soexcept_common(struct knote *kn, struct socket *so);
85int filt_solisten(struct knote *kn, long hint);
86int filt_solistenmodify(struct kevent *kev, struct knote *kn);
87int filt_solistenprocess(struct knote *kn, struct kevent *kev);
88int filt_solisten_common(struct knote *kn, struct socket *so);
89
90const struct filterops solisten_filtops = {
91 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
92 .f_attach = NULL((void *)0),
93 .f_detach = filt_sordetach,
94 .f_event = filt_solisten,
95 .f_modify = filt_solistenmodify,
96 .f_process = filt_solistenprocess,
97};
98
99const struct filterops soread_filtops = {
100 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
101 .f_attach = NULL((void *)0),
102 .f_detach = filt_sordetach,
103 .f_event = filt_soread,
104 .f_modify = filt_soreadmodify,
105 .f_process = filt_soreadprocess,
106};
107
108const struct filterops sowrite_filtops = {
109 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
110 .f_attach = NULL((void *)0),
111 .f_detach = filt_sowdetach,
112 .f_event = filt_sowrite,
113 .f_modify = filt_sowritemodify,
114 .f_process = filt_sowriteprocess,
115};
116
117const struct filterops soexcept_filtops = {
118 .f_flags = FILTEROP_ISFD0x00000001 | FILTEROP_MPSAFE0x00000002,
119 .f_attach = NULL((void *)0),
120 .f_detach = filt_sordetach,
121 .f_event = filt_soexcept,
122 .f_modify = filt_soexceptmodify,
123 .f_process = filt_soexceptprocess,
124};
125
126#ifndef SOMINCONN80
127#define SOMINCONN80 80
128#endif /* SOMINCONN */
129
130int somaxconn = SOMAXCONN128;
131int sominconn = SOMINCONN80;
132
133struct pool socket_pool;
134#ifdef SOCKET_SPLICE1
135struct pool sosplice_pool;
136struct taskq *sosplice_taskq;
137struct rwlock sosplice_lock = RWLOCK_INITIALIZER("sosplicelk"){ 0, "sosplicelk" };
138#endif
139
140void
141soinit(void)
142{
143 pool_init(&socket_pool, sizeof(struct socket), 0, IPL_SOFTNET0x5, 0,
144 "sockpl", NULL((void *)0));
145#ifdef SOCKET_SPLICE1
146 pool_init(&sosplice_pool, sizeof(struct sosplice), 0, IPL_SOFTNET0x5, 0,
147 "sosppl", NULL((void *)0));
148#endif
149}
150
151struct socket *
152soalloc(int prflags)
153{
154 struct socket *so;
155
156 so = pool_get(&socket_pool, prflags);
157 if (so == NULL((void *)0))
158 return (NULL((void *)0));
159 rw_init(&so->so_lock, "solock")_rw_init_flags(&so->so_lock, "solock", 0, ((void *)0));
160 return (so);
161}
162
163/*
164 * Socket operation routines.
165 * These routines are called by the routines in
166 * sys_socket.c or from a system process, and
167 * implement the semantics of socket operations by
168 * switching out to the protocol specific routines.
169 */
170int
171socreate(int dom, struct socket **aso, int type, int proto)
172{
173 struct proc *p = curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
; /* XXX */
174 const struct protosw *prp;
175 struct socket *so;
176 int error, s;
177
178 if (proto)
179 prp = pffindproto(dom, proto, type);
180 else
181 prp = pffindtype(dom, type);
182 if (prp == NULL((void *)0) || prp->pr_attach == NULL((void *)0))
183 return (EPROTONOSUPPORT43);
184 if (prp->pr_type != type)
185 return (EPROTOTYPE41);
186 so = soalloc(PR_WAITOK0x0001 | PR_ZERO0x0008);
187 klist_init(&so->so_rcv.sb_sel.si_note, &socket_klistops, so);
188 klist_init(&so->so_snd.sb_sel.si_note, &socket_klistops, so);
189 sigio_init(&so->so_sigio);
190 TAILQ_INIT(&so->so_q0)do { (&so->so_q0)->tqh_first = ((void *)0); (&so
->so_q0)->tqh_last = &(&so->so_q0)->tqh_first
; } while (0)
;
191 TAILQ_INIT(&so->so_q)do { (&so->so_q)->tqh_first = ((void *)0); (&so
->so_q)->tqh_last = &(&so->so_q)->tqh_first
; } while (0)
;
192 so->so_type = type;
193 if (suser(p) == 0)
194 so->so_state = SS_PRIV0x080;
195 so->so_ruid = p->p_ucred->cr_ruid;
196 so->so_euid = p->p_ucred->cr_uid;
197 so->so_rgid = p->p_ucred->cr_rgid;
198 so->so_egid = p->p_ucred->cr_gid;
199 so->so_cpid = p->p_p->ps_pid;
200 so->so_proto = prp;
201 so->so_snd.sb_timeo_nsecs = INFSLP0xffffffffffffffffULL;
202 so->so_rcv.sb_timeo_nsecs = INFSLP0xffffffffffffffffULL;
203
204 s = solock(so);
205 error = (*prp->pr_attach)(so, proto);
206 if (error) {
207 so->so_state |= SS_NOFDREF0x001;
208 /* sofree() calls sounlock(). */
209 sofree(so, s);
210 return (error);
211 }
212 sounlock(so, s);
213 *aso = so;
214 return (0);
215}
216
217int
218sobind(struct socket *so, struct mbuf *nam, struct proc *p)
219{
220 int error;
221
222 soassertlocked(so);
223
224 error = (*so->so_proto->pr_usrreq)(so, PRU_BIND2, NULL((void *)0), nam, NULL((void *)0), p);
225 return (error);
226}
227
228int
229solisten(struct socket *so, int backlog)
230{
231 int error;
232
233 soassertlocked(so);
234
235 if (so->so_state & (SS_ISCONNECTED0x002|SS_ISCONNECTING0x004|SS_ISDISCONNECTING0x008))
236 return (EINVAL22);
237#ifdef SOCKET_SPLICE1
238 if (isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket) || issplicedback(so)((so)->so_sp && (so)->so_sp->ssp_soback))
239 return (EOPNOTSUPP45);
240#endif /* SOCKET_SPLICE */
241 error = (*so->so_proto->pr_usrreq)(so, PRU_LISTEN3, NULL((void *)0), NULL((void *)0), NULL((void *)0),
242 curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
243 if (error)
244 return (error);
245 if (TAILQ_FIRST(&so->so_q)((&so->so_q)->tqh_first) == NULL((void *)0))
246 so->so_options |= SO_ACCEPTCONN0x0002;
247 if (backlog < 0 || backlog > somaxconn)
248 backlog = somaxconn;
249 if (backlog < sominconn)
250 backlog = sominconn;
251 so->so_qlimit = backlog;
252 return (0);
253}
254
255#define SOSP_FREEING_READ1 1
256#define SOSP_FREEING_WRITE2 2
257void
258sofree(struct socket *so, int s)
259{
260 soassertlocked(so);
261
262 if (so->so_pcb || (so->so_state & SS_NOFDREF0x001) == 0) {
263 sounlock(so, s);
264 return;
265 }
266 if (so->so_head) {
267 /*
268 * We must not decommission a socket that's on the accept(2)
269 * queue. If we do, then accept(2) may hang after select(2)
270 * indicated that the listening socket was ready.
271 */
272 if (!soqremque(so, 0)) {
273 sounlock(so, s);
274 return;
275 }
276 }
277 sigio_free(&so->so_sigio);
278 klist_free(&so->so_rcv.sb_sel.si_note);
279 klist_free(&so->so_snd.sb_sel.si_note);
280#ifdef SOCKET_SPLICE1
281 if (so->so_sp) {
282 if (issplicedback(so)((so)->so_sp && (so)->so_sp->ssp_soback)) {
283 int freeing = SOSP_FREEING_WRITE2;
284
285 if (so->so_sp->ssp_soback == so)
286 freeing |= SOSP_FREEING_READ1;
287 sounsplice(so->so_sp->ssp_soback, so, freeing);
288 }
289 if (isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket)) {
290 int freeing = SOSP_FREEING_READ1;
291
292 if (so == so->so_sp->ssp_socket)
293 freeing |= SOSP_FREEING_WRITE2;
294 sounsplice(so, so->so_sp->ssp_socket, freeing);
295 }
296 }
297#endif /* SOCKET_SPLICE */
298 sbrelease(so, &so->so_snd);
299 sorflush(so);
300 sounlock(so, s);
301#ifdef SOCKET_SPLICE1
302 if (so->so_sp) {
303 /* Reuse splice idle, sounsplice() has been called before. */
304 timeout_set_proc(&so->so_sp->ssp_idleto, soreaper, so);
305 timeout_add(&so->so_sp->ssp_idleto, 0);
306 } else
307#endif /* SOCKET_SPLICE */
308 {
309 pool_put(&socket_pool, so);
310 }
311}
312
313static inline uint64_t
314solinger_nsec(struct socket *so)
315{
316 if (so->so_linger == 0)
317 return INFSLP0xffffffffffffffffULL;
318
319 return SEC_TO_NSEC(so->so_linger);
320}
321
322/*
323 * Close a socket on last file table reference removal.
324 * Initiate disconnect if connected.
325 * Free socket when disconnect complete.
326 */
327int
328soclose(struct socket *so, int flags)
329{
330 struct socket *so2;
331 int s, error = 0;
332
333 s = solock(so);
334 /* Revoke async IO early. There is a final revocation in sofree(). */
335 sigio_free(&so->so_sigio);
336 if (so->so_state & SS_ISCONNECTED0x002) {
337 if (so->so_pcb == NULL((void *)0))
338 goto discard;
339 if ((so->so_state & SS_ISDISCONNECTING0x008) == 0) {
340 error = sodisconnect(so);
341 if (error)
342 goto drop;
343 }
344 if (so->so_options & SO_LINGER0x0080) {
345 if ((so->so_state & SS_ISDISCONNECTING0x008) &&
346 (flags & MSG_DONTWAIT0x80))
347 goto drop;
348 while (so->so_state & SS_ISCONNECTED0x002) {
349 error = sosleep_nsec(so, &so->so_timeo,
350 PSOCK24 | PCATCH0x100, "netcls",
351 solinger_nsec(so));
352 if (error)
353 break;
354 }
355 }
356 }
357drop:
358 if (so->so_pcb) {
359 int error2;
360 KASSERT(so->so_proto->pr_detach)((so->so_proto->pr_detach) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/kern/uipc_socket.c", 360, "so->so_proto->pr_detach"
))
;
361 error2 = (*so->so_proto->pr_detach)(so);
362 if (error == 0)
363 error = error2;
364 }
365 if (so->so_options & SO_ACCEPTCONN0x0002) {
366 while ((so2 = TAILQ_FIRST(&so->so_q0)((&so->so_q0)->tqh_first)) != NULL((void *)0)) {
367 (void) soqremque(so2, 0);
368 (void) soabort(so2);
369 }
370 while ((so2 = TAILQ_FIRST(&so->so_q)((&so->so_q)->tqh_first)) != NULL((void *)0)) {
371 (void) soqremque(so2, 1);
372 (void) soabort(so2);
373 }
374 }
375discard:
376 if (so->so_state & SS_NOFDREF0x001)
377 panic("soclose NOFDREF: so %p, so_type %d", so, so->so_type);
378 so->so_state |= SS_NOFDREF0x001;
379 /* sofree() calls sounlock(). */
380 sofree(so, s);
381 return (error);
382}
383
384int
385soabort(struct socket *so)
386{
387 soassertlocked(so);
388
389 return (*so->so_proto->pr_usrreq)(so, PRU_ABORT10, NULL((void *)0), NULL((void *)0), NULL((void *)0),
390 curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
391}
392
393int
394soaccept(struct socket *so, struct mbuf *nam)
395{
396 int error = 0;
397
398 soassertlocked(so);
399
400 if ((so->so_state & SS_NOFDREF0x001) == 0)
401 panic("soaccept !NOFDREF: so %p, so_type %d", so, so->so_type);
402 so->so_state &= ~SS_NOFDREF0x001;
403 if ((so->so_state & SS_ISDISCONNECTED0x800) == 0 ||
404 (so->so_proto->pr_flags & PR_ABRTACPTDIS0x20) == 0)
405 error = (*so->so_proto->pr_usrreq)(so, PRU_ACCEPT5, NULL((void *)0),
406 nam, NULL((void *)0), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
407 else
408 error = ECONNABORTED53;
409 return (error);
410}
411
412int
413soconnect(struct socket *so, struct mbuf *nam)
414{
415 int error;
416
417 soassertlocked(so);
418
419 if (so->so_options & SO_ACCEPTCONN0x0002)
420 return (EOPNOTSUPP45);
421 /*
422 * If protocol is connection-based, can only connect once.
423 * Otherwise, if connected, try to disconnect first.
424 * This allows user to disconnect by connecting to, e.g.,
425 * a null address.
426 */
427 if (so->so_state & (SS_ISCONNECTED0x002|SS_ISCONNECTING0x004) &&
428 ((so->so_proto->pr_flags & PR_CONNREQUIRED0x04) ||
429 (error = sodisconnect(so))))
Although the value stored to 'error' is used in the enclosing expression, the value is never actually read from 'error'
430 error = EISCONN56;
431 else
432 error = (*so->so_proto->pr_usrreq)(so, PRU_CONNECT4,
433 NULL((void *)0), nam, NULL((void *)0), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
434 return (error);
435}
436
437int
438soconnect2(struct socket *so1, struct socket *so2)
439{
440 int s, error;
441
442 s = solock(so1);
443 error = (*so1->so_proto->pr_usrreq)(so1, PRU_CONNECT217, NULL((void *)0),
444 (struct mbuf *)so2, NULL((void *)0), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
445 sounlock(so1, s);
446 return (error);
447}
448
449int
450sodisconnect(struct socket *so)
451{
452 int error;
453
454 soassertlocked(so);
455
456 if ((so->so_state & SS_ISCONNECTED0x002) == 0)
457 return (ENOTCONN57);
458 if (so->so_state & SS_ISDISCONNECTING0x008)
459 return (EALREADY37);
460 error = (*so->so_proto->pr_usrreq)(so, PRU_DISCONNECT6, NULL((void *)0), NULL((void *)0),
461 NULL((void *)0), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
462 return (error);
463}
464
465int m_getuio(struct mbuf **, int, long, struct uio *);
466
467#define SBLOCKWAIT(f)(((f) & 0x80) ? 0x0002 : 0x0001) (((f) & MSG_DONTWAIT0x80) ? M_NOWAIT0x0002 : M_WAITOK0x0001)
468/*
469 * Send on a socket.
470 * If send must go all at once and message is larger than
471 * send buffering, then hard error.
472 * Lock against other senders.
473 * If must go all at once and not enough room now, then
474 * inform user that this would block and do nothing.
475 * Otherwise, if nonblocking, send as much as possible.
476 * The data to be sent is described by "uio" if nonzero,
477 * otherwise by the mbuf chain "top" (which must be null
478 * if uio is not). Data provided in mbuf chain must be small
479 * enough to send all at once.
480 *
481 * Returns nonzero on error, timeout or signal; callers
482 * must check for short counts if EINTR/ERESTART are returned.
483 * Data and control buffers are freed on return.
484 */
485int
486sosend(struct socket *so, struct mbuf *addr, struct uio *uio, struct mbuf *top,
487 struct mbuf *control, int flags)
488{
489 long space, clen = 0;
490 size_t resid;
491 int error, s;
492 int atomic = sosendallatonce(so)((so)->so_proto->pr_flags & 0x01) || top;
493
494 if (uio)
495 resid = uio->uio_resid;
496 else
497 resid = top->m_pkthdrM_dat.MH.MH_pkthdr.len;
498 /* MSG_EOR on a SOCK_STREAM socket is invalid. */
499 if (so->so_type == SOCK_STREAM1 && (flags & MSG_EOR0x8)) {
500 m_freem(top);
501 m_freem(control);
502 return (EINVAL22);
503 }
504 if (uio && uio->uio_procp)
505 uio->uio_procp->p_ru.ru_msgsnd++;
506 if (control) {
507 /*
508 * In theory clen should be unsigned (since control->m_len is).
509 * However, space must be signed, as it might be less than 0
510 * if we over-committed, and we must use a signed comparison
511 * of space and clen.
512 */
513 clen = control->m_lenm_hdr.mh_len;
514 /* reserve extra space for AF_UNIX's internalize */
515 if (so->so_proto->pr_domain->dom_family == AF_UNIX1 &&
516 clen >= CMSG_ALIGN(sizeof(struct cmsghdr))(((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1))
&&
517 mtod(control, struct cmsghdr *)((struct cmsghdr *)((control)->m_hdr.mh_data))->cmsg_type == SCM_RIGHTS0x01)
518 clen = CMSG_SPACE(((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (((unsigned long)((clen - (((unsigned
long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1)) &~(sizeof
(long) - 1))) * (sizeof(struct fdpass) / sizeof(int))) + (sizeof
(long) - 1)) &~(sizeof(long) - 1)))
519 (clen - CMSG_ALIGN(sizeof(struct cmsghdr))) *((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (((unsigned long)((clen - (((unsigned
long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1)) &~(sizeof
(long) - 1))) * (sizeof(struct fdpass) / sizeof(int))) + (sizeof
(long) - 1)) &~(sizeof(long) - 1)))
520 (sizeof(struct fdpass) / sizeof(int)))((((unsigned long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1
)) &~(sizeof(long) - 1)) + (((unsigned long)((clen - (((unsigned
long)(sizeof(struct cmsghdr)) + (sizeof(long) - 1)) &~(sizeof
(long) - 1))) * (sizeof(struct fdpass) / sizeof(int))) + (sizeof
(long) - 1)) &~(sizeof(long) - 1)))
;
521 }
522
523#define snderr(errno){ error = errno; goto release; } { error = errno; goto release; }
524
525 s = solock(so);
526restart:
527 if ((error = sblock(so, &so->so_snd, SBLOCKWAIT(flags)(((flags) & 0x80) ? 0x0002 : 0x0001))) != 0)
528 goto out;
529 so->so_state |= SS_ISSENDING0x2000;
530 do {
531 if (so->so_state & SS_CANTSENDMORE0x010)
532 snderr(EPIPE){ error = 32; goto release; };
533 if (so->so_error) {
534 error = so->so_error;
535 so->so_error = 0;
536 snderr(error){ error = error; goto release; };
537 }
538 if ((so->so_state & SS_ISCONNECTED0x002) == 0) {
539 if (so->so_proto->pr_flags & PR_CONNREQUIRED0x04) {
540 if (!(resid == 0 && clen != 0))
541 snderr(ENOTCONN){ error = 57; goto release; };
542 } else if (addr == NULL((void *)0))
543 snderr(EDESTADDRREQ){ error = 39; goto release; };
544 }
545 space = sbspace(so, &so->so_snd);
546 if (flags & MSG_OOB0x1)
547 space += 1024;
548 if (so->so_proto->pr_domain->dom_family == AF_UNIX1) {
549 if (atomic && resid > so->so_snd.sb_hiwat)
550 snderr(EMSGSIZE){ error = 40; goto release; };
551 } else {
552 if (clen > so->so_snd.sb_hiwat ||
553 (atomic && resid > so->so_snd.sb_hiwat - clen))
554 snderr(EMSGSIZE){ error = 40; goto release; };
555 }
556 if (space < clen ||
557 (space - clen < resid &&
558 (atomic || space < so->so_snd.sb_lowat))) {
559 if (flags & MSG_DONTWAIT0x80)
560 snderr(EWOULDBLOCK){ error = 35; goto release; };
561 sbunlock(so, &so->so_snd);
562 error = sbwait(so, &so->so_snd);
563 so->so_state &= ~SS_ISSENDING0x2000;
564 if (error)
565 goto out;
566 goto restart;
567 }
568 space -= clen;
569 do {
570 if (uio == NULL((void *)0)) {
571 /*
572 * Data is prepackaged in "top".
573 */
574 resid = 0;
575 if (flags & MSG_EOR0x8)
576 top->m_flagsm_hdr.mh_flags |= M_EOR0x0004;
577 } else {
578 sounlock(so, s);
579 error = m_getuio(&top, atomic, space, uio);
580 s = solock(so);
581 if (error)
582 goto release;
583 space -= top->m_pkthdrM_dat.MH.MH_pkthdr.len;
584 resid = uio->uio_resid;
585 if (flags & MSG_EOR0x8)
586 top->m_flagsm_hdr.mh_flags |= M_EOR0x0004;
587 }
588 if (resid == 0)
589 so->so_state &= ~SS_ISSENDING0x2000;
590 if (top && so->so_options & SO_ZEROIZE0x2000)
591 top->m_flagsm_hdr.mh_flags |= M_ZEROIZE0x2000;
592 error = (*so->so_proto->pr_usrreq)(so,
593 (flags & MSG_OOB0x1) ? PRU_SENDOOB14 : PRU_SEND9,
594 top, addr, control, curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
595 clen = 0;
596 control = NULL((void *)0);
597 top = NULL((void *)0);
598 if (error)
599 goto release;
600 } while (resid && space > 0);
601 } while (resid);
602
603release:
604 so->so_state &= ~SS_ISSENDING0x2000;
605 sbunlock(so, &so->so_snd);
606out:
607 sounlock(so, s);
608 m_freem(top);
609 m_freem(control);
610 return (error);
611}
612
613int
614m_getuio(struct mbuf **mp, int atomic, long space, struct uio *uio)
615{
616 struct mbuf *m, *top = NULL((void *)0);
617 struct mbuf **nextp = &top;
618 u_long len, mlen;
619 size_t resid = uio->uio_resid;
620 int error;
621
622 do {
623 if (top == NULL((void *)0)) {
624 MGETHDR(m, M_WAIT, MT_DATA)m = m_gethdr((0x0001), (1));
625 mlen = MHLEN((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr));
626 m->m_pkthdrM_dat.MH.MH_pkthdr.len = 0;
627 m->m_pkthdrM_dat.MH.MH_pkthdr.ph_ifidx = 0;
628 } else {
629 MGET(m, M_WAIT, MT_DATA)m = m_get((0x0001), (1));
630 mlen = MLEN(256 - sizeof(struct m_hdr));
631 }
632 /* chain mbuf together */
633 *nextp = m;
634 nextp = &m->m_nextm_hdr.mh_next;
635
636 resid = ulmin(resid, space);
637 if (resid >= MINCLSIZE(((256 - sizeof(struct m_hdr)) - sizeof(struct pkthdr)) + (256
- sizeof(struct m_hdr)) + 1)
) {
638 MCLGETL(m, M_NOWAIT, ulmin(resid, MAXMCLBYTES))m_clget((m), (0x0002), (ulmin(resid, (64 * 1024))));
639 if ((m->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0)
640 MCLGETL(m, M_NOWAIT, MCLBYTES)m_clget((m), (0x0002), ((1 << 11)));
641 if ((m->m_flagsm_hdr.mh_flags & M_EXT0x0001) == 0)
642 goto nopages;
643 mlen = m->m_extM_dat.MH.MH_dat.MH_ext.ext_size;
644 len = ulmin(mlen, resid);
645 /*
646 * For datagram protocols, leave room
647 * for protocol headers in first mbuf.
648 */
649 if (atomic && m == top && len < mlen - max_hdr)
650 m->m_datam_hdr.mh_data += max_hdr;
651 } else {
652nopages:
653 len = ulmin(mlen, resid);
654 /*
655 * For datagram protocols, leave room
656 * for protocol headers in first mbuf.
657 */
658 if (atomic && m == top && len < mlen - max_hdr)
659 m_align(m, len);
660 }
661
662 error = uiomove(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)), len, uio);
663 if (error) {
664 m_freem(top);
665 return (error);
666 }
667
668 /* adjust counters */
669 resid = uio->uio_resid;
670 space -= len;
671 m->m_lenm_hdr.mh_len = len;
672 top->m_pkthdrM_dat.MH.MH_pkthdr.len += len;
673
674 /* Is there more space and more data? */
675 } while (space > 0 && resid > 0);
676
677 *mp = top;
678 return 0;
679}
680
681/*
682 * Following replacement or removal of the first mbuf on the first
683 * mbuf chain of a socket buffer, push necessary state changes back
684 * into the socket buffer so that other consumers see the values
685 * consistently. 'nextrecord' is the callers locally stored value of
686 * the original value of sb->sb_mb->m_nextpkt which must be restored
687 * when the lead mbuf changes. NOTE: 'nextrecord' may be NULL.
688 */
689void
690sbsync(struct sockbuf *sb, struct mbuf *nextrecord)
691{
692
693 /*
694 * First, update for the new value of nextrecord. If necessary,
695 * make it the first record.
696 */
697 if (sb->sb_mb != NULL((void *)0))
698 sb->sb_mb->m_nextpktm_hdr.mh_nextpkt = nextrecord;
699 else
700 sb->sb_mb = nextrecord;
701
702 /*
703 * Now update any dependent socket buffer fields to reflect
704 * the new state. This is an inline of SB_EMPTY_FIXUP, with
705 * the addition of a second clause that takes care of the
706 * case where sb_mb has been updated, but remains the last
707 * record.
708 */
709 if (sb->sb_mb == NULL((void *)0)) {
710 sb->sb_mbtail = NULL((void *)0);
711 sb->sb_lastrecord = NULL((void *)0);
712 } else if (sb->sb_mb->m_nextpktm_hdr.mh_nextpkt == NULL((void *)0))
713 sb->sb_lastrecord = sb->sb_mb;
714}
715
716/*
717 * Implement receive operations on a socket.
718 * We depend on the way that records are added to the sockbuf
719 * by sbappend*. In particular, each record (mbufs linked through m_next)
720 * must begin with an address if the protocol so specifies,
721 * followed by an optional mbuf or mbufs containing ancillary data,
722 * and then zero or more mbufs of data.
723 * In order to avoid blocking network for the entire time here, we release
724 * the solock() while doing the actual copy to user space.
725 * Although the sockbuf is locked, new data may still be appended,
726 * and thus we must maintain consistency of the sockbuf during that time.
727 *
728 * The caller may receive the data as a single mbuf chain by supplying
729 * an mbuf **mp0 for use in returning the chain. The uio is then used
730 * only for the count in uio_resid.
731 */
732int
733soreceive(struct socket *so, struct mbuf **paddr, struct uio *uio,
734 struct mbuf **mp0, struct mbuf **controlp, int *flagsp,
735 socklen_t controllen)
736{
737 struct mbuf *m, **mp;
738 struct mbuf *cm;
739 u_long len, offset, moff;
740 int flags, error, s, type, uio_error = 0;
741 const struct protosw *pr = so->so_proto;
742 struct mbuf *nextrecord;
743 size_t resid, orig_resid = uio->uio_resid;
744
745 mp = mp0;
746 if (paddr)
747 *paddr = NULL((void *)0);
748 if (controlp)
749 *controlp = NULL((void *)0);
750 if (flagsp)
751 flags = *flagsp &~ MSG_EOR0x8;
752 else
753 flags = 0;
754 if (flags & MSG_OOB0x1) {
755 m = m_get(M_WAIT0x0001, MT_DATA1);
756 s = solock(so);
757 error = (*pr->pr_usrreq)(so, PRU_RCVOOB13, m,
758 (struct mbuf *)(long)(flags & MSG_PEEK0x2), NULL((void *)0), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
759 sounlock(so, s);
760 if (error)
761 goto bad;
762 do {
763 error = uiomove(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)),
764 ulmin(uio->uio_resid, m->m_lenm_hdr.mh_len), uio);
765 m = m_free(m);
766 } while (uio->uio_resid && error == 0 && m);
767bad:
768 m_freem(m);
769 return (error);
770 }
771 if (mp)
772 *mp = NULL((void *)0);
773
774 s = solock(so);
775restart:
776 if ((error = sblock(so, &so->so_rcv, SBLOCKWAIT(flags)(((flags) & 0x80) ? 0x0002 : 0x0001))) != 0) {
777 sounlock(so, s);
778 return (error);
779 }
780
781 m = so->so_rcv.sb_mb;
782#ifdef SOCKET_SPLICE1
783 if (isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket))
784 m = NULL((void *)0);
785#endif /* SOCKET_SPLICE */
786 /*
787 * If we have less data than requested, block awaiting more
788 * (subject to any timeout) if:
789 * 1. the current count is less than the low water mark,
790 * 2. MSG_WAITALL is set, and it is possible to do the entire
791 * receive operation at once if we block (resid <= hiwat), or
792 * 3. MSG_DONTWAIT is not set.
793 * If MSG_WAITALL is set but resid is larger than the receive buffer,
794 * we have to do the receive in sections, and thus risk returning
795 * a short count if a timeout or signal occurs after we start.
796 */
797 if (m == NULL((void *)0) || (((flags & MSG_DONTWAIT0x80) == 0 &&
798 so->so_rcv.sb_cc < uio->uio_resid) &&
799 (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
800 ((flags & MSG_WAITALL0x40) && uio->uio_resid <= so->so_rcv.sb_hiwat)) &&
801 m->m_nextpktm_hdr.mh_nextpkt == NULL((void *)0) && (pr->pr_flags & PR_ATOMIC0x01) == 0)) {
802#ifdef DIAGNOSTIC1
803 if (m == NULL((void *)0) && so->so_rcv.sb_cc)
804#ifdef SOCKET_SPLICE1
805 if (!isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket))
806#endif /* SOCKET_SPLICE */
807 panic("receive 1: so %p, so_type %d, sb_cc %lu",
808 so, so->so_type, so->so_rcv.sb_cc);
809#endif
810 if (so->so_error) {
811 if (m)
812 goto dontblock;
813 error = so->so_error;
814 if ((flags & MSG_PEEK0x2) == 0)
815 so->so_error = 0;
816 goto release;
817 }
818 if (so->so_state & SS_CANTRCVMORE0x020) {
819 if (m)
820 goto dontblock;
821 else if (so->so_rcv.sb_cc == 0)
822 goto release;
823 }
824 for (; m; m = m->m_nextm_hdr.mh_next)
825 if (m->m_typem_hdr.mh_type == MT_OOBDATA7 || (m->m_flagsm_hdr.mh_flags & M_EOR0x0004)) {
826 m = so->so_rcv.sb_mb;
827 goto dontblock;
828 }
829 if ((so->so_state & (SS_ISCONNECTED0x002|SS_ISCONNECTING0x004)) == 0 &&
830 (so->so_proto->pr_flags & PR_CONNREQUIRED0x04)) {
831 error = ENOTCONN57;
832 goto release;
833 }
834 if (uio->uio_resid == 0 && controlp == NULL((void *)0))
835 goto release;
836 if (flags & MSG_DONTWAIT0x80) {
837 error = EWOULDBLOCK35;
838 goto release;
839 }
840 SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 1");
841 SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 1");
842 sbunlock(so, &so->so_rcv);
843 error = sbwait(so, &so->so_rcv);
844 if (error) {
845 sounlock(so, s);
846 return (error);
847 }
848 goto restart;
849 }
850dontblock:
851 /*
852 * On entry here, m points to the first record of the socket buffer.
853 * From this point onward, we maintain 'nextrecord' as a cache of the
854 * pointer to the next record in the socket buffer. We must keep the
855 * various socket buffer pointers and local stack versions of the
856 * pointers in sync, pushing out modifications before operations that
857 * may sleep, and re-reading them afterwards.
858 *
859 * Otherwise, we will race with the network stack appending new data
860 * or records onto the socket buffer by using inconsistent/stale
861 * versions of the field, possibly resulting in socket buffer
862 * corruption.
863 */
864 if (uio->uio_procp)
865 uio->uio_procp->p_ru.ru_msgrcv++;
866 KASSERT(m == so->so_rcv.sb_mb)((m == so->so_rcv.sb_mb) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/kern/uipc_socket.c", 866, "m == so->so_rcv.sb_mb"
))
;
867 SBLASTRECORDCHK(&so->so_rcv, "soreceive 1");
868 SBLASTMBUFCHK(&so->so_rcv, "soreceive 1");
869 nextrecord = m->m_nextpktm_hdr.mh_nextpkt;
870 if (pr->pr_flags & PR_ADDR0x02) {
871#ifdef DIAGNOSTIC1
872 if (m->m_typem_hdr.mh_type != MT_SONAME3)
873 panic("receive 1a: so %p, so_type %d, m %p, m_type %d",
874 so, so->so_type, m, m->m_typem_hdr.mh_type);
875#endif
876 orig_resid = 0;
877 if (flags & MSG_PEEK0x2) {
878 if (paddr)
879 *paddr = m_copym(m, 0, m->m_lenm_hdr.mh_len, M_NOWAIT0x0002);
880 m = m->m_nextm_hdr.mh_next;
881 } else {
882 sbfree(so, &so->so_rcv, m)do { (&so->so_rcv)->sb_cc -= (m)->m_hdr.mh_len; if
((m)->m_hdr.mh_type != 6 && (m)->m_hdr.mh_type
!= 3) (&so->so_rcv)->sb_datacc -= (m)->m_hdr.mh_len
; (&so->so_rcv)->sb_mbcnt -= 256; if ((m)->m_hdr
.mh_flags & 0x0001) (&so->so_rcv)->sb_mbcnt -= (
m)->M_dat.MH.MH_dat.MH_ext.ext_size; } while ( 0)
;
883 if (paddr) {
884 *paddr = m;
885 so->so_rcv.sb_mb = m->m_nextm_hdr.mh_next;
886 m->m_nextm_hdr.mh_next = NULL((void *)0);
887 m = so->so_rcv.sb_mb;
888 } else {
889 so->so_rcv.sb_mb = m_free(m);
890 m = so->so_rcv.sb_mb;
891 }
892 sbsync(&so->so_rcv, nextrecord);
893 }
894 }
895 while (m && m->m_typem_hdr.mh_type == MT_CONTROL6 && error == 0) {
896 int skip = 0;
897 if (flags & MSG_PEEK0x2) {
898 if (mtod(m, struct cmsghdr *)((struct cmsghdr *)((m)->m_hdr.mh_data))->cmsg_type ==
899 SCM_RIGHTS0x01) {
900 /* don't leak internalized SCM_RIGHTS msgs */
901 skip = 1;
902 } else if (controlp)
903 *controlp = m_copym(m, 0, m->m_lenm_hdr.mh_len, M_NOWAIT0x0002);
904 m = m->m_nextm_hdr.mh_next;
905 } else {
906 sbfree(so, &so->so_rcv, m)do { (&so->so_rcv)->sb_cc -= (m)->m_hdr.mh_len; if
((m)->m_hdr.mh_type != 6 && (m)->m_hdr.mh_type
!= 3) (&so->so_rcv)->sb_datacc -= (m)->m_hdr.mh_len
; (&so->so_rcv)->sb_mbcnt -= 256; if ((m)->m_hdr
.mh_flags & 0x0001) (&so->so_rcv)->sb_mbcnt -= (
m)->M_dat.MH.MH_dat.MH_ext.ext_size; } while ( 0)
;
907 so->so_rcv.sb_mb = m->m_nextm_hdr.mh_next;
908 m->m_nextpktm_hdr.mh_nextpkt = m->m_nextm_hdr.mh_next = NULL((void *)0);
909 cm = m;
910 m = so->so_rcv.sb_mb;
911 sbsync(&so->so_rcv, nextrecord);
912 if (controlp) {
913 if (pr->pr_domain->dom_externalize) {
914 sounlock(so, s);
915 error =
916 (*pr->pr_domain->dom_externalize)
917 (cm, controllen, flags);
918 s = solock(so);
919 }
920 *controlp = cm;
921 } else {
922 /*
923 * Dispose of any SCM_RIGHTS message that went
924 * through the read path rather than recv.
925 */
926 if (pr->pr_domain->dom_dispose)
927 pr->pr_domain->dom_dispose(cm);
928 m_free(cm);
929 }
930 }
931 if (m != NULL((void *)0))
932 nextrecord = so->so_rcv.sb_mb->m_nextpktm_hdr.mh_nextpkt;
933 else
934 nextrecord = so->so_rcv.sb_mb;
935 if (controlp && !skip)
936 controlp = &(*controlp)->m_nextm_hdr.mh_next;
937 orig_resid = 0;
938 }
939
940 /* If m is non-NULL, we have some data to read. */
941 if (m) {
942 type = m->m_typem_hdr.mh_type;
943 if (type == MT_OOBDATA7)
944 flags |= MSG_OOB0x1;
945 if (m->m_flagsm_hdr.mh_flags & M_BCAST0x0100)
946 flags |= MSG_BCAST0x100;
947 if (m->m_flagsm_hdr.mh_flags & M_MCAST0x0200)
948 flags |= MSG_MCAST0x200;
949 }
950 SBLASTRECORDCHK(&so->so_rcv, "soreceive 2");
951 SBLASTMBUFCHK(&so->so_rcv, "soreceive 2");
952
953 moff = 0;
954 offset = 0;
955 while (m && uio->uio_resid > 0 && error == 0) {
956 if (m->m_typem_hdr.mh_type == MT_OOBDATA7) {
957 if (type != MT_OOBDATA7)
958 break;
959 } else if (type == MT_OOBDATA7) {
960 break;
961 } else if (m->m_typem_hdr.mh_type == MT_CONTROL6) {
962 /*
963 * If there is more than one control message in the
964 * stream, we do a short read. Next can be received
965 * or disposed by another system call.
966 */
967 break;
968#ifdef DIAGNOSTIC1
969 } else if (m->m_typem_hdr.mh_type != MT_DATA1 && m->m_typem_hdr.mh_type != MT_HEADER2) {
970 panic("receive 3: so %p, so_type %d, m %p, m_type %d",
971 so, so->so_type, m, m->m_typem_hdr.mh_type);
972#endif
973 }
974 so->so_state &= ~SS_RCVATMARK0x040;
975 len = uio->uio_resid;
976 if (so->so_oobmark && len > so->so_oobmark - offset)
977 len = so->so_oobmark - offset;
978 if (len > m->m_lenm_hdr.mh_len - moff)
979 len = m->m_lenm_hdr.mh_len - moff;
980 /*
981 * If mp is set, just pass back the mbufs.
982 * Otherwise copy them out via the uio, then free.
983 * Sockbuf must be consistent here (points to current mbuf,
984 * it points to next record) when we drop priority;
985 * we must note any additions to the sockbuf when we
986 * block interrupts again.
987 */
988 if (mp == NULL((void *)0) && uio_error == 0) {
989 SBLASTRECORDCHK(&so->so_rcv, "soreceive uiomove");
990 SBLASTMBUFCHK(&so->so_rcv, "soreceive uiomove");
991 resid = uio->uio_resid;
992 sounlock(so, s);
993 uio_error = uiomove(mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data)) + moff, len, uio);
994 s = solock(so);
995 if (uio_error)
996 uio->uio_resid = resid - len;
997 } else
998 uio->uio_resid -= len;
999 if (len == m->m_lenm_hdr.mh_len - moff) {
1000 if (m->m_flagsm_hdr.mh_flags & M_EOR0x0004)
1001 flags |= MSG_EOR0x8;
1002 if (flags & MSG_PEEK0x2) {
1003 m = m->m_nextm_hdr.mh_next;
1004 moff = 0;
1005 orig_resid = 0;
1006 } else {
1007 nextrecord = m->m_nextpktm_hdr.mh_nextpkt;
1008 sbfree(so, &so->so_rcv, m)do { (&so->so_rcv)->sb_cc -= (m)->m_hdr.mh_len; if
((m)->m_hdr.mh_type != 6 && (m)->m_hdr.mh_type
!= 3) (&so->so_rcv)->sb_datacc -= (m)->m_hdr.mh_len
; (&so->so_rcv)->sb_mbcnt -= 256; if ((m)->m_hdr
.mh_flags & 0x0001) (&so->so_rcv)->sb_mbcnt -= (
m)->M_dat.MH.MH_dat.MH_ext.ext_size; } while ( 0)
;
1009 if (mp) {
1010 *mp = m;
1011 mp = &m->m_nextm_hdr.mh_next;
1012 so->so_rcv.sb_mb = m = m->m_nextm_hdr.mh_next;
1013 *mp = NULL((void *)0);
1014 } else {
1015 so->so_rcv.sb_mb = m_free(m);
1016 m = so->so_rcv.sb_mb;
1017 }
1018 /*
1019 * If m != NULL, we also know that
1020 * so->so_rcv.sb_mb != NULL.
1021 */
1022 KASSERT(so->so_rcv.sb_mb == m)((so->so_rcv.sb_mb == m) ? (void)0 : __assert("diagnostic "
, "/usr/src/sys/kern/uipc_socket.c", 1022, "so->so_rcv.sb_mb == m"
))
;
1023 if (m) {
1024 m->m_nextpktm_hdr.mh_nextpkt = nextrecord;
1025 if (nextrecord == NULL((void *)0))
1026 so->so_rcv.sb_lastrecord = m;
1027 } else {
1028 so->so_rcv.sb_mb = nextrecord;
1029 SB_EMPTY_FIXUP(&so->so_rcv)do { if ((&so->so_rcv)->sb_mb == ((void *)0)) { (&
so->so_rcv)->sb_mbtail = ((void *)0); (&so->so_rcv
)->sb_lastrecord = ((void *)0); } } while ( 0)
;
1030 }
1031 SBLASTRECORDCHK(&so->so_rcv, "soreceive 3");
1032 SBLASTMBUFCHK(&so->so_rcv, "soreceive 3");
1033 }
1034 } else {
1035 if (flags & MSG_PEEK0x2) {
1036 moff += len;
1037 orig_resid = 0;
1038 } else {
1039 if (mp)
1040 *mp = m_copym(m, 0, len, M_WAIT0x0001);
1041 m->m_datam_hdr.mh_data += len;
1042 m->m_lenm_hdr.mh_len -= len;
1043 so->so_rcv.sb_cc -= len;
1044 so->so_rcv.sb_datacc -= len;
1045 }
1046 }
1047 if (so->so_oobmark) {
1048 if ((flags & MSG_PEEK0x2) == 0) {
1049 so->so_oobmark -= len;
1050 if (so->so_oobmark == 0) {
1051 so->so_state |= SS_RCVATMARK0x040;
1052 break;
1053 }
1054 } else {
1055 offset += len;
1056 if (offset == so->so_oobmark)
1057 break;
1058 }
1059 }
1060 if (flags & MSG_EOR0x8)
1061 break;
1062 /*
1063 * If the MSG_WAITALL flag is set (for non-atomic socket),
1064 * we must not quit until "uio->uio_resid == 0" or an error
1065 * termination. If a signal/timeout occurs, return
1066 * with a short count but without error.
1067 * Keep sockbuf locked against other readers.
1068 */
1069 while (flags & MSG_WAITALL0x40 && m == NULL((void *)0) && uio->uio_resid > 0 &&
1070 !sosendallatonce(so)((so)->so_proto->pr_flags & 0x01) && !nextrecord) {
1071 if (so->so_error || so->so_state & SS_CANTRCVMORE0x020)
1072 break;
1073 SBLASTRECORDCHK(&so->so_rcv, "soreceive sbwait 2");
1074 SBLASTMBUFCHK(&so->so_rcv, "soreceive sbwait 2");
1075 error = sbwait(so, &so->so_rcv);
1076 if (error) {
1077 sbunlock(so, &so->so_rcv);
1078 sounlock(so, s);
1079 return (0);
1080 }
1081 if ((m = so->so_rcv.sb_mb) != NULL((void *)0))
1082 nextrecord = m->m_nextpktm_hdr.mh_nextpkt;
1083 }
1084 }
1085
1086 if (m && pr->pr_flags & PR_ATOMIC0x01) {
1087 flags |= MSG_TRUNC0x10;
1088 if ((flags & MSG_PEEK0x2) == 0)
1089 (void) sbdroprecord(so, &so->so_rcv);
1090 }
1091 if ((flags & MSG_PEEK0x2) == 0) {
1092 if (m == NULL((void *)0)) {
1093 /*
1094 * First part is an inline SB_EMPTY_FIXUP(). Second
1095 * part makes sure sb_lastrecord is up-to-date if
1096 * there is still data in the socket buffer.
1097 */
1098 so->so_rcv.sb_mb = nextrecord;
1099 if (so->so_rcv.sb_mb == NULL((void *)0)) {
1100 so->so_rcv.sb_mbtail = NULL((void *)0);
1101 so->so_rcv.sb_lastrecord = NULL((void *)0);
1102 } else if (nextrecord->m_nextpktm_hdr.mh_nextpkt == NULL((void *)0))
1103 so->so_rcv.sb_lastrecord = nextrecord;
1104 }
1105 SBLASTRECORDCHK(&so->so_rcv, "soreceive 4");
1106 SBLASTMBUFCHK(&so->so_rcv, "soreceive 4");
1107 if (pr->pr_flags & PR_WANTRCVD0x08 && so->so_pcb)
1108 (*pr->pr_usrreq)(so, PRU_RCVD8, NULL((void *)0),
1109 (struct mbuf *)(long)flags, NULL((void *)0), curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
1110 }
1111 if (orig_resid == uio->uio_resid && orig_resid &&
1112 (flags & MSG_EOR0x8) == 0 && (so->so_state & SS_CANTRCVMORE0x020) == 0) {
1113 sbunlock(so, &so->so_rcv);
1114 goto restart;
1115 }
1116
1117 if (uio_error)
1118 error = uio_error;
1119
1120 if (flagsp)
1121 *flagsp |= flags;
1122release:
1123 sbunlock(so, &so->so_rcv);
1124 sounlock(so, s);
1125 return (error);
1126}
1127
1128int
1129soshutdown(struct socket *so, int how)
1130{
1131 const struct protosw *pr = so->so_proto;
1132 int s, error = 0;
1133
1134 s = solock(so);
1135 switch (how) {
1136 case SHUT_RD0:
1137 sorflush(so);
1138 break;
1139 case SHUT_RDWR2:
1140 sorflush(so);
1141 /* FALLTHROUGH */
1142 case SHUT_WR1:
1143 error = (*pr->pr_usrreq)(so, PRU_SHUTDOWN7, NULL((void *)0), NULL((void *)0), NULL((void *)0),
1144 curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
);
1145 break;
1146 default:
1147 error = EINVAL22;
1148 break;
1149 }
1150 sounlock(so, s);
1151
1152 return (error);
1153}
1154
1155void
1156sorflush(struct socket *so)
1157{
1158 struct sockbuf *sb = &so->so_rcv;
1159 struct mbuf *m;
1160 const struct protosw *pr = so->so_proto;
1161 int error;
1162
1163 sb->sb_flags |= SB_NOINTR0x40;
1164 error = sblock(so, sb, M_WAITOK0x0001);
1165 /* with SB_NOINTR and M_WAITOK sblock() must not fail */
1166 KASSERT(error == 0)((error == 0) ? (void)0 : __assert("diagnostic ", "/usr/src/sys/kern/uipc_socket.c"
, 1166, "error == 0"))
;
1167 socantrcvmore(so);
1168 m = sb->sb_mb;
1169 memset(&sb->sb_startzero, 0,__builtin_memset((&sb->sb_cc), (0), ((caddr_t)&sb->
sb_flags - (caddr_t)&sb->sb_cc))
1170 (caddr_t)&sb->sb_endzero - (caddr_t)&sb->sb_startzero)__builtin_memset((&sb->sb_cc), (0), ((caddr_t)&sb->
sb_flags - (caddr_t)&sb->sb_cc))
;
1171 sb->sb_timeo_nsecs = INFSLP0xffffffffffffffffULL;
1172 sbunlock(so, sb);
1173 if (pr->pr_flags & PR_RIGHTS0x10 && pr->pr_domain->dom_dispose)
1174 (*pr->pr_domain->dom_dispose)(m);
1175 m_purge(m);
1176}
1177
1178#ifdef SOCKET_SPLICE1
1179
1180#define so_splicelenso_sp->ssp_len so_sp->ssp_len
1181#define so_splicemaxso_sp->ssp_max so_sp->ssp_max
1182#define so_idletvso_sp->ssp_idletv so_sp->ssp_idletv
1183#define so_idletoso_sp->ssp_idleto so_sp->ssp_idleto
1184#define so_splicetaskso_sp->ssp_task so_sp->ssp_task
1185
1186int
1187sosplice(struct socket *so, int fd, off_t max, struct timeval *tv)
1188{
1189 struct file *fp;
1190 struct socket *sosp;
1191 struct sosplice *sp;
1192 struct taskq *tq;
1193 int error = 0;
1194
1195 soassertlocked(so);
1196
1197 if (sosplice_taskq == NULL((void *)0)) {
1198 rw_enter_write(&sosplice_lock);
1199 if (sosplice_taskq == NULL((void *)0)) {
1200 tq = taskq_create("sosplice", 1, IPL_SOFTNET0x5,
1201 TASKQ_MPSAFE(1 << 0));
1202 /* Ensure the taskq is fully visible to other CPUs. */
1203 membar_producer()do { __asm volatile("" ::: "memory"); } while (0);
1204 sosplice_taskq = tq;
1205 }
1206 rw_exit_write(&sosplice_lock);
1207 }
1208 if (sosplice_taskq == NULL((void *)0))
1209 return (ENOMEM12);
1210
1211 if ((so->so_proto->pr_flags & PR_SPLICE0x40) == 0)
1212 return (EPROTONOSUPPORT43);
1213 if (so->so_options & SO_ACCEPTCONN0x0002)
1214 return (EOPNOTSUPP45);
1215 if ((so->so_state & (SS_ISCONNECTED0x002|SS_ISCONNECTING0x004)) == 0 &&
1216 (so->so_proto->pr_flags & PR_CONNREQUIRED0x04))
1217 return (ENOTCONN57);
1218 if (so->so_sp == NULL((void *)0)) {
1219 sp = pool_get(&sosplice_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
1220 if (so->so_sp == NULL((void *)0))
1221 so->so_sp = sp;
1222 else
1223 pool_put(&sosplice_pool, sp);
1224 }
1225
1226 /* If no fd is given, unsplice by removing existing link. */
1227 if (fd < 0) {
1228 /* Lock receive buffer. */
1229 if ((error = sblock(so, &so->so_rcv, M_WAITOK0x0001)) != 0) {
1230 return (error);
1231 }
1232 if (so->so_sp->ssp_socket)
1233 sounsplice(so, so->so_sp->ssp_socket, 0);
1234 sbunlock(so, &so->so_rcv);
1235 return (0);
1236 }
1237
1238 if (max && max < 0)
1239 return (EINVAL22);
1240
1241 if (tv && (tv->tv_sec < 0 || !timerisvalid(tv)((tv)->tv_usec >= 0 && (tv)->tv_usec < 1000000
)
))
1242 return (EINVAL22);
1243
1244 /* Find sosp, the drain socket where data will be spliced into. */
1245 if ((error = getsock(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
, fd, &fp)) != 0)
1246 return (error);
1247 sosp = fp->f_data;
1248 if (sosp->so_proto->pr_usrreq != so->so_proto->pr_usrreq) {
1249 error = EPROTONOSUPPORT43;
1250 goto frele;
1251 }
1252 if (sosp->so_sp == NULL((void *)0)) {
1253 sp = pool_get(&sosplice_pool, PR_WAITOK0x0001 | PR_ZERO0x0008);
1254 if (sosp->so_sp == NULL((void *)0))
1255 sosp->so_sp = sp;
1256 else
1257 pool_put(&sosplice_pool, sp);
1258 }
1259
1260 /* Lock both receive and send buffer. */
1261 if ((error = sblock(so, &so->so_rcv, M_WAITOK0x0001)) != 0) {
1262 goto frele;
1263 }
1264 if ((error = sblock(so, &sosp->so_snd, M_WAITOK0x0001)) != 0) {
1265 sbunlock(so, &so->so_rcv);
1266 goto frele;
1267 }
1268
1269 if (so->so_sp->ssp_socket || sosp->so_sp->ssp_soback) {
1270 error = EBUSY16;
1271 goto release;
1272 }
1273 if (sosp->so_options & SO_ACCEPTCONN0x0002) {
1274 error = EOPNOTSUPP45;
1275 goto release;
1276 }
1277 if ((sosp->so_state & (SS_ISCONNECTED0x002|SS_ISCONNECTING0x004)) == 0) {
1278 error = ENOTCONN57;
1279 goto release;
1280 }
1281
1282 /* Splice so and sosp together. */
1283 so->so_sp->ssp_socket = sosp;
1284 sosp->so_sp->ssp_soback = so;
1285 so->so_splicelenso_sp->ssp_len = 0;
1286 so->so_splicemaxso_sp->ssp_max = max;
1287 if (tv)
1288 so->so_idletvso_sp->ssp_idletv = *tv;
1289 else
1290 timerclear(&so->so_idletv)(&so->so_sp->ssp_idletv)->tv_sec = (&so->
so_sp->ssp_idletv)->tv_usec = 0
;
1291 timeout_set_proc(&so->so_idletoso_sp->ssp_idleto, soidle, so);
1292 task_set(&so->so_splicetaskso_sp->ssp_task, sotask, so);
1293
1294 /*
1295 * To prevent softnet interrupt from calling somove() while
1296 * we sleep, the socket buffers are not marked as spliced yet.
1297 */
1298 if (somove(so, M_WAIT0x0001)) {
1299 so->so_rcv.sb_flags |= SB_SPLICE0x20;
1300 sosp->so_snd.sb_flags |= SB_SPLICE0x20;
1301 }
1302
1303 release:
1304 sbunlock(sosp, &sosp->so_snd);
1305 sbunlock(so, &so->so_rcv);
1306 frele:
1307 /*
1308 * FRELE() must not be called with the socket lock held. It is safe to
1309 * release the lock here as long as no other operation happen on the
1310 * socket when sosplice() returns. The dance could be avoided by
1311 * grabbing the socket lock inside this function.
1312 */
1313 sounlock(so, SL_LOCKED0x42);
1314 FRELE(fp, curproc)(_atomic_sub_int_nv((&fp->f_count), 1) == 0 ? fdrop(fp
, ({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc) : 0)
;
1315 solock(so);
1316 return (error);
1317}
1318
1319void
1320sounsplice(struct socket *so, struct socket *sosp, int freeing)
1321{
1322 soassertlocked(so);
1323
1324 task_del(sosplice_taskq, &so->so_splicetaskso_sp->ssp_task);
1325 timeout_del(&so->so_idletoso_sp->ssp_idleto);
1326 sosp->so_snd.sb_flags &= ~SB_SPLICE0x20;
1327 so->so_rcv.sb_flags &= ~SB_SPLICE0x20;
1328 so->so_sp->ssp_socket = sosp->so_sp->ssp_soback = NULL((void *)0);
1329 /* Do not wakeup a socket that is about to be freed. */
1330 if ((freeing & SOSP_FREEING_READ1) == 0 && soreadable(so))
1331 sorwakeup(so);
1332 if ((freeing & SOSP_FREEING_WRITE2) == 0 && sowriteable(sosp)((sbspace((sosp), &(sosp)->so_snd) >= (sosp)->so_snd
.sb_lowat && (((sosp)->so_state & 0x002) || ((
sosp)->so_proto->pr_flags & 0x04)==0)) || ((sosp)->
so_state & 0x010) || (sosp)->so_error)
)
1333 sowwakeup(sosp);
1334}
1335
1336void
1337soidle(void *arg)
1338{
1339 struct socket *so = arg;
1340 int s;
1341
1342 s = solock(so);
1343 if (so->so_rcv.sb_flags & SB_SPLICE0x20) {
1344 so->so_error = ETIMEDOUT60;
1345 sounsplice(so, so->so_sp->ssp_socket, 0);
1346 }
1347 sounlock(so, s);
1348}
1349
1350void
1351sotask(void *arg)
1352{
1353 struct socket *so = arg;
1354 int s;
1355
1356 s = solock(so);
1357 if (so->so_rcv.sb_flags & SB_SPLICE0x20) {
1358 /*
1359 * We may not sleep here as sofree() and unsplice() may be
1360 * called from softnet interrupt context. This would remove
1361 * the socket during somove().
1362 */
1363 somove(so, M_DONTWAIT0x0002);
1364 }
1365 sounlock(so, s);
1366
1367 /* Avoid user land starvation. */
1368 yield();
1369}
1370
1371/*
1372 * The socket splicing task or idle timeout may sleep while grabbing the net
1373 * lock. As sofree() can be called anytime, sotask() or soidle() could access
1374 * the socket memory of a freed socket after wakeup. So delay the pool_put()
1375 * after all pending socket splicing tasks or timeouts have finished. Do this
1376 * by scheduling it on the same threads.
1377 */
1378void
1379soreaper(void *arg)
1380{
1381 struct socket *so = arg;
1382
1383 /* Reuse splice task, sounsplice() has been called before. */
1384 task_set(&so->so_sp->ssp_task, soput, so);
1385 task_add(sosplice_taskq, &so->so_sp->ssp_task);
1386}
1387
1388void
1389soput(void *arg)
1390{
1391 struct socket *so = arg;
1392
1393 pool_put(&sosplice_pool, so->so_sp);
1394 pool_put(&socket_pool, so);
1395}
1396
1397/*
1398 * Move data from receive buffer of spliced source socket to send
1399 * buffer of drain socket. Try to move as much as possible in one
1400 * big chunk. It is a TCP only implementation.
1401 * Return value 0 means splicing has been finished, 1 continue.
1402 */
1403int
1404somove(struct socket *so, int wait)
1405{
1406 struct socket *sosp = so->so_sp->ssp_socket;
1407 struct mbuf *m, **mp, *nextrecord;
1408 u_long len, off, oobmark;
1409 long space;
1410 int error = 0, maxreached = 0;
1411 unsigned int state;
1412
1413 soassertlocked(so);
1414
1415 nextpkt:
1416 if (so->so_error) {
1417 error = so->so_error;
1418 goto release;
1419 }
1420 if (sosp->so_state & SS_CANTSENDMORE0x010) {
1421 error = EPIPE32;
1422 goto release;
1423 }
1424 if (sosp->so_error && sosp->so_error != ETIMEDOUT60 &&
1425 sosp->so_error != EFBIG27 && sosp->so_error != ELOOP62) {
1426 error = sosp->so_error;
1427 goto release;
1428 }
1429 if ((sosp->so_state & SS_ISCONNECTED0x002) == 0)
1430 goto release;
1431
1432 /* Calculate how many bytes can be copied now. */
1433 len = so->so_rcv.sb_datacc;
1434 if (so->so_splicemaxso_sp->ssp_max) {
1435 KASSERT(so->so_splicelen < so->so_splicemax)((so->so_sp->ssp_len < so->so_sp->ssp_max) ? (
void)0 : __assert("diagnostic ", "/usr/src/sys/kern/uipc_socket.c"
, 1435, "so->so_splicelen < so->so_splicemax"))
;
1436 if (so->so_splicemaxso_sp->ssp_max <= so->so_splicelenso_sp->ssp_len + len) {
1437 len = so->so_splicemaxso_sp->ssp_max - so->so_splicelenso_sp->ssp_len;
1438 maxreached = 1;
1439 }
1440 }
1441 space = sbspace(sosp, &sosp->so_snd);
1442 if (so->so_oobmark && so->so_oobmark < len &&
1443 so->so_oobmark < space + 1024)
1444 space += 1024;
1445 if (space <= 0) {
1446 maxreached = 0;
1447 goto release;
1448 }
1449 if (space < len) {
1450 maxreached = 0;
1451 if (space < sosp->so_snd.sb_lowat)
1452 goto release;
1453 len = space;
1454 }
1455 sosp->so_state |= SS_ISSENDING0x2000;
1456
1457 SBLASTRECORDCHK(&so->so_rcv, "somove 1");
1458 SBLASTMBUFCHK(&so->so_rcv, "somove 1");
1459 m = so->so_rcv.sb_mb;
1460 if (m == NULL((void *)0))
1461 goto release;
1462 nextrecord = m->m_nextpktm_hdr.mh_nextpkt;
1463
1464 /* Drop address and control information not used with splicing. */
1465 if (so->so_proto->pr_flags & PR_ADDR0x02) {
1466#ifdef DIAGNOSTIC1
1467 if (m->m_typem_hdr.mh_type != MT_SONAME3)
1468 panic("somove soname: so %p, so_type %d, m %p, "
1469 "m_type %d", so, so->so_type, m, m->m_typem_hdr.mh_type);
1470#endif
1471 m = m->m_nextm_hdr.mh_next;
1472 }
1473 while (m && m->m_typem_hdr.mh_type == MT_CONTROL6)
1474 m = m->m_nextm_hdr.mh_next;
1475 if (m == NULL((void *)0)) {
1476 sbdroprecord(so, &so->so_rcv);
1477 if (so->so_proto->pr_flags & PR_WANTRCVD0x08 && so->so_pcb)
1478 (so->so_proto->pr_usrreq)(so, PRU_RCVD8, NULL((void *)0),
1479 NULL((void *)0), NULL((void *)0), NULL((void *)0));
1480 goto nextpkt;
1481 }
1482
1483 /*
1484 * By splicing sockets connected to localhost, userland might create a
1485 * loop. Dissolve splicing with error if loop is detected by counter.
1486 *
1487 * If we deal with looped broadcast/multicast packet we bail out with
1488 * no error to suppress splice termination.
1489 */
1490 if ((m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) &&
1491 ((m->m_pkthdrM_dat.MH.MH_pkthdr.ph_loopcnt++ >= M_MAXLOOP128) ||
1492 ((m->m_flagsm_hdr.mh_flags & M_LOOP0x0040) && (m->m_flagsm_hdr.mh_flags & (M_BCAST0x0100|M_MCAST0x0200))))) {
1493 error = ELOOP62;
1494 goto release;
1495 }
1496
1497 if (so->so_proto->pr_flags & PR_ATOMIC0x01) {
1498 if ((m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) == 0)
1499 panic("somove !PKTHDR: so %p, so_type %d, m %p, "
1500 "m_type %d", so, so->so_type, m, m->m_typem_hdr.mh_type);
1501 if (sosp->so_snd.sb_hiwat < m->m_pkthdrM_dat.MH.MH_pkthdr.len) {
1502 error = EMSGSIZE40;
1503 goto release;
1504 }
1505 if (len < m->m_pkthdrM_dat.MH.MH_pkthdr.len)
1506 goto release;
1507 if (m->m_pkthdrM_dat.MH.MH_pkthdr.len < len) {
1508 maxreached = 0;
1509 len = m->m_pkthdrM_dat.MH.MH_pkthdr.len;
1510 }
1511 /*
1512 * Throw away the name mbuf after it has been assured
1513 * that the whole first record can be processed.
1514 */
1515 m = so->so_rcv.sb_mb;
1516 sbfree(so, &so->so_rcv, m)do { (&so->so_rcv)->sb_cc -= (m)->m_hdr.mh_len; if
((m)->m_hdr.mh_type != 6 && (m)->m_hdr.mh_type
!= 3) (&so->so_rcv)->sb_datacc -= (m)->m_hdr.mh_len
; (&so->so_rcv)->sb_mbcnt -= 256; if ((m)->m_hdr
.mh_flags & 0x0001) (&so->so_rcv)->sb_mbcnt -= (
m)->M_dat.MH.MH_dat.MH_ext.ext_size; } while ( 0)
;
1517 so->so_rcv.sb_mb = m_free(m);
1518 sbsync(&so->so_rcv, nextrecord);
1519 }
1520 /*
1521 * Throw away the control mbufs after it has been assured
1522 * that the whole first record can be processed.
1523 */
1524 m = so->so_rcv.sb_mb;
1525 while (m && m->m_typem_hdr.mh_type == MT_CONTROL6) {
1526 sbfree(so, &so->so_rcv, m)do { (&so->so_rcv)->sb_cc -= (m)->m_hdr.mh_len; if
((m)->m_hdr.mh_type != 6 && (m)->m_hdr.mh_type
!= 3) (&so->so_rcv)->sb_datacc -= (m)->m_hdr.mh_len
; (&so->so_rcv)->sb_mbcnt -= 256; if ((m)->m_hdr
.mh_flags & 0x0001) (&so->so_rcv)->sb_mbcnt -= (
m)->M_dat.MH.MH_dat.MH_ext.ext_size; } while ( 0)
;
1527 so->so_rcv.sb_mb = m_free(m);
1528 m = so->so_rcv.sb_mb;
1529 sbsync(&so->so_rcv, nextrecord);
1530 }
1531
1532 SBLASTRECORDCHK(&so->so_rcv, "somove 2");
1533 SBLASTMBUFCHK(&so->so_rcv, "somove 2");
1534
1535 /* Take at most len mbufs out of receive buffer. */
1536 for (off = 0, mp = &m; off <= len && *mp;
1537 off += (*mp)->m_lenm_hdr.mh_len, mp = &(*mp)->m_nextm_hdr.mh_next) {
1538 u_long size = len - off;
1539
1540#ifdef DIAGNOSTIC1
1541 if ((*mp)->m_typem_hdr.mh_type != MT_DATA1 && (*mp)->m_typem_hdr.mh_type != MT_HEADER2)
1542 panic("somove type: so %p, so_type %d, m %p, "
1543 "m_type %d", so, so->so_type, *mp, (*mp)->m_typem_hdr.mh_type);
1544#endif
1545 if ((*mp)->m_lenm_hdr.mh_len > size) {
1546 /*
1547 * Move only a partial mbuf at maximum splice length or
1548 * if the drain buffer is too small for this large mbuf.
1549 */
1550 if (!maxreached && so->so_snd.sb_datacc > 0) {
1551 len -= size;
1552 break;
1553 }
1554 *mp = m_copym(so->so_rcv.sb_mb, 0, size, wait);
1555 if (*mp == NULL((void *)0)) {
1556 len -= size;
1557 break;
1558 }
1559 so->so_rcv.sb_mb->m_datam_hdr.mh_data += size;
1560 so->so_rcv.sb_mb->m_lenm_hdr.mh_len -= size;
1561 so->so_rcv.sb_cc -= size;
1562 so->so_rcv.sb_datacc -= size;
1563 } else {
1564 *mp = so->so_rcv.sb_mb;
1565 sbfree(so, &so->so_rcv, *mp)do { (&so->so_rcv)->sb_cc -= (*mp)->m_hdr.mh_len
; if ((*mp)->m_hdr.mh_type != 6 && (*mp)->m_hdr
.mh_type != 3) (&so->so_rcv)->sb_datacc -= (*mp)->
m_hdr.mh_len; (&so->so_rcv)->sb_mbcnt -= 256; if ((
*mp)->m_hdr.mh_flags & 0x0001) (&so->so_rcv)->
sb_mbcnt -= (*mp)->M_dat.MH.MH_dat.MH_ext.ext_size; } while
( 0)
;
1566 so->so_rcv.sb_mb = (*mp)->m_nextm_hdr.mh_next;
1567 sbsync(&so->so_rcv, nextrecord);
1568 }
1569 }
1570 *mp = NULL((void *)0);
1571
1572 SBLASTRECORDCHK(&so->so_rcv, "somove 3");
1573 SBLASTMBUFCHK(&so->so_rcv, "somove 3");
1574 SBCHECK(so, &so->so_rcv);
1575 if (m == NULL((void *)0))
1576 goto release;
1577 m->m_nextpktm_hdr.mh_nextpkt = NULL((void *)0);
1578 if (m->m_flagsm_hdr.mh_flags & M_PKTHDR0x0002) {
1579 m_resethdr(m);
1580 m->m_pkthdrM_dat.MH.MH_pkthdr.len = len;
1581 }
1582
1583 /* Send window update to source peer as receive buffer has changed. */
1584 if (so->so_proto->pr_flags & PR_WANTRCVD0x08 && so->so_pcb)
1585 (so->so_proto->pr_usrreq)(so, PRU_RCVD8, NULL((void *)0),
1586 NULL((void *)0), NULL((void *)0), NULL((void *)0));
1587
1588 /* Receive buffer did shrink by len bytes, adjust oob. */
1589 state = so->so_state;
1590 so->so_state &= ~SS_RCVATMARK0x040;
1591 oobmark = so->so_oobmark;
1592 so->so_oobmark = oobmark > len ? oobmark - len : 0;
1593 if (oobmark) {
1594 if (oobmark == len)
1595 so->so_state |= SS_RCVATMARK0x040;
1596 if (oobmark >= len)
1597 oobmark = 0;
1598 }
1599
1600 /*
1601 * Handle oob data. If any malloc fails, ignore error.
1602 * TCP urgent data is not very reliable anyway.
1603 */
1604 while (((state & SS_RCVATMARK0x040) || oobmark) &&
1605 (so->so_options & SO_OOBINLINE0x0100)) {
1606 struct mbuf *o = NULL((void *)0);
1607
1608 if (state & SS_RCVATMARK0x040) {
1609 o = m_get(wait, MT_DATA1);
1610 state &= ~SS_RCVATMARK0x040;
1611 } else if (oobmark) {
1612 o = m_split(m, oobmark, wait);
1613 if (o) {
1614 error = (*sosp->so_proto->pr_usrreq)(sosp,
1615 PRU_SEND9, m, NULL((void *)0), NULL((void *)0), NULL((void *)0));
1616 if (error) {
1617 if (sosp->so_state & SS_CANTSENDMORE0x010)
1618 error = EPIPE32;
1619 m_freem(o);
1620 goto release;
1621 }
1622 len -= oobmark;
1623 so->so_splicelenso_sp->ssp_len += oobmark;
1624 m = o;
1625 o = m_get(wait, MT_DATA1);
1626 }
1627 oobmark = 0;
1628 }
1629 if (o) {
1630 o->m_lenm_hdr.mh_len = 1;
1631 *mtod(o, caddr_t)((caddr_t)((o)->m_hdr.mh_data)) = *mtod(m, caddr_t)((caddr_t)((m)->m_hdr.mh_data));
1632 error = (*sosp->so_proto->pr_usrreq)(sosp, PRU_SENDOOB14,
1633 o, NULL((void *)0), NULL((void *)0), NULL((void *)0));
1634 if (error) {
1635 if (sosp->so_state & SS_CANTSENDMORE0x010)
1636 error = EPIPE32;
1637 m_freem(m);
1638 goto release;
1639 }
1640 len -= 1;
1641 so->so_splicelenso_sp->ssp_len += 1;
1642 if (oobmark) {
1643 oobmark -= 1;
1644 if (oobmark == 0)
1645 state |= SS_RCVATMARK0x040;
1646 }
1647 m_adj(m, 1);
1648 }
1649 }
1650
1651 /* Append all remaining data to drain socket. */
1652 if (so->so_rcv.sb_cc == 0 || maxreached)
1653 sosp->so_state &= ~SS_ISSENDING0x2000;
1654 error = (*sosp->so_proto->pr_usrreq)(sosp, PRU_SEND9, m, NULL((void *)0), NULL((void *)0),
1655 NULL((void *)0));
1656 if (error) {
1657 if (sosp->so_state & SS_CANTSENDMORE0x010)
1658 error = EPIPE32;
1659 goto release;
1660 }
1661 so->so_splicelenso_sp->ssp_len += len;
1662
1663 /* Move several packets if possible. */
1664 if (!maxreached && nextrecord)
1665 goto nextpkt;
1666
1667 release:
1668 sosp->so_state &= ~SS_ISSENDING0x2000;
1669 if (!error && maxreached && so->so_splicemaxso_sp->ssp_max == so->so_splicelenso_sp->ssp_len)
1670 error = EFBIG27;
1671 if (error)
1672 so->so_error = error;
1673 if (((so->so_state & SS_CANTRCVMORE0x020) && so->so_rcv.sb_cc == 0) ||
1674 (sosp->so_state & SS_CANTSENDMORE0x010) || maxreached || error) {
1675 sounsplice(so, sosp, 0);
1676 return (0);
1677 }
1678 if (timerisset(&so->so_idletv)((&so->so_sp->ssp_idletv)->tv_sec || (&so->
so_sp->ssp_idletv)->tv_usec)
)
1679 timeout_add_tv(&so->so_idletoso_sp->ssp_idleto, &so->so_idletvso_sp->ssp_idletv);
1680 return (1);
1681}
1682
1683#endif /* SOCKET_SPLICE */
1684
1685void
1686sorwakeup(struct socket *so)
1687{
1688 soassertlocked(so);
1689
1690#ifdef SOCKET_SPLICE1
1691 if (so->so_rcv.sb_flags & SB_SPLICE0x20) {
1692 /*
1693 * TCP has a sendbuffer that can handle multiple packets
1694 * at once. So queue the stream a bit to accumulate data.
1695 * The sosplice thread will call somove() later and send
1696 * the packets calling tcp_output() only once.
1697 * In the UDP case, send out the packets immediately.
1698 * Using a thread would make things slower.
1699 */
1700 if (so->so_proto->pr_flags & PR_WANTRCVD0x08)
1701 task_add(sosplice_taskq, &so->so_splicetaskso_sp->ssp_task);
1702 else
1703 somove(so, M_DONTWAIT0x0002);
1704 }
1705 if (isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket))
1706 return;
1707#endif
1708 sowakeup(so, &so->so_rcv);
1709 if (so->so_upcall)
1710 (*(so->so_upcall))(so, so->so_upcallarg, M_DONTWAIT0x0002);
1711}
1712
1713void
1714sowwakeup(struct socket *so)
1715{
1716 soassertlocked(so);
1717
1718#ifdef SOCKET_SPLICE1
1719 if (so->so_snd.sb_flags & SB_SPLICE0x20)
1720 task_add(sosplice_taskq, &so->so_sp->ssp_soback->so_splicetaskso_sp->ssp_task);
1721 if (issplicedback(so)((so)->so_sp && (so)->so_sp->ssp_soback))
1722 return;
1723#endif
1724 sowakeup(so, &so->so_snd);
1725}
1726
1727int
1728sosetopt(struct socket *so, int level, int optname, struct mbuf *m)
1729{
1730 int error = 0;
1731
1732 soassertlocked(so);
1733
1734 if (level != SOL_SOCKET0xffff) {
1735 if (so->so_proto->pr_ctloutput) {
1736 error = (*so->so_proto->pr_ctloutput)(PRCO_SETOPT1, so,
1737 level, optname, m);
1738 return (error);
1739 }
1740 error = ENOPROTOOPT42;
1741 } else {
1742 switch (optname) {
1743 case SO_BINDANY0x1000:
1744 if ((error = suser(curproc({struct cpu_info *__ci; asm volatile("movq %%gs:%P1,%0" : "=r"
(__ci) :"n" (__builtin_offsetof(struct cpu_info, ci_self)));
__ci;})->ci_curproc
)) != 0) /* XXX */
1745 return (error);
1746 break;
1747 }
1748
1749 switch (optname) {
1750
1751 case SO_LINGER0x0080:
1752 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len != sizeof (struct linger) ||
1753 mtod(m, struct linger *)((struct linger *)((m)->m_hdr.mh_data))->l_linger < 0 ||
1754 mtod(m, struct linger *)((struct linger *)((m)->m_hdr.mh_data))->l_linger > SHRT_MAX0x7fff)
1755 return (EINVAL22);
1756 so->so_linger = mtod(m, struct linger *)((struct linger *)((m)->m_hdr.mh_data))->l_linger;
1757 /* FALLTHROUGH */
1758
1759 case SO_BINDANY0x1000:
1760 case SO_DEBUG0x0001:
1761 case SO_KEEPALIVE0x0008:
1762 case SO_USELOOPBACK0x0040:
1763 case SO_BROADCAST0x0020:
1764 case SO_REUSEADDR0x0004:
1765 case SO_REUSEPORT0x0200:
1766 case SO_OOBINLINE0x0100:
1767 case SO_TIMESTAMP0x0800:
1768 case SO_ZEROIZE0x2000:
1769 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof (int))
1770 return (EINVAL22);
1771 if (*mtod(m, int *)((int *)((m)->m_hdr.mh_data)))
1772 so->so_options |= optname;
1773 else
1774 so->so_options &= ~optname;
1775 break;
1776
1777 case SO_DONTROUTE0x0010:
1778 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof (int))
1779 return (EINVAL22);
1780 if (*mtod(m, int *)((int *)((m)->m_hdr.mh_data)))
1781 error = EOPNOTSUPP45;
1782 break;
1783
1784 case SO_SNDBUF0x1001:
1785 case SO_RCVBUF0x1002:
1786 case SO_SNDLOWAT0x1003:
1787 case SO_RCVLOWAT0x1004:
1788 {
1789 u_long cnt;
1790
1791 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof (int))
1792 return (EINVAL22);
1793 cnt = *mtod(m, int *)((int *)((m)->m_hdr.mh_data));
1794 if ((long)cnt <= 0)
1795 cnt = 1;
1796 switch (optname) {
1797
1798 case SO_SNDBUF0x1001:
1799 if (so->so_state & SS_CANTSENDMORE0x010)
1800 return (EINVAL22);
1801 if (sbcheckreserve(cnt, so->so_snd.sb_wat) ||
1802 sbreserve(so, &so->so_snd, cnt))
1803 return (ENOBUFS55);
1804 so->so_snd.sb_wat = cnt;
1805 break;
1806
1807 case SO_RCVBUF0x1002:
1808 if (so->so_state & SS_CANTRCVMORE0x020)
1809 return (EINVAL22);
1810 if (sbcheckreserve(cnt, so->so_rcv.sb_wat) ||
1811 sbreserve(so, &so->so_rcv, cnt))
1812 return (ENOBUFS55);
1813 so->so_rcv.sb_wat = cnt;
1814 break;
1815
1816 case SO_SNDLOWAT0x1003:
1817 so->so_snd.sb_lowat =
1818 (cnt > so->so_snd.sb_hiwat) ?
1819 so->so_snd.sb_hiwat : cnt;
1820 break;
1821 case SO_RCVLOWAT0x1004:
1822 so->so_rcv.sb_lowat =
1823 (cnt > so->so_rcv.sb_hiwat) ?
1824 so->so_rcv.sb_hiwat : cnt;
1825 break;
1826 }
1827 break;
1828 }
1829
1830 case SO_SNDTIMEO0x1005:
1831 case SO_RCVTIMEO0x1006:
1832 {
1833 struct timeval tv;
1834 uint64_t nsecs;
1835
1836 if (m == NULL((void *)0) || m->m_lenm_hdr.mh_len < sizeof (tv))
1837 return (EINVAL22);
1838 memcpy(&tv, mtod(m, struct timeval *), sizeof tv)__builtin_memcpy((&tv), (((struct timeval *)((m)->m_hdr
.mh_data))), (sizeof tv))
;
1839 if (!timerisvalid(&tv)((&tv)->tv_usec >= 0 && (&tv)->tv_usec
< 1000000)
)
1840 return (EINVAL22);
1841 nsecs = TIMEVAL_TO_NSEC(&tv);
1842 if (nsecs == UINT64_MAX0xffffffffffffffffULL)
1843 return (EDOM33);
1844 if (nsecs == 0)
1845 nsecs = INFSLP0xffffffffffffffffULL;
1846 switch (optname) {
1847
1848 case SO_SNDTIMEO0x1005:
1849 so->so_snd.sb_timeo_nsecs = nsecs;
1850 break;
1851 case SO_RCVTIMEO0x1006:
1852 so->so_rcv.sb_timeo_nsecs = nsecs;
1853 break;
1854 }
1855 break;
1856 }
1857
1858 case SO_RTABLE0x1021:
1859 if (so->so_proto->pr_domain &&
1860 so->so_proto->pr_domain->dom_protosw &&
1861 so->so_proto->pr_ctloutput) {
1862 const struct domain *dom =
1863 so->so_proto->pr_domain;
1864
1865 level = dom->dom_protosw->pr_protocol;
1866 error = (*so->so_proto->pr_ctloutput)
1867 (PRCO_SETOPT1, so, level, optname, m);
1868 return (error);
1869 }
1870 error = ENOPROTOOPT42;
1871 break;
1872
1873#ifdef SOCKET_SPLICE1
1874 case SO_SPLICE0x1023:
1875 if (m == NULL((void *)0)) {
1876 error = sosplice(so, -1, 0, NULL((void *)0));
1877 } else if (m->m_lenm_hdr.mh_len < sizeof(int)) {
1878 return (EINVAL22);
1879 } else if (m->m_lenm_hdr.mh_len < sizeof(struct splice)) {
1880 error = sosplice(so, *mtod(m, int *)((int *)((m)->m_hdr.mh_data)), 0, NULL((void *)0));
1881 } else {
1882 error = sosplice(so,
1883 mtod(m, struct splice *)((struct splice *)((m)->m_hdr.mh_data))->sp_fd,
1884 mtod(m, struct splice *)((struct splice *)((m)->m_hdr.mh_data))->sp_max,
1885 &mtod(m, struct splice *)((struct splice *)((m)->m_hdr.mh_data))->sp_idle);
1886 }
1887 break;
1888#endif /* SOCKET_SPLICE */
1889
1890 default:
1891 error = ENOPROTOOPT42;
1892 break;
1893 }
1894 if (error == 0 && so->so_proto->pr_ctloutput) {
1895 (*so->so_proto->pr_ctloutput)(PRCO_SETOPT1, so,
1896 level, optname, m);
1897 }
1898 }
1899
1900 return (error);
1901}
1902
1903int
1904sogetopt(struct socket *so, int level, int optname, struct mbuf *m)
1905{
1906 int error = 0;
1907
1908 soassertlocked(so);
1909
1910 if (level != SOL_SOCKET0xffff) {
1911 if (so->so_proto->pr_ctloutput) {
1912 m->m_lenm_hdr.mh_len = 0;
1913
1914 error = (*so->so_proto->pr_ctloutput)(PRCO_GETOPT0, so,
1915 level, optname, m);
1916 if (error)
1917 return (error);
1918 return (0);
1919 } else
1920 return (ENOPROTOOPT42);
1921 } else {
1922 m->m_lenm_hdr.mh_len = sizeof (int);
1923
1924 switch (optname) {
1925
1926 case SO_LINGER0x0080:
1927 m->m_lenm_hdr.mh_len = sizeof (struct linger);
1928 mtod(m, struct linger *)((struct linger *)((m)->m_hdr.mh_data))->l_onoff =
1929 so->so_options & SO_LINGER0x0080;
1930 mtod(m, struct linger *)((struct linger *)((m)->m_hdr.mh_data))->l_linger = so->so_linger;
1931 break;
1932
1933 case SO_BINDANY0x1000:
1934 case SO_USELOOPBACK0x0040:
1935 case SO_DEBUG0x0001:
1936 case SO_KEEPALIVE0x0008:
1937 case SO_REUSEADDR0x0004:
1938 case SO_REUSEPORT0x0200:
1939 case SO_BROADCAST0x0020:
1940 case SO_OOBINLINE0x0100:
1941 case SO_TIMESTAMP0x0800:
1942 case SO_ZEROIZE0x2000:
1943 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_options & optname;
1944 break;
1945
1946 case SO_DONTROUTE0x0010:
1947 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = 0;
1948 break;
1949
1950 case SO_TYPE0x1008:
1951 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_type;
1952 break;
1953
1954 case SO_ERROR0x1007:
1955 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_error;
1956 so->so_error = 0;
1957 break;
1958
1959 case SO_DOMAIN0x1024:
1960 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_proto->pr_domain->dom_family;
1961 break;
1962
1963 case SO_PROTOCOL0x1025:
1964 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_proto->pr_protocol;
1965 break;
1966
1967 case SO_SNDBUF0x1001:
1968 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_snd.sb_hiwat;
1969 break;
1970
1971 case SO_RCVBUF0x1002:
1972 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_rcv.sb_hiwat;
1973 break;
1974
1975 case SO_SNDLOWAT0x1003:
1976 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_snd.sb_lowat;
1977 break;
1978
1979 case SO_RCVLOWAT0x1004:
1980 *mtod(m, int *)((int *)((m)->m_hdr.mh_data)) = so->so_rcv.sb_lowat;
1981 break;
1982
1983 case SO_SNDTIMEO0x1005:
1984 case SO_RCVTIMEO0x1006:
1985 {
1986 struct timeval tv;
1987 uint64_t nsecs = (optname == SO_SNDTIMEO0x1005 ?
1988 so->so_snd.sb_timeo_nsecs :
1989 so->so_rcv.sb_timeo_nsecs);
1990
1991 m->m_lenm_hdr.mh_len = sizeof(struct timeval);
1992 memset(&tv, 0, sizeof(tv))__builtin_memset((&tv), (0), (sizeof(tv)));
1993 if (nsecs != INFSLP0xffffffffffffffffULL)
1994 NSEC_TO_TIMEVAL(nsecs, &tv);
1995 memcpy(mtod(m, struct timeval *), &tv, sizeof tv)__builtin_memcpy((((struct timeval *)((m)->m_hdr.mh_data))
), (&tv), (sizeof tv))
;
1996 break;
1997 }
1998
1999 case SO_RTABLE0x1021:
2000 if (so->so_proto->pr_domain &&
2001 so->so_proto->pr_domain->dom_protosw &&
2002 so->so_proto->pr_ctloutput) {
2003 const struct domain *dom =
2004 so->so_proto->pr_domain;
2005
2006 level = dom->dom_protosw->pr_protocol;
2007 error = (*so->so_proto->pr_ctloutput)
2008 (PRCO_GETOPT0, so, level, optname, m);
2009 if (error)
2010 return (error);
2011 break;
2012 }
2013 return (ENOPROTOOPT42);
2014
2015#ifdef SOCKET_SPLICE1
2016 case SO_SPLICE0x1023:
2017 {
2018 off_t len;
2019
2020 m->m_lenm_hdr.mh_len = sizeof(off_t);
2021 len = so->so_sp ? so->so_sp->ssp_len : 0;
2022 memcpy(mtod(m, off_t *), &len, sizeof(off_t))__builtin_memcpy((((off_t *)((m)->m_hdr.mh_data))), (&
len), (sizeof(off_t)))
;
2023 break;
2024 }
2025#endif /* SOCKET_SPLICE */
2026
2027 case SO_PEERCRED0x1022:
2028 if (so->so_proto->pr_protocol == AF_UNIX1) {
2029 struct unpcb *unp = sotounpcb(so)((struct unpcb *)((so)->so_pcb));
2030
2031 if (unp->unp_flags & UNP_FEIDS0x01) {
2032 m->m_lenm_hdr.mh_len = sizeof(unp->unp_connid);
2033 memcpy(mtod(m, caddr_t),__builtin_memcpy((((caddr_t)((m)->m_hdr.mh_data))), (&
(unp->unp_connid)), (m->m_hdr.mh_len))
2034 &(unp->unp_connid), m->m_len)__builtin_memcpy((((caddr_t)((m)->m_hdr.mh_data))), (&
(unp->unp_connid)), (m->m_hdr.mh_len))
;
2035 break;
2036 }
2037 return (ENOTCONN57);
2038 }
2039 return (EOPNOTSUPP45);
2040
2041 default:
2042 return (ENOPROTOOPT42);
2043 }
2044 return (0);
2045 }
2046}
2047
2048void
2049sohasoutofband(struct socket *so)
2050{
2051 pgsigio(&so->so_sigio, SIGURG16, 0);
2052 selwakeup(&so->so_rcv.sb_sel);
2053}
2054
2055int
2056soo_kqfilter(struct file *fp, struct knote *kn)
2057{
2058 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2059 struct sockbuf *sb;
2060 int s;
2061
2062 s = solock(so);
2063 switch (kn->kn_filterkn_kevent.filter) {
2064 case EVFILT_READ(-1):
2065 if (so->so_options & SO_ACCEPTCONN0x0002)
2066 kn->kn_fop = &solisten_filtops;
2067 else
2068 kn->kn_fop = &soread_filtops;
2069 sb = &so->so_rcv;
2070 break;
2071 case EVFILT_WRITE(-2):
2072 kn->kn_fop = &sowrite_filtops;
2073 sb = &so->so_snd;
2074 break;
2075 case EVFILT_EXCEPT(-9):
2076 kn->kn_fop = &soexcept_filtops;
2077 sb = &so->so_rcv;
2078 break;
2079 default:
2080 sounlock(so, s);
2081 return (EINVAL22);
2082 }
2083
2084 klist_insert_locked(&sb->sb_sel.si_note, kn);
2085 sounlock(so, s);
2086
2087 return (0);
2088}
2089
2090void
2091filt_sordetach(struct knote *kn)
2092{
2093 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2094
2095 klist_remove(&so->so_rcv.sb_sel.si_note, kn);
2096}
2097
2098int
2099filt_soread_common(struct knote *kn, struct socket *so)
2100{
2101 int rv = 0;
2102
2103 soassertlocked(so);
2104
2105 kn->kn_datakn_kevent.data = so->so_rcv.sb_cc;
2106#ifdef SOCKET_SPLICE1
2107 if (isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket)) {
2108 rv = 0;
2109 } else
2110#endif /* SOCKET_SPLICE */
2111 if (so->so_state & SS_CANTRCVMORE0x020) {
2112 kn->kn_flagskn_kevent.flags |= EV_EOF0x8000;
2113 if (kn->kn_flagskn_kevent.flags & __EV_POLL0x1000) {
2114 if (so->so_state & SS_ISDISCONNECTED0x800)
2115 kn->kn_flagskn_kevent.flags |= __EV_HUP0x2000;
2116 }
2117 kn->kn_fflagskn_kevent.fflags = so->so_error;
2118 rv = 1;
2119 } else if (so->so_error) { /* temporary udp error */
2120 rv = 1;
2121 } else if (kn->kn_sfflags & NOTE_LOWAT0x0001) {
2122 rv = (kn->kn_datakn_kevent.data >= kn->kn_sdata);
2123 } else {
2124 rv = (kn->kn_datakn_kevent.data >= so->so_rcv.sb_lowat);
2125 }
2126
2127 return rv;
2128}
2129
2130int
2131filt_soread(struct knote *kn, long hint)
2132{
2133 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2134
2135 return (filt_soread_common(kn, so));
2136}
2137
2138int
2139filt_soreadmodify(struct kevent *kev, struct knote *kn)
2140{
2141 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2142 int rv, s;
2143
2144 s = solock(so);
2145 knote_modify(kev, kn);
2146 rv = filt_soread_common(kn, so);
2147 sounlock(so, s);
2148
2149 return (rv);
2150}
2151
2152int
2153filt_soreadprocess(struct knote *kn, struct kevent *kev)
2154{
2155 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2156 int rv, s;
2157
2158 s = solock(so);
2159 if (kev != NULL((void *)0) && (kn->kn_flagskn_kevent.flags & EV_ONESHOT0x0010))
2160 rv = 1;
2161 else
2162 rv = filt_soread_common(kn, so);
2163 if (rv != 0)
2164 knote_submit(kn, kev);
2165 sounlock(so, s);
2166
2167 return (rv);
2168}
2169
2170void
2171filt_sowdetach(struct knote *kn)
2172{
2173 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2174
2175 klist_remove(&so->so_snd.sb_sel.si_note, kn);
2176}
2177
2178int
2179filt_sowrite_common(struct knote *kn, struct socket *so)
2180{
2181 int rv;
2182
2183 soassertlocked(so);
2184
2185 kn->kn_datakn_kevent.data = sbspace(so, &so->so_snd);
2186 if (so->so_state & SS_CANTSENDMORE0x010) {
2187 kn->kn_flagskn_kevent.flags |= EV_EOF0x8000;
2188 if (kn->kn_flagskn_kevent.flags & __EV_POLL0x1000) {
2189 if (so->so_state & SS_ISDISCONNECTED0x800)
2190 kn->kn_flagskn_kevent.flags |= __EV_HUP0x2000;
2191 }
2192 kn->kn_fflagskn_kevent.fflags = so->so_error;
2193 rv = 1;
2194 } else if (so->so_error) { /* temporary udp error */
2195 rv = 1;
2196 } else if (((so->so_state & SS_ISCONNECTED0x002) == 0) &&
2197 (so->so_proto->pr_flags & PR_CONNREQUIRED0x04)) {
2198 rv = 0;
2199 } else if (kn->kn_sfflags & NOTE_LOWAT0x0001) {
2200 rv = (kn->kn_datakn_kevent.data >= kn->kn_sdata);
2201 } else {
2202 rv = (kn->kn_datakn_kevent.data >= so->so_snd.sb_lowat);
2203 }
2204
2205 return (rv);
2206}
2207
2208int
2209filt_sowrite(struct knote *kn, long hint)
2210{
2211 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2212
2213 return (filt_sowrite_common(kn, so));
2214}
2215
2216int
2217filt_sowritemodify(struct kevent *kev, struct knote *kn)
2218{
2219 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2220 int rv, s;
2221
2222 s = solock(so);
2223 knote_modify(kev, kn);
2224 rv = filt_sowrite_common(kn, so);
2225 sounlock(so, s);
2226
2227 return (rv);
2228}
2229
2230int
2231filt_sowriteprocess(struct knote *kn, struct kevent *kev)
2232{
2233 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2234 int rv, s;
2235
2236 s = solock(so);
2237 if (kev != NULL((void *)0) && (kn->kn_flagskn_kevent.flags & EV_ONESHOT0x0010))
2238 rv = 1;
2239 else
2240 rv = filt_sowrite_common(kn, so);
2241 if (rv != 0)
2242 knote_submit(kn, kev);
2243 sounlock(so, s);
2244
2245 return (rv);
2246}
2247
2248int
2249filt_soexcept_common(struct knote *kn, struct socket *so)
2250{
2251 int rv = 0;
2252
2253 soassertlocked(so);
2254
2255#ifdef SOCKET_SPLICE1
2256 if (isspliced(so)((so)->so_sp && (so)->so_sp->ssp_socket)) {
2257 rv = 0;
2258 } else
2259#endif /* SOCKET_SPLICE */
2260 if (kn->kn_sfflags & NOTE_OOB0x0004) {
2261 if (so->so_oobmark || (so->so_state & SS_RCVATMARK0x040)) {
2262 kn->kn_fflagskn_kevent.fflags |= NOTE_OOB0x0004;
2263 kn->kn_datakn_kevent.data -= so->so_oobmark;
2264 rv = 1;
2265 }
2266 }
2267
2268 if (kn->kn_flagskn_kevent.flags & __EV_POLL0x1000) {
2269 if (so->so_state & SS_ISDISCONNECTED0x800) {
2270 kn->kn_flagskn_kevent.flags |= __EV_HUP0x2000;
2271 rv = 1;
2272 }
2273 }
2274
2275 return rv;
2276}
2277
2278int
2279filt_soexcept(struct knote *kn, long hint)
2280{
2281 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2282
2283 return (filt_soexcept_common(kn, so));
2284}
2285
2286int
2287filt_soexceptmodify(struct kevent *kev, struct knote *kn)
2288{
2289 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2290 int rv, s;
2291
2292 s = solock(so);
2293 knote_modify(kev, kn);
2294 rv = filt_soexcept_common(kn, so);
2295 sounlock(so, s);
2296
2297 return (rv);
2298}
2299
2300int
2301filt_soexceptprocess(struct knote *kn, struct kevent *kev)
2302{
2303 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2304 int rv, s;
2305
2306 s = solock(so);
2307 if (kev != NULL((void *)0) && (kn->kn_flagskn_kevent.flags & EV_ONESHOT0x0010))
2308 rv = 1;
2309 else
2310 rv = filt_soexcept_common(kn, so);
2311 if (rv != 0)
2312 knote_submit(kn, kev);
2313 sounlock(so, s);
2314
2315 return (rv);
2316}
2317
2318int
2319filt_solisten_common(struct knote *kn, struct socket *so)
2320{
2321 int active;
2322
2323 soassertlocked(so);
2324
2325 kn->kn_datakn_kevent.data = so->so_qlen;
2326 active = (kn->kn_datakn_kevent.data != 0);
2327
2328 if (kn->kn_flagskn_kevent.flags & (__EV_POLL0x1000 | __EV_SELECT0x0800)) {
2329 if (so->so_state & SS_ISDISCONNECTED0x800) {
2330 kn->kn_flagskn_kevent.flags |= __EV_HUP0x2000;
2331 active = 1;
2332 } else {
2333 active = soreadable(so);
2334 }
2335 }
2336
2337 return (active);
2338}
2339
2340int
2341filt_solisten(struct knote *kn, long hint)
2342{
2343 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2344
2345 return (filt_solisten_common(kn, so));
2346}
2347
2348int
2349filt_solistenmodify(struct kevent *kev, struct knote *kn)
2350{
2351 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2352 int rv, s;
2353
2354 s = solock(so);
2355 knote_modify(kev, kn);
2356 rv = filt_solisten_common(kn, so);
2357 sounlock(so, s);
2358
2359 return (rv);
2360}
2361
2362int
2363filt_solistenprocess(struct knote *kn, struct kevent *kev)
2364{
2365 struct socket *so = kn->kn_fpkn_ptr.p_fp->f_data;
2366 int rv, s;
2367
2368 s = solock(so);
2369 if (kev != NULL((void *)0) && (kn->kn_flagskn_kevent.flags & EV_ONESHOT0x0010))
2370 rv = 1;
2371 else
2372 rv = filt_solisten_common(kn, so);
2373 if (rv != 0)
2374 knote_submit(kn, kev);
2375 sounlock(so, s);
2376
2377 return (rv);
2378}
2379
2380void
2381klist_soassertlk(void *arg)
2382{
2383 struct socket *so = arg;
2384
2385 soassertlocked(so);
2386}
2387
2388int
2389klist_solock(void *arg)
2390{
2391 struct socket *so = arg;
2392
2393 return (solock(so));
2394}
2395
2396void
2397klist_sounlock(void *arg, int ls)
2398{
2399 struct socket *so = arg;
2400
2401 sounlock(so, ls);
2402}
2403
2404const struct klistops socket_klistops = {
2405 .klo_assertlk = klist_soassertlk,
2406 .klo_lock = klist_solock,
2407 .klo_unlock = klist_sounlock,
2408};
2409
2410#ifdef DDB1
2411void
2412sobuf_print(struct sockbuf *,
2413 int (*)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))));
2414
2415void
2416sobuf_print(struct sockbuf *sb,
2417 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
2418{
2419 (*pr)("\tsb_cc: %lu\n", sb->sb_cc);
2420 (*pr)("\tsb_datacc: %lu\n", sb->sb_datacc);
2421 (*pr)("\tsb_hiwat: %lu\n", sb->sb_hiwat);
2422 (*pr)("\tsb_wat: %lu\n", sb->sb_wat);
2423 (*pr)("\tsb_mbcnt: %lu\n", sb->sb_mbcnt);
2424 (*pr)("\tsb_mbmax: %lu\n", sb->sb_mbmax);
2425 (*pr)("\tsb_lowat: %ld\n", sb->sb_lowat);
2426 (*pr)("\tsb_mb: %p\n", sb->sb_mb);
2427 (*pr)("\tsb_mbtail: %p\n", sb->sb_mbtail);
2428 (*pr)("\tsb_lastrecord: %p\n", sb->sb_lastrecord);
2429 (*pr)("\tsb_sel: ...\n");
2430 (*pr)("\tsb_flags: %i\n", sb->sb_flags);
2431 (*pr)("\tsb_timeo_nsecs: %llu\n", sb->sb_timeo_nsecs);
2432}
2433
2434void
2435so_print(void *v,
2436 int (*pr)(const char *, ...) __attribute__((__format__(__kprintf__,1,2))))
2437{
2438 struct socket *so = v;
2439
2440 (*pr)("socket %p\n", so);
2441 (*pr)("so_type: %i\n", so->so_type);
2442 (*pr)("so_options: 0x%04x\n", so->so_options); /* %b */
2443 (*pr)("so_linger: %i\n", so->so_linger);
2444 (*pr)("so_state: 0x%04x\n", so->so_state);
2445 (*pr)("so_pcb: %p\n", so->so_pcb);
2446 (*pr)("so_proto: %p\n", so->so_proto);
2447 (*pr)("so_sigio: %p\n", so->so_sigio.sir_sigio);
2448
2449 (*pr)("so_head: %p\n", so->so_head);
2450 (*pr)("so_onq: %p\n", so->so_onq);
2451 (*pr)("so_q0: @%p first: %p\n", &so->so_q0, TAILQ_FIRST(&so->so_q0)((&so->so_q0)->tqh_first));
2452 (*pr)("so_q: @%p first: %p\n", &so->so_q, TAILQ_FIRST(&so->so_q)((&so->so_q)->tqh_first));
2453 (*pr)("so_eq: next: %p\n", TAILQ_NEXT(so, so_qe)((so)->so_qe.tqe_next));
2454 (*pr)("so_q0len: %i\n", so->so_q0len);
2455 (*pr)("so_qlen: %i\n", so->so_qlen);
2456 (*pr)("so_qlimit: %i\n", so->so_qlimit);
2457 (*pr)("so_timeo: %i\n", so->so_timeo);
2458 (*pr)("so_obmark: %lu\n", so->so_oobmark);
2459
2460 (*pr)("so_sp: %p\n", so->so_sp);
2461 if (so->so_sp != NULL((void *)0)) {
2462 (*pr)("\tssp_socket: %p\n", so->so_sp->ssp_socket);
2463 (*pr)("\tssp_soback: %p\n", so->so_sp->ssp_soback);
2464 (*pr)("\tssp_len: %lld\n",
2465 (unsigned long long)so->so_sp->ssp_len);
2466 (*pr)("\tssp_max: %lld\n",
2467 (unsigned long long)so->so_sp->ssp_max);
2468 (*pr)("\tssp_idletv: %lld %ld\n", so->so_sp->ssp_idletv.tv_sec,
2469 so->so_sp->ssp_idletv.tv_usec);
2470 (*pr)("\tssp_idleto: %spending (@%i)\n",
2471 timeout_pending(&so->so_sp->ssp_idleto)((&so->so_sp->ssp_idleto)->to_flags & 0x02) ? "" : "not ",
2472 so->so_sp->ssp_idleto.to_time);
2473 }
2474
2475 (*pr)("so_rcv:\n");
2476 sobuf_print(&so->so_rcv, pr);
2477 (*pr)("so_snd:\n");
2478 sobuf_print(&so->so_snd, pr);
2479
2480 (*pr)("so_upcall: %p so_upcallarg: %p\n",
2481 so->so_upcall, so->so_upcallarg);
2482
2483 (*pr)("so_euid: %d so_ruid: %d\n", so->so_euid, so->so_ruid);
2484 (*pr)("so_egid: %d so_rgid: %d\n", so->so_egid, so->so_rgid);
2485 (*pr)("so_cpid: %d\n", so->so_cpid);
2486}
2487#endif