From 212ff484221c801b00925e9c7ac84a8b7d8b534f Mon Sep 17 00:00:00 2001 From: gbucchino Date: Mon, 8 Jul 2024 07:55:39 +0200 Subject: [PATCH] Upd project --- common.h | 5 +++-- exec.sh | 6 ++++++ load_bpf | Bin 17360 -> 16680 bytes load_bpf.c | 15 +++++++++++---- tp_tcp.c | 41 ++++++++++++++++++++++++++++++----------- tp_tcp.o | Bin 9200 -> 11400 bytes 6 files changed, 50 insertions(+), 17 deletions(-) create mode 100755 exec.sh diff --git a/common.h b/common.h index 4a963a0..4dd82a4 100644 --- a/common.h +++ b/common.h @@ -2,10 +2,11 @@ #define H_COMMON struct reset { - __u8 saddr[4]; - __u8 daddr[4]; __u16 sport; __u16 dport; + __u32 saddr; +// __u8 saddr[4]; +// __u8 daddr[4]; }; #endif diff --git a/exec.sh b/exec.sh new file mode 100755 index 0000000..7f02103 --- /dev/null +++ b/exec.sh @@ -0,0 +1,6 @@ +#!/usr/bin/sh + + +clang-11 -g -O2 -target bpf -c tp_tcp.c -o tp_tcp.o +gcc load_bpf.c -o load_bpf -lbpf +sudo ./load_bpf diff --git a/load_bpf b/load_bpf index c2d9e15e11881ac18e8731ec2020915336dacecf..b2f52daeaea5acc0d7e8d2aa0b7e5aa770b37755 100755 GIT binary patch literal 16680 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 literal 17360 zcmeHPYiu0V6~6X5i3!QtMQK!lNDD$KKTuk!1Q3FR(D0~4169E)pc(|!<{6;0Mulv@bLXD*?0C0A zt=d1`Bki1fzVo>Ep1Je5zH|NEP*+EFRh3}!h)ac(PO_1JQmnm%ErbY&7I7kuUlpf| z>40nS3n;al_gC8r=C#Vs15SSXl-|uxQ+CX`g~Z9P98IVSn2UPblKiGoQORz8w+hOf z^@aL0at3MgSl}tue&$X;%FRflZ9lT2nD1A94=c`oB$D5l@*7ir%#TrnK+HLx)O`9q zrQ*4HJ2`=vlP%HOx2y=2Cp40#a<*sAepkYe+WBRP)4opCS1vD$Rr{H%?uw@{9#nPv7$U;MyBz zr)sI))CP)2Hbi94=_gJ@p7eIVZbHe%h`(SyA17Xpjzcl0gp%TECGf98QOf>q*p|ZQ zm9amw41RT)I2V?&KOOcOer|dcK&kc&mBDW)gMU~Cf29omHQ*Y4Zt4I~sy*kTUyIzv zBpaO@Rv8g9ZT3YomYLqLsx6jGm>a^~F;f^uUp$#GGFCWk8HR0I(y%+#YsAATBbH3w zkWCq8%!~`dlHJ#vJ#dXB!;vDOH=2k@kKTyUz0F93<7Sb*Czi|ed-`P^J!vy+nN)jGmC2NuFnXitb~IsHM#4&lMJj7$L@FIkSiML_&p;Rk ziEu2sopOUKu1Do29*!miWb~OXIX{(qsMIW0c6GM48Owajd>055Ti13NexDy#r9)Wm z6q=kuGo2#3_B^Ka^yHS&&4I9-=j;wqeDx`s9UvZq8(Ag?emqAFNlq4XrL z+v=~QD><&PtE40#DzE`UcO?z#r z5c>BITGjcZ`ruQwhYJbGU+@N0`Lo}|v2I}iC6fC|KR%iVo&6`0=@n!AsFYtMnO=3q z4@&ttlIc}re7}^RB$-|@#`jA3QIhG^Vtluhe@!yIQjG7E@&hE(<9j?MyKusqkM!LRJ*Dr2{Ak_6ofP=6 z;;=tM+Fx)Au_ed#+%f&o2bbxGCOmr85&ebZ);t6-Re;+3Xs@h?{dcZ-9V(Gsx=|lo z(LqH$_m(wFA6oGwgt10+X{;ZIBhwy%T(z0~n2+BG3k z({o1<__uI+n5@R;BjUr9?(qW{8bJv@LN8#C(#zcAbo!s5F*9}v40EAZheEH)2zM4D z{DCSNLM5p1Wt4NFk)hCtG`gu^^dJ<2J4S@H0JZM`JQf3DS9~er%K*a{Y=eg4+(R*Q zAq?>yM@5!=66DiT@R>R3lT<$E**?#}=Nank@CuWBY6w=%ySvcY=g=ip=ThZ=1q>Y> zycDpVqK`k95sp&BI_ydgqLPCmI~SEKqDt<8iR{d~mOi}kE`4~_9wbW7Jr9>NW!%RG zcRVJtZ|K9JyU?-yk`ErNL3tnAv2Unl>_)04cNo%sNO370syh(6zwW?Mu>0x`9PG^5 zdHo&Ejor3QFnjkleQ5K2M+wk6MnpQ#+m)D*6t=gU9vQsWT_v>dZq7dXy?QTI_=eiO3UW?y+ zwD}xx5%kvYs&1P-y&DaJNb$do-)YbKqUi}3{)~u$v`Col??nBGQi)f@%L%`4o=_55wT3))Dh9L zoFuH#5n=gB(j98Ta7ySP)8%yW=al+549(R_r6^`9QkC#6g)!65#YY_!If`5Q97 z((^ZBKUeMJZ^IgFb1`3WX39;7fQ`@;he%WYJny1~WTLOwOpGXi@dj1kb{|xB{4E~W zkJT;NAE>1%mH?%^Pjv)KpHk*_VA>_+?SD_(O^xQT!#v-&UOK+ZnJ+E8E&G(iXRy-O+GDYr^-VzNW_JC90$?^Dk@i zH#Pa$t2FmuRP#Opr-cW95i(5+b_nH%G)4NwcCu zsrd5y0x@^W`F&Q#nRF<$qs;6G3zbO;vnKJm> zW$+sGi|Tb>FDJ?VPVJZm{G{pzu`^JtYb2bKui3bI?2Ai)Q~v!b|MG8+FnJ2UdW`?w z0o$IBGnGApN#eh)c1fJACi!;Y6vv&nT`JBjb#mn2MBz46Ce8z8@R!TrpOnGp;kiQj zakobUu1z+(P`U_ssqu3S@I?hHN1-QeWvpy(udhc;?s_q-xPdJv2{VIz9g(Eb7fW`B zV@AYErZYx3J0NHxwPE+eF? z2zvWEVXW+0(;DnD)^v2N4{b0u1Y5g86jg3w>B(ee`%CYK2{?ADH2=%}LbP2b;N0-y z+yf-{=wN|@_vbjnHcjriDe^bWNZ7(Q9JvFhNaKu5=_`&lWphrEFHRt$+FN&!g5o_+ zMkJFo`ooC`?SJZA1FJ|hVPrEVQa+h2I)z2qlD*^IMrw?Oy_>*xK1>h5Llm^@lV4!WY?= zKs=jUX& zf*>r}uJ*NSdvF;wgyYd3RG+jcG8#uC*N1a1e7JkWaZ_;Ih5qd#%`5RJ!n4{YexGN~ z^Gc>GzXAR<7iO8~Im}b4CTc&~aQhW3wxd8fWq+OzF+Zpb-TCAG->m#wmEDM% z&okFlhsmG*2Eg^R|LwrYL`~D_<-sP!$;V05Rwv~kIQ=!{$NZ?%7-d&@afi#F=WEQl zy&Q&R=6AdN`8|pGk7#f>i0fzQUKE_|=lLIV{yPZUyZir3<DY%0;Zw%2qgyw3TCjNUD?^k!*v&{UD@U3(B^E`I6 z5g>@|Y-v(v{B~Z}(-{t=Y!2AAre6k;($35_+F0wz*i$|6M1TD5%;mH2X-+{*I zF9OQcZ}R~qGGjmHpFrXC=Xt|`^5=HC{aOAD1&YP(=lA4Wl|R?R_EeXXXdgad%DkXr zf1b~>g8iMG#~#}d->(8{>V87cAs>F+9=?Cj^}%gNu|P+c+r_OeCD+S_G_7%&NL9zh Mw#5vWgG&_u1V6#mApigX diff --git a/load_bpf.c b/load_bpf.c index 0f5ab34..7f0a3f1 100644 --- a/load_bpf.c +++ b/load_bpf.c @@ -27,7 +27,7 @@ int main(void){ return -1; } //LIBBPF_OPTS(bpf_map_create_opts, opts, .map_flags = BPF_F_MMAPABLE); - map_fd = bpf_create_map(BPF_MAP_TYPE_HASH, sizeof(int), sizeof(struct reset), 4096, BPF_ANY); + map_fd = bpf_create_map(BPF_MAP_TYPE_ARRAY, sizeof(int), sizeof(struct reset), 4096, BPF_ANY); printf("Create map: %d\n", map_fd); err = bpf_object__load(obj); @@ -63,9 +63,16 @@ int main(void){ int e = bpf_map_lookup_elem(map_fd, &keys, &s_reset); if (e == 0){ //printf("%lld\n", stats); - struct in_addr *src = (struct in_addr*)&s_reset.saddr; - struct in_addr *dest = (struct in_addr*)&s_reset.daddr; - printf("Sport: %d; dport: %d %s %s\n", s_reset.sport, s_reset.dport, inet_ntoa(*src), inet_ntoa(*dest)); + __u8 saddr[4]; + saddr[0] = s_reset.saddr & 0xFF; + saddr[1] = (s_reset.saddr >> 8) & 0xFF; + saddr[2] = (s_reset.saddr >> 16) & 0xFF; + saddr[3] = (s_reset.saddr >> 24) & 0xFF; + //struct in_addr *src = (struct in_addr*)&s_reset.saddr; + struct in_addr *src = (struct in_addr*)&saddr; + //struct in_addr *dest = (struct in_addr*)&s_reset.daddr; + //printf("Sport: %d; dport: %d %s %s\n", s_reset.sport, s_reset.dport, inet_ntoa(*src), inet_ntoa(*dest)); + printf("Sport: %d; dport: %d %s\n", s_reset.sport, s_reset.dport, inet_ntoa(*src)); } } diff --git a/tp_tcp.c b/tp_tcp.c index 1601494..fd07093 100644 --- a/tp_tcp.c +++ b/tp_tcp.c @@ -27,8 +27,8 @@ struct ctx_reset { }; struct { -// __uint(type, BPF_MAP_TYPE_ARRAY); - __uint(type, BPF_MAP_TYPE_HASH); + __uint(type, BPF_MAP_TYPE_ARRAY); +// __uint(type, BPF_MAP_TYPE_HASH); __uint(max_entries, 4096); __type(key, int); __type(value, sizeof(struct reset)); @@ -53,25 +53,44 @@ struct { */ //SEC("tp/tcp_retransmit_synack") -SEC("tracepoint/tcp/tcp_receive_reset") //int tcp_retransmit(struct sock *sk){ +//SEC("tracepoint/tcp/tcp_receive_reset") +SEC("tracepoint/tcp/tcp_send_reset") int tcp_retransmit(struct ctx_reset *ctx){ - long long *stats; struct reset *s_reset; int keys = 0; s_reset = bpf_map_lookup_elem(&tcp_reset_stats, &keys); - if (!s_reset) + if (!s_reset){ + bpf_printk("Failed to get the map"); return 0; + } - if (!ctx) - return 0; - - //*stats += 1; - s_reset->saddr[0] = ctx->saddr[0]; + /*s_reset->saddr[0] = ctx->saddr[0]; s_reset->saddr[1] = ctx->saddr[1]; s_reset->saddr[2] = ctx->saddr[2]; - s_reset->saddr[3] = ctx->saddr[3]; + s_reset->saddr[3] = ctx->saddr[3];*/ + //memcpy(s_reset->saddr, ctx->saddr, 4); + s_reset->saddr = (ctx->saddr[0]) + + (ctx->saddr[1] << 8) + + (ctx->saddr[2] << 16) + + (ctx->saddr[3] << 24); + __u8 saddr[4]; + saddr[0] = s_reset->saddr & 0xFF; + saddr[1] = (s_reset->saddr >> 8) & 0xFF; + saddr[2] = (s_reset->saddr >> 16) & 0xFF; + saddr[3] = (s_reset->saddr >> 24) & 0xFF; + bpf_printk("Saddr: %d %d", ctx->saddr[0], ctx->saddr[1]); + bpf_printk("Saddr: %d %d", ctx->saddr[2], ctx->saddr[3]); + bpf_printk("Saddr: %d %d", saddr[0], saddr[1]); + bpf_printk("Saddr: %d %d", saddr[2], saddr[3]); + + //bpf_printk("Daddr: %d %d\n", ctx->daddr[0], ctx->daddr[1]); + //bpf_printk("Daddr: %d %d\n", ctx->daddr[2], ctx->daddr[3]); + //bpf_printk("D: %d %d", s_reset->daddr[0], s_reset->daddr[1]); + //if (sizeof(ctx->daddr) == 4) + bpf_printk("%d", sizeof(struct reset)); + //memcpy(s_reset->daddr, ctx->daddr, 4); /*s_reset->daddr[0] = ctx->daddr[0]; s_reset->daddr[1] = ctx->daddr[1]; s_reset->daddr[2] = ctx->daddr[2]; diff --git a/tp_tcp.o b/tp_tcp.o index 8fa2941c18975b8308ac6d5806eeb69f3c476d7d..5ea79bb1b0eb17cb2d299a92d6d9b099f5f7453d 100644 GIT binary patch literal 11400 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