Home | History | Annotate | Line # | Download | only in common
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*/
     49 int
     50 compat_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