1 1.32 andvar /* $NetBSD: linux32_socket.c,v 1.32 2022/12/24 15:23:02 andvar Exp $ */ 2 1.1 manu 3 1.1 manu /*- 4 1.1 manu * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. 5 1.1 manu * 6 1.1 manu * Redistribution and use in source and binary forms, with or without 7 1.1 manu * modification, are permitted provided that the following conditions 8 1.1 manu * are met: 9 1.1 manu * 1. Redistributions of source code must retain the above copyright 10 1.1 manu * notice, this list of conditions and the following disclaimer. 11 1.1 manu * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 manu * notice, this list of conditions and the following disclaimer in the 13 1.1 manu * documentation and/or other materials provided with the distribution. 14 1.1 manu * 3. All advertising materials mentioning features or use of this software 15 1.1 manu * must display the following acknowledgement: 16 1.1 manu * This product includes software developed by Emmanuel Dreyfus 17 1.1 manu * 4. The name of the author may not be used to endorse or promote 18 1.1 manu * products derived from this software without specific prior written 19 1.1 manu * permission. 20 1.1 manu * 21 1.1 manu * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' 22 1.1 manu * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 1.1 manu * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 1.1 manu * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 25 1.1 manu * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 1.1 manu * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 1.1 manu * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 1.1 manu * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 1.1 manu * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 1.1 manu * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 1.1 manu * POSSIBILITY OF SUCH DAMAGE. 32 1.1 manu */ 33 1.1 manu 34 1.1 manu #include <sys/cdefs.h> 35 1.1 manu 36 1.32 andvar __KERNEL_RCSID(0, "$NetBSD: linux32_socket.c,v 1.32 2022/12/24 15:23:02 andvar Exp $"); 37 1.1 manu 38 1.1 manu #include <sys/types.h> 39 1.1 manu #include <sys/param.h> 40 1.1 manu #include <sys/fstypes.h> 41 1.1 manu #include <sys/signal.h> 42 1.1 manu #include <sys/dirent.h> 43 1.1 manu #include <sys/kernel.h> 44 1.1 manu #include <sys/fcntl.h> 45 1.1 manu #include <sys/select.h> 46 1.1 manu #include <sys/proc.h> 47 1.1 manu #include <sys/ucred.h> 48 1.1 manu #include <sys/swap.h> 49 1.6 christos #include <sys/file.h> 50 1.6 christos #include <sys/vnode.h> 51 1.6 christos #include <sys/filedesc.h> 52 1.1 manu 53 1.1 manu #include <machine/types.h> 54 1.1 manu 55 1.6 christos #include <net/if.h> 56 1.8 njoly #include <net/if_dl.h> 57 1.8 njoly #include <net/if_types.h> 58 1.7 njoly #include <net/route.h> 59 1.7 njoly 60 1.7 njoly #include <netinet/in.h> 61 1.7 njoly #include <netinet/ip_mroute.h> 62 1.6 christos 63 1.1 manu #include <sys/syscallargs.h> 64 1.1 manu 65 1.1 manu #include <compat/netbsd32/netbsd32.h> 66 1.7 njoly #include <compat/netbsd32/netbsd32_ioctl.h> 67 1.1 manu #include <compat/netbsd32/netbsd32_conv.h> 68 1.1 manu #include <compat/netbsd32/netbsd32_syscallargs.h> 69 1.8 njoly 70 1.8 njoly #include <compat/sys/socket.h> 71 1.6 christos #include <compat/sys/sockio.h> 72 1.1 manu 73 1.1 manu #include <compat/linux/common/linux_types.h> 74 1.6 christos #include <compat/linux/common/linux_types.h> 75 1.1 manu #include <compat/linux/common/linux_signal.h> 76 1.1 manu #include <compat/linux/common/linux_machdep.h> 77 1.1 manu #include <compat/linux/common/linux_misc.h> 78 1.1 manu #include <compat/linux/common/linux_oldolduname.h> 79 1.6 christos #include <compat/linux/common/linux_ioctl.h> 80 1.6 christos #include <compat/linux/common/linux_sockio.h> 81 1.10 ad #include <compat/linux/common/linux_ipc.h> 82 1.10 ad #include <compat/linux/common/linux_sem.h> 83 1.1 manu #include <compat/linux/linux_syscallargs.h> 84 1.1 manu 85 1.1 manu #include <compat/linux32/common/linux32_types.h> 86 1.1 manu #include <compat/linux32/common/linux32_signal.h> 87 1.1 manu #include <compat/linux32/common/linux32_machdep.h> 88 1.1 manu #include <compat/linux32/common/linux32_sysctl.h> 89 1.1 manu #include <compat/linux32/common/linux32_socketcall.h> 90 1.8 njoly #include <compat/linux32/common/linux32_sockio.h> 91 1.6 christos #include <compat/linux32/common/linux32_ioctl.h> 92 1.1 manu #include <compat/linux32/linux32_syscallargs.h> 93 1.1 manu 94 1.11 joerg int linux32_getifname(struct lwp *, register_t *, void *); 95 1.9 njoly int linux32_getifconf(struct lwp *, register_t *, void *); 96 1.8 njoly int linux32_getifhwaddr(struct lwp *, register_t *, u_int, void *); 97 1.8 njoly 98 1.1 manu int 99 1.5 dsl linux32_sys_socketpair(struct lwp *l, const struct linux32_sys_socketpair_args *uap, register_t *retval) 100 1.1 manu { 101 1.5 dsl /* { 102 1.1 manu syscallarg(int) domain; 103 1.1 manu syscallarg(int) type; 104 1.1 manu syscallarg(int) protocol; 105 1.1 manu syscallarg(netbsd32_intp) rsv; 106 1.5 dsl } */ 107 1.1 manu struct linux_sys_socketpair_args ua; 108 1.1 manu 109 1.1 manu NETBSD32TO64_UAP(domain); 110 1.1 manu NETBSD32TO64_UAP(type); 111 1.1 manu NETBSD32TO64_UAP(protocol); 112 1.15 njoly NETBSD32TOP_UAP(rsv, int); 113 1.1 manu 114 1.1 manu return linux_sys_socketpair(l, &ua, retval); 115 1.1 manu } 116 1.1 manu 117 1.1 manu int 118 1.5 dsl linux32_sys_sendto(struct lwp *l, const struct linux32_sys_sendto_args *uap, register_t *retval) 119 1.1 manu { 120 1.5 dsl /* { 121 1.1 manu syscallarg(int) s; 122 1.5 dsl syscallarg(netbsd32_voidp) msg; 123 1.1 manu syscallarg(int) len; 124 1.1 manu syscallarg(int) flags; 125 1.1 manu syscallarg(netbsd32_osockaddrp_t) to; 126 1.1 manu syscallarg(int) tolen; 127 1.5 dsl } */ 128 1.1 manu struct linux_sys_sendto_args ua; 129 1.1 manu 130 1.1 manu NETBSD32TO64_UAP(s); 131 1.1 manu NETBSD32TOP_UAP(msg, void); 132 1.1 manu NETBSD32TO64_UAP(len); 133 1.1 manu NETBSD32TO64_UAP(flags); 134 1.1 manu NETBSD32TOP_UAP(to, struct osockaddr); 135 1.1 manu NETBSD32TO64_UAP(tolen); 136 1.1 manu 137 1.1 manu return linux_sys_sendto(l, &ua, retval); 138 1.1 manu } 139 1.1 manu 140 1.1 manu 141 1.1 manu int 142 1.5 dsl linux32_sys_recvfrom(struct lwp *l, const struct linux32_sys_recvfrom_args *uap, register_t *retval) 143 1.1 manu { 144 1.5 dsl /* { 145 1.1 manu syscallarg(int) s; 146 1.5 dsl syscallarg(netbsd32_voidp) buf; 147 1.1 manu syscallarg(netbsd32_size_t) len; 148 1.1 manu syscallarg(int) flags; 149 1.1 manu syscallarg(netbsd32_osockaddrp_t) from; 150 1.1 manu syscallarg(netbsd32_intp) fromlenaddr; 151 1.5 dsl } */ 152 1.1 manu struct linux_sys_recvfrom_args ua; 153 1.1 manu 154 1.1 manu NETBSD32TO64_UAP(s); 155 1.1 manu NETBSD32TOP_UAP(buf, void); 156 1.1 manu NETBSD32TO64_UAP(len); 157 1.1 manu NETBSD32TO64_UAP(flags); 158 1.1 manu NETBSD32TOP_UAP(from, struct osockaddr); 159 1.1 manu NETBSD32TOP_UAP(fromlenaddr, unsigned int); 160 1.1 manu 161 1.1 manu return linux_sys_recvfrom(l, &ua, retval); 162 1.1 manu } 163 1.1 manu 164 1.1 manu int 165 1.5 dsl linux32_sys_setsockopt(struct lwp *l, const struct linux32_sys_setsockopt_args *uap, register_t *retval) 166 1.1 manu { 167 1.5 dsl /* { 168 1.1 manu syscallarg(int) s; 169 1.1 manu syscallarg(int) level; 170 1.1 manu syscallarg(int) optname; 171 1.1 manu syscallarg(netbsd32_voidp) optval; 172 1.1 manu syscallarg(int) optlen; 173 1.5 dsl } */ 174 1.1 manu struct linux_sys_setsockopt_args ua; 175 1.1 manu 176 1.1 manu NETBSD32TO64_UAP(s); 177 1.1 manu NETBSD32TO64_UAP(level); 178 1.1 manu NETBSD32TO64_UAP(optname); 179 1.1 manu NETBSD32TOP_UAP(optval, void); 180 1.1 manu NETBSD32TO64_UAP(optlen); 181 1.1 manu 182 1.1 manu return linux_sys_setsockopt(l, &ua, retval); 183 1.1 manu } 184 1.1 manu 185 1.1 manu 186 1.1 manu int 187 1.5 dsl linux32_sys_getsockopt(struct lwp *l, const struct linux32_sys_getsockopt_args *uap, register_t *retval) 188 1.1 manu { 189 1.5 dsl /* { 190 1.1 manu syscallarg(int) s; 191 1.1 manu syscallarg(int) level; 192 1.1 manu syscallarg(int) optname; 193 1.1 manu syscallarg(netbsd32_voidp) optval; 194 1.1 manu syscallarg(netbsd32_intp) optlen; 195 1.5 dsl } */ 196 1.1 manu struct linux_sys_getsockopt_args ua; 197 1.1 manu 198 1.1 manu NETBSD32TO64_UAP(s); 199 1.1 manu NETBSD32TO64_UAP(level); 200 1.1 manu NETBSD32TO64_UAP(optname); 201 1.1 manu NETBSD32TOP_UAP(optval, void); 202 1.1 manu NETBSD32TOP_UAP(optlen, int); 203 1.1 manu 204 1.1 manu return linux_sys_getsockopt(l, &ua, retval); 205 1.1 manu } 206 1.1 manu 207 1.1 manu int 208 1.5 dsl linux32_sys_socket(struct lwp *l, const struct linux32_sys_socket_args *uap, register_t *retval) 209 1.1 manu { 210 1.5 dsl /* { 211 1.1 manu syscallarg(int) domain; 212 1.1 manu syscallarg(int) type; 213 1.1 manu syscallarg(int) protocol; 214 1.5 dsl } */ 215 1.1 manu struct linux_sys_socket_args ua; 216 1.1 manu 217 1.1 manu NETBSD32TO64_UAP(domain); 218 1.1 manu NETBSD32TO64_UAP(type); 219 1.1 manu NETBSD32TO64_UAP(protocol); 220 1.1 manu 221 1.1 manu return linux_sys_socket(l, &ua, retval); 222 1.1 manu } 223 1.1 manu 224 1.1 manu int 225 1.5 dsl linux32_sys_bind(struct lwp *l, const struct linux32_sys_bind_args *uap, register_t *retval) 226 1.1 manu { 227 1.5 dsl /* { 228 1.1 manu syscallarg(int) s; 229 1.1 manu syscallarg(netbsd32_osockaddrp_t) name; 230 1.1 manu syscallarg(int) namelen; 231 1.5 dsl } */ 232 1.1 manu struct linux_sys_bind_args ua; 233 1.1 manu 234 1.1 manu NETBSD32TO64_UAP(s); 235 1.15 njoly NETBSD32TOP_UAP(name, struct osockaddr); 236 1.1 manu NETBSD32TO64_UAP(namelen); 237 1.1 manu 238 1.1 manu return linux_sys_bind(l, &ua, retval); 239 1.1 manu } 240 1.1 manu 241 1.1 manu int 242 1.5 dsl linux32_sys_connect(struct lwp *l, const struct linux32_sys_connect_args *uap, register_t *retval) 243 1.1 manu { 244 1.5 dsl /* { 245 1.1 manu syscallarg(int) s; 246 1.1 manu syscallarg(netbsd32_osockaddrp_t) name; 247 1.1 manu syscallarg(int) namelen; 248 1.5 dsl } */ 249 1.1 manu struct linux_sys_connect_args ua; 250 1.1 manu 251 1.1 manu NETBSD32TO64_UAP(s); 252 1.15 njoly NETBSD32TOP_UAP(name, struct osockaddr); 253 1.1 manu NETBSD32TO64_UAP(namelen); 254 1.1 manu 255 1.2 manu #ifdef DEBUG_LINUX 256 1.1 manu printf("linux32_sys_connect: s = %d, name = %p, namelen = %d\n", 257 1.1 manu SCARG(&ua, s), SCARG(&ua, name), SCARG(&ua, namelen)); 258 1.2 manu #endif 259 1.1 manu 260 1.1 manu return linux_sys_connect(l, &ua, retval); 261 1.1 manu } 262 1.1 manu 263 1.1 manu int 264 1.5 dsl linux32_sys_accept(struct lwp *l, const struct linux32_sys_accept_args *uap, register_t *retval) 265 1.1 manu { 266 1.5 dsl /* { 267 1.1 manu syscallarg(int) s; 268 1.1 manu syscallarg(netbsd32_osockaddrp_t) name; 269 1.1 manu syscallarg(netbsd32_intp) anamelen; 270 1.5 dsl } */ 271 1.1 manu struct linux_sys_accept_args ua; 272 1.1 manu 273 1.1 manu NETBSD32TO64_UAP(s); 274 1.15 njoly NETBSD32TOP_UAP(name, struct osockaddr); 275 1.1 manu NETBSD32TOP_UAP(anamelen, int); 276 1.1 manu 277 1.1 manu return linux_sys_accept(l, &ua, retval); 278 1.1 manu } 279 1.1 manu 280 1.1 manu int 281 1.5 dsl linux32_sys_getpeername(struct lwp *l, const struct linux32_sys_getpeername_args *uap, register_t *retval) 282 1.1 manu { 283 1.5 dsl /* { 284 1.1 manu syscallarg(int) fdes; 285 1.1 manu syscallarg(netbsd32_sockaddrp_t) asa; 286 1.1 manu syscallarg(netbsd32_intp) alen; 287 1.5 dsl } */ 288 1.1 manu struct linux_sys_getpeername_args ua; 289 1.1 manu 290 1.1 manu NETBSD32TO64_UAP(fdes); 291 1.15 njoly NETBSD32TOP_UAP(asa, struct sockaddr); 292 1.1 manu NETBSD32TOP_UAP(alen, int); 293 1.1 manu 294 1.1 manu return linux_sys_getpeername(l, &ua, retval); 295 1.1 manu } 296 1.1 manu 297 1.1 manu int 298 1.5 dsl linux32_sys_getsockname(struct lwp *l, const struct linux32_sys_getsockname_args *uap, register_t *retval) 299 1.1 manu { 300 1.5 dsl /* { 301 1.1 manu syscallarg(int) fdec; 302 1.1 manu syscallarg(netbsd32_charp) asa; 303 1.1 manu syscallarg(netbsd32_intp) alen; 304 1.5 dsl } */ 305 1.1 manu struct linux_sys_getsockname_args ua; 306 1.1 manu 307 1.1 manu NETBSD32TO64_UAP(fdec); 308 1.15 njoly NETBSD32TOP_UAP(asa, char); 309 1.1 manu NETBSD32TOP_UAP(alen, int); 310 1.1 manu 311 1.1 manu return linux_sys_getsockname(l, &ua, retval); 312 1.1 manu } 313 1.1 manu 314 1.1 manu int 315 1.5 dsl linux32_sys_sendmsg(struct lwp *l, const struct linux32_sys_sendmsg_args *uap, register_t *retval) 316 1.1 manu { 317 1.5 dsl /* { 318 1.1 manu syscallarg(int) s; 319 1.1 manu syscallarg(netbsd32_msghdrp_t) msg; 320 1.1 manu syscallarg(int) flags; 321 1.5 dsl } */ 322 1.1 manu struct linux_sys_sendmsg_args ua; 323 1.1 manu 324 1.1 manu NETBSD32TO64_UAP(s); 325 1.1 manu NETBSD32TOP_UAP(msg, struct msghdr); 326 1.1 manu NETBSD32TO64_UAP(flags); 327 1.1 manu 328 1.1 manu return linux_sys_sendmsg(l, &ua, retval); 329 1.1 manu } 330 1.1 manu 331 1.1 manu int 332 1.5 dsl linux32_sys_recvmsg(struct lwp *l, const struct linux32_sys_recvmsg_args *uap, register_t *retval) 333 1.1 manu { 334 1.5 dsl /* { 335 1.1 manu syscallarg(int) s; 336 1.1 manu syscallarg(netbsd32_msghdrp_t) msg; 337 1.1 manu syscallarg(int) flags; 338 1.5 dsl } */ 339 1.1 manu struct linux_sys_recvmsg_args ua; 340 1.1 manu 341 1.1 manu NETBSD32TO64_UAP(s); 342 1.1 manu NETBSD32TOP_UAP(msg, struct msghdr); 343 1.1 manu NETBSD32TO64_UAP(flags); 344 1.1 manu 345 1.1 manu return linux_sys_recvmsg(l, &ua, retval); 346 1.1 manu } 347 1.1 manu 348 1.1 manu int 349 1.5 dsl linux32_sys_send(struct lwp *l, const struct linux32_sys_send_args *uap, register_t *retval) 350 1.1 manu { 351 1.5 dsl /* { 352 1.1 manu syscallarg(int) s; 353 1.1 manu syscallarg(netbsd32_voidp) buf; 354 1.1 manu syscallarg(int) len; 355 1.1 manu syscallarg(int) flags; 356 1.5 dsl } */ 357 1.1 manu struct sys_sendto_args ua; 358 1.1 manu 359 1.1 manu NETBSD32TO64_UAP(s); 360 1.1 manu NETBSD32TOP_UAP(buf, void); 361 1.1 manu NETBSD32TO64_UAP(len); 362 1.1 manu NETBSD32TO64_UAP(flags); 363 1.1 manu SCARG(&ua, to) = NULL; 364 1.1 manu SCARG(&ua, tolen) = 0; 365 1.1 manu 366 1.1 manu return sys_sendto(l, &ua, retval); 367 1.1 manu } 368 1.1 manu 369 1.1 manu int 370 1.5 dsl linux32_sys_recv(struct lwp *l, const struct linux32_sys_recv_args *uap, register_t *retval) 371 1.1 manu { 372 1.5 dsl /* { 373 1.1 manu syscallarg(int) s; 374 1.1 manu syscallarg(netbsd32_voidp) buf; 375 1.1 manu syscallarg(int) len; 376 1.1 manu syscallarg(int) flags; 377 1.5 dsl } */ 378 1.1 manu struct sys_recvfrom_args ua; 379 1.1 manu 380 1.1 manu NETBSD32TO64_UAP(s); 381 1.1 manu NETBSD32TOP_UAP(buf, void); 382 1.1 manu NETBSD32TO64_UAP(len); 383 1.1 manu NETBSD32TO64_UAP(flags); 384 1.1 manu SCARG(&ua, from) = NULL; 385 1.1 manu SCARG(&ua, fromlenaddr) = NULL; 386 1.1 manu 387 1.1 manu return sys_recvfrom(l, &ua, retval); 388 1.1 manu } 389 1.6 christos 390 1.6 christos int 391 1.11 joerg linux32_getifname(struct lwp *l, register_t *retval, void *data) 392 1.11 joerg { 393 1.11 joerg struct ifnet *ifp; 394 1.11 joerg struct linux32_ifreq ifr; 395 1.11 joerg int error; 396 1.22 ozaki int s; 397 1.11 joerg 398 1.11 joerg error = copyin(data, &ifr, sizeof(ifr)); 399 1.11 joerg if (error) 400 1.11 joerg return error; 401 1.11 joerg 402 1.22 ozaki s = pserialize_read_enter(); 403 1.18 rmind ifp = if_byindex(ifr.ifr_ifru.ifru_ifindex); 404 1.22 ozaki if (ifp == NULL) { 405 1.22 ozaki pserialize_read_exit(s); 406 1.11 joerg return ENODEV; 407 1.22 ozaki } 408 1.11 joerg 409 1.11 joerg strncpy(ifr.ifr_name, ifp->if_xname, sizeof(ifr.ifr_name)); 410 1.22 ozaki pserialize_read_exit(s); 411 1.11 joerg 412 1.12 joerg return copyout(&ifr, data, sizeof(ifr)); 413 1.11 joerg } 414 1.11 joerg 415 1.11 joerg int 416 1.9 njoly linux32_getifconf(struct lwp *l, register_t *retval, void *data) 417 1.9 njoly { 418 1.19 ozaki struct linux32_ifreq ifr, *ifrp = NULL; 419 1.17 christos struct linux32_ifconf ifc; 420 1.9 njoly struct ifnet *ifp; 421 1.9 njoly struct sockaddr *sa; 422 1.9 njoly struct osockaddr *osa; 423 1.20 maxv int space = 0, error; 424 1.9 njoly const int sz = (int)sizeof(ifr); 425 1.19 ozaki bool docopy; 426 1.21 ozaki int s; 427 1.23 ozaki int bound; 428 1.21 ozaki struct psref psref; 429 1.9 njoly 430 1.17 christos error = copyin(data, &ifc, sizeof(ifc)); 431 1.17 christos if (error) 432 1.17 christos return error; 433 1.17 christos 434 1.19 ozaki docopy = NETBSD32PTR64(ifc.ifc_req) != NULL; 435 1.19 ozaki if (docopy) { 436 1.31 msaitoh if (ifc.ifc_len < 0) 437 1.31 msaitoh return EINVAL; 438 1.31 msaitoh 439 1.17 christos space = ifc.ifc_len; 440 1.19 ozaki ifrp = NETBSD32PTR64(ifc.ifc_req); 441 1.19 ozaki } 442 1.31 msaitoh memset(&ifr, 0, sizeof(ifr)); 443 1.9 njoly 444 1.23 ozaki bound = curlwp_bind(); 445 1.21 ozaki s = pserialize_read_enter(); 446 1.21 ozaki IFNET_READER_FOREACH(ifp) { 447 1.26 ozaki struct ifaddr *ifa; 448 1.27 ozaki if_acquire(ifp, &psref); 449 1.28 ozaki pserialize_read_exit(s); 450 1.21 ozaki 451 1.9 njoly (void)strncpy(ifr.ifr_name, ifp->if_xname, 452 1.9 njoly sizeof(ifr.ifr_name)); 453 1.21 ozaki if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { 454 1.21 ozaki error = ENAMETOOLONG; 455 1.21 ozaki goto release_exit; 456 1.21 ozaki } 457 1.24 ozaki 458 1.28 ozaki s = pserialize_read_enter(); 459 1.25 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 460 1.26 ozaki struct psref psref_ifa; 461 1.26 ozaki ifa_acquire(ifa, &psref_ifa); 462 1.26 ozaki pserialize_read_exit(s); 463 1.26 ozaki 464 1.9 njoly sa = ifa->ifa_addr; 465 1.9 njoly if (sa->sa_family != AF_INET || 466 1.9 njoly sa->sa_len > sizeof(*osa)) 467 1.26 ozaki goto next; 468 1.9 njoly memcpy(&ifr.ifr_addr, sa, sa->sa_len); 469 1.9 njoly osa = (struct osockaddr *)&ifr.ifr_addr; 470 1.9 njoly osa->sa_family = sa->sa_family; 471 1.9 njoly if (space >= sz) { 472 1.9 njoly error = copyout(&ifr, ifrp, sz); 473 1.26 ozaki if (error != 0) { 474 1.26 ozaki ifa_release(ifa, &psref_ifa); 475 1.21 ozaki goto release_exit; 476 1.26 ozaki } 477 1.9 njoly ifrp++; 478 1.9 njoly } 479 1.9 njoly space -= sz; 480 1.26 ozaki next: 481 1.26 ozaki s = pserialize_read_enter(); 482 1.26 ozaki ifa_release(ifa, &psref_ifa); 483 1.9 njoly } 484 1.21 ozaki 485 1.29 ozaki KASSERT(pserialize_in_read_section()); 486 1.27 ozaki if_release(ifp, &psref); 487 1.9 njoly } 488 1.21 ozaki pserialize_read_exit(s); 489 1.23 ozaki curlwp_bindx(bound); 490 1.9 njoly 491 1.19 ozaki if (docopy) 492 1.17 christos ifc.ifc_len -= space; 493 1.9 njoly else 494 1.17 christos ifc.ifc_len = -space; 495 1.9 njoly 496 1.17 christos return copyout(&ifc, data, sizeof(ifc)); 497 1.21 ozaki 498 1.21 ozaki release_exit: 499 1.27 ozaki if_release(ifp, &psref); 500 1.23 ozaki curlwp_bindx(bound); 501 1.21 ozaki return error; 502 1.9 njoly } 503 1.9 njoly 504 1.9 njoly int 505 1.8 njoly linux32_getifhwaddr(struct lwp *l, register_t *retval, u_int fd, 506 1.8 njoly void *data) 507 1.8 njoly { 508 1.8 njoly struct linux32_ifreq lreq; 509 1.8 njoly file_t *fp; 510 1.8 njoly struct ifaddr *ifa; 511 1.8 njoly struct ifnet *ifp; 512 1.8 njoly struct sockaddr_dl *sadl; 513 1.8 njoly int error, found; 514 1.8 njoly int index, ifnum; 515 1.21 ozaki int s; 516 1.8 njoly 517 1.8 njoly /* 518 1.8 njoly * We can't emulate this ioctl by calling sys_ioctl() to run 519 1.8 njoly * SIOCGIFCONF, because the user buffer is not of the right 520 1.8 njoly * type to take those results. We can't use kernel buffers to 521 1.8 njoly * receive the results, as the implementation of sys_ioctl() 522 1.8 njoly * and ifconf() [which implements SIOCGIFCONF] use 523 1.8 njoly * copyin()/copyout() which will fail on kernel addresses. 524 1.8 njoly * 525 1.8 njoly * So, we must duplicate code from sys_ioctl() and ifconf(). Ugh. 526 1.8 njoly */ 527 1.8 njoly 528 1.8 njoly if ((fp = fd_getfile(fd)) == NULL) 529 1.8 njoly return (EBADF); 530 1.8 njoly 531 1.8 njoly KERNEL_LOCK(1, NULL); 532 1.8 njoly 533 1.8 njoly if ((fp->f_flag & (FREAD | FWRITE)) == 0) { 534 1.8 njoly error = EBADF; 535 1.8 njoly goto out; 536 1.8 njoly } 537 1.8 njoly 538 1.8 njoly error = copyin(data, &lreq, sizeof(lreq)); 539 1.8 njoly if (error) 540 1.8 njoly goto out; 541 1.8 njoly lreq.ifr_name[LINUX32_IFNAMSIZ-1] = '\0'; /* just in case */ 542 1.8 njoly 543 1.8 njoly /* 544 1.8 njoly * Try real interface name first, then fake "ethX" 545 1.8 njoly */ 546 1.8 njoly found = 0; 547 1.21 ozaki s = pserialize_read_enter(); 548 1.21 ozaki IFNET_READER_FOREACH(ifp) { 549 1.8 njoly if (found) 550 1.8 njoly break; 551 1.8 njoly if (strcmp(lreq.ifr_name, ifp->if_xname)) 552 1.8 njoly /* not this interface */ 553 1.8 njoly continue; 554 1.8 njoly found=1; 555 1.25 ozaki if (IFADDR_READER_EMPTY(ifp)) { 556 1.8 njoly error = ENODEV; 557 1.8 njoly goto out; 558 1.8 njoly } 559 1.25 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 560 1.8 njoly sadl = satosdl(ifa->ifa_addr); 561 1.8 njoly /* only return ethernet addresses */ 562 1.8 njoly /* XXX what about FDDI, etc. ? */ 563 1.8 njoly if (sadl->sdl_family != AF_LINK || 564 1.8 njoly sadl->sdl_type != IFT_ETHER) 565 1.8 njoly continue; 566 1.8 njoly memcpy(&lreq.ifr_hwaddr.sa_data, CLLADDR(sadl), 567 1.8 njoly MIN(sadl->sdl_alen, 568 1.8 njoly sizeof(lreq.ifr_hwaddr.sa_data))); 569 1.8 njoly lreq.ifr_hwaddr.sa_family = 570 1.8 njoly sadl->sdl_family; 571 1.21 ozaki pserialize_read_exit(s); 572 1.21 ozaki 573 1.8 njoly error = copyout(&lreq, data, sizeof(lreq)); 574 1.8 njoly goto out; 575 1.8 njoly } 576 1.8 njoly } 577 1.21 ozaki pserialize_read_exit(s); 578 1.8 njoly 579 1.8 njoly if (strncmp(lreq.ifr_name, "eth", 3) == 0) { 580 1.8 njoly for (ifnum = 0, index = 3; 581 1.16 bouyer index < LINUX32_IFNAMSIZ && lreq.ifr_name[index] != '\0'; 582 1.8 njoly index++) { 583 1.8 njoly ifnum *= 10; 584 1.8 njoly ifnum += lreq.ifr_name[index] - '0'; 585 1.8 njoly } 586 1.8 njoly 587 1.8 njoly error = EINVAL; /* in case we don't find one */ 588 1.21 ozaki s = pserialize_read_enter(); 589 1.21 ozaki IFNET_READER_FOREACH(ifp) { 590 1.8 njoly memcpy(lreq.ifr_name, ifp->if_xname, 591 1.8 njoly MIN(LINUX32_IFNAMSIZ, IFNAMSIZ)); 592 1.25 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 593 1.8 njoly sadl = satosdl(ifa->ifa_addr); 594 1.8 njoly /* only return ethernet addresses */ 595 1.8 njoly /* XXX what about FDDI, etc. ? */ 596 1.8 njoly if (sadl->sdl_family != AF_LINK || 597 1.8 njoly sadl->sdl_type != IFT_ETHER) 598 1.8 njoly continue; 599 1.8 njoly if (ifnum--) 600 1.32 andvar /* not the requested iface */ 601 1.8 njoly continue; 602 1.8 njoly memcpy(&lreq.ifr_hwaddr.sa_data, 603 1.8 njoly CLLADDR(sadl), 604 1.8 njoly MIN(sadl->sdl_alen, 605 1.8 njoly sizeof(lreq.ifr_hwaddr.sa_data))); 606 1.8 njoly lreq.ifr_hwaddr.sa_family = 607 1.8 njoly sadl->sdl_family; 608 1.21 ozaki pserialize_read_exit(s); 609 1.21 ozaki 610 1.8 njoly error = copyout(&lreq, data, sizeof(lreq)); 611 1.21 ozaki goto out; 612 1.8 njoly } 613 1.8 njoly } 614 1.21 ozaki pserialize_read_exit(s); 615 1.8 njoly } else { 616 1.8 njoly /* unknown interface, not even an "eth*" name */ 617 1.8 njoly error = ENODEV; 618 1.8 njoly } 619 1.8 njoly 620 1.8 njoly out: 621 1.8 njoly KERNEL_UNLOCK_ONE(NULL); 622 1.8 njoly fd_putfile(fd); 623 1.8 njoly return error; 624 1.8 njoly } 625 1.8 njoly 626 1.8 njoly int 627 1.6 christos linux32_ioctl_socket(struct lwp *l, const struct linux32_sys_ioctl_args *uap, register_t *retval) 628 1.6 christos { 629 1.6 christos /* { 630 1.6 christos syscallarg(int) fd; 631 1.6 christos syscallarg(u_long) com; 632 1.6 christos syscallarg(void *) data; 633 1.6 christos } */ 634 1.6 christos u_long com; 635 1.6 christos int error = 0, isdev = 0, dosys = 1; 636 1.6 christos struct netbsd32_ioctl_args ia; 637 1.6 christos file_t *fp; 638 1.6 christos struct vnode *vp; 639 1.6 christos int (*ioctlf)(file_t *, u_long, void *); 640 1.6 christos struct ioctl_pt pt; 641 1.6 christos 642 1.6 christos if ((fp = fd_getfile(SCARG(uap, fd))) == NULL) 643 1.6 christos return (EBADF); 644 1.6 christos 645 1.6 christos if (fp->f_type == DTYPE_VNODE) { 646 1.6 christos vp = (struct vnode *)fp->f_data; 647 1.6 christos isdev = vp->v_type == VCHR; 648 1.6 christos } 649 1.6 christos 650 1.6 christos /* 651 1.6 christos * Don't try to interpret socket ioctl calls that are done 652 1.6 christos * on a device filedescriptor, just pass them through, to 653 1.6 christos * emulate Linux behaviour. Use PTIOCLINUX so that the 654 1.6 christos * device will only handle these if it's prepared to do 655 1.6 christos * so, to avoid unexpected things from happening. 656 1.6 christos */ 657 1.6 christos if (isdev) { 658 1.6 christos dosys = 0; 659 1.6 christos ioctlf = fp->f_ops->fo_ioctl; 660 1.6 christos pt.com = SCARG(uap, com); 661 1.6 christos pt.data = (void *)NETBSD32PTR64(SCARG(uap, data)); 662 1.6 christos error = ioctlf(fp, PTIOCLINUX, &pt); 663 1.6 christos /* 664 1.6 christos * XXX hack: if the function returns EJUSTRETURN, 665 1.6 christos * it has stuffed a sysctl return value in pt.data. 666 1.6 christos */ 667 1.6 christos if (error == EJUSTRETURN) { 668 1.6 christos retval[0] = (register_t)pt.data; 669 1.6 christos error = 0; 670 1.6 christos } 671 1.6 christos goto out; 672 1.6 christos } 673 1.6 christos 674 1.6 christos com = SCARG(uap, com); 675 1.6 christos retval[0] = 0; 676 1.6 christos 677 1.6 christos switch (com) { 678 1.11 joerg case LINUX_SIOCGIFNAME: 679 1.11 joerg error = linux32_getifname(l, retval, SCARG_P32(uap, data)); 680 1.11 joerg dosys = 0; 681 1.11 joerg break; 682 1.6 christos case LINUX_SIOCGIFCONF: 683 1.9 njoly error = linux32_getifconf(l, retval, SCARG_P32(uap, data)); 684 1.9 njoly dosys = 0; 685 1.6 christos break; 686 1.6 christos case LINUX_SIOCGIFFLAGS: 687 1.13 njoly SCARG(&ia, com) = OSIOCGIFFLAGS32; 688 1.6 christos break; 689 1.6 christos case LINUX_SIOCSIFFLAGS: 690 1.13 njoly SCARG(&ia, com) = OSIOCSIFFLAGS32; 691 1.6 christos break; 692 1.6 christos case LINUX_SIOCGIFADDR: 693 1.13 njoly SCARG(&ia, com) = OOSIOCGIFADDR32; 694 1.6 christos break; 695 1.6 christos case LINUX_SIOCGIFDSTADDR: 696 1.13 njoly SCARG(&ia, com) = OOSIOCGIFDSTADDR32; 697 1.6 christos break; 698 1.6 christos case LINUX_SIOCGIFBRDADDR: 699 1.13 njoly SCARG(&ia, com) = OOSIOCGIFBRDADDR32; 700 1.6 christos break; 701 1.6 christos case LINUX_SIOCGIFNETMASK: 702 1.13 njoly SCARG(&ia, com) = OOSIOCGIFNETMASK32; 703 1.6 christos break; 704 1.14 njoly case LINUX_SIOCGIFMTU: 705 1.14 njoly SCARG(&ia, com) = OSIOCGIFMTU32; 706 1.14 njoly break; 707 1.6 christos case LINUX_SIOCADDMULTI: 708 1.13 njoly SCARG(&ia, com) = OSIOCADDMULTI32; 709 1.6 christos break; 710 1.6 christos case LINUX_SIOCDELMULTI: 711 1.13 njoly SCARG(&ia, com) = OSIOCDELMULTI32; 712 1.6 christos break; 713 1.6 christos case LINUX_SIOCGIFHWADDR: 714 1.8 njoly error = linux32_getifhwaddr(l, retval, SCARG(uap, fd), 715 1.8 njoly SCARG_P32(uap, data)); 716 1.6 christos dosys = 0; 717 1.6 christos break; 718 1.6 christos default: 719 1.6 christos error = EINVAL; 720 1.6 christos } 721 1.6 christos 722 1.6 christos out: 723 1.6 christos fd_putfile(SCARG(uap, fd)); 724 1.6 christos 725 1.6 christos if (error == 0 && dosys) { 726 1.6 christos SCARG(&ia, fd) = SCARG(uap, fd); 727 1.6 christos SCARG(&ia, data) = SCARG(uap, data); 728 1.6 christos error = netbsd32_ioctl(curlwp, &ia, retval); 729 1.6 christos } 730 1.6 christos 731 1.6 christos return error; 732 1.6 christos } 733