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 in.s_addr = ipaddr; 112 113 put_in_addr(proc, name, in); 114 } 115 116 static void 117 put_ipproto(struct trace_proc * proc, const char * name, ipproto_t proto) 118 { 119 const char *text = NULL; 120 121 if (!valuesonly) { 122 switch (proto) { 123 TEXT(IPPROTO_ICMP); 124 TEXT(IPPROTO_TCP); 125 TEXT(IPPROTO_UDP); 126 } 127 } 128 129 if (text != NULL) 130 put_field(proc, name, text); 131 else 132 put_value(proc, name, "%u", proto); 133 } 134 135 static const struct flags tcpconf_flags[] = { 136 FLAG_ZERO(NWTC_NOFLAGS), 137 FLAG_MASK(NWTC_ACC_MASK, NWTC_EXCL), 138 FLAG_MASK(NWTC_ACC_MASK, NWTC_SHARED), 139 FLAG_MASK(NWTC_ACC_MASK, NWTC_COPY), 140 FLAG_MASK(NWTC_LOCPORT_MASK, NWTC_LP_UNSET), 141 FLAG_MASK(NWTC_LOCPORT_MASK, NWTC_LP_SET), 142 FLAG_MASK(NWTC_LOCPORT_MASK, NWTC_LP_SEL), 143 FLAG(NWTC_SET_RA), 144 FLAG(NWTC_UNSET_RA), 145 FLAG(NWTC_SET_RP), 146 FLAG(NWTC_UNSET_RP), 147 }; 148 149 #define put_port(proc, name, port) \ 150 put_value(proc, name, "%u", ntohs(port)) 151 152 static const struct flags tcpcl_flags[] = { 153 FLAG_ZERO(TCF_DEFAULT), 154 FLAG(TCF_ASYNCH), 155 }; 156 157 static const struct flags tcpopt_flags[] = { 158 FLAG_ZERO(NWTO_NOFLAG), 159 FLAG(NWTO_SND_URG), 160 FLAG(NWTO_SND_NOTURG), 161 FLAG(NWTO_RCV_URG), 162 FLAG(NWTO_RCV_NOTURG), 163 FLAG(NWTO_BSD_URG), 164 FLAG(NWTO_NOTBSD_URG), 165 FLAG(NWTO_DEL_RST), 166 FLAG(NWTO_BULK), 167 FLAG(NWTO_NOBULK), 168 }; 169 170 static const struct flags udpopt_flags[] = { 171 FLAG_ZERO(NWUO_NOFLAGS), 172 FLAG_MASK(NWUO_ACC_MASK, NWUO_EXCL), 173 FLAG_MASK(NWUO_ACC_MASK, NWUO_SHARED), 174 FLAG_MASK(NWUO_ACC_MASK, NWUO_COPY), 175 FLAG_MASK(NWUO_LOCPORT_MASK, NWUO_LP_SET), 176 FLAG_MASK(NWUO_LOCPORT_MASK, NWUO_LP_SEL), 177 FLAG_MASK(NWUO_LOCPORT_MASK, NWUO_LP_ANY), 178 FLAG(NWUO_EN_LOC), 179 FLAG(NWUO_DI_LOC), 180 FLAG(NWUO_EN_BROAD), 181 FLAG(NWUO_DI_BROAD), 182 FLAG(NWUO_RP_SET), 183 FLAG(NWUO_RP_ANY), 184 FLAG(NWUO_RA_SET), 185 FLAG(NWUO_RA_ANY), 186 FLAG(NWUO_RWDATONLY), 187 FLAG(NWUO_RWDATALL), 188 FLAG(NWUO_EN_IPOPT), 189 FLAG(NWUO_DI_IPOPT), 190 }; 191 192 static void 193 put_struct_uucred(struct trace_proc * proc, const char * name, int flags, 194 vir_bytes addr) 195 { 196 struct uucred cred; 197 198 if (!put_open_struct(proc, name, flags, addr, &cred, sizeof(cred))) 199 return; 200 201 put_value(proc, "cr_uid", "%u", cred.cr_uid); 202 if (verbose > 0) { 203 put_value(proc, "cr_gid", "%u", cred.cr_gid); 204 if (verbose > 1) 205 put_value(proc, "cr_ngroups", "%d", cred.cr_ngroups); 206 put_groups(proc, "cr_groups", PF_LOCADDR, 207 (vir_bytes)&cred.cr_groups, cred.cr_ngroups); 208 } 209 210 put_close_struct(proc, verbose > 0); 211 } 212 213 static void 214 put_msg_control(struct trace_proc * proc, struct msg_control * ptr) 215 { 216 struct msghdr msg; 217 struct cmsghdr *cmsg; 218 size_t len; 219 unsigned int i; 220 221 if (ptr->msg_controllen > sizeof(ptr->msg_control)) { 222 put_field(proc, NULL, ".."); 223 224 return; 225 } 226 227 put_open(proc, NULL, PF_NONAME, "[", ", "); 228 229 memset(&msg, 0, sizeof(msg)); 230 msg.msg_control = ptr->msg_control; 231 msg.msg_controllen = ptr->msg_controllen; 232 233 /* 234 * TODO: decide if we need a verbosity-based limit here. The argument 235 * in favor of printing everything is that upon receipt, SCM_RIGHTS 236 * actually creates new file descriptors, which is pretty essential in 237 * terms of figuring out what is happening in a process. In addition, 238 * these calls should be sufficiently rare that the lengthy output is 239 * not really disruptive for the general output flow. 240 */ 241 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 242 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 243 put_open(proc, NULL, 0, "{", ", "); 244 245 if (verbose > 0) 246 put_value(proc, "cmsg_len", "%u", cmsg->cmsg_len); 247 if (!valuesonly && cmsg->cmsg_level == SOL_SOCKET) 248 put_field(proc, "cmsg_level", "SOL_SOCKET"); 249 else 250 put_value(proc, "cmsg_level", "%d", cmsg->cmsg_level); 251 if (cmsg->cmsg_level == SOL_SOCKET) 252 put_cmsg_type(proc, "cmsg_type", cmsg->cmsg_type); 253 254 len = cmsg->cmsg_len - CMSG_LEN(0); 255 256 /* Print the contents of the messages that we know. */ 257 if (cmsg->cmsg_level == SOL_SOCKET && 258 cmsg->cmsg_type == SCM_RIGHTS) { 259 put_open(proc, NULL, PF_NONAME, "[", ", "); 260 for (i = 0; i < len / sizeof(int); i++) 261 put_fd(proc, NULL, 262 ((int *)CMSG_DATA(cmsg))[i]); 263 put_close(proc, "]"); 264 } else if (cmsg->cmsg_level == SOL_SOCKET && 265 cmsg->cmsg_type == SCM_CREDS) { 266 put_struct_uucred(proc, NULL, PF_LOCADDR, 267 (vir_bytes)CMSG_DATA(cmsg)); 268 } else if (len > 0) 269 put_field(proc, NULL, ".."); 270 271 put_close(proc, "}"); 272 } 273 274 put_close(proc, "]"); 275 } 276 277 int 278 net_ioctl_arg(struct trace_proc * proc, unsigned long req, void * ptr, int dir) 279 { 280 const char *text; 281 nwio_ipopt_t *ipopt; 282 nwio_tcpconf_t *nwtc; 283 nwio_tcpcl_t *nwtcl; 284 nwio_tcpopt_t *nwto; 285 tcp_cookie_t *cookie; 286 nwio_udpopt_t *nwuo; 287 struct sockaddr_un *sun; 288 int i; 289 290 switch (req) { 291 case FIONREAD: 292 /* 293 * Arguably this does not belong here, but as of writing, the 294 * network services are the only ones actually implementing 295 * support for this IOCTL, and we don't have a more suitable 296 * place to put it either. 297 */ 298 if (ptr == NULL) 299 return IF_IN; 300 301 put_value(proc, NULL, "%d", *(int *)ptr); 302 return IF_ALL; 303 304 case NWIOSIPOPT: 305 case NWIOGIPOPT: 306 if ((ipopt = (nwio_ipopt_t *)ptr) == NULL) 307 return dir; 308 309 put_flags(proc, "nwio_flags", ipopt_flags, COUNT(ipopt_flags), 310 "0x%x", ipopt->nwio_flags); 311 312 if (ipopt->nwio_flags & NWIO_REMSPEC) 313 put_ipaddr(proc, "nwio_rem", ipopt->nwio_rem); 314 if (ipopt->nwio_flags & NWIO_PROTOSPEC) 315 put_ipproto(proc, "nwio_proto", ipopt->nwio_proto); 316 317 return 0; /* TODO: the remaining fields */ 318 319 case NWIOSTCPCONF: 320 case NWIOGTCPCONF: 321 if ((nwtc = (nwio_tcpconf_t *)ptr) == NULL) 322 return dir; 323 324 put_flags(proc, "nwtc_flags", tcpconf_flags, 325 COUNT(tcpconf_flags), "0x%x", nwtc->nwtc_flags); 326 327 /* The local address cannot be set, just retrieved. */ 328 if (req == NWIOGTCPCONF) 329 put_ipaddr(proc, "nwtc_locaddr", nwtc->nwtc_locaddr); 330 331 if ((nwtc->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET) 332 put_port(proc, "nwtc_locport", nwtc->nwtc_locport); 333 334 if (nwtc->nwtc_flags & NWTC_SET_RA) 335 put_ipaddr(proc, "nwtc_remaddr", nwtc->nwtc_remaddr); 336 337 if (nwtc->nwtc_flags & NWTC_SET_RP) 338 put_port(proc, "nwtc_remport", nwtc->nwtc_remport); 339 340 return IF_ALL; 341 342 case NWIOTCPCONN: 343 case NWIOTCPLISTEN: 344 if ((nwtcl = (nwio_tcpcl_t *)ptr) == NULL) 345 return dir; 346 347 put_flags(proc, "nwtcl_flags", tcpcl_flags, 348 COUNT(tcpcl_flags), "0x%x", nwtcl->nwtcl_flags); 349 350 /* We pretend the unused nwtcl_ttl field does not exist. */ 351 return IF_ALL; 352 353 case NWIOSTCPOPT: 354 case NWIOGTCPOPT: 355 if ((nwto = (nwio_tcpopt_t *)ptr) == NULL) 356 return dir; 357 358 put_flags(proc, "nwto_flags", tcpopt_flags, 359 COUNT(tcpopt_flags), "0x%x", nwto->nwto_flags); 360 return IF_ALL; 361 362 case NWIOTCPLISTENQ: 363 case NWIOSUDSBLOG: 364 if (ptr == NULL) 365 return IF_OUT; 366 367 put_value(proc, NULL, "%d", *(int *)ptr); 368 return IF_ALL; 369 370 case NWIOGTCPCOOKIE: 371 case NWIOTCPACCEPTTO: 372 if ((cookie = (tcp_cookie_t *)ptr) == NULL) 373 return dir; 374 375 put_value(proc, "tc_ref", "%"PRIu32, cookie->tc_ref); 376 if (verbose > 0) 377 put_buf(proc, "tc_secret", PF_LOCADDR, 378 (vir_bytes)&cookie->tc_secret, 379 sizeof(cookie->tc_secret)); 380 return (verbose > 0) ? IF_ALL : 0; 381 382 case NWIOTCPGERROR: 383 if (ptr == NULL) 384 return IF_IN; 385 386 i = *(int *)ptr; 387 if (!valuesonly && (text = get_error_name(i)) != NULL) 388 put_field(proc, NULL, text); 389 else 390 put_value(proc, NULL, "%d", i); 391 return IF_ALL; 392 393 case NWIOSUDPOPT: 394 case NWIOGUDPOPT: 395 if ((nwuo = (nwio_udpopt_t *)ptr) == NULL) 396 return dir; 397 398 put_flags(proc, "nwuo_flags", udpopt_flags, 399 COUNT(udpopt_flags), "0x%x", nwuo->nwuo_flags); 400 401 /* The local address cannot be set, just retrieved. */ 402 if (req == NWIOGUDPOPT) 403 put_ipaddr(proc, "nwuo_locaddr", nwuo->nwuo_locaddr); 404 405 if ((nwuo->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET) 406 put_port(proc, "nwuo_locport", nwuo->nwuo_locport); 407 408 if (nwuo->nwuo_flags & NWUO_RA_SET) 409 put_ipaddr(proc, "nwuo_remaddr", nwuo->nwuo_remaddr); 410 411 if (nwuo->nwuo_flags & NWUO_RP_SET) 412 put_port(proc, "nwuo_remport", nwuo->nwuo_remport); 413 414 return IF_ALL; 415 416 case NWIOGUDSFADDR: 417 case NWIOSUDSTADDR: 418 case NWIOSUDSADDR: 419 case NWIOGUDSADDR: 420 case NWIOGUDSPADDR: 421 case NWIOSUDSCONN: 422 case NWIOSUDSACCEPT: 423 if ((sun = (struct sockaddr_un *)ptr) == NULL) 424 return dir; 425 426 put_socket_family(proc, "sun_family", sun->sun_family); 427 428 /* This could be extended to a generic sockaddr printer.. */ 429 if (sun->sun_family == AF_LOCAL) { 430 put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH, 431 (vir_bytes)&sun->sun_path, sizeof(sun->sun_path)); 432 return IF_ALL; /* skipping sun_len, it's unused */ 433 } else 434 return 0; 435 436 case NWIOSUDSTYPE: 437 case NWIOGUDSSOTYPE: 438 if (ptr == NULL) 439 return dir; 440 441 put_socket_type(proc, NULL, *(int *)ptr); 442 return IF_ALL; 443 444 case NWIOSUDSSHUT: 445 if (ptr == NULL) 446 return IF_OUT; 447 448 put_shutdown_how(proc, NULL, *(int *)ptr); 449 return IF_ALL; 450 451 case NWIOSUDSPAIR: 452 if (ptr == NULL) 453 return IF_OUT; 454 455 put_dev(proc, NULL, *(dev_t *)ptr); 456 return IF_ALL; 457 458 case NWIOSUDSCTRL: 459 if (ptr == NULL) 460 return IF_OUT; 461 462 /* FALLTHROUGH */ 463 case NWIOGUDSCTRL: 464 if (ptr == NULL) 465 return IF_IN; 466 467 put_msg_control(proc, (struct msg_control *)ptr); 468 return IF_ALL; 469 470 case NWIOGUDSPEERCRED: 471 if (ptr == NULL) 472 return IF_IN; 473 474 put_struct_uucred(proc, NULL, PF_LOCADDR, (vir_bytes)ptr); 475 return IF_ALL; 476 477 case NWIOGUDSSNDBUF: 478 case NWIOSUDSSNDBUF: 479 case NWIOGUDSRCVBUF: 480 case NWIOSUDSRCVBUF: 481 if (ptr == NULL) 482 return dir; 483 484 put_value(proc, NULL, "%zu", *(size_t *)ptr); 485 return IF_ALL; 486 487 default: 488 return 0; 489 } 490 } 491