vfs: check userland buffers before reading them.
[haiku.git] / src / bin / network / netstat / netstat.cpp
blob85fde801ef92da29afcb7ba56c757659fc40c298
1 /*
2 * Copyright 2006-2009, Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
5 * Authors:
6 * Axel Dörfler, axeld@pinc-software.de
7 * James Woodcock
8 */
10 #include <arpa/inet.h>
11 #include <errno.h>
12 #include <getopt.h>
13 #include <net/if.h>
14 #include <netdb.h>
15 #include <netinet/in.h>
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <string.h>
19 #include <unistd.h>
21 #include <SupportDefs.h>
23 #include <net_stat.h>
24 #include <syscalls.h>
27 extern const char* __progname;
28 const char* kProgramName = __progname;
30 static int sResolveNames = 1;
32 struct address_family {
33 int family;
34 const char* name;
35 const char* identifiers[4];
36 void (*print_address)(sockaddr* address);
39 // AF_INET family
40 static void inet_print_address(sockaddr* address);
42 static const address_family kFamilies[] = {
44 AF_INET,
45 "inet",
46 {"AF_INET", "inet", "ipv4", NULL},
47 inet_print_address
49 { -1, NULL, {NULL}, NULL }
53 static void
54 inet_print_address(sockaddr* _address)
56 sockaddr_in& address = *(sockaddr_in *)_address;
58 if (address.sin_family != AF_INET || address.sin_len == 0) {
59 printf("%-22s", "-");
60 return;
63 hostent* host = NULL;
64 servent* service = NULL;
65 if (sResolveNames) {
66 host = gethostbyaddr((const char*)&address.sin_addr, sizeof(in_addr),
67 AF_INET);
68 service = getservbyport(address.sin_port, NULL);
71 const char *hostName;
72 if (host != NULL)
73 hostName = host->h_name;
74 else if (address.sin_addr.s_addr == INADDR_ANY)
75 hostName = "*";
76 else
77 hostName = inet_ntoa(address.sin_addr);
79 char buffer[128];
80 int length = strlcpy(buffer, hostName, sizeof(buffer));
82 char port[64];
83 if (service != NULL)
84 strlcpy(port, service->s_name, sizeof(port));
85 else if (address.sin_port == 0)
86 strcpy(port, "*");
87 else
88 snprintf(port, sizeof(port), "%u", ntohs(address.sin_port));
90 snprintf(buffer + length, sizeof(buffer) - length, ":%s", port);
92 printf("%-22s", buffer);
96 // #pragma mark -
99 void
100 usage(int status)
102 printf("usage: %s [-nh]\n", kProgramName);
103 printf("options:\n");
104 printf(" -n don't resolve names\n");
105 printf(" -h this help\n");
107 exit(status);
111 bool
112 get_address_family(const char* argument, int32& familyIndex)
114 for (int32 i = 0; kFamilies[i].family >= 0; i++) {
115 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) {
116 if (!strcmp(argument, kFamilies[i].identifiers[j])) {
117 // found a match
118 familyIndex = i;
119 return true;
124 // defaults to AF_INET
125 familyIndex = 0;
126 return false;
130 // #pragma mark -
134 main(int argc, char** argv)
136 int optionIndex = 0;
137 int opt;
138 static struct option longOptions[] = {
139 {"help", no_argument, 0, 'h'},
140 {"numeric", no_argument, 0, 'n'},
141 {0, 0, 0, 0}
144 do {
145 opt = getopt_long(argc, argv, "hn", longOptions, &optionIndex);
146 switch (opt) {
147 case -1:
148 // end of arguments, do nothing
149 break;
151 case 'n':
152 sResolveNames = 0;
153 break;
155 case 'h':
156 default:
157 usage(0);
158 break;
160 } while (opt != -1);
162 bool printProgram = true;
163 // TODO: add some more program options... :-)
165 printf("Proto Recv-Q Send-Q Local Address Foreign Address "
166 "State Program\n");
168 uint32 cookie = 0;
169 int family = -1;
170 net_stat stat;
171 while (_kern_get_next_socket_stat(family, &cookie, &stat) == B_OK) {
172 protoent* proto = getprotobynumber(stat.protocol);
173 if (proto != NULL)
174 printf("%-6s ", proto->p_name);
175 else
176 printf("%-6d ", stat.protocol);
178 printf("%6lu ", stat.receive_queue_size);
179 printf("%6lu ", stat.send_queue_size);
181 inet_print_address((sockaddr*)&stat.address);
182 inet_print_address((sockaddr*)&stat.peer);
183 printf("%-12s ", stat.state);
185 team_info info;
186 if (printProgram && get_team_info(stat.owner, &info) == B_OK) {
187 // remove arguments
188 char* name = strchr(info.args, ' ');
189 if (name != NULL)
190 name[0] = '\0';
192 // remove path name
193 name = strrchr(info.args, '/');
194 if (name != NULL)
195 name++;
196 else
197 name = info.args;
199 printf("%ld/%s\n", stat.owner, name);
200 } else
201 printf("%ld\n", stat.owner);
204 return 0;