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_msg_control(struct trace_proc * proc, struct msg_control * ptr) 194 { 195 struct msghdr msg; 196 struct cmsghdr *cmsg; 197 size_t len; 198 unsigned int i; 199 200 if (ptr->msg_controllen > sizeof(ptr->msg_control)) { 201 put_field(proc, NULL, ".."); 202 203 return; 204 } 205 206 put_open(proc, NULL, PF_NONAME, "[", ", "); 207 208 memset(&msg, 0, sizeof(msg)); 209 msg.msg_control = ptr->msg_control; 210 msg.msg_controllen = ptr->msg_controllen; 211 212 /* 213 * TODO: decide if we need a verbosity-based limit here. The argument 214 * in favor of printing everything is that upon receipt, SCM_RIGHTS 215 * actually creates new file descriptors, which is pretty essential in 216 * terms of figuring out what is happening in a process. In addition, 217 * these calls should be sufficiently rare that the lengthy output is 218 * not really disruptive for the general output flow. 219 */ 220 for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; 221 cmsg = CMSG_NXTHDR(&msg, cmsg)) { 222 put_open(proc, NULL, 0, "{", ", "); 223 224 if (verbose > 0) 225 put_value(proc, "cmsg_len", "%u", cmsg->cmsg_len); 226 if (!valuesonly && cmsg->cmsg_level == SOL_SOCKET) 227 put_field(proc, "cmsg_level", "SOL_SOCKET"); 228 else 229 put_value(proc, "cmsg_level", "%d", cmsg->cmsg_level); 230 if (cmsg->cmsg_level == SOL_SOCKET) 231 put_cmsg_type(proc, "cmsg_type", cmsg->cmsg_type); 232 233 len = cmsg->cmsg_len - CMSG_LEN(0); 234 235 /* Print the contents of the messages that we know. */ 236 if (cmsg->cmsg_level == SOL_SOCKET && 237 cmsg->cmsg_type == SCM_RIGHTS) { 238 put_open(proc, NULL, PF_NONAME, "[", ", "); 239 for (i = 0; i < len / sizeof(int); i++) 240 put_fd(proc, NULL, 241 ((int *)CMSG_DATA(cmsg))[i]); 242 put_close(proc, "]"); 243 } else if (cmsg->cmsg_level == SOL_SOCKET && 244 cmsg->cmsg_type == SCM_CREDS) { 245 put_struct_uucred(proc, NULL, PF_LOCADDR, 246 (vir_bytes)CMSG_DATA(cmsg)); 247 } else if (len > 0) 248 put_field(proc, NULL, ".."); 249 250 put_close(proc, "}"); 251 } 252 253 put_close(proc, "]"); 254 } 255 256 int 257 net_ioctl_arg(struct trace_proc * proc, unsigned long req, void * ptr, int dir) 258 { 259 const char *text; 260 nwio_ipopt_t *ipopt; 261 nwio_tcpconf_t *nwtc; 262 nwio_tcpcl_t *nwtcl; 263 nwio_tcpopt_t *nwto; 264 tcp_cookie_t *cookie; 265 nwio_udpopt_t *nwuo; 266 struct sockaddr_un *sun; 267 int i; 268 269 switch (req) { 270 case FIONREAD: 271 /* 272 * Arguably this does not belong here, but as of writing, the 273 * network services are the only ones actually implementing 274 * support for this IOCTL, and we don't have a more suitable 275 * place to put it either. 276 */ 277 if (ptr == NULL) 278 return IF_IN; 279 280 put_value(proc, NULL, "%d", *(int *)ptr); 281 return IF_ALL; 282 283 case NWIOSIPOPT: 284 case NWIOGIPOPT: 285 if ((ipopt = (nwio_ipopt_t *)ptr) == NULL) 286 return dir; 287 288 put_flags(proc, "nwio_flags", ipopt_flags, COUNT(ipopt_flags), 289 "0x%x", ipopt->nwio_flags); 290 291 if (ipopt->nwio_flags & NWIO_REMSPEC) 292 put_ipaddr(proc, "nwio_rem", ipopt->nwio_rem); 293 if (ipopt->nwio_flags & NWIO_PROTOSPEC) 294 put_ipproto(proc, "nwio_proto", ipopt->nwio_proto); 295 296 return 0; /* TODO: the remaining fields */ 297 298 case NWIOSTCPCONF: 299 case NWIOGTCPCONF: 300 if ((nwtc = (nwio_tcpconf_t *)ptr) == NULL) 301 return dir; 302 303 put_flags(proc, "nwtc_flags", tcpconf_flags, 304 COUNT(tcpconf_flags), "0x%x", nwtc->nwtc_flags); 305 306 /* The local address cannot be set, just retrieved. */ 307 if (req == NWIOGTCPCONF) 308 put_ipaddr(proc, "nwtc_locaddr", nwtc->nwtc_locaddr); 309 310 if ((nwtc->nwtc_flags & NWTC_LOCPORT_MASK) == NWTC_LP_SET) 311 put_port(proc, "nwtc_locport", nwtc->nwtc_locport); 312 313 if (nwtc->nwtc_flags & NWTC_SET_RA) 314 put_ipaddr(proc, "nwtc_remaddr", nwtc->nwtc_remaddr); 315 316 if (nwtc->nwtc_flags & NWTC_SET_RP) 317 put_port(proc, "nwtc_remport", nwtc->nwtc_remport); 318 319 return IF_ALL; 320 321 case NWIOTCPCONN: 322 case NWIOTCPLISTEN: 323 if ((nwtcl = (nwio_tcpcl_t *)ptr) == NULL) 324 return dir; 325 326 put_flags(proc, "nwtcl_flags", tcpcl_flags, 327 COUNT(tcpcl_flags), "0x%x", nwtcl->nwtcl_flags); 328 329 /* We pretend the unused nwtcl_ttl field does not exist. */ 330 return IF_ALL; 331 332 case NWIOSTCPOPT: 333 case NWIOGTCPOPT: 334 if ((nwto = (nwio_tcpopt_t *)ptr) == NULL) 335 return dir; 336 337 put_flags(proc, "nwto_flags", tcpopt_flags, 338 COUNT(tcpopt_flags), "0x%x", nwto->nwto_flags); 339 return IF_ALL; 340 341 case NWIOTCPLISTENQ: 342 case NWIOSUDSBLOG: 343 if (ptr == NULL) 344 return IF_OUT; 345 346 put_value(proc, NULL, "%d", *(int *)ptr); 347 return IF_ALL; 348 349 case NWIOGTCPCOOKIE: 350 case NWIOTCPACCEPTTO: 351 if ((cookie = (tcp_cookie_t *)ptr) == NULL) 352 return dir; 353 354 put_value(proc, "tc_ref", "%"PRIu32, cookie->tc_ref); 355 if (verbose > 0) 356 put_buf(proc, "tc_secret", PF_LOCADDR, 357 (vir_bytes)&cookie->tc_secret, 358 sizeof(cookie->tc_secret)); 359 return (verbose > 0) ? IF_ALL : 0; 360 361 case NWIOTCPGERROR: 362 if (ptr == NULL) 363 return IF_IN; 364 365 i = *(int *)ptr; 366 if (!valuesonly && (text = get_error_name(i)) != NULL) 367 put_field(proc, NULL, text); 368 else 369 put_value(proc, NULL, "%d", i); 370 return IF_ALL; 371 372 case NWIOSUDPOPT: 373 case NWIOGUDPOPT: 374 if ((nwuo = (nwio_udpopt_t *)ptr) == NULL) 375 return dir; 376 377 put_flags(proc, "nwuo_flags", udpopt_flags, 378 COUNT(udpopt_flags), "0x%x", nwuo->nwuo_flags); 379 380 /* The local address cannot be set, just retrieved. */ 381 if (req == NWIOGUDPOPT) 382 put_ipaddr(proc, "nwuo_locaddr", nwuo->nwuo_locaddr); 383 384 if ((nwuo->nwuo_flags & NWUO_LOCPORT_MASK) == NWUO_LP_SET) 385 put_port(proc, "nwuo_locport", nwuo->nwuo_locport); 386 387 if (nwuo->nwuo_flags & NWUO_RA_SET) 388 put_ipaddr(proc, "nwuo_remaddr", nwuo->nwuo_remaddr); 389 390 if (nwuo->nwuo_flags & NWUO_RP_SET) 391 put_port(proc, "nwuo_remport", nwuo->nwuo_remport); 392 393 return IF_ALL; 394 395 case NWIOGUDSFADDR: 396 case NWIOSUDSTADDR: 397 case NWIOSUDSADDR: 398 case NWIOGUDSADDR: 399 case NWIOGUDSPADDR: 400 case NWIOSUDSCONN: 401 case NWIOSUDSACCEPT: 402 if ((sun = (struct sockaddr_un *)ptr) == NULL) 403 return dir; 404 405 put_socket_family(proc, "sun_family", sun->sun_family); 406 407 /* This could be extended to a generic sockaddr printer.. */ 408 if (sun->sun_family == AF_LOCAL) { 409 put_buf(proc, "sun_path", PF_LOCADDR | PF_PATH, 410 (vir_bytes)&sun->sun_path, sizeof(sun->sun_path)); 411 return IF_ALL; /* skipping sun_len, it's unused */ 412 } else 413 return 0; 414 415 case NWIOSUDSTYPE: 416 case NWIOGUDSSOTYPE: 417 if (ptr == NULL) 418 return dir; 419 420 put_socket_type(proc, NULL, *(int *)ptr); 421 return IF_ALL; 422 423 case NWIOSUDSSHUT: 424 if (ptr == NULL) 425 return IF_OUT; 426 427 put_shutdown_how(proc, NULL, *(int *)ptr); 428 return IF_ALL; 429 430 case NWIOSUDSPAIR: 431 if (ptr == NULL) 432 return IF_OUT; 433 434 put_dev(proc, NULL, *(dev_t *)ptr); 435 return IF_ALL; 436 437 case NWIOSUDSCTRL: 438 if (ptr == NULL) 439 return IF_OUT; 440 441 /* FALLTHROUGH */ 442 case NWIOGUDSCTRL: 443 if (ptr == NULL) 444 return IF_IN; 445 446 put_msg_control(proc, (struct msg_control *)ptr); 447 return IF_ALL; 448 449 case NWIOGUDSPEERCRED: 450 if (ptr == NULL) 451 return IF_IN; 452 453 put_struct_uucred(proc, NULL, PF_LOCADDR, (vir_bytes)ptr); 454 return IF_ALL; 455 456 case NWIOGUDSSNDBUF: 457 case NWIOSUDSSNDBUF: 458 case NWIOGUDSRCVBUF: 459 case NWIOSUDSRCVBUF: 460 if (ptr == NULL) 461 return dir; 462 463 put_value(proc, NULL, "%zu", *(size_t *)ptr); 464 return IF_ALL; 465 466 default: 467 return 0; 468 } 469 } 470