1 1.24 riastrad /* $NetBSD: uipc_syscalls_40.c,v 1.24 2022/07/07 18:17:33 riastradh Exp $ */ 2 1.1 christos 3 1.1 christos /* written by Pavel Cahyna, 2006. Public domain. */ 4 1.1 christos 5 1.1 christos #include <sys/cdefs.h> 6 1.24 riastrad __KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.24 2022/07/07 18:17:33 riastradh Exp $"); 7 1.17 pgoyette 8 1.17 pgoyette #if defined(_KERNEL_OPT) 9 1.17 pgoyette #include "opt_compat_netbsd.h" 10 1.17 pgoyette #endif 11 1.1 christos 12 1.1 christos /* 13 1.1 christos * System call interface to the socket abstraction. 14 1.1 christos */ 15 1.1 christos 16 1.1 christos #include <sys/param.h> 17 1.1 christos #include <sys/kernel.h> 18 1.1 christos #include <sys/msg.h> 19 1.1 christos #include <sys/sysctl.h> 20 1.1 christos #include <sys/syscallargs.h> 21 1.1 christos #include <sys/errno.h> 22 1.17 pgoyette #include <sys/compat_stub.h> 23 1.1 christos 24 1.1 christos #include <net/if.h> 25 1.1 christos 26 1.1 christos #include <compat/sys/socket.h> 27 1.3 christos #include <compat/sys/sockio.h> 28 1.1 christos 29 1.17 pgoyette #include <compat/common/compat_mod.h> 30 1.17 pgoyette 31 1.1 christos /* 32 1.20 msaitoh * Return interface configuration of system. List may be used in later 33 1.20 msaitoh * ioctl's (above) to get other information. 34 1.1 christos */ 35 1.1 christos /*ARGSUSED*/ 36 1.16 christos static int 37 1.17 pgoyette compat_ifconf(u_long cmd, void *data) 38 1.1 christos { 39 1.1 christos struct oifconf *ifc = data; 40 1.1 christos struct ifnet *ifp; 41 1.8 ozaki struct oifreq ifr, *ifrp = NULL; 42 1.8 ozaki int space = 0, error = 0; 43 1.1 christos const int sz = (int)sizeof(ifr); 44 1.9 ozaki int s; 45 1.10 ozaki int bound; 46 1.9 ozaki struct psref psref; 47 1.1 christos 48 1.16 christos switch (cmd) { 49 1.16 christos case OSIOCGIFCONF: 50 1.16 christos case OOSIOCGIFCONF: 51 1.16 christos break; 52 1.16 christos default: 53 1.16 christos return ENOSYS; 54 1.16 christos } 55 1.16 christos 56 1.24 riastrad const bool docopy = ifc->ifc_req != NULL; 57 1.8 ozaki if (docopy) { 58 1.23 msaitoh if (ifc->ifc_len < 0) 59 1.23 msaitoh return EINVAL; 60 1.23 msaitoh 61 1.4 enami space = ifc->ifc_len; 62 1.8 ozaki ifrp = ifc->ifc_req; 63 1.8 ozaki } 64 1.23 msaitoh memset(&ifr, 0, sizeof(ifr)); 65 1.8 ozaki 66 1.10 ozaki bound = curlwp_bind(); 67 1.9 ozaki s = pserialize_read_enter(); 68 1.9 ozaki IFNET_READER_FOREACH(ifp) { 69 1.12 ozaki struct ifaddr *ifa; 70 1.12 ozaki 71 1.13 ozaki if_acquire(ifp, &psref); 72 1.14 ozaki pserialize_read_exit(s); 73 1.9 ozaki 74 1.1 christos (void)strncpy(ifr.ifr_name, ifp->if_xname, 75 1.1 christos sizeof(ifr.ifr_name)); 76 1.9 ozaki if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { 77 1.9 ozaki error = ENAMETOOLONG; 78 1.9 ozaki goto release_exit; 79 1.9 ozaki } 80 1.11 ozaki if (IFADDR_READER_EMPTY(ifp)) { 81 1.1 christos memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 82 1.4 enami if (space >= sz) { 83 1.1 christos error = copyout(&ifr, ifrp, sz); 84 1.1 christos if (error != 0) 85 1.9 ozaki goto release_exit; 86 1.1 christos ifrp++; 87 1.1 christos } 88 1.4 enami space -= sizeof(ifr); 89 1.14 ozaki goto next; 90 1.1 christos } 91 1.1 christos 92 1.14 ozaki s = pserialize_read_enter(); 93 1.11 ozaki IFADDR_READER_FOREACH(ifa, ifp) { 94 1.1 christos struct sockaddr *sa = ifa->ifa_addr; 95 1.12 ozaki struct psref psref_ifa; 96 1.12 ozaki 97 1.12 ozaki ifa_acquire(ifa, &psref_ifa); 98 1.12 ozaki pserialize_read_exit(s); 99 1.1 christos #ifdef COMPAT_OSOCK 100 1.1 christos if (cmd == OOSIOCGIFCONF) { 101 1.1 christos struct osockaddr *osa = 102 1.4 enami (struct osockaddr *)&ifr.ifr_addr; 103 1.1 christos /* 104 1.1 christos * If it does not fit, we don't bother with it 105 1.1 christos */ 106 1.14 ozaki if (sa->sa_len > sizeof(*osa)) 107 1.14 ozaki goto next_ifa; 108 1.1 christos memcpy(&ifr.ifr_addr, sa, sa->sa_len); 109 1.1 christos osa->sa_family = sa->sa_family; 110 1.4 enami if (space >= sz) { 111 1.1 christos error = copyout(&ifr, ifrp, sz); 112 1.1 christos ifrp++; 113 1.1 christos } 114 1.1 christos } else 115 1.1 christos #endif 116 1.1 christos if (sa->sa_len <= sizeof(*sa)) { 117 1.1 christos memcpy(&ifr.ifr_addr, sa, sa->sa_len); 118 1.4 enami if (space >= sz) { 119 1.1 christos error = copyout(&ifr, ifrp, sz); 120 1.1 christos ifrp++; 121 1.1 christos } 122 1.1 christos } else { 123 1.4 enami space -= sa->sa_len - sizeof(*sa); 124 1.4 enami if (space >= sz) { 125 1.22 maxv error = copyout(&ifr.ifr_name, ifrp, 126 1.1 christos sizeof(ifr.ifr_name)); 127 1.1 christos if (error == 0) { 128 1.1 christos error = copyout(sa, 129 1.1 christos &ifrp->ifr_addr, 130 1.1 christos sa->sa_len); 131 1.1 christos } 132 1.1 christos ifrp = (struct oifreq *) 133 1.1 christos (sa->sa_len + 134 1.1 christos (char *)&ifrp->ifr_addr); 135 1.1 christos } 136 1.1 christos } 137 1.14 ozaki if (error != 0) { 138 1.14 ozaki ifa_release(ifa, &psref_ifa); 139 1.14 ozaki goto release_exit; 140 1.14 ozaki } 141 1.14 ozaki space -= sz; 142 1.14 ozaki 143 1.15 martin #ifdef COMPAT_OSOCK 144 1.14 ozaki next_ifa: 145 1.15 martin #endif 146 1.12 ozaki s = pserialize_read_enter(); 147 1.12 ozaki ifa_release(ifa, &psref_ifa); 148 1.1 christos } 149 1.14 ozaki pserialize_read_exit(s); 150 1.9 ozaki 151 1.14 ozaki next: 152 1.14 ozaki s = pserialize_read_enter(); 153 1.13 ozaki if_release(ifp, &psref); 154 1.1 christos } 155 1.9 ozaki pserialize_read_exit(s); 156 1.10 ozaki curlwp_bindx(bound); 157 1.9 ozaki 158 1.8 ozaki if (docopy) 159 1.1 christos ifc->ifc_len -= space; 160 1.1 christos else 161 1.4 enami ifc->ifc_len = -space; 162 1.20 msaitoh return 0; 163 1.9 ozaki 164 1.9 ozaki release_exit: 165 1.13 ozaki if_release(ifp, &psref); 166 1.10 ozaki curlwp_bindx(bound); 167 1.9 ozaki return error; 168 1.1 christos } 169 1.16 christos 170 1.17 pgoyette void 171 1.16 christos uipc_syscalls_40_init(void) 172 1.16 christos { 173 1.17 pgoyette 174 1.21 pgoyette MODULE_HOOK_SET(uipc_syscalls_40_hook, compat_ifconf); 175 1.16 christos } 176 1.17 pgoyette 177 1.16 christos void 178 1.16 christos uipc_syscalls_40_fini(void) 179 1.16 christos { 180 1.17 pgoyette 181 1.18 pgoyette MODULE_HOOK_UNSET(uipc_syscalls_40_hook); 182 1.16 christos } 183