convert VOP_UNLOCK and vrele into vput's; add proc parameter to union_dircache
[unix-history] / usr / src / sys / kern / uipc_syscalls.c
CommitLineData
da7c5cc6 1/*
da7c5cc6 2 *
dbf0c423 3 * %sccs.include.redist.c%
96e6449f 4 *
01eea121 5 * @(#)uipc_syscalls.c 8.6 (Berkeley) %G%
da7c5cc6 6 */
c8c7dd0e 7
38a01dbe 8#include <sys/param.h>
01eea121 9#include <sys/systm.h>
38a01dbe
KB
10#include <sys/filedesc.h>
11#include <sys/proc.h>
12#include <sys/file.h>
13#include <sys/buf.h>
14#include <sys/malloc.h>
15#include <sys/mbuf.h>
16#include <sys/protosw.h>
17#include <sys/socket.h>
18#include <sys/socketvar.h>
813b7cd1 19#ifdef KTRACE
38a01dbe 20#include <sys/ktrace.h>
813b7cd1 21#endif
4147b3f6 22
01eea121
CD
23#include <sys/mount.h>
24#include <sys/syscallargs.h>
25
c8c7dd0e 26/*
cf012934 27 * System call interface to the socket abstraction.
c8c7dd0e 28 */
8ffc8876
CT
29#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
30#define COMPAT_OLDSOCK
31#endif
c8c7dd0e 32
88a7a62a
SL
33extern struct fileops socketops;
34
01eea121 35int
85843d69
KM
36socket(p, uap, retval)
37 struct proc *p;
01eea121
CD
38 register struct socket_args /* {
39 syscallarg(int) domain;
40 syscallarg(int) type;
41 syscallarg(int) protocol;
42 } */ *uap;
43 register_t *retval;
85843d69 44{
5e00df3b 45 struct filedesc *fdp = p->p_fd;
2b4b57cd 46 struct socket *so;
0c9a45f0 47 struct file *fp;
76ffad7c 48 int fd, error;
c8c7dd0e 49
5e00df3b 50 if (error = falloc(p, &fp, &fd))
d9c2f47f 51 return (error);
4147b3f6
BJ
52 fp->f_flag = FREAD|FWRITE;
53 fp->f_type = DTYPE_SOCKET;
88a7a62a 54 fp->f_ops = &socketops;
01eea121
CD
55 if (error = socreate(SCARG(uap, domain), &so, SCARG(uap, type),
56 SCARG(uap, protocol))) {
994fd74e 57 fdp->fd_ofiles[fd] = 0;
336f999d 58 ffree(fp);
76ffad7c
MK
59 } else {
60 fp->f_data = (caddr_t)so;
85843d69 61 *retval = fd;
76ffad7c 62 }
d9c2f47f 63 return (error);
c8c7dd0e 64}
ae921915 65
85843d69 66/* ARGSUSED */
01eea121 67int
85843d69
KM
68bind(p, uap, retval)
69 struct proc *p;
01eea121
CD
70 register struct bind_args /* {
71 syscallarg(int) s;
72 syscallarg(caddr_t) name;
73 syscallarg(int) namelen;
74 } */ *uap;
75 register_t *retval;
85843d69 76{
5e00df3b 77 struct file *fp;
cf012934 78 struct mbuf *nam;
76ffad7c 79 int error;
ae921915 80
01eea121 81 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 82 return (error);
01eea121
CD
83 if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
84 MT_SONAME))
d9c2f47f 85 return (error);
76ffad7c 86 error = sobind((struct socket *)fp->f_data, nam);
cf012934 87 m_freem(nam);
d9c2f47f 88 return (error);
cf012934
BJ
89}
90
85843d69 91/* ARGSUSED */
01eea121 92int
85843d69
KM
93listen(p, uap, retval)
94 struct proc *p;
01eea121
CD
95 register struct listen_args /* {
96 syscallarg(int) s;
97 syscallarg(int) backlog;
98 } */ *uap;
99 register_t *retval;
85843d69 100{
5e00df3b 101 struct file *fp;
76ffad7c 102 int error;
cf012934 103
01eea121 104 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 105 return (error);
01eea121 106 return (solisten((struct socket *)fp->f_data, SCARG(uap, backlog)));
cf012934
BJ
107}
108
8ffc8876 109#ifdef COMPAT_OLDSOCK
01eea121 110int
85843d69
KM
111accept(p, uap, retval)
112 struct proc *p;
01eea121
CD
113 struct accept_args /* {
114 syscallarg(int) s;
115 syscallarg(caddr_t) name;
116 syscallarg(int *) anamelen;
117 } */ *uap;
118 register_t *retval;
85843d69 119{
76ffad7c 120
01eea121 121 return (accept1(p, uap, retval, 0));
f4d2893a
MK
122}
123
01eea121
CD
124int
125compat_43_accept(p, uap, retval)
85843d69 126 struct proc *p;
01eea121
CD
127 struct accept_args /* {
128 syscallarg(int) s;
129 syscallarg(caddr_t) name;
130 syscallarg(int *) anamelen;
131 } */ *uap;
132 register_t *retval;
85843d69 133{
76ffad7c 134
01eea121 135 return (accept1(p, uap, retval, 1));
f4d2893a 136}
8ffc8876 137#else /* COMPAT_OLDSOCK */
f4d2893a 138
76ffad7c 139#define accept1 accept
f4d2893a 140#endif
76ffad7c 141
01eea121
CD
142int
143accept1(p, uap, retval, compat_43)
85843d69 144 struct proc *p;
01eea121
CD
145 register struct accept_args /* {
146 syscallarg(int) s;
147 syscallarg(caddr_t) name;
148 syscallarg(int *) anamelen;
149 } */ *uap;
150 register_t *retval;
151 int compat_43;
85843d69 152{
0c9a45f0 153 struct file *fp;
cf012934 154 struct mbuf *nam;
01eea121 155 int namelen, error, s, tmpfd;
cf012934
BJ
156 register struct socket *so;
157
01eea121 158 if (SCARG(uap, name) && (error = copyin((caddr_t)SCARG(uap, anamelen),
7a22a33c 159 (caddr_t)&namelen, sizeof (namelen))))
d9c2f47f 160 return (error);
01eea121 161 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 162 return (error);
2b4b57cd 163 s = splnet();
88a7a62a 164 so = (struct socket *)fp->f_data;
4147b3f6 165 if ((so->so_options & SO_ACCEPTCONN) == 0) {
4147b3f6 166 splx(s);
d9c2f47f 167 return (EINVAL);
4147b3f6
BJ
168 }
169 if ((so->so_state & SS_NBIO) && so->so_qlen == 0) {
2b4b57cd 170 splx(s);
d9c2f47f 171 return (EWOULDBLOCK);
2b4b57cd 172 }
4147b3f6 173 while (so->so_qlen == 0 && so->so_error == 0) {
62229532
BJ
174 if (so->so_state & SS_CANTRCVMORE) {
175 so->so_error = ECONNABORTED;
176 break;
177 }
27f43765
MK
178 if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
179 netcon, 0)) {
180 splx(s);
d9c2f47f 181 return (error);
27f43765 182 }
62229532 183 }
f269ef23 184 if (so->so_error) {
27f43765 185 error = so->so_error;
f4ed5810 186 so->so_error = 0;
f269ef23 187 splx(s);
d9c2f47f 188 return (error);
f269ef23 189 }
01eea121 190 if (error = falloc(p, &fp, &tmpfd)) {
2b4b57cd 191 splx(s);
d9c2f47f 192 return (error);
cf012934 193 }
01eea121 194 *retval = tmpfd;
cf012934
BJ
195 { struct socket *aso = so->so_q;
196 if (soqremque(aso, 1) == 0)
197 panic("accept");
198 so = aso;
2b4b57cd 199 }
4147b3f6
BJ
200 fp->f_type = DTYPE_SOCKET;
201 fp->f_flag = FREAD|FWRITE;
88a7a62a
SL
202 fp->f_ops = &socketops;
203 fp->f_data = (caddr_t)so;
cce93e4b 204 nam = m_get(M_WAIT, MT_SONAME);
66f52238 205 (void) soaccept(so, nam);
01eea121 206 if (SCARG(uap, name)) {
8ffc8876 207#ifdef COMPAT_OLDSOCK
01eea121 208 if (compat_43)
f4d2893a
MK
209 mtod(nam, struct osockaddr *)->sa_family =
210 mtod(nam, struct sockaddr *)->sa_family;
211#endif
cf012934
BJ
212 if (namelen > nam->m_len)
213 namelen = nam->m_len;
214 /* SHOULD COPY OUT A CHAIN HERE */
01eea121
CD
215 if ((error = copyout(mtod(nam, caddr_t),
216 (caddr_t)SCARG(uap, name), (u_int)namelen)) == 0)
7a22a33c 217 error = copyout((caddr_t)&namelen,
01eea121
CD
218 (caddr_t)SCARG(uap, anamelen),
219 sizeof (*SCARG(uap, anamelen)));
cf012934
BJ
220 }
221 m_freem(nam);
2b4b57cd 222 splx(s);
d9c2f47f 223 return (error);
ae921915
BJ
224}
225
85843d69 226/* ARGSUSED */
01eea121 227int
85843d69
KM
228connect(p, uap, retval)
229 struct proc *p;
01eea121
CD
230 register struct connect_args /* {
231 syscallarg(int) s;
232 syscallarg(caddr_t) name;
233 syscallarg(int) namelen;
234 } */ *uap;
235 register_t *retval;
85843d69 236{
5e00df3b 237 struct file *fp;
c8c7dd0e 238 register struct socket *so;
cf012934 239 struct mbuf *nam;
27f43765 240 int error, s;
c8c7dd0e 241
01eea121 242 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 243 return (error);
88a7a62a 244 so = (struct socket *)fp->f_data;
27f43765 245 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
d9c2f47f 246 return (EALREADY);
01eea121
CD
247 if (error = sockargs(&nam, SCARG(uap, name), SCARG(uap, namelen),
248 MT_SONAME))
d9c2f47f 249 return (error);
27f43765
MK
250 error = soconnect(so, nam);
251 if (error)
cf012934 252 goto bad;
27f43765 253 if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING)) {
6222acc3 254 m_freem(nam);
d9c2f47f 255 return (EINPROGRESS);
6222acc3 256 }
c8c7dd0e 257 s = splnet();
cc15ab5d 258 while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
27f43765
MK
259 if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
260 netcon, 0))
261 break;
262 if (error == 0) {
263 error = so->so_error;
264 so->so_error = 0;
265 }
cc15ab5d 266 splx(s);
cf012934 267bad:
6750daae 268 so->so_state &= ~SS_ISCONNECTING;
cf012934 269 m_freem(nam);
27f43765
MK
270 if (error == ERESTART)
271 error = EINTR;
d9c2f47f 272 return (error);
c8c7dd0e
BJ
273}
274
01eea121 275int
85843d69
KM
276socketpair(p, uap, retval)
277 struct proc *p;
01eea121
CD
278 register struct socketpair_args /* {
279 syscallarg(int) domain;
280 syscallarg(int) type;
281 syscallarg(int) protocol;
282 syscallarg(int *) rsv;
283 } */ *uap;
284 register_t *retval;
85843d69 285{
5e00df3b 286 register struct filedesc *fdp = p->p_fd;
0c9a45f0 287 struct file *fp1, *fp2;
5a48956d 288 struct socket *so1, *so2;
76ffad7c 289 int fd, error, sv[2];
cf012934 290
01eea121
CD
291 if (error = socreate(SCARG(uap, domain), &so1, SCARG(uap, type),
292 SCARG(uap, protocol)))
d9c2f47f 293 return (error);
01eea121
CD
294 if (error = socreate(SCARG(uap, domain), &so2, SCARG(uap, type),
295 SCARG(uap, protocol)))
b242cf10 296 goto free1;
5e00df3b 297 if (error = falloc(p, &fp1, &fd))
5a48956d 298 goto free2;
0c9a45f0 299 sv[0] = fd;
5a48956d
SL
300 fp1->f_flag = FREAD|FWRITE;
301 fp1->f_type = DTYPE_SOCKET;
302 fp1->f_ops = &socketops;
303 fp1->f_data = (caddr_t)so1;
5e00df3b 304 if (error = falloc(p, &fp2, &fd))
5a48956d
SL
305 goto free3;
306 fp2->f_flag = FREAD|FWRITE;
307 fp2->f_type = DTYPE_SOCKET;
308 fp2->f_ops = &socketops;
309 fp2->f_data = (caddr_t)so2;
0c9a45f0 310 sv[1] = fd;
76ffad7c 311 if (error = soconnect2(so1, so2))
5a48956d 312 goto free4;
01eea121 313 if (SCARG(uap, type) == SOCK_DGRAM) {
33446404
MK
314 /*
315 * Datagram socket connection is asymmetric.
316 */
76ffad7c 317 if (error = soconnect2(so2, so1))
33446404
MK
318 goto free4;
319 }
01eea121
CD
320 error = copyout((caddr_t)sv, (caddr_t)SCARG(uap, rsv),
321 2 * sizeof (int));
85843d69
KM
322 retval[0] = sv[0]; /* XXX ??? */
323 retval[1] = sv[1]; /* XXX ??? */
d9c2f47f 324 return (error);
5a48956d 325free4:
336f999d 326 ffree(fp2);
994fd74e 327 fdp->fd_ofiles[sv[1]] = 0;
5a48956d 328free3:
336f999d 329 ffree(fp1);
994fd74e 330 fdp->fd_ofiles[sv[0]] = 0;
5a48956d 331free2:
8011f5df 332 (void)soclose(so2);
b242cf10 333free1:
8011f5df 334 (void)soclose(so1);
d9c2f47f 335 return (error);
cf012934
BJ
336}
337
01eea121 338int
85843d69
KM
339sendto(p, uap, retval)
340 struct proc *p;
01eea121
CD
341 register struct sendto_args /* {
342 syscallarg(int) s;
343 syscallarg(caddr_t) buf;
344 syscallarg(size_t) len;
345 syscallarg(int) flags;
346 syscallarg(caddr_t) to;
347 syscallarg(int) tolen;
348 } */ *uap;
349 register_t *retval;
85843d69 350{
88a7a62a 351 struct msghdr msg;
d3d550b5 352 struct iovec aiov;
c8c7dd0e 353
01eea121
CD
354 msg.msg_name = SCARG(uap, to);
355 msg.msg_namelen = SCARG(uap, tolen);
88a7a62a
SL
356 msg.msg_iov = &aiov;
357 msg.msg_iovlen = 1;
27f43765 358 msg.msg_control = 0;
8ffc8876 359#ifdef COMPAT_OLDSOCK
27f43765
MK
360 msg.msg_flags = 0;
361#endif
01eea121
CD
362 aiov.iov_base = SCARG(uap, buf);
363 aiov.iov_len = SCARG(uap, len);
364 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
c8c7dd0e
BJ
365}
366
8ffc8876 367#ifdef COMPAT_OLDSOCK
01eea121
CD
368int
369compat_43_send(p, uap, retval)
85843d69 370 struct proc *p;
01eea121
CD
371 register struct compat_43_send_args /* {
372 syscallarg(int) s;
373 syscallarg(caddr_t) buf;
374 syscallarg(int) len;
375 syscallarg(int) flags;
376 } */ *uap;
377 register_t *retval;
85843d69 378{
88a7a62a 379 struct msghdr msg;
a6b6f679 380 struct iovec aiov;
cc15ab5d 381
88a7a62a
SL
382 msg.msg_name = 0;
383 msg.msg_namelen = 0;
384 msg.msg_iov = &aiov;
385 msg.msg_iovlen = 1;
01eea121
CD
386 aiov.iov_base = SCARG(uap, buf);
387 aiov.iov_len = SCARG(uap, len);
6d47a3da 388 msg.msg_control = 0;
27f43765 389 msg.msg_flags = 0;
01eea121 390 return (sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval));
88a7a62a
SL
391}
392
7a22a33c 393#define MSG_COMPAT 0x8000
01eea121
CD
394int
395compat_43_sendmsg(p, uap, retval)
85843d69 396 struct proc *p;
01eea121
CD
397 register struct compat_43_sendmsg_args /* {
398 syscallarg(int) s;
399 syscallarg(caddr_t) msg;
400 syscallarg(int) flags;
401 } */ *uap;
402 register_t *retval;
85843d69 403{
6d47a3da 404 struct msghdr msg;
813b7cd1 405 struct iovec aiov[UIO_SMALLIOV], *iov;
76ffad7c 406 int error;
6d47a3da 407
01eea121
CD
408 if (error = copyin(SCARG(uap, msg), (caddr_t)&msg,
409 sizeof (struct omsghdr)))
d9c2f47f 410 return (error);
813b7cd1
MT
411 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
412 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
d9c2f47f 413 return (EMSGSIZE);
813b7cd1
MT
414 MALLOC(iov, struct iovec *,
415 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
416 M_WAITOK);
417 } else
418 iov = aiov;
419 if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
420 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
421 goto done;
7a22a33c 422 msg.msg_flags = MSG_COMPAT;
813b7cd1 423 msg.msg_iov = iov;
01eea121 424 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
813b7cd1
MT
425done:
426 if (iov != aiov)
427 FREE(iov, M_IOV);
d9c2f47f 428 return (error);
6d47a3da
MK
429}
430#endif
431
01eea121 432int
85843d69
KM
433sendmsg(p, uap, retval)
434 struct proc *p;
01eea121
CD
435 register struct sendmsg_args /* {
436 syscallarg(int) s;
437 syscallarg(caddr_t) msg;
438 syscallarg(int) flags;
439 } */ *uap;
440 register_t *retval;
85843d69 441{
88a7a62a 442 struct msghdr msg;
813b7cd1 443 struct iovec aiov[UIO_SMALLIOV], *iov;
76ffad7c 444 int error;
88a7a62a 445
01eea121 446 if (error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof (msg)))
d9c2f47f 447 return (error);
813b7cd1
MT
448 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
449 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
d9c2f47f 450 return (EMSGSIZE);
813b7cd1
MT
451 MALLOC(iov, struct iovec *,
452 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
453 M_WAITOK);
454 } else
455 iov = aiov;
3eb6310a 456 if (msg.msg_iovlen &&
813b7cd1
MT
457 (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
458 (unsigned)(msg.msg_iovlen * sizeof (struct iovec)))))
459 goto done;
460 msg.msg_iov = iov;
8ffc8876 461#ifdef COMPAT_OLDSOCK
27f43765
MK
462 msg.msg_flags = 0;
463#endif
01eea121 464 error = sendit(p, SCARG(uap, s), &msg, SCARG(uap, flags), retval);
813b7cd1
MT
465done:
466 if (iov != aiov)
467 FREE(iov, M_IOV);
d9c2f47f 468 return (error);
88a7a62a
SL
469}
470
01eea121 471int
5e00df3b
KM
472sendit(p, s, mp, flags, retsize)
473 register struct proc *p;
88a7a62a
SL
474 int s;
475 register struct msghdr *mp;
01eea121
CD
476 int flags;
477 register_t *retsize;
88a7a62a 478{
5e00df3b 479 struct file *fp;
88a7a62a
SL
480 struct uio auio;
481 register struct iovec *iov;
482 register int i;
27f43765 483 struct mbuf *to, *control;
76ffad7c 484 int len, error;
813b7cd1
MT
485#ifdef KTRACE
486 struct iovec *ktriov = NULL;
487#endif
88a7a62a 488
5e00df3b 489 if (error = getsock(p->p_fd, s, &fp))
76ffad7c 490 return (error);
88a7a62a
SL
491 auio.uio_iov = mp->msg_iov;
492 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 493 auio.uio_segflg = UIO_USERSPACE;
c4ec2128 494 auio.uio_rw = UIO_WRITE;
994fd74e 495 auio.uio_procp = p;
88a7a62a
SL
496 auio.uio_offset = 0; /* XXX */
497 auio.uio_resid = 0;
498 iov = mp->msg_iov;
125c8f95 499 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
6d366756 500 if (auio.uio_resid + iov->iov_len < auio.uio_resid)
7a22a33c 501 return (EINVAL);
6d366756 502 auio.uio_resid += iov->iov_len;
88a7a62a
SL
503 }
504 if (mp->msg_name) {
76ffad7c
MK
505 if (error = sockargs(&to, mp->msg_name, mp->msg_namelen,
506 MT_SONAME))
507 return (error);
88a7a62a
SL
508 } else
509 to = 0;
6d47a3da 510 if (mp->msg_control) {
7a22a33c 511 if (mp->msg_controllen < sizeof(struct cmsghdr)
8ffc8876 512#ifdef COMPAT_OLDSOCK
a7a4c7b9 513 && mp->msg_flags != MSG_COMPAT
7a22a33c 514#endif
a7a4c7b9 515 ) {
7a22a33c
MK
516 error = EINVAL;
517 goto bad;
518 }
76ffad7c
MK
519 if (error = sockargs(&control, mp->msg_control,
520 mp->msg_controllen, MT_CONTROL))
6d47a3da 521 goto bad;
8ffc8876 522#ifdef COMPAT_OLDSOCK
7a22a33c 523 if (mp->msg_flags == MSG_COMPAT) {
27f43765 524 register struct cmsghdr *cm;
76ffad7c 525
27f43765 526 M_PREPEND(control, sizeof(*cm), M_WAIT);
76ffad7c
MK
527 if (control == 0) {
528 error = ENOBUFS;
529 goto bad;
530 } else {
27f43765
MK
531 cm = mtod(control, struct cmsghdr *);
532 cm->cmsg_len = control->m_len;
533 cm->cmsg_level = SOL_SOCKET;
534 cm->cmsg_type = SCM_RIGHTS;
535 }
536 }
537#endif
6d47a3da
MK
538 } else
539 control = 0;
813b7cd1 540#ifdef KTRACE
5e00df3b 541 if (KTRPOINT(p, KTR_GENIO)) {
813b7cd1
MT
542 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
543
544 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
545 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
546 }
547#endif
88a7a62a 548 len = auio.uio_resid;
76ffad7c 549 if (error = sosend((struct socket *)fp->f_data, to, &auio,
7a22a33c 550 (struct mbuf *)0, control, flags)) {
76ffad7c
MK
551 if (auio.uio_resid != len && (error == ERESTART ||
552 error == EINTR || error == EWOULDBLOCK))
553 error = 0;
554 if (error == EPIPE)
5e00df3b 555 psignal(p, SIGPIPE);
813b7cd1
MT
556 }
557 if (error == 0)
85843d69 558 *retsize = len - auio.uio_resid;
813b7cd1
MT
559#ifdef KTRACE
560 if (ktriov != NULL) {
561 if (error == 0)
5e00df3b 562 ktrgenio(p->p_tracep, s, UIO_WRITE,
81ba99b6 563 ktriov, *retsize, error);
813b7cd1
MT
564 FREE(ktriov, M_TEMP);
565 }
566#endif
6d47a3da 567bad:
88a7a62a
SL
568 if (to)
569 m_freem(to);
76ffad7c 570 return (error);
cf012934
BJ
571}
572
8ffc8876 573#ifdef COMPAT_OLDSOCK
01eea121
CD
574int
575compat_43_recvfrom(p, uap, retval)
85843d69 576 struct proc *p;
01eea121
CD
577 struct recvfrom_args /* {
578 syscallarg(int) s;
579 syscallarg(caddr_t) buf;
580 syscallarg(size_t) len;
581 syscallarg(int) flags;
582 syscallarg(caddr_t) from;
583 syscallarg(int *) fromlenaddr;
584 } */ *uap;
585 register_t *retval;
85843d69 586{
76ffad7c 587
01eea121 588 SCARG(uap, flags) |= MSG_COMPAT;
d9c2f47f 589 return (recvfrom(p, uap, retval));
f4d2893a 590}
f4d2893a 591#endif
76ffad7c 592
01eea121 593int
85843d69
KM
594recvfrom(p, uap, retval)
595 struct proc *p;
01eea121
CD
596 register struct recvfrom_args /* {
597 syscallarg(int) s;
598 syscallarg(caddr_t) buf;
599 syscallarg(size_t) len;
600 syscallarg(int) flags;
601 syscallarg(caddr_t) from;
602 syscallarg(int *) fromlenaddr;
603 } */ *uap;
604 register_t *retval;
85843d69 605{
88a7a62a 606 struct msghdr msg;
cf012934 607 struct iovec aiov;
7a22a33c 608 int error;
cf012934 609
01eea121
CD
610 if (SCARG(uap, fromlenaddr)) {
611 if (error = copyin((caddr_t)SCARG(uap, fromlenaddr),
7a22a33c 612 (caddr_t)&msg.msg_namelen, sizeof (msg.msg_namelen)))
d9c2f47f 613 return (error);
6d47a3da 614 } else
7a22a33c 615 msg.msg_namelen = 0;
01eea121 616 msg.msg_name = SCARG(uap, from);
88a7a62a
SL
617 msg.msg_iov = &aiov;
618 msg.msg_iovlen = 1;
01eea121
CD
619 aiov.iov_base = SCARG(uap, buf);
620 aiov.iov_len = SCARG(uap, len);
6d47a3da 621 msg.msg_control = 0;
01eea121
CD
622 msg.msg_flags = SCARG(uap, flags);
623 return (recvit(p, SCARG(uap, s), &msg,
624 (caddr_t)SCARG(uap, fromlenaddr), retval));
cf012934 625}
76ffad7c 626
8ffc8876 627#ifdef COMPAT_OLDSOCK
01eea121
CD
628int
629compat_43_recv(p, uap, retval)
85843d69 630 struct proc *p;
01eea121
CD
631 register struct compat_43_recv_args /* {
632 syscallarg(int) s;
633 syscallarg(caddr_t) buf;
634 syscallarg(int) len;
635 syscallarg(int) flags;
636 } */ *uap;
637 register_t *retval;
85843d69 638{
88a7a62a 639 struct msghdr msg;
cf012934
BJ
640 struct iovec aiov;
641
88a7a62a
SL
642 msg.msg_name = 0;
643 msg.msg_namelen = 0;
644 msg.msg_iov = &aiov;
645 msg.msg_iovlen = 1;
01eea121
CD
646 aiov.iov_base = SCARG(uap, buf);
647 aiov.iov_len = SCARG(uap, len);
6d47a3da 648 msg.msg_control = 0;
01eea121
CD
649 msg.msg_flags = SCARG(uap, flags);
650 return (recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval));
6d47a3da
MK
651}
652
7a22a33c
MK
653/*
654 * Old recvmsg. This code takes advantage of the fact that the old msghdr
655 * overlays the new one, missing only the flags, and with the (old) access
656 * rights where the control fields are now.
657 */
01eea121
CD
658int
659compat_43_recvmsg(p, uap, retval)
85843d69 660 struct proc *p;
01eea121
CD
661 register struct compat_43_recvmsg_args /* {
662 syscallarg(int) s;
663 syscallarg(struct omsghdr *) msg;
664 syscallarg(int) flags;
665 } */ *uap;
666 register_t *retval;
85843d69 667{
6d47a3da 668 struct msghdr msg;
813b7cd1 669 struct iovec aiov[UIO_SMALLIOV], *iov;
76ffad7c 670 int error;
6d47a3da 671
01eea121 672 if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
76ffad7c 673 sizeof (struct omsghdr)))
d9c2f47f 674 return (error);
813b7cd1
MT
675 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
676 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
d9c2f47f 677 return (EMSGSIZE);
813b7cd1
MT
678 MALLOC(iov, struct iovec *,
679 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
680 M_WAITOK);
681 } else
682 iov = aiov;
01eea121 683 msg.msg_flags = SCARG(uap, flags) | MSG_COMPAT;
813b7cd1
MT
684 if (error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
685 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
686 goto done;
687 msg.msg_iov = iov;
01eea121
CD
688 error = recvit(p, SCARG(uap, s), &msg,
689 (caddr_t)&SCARG(uap, msg)->msg_namelen, retval);
7a22a33c
MK
690
691 if (msg.msg_controllen && error == 0)
692 error = copyout((caddr_t)&msg.msg_controllen,
01eea121 693 (caddr_t)&SCARG(uap, msg)->msg_accrightslen, sizeof (int));
813b7cd1
MT
694done:
695 if (iov != aiov)
696 FREE(iov, M_IOV);
d9c2f47f 697 return (error);
cf012934 698}
6d47a3da 699#endif
cf012934 700
01eea121 701int
85843d69
KM
702recvmsg(p, uap, retval)
703 struct proc *p;
01eea121
CD
704 register struct recvmsg_args /* {
705 syscallarg(int) s;
706 syscallarg(struct msghdr *) msg;
707 syscallarg(int) flags;
708 } */ *uap;
709 register_t *retval;
85843d69 710{
88a7a62a 711 struct msghdr msg;
813b7cd1 712 struct iovec aiov[UIO_SMALLIOV], *uiov, *iov;
76ffad7c
MK
713 register int error;
714
01eea121
CD
715 if (error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
716 sizeof (msg)))
d9c2f47f 717 return (error);
813b7cd1
MT
718 if ((u_int)msg.msg_iovlen >= UIO_SMALLIOV) {
719 if ((u_int)msg.msg_iovlen >= UIO_MAXIOV)
d9c2f47f 720 return (EMSGSIZE);
813b7cd1
MT
721 MALLOC(iov, struct iovec *,
722 sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
723 M_WAITOK);
724 } else
725 iov = aiov;
8ffc8876 726#ifdef COMPAT_OLDSOCK
01eea121 727 msg.msg_flags = SCARG(uap, flags) &~ MSG_COMPAT;
7a22a33c 728#else
01eea121 729 msg.msg_flags = SCARG(uap, flags);
7a22a33c 730#endif
27f43765 731 uiov = msg.msg_iov;
813b7cd1
MT
732 msg.msg_iov = iov;
733 if (error = copyin((caddr_t)uiov, (caddr_t)iov,
734 (unsigned)(msg.msg_iovlen * sizeof (struct iovec))))
735 goto done;
01eea121 736 if ((error = recvit(p, SCARG(uap, s), &msg, (caddr_t)0, retval)) == 0) {
76ffad7c 737 msg.msg_iov = uiov;
01eea121
CD
738 error = copyout((caddr_t)&msg, (caddr_t)SCARG(uap, msg),
739 sizeof(msg));
76ffad7c 740 }
813b7cd1
MT
741done:
742 if (iov != aiov)
743 FREE(iov, M_IOV);
d9c2f47f 744 return (error);
cf012934
BJ
745}
746
01eea121 747int
5e00df3b
KM
748recvit(p, s, mp, namelenp, retsize)
749 register struct proc *p;
7a22a33c 750 int s;
88a7a62a 751 register struct msghdr *mp;
7a22a33c 752 caddr_t namelenp;
01eea121 753 register_t *retsize;
cf012934 754{
5e00df3b 755 struct file *fp;
88a7a62a
SL
756 struct uio auio;
757 register struct iovec *iov;
758 register int i;
76ffad7c 759 int len, error;
7a22a33c 760 struct mbuf *from = 0, *control = 0;
813b7cd1
MT
761#ifdef KTRACE
762 struct iovec *ktriov = NULL;
763#endif
88a7a62a 764
5e00df3b 765 if (error = getsock(p->p_fd, s, &fp))
76ffad7c 766 return (error);
88a7a62a
SL
767 auio.uio_iov = mp->msg_iov;
768 auio.uio_iovcnt = mp->msg_iovlen;
c41770c0 769 auio.uio_segflg = UIO_USERSPACE;
c4ec2128 770 auio.uio_rw = UIO_READ;
994fd74e 771 auio.uio_procp = p;
88a7a62a
SL
772 auio.uio_offset = 0; /* XXX */
773 auio.uio_resid = 0;
774 iov = mp->msg_iov;
125c8f95 775 for (i = 0; i < mp->msg_iovlen; i++, iov++) {
6d366756 776 if (auio.uio_resid + iov->iov_len < auio.uio_resid)
7a22a33c 777 return (EINVAL);
6d366756 778 auio.uio_resid += iov->iov_len;
88a7a62a 779 }
813b7cd1 780#ifdef KTRACE
5e00df3b 781 if (KTRPOINT(p, KTR_GENIO)) {
813b7cd1
MT
782 int iovlen = auio.uio_iovcnt * sizeof (struct iovec);
783
784 MALLOC(ktriov, struct iovec *, iovlen, M_TEMP, M_WAITOK);
785 bcopy((caddr_t)auio.uio_iov, (caddr_t)ktriov, iovlen);
786 }
787#endif
88a7a62a 788 len = auio.uio_resid;
76ffad7c 789 if (error = soreceive((struct socket *)fp->f_data, &from, &auio,
34827683
KM
790 (struct mbuf **)0, mp->msg_control ? &control : (struct mbuf **)0,
791 &mp->msg_flags)) {
76ffad7c
MK
792 if (auio.uio_resid != len && (error == ERESTART ||
793 error == EINTR || error == EWOULDBLOCK))
794 error = 0;
795 }
813b7cd1
MT
796#ifdef KTRACE
797 if (ktriov != NULL) {
798 if (error == 0)
5e00df3b 799 ktrgenio(p->p_tracep, s, UIO_READ,
81ba99b6 800 ktriov, len - auio.uio_resid, error);
813b7cd1
MT
801 FREE(ktriov, M_TEMP);
802 }
803#endif
76ffad7c
MK
804 if (error)
805 goto out;
85843d69 806 *retsize = len - auio.uio_resid;
88a7a62a
SL
807 if (mp->msg_name) {
808 len = mp->msg_namelen;
809 if (len <= 0 || from == 0)
810 len = 0;
811 else {
8ffc8876 812#ifdef COMPAT_OLDSOCK
7a22a33c 813 if (mp->msg_flags & MSG_COMPAT)
f4d2893a
MK
814 mtod(from, struct osockaddr *)->sa_family =
815 mtod(from, struct sockaddr *)->sa_family;
816#endif
7a22a33c 817 if (len > from->m_len)
88a7a62a 818 len = from->m_len;
7a22a33c
MK
819 /* else if len < from->m_len ??? */
820 if (error = copyout(mtod(from, caddr_t),
821 (caddr_t)mp->msg_name, (unsigned)len))
822 goto out;
88a7a62a 823 }
a2aebb63 824 mp->msg_namelen = len;
7a22a33c
MK
825 if (namelenp &&
826 (error = copyout((caddr_t)&len, namelenp, sizeof (int)))) {
8ffc8876 827#ifdef COMPAT_OLDSOCK
7a22a33c
MK
828 if (mp->msg_flags & MSG_COMPAT)
829 error = 0; /* old recvfrom didn't check */
830 else
831#endif
832 goto out;
88a7a62a 833 }
6d47a3da
MK
834 }
835 if (mp->msg_control) {
8ffc8876 836#ifdef COMPAT_OLDSOCK
7a22a33c
MK
837 /*
838 * We assume that old recvmsg calls won't receive access
839 * rights and other control info, esp. as control info
840 * is always optional and those options didn't exist in 4.3.
841 * If we receive rights, trim the cmsghdr; anything else
842 * is tossed.
843 */
844 if (control && mp->msg_flags & MSG_COMPAT) {
845 if (mtod(control, struct cmsghdr *)->cmsg_level !=
846 SOL_SOCKET ||
847 mtod(control, struct cmsghdr *)->cmsg_type !=
848 SCM_RIGHTS) {
849 mp->msg_controllen = 0;
850 goto out;
27f43765 851 }
7a22a33c
MK
852 control->m_len -= sizeof (struct cmsghdr);
853 control->m_data += sizeof (struct cmsghdr);
27f43765 854 }
7a22a33c 855#endif
6d47a3da
MK
856 len = mp->msg_controllen;
857 if (len <= 0 || control == 0)
858 len = 0;
859 else {
860 if (len >= control->m_len)
861 len = control->m_len;
862 else
863 mp->msg_flags |= MSG_CTRUNC;
7a22a33c 864 error = copyout((caddr_t)mtod(control, caddr_t),
6d47a3da
MK
865 (caddr_t)mp->msg_control, (unsigned)len);
866 }
a2aebb63 867 mp->msg_controllen = len;
88a7a62a 868 }
76ffad7c 869out:
88a7a62a
SL
870 if (from)
871 m_freem(from);
6d47a3da
MK
872 if (control)
873 m_freem(control);
76ffad7c 874 return (error);
cf012934
BJ
875}
876
85843d69 877/* ARGSUSED */
01eea121 878int
85843d69
KM
879shutdown(p, uap, retval)
880 struct proc *p;
01eea121
CD
881 register struct shutdown_args /* {
882 syscallarg(int) s;
883 syscallarg(int) how;
884 } */ *uap;
885 register_t *retval;
85843d69 886{
6ef233bf 887 struct file *fp;
76ffad7c 888 int error;
cf012934 889
01eea121 890 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 891 return (error);
01eea121 892 return (soshutdown((struct socket *)fp->f_data, SCARG(uap, how)));
cf012934
BJ
893}
894
85843d69 895/* ARGSUSED */
01eea121 896int
85843d69
KM
897setsockopt(p, uap, retval)
898 struct proc *p;
01eea121
CD
899 register struct setsockopt_args /* {
900 syscallarg(int) s;
901 syscallarg(int) level;
902 syscallarg(int) name;
903 syscallarg(caddr_t) val;
904 syscallarg(int) valsize;
905 } */ *uap;
906 register_t *retval;
85843d69 907{
66f52238 908 struct file *fp;
d2cba8de 909 struct mbuf *m = NULL;
76ffad7c 910 int error;
66f52238 911
01eea121 912 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 913 return (error);
01eea121 914 if (SCARG(uap, valsize) > MLEN)
d9c2f47f 915 return (EINVAL);
01eea121 916 if (SCARG(uap, val)) {
d2cba8de 917 m = m_get(M_WAIT, MT_SOOPTS);
76ffad7c 918 if (m == NULL)
d9c2f47f 919 return (ENOBUFS);
01eea121
CD
920 if (error = copyin(SCARG(uap, val), mtod(m, caddr_t),
921 (u_int)SCARG(uap, valsize))) {
61ec2127 922 (void) m_free(m);
d9c2f47f 923 return (error);
61ec2127 924 }
01eea121 925 m->m_len = SCARG(uap, valsize);
66f52238 926 }
01eea121
CD
927 return (sosetopt((struct socket *)fp->f_data, SCARG(uap, level),
928 SCARG(uap, name), m));
66f52238
SL
929}
930
85843d69 931/* ARGSUSED */
01eea121 932int
85843d69
KM
933getsockopt(p, uap, retval)
934 struct proc *p;
01eea121
CD
935 register struct getsockopt_args /* {
936 syscallarg(int) s;
937 syscallarg(int) level;
938 syscallarg(int) name;
939 syscallarg(caddr_t) val;
940 syscallarg(int *) avalsize;
941 } */ *uap;
942 register_t *retval;
85843d69 943{
66f52238 944 struct file *fp;
d2cba8de 945 struct mbuf *m = NULL;
76ffad7c 946 int valsize, error;
66f52238 947
01eea121 948 if (error = getsock(p->p_fd, SCARG(uap, s), &fp))
d9c2f47f 949 return (error);
01eea121
CD
950 if (SCARG(uap, val)) {
951 if (error = copyin((caddr_t)SCARG(uap, avalsize),
952 (caddr_t)&valsize, sizeof (valsize)))
d9c2f47f 953 return (error);
61ec2127
SL
954 } else
955 valsize = 0;
01eea121
CD
956 if ((error = sogetopt((struct socket *)fp->f_data, SCARG(uap, level),
957 SCARG(uap, name), &m)) == 0 && SCARG(uap, val) && valsize &&
958 m != NULL) {
d2cba8de
SL
959 if (valsize > m->m_len)
960 valsize = m->m_len;
01eea121
CD
961 error = copyout(mtod(m, caddr_t), SCARG(uap, val),
962 (u_int)valsize);
76ffad7c
MK
963 if (error == 0)
964 error = copyout((caddr_t)&valsize,
01eea121 965 (caddr_t)SCARG(uap, avalsize), sizeof (valsize));
d2cba8de 966 }
d2cba8de
SL
967 if (m != NULL)
968 (void) m_free(m);
d9c2f47f 969 return (error);
66f52238
SL
970}
971
85843d69 972/* ARGSUSED */
01eea121 973int
85843d69
KM
974pipe(p, uap, retval)
975 struct proc *p;
01eea121
CD
976 void *uap;
977 register_t *retval;
cf012934 978{
5e00df3b 979 register struct filedesc *fdp = p->p_fd;
0c9a45f0 980 struct file *rf, *wf;
cf012934 981 struct socket *rso, *wso;
76ffad7c 982 int fd, error;
cf012934 983
76ffad7c 984 if (error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0))
d9c2f47f 985 return (error);
76ffad7c 986 if (error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0))
b242cf10 987 goto free1;
5e00df3b 988 if (error = falloc(p, &rf, &fd))
cf012934 989 goto free2;
85843d69 990 retval[0] = fd;
cf012934
BJ
991 rf->f_flag = FREAD;
992 rf->f_type = DTYPE_SOCKET;
88a7a62a
SL
993 rf->f_ops = &socketops;
994 rf->f_data = (caddr_t)rso;
5e00df3b 995 if (error = falloc(p, &wf, &fd))
cf012934
BJ
996 goto free3;
997 wf->f_flag = FWRITE;
998 wf->f_type = DTYPE_SOCKET;
88a7a62a
SL
999 wf->f_ops = &socketops;
1000 wf->f_data = (caddr_t)wso;
85843d69 1001 retval[1] = fd;
76ffad7c 1002 if (error = unp_connect2(wso, rso))
cf012934 1003 goto free4;
d9c2f47f 1004 return (0);
cf012934 1005free4:
336f999d 1006 ffree(wf);
994fd74e 1007 fdp->fd_ofiles[retval[1]] = 0;
cf012934 1008free3:
336f999d 1009 ffree(rf);
994fd74e 1010 fdp->fd_ofiles[retval[0]] = 0;
cf012934 1011free2:
8011f5df 1012 (void)soclose(wso);
b242cf10 1013free1:
8011f5df 1014 (void)soclose(rso);
d9c2f47f 1015 return (error);
cc15ab5d 1016}
a3076b07
BJ
1017
1018/*
70f2eac5 1019 * Get socket name.
a3076b07 1020 */
8ffc8876 1021#ifdef COMPAT_OLDSOCK
01eea121 1022int
85843d69
KM
1023getsockname(p, uap, retval)
1024 struct proc *p;
01eea121
CD
1025 struct getsockname_args /* {
1026 syscallarg(int) fdes;
1027 syscallarg(caddr_t) asa;
1028 syscallarg(int *) alen;
1029 } */ *uap;
1030 register_t *retval;
85843d69 1031{
76ffad7c 1032
01eea121 1033 return (getsockname1(p, uap, retval, 0));
f4d2893a
MK
1034}
1035
01eea121
CD
1036int
1037compat_43_getsockname(p, uap, retval)
85843d69 1038 struct proc *p;
01eea121
CD
1039 struct getsockname_args /* {
1040 syscallarg(int) fdes;
1041 syscallarg(caddr_t) asa;
1042 syscallarg(int *) alen;
1043 } */ *uap;
1044 register_t *retval;
85843d69 1045{
76ffad7c 1046
01eea121 1047 return (getsockname1(p, uap, retval, 1));
f4d2893a 1048}
8ffc8876 1049#else /* COMPAT_OLDSOCK */
f4d2893a 1050
76ffad7c 1051#define getsockname1 getsockname
f4d2893a 1052#endif
76ffad7c 1053
85843d69 1054/* ARGSUSED */
01eea121
CD
1055int
1056getsockname1(p, uap, retval, compat_43)
85843d69 1057 struct proc *p;
01eea121
CD
1058 register struct getsockname_args /* {
1059 syscallarg(int) fdes;
1060 syscallarg(caddr_t) asa;
1061 syscallarg(int *) alen;
1062 } */ *uap;
1063 register_t *retval;
1064 int compat_43;
85843d69 1065{
5e00df3b 1066 struct file *fp;
05d69517 1067 register struct socket *so;
cf012934 1068 struct mbuf *m;
76ffad7c 1069 int len, error;
a3076b07 1070
01eea121 1071 if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp))
d9c2f47f 1072 return (error);
01eea121
CD
1073 if (error = copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len,
1074 sizeof (len)))
d9c2f47f 1075 return (error);
88a7a62a 1076 so = (struct socket *)fp->f_data;
cce93e4b 1077 m = m_getclr(M_WAIT, MT_SONAME);
76ffad7c 1078 if (m == NULL)
d9c2f47f 1079 return (ENOBUFS);
76ffad7c 1080 if (error = (*so->so_proto->pr_usrreq)(so, PRU_SOCKADDR, 0, m, 0))
70f2eac5
SL
1081 goto bad;
1082 if (len > m->m_len)
1083 len = m->m_len;
8ffc8876 1084#ifdef COMPAT_OLDSOCK
01eea121 1085 if (compat_43)
f4d2893a
MK
1086 mtod(m, struct osockaddr *)->sa_family =
1087 mtod(m, struct sockaddr *)->sa_family;
1088#endif
01eea121 1089 error = copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len);
76ffad7c 1090 if (error == 0)
01eea121 1091 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen),
f4d2893a 1092 sizeof (len));
cf012934
BJ
1093bad:
1094 m_freem(m);
d9c2f47f 1095 return (error);
cf012934
BJ
1096}
1097
f4d2893a
MK
1098/*
1099 * Get name of peer for connected socket.
1100 */
8ffc8876 1101#ifdef COMPAT_OLDSOCK
01eea121 1102int
85843d69
KM
1103getpeername(p, uap, retval)
1104 struct proc *p;
01eea121
CD
1105 struct getpeername_args /* {
1106 syscallarg(int) fdes;
1107 syscallarg(caddr_t) asa;
1108 syscallarg(int *) alen;
1109 } */ *uap;
1110 register_t *retval;
85843d69 1111{
76ffad7c 1112
01eea121 1113 return (getpeername1(p, uap, retval, 0));
6d47a3da 1114}
6d47a3da 1115
01eea121
CD
1116int
1117compat_43_getpeername(p, uap, retval)
85843d69 1118 struct proc *p;
01eea121
CD
1119 struct getpeername_args /* {
1120 syscallarg(int) fdes;
1121 syscallarg(caddr_t) asa;
1122 syscallarg(int *) alen;
1123 } */ *uap;
1124 register_t *retval;
85843d69 1125{
76ffad7c 1126
01eea121 1127 return (getpeername1(p, uap, retval, 1));
f4d2893a 1128}
8ffc8876 1129#else /* COMPAT_OLDSOCK */
f4d2893a 1130
76ffad7c 1131#define getpeername1 getpeername
f4d2893a 1132#endif
76ffad7c 1133
85843d69 1134/* ARGSUSED */
01eea121
CD
1135int
1136getpeername1(p, uap, retval, compat_43)
85843d69 1137 struct proc *p;
01eea121
CD
1138 register struct getpeername_args /* {
1139 syscallarg(int) fdes;
1140 syscallarg(caddr_t) asa;
1141 syscallarg(int *) alen;
1142 } */ *uap;
1143 register_t *retval;
1144 int compat_43;
85843d69 1145{
5e00df3b 1146 struct file *fp;
a7343092
SL
1147 register struct socket *so;
1148 struct mbuf *m;
76ffad7c 1149 int len, error;
a7343092 1150
01eea121 1151 if (error = getsock(p->p_fd, SCARG(uap, fdes), &fp))
d9c2f47f 1152 return (error);
a7343092 1153 so = (struct socket *)fp->f_data;
76ffad7c 1154 if ((so->so_state & (SS_ISCONNECTED|SS_ISCONFIRMING)) == 0)
d9c2f47f 1155 return (ENOTCONN);
01eea121
CD
1156 if (error =
1157 copyin((caddr_t)SCARG(uap, alen), (caddr_t)&len, sizeof (len)))
2c8123d6 1158 return (error);
a7343092 1159 m = m_getclr(M_WAIT, MT_SONAME);
76ffad7c 1160 if (m == NULL)
d9c2f47f 1161 return (ENOBUFS);
76ffad7c 1162 if (error = (*so->so_proto->pr_usrreq)(so, PRU_PEERADDR, 0, m, 0))
a7343092
SL
1163 goto bad;
1164 if (len > m->m_len)
1165 len = m->m_len;
8ffc8876 1166#ifdef COMPAT_OLDSOCK
01eea121 1167 if (compat_43)
f4d2893a
MK
1168 mtod(m, struct osockaddr *)->sa_family =
1169 mtod(m, struct sockaddr *)->sa_family;
1170#endif
01eea121
CD
1171 if (error =
1172 copyout(mtod(m, caddr_t), (caddr_t)SCARG(uap, asa), (u_int)len))
a7343092 1173 goto bad;
01eea121 1174 error = copyout((caddr_t)&len, (caddr_t)SCARG(uap, alen), sizeof (len));
a7343092
SL
1175bad:
1176 m_freem(m);
d9c2f47f 1177 return (error);
a7343092
SL
1178}
1179
01eea121 1180int
7a22a33c
MK
1181sockargs(mp, buf, buflen, type)
1182 struct mbuf **mp;
1183 caddr_t buf;
1184 int buflen, type;
cf012934 1185{
1d123e2b 1186 register struct sockaddr *sa;
cf012934 1187 register struct mbuf *m;
127f7d76 1188 int error;
cf012934 1189
7a22a33c 1190 if ((u_int)buflen > MLEN) {
8ffc8876 1191#ifdef COMPAT_OLDSOCK
7a22a33c
MK
1192 if (type == MT_SONAME && (u_int)buflen <= 112)
1193 buflen = MLEN; /* unix domain compat. hack */
3eb6310a
MK
1194 else
1195#endif
cf012934 1196 return (EINVAL);
3eb6310a 1197 }
98447d3f 1198 m = m_get(M_WAIT, type);
7c52d753
SL
1199 if (m == NULL)
1200 return (ENOBUFS);
7a22a33c
MK
1201 m->m_len = buflen;
1202 error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
01eea121 1203 if (error) {
cf012934 1204 (void) m_free(m);
01eea121
CD
1205 return (error);
1206 }
1207 *mp = m;
1208 if (type == MT_SONAME) {
1209 sa = mtod(m, struct sockaddr *);
76ffad7c 1210
8ffc8876 1211#if defined(COMPAT_OLDSOCK) && BYTE_ORDER != BIG_ENDIAN
01eea121
CD
1212 if (sa->sa_family == 0 && sa->sa_len < AF_MAX)
1213 sa->sa_family = sa->sa_len;
f4d2893a 1214#endif
01eea121 1215 sa->sa_len = buflen;
a2aebb63 1216 }
01eea121 1217 return (0);
cf012934 1218}
88a7a62a 1219
01eea121 1220int
5e00df3b
KM
1221getsock(fdp, fdes, fpp)
1222 struct filedesc *fdp;
1223 int fdes;
1224 struct file **fpp;
88a7a62a
SL
1225{
1226 register struct file *fp;
1227
8429d022 1228 if ((unsigned)fdes >= fdp->fd_nfiles ||
994fd74e 1229 (fp = fdp->fd_ofiles[fdes]) == NULL)
5e00df3b
KM
1230 return (EBADF);
1231 if (fp->f_type != DTYPE_SOCKET)
1232 return (ENOTSOCK);
1233 *fpp = fp;
1234 return (0);
88a7a62a 1235}