xref: /linux-tools/ebpf/libbpf-bootstrap/conn.c (revision cf38d8f6bf0895297006d1c1b4976f0072bae4c9)
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;
int_exit(int sig)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];
event_handler(void * _ctx,void * data,size_t size)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 
main(int argc,char * argv[])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