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