* Exports the syncache entries to userland so that netstat can display * them alongside the other sockets. This function is intended to be * called only from tcp_pcblist. * * Due to concurrency on an active system, the number of pcbs exported * may have no relation to max_pcbs. max_pcbs merely indicates the * amount of space the caller allocated for this function to use. */
| 2552 | * amount of space the caller allocated for this function to use. |
| 2553 | */ |
| 2554 | int |
| 2555 | syncache_pcblist(struct sysctl_req *req) |
| 2556 | { |
| 2557 | struct xtcpcb xt; |
| 2558 | struct syncache *sc; |
| 2559 | struct syncache_head *sch; |
| 2560 | int error, i; |
| 2561 | |
| 2562 | bzero(&xt, sizeof(xt)); |
| 2563 | xt.xt_len = sizeof(xt); |
| 2564 | xt.t_state = TCPS_SYN_RECEIVED; |
| 2565 | xt.xt_inp.xi_socket.xso_protocol = IPPROTO_TCP; |
| 2566 | xt.xt_inp.xi_socket.xso_len = sizeof (struct xsocket); |
| 2567 | xt.xt_inp.xi_socket.so_type = SOCK_STREAM; |
| 2568 | xt.xt_inp.xi_socket.so_state = SS_ISCONNECTING; |
| 2569 | |
| 2570 | for (i = 0; i < V_tcp_syncache.hashsize; i++) { |
| 2571 | sch = &V_tcp_syncache.hashbase[i]; |
| 2572 | SCH_LOCK(sch); |
| 2573 | TAILQ_FOREACH(sc, &sch->sch_bucket, sc_hash) { |
| 2574 | if (cr_cansee(req->td->td_ucred, sc->sc_cred) != 0) |
| 2575 | continue; |
| 2576 | if (sc->sc_inc.inc_flags & INC_ISIPV6) |
| 2577 | xt.xt_inp.inp_vflag = INP_IPV6; |
| 2578 | else |
| 2579 | xt.xt_inp.inp_vflag = INP_IPV4; |
| 2580 | bcopy(&sc->sc_inc, &xt.xt_inp.inp_inc, |
| 2581 | sizeof (struct in_conninfo)); |
| 2582 | error = SYSCTL_OUT(req, &xt, sizeof xt); |
| 2583 | if (error) { |
| 2584 | SCH_UNLOCK(sch); |
| 2585 | return (0); |
| 2586 | } |
| 2587 | } |
| 2588 | SCH_UNLOCK(sch); |
| 2589 | } |
| 2590 | |
| 2591 | return (0); |
| 2592 | } |
no test coverage detected