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