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