From 4a61c204059cb29fa252873c5ae3b9eada5f5588 Mon Sep 17 00:00:00 2001 From: Doug MacEachern Date: Mon, 3 Dec 2007 03:02:34 +0000 Subject: [PATCH] [SIGAR-76] Implement sigar_proc_port_get for Solaris --- src/os/solaris/sigar_os.h | 17 +++++ src/os/solaris/solaris_sigar.c | 118 ++++++++++++++++++++++++++++++++- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/src/os/solaris/sigar_os.h b/src/os/solaris/sigar_os.h index fdaa411e..cf431210 100644 --- a/src/os/solaris/sigar_os.h +++ b/src/os/solaris/sigar_os.h @@ -198,6 +198,10 @@ typedef struct ps_prochandle * (*proc_grab_func_t)(pid_t, int, int *); typedef void (*proc_free_func_t)(struct ps_prochandle *); +typedef int (*proc_create_agent_func_t)(struct ps_prochandle *); + +typedef void (*proc_destroy_agent_func_t)(struct ps_prochandle *); + typedef void (*proc_objname_func_t)(struct ps_prochandle *, uintptr_t, const char *, size_t); @@ -205,6 +209,14 @@ typedef char * (*proc_dirname_func_t)(const char *, char *, size_t); typedef char * (*proc_exename_func_t)(struct ps_prochandle *, char *, size_t); +typedef int (*proc_fstat64_func_t)(struct ps_prochandle *, int, void *); + +typedef int (*proc_getsockopt_func_t)(struct ps_prochandle *, + int, int, int, void *, int *); + +typedef int (*proc_getsockname_func_t)(struct ps_prochandle *, + int, struct sockaddr *, socklen_t *); + struct sigar_t { SIGAR_T_BASE; @@ -251,9 +263,14 @@ struct sigar_t { void *plib; proc_grab_func_t pgrab; proc_free_func_t pfree; + proc_create_agent_func_t pcreate_agent; + proc_destroy_agent_func_t pdestroy_agent; proc_objname_func_t pobjname; proc_dirname_func_t pdirname; proc_exename_func_t pexename; + proc_fstat64_func_t pfstat64; + proc_getsockopt_func_t pgetsockopt; + proc_getsockname_func_t pgetsockname; sigar_cache_t *pargs; diff --git a/src/os/solaris/solaris_sigar.c b/src/os/solaris/solaris_sigar.c index cc0bfc51..0f21e20a 100644 --- a/src/os/solaris/solaris_sigar.c +++ b/src/os/solaris/solaris_sigar.c @@ -32,6 +32,7 @@ #include #include #include +#include #define PROC_ERRNO ((errno == ENOENT) ? ESRCH : errno) @@ -568,9 +569,14 @@ static int sigar_init_libproc(sigar_t *sigar) sigar->pgrab = (proc_grab_func_t)dlsym(sigar->plib, "Pgrab"); sigar->pfree = (proc_free_func_t)dlsym(sigar->plib, "Pfree"); + sigar->pcreate_agent = (proc_create_agent_func_t)dlsym(sigar->plib, "Pcreate_agent"); + sigar->pdestroy_agent = (proc_destroy_agent_func_t)dlsym(sigar->plib, "Pdestroy_agent"); sigar->pobjname = (proc_objname_func_t)dlsym(sigar->plib, "Pobjname"); sigar->pexename = (proc_exename_func_t)dlsym(sigar->plib, "Pexecname"); sigar->pdirname = (proc_dirname_func_t)dlsym(sigar->plib, "proc_dirname"); + sigar->pfstat64 = (proc_fstat64_func_t)dlsym(sigar->plib, "pr_fstat64"); + sigar->pgetsockopt = (proc_getsockopt_func_t)dlsym(sigar->plib, "pr_getsockopt"); + sigar->pgetsockname = (proc_getsockname_func_t)dlsym(sigar->plib, "pr_getsockname"); CHECK_PSYM(pgrab); CHECK_PSYM(pfree); @@ -2606,10 +2612,120 @@ int sigar_nfs_server_v3_get(sigar_t *sigar, return sigar_nfs_get(sigar, "rfsproccnt_v3", nfs_v3_names, (char *)nfs); } +static int find_port(sigar_t *sigar, struct ps_prochandle *phandle, + sigar_pid_t pid, unsigned long port) +{ + DIR *dirp; + struct dirent *ent; + char pname[PATH_MAX]; + struct stat64 statb; + int found=0; + + sprintf(pname, "/proc/%d/fd", (int)pid); + + if (!(dirp = opendir(pname))) { + return 0; + } + + while ((ent = readdir(dirp))) { + int fd; + + if (!isdigit(ent->d_name[0])) { + continue; + } + fd = atoi(ent->d_name); + + if (sigar->pfstat64(phandle, fd, &statb) == -1) { + continue; + } + + if ((statb.st_mode & S_IFMT) == S_IFSOCK) { + struct sockaddr_in sin; + struct sockaddr *sa = (struct sockaddr *)&sin; + socklen_t len = sizeof(sin); + int opt, optsz, rc; + + optsz = sizeof(opt); + rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_TYPE, &opt, &optsz); + if (rc != 0) { + continue; + } + if (opt != SOCK_STREAM) { + continue; + } + optsz = sizeof(opt); + rc = sigar->pgetsockopt(phandle, fd, SOL_SOCKET, SO_ACCEPTCONN, &opt, &optsz); + if (rc != 0) { + continue; + } + if (opt != SO_ACCEPTCONN) { + continue; + } + + rc = sigar->pgetsockname(phandle, fd, sa, &len); + if (rc != 0) { + continue; + } + + if ((sa->sa_family == AF_INET) || + (sa->sa_family == AF_INET6)) + { + if (ntohs(sin.sin_port) == port) { + found = 1; + break; + } + } + } + } + + closedir(dirp); + + return found; +} + +/* derived from /usr/bin/pfiles.c */ int sigar_proc_port_get(sigar_t *sigar, int protocol, unsigned long port, sigar_pid_t *pid) { - return SIGAR_ENOTIMPL; + sigar_proc_list_t pids; + int i, status, found=0; + + if ((status = sigar_init_libproc(sigar)) != SIGAR_OK) { + return SIGAR_ENOTIMPL; + } + status = sigar_proc_list_get(sigar, &pids); + if (status != SIGAR_OK) { + return status; + } + + for (i=0; ipcreate_agent(phandle) == 0) { + found = find_port(sigar, phandle, ps_id, port); + sigar->pdestroy_agent(phandle); + } + + sigar->pfree(phandle); + if (found) { + *pid = ps_id; + break; + } + } + + sigar_proc_list_destroy(sigar, &pids); + + return found ? SIGAR_OK : ENOENT; } int sigar_os_sys_info_get(sigar_t *sigar,