Annotation of sys/compat/linux/linux_socket.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: linux_socket.c,v 1.36 2007/06/06 09:59:21 henning Exp $ */
2: /* $NetBSD: linux_socket.c,v 1.14 1996/04/05 00:01:50 christos Exp $ */
3:
4: /*
5: * Copyright (c) 1995 Frank van der Linden
6: * All rights reserved.
7: *
8: * Redistribution and use in source and binary forms, with or without
9: * modification, are permitted provided that the following conditions
10: * are met:
11: * 1. Redistributions of source code must retain the above copyright
12: * notice, this list of conditions and the following disclaimer.
13: * 2. Redistributions in binary form must reproduce the above copyright
14: * notice, this list of conditions and the following disclaimer in the
15: * documentation and/or other materials provided with the distribution.
16: * 3. All advertising materials mentioning features or use of this software
17: * must display the following acknowledgement:
18: * This product includes software developed for the NetBSD Project
19: * by Frank van der Linden
20: * 4. The name of the author may not be used to endorse or promote products
21: * derived from this software without specific prior written permission
22: *
23: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
24: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
25: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
26: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
27: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
28: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
32: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33: */
34:
35: #include <sys/param.h>
36: #include <sys/kernel.h>
37: #include <sys/systm.h>
38: #include <sys/buf.h>
39: #include <sys/malloc.h>
40: #include <sys/ioctl.h>
41: #include <sys/tty.h>
42: #include <sys/file.h>
43: #include <sys/filedesc.h>
44: #include <sys/selinfo.h>
45: #include <sys/socket.h>
46: #include <sys/socketvar.h>
47: #include <net/if.h>
48: #include <net/if_types.h>
49: #include <net/if_dl.h>
50: #include <netinet/in.h>
51: #include <netinet/in_systm.h>
52: #include <netinet/ip.h>
53: #include <netinet/tcp.h>
54: #include <sys/mount.h>
55: #include <sys/proc.h>
56: #include <sys/vnode.h>
57: #include <sys/device.h>
58:
59: #include <sys/syscallargs.h>
60:
61: #include <compat/linux/linux_types.h>
62: #include <compat/linux/linux_util.h>
63: #include <compat/linux/linux_signal.h>
64: #include <compat/linux/linux_syscallargs.h>
65: #include <compat/linux/linux_ioctl.h>
66: #include <compat/linux/linux_socket.h>
67: #include <compat/linux/linux_socketcall.h>
68: #include <compat/linux/linux_sockio.h>
69:
70: /*
71: * All the calls in this file are entered via one common system
72: * call in Linux, represented here by linux_socketcall()
73: * Arguments for the various calls are on the user stack. A pointer
74: * to them is the only thing that is passed. It is up to the various
75: * calls to copy them in themselves. To make it look better, they
76: * are copied to structures.
77: */
78:
79: static int linux_to_bsd_domain (int);
80: static int bsd_to_linux_domain(int);
81:
82: int linux_socket(struct proc *, void *, register_t *);
83: int linux_bind(struct proc *, void *, register_t *);
84: int linux_connect(struct proc *, void *, register_t *);
85: int linux_listen(struct proc *, void *, register_t *);
86: int linux_accept(struct proc *, void *, register_t *);
87: int linux_getsockname(struct proc *, void *, register_t *);
88: int linux_getpeername(struct proc *, void *, register_t *);
89: int linux_socketpair(struct proc *, void *, register_t *);
90: int linux_send(struct proc *, void *, register_t *);
91: int linux_recv(struct proc *, void *, register_t *);
92: int linux_sendto(struct proc *, void *, register_t *);
93: int linux_recvfrom(struct proc *, void *, register_t *);
94: int linux_shutdown(struct proc *, void *, register_t *);
95: int linux_to_bsd_sopt_level(int);
96: int linux_to_bsd_so_sockopt(int);
97: int linux_to_bsd_ip_sockopt(int);
98: int linux_to_bsd_tcp_sockopt(int);
99: int linux_to_bsd_udp_sockopt(int);
100: int linux_setsockopt(struct proc *, void *, register_t *);
101: int linux_getsockopt(struct proc *, void *, register_t *);
102: int linux_recvmsg(struct proc *, void *, register_t *);
103: int linux_sendmsg(struct proc *, void *, register_t *);
104:
105: int linux_check_hdrincl(struct proc *, int, register_t *, caddr_t *);
106: int linux_sendto_hdrincl(struct proc *, struct sys_sendto_args *,
107: register_t *, caddr_t *);
108:
109: int linux_sa_get(struct proc *, caddr_t *, struct sockaddr **,
110: const struct osockaddr *, int *);
111: int linux_sa_put(struct osockaddr *);
112:
113: static const int linux_to_bsd_domain_[LINUX_AF_MAX] = {
114: AF_UNSPEC,
115: AF_UNIX,
116: AF_INET,
117: -1, /* LINUX_AF_AX25 */
118: -1, /* IPX */
119: AF_APPLETALK,
120: -1, /* LINUX_AF_NETROM */
121: -1, /* LINUX_AF_BRIDGE */
122: -1, /* LINUX_AF_ATMPVC */
123: -1, /* LINUX_AF_X25 */
124: AF_INET6,
125: -1, /* LINUX_AF_ROSE */
126: AF_DECnet,
127: -1, /* LINUX_AF_NETBEUI */
128: -1, /* LINUX_AF_SECURITY */
129: -1, /* pseudo_AF_KEY */
130: AF_ROUTE, /* LINUX_AF_NETLINK */
131: -1, /* LINUX_AF_PACKET */
132: -1, /* LINUX_AF_ASH */
133: -1, /* LINUX_AF_ECONET */
134: -1, /* LINUX_AF_ATMSVC */
135: AF_SNA,
136: /* rest up to LINUX_AF_MAX-1 is not allocated */
137: -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
138: };
139:
140: static const int bsd_to_linux_domain_[AF_MAX] = {
141: LINUX_AF_UNSPEC,
142: LINUX_AF_UNIX,
143: LINUX_AF_INET,
144: -1, /* AF_IMPLINK */
145: -1, /* AF_PUP */
146: -1, /* AF_CHAOS */
147: -1, /* AF_NS */
148: -1, /* AF_ISO */
149: -1, /* AF_ECMA */
150: -1, /* AF_DATAKIT */
151: -1, /* AF_CCITT */
152: -1, /* LINUX_AF_SNA */
153: -1, /* LINUX_AF_DECnet */
154: -1, /* AF_DLI */
155: -1, /* AF_LAT */
156: -1, /* AF_HYLINK */
157: LINUX_AF_APPLETALK,
158: -1, /* LINUX_AF_NETLINK */
159: -1, /* AF_LINK */
160: -1, /* AF_XTP */
161: -1, /* AF_COIP */
162: -1, /* AF_CNT */
163: -1, /* pseudo_AF_RTIP */
164: LINUX_AF_IPX,
165: LINUX_AF_INET6,
166: -1, /* pseudo_AF_PIP */
167: -1, /* AF_ISDN */
168: -1, /* AF_NATM */
169: -1, /* AF_ARP */
170: -1, /* LINUX_pseudo_AF_KEY */
171: -1, /* pseudo_AF_HDRCMPLT */
172: };
173:
174: /*
175: * Convert between Linux and BSD socket domain values
176: */
177: static int
178: linux_to_bsd_domain(ldom)
179: int ldom;
180: {
181: if (ldom < 0 || ldom >= LINUX_AF_MAX)
182: return (-1);
183:
184: return linux_to_bsd_domain_[ldom];
185: }
186:
187: /*
188: * Convert between BSD and Linux socket domain values
189: */
190: static int
191: bsd_to_linux_domain(bdom)
192: int bdom;
193: {
194: if (bdom < 0 || bdom >= AF_MAX)
195: return (-1);
196:
197: return bsd_to_linux_domain_[bdom];
198: }
199:
200: int
201: linux_socket(p, v, retval)
202: struct proc *p;
203: void *v;
204: register_t *retval;
205: {
206: struct linux_socket_args /* {
207: syscallarg(int) domain;
208: syscallarg(int) type;
209: syscallarg(int) protocol;
210: } */ *uap = v;
211: struct linux_socket_args lsa;
212: struct sys_socket_args bsa;
213: int error;
214:
215: if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
216: return error;
217:
218: SCARG(&bsa, protocol) = lsa.protocol;
219: SCARG(&bsa, type) = lsa.type;
220: SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
221: if (SCARG(&bsa, domain) == -1)
222: return EINVAL;
223: return sys_socket(p, &bsa, retval);
224: }
225:
226: int
227: linux_bind(p, v, retval)
228: struct proc *p;
229: void *v;
230: register_t *retval;
231: {
232: struct linux_bind_args /* {
233: syscallarg(int) s;
234: syscallarg(struct sockaddr *) name;
235: syscallarg(int) namelen;
236: } */ *uap = v;
237: struct linux_bind_args lba;
238: struct sys_bind_args bba;
239: int error;
240: int namlen;
241:
242: if ((error = copyin((caddr_t) uap, (caddr_t) &lba, sizeof lba)))
243: return error;
244:
245: SCARG(&bba, s) = lba.s;
246: namlen = lba.namelen;
247: if (lba.name) {
248: struct sockaddr *sa;
249: caddr_t sg = stackgap_init(p->p_emul);
250:
251: error = linux_sa_get(p, &sg, &sa, lba.name, &namlen);
252: if (error)
253: return (error);
254: SCARG(&bba, name) = sa;
255: } else
256: SCARG(&bba, name) = NULL;
257: SCARG(&bba, namelen) = namlen;
258:
259: return sys_bind(p, &bba, retval);
260: }
261:
262: int
263: linux_connect(p, v, retval)
264: struct proc *p;
265: void *v;
266: register_t *retval;
267: {
268: struct linux_connect_args /* {
269: syscallarg(int) s;
270: syscallarg(struct osockaddr *) name;
271: syscallarg(int) namelen;
272: } */ *uap = v;
273: struct linux_connect_args lca;
274: struct sys_connect_args bca;
275: struct sockaddr *sa;
276: caddr_t sg = stackgap_init(p->p_emul);
277: int namlen;
278: int error;
279:
280: if ((error = copyin((caddr_t) uap, (caddr_t) &lca, sizeof lca)))
281: return error;
282:
283: namlen = lca.namelen;
284: error = linux_sa_get(p, &sg, &sa, lca.name, &namlen);
285: if (error)
286: return (error);
287:
288: SCARG(&bca, s) = lca.s;
289: SCARG(&bca, name) = sa;
290: SCARG(&bca, namelen) = (unsigned int)namlen;
291:
292: error = sys_connect(p, &bca, retval);
293:
294: if (error == EISCONN) {
295: struct sys_getsockopt_args bga;
296: #if 0
297: struct sys_fcntl_args fca;
298: #endif
299: void *status, *statusl;
300: int stat, statl = sizeof stat;
301:
302: #if 0
303: SCARG(&fca, fd) = lca.s;
304: SCARG(&fca, cmd) = F_GETFL;
305: SCARG(&fca, arg) = 0;
306: if (sys_fcntl(p, &fca, retval) == -1 ||
307: (*retval & O_NONBLOCK) == 0)
308: return error;
309: #endif
310:
311: status = stackgap_alloc(&sg, sizeof stat);
312: statusl = stackgap_alloc(&sg, sizeof statusl);
313:
314: if ((error = copyout(&statl, statusl, sizeof statl)))
315: return error;
316:
317: SCARG(&bga, s) = lca.s;
318: SCARG(&bga, level) = SOL_SOCKET;
319: SCARG(&bga, name) = SO_ERROR;
320: SCARG(&bga, val) = status;
321: SCARG(&bga, avalsize) = statusl;
322:
323: error = sys_getsockopt(p, &bga, retval);
324: if (error)
325: return error;
326: if ((error = copyin(status, &stat, sizeof stat)))
327: return error;
328: return stat;
329: }
330: return error;
331: }
332:
333: int
334: linux_listen(p, v, retval)
335: struct proc *p;
336: void *v;
337: register_t *retval;
338: {
339: struct linux_listen_args /* {
340: syscallarg(int) s;
341: syscallarg(int) backlog;
342: } */ *uap = v;
343: struct linux_listen_args lla;
344: struct sys_listen_args bla;
345: int error;
346:
347: if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
348: return error;
349:
350: SCARG(&bla, s) = lla.s;
351: SCARG(&bla, backlog) = lla.backlog;
352:
353: return sys_listen(p, &bla, retval);
354: }
355:
356: int
357: linux_accept(p, v, retval)
358: struct proc *p;
359: void *v;
360: register_t *retval;
361: {
362: struct linux_accept_args /* {
363: syscallarg(int) s;
364: syscallarg(struct sockaddr *) addr;
365: syscallarg(int *) namelen;
366: } */ *uap = v;
367: struct linux_accept_args laa;
368: struct compat_43_sys_accept_args baa;
369: struct sys_fcntl_args fca;
370: int error;
371:
372: if ((error = copyin((caddr_t) uap, (caddr_t) &laa, sizeof laa)))
373: return error;
374:
375: SCARG(&baa, s) = laa.s;
376: SCARG(&baa, name) = (caddr_t) laa.addr;
377: SCARG(&baa, anamelen) = laa.namelen;
378:
379: error = compat_43_sys_accept(p, &baa, retval);
380: if (error)
381: return (error);
382:
383: /*
384: * linux appears not to copy flags from the parent socket to the
385: * accepted one, so we must clear the flags in the new descriptor.
386: * Ignore any errors, because we already have an open fd.
387: */
388: SCARG(&fca, fd) = *retval;
389: SCARG(&fca, cmd) = F_SETFL;
390: SCARG(&fca, arg) = 0;
391: (void)sys_fcntl(p, &fca, retval);
392: *retval = SCARG(&fca, fd);
393: return (0);
394: }
395:
396: int
397: linux_getsockname(p, v, retval)
398: struct proc *p;
399: void *v;
400: register_t *retval;
401: {
402: struct linux_getsockname_args /* {
403: syscallarg(int) s;
404: syscallarg(caddr_t) addr;
405: syscallarg(int *) namelen;
406: } */ *uap = v;
407: struct linux_getsockname_args lga;
408: struct sys_getsockname_args bga;
409: int error;
410:
411: if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
412: return error;
413:
414: SCARG(&bga, fdes) = lga.s;
415: SCARG(&bga, asa) = (struct sockaddr *) lga.addr;
416: SCARG(&bga, alen) = lga.namelen;
417:
418: error = sys_getsockname(p, &bga, retval);
419: if (error)
420: return (error);
421:
422: if ((error = linux_sa_put((struct osockaddr *)lga.addr)))
423: return (error);
424:
425: return (0);
426: }
427:
428: int
429: linux_getpeername(p, v, retval)
430: struct proc *p;
431: void *v;
432: register_t *retval;
433: {
434: struct linux_getpeername_args /* {
435: syscallarg(int) s;
436: syscallarg(struct sockaddr *) addr;
437: syscallarg(int *) namelen;
438: } */ *uap = v;
439: struct linux_getpeername_args lga;
440: struct sys_getpeername_args bga;
441: int error;
442:
443: if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
444: return error;
445:
446: SCARG(&bga, fdes) = lga.s;
447: SCARG(&bga, asa) = (struct sockaddr *) lga.addr;
448: SCARG(&bga, alen) = lga.namelen;
449:
450: error = sys_getpeername(p, &bga, retval);
451: if (error)
452: return (error);
453:
454: if ((error = linux_sa_put((struct osockaddr *)lga.addr)))
455: return (error);
456:
457: return (0);
458: }
459:
460: int
461: linux_socketpair(p, v, retval)
462: struct proc *p;
463: void *v;
464: register_t *retval;
465: {
466: struct linux_socketpair_args /* {
467: syscallarg(int) domain;
468: syscallarg(int) type;
469: syscallarg(int) protocol;
470: syscallarg(int *) rsv;
471: } */ *uap = v;
472: struct linux_socketpair_args lsa;
473: struct sys_socketpair_args bsa;
474: int error;
475:
476: if ((error = copyin((caddr_t) uap, &lsa, sizeof lsa)))
477: return error;
478:
479: SCARG(&bsa, domain) = linux_to_bsd_domain(lsa.domain);
480: if (SCARG(&bsa, domain) == -1)
481: return EINVAL;
482: SCARG(&bsa, type) = lsa.type;
483: SCARG(&bsa, protocol) = lsa.protocol;
484: SCARG(&bsa, rsv) = lsa.rsv;
485:
486: return sys_socketpair(p, &bsa, retval);
487: }
488:
489: int
490: linux_send(p, v, retval)
491: struct proc *p;
492: void *v;
493: register_t *retval;
494: {
495: struct linux_send_args /* {
496: syscallarg(int) s;
497: syscallarg(void *) msg;
498: syscallarg(int) len;
499: syscallarg(int) flags;
500: } */ *uap = v;
501: struct linux_send_args lsa;
502: struct compat_43_sys_send_args bsa;
503: int error;
504:
505: if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
506: return error;
507:
508: SCARG(&bsa, s) = lsa.s;
509: SCARG(&bsa, buf) = lsa.msg;
510: SCARG(&bsa, len) = lsa.len;
511: SCARG(&bsa, flags) = lsa.flags;
512:
513: return compat_43_sys_send(p, &bsa, retval);
514: }
515:
516: int
517: linux_recv(p, v, retval)
518: struct proc *p;
519: void *v;
520: register_t *retval;
521: {
522: struct linux_recv_args /* {
523: syscallarg(int) s;
524: syscallarg(void *) msg;
525: syscallarg(int) len;
526: syscallarg(int) flags;
527: } */ *uap = v;
528: struct linux_recv_args lra;
529: struct compat_43_sys_recv_args bra;
530: int error;
531:
532: if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
533: return error;
534:
535: SCARG(&bra, s) = lra.s;
536: SCARG(&bra, buf) = lra.msg;
537: SCARG(&bra, len) = lra.len;
538: SCARG(&bra, flags) = lra.flags;
539:
540: return compat_43_sys_recv(p, &bra, retval);
541: }
542:
543: int
544: linux_check_hdrincl(p, fd, retval, sgp)
545: struct proc *p;
546: int fd;
547: register_t *retval;
548: caddr_t *sgp;
549: {
550: struct sys_getsockopt_args /* {
551: int s;
552: int level;
553: int name;
554: caddr_t val;
555: int *avalsize;
556: } */ gsa;
557: int error;
558: caddr_t val;
559: int *valsize;
560: int size_val = sizeof val;
561: int optval;
562:
563: val = stackgap_alloc(sgp, sizeof(optval));
564: valsize = stackgap_alloc(sgp, sizeof(size_val));
565:
566: if ((error = copyout(&size_val, valsize, sizeof(size_val))))
567: return (error);
568: SCARG(&gsa, s) = fd;
569: SCARG(&gsa, level) = IPPROTO_IP;
570: SCARG(&gsa, name) = IP_HDRINCL;
571: SCARG(&gsa, val) = val;
572: SCARG(&gsa, avalsize) = valsize;
573:
574: if ((error = sys_getsockopt(p, &gsa, retval)))
575: return (error);
576: if ((error = copyin(val, &optval, sizeof(optval))))
577: return (error);
578: return (optval == 0);
579: }
580:
581: /*
582: * linux_ip_copysize defines how many bytes we should copy
583: * from the beginning of the IP packet before we customize it for BSD.
584: * It should include all the fields we modify (ip_len and ip_off)
585: * and be as small as possible to minimize copying overhead.
586: */
587: #define linux_ip_copysize 8
588:
589: int
590: linux_sendto_hdrincl(p, bsa, retval, sgp)
591: struct proc *p;
592: struct sys_sendto_args *bsa;
593: register_t *retval;
594: caddr_t *sgp;
595: {
596: struct sys_sendmsg_args ssa;
597: struct ip *packet, rpacket;
598: struct msghdr *msg, rmsg;
599: struct iovec *iov, riov[2];
600: int error;
601:
602: /* Check the packet isn't too small before we mess with it */
603: if (SCARG(bsa, len) < linux_ip_copysize)
604: return EINVAL;
605:
606: /*
607: * Tweaking the user buffer in place would be bad manners.
608: * We create a corrected IP header with just the needed length,
609: * then use an iovec to glue it to the rest of the user packet
610: * when calling sendmsg().
611: */
612: packet = (struct ip *)stackgap_alloc(sgp, linux_ip_copysize);
613: msg = (struct msghdr *)stackgap_alloc(sgp, sizeof(*msg));
614: iov = (struct iovec *)stackgap_alloc(sgp, sizeof(*iov)*2);
615:
616: /* Make a copy of the beginning of the packet to be sent */
617: if ((error = copyin(SCARG(bsa, buf), (caddr_t)&rpacket,
618: linux_ip_copysize)))
619: return error;
620:
621: /* Convert fields from Linux to BSD raw IP socket format */
622: rpacket.ip_len = SCARG(bsa, len);
623: error = copyout(&rpacket, packet, linux_ip_copysize);
624: if (error)
625: return (error);
626:
627: riov[0].iov_base = (char *)packet;
628: riov[0].iov_len = linux_ip_copysize;
629: riov[1].iov_base = (caddr_t)SCARG(bsa, buf) + linux_ip_copysize;
630: riov[1].iov_len = SCARG(bsa, len) - linux_ip_copysize;
631:
632: error = copyout(&riov[0], iov, sizeof(riov));
633: if (error)
634: return (error);
635:
636: /* Prepare the msghdr and iovec structures describing the new packet */
637: rmsg.msg_name = (void *)SCARG(bsa, to);
638: rmsg.msg_namelen = SCARG(bsa, tolen);
639: rmsg.msg_iov = iov;
640: rmsg.msg_iovlen = 2;
641: rmsg.msg_control = NULL;
642: rmsg.msg_controllen = 0;
643: rmsg.msg_flags = 0;
644:
645: error = copyout(&riov[0], iov, sizeof(riov));
646: if (error)
647: return (error);
648:
649: SCARG(&ssa, s) = SCARG(bsa, s);
650: SCARG(&ssa, msg) = msg;
651: SCARG(&ssa, flags) = SCARG(bsa, flags);
652: return sys_sendmsg(p, &ssa, retval);
653: }
654:
655: int
656: linux_sendto(p, v, retval)
657: struct proc *p;
658: void *v;
659: register_t *retval;
660: {
661: struct linux_sendto_args /* {
662: syscallarg(int) s;
663: syscallarg(void *) msg;
664: syscallarg(int) len;
665: syscallarg(int) flags;
666: syscallarg(osockaddr *) to;
667: syscallarg(int) tolen;
668: } */ *uap = v;
669: struct linux_sendto_args lsa;
670: struct sys_sendto_args bsa;
671: int error;
672: int tolen;
673: caddr_t sg = stackgap_init(p->p_emul);
674:
675: if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
676: return error;
677:
678: SCARG(&bsa, s) = lsa.s;
679: SCARG(&bsa, buf) = lsa.msg;
680: SCARG(&bsa, len) = lsa.len;
681: SCARG(&bsa, flags) = lsa.flags;
682: tolen = lsa.tolen;
683: if (lsa.to) {
684: struct sockaddr *sa;
685:
686: if ((error = linux_sa_get(p, &sg, &sa, lsa.to, &tolen)))
687: return (error);
688: SCARG(&bsa, to) = sa;
689: } else
690: SCARG(&bsa, to) = NULL;
691: SCARG(&bsa, tolen) = tolen;
692:
693: if (linux_check_hdrincl(p, lsa.s, retval, &sg) == 0)
694: return linux_sendto_hdrincl(p, &bsa, retval, &sg);
695: return sys_sendto(p, &bsa, retval);
696: }
697:
698: int
699: linux_recvfrom(p, v, retval)
700: struct proc *p;
701: void *v;
702: register_t *retval;
703: {
704: struct linux_recvfrom_args /* {
705: syscallarg(int) s;
706: syscallarg(void *) buf;
707: syscallarg(int) len;
708: syscallarg(int) flags;
709: syscallarg(struct osockaddr *) from;
710: syscallarg(int *) fromlen;
711: } */ *uap = v;
712: struct linux_recvfrom_args lra;
713: struct sys_recvfrom_args bra;
714: int error;
715:
716: if ((error = copyin((caddr_t) uap, (caddr_t) &lra, sizeof lra)))
717: return error;
718:
719: SCARG(&bra, s) = lra.s;
720: SCARG(&bra, buf) = lra.buf;
721: SCARG(&bra, len) = lra.len;
722: SCARG(&bra, flags) = lra.flags;
723: SCARG(&bra, from) = (struct sockaddr *) lra.from;
724: SCARG(&bra, fromlenaddr) = lra.fromlen;
725:
726: if ((error = sys_recvfrom(p, &bra, retval)))
727: return (error);
728:
729: if (lra.from && (error = linux_sa_put(lra.from)))
730: return (error);
731:
732: return (0);
733: }
734:
735: int
736: linux_shutdown(p, v, retval)
737: struct proc *p;
738: void *v;
739: register_t *retval;
740: {
741: struct linux_shutdown_args /* {
742: syscallarg(int) s;
743: syscallarg(int) how;
744: } */ *uap = v;
745: struct linux_shutdown_args lsa;
746: struct sys_shutdown_args bsa;
747: int error;
748:
749: if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
750: return error;
751:
752: SCARG(&bsa, s) = lsa.s;
753: SCARG(&bsa, how) = lsa.how;
754:
755: return sys_shutdown(p, &bsa, retval);
756: }
757:
758: /*
759: * Convert socket option level from Linux to OpenBSD value. Only SOL_SOCKET
760: * is different, the rest matches IPPROTO_* on both systems.
761: */
762: int
763: linux_to_bsd_sopt_level(llevel)
764: int llevel;
765: {
766:
767: switch (llevel) {
768: case LINUX_SOL_SOCKET:
769: return SOL_SOCKET;
770: case LINUX_SOL_IP:
771: return IPPROTO_IP;
772: case LINUX_SOL_TCP:
773: return IPPROTO_TCP;
774: case LINUX_SOL_UDP:
775: return IPPROTO_UDP;
776: default:
777: return -1;
778: }
779: }
780:
781: /*
782: * Convert Linux socket level socket option numbers to OpenBSD values.
783: */
784: int
785: linux_to_bsd_so_sockopt(lopt)
786: int lopt;
787: {
788:
789: switch (lopt) {
790: case LINUX_SO_DEBUG:
791: return SO_DEBUG;
792: case LINUX_SO_REUSEADDR:
793: /*
794: * Linux does not implement SO_REUSEPORT, but allows reuse
795: * of a host:port pair through SO_REUSEADDR even if the
796: * address is not a multicast-address. Effectively, this
797: * means that we should use SO_REUSEPORT to allow Linux
798: * applications to not exit with EADDRINUSE.
799: */
800: return SO_REUSEPORT;
801: case LINUX_SO_TYPE:
802: return SO_TYPE;
803: case LINUX_SO_ERROR:
804: return SO_ERROR;
805: case LINUX_SO_DONTROUTE:
806: return SO_DONTROUTE;
807: case LINUX_SO_BROADCAST:
808: return SO_BROADCAST;
809: case LINUX_SO_SNDBUF:
810: return SO_SNDBUF;
811: case LINUX_SO_RCVBUF:
812: return SO_RCVBUF;
813: case LINUX_SO_KEEPALIVE:
814: return SO_KEEPALIVE;
815: case LINUX_SO_OOBINLINE:
816: return SO_OOBINLINE;
817: case LINUX_SO_LINGER:
818: return SO_LINGER;
819: case LINUX_SO_PRIORITY:
820: case LINUX_SO_NO_CHECK:
821: default:
822: return -1;
823: }
824: }
825:
826: /*
827: * Convert Linux IP level socket option number to OpenBSD values.
828: */
829: int
830: linux_to_bsd_ip_sockopt(lopt)
831: int lopt;
832: {
833:
834: switch (lopt) {
835: case LINUX_IP_TOS:
836: return IP_TOS;
837: case LINUX_IP_TTL:
838: return IP_TTL;
839: case LINUX_IP_MULTICAST_TTL:
840: return IP_MULTICAST_TTL;
841: case LINUX_IP_MULTICAST_LOOP:
842: return IP_MULTICAST_LOOP;
843: case LINUX_IP_MULTICAST_IF:
844: return IP_MULTICAST_IF;
845: case LINUX_IP_ADD_MEMBERSHIP:
846: return IP_ADD_MEMBERSHIP;
847: case LINUX_IP_DROP_MEMBERSHIP:
848: return IP_DROP_MEMBERSHIP;
849: case LINUX_IP_HDRINCL:
850: return IP_HDRINCL;
851: default:
852: return -1;
853: }
854: }
855:
856: /*
857: * Convert Linux TCP level socket option number to OpenBSD values.
858: */
859: int
860: linux_to_bsd_tcp_sockopt(lopt)
861: int lopt;
862: {
863:
864: switch (lopt) {
865: case LINUX_TCP_NODELAY:
866: return TCP_NODELAY;
867: case LINUX_TCP_MAXSEG:
868: return TCP_MAXSEG;
869: default:
870: return -1;
871: }
872: }
873:
874: /*
875: * Convert Linux UDP level socket option number to OpenBSD values.
876: */
877: int
878: linux_to_bsd_udp_sockopt(lopt)
879: int lopt;
880: {
881:
882: switch (lopt) {
883: default:
884: return -1;
885: }
886: }
887:
888: /*
889: * Another reasonably straightforward function: setsockopt(2).
890: * The level and option numbers are converted; the values passed
891: * are not (yet) converted, the ones currently implemented don't
892: * need conversion, as they are the same on both systems.
893: */
894: int
895: linux_setsockopt(p, v, retval)
896: struct proc *p;
897: void *v;
898: register_t *retval;
899: {
900: struct linux_setsockopt_args /* {
901: syscallarg(int) s;
902: syscallarg(int) level;
903: syscallarg(int) optname;
904: syscallarg(void *) optval;
905: syscallarg(int) optlen;
906: } */ *uap = v;
907: struct linux_setsockopt_args lsa;
908: struct sys_setsockopt_args bsa;
909: int error, name;
910:
911: if ((error = copyin((caddr_t) uap, (caddr_t) &lsa, sizeof lsa)))
912: return error;
913:
914: SCARG(&bsa, s) = lsa.s;
915: SCARG(&bsa, level) = linux_to_bsd_sopt_level(lsa.level);
916: SCARG(&bsa, val) = lsa.optval;
917: SCARG(&bsa, valsize) = lsa.optlen;
918:
919: switch (SCARG(&bsa, level)) {
920: case SOL_SOCKET:
921: name = linux_to_bsd_so_sockopt(lsa.optname);
922: break;
923: case IPPROTO_IP:
924: name = linux_to_bsd_ip_sockopt(lsa.optname);
925: break;
926: case IPPROTO_TCP:
927: name = linux_to_bsd_tcp_sockopt(lsa.optname);
928: break;
929: case IPPROTO_UDP:
930: name = linux_to_bsd_udp_sockopt(lsa.optname);
931: break;
932: default:
933: return EINVAL;
934: }
935:
936: if (name == -1)
937: return EINVAL;
938: SCARG(&bsa, name) = name;
939:
940: return sys_setsockopt(p, &bsa, retval);
941: }
942:
943: /*
944: * getsockopt(2) is very much the same as setsockopt(2) (see above)
945: */
946: int
947: linux_getsockopt(p, v, retval)
948: struct proc *p;
949: void *v;
950: register_t *retval;
951: {
952: struct linux_getsockopt_args /* {
953: syscallarg(int) s;
954: syscallarg(int) level;
955: syscallarg(int) optname;
956: syscallarg(void *) optval;
957: syscallarg(int) *optlen;
958: } */ *uap = v;
959: struct linux_getsockopt_args lga;
960: struct sys_getsockopt_args bga;
961: int error, name;
962:
963: if ((error = copyin((caddr_t) uap, (caddr_t) &lga, sizeof lga)))
964: return error;
965:
966: SCARG(&bga, s) = lga.s;
967: SCARG(&bga, level) = linux_to_bsd_sopt_level(lga.level);
968: SCARG(&bga, val) = lga.optval;
969: SCARG(&bga, avalsize) = lga.optlen;
970:
971: switch (SCARG(&bga, level)) {
972: case SOL_SOCKET:
973: name = linux_to_bsd_so_sockopt(lga.optname);
974: break;
975: case IPPROTO_IP:
976: name = linux_to_bsd_ip_sockopt(lga.optname);
977: break;
978: case IPPROTO_TCP:
979: name = linux_to_bsd_tcp_sockopt(lga.optname);
980: break;
981: case IPPROTO_UDP:
982: name = linux_to_bsd_udp_sockopt(lga.optname);
983: break;
984: default:
985: return EINVAL;
986: }
987:
988: if (name == -1)
989: return EINVAL;
990: SCARG(&bga, name) = name;
991:
992: return sys_getsockopt(p, &bga, retval);
993: }
994:
995: int
996: linux_recvmsg(p, v, retval)
997: struct proc *p;
998: void *v;
999: register_t *retval;
1000: {
1001: struct linux_recvmsg_args /* {
1002: syscallarg(int) s;
1003: syscallarg(caddr_t) msg;
1004: syscallarg(int) flags;
1005: } */ *uap = v;
1006: struct linux_recvmsg_args lla;
1007: struct sys_recvmsg_args bla;
1008: struct msghdr msg;
1009: int error;
1010:
1011: if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
1012: return error;
1013:
1014: SCARG(&bla, s) = lla.s;
1015: SCARG(&bla, msg) = (struct msghdr *)lla.msg;
1016: SCARG(&bla, flags) = lla.flags;
1017:
1018: error = sys_recvmsg(p, &bla, retval);
1019: if (error)
1020: return (error);
1021:
1022: error = copyin(lla.msg, (caddr_t)&msg, sizeof(msg));
1023:
1024: if (!error && msg.msg_name && msg.msg_namelen > 2)
1025: error = linux_sa_put(msg.msg_name);
1026:
1027: return (error);
1028: }
1029:
1030: int
1031: linux_sendmsg(p, v, retval)
1032: struct proc *p;
1033: void *v;
1034: register_t *retval;
1035: {
1036: struct linux_sendmsg_args /* {
1037: syscallarg(int) s;
1038: syscallarg(struct msghdr *) msg;
1039: syscallarg(int) flags;
1040: } */ *uap = v;
1041: struct linux_sendmsg_args lla;
1042: struct sys_sendmsg_args bla;
1043: struct msghdr msg, *nmsg = NULL;
1044: int error;
1045: caddr_t control;
1046: int level;
1047:
1048: if ((error = copyin((caddr_t) uap, (caddr_t) &lla, sizeof lla)))
1049: return error;
1050:
1051: if ((error = copyin(lla.msg, (caddr_t) &msg, sizeof(msg))))
1052: return (error);
1053:
1054: if (msg.msg_name) {
1055: struct sockaddr *sa;
1056: caddr_t sg = stackgap_init(p->p_emul);
1057:
1058: nmsg = (struct msghdr *)stackgap_alloc(&sg,
1059: sizeof(struct msghdr));
1060: if (!nmsg)
1061: return (ENOMEM);
1062:
1063: error = linux_sa_get(p, &sg, &sa,
1064: (struct osockaddr *)msg.msg_name, &msg.msg_namelen);
1065: if (error)
1066: return (error);
1067:
1068: msg.msg_name = (struct sockaddr *)sa;
1069: if ((error = copyout(&msg, nmsg, sizeof(struct msghdr))))
1070: return (error);
1071: lla.msg = nmsg;
1072: }
1073:
1074: SCARG(&bla, s) = lla.s;
1075: SCARG(&bla, msg) = lla.msg;
1076: SCARG(&bla, flags) = lla.flags;
1077:
1078: error = copyin(lla.msg->msg_control, &control, sizeof(caddr_t));
1079: if (error)
1080: return error;
1081: if (control == NULL)
1082: goto done;
1083: error = copyin(&((struct cmsghdr *)control)->cmsg_level,
1084: &level, sizeof(int));
1085: if (error)
1086: return error;
1087: if (level == 1) {
1088: /*
1089: * Linux thinks that SOL_SOCKET is 1; we know that it's really
1090: * 0xffff, of course.
1091: */
1092: level = SOL_SOCKET;
1093: /*
1094: * XXX should use stack gap!
1095: * We don't because the control header is variable length
1096: * up to 2048 bytes, and there's only 512 bytes of gap.
1097: */
1098: error = copyout(&level, &((struct cmsghdr *)control)->
1099: cmsg_level, sizeof(int));
1100: if (error)
1101: return error;
1102: }
1103: done:
1104: error = sys_sendmsg(p, &bla, retval);
1105: /* replace level, just in case somebody cares. */
1106: if (level == SOL_SOCKET) {
1107: level = 1;
1108: /* don't worry about the error */
1109: copyout(&level, &((struct cmsghdr *)control)->cmsg_level,
1110: sizeof(int));
1111: }
1112: return (error);
1113: }
1114:
1115: /*
1116: * Copy the osockaddr structure pointed to by osa to kernel, adjust
1117: * family and convert to sockaddr, allocate stackgap and put the
1118: * the converted structure there, address on stackgap returned in sap.
1119: */
1120: int
1121: linux_sa_get(p, sgp, sap, osa, osalen)
1122: struct proc *p;
1123: caddr_t *sgp;
1124: struct sockaddr **sap;
1125: const struct osockaddr *osa;
1126: int *osalen;
1127: {
1128: int error=0, bdom;
1129: struct sockaddr *sa, *usa;
1130: struct osockaddr *kosa;
1131: int alloclen;
1132: #ifdef INET6
1133: int oldv6size;
1134: struct sockaddr_in6 *sin6;
1135: #endif
1136:
1137: if (*osalen < 2 || *osalen > UCHAR_MAX || !osa) {
1138: return (EINVAL);
1139: }
1140:
1141: alloclen = *osalen;
1142: #ifdef INET6
1143: oldv6size = 0;
1144: /*
1145: * Check for old (pre-RFC2553) sockaddr_in6. We may accept it
1146: * if it's a v4-mapped address, so reserve the proper space
1147: * for it.
1148: */
1149: if (alloclen == sizeof (struct sockaddr_in6) - sizeof (u_int32_t)) {
1150: alloclen = sizeof (struct sockaddr_in6);
1151: oldv6size = 1;
1152: }
1153: #endif
1154:
1155: kosa = (struct osockaddr *) malloc(alloclen, M_TEMP, M_WAITOK);
1156:
1157: if ((error = copyin(osa, (caddr_t) kosa, *osalen))) {
1158: goto out;
1159: }
1160:
1161: bdom = linux_to_bsd_domain(kosa->sa_family);
1162: if (bdom == -1) {
1163: error = EINVAL;
1164: goto out;
1165: }
1166:
1167: #ifdef INET6
1168: /*
1169: * Older Linux IPv6 code uses obsolete RFC2133 struct sockaddr_in6,
1170: * which lacks the scope id compared with RFC2553 one. If we detect
1171: * the situation, reject the address.
1172: *
1173: * Still accept addresses for which the scope id is not used.
1174: */
1175: if (oldv6size && bdom == AF_INET6) {
1176: sin6 = (struct sockaddr_in6 *)kosa;
1177: if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr) ||
1178: (!IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr) &&
1179: !IN6_IS_ADDR_SITELOCAL(&sin6->sin6_addr) &&
1180: !IN6_IS_ADDR_V4COMPAT(&sin6->sin6_addr) &&
1181: !IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr) &&
1182: !IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))) {
1183: sin6->sin6_scope_id = 0;
1184: } else {
1185: error = EINVAL;
1186: goto out;
1187: }
1188: } else
1189: #endif
1190: if (bdom == AF_INET) {
1191: alloclen = sizeof(struct sockaddr_in);
1192: }
1193:
1194: sa = (struct sockaddr *) kosa;
1195: sa->sa_family = bdom;
1196: sa->sa_len = alloclen;
1197:
1198: usa = (struct sockaddr *) stackgap_alloc(sgp, alloclen);
1199: if (!usa) {
1200: error = ENOMEM;
1201: goto out;
1202: }
1203:
1204: if ((error = copyout(sa, usa, alloclen))) {
1205: goto out;
1206: }
1207:
1208: *sap = usa;
1209:
1210: out:
1211: *osalen = alloclen;
1212: free(kosa, M_TEMP);
1213: return (error);
1214: }
1215:
1216: int
1217: linux_sa_put(osa)
1218: struct osockaddr *osa;
1219: {
1220: struct sockaddr sa;
1221: struct osockaddr *kosa;
1222: int error, bdom, len;
1223:
1224: /*
1225: * Only read/write the sockaddr family and length part, the rest is
1226: * not changed.
1227: */
1228: len = sizeof(sa.sa_len) + sizeof(sa.sa_family);
1229:
1230: error = copyin((caddr_t) osa, (caddr_t) &sa, len);
1231: if (error)
1232: return (error);
1233:
1234: bdom = bsd_to_linux_domain(sa.sa_family);
1235: if (bdom == -1)
1236: return (EINVAL);
1237:
1238: /* Note: we convert from sockaddr to osockaddr here, too */
1239: kosa = (struct osockaddr *) &sa;
1240: kosa->sa_family = bdom;
1241: error = copyout(kosa, osa, len);
1242: if (error)
1243: return (error);
1244:
1245: return (0);
1246: }
1247:
1248: /*
1249: * Entry point to all Linux socket calls. Just check which call to
1250: * make and take appropriate action.
1251: */
1252: int
1253: linux_sys_socketcall(p, v, retval)
1254: struct proc *p;
1255: void *v;
1256: register_t *retval;
1257: {
1258: struct linux_sys_socketcall_args /* {
1259: syscallarg(int) what;
1260: syscallarg(void *) args;
1261: } */ *uap = v;
1262:
1263: switch (SCARG(uap, what)) {
1264: case LINUX_SYS_socket:
1265: return linux_socket(p, SCARG(uap, args), retval);
1266: case LINUX_SYS_bind:
1267: return linux_bind(p, SCARG(uap, args), retval);
1268: case LINUX_SYS_connect:
1269: return linux_connect(p, SCARG(uap, args), retval);
1270: case LINUX_SYS_listen:
1271: return linux_listen(p, SCARG(uap, args), retval);
1272: case LINUX_SYS_accept:
1273: return linux_accept(p, SCARG(uap, args), retval);
1274: case LINUX_SYS_getsockname:
1275: return linux_getsockname(p, SCARG(uap, args), retval);
1276: case LINUX_SYS_getpeername:
1277: return linux_getpeername(p, SCARG(uap, args), retval);
1278: case LINUX_SYS_socketpair:
1279: return linux_socketpair(p, SCARG(uap, args), retval);
1280: case LINUX_SYS_send:
1281: return linux_send(p, SCARG(uap, args), retval);
1282: case LINUX_SYS_recv:
1283: return linux_recv(p, SCARG(uap, args), retval);
1284: case LINUX_SYS_sendto:
1285: return linux_sendto(p, SCARG(uap, args), retval);
1286: case LINUX_SYS_recvfrom:
1287: return linux_recvfrom(p, SCARG(uap, args), retval);
1288: case LINUX_SYS_shutdown:
1289: return linux_shutdown(p, SCARG(uap, args), retval);
1290: case LINUX_SYS_setsockopt:
1291: return linux_setsockopt(p, SCARG(uap, args), retval);
1292: case LINUX_SYS_getsockopt:
1293: return linux_getsockopt(p, SCARG(uap, args), retval);
1294: case LINUX_SYS_sendmsg:
1295: return linux_sendmsg(p, SCARG(uap, args), retval);
1296: case LINUX_SYS_recvmsg:
1297: return linux_recvmsg(p, SCARG(uap, args), retval);
1298: default:
1299: return ENOSYS;
1300: }
1301: }
1302:
1303: int
1304: linux_ioctl_socket(p, v, retval)
1305: register struct proc *p;
1306: void *v;
1307: register_t *retval;
1308: {
1309: struct linux_sys_ioctl_args /* {
1310: syscallarg(int) fd;
1311: syscallarg(u_long) com;
1312: syscallarg(caddr_t) data;
1313: } */ *uap = v;
1314: u_long com;
1315: struct sys_ioctl_args ia;
1316: struct file *fp;
1317: struct filedesc *fdp;
1318: struct vnode *vp;
1319: int (*ioctlf)(struct file *, u_long, caddr_t, struct proc *);
1320: struct ioctl_pt pt;
1321: int error = 0, isdev = 0, dosys = 1;
1322:
1323: fdp = p->p_fd;
1324: if ((fp = fd_getfile(fdp, SCARG(uap, fd))) == NULL)
1325: return (EBADF);
1326: FREF(fp);
1327:
1328: if (fp->f_type == DTYPE_VNODE) {
1329: vp = (struct vnode *)fp->f_data;
1330: isdev = vp->v_type == VCHR;
1331: }
1332:
1333: /*
1334: * Don't try to interpret socket ioctl calls that are done
1335: * on a device filedescriptor, just pass them through, to
1336: * emulate Linux behaviour. Use PTIOCLINUX so that the
1337: * device will only handle these if it's prepared to do
1338: * so, to avoid unexpected things from happening.
1339: */
1340: if (isdev) {
1341: dosys = 0;
1342: ioctlf = fp->f_ops->fo_ioctl;
1343: pt.com = SCARG(uap, com);
1344: pt.data = SCARG(uap, data);
1345: error = ioctlf(fp, PTIOCLINUX, (caddr_t)&pt, p);
1346: /*
1347: * XXX hack: if the function returns EJUSTRETURN,
1348: * it has stuffed a sysctl return value in pt.data.
1349: */
1350: if (error == EJUSTRETURN) {
1351: retval[0] = (register_t)pt.data;
1352: error = 0;
1353: }
1354: goto out;
1355: }
1356:
1357: com = SCARG(uap, com);
1358: retval[0] = 0;
1359:
1360: switch (com) {
1361: case LINUX_FIOSETOWN:
1362: SCARG(&ia, com) = FIOSETOWN;
1363: break;
1364: case LINUX_SIOCSPGRP:
1365: SCARG(&ia, com) = SIOCSPGRP;
1366: break;
1367: case LINUX_FIOGETOWN:
1368: SCARG(&ia, com) = FIOGETOWN;
1369: break;
1370: case LINUX_SIOCGPGRP:
1371: SCARG(&ia, com) = SIOCGPGRP;
1372: break;
1373: case LINUX_SIOCATMARK:
1374: SCARG(&ia, com) = SIOCATMARK;
1375: break;
1376: #if 0
1377: case LINUX_SIOCGSTAMP:
1378: SCARG(&ia, com) = SIOCGSTAMP;
1379: break;
1380: #endif
1381: case LINUX_SIOCGIFCONF:
1382: SCARG(&ia, com) = OSIOCGIFCONF;
1383: break;
1384: case LINUX_SIOCGIFFLAGS:
1385: SCARG(&ia, com) = SIOCGIFFLAGS;
1386: break;
1387: case LINUX_SIOCGIFADDR:
1388: SCARG(&ia, com) = OSIOCGIFADDR;
1389: break;
1390: case LINUX_SIOCGIFDSTADDR:
1391: SCARG(&ia, com) = OSIOCGIFDSTADDR;
1392: break;
1393: case LINUX_SIOCGIFBRDADDR:
1394: SCARG(&ia, com) = OSIOCGIFBRDADDR;
1395: break;
1396: case LINUX_SIOCGIFNETMASK:
1397: SCARG(&ia, com) = OSIOCGIFNETMASK;
1398: break;
1399: case LINUX_SIOCGIFMETRIC:
1400: SCARG(&ia, com) = SIOCGIFMETRIC;
1401: break;
1402: case LINUX_SIOCGIFMTU:
1403: SCARG(&ia, com) = SIOCGIFMTU;
1404: break;
1405: case LINUX_SIOCADDMULTI:
1406: SCARG(&ia, com) = SIOCADDMULTI;
1407: break;
1408: case LINUX_SIOCDELMULTI:
1409: SCARG(&ia, com) = SIOCDELMULTI;
1410: break;
1411: case LINUX_SIOCGIFHWADDR: {
1412: struct linux_ifreq *ifr = (struct linux_ifreq *)SCARG(uap, data);
1413: struct sockaddr_dl *sdl;
1414: struct ifnet *ifp;
1415: struct ifaddr *ifa;
1416:
1417: /*
1418: * Note that we don't actually respect the name in the ifreq
1419: * structure, as Linux interface names are all different.
1420: */
1421: TAILQ_FOREACH(ifp, &ifnet, if_list) {
1422: if (ifp->if_type != IFT_ETHER)
1423: continue;
1424: TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) {
1425: if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
1426: (sdl->sdl_family == AF_LINK) &&
1427: (sdl->sdl_type == IFT_ETHER)) {
1428: error = copyout(LLADDR(sdl),
1429: (caddr_t)&ifr->ifr_hwaddr.sa_data,
1430: LINUX_IFHWADDRLEN);
1431: dosys = 0;
1432: goto out;
1433: }
1434: }
1435: }
1436: error = ENOENT;
1437: break;
1438: }
1439: default:
1440: error = EINVAL;
1441: }
1442:
1443: out:
1444: if (error == 0 && dosys) {
1445: SCARG(&ia, fd) = SCARG(uap, fd);
1446: SCARG(&ia, data) = SCARG(uap, data);
1447: error = sys_ioctl(p, &ia, retval);
1448: }
1449:
1450: FRELE(fp);
1451: return (error);
1452: }
CVSweb