clocal, nonblock, other carrier related stuff
[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 *
a2aebb63 17 * @(#)uipc_syscalls.c 7.8 (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
f4d2893a
MK
98#ifdef COMPAT_43
99accept()
100{
101 accept1(0);
102}
103
104oaccept()
105{
106 accept1(1);
107}
108
109accept1(compat_43)
110#else
cf012934 111accept()
f4d2893a 112#endif
cf012934
BJ
113{
114 register struct a {
115 int s;
116 caddr_t name;
117 int *anamelen;
cf012934
BJ
118 } *uap = (struct a *)u.u_ap;
119 register struct file *fp;
120 struct mbuf *nam;
cf012934
BJ
121 int namelen;
122 int s;
123 register struct socket *so;
124
125 if (uap->name == 0)
126 goto noname;
127f7d76
SL
127 u.u_error = copyin((caddr_t)uap->anamelen, (caddr_t)&namelen,
128 sizeof (namelen));
129 if (u.u_error)
cf012934 130 return;
b32450f4 131 if (useracc((caddr_t)uap->name, (u_int)namelen, B_WRITE) == 0) {
cf012934
BJ
132 u.u_error = EFAULT;
133 return;
134 }
135noname:
88a7a62a 136 fp = getsock(uap->s);
cf012934 137 if (fp == 0)
66f52238 138 return;
2b4b57cd 139 s = splnet();
88a7a62a 140 so = (struct socket *)fp->f_data;
4147b3f6
BJ
141 if ((so->so_options & SO_ACCEPTCONN) == 0) {
142 u.u_error = EINVAL;
143 splx(s);
66f52238 144 return;
4147b3f6
BJ
145 }
146 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
2b4b57cd
BJ
147 u.u_error = EWOULDBLOCK;
148 splx(s);
66f52238 149 return;
2b4b57cd 150 }
4147b3f6 151 while (so->so_qlen == 0 && so->so_error == 0) {
62229532
BJ
152 if (so->so_state & SS_CANTRCVMORE) {
153 so->so_error = ECONNABORTED;
154 break;
155 }
d08c5322 156 sleep((caddr_t)&so->so_timeo, PZERO+1);
62229532 157 }
f269ef23
BJ
158 if (so->so_error) {
159 u.u_error = so->so_error;
f4ed5810 160 so->so_error = 0;
f269ef23 161 splx(s);
66f52238 162 return;
f269ef23 163 }
88a7a62a 164 if (ufalloc(0) < 0) {
4147b3f6 165 splx(s);
66f52238 166 return;
4147b3f6
BJ
167 }
168 fp = falloc();
169 if (fp == 0) {
170 u.u_ofile[u.u_r.r_val1] = 0;
2b4b57cd 171 splx(s);
66f52238 172 return;
cf012934
BJ
173 }
174 { struct socket *aso = so->so_q;
175 if (soqremque(aso, 1) == 0)
176 panic("accept");
177 so = aso;
2b4b57cd 178 }
4147b3f6
BJ
179 fp->f_type = DTYPE_SOCKET;
180 fp->f_flag = FREAD|FWRITE;
88a7a62a
SL
181 fp->f_ops = &socketops;
182 fp->f_data = (caddr_t)so;
cce93e4b 183 nam = m_get(M_WAIT, MT_SONAME);
66f52238 184 (void) soaccept(so, nam);
cf012934 185 if (uap->name) {
f4d2893a
MK
186#ifdef COMPAT_43
187 if (compat_43)
188 mtod(nam, struct osockaddr *)->sa_family =
189 mtod(nam, struct sockaddr *)->sa_family;
190#endif
cf012934
BJ
191 if (namelen > nam->m_len)
192 namelen = nam->m_len;
193 /* SHOULD COPY OUT A CHAIN HERE */
b32450f4
BJ
194 (void) copyout(mtod(nam, caddr_t), (caddr_t)uap->name,
195 (u_int)namelen);
196 (void) copyout((caddr_t)&namelen, (caddr_t)uap->anamelen,
cf012934
BJ
197 sizeof (*uap->anamelen));
198 }
199 m_freem(nam);
2b4b57cd 200 splx(s);
ae921915
BJ
201}
202
cf012934 203connect()
c8c7dd0e
BJ
204{
205 register struct a {
cf012934
BJ
206 int s;
207 caddr_t name;
208 int namelen;
c8c7dd0e 209 } *uap = (struct a *)u.u_ap;
c8c7dd0e
BJ
210 register struct file *fp;
211 register struct socket *so;
cf012934 212 struct mbuf *nam;
c8c7dd0e
BJ
213 int s;
214
88a7a62a 215 fp = getsock(uap->s);
c8c7dd0e
BJ
216 if (fp == 0)
217 return;
88a7a62a 218 so = (struct socket *)fp->f_data;
a7a77c02
MK
219 if ((so->so_state & SS_NBIO) &&
220 (so->so_state & SS_ISCONNECTING)) {
6222acc3 221 u.u_error = EALREADY;
a7a77c02
MK
222 return;
223 }
98447d3f 224 u.u_error = sockargs(&nam, uap->name, uap->namelen, MT_SONAME);
c8c7dd0e
BJ
225 if (u.u_error)
226 return;
66f52238 227 u.u_error = soconnect(so, nam);
cf012934
BJ
228 if (u.u_error)
229 goto bad;
6222acc3
MK
230 if ((so->so_state & SS_NBIO) &&
231 (so->so_state & SS_ISCONNECTING)) {
232 u.u_error = EINPROGRESS;
233 m_freem(nam);
234 return;
235 }
c8c7dd0e 236 s = splnet();
88a7a62a
SL
237 if (setjmp(&u.u_qsave)) {
238 if (u.u_error == 0)
239 u.u_error = EINTR;
240 goto bad2;
c8c7dd0e 241 }
cc15ab5d 242 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
c8c7dd0e
BJ
243 sleep((caddr_t)&so->so_timeo, PZERO+1);
244 u.u_error = so->so_error;
cc15ab5d 245 so->so_error = 0;
88a7a62a 246bad2:
cc15ab5d 247 splx(s);
cf012934 248bad:
6750daae 249 so->so_state &= ~SS_ISCONNECTING;
cf012934 250 m_freem(nam);
c8c7dd0e
BJ
251}
252
cf012934
BJ
253socketpair()
254{
5a48956d
SL
255 register struct a {
256 int domain;
257 int type;
258 int protocol;
259 int *rsv;
260 } *uap = (struct a *)u.u_ap;
261 register struct file *fp1, *fp2;
262 struct socket *so1, *so2;
263 int sv[2];
cf012934 264
5a48956d
SL
265 if (useracc((caddr_t)uap->rsv, 2 * sizeof (int), B_WRITE) == 0) {
266 u.u_error = EFAULT;
267 return;
268 }
269 u.u_error = socreate(uap->domain, &so1, uap->type, uap->protocol);
270 if (u.u_error)
271 return;
272 u.u_error = socreate(uap->domain, &so2, uap->type, uap->protocol);
273 if (u.u_error)
f4d2893a 274 goto freeit;
5a48956d
SL
275 fp1 = falloc();
276 if (fp1 == NULL)
277 goto free2;
278 sv[0] = u.u_r.r_val1;
279 fp1->f_flag = FREAD|FWRITE;
280 fp1->f_type = DTYPE_SOCKET;
281 fp1->f_ops = &socketops;
282 fp1->f_data = (caddr_t)so1;
283 fp2 = falloc();
284 if (fp2 == NULL)
285 goto free3;
286 fp2->f_flag = FREAD|FWRITE;
287 fp2->f_type = DTYPE_SOCKET;
288 fp2->f_ops = &socketops;
289 fp2->f_data = (caddr_t)so2;
290 sv[1] = u.u_r.r_val1;
291 u.u_error = soconnect2(so1, so2);
292 if (u.u_error)
293 goto free4;
33446404
MK
294 if (uap->type == SOCK_DGRAM) {
295 /*
296 * Datagram socket connection is asymmetric.
297 */
298 u.u_error = soconnect2(so2, so1);
299 if (u.u_error)
300 goto free4;
301 }
302 u.u_r.r_val1 = 0;
5a48956d
SL
303 (void) copyout((caddr_t)sv, (caddr_t)uap->rsv, 2 * sizeof (int));
304 return;
305free4:
306 fp2->f_count = 0;
307 u.u_ofile[sv[1]] = 0;
308free3:
309 fp1->f_count = 0;
310 u.u_ofile[sv[0]] = 0;
311free2:
8011f5df 312 (void)soclose(so2);
f4d2893a 313freeit:
8011f5df 314 (void)soclose(so1);
cf012934
BJ
315}
316
317sendto()
c8c7dd0e
BJ
318{
319 register struct a {
cf012934
BJ
320 int s;
321 caddr_t buf;
322 int len;
323 int flags;
324 caddr_t to;
325 int tolen;
c8c7dd0e 326 } *uap = (struct a *)u.u_ap;
88a7a62a 327 struct msghdr msg;
d3d550b5 328 struct iovec aiov;
c8c7dd0e 329
88a7a62a
SL
330 msg.msg_name = uap->to;
331 msg.msg_namelen = uap->tolen;
332 msg.msg_iov = &aiov;
333 msg.msg_iovlen = 1;
cf012934
BJ
334 aiov.iov_base = uap->buf;
335 aiov.iov_len = uap->len;
88a7a62a 336 msg.msg_accrights = 0;
6d47a3da 337 msg.msg_control = 0;
88a7a62a 338 sendit(uap->s, &msg, uap->flags);
c8c7dd0e
BJ
339}
340
6d47a3da 341#ifdef COMPAT_43
f4d2893a 342
6d47a3da 343osend()
cc15ab5d
BJ
344{
345 register struct a {
cf012934
BJ
346 int s;
347 caddr_t buf;
348 int len;
349 int flags;
cc15ab5d 350 } *uap = (struct a *)u.u_ap;
88a7a62a 351 struct msghdr msg;
a6b6f679 352 struct iovec aiov;
cc15ab5d 353
88a7a62a
SL
354 msg.msg_name = 0;
355 msg.msg_namelen = 0;
356 msg.msg_iov = &aiov;
357 msg.msg_iovlen = 1;
cf012934
BJ
358 aiov.iov_base = uap->buf;
359 aiov.iov_len = uap->len;
88a7a62a 360 msg.msg_accrights = 0;
6d47a3da 361 msg.msg_control = 0;
88a7a62a
SL
362 sendit(uap->s, &msg, uap->flags);
363}
364
6d47a3da
MK
365osendmsg()
366{
367 register struct a {
368 int s;
369 caddr_t msg;
370 int flags;
371 } *uap = (struct a *)u.u_ap;
372 struct msghdr msg;
373 struct iovec aiov[MSG_MAXIOVLEN];
374
375 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (struct omsghdr));
376 if (u.u_error)
377 return;
378 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
379 u.u_error = EMSGSIZE;
380 return;
381 }
382 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
383 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
384 if (u.u_error)
385 return;
386 msg.msg_control = 0;
387 msg.msg_controllen = 0;
388 sendit(uap->s, &msg, uap->flags);
389}
390#endif
391
88a7a62a
SL
392sendmsg()
393{
394 register struct a {
395 int s;
396 caddr_t msg;
397 int flags;
398 } *uap = (struct a *)u.u_ap;
399 struct msghdr msg;
400 struct iovec aiov[MSG_MAXIOVLEN];
401
402 u.u_error = copyin(uap->msg, (caddr_t)&msg, sizeof (msg));
403 if (u.u_error)
404 return;
405 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
406 u.u_error = EMSGSIZE;
cf012934
BJ
407 return;
408 }
6d47a3da 409 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
88a7a62a 410 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
cf012934
BJ
411 if (u.u_error)
412 return;
88a7a62a 413 msg.msg_iov = aiov;
88a7a62a
SL
414 sendit(uap->s, &msg, uap->flags);
415}
416
417sendit(s, mp, flags)
418 int s;
419 register struct msghdr *mp;
420 int flags;
421{
422 register struct file *fp;
423 struct uio auio;
424 register struct iovec *iov;
425 register int i;
6d47a3da 426 struct mbuf *to, *rights, *control;
88a7a62a
SL
427 int len;
428
429 fp = getsock(s);
430 if (fp == 0)
431 return;
432 auio.uio_iov = mp->msg_iov;
433 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 434 auio.uio_segflg = UIO_USERSPACE;
88a7a62a
SL
435 auio.uio_offset = 0; /* XXX */
436 auio.uio_resid = 0;
437 iov = mp->msg_iov;
125c8f95 438 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
88a7a62a
SL
439 if (iov->iov_len < 0) {
440 u.u_error = EINVAL;
441 return;
442 }
0f6422b0
MK
443 if (iov->iov_len == 0)
444 continue;
88a7a62a
SL
445 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_READ) == 0) {
446 u.u_error = EFAULT;
447 return;
448 }
449 auio.uio_resid += iov->iov_len;
88a7a62a
SL
450 }
451 if (mp->msg_name) {
452 u.u_error =
98447d3f 453 sockargs(&to, mp->msg_name, mp->msg_namelen, MT_SONAME);
88a7a62a
SL
454 if (u.u_error)
455 return;
456 } else
457 to = 0;
458 if (mp->msg_accrights) {
459 u.u_error =
98447d3f
MK
460 sockargs(&rights, mp->msg_accrights, mp->msg_accrightslen,
461 MT_RIGHTS);
88a7a62a
SL
462 if (u.u_error)
463 goto bad;
464 } else
465 rights = 0;
6d47a3da
MK
466 if (mp->msg_control) {
467 u.u_error =
468 sockargs(&control, mp->msg_control, mp->msg_controllen,
469 MT_CONTROL);
470 if (u.u_error)
471 goto bad;
472 } else
473 control = 0;
88a7a62a 474 len = auio.uio_resid;
6d47a3da
MK
475 if (setjmp(&u.u_qsave)) { /* XXX */
476 if (auio.uio_resid == len) {
477 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
478 u.u_error = EINTR;
479 else
480 u.u_eosys = RESTARTSYS;
481 }
482 } else
483 u.u_error = sosend((struct socket *)fp->f_data, to, &auio,
484 flags, rights, control);
88a7a62a 485 u.u_r.r_val1 = len - auio.uio_resid;
6d47a3da 486bad:
88a7a62a
SL
487 if (rights)
488 m_freem(rights);
88a7a62a
SL
489 if (to)
490 m_freem(to);
6d47a3da
MK
491 if (control)
492 m_freem(control);
cf012934
BJ
493}
494
f4d2893a
MK
495#ifdef COMPAT_43
496recvfrom()
497{
498 recvfrom1(0);
499}
500
501orecvfrom()
502{
503 recvfrom1(1);
504}
505
506recvfrom1(compat_43)
507{ /* vi will want an extra } to be happy! */
508#else
cf012934
BJ
509recvfrom()
510{
f4d2893a
MK
511 int compat_43 = 0;
512#endif
cf012934
BJ
513 register struct a {
514 int s;
515 caddr_t buf;
516 int len;
517 int flags;
518 caddr_t from;
519 int *fromlenaddr;
520 } *uap = (struct a *)u.u_ap;
88a7a62a 521 struct msghdr msg;
cf012934 522 struct iovec aiov;
88a7a62a 523 int len;
cf012934 524
6d47a3da
MK
525 if (uap->fromlenaddr) {
526 u.u_error = copyin((caddr_t)uap->fromlenaddr, (caddr_t)&len,
527 sizeof (len));
528 if (u.u_error)
529 return;
530 } else
531 len = 0;
88a7a62a
SL
532 msg.msg_name = uap->from;
533 msg.msg_namelen = len;
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;
a2aebb63 541 recvit(uap->s, &msg, (caddr_t)uap->fromlenaddr, (caddr_t)0, compat_43);
cf012934 542}
6d47a3da 543#ifdef COMPAT_43
6d47a3da 544orecv()
cf012934
BJ
545{
546 register struct a {
547 int s;
548 caddr_t buf;
549 int len;
550 int flags;
551 } *uap = (struct a *)u.u_ap;
88a7a62a 552 struct msghdr msg;
cf012934
BJ
553 struct iovec aiov;
554
88a7a62a
SL
555 msg.msg_name = 0;
556 msg.msg_namelen = 0;
557 msg.msg_iov = &aiov;
558 msg.msg_iovlen = 1;
cf012934
BJ
559 aiov.iov_base = uap->buf;
560 aiov.iov_len = uap->len;
88a7a62a 561 msg.msg_accrights = 0;
6d47a3da
MK
562 msg.msg_control = 0;
563 msg.msg_flags = uap->flags;
a2aebb63 564 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
6d47a3da
MK
565}
566
567orecvmsg()
568{
569 register struct a {
570 int s;
571 struct omsghdr *msg;
572 int flags;
573 } *uap = (struct a *)u.u_ap;
574 struct msghdr msg;
575 struct iovec aiov[MSG_MAXIOVLEN];
576
577 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg,
578 sizeof (struct omsghdr));
579 if (u.u_error)
580 return;
581 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
582 u.u_error = EMSGSIZE;
583 return;
584 }
585 msg.msg_control = 0;
586 msg.msg_flags = uap->flags;
587 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
588 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
589 if (u.u_error)
590 return;
591 msg.msg_iov = aiov;
592 if (msg.msg_accrights)
593 if (useracc((caddr_t)msg.msg_accrights,
594 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
595 u.u_error = EFAULT;
596 return;
597 }
598
599 recvit(uap->s, &msg, (caddr_t)&uap->msg->msg_namelen,
a2aebb63 600 (caddr_t)&uap->msg->msg_accrightslen, /* compat_43 */1);
cf012934 601}
6d47a3da 602#endif
cf012934 603
88a7a62a 604recvmsg()
cf012934 605{
88a7a62a
SL
606 register struct a {
607 int s;
608 struct msghdr *msg;
609 int flags;
610 } *uap = (struct a *)u.u_ap;
611 struct msghdr msg;
f4d2893a 612 struct iovec aiov[MSG_MAXIOVLEN], *uiov;
cf012934 613
88a7a62a
SL
614 u.u_error = copyin((caddr_t)uap->msg, (caddr_t)&msg, sizeof (msg));
615 if (u.u_error)
616 return;
617 if ((u_int)msg.msg_iovlen >= sizeof (aiov) / sizeof (aiov[0])) {
618 u.u_error = EMSGSIZE;
619 return;
620 }
6d47a3da
MK
621 msg.msg_flags = uap->flags;
622 u.u_error = copyin((caddr_t)msg.msg_iov, (caddr_t)aiov,
88a7a62a
SL
623 (unsigned)(msg.msg_iovlen * sizeof (aiov[0])));
624 if (u.u_error)
625 return;
f4d2893a 626 uiov = msg.msg_iov;
88a7a62a
SL
627 msg.msg_iov = aiov;
628 if (msg.msg_accrights)
629 if (useracc((caddr_t)msg.msg_accrights,
630 (unsigned)msg.msg_accrightslen, B_WRITE) == 0) {
631 u.u_error = EFAULT;
632 return;
633 }
6d47a3da
MK
634 if (msg.msg_control)
635 if (useracc((caddr_t)msg.msg_control,
636 (unsigned)msg.msg_controllen, B_WRITE) == 0) {
637 u.u_error = EFAULT;
638 return;
639 }
a2aebb63 640 recvit(uap->s, &msg, (caddr_t)0, (caddr_t)0, 0);
f4d2893a
MK
641 msg.msg_iov = uiov;
642 u.u_error = copyout((caddr_t)&msg, (caddr_t)uap->msg, sizeof(msg));
cf012934
BJ
643}
644
a2aebb63 645recvit(s, mp, namelenp, rightslenp, compat_43)
f4d2893a 646 int s, compat_43;
88a7a62a 647 register struct msghdr *mp;
a2aebb63 648 caddr_t namelenp, rightslenp;
cf012934 649{
88a7a62a
SL
650 register struct file *fp;
651 struct uio auio;
652 register struct iovec *iov;
653 register int i;
88a7a62a 654 int len;
6d47a3da 655 struct mbuf *from = 0, *rights = 0, *control = 0;
88a7a62a
SL
656
657 fp = getsock(s);
658 if (fp == 0)
659 return;
660 auio.uio_iov = mp->msg_iov;
661 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 662 auio.uio_segflg = UIO_USERSPACE;
88a7a62a
SL
663 auio.uio_offset = 0; /* XXX */
664 auio.uio_resid = 0;
665 iov = mp->msg_iov;
125c8f95 666 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
88a7a62a
SL
667 if (iov->iov_len < 0) {
668 u.u_error = EINVAL;
669 return;
670 }
0f6422b0
MK
671 if (iov->iov_len == 0)
672 continue;
88a7a62a
SL
673 if (useracc(iov->iov_base, (u_int)iov->iov_len, B_WRITE) == 0) {
674 u.u_error = EFAULT;
675 return;
676 }
677 auio.uio_resid += iov->iov_len;
88a7a62a
SL
678 }
679 len = auio.uio_resid;
6d47a3da
MK
680 if (setjmp(&u.u_qsave)) { /* XXX */
681 if (auio.uio_resid == len) {
682 if ((u.u_sigintr & sigmask(u.u_procp->p_cursig)) != 0)
683 u.u_error = EINTR;
684 else
685 u.u_eosys = RESTARTSYS;
686 }
687 } else
688 u.u_error = soreceive((struct socket *)fp->f_data, &from, &auio,
689 &mp->msg_flags, &rights, &control);
88a7a62a
SL
690 u.u_r.r_val1 = len - auio.uio_resid;
691 if (mp->msg_name) {
692 len = mp->msg_namelen;
693 if (len <= 0 || from == 0)
694 len = 0;
695 else {
f4d2893a
MK
696#ifdef COMPAT_43
697 if (compat_43)
698 mtod(from, struct osockaddr *)->sa_family =
699 mtod(from, struct sockaddr *)->sa_family;
700#endif
701 if (len > from->m_len) /* ??? */
88a7a62a 702 len = from->m_len;
6d47a3da 703 (void) copyout(mtod(from, caddr_t),
88a7a62a
SL
704 (caddr_t)mp->msg_name, (unsigned)len);
705 }
a2aebb63 706 mp->msg_namelen = len;
6d47a3da
MK
707 if (namelenp)
708 (void) copyout((caddr_t)&len, namelenp, sizeof (int));
88a7a62a
SL
709 }
710 if (mp->msg_accrights) {
711 len = mp->msg_accrightslen;
712 if (len <= 0 || rights == 0)
713 len = 0;
714 else {
715 if (len > rights->m_len)
716 len = rights->m_len;
717 (void) copyout((caddr_t)mtod(rights, caddr_t),
718 (caddr_t)mp->msg_accrights, (unsigned)len);
719 }
a2aebb63 720 mp->msg_accrightslen = len;
6d47a3da
MK
721 if (rightslenp)
722 (void) copyout((caddr_t)&len, rightslenp, sizeof (int));
723 }
724 if (mp->msg_control) {
725 len = mp->msg_controllen;
726 if (len <= 0 || control == 0)
727 len = 0;
728 else {
729 if (len >= control->m_len)
730 len = control->m_len;
731 else
732 mp->msg_flags |= MSG_CTRUNC;
733 (void) copyout((caddr_t)mtod(control, caddr_t),
734 (caddr_t)mp->msg_control, (unsigned)len);
735 }
a2aebb63 736 mp->msg_controllen = len;
88a7a62a
SL
737 }
738 if (rights)
739 m_freem(rights);
740 if (from)
741 m_freem(from);
6d47a3da
MK
742 if (control)
743 m_freem(control);
cf012934
BJ
744}
745
746shutdown()
747{
6ef233bf
SL
748 struct a {
749 int s;
750 int how;
751 } *uap = (struct a *)u.u_ap;
752 struct file *fp;
cf012934 753
88a7a62a 754 fp = getsock(uap->s);
6ef233bf
SL
755 if (fp == 0)
756 return;
88a7a62a 757 u.u_error = soshutdown((struct socket *)fp->f_data, uap->how);
cf012934
BJ
758}
759
66f52238
SL
760setsockopt()
761{
762 struct a {
763 int s;
764 int level;
765 int name;
766 caddr_t val;
767 int valsize;
768 } *uap = (struct a *)u.u_ap;
769 struct file *fp;
d2cba8de 770 struct mbuf *m = NULL;
66f52238 771
88a7a62a 772 fp = getsock(uap->s);
66f52238
SL
773 if (fp == 0)
774 return;
66f52238
SL
775 if (uap->valsize > MLEN) {
776 u.u_error = EINVAL;
777 return;
778 }
d2cba8de
SL
779 if (uap->val) {
780 m = m_get(M_WAIT, MT_SOOPTS);
7c52d753 781 if (m == NULL) {
d2cba8de
SL
782 u.u_error = ENOBUFS;
783 return;
784 }
88a7a62a
SL
785 u.u_error =
786 copyin(uap->val, mtod(m, caddr_t), (u_int)uap->valsize);
61ec2127
SL
787 if (u.u_error) {
788 (void) m_free(m);
789 return;
790 }
d2cba8de 791 m->m_len = uap->valsize;
66f52238 792 }
88a7a62a
SL
793 u.u_error =
794 sosetopt((struct socket *)fp->f_data, uap->level, uap->name, m);
66f52238
SL
795}
796
797getsockopt()
798{
799 struct a {
800 int s;
801 int level;
802 int name;
803 caddr_t val;
804 int *avalsize;
805 } *uap = (struct a *)u.u_ap;
806 struct file *fp;
d2cba8de 807 struct mbuf *m = NULL;
66f52238
SL
808 int valsize;
809
88a7a62a 810 fp = getsock(uap->s);
66f52238
SL
811 if (fp == 0)
812 return;
d2cba8de
SL
813 if (uap->val) {
814 u.u_error = copyin((caddr_t)uap->avalsize, (caddr_t)&valsize,
815 sizeof (valsize));
816 if (u.u_error)
817 return;
61ec2127
SL
818 } else
819 valsize = 0;
88a7a62a 820 u.u_error =
61ec2127 821 sogetopt((struct socket *)fp->f_data, uap->level, uap->name, &m);
66f52238
SL
822 if (u.u_error)
823 goto bad;
61ec2127 824 if (uap->val && valsize && m != NULL) {
d2cba8de
SL
825 if (valsize > m->m_len)
826 valsize = m->m_len;
827 u.u_error = copyout(mtod(m, caddr_t), uap->val, (u_int)valsize);
828 if (u.u_error)
829 goto bad;
830 u.u_error = copyout((caddr_t)&valsize, (caddr_t)uap->avalsize,
831 sizeof (valsize));
832 }
66f52238 833bad:
d2cba8de
SL
834 if (m != NULL)
835 (void) m_free(m);
66f52238
SL
836}
837
cf012934
BJ
838pipe()
839{
840 register struct file *rf, *wf;
841 struct socket *rso, *wso;
842 int r;
843
88a7a62a 844 u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
2b4b57cd
BJ
845 if (u.u_error)
846 return;
88a7a62a 847 u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
cf012934 848 if (u.u_error)
f4d2893a 849 goto freeit;
cf012934
BJ
850 rf = falloc();
851 if (rf == NULL)
852 goto free2;
853 r = u.u_r.r_val1;
854 rf->f_flag = FREAD;
855 rf->f_type = DTYPE_SOCKET;
88a7a62a
SL
856 rf->f_ops = &socketops;
857 rf->f_data = (caddr_t)rso;
cf012934
BJ
858 wf = falloc();
859 if (wf == NULL)
860 goto free3;
861 wf->f_flag = FWRITE;
862 wf->f_type = DTYPE_SOCKET;
88a7a62a
SL
863 wf->f_ops = &socketops;
864 wf->f_data = (caddr_t)wso;
cf012934
BJ
865 u.u_r.r_val2 = u.u_r.r_val1;
866 u.u_r.r_val1 = r;
d97afdcc 867 if (u.u_error = unp_connect2(wso, rso))
cf012934 868 goto free4;
9c58d471
MK
869 wso->so_state |= SS_CANTRCVMORE;
870 rso->so_state |= SS_CANTSENDMORE;
cf012934
BJ
871 return;
872free4:
873 wf->f_count = 0;
874 u.u_ofile[u.u_r.r_val2] = 0;
875free3:
876 rf->f_count = 0;
877 u.u_ofile[r] = 0;
878free2:
8011f5df 879 (void)soclose(wso);
f4d2893a 880freeit:
8011f5df 881 (void)soclose(rso);
cc15ab5d 882}
a3076b07
BJ
883
884/*
70f2eac5 885 * Get socket name.
a3076b07 886 */
f4d2893a
MK
887#ifdef COMPAT_43
888getsockname()
889{
890 getsockname1(0);
891}
892
893ogetsockname()
894{
895 getsockname1(1);
896}
897
898getsockname1(compat_43)
899#else
70f2eac5 900getsockname()
f4d2893a 901#endif
a3076b07
BJ
902{
903 register struct a {
904 int fdes;
70f2eac5
SL
905 caddr_t asa;
906 int *alen;
a3076b07
BJ
907 } *uap = (struct a *)u.u_ap;
908 register struct file *fp;
05d69517 909 register struct socket *so;
cf012934 910 struct mbuf *m;
70f2eac5 911 int len;
a3076b07 912
88a7a62a 913 fp = getsock(uap->fdes);
a3076b07
BJ
914 if (fp == 0)
915 return;
70f2eac5
SL
916 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
917 if (u.u_error)
918 return;
88a7a62a 919 so = (struct socket *)fp->f_data;
cce93e4b 920 m = m_getclr(M_WAIT, MT_SONAME);
7c52d753
SL
921 if (m == NULL) {
922 u.u_error = ENOBUFS;
923 return;
924 }
70f2eac5
SL
925 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0);
926 if (u.u_error)
927 goto bad;
928 if (len > m->m_len)
929 len = m->m_len;
f4d2893a
MK
930#ifdef COMPAT_43
931 if (compat_43)
932 mtod(m, struct osockaddr *)->sa_family =
933 mtod(m, struct sockaddr *)->sa_family;
934#endif
70f2eac5 935 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
f4d2893a
MK
936 if (u.u_error == 0)
937 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen,
938 sizeof (len));
cf012934
BJ
939bad:
940 m_freem(m);
941}
942
f4d2893a
MK
943/*
944 * Get name of peer for connected socket.
945 */
6d47a3da 946#ifdef COMPAT_43
f4d2893a 947getpeername()
6d47a3da 948{
f4d2893a 949 getpeername1(0);
6d47a3da 950}
6d47a3da 951
f4d2893a
MK
952ogetpeername()
953{
954 getpeername1(1);
955}
956
957getpeername1(compat_43)
958#else
a7343092 959getpeername()
f4d2893a 960#endif
a7343092
SL
961{
962 register struct a {
963 int fdes;
964 caddr_t asa;
965 int *alen;
966 } *uap = (struct a *)u.u_ap;
967 register struct file *fp;
968 register struct socket *so;
969 struct mbuf *m;
970 int len;
971
972 fp = getsock(uap->fdes);
973 if (fp == 0)
974 return;
975 so = (struct socket *)fp->f_data;
976 if ((so->so_state & SS_ISCONNECTED) == 0) {
977 u.u_error = ENOTCONN;
978 return;
979 }
980 m = m_getclr(M_WAIT, MT_SONAME);
981 if (m == NULL) {
982 u.u_error = ENOBUFS;
983 return;
984 }
985 u.u_error = copyin((caddr_t)uap->alen, (caddr_t)&len, sizeof (len));
986 if (u.u_error)
987 return;
988 u.u_error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0);
989 if (u.u_error)
990 goto bad;
991 if (len > m->m_len)
992 len = m->m_len;
f4d2893a
MK
993#ifdef COMPAT_43
994 if (compat_43)
995 mtod(m, struct osockaddr *)->sa_family =
996 mtod(m, struct sockaddr *)->sa_family;
997#endif
a7343092
SL
998 u.u_error = copyout(mtod(m, caddr_t), (caddr_t)uap->asa, (u_int)len);
999 if (u.u_error)
1000 goto bad;
1001 u.u_error = copyout((caddr_t)&len, (caddr_t)uap->alen, sizeof (len));
1002bad:
1003 m_freem(m);
1004}
1005
98447d3f 1006sockargs(aname, name, namelen, type)
cf012934
BJ
1007 struct mbuf **aname;
1008 caddr_t name;
98447d3f 1009 int namelen, type;
cf012934
BJ
1010{
1011 register struct mbuf *m;
127f7d76 1012 int error;
cf012934 1013
7e4a3868 1014 if ((u_int)namelen > MLEN)
cf012934 1015 return (EINVAL);
98447d3f 1016 m = m_get(M_WAIT, type);
7c52d753
SL
1017 if (m == NULL)
1018 return (ENOBUFS);
cf012934 1019 m->m_len = namelen;
127f7d76
SL
1020 error = copyin(name, mtod(m, caddr_t), (u_int)namelen);
1021 if (error)
cf012934 1022 (void) m_free(m);
127f7d76
SL
1023 else
1024 *aname = m;
a2aebb63
KS
1025 if (type == MT_SONAME) {
1026 register struct sockaddr *sa = mtod(m, struct sockaddr *);
f4d2893a 1027#if defined(COMPAT_43) && BYTE_ORDER != BIG_ENDIAN
a2aebb63
KS
1028 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1029 sa->sa_family = sa->sa_len;
f4d2893a 1030#endif
a2aebb63
KS
1031 sa->sa_len = namelen;
1032 }
127f7d76 1033 return (error);
cf012934 1034}
88a7a62a
SL
1035
1036struct file *
1037getsock(fdes)
1038 int fdes;
1039{
1040 register struct file *fp;
1041
1042 fp = getf(fdes);
1043 if (fp == NULL)
1044 return (0);
1045 if (fp->f_type != DTYPE_SOCKET) {
1046 u.u_error = ENOTSOCK;
1047 return (0);
1048 }
1049 return (fp);
1050}