1/*	$NetBSD: kttcp.c,v 1.29 2011/12/20 23:56:28 christos Exp $	*/
2
3/*
4 * Copyright (c) 2002 Wasabi Systems, Inc.
5 * All rights reserved.
6 *
7 * Written by Frank van der Linden and Jason R. Thorpe for
8 * Wasabi Systems, Inc.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 *    must display the following acknowledgement:
20 *	This product includes software developed for the NetBSD Project by
21 *	Wasabi Systems, Inc.
22 * 4. The name of Wasabi Systems, Inc. may not be used to endorse
23 *    or promote products derived from this software without specific prior
24 *    written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL WASABI SYSTEMS, INC
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39/*
40 * kttcp.c -- provides kernel support for testing network testing,
41 *            see kttcp(4)
42 */
43
44#include <sys/cdefs.h>
45__KERNEL_RCSID(0, "$NetBSD: kttcp.c,v 1.29 2011/12/20 23:56:28 christos Exp $");
46
47#include <sys/param.h>
48#include <sys/types.h>
49#include <sys/ioctl.h>
50#include <sys/file.h>
51#include <sys/filedesc.h>
52#include <sys/conf.h>
53#include <sys/systm.h>
54#include <sys/protosw.h>
55#include <sys/proc.h>
56#include <sys/resourcevar.h>
57#include <sys/signal.h>
58#include <sys/socketvar.h>
59#include <sys/socket.h>
60#include <sys/mbuf.h>
61#include <sys/mount.h>
62#include <sys/syscallargs.h>
63
64#include <dev/kttcpio.h>
65
66static int kttcp_send(struct lwp *l, struct kttcp_io_args *);
67static int kttcp_recv(struct lwp *l, struct kttcp_io_args *);
68static int kttcp_sosend(struct socket *, unsigned long long,
69			unsigned long long *, struct lwp *, int);
70static int kttcp_soreceive(struct socket *, unsigned long long,
71			   unsigned long long *, struct lwp *, int *);
72
73void	kttcpattach(int);
74
75dev_type_ioctl(kttcpioctl);
76
77const struct cdevsw kttcp_cdevsw = {
78	nullopen, nullclose, noread, nowrite, kttcpioctl,
79	nostop, notty, nopoll, nommap, nokqfilter, D_OTHER
80};
81
82void
83kttcpattach(int count)
84{
85	/* Do nothing. */
86}
87
88int
89kttcpioctl(dev_t dev, u_long cmd, void *data, int flag,
90    struct lwp *l)
91{
92	int error;
93
94	if ((flag & FWRITE) == 0)
95		return EPERM;
96
97	switch (cmd) {
98	case KTTCP_IO_SEND:
99		error = kttcp_send(l, (struct kttcp_io_args *) data);
100		break;
101
102	case KTTCP_IO_RECV:
103		error = kttcp_recv(l, (struct kttcp_io_args *) data);
104		break;
105
106	default:
107		return EINVAL;
108	}
109
110	return error;
111}
112
113static int
114kttcp_send(struct lwp *l, struct kttcp_io_args *kio)
115{
116	struct socket *so;
117	int error;
118	struct timeval t0, t1;
119	unsigned long long len, done;
120
121	if (kio->kio_totalsize >= KTTCP_MAX_XMIT)
122		return EINVAL;
123
124	if ((error = fd_getsock(kio->kio_socket, &so)) != 0)
125		return error;
126
127	len = kio->kio_totalsize;
128	microtime(&t0);
129	do {
130		error = kttcp_sosend(so, len, &done, l, 0);
131		len -= done;
132	} while (error == 0 && len > 0);
133
134	fd_putfile(kio->kio_socket);
135
136	microtime(&t1);
137	if (error != 0)
138		return error;
139	timersub(&t1, &t0, &kio->kio_elapsed);
140
141	kio->kio_bytesdone = kio->kio_totalsize - len;
142
143	return 0;
144}
145
146static int
147kttcp_recv(struct lwp *l, struct kttcp_io_args *kio)
148{
149	struct socket *so;
150	int error;
151	struct timeval t0, t1;
152	unsigned long long len, done;
153
154	done = 0;	/* XXX gcc */
155
156	if (kio->kio_totalsize > KTTCP_MAX_XMIT)
157		return EINVAL;
158
159	if ((error = fd_getsock(kio->kio_socket, &so)) != 0)
160		return error;
161	len = kio->kio_totalsize;
162	microtime(&t0);
163	do {
164		error = kttcp_soreceive(so, len, &done, l, NULL);
165		len -= done;
166	} while (error == 0 && len > 0 && done > 0);
167
168	fd_putfile(kio->kio_socket);
169
170	microtime(&t1);
171	if (error == EPIPE)
172		error = 0;
173	if (error != 0)
174		return error;
175	timersub(&t1, &t0, &kio->kio_elapsed);
176
177	kio->kio_bytesdone = kio->kio_totalsize - len;
178
179	return 0;
180}
181
182#define SBLOCKWAIT(f)   (((f) & MSG_DONTWAIT) ? M_NOWAIT : M_WAITOK)
183
184/*
185 * Slightly changed version of sosend()
186 */
187static int
188kttcp_sosend(struct socket *so, unsigned long long slen,
189	     unsigned long long *done, struct lwp *l, int flags)
190{
191	struct mbuf **mp, *m, *top;
192	long space, len, mlen;
193	int error, dontroute, atomic;
194	long long resid;
195
196	atomic = sosendallatonce(so);
197	resid = slen;
198	top = NULL;
199	/*
200	 * In theory resid should be unsigned.
201	 * However, space must be signed, as it might be less than 0
202	 * if we over-committed, and we must use a signed comparison
203	 * of space and resid.  On the other hand, a negative resid
204	 * causes us to loop sending 0-length segments to the protocol.
205	 */
206	if (resid < 0) {
207		error = EINVAL;
208		goto out;
209	}
210	dontroute =
211	    (flags & MSG_DONTROUTE) && (so->so_options & SO_DONTROUTE) == 0 &&
212	    (so->so_proto->pr_flags & PR_ATOMIC);
213	l->l_ru.ru_msgsnd++;
214#define	snderr(errno)	{ error = errno; goto release; }
215	solock(so);
216 restart:
217	if ((error = sblock(&so->so_snd, SBLOCKWAIT(flags))) != 0)
218		goto out;
219	do {
220		if (so->so_state & SS_CANTSENDMORE)
221			snderr(EPIPE);
222		if (so->so_error) {
223			error = so->so_error;
224			so->so_error = 0;
225			goto release;
226		}
227		if ((so->so_state & SS_ISCONNECTED) == 0) {
228			if (so->so_proto->pr_flags & PR_CONNREQUIRED) {
229				if ((so->so_state & SS_ISCONFIRMING) == 0)
230					snderr(ENOTCONN);
231			} else
232				snderr(EDESTADDRREQ);
233		}
234		space = sbspace(&so->so_snd);
235		if (flags & MSG_OOB)
236			space += 1024;
237		if ((atomic && resid > so->so_snd.sb_hiwat))
238			snderr(EMSGSIZE);
239		if (space < resid && (atomic || space < so->so_snd.sb_lowat)) {
240			if (so->so_state & SS_NBIO)
241				snderr(EWOULDBLOCK);
242			SBLASTRECORDCHK(&so->so_rcv,
243			    "kttcp_soreceive sbwait 1");
244			SBLASTMBUFCHK(&so->so_rcv,
245			    "kttcp_soreceive sbwait 1");
246			sbunlock(&so->so_snd);
247			error = sbwait(&so->so_snd);
248			if (error)
249				goto out;
250			goto restart;
251		}
252		mp = &top;
253		do {
254			sounlock(so);
255			do {
256				if (top == 0) {
257					m = m_gethdr(M_WAIT, MT_DATA);
258					mlen = MHLEN;
259					m->m_pkthdr.len = 0;
260					m->m_pkthdr.rcvif = NULL;
261				} else {
262					m = m_get(M_WAIT, MT_DATA);
263					mlen = MLEN;
264				}
265				if (resid >= MINCLSIZE && space >= MCLBYTES) {
266					m_clget(m, M_WAIT);
267					if ((m->m_flags & M_EXT) == 0)
268						goto nopages;
269					mlen = MCLBYTES;
270#ifdef	MAPPED_MBUFS
271					len = lmin(MCLBYTES, resid);
272#else
273					if (atomic && top == 0) {
274						len = lmin(MCLBYTES - max_hdr,
275						    resid);
276						m->m_data += max_hdr;
277					} else
278						len = lmin(MCLBYTES, resid);
279#endif
280					space -= len;
281				} else {
282nopages:
283					len = lmin(lmin(mlen, resid), space);
284					space -= len;
285					/*
286					 * For datagram protocols, leave room
287					 * for protocol headers in first mbuf.
288					 */
289					if (atomic && top == 0 && len < mlen)
290						MH_ALIGN(m, len);
291				}
292				resid -= len;
293				m->m_len = len;
294				*mp = m;
295				top->m_pkthdr.len += len;
296				if (error)
297					goto release;
298				mp = &m->m_next;
299				if (resid <= 0) {
300					if (flags & MSG_EOR)
301						top->m_flags |= M_EOR;
302					break;
303				}
304			} while (space > 0 && atomic);
305			solock(so);
306
307			if (so->so_state & SS_CANTSENDMORE)
308				snderr(EPIPE);
309			if (dontroute)
310				so->so_options |= SO_DONTROUTE;
311			if (resid > 0)
312				so->so_state |= SS_MORETOCOME;
313			error = (*so->so_proto->pr_usrreq)(so,
314			    (flags & MSG_OOB) ? PRU_SENDOOB : PRU_SEND,
315			    top, NULL, NULL, l);
316			if (dontroute)
317				so->so_options &= ~SO_DONTROUTE;
318			if (resid > 0)
319				so->so_state &= ~SS_MORETOCOME;
320			top = 0;
321			mp = &top;
322			if (error)
323				goto release;
324		} while (resid && space > 0);
325	} while (resid);
326
327 release:
328	sbunlock(&so->so_snd);
329 out:
330 	sounlock(so);
331	if (top)
332		m_freem(top);
333	*done = slen - resid;
334#if 0
335	printf("sosend: error %d slen %llu resid %lld\n", error, slen, resid);
336#endif
337	return (error);
338}
339
340static int
341kttcp_soreceive(struct socket *so, unsigned long long slen,
342    unsigned long long *done, struct lwp *l, int *flagsp)
343{
344	struct mbuf *m, **mp;
345	int flags, len, error, offset, moff, type;
346	long long orig_resid, resid;
347	const struct protosw *pr;
348	struct mbuf *nextrecord;
349
350	pr = so->so_proto;
351	mp = NULL;
352	type = 0;
353	resid = orig_resid = slen;
354	if (flagsp)
355		flags = *flagsp &~ MSG_EOR;
356	else
357 		flags = 0;
358	if (flags & MSG_OOB) {
359		m = m_get(M_WAIT, MT_DATA);
360		solock(so);
361		error = (*pr->pr_usrreq)(so, PRU_RCVOOB, m,
362		    (struct mbuf *)(long)(flags & MSG_PEEK), NULL, NULL);
363		sounlock(so);
364		if (error)
365			goto bad;
366		do {
367			resid -= min(resid, m->m_len);
368			m = m_free(m);
369		} while (resid && error == 0 && m);
370 bad:
371		if (m)
372			m_freem(m);
373		return (error);
374	}
375	if (mp)
376		*mp = NULL;
377	solock(so);
378	if (so->so_state & SS_ISCONFIRMING && resid)
379		(*pr->pr_usrreq)(so, PRU_RCVD, NULL, NULL, NULL, NULL);
380 restart:
381	if ((error = sblock(&so->so_rcv, SBLOCKWAIT(flags))) != 0)
382		return (error);
383	m = so->so_rcv.sb_mb;
384	/*
385	 * If we have less data than requested, block awaiting more
386	 * (subject to any timeout) if:
387	 *   1. the current count is less than the low water mark,
388	 *   2. MSG_WAITALL is set, and it is possible to do the entire
389	 *	receive operation at once if we block (resid <= hiwat), or
390	 *   3. MSG_DONTWAIT is not set.
391	 * If MSG_WAITALL is set but resid is larger than the receive buffer,
392	 * we have to do the receive in sections, and thus risk returning
393	 * a short count if a timeout or signal occurs after we start.
394	 */
395	if (m == NULL || (((flags & MSG_DONTWAIT) == 0 &&
396	    so->so_rcv.sb_cc < resid) &&
397	    (so->so_rcv.sb_cc < so->so_rcv.sb_lowat ||
398	    ((flags & MSG_WAITALL) && resid <= so->so_rcv.sb_hiwat)) &&
399	    m->m_nextpkt == NULL && (pr->pr_flags & PR_ATOMIC) == 0)) {
400#ifdef DIAGNOSTIC
401		if (m == NULL && so->so_rcv.sb_cc)
402			panic("receive 1");
403#endif
404		if (so->so_error) {
405			if (m)
406				goto dontblock;
407			error = so->so_error;
408			if ((flags & MSG_PEEK) == 0)
409				so->so_error = 0;
410			goto release;
411		}
412		if (so->so_state & SS_CANTRCVMORE) {
413			if (m)
414				goto dontblock;
415			else
416				goto release;
417		}
418		for (; m; m = m->m_next)
419			if (m->m_type == MT_OOBDATA  || (m->m_flags & M_EOR)) {
420				m = so->so_rcv.sb_mb;
421				goto dontblock;
422			}
423		if ((so->so_state & (SS_ISCONNECTED|SS_ISCONNECTING)) == 0 &&
424		    (so->so_proto->pr_flags & PR_CONNREQUIRED)) {
425			error = ENOTCONN;
426			goto release;
427		}
428		if (resid == 0)
429			goto release;
430		if ((so->so_state & SS_NBIO) ||
431		    (flags & (MSG_DONTWAIT|MSG_NBIO))) {
432			error = EWOULDBLOCK;
433			goto release;
434		}
435		sbunlock(&so->so_rcv);
436		error = sbwait(&so->so_rcv);
437		if (error) {
438			sounlock(so);
439			return (error);
440		}
441		goto restart;
442	}
443 dontblock:
444	/*
445	 * On entry here, m points to the first record of the socket buffer.
446	 * While we process the initial mbufs containing address and control
447	 * info, we save a copy of m->m_nextpkt into nextrecord.
448	 */
449#ifdef notyet /* XXXX */
450	if (uio->uio_lwp)
451		uio->uio_lwp->l_ru.ru_msgrcv++;
452#endif
453	KASSERT(m == so->so_rcv.sb_mb);
454	SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 1");
455	SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 1");
456	nextrecord = m->m_nextpkt;
457	if (pr->pr_flags & PR_ADDR) {
458#ifdef DIAGNOSTIC
459		if (m->m_type != MT_SONAME)
460			panic("receive 1a");
461#endif
462		orig_resid = 0;
463		if (flags & MSG_PEEK) {
464			m = m->m_next;
465		} else {
466			sbfree(&so->so_rcv, m);
467			MFREE(m, so->so_rcv.sb_mb);
468			m = so->so_rcv.sb_mb;
469		}
470	}
471	while (m && m->m_type == MT_CONTROL && error == 0) {
472		if (flags & MSG_PEEK) {
473			m = m->m_next;
474		} else {
475			sbfree(&so->so_rcv, m);
476			MFREE(m, so->so_rcv.sb_mb);
477			m = so->so_rcv.sb_mb;
478		}
479	}
480
481	/*
482	 * If m is non-NULL, we have some data to read.  From now on,
483	 * make sure to keep sb_lastrecord consistent when working on
484	 * the last packet on the chain (nextrecord == NULL) and we
485	 * change m->m_nextpkt.
486	 */
487	if (m) {
488		if ((flags & MSG_PEEK) == 0) {
489			m->m_nextpkt = nextrecord;
490			/*
491			 * If nextrecord == NULL (this is a single chain),
492			 * then sb_lastrecord may not be valid here if m
493			 * was changed earlier.
494			 */
495			if (nextrecord == NULL) {
496				KASSERT(so->so_rcv.sb_mb == m);
497				so->so_rcv.sb_lastrecord = m;
498			}
499		}
500		type = m->m_type;
501		if (type == MT_OOBDATA)
502			flags |= MSG_OOB;
503	} else {
504		if ((flags & MSG_PEEK) == 0) {
505			KASSERT(so->so_rcv.sb_mb == m);
506			so->so_rcv.sb_mb = nextrecord;
507			SB_EMPTY_FIXUP(&so->so_rcv);
508		}
509	}
510	SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 2");
511	SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 2");
512
513	moff = 0;
514	offset = 0;
515	while (m && resid > 0 && error == 0) {
516		if (m->m_type == MT_OOBDATA) {
517			if (type != MT_OOBDATA)
518				break;
519		} else if (type == MT_OOBDATA)
520			break;
521#ifdef DIAGNOSTIC
522		else if (m->m_type != MT_DATA && m->m_type != MT_HEADER)
523			panic("receive 3");
524#endif
525		so->so_state &= ~SS_RCVATMARK;
526		len = resid;
527		if (so->so_oobmark && len > so->so_oobmark - offset)
528			len = so->so_oobmark - offset;
529		if (len > m->m_len - moff)
530			len = m->m_len - moff;
531		/*
532		 * If mp is set, just pass back the mbufs.
533		 * Otherwise copy them out via the uio, then free.
534		 * Sockbuf must be consistent here (points to current mbuf,
535		 * it points to next record) when we drop priority;
536		 * we must note any additions to the sockbuf when we
537		 * block interrupts again.
538		 */
539		resid -= len;
540		if (len == m->m_len - moff) {
541			if (m->m_flags & M_EOR)
542				flags |= MSG_EOR;
543			if (flags & MSG_PEEK) {
544				m = m->m_next;
545				moff = 0;
546			} else {
547				nextrecord = m->m_nextpkt;
548				sbfree(&so->so_rcv, m);
549				if (mp) {
550					*mp = m;
551					mp = &m->m_next;
552					so->so_rcv.sb_mb = m = m->m_next;
553					*mp = NULL;
554				} else {
555					MFREE(m, so->so_rcv.sb_mb);
556					m = so->so_rcv.sb_mb;
557				}
558				/*
559				 * If m != NULL, we also know that
560				 * so->so_rcv.sb_mb != NULL.
561				 */
562				KASSERT(so->so_rcv.sb_mb == m);
563				if (m) {
564					m->m_nextpkt = nextrecord;
565					if (nextrecord == NULL)
566						so->so_rcv.sb_lastrecord = m;
567				} else {
568					so->so_rcv.sb_mb = nextrecord;
569					SB_EMPTY_FIXUP(&so->so_rcv);
570				}
571				SBLASTRECORDCHK(&so->so_rcv,
572				    "kttcp_soreceive 3");
573				SBLASTMBUFCHK(&so->so_rcv,
574				    "kttcp_soreceive 3");
575			}
576		} else {
577			if (flags & MSG_PEEK)
578				moff += len;
579			else {
580				if (mp) {
581					sounlock(so);
582					*mp = m_copym(m, 0, len, M_WAIT);
583					solock(so);
584				}
585				m->m_data += len;
586				m->m_len -= len;
587				so->so_rcv.sb_cc -= len;
588			}
589		}
590		if (so->so_oobmark) {
591			if ((flags & MSG_PEEK) == 0) {
592				so->so_oobmark -= len;
593				if (so->so_oobmark == 0) {
594					so->so_state |= SS_RCVATMARK;
595					break;
596				}
597			} else {
598				offset += len;
599				if (offset == so->so_oobmark)
600					break;
601			}
602		}
603		if (flags & MSG_EOR)
604			break;
605		/*
606		 * If the MSG_WAITALL flag is set (for non-atomic socket),
607		 * we must not quit until "uio->uio_resid == 0" or an error
608		 * termination.  If a signal/timeout occurs, return
609		 * with a short count but without error.
610		 * Keep sockbuf locked against other readers.
611		 */
612		while (flags & MSG_WAITALL && m == NULL && resid > 0 &&
613		    !sosendallatonce(so) && !nextrecord) {
614			if (so->so_error || so->so_state & SS_CANTRCVMORE)
615				break;
616			/*
617			 * If we are peeking and the socket receive buffer is
618			 * full, stop since we can't get more data to peek at.
619			 */
620			if ((flags & MSG_PEEK) && sbspace(&so->so_rcv) <= 0)
621				break;
622			/*
623			 * If we've drained the socket buffer, tell the
624			 * protocol in case it needs to do something to
625			 * get it filled again.
626			 */
627			if ((pr->pr_flags & PR_WANTRCVD) && so->so_pcb)
628				(*pr->pr_usrreq)(so, PRU_RCVD, NULL,
629				    (struct mbuf *)(long)flags, NULL, NULL);
630			SBLASTRECORDCHK(&so->so_rcv,
631			    "kttcp_soreceive sbwait 2");
632			SBLASTMBUFCHK(&so->so_rcv,
633			    "kttcp_soreceive sbwait 2");
634			error = sbwait(&so->so_rcv);
635			if (error) {
636				sbunlock(&so->so_rcv);
637				sounlock(so);
638				return (0);
639			}
640			if ((m = so->so_rcv.sb_mb) != NULL)
641				nextrecord = m->m_nextpkt;
642		}
643	}
644
645	if (m && pr->pr_flags & PR_ATOMIC) {
646		flags |= MSG_TRUNC;
647		if ((flags & MSG_PEEK) == 0)
648			(void) sbdroprecord(&so->so_rcv);
649	}
650	if ((flags & MSG_PEEK) == 0) {
651		if (m == NULL) {
652			/*
653			 * First part is an SB_EMPTY_FIXUP().  Second part
654			 * makes sure sb_lastrecord is up-to-date if
655			 * there is still data in the socket buffer.
656			 */
657			so->so_rcv.sb_mb = nextrecord;
658			if (so->so_rcv.sb_mb == NULL) {
659				so->so_rcv.sb_mbtail = NULL;
660				so->so_rcv.sb_lastrecord = NULL;
661			} else if (nextrecord->m_nextpkt == NULL)
662				so->so_rcv.sb_lastrecord = nextrecord;
663		}
664		SBLASTRECORDCHK(&so->so_rcv, "kttcp_soreceive 4");
665		SBLASTMBUFCHK(&so->so_rcv, "kttcp_soreceive 4");
666		if (pr->pr_flags & PR_WANTRCVD && so->so_pcb)
667			(*pr->pr_usrreq)(so, PRU_RCVD, NULL,
668			    (struct mbuf *)(long)flags, NULL, NULL);
669	}
670	if (orig_resid == resid && orig_resid &&
671	    (flags & MSG_EOR) == 0 && (so->so_state & SS_CANTRCVMORE) == 0) {
672		sbunlock(&so->so_rcv);
673		goto restart;
674	}
675
676	if (flagsp)
677		*flagsp |= flags;
678 release:
679	sbunlock(&so->so_rcv);
680	sounlock(so);
681	*done = slen - resid;
682#if 0
683	printf("soreceive: error %d slen %llu resid %lld\n", error, slen, resid);
684#endif
685	return (error);
686}
687