netstat: Added family, protocol, and state filter options
* Uses the same option names as net-tools's netstat. Change-Id: I3363a091dfa1bcf09065f77d3fdc9c9bf27cbcaf Reviewed-on: https://review.haiku-os.org/c/haiku/+/1701 Reviewed-by: Adrien Destugues <pulkomandy@gmail.com>
This commit is contained in:
parent
96e64e6e14
commit
20a31c45b9
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
|
* Copyright 2006-2019, Haiku, Inc. All Rights Reserved.
|
||||||
* Distributed under the terms of the MIT License.
|
* Distributed under the terms of the MIT License.
|
||||||
*
|
*
|
||||||
* Authors:
|
* Authors:
|
||||||
@ -7,6 +7,7 @@
|
|||||||
* James Woodcock
|
* James Woodcock
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
@ -36,6 +37,24 @@ struct address_family {
|
|||||||
void (*print_address)(sockaddr* address);
|
void (*print_address)(sockaddr* address);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum filter_flags {
|
||||||
|
FILTER_FAMILY_MASK = 0x0000ff,
|
||||||
|
FILTER_PROTOCOL_MASK = 0x00ff00,
|
||||||
|
FILTER_STATE_MASK = 0xff0000,
|
||||||
|
|
||||||
|
// Families
|
||||||
|
FILTER_AF_INET = 0x000001,
|
||||||
|
FILTER_AF_INET6 = 0x000002,
|
||||||
|
FILTER_AF_UNIX = 0x000004,
|
||||||
|
|
||||||
|
// Protocols
|
||||||
|
FILTER_IPPROTO_TCP = 0x000100,
|
||||||
|
FILTER_IPPROTO_UDP = 0x000200,
|
||||||
|
|
||||||
|
// States
|
||||||
|
FILTER_STATE_LISTEN = 0x010000,
|
||||||
|
};
|
||||||
|
|
||||||
// AF_INET family
|
// AF_INET family
|
||||||
static void inet_print_address(sockaddr* address);
|
static void inet_print_address(sockaddr* address);
|
||||||
|
|
||||||
@ -99,10 +118,17 @@ inet_print_address(sockaddr* _address)
|
|||||||
void
|
void
|
||||||
usage(int status)
|
usage(int status)
|
||||||
{
|
{
|
||||||
printf("usage: %s [-nh]\n", kProgramName);
|
printf("Usage: %s [-nh]\n", kProgramName);
|
||||||
printf("options:\n");
|
printf("Options:\n");
|
||||||
printf(" -n don't resolve names\n");
|
printf(" -n don't resolve names\n");
|
||||||
printf(" -h this help\n");
|
printf(" -h this help\n");
|
||||||
|
printf("Filter options:\n");
|
||||||
|
printf(" -4 IPv4\n");
|
||||||
|
printf(" -6 IPv6\n");
|
||||||
|
printf(" -x Unix\n");
|
||||||
|
printf(" -t TCP\n");
|
||||||
|
printf(" -u UDP\n");
|
||||||
|
printf(" -l listen state\n");
|
||||||
|
|
||||||
exit(status);
|
exit(status);
|
||||||
}
|
}
|
||||||
@ -135,14 +161,27 @@ main(int argc, char** argv)
|
|||||||
{
|
{
|
||||||
int optionIndex = 0;
|
int optionIndex = 0;
|
||||||
int opt;
|
int opt;
|
||||||
static struct option longOptions[] = {
|
int filter = 0;
|
||||||
|
|
||||||
|
const static struct option kLongOptions[] = {
|
||||||
{"help", no_argument, 0, 'h'},
|
{"help", no_argument, 0, 'h'},
|
||||||
{"numeric", no_argument, 0, 'n'},
|
{"numeric", no_argument, 0, 'n'},
|
||||||
|
|
||||||
|
{"inet", no_argument, 0, '4'},
|
||||||
|
{"inet6", no_argument, 0, '6'},
|
||||||
|
{"unix", no_argument, 0, 'x'},
|
||||||
|
|
||||||
|
{"tcp", no_argument, 0, 't'},
|
||||||
|
{"udp", no_argument, 0, 'u'},
|
||||||
|
|
||||||
|
{"listen", no_argument, 0, 'l'},
|
||||||
|
|
||||||
{0, 0, 0, 0}
|
{0, 0, 0, 0}
|
||||||
};
|
};
|
||||||
|
|
||||||
do {
|
do {
|
||||||
opt = getopt_long(argc, argv, "hn", longOptions, &optionIndex);
|
opt = getopt_long(argc, argv, "hn46xtul", kLongOptions,
|
||||||
|
&optionIndex);
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case -1:
|
case -1:
|
||||||
// end of arguments, do nothing
|
// end of arguments, do nothing
|
||||||
@ -152,6 +191,28 @@ main(int argc, char** argv)
|
|||||||
sResolveNames = 0;
|
sResolveNames = 0;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Family filter
|
||||||
|
case '4':
|
||||||
|
filter |= FILTER_AF_INET;
|
||||||
|
break;
|
||||||
|
case '6':
|
||||||
|
filter |= FILTER_AF_INET6;
|
||||||
|
break;
|
||||||
|
case 'x':
|
||||||
|
filter |= FILTER_AF_UNIX;
|
||||||
|
break;
|
||||||
|
// Protocol filter
|
||||||
|
case 't':
|
||||||
|
filter |= FILTER_IPPROTO_TCP;
|
||||||
|
break;
|
||||||
|
case 'u':
|
||||||
|
filter |= FILTER_IPPROTO_UDP;
|
||||||
|
break;
|
||||||
|
// State filter
|
||||||
|
case 'l':
|
||||||
|
filter |= FILTER_STATE_LISTEN;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'h':
|
case 'h':
|
||||||
default:
|
default:
|
||||||
usage(0);
|
usage(0);
|
||||||
@ -169,6 +230,27 @@ main(int argc, char** argv)
|
|||||||
int family = -1;
|
int family = -1;
|
||||||
net_stat stat;
|
net_stat stat;
|
||||||
while (_kern_get_next_socket_stat(family, &cookie, &stat) == B_OK) {
|
while (_kern_get_next_socket_stat(family, &cookie, &stat) == B_OK) {
|
||||||
|
// Filter families
|
||||||
|
if ((filter & FILTER_FAMILY_MASK) != 0) {
|
||||||
|
if (((filter & FILTER_AF_INET) == 0 || family != AF_INET)
|
||||||
|
&& ((filter & FILTER_AF_INET6) == 0 || family != AF_INET6)
|
||||||
|
&& ((filter & FILTER_AF_UNIX) == 0 || family != AF_UNIX))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Filter protocols
|
||||||
|
if ((filter & FILTER_PROTOCOL_MASK) != 0) {
|
||||||
|
if (((filter & FILTER_IPPROTO_TCP) == 0
|
||||||
|
|| stat.protocol != IPPROTO_TCP)
|
||||||
|
&& ((filter & FILTER_IPPROTO_UDP) == 0
|
||||||
|
|| stat.protocol != IPPROTO_UDP))
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ((filter & FILTER_STATE_MASK) != 0) {
|
||||||
|
if ((filter & FILTER_STATE_LISTEN) == 0
|
||||||
|
|| strcmp(stat.state, "listen") != 0)
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
protoent* proto = getprotobynumber(stat.protocol);
|
protoent* proto = getprotobynumber(stat.protocol);
|
||||||
if (proto != NULL)
|
if (proto != NULL)
|
||||||
printf("%-6s ", proto->p_name);
|
printf("%-6s ", proto->p_name);
|
||||||
|
Loading…
Reference in New Issue
Block a user