diff --git a/include/sigar_format.h b/include/sigar_format.h index c9f0dc31..a870e6f8 100644 --- a/include/sigar_format.h +++ b/include/sigar_format.h @@ -42,5 +42,8 @@ SIGAR_DECLARE(const char *)sigar_net_connection_state_get(int state); SIGAR_DECLARE(char *) sigar_net_interface_flags_to_string(sigar_uint64_t flags, char *buf); +SIGAR_DECLARE(char *)sigar_net_services_name_get(sigar_t *sigar, + int protocol, unsigned long port); + #endif diff --git a/include/sigar_private.h b/include/sigar_private.h index 67227cea..96753451 100644 --- a/include/sigar_private.h +++ b/include/sigar_private.h @@ -71,7 +71,9 @@ int ifconf_len; \ char *self_path; \ sigar_cache_t *proc_cpu; \ - sigar_cache_t *net_listen + sigar_cache_t *net_listen; \ + sigar_cache_t *net_services_tcp; \ + sigar_cache_t *net_services_udp #if defined(WIN32) # define SIGAR_INLINE __inline diff --git a/src/sigar.c b/src/sigar.c index c1a2b708..0a71fbc4 100644 --- a/src/sigar.c +++ b/src/sigar.c @@ -50,6 +50,8 @@ SIGAR_DECLARE(int) sigar_open(sigar_t **sigar) (*sigar)->self_path = NULL; (*sigar)->proc_cpu = NULL; (*sigar)->net_listen = NULL; + (*sigar)->net_services_tcp = NULL; + (*sigar)->net_services_udp = NULL; } return status; @@ -69,6 +71,12 @@ SIGAR_DECLARE(int) sigar_close(sigar_t *sigar) if (sigar->net_listen) { sigar_cache_destroy(sigar->net_listen); } + if (sigar->net_services_tcp) { + sigar_cache_destroy(sigar->net_services_tcp); + } + if (sigar->net_services_udp) { + sigar_cache_destroy(sigar->net_services_udp); + } return sigar_os_close(sigar); } diff --git a/src/sigar_format.c b/src/sigar_format.c index 958f9109..d7a67583 100644 --- a/src/sigar_format.c +++ b/src/sigar_format.c @@ -521,3 +521,86 @@ SIGAR_DECLARE(char *) sigar_net_interface_flags_to_string(sigar_uint64_t flags, return buf; } + +#ifdef WIN32 +#define NET_SERVICES_FILE "C:\\windows\\system32\\drivers\\etc\\services" +#else +#define NET_SERVICES_FILE "/etc/services" +#endif + +static int net_services_parse(sigar_cache_t *names, char *type) +{ + FILE *fp; + char buffer[8192], *ptr; + char *file; + + + if (!(file = getenv("SIGAR_NET_SERVICES_FILE"))) { + file = NET_SERVICES_FILE; + } + + if (!(fp = fopen(file, "r"))) { + return errno; + } + + while ((ptr = fgets(buffer, sizeof(buffer), fp))) { + int port; + char name[256], proto[56]; + sigar_cache_entry_t *entry; + + while (sigar_isspace(*ptr)) { + ++ptr; + } + if ((*ptr == '#') || (*ptr == '\0')) { + continue; + } + + if (sscanf(ptr, "%s%d/%s", name, &port, proto) != 3) { + continue; + } + if (!strEQ(type, proto)) { + continue; + } + + entry = sigar_cache_get(names, port); + if (!entry->value) { + entry->value = strdup(name); + } + } + + fclose(fp); + return SIGAR_OK; +} + +SIGAR_DECLARE(char *)sigar_net_services_name_get(sigar_t *sigar, + int protocol, unsigned long port) +{ + sigar_cache_entry_t *entry; + sigar_cache_t **names; + char *pname; + + switch (protocol) { + case SIGAR_NETCONN_TCP: + names = &sigar->net_services_tcp; + pname = "tcp"; + break; + case SIGAR_NETCONN_UDP: + names = &sigar->net_services_udp; + pname = "udp"; + break; + default: + return NULL; + } + + if (*names == NULL) { + *names = sigar_cache_new(1024); + net_services_parse(*names, pname); + } + + if ((entry = sigar_cache_find(*names, port))) { + return (char *)entry->value; + } + else { + return NULL; + } +}