uipc_syscalls_40.c revision 1.13
1/* $NetBSD: uipc_syscalls_40.c,v 1.13 2017/03/14 09:03:08 ozaki-r Exp $ */ 2 3/* written by Pavel Cahyna, 2006. Public domain. */ 4 5#include <sys/cdefs.h> 6__KERNEL_RCSID(0, "$NetBSD: uipc_syscalls_40.c,v 1.13 2017/03/14 09:03:08 ozaki-r Exp $"); 7 8/* 9 * System call interface to the socket abstraction. 10 */ 11 12#include <sys/param.h> 13#include <sys/kernel.h> 14#include <sys/msg.h> 15#include <sys/sysctl.h> 16#include <sys/syscallargs.h> 17#include <sys/errno.h> 18 19#include <net/if.h> 20 21#include <compat/sys/socket.h> 22#include <compat/sys/sockio.h> 23 24#ifdef COMPAT_OIFREQ 25/* 26 * Return interface configuration 27 * of system. List may be used 28 * in later ioctl's (above) to get 29 * other information. 30 */ 31/*ARGSUSED*/ 32int 33compat_ifconf(u_long cmd, void *data) 34{ 35 struct oifconf *ifc = data; 36 struct ifnet *ifp; 37 struct oifreq ifr, *ifrp = NULL; 38 int space = 0, error = 0; 39 const int sz = (int)sizeof(ifr); 40 const bool docopy = ifc->ifc_req != NULL; 41 int s; 42 int bound; 43 struct psref psref; 44 45 if (docopy) { 46 space = ifc->ifc_len; 47 ifrp = ifc->ifc_req; 48 } 49 50 bound = curlwp_bind(); 51 s = pserialize_read_enter(); 52 IFNET_READER_FOREACH(ifp) { 53 struct ifaddr *ifa; 54 55 if_acquire(ifp, &psref); 56 57 (void)strncpy(ifr.ifr_name, ifp->if_xname, 58 sizeof(ifr.ifr_name)); 59 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') { 60 error = ENAMETOOLONG; 61 goto release_exit; 62 } 63 if (IFADDR_READER_EMPTY(ifp)) { 64 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 65 if (space >= sz) { 66 error = copyout(&ifr, ifrp, sz); 67 if (error != 0) 68 goto release_exit; 69 ifrp++; 70 } 71 space -= sizeof(ifr); 72 continue; 73 } 74 75 IFADDR_READER_FOREACH(ifa, ifp) { 76 struct sockaddr *sa = ifa->ifa_addr; 77 struct psref psref_ifa; 78 79 ifa_acquire(ifa, &psref_ifa); 80 pserialize_read_exit(s); 81#ifdef COMPAT_OSOCK 82 if (cmd == OOSIOCGIFCONF) { 83 struct osockaddr *osa = 84 (struct osockaddr *)&ifr.ifr_addr; 85 /* 86 * If it does not fit, we don't bother with it 87 */ 88 if (sa->sa_len > sizeof(*osa)) { 89 s = pserialize_read_enter(); 90 ifa_release(ifa, &psref_ifa); 91 continue; 92 } 93 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 94 osa->sa_family = sa->sa_family; 95 if (space >= sz) { 96 error = copyout(&ifr, ifrp, sz); 97 ifrp++; 98 } 99 } else 100#endif 101 if (sa->sa_len <= sizeof(*sa)) { 102 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 103 if (space >= sz) { 104 error = copyout(&ifr, ifrp, sz); 105 ifrp++; 106 } 107 } else { 108 space -= sa->sa_len - sizeof(*sa); 109 if (space >= sz) { 110 error = copyout(&ifr, ifrp, 111 sizeof(ifr.ifr_name)); 112 if (error == 0) { 113 error = copyout(sa, 114 &ifrp->ifr_addr, 115 sa->sa_len); 116 } 117 ifrp = (struct oifreq *) 118 (sa->sa_len + 119 (char *)&ifrp->ifr_addr); 120 } 121 } 122 s = pserialize_read_enter(); 123 ifa_release(ifa, &psref_ifa); 124 if (error != 0) 125 goto release_exit; 126 space -= sz; 127 } 128 129 if_release(ifp, &psref); 130 } 131 pserialize_read_exit(s); 132 curlwp_bindx(bound); 133 134 if (docopy) 135 ifc->ifc_len -= space; 136 else 137 ifc->ifc_len = -space; 138 return (0); 139 140release_exit: 141 pserialize_read_exit(s); 142 if_release(ifp, &psref); 143 curlwp_bindx(bound); 144 return error; 145} 146#endif 147