uipc_syscalls_40.c revision 1.1
1/* $NetBSD: uipc_syscalls_40.c,v 1.1 2007/05/29 21:32:27 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.1 2007/05/29 21:32:27 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#include <compat/sys/sockio.h> 39#endif 40/* 41 * Return interface configuration 42 * of system. List may be used 43 * in later ioctl's (above) to get 44 * other information. 45 */ 46/*ARGSUSED*/ 47int 48compat_ifconf(u_long cmd, void *data) 49{ 50 struct oifconf *ifc = data; 51 struct ifnet *ifp; 52 struct ifaddr *ifa; 53 struct oifreq ifr, *ifrp; 54 int space = ifc->ifc_len, error = 0; 55 const int sz = (int)sizeof(ifr); 56 int sign; 57 58 if ((ifrp = ifc->ifc_req) == NULL) { 59 space = 0; 60 sign = -1; 61 } else { 62 sign = 1; 63 } 64 IFNET_FOREACH(ifp) { 65 (void)strncpy(ifr.ifr_name, ifp->if_xname, 66 sizeof(ifr.ifr_name)); 67 if (ifr.ifr_name[sizeof(ifr.ifr_name) - 1] != '\0') 68 return ENAMETOOLONG; 69 if (TAILQ_EMPTY(&ifp->if_addrlist)) { 70 memset(&ifr.ifr_addr, 0, sizeof(ifr.ifr_addr)); 71 if (ifrp != NULL && space >= sz) { 72 error = copyout(&ifr, ifrp, sz); 73 if (error != 0) 74 break; 75 ifrp++; 76 } 77 space -= sizeof(ifr) * sign; 78 continue; 79 } 80 81 TAILQ_FOREACH(ifa, &ifp->if_addrlist, ifa_list) { 82 struct sockaddr *sa = ifa->ifa_addr; 83#ifdef COMPAT_OSOCK 84 if (cmd == OOSIOCGIFCONF) { 85 struct osockaddr *osa = 86 (struct osockaddr *)&ifr.ifr_addr; 87 /* 88 * If it does not fit, we don't bother with it 89 */ 90 if (sa->sa_len > sizeof(*osa)) 91 continue; 92 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 93 osa->sa_family = sa->sa_family; 94 if (ifrp != NULL && space >= sz) { 95 error = copyout(&ifr, ifrp, sz); 96 ifrp++; 97 } 98 } else 99#endif 100 if (sa->sa_len <= sizeof(*sa)) { 101 memcpy(&ifr.ifr_addr, sa, sa->sa_len); 102 if (ifrp != NULL && space >= sz) { 103 error = copyout(&ifr, ifrp, sz); 104 ifrp++; 105 } 106 } else { 107 space -= (sa->sa_len - sizeof(*sa)) * sign; 108 if (ifrp != NULL && space >= sz) { 109 error = copyout(&ifr, ifrp, 110 sizeof(ifr.ifr_name)); 111 if (error == 0) { 112 error = copyout(sa, 113 &ifrp->ifr_addr, 114 sa->sa_len); 115 } 116 ifrp = (struct oifreq *) 117 (sa->sa_len + 118 (char *)&ifrp->ifr_addr); 119 } 120 } 121 if (error != 0) 122 break; 123 space -= sz * sign; 124 } 125 } 126 if (ifrp != NULL) 127 ifc->ifc_len -= space; 128 else 129 ifc->ifc_len = space; 130 return error; 131} 132