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