Deleted Added
full compact
sctp_syscalls.c (123094) sctp_syscalls.c (123811)
1/*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * sendfile(2) and related extensions:
6 * Copyright (c) 1998, David Greenman. 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. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
37 */
38
39#include <sys/cdefs.h>
1/*
2 * Copyright (c) 1982, 1986, 1989, 1990, 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * sendfile(2) and related extensions:
6 * Copyright (c) 1998, David Greenman. 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. All advertising materials mentioning features or use of this software
17 * must display the following acknowledgement:
18 * This product includes software developed by the University of
19 * California, Berkeley and its contributors.
20 * 4. Neither the name of the University nor the names of its contributors
21 * may be used to endorse or promote products derived from this software
22 * without specific prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 *
36 * @(#)uipc_syscalls.c 8.4 (Berkeley) 2/21/94
37 */
38
39#include <sys/cdefs.h>
40__FBSDID("$FreeBSD: head/sys/kern/uipc_syscalls.c 123094 2003-12-01 22:12:50Z dg $");
40__FBSDID("$FreeBSD: head/sys/kern/uipc_syscalls.c 123811 2003-12-24 18:47:43Z alfred $");
41
42#include "opt_compat.h"
43#include "opt_ktrace.h"
44#include "opt_mac.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/lock.h>
50#include <sys/mac.h>
51#include <sys/mutex.h>
52#include <sys/sysproto.h>
53#include <sys/malloc.h>
54#include <sys/filedesc.h>
55#include <sys/event.h>
56#include <sys/proc.h>
57#include <sys/fcntl.h>
58#include <sys/file.h>
59#include <sys/filio.h>
60#include <sys/mount.h>
61#include <sys/mbuf.h>
62#include <sys/protosw.h>
63#include <sys/sf_buf.h>
64#include <sys/socket.h>
65#include <sys/socketvar.h>
66#include <sys/signalvar.h>
67#include <sys/syscallsubr.h>
68#include <sys/uio.h>
69#include <sys/vnode.h>
70#ifdef KTRACE
71#include <sys/ktrace.h>
72#endif
73
74#include <vm/vm.h>
75#include <vm/vm_object.h>
76#include <vm/vm_page.h>
77#include <vm/vm_pageout.h>
78#include <vm/vm_kern.h>
79#include <vm/vm_extern.h>
80
81static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
82static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
83
84static int accept1(struct thread *td, struct accept_args *uap, int compat);
85static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat);
86static int getsockname1(struct thread *td, struct getsockname_args *uap,
87 int compat);
88static int getpeername1(struct thread *td, struct getpeername_args *uap,
89 int compat);
90
91/*
92 * System call interface to the socket abstraction.
93 */
94#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
95#define COMPAT_OLDSOCK
96#endif
97
98/*
99 * MPSAFE
100 */
101int
102socket(td, uap)
103 struct thread *td;
104 register struct socket_args /* {
105 int domain;
106 int type;
107 int protocol;
108 } */ *uap;
109{
110 struct filedesc *fdp;
111 struct socket *so;
112 struct file *fp;
113 int fd, error;
114
115 mtx_lock(&Giant);
116 fdp = td->td_proc->p_fd;
117 error = falloc(td, &fp, &fd);
118 if (error)
119 goto done2;
120 /* An extra reference on `fp' has been held for us by falloc(). */
121 error = socreate(uap->domain, &so, uap->type, uap->protocol,
122 td->td_ucred, td);
123 FILEDESC_LOCK(fdp);
124 if (error) {
125 if (fdp->fd_ofiles[fd] == fp) {
126 fdp->fd_ofiles[fd] = NULL;
127 FILEDESC_UNLOCK(fdp);
128 fdrop(fp, td);
129 } else
130 FILEDESC_UNLOCK(fdp);
131 } else {
132 fp->f_data = so; /* already has ref count */
133 fp->f_flag = FREAD|FWRITE;
134 fp->f_ops = &socketops;
135 fp->f_type = DTYPE_SOCKET;
136 FILEDESC_UNLOCK(fdp);
137 td->td_retval[0] = fd;
138 }
139 fdrop(fp, td);
140done2:
141 mtx_unlock(&Giant);
142 return (error);
143}
144
145/*
146 * MPSAFE
147 */
148/* ARGSUSED */
149int
150bind(td, uap)
151 struct thread *td;
152 register struct bind_args /* {
153 int s;
154 caddr_t name;
155 int namelen;
156 } */ *uap;
157{
158 struct sockaddr *sa;
159 int error;
160
161 if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0)
162 return (error);
163
164 return (kern_bind(td, uap->s, sa));
165}
166
167int
168kern_bind(td, fd, sa)
169 struct thread *td;
170 int fd;
171 struct sockaddr *sa;
172{
173 struct socket *so;
174 int error;
175
176 mtx_lock(&Giant);
177 if ((error = fgetsock(td, fd, &so, NULL)) != 0)
178 goto done2;
179#ifdef MAC
180 error = mac_check_socket_bind(td->td_ucred, so, sa);
181 if (error)
182 goto done1;
183#endif
184 error = sobind(so, sa, td);
185#ifdef MAC
186done1:
187#endif
188 fputsock(so);
189done2:
190 mtx_unlock(&Giant);
191 FREE(sa, M_SONAME);
192 return (error);
193}
194
195/*
196 * MPSAFE
197 */
198/* ARGSUSED */
199int
200listen(td, uap)
201 struct thread *td;
202 register struct listen_args /* {
203 int s;
204 int backlog;
205 } */ *uap;
206{
207 struct socket *so;
208 int error;
209
210 mtx_lock(&Giant);
211 if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
212#ifdef MAC
213 error = mac_check_socket_listen(td->td_ucred, so);
214 if (error)
215 goto done;
216#endif
217 error = solisten(so, uap->backlog, td);
218#ifdef MAC
219done:
220#endif
221 fputsock(so);
222 }
223 mtx_unlock(&Giant);
224 return(error);
225}
226
227/*
228 * accept1()
229 * MPSAFE
230 */
231static int
232accept1(td, uap, compat)
233 struct thread *td;
234 register struct accept_args /* {
235 int s;
41
42#include "opt_compat.h"
43#include "opt_ktrace.h"
44#include "opt_mac.h"
45
46#include <sys/param.h>
47#include <sys/systm.h>
48#include <sys/kernel.h>
49#include <sys/lock.h>
50#include <sys/mac.h>
51#include <sys/mutex.h>
52#include <sys/sysproto.h>
53#include <sys/malloc.h>
54#include <sys/filedesc.h>
55#include <sys/event.h>
56#include <sys/proc.h>
57#include <sys/fcntl.h>
58#include <sys/file.h>
59#include <sys/filio.h>
60#include <sys/mount.h>
61#include <sys/mbuf.h>
62#include <sys/protosw.h>
63#include <sys/sf_buf.h>
64#include <sys/socket.h>
65#include <sys/socketvar.h>
66#include <sys/signalvar.h>
67#include <sys/syscallsubr.h>
68#include <sys/uio.h>
69#include <sys/vnode.h>
70#ifdef KTRACE
71#include <sys/ktrace.h>
72#endif
73
74#include <vm/vm.h>
75#include <vm/vm_object.h>
76#include <vm/vm_page.h>
77#include <vm/vm_pageout.h>
78#include <vm/vm_kern.h>
79#include <vm/vm_extern.h>
80
81static int sendit(struct thread *td, int s, struct msghdr *mp, int flags);
82static int recvit(struct thread *td, int s, struct msghdr *mp, void *namelenp);
83
84static int accept1(struct thread *td, struct accept_args *uap, int compat);
85static int do_sendfile(struct thread *td, struct sendfile_args *uap, int compat);
86static int getsockname1(struct thread *td, struct getsockname_args *uap,
87 int compat);
88static int getpeername1(struct thread *td, struct getpeername_args *uap,
89 int compat);
90
91/*
92 * System call interface to the socket abstraction.
93 */
94#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
95#define COMPAT_OLDSOCK
96#endif
97
98/*
99 * MPSAFE
100 */
101int
102socket(td, uap)
103 struct thread *td;
104 register struct socket_args /* {
105 int domain;
106 int type;
107 int protocol;
108 } */ *uap;
109{
110 struct filedesc *fdp;
111 struct socket *so;
112 struct file *fp;
113 int fd, error;
114
115 mtx_lock(&Giant);
116 fdp = td->td_proc->p_fd;
117 error = falloc(td, &fp, &fd);
118 if (error)
119 goto done2;
120 /* An extra reference on `fp' has been held for us by falloc(). */
121 error = socreate(uap->domain, &so, uap->type, uap->protocol,
122 td->td_ucred, td);
123 FILEDESC_LOCK(fdp);
124 if (error) {
125 if (fdp->fd_ofiles[fd] == fp) {
126 fdp->fd_ofiles[fd] = NULL;
127 FILEDESC_UNLOCK(fdp);
128 fdrop(fp, td);
129 } else
130 FILEDESC_UNLOCK(fdp);
131 } else {
132 fp->f_data = so; /* already has ref count */
133 fp->f_flag = FREAD|FWRITE;
134 fp->f_ops = &socketops;
135 fp->f_type = DTYPE_SOCKET;
136 FILEDESC_UNLOCK(fdp);
137 td->td_retval[0] = fd;
138 }
139 fdrop(fp, td);
140done2:
141 mtx_unlock(&Giant);
142 return (error);
143}
144
145/*
146 * MPSAFE
147 */
148/* ARGSUSED */
149int
150bind(td, uap)
151 struct thread *td;
152 register struct bind_args /* {
153 int s;
154 caddr_t name;
155 int namelen;
156 } */ *uap;
157{
158 struct sockaddr *sa;
159 int error;
160
161 if ((error = getsockaddr(&sa, uap->name, uap->namelen)) != 0)
162 return (error);
163
164 return (kern_bind(td, uap->s, sa));
165}
166
167int
168kern_bind(td, fd, sa)
169 struct thread *td;
170 int fd;
171 struct sockaddr *sa;
172{
173 struct socket *so;
174 int error;
175
176 mtx_lock(&Giant);
177 if ((error = fgetsock(td, fd, &so, NULL)) != 0)
178 goto done2;
179#ifdef MAC
180 error = mac_check_socket_bind(td->td_ucred, so, sa);
181 if (error)
182 goto done1;
183#endif
184 error = sobind(so, sa, td);
185#ifdef MAC
186done1:
187#endif
188 fputsock(so);
189done2:
190 mtx_unlock(&Giant);
191 FREE(sa, M_SONAME);
192 return (error);
193}
194
195/*
196 * MPSAFE
197 */
198/* ARGSUSED */
199int
200listen(td, uap)
201 struct thread *td;
202 register struct listen_args /* {
203 int s;
204 int backlog;
205 } */ *uap;
206{
207 struct socket *so;
208 int error;
209
210 mtx_lock(&Giant);
211 if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
212#ifdef MAC
213 error = mac_check_socket_listen(td->td_ucred, so);
214 if (error)
215 goto done;
216#endif
217 error = solisten(so, uap->backlog, td);
218#ifdef MAC
219done:
220#endif
221 fputsock(so);
222 }
223 mtx_unlock(&Giant);
224 return(error);
225}
226
227/*
228 * accept1()
229 * MPSAFE
230 */
231static int
232accept1(td, uap, compat)
233 struct thread *td;
234 register struct accept_args /* {
235 int s;
236 caddr_t name;
237 int *anamelen;
236 struct sockaddr * __restrict name;
237 socklen_t * __restrict anamelen;
238 } */ *uap;
239 int compat;
240{
241 struct filedesc *fdp;
242 struct file *nfp = NULL;
243 struct sockaddr *sa;
238 } */ *uap;
239 int compat;
240{
241 struct filedesc *fdp;
242 struct file *nfp = NULL;
243 struct sockaddr *sa;
244 int namelen, error, s;
244 socklen_t namelen;
245 int error, s;
245 struct socket *head, *so;
246 int fd;
247 u_int fflag;
248 pid_t pgid;
249 int tmp;
250
251 fdp = td->td_proc->p_fd;
252 if (uap->name) {
253 error = copyin(uap->anamelen, &namelen, sizeof (namelen));
254 if(error)
255 goto done3;
256 if (namelen < 0) {
257 error = EINVAL;
258 goto done3;
259 }
260 }
261 mtx_lock(&Giant);
262 error = fgetsock(td, uap->s, &head, &fflag);
263 if (error)
264 goto done2;
265 s = splnet();
266 if ((head->so_options & SO_ACCEPTCONN) == 0) {
267 splx(s);
268 error = EINVAL;
269 goto done;
270 }
271 while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
272 if (head->so_state & SS_CANTRCVMORE) {
273 head->so_error = ECONNABORTED;
274 break;
275 }
276 if ((head->so_state & SS_NBIO) != 0) {
277 head->so_error = EWOULDBLOCK;
278 break;
279 }
280 error = tsleep(&head->so_timeo, PSOCK | PCATCH,
281 "accept", 0);
282 if (error) {
283 splx(s);
284 goto done;
285 }
286 }
287 if (head->so_error) {
288 error = head->so_error;
289 head->so_error = 0;
290 splx(s);
291 goto done;
292 }
293
294 /*
295 * At this point we know that there is at least one connection
296 * ready to be accepted. Remove it from the queue prior to
297 * allocating the file descriptor for it since falloc() may
298 * block allowing another process to accept the connection
299 * instead.
300 */
301 so = TAILQ_FIRST(&head->so_comp);
302 TAILQ_REMOVE(&head->so_comp, so, so_list);
303 head->so_qlen--;
304
305 error = falloc(td, &nfp, &fd);
306 if (error) {
307 /*
308 * Probably ran out of file descriptors. Put the
309 * unaccepted connection back onto the queue and
310 * do another wakeup so some other process might
311 * have a chance at it.
312 */
313 TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
314 head->so_qlen++;
315 wakeup_one(&head->so_timeo);
316 splx(s);
317 goto done;
318 }
319 /* An extra reference on `nfp' has been held for us by falloc(). */
320 td->td_retval[0] = fd;
321
322 /* connection has been removed from the listen queue */
323 KNOTE(&head->so_rcv.sb_sel.si_note, 0);
324
325 so->so_state &= ~SS_COMP;
326 so->so_head = NULL;
327 pgid = fgetown(&head->so_sigio);
328 if (pgid != 0)
329 fsetown(pgid, &so->so_sigio);
330
331 FILE_LOCK(nfp);
332 soref(so); /* file descriptor reference */
333 nfp->f_data = so; /* nfp has ref count from falloc */
334 nfp->f_flag = fflag;
335 nfp->f_ops = &socketops;
336 nfp->f_type = DTYPE_SOCKET;
337 FILE_UNLOCK(nfp);
338 /* Sync socket nonblocking/async state with file flags */
339 tmp = fflag & FNONBLOCK;
340 (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
341 tmp = fflag & FASYNC;
342 (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
343 sa = 0;
344 error = soaccept(so, &sa);
345 if (error) {
346 /*
347 * return a namelen of zero for older code which might
348 * ignore the return value from accept.
349 */
350 if (uap->name != NULL) {
351 namelen = 0;
352 (void) copyout(&namelen,
353 uap->anamelen, sizeof(*uap->anamelen));
354 }
355 goto noconnection;
356 }
357 if (sa == NULL) {
358 namelen = 0;
359 if (uap->name)
360 goto gotnoname;
361 splx(s);
362 error = 0;
363 goto done;
364 }
365 if (uap->name) {
366 /* check sa_len before it is destroyed */
367 if (namelen > sa->sa_len)
368 namelen = sa->sa_len;
369#ifdef COMPAT_OLDSOCK
370 if (compat)
371 ((struct osockaddr *)sa)->sa_family =
372 sa->sa_family;
373#endif
374 error = copyout(sa, uap->name, (u_int)namelen);
375 if (!error)
376gotnoname:
377 error = copyout(&namelen,
378 uap->anamelen, sizeof (*uap->anamelen));
379 }
380noconnection:
381 if (sa)
382 FREE(sa, M_SONAME);
383
384 /*
385 * close the new descriptor, assuming someone hasn't ripped it
386 * out from under us.
387 */
388 if (error) {
389 FILEDESC_LOCK(fdp);
390 if (fdp->fd_ofiles[fd] == nfp) {
391 fdp->fd_ofiles[fd] = NULL;
392 FILEDESC_UNLOCK(fdp);
393 fdrop(nfp, td);
394 } else {
395 FILEDESC_UNLOCK(fdp);
396 }
397 }
398 splx(s);
399
400 /*
401 * Release explicitly held references before returning.
402 */
403done:
404 if (nfp != NULL)
405 fdrop(nfp, td);
406 fputsock(head);
407done2:
408 mtx_unlock(&Giant);
409done3:
410 return (error);
411}
412
413/*
414 * MPSAFE (accept1() is MPSAFE)
415 */
416int
417accept(td, uap)
418 struct thread *td;
419 struct accept_args *uap;
420{
421
422 return (accept1(td, uap, 0));
423}
424
425#ifdef COMPAT_OLDSOCK
426/*
427 * MPSAFE (accept1() is MPSAFE)
428 */
429int
430oaccept(td, uap)
431 struct thread *td;
432 struct accept_args *uap;
433{
434
435 return (accept1(td, uap, 1));
436}
437#endif /* COMPAT_OLDSOCK */
438
439/*
440 * MPSAFE
441 */
442/* ARGSUSED */
443int
444connect(td, uap)
445 struct thread *td;
446 register struct connect_args /* {
447 int s;
448 caddr_t name;
449 int namelen;
450 } */ *uap;
451{
452 struct sockaddr *sa;
453 int error;
454
455 error = getsockaddr(&sa, uap->name, uap->namelen);
456 if (error)
457 return error;
458
459 return (kern_connect(td, uap->s, sa));
460}
461
462
463int
464kern_connect(td, fd, sa)
465 struct thread *td;
466 int fd;
467 struct sockaddr *sa;
468{
469 struct socket *so;
470 int error, s;
471 int interrupted = 0;
472
473 mtx_lock(&Giant);
474 if ((error = fgetsock(td, fd, &so, NULL)) != 0)
475 goto done2;
476 if (so->so_state & SS_ISCONNECTING) {
477 error = EALREADY;
478 goto done1;
479 }
480#ifdef MAC
481 error = mac_check_socket_connect(td->td_ucred, so, sa);
482 if (error)
483 goto bad;
484#endif
485 error = soconnect(so, sa, td);
486 if (error)
487 goto bad;
488 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
489 error = EINPROGRESS;
490 goto done1;
491 }
492 s = splnet();
493 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
494 error = tsleep(&so->so_timeo, PSOCK | PCATCH, "connec", 0);
495 if (error) {
496 if (error == EINTR || error == ERESTART)
497 interrupted = 1;
498 break;
499 }
500 }
501 if (error == 0) {
502 error = so->so_error;
503 so->so_error = 0;
504 }
505 splx(s);
506bad:
507 if (!interrupted)
508 so->so_state &= ~SS_ISCONNECTING;
509 if (error == ERESTART)
510 error = EINTR;
511done1:
512 fputsock(so);
513done2:
514 mtx_unlock(&Giant);
515 FREE(sa, M_SONAME);
516 return (error);
517}
518
519/*
520 * MPSAFE
521 */
522int
523socketpair(td, uap)
524 struct thread *td;
525 register struct socketpair_args /* {
526 int domain;
527 int type;
528 int protocol;
529 int *rsv;
530 } */ *uap;
531{
532 register struct filedesc *fdp = td->td_proc->p_fd;
533 struct file *fp1, *fp2;
534 struct socket *so1, *so2;
535 int fd, error, sv[2];
536
537 mtx_lock(&Giant);
538 error = socreate(uap->domain, &so1, uap->type, uap->protocol,
539 td->td_ucred, td);
540 if (error)
541 goto done2;
542 error = socreate(uap->domain, &so2, uap->type, uap->protocol,
543 td->td_ucred, td);
544 if (error)
545 goto free1;
546 /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
547 error = falloc(td, &fp1, &fd);
548 if (error)
549 goto free2;
550 sv[0] = fd;
551 fp1->f_data = so1; /* so1 already has ref count */
552 error = falloc(td, &fp2, &fd);
553 if (error)
554 goto free3;
555 fp2->f_data = so2; /* so2 already has ref count */
556 sv[1] = fd;
557 error = soconnect2(so1, so2);
558 if (error)
559 goto free4;
560 if (uap->type == SOCK_DGRAM) {
561 /*
562 * Datagram socket connection is asymmetric.
563 */
564 error = soconnect2(so2, so1);
565 if (error)
566 goto free4;
567 }
568 FILE_LOCK(fp1);
569 fp1->f_flag = FREAD|FWRITE;
570 fp1->f_ops = &socketops;
571 fp1->f_type = DTYPE_SOCKET;
572 FILE_UNLOCK(fp1);
573 FILE_LOCK(fp2);
574 fp2->f_flag = FREAD|FWRITE;
575 fp2->f_ops = &socketops;
576 fp2->f_type = DTYPE_SOCKET;
577 FILE_UNLOCK(fp2);
578 error = copyout(sv, uap->rsv, 2 * sizeof (int));
579 fdrop(fp1, td);
580 fdrop(fp2, td);
581 goto done2;
582free4:
583 FILEDESC_LOCK(fdp);
584 if (fdp->fd_ofiles[sv[1]] == fp2) {
585 fdp->fd_ofiles[sv[1]] = NULL;
586 FILEDESC_UNLOCK(fdp);
587 fdrop(fp2, td);
588 } else
589 FILEDESC_UNLOCK(fdp);
590 fdrop(fp2, td);
591free3:
592 FILEDESC_LOCK(fdp);
593 if (fdp->fd_ofiles[sv[0]] == fp1) {
594 fdp->fd_ofiles[sv[0]] = NULL;
595 FILEDESC_UNLOCK(fdp);
596 fdrop(fp1, td);
597 } else
598 FILEDESC_UNLOCK(fdp);
599 fdrop(fp1, td);
600free2:
601 (void)soclose(so2);
602free1:
603 (void)soclose(so1);
604done2:
605 mtx_unlock(&Giant);
606 return (error);
607}
608
609static int
610sendit(td, s, mp, flags)
611 register struct thread *td;
612 int s;
613 register struct msghdr *mp;
614 int flags;
615{
616 struct mbuf *control;
617 struct sockaddr *to;
618 int error;
619
620 if (mp->msg_name != NULL) {
621 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
622 if (error) {
623 to = NULL;
624 goto bad;
625 }
626 mp->msg_name = to;
627 } else
628 to = NULL;
629
630 if (mp->msg_control) {
631 if (mp->msg_controllen < sizeof(struct cmsghdr)
632#ifdef COMPAT_OLDSOCK
633 && mp->msg_flags != MSG_COMPAT
634#endif
635 ) {
636 error = EINVAL;
637 goto bad;
638 }
639 error = sockargs(&control, mp->msg_control,
640 mp->msg_controllen, MT_CONTROL);
641 if (error)
642 goto bad;
643#ifdef COMPAT_OLDSOCK
644 if (mp->msg_flags == MSG_COMPAT) {
645 register struct cmsghdr *cm;
646
647 M_PREPEND(control, sizeof(*cm), M_TRYWAIT);
648 if (control == 0) {
649 error = ENOBUFS;
650 goto bad;
651 } else {
652 cm = mtod(control, struct cmsghdr *);
653 cm->cmsg_len = control->m_len;
654 cm->cmsg_level = SOL_SOCKET;
655 cm->cmsg_type = SCM_RIGHTS;
656 }
657 }
658#endif
659 } else {
660 control = NULL;
661 }
662
663 error = kern_sendit(td, s, mp, flags, control);
664
665bad:
666 if (to)
667 FREE(to, M_SONAME);
668 return (error);
669}
670
671int
672kern_sendit(td, s, mp, flags, control)
673 struct thread *td;
674 int s;
675 struct msghdr *mp;
676 int flags;
677 struct mbuf *control;
678{
679 struct uio auio;
680 struct iovec *iov;
681 struct socket *so;
682 int i;
683 int len, error;
684#ifdef KTRACE
685 struct iovec *ktriov = NULL;
686 struct uio ktruio;
687 int iovlen;
688#endif
689
690 mtx_lock(&Giant);
691 if ((error = fgetsock(td, s, &so, NULL)) != 0)
692 goto bad2;
693
694#ifdef MAC
695 error = mac_check_socket_send(td->td_ucred, so);
696 if (error)
697 goto bad;
698#endif
699
700 auio.uio_iov = mp->msg_iov;
701 auio.uio_iovcnt = mp->msg_iovlen;
702 auio.uio_segflg = UIO_USERSPACE;
703 auio.uio_rw = UIO_WRITE;
704 auio.uio_td = td;
705 auio.uio_offset = 0; /* XXX */
706 auio.uio_resid = 0;
707 iov = mp->msg_iov;
708 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
709 if ((auio.uio_resid += iov->iov_len) < 0) {
710 error = EINVAL;
711 goto bad;
712 }
713 }
714#ifdef KTRACE
715 if (KTRPOINT(td, KTR_GENIO)) {
716 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
717 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
718 bcopy(auio.uio_iov, ktriov, iovlen);
719 ktruio = auio;
720 }
721#endif
722 len = auio.uio_resid;
723 error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio,
724 0, control, flags, td);
725 if (error) {
726 if (auio.uio_resid != len && (error == ERESTART ||
727 error == EINTR || error == EWOULDBLOCK))
728 error = 0;
729 /* Generation of SIGPIPE can be controlled per socket */
730 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE)) {
731 PROC_LOCK(td->td_proc);
732 psignal(td->td_proc, SIGPIPE);
733 PROC_UNLOCK(td->td_proc);
734 }
735 }
736 if (error == 0)
737 td->td_retval[0] = len - auio.uio_resid;
738#ifdef KTRACE
739 if (ktriov != NULL) {
740 if (error == 0) {
741 ktruio.uio_iov = ktriov;
742 ktruio.uio_resid = td->td_retval[0];
743 ktrgenio(s, UIO_WRITE, &ktruio, error);
744 }
745 FREE(ktriov, M_TEMP);
746 }
747#endif
748bad:
749 fputsock(so);
750bad2:
751 mtx_unlock(&Giant);
752 return (error);
753}
754
755/*
756 * MPSAFE
757 */
758int
759sendto(td, uap)
760 struct thread *td;
761 register struct sendto_args /* {
762 int s;
763 caddr_t buf;
764 size_t len;
765 int flags;
766 caddr_t to;
767 int tolen;
768 } */ *uap;
769{
770 struct msghdr msg;
771 struct iovec aiov;
772 int error;
773
774 msg.msg_name = uap->to;
775 msg.msg_namelen = uap->tolen;
776 msg.msg_iov = &aiov;
777 msg.msg_iovlen = 1;
778 msg.msg_control = 0;
779#ifdef COMPAT_OLDSOCK
780 msg.msg_flags = 0;
781#endif
782 aiov.iov_base = uap->buf;
783 aiov.iov_len = uap->len;
784 error = sendit(td, uap->s, &msg, uap->flags);
785 return (error);
786}
787
788#ifdef COMPAT_OLDSOCK
789/*
790 * MPSAFE
791 */
792int
793osend(td, uap)
794 struct thread *td;
795 register struct osend_args /* {
796 int s;
797 caddr_t buf;
798 int len;
799 int flags;
800 } */ *uap;
801{
802 struct msghdr msg;
803 struct iovec aiov;
804 int error;
805
806 msg.msg_name = 0;
807 msg.msg_namelen = 0;
808 msg.msg_iov = &aiov;
809 msg.msg_iovlen = 1;
810 aiov.iov_base = uap->buf;
811 aiov.iov_len = uap->len;
812 msg.msg_control = 0;
813 msg.msg_flags = 0;
814 error = sendit(td, uap->s, &msg, uap->flags);
815 return (error);
816}
817
818/*
819 * MPSAFE
820 */
821int
822osendmsg(td, uap)
823 struct thread *td;
824 register struct osendmsg_args /* {
825 int s;
826 caddr_t msg;
827 int flags;
828 } */ *uap;
829{
830 struct msghdr msg;
831 struct iovec aiov[UIO_SMALLIOV], *iov;
832 int error;
833
834 error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
835 if (error)
836 goto done2;
837 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
838 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
839 error = EMSGSIZE;
840 goto done2;
841 }
842 MALLOC(iov, struct iovec *,
843 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
844 M_WAITOK);
845 } else {
846 iov = aiov;
847 }
848 error = copyin(msg.msg_iov, iov,
849 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
850 if (error)
851 goto done;
852 msg.msg_flags = MSG_COMPAT;
853 msg.msg_iov = iov;
854 error = sendit(td, uap->s, &msg, uap->flags);
855done:
856 if (iov != aiov)
857 FREE(iov, M_IOV);
858done2:
859 return (error);
860}
861#endif
862
863/*
864 * MPSAFE
865 */
866int
867sendmsg(td, uap)
868 struct thread *td;
869 register struct sendmsg_args /* {
870 int s;
871 caddr_t msg;
872 int flags;
873 } */ *uap;
874{
875 struct msghdr msg;
876 struct iovec aiov[UIO_SMALLIOV], *iov;
877 int error;
878
879 error = copyin(uap->msg, &msg, sizeof (msg));
880 if (error)
881 goto done2;
882 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
883 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
884 error = EMSGSIZE;
885 goto done2;
886 }
887 MALLOC(iov, struct iovec *,
888 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
889 M_WAITOK);
890 } else {
891 iov = aiov;
892 }
893 if (msg.msg_iovlen &&
894 (error = copyin(msg.msg_iov, iov,
895 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
896 goto done;
897 msg.msg_iov = iov;
898#ifdef COMPAT_OLDSOCK
899 msg.msg_flags = 0;
900#endif
901 error = sendit(td, uap->s, &msg, uap->flags);
902done:
903 if (iov != aiov)
904 FREE(iov, M_IOV);
905done2:
906 return (error);
907}
908
909static int
910recvit(td, s, mp, namelenp)
911 register struct thread *td;
912 int s;
913 register struct msghdr *mp;
914 void *namelenp;
915{
916 struct uio auio;
917 register struct iovec *iov;
918 register int i;
246 struct socket *head, *so;
247 int fd;
248 u_int fflag;
249 pid_t pgid;
250 int tmp;
251
252 fdp = td->td_proc->p_fd;
253 if (uap->name) {
254 error = copyin(uap->anamelen, &namelen, sizeof (namelen));
255 if(error)
256 goto done3;
257 if (namelen < 0) {
258 error = EINVAL;
259 goto done3;
260 }
261 }
262 mtx_lock(&Giant);
263 error = fgetsock(td, uap->s, &head, &fflag);
264 if (error)
265 goto done2;
266 s = splnet();
267 if ((head->so_options & SO_ACCEPTCONN) == 0) {
268 splx(s);
269 error = EINVAL;
270 goto done;
271 }
272 while (TAILQ_EMPTY(&head->so_comp) && head->so_error == 0) {
273 if (head->so_state & SS_CANTRCVMORE) {
274 head->so_error = ECONNABORTED;
275 break;
276 }
277 if ((head->so_state & SS_NBIO) != 0) {
278 head->so_error = EWOULDBLOCK;
279 break;
280 }
281 error = tsleep(&head->so_timeo, PSOCK | PCATCH,
282 "accept", 0);
283 if (error) {
284 splx(s);
285 goto done;
286 }
287 }
288 if (head->so_error) {
289 error = head->so_error;
290 head->so_error = 0;
291 splx(s);
292 goto done;
293 }
294
295 /*
296 * At this point we know that there is at least one connection
297 * ready to be accepted. Remove it from the queue prior to
298 * allocating the file descriptor for it since falloc() may
299 * block allowing another process to accept the connection
300 * instead.
301 */
302 so = TAILQ_FIRST(&head->so_comp);
303 TAILQ_REMOVE(&head->so_comp, so, so_list);
304 head->so_qlen--;
305
306 error = falloc(td, &nfp, &fd);
307 if (error) {
308 /*
309 * Probably ran out of file descriptors. Put the
310 * unaccepted connection back onto the queue and
311 * do another wakeup so some other process might
312 * have a chance at it.
313 */
314 TAILQ_INSERT_HEAD(&head->so_comp, so, so_list);
315 head->so_qlen++;
316 wakeup_one(&head->so_timeo);
317 splx(s);
318 goto done;
319 }
320 /* An extra reference on `nfp' has been held for us by falloc(). */
321 td->td_retval[0] = fd;
322
323 /* connection has been removed from the listen queue */
324 KNOTE(&head->so_rcv.sb_sel.si_note, 0);
325
326 so->so_state &= ~SS_COMP;
327 so->so_head = NULL;
328 pgid = fgetown(&head->so_sigio);
329 if (pgid != 0)
330 fsetown(pgid, &so->so_sigio);
331
332 FILE_LOCK(nfp);
333 soref(so); /* file descriptor reference */
334 nfp->f_data = so; /* nfp has ref count from falloc */
335 nfp->f_flag = fflag;
336 nfp->f_ops = &socketops;
337 nfp->f_type = DTYPE_SOCKET;
338 FILE_UNLOCK(nfp);
339 /* Sync socket nonblocking/async state with file flags */
340 tmp = fflag & FNONBLOCK;
341 (void) fo_ioctl(nfp, FIONBIO, &tmp, td->td_ucred, td);
342 tmp = fflag & FASYNC;
343 (void) fo_ioctl(nfp, FIOASYNC, &tmp, td->td_ucred, td);
344 sa = 0;
345 error = soaccept(so, &sa);
346 if (error) {
347 /*
348 * return a namelen of zero for older code which might
349 * ignore the return value from accept.
350 */
351 if (uap->name != NULL) {
352 namelen = 0;
353 (void) copyout(&namelen,
354 uap->anamelen, sizeof(*uap->anamelen));
355 }
356 goto noconnection;
357 }
358 if (sa == NULL) {
359 namelen = 0;
360 if (uap->name)
361 goto gotnoname;
362 splx(s);
363 error = 0;
364 goto done;
365 }
366 if (uap->name) {
367 /* check sa_len before it is destroyed */
368 if (namelen > sa->sa_len)
369 namelen = sa->sa_len;
370#ifdef COMPAT_OLDSOCK
371 if (compat)
372 ((struct osockaddr *)sa)->sa_family =
373 sa->sa_family;
374#endif
375 error = copyout(sa, uap->name, (u_int)namelen);
376 if (!error)
377gotnoname:
378 error = copyout(&namelen,
379 uap->anamelen, sizeof (*uap->anamelen));
380 }
381noconnection:
382 if (sa)
383 FREE(sa, M_SONAME);
384
385 /*
386 * close the new descriptor, assuming someone hasn't ripped it
387 * out from under us.
388 */
389 if (error) {
390 FILEDESC_LOCK(fdp);
391 if (fdp->fd_ofiles[fd] == nfp) {
392 fdp->fd_ofiles[fd] = NULL;
393 FILEDESC_UNLOCK(fdp);
394 fdrop(nfp, td);
395 } else {
396 FILEDESC_UNLOCK(fdp);
397 }
398 }
399 splx(s);
400
401 /*
402 * Release explicitly held references before returning.
403 */
404done:
405 if (nfp != NULL)
406 fdrop(nfp, td);
407 fputsock(head);
408done2:
409 mtx_unlock(&Giant);
410done3:
411 return (error);
412}
413
414/*
415 * MPSAFE (accept1() is MPSAFE)
416 */
417int
418accept(td, uap)
419 struct thread *td;
420 struct accept_args *uap;
421{
422
423 return (accept1(td, uap, 0));
424}
425
426#ifdef COMPAT_OLDSOCK
427/*
428 * MPSAFE (accept1() is MPSAFE)
429 */
430int
431oaccept(td, uap)
432 struct thread *td;
433 struct accept_args *uap;
434{
435
436 return (accept1(td, uap, 1));
437}
438#endif /* COMPAT_OLDSOCK */
439
440/*
441 * MPSAFE
442 */
443/* ARGSUSED */
444int
445connect(td, uap)
446 struct thread *td;
447 register struct connect_args /* {
448 int s;
449 caddr_t name;
450 int namelen;
451 } */ *uap;
452{
453 struct sockaddr *sa;
454 int error;
455
456 error = getsockaddr(&sa, uap->name, uap->namelen);
457 if (error)
458 return error;
459
460 return (kern_connect(td, uap->s, sa));
461}
462
463
464int
465kern_connect(td, fd, sa)
466 struct thread *td;
467 int fd;
468 struct sockaddr *sa;
469{
470 struct socket *so;
471 int error, s;
472 int interrupted = 0;
473
474 mtx_lock(&Giant);
475 if ((error = fgetsock(td, fd, &so, NULL)) != 0)
476 goto done2;
477 if (so->so_state & SS_ISCONNECTING) {
478 error = EALREADY;
479 goto done1;
480 }
481#ifdef MAC
482 error = mac_check_socket_connect(td->td_ucred, so, sa);
483 if (error)
484 goto bad;
485#endif
486 error = soconnect(so, sa, td);
487 if (error)
488 goto bad;
489 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
490 error = EINPROGRESS;
491 goto done1;
492 }
493 s = splnet();
494 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0) {
495 error = tsleep(&so->so_timeo, PSOCK | PCATCH, "connec", 0);
496 if (error) {
497 if (error == EINTR || error == ERESTART)
498 interrupted = 1;
499 break;
500 }
501 }
502 if (error == 0) {
503 error = so->so_error;
504 so->so_error = 0;
505 }
506 splx(s);
507bad:
508 if (!interrupted)
509 so->so_state &= ~SS_ISCONNECTING;
510 if (error == ERESTART)
511 error = EINTR;
512done1:
513 fputsock(so);
514done2:
515 mtx_unlock(&Giant);
516 FREE(sa, M_SONAME);
517 return (error);
518}
519
520/*
521 * MPSAFE
522 */
523int
524socketpair(td, uap)
525 struct thread *td;
526 register struct socketpair_args /* {
527 int domain;
528 int type;
529 int protocol;
530 int *rsv;
531 } */ *uap;
532{
533 register struct filedesc *fdp = td->td_proc->p_fd;
534 struct file *fp1, *fp2;
535 struct socket *so1, *so2;
536 int fd, error, sv[2];
537
538 mtx_lock(&Giant);
539 error = socreate(uap->domain, &so1, uap->type, uap->protocol,
540 td->td_ucred, td);
541 if (error)
542 goto done2;
543 error = socreate(uap->domain, &so2, uap->type, uap->protocol,
544 td->td_ucred, td);
545 if (error)
546 goto free1;
547 /* On success extra reference to `fp1' and 'fp2' is set by falloc. */
548 error = falloc(td, &fp1, &fd);
549 if (error)
550 goto free2;
551 sv[0] = fd;
552 fp1->f_data = so1; /* so1 already has ref count */
553 error = falloc(td, &fp2, &fd);
554 if (error)
555 goto free3;
556 fp2->f_data = so2; /* so2 already has ref count */
557 sv[1] = fd;
558 error = soconnect2(so1, so2);
559 if (error)
560 goto free4;
561 if (uap->type == SOCK_DGRAM) {
562 /*
563 * Datagram socket connection is asymmetric.
564 */
565 error = soconnect2(so2, so1);
566 if (error)
567 goto free4;
568 }
569 FILE_LOCK(fp1);
570 fp1->f_flag = FREAD|FWRITE;
571 fp1->f_ops = &socketops;
572 fp1->f_type = DTYPE_SOCKET;
573 FILE_UNLOCK(fp1);
574 FILE_LOCK(fp2);
575 fp2->f_flag = FREAD|FWRITE;
576 fp2->f_ops = &socketops;
577 fp2->f_type = DTYPE_SOCKET;
578 FILE_UNLOCK(fp2);
579 error = copyout(sv, uap->rsv, 2 * sizeof (int));
580 fdrop(fp1, td);
581 fdrop(fp2, td);
582 goto done2;
583free4:
584 FILEDESC_LOCK(fdp);
585 if (fdp->fd_ofiles[sv[1]] == fp2) {
586 fdp->fd_ofiles[sv[1]] = NULL;
587 FILEDESC_UNLOCK(fdp);
588 fdrop(fp2, td);
589 } else
590 FILEDESC_UNLOCK(fdp);
591 fdrop(fp2, td);
592free3:
593 FILEDESC_LOCK(fdp);
594 if (fdp->fd_ofiles[sv[0]] == fp1) {
595 fdp->fd_ofiles[sv[0]] = NULL;
596 FILEDESC_UNLOCK(fdp);
597 fdrop(fp1, td);
598 } else
599 FILEDESC_UNLOCK(fdp);
600 fdrop(fp1, td);
601free2:
602 (void)soclose(so2);
603free1:
604 (void)soclose(so1);
605done2:
606 mtx_unlock(&Giant);
607 return (error);
608}
609
610static int
611sendit(td, s, mp, flags)
612 register struct thread *td;
613 int s;
614 register struct msghdr *mp;
615 int flags;
616{
617 struct mbuf *control;
618 struct sockaddr *to;
619 int error;
620
621 if (mp->msg_name != NULL) {
622 error = getsockaddr(&to, mp->msg_name, mp->msg_namelen);
623 if (error) {
624 to = NULL;
625 goto bad;
626 }
627 mp->msg_name = to;
628 } else
629 to = NULL;
630
631 if (mp->msg_control) {
632 if (mp->msg_controllen < sizeof(struct cmsghdr)
633#ifdef COMPAT_OLDSOCK
634 && mp->msg_flags != MSG_COMPAT
635#endif
636 ) {
637 error = EINVAL;
638 goto bad;
639 }
640 error = sockargs(&control, mp->msg_control,
641 mp->msg_controllen, MT_CONTROL);
642 if (error)
643 goto bad;
644#ifdef COMPAT_OLDSOCK
645 if (mp->msg_flags == MSG_COMPAT) {
646 register struct cmsghdr *cm;
647
648 M_PREPEND(control, sizeof(*cm), M_TRYWAIT);
649 if (control == 0) {
650 error = ENOBUFS;
651 goto bad;
652 } else {
653 cm = mtod(control, struct cmsghdr *);
654 cm->cmsg_len = control->m_len;
655 cm->cmsg_level = SOL_SOCKET;
656 cm->cmsg_type = SCM_RIGHTS;
657 }
658 }
659#endif
660 } else {
661 control = NULL;
662 }
663
664 error = kern_sendit(td, s, mp, flags, control);
665
666bad:
667 if (to)
668 FREE(to, M_SONAME);
669 return (error);
670}
671
672int
673kern_sendit(td, s, mp, flags, control)
674 struct thread *td;
675 int s;
676 struct msghdr *mp;
677 int flags;
678 struct mbuf *control;
679{
680 struct uio auio;
681 struct iovec *iov;
682 struct socket *so;
683 int i;
684 int len, error;
685#ifdef KTRACE
686 struct iovec *ktriov = NULL;
687 struct uio ktruio;
688 int iovlen;
689#endif
690
691 mtx_lock(&Giant);
692 if ((error = fgetsock(td, s, &so, NULL)) != 0)
693 goto bad2;
694
695#ifdef MAC
696 error = mac_check_socket_send(td->td_ucred, so);
697 if (error)
698 goto bad;
699#endif
700
701 auio.uio_iov = mp->msg_iov;
702 auio.uio_iovcnt = mp->msg_iovlen;
703 auio.uio_segflg = UIO_USERSPACE;
704 auio.uio_rw = UIO_WRITE;
705 auio.uio_td = td;
706 auio.uio_offset = 0; /* XXX */
707 auio.uio_resid = 0;
708 iov = mp->msg_iov;
709 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
710 if ((auio.uio_resid += iov->iov_len) < 0) {
711 error = EINVAL;
712 goto bad;
713 }
714 }
715#ifdef KTRACE
716 if (KTRPOINT(td, KTR_GENIO)) {
717 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
718 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
719 bcopy(auio.uio_iov, ktriov, iovlen);
720 ktruio = auio;
721 }
722#endif
723 len = auio.uio_resid;
724 error = so->so_proto->pr_usrreqs->pru_sosend(so, mp->msg_name, &auio,
725 0, control, flags, td);
726 if (error) {
727 if (auio.uio_resid != len && (error == ERESTART ||
728 error == EINTR || error == EWOULDBLOCK))
729 error = 0;
730 /* Generation of SIGPIPE can be controlled per socket */
731 if (error == EPIPE && !(so->so_options & SO_NOSIGPIPE)) {
732 PROC_LOCK(td->td_proc);
733 psignal(td->td_proc, SIGPIPE);
734 PROC_UNLOCK(td->td_proc);
735 }
736 }
737 if (error == 0)
738 td->td_retval[0] = len - auio.uio_resid;
739#ifdef KTRACE
740 if (ktriov != NULL) {
741 if (error == 0) {
742 ktruio.uio_iov = ktriov;
743 ktruio.uio_resid = td->td_retval[0];
744 ktrgenio(s, UIO_WRITE, &ktruio, error);
745 }
746 FREE(ktriov, M_TEMP);
747 }
748#endif
749bad:
750 fputsock(so);
751bad2:
752 mtx_unlock(&Giant);
753 return (error);
754}
755
756/*
757 * MPSAFE
758 */
759int
760sendto(td, uap)
761 struct thread *td;
762 register struct sendto_args /* {
763 int s;
764 caddr_t buf;
765 size_t len;
766 int flags;
767 caddr_t to;
768 int tolen;
769 } */ *uap;
770{
771 struct msghdr msg;
772 struct iovec aiov;
773 int error;
774
775 msg.msg_name = uap->to;
776 msg.msg_namelen = uap->tolen;
777 msg.msg_iov = &aiov;
778 msg.msg_iovlen = 1;
779 msg.msg_control = 0;
780#ifdef COMPAT_OLDSOCK
781 msg.msg_flags = 0;
782#endif
783 aiov.iov_base = uap->buf;
784 aiov.iov_len = uap->len;
785 error = sendit(td, uap->s, &msg, uap->flags);
786 return (error);
787}
788
789#ifdef COMPAT_OLDSOCK
790/*
791 * MPSAFE
792 */
793int
794osend(td, uap)
795 struct thread *td;
796 register struct osend_args /* {
797 int s;
798 caddr_t buf;
799 int len;
800 int flags;
801 } */ *uap;
802{
803 struct msghdr msg;
804 struct iovec aiov;
805 int error;
806
807 msg.msg_name = 0;
808 msg.msg_namelen = 0;
809 msg.msg_iov = &aiov;
810 msg.msg_iovlen = 1;
811 aiov.iov_base = uap->buf;
812 aiov.iov_len = uap->len;
813 msg.msg_control = 0;
814 msg.msg_flags = 0;
815 error = sendit(td, uap->s, &msg, uap->flags);
816 return (error);
817}
818
819/*
820 * MPSAFE
821 */
822int
823osendmsg(td, uap)
824 struct thread *td;
825 register struct osendmsg_args /* {
826 int s;
827 caddr_t msg;
828 int flags;
829 } */ *uap;
830{
831 struct msghdr msg;
832 struct iovec aiov[UIO_SMALLIOV], *iov;
833 int error;
834
835 error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
836 if (error)
837 goto done2;
838 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
839 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
840 error = EMSGSIZE;
841 goto done2;
842 }
843 MALLOC(iov, struct iovec *,
844 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
845 M_WAITOK);
846 } else {
847 iov = aiov;
848 }
849 error = copyin(msg.msg_iov, iov,
850 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
851 if (error)
852 goto done;
853 msg.msg_flags = MSG_COMPAT;
854 msg.msg_iov = iov;
855 error = sendit(td, uap->s, &msg, uap->flags);
856done:
857 if (iov != aiov)
858 FREE(iov, M_IOV);
859done2:
860 return (error);
861}
862#endif
863
864/*
865 * MPSAFE
866 */
867int
868sendmsg(td, uap)
869 struct thread *td;
870 register struct sendmsg_args /* {
871 int s;
872 caddr_t msg;
873 int flags;
874 } */ *uap;
875{
876 struct msghdr msg;
877 struct iovec aiov[UIO_SMALLIOV], *iov;
878 int error;
879
880 error = copyin(uap->msg, &msg, sizeof (msg));
881 if (error)
882 goto done2;
883 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
884 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
885 error = EMSGSIZE;
886 goto done2;
887 }
888 MALLOC(iov, struct iovec *,
889 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
890 M_WAITOK);
891 } else {
892 iov = aiov;
893 }
894 if (msg.msg_iovlen &&
895 (error = copyin(msg.msg_iov, iov,
896 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
897 goto done;
898 msg.msg_iov = iov;
899#ifdef COMPAT_OLDSOCK
900 msg.msg_flags = 0;
901#endif
902 error = sendit(td, uap->s, &msg, uap->flags);
903done:
904 if (iov != aiov)
905 FREE(iov, M_IOV);
906done2:
907 return (error);
908}
909
910static int
911recvit(td, s, mp, namelenp)
912 register struct thread *td;
913 int s;
914 register struct msghdr *mp;
915 void *namelenp;
916{
917 struct uio auio;
918 register struct iovec *iov;
919 register int i;
919 int len, error;
920 socklen_t len;
921 int error;
920 struct mbuf *m, *control = 0;
921 caddr_t ctlbuf;
922 struct socket *so;
923 struct sockaddr *fromsa = 0;
924#ifdef KTRACE
925 struct iovec *ktriov = NULL;
926 struct uio ktruio;
927 int iovlen;
928#endif
929
930 mtx_lock(&Giant);
931 if ((error = fgetsock(td, s, &so, NULL)) != 0) {
932 mtx_unlock(&Giant);
933 return (error);
934 }
935
936#ifdef MAC
937 error = mac_check_socket_receive(td->td_ucred, so);
938 if (error) {
939 fputsock(so);
940 mtx_unlock(&Giant);
941 return (error);
942 }
943#endif
944
945 auio.uio_iov = mp->msg_iov;
946 auio.uio_iovcnt = mp->msg_iovlen;
947 auio.uio_segflg = UIO_USERSPACE;
948 auio.uio_rw = UIO_READ;
949 auio.uio_td = td;
950 auio.uio_offset = 0; /* XXX */
951 auio.uio_resid = 0;
952 iov = mp->msg_iov;
953 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
954 if ((auio.uio_resid += iov->iov_len) < 0) {
955 fputsock(so);
956 return (EINVAL);
957 }
958 }
959#ifdef KTRACE
960 if (KTRPOINT(td, KTR_GENIO)) {
961 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
962 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
963 bcopy(auio.uio_iov, ktriov, iovlen);
964 ktruio = auio;
965 }
966#endif
967 len = auio.uio_resid;
968 error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
969 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
970 &mp->msg_flags);
971 if (error) {
922 struct mbuf *m, *control = 0;
923 caddr_t ctlbuf;
924 struct socket *so;
925 struct sockaddr *fromsa = 0;
926#ifdef KTRACE
927 struct iovec *ktriov = NULL;
928 struct uio ktruio;
929 int iovlen;
930#endif
931
932 mtx_lock(&Giant);
933 if ((error = fgetsock(td, s, &so, NULL)) != 0) {
934 mtx_unlock(&Giant);
935 return (error);
936 }
937
938#ifdef MAC
939 error = mac_check_socket_receive(td->td_ucred, so);
940 if (error) {
941 fputsock(so);
942 mtx_unlock(&Giant);
943 return (error);
944 }
945#endif
946
947 auio.uio_iov = mp->msg_iov;
948 auio.uio_iovcnt = mp->msg_iovlen;
949 auio.uio_segflg = UIO_USERSPACE;
950 auio.uio_rw = UIO_READ;
951 auio.uio_td = td;
952 auio.uio_offset = 0; /* XXX */
953 auio.uio_resid = 0;
954 iov = mp->msg_iov;
955 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
956 if ((auio.uio_resid += iov->iov_len) < 0) {
957 fputsock(so);
958 return (EINVAL);
959 }
960 }
961#ifdef KTRACE
962 if (KTRPOINT(td, KTR_GENIO)) {
963 iovlen = auio.uio_iovcnt * sizeof (struct iovec);
964 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
965 bcopy(auio.uio_iov, ktriov, iovlen);
966 ktruio = auio;
967 }
968#endif
969 len = auio.uio_resid;
970 error = so->so_proto->pr_usrreqs->pru_soreceive(so, &fromsa, &auio,
971 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
972 &mp->msg_flags);
973 if (error) {
972 if (auio.uio_resid != len && (error == ERESTART ||
974 if (auio.uio_resid != (int)len && (error == ERESTART ||
973 error == EINTR || error == EWOULDBLOCK))
974 error = 0;
975 }
976#ifdef KTRACE
977 if (ktriov != NULL) {
978 if (error == 0) {
979 ktruio.uio_iov = ktriov;
975 error == EINTR || error == EWOULDBLOCK))
976 error = 0;
977 }
978#ifdef KTRACE
979 if (ktriov != NULL) {
980 if (error == 0) {
981 ktruio.uio_iov = ktriov;
980 ktruio.uio_resid = len - auio.uio_resid;
982 ktruio.uio_resid = (int)len - auio.uio_resid;
981 ktrgenio(s, UIO_READ, &ktruio, error);
982 }
983 FREE(ktriov, M_TEMP);
984 }
985#endif
986 if (error)
987 goto out;
983 ktrgenio(s, UIO_READ, &ktruio, error);
984 }
985 FREE(ktriov, M_TEMP);
986 }
987#endif
988 if (error)
989 goto out;
988 td->td_retval[0] = len - auio.uio_resid;
990 td->td_retval[0] = (int)len - auio.uio_resid;
989 if (mp->msg_name) {
990 len = mp->msg_namelen;
991 if (len <= 0 || fromsa == 0)
992 len = 0;
993 else {
994 /* save sa_len before it is destroyed by MSG_COMPAT */
995 len = MIN(len, fromsa->sa_len);
996#ifdef COMPAT_OLDSOCK
997 if (mp->msg_flags & MSG_COMPAT)
998 ((struct osockaddr *)fromsa)->sa_family =
999 fromsa->sa_family;
1000#endif
1001 error = copyout(fromsa, mp->msg_name, (unsigned)len);
1002 if (error)
1003 goto out;
1004 }
1005 mp->msg_namelen = len;
1006 if (namelenp &&
991 if (mp->msg_name) {
992 len = mp->msg_namelen;
993 if (len <= 0 || fromsa == 0)
994 len = 0;
995 else {
996 /* save sa_len before it is destroyed by MSG_COMPAT */
997 len = MIN(len, fromsa->sa_len);
998#ifdef COMPAT_OLDSOCK
999 if (mp->msg_flags & MSG_COMPAT)
1000 ((struct osockaddr *)fromsa)->sa_family =
1001 fromsa->sa_family;
1002#endif
1003 error = copyout(fromsa, mp->msg_name, (unsigned)len);
1004 if (error)
1005 goto out;
1006 }
1007 mp->msg_namelen = len;
1008 if (namelenp &&
1007 (error = copyout(&len, namelenp, sizeof (int)))) {
1009 (error = copyout(&len, namelenp, sizeof (socklen_t)))) {
1008#ifdef COMPAT_OLDSOCK
1009 if (mp->msg_flags & MSG_COMPAT)
1010 error = 0; /* old recvfrom didn't check */
1011 else
1012#endif
1013 goto out;
1014 }
1015 }
1016 if (mp->msg_control) {
1017#ifdef COMPAT_OLDSOCK
1018 /*
1019 * We assume that old recvmsg calls won't receive access
1020 * rights and other control info, esp. as control info
1021 * is always optional and those options didn't exist in 4.3.
1022 * If we receive rights, trim the cmsghdr; anything else
1023 * is tossed.
1024 */
1025 if (control && mp->msg_flags & MSG_COMPAT) {
1026 if (mtod(control, struct cmsghdr *)->cmsg_level !=
1027 SOL_SOCKET ||
1028 mtod(control, struct cmsghdr *)->cmsg_type !=
1029 SCM_RIGHTS) {
1030 mp->msg_controllen = 0;
1031 goto out;
1032 }
1033 control->m_len -= sizeof (struct cmsghdr);
1034 control->m_data += sizeof (struct cmsghdr);
1035 }
1036#endif
1037 len = mp->msg_controllen;
1038 m = control;
1039 mp->msg_controllen = 0;
1040 ctlbuf = mp->msg_control;
1041
1042 while (m && len > 0) {
1043 unsigned int tocopy;
1044
1045 if (len >= m->m_len)
1046 tocopy = m->m_len;
1047 else {
1048 mp->msg_flags |= MSG_CTRUNC;
1049 tocopy = len;
1050 }
1051
1052 if ((error = copyout(mtod(m, caddr_t),
1053 ctlbuf, tocopy)) != 0)
1054 goto out;
1055
1056 ctlbuf += tocopy;
1057 len -= tocopy;
1058 m = m->m_next;
1059 }
1060 mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
1061 }
1062out:
1063 fputsock(so);
1064 mtx_unlock(&Giant);
1065 if (fromsa)
1066 FREE(fromsa, M_SONAME);
1067 if (control)
1068 m_freem(control);
1069 return (error);
1070}
1071
1072/*
1073 * MPSAFE
1074 */
1075int
1076recvfrom(td, uap)
1077 struct thread *td;
1078 register struct recvfrom_args /* {
1079 int s;
1080 caddr_t buf;
1081 size_t len;
1082 int flags;
1010#ifdef COMPAT_OLDSOCK
1011 if (mp->msg_flags & MSG_COMPAT)
1012 error = 0; /* old recvfrom didn't check */
1013 else
1014#endif
1015 goto out;
1016 }
1017 }
1018 if (mp->msg_control) {
1019#ifdef COMPAT_OLDSOCK
1020 /*
1021 * We assume that old recvmsg calls won't receive access
1022 * rights and other control info, esp. as control info
1023 * is always optional and those options didn't exist in 4.3.
1024 * If we receive rights, trim the cmsghdr; anything else
1025 * is tossed.
1026 */
1027 if (control && mp->msg_flags & MSG_COMPAT) {
1028 if (mtod(control, struct cmsghdr *)->cmsg_level !=
1029 SOL_SOCKET ||
1030 mtod(control, struct cmsghdr *)->cmsg_type !=
1031 SCM_RIGHTS) {
1032 mp->msg_controllen = 0;
1033 goto out;
1034 }
1035 control->m_len -= sizeof (struct cmsghdr);
1036 control->m_data += sizeof (struct cmsghdr);
1037 }
1038#endif
1039 len = mp->msg_controllen;
1040 m = control;
1041 mp->msg_controllen = 0;
1042 ctlbuf = mp->msg_control;
1043
1044 while (m && len > 0) {
1045 unsigned int tocopy;
1046
1047 if (len >= m->m_len)
1048 tocopy = m->m_len;
1049 else {
1050 mp->msg_flags |= MSG_CTRUNC;
1051 tocopy = len;
1052 }
1053
1054 if ((error = copyout(mtod(m, caddr_t),
1055 ctlbuf, tocopy)) != 0)
1056 goto out;
1057
1058 ctlbuf += tocopy;
1059 len -= tocopy;
1060 m = m->m_next;
1061 }
1062 mp->msg_controllen = ctlbuf - (caddr_t)mp->msg_control;
1063 }
1064out:
1065 fputsock(so);
1066 mtx_unlock(&Giant);
1067 if (fromsa)
1068 FREE(fromsa, M_SONAME);
1069 if (control)
1070 m_freem(control);
1071 return (error);
1072}
1073
1074/*
1075 * MPSAFE
1076 */
1077int
1078recvfrom(td, uap)
1079 struct thread *td;
1080 register struct recvfrom_args /* {
1081 int s;
1082 caddr_t buf;
1083 size_t len;
1084 int flags;
1083 caddr_t from;
1084 int *fromlenaddr;
1085 struct sockaddr * __restrict from;
1086 socklen_t * __restrict fromlenaddr;
1085 } */ *uap;
1086{
1087 struct msghdr msg;
1088 struct iovec aiov;
1089 int error;
1090
1091 if (uap->fromlenaddr) {
1092 error = copyin(uap->fromlenaddr,
1093 &msg.msg_namelen, sizeof (msg.msg_namelen));
1094 if (error)
1095 goto done2;
1096 } else {
1097 msg.msg_namelen = 0;
1098 }
1099 msg.msg_name = uap->from;
1100 msg.msg_iov = &aiov;
1101 msg.msg_iovlen = 1;
1102 aiov.iov_base = uap->buf;
1103 aiov.iov_len = uap->len;
1104 msg.msg_control = 0;
1105 msg.msg_flags = uap->flags;
1106 error = recvit(td, uap->s, &msg, uap->fromlenaddr);
1107done2:
1108 return(error);
1109}
1110
1111#ifdef COMPAT_OLDSOCK
1112/*
1113 * MPSAFE
1114 */
1115int
1116orecvfrom(td, uap)
1117 struct thread *td;
1118 struct recvfrom_args *uap;
1119{
1120
1121 uap->flags |= MSG_COMPAT;
1122 return (recvfrom(td, uap));
1123}
1124#endif
1125
1126
1127#ifdef COMPAT_OLDSOCK
1128/*
1129 * MPSAFE
1130 */
1131int
1132orecv(td, uap)
1133 struct thread *td;
1134 register struct orecv_args /* {
1135 int s;
1136 caddr_t buf;
1137 int len;
1138 int flags;
1139 } */ *uap;
1140{
1141 struct msghdr msg;
1142 struct iovec aiov;
1143 int error;
1144
1145 msg.msg_name = 0;
1146 msg.msg_namelen = 0;
1147 msg.msg_iov = &aiov;
1148 msg.msg_iovlen = 1;
1149 aiov.iov_base = uap->buf;
1150 aiov.iov_len = uap->len;
1151 msg.msg_control = 0;
1152 msg.msg_flags = uap->flags;
1153 error = recvit(td, uap->s, &msg, NULL);
1154 return (error);
1155}
1156
1157/*
1158 * Old recvmsg. This code takes advantage of the fact that the old msghdr
1159 * overlays the new one, missing only the flags, and with the (old) access
1160 * rights where the control fields are now.
1161 *
1162 * MPSAFE
1163 */
1164int
1165orecvmsg(td, uap)
1166 struct thread *td;
1167 register struct orecvmsg_args /* {
1168 int s;
1169 struct omsghdr *msg;
1170 int flags;
1171 } */ *uap;
1172{
1173 struct msghdr msg;
1174 struct iovec aiov[UIO_SMALLIOV], *iov;
1175 int error;
1176
1177 error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
1178 if (error)
1179 return (error);
1180
1181 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
1182 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
1183 error = EMSGSIZE;
1184 goto done2;
1185 }
1186 MALLOC(iov, struct iovec *,
1187 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
1188 M_WAITOK);
1189 } else {
1190 iov = aiov;
1191 }
1192 msg.msg_flags = uap->flags | MSG_COMPAT;
1193 error = copyin(msg.msg_iov, iov,
1194 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
1195 if (error)
1196 goto done;
1197 msg.msg_iov = iov;
1198 error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
1199
1200 if (msg.msg_controllen && error == 0)
1201 error = copyout(&msg.msg_controllen,
1202 &uap->msg->msg_accrightslen, sizeof (int));
1203done:
1204 if (iov != aiov)
1205 FREE(iov, M_IOV);
1206done2:
1207 return (error);
1208}
1209#endif
1210
1211/*
1212 * MPSAFE
1213 */
1214int
1215recvmsg(td, uap)
1216 struct thread *td;
1217 register struct recvmsg_args /* {
1218 int s;
1219 struct msghdr *msg;
1220 int flags;
1221 } */ *uap;
1222{
1223 struct msghdr msg;
1224 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
1225 register int error;
1226
1227 error = copyin(uap->msg, &msg, sizeof (msg));
1228 if (error)
1229 goto done2;
1230 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
1231 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
1232 error = EMSGSIZE;
1233 goto done2;
1234 }
1235 MALLOC(iov, struct iovec *,
1236 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
1237 M_WAITOK);
1238 } else {
1239 iov = aiov;
1240 }
1241#ifdef COMPAT_OLDSOCK
1242 msg.msg_flags = uap->flags &~ MSG_COMPAT;
1243#else
1244 msg.msg_flags = uap->flags;
1245#endif
1246 uiov = msg.msg_iov;
1247 msg.msg_iov = iov;
1248 error = copyin(uiov, iov,
1249 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
1250 if (error)
1251 goto done;
1252 error = recvit(td, uap->s, &msg, NULL);
1253 if (!error) {
1254 msg.msg_iov = uiov;
1255 error = copyout(&msg, uap->msg, sizeof(msg));
1256 }
1257done:
1258 if (iov != aiov)
1259 FREE(iov, M_IOV);
1260done2:
1261 return (error);
1262}
1263
1264/*
1265 * MPSAFE
1266 */
1267/* ARGSUSED */
1268int
1269shutdown(td, uap)
1270 struct thread *td;
1271 register struct shutdown_args /* {
1272 int s;
1273 int how;
1274 } */ *uap;
1275{
1276 struct socket *so;
1277 int error;
1278
1279 mtx_lock(&Giant);
1280 if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
1281 error = soshutdown(so, uap->how);
1282 fputsock(so);
1283 }
1284 mtx_unlock(&Giant);
1285 return(error);
1286}
1287
1288/*
1289 * MPSAFE
1290 */
1291/* ARGSUSED */
1292int
1293setsockopt(td, uap)
1294 struct thread *td;
1295 register struct setsockopt_args /* {
1296 int s;
1297 int level;
1298 int name;
1299 caddr_t val;
1300 int valsize;
1301 } */ *uap;
1302{
1303 struct socket *so;
1304 struct sockopt sopt;
1305 int error;
1306
1307 if (uap->val == 0 && uap->valsize != 0)
1308 return (EFAULT);
1309 if (uap->valsize < 0)
1310 return (EINVAL);
1311
1312 mtx_lock(&Giant);
1313 if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
1314 sopt.sopt_dir = SOPT_SET;
1315 sopt.sopt_level = uap->level;
1316 sopt.sopt_name = uap->name;
1317 sopt.sopt_val = uap->val;
1318 sopt.sopt_valsize = uap->valsize;
1319 sopt.sopt_td = td;
1320 error = sosetopt(so, &sopt);
1321 fputsock(so);
1322 }
1323 mtx_unlock(&Giant);
1324 return(error);
1325}
1326
1327/*
1328 * MPSAFE
1329 */
1330/* ARGSUSED */
1331int
1332getsockopt(td, uap)
1333 struct thread *td;
1334 register struct getsockopt_args /* {
1335 int s;
1336 int level;
1337 int name;
1087 } */ *uap;
1088{
1089 struct msghdr msg;
1090 struct iovec aiov;
1091 int error;
1092
1093 if (uap->fromlenaddr) {
1094 error = copyin(uap->fromlenaddr,
1095 &msg.msg_namelen, sizeof (msg.msg_namelen));
1096 if (error)
1097 goto done2;
1098 } else {
1099 msg.msg_namelen = 0;
1100 }
1101 msg.msg_name = uap->from;
1102 msg.msg_iov = &aiov;
1103 msg.msg_iovlen = 1;
1104 aiov.iov_base = uap->buf;
1105 aiov.iov_len = uap->len;
1106 msg.msg_control = 0;
1107 msg.msg_flags = uap->flags;
1108 error = recvit(td, uap->s, &msg, uap->fromlenaddr);
1109done2:
1110 return(error);
1111}
1112
1113#ifdef COMPAT_OLDSOCK
1114/*
1115 * MPSAFE
1116 */
1117int
1118orecvfrom(td, uap)
1119 struct thread *td;
1120 struct recvfrom_args *uap;
1121{
1122
1123 uap->flags |= MSG_COMPAT;
1124 return (recvfrom(td, uap));
1125}
1126#endif
1127
1128
1129#ifdef COMPAT_OLDSOCK
1130/*
1131 * MPSAFE
1132 */
1133int
1134orecv(td, uap)
1135 struct thread *td;
1136 register struct orecv_args /* {
1137 int s;
1138 caddr_t buf;
1139 int len;
1140 int flags;
1141 } */ *uap;
1142{
1143 struct msghdr msg;
1144 struct iovec aiov;
1145 int error;
1146
1147 msg.msg_name = 0;
1148 msg.msg_namelen = 0;
1149 msg.msg_iov = &aiov;
1150 msg.msg_iovlen = 1;
1151 aiov.iov_base = uap->buf;
1152 aiov.iov_len = uap->len;
1153 msg.msg_control = 0;
1154 msg.msg_flags = uap->flags;
1155 error = recvit(td, uap->s, &msg, NULL);
1156 return (error);
1157}
1158
1159/*
1160 * Old recvmsg. This code takes advantage of the fact that the old msghdr
1161 * overlays the new one, missing only the flags, and with the (old) access
1162 * rights where the control fields are now.
1163 *
1164 * MPSAFE
1165 */
1166int
1167orecvmsg(td, uap)
1168 struct thread *td;
1169 register struct orecvmsg_args /* {
1170 int s;
1171 struct omsghdr *msg;
1172 int flags;
1173 } */ *uap;
1174{
1175 struct msghdr msg;
1176 struct iovec aiov[UIO_SMALLIOV], *iov;
1177 int error;
1178
1179 error = copyin(uap->msg, &msg, sizeof (struct omsghdr));
1180 if (error)
1181 return (error);
1182
1183 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
1184 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
1185 error = EMSGSIZE;
1186 goto done2;
1187 }
1188 MALLOC(iov, struct iovec *,
1189 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
1190 M_WAITOK);
1191 } else {
1192 iov = aiov;
1193 }
1194 msg.msg_flags = uap->flags | MSG_COMPAT;
1195 error = copyin(msg.msg_iov, iov,
1196 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
1197 if (error)
1198 goto done;
1199 msg.msg_iov = iov;
1200 error = recvit(td, uap->s, &msg, &uap->msg->msg_namelen);
1201
1202 if (msg.msg_controllen && error == 0)
1203 error = copyout(&msg.msg_controllen,
1204 &uap->msg->msg_accrightslen, sizeof (int));
1205done:
1206 if (iov != aiov)
1207 FREE(iov, M_IOV);
1208done2:
1209 return (error);
1210}
1211#endif
1212
1213/*
1214 * MPSAFE
1215 */
1216int
1217recvmsg(td, uap)
1218 struct thread *td;
1219 register struct recvmsg_args /* {
1220 int s;
1221 struct msghdr *msg;
1222 int flags;
1223 } */ *uap;
1224{
1225 struct msghdr msg;
1226 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
1227 register int error;
1228
1229 error = copyin(uap->msg, &msg, sizeof (msg));
1230 if (error)
1231 goto done2;
1232 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
1233 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV) {
1234 error = EMSGSIZE;
1235 goto done2;
1236 }
1237 MALLOC(iov, struct iovec *,
1238 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
1239 M_WAITOK);
1240 } else {
1241 iov = aiov;
1242 }
1243#ifdef COMPAT_OLDSOCK
1244 msg.msg_flags = uap->flags &~ MSG_COMPAT;
1245#else
1246 msg.msg_flags = uap->flags;
1247#endif
1248 uiov = msg.msg_iov;
1249 msg.msg_iov = iov;
1250 error = copyin(uiov, iov,
1251 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)));
1252 if (error)
1253 goto done;
1254 error = recvit(td, uap->s, &msg, NULL);
1255 if (!error) {
1256 msg.msg_iov = uiov;
1257 error = copyout(&msg, uap->msg, sizeof(msg));
1258 }
1259done:
1260 if (iov != aiov)
1261 FREE(iov, M_IOV);
1262done2:
1263 return (error);
1264}
1265
1266/*
1267 * MPSAFE
1268 */
1269/* ARGSUSED */
1270int
1271shutdown(td, uap)
1272 struct thread *td;
1273 register struct shutdown_args /* {
1274 int s;
1275 int how;
1276 } */ *uap;
1277{
1278 struct socket *so;
1279 int error;
1280
1281 mtx_lock(&Giant);
1282 if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
1283 error = soshutdown(so, uap->how);
1284 fputsock(so);
1285 }
1286 mtx_unlock(&Giant);
1287 return(error);
1288}
1289
1290/*
1291 * MPSAFE
1292 */
1293/* ARGSUSED */
1294int
1295setsockopt(td, uap)
1296 struct thread *td;
1297 register struct setsockopt_args /* {
1298 int s;
1299 int level;
1300 int name;
1301 caddr_t val;
1302 int valsize;
1303 } */ *uap;
1304{
1305 struct socket *so;
1306 struct sockopt sopt;
1307 int error;
1308
1309 if (uap->val == 0 && uap->valsize != 0)
1310 return (EFAULT);
1311 if (uap->valsize < 0)
1312 return (EINVAL);
1313
1314 mtx_lock(&Giant);
1315 if ((error = fgetsock(td, uap->s, &so, NULL)) == 0) {
1316 sopt.sopt_dir = SOPT_SET;
1317 sopt.sopt_level = uap->level;
1318 sopt.sopt_name = uap->name;
1319 sopt.sopt_val = uap->val;
1320 sopt.sopt_valsize = uap->valsize;
1321 sopt.sopt_td = td;
1322 error = sosetopt(so, &sopt);
1323 fputsock(so);
1324 }
1325 mtx_unlock(&Giant);
1326 return(error);
1327}
1328
1329/*
1330 * MPSAFE
1331 */
1332/* ARGSUSED */
1333int
1334getsockopt(td, uap)
1335 struct thread *td;
1336 register struct getsockopt_args /* {
1337 int s;
1338 int level;
1339 int name;
1338 caddr_t val;
1339 int *avalsize;
1340 void * __restrict val;
1341 socklen_t * __restrict avalsize;
1340 } */ *uap;
1341{
1342 } */ *uap;
1343{
1342 int valsize, error;
1344 socklen_t valsize;
1345 int error;
1343 struct socket *so;
1344 struct sockopt sopt;
1345
1346 mtx_lock(&Giant);
1347 if ((error = fgetsock(td, uap->s, &so, NULL)) != 0)
1348 goto done2;
1349 if (uap->val) {
1350 error = copyin(uap->avalsize, &valsize, sizeof (valsize));
1351 if (error)
1352 goto done1;
1353 if (valsize < 0) {
1354 error = EINVAL;
1355 goto done1;
1356 }
1357 } else {
1358 valsize = 0;
1359 }
1360
1361 sopt.sopt_dir = SOPT_GET;
1362 sopt.sopt_level = uap->level;
1363 sopt.sopt_name = uap->name;
1364 sopt.sopt_val = uap->val;
1365 sopt.sopt_valsize = (size_t)valsize; /* checked non-negative above */
1366 sopt.sopt_td = td;
1367
1368 error = sogetopt(so, &sopt);
1369 if (error == 0) {
1370 valsize = sopt.sopt_valsize;
1371 error = copyout(&valsize, uap->avalsize, sizeof (valsize));
1372 }
1373done1:
1374 fputsock(so);
1375done2:
1376 mtx_unlock(&Giant);
1377 return (error);
1378}
1379
1380/*
1381 * getsockname1() - Get socket name.
1382 *
1383 * MPSAFE
1384 */
1385/* ARGSUSED */
1386static int
1387getsockname1(td, uap, compat)
1388 struct thread *td;
1389 register struct getsockname_args /* {
1390 int fdes;
1346 struct socket *so;
1347 struct sockopt sopt;
1348
1349 mtx_lock(&Giant);
1350 if ((error = fgetsock(td, uap->s, &so, NULL)) != 0)
1351 goto done2;
1352 if (uap->val) {
1353 error = copyin(uap->avalsize, &valsize, sizeof (valsize));
1354 if (error)
1355 goto done1;
1356 if (valsize < 0) {
1357 error = EINVAL;
1358 goto done1;
1359 }
1360 } else {
1361 valsize = 0;
1362 }
1363
1364 sopt.sopt_dir = SOPT_GET;
1365 sopt.sopt_level = uap->level;
1366 sopt.sopt_name = uap->name;
1367 sopt.sopt_val = uap->val;
1368 sopt.sopt_valsize = (size_t)valsize; /* checked non-negative above */
1369 sopt.sopt_td = td;
1370
1371 error = sogetopt(so, &sopt);
1372 if (error == 0) {
1373 valsize = sopt.sopt_valsize;
1374 error = copyout(&valsize, uap->avalsize, sizeof (valsize));
1375 }
1376done1:
1377 fputsock(so);
1378done2:
1379 mtx_unlock(&Giant);
1380 return (error);
1381}
1382
1383/*
1384 * getsockname1() - Get socket name.
1385 *
1386 * MPSAFE
1387 */
1388/* ARGSUSED */
1389static int
1390getsockname1(td, uap, compat)
1391 struct thread *td;
1392 register struct getsockname_args /* {
1393 int fdes;
1391 caddr_t asa;
1392 int *alen;
1394 struct sockaddr * __restrict asa;
1395 socklen_t * __restrict alen;
1393 } */ *uap;
1394 int compat;
1395{
1396 struct socket *so;
1397 struct sockaddr *sa;
1396 } */ *uap;
1397 int compat;
1398{
1399 struct socket *so;
1400 struct sockaddr *sa;
1398 int len, error;
1401 socklen_t len;
1402 int error;
1399
1400 mtx_lock(&Giant);
1401 if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
1402 goto done2;
1403 error = copyin(uap->alen, &len, sizeof (len));
1404 if (error)
1405 goto done1;
1406 if (len < 0) {
1407 error = EINVAL;
1408 goto done1;
1409 }
1410 sa = 0;
1411 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
1412 if (error)
1413 goto bad;
1414 if (sa == 0) {
1415 len = 0;
1416 goto gotnothing;
1417 }
1418
1419 len = MIN(len, sa->sa_len);
1420#ifdef COMPAT_OLDSOCK
1421 if (compat)
1422 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1423#endif
1424 error = copyout(sa, uap->asa, (u_int)len);
1425 if (error == 0)
1426gotnothing:
1427 error = copyout(&len, uap->alen, sizeof (len));
1428bad:
1429 if (sa)
1430 FREE(sa, M_SONAME);
1431done1:
1432 fputsock(so);
1433done2:
1434 mtx_unlock(&Giant);
1435 return (error);
1436}
1437
1438/*
1439 * MPSAFE
1440 */
1441int
1442getsockname(td, uap)
1443 struct thread *td;
1444 struct getsockname_args *uap;
1445{
1446
1447 return (getsockname1(td, uap, 0));
1448}
1449
1450#ifdef COMPAT_OLDSOCK
1451/*
1452 * MPSAFE
1453 */
1454int
1455ogetsockname(td, uap)
1456 struct thread *td;
1457 struct getsockname_args *uap;
1458{
1459
1460 return (getsockname1(td, uap, 1));
1461}
1462#endif /* COMPAT_OLDSOCK */
1463
1464/*
1465 * getpeername1() - Get name of peer for connected socket.
1466 *
1467 * MPSAFE
1468 */
1469/* ARGSUSED */
1470static int
1471getpeername1(td, uap, compat)
1472 struct thread *td;
1473 register struct getpeername_args /* {
1474 int fdes;
1403
1404 mtx_lock(&Giant);
1405 if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
1406 goto done2;
1407 error = copyin(uap->alen, &len, sizeof (len));
1408 if (error)
1409 goto done1;
1410 if (len < 0) {
1411 error = EINVAL;
1412 goto done1;
1413 }
1414 sa = 0;
1415 error = (*so->so_proto->pr_usrreqs->pru_sockaddr)(so, &sa);
1416 if (error)
1417 goto bad;
1418 if (sa == 0) {
1419 len = 0;
1420 goto gotnothing;
1421 }
1422
1423 len = MIN(len, sa->sa_len);
1424#ifdef COMPAT_OLDSOCK
1425 if (compat)
1426 ((struct osockaddr *)sa)->sa_family = sa->sa_family;
1427#endif
1428 error = copyout(sa, uap->asa, (u_int)len);
1429 if (error == 0)
1430gotnothing:
1431 error = copyout(&len, uap->alen, sizeof (len));
1432bad:
1433 if (sa)
1434 FREE(sa, M_SONAME);
1435done1:
1436 fputsock(so);
1437done2:
1438 mtx_unlock(&Giant);
1439 return (error);
1440}
1441
1442/*
1443 * MPSAFE
1444 */
1445int
1446getsockname(td, uap)
1447 struct thread *td;
1448 struct getsockname_args *uap;
1449{
1450
1451 return (getsockname1(td, uap, 0));
1452}
1453
1454#ifdef COMPAT_OLDSOCK
1455/*
1456 * MPSAFE
1457 */
1458int
1459ogetsockname(td, uap)
1460 struct thread *td;
1461 struct getsockname_args *uap;
1462{
1463
1464 return (getsockname1(td, uap, 1));
1465}
1466#endif /* COMPAT_OLDSOCK */
1467
1468/*
1469 * getpeername1() - Get name of peer for connected socket.
1470 *
1471 * MPSAFE
1472 */
1473/* ARGSUSED */
1474static int
1475getpeername1(td, uap, compat)
1476 struct thread *td;
1477 register struct getpeername_args /* {
1478 int fdes;
1475 caddr_t asa;
1476 int *alen;
1479 struct sockaddr * __restrict asa;
1480 socklen_t * __restrict alen;
1477 } */ *uap;
1478 int compat;
1479{
1480 struct socket *so;
1481 struct sockaddr *sa;
1481 } */ *uap;
1482 int compat;
1483{
1484 struct socket *so;
1485 struct sockaddr *sa;
1482 int len, error;
1486 socklen_t len;
1487 int error;
1483
1484 mtx_lock(&Giant);
1485 if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
1486 goto done2;
1487 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1488 error = ENOTCONN;
1489 goto done1;
1490 }
1491 error = copyin(uap->alen, &len, sizeof (len));
1492 if (error)
1493 goto done1;
1494 if (len < 0) {
1495 error = EINVAL;
1496 goto done1;
1497 }
1498 sa = 0;
1499 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
1500 if (error)
1501 goto bad;
1502 if (sa == 0) {
1503 len = 0;
1504 goto gotnothing;
1505 }
1506 len = MIN(len, sa->sa_len);
1507#ifdef COMPAT_OLDSOCK
1508 if (compat)
1509 ((struct osockaddr *)sa)->sa_family =
1510 sa->sa_family;
1511#endif
1512 error = copyout(sa, uap->asa, (u_int)len);
1513 if (error)
1514 goto bad;
1515gotnothing:
1516 error = copyout(&len, uap->alen, sizeof (len));
1517bad:
1518 if (sa)
1519 FREE(sa, M_SONAME);
1520done1:
1521 fputsock(so);
1522done2:
1523 mtx_unlock(&Giant);
1524 return (error);
1525}
1526
1527/*
1528 * MPSAFE
1529 */
1530int
1531getpeername(td, uap)
1532 struct thread *td;
1533 struct getpeername_args *uap;
1534{
1535
1536 return (getpeername1(td, uap, 0));
1537}
1538
1539#ifdef COMPAT_OLDSOCK
1540/*
1541 * MPSAFE
1542 */
1543int
1544ogetpeername(td, uap)
1545 struct thread *td;
1546 struct ogetpeername_args *uap;
1547{
1548
1549 /* XXX uap should have type `getpeername_args *' to begin with. */
1550 return (getpeername1(td, (struct getpeername_args *)uap, 1));
1551}
1552#endif /* COMPAT_OLDSOCK */
1553
1554int
1555sockargs(mp, buf, buflen, type)
1556 struct mbuf **mp;
1557 caddr_t buf;
1558 int buflen, type;
1559{
1560 register struct sockaddr *sa;
1561 register struct mbuf *m;
1562 int error;
1563
1564 if ((u_int)buflen > MLEN) {
1565#ifdef COMPAT_OLDSOCK
1566 if (type == MT_SONAME && (u_int)buflen <= 112)
1567 buflen = MLEN; /* unix domain compat. hack */
1568 else
1569#endif
1570 return (EINVAL);
1571 }
1572 m = m_get(M_TRYWAIT, type);
1573 if (m == NULL)
1574 return (ENOBUFS);
1575 m->m_len = buflen;
1576 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1577 if (error)
1578 (void) m_free(m);
1579 else {
1580 *mp = m;
1581 if (type == MT_SONAME) {
1582 sa = mtod(m, struct sockaddr *);
1583
1584#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1585 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1586 sa->sa_family = sa->sa_len;
1587#endif
1588 sa->sa_len = buflen;
1589 }
1590 }
1591 return (error);
1592}
1593
1594int
1595getsockaddr(namp, uaddr, len)
1596 struct sockaddr **namp;
1597 caddr_t uaddr;
1598 size_t len;
1599{
1600 struct sockaddr *sa;
1601 int error;
1602
1603 if (len > SOCK_MAXADDRLEN)
1604 return ENAMETOOLONG;
1605 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
1606 error = copyin(uaddr, sa, len);
1607 if (error) {
1608 FREE(sa, M_SONAME);
1609 } else {
1610#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1611 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1612 sa->sa_family = sa->sa_len;
1613#endif
1614 sa->sa_len = len;
1615 *namp = sa;
1616 }
1617 return error;
1618}
1619
1620/*
1621 * sendfile(2)
1622 *
1623 * MPSAFE
1624 *
1625 * int sendfile(int fd, int s, off_t offset, size_t nbytes,
1626 * struct sf_hdtr *hdtr, off_t *sbytes, int flags)
1627 *
1628 * Send a file specified by 'fd' and starting at 'offset' to a socket
1629 * specified by 's'. Send only 'nbytes' of the file or until EOF if
1630 * nbytes == 0. Optionally add a header and/or trailer to the socket
1631 * output. If specified, write the total number of bytes sent into *sbytes.
1632 *
1633 */
1634int
1635sendfile(struct thread *td, struct sendfile_args *uap)
1636{
1637
1638 return (do_sendfile(td, uap, 0));
1639}
1640
1641#ifdef COMPAT_FREEBSD4
1642int
1643freebsd4_sendfile(struct thread *td, struct freebsd4_sendfile_args *uap)
1644{
1645 struct sendfile_args args;
1646
1647 args.fd = uap->fd;
1648 args.s = uap->s;
1649 args.offset = uap->offset;
1650 args.nbytes = uap->nbytes;
1651 args.hdtr = uap->hdtr;
1652 args.sbytes = uap->sbytes;
1653 args.flags = uap->flags;
1654
1655 return (do_sendfile(td, &args, 1));
1656}
1657#endif /* COMPAT_FREEBSD4 */
1658
1659static int
1660do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
1661{
1662 struct vnode *vp;
1663 struct vm_object *obj;
1664 struct socket *so = NULL;
1665 struct mbuf *m;
1666 struct sf_buf *sf;
1667 struct vm_page *pg;
1668 struct writev_args nuap;
1669 struct sf_hdtr hdtr;
1670 off_t off, xfsize, hdtr_size, sbytes = 0;
1671 int error, s;
1672
1673 mtx_lock(&Giant);
1674
1675 hdtr_size = 0;
1676
1677 /*
1678 * The descriptor must be a regular file and have a backing VM object.
1679 */
1680 if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
1681 goto done;
1682 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1683 if (vp->v_type != VREG || VOP_GETVOBJECT(vp, &obj) != 0) {
1684 error = EINVAL;
1685 VOP_UNLOCK(vp, 0, td);
1686 goto done;
1687 }
1688 VOP_UNLOCK(vp, 0, td);
1689 if ((error = fgetsock(td, uap->s, &so, NULL)) != 0)
1690 goto done;
1691 if (so->so_type != SOCK_STREAM) {
1692 error = EINVAL;
1693 goto done;
1694 }
1695 if ((so->so_state & SS_ISCONNECTED) == 0) {
1696 error = ENOTCONN;
1697 goto done;
1698 }
1699 if (uap->offset < 0) {
1700 error = EINVAL;
1701 goto done;
1702 }
1703
1704#ifdef MAC
1705 error = mac_check_socket_send(td->td_ucred, so);
1706 if (error)
1707 goto done;
1708#endif
1709
1710 /*
1711 * If specified, get the pointer to the sf_hdtr struct for
1712 * any headers/trailers.
1713 */
1714 if (uap->hdtr != NULL) {
1715 error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
1716 if (error)
1717 goto done;
1718 /*
1719 * Send any headers. Wimp out and use writev(2).
1720 */
1721 if (hdtr.headers != NULL) {
1722 nuap.fd = uap->s;
1723 nuap.iovp = hdtr.headers;
1724 nuap.iovcnt = hdtr.hdr_cnt;
1725 error = writev(td, &nuap);
1726 if (error)
1727 goto done;
1728 if (compat)
1729 sbytes += td->td_retval[0];
1730 else
1731 hdtr_size += td->td_retval[0];
1732 }
1733 }
1734
1735 /*
1736 * Protect against multiple writers to the socket.
1737 */
1738 (void) sblock(&so->so_snd, M_WAITOK);
1739
1740 /*
1741 * Loop through the pages in the file, starting with the requested
1742 * offset. Get a file page (do I/O if necessary), map the file page
1743 * into an sf_buf, attach an mbuf header to the sf_buf, and queue
1744 * it on the socket.
1745 */
1746 for (off = uap->offset; ; off += xfsize, sbytes += xfsize) {
1747 vm_pindex_t pindex;
1748 vm_offset_t pgoff;
1749
1750 pindex = OFF_TO_IDX(off);
1751 VM_OBJECT_LOCK(obj);
1752retry_lookup:
1753 /*
1754 * Calculate the amount to transfer. Not to exceed a page,
1755 * the EOF, or the passed in nbytes.
1756 */
1757 xfsize = obj->un_pager.vnp.vnp_size - off;
1758 VM_OBJECT_UNLOCK(obj);
1759 if (xfsize > PAGE_SIZE)
1760 xfsize = PAGE_SIZE;
1761 pgoff = (vm_offset_t)(off & PAGE_MASK);
1762 if (PAGE_SIZE - pgoff < xfsize)
1763 xfsize = PAGE_SIZE - pgoff;
1764 if (uap->nbytes && xfsize > (uap->nbytes - sbytes))
1765 xfsize = uap->nbytes - sbytes;
1766 if (xfsize <= 0)
1767 break;
1768 /*
1769 * Optimize the non-blocking case by looking at the socket space
1770 * before going to the extra work of constituting the sf_buf.
1771 */
1772 if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) {
1773 if (so->so_state & SS_CANTSENDMORE)
1774 error = EPIPE;
1775 else
1776 error = EAGAIN;
1777 sbunlock(&so->so_snd);
1778 goto done;
1779 }
1780 VM_OBJECT_LOCK(obj);
1781 /*
1782 * Attempt to look up the page.
1783 *
1784 * Allocate if not found
1785 *
1786 * Wait and loop if busy.
1787 */
1788 pg = vm_page_lookup(obj, pindex);
1789
1790 if (pg == NULL) {
1791 pg = vm_page_alloc(obj, pindex,
1792 VM_ALLOC_NORMAL | VM_ALLOC_WIRED);
1793 if (pg == NULL) {
1794 VM_OBJECT_UNLOCK(obj);
1795 VM_WAIT;
1796 VM_OBJECT_LOCK(obj);
1797 goto retry_lookup;
1798 }
1799 vm_page_lock_queues();
1800 vm_page_wakeup(pg);
1801 } else {
1802 vm_page_lock_queues();
1803 if (vm_page_sleep_if_busy(pg, TRUE, "sfpbsy"))
1804 goto retry_lookup;
1805 /*
1806 * Wire the page so it does not get ripped out from
1807 * under us.
1808 */
1809 vm_page_wire(pg);
1810 }
1811
1812 /*
1813 * If page is not valid for what we need, initiate I/O
1814 */
1815
1816 if (!pg->valid || !vm_page_is_valid(pg, pgoff, xfsize)) {
1817 int bsize, resid;
1818
1819 /*
1820 * Ensure that our page is still around when the I/O
1821 * completes.
1822 */
1823 vm_page_io_start(pg);
1824 vm_page_unlock_queues();
1825 VM_OBJECT_UNLOCK(obj);
1826
1827 /*
1828 * Get the page from backing store.
1829 */
1830 bsize = vp->v_mount->mnt_stat.f_iosize;
1831 vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
1832 /*
1833 * XXXMAC: Because we don't have fp->f_cred here,
1834 * we pass in NOCRED. This is probably wrong, but
1835 * is consistent with our original implementation.
1836 */
1837 error = vn_rdwr(UIO_READ, vp, NULL, MAXBSIZE,
1838 trunc_page(off), UIO_NOCOPY, IO_NODELOCKED |
1839 IO_VMIO | ((MAXBSIZE / bsize) << 16),
1840 td->td_ucred, NOCRED, &resid, td);
1841 VOP_UNLOCK(vp, 0, td);
1842 if (error)
1843 VM_OBJECT_LOCK(obj);
1844 vm_page_lock_queues();
1845 vm_page_flag_clear(pg, PG_ZERO);
1846 vm_page_io_finish(pg);
1847 if (error) {
1848 vm_page_unwire(pg, 0);
1849 /*
1850 * See if anyone else might know about this page.
1851 * If not and it is not valid, then free it.
1852 */
1853 if (pg->wire_count == 0 && pg->valid == 0 &&
1854 pg->busy == 0 && !(pg->flags & PG_BUSY) &&
1855 pg->hold_count == 0) {
1856 vm_page_busy(pg);
1857 vm_page_free(pg);
1858 }
1859 vm_page_unlock_queues();
1860 VM_OBJECT_UNLOCK(obj);
1861 sbunlock(&so->so_snd);
1862 goto done;
1863 }
1864 } else
1865 VM_OBJECT_UNLOCK(obj);
1866 vm_page_unlock_queues();
1867
1868 /*
1869 * Get a sendfile buf. We usually wait as long as necessary,
1870 * but this wait can be interrupted.
1871 */
1872 if ((sf = sf_buf_alloc(pg)) == NULL) {
1873 vm_page_lock_queues();
1874 vm_page_unwire(pg, 0);
1875 if (pg->wire_count == 0 && pg->object == NULL)
1876 vm_page_free(pg);
1877 vm_page_unlock_queues();
1878 sbunlock(&so->so_snd);
1879 error = EINTR;
1880 goto done;
1881 }
1882
1883 /*
1884 * Get an mbuf header and set it up as having external storage.
1885 */
1886 MGETHDR(m, M_TRYWAIT, MT_DATA);
1887 if (m == NULL) {
1888 error = ENOBUFS;
1889 sf_buf_free((void *)sf_buf_kva(sf), sf);
1890 sbunlock(&so->so_snd);
1891 goto done;
1892 }
1893 /*
1894 * Setup external storage for mbuf.
1895 */
1896 MEXTADD(m, sf_buf_kva(sf), PAGE_SIZE, sf_buf_free, sf, M_RDONLY,
1897 EXT_SFBUF);
1898 m->m_data = (char *)sf_buf_kva(sf) + pgoff;
1899 m->m_pkthdr.len = m->m_len = xfsize;
1900 /*
1901 * Add the buffer to the socket buffer chain.
1902 */
1903 s = splnet();
1904retry_space:
1905 /*
1906 * Make sure that the socket is still able to take more data.
1907 * CANTSENDMORE being true usually means that the connection
1908 * was closed. so_error is true when an error was sensed after
1909 * a previous send.
1910 * The state is checked after the page mapping and buffer
1911 * allocation above since those operations may block and make
1912 * any socket checks stale. From this point forward, nothing
1913 * blocks before the pru_send (or more accurately, any blocking
1914 * results in a loop back to here to re-check).
1915 */
1916 if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
1917 if (so->so_state & SS_CANTSENDMORE) {
1918 error = EPIPE;
1919 } else {
1920 error = so->so_error;
1921 so->so_error = 0;
1922 }
1923 m_freem(m);
1924 sbunlock(&so->so_snd);
1925 splx(s);
1926 goto done;
1927 }
1928 /*
1929 * Wait for socket space to become available. We do this just
1930 * after checking the connection state above in order to avoid
1931 * a race condition with sbwait().
1932 */
1933 if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
1934 if (so->so_state & SS_NBIO) {
1935 m_freem(m);
1936 sbunlock(&so->so_snd);
1937 splx(s);
1938 error = EAGAIN;
1939 goto done;
1940 }
1941 error = sbwait(&so->so_snd);
1942 /*
1943 * An error from sbwait usually indicates that we've
1944 * been interrupted by a signal. If we've sent anything
1945 * then return bytes sent, otherwise return the error.
1946 */
1947 if (error) {
1948 m_freem(m);
1949 sbunlock(&so->so_snd);
1950 splx(s);
1951 goto done;
1952 }
1953 goto retry_space;
1954 }
1955 error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, td);
1956 splx(s);
1957 if (error) {
1958 sbunlock(&so->so_snd);
1959 goto done;
1960 }
1961 }
1962 sbunlock(&so->so_snd);
1963
1964 /*
1965 * Send trailers. Wimp out and use writev(2).
1966 */
1967 if (uap->hdtr != NULL && hdtr.trailers != NULL) {
1968 nuap.fd = uap->s;
1969 nuap.iovp = hdtr.trailers;
1970 nuap.iovcnt = hdtr.trl_cnt;
1971 error = writev(td, &nuap);
1972 if (error)
1973 goto done;
1974 if (compat)
1975 sbytes += td->td_retval[0];
1976 else
1977 hdtr_size += td->td_retval[0];
1978 }
1979
1980done:
1981 /*
1982 * If there was no error we have to clear td->td_retval[0]
1983 * because it may have been set by writev.
1984 */
1985 if (error == 0) {
1986 td->td_retval[0] = 0;
1987 }
1988 if (uap->sbytes != NULL) {
1989 if (!compat)
1990 sbytes += hdtr_size;
1991 copyout(&sbytes, uap->sbytes, sizeof(off_t));
1992 }
1993 if (vp)
1994 vrele(vp);
1995 if (so)
1996 fputsock(so);
1997
1998 mtx_unlock(&Giant);
1999
2000 if (error == ERESTART)
2001 error = EINTR;
2002
2003 return (error);
2004}
1488
1489 mtx_lock(&Giant);
1490 if ((error = fgetsock(td, uap->fdes, &so, NULL)) != 0)
1491 goto done2;
1492 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0) {
1493 error = ENOTCONN;
1494 goto done1;
1495 }
1496 error = copyin(uap->alen, &len, sizeof (len));
1497 if (error)
1498 goto done1;
1499 if (len < 0) {
1500 error = EINVAL;
1501 goto done1;
1502 }
1503 sa = 0;
1504 error = (*so->so_proto->pr_usrreqs->pru_peeraddr)(so, &sa);
1505 if (error)
1506 goto bad;
1507 if (sa == 0) {
1508 len = 0;
1509 goto gotnothing;
1510 }
1511 len = MIN(len, sa->sa_len);
1512#ifdef COMPAT_OLDSOCK
1513 if (compat)
1514 ((struct osockaddr *)sa)->sa_family =
1515 sa->sa_family;
1516#endif
1517 error = copyout(sa, uap->asa, (u_int)len);
1518 if (error)
1519 goto bad;
1520gotnothing:
1521 error = copyout(&len, uap->alen, sizeof (len));
1522bad:
1523 if (sa)
1524 FREE(sa, M_SONAME);
1525done1:
1526 fputsock(so);
1527done2:
1528 mtx_unlock(&Giant);
1529 return (error);
1530}
1531
1532/*
1533 * MPSAFE
1534 */
1535int
1536getpeername(td, uap)
1537 struct thread *td;
1538 struct getpeername_args *uap;
1539{
1540
1541 return (getpeername1(td, uap, 0));
1542}
1543
1544#ifdef COMPAT_OLDSOCK
1545/*
1546 * MPSAFE
1547 */
1548int
1549ogetpeername(td, uap)
1550 struct thread *td;
1551 struct ogetpeername_args *uap;
1552{
1553
1554 /* XXX uap should have type `getpeername_args *' to begin with. */
1555 return (getpeername1(td, (struct getpeername_args *)uap, 1));
1556}
1557#endif /* COMPAT_OLDSOCK */
1558
1559int
1560sockargs(mp, buf, buflen, type)
1561 struct mbuf **mp;
1562 caddr_t buf;
1563 int buflen, type;
1564{
1565 register struct sockaddr *sa;
1566 register struct mbuf *m;
1567 int error;
1568
1569 if ((u_int)buflen > MLEN) {
1570#ifdef COMPAT_OLDSOCK
1571 if (type == MT_SONAME && (u_int)buflen <= 112)
1572 buflen = MLEN; /* unix domain compat. hack */
1573 else
1574#endif
1575 return (EINVAL);
1576 }
1577 m = m_get(M_TRYWAIT, type);
1578 if (m == NULL)
1579 return (ENOBUFS);
1580 m->m_len = buflen;
1581 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
1582 if (error)
1583 (void) m_free(m);
1584 else {
1585 *mp = m;
1586 if (type == MT_SONAME) {
1587 sa = mtod(m, struct sockaddr *);
1588
1589#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1590 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1591 sa->sa_family = sa->sa_len;
1592#endif
1593 sa->sa_len = buflen;
1594 }
1595 }
1596 return (error);
1597}
1598
1599int
1600getsockaddr(namp, uaddr, len)
1601 struct sockaddr **namp;
1602 caddr_t uaddr;
1603 size_t len;
1604{
1605 struct sockaddr *sa;
1606 int error;
1607
1608 if (len > SOCK_MAXADDRLEN)
1609 return ENAMETOOLONG;
1610 MALLOC(sa, struct sockaddr *, len, M_SONAME, M_WAITOK);
1611 error = copyin(uaddr, sa, len);
1612 if (error) {
1613 FREE(sa, M_SONAME);
1614 } else {
1615#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
1616 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1617 sa->sa_family = sa->sa_len;
1618#endif
1619 sa->sa_len = len;
1620 *namp = sa;
1621 }
1622 return error;
1623}
1624
1625/*
1626 * sendfile(2)
1627 *
1628 * MPSAFE
1629 *
1630 * int sendfile(int fd, int s, off_t offset, size_t nbytes,
1631 * struct sf_hdtr *hdtr, off_t *sbytes, int flags)
1632 *
1633 * Send a file specified by 'fd' and starting at 'offset' to a socket
1634 * specified by 's'. Send only 'nbytes' of the file or until EOF if
1635 * nbytes == 0. Optionally add a header and/or trailer to the socket
1636 * output. If specified, write the total number of bytes sent into *sbytes.
1637 *
1638 */
1639int
1640sendfile(struct thread *td, struct sendfile_args *uap)
1641{
1642
1643 return (do_sendfile(td, uap, 0));
1644}
1645
1646#ifdef COMPAT_FREEBSD4
1647int
1648freebsd4_sendfile(struct thread *td, struct freebsd4_sendfile_args *uap)
1649{
1650 struct sendfile_args args;
1651
1652 args.fd = uap->fd;
1653 args.s = uap->s;
1654 args.offset = uap->offset;
1655 args.nbytes = uap->nbytes;
1656 args.hdtr = uap->hdtr;
1657 args.sbytes = uap->sbytes;
1658 args.flags = uap->flags;
1659
1660 return (do_sendfile(td, &args, 1));
1661}
1662#endif /* COMPAT_FREEBSD4 */
1663
1664static int
1665do_sendfile(struct thread *td, struct sendfile_args *uap, int compat)
1666{
1667 struct vnode *vp;
1668 struct vm_object *obj;
1669 struct socket *so = NULL;
1670 struct mbuf *m;
1671 struct sf_buf *sf;
1672 struct vm_page *pg;
1673 struct writev_args nuap;
1674 struct sf_hdtr hdtr;
1675 off_t off, xfsize, hdtr_size, sbytes = 0;
1676 int error, s;
1677
1678 mtx_lock(&Giant);
1679
1680 hdtr_size = 0;
1681
1682 /*
1683 * The descriptor must be a regular file and have a backing VM object.
1684 */
1685 if ((error = fgetvp_read(td, uap->fd, &vp)) != 0)
1686 goto done;
1687 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1688 if (vp->v_type != VREG || VOP_GETVOBJECT(vp, &obj) != 0) {
1689 error = EINVAL;
1690 VOP_UNLOCK(vp, 0, td);
1691 goto done;
1692 }
1693 VOP_UNLOCK(vp, 0, td);
1694 if ((error = fgetsock(td, uap->s, &so, NULL)) != 0)
1695 goto done;
1696 if (so->so_type != SOCK_STREAM) {
1697 error = EINVAL;
1698 goto done;
1699 }
1700 if ((so->so_state & SS_ISCONNECTED) == 0) {
1701 error = ENOTCONN;
1702 goto done;
1703 }
1704 if (uap->offset < 0) {
1705 error = EINVAL;
1706 goto done;
1707 }
1708
1709#ifdef MAC
1710 error = mac_check_socket_send(td->td_ucred, so);
1711 if (error)
1712 goto done;
1713#endif
1714
1715 /*
1716 * If specified, get the pointer to the sf_hdtr struct for
1717 * any headers/trailers.
1718 */
1719 if (uap->hdtr != NULL) {
1720 error = copyin(uap->hdtr, &hdtr, sizeof(hdtr));
1721 if (error)
1722 goto done;
1723 /*
1724 * Send any headers. Wimp out and use writev(2).
1725 */
1726 if (hdtr.headers != NULL) {
1727 nuap.fd = uap->s;
1728 nuap.iovp = hdtr.headers;
1729 nuap.iovcnt = hdtr.hdr_cnt;
1730 error = writev(td, &nuap);
1731 if (error)
1732 goto done;
1733 if (compat)
1734 sbytes += td->td_retval[0];
1735 else
1736 hdtr_size += td->td_retval[0];
1737 }
1738 }
1739
1740 /*
1741 * Protect against multiple writers to the socket.
1742 */
1743 (void) sblock(&so->so_snd, M_WAITOK);
1744
1745 /*
1746 * Loop through the pages in the file, starting with the requested
1747 * offset. Get a file page (do I/O if necessary), map the file page
1748 * into an sf_buf, attach an mbuf header to the sf_buf, and queue
1749 * it on the socket.
1750 */
1751 for (off = uap->offset; ; off += xfsize, sbytes += xfsize) {
1752 vm_pindex_t pindex;
1753 vm_offset_t pgoff;
1754
1755 pindex = OFF_TO_IDX(off);
1756 VM_OBJECT_LOCK(obj);
1757retry_lookup:
1758 /*
1759 * Calculate the amount to transfer. Not to exceed a page,
1760 * the EOF, or the passed in nbytes.
1761 */
1762 xfsize = obj->un_pager.vnp.vnp_size - off;
1763 VM_OBJECT_UNLOCK(obj);
1764 if (xfsize > PAGE_SIZE)
1765 xfsize = PAGE_SIZE;
1766 pgoff = (vm_offset_t)(off & PAGE_MASK);
1767 if (PAGE_SIZE - pgoff < xfsize)
1768 xfsize = PAGE_SIZE - pgoff;
1769 if (uap->nbytes && xfsize > (uap->nbytes - sbytes))
1770 xfsize = uap->nbytes - sbytes;
1771 if (xfsize <= 0)
1772 break;
1773 /*
1774 * Optimize the non-blocking case by looking at the socket space
1775 * before going to the extra work of constituting the sf_buf.
1776 */
1777 if ((so->so_state & SS_NBIO) && sbspace(&so->so_snd) <= 0) {
1778 if (so->so_state & SS_CANTSENDMORE)
1779 error = EPIPE;
1780 else
1781 error = EAGAIN;
1782 sbunlock(&so->so_snd);
1783 goto done;
1784 }
1785 VM_OBJECT_LOCK(obj);
1786 /*
1787 * Attempt to look up the page.
1788 *
1789 * Allocate if not found
1790 *
1791 * Wait and loop if busy.
1792 */
1793 pg = vm_page_lookup(obj, pindex);
1794
1795 if (pg == NULL) {
1796 pg = vm_page_alloc(obj, pindex,
1797 VM_ALLOC_NORMAL | VM_ALLOC_WIRED);
1798 if (pg == NULL) {
1799 VM_OBJECT_UNLOCK(obj);
1800 VM_WAIT;
1801 VM_OBJECT_LOCK(obj);
1802 goto retry_lookup;
1803 }
1804 vm_page_lock_queues();
1805 vm_page_wakeup(pg);
1806 } else {
1807 vm_page_lock_queues();
1808 if (vm_page_sleep_if_busy(pg, TRUE, "sfpbsy"))
1809 goto retry_lookup;
1810 /*
1811 * Wire the page so it does not get ripped out from
1812 * under us.
1813 */
1814 vm_page_wire(pg);
1815 }
1816
1817 /*
1818 * If page is not valid for what we need, initiate I/O
1819 */
1820
1821 if (!pg->valid || !vm_page_is_valid(pg, pgoff, xfsize)) {
1822 int bsize, resid;
1823
1824 /*
1825 * Ensure that our page is still around when the I/O
1826 * completes.
1827 */
1828 vm_page_io_start(pg);
1829 vm_page_unlock_queues();
1830 VM_OBJECT_UNLOCK(obj);
1831
1832 /*
1833 * Get the page from backing store.
1834 */
1835 bsize = vp->v_mount->mnt_stat.f_iosize;
1836 vn_lock(vp, LK_SHARED | LK_NOPAUSE | LK_RETRY, td);
1837 /*
1838 * XXXMAC: Because we don't have fp->f_cred here,
1839 * we pass in NOCRED. This is probably wrong, but
1840 * is consistent with our original implementation.
1841 */
1842 error = vn_rdwr(UIO_READ, vp, NULL, MAXBSIZE,
1843 trunc_page(off), UIO_NOCOPY, IO_NODELOCKED |
1844 IO_VMIO | ((MAXBSIZE / bsize) << 16),
1845 td->td_ucred, NOCRED, &resid, td);
1846 VOP_UNLOCK(vp, 0, td);
1847 if (error)
1848 VM_OBJECT_LOCK(obj);
1849 vm_page_lock_queues();
1850 vm_page_flag_clear(pg, PG_ZERO);
1851 vm_page_io_finish(pg);
1852 if (error) {
1853 vm_page_unwire(pg, 0);
1854 /*
1855 * See if anyone else might know about this page.
1856 * If not and it is not valid, then free it.
1857 */
1858 if (pg->wire_count == 0 && pg->valid == 0 &&
1859 pg->busy == 0 && !(pg->flags & PG_BUSY) &&
1860 pg->hold_count == 0) {
1861 vm_page_busy(pg);
1862 vm_page_free(pg);
1863 }
1864 vm_page_unlock_queues();
1865 VM_OBJECT_UNLOCK(obj);
1866 sbunlock(&so->so_snd);
1867 goto done;
1868 }
1869 } else
1870 VM_OBJECT_UNLOCK(obj);
1871 vm_page_unlock_queues();
1872
1873 /*
1874 * Get a sendfile buf. We usually wait as long as necessary,
1875 * but this wait can be interrupted.
1876 */
1877 if ((sf = sf_buf_alloc(pg)) == NULL) {
1878 vm_page_lock_queues();
1879 vm_page_unwire(pg, 0);
1880 if (pg->wire_count == 0 && pg->object == NULL)
1881 vm_page_free(pg);
1882 vm_page_unlock_queues();
1883 sbunlock(&so->so_snd);
1884 error = EINTR;
1885 goto done;
1886 }
1887
1888 /*
1889 * Get an mbuf header and set it up as having external storage.
1890 */
1891 MGETHDR(m, M_TRYWAIT, MT_DATA);
1892 if (m == NULL) {
1893 error = ENOBUFS;
1894 sf_buf_free((void *)sf_buf_kva(sf), sf);
1895 sbunlock(&so->so_snd);
1896 goto done;
1897 }
1898 /*
1899 * Setup external storage for mbuf.
1900 */
1901 MEXTADD(m, sf_buf_kva(sf), PAGE_SIZE, sf_buf_free, sf, M_RDONLY,
1902 EXT_SFBUF);
1903 m->m_data = (char *)sf_buf_kva(sf) + pgoff;
1904 m->m_pkthdr.len = m->m_len = xfsize;
1905 /*
1906 * Add the buffer to the socket buffer chain.
1907 */
1908 s = splnet();
1909retry_space:
1910 /*
1911 * Make sure that the socket is still able to take more data.
1912 * CANTSENDMORE being true usually means that the connection
1913 * was closed. so_error is true when an error was sensed after
1914 * a previous send.
1915 * The state is checked after the page mapping and buffer
1916 * allocation above since those operations may block and make
1917 * any socket checks stale. From this point forward, nothing
1918 * blocks before the pru_send (or more accurately, any blocking
1919 * results in a loop back to here to re-check).
1920 */
1921 if ((so->so_state & SS_CANTSENDMORE) || so->so_error) {
1922 if (so->so_state & SS_CANTSENDMORE) {
1923 error = EPIPE;
1924 } else {
1925 error = so->so_error;
1926 so->so_error = 0;
1927 }
1928 m_freem(m);
1929 sbunlock(&so->so_snd);
1930 splx(s);
1931 goto done;
1932 }
1933 /*
1934 * Wait for socket space to become available. We do this just
1935 * after checking the connection state above in order to avoid
1936 * a race condition with sbwait().
1937 */
1938 if (sbspace(&so->so_snd) < so->so_snd.sb_lowat) {
1939 if (so->so_state & SS_NBIO) {
1940 m_freem(m);
1941 sbunlock(&so->so_snd);
1942 splx(s);
1943 error = EAGAIN;
1944 goto done;
1945 }
1946 error = sbwait(&so->so_snd);
1947 /*
1948 * An error from sbwait usually indicates that we've
1949 * been interrupted by a signal. If we've sent anything
1950 * then return bytes sent, otherwise return the error.
1951 */
1952 if (error) {
1953 m_freem(m);
1954 sbunlock(&so->so_snd);
1955 splx(s);
1956 goto done;
1957 }
1958 goto retry_space;
1959 }
1960 error = (*so->so_proto->pr_usrreqs->pru_send)(so, 0, m, 0, 0, td);
1961 splx(s);
1962 if (error) {
1963 sbunlock(&so->so_snd);
1964 goto done;
1965 }
1966 }
1967 sbunlock(&so->so_snd);
1968
1969 /*
1970 * Send trailers. Wimp out and use writev(2).
1971 */
1972 if (uap->hdtr != NULL && hdtr.trailers != NULL) {
1973 nuap.fd = uap->s;
1974 nuap.iovp = hdtr.trailers;
1975 nuap.iovcnt = hdtr.trl_cnt;
1976 error = writev(td, &nuap);
1977 if (error)
1978 goto done;
1979 if (compat)
1980 sbytes += td->td_retval[0];
1981 else
1982 hdtr_size += td->td_retval[0];
1983 }
1984
1985done:
1986 /*
1987 * If there was no error we have to clear td->td_retval[0]
1988 * because it may have been set by writev.
1989 */
1990 if (error == 0) {
1991 td->td_retval[0] = 0;
1992 }
1993 if (uap->sbytes != NULL) {
1994 if (!compat)
1995 sbytes += hdtr_size;
1996 copyout(&sbytes, uap->sbytes, sizeof(off_t));
1997 }
1998 if (vp)
1999 vrele(vp);
2000 if (so)
2001 fputsock(so);
2002
2003 mtx_unlock(&Giant);
2004
2005 if (error == ERESTART)
2006 error = EINTR;
2007
2008 return (error);
2009}