* Implemented a basic infrastructure for a netstat command.

* Started a netstat command.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19560 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2006-12-19 02:06:07 +00:00
parent 6f9f14ec88
commit 8dfd7ea7bf
10 changed files with 372 additions and 25 deletions
+1
View File
@@ -3,6 +3,7 @@ SubDir HAIKU_TOP src bin network ;
SubInclude HAIKU_TOP src bin network arp ;
SubInclude HAIKU_TOP src bin network ftp ;
SubInclude HAIKU_TOP src bin network ifconfig ;
SubInclude HAIKU_TOP src bin network netstat ;
#SubInclude HAIKU_TOP src bin network pppconfig ;
#SubInclude HAIKU_TOP src bin network ppp_up ;
SubInclude HAIKU_TOP src bin network ping ;
+8
View File
@@ -0,0 +1,8 @@
SubDir HAIKU_TOP src bin network netstat ;
UsePrivateHeaders net ;
BinCommand netstat :
netstat.cpp
: libnetwork.so
;
+182
View File
@@ -0,0 +1,182 @@
/*
* Copyright 2006, Haiku, Inc. All Rights Reserved.
* Distributed under the terms of the MIT License.
*
* Authors:
* Axel Dörfler, [email protected]
*/
#include <SupportDefs.h>
#include <net_stack_driver.h>
#include <net_stat.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <net/if.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
extern const char* __progname;
const char* kProgramName = __progname;
struct address_family {
int family;
const char* name;
const char* identifiers[4];
void (*print_address)(sockaddr* address);
};
// AF_INET family
static void inet_print_address(sockaddr* address);
static const address_family kFamilies[] = {
{
AF_INET,
"inet",
{"AF_INET", "inet", "ipv4", NULL},
inet_print_address
},
{ -1, NULL, {NULL}, NULL }
};
static void
inet_print_address(sockaddr* _address)
{
sockaddr_in& address = *(sockaddr_in *)_address;
if (address.sin_family != AF_INET || address.sin_len == 0) {
printf("%-28s", "-");
return;
}
hostent* host = gethostbyaddr((const char*)_address, sizeof(sockaddr_in), AF_INET);
servent* service = getservbyport(ntohs(address.sin_port), NULL);
char buffer[128];
int length = strlcpy(buffer, host != NULL
? host->h_name : inet_ntoa(address.sin_addr), sizeof(buffer));
if (service != NULL)
snprintf(buffer + length, sizeof(buffer) - length, ":%s", service->s_name);
else
snprintf(buffer + length, sizeof(buffer) - length, ":%u", ntohs(address.sin_port));
printf("%-28s", buffer);
}
// #pragma mark -
void
usage(int status)
{
printf("usage: %s\n", kProgramName);
exit(status);
}
status_t
get_next_stat(int stack, uint32& cookie, int family, net_stat& stat)
{
get_next_stat_args args;
args.cookie = cookie;
args.family = family;
if (ioctl(stack, NET_STACK_GET_NEXT_STAT, &args, sizeof(args)) < 0)
return errno;
cookie = args.cookie;
memcpy(&stat, &args.stat, sizeof(net_stat));
return B_OK;
}
bool
get_address_family(const char* argument, int32& familyIndex)
{
for (int32 i = 0; kFamilies[i].family >= 0; i++) {
for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
if (!strcmp(argument, kFamilies[i].identifiers[j])) {
// found a match
familyIndex = i;
return true;
}
}
}
// defaults to AF_INET
familyIndex = 0;
return false;
}
// #pragma mark -
int
main(int argc, char** argv)
{
if (argc > 1 && (!strcmp(argv[1], "--help") || !strcmp(argv[1], "-h")))
usage(0);
int stack = open(NET_STACK_DRIVER_PATH, O_RDWR);
if (stack < 0) {
fprintf(stderr, "%s: The networking stack doesn't seem to be available.\n",
kProgramName);
return -1;
}
bool printProgram = true;
// TODO: add some program options... :-)
printf("Proto Local Address Foreign Address State Program\n");
uint32 cookie = 0;
int family = -1;
net_stat stat;
while (get_next_stat(stack, cookie, family, stat) == B_OK) {
protoent* proto = getprotobynumber(stat.protocol);
if (proto != NULL)
printf("%-6s ", proto->p_name);
else
printf("%-6d ", stat.protocol);
inet_print_address((sockaddr*)&stat.address);
inet_print_address((sockaddr*)&stat.peer);
printf("%-12s ", stat.state);
team_info info;
if (printProgram && get_team_info(stat.owner, &info) == B_OK) {
// remove arguments
char* name = strchr(info.args, ' ');
if (name != NULL)
name[0] = '\0';
// remove path name
name = strrchr(info.args, '/');
if (name != NULL)
name++;
else
name = info.args;
printf("%ld/%s\n", stat.owner, name);
} else
printf("%ld\n", stat.owner);
}
close(stack);
return 0;
}