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}
|