From 315f3d5df18408ba6cae841163ef47e83c320ac4 Mon Sep 17 00:00:00 2001 From: Jordan Whited Date: Mon, 17 Jun 2024 14:06:53 -0700 Subject: [PATCH] derp/xdp: fix handling of zero value UDP checksums (#12510) validate_udp_checksum was previously indeterminate (not zero) at declaration, and IPv4 zero value UDP checksum packets were being passed to the kernel. Updates tailscale/corp#20689 Signed-off-by: Jordan Whited --- derp/xdp/bpf_bpfeb.o | Bin 23640 -> 24120 bytes derp/xdp/bpf_bpfel.o | Bin 23808 -> 24288 bytes derp/xdp/xdp.c | 2 +- derp/xdp/xdp_linux_test.go | 48 +++++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/derp/xdp/bpf_bpfeb.o b/derp/xdp/bpf_bpfeb.o index 15a96f5ba38fea9ccb755ea799b4e9f10ee5333b..06ff73fc1ff72d33b990dac3db5f64ef6255d183 100644 GIT binary patch literal 24120 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 literal 23640 zcmchfe{5XWmEZ3Sf6Pdx$l))W*{b!EEz2WClt;8gGwWD8lte{}6>%(5mYl3IGvW_% zRunnn3@xfkyHji(DCq*Fcb!&$r0pbe8o66=tSfbh+4eD=bp%08LS0 zH$~a5feNh=_Iu7fcX;QBRMMu{2hZI1Ip^GS?>+bDdqeq`M^2vzheM`*h0OoNy(g$^ zaPw9lQ&PTnm{4Vy@6FwWq%lszH@~sIN_W|2)68j+<)(7krjZP%?RQg_@7jC@`5utu z?y|^BoQC={p((n%_M+Lr=`*H{(#tkqbhL{I`2tSN&2L&iy)kpjm@ogwdO6DPxmf7) z#zc+iLzQQ2{)qMaoURAzcb_c!W1%rhUA}8i6FpvU_&)>jc-`(9!zF0HutPmfr?bmF zV|vKnd9KGVtZ!m}jP!N6t#7^kl|j-PQ~9!_lQzAZw=(*!1ol3?%ckc!Szo_y<*^Q%nj71#|BCd_bz9F^M`M3Ax&CtPx9whE zzguF*A;jkes=;I9BxUs#Y5%j*54jf&OX~3vKNq_~J1Ivb&-wOw{;DL=_Wk(~du%ag z59@6?_3^F7%b?Uhto?Z7hR3ZNFSebgW2<~pB>lFx_(KK)`af{oQBXpRk}l5+2XE^U-;&C>^#@)z1U^`8`)P%^li+|Z_7B4 zb-=}a;v4H9lfJT#zR@oM_44}1G~WD6#%D;zuetGgTi;$|{+R44c4acpLO@sUuw8eY z{l#wc?@2D)oD=`K7fhJs7k8OIptOQfMi?BF%+He`_q3gtxf6E%>5%mg za`xD9kgV8_$4%}{(@xy+27R-f`K4`)RHW zSbwiIuYW{$t{xpCuRL${;xB}Hy+{&-o8z06eym9QuiJRUT)WOE$$EX=#V0#x+f|YJ zYrWL7o*!}AMjo6$SHHiYIQ`zw5GS4&*Cc*!z3vOtJ|N>gE%A2kx9b|>Ci;quBOTwn zNs5jMJNt7nlc5qSy(~Af5APH^)8A))ku;dMJkp%}TwvaUIFxyk5=N= z-?MJN3W(R&u}<(jboLhqOo}vW9SEGhKWH z)W$>d^=;v=4f6X`pDP14{t-LB4`Cmwk{tEo@+)rq$T)mf`qAxk?~t)E!{;!?=*G#j ze?!ilF29UF8BgsPM?5cGdA)&ogY!!{vR(|LznfXky@h=tNo0=npS1OBF=mVecT4nb znq(gg-?i%qoo81`;qe1z+g?+_D4`4M?LA82kK=greK`kPKlSs5loOKvcr3r$hqFE8 z4FjiW>yLJFxrJ}8|2fGEAFTfmN-IuZ!s|Ixl*BYyT8eZ#(SpI+N) zpRVw3iFl!%*w1UdM(SbP-2*=V1(?fZtb?~ZL>;U7x7 zKCtb=d8M{lIoiMY4gI8cbjb6^mV>;IJNJ!}msV>XSX zINeuyTI7>9?Z2@8A>CDuT8<<+-PwO~{U6btk_V7~hvb;wRZ4r4_I#o24#Do5q?h`K zuk1DfaZbwlPLgO>7v#KNWryu}CONIc6T4;KJ!<#S>>GBy{wE`p&lu==hG&o3a~AYG zVm$qRvXk-?l`s*;nN9j&&m+IZSih?Nan%2-WGeYXKdJs=x0}wnjR%;^5q%WQ^>F)2Z^E3VoY{kRoVfEM z#$6A|M-S0AoQ@uyd~z-dke~fR&-DRwK2IM|zTAL~o10e{r`&&6o+mBl@4GgQEOQ#~zrFqv-O0M0 zEOgm^tDk%JTKg+qHhz^)S(be_+CQ}ZB1v)*p9)76?;p4yagLMq270c)$2=Z9w$B?I z_8c!y&+%~V_OUD7<^YwC`tkhE?ULsvsRx+PSsfe9arZc&{2q5H=Jm+ab3b{^{opaL zs2=a}{ax#n=N~>b)Yp?k7_4+YGnKzX-xwF4kag};cHB(-y5)&?E$6zVp9icx`q%dJ zF3a`j+E0l7U8|S#M6&R%9iQ%eaphe(&vJC?vm|1a-%wtBDg z9rm}r?&>4sbZ7tVAOA5G>Ea{u9^KB0wEuiS*6Ztd?&5Le_B~l&Vy=JAC#+q4TyZ{( zr%U$v_e$1|+pIjNYyZyAbsM*sd#=WN8eShAOZ?&$=@0i@*x&c#3e~{%L;XFb_2=eg zy&wJp;?C>%-4fNxw8%NCS?bs1&ZRBp$G^!IKjYV*{R3XMd2PT^uV_DAzejF)K;vwT z+Ynnpi8LS`FaC66&1h{W^A=}^`v4#3gWI%89?Iuzczxf*hF!vtYy*6#2c;NZTQGG^ z5+7OzNnXN-W+m-^ReX-{iyXt_f%8ebcwBB$9{F>1;;ft4a9za@kCex3!V&hP>dkvD z+|!!q*PGsrm++x_)ALXjpHourPTc$TruFYl_@$Uqzg@(q7azJV;Y0TUK3C*EiF8r! zGf3Z&`x4UkO>8@; zZhr|MTpiQmANxqhtoWyFh+oG|X=}Z2#ox2geMMr3q=Q!H03Tc(e-B>)K5*MnmV5H` zzT6`=9Un@WyKw(qDU%Y)Qu;;&ml#( z#}131=dHdzb}$}eufq?mL+}%uMT#r-x9~-N?jR*U{{|`f`BS8@>!fjuvC&EXk-c*m zDP)~rM2dQM{)&{h2kh5-A9TNg43wYzRFUH9`~kjT*F|!a*A+*K^14nUgLou9kB7iRrO zoc2}UJfLe!bC~9)gLvK9RBhAa3pZvxOg&xuK&mkHKjNoy!KjfDLX40c`Tirhnb~01Yr)~*OJ6eEwrwL3moPEU@>8kQ+0pUQ z^tt0Hv51q&^g{M>dVYF3*yB~>R4VVzj%I5zh9Bky@)SCR5Z3|Py#f7=xufrHcbI2wN zUX!R-s2Apn^D_mGOL4xKo}HTGcDoJ?`n@)7+Czg+>Y~B^BX486rpnOq>D*GU`x{ffanpS>|VpPhVC?G`8VoLzd#PFc)s1Ux~Zw==^|Wy}oeKg{X$ z?EL(d#e8~dcIs+;&&FKeA2@&)>OBhBt_d!rF?J}r|Hu;p=c=|zuF0uFk>fpq8CWQ$ z^YaVfo6=u7EFSr{F-k~~FH9{?&Ijm!j$k1>Ik|8kH#eAGJg_*JCOSCyh1^9{bi)!Q zQ_LXqgq(fyr^&uCN&QZvSWM3^1aVq_avWbIpQb^}Yv-#V)N;U9yD){x0^E0LaT*yZ z25yo-LSrZR^lOdlh3!IV1%^8qQ-x+OH@cyPqU7<*TA5gz8IcEW_hw4=z}n3`_>tIH zW8A244T>*JUE6dvP^+QqKSKKr4f+j#W8>$}q>r9DbNtkq&!o?eym4-1jFz68HdJmN z%-ZZ%vzK!ifpEatJ~#ZCQ^(krLlk6-MQlyza9U;J6EoR`VBcOhllRh8c0#sv)pvyy zY$3>hxj4h6)E(910x-`4f}3lmep7xgsa z`H((=o=lCN9Z#c6sb9naEqGr@T!fFU*3Xv*NWbBAHtx+ba^!o;{RB_Ye=)ElXel@O zgIWu9_K!w z6Nud`WH7j00VhbP>@Gkm%8nfVppzj;)v(Q*Iye|mFGx|It;8n z9&(i1e?3~hL!Q_O}F*`O%5xJu(b z4Hw5o&z%_`Ih%fcrQSTWiEL2IuzIONT{(WS`Rv4%sbT>e zIyT<4-ToRprG}5aJ~BR*P7RNZrN>9dhfg=CkG?fNvZd1H9X^V^45yNyFXrr~RdFTMDnA>nuK$eH8l-Lcfju~R2b zjU3-ZH*x_=3fYNMXUE3V^)udMrl-!lIehvQ+#OG)kBy!C+?ED-DX^*j%&54h^Tw9B z$Ihquh>5};v)L*%uH^?V6$<76j%o#ZuO;u)1G>jW?`!et`p5WGNq~#qjortG-`^pn z_qg;P8L|-GM8(|f--KHyNlX}Uw45WZlVzK3^sW=3&d_^+9! z8oh(Q?J?P}3V&dlenjtfA9;-ThM}nNzco!CBY!CH7;Ou=@_%TWn_(L|DSBeqhAvnR zx0>cC-iL-V9^?IAXvuPj{8M?iME?t>c_-d4ho$`Rmrdvq-a&?Aq9?}d%5a~@c>f)a z3;!z<`k3@X9;3ZsSD!z}8%fkBJY)4uA=A7Y<%gyGCj9C;g#HNM7CkZPR}?=Ie%&t>y$zfZdt$uvZgS-l?*hB>i79_o?0>^FSMhss(?gG;Z|+l^ z6#i4w5{*KivW#!OnlB*1_`%OPEp3Qbb4mEPX^9~|%~F2zsA&oIfNzVQnDloP-xGev zv?Ngf=BmeJe_!#cWqkA1TthdpQ-8O1 zVk*Ku67v}4MWp?$gC_iS(g&g^ru=csG=9pYPg-t~ctu=1BwqZl3{W1&4`oM6%Ko0P z#3ORwW5g@+z+=QSQnQS2zM?54@Q?MTWftQ-D&@C+-n87p`Www#Ju~u0mxO=WwA@C2 zMsImc`eotYHZAWHmlfX;u9=p5Sf8R&|Hvmy%lELJMypoOO!-$8OM4`^D z81@J$w1J8MTiY>%q2|$GgFO9+Q0_{9V(!6SmuiJSP1~;XgF3hY+uADa98Q zXB5vU&MRJ0TvB{X@v`FEipz@cC|*%~PjOZ8s_;jq^*xHmBg@fd)4Gh`(zZv151ZCm zjQ8y^%lPJNdlCuy!(H1?T8_Y975=uTEZ6lCkLaXn{Q>E3S$&DhJS)MgK2M z>yNM=Y`+ZQ&JwzJK?oG;Ih@@ zJQV&B@k7heKQZA)*iWB&WZBsxB;5Y!x(VOM{Avr7K5lv2t0w$?)Tb>WeA(!JclJ9@iv1Tc6|jEqkn%zwn8<$AcgKv? zGb0{5%9gP{L{g+*@fh{ranCa5Yb1mDy5qjbq?dS8{ENgjtKT+fB45IJV27(eG0MXc zirc&GYbJ6l2965R&ztPI`>-(SFk70dUG=w6|U2SI?jE^pt*U;awTcZEZCh`&1=a`h=)@CA)(4U=sR^Rrb ziF_ObUl2ZGq54!Xf(x0@vJ=RJG!zvMCLOP)RHZ+T4mWzU}Uw>>6(*|R789gj)B z;@Ok_p2wuGdiJEh?=k6DJ$uqW@R;;9&z|%TJtqB{FrA-qcg^XvO)f6pCZ%&+@Y-il|B{_eTwG3oDHcF!k0s~+R|r00RKJfHN`Jf{2)ExYHF zo=2A3f8RtOVDagVdW?AY_6dJ%qCZ6ZdNYkhfNGFIOmq8?kRKJ1Oj`O-`QhEuhE zyevXWsO`>=Uv7Rw-j*Umd-1zK=fBTM5r-J=Mb76br+Ty@=W~z9`5mIzcl&YJ zoS%Pz2r4JM*6eks@6lWCY6_*q*D=sTuQCwBL zs<@_jt&w>f@Y>%JQ~E%0LUB@YN^wSUUU5nBvf{Gh6~$G>tBPxi*BY6(O|Si}F{KX_ zCln_Yrxa%t=M|R}FDou9UQt|CysEgSc&(9f)NWY+_;&~|9+5!l6N;0HQ;IW+^NLG~ zmlc;4uPCl6UR7LEyw=E3puhh`V~PXC3B^gpDa9GZdBr8g%Zkg2R}@zjuPUx7UTb7L zN;b5gf7kH(e_NpR3B^gpDa9GZdBr8g%Zkg2R}@zjuPUx7UTb8$N@-|6|IXmGe|wc6aZ+(g zaYk`oaY^yA;ZDo!cRD9$S`DPC4wR=lFP zs(4j#P4QYI$AJF+A0vU+{#c+mp*X2Hr8uKFuehXmS#eqMisGu`RmC;MYmJOIH4W|U zj42KjCln_Yrxa%t=M|R}FDou9UQt|CysEgSc&(B7cQCKN`FAg$17)93oK&1roKc)t zTvEKOxU6_ZaaHlE<2^6N)t?d<=x>S5fg=75q&cuKHGAOb_=y7y8-MIca{AZ4^*@-l z|N6N850UGCR?UAA&3~M{>7Uacn4Nw5D*tN;{KMjndXS$D+VFutq~6T4`)kyOe{F0I z;2%{MvzL(GxXP)t#hgBRG?9MgQ#KuxbU@NqUJ<#Z1CqWnDESWC^suA@k{*vbv4)P@IjltEa`xxLkY2$^kqp8CeV}rf3E)kH|o8yb9{cx z-i4}8A}P%Qcj5OHUK5G+d*&nwH@V#VQBu8vkMp-hetwVbyWs~j5xk6)A5@SgMJCCy zn%tz2(qYcE)8&sr7RSf2(?dkp(@st{{^jH(>&M5{f2;gSGW0G#|DQqb@_Qz9`}9dG zc;*eI@Z!EjlFOCe|3UD#kHZne*!(fsP!_+ZL(xz%&P`DeWFoMZ2VweHX5a5_;r=DqH4pIjH z5eVOB_u0F>$5K)#3_CgP``LY-XP)qPS3?ucpTzYuzT`EbOHx-EsroOOf^57Pww&U`aL3Jx&E^dW5 zhaK`~>ES!t&eFkEowpxY)^5(uZPkLav)gn&j#5(XZ_`+@*IIW${q)~C?O6M8Qrkah z><`twTt`*p50w|@jGZ9l_ENdkL#5VZzZPFNek~m=8vmMKr0R;D*=xp5MgP8bU#RPK zsxnUu^54VpW)>ze)u` z2a#9wgg=X4=6Txol-BcS!&=YA+4^ng*{z^ycc|`&kpoj|Q0+Ru1uGOPyPn*6c^u_r zhw3Z-K%N@5>&C{VIzPkOFFP+OuI2UYh<**#wbhM4ZkFfUeeK>S|3N)Z-MF3jKH90q zuSNT5{a^gDSznK|!H8=|wCm5A30E0kjxWUrqH5_CvoG0rU2F^Jc9tG6pVM)ne88$ot^M zw(sZ)vPY6;^}-&z>jT{x!3o_^+A$wb7vRubFkz*kbhkYacN3U!Ywa>zVHd{xuVSfB6AZZq!s`OrvT% zX>$MCK7HZ8M!O31EA4oi{V(j+xwYF!n*mZ|ugU#ud-a9?+QT}p=r4cRlwUIg*r-Pr zdfi5^@e`bPnB0GLzrJW>o_*B}z&P3?3%0zFH1dl#czySnj?w*(l3m}0QNxX$CimH2 z+b+!?iaXi&kYC~aBbzp>-)+GDg2AToE`vMxJebmM&@v7-xf%_rr$#0Ud@tJ)UH*}=`kGTEG|7zT5 zbg<9yx@>IIsCMgOijYYKUI%d=2OAH2pR((u!10ywrgcpwt^82kWgY*;*UdVm`wXoN zyPs6|#R=^|bssSE+{z8rV**0g)+hFwbzH3|)r}EOaOh)%U6_a@+6Oy=`3HqY^dcMq#M_W6G~7Hv>6T|FoK_Dc{F-en?H% zlz)WFkE@xQaW?XmgyYX+EFV!RTpFky2f;L8^%%|Vhdqd`xe>MBG>88p&@GqwPN6I>1`e;e#kL=QF$~{+< z-{V|Sc*DrkxRoH+%Kcd6eo}n3|7P1(1quq1v~SNn^88}^N#ja!vHh{qp}(gpiirrytV3^nWqGrsMntV@|pAi*|ta&zbQoU=30# zJYn)+gE`+9t{E=$nY{hw-_!OA`&bUcPAjtgrQf-)+|%V>)#Zyf%=&8GY|b;TKCQp@ zm%gIqwEqbFWDjZMyvOZ)1?{w9kDlxyuQA_tnssl=Z}cR4j9_A)30R`l?DxMjsKr&X zCv5cgnT{q}ja;?=R~R>*sz?{)jm*&32My zoJ%Tl0nJu!_6f64$Kj8*6QRF&j{v4bt$qv&_qGcbm@ni7~V<*{R?9h3OG?E?0 z&f*)!pJWG>R?pSR4r9lE)WprMtH~b2lSj3UnvC)-S1?Rym3r>UpyKlQk_KGY_iF&oz~L6Q^pu z>9=KlUV!Pzj>EbEzlH9$IG?lrWZNNA-fYeb6+fCyysPYKxhgjc-YeLQPgUN;yUOM{ zvC8{v^k;XN^)ZfVN)fWpd$do`5^7LSYx%-2=}aYNd46O}Jd#fuPVO@7w_(7L{6~%a z^Q-~T5vRd|j5Vn4+^CVwjZ z)XTPEQW8;5c++T$f(*Jp!A2Rck+HXL6mGdE{53P7AM<^=i$Od&= z`;DR>D1GTWb^88GMzUy#KKFPIqo|(RMAMY&$PcfA+8up{qjH*Vdh+AR3pP}Qw%nHsHW}HmeCGFZAS5V3?C}b;d2xp+C_`_oWKWZJIxBKhs%01 zE2*lsAKV8juQxjzUDnDtzSf&v;eMG0dcZ(({Wf=8rKI2V%|Z?z@|&J=ium;5gS34I z{O<5`&WAA2)ZRyt(;OT^PU|L%oaXX1# zuf8(ZA91e3&h_KY^}oUn+Shi>9YrY*^`<#K%lE1KyI_^1_S{ zB0tGR?-?&_N)CjlW~RpvK&<_Qt$oTB_b6>B4pD#13s;P#vJ>9pUdI9NglDbk=1B;3 z?I$LvE7=+EnP9P1kc4j&g?j1Z6kH!092efRhML)f+K`rE`+fVotQ(oIM-V@%7 zFRCqDwos97AvvSV`(m;4{e%7Sp;IxI2$RUzTw**vGdAY!ciiZU#h*Rxz33tDKYeIlt`B96(4 zRB}>Sv;ly@VIWSksTv<2`%U@< zOe~0QNoP{?qca|+jE-$4F*-VT*q=TgpFcc*JWkYc{CWQ(x=@uQlW-YjPN7yG{eIM| z>)IVoiqhE3oEN4o%h!=d_B73Nz1=1S%U z7&Exs3#mzrI7 zolvh)*M5R-QM4SY_67!r&c%EB&YkKz_rvk?y`LEB9iZK6$%M+TkSU{nIWg{IZo+_8 zd$#+B`%Y?E9U?E0&Ejr`0jG^AoSaC^c?S>J#eaZSzb({~)_vPZ#xw%`@$7_drDCw+ zP^GJx#D+bs+RG%`PdMhfXlJOcou>J2`_nx*cs@RGq0$&NA1D9ORF}LF>8Ui1T`qIw z`A=UY8&?w3Oce|63L=?vJjJFuV(&3v1F`;d z1HEo2=`Nla{q#H*dN$!tg>gqdwSZ7zPo`z) z?m;!}C+4T;Gx{DJS%^gRJ&;SNKQLybXwQV>dKb>j%+DoL-jB&;q}N0IG)6Mke||8I zA*FF)1GM2iAGrt{8||ORj#7Qq>QvZSWn{>;U zQ9IvPT(A}WKw)V=K~d2m;m!3ux*v~Un)j!&{xnX+my_v5ItIqGmvK1a^Pm})LmnLh zyU+HXqu{TnL}y1U%c^vT{QeY;WTk1hEqnW?o1*TQpCuj)2BM)gd6ex|^x*oLZ4PQSE+&3<|G@G4TH#B?zUOy~8 z4XaT%=VXXg-L+?DD^t@!oV)*Hl0XLrm`8_&~f99o7-QF zrC9gLkM|A^#ADq91M$KB!S1s))jiJ*_HI~db-R0TFT<&1BlV5zt%bqi4VBlevU;b^ z_s2HW+@R9xnyz)99PH~q7vCV7>xQo;zVxnyri44Vz2{D0bO&O+C;LwK^`2U%u6G!f z6tdHO=LZJkl{4ObqJ8H+*?qPT=1#@pCkKX}-B1AU5!S6g*U#qZys@G7z=gOzVxqD8 zWHt(o?fKzLnT$G&qgqDMJ9v5*Mv30<(q|7|vPS4dD-ykLTg8Xo$5Enpn|N)g%R0F5 zP4HjiLvI{C{3ZTReD>eiq`z+`Zinpto10V@*AIgOU*DuA1m~E40`(7;HmREq2f!uf z-#~rKckwn6IoT%;g6WsP#D9VO!FM*PsKYzK)GpP36L|=4cGC`f;H%65yfEAn+N|i8 z_#{u<48F-s_JgojWd0cHckS7%BFIVpr;&f?UY+W4csn@ia4Yx>^PeK${!X15b~pe| zGrx^|3*KVpnCsB>;6C`r+zdY0wOQSEI0(KYI1D-R@8ig~{^({EbGR9tW*$Yp^XE3J zyu(3ok@*$mTfewjtvb9DeAnTJ!1o+(1Jh5ZsD088f+v{20X|Yhe;f{iR|Vf?-h@09 zYEbu>VbUbLP$v5iqr7!%gYuX!f&)zrD$Gpn?nhS5hPzw$Rz{`TK zGygfYcd9|%6nvZ6y1UB!O~?mh4eAc_zk#<+)T_J9a7}Gls8?lCe^1oYi*)M0)o)_9 z`nyGaSky8Bdors`Ep)DMgL2~nRD^~<9Ex~R`HTYql~`Bfo*hdB=awq_9@A%Bng zr%+!Xu2;M91qQ|AtKbK_>Q%(y5V(uk$}cc~9rA%w_3Em_&EV?}Q~e5a3G#b>u3p_{ zrY{~pjK#U?@D}izBfkUkcbFf8{Fc}1RmtI9;JXfQ1>a*nMe^6NxUoS~|A;>f4l(;w z|HXRMB#|+ik%`W^Jz+P^+T;9`i3zdv66)XshXu<=xDy zsQ0iLdCdO;-t*mn3NzEWBk;X|>Jl7f*6ril))=$C|AvBU#Ni+q|1eRqt;}4hO(tW*z@*P<1iCj`mw$45~8@2f@S4tEg|fit%CoXOdqIstJepfYT0d2QM%m z!8&PqEvRx1cYv=tyaP{Fwt-S3AFf_&fYTaKzzl;4{pp zA>Xo!_%qx2m1Dkw`uex9KJeQEYX7UmC5#XAw}`(PRBOz7yvspVVy1Q6_C2(Z9|e&9 z$H1+)*`}F41#Wr=@noK*dfZHJGyg33p*d0@0{2KEgqdwRbQYFD< z=5M3E`D{r49_mf_vl;8oI~7tPJeLu7fj@92q?#Pw3Es_|LjBI=kP15-1k-aJ>D%*G z7c-sr9+<-Z;V_;5&N%W9;5-_0n9irejy&m)I86Ezjy&n79VYz+N1pU^4wL>>N1pVr zGrxlVZNCvxd8eN2-E{QH-U{;PIvg^h=IB>ECsj z^vjMs>ECmh^yz`yjtA+7947rHW;;H+9VUIxkthAI!=xW^I8UE( zn9kS3%=YlKJIr+7*)fdu=aIY2_Iaf2Fg=glbC{k-=tp}LFZ(>w z#H`ono7j(-_4!vG_IV}7T#x%s^PP|yaX0`@Gao^H@S7pE z!feO$w!<`@MTcoTSDEd2-f@`5v&3x2^Dgr^+S_&)hrahon-pGjh_rySq5fqY#?Vdl zu8GPggo?-IYj{WCrm_aSliKQ*;$0rg595sDrVy9oHeHi;b2*MTHHqGpkw3ddc^8+{ z8Ou$>TwWGonc(u0D8I_(MNv-g*r?r@D9>~GiYOo9@)6wg-4wR+qFix#NtCZ}`Bf3m zoV9~B=%yH#)0xyw%htZI6Xo)oV%(d!JT2_pw)QdC+;pAG>1^btGu96FI5*wXfOul= zy6MjV&CdMv_y@LUP`*RqK+VbHoc=XEm0Py?=XE)5D4gu@kUKk6gR*RM`ezSRZr!)# z16)q;oGIDz-@-M?dsK*I%Tc5gwL`zHrDq*V#PoaKqF|5XYwL4@BfP#S^YD4v;WqFY zhxdX99exx%;_yE3g2UwBOAeENhw!09#pF{IA4-;E1}i)wI4w9Qcv)~>@QUD~;5ES| z!DYd^6DYI(n|WPjk2>kpM+8R&#{`cEP7BTnUKX4eydt3*Vpu~Nw6n4 zA~-5ICU`_}T5wMAvf#Yn6~RTpYl2IH%YyAzQW<}~k6HEvM+8R&({~k=tp12#`tHK5 z&k0@@oEN+zxF~o{a7l1kuy)k(w}~8g*c0sTH#C)^qCO^gL~vSgPVlneyxK(FAL5KUJ+arye7CLxGdP-GHrk9yBJEA zJ;4#dQNc06BZAX{bAp!z=LN3_E(%@~ToPOstoS@=``aYg6C4p76&w>hA~-ELCwN(K zUhs1eXOX ze%`SDHVMY--J10f5gZj96Fed~EjTB5S#VzPir}K)HNhppWx@1a5v5B11$%-cf}?_C zf=2|W1?L1W3(gB(5nL3!Cb%THELidLRHgrdJ;4#dQNc06BZBF>AUEDQ!OMd4f>#6= z1+NJ%2`&p({JdA`zhF;rL~v9veK+LxZ$xlfa8B^D;Jn}!!9~Gqf=hzSg6X>|*WV_= zp5Tb!s9^do%e6NmI4w9Qcv)~>@QUD~;5ES|!DYdUpC>EhFW5eR+WLs7j|!&m&T9HE z*uF2Y_U!Yl^H362Pk3XTaL5u6sB6TB=qFL*_8QSh4JlHjsnyiBX@zhF;rL~vAaOz?={wBVfJ zWx;vDD}sxH*94aYmjx?)*F~u^{{?%3BZ8xX9}6E4zn{*~52)4QEdEKTIy{$}I@~jO z`ml!TFI=gd{#A74SK{VhX;=QicICI^`e)$!7uoCnhWPN*)C-sOKLNo%z^?j1cB)jh zfnSfWXW9M)x8`4EtHby=rrE?LBnG0wY=vOUi6uhg~Q9h`SXxSsQ4 z5i>7-(7%5J1N_RR#?)UuXK~ z)#1k@i|QDz=#e2>DKQu2UX#bToQ_r0Ppi+{tp0yEQJIXv2*0-vv%bx&zU6jYkpCO$ zN39^|QvW+BmoX*LJh%T6=d7;x0eemPxA9r8|IyP%Ds3`F{ijE3+rI5Ty)$30{e4G_ zVvP3>LuMbc*Ob%$A7s7uSGaw!D literal 23808 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 diff --git a/derp/xdp/xdp.c b/derp/xdp/xdp.c index d18a4190b..a72e67264 100644 --- a/derp/xdp/xdp.c +++ b/derp/xdp/xdp.c @@ -244,7 +244,7 @@ static __always_inline int handle_packet(struct xdp_md *ctx, struct packet_conte struct ipv6hdr *ip6; struct udphdr *udp; - int validate_udp_csum; + int validate_udp_csum = 0; if (eth->h_proto == bpf_htons(ETH_P_IP)) { pctx->af = COUNTER_KEY_AF_IPV4; ip = (void *)(eth + 1); diff --git a/derp/xdp/xdp_linux_test.go b/derp/xdp/xdp_linux_test.go index ae14780be..1a59f9444 100644 --- a/derp/xdp/xdp_linux_test.go +++ b/derp/xdp/xdp_linux_test.go @@ -426,6 +426,18 @@ func TestXDP(t *testing.T) { }, }) + ipv4STUNBindingReqUDPZeroCsumTx := getIPv4STUNBindingReq(&ipv4Mutations{ + udpHeaderFn: func(udpH header.UDP) { + udpH.SetChecksum(0) + }, + }) + + ipv6STUNBindingReqUDPZeroCsumPass := getIPv6STUNBindingReq(&ipv6Mutations{ + udpHeaderFn: func(udpH header.UDP) { + udpH.SetChecksum(0) + }, + }) + cases := []struct { name string packetIn []byte @@ -865,6 +877,42 @@ func TestXDP(t *testing.T) { }: uint64(len(ipv6STUNBindingReqSTUNFirstAttrPass)), }, }, + { + name: "ipv4 UDP zero csum TX", + packetIn: ipv4STUNBindingReqUDPZeroCsumTx, + wantCode: xdpActionTX, + wantPacketOut: getIPv4STUNBindingResp(), + wantMetrics: map[bpfCountersKey]uint64{ + { + Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV4), + Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_PACKETS_TX_TOTAL), + ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_UNSPECIFIED), + }: 1, + { + Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV4), + Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_BYTES_TX_TOTAL), + ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_UNSPECIFIED), + }: uint64(len(getIPv4STUNBindingResp())), + }, + }, + { + name: "ipv6 UDP zero csum PASS", + packetIn: ipv6STUNBindingReqUDPZeroCsumPass, + wantCode: xdpActionPass, + wantPacketOut: ipv6STUNBindingReqUDPZeroCsumPass, + wantMetrics: map[bpfCountersKey]uint64{ + { + Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV6), + Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_PACKETS_PASS_TOTAL), + ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_INVALID_UDP_CSUM), + }: 1, + { + Af: uint8(bpfCounterKeyAfCOUNTER_KEY_AF_IPV6), + Pba: uint8(bpfCounterKeyPacketsBytesActionCOUNTER_KEY_BYTES_PASS_TOTAL), + ProgEnd: uint8(bpfCounterKeyProgEndCOUNTER_KEY_END_INVALID_UDP_CSUM), + }: uint64(len(ipv6STUNBindingReqUDPZeroCsumPass)), + }, + }, } server, err := NewSTUNServer(&STUNServerConfig{DeviceName: "fake", DstPort: defaultSTUNPort},