trace(1): resolve all level-5 LLVM warnings
[minix3.git] / minix / usr.bin / trace / ioctl / net.c
blob90be38735d091d8af07914c9ff08eb581a955976
2 #include "inc.h"
4 #include <sys/ioctl.h>
5 #include <sys/ucred.h>
6 #include <net/gen/in.h>
7 #include <net/gen/ether.h>
8 #include <net/gen/eth_io.h>
9 #include <net/gen/arp_io.h>
10 #include <net/gen/ip_io.h>
11 #include <net/gen/route.h>
12 #include <net/gen/tcp.h>
13 #include <net/gen/tcp_io.h>
14 #include <net/gen/udp.h>
15 #include <net/gen/udp_io.h>
16 #include <net/gen/udp_io_hdr.h>
17 #include <net/gen/psip_io.h>
18 #include <arpa/inet.h>
20 const char *
21 net_ioctl_name(unsigned long req)
24 switch (req) {
25 NAME(FIONREAD);
26 NAME(NWIOSETHOPT); /* TODO: print argument */
27 NAME(NWIOGETHOPT); /* TODO: print argument */
28 NAME(NWIOGETHSTAT); /* TODO: print argument */
29 NAME(NWIOARPGIP); /* TODO: print argument */
30 NAME(NWIOARPGNEXT); /* TODO: print argument */
31 NAME(NWIOARPSIP); /* TODO: print argument */
32 NAME(NWIOARPDIP); /* TODO: print argument */
33 NAME(NWIOSIPCONF2); /* TODO: print argument */
34 NAME(NWIOSIPCONF); /* TODO: print argument */
35 NAME(NWIOGIPCONF2); /* TODO: print argument */
36 NAME(NWIOGIPCONF); /* TODO: print argument */
37 NAME(NWIOSIPOPT);
38 NAME(NWIOGIPOPT);
39 NAME(NWIOGIPOROUTE); /* TODO: print argument */
40 NAME(NWIOSIPOROUTE); /* TODO: print argument */
41 NAME(NWIODIPOROUTE); /* TODO: print argument */
42 NAME(NWIOGIPIROUTE); /* TODO: print argument */
43 NAME(NWIOSIPIROUTE); /* TODO: print argument */
44 NAME(NWIODIPIROUTE); /* TODO: print argument */
45 NAME(NWIOSTCPCONF);
46 NAME(NWIOGTCPCONF);
47 NAME(NWIOTCPCONN);
48 NAME(NWIOTCPLISTEN);
49 NAME(NWIOTCPATTACH); /* TODO: print argument */
50 NAME(NWIOTCPSHUTDOWN); /* no argument */
51 NAME(NWIOSTCPOPT);
52 NAME(NWIOGTCPOPT);
53 NAME(NWIOTCPPUSH); /* no argument */
54 NAME(NWIOTCPLISTENQ);
55 NAME(NWIOGTCPCOOKIE);
56 NAME(NWIOTCPACCEPTTO);
57 NAME(NWIOTCPGERROR);
58 NAME(NWIOSUDPOPT);
59 NAME(NWIOGUDPOPT);
60 NAME(NWIOUDPPEEK); /* TODO: print argument */
61 NAME(NWIOSPSIPOPT); /* TODO: print argument */
62 NAME(NWIOGPSIPOPT); /* TODO: print argument */
63 NAME(NWIOGUDSFADDR);
64 NAME(NWIOSUDSTADDR);
65 NAME(NWIOSUDSADDR);
66 NAME(NWIOGUDSADDR);
67 NAME(NWIOGUDSPADDR);
68 NAME(NWIOSUDSTYPE);
69 NAME(NWIOSUDSBLOG);
70 NAME(NWIOSUDSCONN);
71 NAME(NWIOSUDSSHUT);
72 NAME(NWIOSUDSPAIR);
73 NAME(NWIOSUDSACCEPT);
74 NAME(NWIOSUDSCTRL);
75 NAME(NWIOGUDSCTRL);
76 NAME(NWIOGUDSSOTYPE);
77 NAME(NWIOGUDSPEERCRED);
78 NAME(NWIOGUDSSNDBUF);
79 NAME(NWIOSUDSSNDBUF);
80 NAME(NWIOGUDSRCVBUF);
81 NAME(NWIOSUDSRCVBUF);
84 return NULL;
87 static const struct flags ipopt_flags[] = {
88 FLAG_ZERO(NWIO_NOFLAGS),
89 FLAG_MASK(NWIO_ACC_MASK, NWIO_EXCL),
90 FLAG_MASK(NWIO_ACC_MASK, NWIO_SHARED),
91 FLAG_MASK(NWIO_ACC_MASK, NWIO_COPY),
92 FLAG(NWIO_EN_LOC),
93 FLAG(NWIO_DI_LOC),
94 FLAG(NWIO_EN_BROAD),
95 FLAG(NWIO_DI_BROAD),
96 FLAG(NWIO_REMSPEC),
97 FLAG(NWIO_REMANY),
98 FLAG(NWIO_PROTOSPEC),
99 FLAG(NWIO_PROTOANY),
100 FLAG(NWIO_HDR_O_SPEC),
101 FLAG(NWIO_HDR_O_ANY),
102 FLAG(NWIO_RWDATONLY),
103 FLAG(NWIO_RWDATALL),
106 static void
107 put_ipaddr(struct trace_proc * proc, const char * name, ipaddr_t ipaddr)
109 struct in_addr in;
111 if (!valuesonly) {
112 in.s_addr = ipaddr;
114 /* Is this an acceptable encapsulation? */
115 put_value(proc, name, "[%s]", inet_ntoa(in));
116 } else
117 put_value(proc, name, "0x%08x", ntohl(ipaddr));
120 static void
121 put_ipproto(struct trace_proc * proc, const char * name, ipproto_t proto)
123 const char *text = NULL;
125 if (!valuesonly) {
126 switch (proto) {
127 TEXT(IPPROTO_ICMP);
128 TEXT(IPPROTO_TCP);
129 TEXT(IPPROTO_UDP);
133 if (text != NULL)
134 put_field(proc, name, text);
135 else
136 put_value(proc, name, "%u", proto);
139 static const struct flags tcpconf_flags[] = {
140 FLAG_ZERO(NWTC_NOFLAGS),
141 FLAG_MASK(NWTC_ACC_MASK, NWTC_EXCL),
142 FLAG_MASK(NWTC_ACC_MASK, NWTC_SHARED),
143 FLAG_MASK(NWTC_ACC_MASK, NWTC_COPY),
144 FLAG_MASK(NWTC_LOCPORT_MASK, NWTC_LP_UNSET),
145 FLAG_MASK(NWTC_LOCPORT_MASK, NWTC_LP_SET),
146 FLAG_MASK(NWTC_LOCPORT_MASK, NWTC_LP_SEL),
147 FLAG(NWTC_SET_RA),
148 FLAG(NWTC_UNSET_RA),
149 FLAG(NWTC_SET_RP),
150 FLAG(NWTC_UNSET_RP),
153 #define put_port(proc, name, port) \
154 put_value(proc, name, "%u", ntohs(port))
156 static const struct flags tcpcl_flags[] = {
157 FLAG_ZERO(TCF_DEFAULT),
158 FLAG(TCF_ASYNCH),
161 static const struct flags tcpopt_flags[] = {
162 FLAG_ZERO(NWTO_NOFLAG),
163 FLAG(NWTO_SND_URG),
164 FLAG(NWTO_SND_NOTURG),
165 FLAG(NWTO_RCV_URG),
166 FLAG(NWTO_RCV_NOTURG),
167 FLAG(NWTO_BSD_URG),
168 FLAG(NWTO_NOTBSD_URG),
169 FLAG(NWTO_DEL_RST),
170 FLAG(NWTO_BULK),
171 FLAG(NWTO_NOBULK),
174 static const struct flags udpopt_flags[] = {
175 FLAG_ZERO(NWUO_NOFLAGS),
176 FLAG_MASK(NWUO_ACC_MASK, NWUO_EXCL),
177 FLAG_MASK(NWUO_ACC_MASK, NWUO_SHARED),
178 FLAG_MASK(NWUO_ACC_MASK, NWUO_COPY),
179 FLAG_MASK(NWUO_LOCPORT_MASK, NWUO_LP_SET),
180 FLAG_MASK(NWUO_LOCPORT_MASK, NWUO_LP_SEL),
181 FLAG_MASK(NWUO_LOCPORT_MASK, NWUO_LP_ANY),
182 FLAG(NWUO_EN_LOC),
183 FLAG(NWUO_DI_LOC),
184 FLAG(NWUO_EN_BROAD),
185 FLAG(NWUO_DI_BROAD),
186 FLAG(NWUO_RP_SET),
187 FLAG(NWUO_RP_ANY),
188 FLAG(NWUO_RA_SET),
189 FLAG(NWUO_RA_ANY),
190 FLAG(NWUO_RWDATONLY),
191 FLAG(NWUO_RWDATALL),
192 FLAG(NWUO_EN_IPOPT),
193 FLAG(NWUO_DI_IPOPT),
196 static void
197 put_family(struct trace_proc * proc, const char * name, int family)
199 const char *text = NULL;
201 if (!valuesonly) {
202 /* TODO: add all the other protocols */
203 switch (family) {
204 TEXT(AF_UNSPEC);
205 TEXT(AF_LOCAL);
206 TEXT(AF_INET);
207 TEXT(AF_INET6);
211 if (text != NULL)
212 put_field(proc, name, text);
213 else
214 put_value(proc, name, "%d", family);
217 static const struct flags sock_type[] = {
218 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_STREAM),
219 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_DGRAM),
220 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RAW),
221 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_RDM),
222 FLAG_MASK(~SOCK_FLAGS_MASK, SOCK_SEQPACKET),
223 FLAG(SOCK_CLOEXEC),
224 FLAG(SOCK_NONBLOCK),
225 FLAG(SOCK_NOSIGPIPE),
228 static void
229 put_shutdown_how(struct trace_proc * proc, const char * name, int how)
231 const char *text = NULL;
233 if (!valuesonly) {
234 switch (how) {
235 TEXT(SHUT_RD);
236 TEXT(SHUT_WR);
237 TEXT(SHUT_RDWR);
241 if (text != NULL)
242 put_field(proc, name, text);
243 else
244 put_value(proc, name, "%d", how);
247 static void
248 put_struct_uucred(struct trace_proc * proc, const char * name, int flags,
249 vir_bytes addr)
251 struct uucred cred;
253 if (!put_open_struct(proc, name, flags, addr, &cred, sizeof(cred)))
254 return;
256 put_value(proc, "cr_uid", "%u", cred.cr_uid);
257 if (verbose > 0) {
258 put_value(proc, "cr_gid", "%u", cred.cr_gid);
259 if (verbose > 1)
260 put_value(proc, "cr_ngroups", "%d", cred.cr_ngroups);
261 put_groups(proc, "cr_groups", PF_LOCADDR,
262 (vir_bytes)&cred.cr_groups, cred.cr_ngroups);
265 put_close_struct(proc, verbose > 0);
268 static void
269 put_cmsg_type(struct trace_proc * proc, const char * name, int type)
271 const char *text = NULL;
273 if (!valuesonly) {
274 switch (type) {
275 TEXT(SCM_RIGHTS);
276 TEXT(SCM_CREDS);
277 TEXT(SCM_TIMESTAMP);
281 if (text != NULL)
282 put_field(proc, name, text);
283 else
284 put_value(proc, name, "%d", type);
287 static void
288 put_msg_control(struct trace_proc * proc, struct msg_control * ptr)
290 struct msghdr msg;
291 struct cmsghdr *cmsg;
292 size_t len;
293 unsigned int i;
295 if (ptr->msg_controllen > sizeof(ptr->msg_control)) {
296 put_field(proc, NULL, "..");
298 return;
301 put_open(proc, NULL, PF_NONAME, "[", ", ");
303 memset(&msg, 0, sizeof(msg));
304 msg.msg_control = ptr->msg_control;
305 msg.msg_controllen = ptr->msg_controllen;
308 * TODO: decide if we need a verbosity-based limit here. The argument
309 * in favor of printing everything is that upon receipt, SCM_RIGHTS
310 * actually creates new file descriptors, which is pretty essential in
311 * terms of figuring out what is happening in a process. In addition,
312 * these calls should be sufficiently rare that the lengthy output is
313 * not really disruptive for the general output flow.
315 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
316 cmsg = CMSG_NXTHDR(&msg, cmsg)) {
317 put_open(proc, NULL, 0, "{", ", ");
319 if (verbose > 0)
320 put_value(proc, "cmsg_len", "%u", cmsg->cmsg_len);
321 if (!valuesonly && cmsg->cmsg_level == SOL_SOCKET)
322 put_field(proc, "cmsg_level", "SOL_SOCKET");
323 else
324 put_value(proc, "cmsg_level", "%d", cmsg->cmsg_level);
325 if (cmsg->cmsg_level == SOL_SOCKET)
326 put_cmsg_type(proc, "cmsg_type", cmsg->cmsg_type);
328 len = cmsg->cmsg_len - CMSG_LEN(0);
330 /* Print the contents of the messages that we know. */
331 if (cmsg->cmsg_level == SOL_SOCKET &&
332 cmsg->cmsg_type == SCM_RIGHTS) {
333 put_open(proc, NULL, PF_NONAME, "[", ", ");
334 for (i = 0; i < len / sizeof(int); i++)
335 put_fd(proc, NULL,
336 ((int *)CMSG_DATA(cmsg))[i]);
337 put_close(proc, "]");
338 } else if (cmsg->cmsg_level == SOL_SOCKET &&
339 cmsg->cmsg_type == SCM_CREDS) {
340 put_struct_uucred(proc, NULL, PF_LOCADDR,
341 (vir_bytes)CMSG_DATA(cmsg));
342 } else if (len > 0)
343 put_field(proc, NULL, "..");
345 put_close(proc, "}");
348 put_close(proc, "]");
352 net_ioctl_arg(struct trace_proc * proc, unsigned long req, void * ptr, int dir)
354 const char *text;
355 nwio_ipopt_t *ipopt;
356 nwio_tcpconf_t *nwtc;
357 nwio_tcpcl_t *nwtcl;
358 nwio_tcpopt_t *nwto;
359 tcp_cookie_t *cookie;
360 nwio_udpopt_t *nwuo;
361 struct sockaddr_un *sun;
362 int i;
364 switch (req) {
365 case FIONREAD:
367 * Arguably this does not belong here, but as of writing, the
368 * network services are the only ones actually implementing
369 * support for this IOCTL, and we don't have a more suitable
370 * place to put it either.
372 if (ptr == NULL)
373 return IF_IN;
375 put_value(proc, NULL, "%d", *(int *)ptr);
376 return IF_ALL;
378 case NWIOSIPOPT:
379 case NWIOGIPOPT:
380 if ((ipopt = (nwio_ipopt_t *)ptr) == NULL)
381 return dir;
383 put_flags(proc, "nwio_flags", ipopt_flags, COUNT(ipopt_flags),
384 "0x%x", ipopt->nwio_flags);
386 if (ipopt->nwio_flags & NWIO_REMSPEC)
387 put_ipaddr(proc, "nwio_rem", ipopt->nwio_rem);
388 if (ipopt->nwio_flags & NWIO_PROTOSPEC)
389 put_ipproto(proc, "nwio_proto", ipopt->nwio_proto);
391 return 0; /* TODO: the remaining fields */
393 case NWIOSTCPCONF:
394 case NWIOGTCPCONF:
395 if ((nwtc = (nwio_tcpconf_t *)ptr) == NULL)
396 return dir;
398 put_flags(proc, "nwtc_flags", tcpconf_flags,
399 COUNT(tcpconf_flags), "0x%x", nwtc->nwtc_flags);
401 /* The local address cannot be set, just retrieved. */
402 if (req == NWIOGTCPCONF)
403 put_ipaddr(proc, "nwtc_locaddr", nwtc->nwtc_locaddr);
405 if ((nwtc->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET)
406 put_port(proc, "nwtc_locport", nwtc->nwtc_locport);
408 if (nwtc->nwtc_flags & NWTC_SET_RA)
409 put_ipaddr(proc, "nwtc_remaddr", nwtc->nwtc_remaddr);
411 if (nwtc->nwtc_flags & NWTC_SET_RP)
412 put_port(proc, "nwtc_remport", nwtc->nwtc_remport);
414 return IF_ALL;
416 case NWIOTCPCONN:
417 case NWIOTCPLISTEN:
418 if ((nwtcl = (nwio_tcpcl_t *)ptr) == NULL)
419 return dir;
421 put_flags(proc, "nwtcl_flags", tcpcl_flags,
422 COUNT(tcpcl_flags), "0x%x", nwtcl->nwtcl_flags);
424 /* We pretend the unused nwtcl_ttl field does not exist. */
425 return IF_ALL;
427 case NWIOSTCPOPT:
428 case NWIOGTCPOPT:
429 if ((nwto = (nwio_tcpopt_t *)ptr) == NULL)
430 return dir;
432 put_flags(proc, "nwto_flags", tcpopt_flags,
433 COUNT(tcpopt_flags), "0x%x", nwto->nwto_flags);
434 return IF_ALL;
436 case NWIOTCPLISTENQ:
437 case NWIOSUDSBLOG:
438 if (ptr == NULL)
439 return IF_OUT;
441 put_value(proc, NULL, "%d", *(int *)ptr);
442 return IF_ALL;
444 case NWIOGTCPCOOKIE:
445 case NWIOTCPACCEPTTO:
446 if ((cookie = (tcp_cookie_t *)ptr) == NULL)
447 return dir;
449 put_value(proc, "tc_ref", "%"PRIu32, cookie->tc_ref);
450 if (verbose > 0)
451 put_buf(proc, "tc_secret", PF_LOCADDR,
452 (vir_bytes)&cookie->tc_secret,
453 sizeof(cookie->tc_secret));
454 return (verbose > 0) ? IF_ALL : 0;
456 case NWIOTCPGERROR:
457 if (ptr == NULL)
458 return IF_IN;
460 i = *(int *)ptr;
461 if (!valuesonly && (text = get_error_name(i)) != NULL)
462 put_field(proc, NULL, text);
463 else
464 put_value(proc, NULL, "%d", i);
465 return IF_ALL;
467 case NWIOSUDPOPT:
468 case NWIOGUDPOPT:
469 if ((nwuo = (nwio_udpopt_t *)ptr) == NULL)
470 return dir;
472 put_flags(proc, "nwuo_flags", udpopt_flags,
473 COUNT(udpopt_flags), "0x%x", nwuo->nwuo_flags);
475 /* The local address cannot be set, just retrieved. */
476 if (req == NWIOGUDPOPT)
477 put_ipaddr(proc, "nwuo_locaddr", nwuo->nwuo_locaddr);
479 if ((nwuo->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET)
480 put_port(proc, "nwuo_locport", nwuo->nwuo_locport);
482 if (nwuo->nwuo_flags & NWUO_RA_SET)
483 put_ipaddr(proc, "nwuo_remaddr", nwuo->nwuo_remaddr);
485 if (nwuo->nwuo_flags & NWUO_RP_SET)
486 put_port(proc, "nwuo_remport", nwuo->nwuo_remport);
488 return IF_ALL;
490 case NWIOGUDSFADDR:
491 case NWIOSUDSTADDR:
492 case NWIOSUDSADDR:
493 case NWIOGUDSADDR:
494 case NWIOGUDSPADDR:
495 case NWIOSUDSCONN:
496 case NWIOSUDSACCEPT:
497 if ((sun = (struct sockaddr_un *)ptr) == NULL)
498 return dir;
500 put_family(proc, "sun_family", sun->sun_family);
502 /* This could be extended to a generic sockaddr printer.. */
503 if (sun->sun_family == AF_LOCAL) {
504 put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH,
505 (vir_bytes)&sun->sun_path, sizeof(sun->sun_path));
506 return IF_ALL; /* skipping sun_len, it's unused */
507 } else
508 return 0;
510 case NWIOSUDSTYPE:
511 case NWIOGUDSSOTYPE:
512 if (ptr == NULL)
513 return dir;
515 put_flags(proc, NULL, sock_type, COUNT(sock_type), "0x%x",
516 *(int *)ptr);
517 return IF_ALL;
519 case NWIOSUDSSHUT:
520 if (ptr == NULL)
521 return IF_OUT;
523 put_shutdown_how(proc, NULL, *(int *)ptr);
524 return IF_ALL;
526 case NWIOSUDSPAIR:
527 if (ptr == NULL)
528 return IF_OUT;
530 put_dev(proc, NULL, *(dev_t *)ptr);
531 return IF_ALL;
533 case NWIOSUDSCTRL:
534 if (ptr == NULL)
535 return IF_OUT;
537 /* FALLTHROUGH */
538 case NWIOGUDSCTRL:
539 if (ptr == NULL)
540 return IF_IN;
542 put_msg_control(proc, (struct msg_control *)ptr);
543 return IF_ALL;
545 case NWIOGUDSPEERCRED:
546 if (ptr == NULL)
547 return IF_IN;
549 put_struct_uucred(proc, NULL, PF_LOCADDR, (vir_bytes)ptr);
550 return IF_ALL;
552 case NWIOGUDSSNDBUF:
553 case NWIOSUDSSNDBUF:
554 case NWIOGUDSRCVBUF:
555 case NWIOSUDSRCVBUF:
556 if (ptr == NULL)
557 return dir;
559 put_value(proc, NULL, "%zu", *(size_t *)ptr);
560 return IF_ALL;
562 default:
563 return 0;