]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - usr.sbin/jls/jls.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / usr.sbin / jls / jls.c
1 /*-
2  * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
3  * Copyright (c) 2008 Bjoern A. Zeeb <bz@FreeBSD.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD$
28  */
29
30 #include <sys/param.h>
31 #include <sys/types.h>
32 #include <sys/jail.h>
33 #include <sys/sysctl.h>
34
35 #include <sys/socket.h>
36 #include <netinet/in.h>
37 #include <arpa/inet.h>
38 #include <err.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <unistd.h>
45
46 #define FLAG_A          0x00001
47 #define FLAG_V          0x00002
48
49 #ifdef SUPPORT_OLD_XPRISON
50 static
51 char *print_xprison_v1(void *p, char *end, unsigned flags)
52 {
53         struct xprison_v1 *xp;
54         struct in_addr in;
55
56         if ((char *)p + sizeof(struct xprison_v1) > end)
57                 errx(1, "Invalid length for jail");
58
59         xp = (struct xprison_v1 *)p;
60         if (flags & FLAG_V) {
61                 printf("%6d  %-29.29s %.74s\n",
62                         xp->pr_id, xp->pr_host, xp->pr_path);
63                 /* We are not printing an empty line here for state and name. */
64                 /* We are not printing an empty line here for cpusetid. */
65                 /* IPv4 address. */
66                 in.s_addr = htonl(xp->pr_ip);
67                 printf("%6s  %-15.15s\n", "", inet_ntoa(in));
68         } else {
69                 printf("%6d  %-15.15s %-29.29s %.74s\n",
70                     xp->pr_id, inet_ntoa(in), xp->pr_host, xp->pr_path);
71         }
72
73         return ((char *)(xp + 1));
74 }
75 #endif
76
77 static
78 char *print_xprison_v3(void *p, char *end, unsigned flags)
79 {
80         struct xprison *xp;
81         struct in_addr *iap, in;
82         struct in6_addr *ia6p;
83         char buf[INET6_ADDRSTRLEN];
84         const char *state;
85         char *q;
86         uint32_t i;
87
88         if ((char *)p + sizeof(struct xprison) > end)
89                 errx(1, "Invalid length for jail");
90         xp = (struct xprison *)p;
91
92         if (xp->pr_state < 0 || xp->pr_state >= (int)
93             ((sizeof(prison_states) / sizeof(struct prison_state))))
94                 state = "(bogus)";
95         else
96                 state = prison_states[xp->pr_state].state_name;
97
98         /* See if we should print non-ACTIVE jails. No? */
99         if ((flags & FLAG_A) == 0 && strcmp(state, "ALIVE")) {
100                 q = (char *)(xp + 1);
101                 q += (xp->pr_ip4s * sizeof(struct in_addr));
102                 if (q > end)
103                         errx(1, "Invalid length for jail");
104                 q += (xp->pr_ip6s * sizeof(struct in6_addr));
105                 if (q > end)
106                         errx(1, "Invalid length for jail");
107                 return (q);
108         }
109
110         if (flags & FLAG_V)
111                 printf("%6d  %-29.29s %.74s\n",
112                         xp->pr_id, xp->pr_host, xp->pr_path);
113
114         /* Jail state and name. */
115         if (flags & FLAG_V)
116                 printf("%6s  %-29.29s %.74s\n",
117                     "", (xp->pr_name[0] != '\0') ? xp->pr_name : "", state);
118
119         /* cpusetid. */
120         if (flags & FLAG_V)
121                 printf("%6s  %-6d\n",
122                     "", xp->pr_cpusetid);
123
124         q = (char *)(xp + 1);
125         /* IPv4 addresses. */
126         iap = (struct in_addr *)(void *)q;
127         q += (xp->pr_ip4s * sizeof(struct in_addr));
128         if (q > end)
129                 errx(1, "Invalid length for jail");
130         in.s_addr = 0;
131         for (i = 0; i < xp->pr_ip4s; i++) {
132                 if (i == 0 || flags & FLAG_V)
133                         in.s_addr = iap[i].s_addr;
134                 if (flags & FLAG_V)
135                         printf("%6s  %-15.15s\n", "", inet_ntoa(in));
136         }
137         /* IPv6 addresses. */
138         ia6p = (struct in6_addr *)(void *)q;
139         q += (xp->pr_ip6s * sizeof(struct in6_addr));
140         if (q > end)
141                 errx(1, "Invalid length for jail");
142         for (i = 0; i < xp->pr_ip6s; i++) {
143                 if (flags & FLAG_V) {
144                         inet_ntop(AF_INET6, &ia6p[i], buf, sizeof(buf));
145                         printf("%6s  %s\n", "", buf);
146                 }
147         }
148
149         /* If requested print the old style single line version. */
150         if (!(flags & FLAG_V))
151                 printf("%6d  %-15.15s %-29.29s %.74s\n",
152                     xp->pr_id, (in.s_addr) ? inet_ntoa(in) : "",
153                     xp->pr_host, xp->pr_path);
154
155         return (q);
156 }
157
158 static void
159 usage(void)
160 {
161
162         (void)fprintf(stderr, "usage: jls [-av]\n");
163         exit(1);
164 }
165
166 int
167 main(int argc, char *argv[])
168
169         int ch, version;
170         unsigned flags;
171         size_t i, j, len;
172         void *p, *q;
173
174         flags = 0;
175         while ((ch = getopt(argc, argv, "av")) != -1) {
176                 switch (ch) {
177                 case 'a':
178                         flags |= FLAG_A;
179                         break;
180                 case 'v':
181                         flags |= FLAG_V;
182                         break;
183                 default:
184                         usage();
185                 }
186         }
187         argc -= optind;
188         argv += optind;
189
190         if (sysctlbyname("security.jail.list", NULL, &len, NULL, 0) == -1)
191                 err(1, "sysctlbyname(): security.jail.list");
192
193         j = len;
194         for (i = 0; i < 4; i++) {
195                 if (len <= 0)
196                         exit(0);        
197                 p = q = malloc(len);
198                 if (p == NULL)
199                         err(1, "malloc()");
200
201                 if (sysctlbyname("security.jail.list", q, &len, NULL, 0) == -1) {
202                         if (errno == ENOMEM) {
203                                 free(p);
204                                 p = NULL;
205                                 len += j;
206                                 continue;
207                         }
208                         err(1, "sysctlbyname(): security.jail.list");
209                 }
210                 break;
211         }
212         if (p == NULL)
213                 err(1, "sysctlbyname(): security.jail.list");
214         if (len < sizeof(int))
215                 errx(1, "This is no prison. Kernel and userland out of sync?");
216         version = *(int *)p;
217         if (version > XPRISON_VERSION)
218                 errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
219
220         if (flags & FLAG_V) {
221                 printf("   JID  Hostname                      Path\n");
222                 printf("        Name                          State\n");
223                 printf("        CPUSetID\n");
224                 printf("        IP Address(es)\n");
225         } else {
226                 printf("   JID  IP Address      Hostname"
227                     "                      Path\n");
228         }
229         for (; q != NULL && (char *)q + sizeof(int) < (char *)p + len;) {
230                 version = *(int *)q;
231                 if (version > XPRISON_VERSION)
232                         errx(1, "Sci-Fi prison. Kernel/userland out of sync?");
233                 switch (version) {
234 #ifdef SUPPORT_OLD_XPRISON
235                 case 1:
236                         q = print_xprison_v1(q, (char *)p + len, flags);
237                         break;
238                 case 2:
239                         errx(1, "Version 2 was used by multi-IPv4 jail "
240                             "implementations that never made it into the "
241                             "official kernel.");
242                         /* NOTREACHED */
243                         break;
244 #endif
245                 case 3:
246                         q = print_xprison_v3(q, (char *)p + len, flags);
247                         break;
248                 default:
249                         errx(1, "Prison unknown. Kernel/userland out of sync?");
250                         /* NOTREACHED */
251                         break;
252                 }
253         }
254
255         free(p);
256         exit(0);
257 }