/* * call-seq: * Raindrops::Linux.tcp_listener_stats([addrs[, sock]]) => hash * * If specified, +addr+ may be a string or array of strings representing * listen addresses to filter for. Returns a hash with given addresses as * keys and ListenStats objects as the values or a hash of all addresses. * * addrs = %w(0.0.0.0:80 127.0.0.1:8080) * * If +addr+ is nil or not specified, all (IPv4) addresses are returned. * If +sock+ is specified, it should be a Raindrops::InetDiagSock object. */ static VALUE tcp_listener_stats(int argc, VALUE *argv, VALUE self) { VALUE rv = rb_hash_new(); struct nogvl_args args; VALUE addrs, sock; rb_scan_args(argc, argv, "02", &addrs, &sock); /* * allocating page_size instead of OP_LEN since we'll reuse the * buffer for recvmsg() later, we already checked for * OPLEN <= page_size at initialization */ args.iov[2].iov_len = OPLEN; args.iov[2].iov_base = alloca(page_size); args.table = NULL; if (NIL_P(sock)) sock = rb_funcall(cIDSock, id_new, 0); args.fd = my_fileno(sock); switch (TYPE(addrs)) { case T_STRING: rb_hash_aset(rv, addrs, tcp_stats(&args, addrs)); return rv; case T_ARRAY: { long i; long len = RARRAY_LEN(addrs); VALUE cur; if (len == 1) { cur = rb_ary_entry(addrs, 0); rb_hash_aset(rv, cur, tcp_stats(&args, cur)); return rv; } for (i = 0; i < len; i++) { union any_addr check; VALUE cur = rb_ary_entry(addrs, i); parse_addr(&check, cur); rb_hash_aset(rv, cur, Qtrue); } /* fall through */ } case T_NIL: args.table = st_init_strtable(); gen_bytecode_all(&args.iov[2]); break; default: rb_raise(rb_eArgError, "addr must be an array of strings, a string, or nil"); } nl_errcheck(rb_thread_io_blocking_region(diag, &args, args.fd)); st_foreach(args.table, NIL_P(addrs) ? st_to_hash : st_AND_hash, rv); st_free_table(args.table); /* let GC deal with corner cases */ if (argc < 2) rb_io_close(sock); return rv; }
/* FUNCTION: prot_stat() * * Display protocol statistics for TCP, UDP, ICMP, ICMPv6, IPv4, and IPv6. * * PARAM1: CLI_CTX CLI context * * RETURNS: int 0 if successful, otherwise error code * */ STATIC int prot_stat(CLI_CTX ctx) { GIO *gio = ctx->gio; char *pstr = NULL; u_char prot = NO_IPPROTO; int dump_all = FALSE; int i; if (CLI_DEFINED(ctx, 'p')) { pstr = (char *)CLI_VALUE(ctx, 'p'); for (i = 0; i < sizeof(npt) / sizeof(struct netprot); ++i) { if (!stricmp(pstr, npt[i].name)) { prot = npt[i].prot_id; break; } } } else { /* dump information for all protocols (TCP, UDP, ICMP, ICMPv6, * IPv4, and IPv6) */ dump_all = TRUE; } if ((prot == NO_IPPROTO) && !dump_all) { return (CLI_ERR_PARAM); } else { #ifdef IP_V4 if ((prot == IPPROTO_ICMP) || dump_all) icmp_stats(gio); #ifdef NET_STATS if ((prot == IPPROTO_IP) || dump_all) { ip_stats(gio); ipr_stats(gio); } #endif #endif #if defined(IP_V6) && defined(IP6_MENUS) if ((prot == IPPROTO_ICMPV6) || dump_all) icmp6_mib(ctx); if ((prot == IPPROTO_IPV6) || dump_all) ip6_ipmib(ctx); #endif if ((prot == IPPROTO_TCP) || dump_all) tcp_stats(gio); #ifdef IP_V4 if ((prot == IPPROTO_UDP) || dump_all) udp_stats(gio); #endif } return (0); }