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