marc's changes: malloc uio if too large, ktrace
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
da7c5cc6 1/*
6d47a3da 2 * Copyright (c) 1982, 1986, 1988 The Regents of the University of California.
96e6449f 3 * All rights reserved.
da7c5cc6 4 *
96e6449f 5 * Redistribution and use in source and binary forms are permitted
616d42db
KB
6 * provided that the above copyright notice and this paragraph are
7 * duplicated in all such forms and that any documentation,
8 * advertising materials, and other materials related to such
9 * distribution and use acknowledge that the software was developed
10 * by the University of California, Berkeley. The name of the
11 * University may not be used to endorse or promote products derived
12 * from this software without specific prior written permission.
13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
15 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
96e6449f 16 *
6d47a3da 17 * @(#)uipc_syscalls.c 7.6 (Berkeley) %G%
da7c5cc6 18 */
c8c7dd0e 19
94368568 20#include "param.h"
94368568
JB
21#include "dir.h"
22#include "user.h"
6d47a3da 23#include "proc.h"
94368568 24#include "file.h"
94368568 25#include "buf.h"
6d47a3da 26#include "malloc.h"
94368568
JB
27#include "mbuf.h"
28#include "protosw.h"
29#include "socket.h"
30#include "socketvar.h"
4147b3f6 31
c8c7dd0e 32/*
cf012934 33 * System call interface to the socket abstraction.
c8c7dd0e
BJ
34 */
35
88a7a62a
SL
36struct file *getsock();
37extern struct fileops socketops;
38
cf012934 39socket()
c8c7dd0e 40{
cc15ab5d 41 register struct a {
cf012934 42 int domain;
cc15ab5d 43 int type;
cf012934 44 int protocol;
cc15ab5d 45 } *uap = (struct a *)u.u_ap;
2b4b57cd 46 struct socket *so;
cc15ab5d 47 register struct file *fp;
c8c7dd0e 48
dfb67abe 49 if ((fp = falloc()) == NULL)
66f52238 50 return;
4147b3f6
BJ
51 fp->f_flag = FREAD|FWRITE;
52 fp->f_type = DTYPE_SOCKET;
88a7a62a 53 fp->f_ops = &socketops;
66f52238 54 u.u_error = socreate(uap->domain, &so, uap->type, uap->protocol);
cc15ab5d
BJ
55 if (u.u_error)
56 goto bad;
88a7a62a 57 fp->f_data = (caddr_t)so;
cc15ab5d
BJ
58 return;
59bad:
60 u.u_ofile[u.u_r.r_val1] = 0;
61 fp->f_count = 0;
c8c7dd0e 62}
ae921915 63
cf012934 64bind()
ae921915 65{
2b4b57cd 66 register struct a {
cf012934
BJ
67 int s;
68 caddr_t name;
69 int namelen;
2b4b57cd 70 } *uap = (struct a *)u.u_ap;
2b4b57cd 71 register struct file *fp;
cf012934 72 struct mbuf *nam;
ae921915 73
88a7a62a 74 fp = getsock(uap->s);
cf012934
BJ
75 if (fp == 0)
76 return;
98447d3f 77 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
cf012934
BJ
78 if (u.u_error)
79 return;
88a7a62a 80 u.u_error = sobind((struct socket *)fp->f_data, nam);
cf012934 81 m_freem(nam);
cf012934
BJ
82}
83
84listen()
85{
86 register struct a {
87 int s;
88 int backlog;
89 } *uap = (struct a *)u.u_ap;
90 register struct file *fp;
91
88a7a62a 92 fp = getsock(uap->s);
2b4b57cd
BJ
93 if (fp == 0)
94 return;
88a7a62a 95 u.u_error = solisten((struct socket *)fp->f_data, uap->backlog);
cf012934
BJ
96}
97
98accept()
99{
100 register struct a {
101 int s;
102 caddr_t name;
103 int *anamelen;
cf012934
BJ
104 } *uap = (struct a *)u.u_ap;
105 register struct file *fp;
106 struct mbuf *nam;
cf012934
BJ
107 int namelen;
108 int s;
109 register struct socket *so;
110
111 if (uap->name == 0)
112 goto noname;
127f7d76
SL
113 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
114 sizeof (namelen));
115 if (u.u_error)
cf012934 116 return;
b32450f4 117 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
cf012934
BJ
118 u.u_error = EFAULT;
119 return;
120 }
121noname:
88a7a62a 122 fp = getsock(uap->s);
cf012934 123 if (fp == 0)
66f52238 124 return;
2b4b57cd 125 s = splnet();
88a7a62a 126 so = (struct socket *)fp->f_data;
4147b3f6
BJ
127 if ((so->so_options & SO_ACCEPTCONN) == 0) {
128 u.u_error = EINVAL;
129 splx(s);
66f52238 130 return;
4147b3f6
BJ
131 }
132 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
2b4b57cd
BJ
133 u.u_error = EWOULDBLOCK;
134 splx(s);
66f52238 135 return;
2b4b57cd 136 }
4147b3f6 137 while (so->so_qlen == 0 && so->so_error == 0) {
62229532
BJ
138 if (so->so_state & SS_CANTRCVMORE) {
139 so->so_error = ECONNABORTED;
140 break;
141 }
d08c5322 142 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 143 }
f269ef23
BJ
144 if (so->so_error) {
145 u.u_error = so->so_error;
f4ed5810 146 so->so_error = 0;
f269ef23 147 splx(s);
66f52238 148 return;
f269ef23 149 }
88a7a62a 150 if (ufalloc(0) < 0) {
4147b3f6 151 splx(s);
66f52238 152 return;
4147b3f6
BJ
153 }
154 fp = falloc();
155 if (fp == 0) {
156 u.u_ofile[u.u_r.r_val1] = 0;
2b4b57cd 157 splx(s);
66f52238 158 return;
cf012934
BJ
159 }
160 { struct socket *aso = so->so_q;
161 if (soqremque(aso, 1) == 0)
162 panic("accept");
163 so = aso;
2b4b57cd 164 }
4147b3f6
BJ
165 fp->f_type = DTYPE_SOCKET;
166 fp->f_flag = FREAD|FWRITE;
88a7a62a
SL
167 fp->f_ops = &socketops;
168 fp->f_data = (caddr_t)so;
cce93e4b 169 nam = m_get(M_WAIT, MT_SONAME);
66f52238 170 (void) soaccept(so, nam);
cf012934
BJ
171 if (uap->name) {
172 if (namelen > nam->m_len)
173 namelen = nam->m_len;
174 /* SHOULD COPY OUT A CHAIN HERE */
b32450f4
BJ
175 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
176 (u_int)namelen);
177 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
cf012934
BJ
178 sizeof (*uap->anamelen));
179 }
180 m_freem(nam);
2b4b57cd 181 splx(s);
ae921915
BJ
182}
183
6d47a3da
MK
184#ifdef COMPAT_43
185oaccept()
186{
187 return (accept());
188}
189#endif
190
cf012934 191connect()
c8c7dd0e
BJ
192{
193 register struct a {
cf012934
BJ
194 int s;
195 caddr_t name;
196 int namelen;
c8c7dd0e 197 } *uap = (struct a *)u.u_ap;
c8c7dd0e
BJ
198 register struct file *fp;
199 register struct socket *so;
cf012934 200 struct mbuf *nam;
c8c7dd0e
BJ
201 int s;
202
88a7a62a 203 fp = getsock(uap->s);
c8c7dd0e
BJ
204 if (fp == 0)
205 return;
88a7a62a 206 so = (struct socket *)fp->f_data;
a7a77c02
MK
207 if ((so->so_state & SS_NBIO) &&
208 (so->so_state & SS_ISCONNECTING)) {
6222acc3 209 u.u_error = EALREADY;
a7a77c02
MK
210 return;
211 }
98447d3f 212 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
c8c7dd0e
BJ
213 if (u.u_error)
214 return;
66f52238 215 u.u_error = soconnect(so, nam);
cf012934
BJ
216 if (u.u_error)
217 goto bad;
6222acc3
MK
218 if ((so->so_state & SS_NBIO) &&
219 (so->so_state & SS_ISCONNECTING)) {
220 u.u_error = EINPROGRESS;
221 m_freem(nam);
222 return;
223 }
c8c7dd0e 224 s = splnet();
88a7a62a
SL
225 if (setjmp(&u.u_qsave)) {
226 if (u.u_error == 0)
227 u.u_error = EINTR;
228 goto bad2;
c8c7dd0e 229 }
cc15ab5d 230 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
231 sleep((caddr_t)&so->so_timeo, PZERO+1);
232 u.u_error = so->so_error;
cc15ab5d 233 so->so_error = 0;
88a7a62a 234bad2:
cc15ab5d 235 splx(s);
cf012934 236bad:
6750daae 237 so->so_state &= ~SS_ISCONNECTING;
cf012934 238 m_freem(nam);
c8c7dd0e
BJ
239}
240
cf012934
BJ
241socketpair()
242{
5a48956d
SL
243 register struct a {
244 int domain;
245 int type;
246 int protocol;
247 int *rsv;
248 } *uap = (struct a *)u.u_ap;
249 register struct file *fp1, *fp2;
250 struct socket *so1, *so2;
251 int sv[2];
cf012934 252
5a48956d
SL
253 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
254 u.u_error = EFAULT;
255 return;
256 }
257 u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
258 if (u.u_error)
259 return;
260 u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
261 if (u.u_error)
262 goto free;
263 fp1 = falloc();
264 if (fp1 == NULL)
265 goto free2;
266 sv[0] = u.u_r.r_val1;
267 fp1->f_flag = FREAD|FWRITE;
268 fp1->f_type = DTYPE_SOCKET;
269 fp1->f_ops = &socketops;
270 fp1->f_data = (caddr_t)so1;
271 fp2 = falloc();
272 if (fp2 == NULL)
273 goto free3;
274 fp2->f_flag = FREAD|FWRITE;
275 fp2->f_type = DTYPE_SOCKET;
276 fp2->f_ops = &socketops;
277 fp2->f_data = (caddr_t)so2;
278 sv[1] = u.u_r.r_val1;
279 u.u_error = soconnect2(so1, so2);
280 if (u.u_error)
281 goto free4;
33446404
MK
282 if (uap->type == SOCK_DGRAM) {
283 /*
284 * Datagram socket connection is asymmetric.
285 */
286 u.u_error = soconnect2(so2, so1);
287 if (u.u_error)
288 goto free4;
289 }
290 u.u_r.r_val1 = 0;
5a48956d
SL
291 (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
292 return;
293free4:
294 fp2->f_count = 0;
295 u.u_ofile[sv[1]] = 0;
296free3:
297 fp1->f_count = 0;
298 u.u_ofile[sv[0]] = 0;
299free2:
8011f5df 300 (void)soclose(so2);
5a48956d 301free:
8011f5df 302 (void)soclose(so1);
cf012934
BJ
303}
304
305sendto()
c8c7dd0e
BJ
306{
307 register struct a {
cf012934
BJ
308 int s;
309 caddr_t buf;
310 int len;
311 int flags;
312 caddr_t to;
313 int tolen;
c8c7dd0e 314 } *uap = (struct a *)u.u_ap;
88a7a62a 315 struct msghdr msg;
d3d550b5 316 struct iovec aiov;
c8c7dd0e 317
88a7a62a
SL
318 msg.msg_name = uap->to;
319 msg.msg_namelen = uap->tolen;
320 msg.msg_iov = &aiov;
321 msg.msg_iovlen = 1;
cf012934
BJ
322 aiov.iov_base = uap->buf;
323 aiov.iov_len = uap->len;
88a7a62a 324 msg.msg_accrights = 0;
6d47a3da 325 msg.msg_control = 0;
88a7a62a 326 sendit(uap->s, &msg, uap->flags);
c8c7dd0e
BJ
327}
328
6d47a3da
MK
329#ifdef COMPAT_43
330osend()
cc15ab5d
BJ
331{
332 register struct a {
cf012934
BJ
333 int s;
334 caddr_t buf;
335 int len;
336 int flags;
cc15ab5d 337 } *uap = (struct a *)u.u_ap;
88a7a62a 338 struct msghdr msg;
a6b6f679 339 struct iovec aiov;
cc15ab5d 340
88a7a62a
SL
341 msg.msg_name = 0;
342 msg.msg_namelen = 0;
343 msg.msg_iov = &aiov;
344 msg.msg_iovlen = 1;
cf012934
BJ
345 aiov.iov_base = uap->buf;
346 aiov.iov_len = uap->len;
88a7a62a 347 msg.msg_accrights = 0;
6d47a3da 348 msg.msg_control = 0;
88a7a62a
SL
349 sendit(uap->s, &msg, uap->flags);
350}
351
6d47a3da
MK
352osendmsg()
353{
354 register struct a {
355 int s;
356 caddr_t msg;
357 int flags;
358 } *uap = (struct a *)u.u_ap;
359 struct msghdr msg;
360 struct iovec aiov[MSG_MAXIOVLEN];
361
362 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
363 if (u.u_error)
364 return;
365 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
366 u.u_error = EMSGSIZE;
367 return;
368 }
369 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
370 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
371 if (u.u_error)
372 return;
373 msg.msg_control = 0;
374 msg.msg_controllen = 0;
375 sendit(uap->s, &msg, uap->flags);
376}
377#endif
378
88a7a62a
SL
379sendmsg()
380{
381 register struct a {
382 int s;
383 caddr_t msg;
384 int flags;
385 } *uap = (struct a *)u.u_ap;
386 struct msghdr msg;
387 struct iovec aiov[MSG_MAXIOVLEN];
388
389 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
390 if (u.u_error)
391 return;
392 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
393 u.u_error = EMSGSIZE;
cf012934
BJ
394 return;
395 }
6d47a3da 396 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
88a7a62a 397 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
cf012934
BJ
398 if (u.u_error)
399 return;
88a7a62a 400 msg.msg_iov = aiov;
88a7a62a
SL
401 sendit(uap->s, &msg, uap->flags);
402}
403
404sendit(s, mp, flags)
405 int s;
406 register struct msghdr *mp;
407 int flags;
408{
409 register struct file *fp;
410 struct uio auio;
411 register struct iovec *iov;
412 register int i;
6d47a3da 413 struct mbuf *to, *rights, *control;
88a7a62a
SL
414 int len;
415
416 fp = getsock(s);
417 if (fp == 0)
418 return;
419 auio.uio_iov = mp->msg_iov;
420 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 421 auio.uio_segflg = UIO_USERSPACE;
88a7a62a
SL
422 auio.uio_offset = 0; /* XXX */
423 auio.uio_resid = 0;
424 iov = mp->msg_iov;
125c8f95 425 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
88a7a62a
SL
426 if (iov->iov_len < 0) {
427 u.u_error = EINVAL;
428 return;
429 }
0f6422b0
MK
430 if (iov->iov_len == 0)
431 continue;
88a7a62a
SL
432 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
433 u.u_error = EFAULT;
434 return;
435 }
436 auio.uio_resid += iov->iov_len;
88a7a62a
SL
437 }
438 if (mp->msg_name) {
439 u.u_error =
98447d3f 440 sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
88a7a62a
SL
441 if (u.u_error)
442 return;
443 } else
444 to = 0;
445 if (mp->msg_accrights) {
446 u.u_error =
98447d3f
MK
447 sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
448 MT_RIGHTS);
88a7a62a
SL
449 if (u.u_error)
450 goto bad;
451 } else
452 rights = 0;
6d47a3da
MK
453 if (mp->msg_control) {
454 u.u_error =
455 sockargs(&control, mp->msg_control, mp->msg_controllen,
456 MT_CONTROL);
457 if (u.u_error)
458 goto bad;
459 } else
460 control = 0;
88a7a62a 461 len = auio.uio_resid;
6d47a3da
MK
462 if (setjmp(&u.u_qsave)) { /* XXX */
463 if (auio.uio_resid == len) {
464 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
465 u.u_error = EINTR;
466 else
467 u.u_eosys = RESTARTSYS;
468 }
469 } else
470 u.u_error = sosend((struct socket *)fp->f_data, to, &auio,
471 flags, rights, control);
88a7a62a 472 u.u_r.r_val1 = len - auio.uio_resid;
6d47a3da 473bad:
88a7a62a
SL
474 if (rights)
475 m_freem(rights);
88a7a62a
SL
476 if (to)
477 m_freem(to);
6d47a3da
MK
478 if (control)
479 m_freem(control);
cf012934
BJ
480}
481
482recvfrom()
483{
484 register struct a {
485 int s;
486 caddr_t buf;
487 int len;
488 int flags;
489 caddr_t from;
490 int *fromlenaddr;
491 } *uap = (struct a *)u.u_ap;
88a7a62a 492 struct msghdr msg;
cf012934 493 struct iovec aiov;
88a7a62a 494 int len;
cf012934 495
6d47a3da
MK
496 if (uap->fromlenaddr) {
497 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
498 sizeof (len));
499 if (u.u_error)
500 return;
501 } else
502 len = 0;
88a7a62a
SL
503 msg.msg_name = uap->from;
504 msg.msg_namelen = len;
505 msg.msg_iov = &aiov;
506 msg.msg_iovlen = 1;
cf012934
BJ
507 aiov.iov_base = uap->buf;
508 aiov.iov_len = uap->len;
88a7a62a 509 msg.msg_accrights = 0;
6d47a3da
MK
510 msg.msg_control = 0;
511 msg.msg_flags = uap->flags;
512 recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, (caddr_t)0);
cf012934
BJ
513}
514
6d47a3da
MK
515#ifdef COMPAT_43
516orecvfrom()
517{
518 return (recvfrom());
519}
520
521orecv()
cf012934
BJ
522{
523 register struct a {
524 int s;
525 caddr_t buf;
526 int len;
527 int flags;
528 } *uap = (struct a *)u.u_ap;
88a7a62a 529 struct msghdr msg;
cf012934
BJ
530 struct iovec aiov;
531
88a7a62a
SL
532 msg.msg_name = 0;
533 msg.msg_namelen = 0;
534 msg.msg_iov = &aiov;
535 msg.msg_iovlen = 1;
cf012934
BJ
536 aiov.iov_base = uap->buf;
537 aiov.iov_len = uap->len;
88a7a62a 538 msg.msg_accrights = 0;
6d47a3da
MK
539 msg.msg_control = 0;
540 msg.msg_flags = uap->flags;
541 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, (caddr_t)0);
542}
543
544orecvmsg()
545{
546 register struct a {
547 int s;
548 struct omsghdr *msg;
549 int flags;
550 } *uap = (struct a *)u.u_ap;
551 struct msghdr msg;
552 struct iovec aiov[MSG_MAXIOVLEN];
553
554 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
555 sizeof (struct omsghdr));
556 if (u.u_error)
557 return;
558 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
559 u.u_error = EMSGSIZE;
560 return;
561 }
562 msg.msg_control = 0;
563 msg.msg_flags = uap->flags;
564 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
565 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
566 if (u.u_error)
567 return;
568 msg.msg_iov = aiov;
569 if (msg.msg_accrights)
570 if (useracc((caddr_t)msg.msg_accrights,
571 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
572 u.u_error = EFAULT;
573 return;
574 }
575
576 recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen,
577 (caddr_t)&uap->msg->msg_accrightslen, (caddr_t)0);
cf012934 578}
6d47a3da 579#endif
cf012934 580
88a7a62a 581recvmsg()
cf012934 582{
88a7a62a
SL
583 register struct a {
584 int s;
585 struct msghdr *msg;
586 int flags;
587 } *uap = (struct a *)u.u_ap;
588 struct msghdr msg;
589 struct iovec aiov[MSG_MAXIOVLEN];
cf012934 590
88a7a62a
SL
591 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
592 if (u.u_error)
593 return;
594 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
595 u.u_error = EMSGSIZE;
596 return;
597 }
6d47a3da
MK
598 msg.msg_flags = uap->flags;
599 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
88a7a62a
SL
600 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
601 if (u.u_error)
602 return;
603 msg.msg_iov = aiov;
604 if (msg.msg_accrights)
605 if (useracc((caddr_t)msg.msg_accrights,
606 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
607 u.u_error = EFAULT;
608 return;
609 }
6d47a3da
MK
610 if (msg.msg_control)
611 if (useracc((caddr_t)msg.msg_control,
612 (unsigned)msg.msg_controllen, B_WRITE) == 0) {
613 u.u_error = EFAULT;
614 return;
615 }
616 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, (caddr_t)0);
617 u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof (msg));
cf012934
BJ
618}
619
6d47a3da 620recvit(s, mp, namelenp, rightslenp, controllenp)
88a7a62a
SL
621 int s;
622 register struct msghdr *mp;
6d47a3da 623 caddr_t namelenp, rightslenp, controllenp;
cf012934 624{
88a7a62a
SL
625 register struct file *fp;
626 struct uio auio;
627 register struct iovec *iov;
628 register int i;
88a7a62a 629 int len;
6d47a3da 630 struct mbuf *from = 0, *rights = 0, *control = 0;
88a7a62a
SL
631
632 fp = getsock(s);
633 if (fp == 0)
634 return;
635 auio.uio_iov = mp->msg_iov;
636 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 637 auio.uio_segflg = UIO_USERSPACE;
88a7a62a
SL
638 auio.uio_offset = 0; /* XXX */
639 auio.uio_resid = 0;
640 iov = mp->msg_iov;
125c8f95 641 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
88a7a62a
SL
642 if (iov->iov_len < 0) {
643 u.u_error = EINVAL;
644 return;
645 }
0f6422b0
MK
646 if (iov->iov_len == 0)
647 continue;
88a7a62a
SL
648 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
649 u.u_error = EFAULT;
650 return;
651 }
652 auio.uio_resid += iov->iov_len;
88a7a62a
SL
653 }
654 len = auio.uio_resid;
6d47a3da
MK
655 if (setjmp(&u.u_qsave)) { /* XXX */
656 if (auio.uio_resid == len) {
657 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
658 u.u_error = EINTR;
659 else
660 u.u_eosys = RESTARTSYS;
661 }
662 } else
663 u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio,
664 &mp->msg_flags, &rights, &control);
88a7a62a
SL
665 u.u_r.r_val1 = len - auio.uio_resid;
666 if (mp->msg_name) {
667 len = mp->msg_namelen;
668 if (len <= 0 || from == 0)
669 len = 0;
670 else {
671 if (len > from->m_len)
672 len = from->m_len;
6d47a3da 673 (void) copyout(mtod(from, caddr_t),
88a7a62a
SL
674 (caddr_t)mp->msg_name, (unsigned)len);
675 }
6d47a3da
MK
676 if (namelenp)
677 (void) copyout((caddr_t)&len, namelenp, sizeof (int));
88a7a62a
SL
678 }
679 if (mp->msg_accrights) {
680 len = mp->msg_accrightslen;
681 if (len <= 0 || rights == 0)
682 len = 0;
683 else {
684 if (len > rights->m_len)
685 len = rights->m_len;
686 (void) copyout((caddr_t)mtod(rights, caddr_t),
687 (caddr_t)mp->msg_accrights, (unsigned)len);
688 }
6d47a3da
MK
689 if (rightslenp)
690 (void) copyout((caddr_t)&len, rightslenp, sizeof (int));
691 }
692 if (mp->msg_control) {
693 len = mp->msg_controllen;
694 if (len <= 0 || control == 0)
695 len = 0;
696 else {
697 if (len >= control->m_len)
698 len = control->m_len;
699 else
700 mp->msg_flags |= MSG_CTRUNC;
701 (void) copyout((caddr_t)mtod(control, caddr_t),
702 (caddr_t)mp->msg_control, (unsigned)len);
703 }
704 if (controllenp)
705 (void) copyout((caddr_t)&len, controllenp, sizeof(int));
88a7a62a
SL
706 }
707 if (rights)
708 m_freem(rights);
709 if (from)
710 m_freem(from);
6d47a3da
MK
711 if (control)
712 m_freem(control);
cf012934
BJ
713}
714
715shutdown()
716{
6ef233bf
SL
717 struct a {
718 int s;
719 int how;
720 } *uap = (struct a *)u.u_ap;
721 struct file *fp;
cf012934 722
88a7a62a 723 fp = getsock(uap->s);
6ef233bf
SL
724 if (fp == 0)
725 return;
88a7a62a 726 u.u_error = soshutdown((struct socket *)fp->f_data, uap->how);
cf012934
BJ
727}
728
66f52238
SL
729setsockopt()
730{
731 struct a {
732 int s;
733 int level;
734 int name;
735 caddr_t val;
736 int valsize;
737 } *uap = (struct a *)u.u_ap;
738 struct file *fp;
d2cba8de 739 struct mbuf *m = NULL;
66f52238 740
88a7a62a 741 fp = getsock(uap->s);
66f52238
SL
742 if (fp == 0)
743 return;
66f52238
SL
744 if (uap->valsize > MLEN) {
745 u.u_error = EINVAL;
746 return;
747 }
d2cba8de
SL
748 if (uap->val) {
749 m = m_get(M_WAIT, MT_SOOPTS);
7c52d753 750 if (m == NULL) {
d2cba8de
SL
751 u.u_error = ENOBUFS;
752 return;
753 }
88a7a62a
SL
754 u.u_error =
755 copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
61ec2127
SL
756 if (u.u_error) {
757 (void) m_free(m);
758 return;
759 }
d2cba8de 760 m->m_len = uap->valsize;
66f52238 761 }
88a7a62a
SL
762 u.u_error =
763 sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m);
66f52238
SL
764}
765
766getsockopt()
767{
768 struct a {
769 int s;
770 int level;
771 int name;
772 caddr_t val;
773 int *avalsize;
774 } *uap = (struct a *)u.u_ap;
775 struct file *fp;
d2cba8de 776 struct mbuf *m = NULL;
66f52238
SL
777 int valsize;
778
88a7a62a 779 fp = getsock(uap->s);
66f52238
SL
780 if (fp == 0)
781 return;
d2cba8de
SL
782 if (uap->val) {
783 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
784 sizeof (valsize));
785 if (u.u_error)
786 return;
61ec2127
SL
787 } else
788 valsize = 0;
88a7a62a 789 u.u_error =
61ec2127 790 sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m);
66f52238
SL
791 if (u.u_error)
792 goto bad;
61ec2127 793 if (uap->val && valsize && m != NULL) {
d2cba8de
SL
794 if (valsize > m->m_len)
795 valsize = m->m_len;
796 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
797 if (u.u_error)
798 goto bad;
799 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
800 sizeof (valsize));
801 }
66f52238 802bad:
d2cba8de
SL
803 if (m != NULL)
804 (void) m_free(m);
66f52238
SL
805}
806
cf012934
BJ
807pipe()
808{
809 register struct file *rf, *wf;
810 struct socket *rso, *wso;
811 int r;
812
88a7a62a 813 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
2b4b57cd
BJ
814 if (u.u_error)
815 return;
88a7a62a 816 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
cf012934
BJ
817 if (u.u_error)
818 goto free;
819 rf = falloc();
820 if (rf == NULL)
821 goto free2;
822 r = u.u_r.r_val1;
823 rf->f_flag = FREAD;
824 rf->f_type = DTYPE_SOCKET;
88a7a62a
SL
825 rf->f_ops = &socketops;
826 rf->f_data = (caddr_t)rso;
cf012934
BJ
827 wf = falloc();
828 if (wf == NULL)
829 goto free3;
830 wf->f_flag = FWRITE;
831 wf->f_type = DTYPE_SOCKET;
88a7a62a
SL
832 wf->f_ops = &socketops;
833 wf->f_data = (caddr_t)wso;
cf012934
BJ
834 u.u_r.r_val2 = u.u_r.r_val1;
835 u.u_r.r_val1 = r;
d97afdcc 836 if (u.u_error = unp_connect2(wso, rso))
cf012934 837 goto free4;
9c58d471
MK
838 wso->so_state |= SS_CANTRCVMORE;
839 rso->so_state |= SS_CANTSENDMORE;
cf012934
BJ
840 return;
841free4:
842 wf->f_count = 0;
843 u.u_ofile[u.u_r.r_val2] = 0;
844free3:
845 rf->f_count = 0;
846 u.u_ofile[r] = 0;
847free2:
8011f5df 848 (void)soclose(wso);
cf012934 849free:
8011f5df 850 (void)soclose(rso);
cc15ab5d 851}
a3076b07
BJ
852
853/*
70f2eac5 854 * Get socket name.
a3076b07 855 */
70f2eac5 856getsockname()
a3076b07
BJ
857{
858 register struct a {
859 int fdes;
70f2eac5
SL
860 caddr_t asa;
861 int *alen;
a3076b07
BJ
862 } *uap = (struct a *)u.u_ap;
863 register struct file *fp;
05d69517 864 register struct socket *so;
cf012934 865 struct mbuf *m;
70f2eac5 866 int len;
a3076b07 867
88a7a62a 868 fp = getsock(uap->fdes);
a3076b07
BJ
869 if (fp == 0)
870 return;
70f2eac5
SL
871 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
872 if (u.u_error)
873 return;
88a7a62a 874 so = (struct socket *)fp->f_data;
cce93e4b 875 m = m_getclr(M_WAIT, MT_SONAME);
7c52d753
SL
876 if (m == NULL) {
877 u.u_error = ENOBUFS;
878 return;
879 }
70f2eac5
SL
880 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
881 if (u.u_error)
882 goto bad;
883 if (len > m->m_len)
884 len = m->m_len;
885 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
05d69517 886 if (u.u_error)
cf012934 887 goto bad;
70f2eac5 888 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
cf012934
BJ
889bad:
890 m_freem(m);
891}
892
6d47a3da
MK
893#ifdef COMPAT_43
894ogetsockname()
895{
896 return (getsockname());
897}
898#endif
899
a7343092
SL
900/*
901 * Get name of peer for connected socket.
902 */
903getpeername()
904{
905 register struct a {
906 int fdes;
907 caddr_t asa;
908 int *alen;
909 } *uap = (struct a *)u.u_ap;
910 register struct file *fp;
911 register struct socket *so;
912 struct mbuf *m;
913 int len;
914
915 fp = getsock(uap->fdes);
916 if (fp == 0)
917 return;
918 so = (struct socket *)fp->f_data;
919 if ((so->so_state & SS_ISCONNECTED) == 0) {
920 u.u_error = ENOTCONN;
921 return;
922 }
923 m = m_getclr(M_WAIT, MT_SONAME);
924 if (m == NULL) {
925 u.u_error = ENOBUFS;
926 return;
927 }
928 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
929 if (u.u_error)
930 return;
931 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
932 if (u.u_error)
933 goto bad;
934 if (len > m->m_len)
935 len = m->m_len;
936 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
937 if (u.u_error)
938 goto bad;
939 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
940bad:
941 m_freem(m);
942}
943
6d47a3da
MK
944#ifdef COMPAT_43
945ogetpeername()
946{
947 return (getpeername());
948}
949#endif
950
98447d3f 951sockargs(aname, name, namelen, type)
cf012934
BJ
952 struct mbuf **aname;
953 caddr_t name;
98447d3f 954 int namelen, type;
cf012934
BJ
955{
956 register struct mbuf *m;
127f7d76 957 int error;
cf012934 958
7e4a3868 959 if ((u_int)namelen > MLEN)
cf012934 960 return (EINVAL);
98447d3f 961 m = m_get(M_WAIT, type);
7c52d753
SL
962 if (m == NULL)
963 return (ENOBUFS);
cf012934 964 m->m_len = namelen;
127f7d76
SL
965 error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
966 if (error)
cf012934 967 (void) m_free(m);
127f7d76
SL
968 else
969 *aname = m;
970 return (error);
cf012934 971}
88a7a62a
SL
972
973struct file *
974getsock(fdes)
975 int fdes;
976{
977 register struct file *fp;
978
979 fp = getf(fdes);
980 if (fp == NULL)
981 return (0);
982 if (fp->f_type != DTYPE_SOCKET) {
983 u.u_error = ENOTSOCK;
984 return (0);
985 }
986 return (fp);
987}