1 /* $NetBSD: linux_socket.c,v 1.50.2.1 2004/09/20 05:59:47 tron Exp $ */
2
3 /*-
4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden and Eric Haszlakiewicz.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 /*
40 * Functions in multiarch:
41 * linux_sys_socketcall : linux_socketcall.c
42 */
43
44 #include <sys/cdefs.h>
45 __KERNEL_RCSID(0, "$NetBSD: linux_socket.c,v 1.50.2.1 2004/09/20 05:59:47 tron Exp $");
46
47 #if defined(_KERNEL_OPT)
48 #include "opt_inet.h"
49 #endif
50
51 #include <sys/param.h>
52 #include <sys/kernel.h>
53 #include <sys/systm.h>
54 #include <sys/buf.h>
55 #include <sys/malloc.h>
56 #include <sys/ioctl.h>
57 #include <sys/tty.h>
58 #include <sys/file.h>
59 #include <sys/filedesc.h>
60 #include <sys/select.h>
61 #include <sys/socket.h>
62 #include <sys/socketvar.h>
63 #include <sys/domain.h>
64 #include <net/if.h>
65 #include <net/if_dl.h>
66 #include <net/if_types.h>
67 #include <netinet/in.h>
68 #include <netinet/tcp.h>
69 #include <sys/mount.h>
70 #include <sys/proc.h>
71 #include <sys/vnode.h>
72 #include <sys/device.h>
73 #include <sys/protosw.h>
74 #include <sys/mbuf.h>
75 #include <sys/syslog.h>
76 #include <sys/exec.h>
77
78 #include <sys/sa.h>
79 #include <sys/syscallargs.h>
80
81 #ifdef INET6
82 #include <netinet/ip6.h>
83 #include <netinet6/ip6_var.h>
84 #endif
85
86 #include <compat/linux/common/linux_types.h>
87 #include <compat/linux/common/linux_util.h>
88 #include <compat/linux/common/linux_signal.h>
89 #include <compat/linux/common/linux_ioctl.h>
90 #include <compat/linux/common/linux_socket.h>
91 #include <compat/linux/common/linux_socketcall.h>
92 #include <compat/linux/common/linux_sockio.h>
93
94 #include <compat/linux/linux_syscallargs.h>
95
96 #ifdef DEBUG_LINUX
97 #define DPRINTF(a) uprintf a
98 #else
99 #define DPRINTF(a)
100 #endif
101
102 /*
103 * The calls in this file are entered either via the linux_socketcall()
104 * interface or, on the Alpha, as individual syscalls. The
105 * linux_socketcall function does any massaging of arguments so that all
106 * the calls in here need not think that they are anything other
107 * than a normal syscall.
108 */
109
110 static int linux_to_bsd_domain __P((int));
111 static int bsd_to_linux_domain __P((int));
112 int linux_to_bsd_sopt_level __P((int));
113 int linux_to_bsd_so_sockopt __P((int));
114 int linux_to_bsd_ip_sockopt __P((int));
115 int linux_to_bsd_tcp_sockopt __P((int));
116 int linux_to_bsd_udp_sockopt __P((int));
117 int linux_getifhwaddr __P((struct proc *, register_t *, u_int, void *));
118 static int linux_sa_get __P((struct proc *, int, caddr_t *, struct sockaddr **,
119 const struct osockaddr *, int *));
120 static int linux_sa_put __P((struct osockaddr *osa));
121 static int linux_to_bsd_msg_flags __P((int));
122 static int bsd_to_linux_msg_flags __P((int));
123
124 static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
125 AF_UNSPEC,
126 AF_UNIX,
127 AF_INET,
128 AF_CCITT, /* LINUX_AF_AX25 */
129 AF_IPX,
130 AF_APPLETALK,
131 -1, /* LINUX_AF_NETROM */
132 -1, /* LINUX_AF_BRIDGE */
133 -1, /* LINUX_AF_ATMPVC */
134 AF_CCITT, /* LINUX_AF_X25 */
135 AF_INET6,
136 -1, /* LINUX_AF_ROSE */
137 AF_DECnet,
138 -1, /* LINUX_AF_NETBEUI */
139 -1, /* LINUX_AF_SECURITY */
140 pseudo_AF_KEY,
141 AF_ROUTE, /* LINUX_AF_NETLINK */
142 -1, /* LINUX_AF_PACKET */
143 -1, /* LINUX_AF_ASH */
144 -1, /* LINUX_AF_ECONET */
145 -1, /* LINUX_AF_ATMSVC */
146 AF_SNA,
147 /* rest up to LINUX_AF_MAX-1 is not allocated */
148 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
149 };
150
151 static const int bsd_to_linux_domain_[AF_MAX] = {
152 LINUX_AF_UNSPEC,
153 LINUX_AF_UNIX,
154 LINUX_AF_INET,
155 -1, /* AF_IMPLINK */
156 -1, /* AF_PUP */
157 -1, /* AF_CHAOS */
158 -1, /* AF_NS */
159 -1, /* AF_ISO */
160 -1, /* AF_ECMA */
161 -1, /* AF_DATAKIT */
162 LINUX_AF_AX25, /* AF_CCITT */
163 LINUX_AF_SNA,
164 LINUX_AF_DECnet,
165 -1, /* AF_DLI */
166 -1, /* AF_LAT */
167 -1, /* AF_HYLINK */
168 LINUX_AF_APPLETALK,
169 LINUX_AF_NETLINK,
170 -1, /* AF_LINK */
171 -1, /* AF_XTP */
172 -1, /* AF_COIP */
173 -1, /* AF_CNT */
174 -1, /* pseudo_AF_RTIP */
175 LINUX_AF_IPX,
176 LINUX_AF_INET6,
177 -1, /* pseudo_AF_PIP */
178 -1, /* AF_ISDN */
179 -1, /* AF_NATM */
180 -1, /* AF_ARP */
181 LINUX_pseudo_AF_KEY,
182 -1, /* pseudo_AF_HDRCMPLT */
183 };
184
185 static const int bsd_to_linux_msg_flags_[] = {
186 MSG_OOB, LINUX_MSG_OOB,
187 MSG_PEEK, LINUX_MSG_PEEK,
188 MSG_DONTROUTE, LINUX_MSG_DONTROUTE,
189 MSG_EOR, LINUX_MSG_EOR,
190 MSG_TRUNC, LINUX_MSG_TRUNC,
191 MSG_CTRUNC, LINUX_MSG_CTRUNC,
192 MSG_WAITALL, LINUX_MSG_WAITALL,
193 MSG_DONTWAIT, LINUX_MSG_DONTWAIT,
194 MSG_BCAST, 0, /* not supported, clear */
195 MSG_MCAST, 0, /* not supported, clear */
196 -1, /* not supp */ LINUX_MSG_PROBE,
197 -1, /* not supp */ LINUX_MSG_FIN,
198 -1, /* not supp */ LINUX_MSG_SYN,
199 -1, /* not supp */ LINUX_MSG_CONFIRM,
200 -1, /* not supp */ LINUX_MSG_RST,
201 -1, /* not supp */ LINUX_MSG_ERRQUEUE,
202 -1, /* not supp */ LINUX_MSG_NOSIGNAL,
203 -1, /* not supp */ LINUX_MSG_MORE,
204 };
205
206 /*
207 * Convert between Linux and BSD socket domain values
208 */
209 static int
210 linux_to_bsd_domain(ldom)
211 int ldom;
212 {
213 if (ldom < 0 || ldom >= LINUX_AF_MAX)
214 return (-1);
215
216 return linux_to_bsd_domain_[ldom];
217 }
218
219 /*
220 * Convert between BSD and Linux socket domain values
221 */
222 static int
223 bsd_to_linux_domain(bdom)
224 int bdom;
225 {
226 if (bdom < 0 || bdom >= AF_MAX)
227 return (-1);
228
229 return bsd_to_linux_domain_[bdom];
230 }
231
232 static int
233 linux_to_bsd_msg_flags(lflag)
234 int lflag;
235 {
236 int i, lfl, bfl;
237 int bflag = 0;
238
239 if (lflag == 0)
240 return (0);
241
242 for(i=0; i < sizeof(bsd_to_linux_msg_flags_)/2; i += 2) {
243 bfl = bsd_to_linux_msg_flags_[i];
244 lfl = bsd_to_linux_msg_flags_[i+1];
245
246 if (lfl == 0)
247 continue;
248
249 if (lflag & lfl) {
250 if (bfl < 0)
251 return (-1);
252
253 bflag |= bfl;
254 }
255 }
256
257 return (bflag);
258 }
259
260 static int
261 bsd_to_linux_msg_flags(bflag)
262 int bflag;
263 {
264 int i, lfl, bfl;
265 int lflag = 0;
266
267 if (bflag == 0)
268 return (0);
269
270 for(i=0; i < sizeof(bsd_to_linux_msg_flags_)/2; i += 2) {
271 bfl = bsd_to_linux_msg_flags_[i];
272 lfl = bsd_to_linux_msg_flags_[i+1];
273
274 if (bfl <= 0)
275 continue;
276
277 if (bflag & bfl) {
278 if (lfl < 0)
279 return (-1);
280
281 lflag |= lfl;
282 }
283 }
284
285 return (lflag);
286 }
287
288 int
289 linux_sys_socket(l, v, retval)
290 struct lwp *l;
291 void *v;
292 register_t *retval;
293 {
294 struct linux_sys_socket_args /* {
295 syscallarg(int) domain;
296 syscallarg(int) type;
297 syscallarg(int) protocol;
298 } */ *uap = v;
299 struct sys_socket_args bsa;
300 int error;
301
302 SCARG(&bsa, protocol) = SCARG(uap, protocol);
303 SCARG(&bsa, type) = SCARG(uap, type);
304 SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
305 if (SCARG(&bsa, domain) == -1)
306 return EINVAL;
307 error = sys_socket(l, &bsa, retval);
308
309 #ifdef INET6
310 /*
311 * Linux AF_INET6 socket has IPV6_V6ONLY setsockopt set to 0 by
312 * default and some apps depend on this. So, set V6ONLY to 0
313 * for Linux apps if the sysctl value is set to 1.
314 */
315 if (!error && ip6_v6only && SCARG(&bsa, domain) == PF_INET6) {
316 struct proc *p = l->l_proc;
317 struct file *fp;
318
319 if (getsock(p->p_fd, *retval, &fp) == 0) {
320 struct mbuf *m;
321
322 m = m_get(M_WAIT, MT_SOOPTS);
323 m->m_len = sizeof(int);
324 *mtod(m, int *) = 0;
325
326 /* ignore error */
327 (void) sosetopt((struct socket *)fp->f_data,
328 IPPROTO_IPV6, IPV6_V6ONLY, m);
329
330 FILE_UNUSE(fp, p);
331 }
332 }
333 #endif
334
335 return (error);
336 }
337
338 int
339 linux_sys_socketpair(l, v, retval)
340 struct lwp *l;
341 void *v;
342 register_t *retval;
343 {
344 struct linux_sys_socketpair_args /* {
345 syscallarg(int) domain;
346 syscallarg(int) type;
347 syscallarg(int) protocol;
348 syscallarg(int *) rsv;
349 } */ *uap = v;
350 struct sys_socketpair_args bsa;
351
352 SCARG(&bsa, domain) = linux_to_bsd_domain(SCARG(uap, domain));
353 if (SCARG(&bsa, domain) == -1)
354 return EINVAL;
355 SCARG(&bsa, type) = SCARG(uap, type);
356 SCARG(&bsa, protocol) = SCARG(uap, protocol);
357 SCARG(&bsa, rsv) = SCARG(uap, rsv);
358
359 return sys_socketpair(l, &bsa, retval);
360 }
361
362 int
363 linux_sys_sendto(l, v, retval)
364 struct lwp *l;
365 void *v;
366 register_t *retval;
367 {
368 struct linux_sys_sendto_args /* {
369 syscallarg(int) s;
370 syscallarg(void *) msg;
371 syscallarg(int) len;
372 syscallarg(int) flags;
373 syscallarg(struct osockaddr *) to;
374 syscallarg(int) tolen;
375 } */ *uap = v;
376 struct proc *p = l->l_proc;
377 struct sys_sendto_args bsa;
378 int tolen;
379
380 SCARG(&bsa, s) = SCARG(uap, s);
381 SCARG(&bsa, buf) = SCARG(uap, msg);
382 SCARG(&bsa, len) = (size_t) SCARG(uap, len);
383 SCARG(&bsa, flags) = SCARG(uap, flags);
384 tolen = SCARG(uap, tolen);
385 if (SCARG(uap, to)) {
386 struct sockaddr *sa;
387 int error;
388 caddr_t sg = stackgap_init(p, 0);
389
390 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
391 SCARG(uap, to), &tolen);
392 if (error)
393 return (error);
394
395 SCARG(&bsa, to) = sa;
396 } else
397 SCARG(&bsa, to) = NULL;
398 SCARG(&bsa, tolen) = tolen;
399
400 return (sys_sendto(l, &bsa, retval));
401 }
402
403 int
404 linux_sys_sendmsg(l, v, retval)
405 struct lwp *l;
406 void *v;
407 register_t *retval;
408 {
409 struct linux_sys_sendmsg_args /* {
410 syscallarg(int) s;
411 syscallarg(struct msghdr *) msg;
412 syscallarg(u_int) flags;
413 } */ *uap = v;
414 struct proc *p = l->l_proc;
415 struct msghdr msg;
416 int error;
417 struct iovec aiov[UIO_SMALLIOV], *iov;
418 caddr_t sg = 0;
419 int bflags;
420 u_int8_t *control=NULL;
421
422 error = copyin(SCARG(uap, msg), (caddr_t)&msg, sizeof(msg));
423 if (error)
424 return (error);
425 if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
426 if ((unsigned int)msg.msg_iovlen > IOV_MAX)
427 return (EMSGSIZE);
428 iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
429 M_IOV, M_WAITOK);
430 } else
431 iov = aiov;
432 if ((unsigned int)msg.msg_iovlen > 0) {
433 error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
434 (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
435 if (error)
436 goto done;
437 }
438 msg.msg_iov = iov;
439 msg.msg_flags = 0;
440
441 /* Convert the sockaddr if necessary */
442 if (msg.msg_name) {
443 struct sockaddr *sa;
444 sg = stackgap_init(p, 0);
445
446 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
447 (struct osockaddr *) msg.msg_name, &msg.msg_namelen);
448 if (error)
449 goto done;
450 msg.msg_name = sa;
451 }
452
453 /*
454 * Translate message flags.
455 */
456 bflags = linux_to_bsd_msg_flags(SCARG(uap, flags));
457 if (bflags < 0) {
458 /* Some supported flag */
459 error = EINVAL;
460 goto done;
461 }
462
463 /*
464 * Handle cmsg if there is any.
465 */
466 if (CMSG_FIRSTHDR(&msg)) {
467 struct cmsghdr cmsg, *cc;
468 int changed = 0;
469 ssize_t resid = msg.msg_controllen;
470 size_t clen, cidx = 0, cspace;
471
472 /*
473 * Limit the size even more than what sockargs() would do,
474 * We need to fit into stackgap space.
475 */
476 if (msg.msg_controllen > (STACKGAPLEN / 2)) {
477 /* Sorry guys! */
478 error = EMSGSIZE;
479 goto done;
480 }
481
482 control = malloc((clen = msg.msg_controllen), M_TEMP, M_WAITOK);
483 if (!control) {
484 error = ENOMEM;
485 goto done;
486 }
487
488 cc = CMSG_FIRSTHDR(&msg);
489 do {
490 error = copyin(cc, &cmsg, sizeof(cmsg));
491 if (error)
492 goto done;
493
494 /*
495 * Sanity check the control message length.
496 */
497 if (cmsg.cmsg_len > resid
498 || cmsg.cmsg_len < sizeof(struct cmsghdr)) {
499 error = EINVAL;
500 goto done;
501 }
502
503 /*
504 * Refuse unsupported control messages, and
505 * translate fields as appropriate.
506 */
507 switch (cmsg.cmsg_level) {
508 case LINUX_SOL_SOCKET:
509 /* It only differs on some archs */
510 if (LINUX_SOL_SOCKET != SOL_SOCKET) {
511 cmsg.cmsg_level = SOL_SOCKET;
512 changed = 1;
513 }
514
515 switch(cmsg.cmsg_type) {
516 case LINUX_SCM_RIGHTS:
517 /* Linux SCM_RIGHTS is same as NetBSD */
518 break;
519
520 default:
521 /* other types not supported */
522 error = EINVAL;
523 goto done;
524 }
525 break;
526 default:
527 /* pray and leave intact */
528 break;
529 }
530
531 cspace = CMSG_SPACE(cmsg.cmsg_len - sizeof(cmsg));
532
533 /* Check the buffer is big enough */
534 if (__predict_false(cidx + cspace > clen)) {
535 u_int8_t *nc;
536
537 clen = cidx + cspace;
538 nc = realloc(control, clen, M_TEMP, M_WAITOK);
539 if (!nc) {
540 error = ENOMEM;
541 goto done;
542 }
543 control = nc;
544 }
545
546 /* Copy header */
547 memcpy(&control[cidx], &cmsg, sizeof(cmsg));
548
549 /* Zero are between header and data */
550 memset(&control[cidx+sizeof(cmsg)], 0,
551 CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg));
552
553 /* Copyin the data */
554 error = copyin(LINUX_CMSG_DATA(cc),
555 CMSG_DATA(control),
556 cmsg.cmsg_len - sizeof(cmsg));
557 if (error)
558 goto done;
559
560 /*
561 * If there is alignment difference, we changed
562 * layout of cmsg.
563 */
564 if (LINUX_CMSG_ALIGNDIFF)
565 changed = 1;
566
567 resid -= cspace;
568 cidx += cspace;
569 } while ((cc = LINUX_CMSG_NXTHDR(&msg, cc)) && resid > 0);
570
571 /*
572 * If any of the passed control message needed
573 * a change, put the changed data into stackgap
574 * and adjust msg appropriately.
575 */
576 if (changed) {
577 char *newc;
578
579 /*
580 * Check again the total len is maximum half of
581 * stackgap. The length might change if the
582 * alignment is different.
583 */
584 if (clen > STACKGAPLEN/2) {
585 error = EMSGSIZE;
586 goto done;
587 }
588
589 /*
590 * Allocate space on stack within stackgap, and
591 * copy changed data there.
592 */
593 if (!sg)
594 sg = stackgap_init(p, STACKGAPLEN/3);
595 newc = stackgap_alloc(p, &sg, clen);
596 if (!newc) {
597 error = ENOMEM;
598 goto done;
599 }
600
601 error = copyout(control, newc, clen);
602 if (error)
603 goto done;
604
605 msg.msg_control = newc;
606 msg.msg_controllen = clen;
607 }
608
609 free(control, M_TEMP);
610 control = NULL;
611 }
612
613 error = sendit(p, SCARG(uap, s), &msg, bflags, retval);
614
615 done:
616 if (control)
617 free(control, M_TEMP);
618 if (iov != aiov)
619 free(iov, M_IOV);
620 return (error);
621 }
622
623 int
624 linux_sys_recvfrom(l, v, retval)
625 struct lwp *l;
626 void *v;
627 register_t *retval;
628 {
629 struct linux_sys_recvfrom_args /* {
630 syscallarg(int) s;
631 syscallarg(void *) buf;
632 syscallarg(int) len;
633 syscallarg(int) flags;
634 syscallarg(struct osockaddr *) from;
635 syscallarg(int *) fromlenaddr;
636 } */ *uap = v;
637 int error;
638 struct sys_recvfrom_args bra;
639
640 SCARG(&bra, s) = SCARG(uap, s);
641 SCARG(&bra, buf) = SCARG(uap, buf);
642 SCARG(&bra, len) = SCARG(uap, len);
643 SCARG(&bra, flags) = SCARG(uap, flags);
644 SCARG(&bra, from) = (struct sockaddr *) SCARG(uap, from);
645 SCARG(&bra, fromlenaddr) = SCARG(uap, fromlenaddr);
646
647 if ((error = sys_recvfrom(l, &bra, retval)))
648 return (error);
649
650 if (SCARG(uap, from) && (error = linux_sa_put(SCARG(uap, from))))
651 return (error);
652
653 return (0);
654 }
655
656 int
657 linux_sys_recvmsg(l, v, retval)
658 struct lwp *l;
659 void *v;
660 register_t *retval;
661 {
662 struct linux_sys_recvmsg_args /* {
663 syscallarg(int) s;
664 syscallarg(struct msghdr *) msg;
665 syscallarg(u_int) flags;
666 } */ *uap = v;
667 struct msghdr msg;
668 int error;
669 struct sys_recvmsg_args bsa;
670 int lflags;
671 u_int8_t *ocontrol = NULL; /* XXX: gcc */
672 socklen_t ocontrollen = 0;
673
674 /*
675 * Data alignment is different on some architectures. If control
676 * message is expected, we must arrange for the control message
677 * to be initially put elsewhere, and copy to target place
678 * with Linux alignment.
679 */
680 if (LINUX_CMSG_ALIGNDIFF) {
681 error = copyin(SCARG(uap, msg), &msg, sizeof(msg));
682 if (error)
683 return (error);
684
685 if (CMSG_FIRSTHDR(&msg)) {
686 caddr_t sg;
687
688 /* Need to fit within stackgap */
689 if (msg.msg_controllen > STACKGAPLEN/2) {
690 /* Sorry guys! */
691 return (EINVAL);
692 }
693
694 sg = stackgap_init(l->l_proc, STACKGAPLEN/3);
695
696 ocontrol = msg.msg_control;
697 ocontrollen = msg.msg_controllen;
698
699 /* space for at least one message's worth align */
700 msg.msg_controllen += CMSG_ALIGN(1);
701
702 msg.msg_control = stackgap_alloc(l->l_proc, &sg,
703 msg.msg_controllen);
704 if (!msg.msg_control)
705 return (ENOMEM);
706
707 /*
708 * Okay to overwrite the original structure, it's
709 * supposed to be writable.
710 */
711 error = copyout(&msg, SCARG(uap, msg), sizeof(msg));
712 if (error)
713 return (error);
714 }
715 }
716
717 SCARG(&bsa, s) = SCARG(uap, s);
718 SCARG(&bsa, msg) = SCARG(uap, msg);
719 SCARG(&bsa, flags) = linux_to_bsd_msg_flags(SCARG(uap, flags));
720
721 if (SCARG(&bsa, flags) < 0) {
722 /* Some unsupported flag */
723 return (EINVAL);
724 }
725
726 if ((error = sys_recvmsg(l, &bsa, retval)))
727 goto done;
728
729 /* Fixup sockaddr */
730 error = copyin((caddr_t)SCARG(uap, msg), (caddr_t)&msg,
731 sizeof(msg));
732 if (error)
733 goto done;
734
735 if (msg.msg_name && msg.msg_namelen > 2) {
736 if ((error = linux_sa_put(msg.msg_name)))
737 goto done;
738 }
739
740 /* Fixup msg flags */
741 lflags = bsd_to_linux_msg_flags(msg.msg_flags);
742 if (lflags < 0) {
743 /* Some flag unsupported by Linux */
744 error = EINVAL;
745 goto done;
746 }
747 error = copyout(&lflags, (u_int8_t *) SCARG(uap, msg) +
748 offsetof(struct msghdr, msg_flags), sizeof(lflags));
749 if (error)
750 goto done;
751
752 /*
753 * Fixup cmsg. We handle two things:
754 * 1. different values for level/type on some archs
755 * 2. different alignment of CMSG_DATA on some archs
756 */
757 if (CMSG_FIRSTHDR(&msg)) {
758 struct cmsghdr cmsg, *cc;
759 int changed = 0;
760 size_t resid = ocontrollen;
761
762 cc = CMSG_FIRSTHDR(&msg);
763 do {
764 error = copyin(cc, &cmsg, sizeof(cmsg));
765 if (error)
766 goto done;
767
768 switch (cmsg.cmsg_level) {
769 case SOL_SOCKET:
770 if (SOL_SOCKET != LINUX_SOL_SOCKET) {
771 cmsg.cmsg_level = LINUX_SOL_SOCKET;
772 changed = 1;
773 }
774
775 switch (cmsg.cmsg_type) {
776 case SCM_RIGHTS:
777 /* Linux SCM_RIGHTS is same as NetBSD */
778 break;
779
780 default:
781 /* other types not supported */
782 error = EINVAL;
783 goto done;
784 }
785 default:
786 /* pray and leave intact */
787 break;
788 }
789
790 if (LINUX_CMSG_ALIGNDIFF) {
791 int i;
792 u_int8_t d, *sd, *td;
793
794 /*
795 * Sanity check.
796 */
797 if (cmsg.cmsg_len > resid
798 || cmsg.cmsg_len < sizeof(cmsg)) {
799 error = EINVAL;
800 goto done;
801 }
802
803 /*
804 * Need to copy the cmsg from scratch area
805 * to the original place, converting data
806 * alignment from NetBSD to Linux one.
807 */
808 error = copyout(&cmsg, ocontrol, sizeof(cmsg));
809 if (error)
810 goto done;
811 /* zero pad */
812 for(i=0; i < LINUX_CMSG_ALIGN(sizeof(cmsg)) - sizeof(cmsg); i++) {
813 copyout("",&ocontrol[sizeof(cmsg)+i],1);
814 }
815
816 sd = CMSG_DATA(cc);
817 td = LINUX_CMSG_DATA(ocontrol);
818
819 /* This is not particularily effective, but ..*/
820 d = '\0';
821 for(i=0; i < cmsg.cmsg_len - sizeof(cmsg); i++){
822 copyin(sd++, &d, 1);
823 copyout(&d, td++, 1);
824 }
825
826 resid -= (td - ocontrol);
827 ocontrol = td;
828 } else if (changed) {
829 /* Update cmsghdr in-place */
830 error = copyout(&cmsg, cc, sizeof(cmsg));
831 if (error)
832 goto done;
833 changed = 0;
834 }
835 } while((cc = CMSG_NXTHDR(&msg, cc)));
836 }
837
838 done:
839 return (error);
840 }
841
842 /*
843 * Convert socket option level from Linux to NetBSD value. Only SOL_SOCKET
844 * is different, the rest matches IPPROTO_* on both systems.
845 */
846 int
847 linux_to_bsd_sopt_level(llevel)
848 int llevel;
849 {
850
851 switch (llevel) {
852 case LINUX_SOL_SOCKET:
853 return SOL_SOCKET;
854 case LINUX_SOL_IP:
855 return IPPROTO_IP;
856 case LINUX_SOL_TCP:
857 return IPPROTO_TCP;
858 case LINUX_SOL_UDP:
859 return IPPROTO_UDP;
860 default:
861 return -1;
862 }
863 }
864
865 /*
866 * Convert Linux socket level socket option numbers to NetBSD values.
867 */
868 int
869 linux_to_bsd_so_sockopt(lopt)
870 int lopt;
871 {
872
873 switch (lopt) {
874 case LINUX_SO_DEBUG:
875 return SO_DEBUG;
876 case LINUX_SO_REUSEADDR:
877 /*
878 * Linux does not implement SO_REUSEPORT, but allows reuse of a
879 * host:port pair through SO_REUSEADDR even if the address is not a
880 * multicast-address. Effectively, this means that we should use
881 * SO_REUSEPORT to allow Linux applications to not exit with
882 * EADDRINUSE
883 */
884 return SO_REUSEPORT;
885 case LINUX_SO_TYPE:
886 return SO_TYPE;
887 case LINUX_SO_ERROR:
888 return SO_ERROR;
889 case LINUX_SO_DONTROUTE:
890 return SO_DONTROUTE;
891 case LINUX_SO_BROADCAST:
892 return SO_BROADCAST;
893 case LINUX_SO_SNDBUF:
894 return SO_SNDBUF;
895 case LINUX_SO_RCVBUF:
896 return SO_RCVBUF;
897 case LINUX_SO_KEEPALIVE:
898 return SO_KEEPALIVE;
899 case LINUX_SO_OOBINLINE:
900 return SO_OOBINLINE;
901 case LINUX_SO_LINGER:
902 return SO_LINGER;
903 case LINUX_SO_PRIORITY:
904 case LINUX_SO_NO_CHECK:
905 default:
906 return -1;
907 }
908 }
909
910 /*
911 * Convert Linux IP level socket option number to NetBSD values.
912 */
913 int
914 linux_to_bsd_ip_sockopt(lopt)
915 int lopt;
916 {
917
918 switch (lopt) {
919 case LINUX_IP_TOS:
920 return IP_TOS;
921 case LINUX_IP_TTL:
922 return IP_TTL;
923 case LINUX_IP_MULTICAST_TTL:
924 return IP_MULTICAST_TTL;
925 case LINUX_IP_MULTICAST_LOOP:
926 return IP_MULTICAST_LOOP;
927 case LINUX_IP_MULTICAST_IF:
928 return IP_MULTICAST_IF;
929 case LINUX_IP_ADD_MEMBERSHIP:
930 return IP_ADD_MEMBERSHIP;
931 case LINUX_IP_DROP_MEMBERSHIP:
932 return IP_DROP_MEMBERSHIP;
933 default:
934 return -1;
935 }
936 }
937
938 /*
939 * Convert Linux TCP level socket option number to NetBSD values.
940 */
941 int
942 linux_to_bsd_tcp_sockopt(lopt)
943 int lopt;
944 {
945
946 switch (lopt) {
947 case LINUX_TCP_NODELAY:
948 return TCP_NODELAY;
949 case LINUX_TCP_MAXSEG:
950 return TCP_MAXSEG;
951 default:
952 return -1;
953 }
954 }
955
956 /*
957 * Convert Linux UDP level socket option number to NetBSD values.
958 */
959 int
960 linux_to_bsd_udp_sockopt(lopt)
961 int lopt;
962 {
963
964 switch (lopt) {
965 default:
966 return -1;
967 }
968 }
969
970 /*
971 * Another reasonably straightforward function: setsockopt(2).
972 * The level and option numbers are converted; the values passed
973 * are not (yet) converted, the ones currently implemented don't
974 * need conversion, as they are the same on both systems.
975 */
976 int
977 linux_sys_setsockopt(l, v, retval)
978 struct lwp *l;
979 void *v;
980 register_t *retval;
981 {
982 struct linux_sys_setsockopt_args /* {
983 syscallarg(int) s;
984 syscallarg(int) level;
985 syscallarg(int) optname;
986 syscallarg(void *) optval;
987 syscallarg(int) optlen;
988 } */ *uap = v;
989 struct sys_setsockopt_args bsa;
990 int name;
991
992 SCARG(&bsa, s) = SCARG(uap, s);
993 SCARG(&bsa, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
994 SCARG(&bsa, val) = SCARG(uap, optval);
995 SCARG(&bsa, valsize) = SCARG(uap, optlen);
996
997 switch (SCARG(&bsa, level)) {
998 case SOL_SOCKET:
999 name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
1000 break;
1001 case IPPROTO_IP:
1002 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
1003 break;
1004 case IPPROTO_TCP:
1005 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
1006 break;
1007 case IPPROTO_UDP:
1008 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
1009 break;
1010 default:
1011 return EINVAL;
1012 }
1013
1014 if (name == -1)
1015 return EINVAL;
1016 SCARG(&bsa, name) = name;
1017
1018 return sys_setsockopt(l, &bsa, retval);
1019 }
1020
1021 /*
1022 * getsockopt(2) is very much the same as setsockopt(2) (see above)
1023 */
1024 int
1025 linux_sys_getsockopt(l, v, retval)
1026 struct lwp *l;
1027 void *v;
1028 register_t *retval;
1029 {
1030 struct linux_sys_getsockopt_args /* {
1031 syscallarg(int) s;
1032 syscallarg(int) level;
1033 syscallarg(int) optname;
1034 syscallarg(void *) optval;
1035 syscallarg(int *) optlen;
1036 } */ *uap = v;
1037 struct sys_getsockopt_args bga;
1038 int name;
1039
1040 SCARG(&bga, s) = SCARG(uap, s);
1041 SCARG(&bga, level) = linux_to_bsd_sopt_level(SCARG(uap, level));
1042 SCARG(&bga, val) = SCARG(uap, optval);
1043 SCARG(&bga, avalsize) = SCARG(uap, optlen);
1044
1045 switch (SCARG(&bga, level)) {
1046 case SOL_SOCKET:
1047 name = linux_to_bsd_so_sockopt(SCARG(uap, optname));
1048 break;
1049 case IPPROTO_IP:
1050 name = linux_to_bsd_ip_sockopt(SCARG(uap, optname));
1051 break;
1052 case IPPROTO_TCP:
1053 name = linux_to_bsd_tcp_sockopt(SCARG(uap, optname));
1054 break;
1055 case IPPROTO_UDP:
1056 name = linux_to_bsd_udp_sockopt(SCARG(uap, optname));
1057 break;
1058 default:
1059 return EINVAL;
1060 }
1061
1062 if (name == -1)
1063 return EINVAL;
1064 SCARG(&bga, name) = name;
1065
1066 return sys_getsockopt(l, &bga, retval);
1067 }
1068
1069 #define IF_NAME_LEN 16
1070
1071 int
1072 linux_getifhwaddr(p, retval, fd, data)
1073 struct proc *p;
1074 register_t *retval;
1075 u_int fd;
1076 void *data;
1077 {
1078 /* Not the full structure, just enough to map what we do here */
1079 struct linux_ifreq {
1080 char if_name[IF_NAME_LEN];
1081 struct osockaddr hwaddr;
1082 } lreq;
1083 struct filedesc *fdp;
1084 struct file *fp;
1085 struct ifaddr *ifa;
1086 struct ifnet *ifp;
1087 struct sockaddr_dl *sadl;
1088 int error, found;
1089 int index, ifnum;
1090
1091 /*
1092 * We can't emulate this ioctl by calling sys_ioctl() to run
1093 * SIOCGIFCONF, because the user buffer is not of the right
1094 * type to take those results. We can't use kernel buffers to
1095 * receive the results, as the implementation of sys_ioctl()
1096 * and ifconf() [which implements SIOCGIFCONF] use
1097 * copyin()/copyout() which will fail on kernel addresses.
1098 *
1099 * So, we must duplicate code from sys_ioctl() and ifconf(). Ugh.
1100 */
1101
1102 fdp = p->p_fd;
1103 if ((fp = fd_getfile(fdp, fd)) == NULL)
1104 return (EBADF);
1105
1106 FILE_USE(fp);
1107 if ((fp->f_flag & (FREAD | FWRITE)) == 0) {
1108 error = EBADF;
1109 goto out;
1110 }
1111
1112 error = copyin(data, (caddr_t)&lreq, sizeof(lreq));
1113 if (error)
1114 goto out;
1115 lreq.if_name[IF_NAME_LEN-1] = '\0'; /* just in case */
1116
1117 /*
1118 * Try real interface name first, then fake "ethX"
1119 */
1120 for (ifp = ifnet.tqh_first, found = 0;
1121 ifp != 0 && !found;
1122 ifp = ifp->if_list.tqe_next) {
1123 if (strcmp(lreq.if_name, ifp->if_xname))
1124 /* not this interface */
1125 continue;
1126 found=1;
1127 if ((ifa = ifp->if_addrlist.tqh_first) != 0) {
1128 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1129 sadl = (struct sockaddr_dl *)ifa->ifa_addr;
1130 /* only return ethernet addresses */
1131 /* XXX what about FDDI, etc. ? */
1132 if (sadl->sdl_family != AF_LINK ||
1133 sadl->sdl_type != IFT_ETHER)
1134 continue;
1135 memcpy((caddr_t)&lreq.hwaddr.sa_data,
1136 LLADDR(sadl),
1137 MIN(sadl->sdl_alen,
1138 sizeof(lreq.hwaddr.sa_data)));
1139 lreq.hwaddr.sa_family =
1140 sadl->sdl_family;
1141 error = copyout((caddr_t)&lreq, data,
1142 sizeof(lreq));
1143 goto out;
1144 }
1145 } else {
1146 error = ENODEV;
1147 goto out;
1148 }
1149 }
1150
1151 if (strncmp(lreq.if_name, "eth", 3) == 0) {
1152 for (ifnum = 0, index = 3;
1153 lreq.if_name[index] != '\0' && index < IF_NAME_LEN;
1154 index++) {
1155 ifnum *= 10;
1156 ifnum += lreq.if_name[index] - '';
1157 }
1158
1159 error = EINVAL; /* in case we don't find one */
1160 for (ifp = ifnet.tqh_first, found = 0;
1161 ifp != 0 && !found;
1162 ifp = ifp->if_list.tqe_next) {
1163 memcpy(lreq.if_name, ifp->if_xname,
1164 MIN(IF_NAME_LEN, IFNAMSIZ));
1165 if ((ifa = ifp->if_addrlist.tqh_first) == 0)
1166 /* no addresses on this interface */
1167 continue;
1168 else
1169 for (; ifa != 0; ifa = ifa->ifa_list.tqe_next) {
1170 sadl = (struct sockaddr_dl *)ifa->ifa_addr;
1171 /* only return ethernet addresses */
1172 /* XXX what about FDDI, etc. ? */
1173 if (sadl->sdl_family != AF_LINK ||
1174 sadl->sdl_type != IFT_ETHER)
1175 continue;
1176 if (ifnum--)
1177 /* not the reqested iface */
1178 continue;
1179 memcpy((caddr_t)&lreq.hwaddr.sa_data,
1180 LLADDR(sadl),
1181 MIN(sadl->sdl_alen,
1182 sizeof(lreq.hwaddr.sa_data)));
1183 lreq.hwaddr.sa_family =
1184 sadl->sdl_family;
1185 error = copyout((caddr_t)&lreq, data,
1186 sizeof(lreq));
1187 found = 1;
1188 break;
1189 }
1190 }
1191 } else {
1192 /* unknown interface, not even an "eth*" name */
1193 error = ENODEV;
1194 }
1195
1196 out:
1197 FILE_UNUSE(fp, p);
1198 return error;
1199 }
1200 #undef IF_NAME_LEN
1201
1202 int
1203 linux_ioctl_socket(p, uap, retval)
1204 struct proc *p;
1205 struct linux_sys_ioctl_args /* {
1206 syscallarg(int) fd;
1207 syscallarg(u_long) com;
1208 syscallarg(caddr_t) data;
1209 } */ *uap;
1210 register_t *retval;
1211 {
1212 u_long com;
1213 int error = 0, isdev = 0, dosys = 1;
1214 struct sys_ioctl_args ia;
1215 struct file *fp;
1216 struct filedesc *fdp;
1217 struct vnode *vp;
1218 int (*ioctlf)(struct file *, u_long, void *, struct proc *);
1219 struct ioctl_pt pt;
1220
1221 fdp = p->p_fd;
1222 if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1223 return (EBADF);
1224
1225 FILE_USE(fp);
1226
1227 if (fp->f_type == DTYPE_VNODE) {
1228 vp = (struct vnode *)fp->f_data;
1229 isdev = vp->v_type == VCHR;
1230 }
1231
1232 /*
1233 * Don't try to interpret socket ioctl calls that are done
1234 * on a device filedescriptor, just pass them through, to
1235 * emulate Linux behaviour. Use PTIOCLINUX so that the
1236 * device will only handle these if it's prepared to do
1237 * so, to avoid unexpected things from happening.
1238 */
1239 if (isdev) {
1240 dosys = 0;
1241 ioctlf = fp->f_ops->fo_ioctl;
1242 pt.com = SCARG(uap, com);
1243 pt.data = SCARG(uap, data);
1244 error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
1245 /*
1246 * XXX hack: if the function returns EJUSTRETURN,
1247 * it has stuffed a sysctl return value in pt.data.
1248 */
1249 if (error == EJUSTRETURN) {
1250 retval[0] = (register_t)pt.data;
1251 error = 0;
1252 }
1253 goto out;
1254 }
1255
1256 com = SCARG(uap, com);
1257 retval[0] = 0;
1258
1259 switch (com) {
1260 case LINUX_SIOCGIFCONF:
1261 SCARG(&ia, com) = OSIOCGIFCONF;
1262 break;
1263 case LINUX_SIOCGIFFLAGS:
1264 SCARG(&ia, com) = SIOCGIFFLAGS;
1265 break;
1266 case LINUX_SIOCSIFFLAGS:
1267 SCARG(&ia, com) = SIOCSIFFLAGS;
1268 break;
1269 case LINUX_SIOCGIFADDR:
1270 SCARG(&ia, com) = OSIOCGIFADDR;
1271 break;
1272 case LINUX_SIOCGIFDSTADDR:
1273 SCARG(&ia, com) = OSIOCGIFDSTADDR;
1274 break;
1275 case LINUX_SIOCGIFBRDADDR:
1276 SCARG(&ia, com) = OSIOCGIFBRDADDR;
1277 break;
1278 case LINUX_SIOCGIFNETMASK:
1279 SCARG(&ia, com) = OSIOCGIFNETMASK;
1280 break;
1281 case LINUX_SIOCADDMULTI:
1282 SCARG(&ia, com) = SIOCADDMULTI;
1283 break;
1284 case LINUX_SIOCDELMULTI:
1285 SCARG(&ia, com) = SIOCDELMULTI;
1286 break;
1287 case LINUX_SIOCGIFHWADDR:
1288 error = linux_getifhwaddr(p, retval, SCARG(uap, fd),
1289 SCARG(uap, data));
1290 dosys = 0;
1291 break;
1292 default:
1293 error = EINVAL;
1294 }
1295
1296 out:
1297 FILE_UNUSE(fp, p);
1298
1299 if (error ==0 && dosys) {
1300 SCARG(&ia, fd) = SCARG(uap, fd);
1301 SCARG(&ia, data) = SCARG(uap, data);
1302 /* XXX NJWLWP */
1303 error = sys_ioctl(curlwp, &ia, retval);
1304 }
1305
1306 return error;
1307 }
1308
1309 int
1310 linux_sys_connect(l, v, retval)
1311 struct lwp *l;
1312 void *v;
1313 register_t *retval;
1314 {
1315 struct linux_sys_connect_args /* {
1316 syscallarg(int) s;
1317 syscallarg(const struct sockaddr *) name;
1318 syscallarg(int) namelen;
1319 } */ *uap = v;
1320 struct proc *p = l->l_proc;
1321 int error;
1322 struct sockaddr *sa;
1323 struct sys_connect_args bca;
1324 caddr_t sg = stackgap_init(p, 0);
1325 int namlen;
1326
1327 namlen = SCARG(uap, namelen);
1328 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
1329 SCARG(uap, name), &namlen);
1330 if (error)
1331 return (error);
1332
1333 SCARG(&bca, s) = SCARG(uap, s);
1334 SCARG(&bca, name) = sa;
1335 SCARG(&bca, namelen) = (unsigned int) namlen;
1336
1337 error = sys_connect(l, &bca, retval);
1338
1339 if (error == EISCONN) {
1340 struct file *fp;
1341 struct socket *so;
1342 int s, state, prflags;
1343
1344 /* getsock() will use the descriptor for us */
1345 if (getsock(p->p_fd, SCARG(uap, s), &fp) != 0)
1346 return EISCONN;
1347
1348 s = splsoftnet();
1349 so = (struct socket *)fp->f_data;
1350 state = so->so_state;
1351 prflags = so->so_proto->pr_flags;
1352 splx(s);
1353 FILE_UNUSE(fp, p);
1354 /*
1355 * We should only let this call succeed once per
1356 * non-blocking connect; however we don't have
1357 * a convenient place to keep that state..
1358 */
1359 if ((state & SS_NBIO) && (state & SS_ISCONNECTED) &&
1360 (prflags & PR_CONNREQUIRED))
1361 return 0;
1362 }
1363
1364 return (error);
1365 }
1366
1367 int
1368 linux_sys_bind(l, v, retval)
1369 struct lwp *l;
1370 void *v;
1371 register_t *retval;
1372 {
1373 struct linux_sys_bind_args /* {
1374 syscallarg(int) s;
1375 syscallarg(const struct osockaddr *) name;
1376 syscallarg(int) namelen;
1377 } */ *uap = v;
1378 struct proc *p = l->l_proc;
1379 int error, namlen;
1380 struct sys_bind_args bsa;
1381
1382 namlen = SCARG(uap, namelen);
1383 SCARG(&bsa, s) = SCARG(uap, s);
1384 if (SCARG(uap, name)) {
1385 struct sockaddr *sa;
1386 caddr_t sg = stackgap_init(p, 0);
1387
1388 error = linux_sa_get(p, SCARG(uap, s), &sg, &sa,
1389 SCARG(uap, name), &namlen);
1390 if (error)
1391 return (error);
1392
1393 SCARG(&bsa, name) = sa;
1394 } else
1395 SCARG(&bsa, name) = NULL;
1396 SCARG(&bsa, namelen) = namlen;
1397
1398 return (sys_bind(l, &bsa, retval));
1399 }
1400
1401 int
1402 linux_sys_getsockname(l, v, retval)
1403 struct lwp *l;
1404 void *v;
1405 register_t *retval;
1406 {
1407 struct linux_sys_getsockname_args /* {
1408 syscallarg(int) fdes;
1409 syscallarg(caddr_t) asa;
1410 syscallarg(int *) alen;
1411 } */ *uap = v;
1412 int error;
1413
1414 if ((error = sys_getsockname(l, uap, retval)) != 0)
1415 return (error);
1416
1417 if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
1418 return (error);
1419
1420 return (0);
1421 }
1422
1423 int
1424 linux_sys_getpeername(l, v, retval)
1425 struct lwp *l;
1426 void *v;
1427 register_t *retval;
1428 {
1429 struct sys_getpeername_args /* {
1430 syscallarg(int) fdes;
1431 syscallarg(caddr_t) asa;
1432 syscallarg(int *) alen;
1433 } */ *uap = v;
1434 int error;
1435
1436 if ((error = sys_getpeername(l, uap, retval)) != 0)
1437 return (error);
1438
1439 if ((error = linux_sa_put((struct osockaddr *)SCARG(uap, asa))))
1440 return (error);
1441
1442 return (0);
1443 }
1444
1445 /*
1446 * Copy the osockaddr structure pointed to by osa to kernel, adjust
1447 * family and convert to sockaddr, allocate stackgap and put the
1448 * the converted structure there, address on stackgap returned in sap.
1449 */
1450 static int
1451 linux_sa_get(p, s, sgp, sap, osa, osalen)
1452 struct proc *p;
1453 int s;
1454 caddr_t *sgp;
1455 struct sockaddr **sap;
1456 const struct osockaddr *osa;
1457 int *osalen;
1458 {
1459 int error=0, bdom;
1460 struct sockaddr *sa, *usa;
1461 struct osockaddr *kosa = (struct osockaddr *) &sa;
1462 int alloclen;
1463 #ifdef INET6
1464 int oldv6size;
1465 struct sockaddr_in6 *sin6;
1466 #endif
1467
1468 if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
1469 DPRINTF(("bad osa=%p osalen=%d\n", osa, *osalen));
1470 return (EINVAL);
1471 }
1472
1473 alloclen = *osalen;
1474 #ifdef INET6
1475 oldv6size = 0;
1476 /*
1477 * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
1478 * if it's a v4-mapped address, so reserve the proper space
1479 * for it.
1480 */
1481 if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
1482 alloclen = sizeof (struct sockaddr_in6);
1483 oldv6size = 1;
1484 }
1485 #endif
1486
1487 kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
1488
1489 if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
1490 DPRINTF(("error copying osa %d\n", error));
1491 goto out;
1492 }
1493
1494 bdom = linux_to_bsd_domain(kosa->sa_family);
1495 if (bdom == -1) {
1496 DPRINTF(("bad linux family=%d\n", kosa->sa_family));
1497 error = EINVAL;
1498 goto out;
1499 }
1500
1501 #ifdef INET6
1502 /*
1503 * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
1504 * which lacks the scope id compared with RFC2553 one. If we detect
1505 * the situation, reject the address and write a message to system log.
1506 *
1507 * Still accept addresses for which the scope id is not used.
1508 */
1509 if (oldv6size && bdom == AF_INET6) {
1510 sin6 = (struct sockaddr_in6 *)kosa;
1511 if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
1512 (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
1513 !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
1514 !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
1515 !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
1516 !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
1517 sin6->sin6_scope_id = 0;
1518 } else {
1519 struct proc *p = curproc; /* XXX */
1520 int uid = p->p_cred && p->p_ucred ?
1521 p->p_ucred->cr_uid : -1;
1522
1523 log(LOG_DEBUG,
1524 "pid %d (%s), uid %d: obsolete pre-RFC2553 "
1525 "sockaddr_in6 rejected",
1526 p->p_pid, p->p_comm, uid);
1527 error = EINVAL;
1528 goto out;
1529 }
1530 }
1531 #endif
1532
1533 /*
1534 * If the family is unspecified, use address family of the
1535 * socket. This avoid triggering COMPAT_43 struct socket family check
1536 * in sockargs() on little-endian machines, and strict family checks
1537 * in netinet/in_pcb.c et.al.
1538 */
1539 if (bdom == AF_UNSPEC) {
1540 struct file *fp;
1541 struct socket *so;
1542
1543 /* getsock() will use the descriptor for us */
1544 if ((error = getsock(p->p_fd, s, &fp)) != 0)
1545 goto out;
1546
1547 so = (struct socket *)fp->f_data;
1548 bdom = so->so_proto->pr_domain->dom_family;
1549
1550 FILE_UNUSE(fp, p);
1551
1552 DPRINTF(("AF_UNSPEC family adjusted to %d\n", bdom));
1553 }
1554
1555 if (bdom == AF_INET) {
1556 alloclen = sizeof(struct sockaddr_in);
1557 }
1558
1559 sa = (struct sockaddr *) kosa;
1560 sa->sa_family = bdom;
1561 sa->sa_len = alloclen;
1562 #ifdef DEBUG_LINUX
1563 DPRINTF(("family %d, len = %d [ ", sa->sa_family, sa->sa_len));
1564 for (bdom = 0; bdom < sizeof(sa->sa_data); bdom++)
1565 DPRINTF(("%02x ", sa->sa_data[bdom]));
1566 DPRINTF(("\n"));
1567 #endif
1568
1569 usa = (struct sockaddr *) stackgap_alloc(p, sgp, alloclen);
1570 if (!usa) {
1571 error = ENOMEM;
1572 goto out;
1573 }
1574
1575 if ((error = copyout(sa, usa, alloclen))) {
1576 DPRINTF(("error copying out socket %d\n", error));
1577 goto out;
1578 }
1579
1580 *sap = usa;
1581
1582 out:
1583 *osalen = alloclen;
1584 free(kosa, M_TEMP);
1585 return (error);
1586 }
1587
1588 static int
1589 linux_sa_put(osa)
1590 struct osockaddr *osa;
1591 {
1592 struct sockaddr sa;
1593 struct osockaddr *kosa;
1594 int error, bdom, len;
1595
1596 /*
1597 * Only read/write the sockaddr family and length part, the rest is
1598 * not changed.
1599 */
1600 len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
1601
1602 error = copyin((caddr_t) osa, (caddr_t) &sa, len);
1603 if (error)
1604 return (error);
1605
1606 bdom = bsd_to_linux_domain(sa.sa_family);
1607 if (bdom == -1)
1608 return (EINVAL);
1609
1610 /* Note: we convert from sockaddr to osockaddr here, too */
1611 kosa = (struct osockaddr *) &sa;
1612 kosa->sa_family = bdom;
1613 error = copyout(kosa, osa, len);
1614 if (error)
1615 return (error);
1616
1617 return (0);
1618 }
1619
1620 int
1621 linux_sys_recv(l, v, retval)
1622 struct lwp *l;
1623 void *v;
1624 register_t *retval;
1625 {
1626 struct linux_sys_recv_args /* {
1627 syscallarg(int) s;
1628 syscallarg(void *) buf;
1629 syscallarg(int) len;
1630 syscallarg(int) flags;
1631 } */ *uap = v;
1632 struct sys_recvfrom_args bra;
1633
1634
1635 SCARG(&bra, s) = SCARG(uap, s);
1636 SCARG(&bra, buf) = SCARG(uap, buf);
1637 SCARG(&bra, len) = (size_t) SCARG(uap, len);
1638 SCARG(&bra, flags) = SCARG(uap, flags);
1639 SCARG(&bra, from) = NULL;
1640 SCARG(&bra, fromlenaddr) = NULL;
1641
1642 return (sys_recvfrom(l, &bra, retval));
1643 }
1644
1645 int
1646 linux_sys_send(l, v, retval)
1647 struct lwp *l;
1648 void *v;
1649 register_t *retval;
1650 {
1651 struct linux_sys_send_args /* {
1652 syscallarg(int) s;
1653 syscallarg(caddr_t) buf;
1654 syscallarg(int) len;
1655 syscallarg(int) flags;
1656 } */ *uap = v;
1657 struct sys_sendto_args bsa;
1658
1659 SCARG(&bsa, s) = SCARG(uap, s);
1660 SCARG(&bsa, buf) = SCARG(uap, buf);
1661 SCARG(&bsa, len) = SCARG(uap, len);
1662 SCARG(&bsa, flags) = SCARG(uap, flags);
1663 SCARG(&bsa, to) = NULL;
1664 SCARG(&bsa, tolen) = 0;
1665
1666 return (sys_sendto(l, &bsa, retval));
1667 }
1668
1669 int
1670 linux_sys_accept(l, v, retval)
1671 struct lwp *l;
1672 void *v;
1673 register_t *retval;
1674 {
1675 struct linux_sys_accept_args /* {
1676 syscallarg(int) s;
1677 syscallarg(struct osockaddr *) name;
1678 syscallarg(int *) anamelen;
1679 } */ *uap = v;
1680 int error;
1681 struct sys_accept_args baa;
1682
1683 SCARG(&baa, s) = SCARG(uap, s);
1684 SCARG(&baa, name) = (struct sockaddr *) SCARG(uap, name);
1685 SCARG(&baa, anamelen) = (unsigned int *) SCARG(uap, anamelen);
1686
1687 if ((error = sys_accept(l, &baa, retval)))
1688 return (error);
1689
1690 if (SCARG(uap, name) && (error = linux_sa_put(SCARG(uap, name))))
1691 return (error);
1692
1693 return (0);
1694 }
Cache object: 2e3edbe087601e3cd55f92a4df680d88
|