1 #include <signal.h> 2 #include <stdio.h> 3 #include <time.h> 4 #include <sys/resource.h> 5 #include <bpf/libbpf.h> 6 #include <time.h> 7 #include <sys/socket.h> 8 #include <netinet/in.h> 9 #include <netinet/ip.h> 10 11 #include "conn.h" 12 #include "conn.skel.h" 13 14 #include <map> 15 #include <algorithm> 16 #include <tuple> 17 #include <string> 18 #include <set> 19 using namespace std; 20 21 22 23 // cpp code, to compile run `CC=g++ make conn` 24 25 static struct ring_buffer *ring_buf = NULL; 26 static struct conn_bpf *skel = NULL; 27 static int exiting = 0; 28 static void int_exit(int sig) { 29 exiting = 1; 30 if (ring_buf) { 31 ring_buffer__free(ring_buf); 32 ring_buf= NULL; 33 } 34 if (skel){ 35 conn_bpf__destroy(skel); 36 skel = NULL; 37 } 38 } 39 40 using xtt = tuple<time_t, string, string>; 41 static map<int, xtt> pids; 42 char ob[256]; 43 static int event_handler(void *_ctx, void *data, size_t size) { 44 if (size != sizeof(struct conn_event)){ 45 printf("receive unmatch size %d\n", (int)size); 46 return 0; 47 } 48 struct conn_event* event = (struct conn_event*)data; 49 struct sockaddr_in* addr = (struct sockaddr_in*)(&(event->addr)); 50 int port=0; 51 if (addr->sin_family==AF_INET) { 52 unsigned char *ip = (unsigned char*)(&(addr->sin_addr.s_addr)); 53 sprintf(ob, "%d.%d.%d.%d", ip[0], ip[1], ip[2], ip[3]); 54 port = ntohs(addr->sin_port); 55 } else if (addr->sin_family==AF_INET6) { 56 struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr; 57 unsigned char *ip6 = addr6->sin6_addr.s6_addr; 58 int k=0; for (k=0; k<16; k++) if (ip6[k]) break; 59 int j=0; 60 if (k==10) { 61 ob[0]=':'; ob[1]=':'; j=2; 62 for (; k<12; k++) { 63 if (ip6[k]!=0xff) break; 64 else { ob[j++]='F'; ob[j++]='F'; } 65 } 66 if (k==12) { 67 sprintf(ob+j, ":%d.%d.%d.%d", ip6[12], ip6[13], ip6[14], ip6[15]); 68 } else { 69 while(k<16) { 70 if (k%4) ob[j++]=':'; 71 j+=sprintf(ob+j, "%X", ip6[k]); 72 k++; 73 } 74 } 75 } else { 76 if (k>4) { 77 ob[0]=':'; ob[1]=':'; j=2; 78 while(k<16) { 79 if (k%4) ob[j++]=':'; 80 j+=sprintf(ob+j, "%X", ip6[k]); 81 k++; 82 } 83 } 84 } 85 port = ntohs(addr6->sin6_port); 86 } else return 0; 87 int pid = event->pid; 88 time_t ctime = time(NULL); 89 char dir_in = 0; 90 if (pid<0) { pid=-pid; dir_in=1; } 91 if (pids.count(pid)==0 || ctime-get<0>(pids[pid]) > 1000) { 92 char b[128]; 93 char comm[128]; 94 char host[128]; 95 sprintf(b, "/proc/%d/comm", pid); 96 FILE* fp; 97 size_t i=0; 98 fp = fopen(b, "r"); if (fp) { 99 comm[0]=0; fgets(comm, sizeof(comm), fp); 100 while(i<sizeof(comm)&&comm[i]!=0&&comm[i]!='\n'&&comm[i]!='\r') i++; 101 comm[i]=0; 102 fclose(fp); 103 } 104 if (i<1) strcpy(comm, "unknown-command"); 105 sprintf(b, "/proc/%d/root/etc/hostname", pid); 106 i=0; fp = fopen(b, "r"); if (fp) { 107 host[0]=0; fgets(host, sizeof(host), fp); 108 while(i<sizeof(host)&&host[i]!=0&&host[i]!='\n'&&host[i]!='\r') i++; 109 host[i]=0; 110 fclose(fp); 111 } 112 if (i<1) strcpy(host, "unknown-host"); 113 pids[pid] = make_tuple(ctime, string(comm), string(host)); 114 } 115 if (dir_in) { 116 // if (port) 117 printf("[%s@%s] accept connection from <%s>\n", get<1>(pids[pid]).c_str(), get<2>(pids[pid]).c_str(), ob); 118 } else { 119 if (port) 120 printf("[%s@%s] try to connect <%s:%d>\n", get<1>(pids[pid]).c_str(), get<2>(pids[pid]).c_str(), ob, port); 121 else 122 printf("[%s@%s] try to reach <%s>\n", get<1>(pids[pid]).c_str(), get<2>(pids[pid]).c_str(), ob); 123 } 124 return 0; 125 } 126 127 int main(int argc, char *argv[]) { 128 int err; 129 signal(SIGINT, int_exit); 130 signal(SIGTERM, int_exit); 131 skel = conn_bpf__open(); 132 if (!skel) { 133 fprintf(stderr, "Failed to open and load BPF skeleton\n"); 134 return 1; 135 } 136 err = conn_bpf__load(skel); 137 if (err) { 138 fprintf(stderr, "Failed to load and verify BPF skeleton\n"); 139 goto cleanup; 140 } 141 err = conn_bpf__attach(skel); 142 if (err) { 143 fprintf(stderr, "Failed to attach BPF skeleton\n"); 144 goto cleanup; 145 } 146 ring_buf = ring_buffer__new(bpf_map__fd(skel->maps.conns), event_handler, NULL, NULL); 147 if (!ring_buf) { 148 perror("Fail to alloc ring buf"); 149 goto cleanup; 150 } 151 while (!exiting) { 152 if(ring_buffer__poll(ring_buf, -1) < 0) break; 153 } 154 155 cleanup: 156 int_exit(0); 157 return 0; 158 } 159