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