1 /* $NetBSD: uipc_syscalls_40.c,v 1.7 2011/01/19 10:21:16 tsutsui 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.7 2011/01/19 10:21:16 tsutsui 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*/ 32 int 33 compat_ifconf(u_long cmd, void *data) 34 { 35 struct oifconf *ifc = data; 36 struct ifnet *ifp; 37 struct ifaddr *ifa; 38 struct oifreq ifr, *ifrp; 39 int space, error = 0; 40 const int sz = (int)sizeof(ifr); 41 42 if ((ifrp = ifc->ifc_req) == NULL) 43 space = 0; 44 else 45 space = ifc->ifc_len; 46 IFNET_FOREACH(ifp) { 47 (void)strncpy(ifr.ifr_name, ifp->if_xname, 48 sizeof(ifr.ifr_name)); 49 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') 50 return ENAMETOOLONG; 51 if (IFADDR_EMPTY(ifp)) { 52 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 53 if (space >= sz) { 54 error = copyout(&ifr, ifrp, sz); 55 if (error != 0) 56 return (error); 57 ifrp++; 58 } 59 space -= sizeof(ifr); 60 continue; 61 } 62 63 IFADDR_FOREACH(ifa, ifp) { 64 struct sockaddr *sa = ifa->ifa_addr; 65 #ifdef COMPAT_OSOCK 66 if (cmd == OOSIOCGIFCONF) { 67 struct osockaddr *osa = 68 (struct osockaddr *)&ifr.ifr_addr; 69 /* 70 * If it does not fit, we don't bother with it 71 */ 72 if (sa->sa_len > sizeof(*osa)) 73 continue; 74 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 75 osa->sa_family = sa->sa_family; 76 if (space >= sz) { 77 error = copyout(&ifr, ifrp, sz); 78 ifrp++; 79 } 80 } else 81 #endif 82 if (sa->sa_len <= sizeof(*sa)) { 83 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 84 if (space >= sz) { 85 error = copyout(&ifr, ifrp, sz); 86 ifrp++; 87 } 88 } else { 89 space -= sa->sa_len - sizeof(*sa); 90 if (space >= sz) { 91 error = copyout(&ifr, ifrp, 92 sizeof(ifr.ifr_name)); 93 if (error == 0) { 94 error = copyout(sa, 95 &ifrp->ifr_addr, 96 sa->sa_len); 97 } 98 ifrp = (struct oifreq *) 99 (sa->sa_len + 100 (char *)&ifrp->ifr_addr); 101 } 102 } 103 if (error != 0) 104 return (error); 105 space -= sz; 106 } 107 } 108 if (ifrp != NULL) 109 ifc->ifc_len -= space; 110 else 111 ifc->ifc_len = -space; 112 return (0); 113 } 114 #endif 115