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