1 /* 2 * Copyright 2006-2007, Haiku, Inc. All Rights Reserved. 3 * Distributed under the terms of the MIT License. 4 * 5 * Authors: 6 * Axel Dörfler, axeld@pinc-software.de 7 * James Woodcock 8 */ 9 10 11 #include <SupportDefs.h> 12 13 #include <net_stack_driver.h> 14 #include <net_stat.h> 15 16 #include <arpa/inet.h> 17 #include <netdb.h> 18 #include <net/if.h> 19 #include <netinet/in.h> 20 21 #include <errno.h> 22 #include <stdio.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <unistd.h> 26 #include <getopt.h> 27 28 29 extern const char* __progname; 30 const char* kProgramName = __progname; 31 32 static int sResolveNames = 1; 33 34 struct address_family { 35 int family; 36 const char* name; 37 const char* identifiers[4]; 38 void (*print_address)(sockaddr* address); 39 }; 40 41 // AF_INET family 42 static void inet_print_address(sockaddr* address); 43 44 static const address_family kFamilies[] = { 45 { 46 AF_INET, 47 "inet", 48 {"AF_INET", "inet", "ipv4", NULL}, 49 inet_print_address 50 }, 51 { -1, NULL, {NULL}, NULL } 52 }; 53 54 55 static void 56 inet_print_address(sockaddr* _address) 57 { 58 sockaddr_in& address = *(sockaddr_in *)_address; 59 60 if (address.sin_family != AF_INET || address.sin_len == 0) { 61 printf("%-22s", "-"); 62 return; 63 } 64 65 hostent* host = NULL; 66 servent* service = NULL; 67 if (sResolveNames) { 68 host = gethostbyaddr((const char*)&address.sin_addr, sizeof(in_addr), 69 AF_INET); 70 service = getservbyport(ntohs(address.sin_port), NULL); 71 } 72 73 const char *hostName; 74 if (host != NULL) 75 hostName = host->h_name; 76 else if (address.sin_addr.s_addr == INADDR_ANY) 77 hostName = "*"; 78 else 79 hostName = inet_ntoa(address.sin_addr); 80 81 char buffer[128]; 82 int length = strlcpy(buffer, hostName, sizeof(buffer)); 83 84 char port[64]; 85 if (service != NULL) 86 strlcpy(port, service->s_name, sizeof(port)); 87 else if (address.sin_port == 0) 88 strcpy(port, "*"); 89 else 90 snprintf(port, sizeof(port), "%u", ntohs(address.sin_port)); 91 92 snprintf(buffer + length, sizeof(buffer) - length, ":%s", port); 93 94 printf("%-22s", buffer); 95 } 96 97 98 // #pragma mark - 99 100 101 void 102 usage(int status) 103 { 104 printf("usage: %s [-nh]\n", kProgramName); 105 printf("options:\n"); 106 printf(" -n don't resolve names\n"); 107 printf(" -h this help\n"); 108 109 exit(status); 110 } 111 112 113 status_t 114 get_next_stat(int stack, uint32& cookie, int family, net_stat& stat) 115 { 116 get_next_stat_args args; 117 args.cookie = cookie; 118 args.family = family; 119 120 if (ioctl(stack, NET_STACK_GET_NEXT_STAT, &args, sizeof(args)) < 0) 121 return errno; 122 123 cookie = args.cookie; 124 memcpy(&stat, &args.stat, sizeof(net_stat)); 125 return B_OK; 126 } 127 128 129 bool 130 get_address_family(const char* argument, int32& familyIndex) 131 { 132 for (int32 i = 0; kFamilies[i].family >= 0; i++) { 133 for (int32 j = 0; kFamilies[i].identifiers[j]; j++) { 134 if (!strcmp(argument, kFamilies[i].identifiers[j])) { 135 // found a match 136 familyIndex = i; 137 return true; 138 } 139 } 140 } 141 142 // defaults to AF_INET 143 familyIndex = 0; 144 return false; 145 } 146 147 148 // #pragma mark - 149 150 151 int 152 main(int argc, char** argv) 153 { 154 int optionIndex = 0; 155 int opt; 156 static struct option longOptions[] = { 157 {"help", no_argument, 0, 'h'}, 158 {"numeric", no_argument, 0, 'n'}, 159 {0, 0, 0, 0} 160 }; 161 162 do { 163 opt = getopt_long(argc, argv, "hn", longOptions, &optionIndex); 164 switch (opt) { 165 case -1: 166 // end of arguments, do nothing 167 break; 168 169 case 'n': 170 sResolveNames = 0; 171 break; 172 173 case 'h': 174 default: 175 usage(0); 176 break; 177 } 178 } while (opt != -1); 179 180 int stack = open(NET_STACK_DRIVER_PATH, O_RDWR); 181 if (stack < 0) { 182 fprintf(stderr, "%s: The networking stack doesn't seem to be " 183 "available.\n", kProgramName); 184 return -1; 185 } 186 187 bool printProgram = true; 188 // TODO: add some more program options... :-) 189 190 printf("Proto Recv-Q Send-Q Local Address Foreign Address " 191 "State Program\n"); 192 193 uint32 cookie = 0; 194 int family = -1; 195 net_stat stat; 196 while (get_next_stat(stack, cookie, family, stat) == B_OK) { 197 protoent* proto = getprotobynumber(stat.protocol); 198 if (proto != NULL) 199 printf("%-6s ", proto->p_name); 200 else 201 printf("%-6d ", stat.protocol); 202 203 printf("%6lu ", stat.receive_queue_size); 204 printf("%6lu ", stat.send_queue_size); 205 206 inet_print_address((sockaddr*)&stat.address); 207 inet_print_address((sockaddr*)&stat.peer); 208 printf("%-12s ", stat.state); 209 210 team_info info; 211 if (printProgram && get_team_info(stat.owner, &info) == B_OK) { 212 // remove arguments 213 char* name = strchr(info.args, ' '); 214 if (name != NULL) 215 name[0] = '\0'; 216 217 // remove path name 218 name = strrchr(info.args, '/'); 219 if (name != NULL) 220 name++; 221 else 222 name = info.args; 223 224 printf("%ld/%s\n", stat.owner, name); 225 } else 226 printf("%ld\n", stat.owner); 227 } 228 229 close(stack); 230 return 0; 231 } 232 233