1 /* $OpenBSD: linux_socket.c,v 1.33 2005/06/07 02:30:47 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/select.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 AF_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
linux_to_bsd_domain(ldom)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
bsd_to_linux_domain(bdom)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
linux_socket(p,v,retval)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
linux_bind(p,v,retval)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
linux_connect(p,v,retval)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
linux_listen(p,v,retval)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
linux_accept(p,v,retval)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
linux_getsockname(p,v,retval)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
linux_getpeername(p,v,retval)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
linux_socketpair(p,v,retval)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
linux_send(p,v,retval)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
linux_recv(p,v,retval)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
linux_check_hdrincl(p,fd,retval,sgp)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
linux_sendto_hdrincl(p,bsa,retval,sgp)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
linux_sendto(p,v,retval)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
linux_recvfrom(p,v,retval)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
linux_shutdown(p,v,retval)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
linux_to_bsd_sopt_level(llevel)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
linux_to_bsd_so_sockopt(lopt)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
linux_to_bsd_ip_sockopt(lopt)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
linux_to_bsd_tcp_sockopt(lopt)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
linux_to_bsd_udp_sockopt(lopt)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
linux_setsockopt(p,v,retval)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
linux_getsockopt(p,v,retval)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
linux_recvmsg(p,v,retval)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
linux_sendmsg(p,v,retval)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
linux_sa_get(p,sgp,sap,osa,osalen)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
linux_sa_put(osa)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
linux_sys_socketcall(p,v,retval)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
linux_ioctl_socket(p,v,retval)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 for (ifp = ifnet.tqh_first; ifp != 0;
1422 ifp = ifp->if_list.tqe_next) {
1423 if (ifp->if_type != IFT_ETHER)
1424 continue;
1425 for (ifa = ifp->if_addrlist.tqh_first; ifa;
1426 ifa = ifa->ifa_list.tqe_next) {
1427 if ((sdl = (struct sockaddr_dl *)ifa->ifa_addr) &&
1428 (sdl->sdl_family == AF_LINK) &&
1429 (sdl->sdl_type == IFT_ETHER)) {
1430 error = copyout(LLADDR(sdl),
1431 (caddr_t)&ifr->ifr_hwaddr.sa_data,
1432 LINUX_IFHWADDRLEN);
1433 dosys = 0;
1434 goto out;
1435 }
1436 }
1437 }
1438 error = ENOENT;
1439 break;
1440 }
1441 default:
1442 error = EINVAL;
1443 }
1444
1445 out:
1446 if (error == 0 && dosys) {
1447 SCARG(&ia, fd) = SCARG(uap, fd);
1448 SCARG(&ia, data) = SCARG(uap, data);
1449 error = sys_ioctl(p, &ia, retval);
1450 }
1451
1452 FRELE(fp);
1453 return (error);
1454 }
1455