1 2 #include "inc.h" 3 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> 19 20 const char * 21 net_ioctl_name(unsigned long req) 22 { 23 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); 82 } 83 84 return NULL; 85 } 86 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), 104 }; 105 106 static void 107 put_ipaddr(struct trace_proc * proc, const char * name, ipaddr_t ipaddr) 108 { 109 struct in_addr in; 110 111 if (!valuesonly) { 112 in.s_addr = ipaddr; 113 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)); 118 } 119 120 static void 121 put_ipproto(struct trace_proc * proc, const char * name, ipproto_t proto) 122 { 123 const char *text = NULL; 124 125 if (!valuesonly) { 126 switch (proto) { 127 TEXT(IPPROTO_ICMP); 128 TEXT(IPPROTO_TCP); 129 TEXT(IPPROTO_UDP); 130 } 131 } 132 133 if (text != NULL) 134 put_field(proc, name, text); 135 else 136 put_value(proc, name, "%u", proto); 137 } 138 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), 151 }; 152 153 #define put_port(proc, name, port) \ 154 put_value(proc, name, "%u", ntohs(port)) 155 156 static const struct flags tcpcl_flags[] = { 157 FLAG_ZERO(TCF_DEFAULT), 158 FLAG(TCF_ASYNCH), 159 }; 160 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), 172 }; 173 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), 194 }; 195 196 static void 197 put_family(struct trace_proc * proc, const char * name, int family) 198 { 199 const char *text = NULL; 200 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); 208 } 209 } 210 211 if (text != NULL) 212 put_field(proc, name, text); 213 else 214 put_value(proc, name, "%d", family); 215 } 216 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), 226 }; 227 228 static void 229 put_shutdown_how(struct trace_proc * proc, const char * name, int how) 230 { 231 const char *text = NULL; 232 233 if (!valuesonly) { 234 switch (how) { 235 TEXT(SHUT_RD); 236 TEXT(SHUT_WR); 237 TEXT(SHUT_RDWR); 238 } 239 } 240 241 if (text != NULL) 242 put_field(proc, name, text); 243 else 244 put_value(proc, name, "%d", how); 245 } 246 247 static void 248 put_struct_uucred(struct trace_proc * proc, const char * name, int flags, 249 vir_bytes addr) 250 { 251 struct uucred cred; 252 253 if (!put_open_struct(proc, name, flags, addr, &cred, sizeof(cred))) 254 return; 255 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); 263 } 264 265 put_close_struct(proc, verbose > 0); 266 } 267 268 static void 269 put_cmsg_type(struct trace_proc * proc, const char * name, int type) 270 { 271 const char *text = NULL; 272 273 if (!valuesonly) { 274 switch (type) { 275 TEXT(SCM_RIGHTS); 276 TEXT(SCM_CREDS); 277 TEXT(SCM_TIMESTAMP); 278 } 279 } 280 281 if (text != NULL) 282 put_field(proc, name, text); 283 else 284 put_value(proc, name, "%d", type); 285 } 286 287 static void 288 put_msg_control(struct trace_proc * proc, struct msg_control * ptr) 289 { 290 struct msghdr msg; 291 struct cmsghdr *cmsg; 292 size_t len; 293 unsigned int i; 294 295 if (ptr->msg_controllen > sizeof(ptr->msg_control)) { 296 put_field(proc, NULL, ".."); 297 298 return; 299 } 300 301 put_open(proc, NULL, PF_NONAME, "[", ", "); 302 303 memset(&msg, 0, sizeof(msg)); 304 msg.msg_control = ptr->msg_control; 305 msg.msg_controllen = ptr->msg_controllen; 306 307 /* 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. 314 */ 315 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 316 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 317 put_open(proc, NULL, 0, "{", ", "); 318 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); 327 328 len = cmsg->cmsg_len - CMSG_LEN(0); 329 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, ".."); 344 345 put_close(proc, "}"); 346 } 347 348 put_close(proc, "]"); 349 } 350 351 int 352 net_ioctl_arg(struct trace_proc * proc, unsigned long req, void * ptr, int dir) 353 { 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; 363 364 switch (req) { 365 case FIONREAD: 366 /* 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. 371 */ 372 if (ptr == NULL) 373 return IF_IN; 374 375 put_value(proc, NULL, "%d", *(int *)ptr); 376 return IF_ALL; 377 378 case NWIOSIPOPT: 379 case NWIOGIPOPT: 380 if ((ipopt = (nwio_ipopt_t *)ptr) == NULL) 381 return dir; 382 383 put_flags(proc, "nwio_flags", ipopt_flags, COUNT(ipopt_flags), 384 "0x%x", ipopt->nwio_flags); 385 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); 390 391 return 0; /* TODO: the remaining fields */ 392 393 case NWIOSTCPCONF: 394 case NWIOGTCPCONF: 395 if ((nwtc = (nwio_tcpconf_t *)ptr) == NULL) 396 return dir; 397 398 put_flags(proc, "nwtc_flags", tcpconf_flags, 399 COUNT(tcpconf_flags), "0x%x", nwtc->nwtc_flags); 400 401 /* The local address cannot be set, just retrieved. */ 402 if (req == NWIOGTCPCONF) 403 put_ipaddr(proc, "nwtc_locaddr", nwtc->nwtc_locaddr); 404 405 if ((nwtc->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET) 406 put_port(proc, "nwtc_locport", nwtc->nwtc_locport); 407 408 if (nwtc->nwtc_flags & NWTC_SET_RA) 409 put_ipaddr(proc, "nwtc_remaddr", nwtc->nwtc_remaddr); 410 411 if (nwtc->nwtc_flags & NWTC_SET_RP) 412 put_port(proc, "nwtc_remport", nwtc->nwtc_remport); 413 414 return IF_ALL; 415 416 case NWIOTCPCONN: 417 case NWIOTCPLISTEN: 418 if ((nwtcl = (nwio_tcpcl_t *)ptr) == NULL) 419 return dir; 420 421 put_flags(proc, "nwtcl_flags", tcpcl_flags, 422 COUNT(tcpcl_flags), "0x%x", nwtcl->nwtcl_flags); 423 424 /* We pretend the unused nwtcl_ttl field does not exist. */ 425 return IF_ALL; 426 427 case NWIOSTCPOPT: 428 case NWIOGTCPOPT: 429 if ((nwto = (nwio_tcpopt_t *)ptr) == NULL) 430 return dir; 431 432 put_flags(proc, "nwto_flags", tcpopt_flags, 433 COUNT(tcpopt_flags), "0x%x", nwto->nwto_flags); 434 return IF_ALL; 435 436 case NWIOTCPLISTENQ: 437 case NWIOSUDSBLOG: 438 if (ptr == NULL) 439 return IF_OUT; 440 441 put_value(proc, NULL, "%d", *(int *)ptr); 442 return IF_ALL; 443 444 case NWIOGTCPCOOKIE: 445 case NWIOTCPACCEPTTO: 446 if ((cookie = (tcp_cookie_t *)ptr) == NULL) 447 return dir; 448 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; 455 456 case NWIOTCPGERROR: 457 if (ptr == NULL) 458 return IF_IN; 459 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; 466 467 case NWIOSUDPOPT: 468 case NWIOGUDPOPT: 469 if ((nwuo = (nwio_udpopt_t *)ptr) == NULL) 470 return dir; 471 472 put_flags(proc, "nwuo_flags", udpopt_flags, 473 COUNT(udpopt_flags), "0x%x", nwuo->nwuo_flags); 474 475 /* The local address cannot be set, just retrieved. */ 476 if (req == NWIOGUDPOPT) 477 put_ipaddr(proc, "nwuo_locaddr", nwuo->nwuo_locaddr); 478 479 if ((nwuo->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET) 480 put_port(proc, "nwuo_locport", nwuo->nwuo_locport); 481 482 if (nwuo->nwuo_flags & NWUO_RA_SET) 483 put_ipaddr(proc, "nwuo_remaddr", nwuo->nwuo_remaddr); 484 485 if (nwuo->nwuo_flags & NWUO_RP_SET) 486 put_port(proc, "nwuo_remport", nwuo->nwuo_remport); 487 488 return IF_ALL; 489 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; 499 500 put_family(proc, "sun_family", sun->sun_family); 501 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; 509 510 case NWIOSUDSTYPE: 511 case NWIOGUDSSOTYPE: 512 if (ptr == NULL) 513 return dir; 514 515 put_flags(proc, NULL, sock_type, COUNT(sock_type), "0x%x", 516 *(int *)ptr); 517 return IF_ALL; 518 519 case NWIOSUDSSHUT: 520 if (ptr == NULL) 521 return IF_OUT; 522 523 put_shutdown_how(proc, NULL, *(int *)ptr); 524 return IF_ALL; 525 526 case NWIOSUDSPAIR: 527 if (ptr == NULL) 528 return IF_OUT; 529 530 put_dev(proc, NULL, *(dev_t *)ptr); 531 return IF_ALL; 532 533 case NWIOSUDSCTRL: 534 if (ptr == NULL) 535 return IF_OUT; 536 537 /* FALLTHROUGH */ 538 case NWIOGUDSCTRL: 539 if (ptr == NULL) 540 return IF_IN; 541 542 put_msg_control(proc, (struct msg_control *)ptr); 543 return IF_ALL; 544 545 case NWIOGUDSPEERCRED: 546 if (ptr == NULL) 547 return IF_IN; 548 549 put_struct_uucred(proc, NULL, PF_LOCADDR, (vir_bytes)ptr); 550 return IF_ALL; 551 552 case NWIOGUDSSNDBUF: 553 case NWIOSUDSSNDBUF: 554 case NWIOGUDSRCVBUF: 555 case NWIOSUDSRCVBUF: 556 if (ptr == NULL) 557 return dir; 558 559 put_value(proc, NULL, "%zu", *(size_t *)ptr); 560 return IF_ALL; 561 562 default: 563 return 0; 564 } 565 } 566