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