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