uipc_syscalls_40.c revision 1.2
1/* $NetBSD: uipc_syscalls_40.c,v 1.2 2007/05/29 23:57:33 christos 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.2 2007/05/29 23:57:33 christos Exp $"); 7 8/* 9 * System call interface to the socket abstraction. 10 */ 11 12#include "opt_compat_netbsd.h" 13#include "opt_compat_linux.h" 14#include "opt_compat_svr4.h" 15#include "opt_compat_ultrix.h" 16#include "opt_compat_43.h" 17 18#include <sys/param.h> 19#include <sys/kernel.h> 20#include <sys/msg.h> 21#include <sys/sysctl.h> 22#include <sys/mount.h> 23#include <sys/syscallargs.h> 24#include <sys/errno.h> 25 26#include <net/if.h> 27 28#if defined(COMPAT_43) || defined(COMPAT_LINUX) || defined(COMPAT_SVR4) || \ 29 defined(COMPAT_ULTRIX) || defined(LKM) 30#define COMPAT_OSOCK 31#include <compat/sys/socket.h> 32#endif 33 34#if defined(COMPAT_09) || defined(COMPAT_10) || defined(COMPAT_11) || \ 35 defined(COMPAT_12) || defined(COMPAT_13) || defined(COMPAT_14) || \ 36 defined(COMPAT_15) || defined(COMPAT_16) || defined(COMPAT_20) || \ 37 defined(COMPAT_30) || defined(COMPAT_40) 38#define COMPAT_OIFREQ 39#include <compat/sys/sockio.h> 40#endif 41#ifdef COMPAT_OIFREQ 42/* 43 * Return interface configuration 44 * of system. List may be used 45 * in later ioctl's (above) to get 46 * other information. 47 */ 48/*ARGSUSED*/ 49int 50compat_ifconf(u_long cmd, void *data) 51{ 52 struct oifconf *ifc = data; 53 struct ifnet *ifp; 54 struct ifaddr *ifa; 55 struct oifreq ifr, *ifrp; 56 int space = ifc->ifc_len, error = 0; 57 const int sz = (int)sizeof(ifr); 58 int sign; 59 60 if ((ifrp = ifc->ifc_req) == NULL) { 61 space = 0; 62 sign = -1; 63 } else { 64 sign = 1; 65 } 66 IFNET_FOREACH(ifp) { 67 (void)strncpy(ifr.ifr_name, ifp->if_xname, 68 sizeof(ifr.ifr_name)); 69 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') 70 return ENAMETOOLONG; 71 if (TAILQ_EMPTY(&ifp->if_addrlist)) { 72 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 73 if (ifrp != NULL && space >= sz) { 74 error = copyout(&ifr, ifrp, sz); 75 if (error != 0) 76 break; 77 ifrp++; 78 } 79 space -= sizeof(ifr) * sign; 80 continue; 81 } 82 83 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 84 struct sockaddr *sa = ifa->ifa_addr; 85#ifdef COMPAT_OSOCK 86 if (cmd == OOSIOCGIFCONF) { 87 struct osockaddr *osa = 88 (struct osockaddr *)&ifr.ifr_addr; 89 /* 90 * If it does not fit, we don't bother with it 91 */ 92 if (sa->sa_len > sizeof(*osa)) 93 continue; 94 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 95 osa->sa_family = sa->sa_family; 96 if (ifrp != NULL && space >= sz) { 97 error = copyout(&ifr, ifrp, sz); 98 ifrp++; 99 } 100 } else 101#endif 102 if (sa->sa_len <= sizeof(*sa)) { 103 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 104 if (ifrp != NULL && space >= sz) { 105 error = copyout(&ifr, ifrp, sz); 106 ifrp++; 107 } 108 } else { 109 space -= (sa->sa_len - sizeof(*sa)) * sign; 110 if (ifrp != NULL && space >= sz) { 111 error = copyout(&ifr, ifrp, 112 sizeof(ifr.ifr_name)); 113 if (error == 0) { 114 error = copyout(sa, 115 &ifrp->ifr_addr, 116 sa->sa_len); 117 } 118 ifrp = (struct oifreq *) 119 (sa->sa_len + 120 (char *)&ifrp->ifr_addr); 121 } 122 } 123 if (error != 0) 124 break; 125 space -= sz * sign; 126 } 127 } 128 if (ifrp != NULL) 129 ifc->ifc_len -= space; 130 else 131 ifc->ifc_len = space; 132 return error; 133} 134#endif 135