this code has been folded in long ago
This commit is contained in:
		
							parent
							
								
									ba722ea9c6
								
							
						
					
					
						commit
						a05665240a
					
				@ -1,211 +0,0 @@
 | 
				
			|||||||
#include <stdio.h>
 | 
					 | 
				
			||||||
#include <ctype.h>
 | 
					 | 
				
			||||||
#include <errno.h>
 | 
					 | 
				
			||||||
#include <stdlib.h>
 | 
					 | 
				
			||||||
#include <string.h>
 | 
					 | 
				
			||||||
#include <dirent.h>
 | 
					 | 
				
			||||||
#include <sys/stat.h>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * eam can provide per-process measurements, but at the moment requires
 | 
					 | 
				
			||||||
 * a pid.  something we cannot store in the database.  however, we could
 | 
					 | 
				
			||||||
 * store a service port in the database (e.g. 8009 for tomcat ajp) and 
 | 
					 | 
				
			||||||
 * figure out the pid given that.
 | 
					 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 * it is possible via /proc/net/tcp and /proc/$pid/fd/
 | 
					 | 
				
			||||||
 * to map a tcp port to one (or more if forked) process id(s).
 | 
					 | 
				
			||||||
 * caveats: expensive to scan /proc/$pid/fd
 | 
					 | 
				
			||||||
 *          must own process or be root to read /proc/$pid/fd
 | 
					 | 
				
			||||||
 * brutal to provide similar functionality on other platforms,
 | 
					 | 
				
			||||||
 * tho possible (see lsof).
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char *sigar_skip_token(char *p)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    while (isspace(*p)) p++;
 | 
					 | 
				
			||||||
    while (*p && !isspace(*p)) p++;
 | 
					 | 
				
			||||||
    return p;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static char *sigar_skip_multiple_token(char *p, int count)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    int i;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    for (i = 0; i < count; i++) {
 | 
					 | 
				
			||||||
        p = sigar_skip_token(p);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return p;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int get_process_ppid(char *pid, char *buf, int buflen)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
    FILE *fp;
 | 
					 | 
				
			||||||
    char buffer[1024], *ptr, *ptr2;
 | 
					 | 
				
			||||||
    sprintf(buffer, "/proc/%s/stat", pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!(fp = fopen(buffer, "r"))) {
 | 
					 | 
				
			||||||
        return errno;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ptr = fgets(buffer, sizeof(buffer), fp);
 | 
					 | 
				
			||||||
    fclose(fp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ptr = sigar_skip_multiple_token(ptr, 3);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while (isspace(*ptr)) {
 | 
					 | 
				
			||||||
        ++ptr;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    ptr2 = strchr(ptr, ' ');
 | 
					 | 
				
			||||||
    *ptr2 = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    strncpy(buf, ptr2, buflen);
 | 
					 | 
				
			||||||
    buf[buflen] = '\0';
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct {
 | 
					 | 
				
			||||||
    int port;
 | 
					 | 
				
			||||||
    int inode;
 | 
					 | 
				
			||||||
    int uid;
 | 
					 | 
				
			||||||
    int pid;
 | 
					 | 
				
			||||||
    char name[1024];
 | 
					 | 
				
			||||||
} portmap_t;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int portmap_lookup_inode(portmap_t *map) {
 | 
					 | 
				
			||||||
    FILE *fp;
 | 
					 | 
				
			||||||
    char buffer[8192], *ptr;
 | 
					 | 
				
			||||||
    int inode = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if ((fp = fopen("/proc/net/tcp", "r")) < 0) {
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fgets(buffer, sizeof(buffer), fp); /* skip header */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while ((ptr = fgets(buffer, sizeof(buffer), fp))) {
 | 
					 | 
				
			||||||
        ptr = sigar_skip_token(ptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if ((ptr = strchr(ptr, ':'))) {
 | 
					 | 
				
			||||||
            unsigned long port = strtoul(++ptr, &ptr, 16);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
            if (!(map->port == (port & 0xffff))) {
 | 
					 | 
				
			||||||
                continue;
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ptr = sigar_skip_multiple_token(ptr, 5);
 | 
					 | 
				
			||||||
        map->uid = strtoul(ptr, &ptr, 10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        ptr = sigar_skip_token(ptr);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        inode = map->inode = strtoul(ptr, &ptr, 10);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        break;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    fclose(fp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return inode ? 0 : ENOENT;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int portmap_lookup_pid(portmap_t *map, char *pid) {
 | 
					 | 
				
			||||||
    DIR *dirp;
 | 
					 | 
				
			||||||
    struct dirent *dp;
 | 
					 | 
				
			||||||
    char fname[1024], dname[1024];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    map->pid = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    sprintf(dname, "/proc/%s/fd", pid);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!(dirp = opendir(dname))) {
 | 
					 | 
				
			||||||
        return errno;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while ((dp = readdir(dirp))) {
 | 
					 | 
				
			||||||
        struct stat statbuf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!isdigit(*dp->d_name)) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        sprintf(fname, "%s/%s", dname, dp->d_name);
 | 
					 | 
				
			||||||
        //printf("check %s\n", fname);
 | 
					 | 
				
			||||||
        if (stat(fname, &statbuf)) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (statbuf.st_ino == map->inode) {
 | 
					 | 
				
			||||||
            map->pid = atoi(pid);
 | 
					 | 
				
			||||||
            break;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
    closedir(dirp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return map->pid == -1 ? ENOENT : 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int portmap_lookup_pid_scan(portmap_t *map) {
 | 
					 | 
				
			||||||
    DIR *dirp;
 | 
					 | 
				
			||||||
    struct dirent *dp;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    char dname[1024];
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (!(dirp = opendir("/proc"))) {
 | 
					 | 
				
			||||||
        return -1;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    map->pid = -1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    while ((dp = readdir(dirp))) {
 | 
					 | 
				
			||||||
        struct stat statbuf;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!isdigit(*dp->d_name)) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        sprintf(dname, "/proc/%s", dp->d_name);
 | 
					 | 
				
			||||||
        if (stat(dname, &statbuf)) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (!(statbuf.st_uid == map->uid)) {
 | 
					 | 
				
			||||||
            continue;
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        if (portmap_lookup_pid(map, dp->d_name) == 0) {
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
            char *pid = dp->d_name;
 | 
					 | 
				
			||||||
            char ppid[16];
 | 
					 | 
				
			||||||
            get_process_ppid(pid, ppid, sizeof(ppid));
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
            //break;
 | 
					 | 
				
			||||||
            printf("%s has inode %d\n", dp->d_name, map->inode);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    closedir(dirp);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return map->pid == -1 ? ENOENT : 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int main(int argc, char **argv) {
 | 
					 | 
				
			||||||
    portmap_t map;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (argc != 2) {
 | 
					 | 
				
			||||||
        printf("usage: %s port\n", argv[0]);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    map.port = atoi(argv[1]);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    if (portmap_lookup_inode(&map) == 0) {
 | 
					 | 
				
			||||||
        if (portmap_lookup_pid_scan(&map) == 0) {
 | 
					 | 
				
			||||||
            printf("inode=%d, pid=%d\n", map.inode, map.pid);
 | 
					 | 
				
			||||||
        }
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    return 1;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user