From 85cab33148b05cd4ceee955f0bcb31392ae619bc Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 06:07:36 -0600 Subject: [PATCH 001/530] clean up README a bit --- README.md | 24 +++++++++++++++++------- doc/img/dependency-resolution.png | Bin 0 -> 10766 bytes 2 files changed, 17 insertions(+), 7 deletions(-) create mode 100644 doc/img/dependency-resolution.png diff --git a/README.md b/README.md index f9a9f98..713e281 100644 --- a/README.md +++ b/README.md @@ -1,16 +1,26 @@ # ifupdown-ng -This package is a work in progress implementation of the ifupdown suite. It is -intended to be largely compatible with ifupdown and ifupdown2, with some caveats: +ifupdown-ng is a network device manager that is largely compatible with Debian +ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. + +## Dependency Resolution + +![Dependency resolution example](doc/img/dependency-resolution.png) + +ifupdown-ng uses a dependency resolver to determine interface bring-up order +in a deterministic way. To use this feature, you must declare relationships +between interfaces with the `requires` keyword. This keeps the implementation +efficient. For convenience, the `requires` keyword is exported to executors +as the `IF_REQUIRES` environment variable. + +For compatibility with some legacy ifupdown executors, we also provide the +`requires` keyword under other environment variables in some cases. + +## Caveats * ifupdown2 python plugins are not supported at this time. An executor could be written to handle them. -* ifupdown-ng uses a SAT solver to determine interface bring-up order, like - ifupdown2. However, relationships must be explicitly defined instead of - inferred by plugins in ifupdown2. This simplifies the executors and ensures - consistent behaviour across executors. - * ifupdown-ng retains compatibility with /etc/network/if-X.d scripts, but will prefer using executors in /usr/libexec/ifupdown-ng where appropriate. diff --git a/doc/img/dependency-resolution.png b/doc/img/dependency-resolution.png new file mode 100644 index 0000000000000000000000000000000000000000..dc28eea71de2ae29875dc6b0075e18193b7d642c GIT binary patch literal 10766 zcmc(FbyQT*7w*u~A<`|<1JWhkAs`?kAgM#QbW4gLAUOg8QX(xa-5}ivNHcUJAu;dF z@4fYUt@r0!z_1qFxp(e4`+ob2{a!~)g%FPh4+4P@s;MgKg5Oo(=lUKtcx7hHKLNk6 zEj3gWAxP9$c5`7O1i}PSQf`@31?1Ud@m{bKN*Mky|*I(qUykWxs!X_N^DUR7}6r19L@!X^zXh*yh1&hDVyX zYKu#ZjoJDnNvx8;e`jqT`)Hn5v|JCR*36jtm3rYuMYVNW-R<4~Q5qbnVs->WtPnK8 zeZ)ee9MMeVi>JQU*Hd+OcYpi-{hdK^xNcFHa&AazDU_8AH&2%{BO_z9+0UzQ!>#s_ zJKo~ph+IH`)cC}N>+L^}*Dx3hH#ff5!GfHc8g8|bW8{dHl@*4Um)GULe=Lt5lc1rY zQHi-Q-Q3t8{Vj zX9a=4e(~Z3xaPfZ`Pun-1y-`0vN9sBWIRGb!f)Tc$;!#0;o;*aq^3sh?K!-D^JWDx zl&(`ewKZ469YIJN@xs&x>)EqsM`vfRB{30g(u;%I%upzyq}M@LjzXl4j!y7mv!7L0 z6e*RozgPq@W0_Z?tq{%4*@U*Lnwp%Oo4}{U#AmNw#V#+KYr+Mv+&72A)6>&U2i8fh zWuHKGxRR?~*OYgbT4m6((J-(_zdtYD`uBHNdFHEb(bnbhTD5sQ`p$Sh{(D81&qB6j zx0h>i$}^VOtS7KL`g~nAGyh{OPI9~-m6bWR69r@aiR`~qref6dzjk#g(g@p;<6@%I zJT`|sVq^QHRcK}Wxu`AuW%1N_!PE4lH9ZD zi)Vg&b@Hb65ga|m5fKwZK=Z`=@k?W4JqL%9{`AW@lV;y!g21O9UML#OCkb)Abghmqb3=B3jG?0^!$TBc6WH?ywyp>Q_ zRb}Gl<~C~b<_GIs`-nPG@q-UWT4G`-YNv*WhwEKd(0$Lg+G|;xAClawc)P9Z?dNBO z7=&{`q1^|68kxyn_KY}?V#I=7=Z6ha)i*RSKYA3Ns2rH_{yzI^*Zccoo_kajye9X4 z#9vruh`PUeMc?z09>3BsCRZh{qrd;XqnfhCY=y;aoin57-fYP8VuMO(uUN&OQGTHh z6i^mxYwMq0hYa(&h8CxYAy#s{?Y-Ys4jTMI3xSX){+Exzp3Jod$$aGZs_iF6b%(S7+6*UZdpFkO_`)z#HufS-IJ6QkaCf{mP< zd^u5D+QJxbS4>iJt&>=$>xEfB`1QqM6|~pfWqeQ~lW2Fkv~#ul!^+Bv#psX4J>JfG z4JB--0wa$}J;|S+9-Te0w7*juO?yJ55WYa#(7ikByB5 z7rmDuboxcgkA#d2T}DQxHouyv=(x4AymO$N!BWyXOu0F9S2#k{P*amYU0vPfeD7sw zYBx4`&(-NBDK&L}ZH!36PZ(>8V{ymunV$}YX|I@nTmm0*XnDie$EUrw7pJJG2%GN% zp_nz|#}9#p26r50W@csXs*@hx80sy;BEy)2Kt8KZ_zl9**)x^-?JgyiXg%K^D~sZ- zN%Vzu>$@Z8TBgByEHWJ8E~oi-C%ajzvOdl2H4zaJs~zF^*nE+wQ-ie$jauH_wXYT^ zZ$fG})ojpxx96(3l``X@rj5Z@_c%Q-9w0kDm(k8O%5M*8*-$MuSgA?d zABJ3bL1SXS)Dqx&xF{8x+KHVZ=>GC0HKYv`tIZqio`bGQxi1wI10+}Ht&d-rhHl_6 zdW1CBBeJL{*U`8kMi2Dt8{d~2W#mTA;{9614z>4ib(Qn+X=op?z!-)%w0voJu92^s zo4hSCUemp)%1*0qTI_JgLmZg2*R9?`;Krp>H&~ufKHaf6)f3D`{aS$9&fcETl!(@4 zco5V*B(2W0=j)||>xYrTVw&Zfcc;003Ek1rw2?>DUx z*RO#A@pQHK?l31i)1;J?+N#34zL>1gykehGk?GaJ6s$|H2B>uA))eAy*D5sOWEws1 z)&R}JgMkbI4I2pFNZYf#Y*e$gEqa!2-V^2yJD4aWc5rZT*`E{6O{Tu-_IC(;NatCr zl|~(ealB;BG%2@me#bq+5?J=|j&2WEaz>VJtT}q32>CdAy7)!;*C6DbGUvdoi(B?H z8ygN&?-eYEx$5_hoNQR6IU1?Fms`1UM~i-kl~9!>7x(OEii(&Y>BLVo)d-*=NlE1T z`ugVUeF@+(1J&vdO7Z0M)b(Uttu{Z6+_=uEd$~Q7l!~gamOQjgP0-KJ@8Odtbl?H8 zGLG&)T5iYKTWV!=Znyu;_*PWZ-WGzfvcDg@)*I(8{!m8LPw?~6(NP;f<_e2W?7csYsgB~x zDuolw5)w4(`DF98j%z;>&HMbap^q#PATFO!bjVjm>3%F$ocLc$_8^K3_(QgJ)5|Wc2JbLs9AeW(wq;t>O zw<){N{8rd%tYmY|exl&G2+&2~g4Ul5c?vQmy?#J@(+oet->1>|Zja}qdc@VqMxH_O z@07e308~|Sa&p!|i__IGq{1B#aK8`M{E?)jB#p#dj*a#83aAR--h5qLMrI}_6H{AB zVxbrMfRG^RGfz(uEG(=9eXjhe;um@f3K;XBzI*^nIu2SNE(B^=5xldrGn>*ykzx;H zDWIpPq*M`r$N2mE+w^{yKjdQOEbYWl>r3idhAZSmhB@mj$nZq^L5S>O+KfpJQRs0 zyoHZ6QqmN!^-2vU5+179bcEpoW}t)@{%&<`t*Ev(#nH9^(-|?%!Nv8p#(qY(+_d=~ z*_i zp8GU!CFtelT)78^^rlSLa06w%e zU&lv|hxO#ilhIORQE(l3mV~zHX$rFUn4r37VzI&N)YKGMI0aW%ey~igyVFom6H$sR zXS*}Rosq;U-riyzot@A%;p)KUp#^GyAFgXXgkW8m+1YWFl$82LMpVFizZVzh=oabd zSw;3J%k;gbv~YAJ1l1=dCYG%d$DqSO?&9SYnU%$ej*h;3csMdu+0zp&T9u=wiCLhH zbICzV=R}OQQOV;icOj(!5qs6JmLND=};D2KxagN3{f-7SCj9&8Bh{oNm z3^_m$gBEtn)1%wLGiIV?3>qP#RcJN?B?bmT(|K6z}biRySR}@84~$niYy_CiT8hc>|(!YiPI{-7j<_zI5fck%B9}_ zO5jIT6~LizK)lyCHgc+~tCO2m&}MP7aUf4WKmjjw@$gW}k`5RxHYSG%WSN3fQ(si!N=Zqr92^h<=Kpqgn$WF* z4q|R?9T$d4x){`oBL8+ZG=Q~o@bdPA;t=cT>xTir5=K7LH!zUrp|BdwmP4U<8ow0@ z0|U`BzuZ)BZ^1ex(Ct0<=fc4|P>&%AUN{wiH}FjGJIp=~3kz#oTx?O;9JiTcRGaC# zy}oe0yYa~@C}0s6r*6GD!3W^S@3bJMnJz+D-tv#jd2jkR&Z=$u_C%p=PYg9{f@)uT zdkAbeL(T8vAU~3r@yAzocJ@dzGBOT8rNiWz0TV{y%U0b|pp{Y_Zem|LJPN=7XjEyY zzT1z`W!u}^&;HJsCF&NvHa5ZsTzhLmTjr6rwl*1FxRB$V(68ZPm~je_09SyJ0tTsw z9umx^m7xkmlY@pGWsT8O&}AM1iU*D-r>B1kklA6tl6FA&6x^}Rzq4)3VAFuV&wskE zVFQ?^2A#$4d@lzu!%xl4QUP~Yo0GG%eYHHb6`F$VKyU!qV`OBMa9h7O?$`glb;zHQi+R;kF9h@{!X!aOhZFs)Bouasu}&=naZ2ko=thpLk9iYDIg=m z_)z6zm{F;+kr54O48K!eKL!$Xy3`m4++Nf5L1W+0P*-9W1fyAq%dML_o(Sf9K22yOD-T%qXqc8hDEW ze}~zM5J&L{b4GUS&t1K}YhYyz8$F>Y7O$eB;(v48d--p--1QXk6i^XNz%p}k(98m_ z9$8vhNeU;f4IK!?H0tN6ywNVKM9^TOqd866&MjSu!$qAL`~w0K;^WOL1ZDxbyE|w+ z)B!41bkRE$P_jrJjxNBgE3HQu^k2NFf~p(>4%+Cs-%;e84Bw-A-V1y%QCSvDvf?;hb zp5(-#+)HozwIeCzmYX`QteO6PTu_8PKvMk89osHRSbm_|K zgD_#015syZ4vo&e7yml7c$6te?hIT0s(<*gbbW)@(fa${V`oZLx+f%!j`+XIgQ77u z{${q6S#(A)3k%mwZ1RiG9?(s)tEs7B27`i>2q+UJ_k8U*A9tR=#9pJWCgT*t%w5TS zYgQ8-6-9CG!BReBF!3ka_dDlR@||QytO<5kt(fWDqjy>h-mC8(I&ZRUSMYf;gMZl57F8awp=CeC5{3%-XebGB=GITl)H=?K02g5U z%tw>Jsafa>k?suOM2>IMSHVJs?{44j!=WX)r;x)n^gH+Or;x4H!yY!4?|hP~kgdq* z2*g?^(!J5Av4A-hG7A5W4USPl4~Ysa^%IJ}TXAL-O>f9KAxFy&ee)OkixI(*^Q`y4 z>)+f*1}SxjrjwB&yV|+=sV6RtIRI=6n~gx;GNtYSDwstP_?J z%^Q+?m_rRx_2`9z3;7z9fc!N7&4Kld$c;}uv7xnhg$uG06PWIWEzgCMt*YCluk8S1o|35s&)T+}<@!bA%kBMVCGD@Xp#n&&mu zKx|u|%f8Bt4D-QX5il2LYkYe*tY>6|hl7J-DD%ZV6~pD%;BAnZxWL1Q3VfURcb3v3 zt)xVf#_WSJts$3(f+Rak*i3Cb12UFx*GQX|5fJu~9M#IKC_&_fEzSr}Th9lTqt#~U zQNnz?{SiUbX0`uchNcsq)lG@jk@hbY?u1>We~QI2{}DHvyiitFb}y;N+{C8w0h$O% z4aR^oQh**5K|w)H=X3U#>xtU4DPOhgMMrHWzdch`SGP2d=>L?N8JjNZ%pxH0$&u4H z(jE3iCP+H)?#kMv#UBpfp&uaYGSD`p50xvRN+@hlh$K?d(IEls8CVW(Ny*6;pw$@G zyD*12mj1NuaXE~Jpuh@csj&AlzKsB$iX2OV`SEJ^e-xb`!~tB44D3<8_c06Wr}M^v zdM#yTY(Rl4d`@A5Su$Aw1%n%};O=g2By@B!4epz(#pNxQ#ze)yav=eo@#y@#hgjyO zt)C6Mel~q9EG~|?*5UU%;5S(UDd8|+K^UtXD(;TR2Iioo=ic)71T>c?&OK+_6Rtqf zf-5i*5fORs*UW$>qYv6HN)RFjsWYDVe7eR*uN3>$&jEZcqiP${-?OuZ`g3TYodWyk z;d@1ScC8F^1F#gyPf88x`&|K6}@blbpd1_gl`+!M#B4Vab_lIg(m zH;m148sjDCI3C;M;lPpT?&%r-)93|ENH&Sgk6M`$N>;reA3=m{Mwujlt2X~b6K!$u z>Ez_3j=%pCKxh)cI`s9a&NX`R0rgP{jg5)|+QW9}v+!i2movI-X9VHe(*?4{!Jxd# z$^;^M2}Pin*@6G}qoyWbEs<@k6?yB-#ls`?nF!Dk8RU&%>C37JY(g3ow^?@+Z${o- z!x{$DNta>j#sSYvOkzMKt^hMY42WTUt_OhBgr=GWQUm!4n7j;dUU5`ZdbLuM)6+kI z3SXV8u~*g5Pyj4~i<^68XD9mGHxA7VF`(s0Z?cPOR}N$!2I%SOO*s4rx^utB#q}vi zm*1*D3aG3qYi-~x%H`;^0X6Q^@hvlxzRQx|&dzRhb~b8m&It6)+=>bkz_B=Zc)CiB z>jJaF>lWR5%3IN8 zkOW5zfo$G_GTeFvkUA&oVTY$dJdIu$<*jANQ+FzGy^g8kwrn|BT{81NH18@H+KaNs zJru6KCb_07LpMAzjKt&*(6+aOnP;M!0%(seaB7{f5W~VI;&h>+?kZ~9IHtb1Vx9z- z6Ildii#JzozpL87byv>?1CNhj2Vw~cvH?=&CDlC_hZq6Z=(Hjb=jJyV0z-5MTIu8L zMMZ5zdTlaiiS)$^-acr~O=$i%{MowH%P; zI%&rVHXt$WpZ2ql zIL?S(onkm8`ROLc;-W*bZD!pPjN#te>a2mKFYq~HoLemHnjUb^8jOpGh_nSEMJs#+ z<5PQUX(rwUVO&ZQ63S*t4{CnmYcV$-ns`C$HoTjt=wgcvCz?j<4F)X$&ux7G>BPXKb7xqf!gG^ zblltpj;&TWM+1Bg#r%XkEwI4L`0WPoO?vaccC}MaXpNwPiIN;qK4VrZN5ZE+J%Y7* zn|MV;OG?sa4*V_ziimmWKa|0_x#33QBGc84YhSQQAG+Rw4y&|zq>hMLY{B#Ix6rw(S?m_ogKbUyFEJw{w?z%MSv z}Sv^c_E6;U-+I%PQe58oc?wZuXnh7DjQNo{8}nr> z?V#7omu+99GzCLDQ)dMY$6R2gF*?l& zWq*%`D_L^dhYLa3E8lWXApK9-Ce}x{)A&c5eJe|K4qd9?35lIIE;NLKp3I!MVm@T? z15oS7eiqE9*|dx!c~6-vV+bH#2NlIbIv`YNy+Icek^Z+Z+jo;j$@{o&PTalTerHmj zi6>_JD>s*Ai(k`AX0l_L2)EOc)9rPSG9nWAnEZcJpgmJ>RI7~;)E2Xkm&YF=Bx4c% zw_);#;cg`{YgqEmv)DOSb z9K2VhSD2Rc!i0qtv)-H3#m%mto9KCY(Io?WHKV9!$))3xktLdVTQ^=O!26 ztn)l{YOGzQF*Vgp%=J2)E{A`RqR9|EEj8Bc$zltWHy>ju*z6!PO?mQBzCGp(K7oU+ z4L7&bxsA)gX28vgGLw0V&TReISL}sqSzhZNQDVBwzEP8Xdy%4Nct)iZATj{ngYxs| z52}rzN$QV;Xb2q~9hnnUnUd94*4M*;rK-T2id?x&DKeEoE;NxfQsJqnz((&bj|V$* zjQ;qV`CG4zh?Jx?w6rh){aznLQ)d;v~$MHn&Dl!Nl|wM;nI%q-T#!bny(nxB!wsglQNa}RR{2vQ3iNkVWC34 zt{iWwC{Fv#3?=CGk${nyyn4l)I>1bhXW{HjoS+)^^QXi&eJ&v(q3o|;(f@0UQ#3VY z_-}Sk36H3aP~^(;5rc9pR}Xi2(>u^ry?uRY{*gWX+`ATZ?!d)s;!P>>hof&}(Ki-3 zlrEZMP&`&+|AK&4WN`LabWi>W_@=WB?(BdOguQ!*es=JO_Mvi2+tErVzyGC6v)Q`n z(w5HizqBPKM9jc`>F@9VR#v9$;_|pa6aEg6!;Yb$r{!-x3pjQM%~p_Ju0+0{t&qc} zq`XZo9J4tBwh1Z{jJ-U>*ro<4E3K$g-reo>eF!Q`Ej6l%E;DN_JN)`3yQO8rI$2$* zH;%Co3!g#`ps=x10NaVX*&eX8YIUpH{AJ z5eGkif^sYkP+q~<1XQx`-@pHlr%^z8dAZv@XjGaa;y9x*u)H)sJNAu*8W89 z=HZKS(|o|uQDhY5zPx$!2>3d<(sxjAX~EsM694w9M*8OFJ_Cn~Q&6xYuXljzcS+WBiRKzBtN8XNVHcemT^p*SODlQBSmuoUU5gTOK$(A?S$ z5>iGa(I~$lB{_L~U7aW)wLsS%!>2E)AQ3__L|_+G1#)k$E#+L+IU@k;!o$O30S*us z6uRG}F1WfimiyY#@hM95*wb8IdWqfbr~8b3Ra)QM(*&~vyVYXuum4AeTaq-=+uC^? z^b-yo7)`Lo=Z8z>qOOR($s)b}KY#vg)p<+b5zxm3&BF|e^ic%%v#@>2-4vYq!Gi~r zpnU%=hZ4saurVT4-afu_O!om11n|Q+MMYmAcLwAC?#?8Fz;(>&!vDs2Jmj*@33wwK zU%q^)1{ro|kstP=&g@t*CH~8)Y~7;1iHQl08bL-R`?l=OedA0F@104`bp&D+%3GFr zlo8c!+11r$eto`g%~#ThWAA!j~3`#P=}K z#k~DT{Y{>q2PzWo;~Q5Bn>4+vK=j=r91jBmu~wEG*vDrR8;$}(V!KC1h!mq*duRZ_p=IVTT ze*aWX*trl*IsDnbrM-D#Om`a5@iFfe%T`w`&g872inWLqi@mMc_Zc$b=|8NH>Z0s| zZvI7G(x<;TrW@~s?Wg18;^G!Z=EEAgk*-{UncC<%v2t%kkCQHCt{{d62G|gnu}#h1 zCEIV848^=j%cEt)q|1nV39*6&Wlsn$cGhNfbWSI&aDpnSb20p6SwFGd#PW?92H{gC zaoIe-fiAuCK4pZfY_)+;r?%Sao*zLV;vIflbZ`*1?MOk%T@| zov%r@Nm%d8RPGza{!D(zz!C{ z=vew+KmXF~6X>1xw(zj@O(uK%E#yy^>vJ^4O z)3b`bEvmkfe7=FZP?o7%isp3~H{kPY`Agx>WaY>$IF2A|f|jgODBdmiwN^XeVR zC}cdgJMX;|ucI@1N*LHL_8~tp^!Vta)lJ6Few}eB3_-oxAT2`0=?s;fbAF)nVw2fo zQNEtQ@MAykzw$ro8XAP-m^K}BYtEXeTOV8~)MlKWom~bh4x6-UXW@;a*A;Fewx0r* zdv8*AR`!cC12H51?TmuJMzZOpp^#YB*;U(rwwUElK3q0@ymYT%-!s8*RlMNRD!l7t z`Ug_JXwU{|*B63)dSni}Y(OFQ1t77;g@rD}mrCs4JWJL(nY^q!H>4sXlLuj)$l%&H z>fDKKRo>JIpfYVo-2en?Ngg}jdU*c#{Q8XNf6A}1p^eSKu_*=LF#@PzdJ z`W5YYuwXmsc6BKTkV;$B-N}hpTvBqv?Cyl}_PgLiz*zonPeg*)!s;vu!~Z6W^KO4+ z7z{#*qJ~?ltmE#;KjVUi#isp56NIMG(b0xuZ7A$KG$cy{(Q3RROAf$r57Qj#O7CM! z)c6uWYy*#@<3pVrNf-+E{zqu7xk>&R4Y&!wR05*cASo%Ss}`&QeePNVV$x1{D2+c9 zc>DW{&DU4@pV7FIqfr@(W##M^vA=d`Tu|c^V+tK`LNG({2pH`HseJ4;Mz;>?PcuNy zf*Lgt7ZXdHB*S}pbR5JrlIq|O#sXejTdM%0ARi2@ZHkBYS2{0AyLoyR1P4PBwHJo~ z?0pHMjsmF_s-1v#1jZLc<_0hW+%FDZ(Z~coLCZ$50g!mif0Doi5WThVna!@|^XlrV zDqCU#P~-cvm7VKkZ|ju6s2kL*B?H6@SJ&57DO8n$N5{?~fhk%8|9gU6+TT+1YiKB+ zSo$&;7%d>Vjs=|k4tHu=HzdK405aGsw^g<3WO65jEgBLF* zz>FJ*gv4iHrGT9U4t6#eEYmI0R~~DlprAo2hL&ZPPHe}gq(org5HWFb;$9psMds!{ z?C9tqp`eHe!N38bUB$#Mr@au(LQ4QG$fi*a-f)&ooc&Ch92jq4WyMTn*X~*GPaFfa zd25meH@El?!wX^+6ub|J8)}Ts&W;NYFD(NGa=d`+^Kki`;K)cERHz6-4#2o(=jK41 zEnB27pF0L#zyAD510Dwy!3K5f^yep5jS(SWrGdBqEG~~$?h*ed%Lbe^*29O5xOdIj zL=c&9a^kj7?~3vA<;%YQelQ0|3I<3}ei6v=0hOJco|Z2)P+&`JpPQpOKR Date: Fri, 24 Jul 2020 06:09:42 -0600 Subject: [PATCH 002/530] more readme hacking --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 713e281..6945ecf 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,9 @@ ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. ## Dependency Resolution +
![Dependency resolution example](doc/img/dependency-resolution.png) +
ifupdown-ng uses a dependency resolver to determine interface bring-up order in a deterministic way. To use this feature, you must declare relationships From ef6600a91e1ef78dc001d4f99bf7a3e12d9ba372 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 06:11:20 -0600 Subject: [PATCH 003/530] more tweaking --- README.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/README.md b/README.md index 6945ecf..713e281 100644 --- a/README.md +++ b/README.md @@ -5,9 +5,7 @@ ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. ## Dependency Resolution -
![Dependency resolution example](doc/img/dependency-resolution.png) -
ifupdown-ng uses a dependency resolver to determine interface bring-up order in a deterministic way. To use this feature, you must declare relationships From 7eb81a1b3a1c51ed4e5ab42e917cd126f5314477 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 06:13:01 -0600 Subject: [PATCH 004/530] more tweaking --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 713e281..0e077e0 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. ## Dependency Resolution -![Dependency resolution example](doc/img/dependency-resolution.png) +Dependency resolution example ifupdown-ng uses a dependency resolver to determine interface bring-up order in a deterministic way. To use this feature, you must declare relationships @@ -16,6 +16,8 @@ as the `IF_REQUIRES` environment variable. For compatibility with some legacy ifupdown executors, we also provide the `requires` keyword under other environment variables in some cases. +
+ ## Caveats * ifupdown2 python plugins are not supported at this time. An executor could be From ef86d9400bd7b630127fa1fce0aef2bdb2428b1a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 06:13:43 -0600 Subject: [PATCH 005/530] more tweaking --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 0e077e0..4fef509 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. ## Dependency Resolution -Dependency resolution example +Dependency resolution example ifupdown-ng uses a dependency resolver to determine interface bring-up order in a deterministic way. To use this feature, you must declare relationships From 464c078bbe96d05f99a66c263e5bdbc46a63575a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 06:15:10 -0600 Subject: [PATCH 006/530] github won't let us float elements, gross --- README.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/README.md b/README.md index 4fef509..713e281 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. ## Dependency Resolution -Dependency resolution example +![Dependency resolution example](doc/img/dependency-resolution.png) ifupdown-ng uses a dependency resolver to determine interface bring-up order in a deterministic way. To use this feature, you must declare relationships @@ -16,8 +16,6 @@ as the `IF_REQUIRES` environment variable. For compatibility with some legacy ifupdown executors, we also provide the `requires` keyword under other environment variables in some cases. -
- ## Caveats * ifupdown2 python plugins are not supported at this time. An executor could be From 713d5071d54e11121ea0f1e53581c7ccb904bdcc Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 07:13:04 -0600 Subject: [PATCH 007/530] state: don't consider missing state file to be a fatal error --- libifupdown/state.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libifupdown/state.c b/libifupdown/state.c index 89ad105..74d0e0c 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -45,8 +45,9 @@ lif_state_read_path(struct lif_dict *state, const char *path) FILE *fd = fopen(path, "r"); bool ret; + /* if file cannot be opened, assume an empty state */ if (fd == NULL) - return false; + return true; ret = lif_state_read(state, fd); fclose(fd); From 6d1c67ed380d0afb6f3e126307a548a878bff15f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 07:17:18 -0600 Subject: [PATCH 008/530] README: note how to build apps, docs and run the tests --- README.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 713e281..7bc19dc 100644 --- a/README.md +++ b/README.md @@ -24,5 +24,11 @@ For compatibility with some legacy ifupdown executors, we also provide the * ifupdown-ng retains compatibility with /etc/network/if-X.d scripts, but will prefer using executors in /usr/libexec/ifupdown-ng where appropriate. -This package is planned to replace BusyBox ifupdown in Alpine at some point in -the future. +## Building + +Simply do `make` and `make install` to build and install. + +To run the tests, do `make check`. + +To build the documentation, do `make docs` and `make install_docs`. Building +the documentation requires scdoc (`apk add scdoc`). From bc48534814cce147fabd06af8309daff4101b820 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 07:48:14 -0600 Subject: [PATCH 009/530] add ifquery manpage --- Makefile | 13 ++++++++++ doc/ifquery.scd | 66 +++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 79 insertions(+) create mode 100644 doc/ifquery.scd diff --git a/Makefile b/Makefile index 36cd719..4c21443 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,5 @@ +SCDOC := scdoc + PACKAGE_NAME := ifupdown-ng PACKAGE_VERSION := 0.2 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new @@ -54,6 +56,7 @@ libifupdown.a: ${LIBIFUPDOWN_OBJ} clean: rm -f ${LIBIFUPDOWN_OBJ} ${CMD_OBJ} rm -f ${CMDS} ${MULTICALL} + rm -f ${MANPAGES} check: libifupdown.a ${CMDS} kyua test @@ -63,3 +66,13 @@ install: all for i in ${CMDS}; do \ ln -s /sbin/${MULTICALL} ${DESTDIR}/sbin/$$i; \ done + +.scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8: + ${SCDOC} < $< > $@ + +MANPAGES = \ + doc/ifquery.8 + +docs: ${MANPAGES} + +.SUFFIXES: .scd .1 .2 .3 .4 .5 .6 .7 .8 diff --git a/doc/ifquery.scd b/doc/ifquery.scd new file mode 100644 index 0000000..12d47a5 --- /dev/null +++ b/doc/ifquery.scd @@ -0,0 +1,66 @@ +ifquery(8) + +# NAME + +ifquery - query interface configuration and state + +# SYNOPSIS + +*ifquery* [<_options_>...] <_interfaces_...> + +*ifquery* -L|--list + +*ifquery* -s|--state + +# DESCRIPTION + +*ifquery* is used to extract information from the interface configuration +file. It can also be used to convert from old versions of the interface +configuration file to the current format. + +# OPTIONS + +*-a, --auto* + Only match interfaces that are marked as _auto_. + +*-h, --help* + Display supported options to ifquery. + +*-i, --interfaces* _FILE_ + Use _FILE_ as the config database. + +*-s, --state* + Query the state database instead of the config database. + +*-D, --dot* + Generate a dependency graph that can be used with GraphViz + *dot*(1). Used with *--list*. + +*-I, --include* _PATTERN_ + Include _PATTERN_ when matching against the config or state + database. + +*-L, --list* + List interfaces which exist in the configuration database. + +*-P, --pretty-print* + When listing interfaces, print their configuration in a format + that is compatible with *interfaces*(5) files. + +*-S, --state-file* _FILE_ + Use _FILE_ as the state database. + +*-V, --version* + Print the ifupdown-ng version and exit. + +*-X, --exclude* _PATTERN_ + Exclude _PATTERN_ when matching against the config or state + database. + +# SEE ALSO + +*ifup*(8), *ifdown*(8), *interfaces*(5) + +# AUTHORS + +Ariadne Conill From 915f04912c2cf99f7af16b0be80806c2e35be534 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 07:48:50 -0600 Subject: [PATCH 010/530] update gitignore --- .gitignore | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitignore b/.gitignore index f22f97e..60655e7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,14 @@ *.o *.a +*.1 +*.2 +*.3 +*.4 +*.5 +*.6 +*.7 +*.8 +ifupdown ifquery ifup ifdown From cebe24e1ecd242ea5e8e1987f4453adf77798ea1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 07:55:29 -0600 Subject: [PATCH 011/530] docs: properly format see also section --- doc/ifquery.scd | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/doc/ifquery.scd b/doc/ifquery.scd index 12d47a5..f00ef82 100644 --- a/doc/ifquery.scd +++ b/doc/ifquery.scd @@ -59,7 +59,9 @@ configuration file to the current format. # SEE ALSO -*ifup*(8), *ifdown*(8), *interfaces*(5) +*ifup*(8)++ +*ifdown*(8)++ +*interfaces*(5) # AUTHORS From 475aeb2992734ae1fdd7d29cbd67aba025c5a38e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 08:28:29 -0600 Subject: [PATCH 012/530] add docs for ifdown/ifup/interfaces too --- Makefile | 5 +- doc/ifdown.scd | 56 ++++++++++++++++ doc/ifup.scd | 56 ++++++++++++++++ doc/interfaces.scd | 160 +++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 doc/ifdown.scd create mode 100644 doc/ifup.scd create mode 100644 doc/interfaces.scd diff --git a/Makefile b/Makefile index 4c21443..fe0f01f 100644 --- a/Makefile +++ b/Makefile @@ -71,7 +71,10 @@ install: all ${SCDOC} < $< > $@ MANPAGES = \ - doc/ifquery.8 + doc/ifquery.8 \ + doc/ifup.8 \ + doc/ifdown.8 \ + doc/interfaces.5 docs: ${MANPAGES} diff --git a/doc/ifdown.scd b/doc/ifdown.scd new file mode 100644 index 0000000..fd54fff --- /dev/null +++ b/doc/ifdown.scd @@ -0,0 +1,56 @@ +ifdown(8) + +# NAME + +ifdown - take interfaces down + +# SYNOPSIS + +ifdown [<_options_>...] <_interfaces_> + +# DESCRIPTION + +*ifdown* is used to deconfigure interfaces according to how they are +configured in the configuration database. + +# OPTIONS + +*-a, --auto* + Only match interfaces that are marked as _auto_. + +*-h, --help* + Display supported options to ifquery. + +*-i, --interfaces* _FILE_ + Use _FILE_ as the config database. + +*-n, --no-act* + Show what commands would be run instead of actually running + them. Useful for testing configuration changes. + +*-v, --verbose* + Show what commands are being run as they are executed. + +*-I, --include* _PATTERN_ + Include _PATTERN_ when matching against the config or state + database. + +*-S, --state-file* _FILE_ + Use _FILE_ as the state database. + +*-V, --version* + Print the ifupdown-ng version and exit. + +*-X, --exclude* _PATTERN_ + Exclude _PATTERN_ when matching against the config or state + database. + +# SEE ALSO + +*ifup*(8)++ +*ifquery*(8)++ +*interfaces*(5) + +# AUTHORS + +Ariadne Conill diff --git a/doc/ifup.scd b/doc/ifup.scd new file mode 100644 index 0000000..4d50908 --- /dev/null +++ b/doc/ifup.scd @@ -0,0 +1,56 @@ +ifup(8) + +# NAME + +ifup - bring interfaces up + +# SYNOPSIS + +ifup [<_options_>...] <_interfaces_> + +# DESCRIPTION + +*ifup* is used to configure interfaces according to how they are +configured in the configuration database. + +# OPTIONS + +*-a, --auto* + Only match interfaces that are marked as _auto_. + +*-h, --help* + Display supported options to ifquery. + +*-i, --interfaces* _FILE_ + Use _FILE_ as the config database. + +*-n, --no-act* + Show what commands would be run instead of actually running + them. Useful for testing configuration changes. + +*-v, --verbose* + Show what commands are being run as they are executed. + +*-I, --include* _PATTERN_ + Include _PATTERN_ when matching against the config or state + database. + +*-S, --state-file* _FILE_ + Use _FILE_ as the state database. + +*-V, --version* + Print the ifupdown-ng version and exit. + +*-X, --exclude* _PATTERN_ + Exclude _PATTERN_ when matching against the config or state + database. + +# SEE ALSO + +*ifdown*(8)++ +*ifquery*(8)++ +*interfaces*(5) + +# AUTHORS + +Ariadne Conill diff --git a/doc/interfaces.scd b/doc/interfaces.scd new file mode 100644 index 0000000..3719e46 --- /dev/null +++ b/doc/interfaces.scd @@ -0,0 +1,160 @@ +interfaces(5) + +# NAME + +*/etc/network/interfaces* - interface configuration database + +# DESCRIPTION + +The */etc/network/interfaces* file is used to specify how network +interfaces are configured. The file is processed by *ifquery*(8), +*ifup*(8) and *ifdown*(8) to introspect and change system state. + +# FILE SYNTAX + +The interface configuration database is composed of a series of +stanzas. Hash symbols designate comments, which are ignored by +the system. + +A stanza is a collection of triples, where a triple is a key and +value combination that is related to an *object*. Triples which +are not associated with an *object* are considered to be part +of the root of the configuration tree. + +The following is a simple example of a stanza: + +``` +auto eth0 +iface eth0 + address 203.0.113.2/24 + gateway 203.0.113.1 +``` + +This stanza defines an interface named *eth0* which is configured +with an address of *203.0.113.2* and gateway of *203.0.113.1*. + +# SUPPORTED KEYWORDS FOR UNASSOCIATED TRIPLES + +*auto* _object_ + Designates that _object_ should be automatically configured + by the system when appropriate. + +*iface* _object_ + Begins a new declaration for _object_. Any child keyword + associated with the declaration will be stored inside + _object_. + +# SUPPORTED KEYWORDS FOR OBJECT TRIPLES + +Any keyword may be used inside an interface declaration block, but +the system will only respond to certain keywords by default: + +*address* _address_ + Associates an IPv4 or IPv6 address in CIDR notation with + the parent interface. + +*gateway* _address_ + Associates an IPv4 or IPv6 address with the parent interface + for use as a default route (gateway). + +*netmask* _netmask_ + Associates a fallback netmask with the parent interface for + addresses which do not have a CIDR length set. This option + is for backwards compatibility and should not be used in new + deployments. + +*requires* _interfaces_... + Designates one or more required interfaces that must be + brought up before configuration of the parent interface. + Interfaces associated with the parent are taken down at + the same time as the parent. + +*use* _option_ + Designates that an option should be used. See _OPTIONS_ + section for more information on options. + +*pre-down* _command_ + Runs _command_ before taking the interface down. + +*down* _command_ + Runs _command_ when the interface is taken down. + +*post-down* _command_ + Runs _command_ after taking the interface down. + +*pre-up* _command_ + Runs _command_ before bringing the interface up. + +*up* _command_ + Runs _command_ when the interface is brought up. + +*post-up* _command_ + Runs _command_ after bringing the interface up. + +Additional packages such as *bonding*, *bridge*, *tunnel* and +*vrf* add additional keywords to this vocabulary. + +# OPTIONS + +The *use* keyword designates that an _option_ should be used. +This system is extendable by additional packages, but the +most common options are: + +*bond* + The interface is a bonded interface. Configuration + of bonded interfaces requires the *bonding* package + to be installed. + +*bridge* + The interface is an ethernet bridge. Configuration + of ethernet bridges requires the *bridge* package + to be installed. + +*dhcp* + Use a DHCP client to learn the IPv4 address of an + interface. + +*loopback* + Designates the interface as a loopback device. + +*tunnel* + The interface is a tunnel. Configuration of tunnels + requires the *tunnel* package to be installed. + +*vrf* + The interface is a VRF. Configuration of VRFs requires + the *vrf* package to be installed. + +# EXAMPLES + +Configure a bridge interface *br0* with *bond0* attached to it, +which is a failover between *eth0* and *eth1*. This requires +the *bonding* and *bridge* packages to be installed: + +``` +auto br0 +iface br0 + use bridge + requires bond0 + address 203.0.113.2/24 + gateway 203.0.113.1 + +iface bond0 + use bond + requires eth0 eth1 + bond-mode 802.3ad + bond-xmit-hash-policy layer2+3 +``` + +Configure a network interface to use DHCP to learn its IPv4 +address: + +``` +auto eth0 +iface eth0 + use dhcp +``` + +# AUTHORS + +Ariadne Conill From 532aaa30de6c6dbe61b164b66fb44e444fcf5d0f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 08:32:58 -0600 Subject: [PATCH 013/530] build: add install_docs target --- Makefile | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fe0f01f..89ce1d7 100644 --- a/Makefile +++ b/Makefile @@ -70,12 +70,26 @@ install: all .scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8: ${SCDOC} < $< > $@ -MANPAGES = \ +MANPAGES_8 = \ doc/ifquery.8 \ doc/ifup.8 \ - doc/ifdown.8 \ + doc/ifdown.8 + +MANPAGES_5 = \ doc/interfaces.5 +MANPAGES = ${MANPAGES_5} ${MANPAGES_8} + docs: ${MANPAGES} +install_docs: docs + for i in ${MANPAGES_5}; do \ + target=$$(basename $$i); \ + install -D -m644 $$i ${DESTDIR}/usr/share/man/man5/$$target; \ + done + for i in ${MANPAGES_8}; do \ + target=$$(basename $$i); \ + install -D -m644 $$i ${DESTDIR}/usr/share/man/man8/$$target; \ + done + .SUFFIXES: .scd .1 .2 .3 .4 .5 .6 .7 .8 From 03e00cbb021c3a97057192f4988c6c8cca485384 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 24 Jul 2020 08:33:22 -0600 Subject: [PATCH 014/530] ifupdown-ng 0.2.1. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 89ce1d7..db9bb05 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ SCDOC := scdoc PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.2 +PACKAGE_VERSION := 0.2.1 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From 60633e4acb8e02f14a8435450ee0c4a34723dbb1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 00:58:32 -0600 Subject: [PATCH 015/530] lifecycle: add backwards compat for netmask triples --- libifupdown/lifecycle.c | 53 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 48 insertions(+), 5 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 1605c8e..174efb2 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -45,13 +45,56 @@ handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[ return true; } +static inline size_t +count_set_bits(const char *netmask) +{ + /* netmask set to CIDR length */ + if (strchr(netmask, '.') == NULL) + return strtol(netmask, NULL, 10); + + size_t r = 0; + struct in_addr in; + + if (inet_pton(AF_INET, netmask, &in) == 0) + return r; + + /* take the IP, put it in host endian order, and + * flip it so that all the set bits are set to the right. + * then we can simply count down from 32 and right-shift + * until the bit field is all zero. + */ + unsigned int bits = htonl(in.s_addr); + for (bits = ~bits, r = 32; bits; bits >>= 1, r--) + ; + + return r; +} + static bool -handle_address(const struct lif_execute_opts *opts, struct lif_address *addr, const char *cmd, const char *lifname) +handle_address(const struct lif_execute_opts *opts, struct lif_address *addr, const char *cmd, const char *lifname, struct lif_interface *iface) { char addrbuf[4096]; - if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) - return false; + if (addr->netmask) + { + if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) + return false; + } + else + { + /* if fallback netmask is not set, default to 255.255.255.0 */ + addr->netmask = 24; + + struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "netmask"); + if (entry != NULL) + addr->netmask = count_set_bits(entry->data); + + if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, false)) + return false; + + /* reset cidrlen */ + addr->netmask = 0; + } return lif_execute_fmt(opts, NULL, "/sbin/ip -%d addr %s %s dev %s", addr->domain == AF_INET ? 4 : 6, cmd, addrbuf, lifname); @@ -95,7 +138,7 @@ handle_up(const struct lif_execute_opts *opts, struct lif_interface *iface, cons { struct lif_address *addr = entry->data; - if (!handle_address(opts, addr, "add", lifname)) + if (!handle_address(opts, addr, "add", lifname, iface)) return false; } else if (!strcmp(entry->key, "gateway")) @@ -131,7 +174,7 @@ handle_down(const struct lif_execute_opts *opts, struct lif_interface *iface, co { struct lif_address *addr = entry->data; - if (!handle_address(opts, addr, "del", lifname)) + if (!handle_address(opts, addr, "del", lifname, iface)) return false; } else if (!strcmp(entry->key, "gateway")) From d582e405b6748a7d671c67f4f0dcfe2bd85aa5f8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 01:02:05 -0600 Subject: [PATCH 016/530] lifecycle: simplify netmask fallback path --- libifupdown/lifecycle.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 174efb2..f773a95 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -74,13 +74,9 @@ static bool handle_address(const struct lif_execute_opts *opts, struct lif_address *addr, const char *cmd, const char *lifname, struct lif_interface *iface) { char addrbuf[4096]; + size_t orig_netmask = addr->netmask; - if (addr->netmask) - { - if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) - return false; - } - else + if (!addr->netmask) { /* if fallback netmask is not set, default to 255.255.255.0 */ addr->netmask = 24; @@ -88,14 +84,14 @@ handle_address(const struct lif_execute_opts *opts, struct lif_address *addr, co struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "netmask"); if (entry != NULL) addr->netmask = count_set_bits(entry->data); - - if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, false)) - return false; - - /* reset cidrlen */ - addr->netmask = 0; } + if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) + return false; + + /* reset the netmask */ + addr->netmask = orig_netmask; + return lif_execute_fmt(opts, NULL, "/sbin/ip -%d addr %s %s dev %s", addr->domain == AF_INET ? 4 : 6, cmd, addrbuf, lifname); } From 492e9e70389da7493be21735968685f31127bb21 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 01:06:21 -0600 Subject: [PATCH 017/530] tests: add tests for fallback netmask handling --- .../static-eth0-v4-netmask.interfaces | 5 +++++ .../static-eth0-v6-netmask.interfaces | 5 +++++ tests/ifdown_test | 20 +++++++++++++++++++ tests/ifup_test | 20 +++++++++++++++++++ 4 files changed, 50 insertions(+) create mode 100644 tests/fixtures/static-eth0-v4-netmask.interfaces create mode 100644 tests/fixtures/static-eth0-v6-netmask.interfaces diff --git a/tests/fixtures/static-eth0-v4-netmask.interfaces b/tests/fixtures/static-eth0-v4-netmask.interfaces new file mode 100644 index 0000000..e9207e8 --- /dev/null +++ b/tests/fixtures/static-eth0-v4-netmask.interfaces @@ -0,0 +1,5 @@ +auto eth0 +iface eth0 + address 203.0.113.2 + netmask 255.255.255.248 + gateway 203.0.113.1 diff --git a/tests/fixtures/static-eth0-v6-netmask.interfaces b/tests/fixtures/static-eth0-v6-netmask.interfaces new file mode 100644 index 0000000..3707e80 --- /dev/null +++ b/tests/fixtures/static-eth0-v6-netmask.interfaces @@ -0,0 +1,5 @@ +auto eth0 +iface eth0 + address 2001:db8:1000:2::2 + netmask 112 + gateway 2001:db8:1000:2::1 diff --git a/tests/ifdown_test b/tests/ifdown_test index 8813359..0104361 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -7,7 +7,9 @@ tests_init \ lo_always_auto \ dual_stack \ static_ipv4 \ + static_ipv4_netmask \ static_ipv6 \ + static_ipv6_netmask \ inet_dhcp \ use_dhcp \ alias_eth0_home \ @@ -43,6 +45,15 @@ static_ipv4_body() { ifdown -S/dev/null -i $FIXTURES/static-eth0-v4.interfaces -n -a } +static_ipv4_netmask_body() { + atf_check -s exit:0 -e ignore \ + -o match:'ip link set down dev lo' \ + -o match:'ip link set down dev eth0' \ + -o match:'del 203.0.113.2/29 dev eth0' \ + -o match:'default via 203.0.113.1' \ + ifdown -S/dev/null -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a +} + static_ipv6_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ @@ -52,6 +63,15 @@ static_ipv6_body() { ifdown -S/dev/null -i $FIXTURES/static-eth0-v6.interfaces -n -a } +static_ipv6_netmask_body() { + atf_check -s exit:0 -e ignore \ + -o match:'ip link set down dev lo' \ + -o match:'ip link set down dev eth0' \ + -o match:'del 2001:db8:1000:2::2/112 dev eth0' \ + -o match:'default via 2001:db8:1000:2::1' \ + ifdown -S/dev/null -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a +} + inet_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ diff --git a/tests/ifup_test b/tests/ifup_test index 2091d0f..9b35d21 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -7,7 +7,9 @@ tests_init \ lo_always_auto \ dual_stack \ static_ipv4 \ + static_ipv4_netmask \ static_ipv6 \ + static_ipv6_netmask \ inet_dhcp \ use_dhcp \ alias_eth0_home \ @@ -43,6 +45,15 @@ static_ipv4_body() { ifup -S/dev/null -i $FIXTURES/static-eth0-v4.interfaces -n -a } +static_ipv4_netmask_body() { + atf_check -s exit:0 -e ignore \ + -o match:'ip link set up dev lo' \ + -o match:'ip link set up dev eth0' \ + -o match:'add 203.0.113.2/29 dev eth0' \ + -o match:'default via 203.0.113.1' \ + ifup -S/dev/null -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a +} + static_ipv6_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ @@ -52,6 +63,15 @@ static_ipv6_body() { ifup -S/dev/null -i $FIXTURES/static-eth0-v6.interfaces -n -a } +static_ipv6_netmask_body() { + atf_check -s exit:0 -e ignore \ + -o match:'ip link set up dev lo' \ + -o match:'ip link set up dev eth0' \ + -o match:'add 2001:db8:1000:2::2/112 dev eth0' \ + -o match:'default via 2001:db8:1000:2::1' \ + ifup -S/dev/null -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a +} + inet_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ From cbcd8e8326c735e31a620466b33ea8dd54f7f496 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 01:16:01 -0600 Subject: [PATCH 018/530] allow for building against libbsd for glibc systems --- Makefile | 7 ++++++- README.md | 9 ++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index db9bb05..e58ec5d 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,6 @@ SCDOC := scdoc +LIBBSD_CFLAGS = +LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng PACKAGE_VERSION := 0.2.1 @@ -7,7 +9,9 @@ PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new INTERFACES_FILE := /etc/network/interfaces STATE_FILE := /run/ifstate -CFLAGS = -ggdb3 -Os -Wall -Wextra +CFLAGS ?= -ggdb3 -Os +CFLAGS += -Wall -Wextra +CFLAGS += ${LIBBSD_CFLAGS} CPPFLAGS = -I. -DINTERFACES_FILE=\"${INTERFACES_FILE}\" -DSTATE_FILE=\"${STATE_FILE}\" -DPACKAGE_NAME=\"${PACKAGE_NAME}\" -DPACKAGE_VERSION=\"${PACKAGE_VERSION}\" -DPACKAGE_BUGREPORT=\"${PACKAGE_BUGREPORT}\" @@ -41,6 +45,7 @@ CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} CMDS = ifup ifdown ifquery LIBS = ${LIBIFUPDOWN_LIB} +LIBS += ${LIBBSD_LIBS} all: libifupdown.a ${MULTICALL} ${CMDS} diff --git a/README.md b/README.md index 7bc19dc..ed81193 100644 --- a/README.md +++ b/README.md @@ -26,7 +26,14 @@ For compatibility with some legacy ifupdown executors, we also provide the ## Building -Simply do `make` and `make install` to build and install. +On musl systems, simply do `make` and `make install` to build and install. + +On glibc systems, you must additionally define LIBBSD_CFLAGS and LIBBSD_LIBS: + + export LIBBSD_CFLAGS=$(pkg-config --cflags libbsd-overlay) + export LIBBSD_LIBS=$(pkg-config --libs libbsd-overlay) + make + make install To run the tests, do `make check`. From 1919f9b0d34f8c0152947eb8f1fa0d78890bb88e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 01:18:03 -0600 Subject: [PATCH 019/530] fix README formatting --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ed81193..1d5e51e 100644 --- a/README.md +++ b/README.md @@ -30,10 +30,10 @@ On musl systems, simply do `make` and `make install` to build and install. On glibc systems, you must additionally define LIBBSD_CFLAGS and LIBBSD_LIBS: - export LIBBSD_CFLAGS=$(pkg-config --cflags libbsd-overlay) - export LIBBSD_LIBS=$(pkg-config --libs libbsd-overlay) - make - make install + export LIBBSD_CFLAGS=$(pkg-config --cflags libbsd-overlay) + export LIBBSD_LIBS=$(pkg-config --libs libbsd-overlay) + make + make install To run the tests, do `make check`. From b35d985ea46f46977eac9787701cbcf3aa1a38cc Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 01:23:14 -0600 Subject: [PATCH 020/530] ifupdown-ng 0.2.2. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index e58ec5d..bd4ac20 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.2.1 +PACKAGE_VERSION := 0.2.2 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From eb8f1938dc12086361b91866db2fa9fc9a2bd15d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 01:58:20 -0600 Subject: [PATCH 021/530] libifupdown: add utility function to determine if a path is executable --- libifupdown/execute.c | 15 +++++++++++++++ libifupdown/execute.h | 1 + 2 files changed, 16 insertions(+) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index 04d29e6..b1242d5 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include @@ -58,3 +59,17 @@ lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const c return WIFEXITED(status) && WEXITSTATUS(status) == 0; } + +bool +lif_file_is_executable(const char *path) +{ + struct stat st; + + if (stat(path, &st)) + return false; + + if (!S_ISREG(st.st_mode)) + return false; + + return access(path, X_OK); +} diff --git a/libifupdown/execute.h b/libifupdown/execute.h index b1f2eb5..3fce6ff 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -25,5 +25,6 @@ struct lif_execute_opts { }; extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); +extern bool lif_file_is_executable(const char *path); #endif From 4a5a37a62022cc62ae8ddeb50a804adb45c45977 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:02:28 -0600 Subject: [PATCH 022/530] build: define EXECUTOR_PATH --- Makefile | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index bd4ac20..2215799 100644 --- a/Makefile +++ b/Makefile @@ -9,10 +9,18 @@ PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new INTERFACES_FILE := /etc/network/interfaces STATE_FILE := /run/ifstate +EXECUTOR_PATH := /usr/libexec/ifupdown-ng + CFLAGS ?= -ggdb3 -Os CFLAGS += -Wall -Wextra CFLAGS += ${LIBBSD_CFLAGS} -CPPFLAGS = -I. -DINTERFACES_FILE=\"${INTERFACES_FILE}\" -DSTATE_FILE=\"${STATE_FILE}\" -DPACKAGE_NAME=\"${PACKAGE_NAME}\" -DPACKAGE_VERSION=\"${PACKAGE_VERSION}\" -DPACKAGE_BUGREPORT=\"${PACKAGE_BUGREPORT}\" +CPPFLAGS = -I. +CPPFLAGS += -DINTERFACES_FILE=\"${INTERFACES_FILE}\" +CPPFLAGS += -DSTATE_FILE=\"${STATE_FILE}\" +CPPFLAGS += -DPACKAGE_NAME=\"${PACKAGE_NAME}\" +CPPFLAGS += -DPACKAGE_VERSION=\"${PACKAGE_VERSION}\" +CPPFLAGS += -DPACKAGE_BUGREPORT=\"${PACKAGE_BUGREPORT}\" +CPPFLAGS += -DEXECUTOR_PATH=\"${EXECUTOR_PATH}\" LIBIFUPDOWN_SRC = \ From 96112d5dc9b221b509b8f27cf7eff693cb9f05e0 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:16:51 -0600 Subject: [PATCH 023/530] libifupdown: execute: add lif_maybe_try_executor() --- cmd/ifupdown.c | 4 +++- libifupdown/execute.c | 16 ++++++++++++++++ libifupdown/execute.h | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 1ed6afe..4983525 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -28,7 +28,9 @@ struct match_options { }; static bool up; -static struct lif_execute_opts exec_opts = {}; +static struct lif_execute_opts exec_opts = { + .executor_path = EXECUTOR_PATH, +}; void ifupdown_usage(void) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index b1242d5..32607e3 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -73,3 +73,19 @@ lif_file_is_executable(const char *path) return access(path, X_OK); } + +bool +lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor) +{ + if (opts->verbose) + fprintf(stderr, "ifupdown: attempting to run %s executor\n", executor); + + char pathbuf[4096]; + + snprintf(pathbuf, sizeof pathbuf, "%s/%s", opts->executor_path, executor); + + if (!lif_file_is_executable(pathbuf)) + return true; + + return lif_execute_fmt(opts, envp, "%s", pathbuf); +} diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 3fce6ff..fc03dbc 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -22,9 +22,11 @@ struct lif_execute_opts { bool verbose; bool mock; + const char *executor_path; }; extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); extern bool lif_file_is_executable(const char *path); +extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor); #endif From 83d64b0a69554e74ce9a40452d2a433db0c62c60 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:18:13 -0600 Subject: [PATCH 024/530] libifupdown: lifecycle: IFACE env variable should be set to the logical ifname --- libifupdown/lifecycle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index f773a95..0c4ff78 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -209,7 +209,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac { char **envp = NULL; - lif_environment_push(&envp, "IFACE", iface->ifname); + lif_environment_push(&envp, "IFACE", lifname); lif_environment_push(&envp, "PHASE", phase); /* try to provide $METHOD for ifupdown1 scripts if we can */ From f8c14fc233cd029dc5badb4c5baf858ad814afcd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:18:53 -0600 Subject: [PATCH 025/530] libifupdown: lifecycle: if in verbose mode, export VERBOSE to executors --- libifupdown/lifecycle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 0c4ff78..3dca04a 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -224,6 +224,9 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac else lif_environment_push(&envp, "MODE", "stop"); + if (opts->verbose) + lif_environment_push(&envp, "VERBOSE", "1"); + struct lif_node *iter; bool did_address = false, did_gateway = false; From 95a72b5663d77e7d0831b2485ccd6e83405f40ca Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:19:15 -0600 Subject: [PATCH 026/530] libifupdown: lifecycle: implement native executor support --- libifupdown/lifecycle.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 3dca04a..4f77c2c 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -45,6 +45,26 @@ handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[ return true; } +static bool +handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface) +{ + struct lif_node *iter; + + LIF_DICT_FOREACH(iter, &iface->vars) + { + struct lif_dict_entry *entry = iter->data; + + if (strcmp(entry->key, "use")) + continue; + + const char *cmd = entry->data; + if (!lif_maybe_run_executor(opts, envp, cmd)) + return false; + } + + return true; +} + static inline size_t count_set_bits(const char *netmask) { @@ -302,6 +322,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac goto on_error; } + handle_executors_for_phase(opts, envp, iface); handle_commands_for_phase(opts, envp, iface, lifname, phase); /* we should do error handling here, but ifupdown1 doesn't */ From dca34ebba7ffa012eac6ea9bd4bff307cc56b50a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:22:27 -0600 Subject: [PATCH 027/530] ifupdown: allow for the executor path to be changed --- cmd/ifupdown.c | 7 ++++++- doc/ifdown.scd | 3 +++ doc/ifup.scd | 3 +++ 3 files changed, 12 insertions(+), 1 deletion(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 4983525..13642c4 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -47,6 +47,7 @@ ifupdown_usage(void) fprintf(stderr, " -X, --exclude PATTERN never match against interfaces matching PATTERN\n"); fprintf(stderr, " -n, --no-act do not actually run any commands\n"); fprintf(stderr, " -v, --verbose show what commands are being run\n"); + fprintf(stderr, " -E, --executor-path PATH use PATH for executor directory\n"); exit(1); } @@ -124,6 +125,7 @@ ifupdown_main(int argc, char *argv[]) {"state-file", required_argument, 0, 'S'}, {"no-act", no_argument, 0, 'n'}, {"verbose", no_argument, 0, 'v'}, + {"executor-path", required_argument, 0, 'E'}, {NULL, 0, 0, 0} }; struct match_options match_opts = {}; @@ -132,7 +134,7 @@ ifupdown_main(int argc, char *argv[]) for (;;) { - int c = getopt_long(argc, argv, "hVi:aI:X:S:nv", long_options, NULL); + int c = getopt_long(argc, argv, "hVi:aI:X:S:nvE:", long_options, NULL); if (c == -1) break; @@ -165,6 +167,9 @@ ifupdown_main(int argc, char *argv[]) case 'v': exec_opts.verbose = true; break; + case 'E': + exec_opts.executor_path = optarg; + break; } } diff --git a/doc/ifdown.scd b/doc/ifdown.scd index fd54fff..051140b 100644 --- a/doc/ifdown.scd +++ b/doc/ifdown.scd @@ -31,6 +31,9 @@ configured in the configuration database. *-v, --verbose* Show what commands are being run as they are executed. +*-E, --executor-path* _PATH_ + Look for executors in the given _PATH_. + *-I, --include* _PATTERN_ Include _PATTERN_ when matching against the config or state database. diff --git a/doc/ifup.scd b/doc/ifup.scd index 4d50908..5d9c8d9 100644 --- a/doc/ifup.scd +++ b/doc/ifup.scd @@ -31,6 +31,9 @@ configured in the configuration database. *-v, --verbose* Show what commands are being run as they are executed. +*-E, --executor-path* _PATH_ + Look for executors in the given _PATH_. + *-I, --include* _PATTERN_ Include _PATTERN_ when matching against the config or state database. From cf8ae46ca01f7ff0d48d043a4e7365cf6cce0c2f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:36:11 -0600 Subject: [PATCH 028/530] executors: add dhcp executor (replacing the built in) --- executors/dhcp | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100755 executors/dhcp diff --git a/executors/dhcp b/executors/dhcp new file mode 100755 index 0000000..a88927f --- /dev/null +++ b/executors/dhcp @@ -0,0 +1,40 @@ +#!/bin/sh + +set -e + +determine_implementation() { + [ -x /sbin/udhcpc ] && echo "udhcpc" && return + echo "???" +} + +start() { + case "$1" in + udhcpc) + /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE + ;; + *) + echo "implementation $1 not supported" + exit 1 + esac +} + +stop() { + case "$1" in + udhcpc) + kill $(cat /var/lib/udhcpc.$IFACE.pid) + ;; + *) + echo "implementation $1 not supported" + exit 1 + esac +} + +impl=$(determine_implementation) + +[ -z "$VERBOSE" ] || set -x + +case "$MODE" in +start) start $impl ;; +stop) stop $impl ;; +*) echo "unknown mode $MODE" ;; +esac From fa0a0d7f797f2570c9efaaa1bb7c8490af34e32a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:38:42 -0600 Subject: [PATCH 029/530] tests: add mock executor --- tests/executors/dhcp | 1 + tests/executors/mock-executor | 3 +++ 2 files changed, 4 insertions(+) create mode 120000 tests/executors/dhcp create mode 100755 tests/executors/mock-executor diff --git a/tests/executors/dhcp b/tests/executors/dhcp new file mode 120000 index 0000000..1322f47 --- /dev/null +++ b/tests/executors/dhcp @@ -0,0 +1 @@ +mock-executor \ No newline at end of file diff --git a/tests/executors/mock-executor b/tests/executors/mock-executor new file mode 100755 index 0000000..ba185da --- /dev/null +++ b/tests/executors/mock-executor @@ -0,0 +1,3 @@ +#!/bin/sh + +echo $0 ${MODE} From 559bf2d1a446459c14dc5addb9f6b04f20dae732 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:49:44 -0600 Subject: [PATCH 030/530] libifupdown: execute: fix behavior of lif_file_is_executable() --- libifupdown/execute.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index 32607e3..b3781dc 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -71,7 +71,7 @@ lif_file_is_executable(const char *path) if (!S_ISREG(st.st_mode)) return false; - return access(path, X_OK); + return !access(path, X_OK); } bool From cd8fbb64fb8373840b9da452cb022e9ece96d268 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:50:24 -0600 Subject: [PATCH 031/530] tests: use mock executors --- tests/ifdown_test | 20 ++++++++++---------- tests/ifup_test | 20 ++++++++++---------- tests/test_env.sh | 1 + 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/tests/ifdown_test b/tests/ifdown_test index 0104361..c7283d5 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -33,7 +33,7 @@ dual_stack_body() { -o match:'del 2001:db8:1000:2::2/64 dev eth0' \ -o match:'default via 203.0.113.1' \ -o match:'default via 2001:db8:1000:2::1' \ - ifdown -S/dev/null -i $FIXTURES/static-eth0.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } static_ipv4_body() { @@ -42,7 +42,7 @@ static_ipv4_body() { -o match:'ip link set down dev eth0' \ -o match:'del 203.0.113.2/24 dev eth0' \ -o match:'default via 203.0.113.1' \ - ifdown -S/dev/null -i $FIXTURES/static-eth0-v4.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } static_ipv4_netmask_body() { @@ -51,7 +51,7 @@ static_ipv4_netmask_body() { -o match:'ip link set down dev eth0' \ -o match:'del 203.0.113.2/29 dev eth0' \ -o match:'default via 203.0.113.1' \ - ifdown -S/dev/null -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } static_ipv6_body() { @@ -60,7 +60,7 @@ static_ipv6_body() { -o match:'ip link set down dev eth0' \ -o match:'del 2001:db8:1000:2::2/64 dev eth0' \ -o match:'default via 2001:db8:1000:2::1' \ - ifdown -S/dev/null -i $FIXTURES/static-eth0-v6.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } static_ipv6_netmask_body() { @@ -69,7 +69,7 @@ static_ipv6_netmask_body() { -o match:'ip link set down dev eth0' \ -o match:'del 2001:db8:1000:2::2/112 dev eth0' \ -o match:'default via 2001:db8:1000:2::1' \ - ifdown -S/dev/null -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } inet_dhcp_body() { @@ -77,7 +77,7 @@ inet_dhcp_body() { -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ -o match:'dhc' \ - ifdown -S/dev/null -i $FIXTURES/dhcp-eth0.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } use_dhcp_body() { @@ -85,7 +85,7 @@ use_dhcp_body() { -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ -o match:'dhc' \ - ifdown -S/dev/null -i $FIXTURES/use-dhcp-eth0.interfaces -n -a + ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { @@ -93,7 +93,7 @@ alias_eth0_home_body() { -o match:'ip link set down dev wlan0' \ -o match:'dhc' \ ifdown -S $FIXTURES/alias-home.ifstate \ - -i $FIXTURES/alias-home-work.interfaces -n wlan0 + -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0 } alias_eth0_work_body() { @@ -104,7 +104,7 @@ alias_eth0_work_body() { -o match:'default via 203.0.113.1' \ -o match:'default via 2001:db8:1000:2::1' \ ifdown -S $FIXTURES/alias-work.ifstate \ - -i $FIXTURES/alias-home-work.interfaces -n wlan0 + -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0 } bonded_bridge_body() { @@ -118,5 +118,5 @@ bonded_bridge_body() { -o match:'default via 203.0.113.1' \ -o match:'default via 2001:db8:1000:2::1' \ ifdown -S $FIXTURES/bonded-bridge.ifstate \ - -i $FIXTURES/bonded-bridge.interfaces -n br0 + -E $EXECUTORS -i $FIXTURES/bonded-bridge.interfaces -n br0 } diff --git a/tests/ifup_test b/tests/ifup_test index 9b35d21..b1850aa 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -33,7 +33,7 @@ dual_stack_body() { -o match:'add 2001:db8:1000:2::2/64 dev eth0' \ -o match:'default via 203.0.113.1' \ -o match:'default via 2001:db8:1000:2::1' \ - ifup -S/dev/null -i $FIXTURES/static-eth0.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } static_ipv4_body() { @@ -42,7 +42,7 @@ static_ipv4_body() { -o match:'ip link set up dev eth0' \ -o match:'add 203.0.113.2/24 dev eth0' \ -o match:'default via 203.0.113.1' \ - ifup -S/dev/null -i $FIXTURES/static-eth0-v4.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } static_ipv4_netmask_body() { @@ -51,7 +51,7 @@ static_ipv4_netmask_body() { -o match:'ip link set up dev eth0' \ -o match:'add 203.0.113.2/29 dev eth0' \ -o match:'default via 203.0.113.1' \ - ifup -S/dev/null -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } static_ipv6_body() { @@ -60,7 +60,7 @@ static_ipv6_body() { -o match:'ip link set up dev eth0' \ -o match:'add 2001:db8:1000:2::2/64 dev eth0' \ -o match:'default via 2001:db8:1000:2::1' \ - ifup -S/dev/null -i $FIXTURES/static-eth0-v6.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } static_ipv6_netmask_body() { @@ -69,7 +69,7 @@ static_ipv6_netmask_body() { -o match:'ip link set up dev eth0' \ -o match:'add 2001:db8:1000:2::2/112 dev eth0' \ -o match:'default via 2001:db8:1000:2::1' \ - ifup -S/dev/null -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } inet_dhcp_body() { @@ -77,7 +77,7 @@ inet_dhcp_body() { -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ -o match:'dhc' \ - ifup -S/dev/null -i $FIXTURES/dhcp-eth0.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } use_dhcp_body() { @@ -85,14 +85,14 @@ use_dhcp_body() { -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ -o match:'dhc' \ - ifup -S/dev/null -i $FIXTURES/use-dhcp-eth0.interfaces -n -a + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev wlan0' \ -o match:'dhc' \ - ifup -S/dev/null -i $FIXTURES/alias-home-work.interfaces -n wlan0=home + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0=home } alias_eth0_work_body() { @@ -102,7 +102,7 @@ alias_eth0_work_body() { -o match:'add 2001:db8:1000:2::2/64 dev wlan0' \ -o match:'default via 203.0.113.1' \ -o match:'default via 2001:db8:1000:2::1' \ - ifup -S/dev/null -i $FIXTURES/alias-home-work.interfaces -n wlan0=work + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0=work } bonded_bridge_body() { @@ -115,5 +115,5 @@ bonded_bridge_body() { -o match:'add 2001:db8:1000:2::2/64 dev br0' \ -o match:'default via 203.0.113.1' \ -o match:'default via 2001:db8:1000:2::1' \ - ifup -S/dev/null -i $FIXTURES/bonded-bridge.interfaces -n br0 + ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/bonded-bridge.interfaces -n br0 } diff --git a/tests/test_env.sh b/tests/test_env.sh index 07a20f7..10f8699 100644 --- a/tests/test_env.sh +++ b/tests/test_env.sh @@ -1,5 +1,6 @@ PATH="$(atf_get_srcdir)/..:$PATH" FIXTURES="$(atf_get_srcdir)/fixtures" +EXECUTORS="$(atf_get_srcdir)/executors" tests_init() { TESTS="$@" From 7eeb7c98b52d4d1444a1ddce566f1193a2694d1d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:50:45 -0600 Subject: [PATCH 032/530] libifupdown: lifecycle: remove built-in dhcp implementation --- libifupdown/lifecycle.c | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 4f77c2c..4d7ac15 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -164,13 +164,6 @@ handle_up(const struct lif_execute_opts *opts, struct lif_interface *iface, cons } } - if (iface->is_dhcp) - { - /* XXX: determine which dhcp client we should use */ - if (!lif_execute_fmt(opts, NULL, "/sbin/udhcpc -b -R -p /var/run/udhcpc.%s.pid -i %s", lifname, lifname)) - return false; - } - return true; } @@ -200,13 +193,6 @@ handle_down(const struct lif_execute_opts *opts, struct lif_interface *iface, co } } - if (iface->is_dhcp) - { - /* XXX: determine which dhcp client we should use */ - if (!lif_execute_fmt(opts, NULL, "/bin/kill $(cat /var/run/udhcpc.%s.pid)", lifname)) - return false; - } - skip_addresses: if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set down dev %s", lifname)) return false; From c51c9f7103fda2959c34ee2d84a24ec27ed39586 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 02:55:09 -0600 Subject: [PATCH 033/530] build: install executor scripts --- Makefile | 5 +++++ {executors => executor-scripts}/dhcp | 0 2 files changed, 5 insertions(+) rename {executors => executor-scripts}/dhcp (100%) diff --git a/Makefile b/Makefile index 2215799..fdd5cc7 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,8 @@ IFQUERY_OBJ = ${IFQUERY_SRC:.c=.o} IFUPDOWN_SRC = cmd/ifupdown.c IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} +EXECUTOR_SCRIPTS = dhcp + CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} CMDS = ifup ifdown ifquery @@ -79,6 +81,9 @@ install: all for i in ${CMDS}; do \ ln -s /sbin/${MULTICALL} ${DESTDIR}/sbin/$$i; \ done + for i in ${EXECUTOR_SCRIPTS}; do \ + install -D -m755 executor-scripts/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \ + done .scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8: ${SCDOC} < $< > $@ diff --git a/executors/dhcp b/executor-scripts/dhcp similarity index 100% rename from executors/dhcp rename to executor-scripts/dhcp From 201e00bbac1ac4ab9740d07d3fb85f25e1dc4954 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 03:04:02 -0600 Subject: [PATCH 034/530] dhcp: add support for dhcpcd --- executor-scripts/dhcp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/executor-scripts/dhcp b/executor-scripts/dhcp index a88927f..46a9b09 100755 --- a/executor-scripts/dhcp +++ b/executor-scripts/dhcp @@ -3,12 +3,19 @@ set -e determine_implementation() { + [ -x /sbin/dhcpcd ] && echo "dhcpcd" && return [ -x /sbin/udhcpc ] && echo "udhcpc" && return echo "???" } start() { case "$1" in + dhcpcd) + [ -z "$IF_HOSTNAME" ] && optargs="$optargs -h $IF_HOSTNAME" + [ -z "$IF_VENDOR" ] && optargs="$optargs -i $IF_VENDOR" + [ -z "$IF_CLIENT" ] && optargs="$optargs -i $IF_CLIENT" + [ -z "$IF_LEASETIME" ] && optargs="$optargs -l $IF_LEASETIME" + /sbin/dhcpcd $optargs $IFACE udhcpc) /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE ;; @@ -20,6 +27,9 @@ start() { stop() { case "$1" in + dhcpcd) + /sbin/dhcpcd -k $IFACE + ;; udhcpc) kill $(cat /var/lib/udhcpc.$IFACE.pid) ;; From 96392f0dd17e43e706d329179377a538b50ed1eb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 03:06:47 -0600 Subject: [PATCH 035/530] dhcp: add dhclient support --- executor-scripts/dhcp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/executor-scripts/dhcp b/executor-scripts/dhcp index 46a9b09..ccdb3a6 100755 --- a/executor-scripts/dhcp +++ b/executor-scripts/dhcp @@ -4,6 +4,7 @@ set -e determine_implementation() { [ -x /sbin/dhcpcd ] && echo "dhcpcd" && return + [ -x /usr/sbin/dhclient ] && echo "dhclient" && return [ -x /sbin/udhcpc ] && echo "udhcpc" && return echo "???" } @@ -16,6 +17,9 @@ start() { [ -z "$IF_CLIENT" ] && optargs="$optargs -i $IF_CLIENT" [ -z "$IF_LEASETIME" ] && optargs="$optargs -l $IF_LEASETIME" /sbin/dhcpcd $optargs $IFACE + dhclient) + /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $IFACE + ;; udhcpc) /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE ;; @@ -30,8 +34,11 @@ stop() { dhcpcd) /sbin/dhcpcd -k $IFACE ;; + dhclient) + kill -9 $(cat /var/run/dhclient.$IFACE.pid) 2>/dev/null + ;; udhcpc) - kill $(cat /var/lib/udhcpc.$IFACE.pid) + kill $(cat /var/run/udhcpc.$IFACE.pid) ;; *) echo "implementation $1 not supported" From 00c1d0f58c2b573575dbe8d6885912ecc0f088e8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 03:08:32 -0600 Subject: [PATCH 036/530] dhcp: react to $PHASE not legacy $MODE --- executor-scripts/dhcp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/executor-scripts/dhcp b/executor-scripts/dhcp index ccdb3a6..91c7266 100755 --- a/executor-scripts/dhcp +++ b/executor-scripts/dhcp @@ -50,8 +50,8 @@ impl=$(determine_implementation) [ -z "$VERBOSE" ] || set -x -case "$MODE" in -start) start $impl ;; -stop) stop $impl ;; -*) echo "unknown mode $MODE" ;; +case "$PHASE" in +up) start $impl ;; +down) stop $impl ;; +*) ;; esac From 38af1ce2d24cc928dcbbdb300b0cd9a2375d81b5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 03:09:41 -0600 Subject: [PATCH 037/530] dhcp: failing to find a supported impl should be a fatal error --- executor-scripts/dhcp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/executor-scripts/dhcp b/executor-scripts/dhcp index 91c7266..bbd0a12 100755 --- a/executor-scripts/dhcp +++ b/executor-scripts/dhcp @@ -6,7 +6,8 @@ determine_implementation() { [ -x /sbin/dhcpcd ] && echo "dhcpcd" && return [ -x /usr/sbin/dhclient ] && echo "dhclient" && return [ -x /sbin/udhcpc ] && echo "udhcpc" && return - echo "???" + echo "could not find a supported DHCP implementation" + exit 1 } start() { @@ -24,8 +25,7 @@ start() { /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE ;; *) - echo "implementation $1 not supported" - exit 1 + ;; esac } @@ -41,8 +41,7 @@ stop() { kill $(cat /var/run/udhcpc.$IFACE.pid) ;; *) - echo "implementation $1 not supported" - exit 1 + ;; esac } From 3e2d447a44bd3a5b6193adac3a5bd0aeb985581d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 03:18:15 -0600 Subject: [PATCH 038/530] build: make distcheck work --- Makefile | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Makefile b/Makefile index fdd5cc7..c653c22 100644 --- a/Makefile +++ b/Makefile @@ -111,3 +111,12 @@ install_docs: docs done .SUFFIXES: .scd .1 .2 .3 .4 .5 .6 .7 .8 + +DIST_NAME = ${PACKAGE_NAME}-${PACKAGE_VERSION} +DIST_TARBALL = ${DIST_NAME}.tar.xz + +distcheck: check dist +dist: ${DIST_TARBALL} +${DIST_TARBALL}: + git archive --format=tar --prefix=${DIST_NAME}/ -o ${DIST_NAME}.tar ${DIST_NAME} + xz ${DIST_NAME}.tar From ea1c39ff5a7bf7f7c93a1ac9f3f055cb036acc79 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 03:18:51 -0600 Subject: [PATCH 039/530] ifupdown-ng 0.3. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index c653c22..76f3475 100644 --- a/Makefile +++ b/Makefile @@ -3,7 +3,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.2.2 +PACKAGE_VERSION := 0.3 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From 4e452c5fec0578c221d0b3a12ef35687b6346993 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 08:47:21 -0600 Subject: [PATCH 040/530] multicall: mark multicall_usage() as noreturn this is needed to shut up coverity --- cmd/multicall.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/multicall.c b/cmd/multicall.c index 9437c03..0eff1bb 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -44,7 +44,7 @@ applet_cmp(const void *a, const void *b) return strcmp(key, applet->name); } -void multicall_usage(void); +void multicall_usage(void) __attribute__((noreturn)); int main(int argc, char *argv[]) From 690190a0b98b577ed7d1db22f6b7fb0882e34114 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 25 Jul 2020 08:49:37 -0600 Subject: [PATCH 041/530] libifupdown: interface-file: do not process use directives unless in an interface context --- libifupdown/interface-file.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index f1dcbad..d7c2835 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -100,6 +100,12 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) { char *executor = lif_next_token(&bufp); + if (cur_iface == NULL) + { + fprintf(stderr, "%s: use '%s' without interface\n", filename, executor); + goto parse_error; + } + /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ if (!strcmp(executor, "dhcp")) cur_iface->is_dhcp = true; From f06ee76d41e550794b92c61c3348cc2916ae8617 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 01:24:06 -0600 Subject: [PATCH 042/530] implement ipv6-ra executor for controlling ipv6 RA setting on a per-NIC basis --- Makefile | 4 +++- executor-scripts/ipv6-ra | 17 +++++++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/ipv6-ra diff --git a/Makefile b/Makefile index 76f3475..dfdf508 100644 --- a/Makefile +++ b/Makefile @@ -48,7 +48,9 @@ IFQUERY_OBJ = ${IFQUERY_SRC:.c=.o} IFUPDOWN_SRC = cmd/ifupdown.c IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} -EXECUTOR_SCRIPTS = dhcp +EXECUTOR_SCRIPTS = \ + dhcp \ + ipv6-ra CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} diff --git a/executor-scripts/ipv6-ra b/executor-scripts/ipv6-ra new file mode 100755 index 0000000..514ca28 --- /dev/null +++ b/executor-scripts/ipv6-ra @@ -0,0 +1,17 @@ +#!/bin/sh + +start() { + echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra +} + +stop() { + echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra +} + +[ -z "$VERBOSE" ] || set -x + +case "$PHASE" in +up) start $impl ;; +down) stop $impl ;; +*) ;; +esac From 052156ac0942d94e8c310fdbc547efc9359d2449 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 02:28:29 -0600 Subject: [PATCH 043/530] ifquery: add --property (ref #4) --- cmd/ifquery.c | 80 +++++++++++++++++++++++++++++++++++++++++++++++-- doc/ifquery.scd | 3 ++ 2 files changed, 81 insertions(+), 2 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index ee21fae..7e49578 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -85,6 +85,73 @@ print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, st } } +static inline size_t +count_set_bits(const char *netmask) +{ + /* netmask set to CIDR length */ + if (strchr(netmask, '.') == NULL) + return strtol(netmask, NULL, 10); + + size_t r = 0; + struct in_addr in; + + if (inet_pton(AF_INET, netmask, &in) == 0) + return r; + + /* take the IP, put it in host endian order, and + * flip it so that all the set bits are set to the right. + * then we can simply count down from 32 and right-shift + * until the bit field is all zero. + */ + unsigned int bits = htonl(in.s_addr); + for (bits = ~bits, r = 32; bits; bits >>= 1, r--) + ; + + return r; +} + +void +print_interface_property(struct lif_interface *iface, const char *property) +{ + struct lif_node *iter; + bool printing_address = !strcmp(property, "address"); + + LIF_DICT_FOREACH(iter, &iface->vars) + { + struct lif_dict_entry *entry = iter->data; + + if (strcmp(entry->key, property)) + continue; + + if (printing_address) + { + struct lif_address *addr = entry->data; + size_t orig_netmask = addr->netmask; + + if (!addr->netmask) + { + /* if fallback netmask is not set, default to 255.255.255.0 */ + addr->netmask = 24; + + struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "netmask"); + if (entry != NULL) + addr->netmask = count_set_bits(entry->data); + } + + char addr_buf[512]; + + if (!lif_address_unparse(addr, addr_buf, sizeof addr_buf, true)) + continue; + + addr->netmask = orig_netmask; + + printf("%s\n", addr_buf); + } + else + printf("%s\n", (const char *) entry->data); + } +} + void ifquery_usage(void) { @@ -103,6 +170,7 @@ ifquery_usage(void) fprintf(stderr, " -S, --state-file FILE use FILE for state\n"); fprintf(stderr, " -s, --state show configured state\n"); fprintf(stderr, " -D, --dot generate a dependency graph\n"); + fprintf(stderr, " -p, --property PROPERTY print values of properties matching PROPERTY\n"); exit(1); } @@ -113,6 +181,7 @@ struct match_options { char *include_pattern; bool pretty_print; bool dot; + char *property; }; void @@ -193,6 +262,7 @@ ifquery_main(int argc, char *argv[]) {"state-file", required_argument, 0, 'S'}, {"state", no_argument, 0, 's'}, {"dot", no_argument, 0, 'D'}, + {"property", required_argument, 0, 'p'}, {NULL, 0, 0, 0} }; struct match_options match_opts = {}; @@ -202,7 +272,7 @@ ifquery_main(int argc, char *argv[]) for (;;) { - int c = getopt_long(argc, argv, "hVi:LaI:X:PS:sD", long_options, NULL); + int c = getopt_long(argc, argv, "hVi:LaI:X:PS:sDp:", long_options, NULL); if (c == -1) break; @@ -240,6 +310,9 @@ ifquery_main(int argc, char *argv[]) case 'D': match_opts.dot = true; break; + case 'p': + match_opts.property = optarg; + break; } } @@ -292,7 +365,10 @@ ifquery_main(int argc, char *argv[]) return EXIT_FAILURE; } - print_interface(iface); + if (match_opts.property != NULL) + print_interface_property(iface, match_opts.property); + else + print_interface(iface); } return EXIT_SUCCESS; diff --git a/doc/ifquery.scd b/doc/ifquery.scd index f00ef82..13902d1 100644 --- a/doc/ifquery.scd +++ b/doc/ifquery.scd @@ -29,6 +29,9 @@ configuration file to the current format. *-i, --interfaces* _FILE_ Use _FILE_ as the config database. +*-p, --property* _PROPERTY_ + Print the values of matching properties for an interface. + *-s, --state* Query the state database instead of the config database. From 987e6399de79fd6e7f7dcfb91e294afba4945c87 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 02:32:00 -0600 Subject: [PATCH 044/530] libifupdown: interface: add support for automatic "use static" insertion --- libifupdown/interface-file.c | 2 ++ libifupdown/interface.c | 7 +++++++ libifupdown/interface.h | 1 + 3 files changed, 10 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index d7c2835..a1e93a2 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -115,6 +115,8 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) cur_iface->is_bridge = true; else if (!strcmp(executor, "bond")) cur_iface->is_bond = true; + else if (!strcmp(executor, "static")) + cur_iface->is_static = true; lif_dict_add(&cur_iface->vars, token, strdup(executor)); } diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 7d59813..7ffa767 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -75,7 +75,14 @@ lif_interface_address_add(struct lif_interface *interface, const char *address) return false; } + if (!interface->is_static) + { + lif_dict_add(&interface->vars, "use", strdup("static")); + interface->is_static = true; + } + lif_dict_add(&interface->vars, "address", addr); + return true; } diff --git a/libifupdown/interface.h b/libifupdown/interface.h index ae7abfe..6e52308 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -52,6 +52,7 @@ struct lif_interface { bool is_auto; bool is_bridge; bool is_bond; + bool is_static; struct lif_dict vars; From 0669e897fdf596dca40c9bc504f8c44714dd9b00 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 02:37:28 -0600 Subject: [PATCH 045/530] tests: add mock static executor --- tests/executors/static | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 tests/executors/static diff --git a/tests/executors/static b/tests/executors/static new file mode 100644 index 0000000..b649c11 --- /dev/null +++ b/tests/executors/static @@ -0,0 +1,18 @@ +#!/bin/sh + +case "$PHASE" in +up) + cmd="add" + ;; +down) + cmd="del" + ;; +esac + +for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do + echo ip addr $cmd $i dev $IFACE +done + +for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do + echo ip route $cmd default via $i +done From 9e4e17707f0cec2b96eb5499534083cb924317ed Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 02:50:01 -0600 Subject: [PATCH 046/530] lifecycle: expose INTERFACES_FILE env var to executors --- cmd/ifupdown.c | 8 ++++---- libifupdown/execute.h | 1 + libifupdown/lifecycle.c | 3 +++ tests/executors/static | 0 4 files changed, 8 insertions(+), 4 deletions(-) mode change 100644 => 100755 tests/executors/static diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 13642c4..2765498 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -30,6 +30,7 @@ struct match_options { static bool up; static struct lif_execute_opts exec_opts = { .executor_path = EXECUTOR_PATH, + .interfaces_file = INTERFACES_FILE, }; void @@ -129,7 +130,6 @@ ifupdown_main(int argc, char *argv[]) {NULL, 0, 0, 0} }; struct match_options match_opts = {}; - char *interfaces_file = INTERFACES_FILE; char *state_file = STATE_FILE; for (;;) @@ -146,7 +146,7 @@ ifupdown_main(int argc, char *argv[]) lif_common_version(); break; case 'i': - interfaces_file = optarg; + exec_opts.interfaces_file = optarg; break; case 'a': match_opts.is_auto = true; @@ -179,9 +179,9 @@ ifupdown_main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!lif_interface_file_parse(&collection, interfaces_file)) + if (!lif_interface_file_parse(&collection, exec_opts.interfaces_file)) { - fprintf(stderr, "%s: could not parse %s\n", argv0, interfaces_file); + fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.interfaces_file); return EXIT_FAILURE; } diff --git a/libifupdown/execute.h b/libifupdown/execute.h index fc03dbc..491a35f 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -23,6 +23,7 @@ struct lif_execute_opts { bool verbose; bool mock; const char *executor_path; + const char *interfaces_file; }; extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 4d7ac15..c47f50c 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -233,6 +233,9 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac if (opts->verbose) lif_environment_push(&envp, "VERBOSE", "1"); + if (opts->interfaces_file) + lif_environment_push(&envp, "INTERFACES_FILE", opts->interfaces_file); + struct lif_node *iter; bool did_address = false, did_gateway = false; diff --git a/tests/executors/static b/tests/executors/static old mode 100644 new mode 100755 From cae16c5758586e4fe9a643b8335ea96bd16ff8a7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 02:59:15 -0600 Subject: [PATCH 047/530] simplify loopback --- libifupdown/interface-file.c | 2 -- libifupdown/interface.c | 4 +--- libifupdown/interface.h | 1 - libifupdown/lifecycle.c | 11 +---------- 4 files changed, 2 insertions(+), 16 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index a1e93a2..5b28227 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -109,8 +109,6 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ if (!strcmp(executor, "dhcp")) cur_iface->is_dhcp = true; - else if (!strcmp(executor, "loopback")) - cur_iface->is_loopback = true; else if (!strcmp(executor, "bridge")) cur_iface->is_bridge = true; else if (!strcmp(executor, "bond")) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 7ffa767..fa149ed 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -141,10 +141,8 @@ lif_interface_collection_init(struct lif_dict *collection) /* always enable loopback interface as part of a collection */ if_lo = lif_interface_collection_find(collection, "lo"); - if_lo->is_auto = if_lo->is_loopback = true; + if_lo->is_auto = true; lif_dict_add(&if_lo->vars, "use", strdup("loopback")); - - lif_interface_address_add(if_lo, "127.0.0.1/8"); } void diff --git a/libifupdown/interface.h b/libifupdown/interface.h index 6e52308..9ef9387 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -48,7 +48,6 @@ struct lif_interface { char *ifname; bool is_dhcp; - bool is_loopback; bool is_auto; bool is_bridge; bool is_bond; diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index c47f50c..c361df2 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -143,9 +143,6 @@ handle_up(const struct lif_execute_opts *opts, struct lif_interface *iface, cons if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set up dev %s", lifname)) return false; - if (iface->is_loopback) - return true; - LIF_DICT_FOREACH(iter, &iface->vars) { struct lif_dict_entry *entry = iter->data; @@ -172,9 +169,6 @@ handle_down(const struct lif_execute_opts *opts, struct lif_interface *iface, co { struct lif_node *iter; - if (iface->is_loopback) - goto skip_addresses; - LIF_DICT_FOREACH(iter, &iface->vars) { struct lif_dict_entry *entry = iter->data; @@ -193,7 +187,6 @@ handle_down(const struct lif_execute_opts *opts, struct lif_interface *iface, co } } -skip_addresses: if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set down dev %s", lifname)) return false; @@ -219,9 +212,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac lif_environment_push(&envp, "PHASE", phase); /* try to provide $METHOD for ifupdown1 scripts if we can */ - if (iface->is_loopback) - lif_environment_push(&envp, "METHOD", "loopback"); - else if (iface->is_dhcp) + if (iface->is_dhcp) lif_environment_push(&envp, "METHOD", "dhcp"); /* same for $MODE */ From e29e552cc2410114b8d4c23407395e4600415d0c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:05:46 -0600 Subject: [PATCH 048/530] port iproute2 configuration from C to shell --- executor-scripts/static | 29 +++++++++++++++++++++++++++++ tests/executors/static | 19 +------------------ 2 files changed, 30 insertions(+), 18 deletions(-) create mode 100755 executor-scripts/static mode change 100755 => 120000 tests/executors/static diff --git a/executor-scripts/static b/executor-scripts/static new file mode 100755 index 0000000..7fc3fdf --- /dev/null +++ b/executor-scripts/static @@ -0,0 +1,29 @@ +#!/bin/sh + +case "$PHASE" in +up) cmd="add" ;; +down) cmd="del" ;; +*) exit 0 ;; +esac + +addr_family() { + if [ "$1" != "${1#*[0-9].[0-9]}" ]; then + echo "-4" + elif [ "$1" != "${1#*:[0-9a-fA-F]}" ]; then + echo "-6" + else + exit 1 + fi +} + +for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do + addrfam=$(addr_family $i) + + ${MOCK} ip $addrfam addr $cmd $i dev $IFACE +done + +for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do + addrfam=$(addr_family $i) + + ${MOCK} ip $addrfam route $cmd default via $i +done diff --git a/tests/executors/static b/tests/executors/static deleted file mode 100755 index b649c11..0000000 --- a/tests/executors/static +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/sh - -case "$PHASE" in -up) - cmd="add" - ;; -down) - cmd="del" - ;; -esac - -for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do - echo ip addr $cmd $i dev $IFACE -done - -for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do - echo ip route $cmd default via $i -done diff --git a/tests/executors/static b/tests/executors/static new file mode 120000 index 0000000..1322f47 --- /dev/null +++ b/tests/executors/static @@ -0,0 +1 @@ +mock-executor \ No newline at end of file From c1e1d30a58f75167199fd7b918adf1c7bc480022 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:12:02 -0600 Subject: [PATCH 049/530] tests: convert ifup/ifdown tests to test with mock executors --- tests/executors/bond | 1 + tests/executors/bridge | 1 + tests/ifdown_test | 35 ++++++++++++----------------------- tests/ifup_test | 35 ++++++++++++----------------------- 4 files changed, 26 insertions(+), 46 deletions(-) create mode 120000 tests/executors/bond create mode 120000 tests/executors/bridge diff --git a/tests/executors/bond b/tests/executors/bond new file mode 120000 index 0000000..1322f47 --- /dev/null +++ b/tests/executors/bond @@ -0,0 +1 @@ +mock-executor \ No newline at end of file diff --git a/tests/executors/bridge b/tests/executors/bridge new file mode 120000 index 0000000..1322f47 --- /dev/null +++ b/tests/executors/bridge @@ -0,0 +1 @@ +mock-executor \ No newline at end of file diff --git a/tests/ifdown_test b/tests/ifdown_test index c7283d5..97fef50 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -29,10 +29,7 @@ dual_stack_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'del 203.0.113.2/24 dev eth0' \ - -o match:'del 2001:db8:1000:2::2/64 dev eth0' \ - -o match:'default via 203.0.113.1' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } @@ -40,8 +37,7 @@ static_ipv4_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'del 203.0.113.2/24 dev eth0' \ - -o match:'default via 203.0.113.1' \ + -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } @@ -49,8 +45,7 @@ static_ipv4_netmask_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'del 203.0.113.2/29 dev eth0' \ - -o match:'default via 203.0.113.1' \ + -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } @@ -58,8 +53,7 @@ static_ipv6_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'del 2001:db8:1000:2::2/64 dev eth0' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } @@ -67,8 +61,7 @@ static_ipv6_netmask_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'del 2001:db8:1000:2::2/112 dev eth0' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } @@ -76,7 +69,7 @@ inet_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'dhc' \ + -o match:'executors/dhcp' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } @@ -84,14 +77,14 @@ use_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev lo' \ -o match:'ip link set down dev eth0' \ - -o match:'dhc' \ + -o match:'executors/dhcp' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev wlan0' \ - -o match:'dhc' \ + -o match:'executors/dhcp' \ ifdown -S $FIXTURES/alias-home.ifstate \ -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0 } @@ -99,10 +92,7 @@ alias_eth0_home_body() { alias_eth0_work_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set down dev wlan0' \ - -o match:'del 203.0.113.2/24 dev wlan0' \ - -o match:'del 2001:db8:1000:2::2/64 dev wlan0' \ - -o match:'default via 203.0.113.1' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifdown -S $FIXTURES/alias-work.ifstate \ -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0 } @@ -113,10 +103,9 @@ bonded_bridge_body() { -o match:'ip link set down dev eth1' \ -o match:'ip link set down dev bond0' \ -o match:'ip link set down dev br0' \ - -o match:'del 203.0.113.2/24 dev br0' \ - -o match:'del 2001:db8:1000:2::2/64 dev br0' \ - -o match:'default via 203.0.113.1' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/bond' \ + -o match:'executors/bridge' \ + -o match:'executors/static' \ ifdown -S $FIXTURES/bonded-bridge.ifstate \ -E $EXECUTORS -i $FIXTURES/bonded-bridge.interfaces -n br0 } diff --git a/tests/ifup_test b/tests/ifup_test index b1850aa..788940c 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -29,10 +29,7 @@ dual_stack_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'add 203.0.113.2/24 dev eth0' \ - -o match:'add 2001:db8:1000:2::2/64 dev eth0' \ - -o match:'default via 203.0.113.1' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } @@ -40,8 +37,7 @@ static_ipv4_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'add 203.0.113.2/24 dev eth0' \ - -o match:'default via 203.0.113.1' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } @@ -49,8 +45,7 @@ static_ipv4_netmask_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'add 203.0.113.2/29 dev eth0' \ - -o match:'default via 203.0.113.1' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } @@ -58,8 +53,7 @@ static_ipv6_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'add 2001:db8:1000:2::2/64 dev eth0' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } @@ -67,8 +61,7 @@ static_ipv6_netmask_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'add 2001:db8:1000:2::2/112 dev eth0' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } @@ -76,7 +69,7 @@ inet_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'dhc' \ + -o match:'executors/dhcp' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } @@ -84,24 +77,21 @@ use_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev lo' \ -o match:'ip link set up dev eth0' \ - -o match:'dhc' \ + -o match:'executors/dhcp' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev wlan0' \ - -o match:'dhc' \ + -o match:'executors/dhcp' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0=home } alias_eth0_work_body() { atf_check -s exit:0 -e ignore \ -o match:'ip link set up dev wlan0' \ - -o match:'add 203.0.113.2/24 dev wlan0' \ - -o match:'add 2001:db8:1000:2::2/64 dev wlan0' \ - -o match:'default via 203.0.113.1' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0=work } @@ -111,9 +101,8 @@ bonded_bridge_body() { -o match:'ip link set up dev eth1' \ -o match:'ip link set up dev bond0' \ -o match:'ip link set up dev br0' \ - -o match:'add 203.0.113.2/24 dev br0' \ - -o match:'add 2001:db8:1000:2::2/64 dev br0' \ - -o match:'default via 203.0.113.1' \ - -o match:'default via 2001:db8:1000:2::1' \ + -o match:'executors/bond' \ + -o match:'executors/bridge' \ + -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/bonded-bridge.interfaces -n br0 } From 43c147c6cfd0bb118c416b67812f8d9a6678ecb3 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:16:52 -0600 Subject: [PATCH 050/530] build: allow for non-linux executors --- Makefile | 6 ++++-- executor-scripts/{ => linux}/dhcp | 0 executor-scripts/{ => linux}/ipv6-ra | 0 executor-scripts/{ => linux}/static | 0 4 files changed, 4 insertions(+), 2 deletions(-) rename executor-scripts/{ => linux}/dhcp (100%) rename executor-scripts/{ => linux}/ipv6-ra (100%) rename executor-scripts/{ => linux}/static (100%) diff --git a/Makefile b/Makefile index dfdf508..fd8a33c 100644 --- a/Makefile +++ b/Makefile @@ -1,3 +1,4 @@ +LAYOUT ?= linux SCDOC := scdoc LIBBSD_CFLAGS = LIBBSD_LIBS = @@ -50,7 +51,8 @@ IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} EXECUTOR_SCRIPTS = \ dhcp \ - ipv6-ra + ipv6-ra \ + static CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} @@ -84,7 +86,7 @@ install: all ln -s /sbin/${MULTICALL} ${DESTDIR}/sbin/$$i; \ done for i in ${EXECUTOR_SCRIPTS}; do \ - install -D -m755 executor-scripts/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \ + install -D -m755 executor-scripts/${LAYOUT}/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \ done .scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8: diff --git a/executor-scripts/dhcp b/executor-scripts/linux/dhcp similarity index 100% rename from executor-scripts/dhcp rename to executor-scripts/linux/dhcp diff --git a/executor-scripts/ipv6-ra b/executor-scripts/linux/ipv6-ra similarity index 100% rename from executor-scripts/ipv6-ra rename to executor-scripts/linux/ipv6-ra diff --git a/executor-scripts/static b/executor-scripts/linux/static similarity index 100% rename from executor-scripts/static rename to executor-scripts/linux/static From 12307aeb9dd38b1e9b40961bde36dac2e9e33f17 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:20:35 -0600 Subject: [PATCH 051/530] lifecycle: remove static address configuration (replaced with static executor) --- libifupdown/lifecycle.c | 75 ++--------------------------------------- 1 file changed, 2 insertions(+), 73 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index c361df2..5018f50 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -90,41 +90,6 @@ count_set_bits(const char *netmask) return r; } -static bool -handle_address(const struct lif_execute_opts *opts, struct lif_address *addr, const char *cmd, const char *lifname, struct lif_interface *iface) -{ - char addrbuf[4096]; - size_t orig_netmask = addr->netmask; - - if (!addr->netmask) - { - /* if fallback netmask is not set, default to 255.255.255.0 */ - addr->netmask = 24; - - struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "netmask"); - if (entry != NULL) - addr->netmask = count_set_bits(entry->data); - } - - if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) - return false; - - /* reset the netmask */ - addr->netmask = orig_netmask; - - return lif_execute_fmt(opts, NULL, "/sbin/ip -%d addr %s %s dev %s", - addr->domain == AF_INET ? 4 : 6, cmd, addrbuf, lifname); -} - -static bool -handle_gateway(const struct lif_execute_opts *opts, const char *gateway, const char *cmd) -{ - int ipver = strchr(gateway, ':') ? 6 : 4; - - return lif_execute_fmt(opts, NULL, "/sbin/ip -%d route %s default via %s", - ipver, cmd, gateway); -} - static bool handle_pre_up(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) { @@ -138,54 +103,18 @@ handle_pre_up(const struct lif_execute_opts *opts, struct lif_interface *iface, static bool handle_up(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) { - struct lif_node *iter; + (void) iface; if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set up dev %s", lifname)) return false; - LIF_DICT_FOREACH(iter, &iface->vars) - { - struct lif_dict_entry *entry = iter->data; - - if (!strcmp(entry->key, "address")) - { - struct lif_address *addr = entry->data; - - if (!handle_address(opts, addr, "add", lifname, iface)) - return false; - } - else if (!strcmp(entry->key, "gateway")) - { - if (!handle_gateway(opts, entry->data, "add")) - return false; - } - } - return true; } static bool handle_down(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) { - struct lif_node *iter; - - LIF_DICT_FOREACH(iter, &iface->vars) - { - struct lif_dict_entry *entry = iter->data; - - if (!strcmp(entry->key, "address")) - { - struct lif_address *addr = entry->data; - - if (!handle_address(opts, addr, "del", lifname, iface)) - return false; - } - else if (!strcmp(entry->key, "gateway")) - { - if (!handle_gateway(opts, entry->data, "del")) - return false; - } - } + (void) iface; if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set down dev %s", lifname)) return false; From 05e8f9bbb577d264752ab14685a44121af97356d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:26:11 -0600 Subject: [PATCH 052/530] make all executor scripts testable/mockable --- executor-scripts/linux/dhcp | 22 ++++++++++++---------- executor-scripts/linux/ipv6-ra | 4 ++-- 2 files changed, 14 insertions(+), 12 deletions(-) diff --git a/executor-scripts/linux/dhcp b/executor-scripts/linux/dhcp index bbd0a12..fa576e7 100755 --- a/executor-scripts/linux/dhcp +++ b/executor-scripts/linux/dhcp @@ -3,6 +3,7 @@ set -e determine_implementation() { + [ -n "$IF_DHCP_PROGRAM" ] && echo "$IF_DHCP_PROGRAM" && return [ -x /sbin/dhcpcd ] && echo "dhcpcd" && return [ -x /usr/sbin/dhclient ] && echo "dhclient" && return [ -x /sbin/udhcpc ] && echo "udhcpc" && return @@ -13,16 +14,17 @@ determine_implementation() { start() { case "$1" in dhcpcd) - [ -z "$IF_HOSTNAME" ] && optargs="$optargs -h $IF_HOSTNAME" - [ -z "$IF_VENDOR" ] && optargs="$optargs -i $IF_VENDOR" - [ -z "$IF_CLIENT" ] && optargs="$optargs -i $IF_CLIENT" - [ -z "$IF_LEASETIME" ] && optargs="$optargs -l $IF_LEASETIME" - /sbin/dhcpcd $optargs $IFACE + [ -n "$IF_HOSTNAME" ] && optargs="$optargs -h $IF_HOSTNAME" + [ -n "$IF_VENDOR" ] && optargs="$optargs -i $IF_VENDOR" + [ -n "$IF_CLIENT" ] && optargs="$optargs -i $IF_CLIENT" + [ -n "$IF_LEASETIME" ] && optargs="$optargs -l $IF_LEASETIME" + ${MOCK} /sbin/dhcpcd $optargs $IFACE + ;; dhclient) - /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $IFACE + ${MOCK} /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $IFACE ;; udhcpc) - /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE + ${MOCK} /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE ;; *) ;; @@ -32,13 +34,13 @@ start() { stop() { case "$1" in dhcpcd) - /sbin/dhcpcd -k $IFACE + ${MOCK} /sbin/dhcpcd -k $IFACE ;; dhclient) - kill -9 $(cat /var/run/dhclient.$IFACE.pid) 2>/dev/null + ${MOCK} kill -9 $(cat /var/run/dhclient.$IFACE.pid) 2>/dev/null ;; udhcpc) - kill $(cat /var/run/udhcpc.$IFACE.pid) + ${MOCK} kill $(cat /var/run/udhcpc.$IFACE.pid) ;; *) ;; diff --git a/executor-scripts/linux/ipv6-ra b/executor-scripts/linux/ipv6-ra index 514ca28..0e16ecf 100755 --- a/executor-scripts/linux/ipv6-ra +++ b/executor-scripts/linux/ipv6-ra @@ -1,11 +1,11 @@ #!/bin/sh start() { - echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra + ${MOCK} echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra } stop() { - echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra + ${MOCK} echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra } [ -z "$VERBOSE" ] || set -x From 52d2bad3b82e9c9cba2c6ee50ed9c1d3cb2e1d18 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:29:16 -0600 Subject: [PATCH 053/530] interface: always attach "use link" executor --- libifupdown/interface-file.c | 5 +++++ libifupdown/interface.c | 1 + 2 files changed, 6 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 5b28227..e8dd906 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -114,7 +114,12 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) else if (!strcmp(executor, "bond")) cur_iface->is_bond = true; else if (!strcmp(executor, "static")) + { cur_iface->is_static = true; + continue; + } + else if (!strcmp(executor, "link")) + continue; lif_dict_add(&cur_iface->vars, token, strdup(executor)); } diff --git a/libifupdown/interface.c b/libifupdown/interface.c index fa149ed..87f6c97 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -62,6 +62,7 @@ lif_interface_init(struct lif_interface *interface, const char *ifname) memset(interface, '\0', sizeof *interface); interface->ifname = strdup(ifname); + lif_dict_add(&interface->vars, "use", strdup("link")); } bool From e046ea6a24e5cfe42ee7d1bd71bfd3926bcc1bb4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:34:04 -0600 Subject: [PATCH 054/530] tests: migrate to mock link executor --- tests/executors/link | 1 + tests/ifdown_test | 34 ++++++++++++---------------------- tests/ifup_test | 34 ++++++++++++---------------------- 3 files changed, 25 insertions(+), 44 deletions(-) create mode 120000 tests/executors/link diff --git a/tests/executors/link b/tests/executors/link new file mode 120000 index 0000000..1322f47 --- /dev/null +++ b/tests/executors/link @@ -0,0 +1 @@ +mock-executor \ No newline at end of file diff --git a/tests/ifdown_test b/tests/ifdown_test index 97fef50..0dcccf0 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -21,69 +21,62 @@ noargs_body() { } lo_always_auto_body() { - atf_check -s exit:0 -e ignore -o match:'ip link set down dev lo' \ - ifdown -S/dev/null -i/dev/null -n -a + atf_check -s exit:0 -e ignore -o match:'executors/link' \ + ifdown -S/dev/null -E $EXECUTORS -i/dev/null -n -a } dual_stack_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } static_ipv4_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } static_ipv4_netmask_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } static_ipv6_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } static_ipv6_netmask_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } inet_dhcp_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/dhcp' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } use_dhcp_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev lo' \ - -o match:'ip link set down dev eth0' \ + -o match:'executors/link' \ -o match:'executors/dhcp' \ ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev wlan0' \ + -o match:'executors/link' \ -o match:'executors/dhcp' \ ifdown -S $FIXTURES/alias-home.ifstate \ -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0 @@ -91,7 +84,7 @@ alias_eth0_home_body() { alias_eth0_work_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev wlan0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifdown -S $FIXTURES/alias-work.ifstate \ -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0 @@ -99,10 +92,7 @@ alias_eth0_work_body() { bonded_bridge_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set down dev eth0' \ - -o match:'ip link set down dev eth1' \ - -o match:'ip link set down dev bond0' \ - -o match:'ip link set down dev br0' \ + -o match:'executors/link' \ -o match:'executors/bond' \ -o match:'executors/bridge' \ -o match:'executors/static' \ diff --git a/tests/ifup_test b/tests/ifup_test index 788940c..cef02d5 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -21,86 +21,76 @@ noargs_body() { } lo_always_auto_body() { - atf_check -s exit:0 -e ignore -o match:'ip link set up dev lo' \ - ifup -S/dev/null -i/dev/null -n -a + atf_check -s exit:0 -e ignore -o match:'executors/link' \ + ifup -S/dev/null -E $EXECUTORS -i/dev/null -n -a } dual_stack_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } static_ipv4_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } static_ipv4_netmask_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } static_ipv6_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } static_ipv6_netmask_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } inet_dhcp_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/dhcp' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } use_dhcp_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev lo' \ - -o match:'ip link set up dev eth0' \ + -o match:'executors/link' \ -o match:'executors/dhcp' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev wlan0' \ + -o match:'executors/link' \ -o match:'executors/dhcp' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0=home } alias_eth0_work_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev wlan0' \ + -o match:'executors/link' \ -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/alias-home-work.interfaces -n wlan0=work } bonded_bridge_body() { atf_check -s exit:0 -e ignore \ - -o match:'ip link set up dev eth0' \ - -o match:'ip link set up dev eth1' \ - -o match:'ip link set up dev bond0' \ - -o match:'ip link set up dev br0' \ + -o match:'executors/link' \ -o match:'executors/bond' \ -o match:'executors/bridge' \ -o match:'executors/static' \ From 83ccb4f81da7a517b5ca9fe102bb2c22b948a11e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:36:31 -0600 Subject: [PATCH 055/530] add link executor --- Makefile | 3 ++- executor-scripts/linux/link | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/link diff --git a/Makefile b/Makefile index fd8a33c..60f91d8 100644 --- a/Makefile +++ b/Makefile @@ -52,7 +52,8 @@ IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} EXECUTOR_SCRIPTS = \ dhcp \ ipv6-ra \ - static + static \ + link CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link new file mode 100755 index 0000000..fb41a48 --- /dev/null +++ b/executor-scripts/linux/link @@ -0,0 +1,2 @@ +#!/bin/sh +${MOCK} ip link set $PHASE dev $IFACE From be00984946872686063762aeff6f7d6da4bff393 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:38:55 -0600 Subject: [PATCH 056/530] lifecycle: stop bringing up links, use link executor instead --- libifupdown/lifecycle.c | 95 +++-------------------------------------- 1 file changed, 5 insertions(+), 90 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 5018f50..0ef6fd3 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -65,73 +65,6 @@ handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp return true; } -static inline size_t -count_set_bits(const char *netmask) -{ - /* netmask set to CIDR length */ - if (strchr(netmask, '.') == NULL) - return strtol(netmask, NULL, 10); - - size_t r = 0; - struct in_addr in; - - if (inet_pton(AF_INET, netmask, &in) == 0) - return r; - - /* take the IP, put it in host endian order, and - * flip it so that all the set bits are set to the right. - * then we can simply count down from 32 and right-shift - * until the bit field is all zero. - */ - unsigned int bits = htonl(in.s_addr); - for (bits = ~bits, r = 32; bits; bits >>= 1, r--) - ; - - return r; -} - -static bool -handle_pre_up(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) -{ - (void) opts; - (void) iface; - (void) lifname; - - return true; -} - -static bool -handle_up(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) -{ - (void) iface; - - if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set up dev %s", lifname)) - return false; - - return true; -} - -static bool -handle_down(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) -{ - (void) iface; - - if (!lif_execute_fmt(opts, NULL, "/sbin/ip link set down dev %s", lifname)) - return false; - - return true; -} - -static bool -handle_post_down(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) -{ - (void) opts; - (void) iface; - (void) lifname; - - return true; -} - bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up) { @@ -210,29 +143,11 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac lif_environment_push(&envp, envkey, (const char *) entry->data); } - if (!strcmp(phase, "pre-up")) - { - if (!handle_pre_up(opts, iface, lifname)) - goto on_error; - } - else if (!strcmp(phase, "up")) - { - if (!handle_up(opts, iface, lifname)) - goto on_error; - } - else if (!strcmp(phase, "down")) - { - if (!handle_down(opts, iface, lifname)) - goto on_error; - } - else if (!strcmp(phase, "post-down")) - { - if (!handle_post_down(opts, iface, lifname)) - goto on_error; - } + if (!handle_executors_for_phase(opts, envp, iface)) + goto handle_error; - handle_executors_for_phase(opts, envp, iface); - handle_commands_for_phase(opts, envp, iface, lifname, phase); + if (!handle_commands_for_phase(opts, envp, iface, lifname, phase)) + goto handle_error; /* we should do error handling here, but ifupdown1 doesn't */ lif_execute_fmt(opts, envp, "/bin/run-parts /etc/network/if-%s.d", phase); @@ -240,7 +155,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac lif_environment_free(&envp); return true; -on_error: +handle_error: lif_environment_free(&envp); return false; } From 08805f7de3bf64e611daefb25fae0c05645abd81 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:39:58 -0600 Subject: [PATCH 057/530] lifecycle: handle_commands_for_phase(): drop unused lifname variable --- libifupdown/lifecycle.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 0ef6fd3..494d5cb 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -24,12 +24,10 @@ #include "libifupdown/tokenize.h" static bool -handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, const char *lifname, const char *phase) +handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, const char *phase) { struct lif_node *iter; - (void) lifname; - LIF_DICT_FOREACH(iter, &iface->vars) { struct lif_dict_entry *entry = iter->data; @@ -146,7 +144,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac if (!handle_executors_for_phase(opts, envp, iface)) goto handle_error; - if (!handle_commands_for_phase(opts, envp, iface, lifname, phase)) + if (!handle_commands_for_phase(opts, envp, iface, phase)) goto handle_error; /* we should do error handling here, but ifupdown1 doesn't */ From 5f078537bfac8da7b056ed58a67a0de951b881ff Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:48:37 -0600 Subject: [PATCH 058/530] tests: add tests for link executor --- tests/Kyuafile | 2 ++ tests/linux/Kyuafile | 5 +++++ tests/linux/link_test | 18 ++++++++++++++++++ 3 files changed, 25 insertions(+) create mode 100644 tests/linux/Kyuafile create mode 100755 tests/linux/link_test diff --git a/tests/Kyuafile b/tests/Kyuafile index 784a85b..a7fb909 100644 --- a/tests/Kyuafile +++ b/tests/Kyuafile @@ -5,3 +5,5 @@ test_suite('ifupdown-ng') atf_test_program{name='ifquery_test'} atf_test_program{name='ifup_test'} atf_test_program{name='ifdown_test'} + +include('linux/Kyuafile') diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile new file mode 100644 index 0000000..c98399c --- /dev/null +++ b/tests/linux/Kyuafile @@ -0,0 +1,5 @@ +syntax(2) + +test_suite('ifupdown-ng') + +atf_test_program{name='link_test'} diff --git a/tests/linux/link_test b/tests/linux/link_test new file mode 100755 index 0000000..6957224 --- /dev/null +++ b/tests/linux/link_test @@ -0,0 +1,18 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/link" + +tests_init up down + +up_body() { + export IFACE=lo PHASE=up MOCK=echo + atf_check -s exit:0 -o match:'ip link set up dev lo' \ + ${EXECUTOR} +} + +down_body() { + export IFACE=lo PHASE=down MOCK=echo + atf_check -s exit:0 -o match:'ip link set down dev lo' \ + ${EXECUTOR} +} From d35a3e3b38da3e84ac2e72575a3ee4eae041385e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 03:54:06 -0600 Subject: [PATCH 059/530] tests: add tests for ipv6-ra executor --- executor-scripts/linux/ipv6-ra | 4 ++-- tests/linux/Kyuafile | 1 + tests/linux/ipv6-ra_test | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 2 deletions(-) create mode 100755 tests/linux/ipv6-ra_test diff --git a/executor-scripts/linux/ipv6-ra b/executor-scripts/linux/ipv6-ra index 0e16ecf..95b5f64 100755 --- a/executor-scripts/linux/ipv6-ra +++ b/executor-scripts/linux/ipv6-ra @@ -1,11 +1,11 @@ #!/bin/sh start() { - ${MOCK} echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra + ${MOCK} /bin/sh -c "echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra" } stop() { - ${MOCK} echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra + ${MOCK} /bin/sh -c "echo 0 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra" } [ -z "$VERBOSE" ] || set -x diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index c98399c..1aa036a 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -3,3 +3,4 @@ syntax(2) test_suite('ifupdown-ng') atf_test_program{name='link_test'} +atf_test_program{name='ipv6-ra_test'} diff --git a/tests/linux/ipv6-ra_test b/tests/linux/ipv6-ra_test new file mode 100755 index 0000000..994823d --- /dev/null +++ b/tests/linux/ipv6-ra_test @@ -0,0 +1,18 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/ipv6-ra" + +tests_init up down + +up_body() { + export IFACE=lo PHASE=up MOCK=echo MOCK_ESC=\\ + atf_check -s exit:0 -o match:'echo 1 > /proc/sys/net/ipv6/conf/lo/accept_ra' \ + ${EXECUTOR} +} + +down_body() { + export IFACE=lo PHASE=down MOCK=echo MOCK_ESC=\\ + atf_check -s exit:0 -o match:'echo 0 > /proc/sys/net/ipv6/conf/lo/accept_ra' \ + ${EXECUTOR} +} From e3a6e08e400e7d899bed32983315b878cb4e7e38 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 04:00:56 -0600 Subject: [PATCH 060/530] tests: add dhcp executor tests --- tests/linux/Kyuafile | 1 + tests/linux/dhcp_test | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100755 tests/linux/dhcp_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 1aa036a..86cdebe 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -4,3 +4,4 @@ test_suite('ifupdown-ng') atf_test_program{name='link_test'} atf_test_program{name='ipv6-ra_test'} +atf_test_program{name='dhcp_test'} diff --git a/tests/linux/dhcp_test b/tests/linux/dhcp_test new file mode 100755 index 0000000..3ff884b --- /dev/null +++ b/tests/linux/dhcp_test @@ -0,0 +1,30 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/dhcp" + +tests_init udhcpc_up dhcpcd_up dhcpcd_down dhclient_up + +udhcpc_up_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc + atf_check -s exit:0 -o match:'/sbin/udhcpc -b -R -p /var/run/udhcpc.eth0.pid -i eth0' \ + ${EXECUTOR} +} + +dhcpcd_up_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=dhcpcd + atf_check -s exit:0 -o match:'/sbin/dhcpcd eth0' \ + ${EXECUTOR} +} + +dhcpcd_down_body() { + export IFACE=eth0 PHASE=down MOCK=echo IF_DHCP_PROGRAM=dhcpcd + atf_check -s exit:0 -o match:'/sbin/dhcpcd -k eth0' \ + ${EXECUTOR} +} + +dhclient_up_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=dhclient + atf_check -s exit:0 -o match:'/usr/sbin/dhclient -pf /var/run/dhclient.eth0.pid eth0' \ + ${EXECUTOR} +} From 83440e3f8890bf47cbbb93a75ed143eb78c14957 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 04:11:17 -0600 Subject: [PATCH 061/530] tests: add static executor tests --- tests/linux/Kyuafile | 1 + tests/linux/static_test | 27 +++++++++++++++++++++++++++ tests/test_env.sh | 2 +- 3 files changed, 29 insertions(+), 1 deletion(-) create mode 100755 tests/linux/static_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 86cdebe..49b3201 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -5,3 +5,4 @@ test_suite('ifupdown-ng') atf_test_program{name='link_test'} atf_test_program{name='ipv6-ra_test'} atf_test_program{name='dhcp_test'} +atf_test_program{name='static_test'} diff --git a/tests/linux/static_test b/tests/linux/static_test new file mode 100755 index 0000000..a07ea8e --- /dev/null +++ b/tests/linux/static_test @@ -0,0 +1,27 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static" +FIXTURES="$(atf_get_srcdir)/../fixtures" + +tests_init up down + +up_body() { + export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" + atf_check -s exit:0 \ + -o match:'addr add 203.0.113.2/24 dev eth0' \ + -o match:'addr add 2001:db8:1000:2::2/64 dev eth0' \ + -o match:'route add default via 203.0.113.1' \ + -o match:'route add default via 2001:db8:1000:2::1' \ + ${EXECUTOR} +} + +down_body() { + export IFACE=eth0 PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" + atf_check -s exit:0 \ + -o match:'addr del 203.0.113.2/24 dev eth0' \ + -o match:'addr del 2001:db8:1000:2::2/64 dev eth0' \ + -o match:'route del default via 203.0.113.1' \ + -o match:'route del default via 2001:db8:1000:2::1' \ + ${EXECUTOR} +} diff --git a/tests/test_env.sh b/tests/test_env.sh index 10f8699..ff44cfa 100644 --- a/tests/test_env.sh +++ b/tests/test_env.sh @@ -1,4 +1,4 @@ -PATH="$(atf_get_srcdir)/..:$PATH" +PATH="$(atf_get_srcdir)/..:$(atf_get_srcdir)/../..:$PATH" FIXTURES="$(atf_get_srcdir)/fixtures" EXECUTORS="$(atf_get_srcdir)/executors" From 326e27cdb45757e24095e71ffaf981eeaabc62e7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 04:13:25 -0600 Subject: [PATCH 062/530] executors: static: bring down routes before addresses --- executor-scripts/linux/static | 38 +++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index 7fc3fdf..f6b75b6 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -1,11 +1,5 @@ #!/bin/sh -case "$PHASE" in -up) cmd="add" ;; -down) cmd="del" ;; -*) exit 0 ;; -esac - addr_family() { if [ "$1" != "${1#*[0-9].[0-9]}" ]; then echo "-4" @@ -16,14 +10,28 @@ addr_family() { fi } -for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do - addrfam=$(addr_family $i) +configure_addresses() { + for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do + addrfam=$(addr_family $i) + ${MOCK} ip $addrfam addr $1 $i dev $IFACE + done +} - ${MOCK} ip $addrfam addr $cmd $i dev $IFACE -done +configure_gateways() { + for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do + addrfam=$(addr_family $i) + ${MOCK} ip $addrfam route $1 default via $i + done +} -for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do - addrfam=$(addr_family $i) - - ${MOCK} ip $addrfam route $cmd default via $i -done +case "$PHASE" in +up) + configure_addresses add + configure_gateways add + ;; +down) + configure_gateways del + configure_addresses del + ;; +*) exit 0 ;; +esac From 8fb2a0571dc1836c668ca67453fff4426b8bdbbc Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 04:18:57 -0600 Subject: [PATCH 063/530] make sure VERBOSE is respected in executors --- executor-scripts/linux/link | 1 + executor-scripts/linux/static | 2 ++ 2 files changed, 3 insertions(+) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index fb41a48..9d1389a 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -1,2 +1,3 @@ #!/bin/sh +[ -z "$VERBOSE" ] || set -x ${MOCK} ip link set $PHASE dev $IFACE diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index f6b75b6..d7e3ee3 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -24,6 +24,8 @@ configure_gateways() { done } +[ -z "$VERBOSE" ] || set -x + case "$PHASE" in up) configure_addresses add From d88d9b7de40511e7bf3b8c5a84cafdb5eda7e248 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 04:20:47 -0600 Subject: [PATCH 064/530] ifupdown-ng 0.4. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 60f91d8..60718c5 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.3 +PACKAGE_VERSION := 0.4 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From 8ef2815ef3801de94c7cbf6e5c4b8831bcff1d5b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 07:41:27 -0600 Subject: [PATCH 065/530] link executor: fix pre-up/post-down bug --- executor-scripts/linux/link | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 9d1389a..8bb9d62 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -1,3 +1,5 @@ #!/bin/sh [ -z "$VERBOSE" ] || set -x -${MOCK} ip link set $PHASE dev $IFACE +case "$PHASE" in +up|down) ${MOCK} ip link set $PHASE dev $IFACE ;; +esac From 7af585e738158db8c8fd02ba0c719d7e8fcaab61 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sun, 26 Jul 2020 09:33:43 -0600 Subject: [PATCH 066/530] ifupdown-ng 0.4.1. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 60718c5..2379964 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.4 +PACKAGE_VERSION := 0.4.1 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From e1918f3fd574e5161ba9dc59573eab8a15f93708 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 08:23:58 -0600 Subject: [PATCH 067/530] ifupdown: add --force for compatibility with busybox ifupdown --- cmd/ifupdown.c | 4 ++++ doc/ifdown.scd | 4 ++++ doc/ifup.scd | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 2765498..66ef4cb 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -49,6 +49,7 @@ ifupdown_usage(void) fprintf(stderr, " -n, --no-act do not actually run any commands\n"); fprintf(stderr, " -v, --verbose show what commands are being run\n"); fprintf(stderr, " -E, --executor-path PATH use PATH for executor directory\n"); + fprintf(stderr, " -f, --force force (de)configuration\n"); exit(1); } @@ -127,6 +128,7 @@ ifupdown_main(int argc, char *argv[]) {"no-act", no_argument, 0, 'n'}, {"verbose", no_argument, 0, 'v'}, {"executor-path", required_argument, 0, 'E'}, + {"force", no_argument, 0, 'f'}, {NULL, 0, 0, 0} }; struct match_options match_opts = {}; @@ -170,6 +172,8 @@ ifupdown_main(int argc, char *argv[]) case 'E': exec_opts.executor_path = optarg; break; + case 'f': + break; } } diff --git a/doc/ifdown.scd b/doc/ifdown.scd index 051140b..15ff53d 100644 --- a/doc/ifdown.scd +++ b/doc/ifdown.scd @@ -18,6 +18,10 @@ configured in the configuration database. *-a, --auto* Only match interfaces that are marked as _auto_. +*-f, --force* + Force deconfiguration of the interface. + This option exists for compatibility with other implementations. + *-h, --help* Display supported options to ifquery. diff --git a/doc/ifup.scd b/doc/ifup.scd index 5d9c8d9..f0a7ed3 100644 --- a/doc/ifup.scd +++ b/doc/ifup.scd @@ -18,6 +18,10 @@ configured in the configuration database. *-a, --auto* Only match interfaces that are marked as _auto_. +*-f, --force* + Force configuration of the interface. + This option exists for compatibility with other implementations. + *-h, --help* Display supported options to ifquery. From 5b9ade9db810c59752b5ecceafe7e11f70d41717 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 08:34:20 -0600 Subject: [PATCH 068/530] executors: port @ncopa's bridge scripts to run as a native executor --- Makefile | 3 +- executor-scripts/linux/bridge | 147 ++++++++++++++++++++++++++++++++++ 2 files changed, 149 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/bridge diff --git a/Makefile b/Makefile index 2379964..39f6aba 100644 --- a/Makefile +++ b/Makefile @@ -53,7 +53,8 @@ EXECUTOR_SCRIPTS = \ dhcp \ ipv6-ra \ static \ - link + link \ + bridge CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} diff --git a/executor-scripts/linux/bridge b/executor-scripts/linux/bridge new file mode 100755 index 0000000..367e947 --- /dev/null +++ b/executor-scripts/linux/bridge @@ -0,0 +1,147 @@ +#!/bin/sh + +# Copyright (C) 2012, 2020 Natanael Copa +# Copyright (C) 2020 Ariadne Conill +# +# Permission to use, copy, modify, and/or distribute this software for any +# purpose with or without fee is hereby granted, provided that the above +# copyright notice and this permission notice appear in all copies. +# +# This software is provided 'as is' and without any warranty, express or +# implied. In no event shall the authors be liable for any damages arising +# from the use of this software. + +all_ports_exist() { + local i= + for i in "$@"; do + [ -d /sys/class/net/$i ] || return 1 + done + return 0 +} + +wait_ports() { + local timeout= waitports= + [ -z "$IF_BRIDGE_WAITPORT" ] && return 0 + set -- $IF_BRIDGE_WAITPORT + timeout="$1" + shift + waitports="$@" + [ -z "$waitports" ] && waitports="$PORTS" + while ! all_ports_exist $waitports; do + [ "$timeout" -eq 0 ] && return 0 + timeout=$(($timeout - 1)) + sleep 1 + done +} + +all_ports() { + local i= + for i in /sys/class/net/*/ifindex; do + i=${i%/*} + i=${i##*/} + case "$i" in + lo|$IFACE) continue;; + *) echo $i;; + esac + done +} + +add_ports() { + local port= + for port in $PORTS; do + if [ -x /etc/network/if-pre-up.d/vlan ]; then + env IFACE=$port /etc/network/if-pre-up.d/vlan + fi + if [ -n "$IF_BRIDGE_HW" ]; then + ip link set dev $port addr $IF_BRIDGE_HW + fi + brctl addif $IFACE $port && ip link set dev $port up + done +} + +del_ports() { + local port= + for port in $PORTS; do + ip link set dev $port down + brctl delif $IFACE $port + if [ -x /etc/network/ip-post-down.d/vlan ]; then + env IFACE=$port /etc/network/if-post-down.d/vlan + fi + done +} + +set_bridge_opts() { + [ -n "$IF_BRIDGE_AGEING" ] \ + && brctl setageing $IFACE $IF_BRIDGE_AGEING + [ -n "$IF_BRIDGE_BRIDGEPRIO" ] \ + && brctl setbridgeprio $IFACE $IF_BRIDGE_BRIDGEPRIO + [ -n "$IF_BRIDGE_FD" ] \ + && brctl setfd $IFACE $IF_BRIDGE_FD + [ -n "$IF_BRIDGE_GCINT" ] \ + && brctl setgcint $IFACE $IF_BRIDGE_GCINT + [ -n "$IF_BRIDGE_HELLO" ] \ + && brctl sethello $IFACE $IF_BRIDGE_HELLO + [ -n "$IF_BRIDGE_MAXAGE" ] \ + && brctl setmaxage $IFACE $IF_BRIDGE_MAXAGE + [ -n "$IF_BRIDGE_PATHCOST" ] \ + && brctl setpathcost $IFACE $IF_BRIDGE_PATHCOST + [ -n "$IF_BRIDGE_PORTPRIO" ] \ + && brctl setportprio $IFACE $IF_BRIDGE_PORTPRIO + [ -n "$IF_BRIDGE_STP" ] \ + && brctl stp $IFACE $IF_BRIDGE_STP +} + +all_ports_ready() { + local port= + for port in $PORTS; do + case $(cat /sys/class/net/$IFACE/brif/$port/state) in + ""|0|3) ;; # 0 = disabled, 3 = forwarding + [12]) return 1;; + esac + done + return 0 +} + +find_maxwait() { + awk '{printf("%.f\n", 2 * $0 / 100); }' \ + /sys/class/net/$IFACE/bridge/forward_delay +} + +wait_bridge() { + local timeout=$IF_BRIDGE_MAXWAIT + if [ -z "$timeout" ]; then + timeout=$(find_maxwait) + fi + ip link set dev $IFACE up + while ! all_ports_ready; do + [ $timeout -eq 0 ] && break + timeout=$(($timeout - 1)) + sleep 1 + done +} + +[ -z "$IF_BRIDGE_PORTS" ] && IF_BRIDGE_PORTS="$IF_REQUIRES" + +case "$IF_BRIDGE_PORTS" in +"") ;; +none) PORTS="";; +all) PORTS=$(all_ports);; +*) PORTS="$IF_BRIDGE_PORTS";; +esac + +[ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit + +case "$PHASE" in +pre-up) + brctl addbr $IFACE || exit 1 + wait_ports + set_bridge_opts + add_ports + wait_bridge + ;; +post-down) + del_ports + ip link set dev $IFACE down + brctl delbr $IFACE || exit 1 + ;; +esac From ef586a6b94728b3e00771cb5705723d355fcb1b2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 09:04:06 -0600 Subject: [PATCH 069/530] build: allow the packager to configure the executor scripts installed --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 39f6aba..3d432b1 100644 --- a/Makefile +++ b/Makefile @@ -49,7 +49,7 @@ IFQUERY_OBJ = ${IFQUERY_SRC:.c=.o} IFUPDOWN_SRC = cmd/ifupdown.c IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} -EXECUTOR_SCRIPTS = \ +EXECUTOR_SCRIPTS ?= \ dhcp \ ipv6-ra \ static \ From cb9d347c8a3b915d72c947d64cfe9f5490bcb150 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 10:40:46 -0600 Subject: [PATCH 070/530] ifupdown-ng 0.4.2. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3d432b1..ccd016e 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.4.1 +PACKAGE_VERSION := 0.4.2 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From 3302089d4b0d710ade4add8f5ebd4db1230c961e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 12:07:09 -0600 Subject: [PATCH 071/530] tests: add mock-dependency-generator (ref #5) --- tests/executors/mock-dependency-generator | 5 +++++ 1 file changed, 5 insertions(+) create mode 100755 tests/executors/mock-dependency-generator diff --git a/tests/executors/mock-dependency-generator b/tests/executors/mock-dependency-generator new file mode 100755 index 0000000..e413947 --- /dev/null +++ b/tests/executors/mock-dependency-generator @@ -0,0 +1,5 @@ +#!/bin/sh + +case "$PHASE" in +depend) echo "eth0 eth1 eth2 eth3 eth4" ;; +esac From 3a75de9f8c7c61db183916f6d961046c2e6b4e1f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 13:01:15 -0600 Subject: [PATCH 072/530] execute: add lif_execute_buf_with_result() to collect a result buffer --- libifupdown/execute.c | 51 +++++++++++++++++++++++++++++++++++++++++++ libifupdown/execute.h | 1 + 2 files changed, 52 insertions(+) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index b3781dc..09e2d98 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -60,6 +60,57 @@ lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const c return WIFEXITED(status) && WEXITSTATUS(status) == 0; } +bool +lif_execute_buf_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...) +{ + char cmdbuf[4096]; + va_list va; + + va_start(va, fmt); + vsnprintf(cmdbuf, sizeof cmdbuf, fmt, va); + va_end(va); + + pid_t child; + char *argv[] = { SHELL, "-c", cmdbuf, NULL }; + + if (opts->verbose) + puts(cmdbuf); + + if (opts->mock) + return true; + + int pipefds[2]; + if (pipe(pipefds) < 0) + { + fprintf(stderr, "execute '%s': %s\n", cmdbuf, strerror(errno)); + return false; + } + + posix_spawn_file_actions_t file_actions; + + posix_spawn_file_actions_init(&file_actions); + posix_spawn_file_actions_addclose(&file_actions, pipefds[0]); + posix_spawn_file_actions_adddup2(&file_actions, pipefds[1], 1); + posix_spawn_file_actions_addclose(&file_actions, pipefds[1]); + + if (posix_spawn(&child, SHELL, &file_actions, NULL, argv, envp) != 0) + { + fprintf(stderr, "execute '%s': %s\n", cmdbuf, strerror(errno)); + return false; + } + + int status; + waitpid(child, &status, 0); + + if (read(pipefds[0], buf, bufsize) < 0) + { + fprintf(stderr, "reading from pipe: %s\n", strerror(errno)); + return false; + } + + return WIFEXITED(status) && WEXITSTATUS(status) == 0; +} + bool lif_file_is_executable(const char *path) { diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 491a35f..44391c9 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -27,6 +27,7 @@ struct lif_execute_opts { }; extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); +extern bool lif_execute_buf_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...); extern bool lif_file_is_executable(const char *path); extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor); From fb5ff4eac29ae69e3ff3b0b6943b9924e1ac78fe Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 13:46:25 -0600 Subject: [PATCH 073/530] lifecycle: add support for learning dependents from executors (ref #5) --- cmd/ifquery.c | 21 +++++++-- libifupdown/execute.c | 34 ++++++++++++-- libifupdown/execute.h | 3 +- libifupdown/lifecycle.c | 86 +++++++++++++++++++++++++++++++++++ libifupdown/lifecycle.h | 1 + tests/executors/mock-executor | 3 +- 6 files changed, 137 insertions(+), 11 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 7e49578..eb01cf5 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -21,9 +21,17 @@ #include "libifupdown/libifupdown.h" #include "cmd/multicall.h" +static struct lif_execute_opts exec_opts = { + .interfaces_file = INTERFACES_FILE, + .executor_path = EXECUTOR_PATH +}; + void print_interface(struct lif_interface *iface) { + if (!lif_lifecycle_query_dependents(&exec_opts, iface, iface->ifname)) + return; + if (iface->is_auto) printf("auto %s\n", iface->ifname); @@ -263,16 +271,16 @@ ifquery_main(int argc, char *argv[]) {"state", no_argument, 0, 's'}, {"dot", no_argument, 0, 'D'}, {"property", required_argument, 0, 'p'}, + {"executor-path", required_argument, 0, 'E'}, {NULL, 0, 0, 0} }; struct match_options match_opts = {}; bool listing = false, listing_stat = false; - char *interfaces_file = INTERFACES_FILE; char *state_file = STATE_FILE; for (;;) { - int c = getopt_long(argc, argv, "hVi:LaI:X:PS:sDp:", long_options, NULL); + int c = getopt_long(argc, argv, "hVi:LaI:X:PS:sDp:E:", long_options, NULL); if (c == -1) break; @@ -284,7 +292,7 @@ ifquery_main(int argc, char *argv[]) lif_common_version(); break; case 'i': - interfaces_file = optarg; + exec_opts.interfaces_file = optarg; break; case 'L': listing = true; @@ -313,6 +321,9 @@ ifquery_main(int argc, char *argv[]) case 'p': match_opts.property = optarg; break; + case 'E': + exec_opts.executor_path = optarg; + break; } } @@ -322,9 +333,9 @@ ifquery_main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!lif_interface_file_parse(&collection, interfaces_file)) + if (!lif_interface_file_parse(&collection, exec_opts.interfaces_file)) { - fprintf(stderr, "%s: could not parse %s\n", argv0, interfaces_file); + fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.interfaces_file); return EXIT_FAILURE; } diff --git a/libifupdown/execute.c b/libifupdown/execute.c index 09e2d98..9b73df9 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -24,6 +24,7 @@ #include #include #include +#include #include "libifupdown/execute.h" @@ -61,7 +62,7 @@ lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const c } bool -lif_execute_buf_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...) +lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...) { char cmdbuf[4096]; va_list va; @@ -99,8 +100,15 @@ lif_execute_buf_with_result(const struct lif_execute_opts *opts, char *buf, size return false; } - int status; - waitpid(child, &status, 0); + close(pipefds[1]); + + struct pollfd pfd = { + .fd = pipefds[0], + .events = POLLIN + }; + + if (poll(&pfd, 1, -1) < 1) + goto no_result; if (read(pipefds[0], buf, bufsize) < 0) { @@ -108,6 +116,10 @@ lif_execute_buf_with_result(const struct lif_execute_opts *opts, char *buf, size return false; } + int status; +no_result: + waitpid(child, &status, 0); + return WIFEXITED(status) && WEXITSTATUS(status) == 0; } @@ -140,3 +152,19 @@ lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], return lif_execute_fmt(opts, envp, "%s", pathbuf); } + +bool +lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize) +{ + if (opts->verbose) + fprintf(stderr, "ifupdown: attempting to run %s executor\n", executor); + + char pathbuf[4096]; + + snprintf(pathbuf, sizeof pathbuf, "%s/%s", opts->executor_path, executor); + + if (!lif_file_is_executable(pathbuf)) + return true; + + return lif_execute_fmt_with_result(opts, buf, bufsize, envp, "%s", pathbuf); +} diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 44391c9..3fbde45 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -27,8 +27,9 @@ struct lif_execute_opts { }; extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); -extern bool lif_execute_buf_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...); +extern bool lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...); extern bool lif_file_is_executable(const char *path); extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor); +extern bool lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize); #endif diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 494d5cb..ffd8c41 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -63,6 +63,89 @@ handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp return true; } +static bool +query_dependents_from_executors(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, char *buf, size_t bufsize) +{ + struct lif_node *iter; + + LIF_DICT_FOREACH(iter, &iface->vars) + { + char resbuf[1024] = {}; + struct lif_dict_entry *entry = iter->data; + struct lif_execute_opts exec_opts = { + .verbose = opts->verbose, + .executor_path = opts->executor_path, + .interfaces_file = opts->interfaces_file + }; + + if (strcmp(entry->key, "use")) + continue; + + const char *cmd = entry->data; + if (!lif_maybe_run_executor_with_result(&exec_opts, envp, cmd, resbuf, sizeof resbuf)) + return false; + + if (!*resbuf) + continue; + + strlcat(buf, " ", bufsize); + strlcat(buf, resbuf, bufsize); + } + + return true; +} + +bool +lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) +{ + char deps[4096] = {}; + char final_deps[4096] = {}; + + if (lifname == NULL) + lifname = iface->ifname; + + char **envp = NULL; + + lif_environment_push(&envp, "IFACE", lifname); + lif_environment_push(&envp, "PHASE", "depend"); + lif_environment_push(&envp, "MODE", "depend"); + + if (opts->verbose) + lif_environment_push(&envp, "VERBOSE", "1"); + + if (opts->interfaces_file) + lif_environment_push(&envp, "INTERFACES_FILE", opts->interfaces_file); + + struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "requires"); + if (entry != NULL) + strlcpy(deps, entry->data, sizeof deps); + + if (!query_dependents_from_executors(opts, envp, iface, deps, sizeof deps)) + return false; + + char *p = deps; + while (*p) + { + char *token = lif_next_token(&p); + + if (strstr(final_deps, token) != NULL) + continue; + + strlcat(final_deps, token, sizeof final_deps); + strlcat(final_deps, " ", sizeof final_deps); + } + + if (entry != NULL) + { + free(entry->data); + entry->data = strdup(final_deps); + } + else + lif_dict_add(&iface->vars, "requires", strdup(final_deps)); + + return true; +} + bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up) { @@ -196,6 +279,9 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa if (lifname == NULL) lifname = iface->ifname; + if (!lif_lifecycle_query_dependents(opts, iface, lifname)) + return false; + if (up) { /* when going up, dependents go up first. */ diff --git a/libifupdown/lifecycle.h b/libifupdown/lifecycle.h index e5b0adc..aebbf6e 100644 --- a/libifupdown/lifecycle.h +++ b/libifupdown/lifecycle.h @@ -19,6 +19,7 @@ #include "libifupdown/interface.h" #include "libifupdown/execute.h" +extern bool lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname); extern bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up); extern bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up); diff --git a/tests/executors/mock-executor b/tests/executors/mock-executor index ba185da..039e4d0 100755 --- a/tests/executors/mock-executor +++ b/tests/executors/mock-executor @@ -1,3 +1,2 @@ #!/bin/sh - -echo $0 ${MODE} +exit 0 From c97594b89bd3ea38af39301878fd38fa4aeeb226 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 13:48:53 -0600 Subject: [PATCH 074/530] tests: add test for mock dependency generator --- tests/fixtures/mock-dependency-generator.interfaces | 2 ++ tests/ifquery_test | 8 +++++++- 2 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/mock-dependency-generator.interfaces diff --git a/tests/fixtures/mock-dependency-generator.interfaces b/tests/fixtures/mock-dependency-generator.interfaces new file mode 100644 index 0000000..d07127f --- /dev/null +++ b/tests/fixtures/mock-dependency-generator.interfaces @@ -0,0 +1,2 @@ +iface br0 + use mock-dependency-generator diff --git a/tests/ifquery_test b/tests/ifquery_test index 52318f5..91c1380 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -12,7 +12,8 @@ tests_init \ use_dhcp \ state_query_home \ state_query_work \ - state_print + state_print \ + learned_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -69,3 +70,8 @@ state_print_body() { atf_check -s exit:0 -o match:"wlan0=work" \ ifquery -S $FIXTURES/alias-work.ifstate -i $FIXTURES/alias-home-work.interfaces -s } + +learned_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0 eth1 eth2 eth3 eth4" \ + ifquery -E $EXECUTORS -i $FIXTURES/mock-dependency-generator.interfaces br0 +} From 21bcbe101765d6347bba5446aebd338558565cbf Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 13:53:21 -0600 Subject: [PATCH 075/530] execute: fix memory leak in lif_execute_fmt_with_result() --- libifupdown/execute.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index 9b73df9..b6a4f84 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -100,6 +100,8 @@ lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size return false; } + posix_spawn_file_actions_destroy(&file_actions); + close(pipefds[1]); struct pollfd pfd = { From cf59f6af4cbccb1a08fc5f3ff1f4b00a61976191 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 14:04:27 -0600 Subject: [PATCH 076/530] tests: add ifup/ifdown tests for learned dependencies (close #5) --- tests/fixtures/mock-dependency-generator.ifstate | 6 ++++++ tests/ifdown_test | 15 ++++++++++++++- tests/ifup_test | 13 ++++++++++++- 3 files changed, 32 insertions(+), 2 deletions(-) create mode 100644 tests/fixtures/mock-dependency-generator.ifstate diff --git a/tests/fixtures/mock-dependency-generator.ifstate b/tests/fixtures/mock-dependency-generator.ifstate new file mode 100644 index 0000000..39cf8ca --- /dev/null +++ b/tests/fixtures/mock-dependency-generator.ifstate @@ -0,0 +1,6 @@ +eth0=eth0 +eth1=eth1 +eth2=eth2 +eth3=eth3 +eth4=eth4 +br0=br0 diff --git a/tests/ifdown_test b/tests/ifdown_test index 0dcccf0..dfd4f77 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -14,7 +14,8 @@ tests_init \ use_dhcp \ alias_eth0_home \ alias_eth0_work \ - bonded_bridge + bonded_bridge \ + learned_dependency noargs_body() { atf_check -s exit:1 -e ignore ifdown -S/dev/null @@ -99,3 +100,15 @@ bonded_bridge_body() { ifdown -S $FIXTURES/bonded-bridge.ifstate \ -E $EXECUTORS -i $FIXTURES/bonded-bridge.interfaces -n br0 } + +learned_dependency_body() { + atf_check -s exit:0 -o ignore \ + -e match:"eth0" \ + -e match:"eth1" \ + -e match:"eth2" \ + -e match:"eth3" \ + -e match:"eth4" \ + ifdown -n -S $FIXTURES/mock-dependency-generator.ifstate \ + -E $EXECUTORS \ + -i $FIXTURES/mock-dependency-generator.interfaces br0 +} diff --git a/tests/ifup_test b/tests/ifup_test index cef02d5..1a2b4ea 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -14,7 +14,8 @@ tests_init \ use_dhcp \ alias_eth0_home \ alias_eth0_work \ - bonded_bridge + bonded_bridge \ + learned_dependency noargs_body() { atf_check -s exit:1 -e ignore ifup -S/dev/null @@ -96,3 +97,13 @@ bonded_bridge_body() { -o match:'executors/static' \ ifup -S/dev/null -E $EXECUTORS -i $FIXTURES/bonded-bridge.interfaces -n br0 } + +learned_dependency_body() { + atf_check -s exit:0 -o ignore \ + -e match:"eth0" \ + -e match:"eth1" \ + -e match:"eth2" \ + -e match:"eth3" \ + -e match:"eth4" \ + ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/mock-dependency-generator.interfaces br0 +} From b1dfa609f915fb81e73b2b93693d20b56d349c04 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 28 Jul 2020 22:41:27 +0200 Subject: [PATCH 077/530] dict: Add lif_dict_find_all(). As a dict can have multiple values for any given key we add a function to query all occurences of a given key and return them as a (new) list. Signed-off-by: Maximilian Wilhelm --- libifupdown/dict.c | 26 ++++++++++++++++++++++++++ libifupdown/dict.h | 2 ++ 2 files changed, 28 insertions(+) diff --git a/libifupdown/dict.c b/libifupdown/dict.c index 4ac7085..ce7333d 100644 --- a/libifupdown/dict.c +++ b/libifupdown/dict.c @@ -3,6 +3,7 @@ * Purpose: wrapping linked lists to provide a naive dictionary * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -65,6 +66,31 @@ lif_dict_find(struct lif_dict *dict, const char *key) return NULL; } +struct lif_list * +lif_dict_find_all(struct lif_dict *dict, const char *key) +{ + struct lif_list *entries = calloc(1, sizeof(struct lif_list)); + struct lif_node *iter; + + LIF_LIST_FOREACH(iter, dict->list.head) + { + struct lif_dict_entry *entry = iter->data; + if (!strcmp(entry->key, key)) + { + struct lif_node *new = calloc(1, sizeof(struct lif_node)); + lif_node_insert_tail(new, entry->data, entries); + } + } + + if (entries->length == 0) + { + free(entries); + return NULL; + } + + return entries; +} + void lif_dict_delete(struct lif_dict *dict, const char *key) { diff --git a/libifupdown/dict.h b/libifupdown/dict.h index 298b349..f435916 100644 --- a/libifupdown/dict.h +++ b/libifupdown/dict.h @@ -3,6 +3,7 @@ * Purpose: wrapping linked lists to provide a naive dictionary * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -38,6 +39,7 @@ extern void lif_dict_init(struct lif_dict *dict); extern void lif_dict_fini(struct lif_dict *dict); extern struct lif_dict_entry *lif_dict_add(struct lif_dict *dict, const char *key, void *data); extern struct lif_dict_entry *lif_dict_find(struct lif_dict *dict, const char *key); +extern struct lif_list *lif_dict_find_all(struct lif_dict *dict, const char *key); extern void lif_dict_delete(struct lif_dict *dict, const char *key); extern void lif_dict_delete_entry(struct lif_dict *dict, struct lif_dict_entry *entry); From f51c976b528fd21ea7177325f18d9db7fd54aa92 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 28 Jul 2020 22:44:22 +0200 Subject: [PATCH 078/530] dict: Add lif_dict_add_once() Add a function to add a key/value pair to the dict only if it doesn't exist within the dict already. As the dict is type agnostic this requires a comparator function to be given. Signed-off-by: Maximilian Wilhelm --- libifupdown/dict.c | 25 +++++++++++++++++++++++++ libifupdown/dict.h | 1 + 2 files changed, 26 insertions(+) diff --git a/libifupdown/dict.c b/libifupdown/dict.c index ce7333d..a0b5f2a 100644 --- a/libifupdown/dict.c +++ b/libifupdown/dict.c @@ -50,6 +50,31 @@ lif_dict_add(struct lif_dict *dict, const char *key, void *data) return entry; } +struct lif_dict_entry * +lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, + int (*compar)(const void *, const void *)) +{ + struct lif_list *existing = lif_dict_find_all(dict, key); + if (existing) + { + struct lif_node *iter; + LIF_LIST_FOREACH(iter, existing->head) + { + if (!compar(data, iter->data)) + return NULL; + } + } + + struct lif_dict_entry *entry = calloc(1, sizeof *entry); + + entry->key = strdup(key); + entry->data = data; + + lif_node_insert_tail(&entry->node, entry, &dict->list); + + return entry; +} + struct lif_dict_entry * lif_dict_find(struct lif_dict *dict, const char *key) { diff --git a/libifupdown/dict.h b/libifupdown/dict.h index f435916..2332c05 100644 --- a/libifupdown/dict.h +++ b/libifupdown/dict.h @@ -38,6 +38,7 @@ struct lif_dict_entry { extern void lif_dict_init(struct lif_dict *dict); extern void lif_dict_fini(struct lif_dict *dict); extern struct lif_dict_entry *lif_dict_add(struct lif_dict *dict, const char *key, void *data); +extern struct lif_dict_entry *lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, int (*compar)(const void *, const void *)); extern struct lif_dict_entry *lif_dict_find(struct lif_dict *dict, const char *key); extern struct lif_list *lif_dict_find_all(struct lif_dict *dict, const char *key); extern void lif_dict_delete(struct lif_dict *dict, const char *key); From 2420023b74d843e4a31c356ab106ac88fbb4b822 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 28 Jul 2020 22:37:41 +0200 Subject: [PATCH 079/530] Add comparator wrapper and type cast values properly. Signed-off-by: Maximilian Wilhelm --- Makefile | 1 + libifupdown/compar.c | 26 ++++++++++++++++++++++++++ libifupdown/compar.h | 21 +++++++++++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 libifupdown/compar.c create mode 100644 libifupdown/compar.h diff --git a/Makefile b/Makefile index ccd016e..d0eca05 100644 --- a/Makefile +++ b/Makefile @@ -25,6 +25,7 @@ CPPFLAGS += -DEXECUTOR_PATH=\"${EXECUTOR_PATH}\" LIBIFUPDOWN_SRC = \ + libifupdown/compar.c \ libifupdown/list.c \ libifupdown/dict.c \ libifupdown/interface.c \ diff --git a/libifupdown/compar.c b/libifupdown/compar.c new file mode 100644 index 0000000..8705404 --- /dev/null +++ b/libifupdown/compar.c @@ -0,0 +1,26 @@ +/* + * libifupdown/compar.c + * Purpose: comparators + * + * Copyright (c) 2020 Maximilian Wilhelm + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include +#include "libifupdown/compar.h" + +int +compar_str (const void *a, const void *b) +{ + const char *str_a = (const char *)a; + const char *str_b = (const char *)b; + + return strcmp (str_a, str_b); +} diff --git a/libifupdown/compar.h b/libifupdown/compar.h new file mode 100644 index 0000000..8652a26 --- /dev/null +++ b/libifupdown/compar.h @@ -0,0 +1,21 @@ +/* + * libifupdown/compar.h + * Purpose: Comparators + * + * Copyright (c) 2020 Maximilian Wilhelm + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#ifndef LIBIFUPDOWN_COMPAR_H__GUARD +#define LIBIFUPDOWN_COMPAR_H__GUARD + +int compar_str (const void *a, const void *b); + +#endif From 73f3690432e128f43751ac170ec2fddeeae710bd Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 28 Jul 2020 22:39:20 +0200 Subject: [PATCH 080/530] Deduce which addons to 'use' from parameters names (closes #6) Signed-off-by: Maximilian Wilhelm --- libifupdown/interface-file.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index e8dd906..205c920 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -19,6 +19,7 @@ #include "libifupdown/interface-file.h" #include "libifupdown/fgetline.h" #include "libifupdown/tokenize.h" +#include "libifupdown/compar.h" bool lif_interface_file_parse(struct lif_dict *collection, const char *filename) @@ -138,6 +139,23 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) else if (cur_iface != NULL) { lif_dict_add(&cur_iface->vars, token, strdup(bufp)); + + /* Check if token looks like - and assume is an addon */ + char *word_end = strchr(token, '-'); + if (word_end) + { + /* Copy word1 to not mangle *token */ + char *addon = strndup(token, word_end - token); + lif_dict_add_once(&cur_iface->vars, "use", addon, compar_str); + + /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ + if (!strcmp(addon, "dhcp")) + cur_iface->is_dhcp = true; + else if (!strcmp(addon, "bridge")) + cur_iface->is_bridge = true; + else if (!strcmp(addon, "bond")) + cur_iface->is_bond = true; + } } } From 9d958892ed8c3f2c47963deaf2a6ba834f499d65 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 28 Jul 2020 23:25:01 +0200 Subject: [PATCH 081/530] Free nodes of a lif_dict_find_all() result. Signed-off-by: Maximilian Wilhelm --- libifupdown/dict.c | 13 +++++++++++-- libifupdown/list.c | 19 +++++++++++++++++++ libifupdown/list.h | 3 +++ 3 files changed, 33 insertions(+), 2 deletions(-) diff --git a/libifupdown/dict.c b/libifupdown/dict.c index a0b5f2a..3dea682 100644 --- a/libifupdown/dict.c +++ b/libifupdown/dict.c @@ -14,6 +14,7 @@ * from the use of this software. */ +#include #include #include #include "libifupdown/dict.h" @@ -55,14 +56,22 @@ lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, int (*compar)(const void *, const void *)) { struct lif_list *existing = lif_dict_find_all(dict, key); - if (existing) + if (existing != NULL) { + bool found = false; struct lif_node *iter; LIF_LIST_FOREACH(iter, existing->head) { if (!compar(data, iter->data)) - return NULL; + { + found = true; + break; + } } + + lif_list_free_nodes (&existing); + if (found) + return NULL; } struct lif_dict_entry *entry = calloc(1, sizeof *entry); diff --git a/libifupdown/list.c b/libifupdown/list.c index 6a44f86..6b92b1c 100644 --- a/libifupdown/list.c +++ b/libifupdown/list.c @@ -3,6 +3,7 @@ * Purpose: linked lists * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,8 +15,26 @@ */ #include +#include #include "libifupdown/list.h" +void +lif_list_free_nodes(struct lif_list **list) +{ + if (*list == NULL) + return; + + struct lif_node *iter; + + LIF_LIST_FOREACH (iter, (*list)->head) + { + free (iter->prev); + } + + free (iter); + free (*list); +} + void lif_node_insert(struct lif_node *node, void *data, struct lif_list *list) { diff --git a/libifupdown/list.h b/libifupdown/list.h index 326eca0..a0155d6 100644 --- a/libifupdown/list.h +++ b/libifupdown/list.h @@ -3,6 +3,7 @@ * Purpose: linked lists * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -29,6 +30,8 @@ struct lif_list { size_t length; }; +extern void lif_list_free_nodes(struct lif_list **list); + extern void lif_node_insert(struct lif_node *node, void *data, struct lif_list *list); extern void lif_node_insert_tail(struct lif_node *node, void *data, struct lif_list *list); extern void lif_node_delete(struct lif_node *node, struct lif_list *list); From 80450810244cdf01da5e5d196d86b750d671cc3a Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 28 Jul 2020 23:30:09 +0200 Subject: [PATCH 082/530] list: Set pointer to free()ed list to NULL. Signed-off-by: Maximilian Wilhelm --- libifupdown/list.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libifupdown/list.c b/libifupdown/list.c index 6b92b1c..11cfcf5 100644 --- a/libifupdown/list.c +++ b/libifupdown/list.c @@ -33,6 +33,7 @@ lif_list_free_nodes(struct lif_list **list) free (iter); free (*list); + *list = NULL; } void From cfbfa07e8572ff4ddeecebec79b13950c61cea1a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 17:53:48 -0400 Subject: [PATCH 083/530] list: refactor lif_list_free_nodes() a bit --- libifupdown/dict.c | 3 ++- libifupdown/list.c | 14 ++++++-------- libifupdown/list.h | 2 +- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/libifupdown/dict.c b/libifupdown/dict.c index 3dea682..3f5b1e1 100644 --- a/libifupdown/dict.c +++ b/libifupdown/dict.c @@ -69,7 +69,8 @@ lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, } } - lif_list_free_nodes (&existing); + lif_list_free_nodes(existing); + if (found) return NULL; } diff --git a/libifupdown/list.c b/libifupdown/list.c index 11cfcf5..6ee43fe 100644 --- a/libifupdown/list.c +++ b/libifupdown/list.c @@ -19,21 +19,19 @@ #include "libifupdown/list.h" void -lif_list_free_nodes(struct lif_list **list) +lif_list_free_nodes(struct lif_list *list) { - if (*list == NULL) + if (list == NULL) return; - struct lif_node *iter; + struct lif_node *iter, *iter_next; - LIF_LIST_FOREACH (iter, (*list)->head) + LIF_LIST_FOREACH_SAFE(iter, iter_next, list->head) { - free (iter->prev); + free (iter); } - free (iter); - free (*list); - *list = NULL; + free (list); } void diff --git a/libifupdown/list.h b/libifupdown/list.h index a0155d6..4a495b5 100644 --- a/libifupdown/list.h +++ b/libifupdown/list.h @@ -30,7 +30,7 @@ struct lif_list { size_t length; }; -extern void lif_list_free_nodes(struct lif_list **list); +extern void lif_list_free_nodes(struct lif_list *list); extern void lif_node_insert(struct lif_node *node, void *data, struct lif_list *list); extern void lif_node_insert_tail(struct lif_node *node, void *data, struct lif_list *list); From 81d0ebc3e8c94495d91d6be9fe19d7e6f85a64ba Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 28 Jul 2020 17:57:51 -0400 Subject: [PATCH 084/530] remove unnecessary strcmp wrapper, use typecasting instead --- Makefile | 1 - libifupdown/compar.c | 26 -------------------------- libifupdown/compar.h | 21 --------------------- libifupdown/dict.c | 2 +- libifupdown/dict.h | 4 +++- libifupdown/interface-file.c | 4 ++-- 6 files changed, 6 insertions(+), 52 deletions(-) delete mode 100644 libifupdown/compar.c delete mode 100644 libifupdown/compar.h diff --git a/Makefile b/Makefile index d0eca05..ccd016e 100644 --- a/Makefile +++ b/Makefile @@ -25,7 +25,6 @@ CPPFLAGS += -DEXECUTOR_PATH=\"${EXECUTOR_PATH}\" LIBIFUPDOWN_SRC = \ - libifupdown/compar.c \ libifupdown/list.c \ libifupdown/dict.c \ libifupdown/interface.c \ diff --git a/libifupdown/compar.c b/libifupdown/compar.c deleted file mode 100644 index 8705404..0000000 --- a/libifupdown/compar.c +++ /dev/null @@ -1,26 +0,0 @@ -/* - * libifupdown/compar.c - * Purpose: comparators - * - * Copyright (c) 2020 Maximilian Wilhelm - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * This software is provided 'as is' and without any warranty, express or - * implied. In no event shall the authors be liable for any damages arising - * from the use of this software. - */ - -#include -#include "libifupdown/compar.h" - -int -compar_str (const void *a, const void *b) -{ - const char *str_a = (const char *)a; - const char *str_b = (const char *)b; - - return strcmp (str_a, str_b); -} diff --git a/libifupdown/compar.h b/libifupdown/compar.h deleted file mode 100644 index 8652a26..0000000 --- a/libifupdown/compar.h +++ /dev/null @@ -1,21 +0,0 @@ -/* - * libifupdown/compar.h - * Purpose: Comparators - * - * Copyright (c) 2020 Maximilian Wilhelm - * - * Permission to use, copy, modify, and/or distribute this software for any - * purpose with or without fee is hereby granted, provided that the above - * copyright notice and this permission notice appear in all copies. - * - * This software is provided 'as is' and without any warranty, express or - * implied. In no event shall the authors be liable for any damages arising - * from the use of this software. - */ - -#ifndef LIBIFUPDOWN_COMPAR_H__GUARD -#define LIBIFUPDOWN_COMPAR_H__GUARD - -int compar_str (const void *a, const void *b); - -#endif diff --git a/libifupdown/dict.c b/libifupdown/dict.c index 3f5b1e1..4906f26 100644 --- a/libifupdown/dict.c +++ b/libifupdown/dict.c @@ -53,7 +53,7 @@ lif_dict_add(struct lif_dict *dict, const char *key, void *data) struct lif_dict_entry * lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, - int (*compar)(const void *, const void *)) + lif_dict_cmp_t compar) { struct lif_list *existing = lif_dict_find_all(dict, key); if (existing != NULL) diff --git a/libifupdown/dict.h b/libifupdown/dict.h index 2332c05..9a48ad2 100644 --- a/libifupdown/dict.h +++ b/libifupdown/dict.h @@ -35,10 +35,12 @@ struct lif_dict_entry { #define LIF_DICT_FOREACH_SAFE(iter, iter_next, dict) \ LIF_LIST_FOREACH_SAFE((iter), (iter_next), (dict)->list.head) +typedef int (*lif_dict_cmp_t)(const void *, const void *); + extern void lif_dict_init(struct lif_dict *dict); extern void lif_dict_fini(struct lif_dict *dict); extern struct lif_dict_entry *lif_dict_add(struct lif_dict *dict, const char *key, void *data); -extern struct lif_dict_entry *lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, int (*compar)(const void *, const void *)); +extern struct lif_dict_entry *lif_dict_add_once(struct lif_dict *dict, const char *key, void *data, lif_dict_cmp_t compar); extern struct lif_dict_entry *lif_dict_find(struct lif_dict *dict, const char *key); extern struct lif_list *lif_dict_find_all(struct lif_dict *dict, const char *key); extern void lif_dict_delete(struct lif_dict *dict, const char *key); diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 205c920..c451d47 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -19,7 +19,6 @@ #include "libifupdown/interface-file.h" #include "libifupdown/fgetline.h" #include "libifupdown/tokenize.h" -#include "libifupdown/compar.h" bool lif_interface_file_parse(struct lif_dict *collection, const char *filename) @@ -146,7 +145,8 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) { /* Copy word1 to not mangle *token */ char *addon = strndup(token, word_end - token); - lif_dict_add_once(&cur_iface->vars, "use", addon, compar_str); + if (lif_dict_add_once(&cur_iface->vars, "use", addon, (lif_dict_cmp_t) strcmp) == NULL) + free(addon); /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ if (!strcmp(addon, "dhcp")) From 37b5c372f39492b98784fd89c730270adffa40d2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 02:09:28 -0600 Subject: [PATCH 085/530] doc: add ifupdown-executor(7) manpage (closes #9) --- Makefile | 5 ++- doc/ifupdown-executor.scd | 84 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 doc/ifupdown-executor.scd diff --git a/Makefile b/Makefile index ccd016e..d4eab62 100644 --- a/Makefile +++ b/Makefile @@ -102,7 +102,10 @@ MANPAGES_8 = \ MANPAGES_5 = \ doc/interfaces.5 -MANPAGES = ${MANPAGES_5} ${MANPAGES_8} +MANPAGES_7 = \ + doc/ifupdown-executor.7 + +MANPAGES = ${MANPAGES_5} ${MANPAGES_7} ${MANPAGES_8} docs: ${MANPAGES} diff --git a/doc/ifupdown-executor.scd b/doc/ifupdown-executor.scd new file mode 100644 index 0000000..2064b4b --- /dev/null +++ b/doc/ifupdown-executor.scd @@ -0,0 +1,84 @@ +ifupdown-executor(7) + +# NAME + +*/usr/libexec/ifupdown-ng/program* - ifupdown executor protocol + +# DESCRIPTION + +The ifupdown executors are programs that are typically installed +into the ifupdown-ng executor path. They follow a specific +protocol documented in this man page. + +# PHASES + +Executors are run to react to seven different phases and are not +required to take any specific action. These phases are: + +*depend* + Called to determine if the executor wishes to change + the dependency graph. The executor should write a + space-delimited list of interface names it is dependent + upon to _stdout_. Those interface names will be merged + into the dependency graph. If an executor does not have + any dependencies, it may simply exit 0 without doing + anything. + +*pre-up* + Called before the interface is going to be brought up. + +*up* + Called when the interface is being brought up. + +*post-up* + Called after the interface was successfully brought up. + +*pre-down* + Called before the interface is going to be taken down. + +*down* + Called when the interface is being taken down. + +*post-down* + Called after the interface was successfully taken down. + +# ENVIRONMENT + +Executors are guaranteed to run with a core set of environment +variables: + +*IFACE* + The name of the interface being configured. + +*INTERFACES_FILE* + The path to the interfaces database file being used. + +*MODE* + Either _start_, _stop_ or _depend_ depending on phase. + This environment variable is present for compatibility + with legacy ifupdown scripts and should not be used in + ifupdown-ng executors. + +*PHASE* + The phase being executed. See the phases section for + more information about phases. + +*VERBOSE* + If present, verbose output is expected from the + executor. + +Additionally, the properties associated with an interface are +provided to executors. The keys are rewritten to begin with +IF_ and are capitalized with dashes converted to underscores. +For example, the property _bridge-ports_ will be rewritten as +_IF_BRIDGE_PORTS_. + +# SEE ALSO + +ifup(8)++ +ifdown(8)++ +interfaces(5) + +# AUTHORS + +Ariadne Conill From e4c3c4e06ef1232ae8e335406e1bf22b9f8b1201 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 02:14:42 -0600 Subject: [PATCH 086/530] mock dependency generator: add support for mock-depends property --- tests/executors/mock-dependency-generator | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/executors/mock-dependency-generator b/tests/executors/mock-dependency-generator index e413947..040035e 100755 --- a/tests/executors/mock-dependency-generator +++ b/tests/executors/mock-dependency-generator @@ -1,5 +1,7 @@ #!/bin/sh +[ -z "$IF_MOCK_DEPENDS" ] && IF_MOCK_DEPENDS="eth0 eth1 eth2 eth3 eth4" + case "$PHASE" in -depend) echo "eth0 eth1 eth2 eth3 eth4" ;; +depend) echo "$IF_MOCK_DEPENDS" ;; esac From edfb91c05fdc5b16a8df604b9e5d4fab0502b671 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 02:24:10 -0600 Subject: [PATCH 087/530] lifecycle: separate environment building into build_environment() --- libifupdown/lifecycle.c | 160 ++++++++++++++++++++-------------------- 1 file changed, 79 insertions(+), 81 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index ffd8c41..2728dd7 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -95,6 +95,81 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const return true; } +static void +build_environment(char **envp[], const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname, const char *phase, const char *mode) +{ + if (lifname == NULL) + lifname = iface->ifname; + + lif_environment_push(envp, "IFACE", lifname); + lif_environment_push(envp, "PHASE", phase); + lif_environment_push(envp, "MODE", mode); + + /* try to provide $METHOD for ifupdown1 scripts if we can */ + if (iface->is_dhcp) + lif_environment_push(envp, "METHOD", "dhcp"); + + if (opts->verbose) + lif_environment_push(envp, "VERBOSE", "1"); + + if (opts->interfaces_file) + lif_environment_push(envp, "INTERFACES_FILE", opts->interfaces_file); + + struct lif_node *iter; + bool did_address = false, did_gateway = false; + + LIF_DICT_FOREACH(iter, &iface->vars) + { + struct lif_dict_entry *entry = iter->data; + + if (!strcmp(entry->key, "address")) + { + if (did_address) + continue; + + struct lif_address *addr = entry->data; + char addrbuf[4096]; + + if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) + continue; + + lif_environment_push(envp, "IF_ADDRESS", addrbuf); + did_address = true; + + continue; + } + else if (!strcmp(entry->key, "gateway")) + { + if (did_gateway) + continue; + + did_gateway = true; + } + else if (!strcmp(entry->key, "requires")) + { + if (iface->is_bridge) + lif_environment_push(envp, "IF_BRIDGE_PORTS", (const char *) entry->data); + + if (iface->is_bond) + lif_environment_push(envp, "IF_BOND_SLAVES", (const char *) entry->data); + } + + char envkey[4096] = "IF_"; + strlcat(envkey, entry->key, sizeof envkey); + char *ep = envkey + 2; + + while (*ep++) + { + *ep = toupper(*ep); + + if (*ep == '-') + *ep = '_'; + } + + lif_environment_push(envp, envkey, (const char *) entry->data); + } +} + bool lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname) { @@ -106,15 +181,7 @@ lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_i char **envp = NULL; - lif_environment_push(&envp, "IFACE", lifname); - lif_environment_push(&envp, "PHASE", "depend"); - lif_environment_push(&envp, "MODE", "depend"); - - if (opts->verbose) - lif_environment_push(&envp, "VERBOSE", "1"); - - if (opts->interfaces_file) - lif_environment_push(&envp, "INTERFACES_FILE", opts->interfaces_file); + build_environment(&envp, opts, iface, lifname, "depend", "depend"); struct lif_dict_entry *entry = lif_dict_find(&iface->vars, "requires"); if (entry != NULL) @@ -143,6 +210,8 @@ lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_i else lif_dict_add(&iface->vars, "requires", strdup(final_deps)); + lif_environment_free(&envp); + return true; } @@ -151,78 +220,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac { char **envp = NULL; - lif_environment_push(&envp, "IFACE", lifname); - lif_environment_push(&envp, "PHASE", phase); - - /* try to provide $METHOD for ifupdown1 scripts if we can */ - if (iface->is_dhcp) - lif_environment_push(&envp, "METHOD", "dhcp"); - - /* same for $MODE */ - if (up) - lif_environment_push(&envp, "MODE", "start"); - else - lif_environment_push(&envp, "MODE", "stop"); - - if (opts->verbose) - lif_environment_push(&envp, "VERBOSE", "1"); - - if (opts->interfaces_file) - lif_environment_push(&envp, "INTERFACES_FILE", opts->interfaces_file); - - struct lif_node *iter; - bool did_address = false, did_gateway = false; - - LIF_DICT_FOREACH(iter, &iface->vars) - { - struct lif_dict_entry *entry = iter->data; - - if (!strcmp(entry->key, "address")) - { - if (did_address) - continue; - - struct lif_address *addr = entry->data; - char addrbuf[4096]; - - if (!lif_address_unparse(addr, addrbuf, sizeof addrbuf, true)) - continue; - - lif_environment_push(&envp, "IF_ADDRESS", addrbuf); - did_address = true; - - continue; - } - else if (!strcmp(entry->key, "gateway")) - { - if (did_gateway) - continue; - - did_gateway = true; - } - else if (!strcmp(entry->key, "requires")) - { - if (iface->is_bridge) - lif_environment_push(&envp, "IF_BRIDGE_PORTS", (const char *) entry->data); - - if (iface->is_bond) - lif_environment_push(&envp, "IF_BOND_SLAVES", (const char *) entry->data); - } - - char envkey[4096] = "IF_"; - strlcat(envkey, entry->key, sizeof envkey); - char *ep = envkey + 2; - - while (*ep++) - { - *ep = toupper(*ep); - - if (*ep == '-') - *ep = '_'; - } - - lif_environment_push(&envp, envkey, (const char *) entry->data); - } + build_environment(&envp, opts, iface, lifname, phase, up ? "start" : "stop"); if (!handle_executors_for_phase(opts, envp, iface)) goto handle_error; From 2be1fa5b0be2dcd7678c06751e83a01df8f987d2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 02:33:00 -0600 Subject: [PATCH 088/530] tests: add a set of more complicated dependency learning tests --- tests/fixtures/mock-dependency-generator-2.ifstate | 4 ++++ .../fixtures/mock-dependency-generator-2.interfaces | 7 +++++++ tests/ifdown_test | 13 ++++++++++++- tests/ifquery_test | 8 +++++++- tests/ifup_test | 11 ++++++++++- 5 files changed, 40 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/mock-dependency-generator-2.ifstate create mode 100644 tests/fixtures/mock-dependency-generator-2.interfaces diff --git a/tests/fixtures/mock-dependency-generator-2.ifstate b/tests/fixtures/mock-dependency-generator-2.ifstate new file mode 100644 index 0000000..6320c87 --- /dev/null +++ b/tests/fixtures/mock-dependency-generator-2.ifstate @@ -0,0 +1,4 @@ +eth0=eth0 +eth1=eth1 +bond0=bond0 +br0=br0 diff --git a/tests/fixtures/mock-dependency-generator-2.interfaces b/tests/fixtures/mock-dependency-generator-2.interfaces new file mode 100644 index 0000000..1f5708d --- /dev/null +++ b/tests/fixtures/mock-dependency-generator-2.interfaces @@ -0,0 +1,7 @@ +iface br0 + use mock-dependency-generator + mock-depends bond0 + +iface bond0 + use mock-dependency-generator + mock-depends eth0 eth1 diff --git a/tests/ifdown_test b/tests/ifdown_test index dfd4f77..6fbad68 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -15,7 +15,8 @@ tests_init \ alias_eth0_home \ alias_eth0_work \ bonded_bridge \ - learned_dependency + learned_dependency \ + learned_dependency_2 noargs_body() { atf_check -s exit:1 -e ignore ifdown -S/dev/null @@ -112,3 +113,13 @@ learned_dependency_body() { -E $EXECUTORS \ -i $FIXTURES/mock-dependency-generator.interfaces br0 } + +learned_dependency_2_body() { + atf_check -s exit:0 -o ignore \ + -e match:"bond0" \ + -e match:"eth0" \ + -e match:"eth1" \ + ifdown -n -S $FIXTURES/mock-dependency-generator-2.ifstate \ + -E $EXECUTORS \ + -i $FIXTURES/mock-dependency-generator-2.interfaces br0 +} diff --git a/tests/ifquery_test b/tests/ifquery_test index 91c1380..0fa5819 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -13,7 +13,8 @@ tests_init \ state_query_home \ state_query_work \ state_print \ - learned_dependency + learned_dependency \ + learned_dependency_2 noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -75,3 +76,8 @@ learned_dependency_body() { atf_check -s exit:0 -o match:"requires eth0 eth1 eth2 eth3 eth4" \ ifquery -E $EXECUTORS -i $FIXTURES/mock-dependency-generator.interfaces br0 } + +learned_dependency_2_body() { + atf_check -s exit:0 -o match:"requires bond0" \ + ifquery -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 +} diff --git a/tests/ifup_test b/tests/ifup_test index 1a2b4ea..18c4902 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -15,7 +15,8 @@ tests_init \ alias_eth0_home \ alias_eth0_work \ bonded_bridge \ - learned_dependency + learned_dependency \ + learned_dependency_2 noargs_body() { atf_check -s exit:1 -e ignore ifup -S/dev/null @@ -107,3 +108,11 @@ learned_dependency_body() { -e match:"eth4" \ ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/mock-dependency-generator.interfaces br0 } + +learned_dependency_2_body() { + atf_check -s exit:0 -o ignore \ + -e match:"bond0" \ + -e match:"eth0" \ + -e match:"eth1" \ + ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 +} From 2fecbfc7e9b34488ea7aa322803ea4ab15cd5db7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 02:37:14 -0600 Subject: [PATCH 089/530] tests: add tests for learned executors --- tests/ifdown_test | 11 ++++++++++- tests/ifquery_test | 8 +++++++- tests/ifup_test | 9 ++++++++- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/tests/ifdown_test b/tests/ifdown_test index 6fbad68..2d06865 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -16,7 +16,8 @@ tests_init \ alias_eth0_work \ bonded_bridge \ learned_dependency \ - learned_dependency_2 + learned_dependency_2 \ + learned_executor noargs_body() { atf_check -s exit:1 -e ignore ifdown -S/dev/null @@ -123,3 +124,11 @@ learned_dependency_2_body() { -E $EXECUTORS \ -i $FIXTURES/mock-dependency-generator-2.interfaces br0 } + +learned_executor_body() { + atf_check -s exit:0 -o ignore \ + -e match:"attempting to run mock executor" \ + ifdown -n -S $FIXTURES/mock-dependency-generator-2.ifstate \ + -E $EXECUTORS \ + -i $FIXTURES/mock-dependency-generator-2.interfaces br0 +} diff --git a/tests/ifquery_test b/tests/ifquery_test index 0fa5819..2a9426d 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -14,7 +14,8 @@ tests_init \ state_query_work \ state_print \ learned_dependency \ - learned_dependency_2 + learned_dependency_2 \ + learned_executor noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -81,3 +82,8 @@ learned_dependency_2_body() { atf_check -s exit:0 -o match:"requires bond0" \ ifquery -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 } + +learned_executor_body() { + atf_check -s exit:0 -o match:"use mock" \ + ifquery -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 +} diff --git a/tests/ifup_test b/tests/ifup_test index 18c4902..311be66 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -16,7 +16,8 @@ tests_init \ alias_eth0_work \ bonded_bridge \ learned_dependency \ - learned_dependency_2 + learned_dependency_2 \ + learned_executor noargs_body() { atf_check -s exit:1 -e ignore ifup -S/dev/null @@ -116,3 +117,9 @@ learned_dependency_2_body() { -e match:"eth1" \ ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 } + +learned_executor_body() { + atf_check -s exit:0 -o ignore \ + -e match:"attempting to run mock executor" \ + ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 +} From 91115edeee4bdc975a5588cf5fe3bea99014c160 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:01:49 -0600 Subject: [PATCH 090/530] ifupdown: use fcntl advisory locks to serialize state changes (closes #8) --- cmd/ifupdown.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++- doc/ifup.scd | 3 +++ 2 files changed, 68 insertions(+), 1 deletion(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 66ef4cb..50b9e33 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -18,6 +18,9 @@ #include #include #include +#include +#include +#include #include "libifupdown/libifupdown.h" #include "cmd/multicall.h" @@ -50,6 +53,7 @@ ifupdown_usage(void) fprintf(stderr, " -v, --verbose show what commands are being run\n"); fprintf(stderr, " -E, --executor-path PATH use PATH for executor directory\n"); fprintf(stderr, " -f, --force force (de)configuration\n"); + fprintf(stderr, " -L, --no-lock do not use a lockfile to serialize state changes\n"); exit(1); } @@ -110,6 +114,54 @@ change_auto_interfaces(struct lif_dict *collection, struct lif_dict *state, stru return true; } +int +acquire_state_lock(const char *state_path) +{ + char lockpath[4096] = {}; + + snprintf(lockpath, sizeof lockpath, "%s.lock", state_path); + + int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC); + if (fd < 0) + { + fprintf(stderr, "opening lockfile %s: %s\n", lockpath, strerror(errno)); + return -1; + } + + int flags = fcntl(fd, F_GETFD); + if (flags < 0) + { + close(fd); + + fprintf(stderr, "getting flags for lockfile: %s\n", strerror(errno)); + return -1; + } + + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) + { + close(fd); + + fprintf(stderr, "setting lockfile close-on-exec: %s\n", strerror(errno)); + return -1; + } + + struct flock fl = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET + }; + + if (fcntl(fd, F_SETLKW, &fl) == -1) + { + close(fd); + + fprintf(stderr, "locking lockfile: %s\n", strerror(errno)); + return -1; + } + + return fd; +} + int ifupdown_main(int argc, char *argv[]) { @@ -129,14 +181,17 @@ ifupdown_main(int argc, char *argv[]) {"verbose", no_argument, 0, 'v'}, {"executor-path", required_argument, 0, 'E'}, {"force", no_argument, 0, 'f'}, + {"no-lock", no_argument, 0, 'L'}, {NULL, 0, 0, 0} }; struct match_options match_opts = {}; char *state_file = STATE_FILE; + int lockfd = -1; + bool no_lock = false; for (;;) { - int c = getopt_long(argc, argv, "hVi:aI:X:S:nvE:", long_options, NULL); + int c = getopt_long(argc, argv, "hVi:aI:X:S:nvE:fL", long_options, NULL); if (c == -1) break; @@ -174,9 +229,15 @@ ifupdown_main(int argc, char *argv[]) break; case 'f': break; + case 'L': + no_lock = true; + break; } } + if (!exec_opts.mock && !no_lock) + lockfd = acquire_state_lock(state_file); + if (!lif_state_read_path(&state, state_file)) { fprintf(stderr, "%s: could not parse %s\n", argv0, state_file); @@ -245,6 +306,9 @@ ifupdown_main(int argc, char *argv[]) return EXIT_FAILURE; } + if (lockfd >= 0) + close(lockfd); + return EXIT_SUCCESS; } diff --git a/doc/ifup.scd b/doc/ifup.scd index f0a7ed3..c315e6d 100644 --- a/doc/ifup.scd +++ b/doc/ifup.scd @@ -42,6 +42,9 @@ configured in the configuration database. Include _PATTERN_ when matching against the config or state database. +*-L, --no-lock* + Do not use a lockfile to serialize state changes. + *-S, --state-file* _FILE_ Use _FILE_ as the state database. From 0ca8e42ee6563f48aa8f02a9cfbea70eec6bf4b4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:10:55 -0600 Subject: [PATCH 091/530] refactoring locking, make it per-interface to avoid deadlocks --- cmd/ifupdown.c | 133 ++++++++++++++++++++++-------------------- libifupdown/execute.h | 2 + 2 files changed, 72 insertions(+), 63 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 50b9e33..bf19a0e 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -34,6 +34,7 @@ static bool up; static struct lif_execute_opts exec_opts = { .executor_path = EXECUTOR_PATH, .interfaces_file = INTERFACES_FILE, + .state_file = STATE_FILE, }; void @@ -67,9 +68,65 @@ is_ifdown() return false; } +int +acquire_state_lock(const char *state_path, const char *lifname) +{ + if (exec_opts.mock || exec_opts.no_lock) + return -1; + + char lockpath[4096] = {}; + + snprintf(lockpath, sizeof lockpath, "%s.%s.lock", state_path, lifname); + + int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC); + if (fd < 0) + { + fprintf(stderr, "opening lockfile %s: %s\n", lockpath, strerror(errno)); + return -1; + } + + int flags = fcntl(fd, F_GETFD); + if (flags < 0) + { + close(fd); + + fprintf(stderr, "getting flags for lockfile: %s\n", strerror(errno)); + return -1; + } + + flags |= FD_CLOEXEC; + if (fcntl(fd, F_SETFD, flags) == -1) + { + close(fd); + + fprintf(stderr, "setting lockfile close-on-exec: %s\n", strerror(errno)); + return -1; + } + + struct flock fl = { + .l_type = F_WRLCK, + .l_whence = SEEK_SET + }; + + if (exec_opts.verbose) + fprintf(stderr, "ifupdown: acquiring lock on %s\n", lockpath); + + if (fcntl(fd, F_SETLKW, &fl) == -1) + { + close(fd); + + fprintf(stderr, "locking lockfile: %s\n", strerror(errno)); + return -1; + } + + return fd; +} + bool change_interface(struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *ifname) { + int lockfd = acquire_state_lock(exec_opts.state_file, ifname); + if (exec_opts.verbose) { fprintf(stderr, "%s: changing state of interface %s to '%s'\n", @@ -80,9 +137,16 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc { fprintf(stderr, "%s: failed to change interface %s state to '%s'\n", argv0, ifname, up ? "up" : "down"); + + if (lockfd != -1) + close(lockfd); + return false; } + if (lockfd != -1) + close(lockfd); + return true; } @@ -114,54 +178,6 @@ change_auto_interfaces(struct lif_dict *collection, struct lif_dict *state, stru return true; } -int -acquire_state_lock(const char *state_path) -{ - char lockpath[4096] = {}; - - snprintf(lockpath, sizeof lockpath, "%s.lock", state_path); - - int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC); - if (fd < 0) - { - fprintf(stderr, "opening lockfile %s: %s\n", lockpath, strerror(errno)); - return -1; - } - - int flags = fcntl(fd, F_GETFD); - if (flags < 0) - { - close(fd); - - fprintf(stderr, "getting flags for lockfile: %s\n", strerror(errno)); - return -1; - } - - flags |= FD_CLOEXEC; - if (fcntl(fd, F_SETFD, flags) == -1) - { - close(fd); - - fprintf(stderr, "setting lockfile close-on-exec: %s\n", strerror(errno)); - return -1; - } - - struct flock fl = { - .l_type = F_WRLCK, - .l_whence = SEEK_SET - }; - - if (fcntl(fd, F_SETLKW, &fl) == -1) - { - close(fd); - - fprintf(stderr, "locking lockfile: %s\n", strerror(errno)); - return -1; - } - - return fd; -} - int ifupdown_main(int argc, char *argv[]) { @@ -185,9 +201,6 @@ ifupdown_main(int argc, char *argv[]) {NULL, 0, 0, 0} }; struct match_options match_opts = {}; - char *state_file = STATE_FILE; - int lockfd = -1; - bool no_lock = false; for (;;) { @@ -215,7 +228,7 @@ ifupdown_main(int argc, char *argv[]) match_opts.exclude_pattern = optarg; break; case 'S': - state_file = optarg; + exec_opts.state_file = optarg; break; case 'n': exec_opts.mock = true; @@ -230,17 +243,14 @@ ifupdown_main(int argc, char *argv[]) case 'f': break; case 'L': - no_lock = true; + exec_opts.no_lock = true; break; } } - if (!exec_opts.mock && !no_lock) - lockfd = acquire_state_lock(state_file); - - if (!lif_state_read_path(&state, state_file)) + if (!lif_state_read_path(&state, exec_opts.state_file)) { - fprintf(stderr, "%s: could not parse %s\n", argv0, state_file); + fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.state_file); return EXIT_FAILURE; } @@ -300,15 +310,12 @@ ifupdown_main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!exec_opts.mock && !lif_state_write_path(&state, state_file)) + if (!exec_opts.mock && !lif_state_write_path(&state, exec_opts.state_file)) { - fprintf(stderr, "%s: could not update %s\n", argv0, state_file); + fprintf(stderr, "%s: could not update %s\n", argv0, exec_opts.state_file); return EXIT_FAILURE; } - if (lockfd >= 0) - close(lockfd); - return EXIT_SUCCESS; } diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 3fbde45..625171d 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -22,8 +22,10 @@ struct lif_execute_opts { bool verbose; bool mock; + bool no_lock; const char *executor_path; const char *interfaces_file; + const char *state_file; }; extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); From c71c01862d28843126940250764fcd01828783dd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:13:34 -0600 Subject: [PATCH 092/530] ifupdown: make the locking errors more useful --- cmd/ifupdown.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index bf19a0e..cf6fb02 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -109,14 +109,14 @@ acquire_state_lock(const char *state_path, const char *lifname) }; if (exec_opts.verbose) - fprintf(stderr, "ifupdown: acquiring lock on %s\n", lockpath); + fprintf(stderr, "%s: acquiring lock on %s\n", argv0, lockpath); - if (fcntl(fd, F_SETLKW, &fl) == -1) + if (fcntl(fd, F_SETLK, &fl) == -1) { close(fd); fprintf(stderr, "locking lockfile: %s\n", strerror(errno)); - return -1; + return -2; } return fd; @@ -127,6 +127,12 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc { int lockfd = acquire_state_lock(exec_opts.state_file, ifname); + if (lockfd == -2) + { + fprintf(stderr, "%s: could not acquire exclusive lock for %s\n", argv0, ifname); + return false; + } + if (exec_opts.verbose) { fprintf(stderr, "%s: changing state of interface %s to '%s'\n", From ef3bdd79da46a95ccaa02eafbc9160f014c1cfa4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:17:12 -0600 Subject: [PATCH 093/530] clean up locking-related errors further --- cmd/ifupdown.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index cf6fb02..37536ab 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -81,8 +81,8 @@ acquire_state_lock(const char *state_path, const char *lifname) int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC); if (fd < 0) { - fprintf(stderr, "opening lockfile %s: %s\n", lockpath, strerror(errno)); - return -1; + fprintf(stderr, "%s: while opening lockfile %s: %s\n", argv0, lockpath, strerror(errno)); + return -2; } int flags = fcntl(fd, F_GETFD); @@ -90,8 +90,8 @@ acquire_state_lock(const char *state_path, const char *lifname) { close(fd); - fprintf(stderr, "getting flags for lockfile: %s\n", strerror(errno)); - return -1; + fprintf(stderr, "%s: while getting flags for lockfile: %s\n", argv0, strerror(errno)); + return -2; } flags |= FD_CLOEXEC; @@ -99,8 +99,8 @@ acquire_state_lock(const char *state_path, const char *lifname) { close(fd); - fprintf(stderr, "setting lockfile close-on-exec: %s\n", strerror(errno)); - return -1; + fprintf(stderr, "%s: while setting lockfile close-on-exec: %s\n", argv0, strerror(errno)); + return -2; } struct flock fl = { @@ -115,7 +115,8 @@ acquire_state_lock(const char *state_path, const char *lifname) { close(fd); - fprintf(stderr, "locking lockfile: %s\n", strerror(errno)); + if (exec_opts.verbose) + fprintf(stderr, "%s: while locking lockfile: %s\n", argv0, strerror(errno)); return -2; } @@ -129,7 +130,7 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc if (lockfd == -2) { - fprintf(stderr, "%s: could not acquire exclusive lock for %s\n", argv0, ifname); + fprintf(stderr, "%s: could not acquire exclusive lock for %s: %s\n", argv0, ifname, strerror(errno)); return false; } From 58bc969bbb9fe1a1811c7f911be81ff65d774bec Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:18:12 -0600 Subject: [PATCH 094/530] ifupdown: only show granular locking errors in verbose mode --- cmd/ifupdown.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 37536ab..94259c1 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -81,7 +81,8 @@ acquire_state_lock(const char *state_path, const char *lifname) int fd = open(lockpath, O_CREAT | O_WRONLY | O_TRUNC); if (fd < 0) { - fprintf(stderr, "%s: while opening lockfile %s: %s\n", argv0, lockpath, strerror(errno)); + if (exec_opts.verbose) + fprintf(stderr, "%s: while opening lockfile %s: %s\n", argv0, lockpath, strerror(errno)); return -2; } @@ -90,7 +91,8 @@ acquire_state_lock(const char *state_path, const char *lifname) { close(fd); - fprintf(stderr, "%s: while getting flags for lockfile: %s\n", argv0, strerror(errno)); + if (exec_opts.verbose) + fprintf(stderr, "%s: while getting flags for lockfile: %s\n", argv0, strerror(errno)); return -2; } @@ -99,7 +101,8 @@ acquire_state_lock(const char *state_path, const char *lifname) { close(fd); - fprintf(stderr, "%s: while setting lockfile close-on-exec: %s\n", argv0, strerror(errno)); + if (exec_opts.verbose) + fprintf(stderr, "%s: while setting lockfile close-on-exec: %s\n", argv0, strerror(errno)); return -2; } From 7a4c16c66585aa3e80ade5876da8a7ad7b40d975 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:19:19 -0600 Subject: [PATCH 095/530] ifupdown-ng 0.5.0. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d4eab62..3b9325b 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.4.2 +PACKAGE_VERSION := 0.5.0 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From ed56d2b33b022fe141da8ed2700aea8671af46bd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 29 Jul 2020 03:51:57 -0600 Subject: [PATCH 096/530] build: actually install ifupdown-executor.7 --- Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Makefile b/Makefile index 3b9325b..08bc891 100644 --- a/Makefile +++ b/Makefile @@ -114,6 +114,10 @@ install_docs: docs target=$$(basename $$i); \ install -D -m644 $$i ${DESTDIR}/usr/share/man/man5/$$target; \ done + for i in ${MANPAGES_7}; do \ + target=$$(basename $$i); \ + install -D -m644 $$i ${DESTDIR}/usr/share/man/man7/$$target; \ + done for i in ${MANPAGES_8}; do \ target=$$(basename $$i); \ install -D -m644 $$i ${DESTDIR}/usr/share/man/man8/$$target; \ From 1964a99e5d54d0242a50961d3bdfe9660e9352a4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 31 Jul 2020 17:12:13 -0600 Subject: [PATCH 097/530] lifecycle: don't insert a requires entry if it would be empty --- libifupdown/lifecycle.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 2728dd7..dc31474 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -207,7 +207,7 @@ lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_i free(entry->data); entry->data = strdup(final_deps); } - else + else if (*final_deps) lif_dict_add(&iface->vars, "requires", strdup(final_deps)); lif_environment_free(&envp); From 0eb25f1d62a910aa7e2e2b871f9eee659557e7a7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 11:32:34 -0600 Subject: [PATCH 098/530] interface file: simplify scanning iface directives for relevant keywords --- libifupdown/interface-file.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index c451d47..4d6f63a 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -82,18 +82,16 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) * or "inet dhcp" or such to designate hints. lets pick up * those hints here. */ - char *inet_type = lif_next_token(&bufp); - if (!*inet_type) - continue; - - char *hint = lif_next_token(&bufp); - if (!*hint) - continue; - - if (!strcmp(hint, "dhcp")) + char *token = lif_next_token(&bufp); + while (*token) { - cur_iface->is_dhcp = true; - lif_dict_add(&cur_iface->vars, "use", strdup("dhcp")); + if (!strcmp(token, "dhcp")) + { + cur_iface->is_dhcp = true; + lif_dict_add(&cur_iface->vars, "use", strdup("dhcp")); + } + + token = lif_next_token(&bufp); } } else if (!strcmp(token, "use")) From 3d5ca9050e009533dd63f893131a8b4f955f72f4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 11:46:10 -0600 Subject: [PATCH 099/530] interface: add lif_interface_collection_inherit() (ref #2) --- libifupdown/interface.c | 30 ++++++++++++++++++++++++++++++ libifupdown/interface.h | 1 + 2 files changed, 31 insertions(+) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 87f6c97..8eab120 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -214,3 +214,33 @@ lif_interface_collection_delete(struct lif_dict *collection, struct lif_interfac lif_dict_delete_entry(collection, entry); } + +bool +lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dict *collection, const char *ifname) +{ + struct lif_interface *parent = lif_interface_collection_find(collection, ifname); + + if (parent == NULL) + return false; + + /* copy the variables */ + struct lif_node *iter; + LIF_DICT_FOREACH(iter, &parent->vars) + { + struct lif_dict_entry *entry = iter->data; + + if (!strcmp(entry->key, "address")) + { + struct lif_address *addr = calloc(1, sizeof *addr); + struct lif_address *other_addr = entry->data; + + memcpy(addr, other_addr, sizeof *addr); + + lif_dict_add(&interface->vars, entry->key, addr); + } + else + lif_dict_add(&interface->vars, entry->key, strdup(entry->data)); + } + + return true; +} diff --git a/libifupdown/interface.h b/libifupdown/interface.h index 9ef9387..045f848 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -73,6 +73,7 @@ extern void lif_interface_collection_init(struct lif_dict *collection); extern void lif_interface_collection_fini(struct lif_dict *collection); extern struct lif_interface *lif_interface_collection_find(struct lif_dict *collection, const char *ifname); extern struct lif_interface *lif_interface_collection_upsert(struct lif_dict *collection, struct lif_interface *interface); +extern bool lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dict *collection, const char *ifname); extern void lif_interface_collection_delete(struct lif_dict *collection, struct lif_interface *interface); #endif From 6c7fa2919dbbced9fe894ef1beba837313ff66ef Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 11:46:56 -0600 Subject: [PATCH 100/530] interface-file: add support for inherit/inherits keyword --- libifupdown/interface-file.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 4d6f63a..74d74c1 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -90,6 +90,22 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) cur_iface->is_dhcp = true; lif_dict_add(&cur_iface->vars, "use", strdup("dhcp")); } + else if (!strcmp(token, "inherits")) + { + token = lif_next_token(&bufp); + + if (!*token) + { + fprintf(stderr, "%s: inherits without interface\n", filename); + goto parse_error; + } + + if (!lif_interface_collection_inherit(cur_iface, collection, token)) + { + fprintf(stderr, "%s: could not inherit %s\n", filename, token); + goto parse_error; + } + } token = lif_next_token(&bufp); } @@ -121,6 +137,22 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) lif_dict_add(&cur_iface->vars, token, strdup(executor)); } + else if (!strcmp(token, "inherit")) + { + token = lif_next_token(&bufp); + + if (!*token) + { + fprintf(stderr, "%s: inherits without interface\n", filename); + goto parse_error; + } + + if (!lif_interface_collection_inherit(cur_iface, collection, token)) + { + fprintf(stderr, "%s: could not inherit %s\n", filename, token); + goto parse_error; + } + } else if (!strcmp(token, "address")) { char *addr = lif_next_token(&bufp); From 6728d2febe46961c75b0520081966ecf77879987 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 11:48:22 -0600 Subject: [PATCH 101/530] interface: add inherit property when inheriting --- libifupdown/interface.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 8eab120..3dca25a 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -223,6 +223,8 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic if (parent == NULL) return false; + lif_dict_add(&interface->vars, "inherit", strdup(ifname)); + /* copy the variables */ struct lif_node *iter; LIF_DICT_FOREACH(iter, &parent->vars) From 0d6b9d5d1708dc3fbf89cf432c36c99dd6ef61cb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 11:48:55 -0600 Subject: [PATCH 102/530] build: fix "ln: file exists" that pops up sometimes --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 08bc891..91058c0 100644 --- a/Makefile +++ b/Makefile @@ -66,7 +66,7 @@ LIBS += ${LIBBSD_LIBS} all: libifupdown.a ${MULTICALL} ${CMDS} ${CMDS}: ${MULTICALL} - ln -s ifupdown $@ + ln -sf ifupdown $@ ${MULTICALL}: ${LIBS} ${CMD_OBJ} ${CC} -o $@ ${CMD_OBJ} ${LIBS} From df2519c1ec39c07a587e12b0e4d3c0c69dbf08ae Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 11:59:36 -0600 Subject: [PATCH 103/530] dict: cleanups --- libifupdown/dict.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libifupdown/dict.c b/libifupdown/dict.c index 4906f26..cb725a6 100644 --- a/libifupdown/dict.c +++ b/libifupdown/dict.c @@ -104,7 +104,7 @@ lif_dict_find(struct lif_dict *dict, const char *key) struct lif_list * lif_dict_find_all(struct lif_dict *dict, const char *key) { - struct lif_list *entries = calloc(1, sizeof(struct lif_list)); + struct lif_list *entries = calloc(1, sizeof *entries); struct lif_node *iter; LIF_LIST_FOREACH(iter, dict->list.head) @@ -112,7 +112,7 @@ lif_dict_find_all(struct lif_dict *dict, const char *key) struct lif_dict_entry *entry = iter->data; if (!strcmp(entry->key, key)) { - struct lif_node *new = calloc(1, sizeof(struct lif_node)); + struct lif_node *new = calloc(1, sizeof *new); lif_node_insert_tail(new, entry->data, entries); } } From 8615cf62efb1a631b40fcb1f931d939dde363acb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:01:06 -0600 Subject: [PATCH 104/530] interface: properly sync parent-child state when inheriting --- libifupdown/interface.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 3dca25a..66b1d02 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -224,6 +224,10 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic return false; lif_dict_add(&interface->vars, "inherit", strdup(ifname)); + interface->is_static = parent->is_static; + interface->is_dhcp = parent->is_dhcp; + interface->is_bond = parent->is_bond; + interface->is_bridge = parent->is_bridge; /* copy the variables */ struct lif_node *iter; @@ -241,7 +245,12 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic lif_dict_add(&interface->vars, entry->key, addr); } else - lif_dict_add(&interface->vars, entry->key, strdup(entry->data)); + { + char *value = strdup(entry->data); + + if (lif_dict_add_once(&interface->vars, entry->key, value, (lif_dict_cmp_t) strcmp) == NULL) + free(value); + } } return true; From 49dd8942f2e12c495477ff108107b142aa6839d0 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:06:39 -0600 Subject: [PATCH 105/530] tests: add inheritance tests we only need to test ifquery, as this is just a merge operation. --- tests/fixtures/inheritance.interfaces | 10 ++++++++++ tests/ifquery_test | 20 +++++++++++++++++++- 2 files changed, 29 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/inheritance.interfaces diff --git a/tests/fixtures/inheritance.interfaces b/tests/fixtures/inheritance.interfaces new file mode 100644 index 0000000..8b5f487 --- /dev/null +++ b/tests/fixtures/inheritance.interfaces @@ -0,0 +1,10 @@ +iface base0 + address 203.0.113.2/24 + address 2001:db8:1000:2::2/64 + +iface inherit0 inherits base0 + address 203.0.113.3/24 + +iface inherit1 + inherit base0 + address 203.0.113.4/24 diff --git a/tests/ifquery_test b/tests/ifquery_test index 2a9426d..68fa518 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -15,7 +15,9 @@ tests_init \ state_print \ learned_dependency \ learned_dependency_2 \ - learned_executor + learned_executor \ + inheritance_0 \ + inheritance_1 noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -87,3 +89,19 @@ learned_executor_body() { atf_check -s exit:0 -o match:"use mock" \ ifquery -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 } + +inheritance_0_body() { + atf_check -s exit:0 -o match:"inherit base0" \ + -o match:"address 203.0.113.2/24" \ + -o match:"address 203.0.113.3/24" \ + -o match:"address 2001:db8:1000:2::2/64" \ + ifquery -E $EXECUTORS -i $FIXTURES/inheritance.interfaces inherit0 +} + +inheritance_1_body() { + atf_check -s exit:0 -o match:"inherit base0" \ + -o match:"address 203.0.113.2/24" \ + -o match:"address 203.0.113.4/24" \ + -o match:"address 2001:db8:1000:2::2/64" \ + ifquery -E $EXECUTORS -i $FIXTURES/inheritance.interfaces inherit1 +} From 369f3ff3c227a1d9da5c54fec1095c51dc36d462 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:08:32 -0600 Subject: [PATCH 106/530] interfaces.5: document inherit option --- doc/interfaces.scd | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 3719e46..ce021e8 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -69,6 +69,10 @@ the system will only respond to certain keywords by default: Interfaces associated with the parent are taken down at the same time as the parent. +*inherit* _interface_ + Designates that the parent interface should inherit + configuration data from _interface_. + *use* _option_ Designates that an option should be used. See _OPTIONS_ section for more information on options. From 8b00727370af542157882d8324626a128a6bbbe4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:09:57 -0600 Subject: [PATCH 107/530] interfaces.5: note that we are compatible with legacy ifupdown1 syntax --- doc/interfaces.scd | 3 +++ 1 file changed, 3 insertions(+) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index ce021e8..262a7a3 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -10,6 +10,9 @@ The */etc/network/interfaces* file is used to specify how network interfaces are configured. The file is processed by *ifquery*(8), *ifup*(8) and *ifdown*(8) to introspect and change system state. +In most cases, syntax from legacy implementations is supported as +well, but that syntax is not discussed here. + # FILE SYNTAX The interface configuration database is composed of a series of From 66e6a09bbedbfa7fbc34588d7edfe00e952970ae Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:11:06 -0600 Subject: [PATCH 108/530] ifupdown-ng 0.6.0. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 91058c0..95d937b 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.5.0 +PACKAGE_VERSION := 0.6.0 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From 049af8b9fb717461da4dc50dcf7542616d2fcbc5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:29:31 -0600 Subject: [PATCH 109/530] interface: if an interface name contains a period, treat it as a vlan device --- libifupdown/interface.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 66b1d02..8841c13 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -62,7 +62,11 @@ lif_interface_init(struct lif_interface *interface, const char *ifname) memset(interface, '\0', sizeof *interface); interface->ifname = strdup(ifname); - lif_dict_add(&interface->vars, "use", strdup("link")); + + if (strchr(ifname, '.') == NULL) + lif_dict_add(&interface->vars, "use", strdup("link")); + else + lif_dict_add(&interface->vars, "use", strdup("vlan")); } bool From 072c1ea1486ec6e02dd78b39e2f1b4a60fbc2e11 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:36:38 -0600 Subject: [PATCH 110/530] ifquery: build full dependency tree when in dot mode --- cmd/ifquery.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index eb01cf5..8b68b15 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -65,6 +65,9 @@ print_interface(struct lif_interface *iface) void print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, struct lif_interface *parent) { + if (!lif_lifecycle_query_dependents(&exec_opts, iface, iface->ifname)) + return; + if (iface->is_up) return; From b27caaedf6c7e276645ea49fc8c518072f85b3ae Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 12:38:05 -0600 Subject: [PATCH 111/530] tests: add mock vlan executor and vlan fixture --- tests/executors/vlan | 7 +++++++ tests/fixtures/vlan.interfaces | 2 ++ 2 files changed, 9 insertions(+) create mode 100755 tests/executors/vlan create mode 100644 tests/fixtures/vlan.interfaces diff --git a/tests/executors/vlan b/tests/executors/vlan new file mode 100755 index 0000000..ba37599 --- /dev/null +++ b/tests/executors/vlan @@ -0,0 +1,7 @@ +#!/bin/sh +case "$PHASE" in +depend) + RAW_DEVICE="${IFACE%.*}" + echo "$RAW_DEVICE" + ;; +esac diff --git a/tests/fixtures/vlan.interfaces b/tests/fixtures/vlan.interfaces new file mode 100644 index 0000000..398c848 --- /dev/null +++ b/tests/fixtures/vlan.interfaces @@ -0,0 +1,2 @@ +iface eth0.8 + address 2001:db8:1000:2::2/64 From 0de4a3f6f925237293e0427147e8dba9c635eb00 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 13:08:30 -0600 Subject: [PATCH 112/530] tests: add ifup/ifdown/ifquery tests for vlans --- tests/fixtures/vlan.ifstate | 2 ++ tests/ifdown_test | 10 +++++++++- tests/ifquery_test | 9 ++++++++- tests/ifup_test | 10 +++++++++- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/fixtures/vlan.ifstate diff --git a/tests/fixtures/vlan.ifstate b/tests/fixtures/vlan.ifstate new file mode 100644 index 0000000..e360c74 --- /dev/null +++ b/tests/fixtures/vlan.ifstate @@ -0,0 +1,2 @@ +eth0=eth0 +eth0.8=eth0.8 diff --git a/tests/ifdown_test b/tests/ifdown_test index 2d06865..e54d148 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -17,7 +17,8 @@ tests_init \ bonded_bridge \ learned_dependency \ learned_dependency_2 \ - learned_executor + learned_executor \ + implicit_vlan noargs_body() { atf_check -s exit:1 -e ignore ifdown -S/dev/null @@ -132,3 +133,10 @@ learned_executor_body() { -E $EXECUTORS \ -i $FIXTURES/mock-dependency-generator-2.interfaces br0 } + +implicit_vlan_body() { + atf_check -s exit:0 -o ignore \ + -e match:"attempting to run vlan executor" \ + -e match:"attempting to run link executor" \ + ifdown -n -S $FIXTURES/vlan.ifstate -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 +} diff --git a/tests/ifquery_test b/tests/ifquery_test index 68fa518..64e8718 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -17,7 +17,8 @@ tests_init \ learned_dependency_2 \ learned_executor \ inheritance_0 \ - inheritance_1 + inheritance_1 \ + implicit_vlan noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -105,3 +106,9 @@ inheritance_1_body() { -o match:"address 2001:db8:1000:2::2/64" \ ifquery -E $EXECUTORS -i $FIXTURES/inheritance.interfaces inherit1 } + +implicit_vlan_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + -o match:"use vlan" \ + ifquery -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 +} diff --git a/tests/ifup_test b/tests/ifup_test index 311be66..594ab11 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -17,7 +17,8 @@ tests_init \ bonded_bridge \ learned_dependency \ learned_dependency_2 \ - learned_executor + learned_executor \ + implicit_vlan noargs_body() { atf_check -s exit:1 -e ignore ifup -S/dev/null @@ -123,3 +124,10 @@ learned_executor_body() { -e match:"attempting to run mock executor" \ ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/mock-dependency-generator-2.interfaces br0 } + +implicit_vlan_body() { + atf_check -s exit:0 -o ignore \ + -e match:"attempting to run vlan executor" \ + -e match:"attempting to run link executor" \ + ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 +} From d9fd545ad11077790c5acd055331cfeb60ad6e96 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 13:14:06 -0600 Subject: [PATCH 113/530] build: add infrastructure for installing stub executors this enables the split setup with ifupdown1 addons and core executors as will be implemented in Alpine 3.13. --- Makefile | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 95d937b..260d8d6 100644 --- a/Makefile +++ b/Makefile @@ -49,13 +49,19 @@ IFQUERY_OBJ = ${IFQUERY_SRC:.c=.o} IFUPDOWN_SRC = cmd/ifupdown.c IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} -EXECUTOR_SCRIPTS ?= \ +EXECUTOR_SCRIPTS_CORE ?= \ dhcp \ ipv6-ra \ static \ link \ + +EXECUTOR_SCRIPTS_OPT ?= \ bridge +EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} + +EXECUTOR_SCRIPTS_STUB ?= + CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} CMDS = ifup ifdown ifquery @@ -90,6 +96,9 @@ install: all for i in ${EXECUTOR_SCRIPTS}; do \ install -D -m755 executor-scripts/${LAYOUT}/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \ done + for i in ${EXECUTOR_SCRIPTS_STUB}; do \ + install -D -m755 executor-scripts/stub/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \ + done .scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8: ${SCDOC} < $< > $@ From 5bf6c84464f5328f6bd5e587da45d26384b664fa Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 13:18:36 -0600 Subject: [PATCH 114/530] add some helper stubs for split ifupdown1-addon setups --- executor-scripts/stub/bond | 5 +++++ executor-scripts/stub/bridge | 4 ++++ executor-scripts/stub/vlan | 7 +++++++ 3 files changed, 16 insertions(+) create mode 100755 executor-scripts/stub/bond create mode 100755 executor-scripts/stub/bridge create mode 100755 executor-scripts/stub/vlan diff --git a/executor-scripts/stub/bond b/executor-scripts/stub/bond new file mode 100755 index 0000000..0548543 --- /dev/null +++ b/executor-scripts/stub/bond @@ -0,0 +1,5 @@ +#!/bin/sh +[ -z "$IF_BOND_MEMBERS" ] && IF_BOND_MEMBERS="$IF_BOND_SLAVES" +case "$PHASE" in +depend) echo "$IF_BOND_MEMBERS" ;; +esac diff --git a/executor-scripts/stub/bridge b/executor-scripts/stub/bridge new file mode 100755 index 0000000..ee1a442 --- /dev/null +++ b/executor-scripts/stub/bridge @@ -0,0 +1,4 @@ +#!/bin/sh +case "$PHASE" in +depend) echo "$IF_BRIDGE_PORTS" ;; +esac diff --git a/executor-scripts/stub/vlan b/executor-scripts/stub/vlan new file mode 100755 index 0000000..ba37599 --- /dev/null +++ b/executor-scripts/stub/vlan @@ -0,0 +1,7 @@ +#!/bin/sh +case "$PHASE" in +depend) + RAW_DEVICE="${IFACE%.*}" + echo "$RAW_DEVICE" + ;; +esac From 3205a89840360757b15e0030151a95ac619bf2a4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 4 Aug 2020 13:20:26 -0600 Subject: [PATCH 115/530] ifupdown-ng 0.7.0. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 260d8d6..d565c49 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.6.0 +PACKAGE_VERSION := 0.7.0 PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new From b87a0df83d5da4cdc2782c6f544f0026b61c8488 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Tue, 11 Aug 2020 09:56:22 -0500 Subject: [PATCH 116/530] Makefile: Update bug reporting URL It should point to the GitHub organisation for ifupdown-ng. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index d565c49..efed6db 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng PACKAGE_VERSION := 0.7.0 -PACKAGE_BUGREPORT := https://github.com/kaniini/ifupdown-ng/issues/new +PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new INTERFACES_FILE := /etc/network/interfaces From ff65bd53b56a3d1f0580fe672f85bdb584e69449 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Tue, 11 Aug 2020 10:21:02 -0500 Subject: [PATCH 117/530] Makefile: Ensure built libs are removed in `clean` This commit ensures that `${LIBIFUPDOWN_LIB}` is removed when `make clean` is run. --- Makefile | 1 + 1 file changed, 1 insertion(+) diff --git a/Makefile b/Makefile index efed6db..98d4328 100644 --- a/Makefile +++ b/Makefile @@ -82,6 +82,7 @@ libifupdown.a: ${LIBIFUPDOWN_OBJ} clean: rm -f ${LIBIFUPDOWN_OBJ} ${CMD_OBJ} + rm -f ${LIBIFUPDOWN_LIB} rm -f ${CMDS} ${MULTICALL} rm -f ${MANPAGES} From f96a74f232ade2b8fc5ec6b0a004da9f70074cee Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 20:40:22 -0600 Subject: [PATCH 118/530] makefile: clarify some things --- Makefile | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Makefile b/Makefile index 98d4328..6ce44b3 100644 --- a/Makefile +++ b/Makefile @@ -66,18 +66,18 @@ CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} CMDS = ifup ifdown ifquery -LIBS = ${LIBIFUPDOWN_LIB} -LIBS += ${LIBBSD_LIBS} +TARGET_LIBS = ${LIBIFUPDOWN_LIB} +LIBS += ${TARGET_LIBS} ${LIBBSD_LIBS} -all: libifupdown.a ${MULTICALL} ${CMDS} +all: ${MULTICALL} ${CMDS} ${CMDS}: ${MULTICALL} ln -sf ifupdown $@ -${MULTICALL}: ${LIBS} ${CMD_OBJ} +${MULTICALL}: ${TARGET_LIBS} ${CMD_OBJ} ${CC} -o $@ ${CMD_OBJ} ${LIBS} -libifupdown.a: ${LIBIFUPDOWN_OBJ} +${LIBIFUPDOWN_LIB}: ${LIBIFUPDOWN_OBJ} ${AR} -rcs $@ ${LIBIFUPDOWN_OBJ} clean: @@ -86,7 +86,7 @@ clean: rm -f ${CMDS} ${MULTICALL} rm -f ${MANPAGES} -check: libifupdown.a ${CMDS} +check: ${LIBIFUPDOWN_LIB} ${CMDS} kyua test install: all From ebd04cafda2b774a393d49ea1fc61190f3efaddb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 20:44:04 -0600 Subject: [PATCH 119/530] commands: refactor applet_usage functions to take a status code (ref #16) --- cmd/ifquery.c | 10 +++++----- cmd/ifupdown.c | 8 ++++---- cmd/multicall.c | 10 +++++----- cmd/multicall.h | 2 +- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 8b68b15..2778dea 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -164,7 +164,7 @@ print_interface_property(struct lif_interface *iface, const char *property) } void -ifquery_usage(void) +ifquery_usage(int status) { fprintf(stderr, "usage: ifquery [options] \n"); fprintf(stderr, " ifquery [options] --list\n"); @@ -183,7 +183,7 @@ ifquery_usage(void) fprintf(stderr, " -D, --dot generate a dependency graph\n"); fprintf(stderr, " -p, --property PROPERTY print values of properties matching PROPERTY\n"); - exit(1); + exit(status); } struct match_options { @@ -289,7 +289,7 @@ ifquery_main(int argc, char *argv[]) switch (c) { case 'h': - ifquery_usage(); + ifquery_usage(EXIT_SUCCESS); break; case 'V': lif_common_version(); @@ -344,7 +344,7 @@ ifquery_main(int argc, char *argv[]) /* --list --state is not allowed */ if (listing && listing_stat) - ifquery_usage(); + ifquery_usage(EXIT_FAILURE); if (listing) { @@ -358,7 +358,7 @@ ifquery_main(int argc, char *argv[]) } if (optind >= argc) - ifquery_usage(); + ifquery_usage(EXIT_FAILURE); int idx = optind; for (; idx < argc; idx++) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 94259c1..9a9aada 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -38,7 +38,7 @@ static struct lif_execute_opts exec_opts = { }; void -ifupdown_usage(void) +ifupdown_usage(int status) { fprintf(stderr, "usage: %s [options] \n", argv0); @@ -56,7 +56,7 @@ ifupdown_usage(void) fprintf(stderr, " -f, --force force (de)configuration\n"); fprintf(stderr, " -L, --no-lock do not use a lockfile to serialize state changes\n"); - exit(1); + exit(status); } bool @@ -220,7 +220,7 @@ ifupdown_main(int argc, char *argv[]) switch (c) { case 'h': - ifupdown_usage(); + ifupdown_usage(EXIT_SUCCESS); break; case 'V': lif_common_version(); @@ -284,7 +284,7 @@ ifupdown_main(int argc, char *argv[]) return EXIT_SUCCESS; } else if (optind >= argc) - ifupdown_usage(); + ifupdown_usage(EXIT_FAILURE); int idx = optind; for (; idx < argc; idx++) diff --git a/cmd/multicall.c b/cmd/multicall.c index 0eff1bb..c6ae3d4 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -44,7 +44,7 @@ applet_cmp(const void *a, const void *b) return strcmp(key, applet->name); } -void multicall_usage(void) __attribute__((noreturn)); +void multicall_usage(int status) __attribute__((noreturn)); int main(int argc, char *argv[]) @@ -59,7 +59,7 @@ main(int argc, char *argv[]) if (app == NULL) { fprintf(stderr, "%s: applet not found\n", argv0); - multicall_usage(); + multicall_usage(EXIT_FAILURE); } return (*app)->main(argc, argv); @@ -69,13 +69,13 @@ int multicall_main(int argc, char *argv[]) { if (argc < 2) - multicall_usage(); + multicall_usage(EXIT_FAILURE); return main(argc - 1, argv + 1); } void -multicall_usage(void) +multicall_usage(int status) { fprintf(stderr, "usage: ifupdown [options]\n"); @@ -90,7 +90,7 @@ multicall_usage(void) fprintf(stderr, "\n"); - exit(EXIT_FAILURE); + exit(status); } struct if_applet ifupdown_applet = { diff --git a/cmd/multicall.h b/cmd/multicall.h index 48bd1ea..6fb26a4 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -21,7 +21,7 @@ struct if_applet { const char *name; int (*const main)(int argc, char *argv[]); - void (*const usage)(void); + void (*const usage)(int status); }; extern char *argv0; From b481db6c20c848888b6c671bd7dc00d936b340d5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 22:07:32 -0600 Subject: [PATCH 120/530] multicall: add support for unified option handling --- cmd/multicall.c | 143 +++++++++++++++++++++++++++++++++++++++++++++++- cmd/multicall.h | 23 ++++++++ 2 files changed, 164 insertions(+), 2 deletions(-) diff --git a/cmd/multicall.c b/cmd/multicall.c index c6ae3d4..65bd9e9 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -13,10 +13,12 @@ * from the use of this software. */ +#define _GNU_SOURCE #include #include #include #include +#include #include "cmd/multicall.h" char *argv0; @@ -33,7 +35,67 @@ struct if_applet *applet_table[] = { &ifupdown_applet, }; -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) +static void +generic_usage(const struct if_applet *applet, int result) +{ + fprintf(stderr, "%s", applet->name); + if (applet->desc != NULL) + fprintf(stderr, " - %s", applet->desc); + + fprintf(stderr, "\n"); + + size_t iter; + for (iter = 0; applet->groups[iter] != NULL; iter++) + { + const struct if_option_group *group = applet->groups[iter]; + + fprintf(stderr, "\n%s:\n", group->desc); + + size_t group_iter; + for (group_iter = 0; group_iter < group->group_size; group_iter++) + { + const struct if_option *opt = &group->group[group_iter]; + + fprintf(stderr, " "); + + if (opt->short_opt) + fprintf(stderr, "-%c", opt->short_opt); + else + fprintf(stderr, " "); + + if (opt->long_opt) + fprintf(stderr, "%c --%-30s", opt->short_opt ? ',' : ' ', + opt->long_opt); + else + fprintf(stderr, "%34s", ""); + + fprintf(stderr, "%s\n", opt->desc); + } + } + + exit(result); +} + +static void +generic_usage_request(int short_opt, const struct if_option *option, const char *opt_arg, const struct if_applet *applet) +{ + (void) short_opt; + (void) option; + (void) opt_arg; + + generic_usage(applet, EXIT_SUCCESS); +} + +static struct if_option global_options[] = { + {'h', "help", "displays program help", false, generic_usage_request}, + {'V', "version", "displays program version", false, (void *) lif_common_version}, +}; + +struct if_option_group global_option_group = { + .desc = "Global options", + .group_size = ARRAY_SIZE(global_options), + .group = global_options +}; int applet_cmp(const void *a, const void *b) @@ -46,11 +108,83 @@ applet_cmp(const void *a, const void *b) void multicall_usage(int status) __attribute__((noreturn)); +static const struct if_option * +lookup_option(const struct if_applet *applet, int opt) +{ + size_t iter; + for (iter = 0; applet->groups[iter] != NULL; iter++) + { + const struct if_option_group *group = applet->groups[iter]; + size_t group_iter; + + for (group_iter = 0; group_iter < group->group_size; group_iter++) + { + const struct if_option *option = &group->group[group_iter]; + + if (option->short_opt == opt) + return option; + } + } + + return NULL; +} + +static void +process_options(const struct if_applet *applet, int argc, char *argv[]) +{ + char short_opts[256] = {}, *p = short_opts; + struct option long_opts[256] = {}; + + size_t iter, long_opt_iter = 0; + for (iter = 0; applet->groups[iter] != NULL; iter++) + { + const struct if_option_group *group = applet->groups[iter]; + size_t group_iter; + + for (group_iter = 0; group_iter < group->group_size; group_iter++) + { + const struct if_option *opt = &group->group[group_iter]; + + if (opt->short_opt) + { + *p++ = opt->short_opt; + if (opt->require_argument) + *p++ = ':'; + } + + if (opt->long_opt) + { + /* XXX: handle long-opts without short-opts */ + long_opts[long_opt_iter] = (struct option) { + .name = opt->long_opt, + .has_arg = opt->require_argument ? required_argument : no_argument, + .val = opt->short_opt + }; + + long_opt_iter++; + } + } + } + + for (;;) + { + int c = getopt_long(argc, argv, short_opts, long_opts, NULL); + if (c == -1) + break; + + const struct if_option *opt = lookup_option(applet, c); + if (opt == NULL) + break; + + opt->handle(c, opt, optarg, applet); + } +} + int main(int argc, char *argv[]) { argv0 = basename(argv[0]); - struct if_applet **app; + const struct if_applet **app; app = bsearch(argv0, applet_table, ARRAY_SIZE(applet_table), sizeof(*applet_table), @@ -62,6 +196,8 @@ main(int argc, char *argv[]) multicall_usage(EXIT_FAILURE); } + process_options(*app, argc, argv); + return (*app)->main(argc, argv); } @@ -74,6 +210,8 @@ multicall_main(int argc, char *argv[]) return main(argc - 1, argv + 1); } +struct if_applet ifupdown_applet; + void multicall_usage(int status) { @@ -97,4 +235,5 @@ struct if_applet ifupdown_applet = { .name = "ifupdown", .main = multicall_main, .usage = multicall_usage, + .groups = { &global_option_group, NULL } }; diff --git a/cmd/multicall.h b/cmd/multicall.h index 6fb26a4..d0f09c9 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -13,17 +13,40 @@ * from the use of this software. */ +#include + #ifndef IFUPDOWN_CMD_MULTICALL_H__GUARD #define IFUPDOWN_CMD_MULTICALL_H__GUARD #include "libifupdown/libifupdown.h" +#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) + +struct if_applet; + +struct if_option { + char short_opt; + const char *long_opt; + const char *desc; + bool require_argument; + void (*const handle)(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet); +}; + +struct if_option_group { + const char *desc; + size_t group_size; + const struct if_option *group; +}; + struct if_applet { const char *name; + const char *desc; int (*const main)(int argc, char *argv[]); void (*const usage)(int status); + const struct if_option_group *groups[4]; }; extern char *argv0; +extern struct if_option_group global_option_group; #endif From b817bdb999a7d3ffa837f047a671fc2af9d7c1f1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 22:12:37 -0600 Subject: [PATCH 121/530] multicall: move match_options to a common include --- cmd/ifquery.c | 9 --------- cmd/ifupdown.c | 6 ------ cmd/multicall.h | 9 +++++++++ 3 files changed, 9 insertions(+), 15 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 2778dea..f84fb28 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -186,15 +186,6 @@ ifquery_usage(int status) exit(status); } -struct match_options { - bool is_auto; - char *exclude_pattern; - char *include_pattern; - bool pretty_print; - bool dot; - char *property; -}; - void list_interfaces(struct lif_dict *collection, struct match_options *opts) { diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 9a9aada..1c42a3f 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -24,12 +24,6 @@ #include "libifupdown/libifupdown.h" #include "cmd/multicall.h" -struct match_options { - bool is_auto; - char *exclude_pattern; - char *include_pattern; -}; - static bool up; static struct lif_execute_opts exec_opts = { .executor_path = EXECUTOR_PATH, diff --git a/cmd/multicall.h b/cmd/multicall.h index d0f09c9..48deb26 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -49,4 +49,13 @@ struct if_applet { extern char *argv0; extern struct if_option_group global_option_group; +struct match_options { + bool is_auto; + char *exclude_pattern; + char *include_pattern; + bool pretty_print; + bool dot; + char *property; +}; + #endif From 2be5add47bc1fc2ebe39fdf508bbe0066266b956 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 22:15:52 -0600 Subject: [PATCH 122/530] multicall: split option handling routines out to multicall-options.c --- Makefile | 4 +- cmd/multicall-options.c | 156 ++++++++++++++++++++++++++++++++++++++++ cmd/multicall.c | 134 ---------------------------------- cmd/multicall.h | 3 + 4 files changed, 162 insertions(+), 135 deletions(-) create mode 100644 cmd/multicall-options.c diff --git a/Makefile b/Makefile index 6ce44b3..f2ad017 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,9 @@ LIBIFUPDOWN_SRC = \ LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o} LIBIFUPDOWN_LIB = libifupdown.a -MULTICALL_SRC = cmd/multicall.c +MULTICALL_SRC = \ + cmd/multicall.c \ + cmd/multicall-options.c MULTICALL_OBJ = ${MULTICALL_SRC:.c=.o} MULTICALL = ifupdown diff --git a/cmd/multicall-options.c b/cmd/multicall-options.c new file mode 100644 index 0000000..415d24a --- /dev/null +++ b/cmd/multicall-options.c @@ -0,0 +1,156 @@ +/* + * cmd/multicall-options.c + * Purpose: multi-call binary frontend -- option handling + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cmd/multicall.h" + +static void +generic_usage(const struct if_applet *applet, int result) +{ + fprintf(stderr, "%s", applet->name); + if (applet->desc != NULL) + fprintf(stderr, " - %s", applet->desc); + + fprintf(stderr, "\n"); + + size_t iter; + for (iter = 0; applet->groups[iter] != NULL; iter++) + { + const struct if_option_group *group = applet->groups[iter]; + + fprintf(stderr, "\n%s:\n", group->desc); + + size_t group_iter; + for (group_iter = 0; group_iter < group->group_size; group_iter++) + { + const struct if_option *opt = &group->group[group_iter]; + + fprintf(stderr, " "); + + if (opt->short_opt) + fprintf(stderr, "-%c", opt->short_opt); + else + fprintf(stderr, " "); + + if (opt->long_opt) + fprintf(stderr, "%c --%-30s", opt->short_opt ? ',' : ' ', + opt->long_opt); + else + fprintf(stderr, "%34s", ""); + + fprintf(stderr, "%s\n", opt->desc); + } + } + + exit(result); +} + +static void +generic_usage_request(int short_opt, const struct if_option *option, const char *opt_arg, const struct if_applet *applet) +{ + (void) short_opt; + (void) option; + (void) opt_arg; + + generic_usage(applet, EXIT_SUCCESS); +} + +static struct if_option global_options[] = { + {'h', "help", "displays program help", false, generic_usage_request}, + {'V', "version", "displays program version", false, (void *) lif_common_version}, +}; + +struct if_option_group global_option_group = { + .desc = "Global options", + .group_size = ARRAY_SIZE(global_options), + .group = global_options +}; + +const struct if_option * +lookup_option(const struct if_applet *applet, int opt) +{ + size_t iter; + for (iter = 0; applet->groups[iter] != NULL; iter++) + { + const struct if_option_group *group = applet->groups[iter]; + size_t group_iter; + + for (group_iter = 0; group_iter < group->group_size; group_iter++) + { + const struct if_option *option = &group->group[group_iter]; + + if (option->short_opt == opt) + return option; + } + } + + return NULL; +} + +void +process_options(const struct if_applet *applet, int argc, char *argv[]) +{ + char short_opts[256] = {}, *p = short_opts; + struct option long_opts[256] = {}; + + size_t iter, long_opt_iter = 0; + for (iter = 0; applet->groups[iter] != NULL; iter++) + { + const struct if_option_group *group = applet->groups[iter]; + size_t group_iter; + + for (group_iter = 0; group_iter < group->group_size; group_iter++) + { + const struct if_option *opt = &group->group[group_iter]; + + if (opt->short_opt) + { + *p++ = opt->short_opt; + if (opt->require_argument) + *p++ = ':'; + } + + if (opt->long_opt) + { + /* XXX: handle long-opts without short-opts */ + long_opts[long_opt_iter] = (struct option) { + .name = opt->long_opt, + .has_arg = opt->require_argument ? required_argument : no_argument, + .val = opt->short_opt + }; + + long_opt_iter++; + } + } + } + + for (;;) + { + int c = getopt_long(argc, argv, short_opts, long_opts, NULL); + if (c == -1) + break; + + const struct if_option *opt = lookup_option(applet, c); + if (opt == NULL) + break; + + opt->handle(c, opt, optarg, applet); + } +} diff --git a/cmd/multicall.c b/cmd/multicall.c index 65bd9e9..6121776 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -35,68 +35,6 @@ struct if_applet *applet_table[] = { &ifupdown_applet, }; -static void -generic_usage(const struct if_applet *applet, int result) -{ - fprintf(stderr, "%s", applet->name); - if (applet->desc != NULL) - fprintf(stderr, " - %s", applet->desc); - - fprintf(stderr, "\n"); - - size_t iter; - for (iter = 0; applet->groups[iter] != NULL; iter++) - { - const struct if_option_group *group = applet->groups[iter]; - - fprintf(stderr, "\n%s:\n", group->desc); - - size_t group_iter; - for (group_iter = 0; group_iter < group->group_size; group_iter++) - { - const struct if_option *opt = &group->group[group_iter]; - - fprintf(stderr, " "); - - if (opt->short_opt) - fprintf(stderr, "-%c", opt->short_opt); - else - fprintf(stderr, " "); - - if (opt->long_opt) - fprintf(stderr, "%c --%-30s", opt->short_opt ? ',' : ' ', - opt->long_opt); - else - fprintf(stderr, "%34s", ""); - - fprintf(stderr, "%s\n", opt->desc); - } - } - - exit(result); -} - -static void -generic_usage_request(int short_opt, const struct if_option *option, const char *opt_arg, const struct if_applet *applet) -{ - (void) short_opt; - (void) option; - (void) opt_arg; - - generic_usage(applet, EXIT_SUCCESS); -} - -static struct if_option global_options[] = { - {'h', "help", "displays program help", false, generic_usage_request}, - {'V', "version", "displays program version", false, (void *) lif_common_version}, -}; - -struct if_option_group global_option_group = { - .desc = "Global options", - .group_size = ARRAY_SIZE(global_options), - .group = global_options -}; - int applet_cmp(const void *a, const void *b) { @@ -108,78 +46,6 @@ applet_cmp(const void *a, const void *b) void multicall_usage(int status) __attribute__((noreturn)); -static const struct if_option * -lookup_option(const struct if_applet *applet, int opt) -{ - size_t iter; - for (iter = 0; applet->groups[iter] != NULL; iter++) - { - const struct if_option_group *group = applet->groups[iter]; - size_t group_iter; - - for (group_iter = 0; group_iter < group->group_size; group_iter++) - { - const struct if_option *option = &group->group[group_iter]; - - if (option->short_opt == opt) - return option; - } - } - - return NULL; -} - -static void -process_options(const struct if_applet *applet, int argc, char *argv[]) -{ - char short_opts[256] = {}, *p = short_opts; - struct option long_opts[256] = {}; - - size_t iter, long_opt_iter = 0; - for (iter = 0; applet->groups[iter] != NULL; iter++) - { - const struct if_option_group *group = applet->groups[iter]; - size_t group_iter; - - for (group_iter = 0; group_iter < group->group_size; group_iter++) - { - const struct if_option *opt = &group->group[group_iter]; - - if (opt->short_opt) - { - *p++ = opt->short_opt; - if (opt->require_argument) - *p++ = ':'; - } - - if (opt->long_opt) - { - /* XXX: handle long-opts without short-opts */ - long_opts[long_opt_iter] = (struct option) { - .name = opt->long_opt, - .has_arg = opt->require_argument ? required_argument : no_argument, - .val = opt->short_opt - }; - - long_opt_iter++; - } - } - } - - for (;;) - { - int c = getopt_long(argc, argv, short_opts, long_opts, NULL); - if (c == -1) - break; - - const struct if_option *opt = lookup_option(applet, c); - if (opt == NULL) - break; - - opt->handle(c, opt, optarg, applet); - } -} - int main(int argc, char *argv[]) { diff --git a/cmd/multicall.h b/cmd/multicall.h index 48deb26..97056a2 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -58,4 +58,7 @@ struct match_options { char *property; }; +extern void process_options(const struct if_applet *applet, int argc, char *argv[]); +extern const struct if_option *lookup_option(const struct if_applet *applet, int opt); + #endif From f871002ecca2ca77d5781d44f6c2b82cc8c8af62 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 22:37:10 -0600 Subject: [PATCH 123/530] multicall: add self_applet --- cmd/multicall.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/cmd/multicall.c b/cmd/multicall.c index 6121776..9c8a891 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -27,6 +27,7 @@ extern struct if_applet ifquery_applet; extern struct if_applet ifup_applet; extern struct if_applet ifdown_applet; struct if_applet ifupdown_applet; +const struct if_applet *self_applet = NULL; struct if_applet *applet_table[] = { &ifdown_applet, @@ -62,6 +63,7 @@ main(int argc, char *argv[]) multicall_usage(EXIT_FAILURE); } + self_applet = *app; process_options(*app, argc, argv); return (*app)->main(argc, argv); From 52509c508cc4a96ed13c83e5ac1b121145da951f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 22:37:36 -0600 Subject: [PATCH 124/530] multicall: migrate match options to shared collection --- Makefile | 3 ++- cmd/ifquery.c | 28 +++------------------------- cmd/ifupdown.c | 1 - cmd/multicall-options.c | 6 +++--- cmd/multicall.h | 12 +++++++++--- 5 files changed, 17 insertions(+), 33 deletions(-) diff --git a/Makefile b/Makefile index f2ad017..a0615be 100644 --- a/Makefile +++ b/Makefile @@ -41,7 +41,8 @@ LIBIFUPDOWN_LIB = libifupdown.a MULTICALL_SRC = \ cmd/multicall.c \ - cmd/multicall-options.c + cmd/multicall-options.c \ + cmd/multicall-match-options.c MULTICALL_OBJ = ${MULTICALL_SRC:.c=.o} MULTICALL = ifupdown diff --git a/cmd/ifquery.c b/cmd/ifquery.c index f84fb28..b1df261 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -174,9 +174,6 @@ ifquery_usage(int status) fprintf(stderr, " -V, --version show this program's version\n"); fprintf(stderr, " -i, --interfaces FILE use FILE for interface definitions\n"); fprintf(stderr, " -L, --list list matching interfaces\n"); - fprintf(stderr, " -a, --auto only match against interfaces hinted as 'auto'\n"); - fprintf(stderr, " -I, --include PATTERN only match against interfaces matching PATTERN\n"); - fprintf(stderr, " -X, --exclude PATTERN never match against interfaces matching PATTERN\n"); fprintf(stderr, " -P, --pretty-print pretty print the interfaces instead of just listing\n"); fprintf(stderr, " -S, --state-file FILE use FILE for state\n"); fprintf(stderr, " -s, --state show configured state\n"); @@ -253,13 +250,8 @@ ifquery_main(int argc, char *argv[]) struct lif_dict state = {}; struct lif_dict collection = {}; struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, {"interfaces", required_argument, 0, 'i'}, {"list", no_argument, 0, 'L'}, - {"auto", no_argument, 0, 'a'}, - {"include", required_argument, 0, 'I'}, - {"exclude", required_argument, 0, 'X'}, {"pretty-print", no_argument, 0, 'P'}, {"state-file", required_argument, 0, 'S'}, {"state", no_argument, 0, 's'}, @@ -268,7 +260,6 @@ ifquery_main(int argc, char *argv[]) {"executor-path", required_argument, 0, 'E'}, {NULL, 0, 0, 0} }; - struct match_options match_opts = {}; bool listing = false, listing_stat = false; char *state_file = STATE_FILE; @@ -279,27 +270,12 @@ ifquery_main(int argc, char *argv[]) break; switch (c) { - case 'h': - ifquery_usage(EXIT_SUCCESS); - break; - case 'V': - lif_common_version(); - break; case 'i': exec_opts.interfaces_file = optarg; break; case 'L': listing = true; break; - case 'a': - match_opts.is_auto = true; - break; - case 'I': - match_opts.include_pattern = optarg; - break; - case 'X': - match_opts.exclude_pattern = optarg; - break; case 'P': match_opts.pretty_print = true; break; @@ -381,6 +357,8 @@ ifquery_main(int argc, char *argv[]) struct if_applet ifquery_applet = { .name = "ifquery", + .desc = "query interface configuration", .main = ifquery_main, - .usage = ifquery_usage + .usage = ifquery_usage, + .groups = { &global_option_group, &match_option_group, NULL }, }; diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 1c42a3f..75d9c61 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -204,7 +204,6 @@ ifupdown_main(int argc, char *argv[]) {"no-lock", no_argument, 0, 'L'}, {NULL, 0, 0, 0} }; - struct match_options match_opts = {}; for (;;) { diff --git a/cmd/multicall-options.c b/cmd/multicall-options.c index 415d24a..30e7db4 100644 --- a/cmd/multicall-options.c +++ b/cmd/multicall-options.c @@ -51,7 +51,7 @@ generic_usage(const struct if_applet *applet, int result) if (opt->long_opt) fprintf(stderr, "%c --%-30s", opt->short_opt ? ',' : ' ', - opt->long_opt); + opt->long_opt_desc ? opt->long_opt_desc : opt->long_opt); else fprintf(stderr, "%34s", ""); @@ -73,8 +73,8 @@ generic_usage_request(int short_opt, const struct if_option *option, const char } static struct if_option global_options[] = { - {'h', "help", "displays program help", false, generic_usage_request}, - {'V', "version", "displays program version", false, (void *) lif_common_version}, + {'h', "help", NULL, "this help", false, generic_usage_request}, + {'V', "version", NULL, "show this program's version", false, (void *) lif_common_version}, }; struct if_option_group global_option_group = { diff --git a/cmd/multicall.h b/cmd/multicall.h index 97056a2..aa5752e 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -27,6 +27,7 @@ struct if_applet; struct if_option { char short_opt; const char *long_opt; + const char *long_opt_desc; const char *desc; bool require_argument; void (*const handle)(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet); @@ -47,18 +48,23 @@ struct if_applet { }; extern char *argv0; +extern const struct if_applet *self_applet; extern struct if_option_group global_option_group; struct match_options { bool is_auto; - char *exclude_pattern; - char *include_pattern; + const char *exclude_pattern; + const char *include_pattern; bool pretty_print; bool dot; - char *property; + const char *property; }; +extern struct match_options match_opts; + extern void process_options(const struct if_applet *applet, int argc, char *argv[]); extern const struct if_option *lookup_option(const struct if_applet *applet, int opt); +extern struct if_option_group match_option_group; + #endif From fdfe8ac080e38fd064ad501d2c23940c1cc91369 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 22:51:53 -0600 Subject: [PATCH 125/530] multicall: migrate execution options to common code --- Makefile | 1 + cmd/ifquery.c | 24 ++--------- cmd/ifupdown.c | 11 ++--- cmd/multicall-exec-options.c | 77 +++++++++++++++++++++++++++++++++++ cmd/multicall-match-options.c | 57 ++++++++++++++++++++++++++ cmd/multicall.h | 3 ++ 6 files changed, 144 insertions(+), 29 deletions(-) create mode 100644 cmd/multicall-exec-options.c create mode 100644 cmd/multicall-match-options.c diff --git a/Makefile b/Makefile index a0615be..6762eec 100644 --- a/Makefile +++ b/Makefile @@ -42,6 +42,7 @@ LIBIFUPDOWN_LIB = libifupdown.a MULTICALL_SRC = \ cmd/multicall.c \ cmd/multicall-options.c \ + cmd/multicall-exec-options.c \ cmd/multicall-match-options.c MULTICALL_OBJ = ${MULTICALL_SRC:.c=.o} MULTICALL = ifupdown diff --git a/cmd/ifquery.c b/cmd/ifquery.c index b1df261..89c84d4 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -21,11 +21,6 @@ #include "libifupdown/libifupdown.h" #include "cmd/multicall.h" -static struct lif_execute_opts exec_opts = { - .interfaces_file = INTERFACES_FILE, - .executor_path = EXECUTOR_PATH -}; - void print_interface(struct lif_interface *iface) { @@ -250,18 +245,14 @@ ifquery_main(int argc, char *argv[]) struct lif_dict state = {}; struct lif_dict collection = {}; struct option long_options[] = { - {"interfaces", required_argument, 0, 'i'}, {"list", no_argument, 0, 'L'}, {"pretty-print", no_argument, 0, 'P'}, - {"state-file", required_argument, 0, 'S'}, {"state", no_argument, 0, 's'}, {"dot", no_argument, 0, 'D'}, {"property", required_argument, 0, 'p'}, - {"executor-path", required_argument, 0, 'E'}, {NULL, 0, 0, 0} }; bool listing = false, listing_stat = false; - char *state_file = STATE_FILE; for (;;) { @@ -270,18 +261,12 @@ ifquery_main(int argc, char *argv[]) break; switch (c) { - case 'i': - exec_opts.interfaces_file = optarg; - break; case 'L': listing = true; break; case 'P': match_opts.pretty_print = true; break; - case 'S': - state_file = optarg; - break; case 's': listing_stat = true; break; @@ -291,15 +276,12 @@ ifquery_main(int argc, char *argv[]) case 'p': match_opts.property = optarg; break; - case 'E': - exec_opts.executor_path = optarg; - break; } } - if (!lif_state_read_path(&state, state_file)) + if (!lif_state_read_path(&state, exec_opts.state_file)) { - fprintf(stderr, "%s: could not parse %s\n", argv0, state_file); + fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.state_file); return EXIT_FAILURE; } @@ -360,5 +342,5 @@ struct if_applet ifquery_applet = { .desc = "query interface configuration", .main = ifquery_main, .usage = ifquery_usage, - .groups = { &global_option_group, &match_option_group, NULL }, + .groups = { &global_option_group, &match_option_group, &exec_option_group }, }; diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 75d9c61..2c4143a 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -25,11 +25,6 @@ #include "cmd/multicall.h" static bool up; -static struct lif_execute_opts exec_opts = { - .executor_path = EXECUTOR_PATH, - .interfaces_file = INTERFACES_FILE, - .state_file = STATE_FILE, -}; void ifupdown_usage(int status) @@ -218,9 +213,6 @@ ifupdown_main(int argc, char *argv[]) case 'V': lif_common_version(); break; - case 'i': - exec_opts.interfaces_file = optarg; - break; case 'a': match_opts.is_auto = true; break; @@ -230,6 +222,9 @@ ifupdown_main(int argc, char *argv[]) case 'X': match_opts.exclude_pattern = optarg; break; + case 'i': + exec_opts.interfaces_file = optarg; + break; case 'S': exec_opts.state_file = optarg; break; diff --git a/cmd/multicall-exec-options.c b/cmd/multicall-exec-options.c new file mode 100644 index 0000000..f043167 --- /dev/null +++ b/cmd/multicall-exec-options.c @@ -0,0 +1,77 @@ +/* + * cmd/multicall-exec-options.c + * Purpose: multi-call binary frontend -- option handling + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cmd/multicall.h" + +struct lif_execute_opts exec_opts = { + .interfaces_file = INTERFACES_FILE, + .executor_path = EXECUTOR_PATH, + .state_file = STATE_FILE +}; + +static void handle_exec(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +{ + (void) opt; + (void) applet; + + switch (short_opt) + { + case 'i': + exec_opts.interfaces_file = opt_arg; + break; + case 'S': + exec_opts.state_file = opt_arg; + break; + case 'n': + exec_opts.mock = true; + exec_opts.verbose = true; + break; + case 'v': + exec_opts.verbose = true; + break; + case 'E': + exec_opts.executor_path = opt_arg; + break; + case 'f': + break; + case 'L': + exec_opts.no_lock = true; + break; + default: + break; + } +} + +static struct if_option exec_options[] = { + {'f', "force", NULL, "force (de)configuration", true, handle_exec}, + {'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, handle_exec}, + {'n', "no-act", NULL, "do not actually run any commands", false, handle_exec}, + {'v', "verbose", NULL, "show what commands are being run", false, handle_exec}, + {'E', "executor-path", "executor-path PATH", "use PATH for executor directory", true, handle_exec}, + {'L', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, handle_exec}, + {'S', "state-file", "state-file FILE", "use FILE for state", true, handle_exec}, +}; + +struct if_option_group exec_option_group = { + .desc = "Execution", + .group_size = ARRAY_SIZE(exec_options), + .group = exec_options +}; diff --git a/cmd/multicall-match-options.c b/cmd/multicall-match-options.c new file mode 100644 index 0000000..d89056a --- /dev/null +++ b/cmd/multicall-match-options.c @@ -0,0 +1,57 @@ +/* + * cmd/multicall-match-options.c + * Purpose: multi-call binary frontend -- option handling + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include "cmd/multicall.h" + +struct match_options match_opts = {}; + +static void handle_match(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +{ + (void) opt; + (void) applet; + + switch (short_opt) + { + case 'a': + match_opts.is_auto = true; + break; + case 'I': + match_opts.include_pattern = opt_arg; + break; + case 'X': + match_opts.exclude_pattern = opt_arg; + break; + default: + break; + } +} + +static struct if_option match_options[] = { + {'a', "auto", NULL, "only match against interfaces hinted as 'auto'", false, handle_match}, + {'I', "include", "include PATTERN", "only match against interfaces matching PATTERN", true, handle_match}, + {'X', "exclude", "exclude PATTERN", "never match against interfaces matching PATTERN", true, handle_match}, +}; + +struct if_option_group match_option_group = { + .desc = "Matching interfaces", + .group_size = ARRAY_SIZE(match_options), + .group = match_options +}; diff --git a/cmd/multicall.h b/cmd/multicall.h index aa5752e..20d2c20 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -67,4 +67,7 @@ extern const struct if_option *lookup_option(const struct if_applet *applet, int extern struct if_option_group match_option_group; +extern struct lif_execute_opts exec_opts; +extern struct if_option_group exec_option_group; + #endif From f6d9f652485b3681210fe4f4af357761cc38a7aa Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 23:03:55 -0600 Subject: [PATCH 126/530] ifquery: port to use option groups --- cmd/ifquery.c | 88 +++++++++++++++++------------------- cmd/multicall-exec-options.c | 4 +- cmd/multicall.h | 2 +- 3 files changed, 45 insertions(+), 49 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 89c84d4..dc9cfbe 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -164,17 +164,6 @@ ifquery_usage(int status) fprintf(stderr, "usage: ifquery [options] \n"); fprintf(stderr, " ifquery [options] --list\n"); - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, " -h, --help this help\n"); - fprintf(stderr, " -V, --version show this program's version\n"); - fprintf(stderr, " -i, --interfaces FILE use FILE for interface definitions\n"); - fprintf(stderr, " -L, --list list matching interfaces\n"); - fprintf(stderr, " -P, --pretty-print pretty print the interfaces instead of just listing\n"); - fprintf(stderr, " -S, --state-file FILE use FILE for state\n"); - fprintf(stderr, " -s, --state show configured state\n"); - fprintf(stderr, " -D, --dot generate a dependency graph\n"); - fprintf(stderr, " -p, --property PROPERTY print values of properties matching PROPERTY\n"); - exit(status); } @@ -239,45 +228,52 @@ list_state(struct lif_dict *state, struct match_options *opts) } } +static bool listing = false, listing_stat = false; + +static void +handle_local(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +{ + (void) opt; + (void) applet; + + switch (short_opt) { + case 'L': + listing = true; + break; + case 'P': + match_opts.pretty_print = true; + break; + case 's': + listing_stat = true; + break; + case 'D': + match_opts.dot = true; + break; + case 'p': + match_opts.property = opt_arg; + break; + } +} + +static struct if_option local_options[] = { + {'s', "state", NULL, "show configured state", false, handle_local}, + {'p', "property", "property PROPERTY", "print values of properties matching PROPERTY", true, handle_local}, + {'D', "dot", NULL, "generate a dependency graph", false, handle_local}, + {'L', "list", NULL, "list matching interfaces", false, handle_local}, + {'P', "pretty-print", NULL, "pretty print the interfaces instead of just listing", false, handle_local}, +}; + +static struct if_option_group local_option_group = { + .desc = "Program-specific options", + .group_size = ARRAY_SIZE(local_options), + .group = local_options +}; + int ifquery_main(int argc, char *argv[]) { struct lif_dict state = {}; struct lif_dict collection = {}; - struct option long_options[] = { - {"list", no_argument, 0, 'L'}, - {"pretty-print", no_argument, 0, 'P'}, - {"state", no_argument, 0, 's'}, - {"dot", no_argument, 0, 'D'}, - {"property", required_argument, 0, 'p'}, - {NULL, 0, 0, 0} - }; - bool listing = false, listing_stat = false; - - for (;;) - { - int c = getopt_long(argc, argv, "hVi:LaI:X:PS:sDp:E:", long_options, NULL); - if (c == -1) - break; - - switch (c) { - case 'L': - listing = true; - break; - case 'P': - match_opts.pretty_print = true; - break; - case 's': - listing_stat = true; - break; - case 'D': - match_opts.dot = true; - break; - case 'p': - match_opts.property = optarg; - break; - } - } if (!lif_state_read_path(&state, exec_opts.state_file)) { @@ -342,5 +338,5 @@ struct if_applet ifquery_applet = { .desc = "query interface configuration", .main = ifquery_main, .usage = ifquery_usage, - .groups = { &global_option_group, &match_option_group, &exec_option_group }, + .groups = { &global_option_group, &match_option_group, &exec_option_group, &local_option_group }, }; diff --git a/cmd/multicall-exec-options.c b/cmd/multicall-exec-options.c index f043167..0ebe85d 100644 --- a/cmd/multicall-exec-options.c +++ b/cmd/multicall-exec-options.c @@ -52,7 +52,7 @@ static void handle_exec(int short_opt, const struct if_option *opt, const char * break; case 'f': break; - case 'L': + case 'l': exec_opts.no_lock = true; break; default: @@ -63,10 +63,10 @@ static void handle_exec(int short_opt, const struct if_option *opt, const char * static struct if_option exec_options[] = { {'f', "force", NULL, "force (de)configuration", true, handle_exec}, {'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, handle_exec}, + {'l', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, handle_exec}, {'n', "no-act", NULL, "do not actually run any commands", false, handle_exec}, {'v', "verbose", NULL, "show what commands are being run", false, handle_exec}, {'E', "executor-path", "executor-path PATH", "use PATH for executor directory", true, handle_exec}, - {'L', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, handle_exec}, {'S', "state-file", "state-file FILE", "use FILE for state", true, handle_exec}, }; diff --git a/cmd/multicall.h b/cmd/multicall.h index 20d2c20..cfbadd5 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -44,7 +44,7 @@ struct if_applet { const char *desc; int (*const main)(int argc, char *argv[]); void (*const usage)(int status); - const struct if_option_group *groups[4]; + const struct if_option_group *groups[16]; }; extern char *argv0; From fda7bfae577ffd10eb1cad58559d223b005d3a2e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 23:10:35 -0600 Subject: [PATCH 127/530] ifquery: use generic_usage() instead of ifquery_usage() --- cmd/ifquery.c | 15 +++------------ cmd/ifupdown.c | 2 -- cmd/multicall-options.c | 5 ++++- cmd/multicall.c | 1 - cmd/multicall.h | 4 +++- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index dc9cfbe..0612823 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -158,15 +158,6 @@ print_interface_property(struct lif_interface *iface, const char *property) } } -void -ifquery_usage(int status) -{ - fprintf(stderr, "usage: ifquery [options] \n"); - fprintf(stderr, " ifquery [options] --list\n"); - - exit(status); -} - void list_interfaces(struct lif_dict *collection, struct match_options *opts) { @@ -289,7 +280,7 @@ ifquery_main(int argc, char *argv[]) /* --list --state is not allowed */ if (listing && listing_stat) - ifquery_usage(EXIT_FAILURE); + generic_usage(self_applet, EXIT_FAILURE); if (listing) { @@ -303,7 +294,7 @@ ifquery_main(int argc, char *argv[]) } if (optind >= argc) - ifquery_usage(EXIT_FAILURE); + generic_usage(self_applet, EXIT_FAILURE); int idx = optind; for (; idx < argc; idx++) @@ -337,6 +328,6 @@ struct if_applet ifquery_applet = { .name = "ifquery", .desc = "query interface configuration", .main = ifquery_main, - .usage = ifquery_usage, + .usage = "ifquery [options] \n ifquery [options] --list", .groups = { &global_option_group, &match_option_group, &exec_option_group, &local_option_group }, }; diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 2c4143a..45410a7 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -320,11 +320,9 @@ ifupdown_main(int argc, char *argv[]) struct if_applet ifup_applet = { .name = "ifup", .main = ifupdown_main, - .usage = ifupdown_usage }; struct if_applet ifdown_applet = { .name = "ifdown", .main = ifupdown_main, - .usage = ifupdown_usage }; diff --git a/cmd/multicall-options.c b/cmd/multicall-options.c index 30e7db4..9037264 100644 --- a/cmd/multicall-options.c +++ b/cmd/multicall-options.c @@ -21,7 +21,7 @@ #include #include "cmd/multicall.h" -static void +void generic_usage(const struct if_applet *applet, int result) { fprintf(stderr, "%s", applet->name); @@ -30,6 +30,9 @@ generic_usage(const struct if_applet *applet, int result) fprintf(stderr, "\n"); + if (applet->usage != NULL) + fprintf(stderr, "\nUsage:\n %s\n", applet->usage); + size_t iter; for (iter = 0; applet->groups[iter] != NULL; iter++) { diff --git a/cmd/multicall.c b/cmd/multicall.c index 9c8a891..ccb7688 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -102,6 +102,5 @@ multicall_usage(int status) struct if_applet ifupdown_applet = { .name = "ifupdown", .main = multicall_main, - .usage = multicall_usage, .groups = { &global_option_group, NULL } }; diff --git a/cmd/multicall.h b/cmd/multicall.h index cfbadd5..23cb836 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -42,8 +42,8 @@ struct if_option_group { struct if_applet { const char *name; const char *desc; + const char *usage; int (*const main)(int argc, char *argv[]); - void (*const usage)(int status); const struct if_option_group *groups[16]; }; @@ -70,4 +70,6 @@ extern struct if_option_group match_option_group; extern struct lif_execute_opts exec_opts; extern struct if_option_group exec_option_group; +void generic_usage(const struct if_applet *applet, int result); + #endif From f7d21d4b466e301134f460d4dcd9447aa55f0f35 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 11 Aug 2020 23:14:55 -0600 Subject: [PATCH 128/530] ifupdown: port to use option groups --- cmd/ifupdown.c | 91 ++++---------------------------------------------- 1 file changed, 7 insertions(+), 84 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 45410a7..c1bce3a 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -26,28 +26,6 @@ static bool up; -void -ifupdown_usage(int status) -{ - fprintf(stderr, "usage: %s [options] \n", argv0); - - fprintf(stderr, "\nOptions:\n"); - fprintf(stderr, " -h, --help this help\n"); - fprintf(stderr, " -V, --version show this program's version\n"); - fprintf(stderr, " -i, --interfaces FILE use FILE for interface definitions\n"); - fprintf(stderr, " -S, --state-file FILE use FILE for state\n"); - fprintf(stderr, " -a, --auto only match against interfaces hinted as 'auto'\n"); - fprintf(stderr, " -I, --include PATTERN only match against interfaces matching PATTERN\n"); - fprintf(stderr, " -X, --exclude PATTERN never match against interfaces matching PATTERN\n"); - fprintf(stderr, " -n, --no-act do not actually run any commands\n"); - fprintf(stderr, " -v, --verbose show what commands are being run\n"); - fprintf(stderr, " -E, --executor-path PATH use PATH for executor directory\n"); - fprintf(stderr, " -f, --force force (de)configuration\n"); - fprintf(stderr, " -L, --no-lock do not use a lockfile to serialize state changes\n"); - - exit(status); -} - bool is_ifdown() { @@ -184,67 +162,6 @@ ifupdown_main(int argc, char *argv[]) struct lif_dict state = {}; struct lif_dict collection = {}; - struct option long_options[] = { - {"help", no_argument, 0, 'h'}, - {"version", no_argument, 0, 'V'}, - {"interfaces", required_argument, 0, 'i'}, - {"auto", no_argument, 0, 'a'}, - {"include", required_argument, 0, 'I'}, - {"exclude", required_argument, 0, 'X'}, - {"state-file", required_argument, 0, 'S'}, - {"no-act", no_argument, 0, 'n'}, - {"verbose", no_argument, 0, 'v'}, - {"executor-path", required_argument, 0, 'E'}, - {"force", no_argument, 0, 'f'}, - {"no-lock", no_argument, 0, 'L'}, - {NULL, 0, 0, 0} - }; - - for (;;) - { - int c = getopt_long(argc, argv, "hVi:aI:X:S:nvE:fL", long_options, NULL); - if (c == -1) - break; - - switch (c) { - case 'h': - ifupdown_usage(EXIT_SUCCESS); - break; - case 'V': - lif_common_version(); - break; - case 'a': - match_opts.is_auto = true; - break; - case 'I': - match_opts.include_pattern = optarg; - break; - case 'X': - match_opts.exclude_pattern = optarg; - break; - case 'i': - exec_opts.interfaces_file = optarg; - break; - case 'S': - exec_opts.state_file = optarg; - break; - case 'n': - exec_opts.mock = true; - exec_opts.verbose = true; - break; - case 'v': - exec_opts.verbose = true; - break; - case 'E': - exec_opts.executor_path = optarg; - break; - case 'f': - break; - case 'L': - exec_opts.no_lock = true; - break; - } - } if (!lif_state_read_path(&state, exec_opts.state_file)) { @@ -272,7 +189,7 @@ ifupdown_main(int argc, char *argv[]) return EXIT_SUCCESS; } else if (optind >= argc) - ifupdown_usage(EXIT_FAILURE); + generic_usage(self_applet, EXIT_FAILURE); int idx = optind; for (; idx < argc; idx++) @@ -319,10 +236,16 @@ ifupdown_main(int argc, char *argv[]) struct if_applet ifup_applet = { .name = "ifup", + .desc = "bring interfaces up", .main = ifupdown_main, + .usage = "ifup [options] ", + .groups = { &global_option_group, &match_option_group, &exec_option_group, }, }; struct if_applet ifdown_applet = { .name = "ifdown", + .desc = "take interfaces down", .main = ifupdown_main, + .usage = "ifdown [options] ", + .groups = { &global_option_group, &match_option_group, &exec_option_group, }, }; From ff4822cf0563776137d87df914cbe7a9e557a81c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 12 Aug 2020 16:53:53 -0600 Subject: [PATCH 129/530] build: allow for applets to be customized --- Makefile | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/Makefile b/Makefile index 6762eec..bf50999 100644 --- a/Makefile +++ b/Makefile @@ -47,11 +47,21 @@ MULTICALL_SRC = \ MULTICALL_OBJ = ${MULTICALL_SRC:.c=.o} MULTICALL = ifupdown +CONFIG_IFQUERY ?= Y IFQUERY_SRC = cmd/ifquery.c -IFQUERY_OBJ = ${IFQUERY_SRC:.c=.o} +MULTICALL_${CONFIG_IFQUERY}_OBJ += ${IFQUERY_SRC:.c=.o} +CMDS_${CONFIG_IFQUERY} += ifquery +CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY +CONFIG_IFUPDOWN ?= Y IFUPDOWN_SRC = cmd/ifupdown.c -IFUPDOWN_OBJ = ${IFUPDOWN_SRC:.c=.o} +MULTICALL_${CONFIG_IFUPDOWN}_OBJ += ${IFUPDOWN_SRC:.c=.o} +CMDS_${CONFIG_IFUPDOWN} += ifup ifdown +CPPFLAGS_${CONFIG_IFUPDOWN} += -DCONFIG_IFUPDOWN + +MULTICALL_OBJ += ${MULTICALL_Y_OBJ} +CMDS += ${CMDS_Y} +CPPFLAGS += ${CPPFLAGS_Y} EXECUTOR_SCRIPTS_CORE ?= \ dhcp \ @@ -68,8 +78,6 @@ EXECUTOR_SCRIPTS_STUB ?= CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} -CMDS = ifup ifdown ifquery - TARGET_LIBS = ${LIBIFUPDOWN_LIB} LIBS += ${TARGET_LIBS} ${LIBBSD_LIBS} From b30e0223d03f989c2625633f5d91a707162a9d83 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 12 Aug 2020 16:56:51 -0600 Subject: [PATCH 130/530] multicall: only enable applets actually compiled in --- cmd/multicall.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/cmd/multicall.c b/cmd/multicall.c index ccb7688..8f18f81 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -23,16 +23,28 @@ char *argv0; +#ifdef CONFIG_IFQUERY extern struct if_applet ifquery_applet; +#endif + +#ifdef CONFIG_IFUPDOWN extern struct if_applet ifup_applet; extern struct if_applet ifdown_applet; +#endif + struct if_applet ifupdown_applet; const struct if_applet *self_applet = NULL; struct if_applet *applet_table[] = { +#ifdef CONFIG_IFUPDOWN &ifdown_applet, +#endif +#ifdef CONFIG_IFQUERY &ifquery_applet, +#endif +#ifdef CONFIG_IFUPDOWN &ifup_applet, +#endif &ifupdown_applet, }; From 196c000161c0118715d473c8a4fafdb0fd15fa64 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 12 Aug 2020 17:09:14 -0600 Subject: [PATCH 131/530] build: further cleanup --- Makefile | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/Makefile b/Makefile index bf50999..91aee84 100644 --- a/Makefile +++ b/Makefile @@ -47,18 +47,21 @@ MULTICALL_SRC = \ MULTICALL_OBJ = ${MULTICALL_SRC:.c=.o} MULTICALL = ifupdown -CONFIG_IFQUERY ?= Y -IFQUERY_SRC = cmd/ifquery.c -MULTICALL_${CONFIG_IFQUERY}_OBJ += ${IFQUERY_SRC:.c=.o} -CMDS_${CONFIG_IFQUERY} += ifquery -CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY - +# enable ifup/ifdown applets (+16 KB) CONFIG_IFUPDOWN ?= Y IFUPDOWN_SRC = cmd/ifupdown.c MULTICALL_${CONFIG_IFUPDOWN}_OBJ += ${IFUPDOWN_SRC:.c=.o} CMDS_${CONFIG_IFUPDOWN} += ifup ifdown CPPFLAGS_${CONFIG_IFUPDOWN} += -DCONFIG_IFUPDOWN +# enable ifquery applet (+4 KB) +# [+20 KB without ifup/ifdown] +CONFIG_IFQUERY ?= Y +IFQUERY_SRC = cmd/ifquery.c +MULTICALL_${CONFIG_IFQUERY}_OBJ += ${IFQUERY_SRC:.c=.o} +CMDS_${CONFIG_IFQUERY} += ifquery +CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY + MULTICALL_OBJ += ${MULTICALL_Y_OBJ} CMDS += ${CMDS_Y} CPPFLAGS += ${CPPFLAGS_Y} @@ -76,8 +79,6 @@ EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} EXECUTOR_SCRIPTS_STUB ?= -CMD_OBJ = ${MULTICALL_OBJ} ${IFQUERY_OBJ} ${IFUPDOWN_OBJ} - TARGET_LIBS = ${LIBIFUPDOWN_LIB} LIBS += ${TARGET_LIBS} ${LIBBSD_LIBS} @@ -86,14 +87,14 @@ all: ${MULTICALL} ${CMDS} ${CMDS}: ${MULTICALL} ln -sf ifupdown $@ -${MULTICALL}: ${TARGET_LIBS} ${CMD_OBJ} - ${CC} -o $@ ${CMD_OBJ} ${LIBS} +${MULTICALL}: ${TARGET_LIBS} ${MULTICALL_OBJ} + ${CC} -o $@ ${MULTICALL_OBJ} ${LIBS} ${LIBIFUPDOWN_LIB}: ${LIBIFUPDOWN_OBJ} ${AR} -rcs $@ ${LIBIFUPDOWN_OBJ} clean: - rm -f ${LIBIFUPDOWN_OBJ} ${CMD_OBJ} + rm -f ${LIBIFUPDOWN_OBJ} ${MULTICALL_OBJ} rm -f ${LIBIFUPDOWN_LIB} rm -f ${CMDS} ${MULTICALL} rm -f ${MANPAGES} From db57f7c07c212f974f44d9adad9d9fa393cfa565 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 13 Aug 2020 00:36:15 -0600 Subject: [PATCH 132/530] readme: mention irc channel --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 1d5e51e..ee219f5 100644 --- a/README.md +++ b/README.md @@ -39,3 +39,7 @@ To run the tests, do `make check`. To build the documentation, do `make docs` and `make install_docs`. Building the documentation requires scdoc (`apk add scdoc`). + +## Discussion + +Discuss ifupdown-ng on IRC: irc.as7007.net #ifupdown-ng From 36f0930c27b31598a66a31952a91b8f5550cab67 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 13 Aug 2020 00:36:50 -0600 Subject: [PATCH 133/530] gitignore: ignore .lock files generated by testsuite --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 60655e7..03cfe15 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ ifupdown ifquery ifup ifdown +*.lock From 05e0ac139be5e1c15875b5dfaa3caf60424082e5 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Wed, 12 Aug 2020 17:38:15 -0500 Subject: [PATCH 134/530] ifctrstat: Initial structure for new applet --- .gitignore | 1 + Makefile | 7 +++ cmd/ifctrstat.c | 111 ++++++++++++++++++++++++++++++++++++++++++ cmd/ifctrstat_linux.c | 37 ++++++++++++++ cmd/multicall.c | 7 +++ 5 files changed, 163 insertions(+) create mode 100644 cmd/ifctrstat.c create mode 100644 cmd/ifctrstat_linux.c diff --git a/.gitignore b/.gitignore index 03cfe15..54feeec 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ ifupdown ifquery ifup ifdown +ifctrstat *.lock diff --git a/Makefile b/Makefile index 91aee84..a284e5a 100644 --- a/Makefile +++ b/Makefile @@ -62,6 +62,13 @@ MULTICALL_${CONFIG_IFQUERY}_OBJ += ${IFQUERY_SRC:.c=.o} CMDS_${CONFIG_IFQUERY} += ifquery CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY +# enable ifctrstat applet (+9 KB) +CONFIG_IFCTRSTAT ?= Y +IFCTRSTAT_SRC = cmd/ifctrstat.c cmd/ifctrstat_linux.c +MULTICALL_${CONFIG_IFCTRSTAT}_OBJ += ${IFCTRSTAT_SRC:.c=.o} +CMDS_${CONFIG_IFCTRSTAT} += ifctrstat +CPPFLAGS_${CONFIG_IFCTRSTAT} += -DCONFIG_IFCTRSTAT + MULTICALL_OBJ += ${MULTICALL_Y_OBJ} CMDS += ${CMDS_Y} CPPFLAGS += ${CPPFLAGS_Y} diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c new file mode 100644 index 0000000..aa4460b --- /dev/null +++ b/cmd/ifctrstat.c @@ -0,0 +1,111 @@ +/* + * cmd/ifctrstat.c + * Purpose: Display statistics about interfaces on the system + * + * Copyright (c) 2020 Adélie Software in the Public Benefit, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include +#include +#include +#include +#include "libifupdown/libifupdown.h" +#include "cmd/multicall.h" + +extern const char *avail_counters[]; +extern int avail_counters_count; + +extern const char *read_counter(const char *interface, const char *counter); + +static bool +counter_is_valid(const char *candidate) +{ + for (int i = 0; i < avail_counters_count; i++) + { + if (strcasecmp(avail_counters[i], candidate) == 0) + return true; + } + + return false; +} + +void +ifstats_list_counters(int short_opt, const struct if_option *opt, + const char *opt_arg, const struct if_applet *applet) +{ + (void) short_opt; + (void) opt; + (void) opt_arg; + (void) applet; + + for (int i = 0; i < avail_counters_count; i++) { + fprintf(stdout, "%s\n", avail_counters[i]); + } + + exit(EXIT_SUCCESS); +} + +int +ifstats_main(int argc, char *argv[]) +{ + if (optind >= argc) + generic_usage(self_applet, EXIT_FAILURE); + + int idx = optind; + if (argc - idx < 2) + { + fprintf(stderr, "%s: interface and counter(s) required\n", + argv0); + return EXIT_FAILURE; + } + + const char *iface = argv[idx++]; + + for (; idx < argc; idx++) + { + if (!counter_is_valid(argv[idx])) + { + fprintf(stderr, "%s: counter %s is not valid or not " + "available\n", argv0, argv[idx]); + return EXIT_FAILURE; + } + + errno = 0; + const char *res = read_counter(iface, argv[idx]); + if (!res) + { + fprintf(stderr, "%s: could not determine value of " + "%s for interface %s: %s\n", argv0, + argv[idx], iface, strerror(errno)); + return EXIT_FAILURE; + } + } + + return EXIT_SUCCESS; +} + +static struct if_option local_options[] = { + {'L', "list", NULL, "List available counters", false, ifstats_list_counters} +}; + +static struct if_option_group local_option_group = { + .desc = "Program-specific options", + .group_size = ARRAY_SIZE(local_options), + .group = local_options +}; + +struct if_applet ifctrstat_applet = { + .name = "ifctrstat", + .desc = "Display statistics about an interface", + .main = ifstats_main, + .usage = "ifctrstat [options] \n ifctrstat [options] --list\n", + .groups = { &global_option_group, &local_option_group, NULL } +}; diff --git a/cmd/ifctrstat_linux.c b/cmd/ifctrstat_linux.c new file mode 100644 index 0000000..0d572da --- /dev/null +++ b/cmd/ifctrstat_linux.c @@ -0,0 +1,37 @@ +/* + * cmd/ifctrstat_linux.c + * Purpose: Implement ifstats system-specific routines for Linux + * + * Copyright (c) 2020 Adélie Software in the Public Benefit, Inc. + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include +#include + +const char *avail_counters[] = { + "rx.octets", + "rx.packets", + "rx.discard", + "rx.errors", + "tx.octets", + "tx.packets", + "tx.discard", + "tx.errors" +}; + +size_t avail_counters_count = sizeof(avail_counters) / sizeof(*avail_counters); + +const char * +read_counter(const char *interface, const char *counter) +{ + errno = ENOSYS; + return NULL; +} diff --git a/cmd/multicall.c b/cmd/multicall.c index 8f18f81..0c041ad 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -32,10 +32,17 @@ extern struct if_applet ifup_applet; extern struct if_applet ifdown_applet; #endif +#ifdef CONFIG_IFCTRSTAT +extern struct if_applet ifctrstat_applet; +#endif + struct if_applet ifupdown_applet; const struct if_applet *self_applet = NULL; struct if_applet *applet_table[] = { +#ifdef CONFIG_IFCTRSTAT + &ifctrstat_applet, +#endif #ifdef CONFIG_IFUPDOWN &ifdown_applet, #endif From 95d943ee44e3f0f4ca2fcb48bf0f2096fd21f785 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Fri, 14 Aug 2020 10:17:01 -0500 Subject: [PATCH 135/530] ifctrstat: Misc style fixes --- Makefile | 2 +- cmd/{ifctrstat_linux.c => ifctrstat-linux.c} | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) rename cmd/{ifctrstat_linux.c => ifctrstat-linux.c} (81%) diff --git a/Makefile b/Makefile index a284e5a..4df2adf 100644 --- a/Makefile +++ b/Makefile @@ -64,7 +64,7 @@ CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY # enable ifctrstat applet (+9 KB) CONFIG_IFCTRSTAT ?= Y -IFCTRSTAT_SRC = cmd/ifctrstat.c cmd/ifctrstat_linux.c +IFCTRSTAT_SRC = cmd/ifctrstat.c cmd/ifctrstat-${LAYOUT}.c MULTICALL_${CONFIG_IFCTRSTAT}_OBJ += ${IFCTRSTAT_SRC:.c=.o} CMDS_${CONFIG_IFCTRSTAT} += ifctrstat CPPFLAGS_${CONFIG_IFCTRSTAT} += -DCONFIG_IFCTRSTAT diff --git a/cmd/ifctrstat_linux.c b/cmd/ifctrstat-linux.c similarity index 81% rename from cmd/ifctrstat_linux.c rename to cmd/ifctrstat-linux.c index 0d572da..664e37e 100644 --- a/cmd/ifctrstat_linux.c +++ b/cmd/ifctrstat-linux.c @@ -1,6 +1,6 @@ /* - * cmd/ifctrstat_linux.c - * Purpose: Implement ifstats system-specific routines for Linux + * cmd/ifctrstat-linux.c + * Purpose: Implement ifctrstat system-specific routines for Linux * * Copyright (c) 2020 Adélie Software in the Public Benefit, Inc. * @@ -15,6 +15,7 @@ #include #include +#include "multicall.h" const char *avail_counters[] = { "rx.octets", @@ -27,7 +28,7 @@ const char *avail_counters[] = { "tx.errors" }; -size_t avail_counters_count = sizeof(avail_counters) / sizeof(*avail_counters); +size_t avail_counters_count = ARRAY_SIZE(avail_counters); const char * read_counter(const char *interface, const char *counter) From 6106164d7c2fe45bd6c6875af7ff41acdab6e9d0 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Fri, 14 Aug 2020 10:49:45 -0500 Subject: [PATCH 136/530] ifctrstat: Add ability to output counter values --- Makefile | 2 +- cmd/ifctrstat-linux.c | 68 +++++++++++++++++++++++++++++++++++++++++-- cmd/ifctrstat.c | 58 +++++++++++++++++++++++++++--------- 3 files changed, 111 insertions(+), 17 deletions(-) diff --git a/Makefile b/Makefile index 4df2adf..d050032 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ MULTICALL_${CONFIG_IFQUERY}_OBJ += ${IFQUERY_SRC:.c=.o} CMDS_${CONFIG_IFQUERY} += ifquery CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY -# enable ifctrstat applet (+9 KB) +# enable ifctrstat applet (+16 KB) CONFIG_IFCTRSTAT ?= Y IFCTRSTAT_SRC = cmd/ifctrstat.c cmd/ifctrstat-${LAYOUT}.c MULTICALL_${CONFIG_IFCTRSTAT}_OBJ += ${IFCTRSTAT_SRC:.c=.o} diff --git a/cmd/ifctrstat-linux.c b/cmd/ifctrstat-linux.c index 664e37e..52d48b8 100644 --- a/cmd/ifctrstat-linux.c +++ b/cmd/ifctrstat-linux.c @@ -14,7 +14,9 @@ */ #include +#include #include +#include #include "multicall.h" const char *avail_counters[] = { @@ -30,9 +32,69 @@ const char *avail_counters[] = { size_t avail_counters_count = ARRAY_SIZE(avail_counters); -const char * +char * read_counter(const char *interface, const char *counter) { - errno = ENOSYS; - return NULL; + FILE *fp; + const char *path; + char full_path[PATH_MAX]; + char buffer[1024]; + size_t in_count; + + errno = 0; + + if (strcasecmp(counter, "rx.octets") == 0) + { + path = "rx_bytes"; + } else if (strcasecmp(counter, "rx.packets") == 0) { + path = "rx_packets"; + } else if (strcasecmp(counter, "rx.discard") == 0) { + path = "rx_dropped"; + } else if (strcasecmp(counter, "rx.errors") == 0) { + path = "rx_errors"; + } else if (strcasecmp(counter, "tx.octets") == 0) { + path = "tx_bytes"; + } else if (strcasecmp(counter, "tx.packets") == 0) { + path = "tx_packets"; + } else if (strcasecmp(counter, "tx.discard") == 0) { + path = "tx_dropped"; + } else if (strcasecmp(counter, "tx.errors") == 0) { + path = "tx_errors"; + } else { + errno = ENOSYS; + return NULL; + } + + if (snprintf(full_path, PATH_MAX, "/sys/class/net/%s/statistics/%s", interface, path) > PATH_MAX) + { + errno = ENOMEM; + return NULL; + } + + fp = fopen(full_path, "r"); + if (!fp) + { + return NULL; + } + + in_count = fread(buffer, 1, sizeof(buffer), fp); + + if (in_count == sizeof(buffer)) + { + errno = ENOMEM; + fclose(fp); + return NULL; + } + + if (ferror(fp)) + { + return NULL; + } + + fclose(fp); + + /* take away the \n, we add our own */ + buffer[in_count - 1] = '\0'; + + return strdup(buffer); } diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index aa4460b..1d376cd 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -37,16 +37,44 @@ counter_is_valid(const char *candidate) return false; } +static void +print_counter(const char *iface, const char *name, const char *value) +{ + fprintf(stdout, "%s: %s\n", name, value); +} + +static int +print_all_counters(const char *iface) +{ + int code = EXIT_SUCCESS; + const char *res; + + for (int i = 0; i < avail_counters_count; i++) { + const char *ctr = avail_counters[i]; + + res = read_counter(iface, ctr); + if (!res) + { + fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, ctr, iface, strerror(errno)); + code = EXIT_FAILURE; + } else { + print_counter(iface, ctr, res); + } + } + + return code; +} + void -ifstats_list_counters(int short_opt, const struct if_option *opt, - const char *opt_arg, const struct if_applet *applet) +ifctrstat_list_counters(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) { (void) short_opt; (void) opt; (void) opt_arg; (void) applet; - for (int i = 0; i < avail_counters_count; i++) { + for (int i = 0; i < avail_counters_count; i++) + { fprintf(stdout, "%s\n", avail_counters[i]); } @@ -54,27 +82,31 @@ ifstats_list_counters(int short_opt, const struct if_option *opt, } int -ifstats_main(int argc, char *argv[]) +ifctrstat_main(int argc, char *argv[]) { if (optind >= argc) generic_usage(self_applet, EXIT_FAILURE); int idx = optind; - if (argc - idx < 2) + if (argc - idx == 0) { - fprintf(stderr, "%s: interface and counter(s) required\n", + fprintf(stderr, "%s: interface required\n", argv0); return EXIT_FAILURE; } const char *iface = argv[idx++]; + if (argc - idx == 0) + { + return print_all_counters(iface); + } + for (; idx < argc; idx++) { if (!counter_is_valid(argv[idx])) { - fprintf(stderr, "%s: counter %s is not valid or not " - "available\n", argv0, argv[idx]); + fprintf(stderr, "%s: counter %s is not valid or not available\n", argv0, argv[idx]); return EXIT_FAILURE; } @@ -82,18 +114,18 @@ ifstats_main(int argc, char *argv[]) const char *res = read_counter(iface, argv[idx]); if (!res) { - fprintf(stderr, "%s: could not determine value of " - "%s for interface %s: %s\n", argv0, - argv[idx], iface, strerror(errno)); + fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, argv[idx], iface, strerror(errno)); return EXIT_FAILURE; } + + print_counter(iface, argv[idx], res); } return EXIT_SUCCESS; } static struct if_option local_options[] = { - {'L', "list", NULL, "List available counters", false, ifstats_list_counters} + {'L', "list", NULL, "List available counters", false, ifctrstat_list_counters} }; static struct if_option_group local_option_group = { @@ -105,7 +137,7 @@ static struct if_option_group local_option_group = { struct if_applet ifctrstat_applet = { .name = "ifctrstat", .desc = "Display statistics about an interface", - .main = ifstats_main, + .main = ifctrstat_main, .usage = "ifctrstat [options] \n ifctrstat [options] --list\n", .groups = { &global_option_group, &local_option_group, NULL } }; From 7b45d3939d6e6ad5cdedd5943f020de6e28f3246 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Fri, 14 Aug 2020 14:27:23 -0500 Subject: [PATCH 137/530] ifctrstat: Add -n option to omit label printing --- cmd/ifctrstat.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index 1d376cd..0409438 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -14,9 +14,10 @@ */ #include +#include +#include #include #include -#include #include "libifupdown/libifupdown.h" #include "cmd/multicall.h" @@ -25,6 +26,8 @@ extern int avail_counters_count; extern const char *read_counter(const char *interface, const char *counter); +static bool show_label = true; + static bool counter_is_valid(const char *candidate) { @@ -40,7 +43,10 @@ counter_is_valid(const char *candidate) static void print_counter(const char *iface, const char *name, const char *value) { - fprintf(stdout, "%s: %s\n", name, value); + if (show_label) + fprintf(stdout, "%s: %s\n", name, value); + else + fprintf(stdout, "%s\n", value); } static int @@ -81,6 +87,17 @@ ifctrstat_list_counters(int short_opt, const struct if_option *opt, const char * exit(EXIT_SUCCESS); } +void +ifctrstat_set_nolabel(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +{ + (void) short_opt; + (void) opt; + (void) opt_arg; + (void) applet; + + show_label = false; +} + int ifctrstat_main(int argc, char *argv[]) { @@ -125,7 +142,8 @@ ifctrstat_main(int argc, char *argv[]) } static struct if_option local_options[] = { - {'L', "list", NULL, "List available counters", false, ifctrstat_list_counters} + {'L', "list", NULL, "List available counters", false, ifctrstat_list_counters}, + {'n', "no-label", NULL, "Print value without counter label", false, ifctrstat_set_nolabel} }; static struct if_option_group local_option_group = { From 1a11bb768f450a512304e5f1235e3ce395ce59c1 Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Mon, 17 Aug 2020 14:13:16 -0500 Subject: [PATCH 138/530] ifctrstat: Use new structure and recalculate binary size --- Makefile | 2 +- cmd/ifctrstat-linux.c | 48 ++++++++++++++++++++----------------------- cmd/ifctrstat.c | 8 ++++---- 3 files changed, 27 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index d050032..8ec124a 100644 --- a/Makefile +++ b/Makefile @@ -62,7 +62,7 @@ MULTICALL_${CONFIG_IFQUERY}_OBJ += ${IFQUERY_SRC:.c=.o} CMDS_${CONFIG_IFQUERY} += ifquery CPPFLAGS_${CONFIG_IFQUERY} += -DCONFIG_IFQUERY -# enable ifctrstat applet (+16 KB) +# enable ifctrstat applet (+1 KB) CONFIG_IFCTRSTAT ?= Y IFCTRSTAT_SRC = cmd/ifctrstat.c cmd/ifctrstat-${LAYOUT}.c MULTICALL_${CONFIG_IFCTRSTAT}_OBJ += ${IFCTRSTAT_SRC:.c=.o} diff --git a/cmd/ifctrstat-linux.c b/cmd/ifctrstat-linux.c index 52d48b8..e7dcfa3 100644 --- a/cmd/ifctrstat-linux.c +++ b/cmd/ifctrstat-linux.c @@ -19,19 +19,28 @@ #include #include "multicall.h" -const char *avail_counters[] = { - "rx.octets", - "rx.packets", - "rx.discard", - "rx.errors", - "tx.octets", - "tx.packets", - "tx.discard", - "tx.errors" +struct counter_desc { + const char *name; + const void *data; +} avail_counters[] = { + {"rx.discard", "rx_dropped"}, + {"rx.errors", "rx_errors"}, + {"rx.octets", "rx_bytes"}, + {"rx.packets", "rx_packets"}, + {"tx.discard", "tx_dropped"}, + {"tx.errors", "tx_errors"}, + {"tx.octets", "tx_bytes"}, + {"tx.packets", "tx_packets"} }; size_t avail_counters_count = ARRAY_SIZE(avail_counters); +static int +counter_compare(const void *key, const void *candidate) +{ + return strcasecmp((const char *)key, ((struct counter_desc *)candidate)->name); +} + char * read_counter(const char *interface, const char *counter) { @@ -40,26 +49,13 @@ read_counter(const char *interface, const char *counter) char full_path[PATH_MAX]; char buffer[1024]; size_t in_count; + struct counter_desc *ctrdata; errno = 0; - if (strcasecmp(counter, "rx.octets") == 0) - { - path = "rx_bytes"; - } else if (strcasecmp(counter, "rx.packets") == 0) { - path = "rx_packets"; - } else if (strcasecmp(counter, "rx.discard") == 0) { - path = "rx_dropped"; - } else if (strcasecmp(counter, "rx.errors") == 0) { - path = "rx_errors"; - } else if (strcasecmp(counter, "tx.octets") == 0) { - path = "tx_bytes"; - } else if (strcasecmp(counter, "tx.packets") == 0) { - path = "tx_packets"; - } else if (strcasecmp(counter, "tx.discard") == 0) { - path = "tx_dropped"; - } else if (strcasecmp(counter, "tx.errors") == 0) { - path = "tx_errors"; + ctrdata = bsearch(counter, avail_counters, avail_counters_count, sizeof(struct counter_desc), counter_compare); + if (ctrdata) { + path = (const char *)ctrdata->data; } else { errno = ENOSYS; return NULL; diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index 0409438..9c12231 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -21,7 +21,7 @@ #include "libifupdown/libifupdown.h" #include "cmd/multicall.h" -extern const char *avail_counters[]; +extern struct counter_desc { const char *name; const void *data; } avail_counters[]; extern int avail_counters_count; extern const char *read_counter(const char *interface, const char *counter); @@ -33,7 +33,7 @@ counter_is_valid(const char *candidate) { for (int i = 0; i < avail_counters_count; i++) { - if (strcasecmp(avail_counters[i], candidate) == 0) + if (strcasecmp(avail_counters[i].name, candidate) == 0) return true; } @@ -56,7 +56,7 @@ print_all_counters(const char *iface) const char *res; for (int i = 0; i < avail_counters_count; i++) { - const char *ctr = avail_counters[i]; + const char *ctr = avail_counters[i].name; res = read_counter(iface, ctr); if (!res) @@ -81,7 +81,7 @@ ifctrstat_list_counters(int short_opt, const struct if_option *opt, const char * for (int i = 0; i < avail_counters_count; i++) { - fprintf(stdout, "%s\n", avail_counters[i]); + fprintf(stdout, "%s\n", avail_counters[i].name); } exit(EXIT_SUCCESS); From 327e738a557cb4829a125c0258d99ff5c5299b4b Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Mon, 17 Aug 2020 14:59:19 -0500 Subject: [PATCH 139/530] Refactor how options are handled --- cmd/ifctrstat.c | 16 +++---- cmd/ifquery.c | 59 +++++++++++++----------- cmd/multicall-exec-options.c | 85 ++++++++++++++++++++--------------- cmd/multicall-match-options.c | 38 ++++++++-------- cmd/multicall-options.c | 10 ++--- cmd/multicall.h | 2 +- 6 files changed, 112 insertions(+), 98 deletions(-) diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index 9c12231..235fb5f 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -43,6 +43,7 @@ counter_is_valid(const char *candidate) static void print_counter(const char *iface, const char *name, const char *value) { + (void) iface; if (show_label) fprintf(stdout, "%s: %s\n", name, value); else @@ -71,13 +72,10 @@ print_all_counters(const char *iface) return code; } -void -ifctrstat_list_counters(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +static void +ifctrstat_list_counters(const char *opt_arg) { - (void) short_opt; - (void) opt; (void) opt_arg; - (void) applet; for (int i = 0; i < avail_counters_count; i++) { @@ -87,14 +85,10 @@ ifctrstat_list_counters(int short_opt, const struct if_option *opt, const char * exit(EXIT_SUCCESS); } -void -ifctrstat_set_nolabel(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +static void +ifctrstat_set_nolabel(const char *opt_arg) { - (void) short_opt; - (void) opt; (void) opt_arg; - (void) applet; - show_label = false; } diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 0612823..520219e 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -222,36 +222,45 @@ list_state(struct lif_dict *state, struct match_options *opts) static bool listing = false, listing_stat = false; static void -handle_local(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +set_listing(const char *opt_arg) { - (void) opt; - (void) applet; + (void) opt_arg; + listing = true; +} - switch (short_opt) { - case 'L': - listing = true; - break; - case 'P': - match_opts.pretty_print = true; - break; - case 's': - listing_stat = true; - break; - case 'D': - match_opts.dot = true; - break; - case 'p': - match_opts.property = opt_arg; - break; - } +static void +set_show_state(const char *opt_arg) +{ + (void) opt_arg; + listing_stat = true; +} + +static void +set_pretty_print(const char *opt_arg) +{ + (void) opt_arg; + match_opts.pretty_print = true; +} + +static void +set_output_dot(const char *opt_arg) +{ + (void) opt_arg; + match_opts.dot = true; +} + +static void +set_property(const char *opt_arg) +{ + match_opts.property = opt_arg; } static struct if_option local_options[] = { - {'s', "state", NULL, "show configured state", false, handle_local}, - {'p', "property", "property PROPERTY", "print values of properties matching PROPERTY", true, handle_local}, - {'D', "dot", NULL, "generate a dependency graph", false, handle_local}, - {'L', "list", NULL, "list matching interfaces", false, handle_local}, - {'P', "pretty-print", NULL, "pretty print the interfaces instead of just listing", false, handle_local}, + {'s', "state", NULL, "show configured state", false, set_show_state}, + {'p', "property", "property PROPERTY", "print values of properties matching PROPERTY", true, set_property}, + {'D', "dot", NULL, "generate a dependency graph", false, set_output_dot}, + {'L', "list", NULL, "list matching interfaces", false, set_listing}, + {'P', "pretty-print", NULL, "pretty print the interfaces instead of just listing", false, set_pretty_print}, }; static struct if_option_group local_option_group = { diff --git a/cmd/multicall-exec-options.c b/cmd/multicall-exec-options.c index 0ebe85d..c87e79e 100644 --- a/cmd/multicall-exec-options.c +++ b/cmd/multicall-exec-options.c @@ -27,47 +27,60 @@ struct lif_execute_opts exec_opts = { .state_file = STATE_FILE }; -static void handle_exec(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +static void +set_interfaces_file(const char *opt_arg) { - (void) opt; - (void) applet; + exec_opts.interfaces_file = opt_arg; +} - switch (short_opt) - { - case 'i': - exec_opts.interfaces_file = opt_arg; - break; - case 'S': - exec_opts.state_file = opt_arg; - break; - case 'n': - exec_opts.mock = true; - exec_opts.verbose = true; - break; - case 'v': - exec_opts.verbose = true; - break; - case 'E': - exec_opts.executor_path = opt_arg; - break; - case 'f': - break; - case 'l': - exec_opts.no_lock = true; - break; - default: - break; - } +static void +set_state_file(const char *opt_arg) +{ + exec_opts.state_file = opt_arg; +} + +static void +set_no_act(const char *opt_arg) +{ + (void) opt_arg; + exec_opts.mock = true; + exec_opts.verbose = true; +} + +static void +set_verbose(const char *opt_arg) +{ + (void) opt_arg; + exec_opts.verbose = true; +} + +static void +set_executor_path(const char *opt_arg) +{ + exec_opts.executor_path = opt_arg; +} + +static void +set_no_lock(const char *opt_arg) +{ + (void) opt_arg; + exec_opts.no_lock = true; +} + +static void +no_op(const char *opt_arg) +{ + (void) opt_arg; } static struct if_option exec_options[] = { - {'f', "force", NULL, "force (de)configuration", true, handle_exec}, - {'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, handle_exec}, - {'l', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, handle_exec}, - {'n', "no-act", NULL, "do not actually run any commands", false, handle_exec}, - {'v', "verbose", NULL, "show what commands are being run", false, handle_exec}, - {'E', "executor-path", "executor-path PATH", "use PATH for executor directory", true, handle_exec}, - {'S', "state-file", "state-file FILE", "use FILE for state", true, handle_exec}, + {'f', "force", NULL, "force (de)configuration", true, no_op}, + {'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, set_interfaces_file}, + {'l', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, set_no_lock}, + {'n', "no-act", NULL, "do not actually run any commands", false, set_no_act}, + {'v', "verbose", NULL, "show what commands are being run", false, set_verbose}, + {'E', "executor-path", "executor-path PATH", "use PATH for executor directory", true, set_executor_path}, + {'S', "state-file", "state-file FILE", "use FILE for state", true, set_state_file}, }; struct if_option_group exec_option_group = { diff --git a/cmd/multicall-match-options.c b/cmd/multicall-match-options.c index d89056a..4a03f3a 100644 --- a/cmd/multicall-match-options.c +++ b/cmd/multicall-match-options.c @@ -23,31 +23,29 @@ struct match_options match_opts = {}; -static void handle_match(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet) +static void +set_auto(const char *opt_arg) { - (void) opt; - (void) applet; + (void) opt_arg; + match_opts.is_auto = true; +} - switch (short_opt) - { - case 'a': - match_opts.is_auto = true; - break; - case 'I': - match_opts.include_pattern = opt_arg; - break; - case 'X': - match_opts.exclude_pattern = opt_arg; - break; - default: - break; - } +static void +set_include_pattern(const char *opt_arg) +{ + match_opts.include_pattern = opt_arg; +} + +static void +set_exclude_pattern(const char *opt_arg) +{ + match_opts.include_pattern = opt_arg; } static struct if_option match_options[] = { - {'a', "auto", NULL, "only match against interfaces hinted as 'auto'", false, handle_match}, - {'I', "include", "include PATTERN", "only match against interfaces matching PATTERN", true, handle_match}, - {'X', "exclude", "exclude PATTERN", "never match against interfaces matching PATTERN", true, handle_match}, + {'a', "auto", NULL, "only match against interfaces hinted as 'auto'", false, set_auto}, + {'I', "include", "include PATTERN", "only match against interfaces matching PATTERN", true, set_include_pattern}, + {'X', "exclude", "exclude PATTERN", "never match against interfaces matching PATTERN", true, set_exclude_pattern}, }; struct if_option_group match_option_group = { diff --git a/cmd/multicall-options.c b/cmd/multicall-options.c index 9037264..8daf7ae 100644 --- a/cmd/multicall-options.c +++ b/cmd/multicall-options.c @@ -21,6 +21,8 @@ #include #include "cmd/multicall.h" +extern const struct if_applet *self_applet; + void generic_usage(const struct if_applet *applet, int result) { @@ -66,13 +68,11 @@ generic_usage(const struct if_applet *applet, int result) } static void -generic_usage_request(int short_opt, const struct if_option *option, const char *opt_arg, const struct if_applet *applet) +generic_usage_request(const char *opt_arg) { - (void) short_opt; - (void) option; (void) opt_arg; - generic_usage(applet, EXIT_SUCCESS); + generic_usage(self_applet, EXIT_SUCCESS); } static struct if_option global_options[] = { @@ -154,6 +154,6 @@ process_options(const struct if_applet *applet, int argc, char *argv[]) if (opt == NULL) break; - opt->handle(c, opt, optarg, applet); + opt->handle(optarg); } } diff --git a/cmd/multicall.h b/cmd/multicall.h index 23cb836..904079b 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -30,7 +30,7 @@ struct if_option { const char *long_opt_desc; const char *desc; bool require_argument; - void (*const handle)(int short_opt, const struct if_option *opt, const char *opt_arg, const struct if_applet *applet); + void (*const handle)(const char *opt_arg); }; struct if_option_group { From e2959275b628151f64ce89ee2f5a36fa20c9778b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:12:34 -0600 Subject: [PATCH 140/530] multicall: add ability for applets to specify a manpage reference --- cmd/multicall-options.c | 3 +++ cmd/multicall.h | 1 + 2 files changed, 4 insertions(+) diff --git a/cmd/multicall-options.c b/cmd/multicall-options.c index 9037264..0c7597a 100644 --- a/cmd/multicall-options.c +++ b/cmd/multicall-options.c @@ -62,6 +62,9 @@ generic_usage(const struct if_applet *applet, int result) } } + if (applet->manpage != NULL) + fprintf(stderr, "\nFor more information: man %s\n", applet->manpage); + exit(result); } diff --git a/cmd/multicall.h b/cmd/multicall.h index 23cb836..0843580 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -43,6 +43,7 @@ struct if_applet { const char *name; const char *desc; const char *usage; + const char *manpage; int (*const main)(int argc, char *argv[]); const struct if_option_group *groups[16]; }; From 520b831bdf8f7a510be6853e242c8dbb173f53f3 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:14:33 -0600 Subject: [PATCH 141/530] cmd: add manpage xrefs where we have manpages already --- cmd/ifquery.c | 1 + cmd/ifupdown.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 0612823..9bc0b9d 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -329,5 +329,6 @@ struct if_applet ifquery_applet = { .desc = "query interface configuration", .main = ifquery_main, .usage = "ifquery [options] \n ifquery [options] --list", + .manpage = "8 ifquery", .groups = { &global_option_group, &match_option_group, &exec_option_group, &local_option_group }, }; diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index c1bce3a..0fa7e29 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -239,6 +239,7 @@ struct if_applet ifup_applet = { .desc = "bring interfaces up", .main = ifupdown_main, .usage = "ifup [options] ", + .manpage = "8 ifup", .groups = { &global_option_group, &match_option_group, &exec_option_group, }, }; @@ -247,5 +248,6 @@ struct if_applet ifdown_applet = { .desc = "take interfaces down", .main = ifupdown_main, .usage = "ifdown [options] ", + .manpage = "8 ifdown", .groups = { &global_option_group, &match_option_group, &exec_option_group, }, }; From 99571a4c0327918e27a7095377b6b05efa3752c0 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:20:55 -0600 Subject: [PATCH 142/530] ifctrstat: fix style issues --- cmd/ifctrstat.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index 9c12231..ec0d1d8 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -43,6 +43,8 @@ counter_is_valid(const char *candidate) static void print_counter(const char *iface, const char *name, const char *value) { + (void) iface; + if (show_label) fprintf(stdout, "%s: %s\n", name, value); else @@ -55,7 +57,8 @@ print_all_counters(const char *iface) int code = EXIT_SUCCESS; const char *res; - for (int i = 0; i < avail_counters_count; i++) { + for (int i = 0; i < avail_counters_count; i++) + { const char *ctr = avail_counters[i].name; res = read_counter(iface, ctr); @@ -63,7 +66,9 @@ print_all_counters(const char *iface) { fprintf(stderr, "%s: could not determine value of %s for interface %s: %s\n", argv0, ctr, iface, strerror(errno)); code = EXIT_FAILURE; - } else { + } + else + { print_counter(iface, ctr, res); } } From 9928beef682154fcd110ba681421197fcb412f9a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:32:07 -0600 Subject: [PATCH 143/530] doc: add ifctrstat(8) manpage --- Makefile | 3 ++- doc/ifctrstat.scd | 39 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) create mode 100644 doc/ifctrstat.scd diff --git a/Makefile b/Makefile index 8ec124a..ef9acff 100644 --- a/Makefile +++ b/Makefile @@ -127,7 +127,8 @@ install: all MANPAGES_8 = \ doc/ifquery.8 \ doc/ifup.8 \ - doc/ifdown.8 + doc/ifdown.8 \ + doc/ifctrstat.8 MANPAGES_5 = \ doc/interfaces.5 diff --git a/doc/ifctrstat.scd b/doc/ifctrstat.scd new file mode 100644 index 0000000..3f17721 --- /dev/null +++ b/doc/ifctrstat.scd @@ -0,0 +1,39 @@ +ifctrstat(8) + +# NAME + +ifctrstat - display interface statistics + +# SYNOPSIS + +*ifctrstat* [<_options_>...] <_interface_> <_counter_> + +*ifctrstat* [<_options_>...] -L|--list + +# DESCRIPTION + +*ifctrstat* is used to query interface statistic counters in +a kernel-agnostic way. This is useful for heterogenous +environments where multiple kernels may be in use. + +# OPTIONS + +*-h, --help* + Display supported options to ifctrstat. + +*-n, --no-label* + Display the requested counter without its label. + +*-L, --list* + List available counters on this system. + +*-V, --version* + Print the ifupdown-ng version and exit. + +# SEE ALSO + +*ifquery*(8) + +# AUTHORS + +A. Wilcox From 0a3f1e33a857633578288c4ad009b7707518bede Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:36:15 -0600 Subject: [PATCH 144/530] ifctrstat: lower-case help text for program-specific options --- cmd/ifctrstat.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index ec0d1d8..85d2ec7 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -147,8 +147,8 @@ ifctrstat_main(int argc, char *argv[]) } static struct if_option local_options[] = { - {'L', "list", NULL, "List available counters", false, ifctrstat_list_counters}, - {'n', "no-label", NULL, "Print value without counter label", false, ifctrstat_set_nolabel} + {'L', "list", NULL, "list available counters", false, ifctrstat_list_counters}, + {'n', "no-label", NULL, "print value without counter label", false, ifctrstat_set_nolabel} }; static struct if_option_group local_option_group = { From b084f1c99c0c3f0a4035be7a8f25816c4361097a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:36:35 -0600 Subject: [PATCH 145/530] ifctrstat: add manpage xref --- cmd/ifctrstat.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmd/ifctrstat.c b/cmd/ifctrstat.c index 85d2ec7..24a5e5b 100644 --- a/cmd/ifctrstat.c +++ b/cmd/ifctrstat.c @@ -161,6 +161,7 @@ struct if_applet ifctrstat_applet = { .name = "ifctrstat", .desc = "Display statistics about an interface", .main = ifctrstat_main, - .usage = "ifctrstat [options] \n ifctrstat [options] --list\n", + .usage = "ifctrstat [options] \n ifctrstat [options] --list", + .manpage = "8 ifctrstat", .groups = { &global_option_group, &local_option_group, NULL } }; From f28270418696561fdcd8c5e111379f9d8ed76d16 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 14:42:30 -0600 Subject: [PATCH 146/530] README: requires keyword is not necessarily required anymore --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ee219f5..50ccfc4 100644 --- a/README.md +++ b/README.md @@ -8,10 +8,10 @@ ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. ![Dependency resolution example](doc/img/dependency-resolution.png) ifupdown-ng uses a dependency resolver to determine interface bring-up order -in a deterministic way. To use this feature, you must declare relationships -between interfaces with the `requires` keyword. This keeps the implementation -efficient. For convenience, the `requires` keyword is exported to executors -as the `IF_REQUIRES` environment variable. +in a deterministic way. + +This is accomplished through a combination of manual hinting using the `requires` +keyword and dependency learning using native executors. For compatibility with some legacy ifupdown executors, we also provide the `requires` keyword under other environment variables in some cases. From 06e2d3b03581ba75de4b63f8130aa8a86aaee083 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 15:13:53 -0600 Subject: [PATCH 147/530] add admin guide --- doc/ADMIN-GUIDE.md | 143 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 doc/ADMIN-GUIDE.md diff --git a/doc/ADMIN-GUIDE.md b/doc/ADMIN-GUIDE.md new file mode 100644 index 0000000..7ff5fd9 --- /dev/null +++ b/doc/ADMIN-GUIDE.md @@ -0,0 +1,143 @@ +# ifupdown-ng for system administrators + +ifupdown-ng is a network device manager which is backwards +compatible with traditional ifup and ifdown as used on Debian +and Alpine systems, while solving many design deficits with +the original approach through robust error handling and the +use of a dependency-solver to determine interface bring-up +order. + +This guide is intended to walk users through using the +ifupdown-ng system without any assumption of familiarity +with the legacy ifupdown system. + +## Important Filesystem Paths + +The ifupdown-ng system uses the following paths, ranked +in order of importance: + +* `/etc/network/interfaces`: the interface configuration + database, which contains information about what + interfaces should be configured. + +* `/run/ifstate`: the interface state file, which denotes + what physical interfaces are configured, and what + interface definition they are configured as. + +* `/usr/libexec/ifupdown-ng`: this directory contains the + native ifupdown-ng executors, which are run as necessary + to configure an interface. See the ifupdown-executor(7) + manual page for more information on how these programs + are written. + +* `/etc/network/if-{up|down|pre-up|post-down}.d`: + these directories contain scripts that are run when an + interface is brought up or down. In general, they follow + the same contract described in ifupdown-executor(7). + +All configuration examples in this guide concern the +`/etc/network/interfaces` file. + +## Basic Configuration + +To begin with, lets look at a basic configuration for a +desktop computer. This scenario involves using the DHCP +helper to learn an IPv4 address dynamically. + +In this case, the `/etc/network/interfaces` file would +look like: + +``` +auto eth0 +iface eth0 + use dhcp +``` + +These configuration statements do two things: designate +that `eth0` should be started automatically with the `auto` +keyword, and designate that the `dhcp` executor should be +used to configure the interface. + +As a more detailed explanation, here is a commented version: + +``` +# Start eth0 automatically. +auto eth0 + +# Begin an interface definition for eth0. +iface eth0 + + # Use the dhcp executor to configure eth0. + use dhcp +``` + +## IPv6 RA Configuration + +With IPv6, stateless auto-configuration is typically used to +configure network interfaces. If you are not interested in +using IPv4 at all, you can simply use the `ipv6-ra` executor +to ensure that an interface is configured to accept IPv6 RA +advertisements: + +``` +auto eth0 +iface eth0 + use ipv6-ra +``` + +## Static Configuration + +We can use the `static` executor to configure static IPv4 and +IPv6 addresses. If you use the `address` keyword, the `static` +executor will automatically be used to configure the interface: + +``` +auto eth0 +iface eth0 + address 203.0.113.2/24 + gateway 203.0.113.1 +``` + +### Multi-homing + +A typical scenario on servers is multi-homing, where a server +has multiple IP addresses on a single interface. In this case +you simply add additional `address` lines like this: + +``` +auto eth0 +iface eth0 + address 203.0.113.2/24 + address 203.0.113.3/24 + address 203.0.113.4/24 + gateway 203.0.113.1 +``` + +### Dual-stack configurations + +Another typical scenario for servers is to run a dual-stack +configuration, where interfaces have both an IPv4 and an IPv6 +address. This is accomplished in a similar way as multi-homing. +You specify the IPv4 and IPv6 addresses you want, followed by +gateways for each: + +``` +auto eth0 +iface eth0 + address 203.0.113.2/24 + address 203.0.113.3/24 + address 203.0.113.4/24 + gateway 203.0.113.1 + + address 2001:db8:1000:2::2/64 + address 2001:db8:1000:2::3/64 + address 2001:db8:1000:2::4/64 + gateway 2001:db8:1000:2::1 +``` + +## Questions + +If you have further questions about how to use ifupdown-ng to +configure a specific scenario, drop by the [ifupdown-ng IRC channel][irc]. + + [irc]: irc://irc.as7007.net/#ifupdown-ng From fb38e22cd13a97945520697860de8f0cd6ed8156 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 15:26:02 -0600 Subject: [PATCH 148/530] admin guide: expand on dependency relationships --- doc/ADMIN-GUIDE.md | 60 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/doc/ADMIN-GUIDE.md b/doc/ADMIN-GUIDE.md index 7ff5fd9..7a9c30f 100644 --- a/doc/ADMIN-GUIDE.md +++ b/doc/ADMIN-GUIDE.md @@ -135,6 +135,66 @@ iface eth0 gateway 2001:db8:1000:2::1 ``` +### Relationships + +As previously mentioned, ifupdown-ng features a dependency +resolver that allows for determining the interface configuration +order. + +![Dependency resolution example](img/dependency-resolution.png) + +In order to make use of this, dependencies can be managed in one +of two ways: + +#### Explicit dependency management using `requires` + +The `requires` keyword can be used to manage explicit +dependencies: + +``` +auto eth0 +iface eth0 + use dhcp + +auto gre0 +iface gre0 + requires eth0 + + use gre + gre-endpoint 203.0.113.2 + gre-ttl 255 + gre-flags ignore-df + + address 203.0.113.194/30 + gateway 203.0.113.193 +``` + +#### Implicit dependency management using executors + +Executors can declare implicit dependencies which work the same +way as explicit dependencies, but are learned at run-time, for +example: + +``` +auto bond0 +iface bond0 + use bond + + bond-members eth0 eth1 + [...] +``` + +Is equivalent to: + +``` +auto bond0 +iface bond0 + use bond + + requires eth0 eth1 + [...] +``` + ## Questions If you have further questions about how to use ifupdown-ng to From d6c7bdb2994f027a4e05428f5cde044e26ed73fd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 15:26:14 -0600 Subject: [PATCH 149/530] README: link to admin guide --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 50ccfc4..a6e30b2 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,8 @@ ifupdown-ng is a network device manager that is largely compatible with Debian ifupdown, BusyBox ifupdown and Cumulus Networks' ifupdown2. +For more information read the [admin guide](doc/ADMIN-GUIDE.md). + ## Dependency Resolution ![Dependency resolution example](doc/img/dependency-resolution.png) From 962ef0d415dfc0bb7df16299655072d6e915cd89 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 15:57:01 -0600 Subject: [PATCH 150/530] link: support `mtu` parameter (like debian) --- executor-scripts/linux/link | 6 +++++- tests/linux/link_test | 8 +++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 8bb9d62..2aafd67 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -1,5 +1,9 @@ #!/bin/sh [ -z "$VERBOSE" ] || set -x +OPTIONS="" case "$PHASE" in -up|down) ${MOCK} ip link set $PHASE dev $IFACE ;; +up|down) + [ -n "$IF_MTU" ] && OPTIONS="$OPTIONS mtu $IF_MTU" + ${MOCK} ip link set $PHASE dev $IFACE $OPTIONS + ;; esac diff --git a/tests/linux/link_test b/tests/linux/link_test index 6957224..717d462 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -3,7 +3,7 @@ . $(atf_get_srcdir)/../test_env.sh EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/link" -tests_init up down +tests_init up down mtu up_body() { export IFACE=lo PHASE=up MOCK=echo @@ -16,3 +16,9 @@ down_body() { atf_check -s exit:0 -o match:'ip link set down dev lo' \ ${EXECUTOR} } + +mtu_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_MTU=1492 + atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \ + ${EXECUTOR} +} From ba2ad348ffd8c0df29b8343a31b4baff31b4c9fc Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 16:10:48 -0600 Subject: [PATCH 151/530] executor scripts: add vrf executor --- Makefile | 3 ++- executor-scripts/linux/vrf | 25 +++++++++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/vrf diff --git a/Makefile b/Makefile index ef9acff..3874745 100644 --- a/Makefile +++ b/Makefile @@ -80,7 +80,8 @@ EXECUTOR_SCRIPTS_CORE ?= \ link \ EXECUTOR_SCRIPTS_OPT ?= \ - bridge + bridge \ + vrf EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} diff --git a/executor-scripts/linux/vrf b/executor-scripts/linux/vrf new file mode 100755 index 0000000..2696d0f --- /dev/null +++ b/executor-scripts/linux/vrf @@ -0,0 +1,25 @@ +#!/bin/sh +handle_init() { + ${MOCK} /sbin/ip link $1 $IFACE type vrf table $IF_VRF_TABLE + ${MOCK} /sbin/ip rule $1 iif $IFACE table $IF_VRF_TABLE + ${MOCK} /sbin/ip rule $1 oif $IFACE table $IF_VRF_TABLE +} + +handle_member() { + ${MOCK} /sbin/ip link set $IFACE master $IF_VRF_MEMBER +} + +[ -n "$VERBOSE" ] && set -x + +case "$PHASE" in +pre-up) + [ -n "$IF_VRF_TABLE" ] && handle_init "add" + [ -n "$IF_VRF_MEMBER" ] && handle_member + ;; +post-down) + [ -n "$IF_VRF_TABLE" ] && handle_init "del" + ;; +*) + exit 0 + ;; +esac From ba98705c8ff13842cbd8c8d0ce5f29a265e65c60 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 16:28:34 -0600 Subject: [PATCH 152/530] tests: add tests for VRF executor --- executor-scripts/linux/vrf | 4 ++++ tests/linux/Kyuafile | 1 + tests/linux/vrf_test | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100755 tests/linux/vrf_test diff --git a/executor-scripts/linux/vrf b/executor-scripts/linux/vrf index 2696d0f..3f3d552 100755 --- a/executor-scripts/linux/vrf +++ b/executor-scripts/linux/vrf @@ -1,4 +1,6 @@ #!/bin/sh +set -e + handle_init() { ${MOCK} /sbin/ip link $1 $IFACE type vrf table $IF_VRF_TABLE ${MOCK} /sbin/ip rule $1 iif $IFACE table $IF_VRF_TABLE @@ -15,9 +17,11 @@ case "$PHASE" in pre-up) [ -n "$IF_VRF_TABLE" ] && handle_init "add" [ -n "$IF_VRF_MEMBER" ] && handle_member + exit 0 ;; post-down) [ -n "$IF_VRF_TABLE" ] && handle_init "del" + exit 0 ;; *) exit 0 diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 49b3201..22bb701 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -6,3 +6,4 @@ atf_test_program{name='link_test'} atf_test_program{name='ipv6-ra_test'} atf_test_program{name='dhcp_test'} atf_test_program{name='static_test'} +atf_test_program{name='vrf_test'} diff --git a/tests/linux/vrf_test b/tests/linux/vrf_test new file mode 100755 index 0000000..942a539 --- /dev/null +++ b/tests/linux/vrf_test @@ -0,0 +1,34 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/vrf" + +tests_init \ + leader_bringup \ + leader_teardown \ + member_bringup + +leader_bringup_body() { + export MOCK=echo IFACE=vrf-red PHASE=pre-up IF_VRF_TABLE=1 IF_VRF_MEMBER= + atf_check -s exit:0 \ + -o match:'ip link add vrf-red type vrf table 1' \ + -o match:'ip rule add iif vrf-red table 1' \ + -o match:'ip rule add oif vrf-red table 1' \ + ${EXECUTOR} +} + +leader_teardown_body() { + export MOCK=echo IFACE=vrf-red PHASE=post-down IF_VRF_TABLE=1 IF_VRF_MEMBER= + atf_check -s exit:0 \ + -o match:'ip link del vrf-red type vrf table 1' \ + -o match:'ip rule del iif vrf-red table 1' \ + -o match:'ip rule del oif vrf-red table 1' \ + ${EXECUTOR} +} + +member_bringup_body() { + export MOCK=echo IFACE=eth0 PHASE=pre-up IF_VRF_MEMBER=vrf-red IF_VRF_TABLE= + atf_check -s exit:0 \ + -o match:'ip link set eth0 master vrf-red' \ + ${EXECUTOR} +} From 2c37b22d7005e8f18e6f58c9569326644dbe764e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 16:52:11 -0600 Subject: [PATCH 153/530] tests: add fixture & test for VRF topology learning --- executor-scripts/linux/vrf | 3 +++ tests/fixtures/vrf.interfaces | 7 +++++++ tests/ifquery_test | 8 +++++++- tests/test_env.sh | 1 + 4 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/vrf.interfaces diff --git a/executor-scripts/linux/vrf b/executor-scripts/linux/vrf index 3f3d552..c42b000 100755 --- a/executor-scripts/linux/vrf +++ b/executor-scripts/linux/vrf @@ -23,6 +23,9 @@ post-down) [ -n "$IF_VRF_TABLE" ] && handle_init "del" exit 0 ;; +depend) + echo "$IF_VRF_MEMBER" + ;; *) exit 0 ;; diff --git a/tests/fixtures/vrf.interfaces b/tests/fixtures/vrf.interfaces new file mode 100644 index 0000000..bfcf11b --- /dev/null +++ b/tests/fixtures/vrf.interfaces @@ -0,0 +1,7 @@ +iface vrf-red + vrf-table 1 + +auto eth0 +iface eth0 + use dhcp + vrf-member vrf-red diff --git a/tests/ifquery_test b/tests/ifquery_test index 64e8718..0b557d7 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -18,7 +18,8 @@ tests_init \ learned_executor \ inheritance_0 \ inheritance_1 \ - implicit_vlan + implicit_vlan \ + vrf_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -112,3 +113,8 @@ implicit_vlan_body() { -o match:"use vlan" \ ifquery -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 } + +vrf_dependency_body() { + atf_check -s exit:0 -o match:"requires vrf-red" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf.interfaces eth0 +} diff --git a/tests/test_env.sh b/tests/test_env.sh index ff44cfa..870dc86 100644 --- a/tests/test_env.sh +++ b/tests/test_env.sh @@ -1,6 +1,7 @@ PATH="$(atf_get_srcdir)/..:$(atf_get_srcdir)/../..:$PATH" FIXTURES="$(atf_get_srcdir)/fixtures" EXECUTORS="$(atf_get_srcdir)/executors" +EXECUTORS_LINUX="$(atf_get_srcdir)/../executor-scripts/linux" tests_init() { TESTS="$@" From a08df1249b6df74dbef5db8b4832858cb96487e2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 18 Aug 2020 20:33:44 -0600 Subject: [PATCH 154/530] admin guide: formatting fixes, discuss executors --- doc/ADMIN-GUIDE.md | 23 ++++++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/doc/ADMIN-GUIDE.md b/doc/ADMIN-GUIDE.md index 7a9c30f..13504ba 100644 --- a/doc/ADMIN-GUIDE.md +++ b/doc/ADMIN-GUIDE.md @@ -135,7 +135,7 @@ iface eth0 gateway 2001:db8:1000:2::1 ``` -### Relationships +## Relationships As previously mentioned, ifupdown-ng features a dependency resolver that allows for determining the interface configuration @@ -146,7 +146,7 @@ order. In order to make use of this, dependencies can be managed in one of two ways: -#### Explicit dependency management using `requires` +### Explicit dependency management using `requires` The `requires` keyword can be used to manage explicit dependencies: @@ -169,7 +169,7 @@ iface gre0 gateway 203.0.113.193 ``` -#### Implicit dependency management using executors +### Implicit dependency management using executors Executors can declare implicit dependencies which work the same way as explicit dependencies, but are learned at run-time, for @@ -195,6 +195,23 @@ iface bond0 [...] ``` +## Executors + +The ifupdown-ng system is expanded with additional features via +executors. Executors are selected on a per-interface basis using +`use` statements, for example: + +``` +auto eth0 +iface eth0 + use dhcp +``` + +Executors are run in the order specified by the `use` statements. +Some executors are automatically added based on other statements +in an interface definition. To see the full list of executors +used for an interface, use the ifquery(8) command. + ## Questions If you have further questions about how to use ifupdown-ng to From eeb40fc689d5050dfcc46215af928f6191de0f7f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 01:50:10 -0600 Subject: [PATCH 155/530] libifupdown: move ARRAY_SIZE() declaration from multicall --- cmd/multicall.h | 2 -- libifupdown/libifupdown.h | 4 ++++ 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/multicall.h b/cmd/multicall.h index bd7cf7d..647e0ba 100644 --- a/cmd/multicall.h +++ b/cmd/multicall.h @@ -20,8 +20,6 @@ #include "libifupdown/libifupdown.h" -#define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) - struct if_applet; struct if_option { diff --git a/libifupdown/libifupdown.h b/libifupdown/libifupdown.h index 87cc5fd..33da802 100644 --- a/libifupdown/libifupdown.h +++ b/libifupdown/libifupdown.h @@ -28,4 +28,8 @@ #include "libifupdown/lifecycle.h" #include "libifupdown/tokenize.h" +#ifndef ARRAY_SIZE +# define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) +#endif + #endif From cb03eb1ee943b802f03255221f9d70c07d94d3cd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 01:57:11 -0600 Subject: [PATCH 156/530] interface-file: remap problematic ifupdown2 tokens to our equivalents --- libifupdown/interface-file.c | 37 +++++++++++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 74d74c1..b59ca8a 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -16,9 +16,38 @@ #include #include #include -#include "libifupdown/interface-file.h" -#include "libifupdown/fgetline.h" -#include "libifupdown/tokenize.h" +#include "libifupdown/libifupdown.h" + +/* internally rewrite problematic ifupdown2 tokens to ifupdown-ng equivalents */ +struct remap_token { + const char *token; + const char *alternative; +}; + +static const struct remap_token tokens[] = { + {"vrf", "vrf-member"} +}; + +static int +token_cmp(const void *a, const void *b) +{ + const char *key = a; + const struct remap_token *token = b; + + return strcmp(key, token->token); +} + +static char * +maybe_remap_token(const char *token) +{ + const struct remap_token *tok = NULL; + static char tokbuf[4096]; + + tok = bsearch(token, tokens, ARRAY_SIZE(tokens), sizeof(*tokens), token_cmp); + strlcpy(tokbuf, tok != NULL ? tok->alternative : token, sizeof tokbuf); + + return tokbuf; +} bool lif_interface_file_parse(struct lif_dict *collection, const char *filename) @@ -167,6 +196,8 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) } else if (cur_iface != NULL) { + token = maybe_remap_token(token); + lif_dict_add(&cur_iface->vars, token, strdup(bufp)); /* Check if token looks like - and assume is an addon */ From 71290da7117181f57c38fc4063394dc5c1acc3d5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 02:14:08 -0600 Subject: [PATCH 157/530] tests: add ifupdown2 vrf configuration fixture, and some tests against it --- tests/fixtures/vrf-ifupdown2.interfaces | 7 +++++++ tests/ifquery_test | 14 +++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/vrf-ifupdown2.interfaces diff --git a/tests/fixtures/vrf-ifupdown2.interfaces b/tests/fixtures/vrf-ifupdown2.interfaces new file mode 100644 index 0000000..242cba5 --- /dev/null +++ b/tests/fixtures/vrf-ifupdown2.interfaces @@ -0,0 +1,7 @@ +iface vrf-red + vrf-table 1 + +auto eth0 +iface eth0 + use dhcp + vrf vrf-red diff --git a/tests/ifquery_test b/tests/ifquery_test index 0b557d7..f6afe13 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -19,7 +19,9 @@ tests_init \ inheritance_0 \ inheritance_1 \ implicit_vlan \ - vrf_dependency + vrf_dependency \ + vrf_ifupdown2_rewrite \ + vrf_ifupdown2_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -118,3 +120,13 @@ vrf_dependency_body() { atf_check -s exit:0 -o match:"requires vrf-red" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf.interfaces eth0 } + +vrf_ifupdown2_rewrite_body() { + atf_check -s exit:0 -o match:"vrf-member vrf-red" \ + ifquery -E $EXECUTORS -i $FIXTURES/vrf-ifupdown2.interfaces eth0 +} + +vrf_ifupdown2_dependency_body() { + atf_check -s exit:0 -o match:"requires vrf-red" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf-ifupdown2.interfaces eth0 +} From 823544aace9639a88a23d71b89694ba4c1eef496 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 06:03:48 -0600 Subject: [PATCH 158/530] interface-file: map ppp-provider --- libifupdown/interface-file.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index b59ca8a..82a3328 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -25,7 +25,8 @@ struct remap_token { }; static const struct remap_token tokens[] = { - {"vrf", "vrf-member"} + {"provider", "ppp-provider"}, /* legacy ifupdown, ifupdown2 */ + {"vrf", "vrf-member"}, }; static int @@ -119,6 +120,10 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) cur_iface->is_dhcp = true; lif_dict_add(&cur_iface->vars, "use", strdup("dhcp")); } + else if (!strcmp(token, "ppp")) + { + lif_dict_add(&cur_iface->vars, "use", strdup("ppp")); + } else if (!strcmp(token, "inherits")) { token = lif_next_token(&bufp); From dd02502461bacb284a1963f3fc8f1ccd9aa1834f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 06:05:29 -0600 Subject: [PATCH 159/530] tests: add ppp fixtures --- tests/fixtures/ppp-legacy.interfaces | 4 ++++ tests/fixtures/ppp.interfaces | 4 ++++ 2 files changed, 8 insertions(+) create mode 100644 tests/fixtures/ppp-legacy.interfaces create mode 100644 tests/fixtures/ppp.interfaces diff --git a/tests/fixtures/ppp-legacy.interfaces b/tests/fixtures/ppp-legacy.interfaces new file mode 100644 index 0000000..8a83490 --- /dev/null +++ b/tests/fixtures/ppp-legacy.interfaces @@ -0,0 +1,4 @@ +auto ppp0 +iface ppp0 inet ppp + requires eth0 + provider someisp diff --git a/tests/fixtures/ppp.interfaces b/tests/fixtures/ppp.interfaces new file mode 100644 index 0000000..4d4cb9b --- /dev/null +++ b/tests/fixtures/ppp.interfaces @@ -0,0 +1,4 @@ +auto ppp0 +iface ppp0 + requires eth0 + ppp-provider someisp From 0dd8dc1b0e0cc21b375f1f5cf87220cfa2efdeaa Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 06:09:05 -0600 Subject: [PATCH 160/530] tests: add ifquery tests for ppp --- tests/ifquery_test | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/ifquery_test b/tests/ifquery_test index f6afe13..67284ec 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -21,7 +21,9 @@ tests_init \ implicit_vlan \ vrf_dependency \ vrf_ifupdown2_rewrite \ - vrf_ifupdown2_dependency + vrf_ifupdown2_dependency \ + ppp_dependency \ + ppp_legacy_rewrite noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -130,3 +132,13 @@ vrf_ifupdown2_dependency_body() { atf_check -s exit:0 -o match:"requires vrf-red" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf-ifupdown2.interfaces eth0 } + +ppp_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/ppp.interfaces ppp0 +} + +ppp_legacy_rewrite_body() { + atf_check -s exit:0 -o match:"ppp-provider someisp" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/ppp-legacy.interfaces ppp0 +} From 472319b84743b2e36d09b85eab652c9e44f21fd5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 06:11:52 -0600 Subject: [PATCH 161/530] add ppp executor --- executor-scripts/linux/ppp | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100755 executor-scripts/linux/ppp diff --git a/executor-scripts/linux/ppp b/executor-scripts/linux/ppp new file mode 100755 index 0000000..ea7b085 --- /dev/null +++ b/executor-scripts/linux/ppp @@ -0,0 +1,7 @@ +#!/bin/sh +set -e +[ -z "$IF_PPP_PROVIDER" ] && exit 0 +case "$PHASE" in +pre-up) ${MOCK} pon $IF_PPP_PROVIDER ;; +post-down) ${MOCK} poff $IF_PPP_PROVIDER ;; +esac From c2465344d576ccf2ea922bf7cfd350fe2d035b2a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 06:15:00 -0600 Subject: [PATCH 162/530] tests: add ppp executor tests --- tests/linux/Kyuafile | 1 + tests/linux/ppp_test | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100755 tests/linux/ppp_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 22bb701..471a8ff 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -7,3 +7,4 @@ atf_test_program{name='ipv6-ra_test'} atf_test_program{name='dhcp_test'} atf_test_program{name='static_test'} atf_test_program{name='vrf_test'} +atf_test_program{name='ppp_test'} diff --git a/tests/linux/ppp_test b/tests/linux/ppp_test new file mode 100755 index 0000000..46bb0e0 --- /dev/null +++ b/tests/linux/ppp_test @@ -0,0 +1,22 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/ppp" + +tests_init \ + bringup \ + teardown \ + +bringup_body() { + export MOCK=echo IFACE=ppp0 PHASE=pre-up IF_PPP_PROVIDER=someisp + atf_check -s exit:0 \ + -o match:'pon someisp' \ + ${EXECUTOR} +} + +teardown_body() { + export MOCK=echo IFACE=ppp0 PHASE=post-down IF_PPP_PROVIDER=someisp + atf_check -s exit:0 \ + -o match:'poff someisp' \ + ${EXECUTOR} +} From e18ab114e03c24c5134830270b5c9ac64a02469e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 06:16:37 -0600 Subject: [PATCH 163/530] ppp: add support for ifupdown2 ppp-physdev for dependency learning --- executor-scripts/linux/ppp | 1 + 1 file changed, 1 insertion(+) diff --git a/executor-scripts/linux/ppp b/executor-scripts/linux/ppp index ea7b085..3ba001b 100755 --- a/executor-scripts/linux/ppp +++ b/executor-scripts/linux/ppp @@ -4,4 +4,5 @@ set -e case "$PHASE" in pre-up) ${MOCK} pon $IF_PPP_PROVIDER ;; post-down) ${MOCK} poff $IF_PPP_PROVIDER ;; +depend) echo "$IF_PPP_PHYSDEV" ;; esac From 9cc74b58c40c27967bf145c4b217e417228ed583 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 02:46:04 -0600 Subject: [PATCH 164/530] interface-file: remap legacy ifupdown & ifupdown2 tunnel parameters --- executor-scripts/linux/tunnel | 30 ++++++++++++++++++++++++++++++ libifupdown/interface-file.c | 7 ++++++- 2 files changed, 36 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/tunnel diff --git a/executor-scripts/linux/tunnel b/executor-scripts/linux/tunnel new file mode 100755 index 0000000..07c6141 --- /dev/null +++ b/executor-scripts/linux/tunnel @@ -0,0 +1,30 @@ +#!/bin/sh + +# Based on alpine's tunnel configuration script. +# Copyright (c) 2017 Kaarle Ritvanen + +PARAMS=$(set | sed -E ' + s/^IF_TUNNEL_([A-Z0-9_]+)=(.+)/\1\n\2/ + ta + d + :a + h + y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + P + g + s/.*\n// + ') + +[ "$PARAMS" ] || exit 0 + +case "$PHASE" in +pre-up) + eval ip tunnel add $IFACE $PARAMS + ;; +post-down) + ip tunnel del $IFACE + ;; +depend) + echo "$IF_TUNNEL_DEV" + ;; +esac diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 82a3328..69a7b42 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -24,9 +24,14 @@ struct remap_token { const char *alternative; }; +/* this list must be in alphabetical order for bsearch */ static const struct remap_token tokens[] = { + {"endpoint", "tunnel-remote"}, /* legacy ifupdown */ + {"local", "tunnel-local"}, /* legacy ifupdown */ {"provider", "ppp-provider"}, /* legacy ifupdown, ifupdown2 */ - {"vrf", "vrf-member"}, + {"tunnel-endpoint", "tunnel-remote"}, /* ifupdown2 */ + {"tunnel-physdev", "tunnel-dev"}, /* ifupdown2 */ + {"vrf", "vrf-member"}, /* ifupdown2 */ }; static int From 36271e86576744fc53084f50c41166b020d8b220 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 02:56:02 -0600 Subject: [PATCH 165/530] build: install tunnel executor by default --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 3874745..77778ba 100644 --- a/Makefile +++ b/Makefile @@ -81,7 +81,8 @@ EXECUTOR_SCRIPTS_CORE ?= \ EXECUTOR_SCRIPTS_OPT ?= \ bridge \ - vrf + vrf \ + tunnel EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} From a4f147b5d01bf5b235198fd104d4d59c151ed97a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:00:17 -0600 Subject: [PATCH 166/530] tests: add some tunnel configuration fixtures --- tests/fixtures/tunnel-ifupdown2.interfaces | 10 ++++++++++ tests/fixtures/tunnel-legacy.interfaces | 10 ++++++++++ tests/fixtures/tunnel.interfaces | 10 ++++++++++ 3 files changed, 30 insertions(+) create mode 100644 tests/fixtures/tunnel-ifupdown2.interfaces create mode 100644 tests/fixtures/tunnel-legacy.interfaces create mode 100644 tests/fixtures/tunnel.interfaces diff --git a/tests/fixtures/tunnel-ifupdown2.interfaces b/tests/fixtures/tunnel-ifupdown2.interfaces new file mode 100644 index 0000000..82a36c5 --- /dev/null +++ b/tests/fixtures/tunnel-ifupdown2.interfaces @@ -0,0 +1,10 @@ +auto tun0 +iface tun0 + tunnel-local 203.0.113.2 + tunnel-endpoint 203.0.113.1 + tunnel-physdev eth0 + address 203.0.113.10/30 + gateway 203.0.113.9 + +iface eth0 + address 203.0.113.2/30 diff --git a/tests/fixtures/tunnel-legacy.interfaces b/tests/fixtures/tunnel-legacy.interfaces new file mode 100644 index 0000000..ff6505c --- /dev/null +++ b/tests/fixtures/tunnel-legacy.interfaces @@ -0,0 +1,10 @@ +auto tun0 +iface tun0 + local 203.0.113.2 + endpoint 203.0.113.1 + tunnel-dev eth0 + address 203.0.113.10/30 + gateway 203.0.113.9 + +iface eth0 + address 203.0.113.2/30 diff --git a/tests/fixtures/tunnel.interfaces b/tests/fixtures/tunnel.interfaces new file mode 100644 index 0000000..586b401 --- /dev/null +++ b/tests/fixtures/tunnel.interfaces @@ -0,0 +1,10 @@ +auto tun0 +iface tun0 + tunnel-local 203.0.113.2 + tunnel-remote 203.0.113.1 + tunnel-dev eth0 + address 203.0.113.10/30 + gateway 203.0.113.9 + +iface eth0 + address 203.0.113.2/30 From c24143982f64a35a57498badec1361b0c0579a98 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:12:43 -0600 Subject: [PATCH 167/530] interface-file: map 'mode' to tunnel-mode --- libifupdown/interface-file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 69a7b42..fe862c3 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -28,6 +28,7 @@ struct remap_token { static const struct remap_token tokens[] = { {"endpoint", "tunnel-remote"}, /* legacy ifupdown */ {"local", "tunnel-local"}, /* legacy ifupdown */ + {"mode", "tunnel-mode"}, /* legacy ifupdown */ {"provider", "ppp-provider"}, /* legacy ifupdown, ifupdown2 */ {"tunnel-endpoint", "tunnel-remote"}, /* ifupdown2 */ {"tunnel-physdev", "tunnel-dev"}, /* ifupdown2 */ From 953666f1fb50a6b0955413a0748d18b21603ae2a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:13:02 -0600 Subject: [PATCH 168/530] tests: add tests for managing the tunnel executor --- tests/fixtures/tunnel-ifupdown2.interfaces | 1 + tests/fixtures/tunnel-legacy.interfaces | 1 + tests/fixtures/tunnel.interfaces | 1 + tests/ifquery_test | 38 +++++++++++++++++++++- 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/fixtures/tunnel-ifupdown2.interfaces b/tests/fixtures/tunnel-ifupdown2.interfaces index 82a36c5..4e93b91 100644 --- a/tests/fixtures/tunnel-ifupdown2.interfaces +++ b/tests/fixtures/tunnel-ifupdown2.interfaces @@ -2,6 +2,7 @@ auto tun0 iface tun0 tunnel-local 203.0.113.2 tunnel-endpoint 203.0.113.1 + tunnel-mode gre tunnel-physdev eth0 address 203.0.113.10/30 gateway 203.0.113.9 diff --git a/tests/fixtures/tunnel-legacy.interfaces b/tests/fixtures/tunnel-legacy.interfaces index ff6505c..bb030bd 100644 --- a/tests/fixtures/tunnel-legacy.interfaces +++ b/tests/fixtures/tunnel-legacy.interfaces @@ -2,6 +2,7 @@ auto tun0 iface tun0 local 203.0.113.2 endpoint 203.0.113.1 + mode gre tunnel-dev eth0 address 203.0.113.10/30 gateway 203.0.113.9 diff --git a/tests/fixtures/tunnel.interfaces b/tests/fixtures/tunnel.interfaces index 586b401..4bf46de 100644 --- a/tests/fixtures/tunnel.interfaces +++ b/tests/fixtures/tunnel.interfaces @@ -2,6 +2,7 @@ auto tun0 iface tun0 tunnel-local 203.0.113.2 tunnel-remote 203.0.113.1 + tunnel-mode gre tunnel-dev eth0 address 203.0.113.10/30 gateway 203.0.113.9 diff --git a/tests/ifquery_test b/tests/ifquery_test index 67284ec..79f9341 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -23,7 +23,12 @@ tests_init \ vrf_ifupdown2_rewrite \ vrf_ifupdown2_dependency \ ppp_dependency \ - ppp_legacy_rewrite + ppp_legacy_rewrite \ + tunnel_dependency \ + tunnel_legacy_dependency \ + tunnel_legacy_rewrite \ + tunnel_ifupdown2_dependency \ + tunnel_ifupdown2_rewrite noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -142,3 +147,34 @@ ppp_legacy_rewrite_body() { atf_check -s exit:0 -o match:"ppp-provider someisp" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/ppp-legacy.interfaces ppp0 } + +tunnel_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel.interfaces tun0 +} + +tunnel_legacy_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-legacy.interfaces tun0 +} + +tunnel_ifupdown2_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-ifupdown2.interfaces tun0 +} + +tunnel_legacy_rewrite_body() { + atf_check -s exit:0 \ + -o match:"tunnel-local 203.0.113.2" \ + -o match:"tunnel-remote 203.0.113.1" \ + -o match:"tunnel-mode gre" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-legacy.interfaces tun0 +} + +tunnel_ifupdown2_rewrite_body() { + atf_check -s exit:0 \ + -o match:"tunnel-local 203.0.113.2" \ + -o match:"tunnel-remote 203.0.113.1" \ + -o match:"tunnel-mode gre" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-ifupdown2.interfaces tun0 +} From 5fb1b4b26ca4f1e71d973c8ece57364571897318 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:13:56 -0600 Subject: [PATCH 169/530] tunnel executor: support mocking --- executor-scripts/linux/tunnel | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/tunnel b/executor-scripts/linux/tunnel index 07c6141..8257a7f 100755 --- a/executor-scripts/linux/tunnel +++ b/executor-scripts/linux/tunnel @@ -19,10 +19,10 @@ PARAMS=$(set | sed -E ' case "$PHASE" in pre-up) - eval ip tunnel add $IFACE $PARAMS + ${MOCK} eval ip tunnel add $IFACE $PARAMS ;; post-down) - ip tunnel del $IFACE + ${MOCK} ip tunnel del $IFACE ;; depend) echo "$IF_TUNNEL_DEV" From 023805105217fbbd0bd09d356b53c91a9cb3ceb3 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:22:44 -0600 Subject: [PATCH 170/530] tests: add tunnel executor tests --- tests/linux/Kyuafile | 1 + tests/linux/tunnel_test | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100755 tests/linux/tunnel_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 471a8ff..99ad1e8 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -8,3 +8,4 @@ atf_test_program{name='dhcp_test'} atf_test_program{name='static_test'} atf_test_program{name='vrf_test'} atf_test_program{name='ppp_test'} +atf_test_program{name='tunnel_test'} diff --git a/tests/linux/tunnel_test b/tests/linux/tunnel_test new file mode 100755 index 0000000..c469a78 --- /dev/null +++ b/tests/linux/tunnel_test @@ -0,0 +1,30 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/tunnel" + +tests_init \ + tunnel_bringup \ + tunnel_teardown + +tunnel_bringup_body() { + export MOCK=echo IFACE=tun0 PHASE=pre-up IF_TUNNEL_TYPE=gre \ + IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8 \ + IF_TUNNEL_TTL=255 + atf_check -s exit:0 \ + -o match:"ip tunnel add tun0" \ + -o match:"type 'gre'" \ + -o match:"ttl '255'" \ + -o match:"local '1.2.3.4'" \ + -o match:"remote '5.6.7.8'" \ + ${EXECUTOR} +} + +tunnel_teardown_body() { + export MOCK=echo IFACE=tun0 PHASE=post-down IF_TUNNEL_TYPE=gre \ + IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8 \ + IF_TUNNEL_TTL=255 + atf_check -s exit:0 \ + -o match:"ip tunnel del tun0" \ + ${EXECUTOR} +} From 075352b631b1b768783b4191d74de1c86053f68a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:29:13 -0600 Subject: [PATCH 171/530] interface-file: remap ttl to tunnel-ttl --- libifupdown/interface-file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index fe862c3..674cecd 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -30,6 +30,7 @@ static const struct remap_token tokens[] = { {"local", "tunnel-local"}, /* legacy ifupdown */ {"mode", "tunnel-mode"}, /* legacy ifupdown */ {"provider", "ppp-provider"}, /* legacy ifupdown, ifupdown2 */ + {"ttl", "tunnel-ttl"}, /* legacy ifupdown */ {"tunnel-endpoint", "tunnel-remote"}, /* ifupdown2 */ {"tunnel-physdev", "tunnel-dev"}, /* ifupdown2 */ {"vrf", "vrf-member"}, /* ifupdown2 */ From 93116920da057df730d76b8026d0d50908045b8b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 19 Aug 2020 03:32:10 -0600 Subject: [PATCH 172/530] tests: verify ttl is remapped to tunnel-ttl --- tests/fixtures/tunnel-ifupdown2.interfaces | 1 + tests/fixtures/tunnel-legacy.interfaces | 1 + tests/fixtures/tunnel.interfaces | 1 + tests/ifquery_test | 2 ++ 4 files changed, 5 insertions(+) diff --git a/tests/fixtures/tunnel-ifupdown2.interfaces b/tests/fixtures/tunnel-ifupdown2.interfaces index 4e93b91..f38e139 100644 --- a/tests/fixtures/tunnel-ifupdown2.interfaces +++ b/tests/fixtures/tunnel-ifupdown2.interfaces @@ -4,6 +4,7 @@ iface tun0 tunnel-endpoint 203.0.113.1 tunnel-mode gre tunnel-physdev eth0 + tunnel-ttl 255 address 203.0.113.10/30 gateway 203.0.113.9 diff --git a/tests/fixtures/tunnel-legacy.interfaces b/tests/fixtures/tunnel-legacy.interfaces index bb030bd..c20ecf7 100644 --- a/tests/fixtures/tunnel-legacy.interfaces +++ b/tests/fixtures/tunnel-legacy.interfaces @@ -4,6 +4,7 @@ iface tun0 endpoint 203.0.113.1 mode gre tunnel-dev eth0 + ttl 255 address 203.0.113.10/30 gateway 203.0.113.9 diff --git a/tests/fixtures/tunnel.interfaces b/tests/fixtures/tunnel.interfaces index 4bf46de..12a081b 100644 --- a/tests/fixtures/tunnel.interfaces +++ b/tests/fixtures/tunnel.interfaces @@ -4,6 +4,7 @@ iface tun0 tunnel-remote 203.0.113.1 tunnel-mode gre tunnel-dev eth0 + tunnel-ttl 255 address 203.0.113.10/30 gateway 203.0.113.9 diff --git a/tests/ifquery_test b/tests/ifquery_test index 79f9341..281f1e2 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -168,6 +168,7 @@ tunnel_legacy_rewrite_body() { -o match:"tunnel-local 203.0.113.2" \ -o match:"tunnel-remote 203.0.113.1" \ -o match:"tunnel-mode gre" \ + -o match:"tunnel-ttl 255" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-legacy.interfaces tun0 } @@ -176,5 +177,6 @@ tunnel_ifupdown2_rewrite_body() { -o match:"tunnel-local 203.0.113.2" \ -o match:"tunnel-remote 203.0.113.1" \ -o match:"tunnel-mode gre" \ + -o match:"tunnel-ttl 255" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-ifupdown2.interfaces tun0 } From cd1b0d5833c102fb5c1f9cfba5f7e9e772ca496c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 02:09:01 -0600 Subject: [PATCH 173/530] tunnel: improve validation of options --- executor-scripts/linux/tunnel | 21 +++++++++++++++++++-- tests/linux/tunnel_test | 10 +++++----- 2 files changed, 24 insertions(+), 7 deletions(-) diff --git a/executor-scripts/linux/tunnel b/executor-scripts/linux/tunnel index 8257a7f..6b6fa49 100755 --- a/executor-scripts/linux/tunnel +++ b/executor-scripts/linux/tunnel @@ -2,6 +2,23 @@ # Based on alpine's tunnel configuration script. # Copyright (c) 2017 Kaarle Ritvanen +# Copyright (c) 2020 Ariadne Conill (extended for ifupdown-ng) + +[ -z "$IF_TUNNEL_LOCAL" ] && exit 1 +[ -z "$IF_TUNNEL_REMOTE" ] && exit 1 +[ -z "$IF_TUNNEL_MODE" ] && exit 1 + +COMMAND="tunnel" +FAMILY="-4" + +case "$IF_TUNNEL_MODE" in +gretap) + COMMAND="link" + ;; +vti6|ipip6|ip6*) + FAMILY="-6" + ;; +esac PARAMS=$(set | sed -E ' s/^IF_TUNNEL_([A-Z0-9_]+)=(.+)/\1\n\2/ @@ -19,10 +36,10 @@ PARAMS=$(set | sed -E ' case "$PHASE" in pre-up) - ${MOCK} eval ip tunnel add $IFACE $PARAMS + ${MOCK} eval ip $FAMILY $COMMAND add $IFACE $PARAMS ;; post-down) - ${MOCK} ip tunnel del $IFACE + ${MOCK} ip $FAMILY $COMMAND del $IFACE ;; depend) echo "$IF_TUNNEL_DEV" diff --git a/tests/linux/tunnel_test b/tests/linux/tunnel_test index c469a78..8bf9534 100755 --- a/tests/linux/tunnel_test +++ b/tests/linux/tunnel_test @@ -8,12 +8,12 @@ tests_init \ tunnel_teardown tunnel_bringup_body() { - export MOCK=echo IFACE=tun0 PHASE=pre-up IF_TUNNEL_TYPE=gre \ + export MOCK=echo IFACE=tun0 PHASE=pre-up IF_TUNNEL_MODE=gre \ IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8 \ IF_TUNNEL_TTL=255 atf_check -s exit:0 \ - -o match:"ip tunnel add tun0" \ - -o match:"type 'gre'" \ + -o match:"ip -4 tunnel add tun0" \ + -o match:"mode 'gre'" \ -o match:"ttl '255'" \ -o match:"local '1.2.3.4'" \ -o match:"remote '5.6.7.8'" \ @@ -21,10 +21,10 @@ tunnel_bringup_body() { } tunnel_teardown_body() { - export MOCK=echo IFACE=tun0 PHASE=post-down IF_TUNNEL_TYPE=gre \ + export MOCK=echo IFACE=tun0 PHASE=post-down IF_TUNNEL_MODE=gre \ IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8 \ IF_TUNNEL_TTL=255 atf_check -s exit:0 \ - -o match:"ip tunnel del tun0" \ + -o match:"ip -4 tunnel del tun0" \ ${EXECUTOR} } From 8f057286d36a8e5bf09b4ccd9d1dd5d3210ee0c6 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 02:30:12 -0600 Subject: [PATCH 174/530] add gre executor --- executor-scripts/linux/gre | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) create mode 100755 executor-scripts/linux/gre diff --git a/executor-scripts/linux/gre b/executor-scripts/linux/gre new file mode 100755 index 0000000..7006d4c --- /dev/null +++ b/executor-scripts/linux/gre @@ -0,0 +1,29 @@ +#!/bin/sh + +# Executor for advanced GRE tunnel management. + +[ -z "$IF_GRE_LOCAL" ] && exit 1 +[ -z "$IF_GRE_REMOTE" ] && exit 1 +[ -z "$IF_GRE_MODE" ] && exit 1 + +COMMAND="link" +FAMILY="-4" +[ "$IF_GRE_MODE" = "ip6gre" ] && FAMILY="-6" + +PARAMS="mode $IF_GRE_MODE local '$IF_GRE_LOCAL' remote '$IF_GRE_REMOTE'" +[ -n "$IF_GRE_TTL" ] && PARAMS="$PARAMS ttl '$IF_GRE_TTL'" +[ -n "$IF_GRE_FLAGS" ] && PARAMS="$PARAMS $IF_GRE_FLAGS" + +[ -n "$PARAMS" ] || exit 0 + +case "$PHASE" in +pre-up) + ${MOCK} eval ip $FAMILY $COMMAND add $IFACE $PARAMS + ;; +post-down) + ${MOCK} ip $FAMILY $COMMAND del $IFACE + ;; +depend) + echo "$IF_TUNNEL_DEV" + ;; +esac From d31f8614a3dc155fa42c3b20fce6abbae79c703e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 02:33:38 -0600 Subject: [PATCH 175/530] gre executor: fix dependency learning --- executor-scripts/linux/gre | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/gre b/executor-scripts/linux/gre index 7006d4c..c747aab 100755 --- a/executor-scripts/linux/gre +++ b/executor-scripts/linux/gre @@ -4,7 +4,7 @@ [ -z "$IF_GRE_LOCAL" ] && exit 1 [ -z "$IF_GRE_REMOTE" ] && exit 1 -[ -z "$IF_GRE_MODE" ] && exit 1 +[ -z "$IF_GRE_MODE" ] && IF_GRE_MODE="gre" COMMAND="link" FAMILY="-4" @@ -24,6 +24,6 @@ post-down) ${MOCK} ip $FAMILY $COMMAND del $IFACE ;; depend) - echo "$IF_TUNNEL_DEV" + echo "$IF_GRE_DEV" ;; esac From 6d2ae938d1bc2f40a51ec8554a7dcf562a1c7e16 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 02:33:51 -0600 Subject: [PATCH 176/530] tests: add ifquery test for gre dependency learning --- tests/fixtures/gre.interfaces | 12 ++++++++++++ tests/ifquery_test | 8 +++++++- 2 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/gre.interfaces diff --git a/tests/fixtures/gre.interfaces b/tests/fixtures/gre.interfaces new file mode 100644 index 0000000..a53ebec --- /dev/null +++ b/tests/fixtures/gre.interfaces @@ -0,0 +1,12 @@ +auto tun0 +iface tun0 + gre-local 203.0.113.2 + gre-remote 203.0.113.1 + gre-dev eth0 + gre-ttl 255 + gre-flags nopmtudisc ignore-df + address 203.0.113.10/30 + gateway 203.0.113.9 + +iface eth0 + address 203.0.113.2/30 diff --git a/tests/ifquery_test b/tests/ifquery_test index 281f1e2..3c4361e 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -28,7 +28,8 @@ tests_init \ tunnel_legacy_dependency \ tunnel_legacy_rewrite \ tunnel_ifupdown2_dependency \ - tunnel_ifupdown2_rewrite + tunnel_ifupdown2_rewrite \ + gre_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -180,3 +181,8 @@ tunnel_ifupdown2_rewrite_body() { -o match:"tunnel-ttl 255" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/tunnel-ifupdown2.interfaces tun0 } + +gre_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/gre.interfaces tun0 +} From c86952ce71387f8330df0600d9f5ea469c6681ff Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 02:40:27 -0600 Subject: [PATCH 177/530] tests: add gre executor tests --- tests/linux/Kyuafile | 1 + tests/linux/gre_test | 45 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100755 tests/linux/gre_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 99ad1e8..7d7389c 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -9,3 +9,4 @@ atf_test_program{name='static_test'} atf_test_program{name='vrf_test'} atf_test_program{name='ppp_test'} atf_test_program{name='tunnel_test'} +atf_test_program{name='gre_test'} diff --git a/tests/linux/gre_test b/tests/linux/gre_test new file mode 100755 index 0000000..1803253 --- /dev/null +++ b/tests/linux/gre_test @@ -0,0 +1,45 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/gre" + +tests_init \ + basic_bringup \ + basic_teardown \ + flags_bringup + +basic_bringup_body() { + export MOCK=echo IFACE=tun0 PHASE=pre-up \ + IF_GRE_LOCAL=1.2.3.4 IF_GRE_REMOTE=5.6.7.8 \ + IF_GRE_TTL=255 + atf_check -s exit:0 \ + -o match:"ip -4 link add tun0" \ + -o match:"mode gre" \ + -o match:"ttl '255'" \ + -o match:"local '1.2.3.4'" \ + -o match:"remote '5.6.7.8'" \ + ${EXECUTOR} +} + +basic_teardown_body() { + export MOCK=echo IFACE=tun0 PHASE=post-down \ + IF_GRE_LOCAL=1.2.3.4 IF_GRE_REMOTE=5.6.7.8 \ + IF_GRE_TTL=255 + atf_check -s exit:0 \ + -o match:"ip -4 link del tun0" \ + ${EXECUTOR} +} + +flags_bringup_body() { + export MOCK=echo IFACE=tun0 PHASE=pre-up \ + IF_GRE_LOCAL=1.2.3.4 IF_GRE_REMOTE=5.6.7.8 \ + IF_GRE_TTL=255 IF_GRE_FLAGS="nopmtudisc ignore-df" + atf_check -s exit:0 \ + -o match:"ip -4 link add tun0" \ + -o match:"mode gre" \ + -o match:"ttl '255'" \ + -o match:"local '1.2.3.4'" \ + -o match:"remote '5.6.7.8'" \ + -o match:"nopmtudisc ignore-df" \ + ${EXECUTOR} +} From 9caffc01c23e945adc2922f18ba0e1e304fd6c45 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 02:59:43 -0600 Subject: [PATCH 178/530] static executor: if vrf-table is set, apply the static route to a specific table --- executor-scripts/linux/static | 5 ++++- tests/fixtures/vrf.interfaces | 1 + tests/linux/static_test | 18 +++++++++++++++++- 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index d7e3ee3..e14ca6b 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -1,5 +1,8 @@ #!/bin/sh +VRF_TABLE="" +[ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" + addr_family() { if [ "$1" != "${1#*[0-9].[0-9]}" ]; then echo "-4" @@ -20,7 +23,7 @@ configure_addresses() { configure_gateways() { for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do addrfam=$(addr_family $i) - ${MOCK} ip $addrfam route $1 default via $i + ${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE done } diff --git a/tests/fixtures/vrf.interfaces b/tests/fixtures/vrf.interfaces index bfcf11b..fc40df2 100644 --- a/tests/fixtures/vrf.interfaces +++ b/tests/fixtures/vrf.interfaces @@ -1,5 +1,6 @@ iface vrf-red vrf-table 1 + gateway 203.0.113.2 auto eth0 iface eth0 diff --git a/tests/linux/static_test b/tests/linux/static_test index a07ea8e..79bf820 100755 --- a/tests/linux/static_test +++ b/tests/linux/static_test @@ -4,7 +4,7 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static" FIXTURES="$(atf_get_srcdir)/../fixtures" -tests_init up down +tests_init up down vrf_up vrf_down up_body() { export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" @@ -25,3 +25,19 @@ down_body() { -o match:'route del default via 2001:db8:1000:2::1' \ ${EXECUTOR} } + +vrf_up_body() { + export IFACE=vrf-red PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ + IF_VRF_TABLE=1 + atf_check -s exit:0 \ + -o match:'route add default via 203.0.113.2 table 1' \ + ${EXECUTOR} +} + +vrf_down_body() { + export IFACE=vrf-red PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ + IF_VRF_TABLE=1 + atf_check -s exit:0 \ + -o match:'route del default via 203.0.113.2 table 1' \ + ${EXECUTOR} +} From d463d455da3a7360f39e8ff60d0737ca61c04996 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:08:29 -0600 Subject: [PATCH 179/530] simplify executor `use` statements --- libifupdown/interface-file.c | 12 ++++++------ libifupdown/interface.c | 23 +++++++++++++---------- libifupdown/interface.h | 1 + 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 674cecd..bd6e0ba 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -125,11 +125,11 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (!strcmp(token, "dhcp")) { cur_iface->is_dhcp = true; - lif_dict_add(&cur_iface->vars, "use", strdup("dhcp")); + lif_interface_use_executor(cur_iface, "dhcp"); } else if (!strcmp(token, "ppp")) { - lif_dict_add(&cur_iface->vars, "use", strdup("ppp")); + lif_interface_use_executor(cur_iface, "ppp"); } else if (!strcmp(token, "inherits")) { @@ -176,7 +176,7 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) else if (!strcmp(executor, "link")) continue; - lif_dict_add(&cur_iface->vars, token, strdup(executor)); + lif_interface_use_executor(cur_iface, executor); } else if (!strcmp(token, "inherit")) { @@ -214,12 +214,12 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) /* Check if token looks like - and assume is an addon */ char *word_end = strchr(token, '-'); - if (word_end) + if (word_end != NULL) { /* Copy word1 to not mangle *token */ char *addon = strndup(token, word_end - token); - if (lif_dict_add_once(&cur_iface->vars, "use", addon, (lif_dict_cmp_t) strcmp) == NULL) - free(addon); + lif_interface_use_executor(cur_iface, addon); + free(addon); /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ if (!strcmp(addon, "dhcp")) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 8841c13..3f3bb69 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -63,10 +63,7 @@ lif_interface_init(struct lif_interface *interface, const char *ifname) interface->ifname = strdup(ifname); - if (strchr(ifname, '.') == NULL) - lif_dict_add(&interface->vars, "use", strdup("link")); - else - lif_dict_add(&interface->vars, "use", strdup("vlan")); + lif_interface_use_executor(interface, strchr(ifname, '.') == NULL ? "link" : "vlan"); } bool @@ -80,11 +77,8 @@ lif_interface_address_add(struct lif_interface *interface, const char *address) return false; } - if (!interface->is_static) - { - lif_dict_add(&interface->vars, "use", strdup("static")); - interface->is_static = true; - } + lif_interface_use_executor(interface, "static"); + interface->is_static = true; lif_dict_add(&interface->vars, "address", addr); @@ -137,6 +131,15 @@ lif_interface_fini(struct lif_interface *interface) free(interface->ifname); } +void +lif_interface_use_executor(struct lif_interface *interface, const char *executor) +{ + char *exec_addon = strdup(executor); + + if (lif_dict_add_once(&interface->vars, "use", exec_addon, (lif_dict_cmp_t) strcmp) == NULL) + free(exec_addon); +} + void lif_interface_collection_init(struct lif_dict *collection) { @@ -147,7 +150,7 @@ lif_interface_collection_init(struct lif_dict *collection) /* always enable loopback interface as part of a collection */ if_lo = lif_interface_collection_find(collection, "lo"); if_lo->is_auto = true; - lif_dict_add(&if_lo->vars, "use", strdup("loopback")); + lif_interface_use_executor(if_lo, "loopback"); } void diff --git a/libifupdown/interface.h b/libifupdown/interface.h index 045f848..8b808b3 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -68,6 +68,7 @@ extern void lif_interface_init(struct lif_interface *interface, const char *ifna extern bool lif_interface_address_add(struct lif_interface *interface, const char *address); extern void lif_interface_address_delete(struct lif_interface *interface, const char *address); extern void lif_interface_fini(struct lif_interface *interface); +extern void lif_interface_use_executor(struct lif_interface *interface, const char *executor); extern void lif_interface_collection_init(struct lif_dict *collection); extern void lif_interface_collection_fini(struct lif_dict *collection); From 846df3272f3117cad0adccd12a772c808c540023 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:10:26 -0600 Subject: [PATCH 180/530] remove lif_interface.is_static, no longer used --- libifupdown/interface-file.c | 5 ----- libifupdown/interface.c | 2 -- libifupdown/interface.h | 1 - 3 files changed, 8 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index bd6e0ba..5508715 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -168,11 +168,6 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) cur_iface->is_bridge = true; else if (!strcmp(executor, "bond")) cur_iface->is_bond = true; - else if (!strcmp(executor, "static")) - { - cur_iface->is_static = true; - continue; - } else if (!strcmp(executor, "link")) continue; diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 3f3bb69..c25591d 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -78,7 +78,6 @@ lif_interface_address_add(struct lif_interface *interface, const char *address) } lif_interface_use_executor(interface, "static"); - interface->is_static = true; lif_dict_add(&interface->vars, "address", addr); @@ -231,7 +230,6 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic return false; lif_dict_add(&interface->vars, "inherit", strdup(ifname)); - interface->is_static = parent->is_static; interface->is_dhcp = parent->is_dhcp; interface->is_bond = parent->is_bond; interface->is_bridge = parent->is_bridge; diff --git a/libifupdown/interface.h b/libifupdown/interface.h index 8b808b3..a562d63 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -51,7 +51,6 @@ struct lif_interface { bool is_auto; bool is_bridge; bool is_bond; - bool is_static; struct lif_dict vars; From e5c592f2c1bcd5bd657a5aeb92ff0cb80fa82fe7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:14:57 -0600 Subject: [PATCH 181/530] remove lif_interface.is_dhcp too --- libifupdown/interface-file.c | 15 ++------------- libifupdown/interface.c | 1 - libifupdown/interface.h | 1 - libifupdown/lifecycle.c | 5 +---- 4 files changed, 3 insertions(+), 19 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 5508715..4eaedd1 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -123,14 +123,9 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) while (*token) { if (!strcmp(token, "dhcp")) - { - cur_iface->is_dhcp = true; lif_interface_use_executor(cur_iface, "dhcp"); - } else if (!strcmp(token, "ppp")) - { lif_interface_use_executor(cur_iface, "ppp"); - } else if (!strcmp(token, "inherits")) { token = lif_next_token(&bufp); @@ -162,14 +157,10 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) } /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ - if (!strcmp(executor, "dhcp")) - cur_iface->is_dhcp = true; - else if (!strcmp(executor, "bridge")) + if (!strcmp(executor, "bridge")) cur_iface->is_bridge = true; else if (!strcmp(executor, "bond")) cur_iface->is_bond = true; - else if (!strcmp(executor, "link")) - continue; lif_interface_use_executor(cur_iface, executor); } @@ -217,9 +208,7 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) free(addon); /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ - if (!strcmp(addon, "dhcp")) - cur_iface->is_dhcp = true; - else if (!strcmp(addon, "bridge")) + if (!strcmp(addon, "bridge")) cur_iface->is_bridge = true; else if (!strcmp(addon, "bond")) cur_iface->is_bond = true; diff --git a/libifupdown/interface.c b/libifupdown/interface.c index c25591d..fe9acea 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -230,7 +230,6 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic return false; lif_dict_add(&interface->vars, "inherit", strdup(ifname)); - interface->is_dhcp = parent->is_dhcp; interface->is_bond = parent->is_bond; interface->is_bridge = parent->is_bridge; diff --git a/libifupdown/interface.h b/libifupdown/interface.h index a562d63..3f2c287 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -47,7 +47,6 @@ extern bool lif_address_unparse(const struct lif_address *address, char *buf, si struct lif_interface { char *ifname; - bool is_dhcp; bool is_auto; bool is_bridge; bool is_bond; diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index dc31474..d2a32e3 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -104,10 +104,7 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, struct lif lif_environment_push(envp, "IFACE", lifname); lif_environment_push(envp, "PHASE", phase); lif_environment_push(envp, "MODE", mode); - - /* try to provide $METHOD for ifupdown1 scripts if we can */ - if (iface->is_dhcp) - lif_environment_push(envp, "METHOD", "dhcp"); + lif_environment_push(envp, "METHOD", "none"); if (opts->verbose) lif_environment_push(envp, "VERBOSE", "1"); From 0928f07af513276febad98b2da6890b8300badee Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:20:07 -0600 Subject: [PATCH 182/530] interface-file: imply static executor use if gateway is specified --- libifupdown/interface-file.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 4eaedd1..1f2d19d 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -192,6 +192,19 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) lif_interface_address_add(cur_iface, addr); } + else if (!strcmp(token, "gateway")) + { + char *addr = lif_next_token(&bufp); + + if (cur_iface == NULL) + { + fprintf(stderr, "%s: gateway '%s' without interface\n", filename, addr); + goto parse_error; + } + + lif_interface_use_executor(cur_iface, "static"); + lif_dict_add(&cur_iface->vars, token, strdup(addr)); + } else if (cur_iface != NULL) { token = maybe_remap_token(token); From 4fdd91beee8bf7d659b4061854ab0153655c1761 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:20:26 -0600 Subject: [PATCH 183/530] test: add test for vrf static route support --- tests/ifquery_test | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ifquery_test b/tests/ifquery_test index 3c4361e..a53c22c 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -22,6 +22,7 @@ tests_init \ vrf_dependency \ vrf_ifupdown2_rewrite \ vrf_ifupdown2_dependency \ + vrf_implicit_static_gateway \ ppp_dependency \ ppp_legacy_rewrite \ tunnel_dependency \ @@ -139,6 +140,11 @@ vrf_ifupdown2_dependency_body() { ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf-ifupdown2.interfaces eth0 } +vrf_implicit_static_gateway_body() { + atf_check -s exit:0 -o match:"use static" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vrf.interfaces vrf-red +} + ppp_dependency_body() { atf_check -s exit:0 -o match:"requires eth0" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/ppp.interfaces ppp0 From d36a522470bf37a327974627149f6a021b59d880 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:34:59 -0600 Subject: [PATCH 184/530] interface-file: add and use report_error() --- libifupdown/interface-file.c | 65 +++++++++++++++++++++++++++++------- 1 file changed, 53 insertions(+), 12 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 1f2d19d..3e0dc6e 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -14,6 +14,7 @@ */ #include +#include #include #include #include "libifupdown/libifupdown.h" @@ -57,6 +58,37 @@ maybe_remap_token(const char *token) return tokbuf; } +/* map keywords to parser functions */ +struct parser_keyword { + const char *token; + bool (*handle)(struct lif_dict *collection, struct lif_interface *cur_iface, const char *filename, size_t lineno, char *token, char *bufp); +}; + +static const struct parser_keyword keywords[] = { +}; + +static int +keyword_cmp(const void *a, const void *b) +{ + const char *key = a; + const struct parser_keyword *token = b; + + return strcmp(key, token->token); +} + +static void +report_error(const char *filename, size_t lineno, const char *errfmt, ...) +{ + char errbuf[4096]; + + va_list va; + va_start(va, errfmt); + vsnprintf(errbuf, sizeof errbuf, errfmt, va); + va_end(va); + + fprintf(stderr, "%s:%zu: %s\n", filename, lineno, errbuf); +} + bool lif_interface_file_parse(struct lif_dict *collection, const char *filename) { @@ -68,15 +100,26 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) return false; char linebuf[4096]; + size_t lineno = 0; while (lif_fgetline(linebuf, sizeof linebuf, f) != NULL) { + lineno++; + char *bufp = linebuf; char *token = lif_next_token(&bufp); if (!*token || !isalpha(*token)) continue; - if (!strcmp(token, "source")) + const struct parser_keyword *parserkw = + bsearch(token, keywords, ARRAY_SIZE(keywords), sizeof(*keywords), keyword_cmp); + + if (parserkw != NULL) + { + if (!parserkw->handle(collection, cur_iface, filename, lineno, token, bufp)) + goto parse_error; + } + else if (!strcmp(token, "source")) { char *source_filename = lif_next_token(&bufp); if (!*source_filename) @@ -84,8 +127,8 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (!strcmp(filename, source_filename)) { - fprintf(stderr, "%s: attempt to source %s would create infinite loop\n", - filename, source_filename); + report_error(filename, lineno, "attempt to source %s would create infinite loop", + source_filename); goto parse_error; } @@ -132,13 +175,13 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (!*token) { - fprintf(stderr, "%s: inherits without interface\n", filename); + report_error(filename, lineno, "inherits without interface"); goto parse_error; } if (!lif_interface_collection_inherit(cur_iface, collection, token)) { - fprintf(stderr, "%s: could not inherit %s\n", filename, token); + report_error(filename, lineno, "could not inherit %s", token); goto parse_error; } } @@ -152,7 +195,7 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (cur_iface == NULL) { - fprintf(stderr, "%s: use '%s' without interface\n", filename, executor); + report_error(filename, lineno, "use '%s' without interface", executor); goto parse_error; } @@ -170,13 +213,13 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (!*token) { - fprintf(stderr, "%s: inherits without interface\n", filename); + report_error(filename, lineno, "inherits without interface"); goto parse_error; } if (!lif_interface_collection_inherit(cur_iface, collection, token)) { - fprintf(stderr, "%s: could not inherit %s\n", filename, token); + report_error(filename, lineno, "could not inherit %s", token); goto parse_error; } } @@ -186,7 +229,7 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (cur_iface == NULL) { - fprintf(stderr, "%s: address '%s' without interface\n", filename, addr); + report_error(filename, lineno, "%s: address '%s' without interface", filename, addr); goto parse_error; } @@ -198,7 +241,7 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (cur_iface == NULL) { - fprintf(stderr, "%s: gateway '%s' without interface\n", filename, addr); + report_error(filename, lineno, "%s: gateway '%s' without interface", filename, addr); goto parse_error; } @@ -233,8 +276,6 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) return true; parse_error: - fprintf(stderr, "libifupdown: %s: failed to parse line \"%s\"\n", - filename, linebuf); fclose(f); return false; } From b57aba1a97913668d6b98996cc137cff56201b93 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:41:07 -0600 Subject: [PATCH 185/530] interface-file: split out auto keyword handling --- libifupdown/interface-file.c | 76 ++++++++++++++++++++---------------- 1 file changed, 43 insertions(+), 33 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 3e0dc6e..a28ae43 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -58,23 +58,8 @@ maybe_remap_token(const char *token) return tokbuf; } -/* map keywords to parser functions */ -struct parser_keyword { - const char *token; - bool (*handle)(struct lif_dict *collection, struct lif_interface *cur_iface, const char *filename, size_t lineno, char *token, char *bufp); -}; - -static const struct parser_keyword keywords[] = { -}; - -static int -keyword_cmp(const void *a, const void *b) -{ - const char *key = a; - const struct parser_keyword *token = b; - - return strcmp(key, token->token); -} +/* XXX: remove this global variable somehow */ +static struct lif_interface *cur_iface = NULL; static void report_error(const char *filename, size_t lineno, const char *errfmt, ...) @@ -89,11 +74,50 @@ report_error(const char *filename, size_t lineno, const char *errfmt, ...) fprintf(stderr, "%s:%zu: %s\n", filename, lineno, errbuf); } +static bool +handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + (void) filename; + (void) lineno; + (void) token; + + char *ifname = lif_next_token(&bufp); + if (!*ifname && cur_iface == NULL) + return false; + else + { + cur_iface = lif_interface_collection_find(collection, ifname); + if (cur_iface == NULL) + return false; + } + + cur_iface->is_auto = true; + return true; +} + +/* map keywords to parser functions */ +struct parser_keyword { + const char *token; + bool (*handle)(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp); +}; + +static const struct parser_keyword keywords[] = { + {"auto", handle_auto}, +}; + +static int +keyword_cmp(const void *a, const void *b) +{ + const char *key = a; + const struct parser_keyword *token = b; + + return strcmp(key, token->token); +} + bool lif_interface_file_parse(struct lif_dict *collection, const char *filename) { lif_interface_collection_init(collection); - struct lif_interface *cur_iface = NULL; FILE *f = fopen(filename, "r"); if (f == NULL) @@ -116,7 +140,7 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (parserkw != NULL) { - if (!parserkw->handle(collection, cur_iface, filename, lineno, token, bufp)) + if (!parserkw->handle(collection, filename, lineno, token, bufp)) goto parse_error; } else if (!strcmp(token, "source")) @@ -134,20 +158,6 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) lif_interface_file_parse(collection, source_filename); } - else if (!strcmp(token, "auto")) - { - char *ifname = lif_next_token(&bufp); - if (!*ifname && cur_iface == NULL) - goto parse_error; - else - { - cur_iface = lif_interface_collection_find(collection, ifname); - if (cur_iface == NULL) - goto parse_error; - } - - cur_iface->is_auto = true; - } else if (!strcmp(token, "iface")) { char *ifname = lif_next_token(&bufp); From df9c0284b1ca0676b3f94a3568f01c2245c909e9 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:45:56 -0600 Subject: [PATCH 186/530] interface-file: let commands initialize the interface collection themselves --- cmd/ifquery.c | 2 ++ cmd/ifupdown.c | 2 ++ libifupdown/interface-file.c | 2 -- 3 files changed, 4 insertions(+), 2 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 1e52247..ac07cbd 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -275,6 +275,8 @@ ifquery_main(int argc, char *argv[]) struct lif_dict state = {}; struct lif_dict collection = {}; + lif_interface_collection_init(&collection); + if (!lif_state_read_path(&state, exec_opts.state_file)) { fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.state_file); diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 0fa7e29..bd9a68e 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -163,6 +163,8 @@ ifupdown_main(int argc, char *argv[]) struct lif_dict state = {}; struct lif_dict collection = {}; + lif_interface_collection_init(&collection); + if (!lif_state_read_path(&state, exec_opts.state_file)) { fprintf(stderr, "%s: could not parse %s\n", argv0, exec_opts.state_file); diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index a28ae43..8a1f002 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -117,8 +117,6 @@ keyword_cmp(const void *a, const void *b) bool lif_interface_file_parse(struct lif_dict *collection, const char *filename) { - lif_interface_collection_init(collection); - FILE *f = fopen(filename, "r"); if (f == NULL) return false; From 4a11d4fdd8fddca706f2ae9f4c64a52a38feb3b5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 03:46:31 -0600 Subject: [PATCH 187/530] interface-file: break out source keyword handling --- libifupdown/interface-file.c | 38 ++++++++++++++++++++++-------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 8a1f002..f1f18ce 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -95,6 +95,28 @@ handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, ch return true; } +static bool +handle_source(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + (void) token; + + char *source_filename = lif_next_token(&bufp); + if (!*source_filename) + { + report_error(filename, lineno, "missing filename to source"); + return false; + } + + if (!strcmp(filename, source_filename)) + { + report_error(filename, lineno, "attempt to source %s would create infinite loop", + source_filename); + return false; + } + + return lif_interface_file_parse(collection, source_filename); +} + /* map keywords to parser functions */ struct parser_keyword { const char *token; @@ -103,6 +125,7 @@ struct parser_keyword { static const struct parser_keyword keywords[] = { {"auto", handle_auto}, + {"source", handle_source}, }; static int @@ -141,21 +164,6 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (!parserkw->handle(collection, filename, lineno, token, bufp)) goto parse_error; } - else if (!strcmp(token, "source")) - { - char *source_filename = lif_next_token(&bufp); - if (!*source_filename) - goto parse_error; - - if (!strcmp(filename, source_filename)) - { - report_error(filename, lineno, "attempt to source %s would create infinite loop", - source_filename); - goto parse_error; - } - - lif_interface_file_parse(collection, source_filename); - } else if (!strcmp(token, "iface")) { char *ifname = lif_next_token(&bufp); From aba140a9770f3527973565489e97ee1e0445b93c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 04:04:34 -0600 Subject: [PATCH 188/530] interface-file: use bsearch to find parser functions --- libifupdown/interface-file.c | 292 ++++++++++++++++++++--------------- 1 file changed, 170 insertions(+), 122 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index f1f18ce..7b2766e 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -74,6 +74,25 @@ report_error(const char *filename, size_t lineno, const char *errfmt, ...) fprintf(stderr, "%s:%zu: %s\n", filename, lineno, errbuf); } +static bool +handle_address(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + (void) collection; + (void) token; + + char *addr = lif_next_token(&bufp); + + if (cur_iface == NULL) + { + report_error(filename, lineno, "%s '%s' without interface", token, addr); + return false; + } + + lif_interface_address_add(cur_iface, addr); + + return true; +} + static bool handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) { @@ -95,6 +114,127 @@ handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, ch return true; } +static bool +handle_gateway(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + (void) collection; + (void) token; + + char *addr = lif_next_token(&bufp); + + if (cur_iface == NULL) + { + report_error(filename, lineno, "%s '%s' without interface", token, addr); + return false; + } + + lif_interface_use_executor(cur_iface, "static"); + lif_dict_add(&cur_iface->vars, token, strdup(addr)); + + return true; +} + +static bool +handle_generic(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + (void) collection; + (void) filename; + (void) lineno; + + if (cur_iface == NULL) + return true; + + token = maybe_remap_token(token); + + lif_dict_add(&cur_iface->vars, token, strdup(bufp)); + + /* Check if token looks like - and assume is an addon */ + char *word_end = strchr(token, '-'); + if (word_end != NULL) + { + /* Copy word1 to not mangle *token */ + char *addon = strndup(token, word_end - token); + lif_interface_use_executor(cur_iface, addon); + free(addon); + + /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ + if (!strcmp(addon, "bridge")) + cur_iface->is_bridge = true; + else if (!strcmp(addon, "bond")) + cur_iface->is_bond = true; + } + + return true; +} + +static bool handle_inherit(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp); + +static bool +handle_iface(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + char *ifname = lif_next_token(&bufp); + if (!*ifname) + { + report_error(filename, lineno, "%s without any other tokens", token); + return false; + } + + cur_iface = lif_interface_collection_find(collection, ifname); + if (cur_iface == NULL) + { + report_error(filename, lineno, "could not upsert interface %s", ifname); + return false; + } + + /* in original ifupdown config, we can have "inet loopback" + * or "inet dhcp" or such to designate hints. lets pick up + * those hints here. + */ + token = lif_next_token(&bufp); + while (*token) + { + if (!strcmp(token, "dhcp")) + lif_interface_use_executor(cur_iface, "dhcp"); + else if (!strcmp(token, "ppp")) + lif_interface_use_executor(cur_iface, "ppp"); + else if (!strcmp(token, "inherits")) + { + if (!handle_inherit(collection, filename, lineno, token, bufp)) + return false; + } + + token = lif_next_token(&bufp); + } + + return true; +} + +static bool +handle_inherit(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + char *target = lif_next_token(&bufp); + + if (cur_iface == NULL) + { + report_error(filename, lineno, "%s '%s' without interface", token, target); + return false; + } + + if (!*target) + { + report_error(filename, lineno, "%s: unspecified interface"); + return false; + } + + if (!lif_interface_collection_inherit(cur_iface, collection, target)) + { + report_error(filename, lineno, "could not inherit %s", target); + return false; + } + + return true; +} + static bool handle_source(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) { @@ -117,6 +257,29 @@ handle_source(struct lif_dict *collection, const char *filename, size_t lineno, return lif_interface_file_parse(collection, source_filename); } +static bool +handle_use(struct lif_dict *collection, const char *filename, size_t lineno, char *token, char *bufp) +{ + (void) collection; + + char *executor = lif_next_token(&bufp); + + if (cur_iface == NULL) + { + report_error(filename, lineno, "%s '%s' without interface", token, executor); + return false; + } + + /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ + if (!strcmp(executor, "bridge")) + cur_iface->is_bridge = true; + else if (!strcmp(executor, "bond")) + cur_iface->is_bond = true; + + lif_interface_use_executor(cur_iface, executor); + return true; +} + /* map keywords to parser functions */ struct parser_keyword { const char *token; @@ -124,8 +287,13 @@ struct parser_keyword { }; static const struct parser_keyword keywords[] = { + {"address", handle_address}, {"auto", handle_auto}, + {"gateway", handle_gateway}, + {"iface", handle_iface}, + {"inherit", handle_inherit}, {"source", handle_source}, + {"use", handle_use}, }; static int @@ -164,128 +332,8 @@ lif_interface_file_parse(struct lif_dict *collection, const char *filename) if (!parserkw->handle(collection, filename, lineno, token, bufp)) goto parse_error; } - else if (!strcmp(token, "iface")) - { - char *ifname = lif_next_token(&bufp); - if (!*ifname) - goto parse_error; - - cur_iface = lif_interface_collection_find(collection, ifname); - if (cur_iface == NULL) - goto parse_error; - - /* in original ifupdown config, we can have "inet loopback" - * or "inet dhcp" or such to designate hints. lets pick up - * those hints here. - */ - char *token = lif_next_token(&bufp); - while (*token) - { - if (!strcmp(token, "dhcp")) - lif_interface_use_executor(cur_iface, "dhcp"); - else if (!strcmp(token, "ppp")) - lif_interface_use_executor(cur_iface, "ppp"); - else if (!strcmp(token, "inherits")) - { - token = lif_next_token(&bufp); - - if (!*token) - { - report_error(filename, lineno, "inherits without interface"); - goto parse_error; - } - - if (!lif_interface_collection_inherit(cur_iface, collection, token)) - { - report_error(filename, lineno, "could not inherit %s", token); - goto parse_error; - } - } - - token = lif_next_token(&bufp); - } - } - else if (!strcmp(token, "use")) - { - char *executor = lif_next_token(&bufp); - - if (cur_iface == NULL) - { - report_error(filename, lineno, "use '%s' without interface", executor); - goto parse_error; - } - - /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ - if (!strcmp(executor, "bridge")) - cur_iface->is_bridge = true; - else if (!strcmp(executor, "bond")) - cur_iface->is_bond = true; - - lif_interface_use_executor(cur_iface, executor); - } - else if (!strcmp(token, "inherit")) - { - token = lif_next_token(&bufp); - - if (!*token) - { - report_error(filename, lineno, "inherits without interface"); - goto parse_error; - } - - if (!lif_interface_collection_inherit(cur_iface, collection, token)) - { - report_error(filename, lineno, "could not inherit %s", token); - goto parse_error; - } - } - else if (!strcmp(token, "address")) - { - char *addr = lif_next_token(&bufp); - - if (cur_iface == NULL) - { - report_error(filename, lineno, "%s: address '%s' without interface", filename, addr); - goto parse_error; - } - - lif_interface_address_add(cur_iface, addr); - } - else if (!strcmp(token, "gateway")) - { - char *addr = lif_next_token(&bufp); - - if (cur_iface == NULL) - { - report_error(filename, lineno, "%s: gateway '%s' without interface", filename, addr); - goto parse_error; - } - - lif_interface_use_executor(cur_iface, "static"); - lif_dict_add(&cur_iface->vars, token, strdup(addr)); - } - else if (cur_iface != NULL) - { - token = maybe_remap_token(token); - - lif_dict_add(&cur_iface->vars, token, strdup(bufp)); - - /* Check if token looks like - and assume is an addon */ - char *word_end = strchr(token, '-'); - if (word_end != NULL) - { - /* Copy word1 to not mangle *token */ - char *addon = strndup(token, word_end - token); - lif_interface_use_executor(cur_iface, addon); - free(addon); - - /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ - if (!strcmp(addon, "bridge")) - cur_iface->is_bridge = true; - else if (!strcmp(addon, "bond")) - cur_iface->is_bond = true; - } - } + else if (!handle_generic(collection, filename, lineno, token, bufp)) + goto parse_error; } fclose(f); From 6d15f21073c969749dd1eae8f687abfe41cf6eca Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 04:07:51 -0600 Subject: [PATCH 189/530] interface: handle is_bridge and is_bond hacks in a single place --- libifupdown/interface-file.c | 12 ------------ libifupdown/interface.c | 6 ++++++ 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 7b2766e..06a3c66 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -156,12 +156,6 @@ handle_generic(struct lif_dict *collection, const char *filename, size_t lineno, char *addon = strndup(token, word_end - token); lif_interface_use_executor(cur_iface, addon); free(addon); - - /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ - if (!strcmp(addon, "bridge")) - cur_iface->is_bridge = true; - else if (!strcmp(addon, "bond")) - cur_iface->is_bond = true; } return true; @@ -270,12 +264,6 @@ handle_use(struct lif_dict *collection, const char *filename, size_t lineno, cha return false; } - /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ - if (!strcmp(executor, "bridge")) - cur_iface->is_bridge = true; - else if (!strcmp(executor, "bond")) - cur_iface->is_bond = true; - lif_interface_use_executor(cur_iface, executor); return true; } diff --git a/libifupdown/interface.c b/libifupdown/interface.c index fe9acea..b662199 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -137,6 +137,12 @@ lif_interface_use_executor(struct lif_interface *interface, const char *executor if (lif_dict_add_once(&interface->vars, "use", exec_addon, (lif_dict_cmp_t) strcmp) == NULL) free(exec_addon); + + /* pass requires as compatibility env vars to appropriate executors (bridge, bond) */ + if (!strcmp(executor, "bridge")) + interface->is_bridge = true; + else if (!strcmp(executor, "bond")) + interface->is_bond = true; } void From ce07e1ff1f09856764273c8bcbc908795bde7e21 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 04:40:38 -0600 Subject: [PATCH 190/530] static: add support for the metric property --- executor-scripts/linux/static | 4 ++-- tests/linux/static_test | 18 +++++++++++++++++- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index e14ca6b..f03b61d 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -1,7 +1,7 @@ #!/bin/sh -VRF_TABLE="" [ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" +[ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC" addr_family() { if [ "$1" != "${1#*[0-9].[0-9]}" ]; then @@ -23,7 +23,7 @@ configure_addresses() { configure_gateways() { for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do addrfam=$(addr_family $i) - ${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE + ${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE $METRIC done } diff --git a/tests/linux/static_test b/tests/linux/static_test index 79bf820..d8bdab2 100755 --- a/tests/linux/static_test +++ b/tests/linux/static_test @@ -4,7 +4,7 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static" FIXTURES="$(atf_get_srcdir)/../fixtures" -tests_init up down vrf_up vrf_down +tests_init up down vrf_up vrf_down metric_up metric_down up_body() { export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" @@ -41,3 +41,19 @@ vrf_down_body() { -o match:'route del default via 203.0.113.2 table 1' \ ${EXECUTOR} } + +metric_up_body() { + export IFACE=vrf-red PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ + IF_VRF_TABLE=1 IF_METRIC=20 + atf_check -s exit:0 \ + -o match:'route add default via 203.0.113.2 table 1 metric 20' \ + ${EXECUTOR} +} + +metric_down_body() { + export IFACE=vrf-red PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/vrf.interfaces" \ + IF_VRF_TABLE=1 IF_METRIC=20 + atf_check -s exit:0 \ + -o match:'route del default via 203.0.113.2 table 1 metric 20' \ + ${EXECUTOR} +} From 05df95964e5a3e462c7a4439877aabe3a52e48bf Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 04:42:48 -0600 Subject: [PATCH 191/530] ifupdown-ng 0.8.0. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 77778ba..df73195 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.7.0 +PACKAGE_VERSION := 0.8.0 PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new From 90ba72efe2acb20703428832d2b4b763989b4ee9 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 20 Aug 2020 04:46:06 -0600 Subject: [PATCH 192/530] makefile: add missing optional executors --- Makefile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index df73195..736e0b6 100644 --- a/Makefile +++ b/Makefile @@ -78,11 +78,13 @@ EXECUTOR_SCRIPTS_CORE ?= \ ipv6-ra \ static \ link \ + ppp EXECUTOR_SCRIPTS_OPT ?= \ bridge \ vrf \ - tunnel + tunnel \ + gre EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} From 72ad50213fc6292b22074a094a8cab6105086b2e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 02:19:01 -0600 Subject: [PATCH 193/530] cmd: fix regression with ifdown -f handling Alpine #11887 --- cmd/multicall-exec-options.c | 2 +- tests/ifdown_test | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/cmd/multicall-exec-options.c b/cmd/multicall-exec-options.c index c87e79e..cd57a22 100644 --- a/cmd/multicall-exec-options.c +++ b/cmd/multicall-exec-options.c @@ -74,7 +74,7 @@ no_op(const char *opt_arg) } static struct if_option exec_options[] = { - {'f', "force", NULL, "force (de)configuration", true, no_op}, + {'f', "force", NULL, "force (de)configuration", false, no_op}, {'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, set_interfaces_file}, {'l', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, set_no_lock}, {'n', "no-act", NULL, "do not actually run any commands", false, set_no_act}, diff --git a/tests/ifdown_test b/tests/ifdown_test index e54d148..3a8510a 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -18,7 +18,8 @@ tests_init \ learned_dependency \ learned_dependency_2 \ learned_executor \ - implicit_vlan + implicit_vlan \ + regress_opt_f noargs_body() { atf_check -s exit:1 -e ignore ifdown -S/dev/null @@ -140,3 +141,8 @@ implicit_vlan_body() { -e match:"attempting to run link executor" \ ifdown -n -S $FIXTURES/vlan.ifstate -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 } + +regress_opt_f_body() { + atf_check -s exit:0 -o ignore -e ignore \ + ifdown -n -S $FIXTURES/vlan.ifstate -E $EXECUTORS -i $FIXTURES/vlan.interfaces -f eth0.8 +} From badcccaa5b83313e5fc1acc1d90e1c1fbe191b65 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 02:58:39 -0600 Subject: [PATCH 194/530] link executor: integrate physical vlan configuration --- executor-scripts/linux/link | 60 ++++++++++++++++++++++++++++++++++--- executor-scripts/stub/vlan | 7 ----- tests/linux/link_test | 35 +++++++++++++++++++++- 3 files changed, 90 insertions(+), 12 deletions(-) delete mode 100755 executor-scripts/stub/vlan diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 2aafd67..d7cf0ad 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -1,9 +1,61 @@ #!/bin/sh -[ -z "$VERBOSE" ] || set -x -OPTIONS="" + +[ -n "$VERBOSE" ] && set -x + +IF_LINK_OPTIONS="$IF_LINK_OPTIONS" +[ -n "$IF_MTU" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS mtu $IF_MTU" + +is_vlan() { + case "$IFACE" in + *#*) return 1 ;; + *:*) return 1 ;; + vlan*.*) return 1 ;; + vlan*) + IF_VLAN_ID="${IFACE#vlan}" + [ -n "${IF_VLAN_RAW_DEVICE:-}" ] && return 0 + return 1 + ;; + *.*) + IF_VLAN_RAW_DEVICE="${IFACE%.*}" + IF_VLAN_ID="${IFACE##*.}" + return 0 + ;; + *) + [ -z "${IF_VLAN_ID:-}" ] && return 1 + [ -z "${IF_VLAN_RAW_DEVICE:-}" ] && return 1 + return 0 + ;; + esac +} + case "$PHASE" in up|down) - [ -n "$IF_MTU" ] && OPTIONS="$OPTIONS mtu $IF_MTU" - ${MOCK} ip link set $PHASE dev $IFACE $OPTIONS + if is_vlan; then + ADD_DEL="add" + [ "$PHASE" = "down" ] && ADD_DEL="delete" + + if [ -e /sys/class/net/$IFACE ]; then + exit 0 + fi + + if [ -z "$MOCK" ]; then + if ! ip link show "$IF_VLAN_RAW_DEVICE" >/dev/null; then + echo "Device $IF_VLAN_RAW_DEVICE for $IFACE does not exist" + exit 1 + fi + fi + + if ! [ -d /proc/net/vlan ]; then + echo "Loading 8021q kernel module for VLAN support" + ${MOCK} modprobe 8021q + fi + + ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" + else + ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS + fi + ;; +depend) + echo "$IF_VLAN_RAW_DEVICE" ;; esac diff --git a/executor-scripts/stub/vlan b/executor-scripts/stub/vlan deleted file mode 100755 index ba37599..0000000 --- a/executor-scripts/stub/vlan +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/sh -case "$PHASE" in -depend) - RAW_DEVICE="${IFACE%.*}" - echo "$RAW_DEVICE" - ;; -esac diff --git a/tests/linux/link_test b/tests/linux/link_test index 717d462..def1b43 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -3,7 +3,14 @@ . $(atf_get_srcdir)/../test_env.sh EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/link" -tests_init up down mtu +tests_init \ + up \ + down \ + mtu \ + vlan_explicit_up \ + vlan_explicit_down \ + vlan_guessed_up \ + vlan_guessed_down up_body() { export IFACE=lo PHASE=up MOCK=echo @@ -22,3 +29,29 @@ mtu_body() { atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \ ${EXECUTOR} } + +vlan_explicit_up_body() { + export IFACE=servers PHASE=up MOCK=echo \ + IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" + atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \ + ${EXECUTOR} +} + +vlan_explicit_down_body() { + export IFACE=servers PHASE=down MOCK=echo \ + IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" + atf_check -s exit:0 -o match:'ip link delete link eth0 name servers type vlan id 123' \ + ${EXECUTOR} +} + +vlan_guessed_up_body() { + export IFACE=eth0.8 PHASE=up MOCK=echo + atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ + ${EXECUTOR} +} + +vlan_guessed_down_body() { + export IFACE=eth0.8 PHASE=down MOCK=echo + atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ + ${EXECUTOR} +} From 8e7c935cdf1fd43b0592336d3913cc4b0e8a6e28 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 03:01:38 -0600 Subject: [PATCH 195/530] link executor tests: test vlan dependency learning --- executor-scripts/linux/link | 4 +++- tests/linux/link_test | 17 ++++++++++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index d7cf0ad..aec3a7c 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -56,6 +56,8 @@ up|down) fi ;; depend) - echo "$IF_VLAN_RAW_DEVICE" + if is_vlan; then + echo "$IF_VLAN_RAW_DEVICE" + fi ;; esac diff --git a/tests/linux/link_test b/tests/linux/link_test index def1b43..1cb2784 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -10,7 +10,9 @@ tests_init \ vlan_explicit_up \ vlan_explicit_down \ vlan_guessed_up \ - vlan_guessed_down + vlan_guessed_down \ + vlan_explicit_depend \ + vlan_guessed_depend up_body() { export IFACE=lo PHASE=up MOCK=echo @@ -55,3 +57,16 @@ vlan_guessed_down_body() { atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } + +vlan_explicit_depend_body() { + export IFACE=servers PHASE=up MOCK=echo \ + IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" + atf_check -s exit:0 -o match:'eth0' \ + ${EXECUTOR} +} + +vlan_guessed_depend_body() { + export IFACE=eth0.8 PHASE=depend + atf_check -s exit:0 -o match:'eth0' \ + ${EXECUTOR} +} From 1384b38c78271f1c5bf0f0a9d28c5f1bd38c1a66 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 03:06:32 -0600 Subject: [PATCH 196/530] interface: use link executor on vlans too --- libifupdown/interface.c | 6 +++++- tests/ifquery_test | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index fe9acea..4f348dc 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -63,7 +63,11 @@ lif_interface_init(struct lif_interface *interface, const char *ifname) interface->ifname = strdup(ifname); - lif_interface_use_executor(interface, strchr(ifname, '.') == NULL ? "link" : "vlan"); + lif_interface_use_executor(interface, "link"); + + /* keep the 'vlan' executor as a config hint for backwards compatibility */ + if (strchr(ifname, '.') != NULL) + lif_interface_use_executor(interface, "vlan"); } bool diff --git a/tests/ifquery_test b/tests/ifquery_test index a53c22c..26c0c6f 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -30,7 +30,9 @@ tests_init \ tunnel_legacy_rewrite \ tunnel_ifupdown2_dependency \ tunnel_ifupdown2_rewrite \ - gre_dependency + gre_dependency \ + vlan_explicit_learned_dependency \ + vlan_guessed_learned_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -192,3 +194,15 @@ gre_dependency_body() { atf_check -s exit:0 -o match:"requires eth0" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/gre.interfaces tun0 } + +vlan_explicit_learned_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + -o match:"use vlan" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan-named.interfaces servers +} + +vlan_guessed_learned_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + -o match:"use vlan" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan.interfaces eth0.8 +} From 3abe6b1bd56e059f0f8f359a9303346ece9bf07e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 03:11:45 -0600 Subject: [PATCH 197/530] github: add kyua debug --- .github/workflows/build.yml | 5 ++++- Makefile | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0197eac..c834aa3 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,5 +15,8 @@ jobs: - name: Checkout uses: actions/checkout@v2 - - name: Build and run tests + - name: Build + run: make + + - name: Run tests run: make check diff --git a/Makefile b/Makefile index 736e0b6..2f3136c 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ clean: rm -f ${MANPAGES} check: ${LIBIFUPDOWN_LIB} ${CMDS} - kyua test + kyua test || kyua report --verbose install: all install -D -m755 ${MULTICALL} ${DESTDIR}/sbin/${MULTICALL} From 14e2fecc200c5d2faa1edef74f22ef4677fb144e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 03:33:57 -0600 Subject: [PATCH 198/530] tests: add vlan-named.interfaces fixture --- tests/fixtures/vlan-named.interfaces | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 tests/fixtures/vlan-named.interfaces diff --git a/tests/fixtures/vlan-named.interfaces b/tests/fixtures/vlan-named.interfaces new file mode 100644 index 0000000..73e8ae2 --- /dev/null +++ b/tests/fixtures/vlan-named.interfaces @@ -0,0 +1,4 @@ +iface servers + vlan-raw-device eth0 + vlan-id 8 + address 2001:db8:1000:2::2/64 From 536612d02b808ec2afed58e83ec4bfb364c2976f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 03:36:26 -0600 Subject: [PATCH 199/530] build: ensure we exit 1 after running kyua report --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 2f3136c..9357aae 100644 --- a/Makefile +++ b/Makefile @@ -111,7 +111,7 @@ clean: rm -f ${MANPAGES} check: ${LIBIFUPDOWN_LIB} ${CMDS} - kyua test || kyua report --verbose + kyua test || (kyua report --verbose && exit 1) install: all install -D -m755 ${MULTICALL} ${DESTDIR}/sbin/${MULTICALL} From f17fa09944ae735d56ae2134f499a12d22c344d6 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 04:00:31 -0600 Subject: [PATCH 200/530] ifupdown-ng 0.8.1. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 9357aae..d7c4a91 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.8.0 +PACKAGE_VERSION := 0.8.1 PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new From 050ab77bd3999b1ef8c60ee2793d55d7999c306f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 10:06:06 -0600 Subject: [PATCH 201/530] tests: add vlan-complex.interface and ifquery test for it --- tests/fixtures/vlan-complex.interfaces | 18 ++++++++++++++++++ tests/ifquery_test | 14 +++++++++++++- 2 files changed, 31 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/vlan-complex.interfaces diff --git a/tests/fixtures/vlan-complex.interfaces b/tests/fixtures/vlan-complex.interfaces new file mode 100644 index 0000000..e06b617 --- /dev/null +++ b/tests/fixtures/vlan-complex.interfaces @@ -0,0 +1,18 @@ +# From Alpine issue #11885. +iface lo inet loopback + +auto eth0 +iface eth0 + address 1.2.3.4/24 + address abcd:ef12:3456:3::4/64 + mtu 8000 + +auto servers +iface servers + address 1.2.10.4/24 + gateway 1.2.10.1 + address abcd:ef12:3456:10::4/64 + gateway abcd:ef12:3456:10::1 + mtu 8000 + vlan-raw-device eth0 + vlan_id 5 diff --git a/tests/ifquery_test b/tests/ifquery_test index 26c0c6f..9d86e28 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -32,7 +32,8 @@ tests_init \ tunnel_ifupdown2_rewrite \ gre_dependency \ vlan_explicit_learned_dependency \ - vlan_guessed_learned_dependency + vlan_guessed_learned_dependency \ + vlan_complex_learned_dependency noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -206,3 +207,14 @@ vlan_guessed_learned_dependency_body() { -o match:"use vlan" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan.interfaces eth0.8 } + +vlan_complex_learned_dependency_body() { + atf_check -s exit:0 -o match:"requires eth0" \ + -o match:"use vlan" \ + -o match:"address 1.2.10.4/24" \ + -o match:"gateway 1.2.10.1" \ + -o match:"address abcd:ef12:3456:10::4/64" \ + -o match:"gateway abcd:ef12:3456:10::1" \ + -o match:"vlan-raw-device eth0" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan-complex.interfaces servers +} From aba4b18862c5c10f22b1b490a478c7fbe83607af Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 10:36:17 -0600 Subject: [PATCH 202/530] lifecycle: add some helpful debug --- libifupdown/lifecycle.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index d2a32e3..58127e2 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -255,7 +255,11 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par /* already up or down, skip */ if (up == iface->is_up) + { + fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s)\n", + iface->ifname, parent->ifname); continue; + } if (opts->verbose) fprintf(stderr, "ifupdown: changing state of dependent interface %s (of %s) to %s\n", From 8fe264a1201a6204a7eb06f4c39c9cfa97538e96 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 10:36:27 -0600 Subject: [PATCH 203/530] link executor: switch to pre-up/post-down --- executor-scripts/linux/link | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index aec3a7c..d8e87a9 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -29,12 +29,14 @@ is_vlan() { } case "$PHASE" in -up|down) +pre-up|post-down) + UP_DOWN="${PHASE##*-}" + if is_vlan; then ADD_DEL="add" - [ "$PHASE" = "down" ] && ADD_DEL="delete" + [ "$UP_DOWN" = "down" ] && ADD_DEL="delete" - if [ -e /sys/class/net/$IFACE ]; then + if [ "$UP_DOWN" = "up" -a -e /sys/class/net/$IFACE ]; then exit 0 fi @@ -51,8 +53,9 @@ up|down) fi ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" + [ "$UP_DOWN" = "up" ] && ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS else - ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS + ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS fi ;; depend) From dc52642d73471dc84cdbc8562c4a11e63e9aec6b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 10:52:10 -0600 Subject: [PATCH 204/530] static executor: default to metric=1 if not specified this is needed to override learned routes if a gateway is configured --- executor-scripts/linux/static | 1 + 1 file changed, 1 insertion(+) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index f03b61d..b1c9f8d 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -1,5 +1,6 @@ #!/bin/sh +[ -z "$IF_METRIC" ] && IF_METRIC="1" [ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" [ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC" From 80cdfc7f961ede97b0b30e02c534c057a3c514e7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 10:56:56 -0600 Subject: [PATCH 205/530] link executor: use slightly different strategy for taking vlans down --- executor-scripts/linux/link | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index d8e87a9..c0d8b51 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -53,7 +53,9 @@ pre-up|post-down) fi ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" - [ "$UP_DOWN" = "up" ] && ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS + [ "$UP_DOWN" = "down" ] && exit 0 + + ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS else ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS fi From dfb979d00dab951b32c8301daa084e91e5ef4846 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 11:03:18 -0600 Subject: [PATCH 206/530] list: add LIF_LIST_FOREACH_REVERSE() --- libifupdown/list.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libifupdown/list.h b/libifupdown/list.h index 4a495b5..877354e 100644 --- a/libifupdown/list.h +++ b/libifupdown/list.h @@ -42,4 +42,7 @@ extern void lif_node_delete(struct lif_node *node, struct lif_list *list); #define LIF_LIST_FOREACH_SAFE(iter, iter_next, head) \ for ((iter) = (head), (iter_next) = (iter)->next; (iter) != NULL; (iter) = (iter_next), (iter_next) = (iter) != NULL ? (iter)->next : NULL) +#define LIF_LIST_FOREACH_REVERSE(iter, tail) \ + for ((iter) = (tail); (iter) != NULL; (iter) = (iter)->prev) + #endif From de20e5f8a98fab8d3cc4467c38661d3b4af25be4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 11:04:48 -0600 Subject: [PATCH 207/530] lifecycle: handle executors in reverse order when taking an interface down --- libifupdown/dict.h | 3 +++ libifupdown/lifecycle.c | 34 +++++++++++++++++++++++----------- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/libifupdown/dict.h b/libifupdown/dict.h index 9a48ad2..2ede9a2 100644 --- a/libifupdown/dict.h +++ b/libifupdown/dict.h @@ -35,6 +35,9 @@ struct lif_dict_entry { #define LIF_DICT_FOREACH_SAFE(iter, iter_next, dict) \ LIF_LIST_FOREACH_SAFE((iter), (iter_next), (dict)->list.head) +#define LIF_DICT_FOREACH_REVERSE(iter, dict) \ + LIF_LIST_FOREACH_REVERSE((iter), (dict)->list.tail) + typedef int (*lif_dict_cmp_t)(const void *, const void *); extern void lif_dict_init(struct lif_dict *dict); diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 58127e2..a70fcc1 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -43,21 +43,33 @@ handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[ return true; } +static inline bool +handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struct lif_execute_opts *opts, char *const envp[]) +{ + if (strcmp(entry->key, "use")) + return true; + + const char *cmd = entry->data; + if (!lif_maybe_run_executor(opts, envp, cmd)) + return false; + + return true; +} + static bool -handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface) +handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, bool up) { struct lif_node *iter; - LIF_DICT_FOREACH(iter, &iface->vars) + if (up) { - struct lif_dict_entry *entry = iter->data; - - if (strcmp(entry->key, "use")) - continue; - - const char *cmd = entry->data; - if (!lif_maybe_run_executor(opts, envp, cmd)) - return false; + LIF_DICT_FOREACH(iter, &iface->vars) + handle_single_executor_for_phase(iter->data, opts, envp); + } + else + { + LIF_DICT_FOREACH_REVERSE(iter, &iface->vars) + handle_single_executor_for_phase(iter->data, opts, envp); } return true; @@ -219,7 +231,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac build_environment(&envp, opts, iface, lifname, phase, up ? "start" : "stop"); - if (!handle_executors_for_phase(opts, envp, iface)) + if (!handle_executors_for_phase(opts, envp, iface, up)) goto handle_error; if (!handle_commands_for_phase(opts, envp, iface, phase)) From b378305286563e7102f833f22f2bb3e4f420f629 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 11:07:40 -0600 Subject: [PATCH 208/530] link executor: don't try to modprobe in mock mode --- executor-scripts/linux/link | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index c0d8b51..2aa78f9 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -45,11 +45,11 @@ pre-up|post-down) echo "Device $IF_VLAN_RAW_DEVICE for $IFACE does not exist" exit 1 fi - fi - if ! [ -d /proc/net/vlan ]; then - echo "Loading 8021q kernel module for VLAN support" - ${MOCK} modprobe 8021q + if ! [ -d /proc/net/vlan ]; then + echo "Loading 8021q kernel module for VLAN support" + ${MOCK} modprobe 8021q + fi fi ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" From db5d2b8afd2b0dd1d62558a8f8b922b732cf1521 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 11:08:42 -0600 Subject: [PATCH 209/530] link tests: fix phasing --- tests/linux/link_test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/linux/link_test b/tests/linux/link_test index 1cb2784..6a8ff24 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -15,51 +15,51 @@ tests_init \ vlan_guessed_depend up_body() { - export IFACE=lo PHASE=up MOCK=echo + export IFACE=lo PHASE=pre-up MOCK=echo atf_check -s exit:0 -o match:'ip link set up dev lo' \ ${EXECUTOR} } down_body() { - export IFACE=lo PHASE=down MOCK=echo + export IFACE=lo PHASE=post-down MOCK=echo atf_check -s exit:0 -o match:'ip link set down dev lo' \ ${EXECUTOR} } mtu_body() { - export IFACE=eth0 PHASE=up MOCK=echo IF_MTU=1492 + export IFACE=eth0 PHASE=pre-up MOCK=echo IF_MTU=1492 atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \ ${EXECUTOR} } vlan_explicit_up_body() { - export IFACE=servers PHASE=up MOCK=echo \ + export IFACE=servers PHASE=pre-up MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \ ${EXECUTOR} } vlan_explicit_down_body() { - export IFACE=servers PHASE=down MOCK=echo \ + export IFACE=servers PHASE=post-down MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link delete link eth0 name servers type vlan id 123' \ ${EXECUTOR} } vlan_guessed_up_body() { - export IFACE=eth0.8 PHASE=up MOCK=echo + export IFACE=eth0.8 PHASE=pre-up MOCK=echo atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } vlan_guessed_down_body() { - export IFACE=eth0.8 PHASE=down MOCK=echo + export IFACE=eth0.8 PHASE=post-down MOCK=echo atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } vlan_explicit_depend_body() { - export IFACE=servers PHASE=up MOCK=echo \ + export IFACE=servers PHASE=pre-up MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'eth0' \ ${EXECUTOR} From aefaaa7457c869428b8f03894cc0a14b8d6d726e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 24 Aug 2020 11:33:56 -0600 Subject: [PATCH 210/530] lifecycle: only print skipping interface message if verbose --- libifupdown/lifecycle.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index a70fcc1..2723f40 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -268,8 +268,9 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par /* already up or down, skip */ if (up == iface->is_up) { - fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s)\n", - iface->ifname, parent->ifname); + if (opts->verbose) + fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s)\n", + iface->ifname, parent->ifname); continue; } From 0ff263a02ae80a62c8248e9ffba2369058ee19d8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 25 Aug 2020 08:09:31 -0600 Subject: [PATCH 211/530] bridge: don't generate dependencies for bridge-ports none --- executor-scripts/stub/bridge | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/executor-scripts/stub/bridge b/executor-scripts/stub/bridge index ee1a442..5eee08c 100755 --- a/executor-scripts/stub/bridge +++ b/executor-scripts/stub/bridge @@ -1,4 +1,8 @@ #!/bin/sh case "$PHASE" in -depend) echo "$IF_BRIDGE_PORTS" ;; +depend) + if [ "$IF_BRIDGE_PORTS" != "none" ]; then + echo "$IF_BRIDGE_PORTS" + fi + ;; esac From 6c7c3f570d35844fb2ef844d8bf4024b95c7431f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 25 Aug 2020 08:14:55 -0600 Subject: [PATCH 212/530] link executor: switch back to up/down phase --- executor-scripts/linux/link | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 2aa78f9..f7ede1f 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -29,14 +29,12 @@ is_vlan() { } case "$PHASE" in -pre-up|post-down) - UP_DOWN="${PHASE##*-}" - +up|down) if is_vlan; then ADD_DEL="add" - [ "$UP_DOWN" = "down" ] && ADD_DEL="delete" + [ "$PHASE" = "down" ] && ADD_DEL="delete" - if [ "$UP_DOWN" = "up" -a -e /sys/class/net/$IFACE ]; then + if [ "$PHASE" = "up" -a -e /sys/class/net/$IFACE ]; then exit 0 fi @@ -53,11 +51,11 @@ pre-up|post-down) fi ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" - [ "$UP_DOWN" = "down" ] && exit 0 + [ "$PHASE" = "down" ] && exit 0 - ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS + ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS else - ${MOCK} ip link set $UP_DOWN dev $IFACE $IF_LINK_OPTIONS + ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS fi ;; depend) From cca3608ad7307ef45faaa095be6aef2b23929800 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 25 Aug 2020 08:16:05 -0600 Subject: [PATCH 213/530] link tests: switch back to up/down from pre-up/post-down --- tests/linux/link_test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/linux/link_test b/tests/linux/link_test index 6a8ff24..1cb2784 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -15,51 +15,51 @@ tests_init \ vlan_guessed_depend up_body() { - export IFACE=lo PHASE=pre-up MOCK=echo + export IFACE=lo PHASE=up MOCK=echo atf_check -s exit:0 -o match:'ip link set up dev lo' \ ${EXECUTOR} } down_body() { - export IFACE=lo PHASE=post-down MOCK=echo + export IFACE=lo PHASE=down MOCK=echo atf_check -s exit:0 -o match:'ip link set down dev lo' \ ${EXECUTOR} } mtu_body() { - export IFACE=eth0 PHASE=pre-up MOCK=echo IF_MTU=1492 + export IFACE=eth0 PHASE=up MOCK=echo IF_MTU=1492 atf_check -s exit:0 -o match:'ip link set up dev eth0 mtu 1492' \ ${EXECUTOR} } vlan_explicit_up_body() { - export IFACE=servers PHASE=pre-up MOCK=echo \ + export IFACE=servers PHASE=up MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \ ${EXECUTOR} } vlan_explicit_down_body() { - export IFACE=servers PHASE=post-down MOCK=echo \ + export IFACE=servers PHASE=down MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link delete link eth0 name servers type vlan id 123' \ ${EXECUTOR} } vlan_guessed_up_body() { - export IFACE=eth0.8 PHASE=pre-up MOCK=echo + export IFACE=eth0.8 PHASE=up MOCK=echo atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } vlan_guessed_down_body() { - export IFACE=eth0.8 PHASE=post-down MOCK=echo + export IFACE=eth0.8 PHASE=down MOCK=echo atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } vlan_explicit_depend_body() { - export IFACE=servers PHASE=pre-up MOCK=echo \ + export IFACE=servers PHASE=up MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'eth0' \ ${EXECUTOR} From 4d64176ea3dac48b36770dda2211253ba054ba2b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 26 Aug 2020 02:06:36 -0600 Subject: [PATCH 214/530] execute: note the phase each executor is being invoked in --- libifupdown/execute.c | 8 ++++---- libifupdown/execute.h | 4 ++-- libifupdown/lifecycle.c | 18 +++++++++--------- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index b6a4f84..d5b7bda 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -140,10 +140,10 @@ lif_file_is_executable(const char *path) } bool -lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor) +lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor, const char *phase) { if (opts->verbose) - fprintf(stderr, "ifupdown: attempting to run %s executor\n", executor); + fprintf(stderr, "ifupdown: attempting to run %s executor for phase %s\n", executor, phase); char pathbuf[4096]; @@ -156,10 +156,10 @@ lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], } bool -lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize) +lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize, const char *phase) { if (opts->verbose) - fprintf(stderr, "ifupdown: attempting to run %s executor\n", executor); + fprintf(stderr, "ifupdown: attempting to run %s executor for phase %s\n", executor, phase); char pathbuf[4096]; diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 625171d..fa4af78 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -31,7 +31,7 @@ struct lif_execute_opts { extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); extern bool lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...); extern bool lif_file_is_executable(const char *path); -extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor); -extern bool lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize); +extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor, const char *phase); +extern bool lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize, const char *phase); #endif diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 2723f40..6db91d6 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -44,39 +44,39 @@ handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[ } static inline bool -handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struct lif_execute_opts *opts, char *const envp[]) +handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struct lif_execute_opts *opts, char *const envp[], const char *phase) { if (strcmp(entry->key, "use")) return true; const char *cmd = entry->data; - if (!lif_maybe_run_executor(opts, envp, cmd)) + if (!lif_maybe_run_executor(opts, envp, cmd, phase)) return false; return true; } static bool -handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, bool up) +handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, bool up, const char *phase) { struct lif_node *iter; if (up) { LIF_DICT_FOREACH(iter, &iface->vars) - handle_single_executor_for_phase(iter->data, opts, envp); + handle_single_executor_for_phase(iter->data, opts, envp, phase); } else { LIF_DICT_FOREACH_REVERSE(iter, &iface->vars) - handle_single_executor_for_phase(iter->data, opts, envp); + handle_single_executor_for_phase(iter->data, opts, envp, phase); } return true; } static bool -query_dependents_from_executors(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, char *buf, size_t bufsize) +query_dependents_from_executors(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, char *buf, size_t bufsize, const char *phase) { struct lif_node *iter; @@ -94,7 +94,7 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const continue; const char *cmd = entry->data; - if (!lif_maybe_run_executor_with_result(&exec_opts, envp, cmd, resbuf, sizeof resbuf)) + if (!lif_maybe_run_executor_with_result(&exec_opts, envp, cmd, resbuf, sizeof resbuf, phase)) return false; if (!*resbuf) @@ -196,7 +196,7 @@ lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_i if (entry != NULL) strlcpy(deps, entry->data, sizeof deps); - if (!query_dependents_from_executors(opts, envp, iface, deps, sizeof deps)) + if (!query_dependents_from_executors(opts, envp, iface, deps, sizeof deps, "depend")) return false; char *p = deps; @@ -231,7 +231,7 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac build_environment(&envp, opts, iface, lifname, phase, up ? "start" : "stop"); - if (!handle_executors_for_phase(opts, envp, iface, up)) + if (!handle_executors_for_phase(opts, envp, iface, up, phase)) goto handle_error; if (!handle_commands_for_phase(opts, envp, iface, phase)) From 68415ce71d21ee84df046a68e9221e5dd34fc1af Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 26 Aug 2020 02:22:30 -0600 Subject: [PATCH 215/530] link executor: add support for hwaddress option --- executor-scripts/linux/link | 1 + tests/linux/link_test | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index f7ede1f..b6b37a8 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -4,6 +4,7 @@ IF_LINK_OPTIONS="$IF_LINK_OPTIONS" [ -n "$IF_MTU" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS mtu $IF_MTU" +[ -n "$IF_HWADDRESS" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS address $IF_HWADDRESS" is_vlan() { case "$IFACE" in diff --git a/tests/linux/link_test b/tests/linux/link_test index 1cb2784..505adcd 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -7,6 +7,7 @@ tests_init \ up \ down \ mtu \ + hwaddress \ vlan_explicit_up \ vlan_explicit_down \ vlan_guessed_up \ @@ -32,6 +33,12 @@ mtu_body() { ${EXECUTOR} } +hwaddress_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_HWADDRESS=12:34:56:78:90:ab + atf_check -s exit:0 -o match:'ip link set up dev eth0 address 12:34:56:78:90:ab' \ + ${EXECUTOR} +} + vlan_explicit_up_body() { export IFACE=servers PHASE=up MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" From 14914f12514b5d9eb5ec73dff3101c02d66312f6 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 26 Aug 2020 03:35:18 -0600 Subject: [PATCH 216/530] executors: use set -e consistently --- executor-scripts/linux/bridge | 2 ++ executor-scripts/linux/gre | 2 ++ executor-scripts/linux/ipv6-ra | 2 ++ executor-scripts/linux/link | 2 ++ executor-scripts/linux/static | 2 ++ executor-scripts/linux/tunnel | 2 ++ executor-scripts/stub/bond | 1 + executor-scripts/stub/bridge | 1 + 8 files changed, 14 insertions(+) diff --git a/executor-scripts/linux/bridge b/executor-scripts/linux/bridge index 367e947..3a4a41c 100755 --- a/executor-scripts/linux/bridge +++ b/executor-scripts/linux/bridge @@ -1,5 +1,7 @@ #!/bin/sh +set -e + # Copyright (C) 2012, 2020 Natanael Copa # Copyright (C) 2020 Ariadne Conill # diff --git a/executor-scripts/linux/gre b/executor-scripts/linux/gre index c747aab..40b96e8 100755 --- a/executor-scripts/linux/gre +++ b/executor-scripts/linux/gre @@ -1,5 +1,7 @@ #!/bin/sh +set -e + # Executor for advanced GRE tunnel management. [ -z "$IF_GRE_LOCAL" ] && exit 1 diff --git a/executor-scripts/linux/ipv6-ra b/executor-scripts/linux/ipv6-ra index 95b5f64..fc6644a 100755 --- a/executor-scripts/linux/ipv6-ra +++ b/executor-scripts/linux/ipv6-ra @@ -1,5 +1,7 @@ #!/bin/sh +set -e + start() { ${MOCK} /bin/sh -c "echo 1 > /proc/sys/net/ipv6/conf/$IFACE/accept_ra" } diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index f7ede1f..8b1b54b 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -1,5 +1,7 @@ #!/bin/sh +set -e + [ -n "$VERBOSE" ] && set -x IF_LINK_OPTIONS="$IF_LINK_OPTIONS" diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index b1c9f8d..04d3ae6 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -1,5 +1,7 @@ #!/bin/sh +set -e + [ -z "$IF_METRIC" ] && IF_METRIC="1" [ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" [ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC" diff --git a/executor-scripts/linux/tunnel b/executor-scripts/linux/tunnel index 6b6fa49..e370b2a 100755 --- a/executor-scripts/linux/tunnel +++ b/executor-scripts/linux/tunnel @@ -1,5 +1,7 @@ #!/bin/sh +set -e + # Based on alpine's tunnel configuration script. # Copyright (c) 2017 Kaarle Ritvanen # Copyright (c) 2020 Ariadne Conill (extended for ifupdown-ng) diff --git a/executor-scripts/stub/bond b/executor-scripts/stub/bond index 0548543..1869611 100755 --- a/executor-scripts/stub/bond +++ b/executor-scripts/stub/bond @@ -1,4 +1,5 @@ #!/bin/sh +set -e [ -z "$IF_BOND_MEMBERS" ] && IF_BOND_MEMBERS="$IF_BOND_SLAVES" case "$PHASE" in depend) echo "$IF_BOND_MEMBERS" ;; diff --git a/executor-scripts/stub/bridge b/executor-scripts/stub/bridge index 5eee08c..d09db3f 100755 --- a/executor-scripts/stub/bridge +++ b/executor-scripts/stub/bridge @@ -1,4 +1,5 @@ #!/bin/sh +set -e case "$PHASE" in depend) if [ "$IF_BRIDGE_PORTS" != "none" ]; then From e52e94fe5e9a476d14e918bf0fc5140a9fd72f1e Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Wed, 26 Aug 2020 22:29:59 +0200 Subject: [PATCH 217/530] static executor: Use vrf-member when setting gateway if present. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/static | 1 + 1 file changed, 1 insertion(+) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index 04d3ae6..aa99533 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -4,6 +4,7 @@ set -e [ -z "$IF_METRIC" ] && IF_METRIC="1" [ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" +[ -n "$IF_VRF_MEMBER" ] && VRF_TABLE="vrf $IF_VRF_MEMBER" [ -n "$IF_METRIC" ] && METRIC="metric $IF_METRIC" addr_family() { From 36fe61d8e78c84251b91b715dbcbc03ada80caef Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Wed, 26 Aug 2020 22:41:32 +0200 Subject: [PATCH 218/530] link executor: Unify code paths. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 5cae17d..7fbad75 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -55,11 +55,9 @@ up|down) ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" [ "$PHASE" = "down" ] && exit 0 + fi ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS - else - ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS - fi ;; depend) if is_vlan; then From e51ce613e6eb716361d317fa54bc18b00951341a Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Wed, 26 Aug 2020 23:02:48 +0200 Subject: [PATCH 219/530] link executor: Add support for dummy interfaces. closes #49 Signed-off-by: Maximilian Wilhelm --- doc/interfaces.scd | 5 +++++ executor-scripts/linux/link | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 262a7a3..9701647 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -66,6 +66,10 @@ the system will only respond to certain keywords by default: is for backwards compatibility and should not be used in new deployments. +*link-type* _link-type_ + Denotes the link-type of the interface. When set to _dummy_, + the interface is created as a virtual dummy interfaces. + *requires* _interfaces_... Designates one or more required interfaces that must be brought up before configuration of the parent interface. @@ -165,3 +169,4 @@ iface eth0 # AUTHORS Ariadne Conill +Maximilian Wilhelm diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 7fbad75..2de4f4c 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -32,6 +32,11 @@ is_vlan() { } case "$PHASE" in +pre-up) + if [ "${IF_LINK_TYPE}" = "dummy" ]; then + ip link add "${IFACE}" type dummy + fi + ;; up|down) if is_vlan; then ADD_DEL="add" From 8f3e1f06f174f65478df37c3c2ae0c7f395c9742 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 27 Aug 2020 00:47:51 +0200 Subject: [PATCH 220/530] link executor: Fix indentation. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 2de4f4c..4d21381 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -62,7 +62,7 @@ up|down) [ "$PHASE" = "down" ] && exit 0 fi - ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS + ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS ;; depend) if is_vlan; then From 61ed18db2c620bc1ce47ab7dd01a5e610479d685 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 27 Aug 2020 01:15:51 +0200 Subject: [PATCH 221/530] lifecycle: Check if script dir exist before executing run-parts. Signed-off-by: Maximilian Wilhelm --- libifupdown/lifecycle.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 6db91d6..b6597c9 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -15,6 +15,9 @@ #include #include +#include +#include +#include #include "libifupdown/environment.h" #include "libifupdown/execute.h" @@ -237,8 +240,17 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac if (!handle_commands_for_phase(opts, envp, iface, phase)) goto handle_error; + /* Check if scripts dir for this phase is present and bail out if it isn't */ + struct stat dir_stat; + char dir_path[4096]; + snprintf (dir_path, 4096, "/etc/network/if-%s.d", phase); + + if (stat (dir_path, &dir_stat) != 0 || S_ISDIR (dir_stat.st_mode) == 0) { + goto handle_error; + } + /* we should do error handling here, but ifupdown1 doesn't */ - lif_execute_fmt(opts, envp, "/bin/run-parts /etc/network/if-%s.d", phase); + lif_execute_fmt(opts, envp, "/bin/run-parts %s", dir_path); lif_environment_free(&envp); return true; From 570679c5bff2915b982736b1bc9ac862a0afb033 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 27 Aug 2020 12:10:12 +0200 Subject: [PATCH 222/530] lifecycle: Make sure to return true when script dir doesn't exist. Signed-off-by: Maximilian Wilhelm --- libifupdown/lifecycle.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index b6597c9..359f533 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -246,12 +246,13 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac snprintf (dir_path, 4096, "/etc/network/if-%s.d", phase); if (stat (dir_path, &dir_stat) != 0 || S_ISDIR (dir_stat.st_mode) == 0) { - goto handle_error; + goto out_free; } /* we should do error handling here, but ifupdown1 doesn't */ lif_execute_fmt(opts, envp, "/bin/run-parts %s", dir_path); +out_free: lif_environment_free(&envp); return true; From 64b24b02edbcf1c586fcfd0c204996c342d0d5ed Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sun, 30 Aug 2020 22:18:07 +0200 Subject: [PATCH 223/530] Remove leading whitespaces before interface attribute values. Signed-off-by: Maximilian Wilhelm --- libifupdown/interface-file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 06a3c66..7589841 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -146,6 +146,10 @@ handle_generic(struct lif_dict *collection, const char *filename, size_t lineno, token = maybe_remap_token(token); + /* Skip any leading whitespaces in value for */ + while (isspace (*bufp)) + bufp++; + lif_dict_add(&cur_iface->vars, token, strdup(bufp)); /* Check if token looks like - and assume is an addon */ From 7d81ceb898e374f37c95b01ddd5c4f6f1203502f Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sun, 30 Aug 2020 22:38:38 +0200 Subject: [PATCH 224/530] link executor: Only create dummy interface when not present. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 4d21381..e50b928 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -34,6 +34,13 @@ is_vlan() { case "$PHASE" in pre-up) if [ "${IF_LINK_TYPE}" = "dummy" ]; then + if [ -d "/sys/class/net/${IFACE}" ]; then + iface_type=$(ip -d link show dev "${IFACE}" | head -n3 | tail -n1 | awk '{ print $1 }') + if [ "${iface_type}" = 'dummy' ]; then + exit 0 + fi + fi + ip link add "${IFACE}" type dummy fi ;; From e854819e8f66de5932192cc9138a07e44b8d5f7f Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sun, 30 Aug 2020 22:38:58 +0200 Subject: [PATCH 225/530] link executor: Delete dummy interface in post-down. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index e50b928..08e6c6f 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -71,6 +71,13 @@ up|down) ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS ;; +post-down) + if [ "${IF_LINK_TYPE}" = "dummy" ]; then + if [ -d "/sys/class/net/${IFACE}" ]; then + ip link del "${IFACE}" + fi + fi + ;; depend) if is_vlan; then echo "$IF_VLAN_RAW_DEVICE" From 2d7668bc019d5e396ac2a629ba96a924301f7f23 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 3 Sep 2020 16:07:27 -0600 Subject: [PATCH 226/530] dhcp executor: add support for udhcpc-opts property --- executor-scripts/linux/dhcp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/executor-scripts/linux/dhcp b/executor-scripts/linux/dhcp index fa576e7..783f6e1 100755 --- a/executor-scripts/linux/dhcp +++ b/executor-scripts/linux/dhcp @@ -24,7 +24,8 @@ start() { ${MOCK} /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $IFACE ;; udhcpc) - ${MOCK} /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE + UDHCPC_OPTS=$(eval echo $IF_UDHCPC_OPTS) + ${MOCK} /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE $UDHCPC_OPTS ;; *) ;; From 7edb29778b17ae4bd45ecd3f3736a700c379600d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 3 Sep 2020 16:11:41 -0600 Subject: [PATCH 227/530] tests: add udhcp-opts related tests --- tests/linux/dhcp_test | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/tests/linux/dhcp_test b/tests/linux/dhcp_test index 3ff884b..c451e74 100755 --- a/tests/linux/dhcp_test +++ b/tests/linux/dhcp_test @@ -3,7 +3,12 @@ . $(atf_get_srcdir)/../test_env.sh EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/dhcp" -tests_init udhcpc_up dhcpcd_up dhcpcd_down dhclient_up +tests_init udhcpc_up \ + dhcpcd_up \ + dhcpcd_down \ + dhclient_up \ + udhcpc_opts_up \ + udhcpc_opts_up_subshell udhcpc_up_body() { export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc @@ -28,3 +33,15 @@ dhclient_up_body() { atf_check -s exit:0 -o match:'/usr/sbin/dhclient -pf /var/run/dhclient.eth0.pid eth0' \ ${EXECUTOR} } + +udhcpc_opts_up_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc IF_UDHCPC_OPTS="-O search" + atf_check -s exit:0 -o match:'/sbin/udhcpc -b -R -p /var/run/udhcpc.eth0.pid -i eth0 -O search' \ + ${EXECUTOR} +} + +udhcpc_opts_up_subshell_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc IF_UDHCPC_OPTS="-O search -x hostname:\$(echo test)" + atf_check -s exit:0 -o match:'/sbin/udhcpc -b -R -p /var/run/udhcpc.eth0.pid -i eth0 -O search -x hostname:test' \ + ${EXECUTOR} +} From 6805262a9b973d794404d9314b4669bfbcaa6225 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 4 Sep 2020 00:48:44 +0200 Subject: [PATCH 228/530] link executor: Add support for interface aliases. Signed-off-by: Maximilian Wilhelm --- doc/interfaces.scd | 3 +++ executor-scripts/linux/link | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 9701647..17bc5aa 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -70,6 +70,9 @@ the system will only respond to certain keywords by default: Denotes the link-type of the interface. When set to _dummy_, the interface is created as a virtual dummy interfaces. +*alias* _alias_ + Sets the given alias on the interface. + *requires* _interfaces_... Designates one or more required interfaces that must be brought up before configuration of the parent interface. diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 08e6c6f..9921840 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -70,6 +70,11 @@ up|down) fi ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS + + # Set alias is configured + if [ "${IF_ALIAS}" ]; then + ${MOCK} ip link set alias "${IF_ALIAS}" dev "${IFACE}" + fi ;; post-down) if [ "${IF_LINK_TYPE}" = "dummy" ]; then From f32481deb97c54c1cb93dd8cdaafb5d5cb474e80 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 4 Sep 2020 12:57:41 -0600 Subject: [PATCH 229/530] add wireguard executor script --- Makefile | 3 ++- executor-scripts/linux/wireguard | 16 ++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/wireguard diff --git a/Makefile b/Makefile index d7c4a91..538f1da 100644 --- a/Makefile +++ b/Makefile @@ -84,7 +84,8 @@ EXECUTOR_SCRIPTS_OPT ?= \ bridge \ vrf \ tunnel \ - gre + gre \ + wireguard EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} diff --git a/executor-scripts/linux/wireguard b/executor-scripts/linux/wireguard new file mode 100755 index 0000000..fa4a059 --- /dev/null +++ b/executor-scripts/linux/wireguard @@ -0,0 +1,16 @@ +#!/bin/sh + +set -e + +[ -n "$VERBOSE" ] && set -x +[ -z "$IF_WIREGUARD_CONFIG_PATH" ] && IF_WIREGUARD_CONFIG_PATH="/etc/wireguard/$IFACE.conf" + +case "$PHASE" in +pre-up) + ${MOCK} ip link add $IFACE type wireguard + ${MOCK} wg setconf $IFACE $IF_WIREGUARD_CONFIG_PATH + ;; +post-down) + ${MOCK} ip link delete dev $IFACE + ;; +esac From acb555b75adeef50c81631adf81c22b404327744 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 4 Sep 2020 13:10:57 -0600 Subject: [PATCH 230/530] tests: add wireguard tests --- tests/fixtures/wireguard.interfaces | 9 ++++++++ tests/ifquery_test | 10 ++++++++- tests/linux/Kyuafile | 1 + tests/linux/wireguard_test | 33 +++++++++++++++++++++++++++++ 4 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/wireguard.interfaces create mode 100755 tests/linux/wireguard_test diff --git a/tests/fixtures/wireguard.interfaces b/tests/fixtures/wireguard.interfaces new file mode 100644 index 0000000..fed6429 --- /dev/null +++ b/tests/fixtures/wireguard.interfaces @@ -0,0 +1,9 @@ +iface eth0 + address 203.0.113.2/24 + gateway 203.0.113.1 + +auto wg0 +iface wg0 + use wireguard + address 1.2.3.4/24 + requires eth0 diff --git a/tests/ifquery_test b/tests/ifquery_test index 9d86e28..e095255 100755 --- a/tests/ifquery_test +++ b/tests/ifquery_test @@ -33,7 +33,8 @@ tests_init \ gre_dependency \ vlan_explicit_learned_dependency \ vlan_guessed_learned_dependency \ - vlan_complex_learned_dependency + vlan_complex_learned_dependency \ + wireguard noargs_body() { atf_check -s exit:1 -e ignore ifquery -S/dev/null @@ -218,3 +219,10 @@ vlan_complex_learned_dependency_body() { -o match:"vlan-raw-device eth0" \ ifquery -E $EXECUTORS_LINUX -i $FIXTURES/vlan-complex.interfaces servers } + +wireguard_body() { + atf_check -s exit:0 \ + -o match:"requires eth0" \ + -o match:"use wireguard" \ + ifquery -E $EXECUTORS_LINUX -i $FIXTURES/wireguard.interfaces wg0 +} diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 7d7389c..050c55d 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -10,3 +10,4 @@ atf_test_program{name='vrf_test'} atf_test_program{name='ppp_test'} atf_test_program{name='tunnel_test'} atf_test_program{name='gre_test'} +atf_test_program{name='wireguard_test'} diff --git a/tests/linux/wireguard_test b/tests/linux/wireguard_test new file mode 100755 index 0000000..ca6e19e --- /dev/null +++ b/tests/linux/wireguard_test @@ -0,0 +1,33 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/wireguard" + +tests_init \ + pre_up \ + pre_up_specified_config \ + post_down + +pre_up_body() { + export IFACE=wg0 PHASE=pre-up MOCK=echo + atf_check -s exit:0 \ + -o match:'ip link add wg0 type wireguard' \ + -o match:'wg setconf wg0 /etc/wireguard/wg0.conf' \ + ${EXECUTOR} +} + +pre_up_specified_config_body() { + export IFACE=wg0 PHASE=pre-up MOCK=echo \ + IF_WIREGUARD_CONFIG_PATH=/etc/wireguard/vpn.conf + atf_check -s exit:0 \ + -o match:'ip link add wg0 type wireguard' \ + -o match:'wg setconf wg0 /etc/wireguard/vpn.conf' \ + ${EXECUTOR} +} + +post_down_body() { + export IFACE=wg0 PHASE=post-down MOCK=echo + atf_check -s exit:0 \ + -o match:'ip link delete dev wg0' \ + ${EXECUTOR} +} From 0e5ec5b26073cb204c1f01899733bc219fa163c6 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 4 Sep 2020 23:21:21 +0200 Subject: [PATCH 231/530] link executor: Refactor VLAN iface management Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 22 +++++++++------------- 1 file changed, 9 insertions(+), 13 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 9921840..9751987 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -43,19 +43,15 @@ pre-up) ip link add "${IFACE}" type dummy fi - ;; -up|down) - if is_vlan; then - ADD_DEL="add" - [ "$PHASE" = "down" ] && ADD_DEL="delete" - if [ "$PHASE" = "up" -a -e /sys/class/net/$IFACE ]; then + if is_vlan; then + if [ -d "/sys/class/net/${IFACE}" ]; then exit 0 fi - if [ -z "$MOCK" ]; then - if ! ip link show "$IF_VLAN_RAW_DEVICE" >/dev/null; then - echo "Device $IF_VLAN_RAW_DEVICE for $IFACE does not exist" + if [ -z "${MOCK}" ]; then + if [ ! -d "/sys/class/net/${IF_VLAN_RAW_DEVICE}" ]; then + echo "Underlay device ${IF_VLAN_RAW_DEVICE} for ${IFACE} does not exist" exit 1 fi @@ -65,10 +61,10 @@ up|down) fi fi - ${MOCK} ip link $ADD_DEL link "$IF_VLAN_RAW_DEVICE" name "$IFACE" type vlan id "$IF_VLAN_ID" - [ "$PHASE" = "down" ] && exit 0 + ${MOCK} ip link add link "${IF_VLAN_RAW_DEVICE}" name "${IFACE}" type vlan id "${IF_VLAN_ID}" fi - + ;; +up|down) ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS # Set alias is configured @@ -77,7 +73,7 @@ up|down) fi ;; post-down) - if [ "${IF_LINK_TYPE}" = "dummy" ]; then + if [ "${IF_LINK_TYPE}" = "dummy" -o is_vlan ]; then if [ -d "/sys/class/net/${IFACE}" ]; then ip link del "${IFACE}" fi From a6b95d495ca0c3b1b5890e61bdec113ae9216046 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 4 Sep 2020 23:32:51 +0200 Subject: [PATCH 232/530] link executor: Only gather and set IFACE_OPTIONS on up. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 9751987..9a716e1 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -4,10 +4,6 @@ set -e [ -n "$VERBOSE" ] && set -x -IF_LINK_OPTIONS="$IF_LINK_OPTIONS" -[ -n "$IF_MTU" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS mtu $IF_MTU" -[ -n "$IF_HWADDRESS" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS address $IF_HWADDRESS" - is_vlan() { case "$IFACE" in *#*) return 1 ;; @@ -64,14 +60,21 @@ pre-up) ${MOCK} ip link add link "${IF_VLAN_RAW_DEVICE}" name "${IFACE}" type vlan id "${IF_VLAN_ID}" fi ;; -up|down) - ${MOCK} ip link set $PHASE dev $IFACE $IF_LINK_OPTIONS +up) + IF_LINK_OPTIONS="$IF_LINK_OPTIONS" + [ -n "$IF_MTU" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS mtu $IF_MTU" + [ -n "$IF_HWADDRESS" ] && IF_LINK_OPTIONS="$IF_LINK_OPTIONS address $IF_HWADDRESS" + + ${MOCK} ip link set up dev "${IFACE}" ${IF_LINK_OPTIONS} # Set alias is configured if [ "${IF_ALIAS}" ]; then ${MOCK} ip link set alias "${IF_ALIAS}" dev "${IFACE}" fi ;; +down) + ${MOCK} ip link set down dev "${IFACE}" + ;; post-down) if [ "${IF_LINK_TYPE}" = "dummy" -o is_vlan ]; then if [ -d "/sys/class/net/${IFACE}" ]; then From 2e6b3ca1ff4a5a21164a97c6531b2eeac5cd760b Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 4 Sep 2020 23:33:27 +0200 Subject: [PATCH 233/530] link executor: Better error message on conflicting link types. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 9a716e1..62e222e 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -32,8 +32,9 @@ pre-up) if [ "${IF_LINK_TYPE}" = "dummy" ]; then if [ -d "/sys/class/net/${IFACE}" ]; then iface_type=$(ip -d link show dev "${IFACE}" | head -n3 | tail -n1 | awk '{ print $1 }') - if [ "${iface_type}" = 'dummy' ]; then - exit 0 + if [ "${iface_type}" != 'dummy' ]; then + echo "Interface ${IFACE} exists but is of type ${iface_type} instead of dummy" + exit 1 fi fi From 58f010fe91b25430c858177cde861a02b10b173c Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 4 Sep 2020 23:45:49 +0200 Subject: [PATCH 234/530] tests: Reflect latest link executor changes Signed-off-by: Maximilian Wilhelm --- tests/linux/link_test | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/tests/linux/link_test b/tests/linux/link_test index 505adcd..e25d1d1 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -8,10 +8,10 @@ tests_init \ down \ mtu \ hwaddress \ - vlan_explicit_up \ - vlan_explicit_down \ - vlan_guessed_up \ - vlan_guessed_down \ + vlan_explicit_pre_up \ + vlan_explicit_post_down \ + vlan_guessed_pre_up \ + vlan_guessed_post_down \ vlan_explicit_depend \ vlan_guessed_depend @@ -39,29 +39,29 @@ hwaddress_body() { ${EXECUTOR} } -vlan_explicit_up_body() { - export IFACE=servers PHASE=up MOCK=echo \ +vlan_explicit_pre_up_body() { + export IFACE=servers PHASE=pre-up MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \ ${EXECUTOR} } -vlan_explicit_down_body() { - export IFACE=servers PHASE=down MOCK=echo \ +vlan_explicit_post_down_body() { + export IFACE=servers PHASE=post-down MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" - atf_check -s exit:0 -o match:'ip link delete link eth0 name servers type vlan id 123' \ + atf_check -s exit:0 -o match:'ip link del servers' \ ${EXECUTOR} } -vlan_guessed_up_body() { - export IFACE=eth0.8 PHASE=up MOCK=echo +vlan_guessed_pre_up_body() { + export IFACE=eth0.8 PHASE=pre-up MOCK=echo atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } -vlan_guessed_down_body() { - export IFACE=eth0.8 PHASE=down MOCK=echo - atf_check -s exit:0 -o match:'ip link delete link eth0 name eth0.8 type vlan id 8' \ +vlan_guessed_post_down_body() { + export IFACE=eth0.8 PHASE=post-down MOCK=echo + atf_check -s exit:0 -o match:'ip link del eth0.8' \ ${EXECUTOR} } From 37a7d8f09710093d26fb9620679e763b83113db3 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 00:15:01 +0200 Subject: [PATCH 235/530] link executor: Make vlan disposal MOCKable again Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 62e222e..14d8d9e 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -77,10 +77,12 @@ down) ${MOCK} ip link set down dev "${IFACE}" ;; post-down) - if [ "${IF_LINK_TYPE}" = "dummy" -o is_vlan ]; then - if [ -d "/sys/class/net/${IFACE}" ]; then - ip link del "${IFACE}" + if [ "${IF_LINK_TYPE}" = "dummy" ] || is_vlan; then + if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then + exit 0 fi + + ip link del "${IFACE}" fi ;; depend) From d24b4ab3e603114339e7dfde2eba9d3f0851b95e Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 00:15:26 +0200 Subject: [PATCH 236/530] link executor: Make dummy creation MOCKable, too Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 14d8d9e..2c1472f 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -38,7 +38,7 @@ pre-up) fi fi - ip link add "${IFACE}" type dummy + ${MOCK} ip link add "${IFACE}" type dummy fi if is_vlan; then From aa3e94acf83df565d2bec870b1d91efdb38595a8 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 00:18:43 +0200 Subject: [PATCH 237/530] link executor: Make link deletion MOCKable again. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 2c1472f..7211d70 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -82,7 +82,7 @@ post-down) exit 0 fi - ip link del "${IFACE}" + ${MOCK} ip link del "${IFACE}" fi ;; depend) From 4a05010539c02aac3b0a87db047bd953d7920743 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 00:24:40 +0200 Subject: [PATCH 238/530] tests: Fix vlan_explicit_depend_body. Signed-off-by: Maximilian Wilhelm --- tests/linux/link_test | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/linux/link_test b/tests/linux/link_test index e25d1d1..c4389f4 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -66,7 +66,7 @@ vlan_guessed_post_down_body() { } vlan_explicit_depend_body() { - export IFACE=servers PHASE=up MOCK=echo \ + export IFACE=servers PHASE=depend \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'eth0' \ ${EXECUTOR} From 32b7dda832c8cfb9965e70d34cd98aa112a9f752 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 00:28:12 +0200 Subject: [PATCH 239/530] tests: Add test for dummy link creation. Signed-off-by: Maximilian Wilhelm --- tests/linux/link_test | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/linux/link_test b/tests/linux/link_test index c4389f4..db3e787 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -13,7 +13,8 @@ tests_init \ vlan_guessed_pre_up \ vlan_guessed_post_down \ vlan_explicit_depend \ - vlan_guessed_depend + vlan_guessed_depend \ + dummy_pre_up up_body() { export IFACE=lo PHASE=up MOCK=echo @@ -77,3 +78,9 @@ vlan_guessed_depend_body() { atf_check -s exit:0 -o match:'eth0' \ ${EXECUTOR} } + +dummy_pre_up_body() { + export IFACE=yolo IF_LINK_TYPE=dummy PHASE=pre-up MOCK=echo + atf_check -s exit:0 -o match:'ip link add yolo type dummy' \ + ${EXECUTOR} +} From be6ce3c31959da3bf8b41450ebcc2542a67a3d16 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 00:35:04 +0200 Subject: [PATCH 240/530] Add executor for managing B.A.T.M.A.N. adv. interfaces Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/batman | 96 +++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 executor-scripts/linux/batman diff --git a/executor-scripts/linux/batman b/executor-scripts/linux/batman new file mode 100644 index 0000000..886377e --- /dev/null +++ b/executor-scripts/linux/batman @@ -0,0 +1,96 @@ +#!/bin/sh +# +# Maximilian Wilhelm +# -- Wed 26 Aug 2020 08:15:58 PM CEST +# +# This executor is responsible for setting up the main B.A.T.M.A.N. adv. interface (eg. bat0) +# as well as managing settings of the underlying interfaces (hardifs). +# +# Know options for the main interface are: +# IF_BATMAN_IFACES Space separated list of interfaces to be part of this B.A.T.M.A.N. adv. instance +# IF_BATMAN_IFACES_IGNORE_REGEX Interfaces to ignore when verifying configuration (regexp) +# IF_BATMAN_DISTRIBUTED_ARP_TABLE 'enable' or 'disable' DAT of this B.A.T.M.A.N. adv. instance +# IF_BATMAN_MULTICAST_MODE 'enable' or 'disable' the multicast mode of this B.A.T.M.A.N. adv. instance +# IF_BATMAN_GW_MODE Set the gateway mode of this B.A.T.M.A.N. adv. instance +# IF_BATMAN_HOP_PENALTY Set the hop penalty of this B.A.T.M.A.N. adv. instance +# +# Known options for underlying interfaces are: +# IF_BATMAN_IFACE_PENALTY Set the hop penalty of this B.A.T.M.A.N. adv. interface +# +set -e + +if [ "$VERBOSE" ]; then + set -x +fi + +if [ "${IF_BATMAN_IFACES}" -o "${IF_BATMAN_IFACE_PENALTY}" ]; then + if ! which batctl >/dev/null 2>&1; then + echo "Error: batctl utility not found!" >&2 + exit 1 + fi +fi + +# +# Compatiblity glue: Newer versions of batctl print a deprecation +# warning when called with -m . Avoid spamming the log and +# producting SPAM by silently handling this here. +mesh_if_param="-m" +if batctl -h 2>&1 | grep -q "meshif"; then + mesh_if_param="meshif" +fi + +# +# Functions to manage main B.A.T.M.A.N. adv. interface +batctl_if () { + for iface in ${IF_BATMAN_IFACES}; do + ${MOCK} batctl "${mesh_if_param}" "${IFACE}" interface "$1" "${iface}" + done +} + +set_batmam_params () { + [ "${IF_BATMAN_DISTRIBUTED_ARP_TABLE}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" distributed_arp_table "${IF_BATMAN_DISTRIBUTED_ARP_TABLE}" + [ "${IF_BATMAN_MULTICAST_MODE}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" multicast_mode "${IF_BATMAN_MULTICAST_MODE}" + [ "${IF_BATMAN_HOP_PENALTY}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" hop_penalty "${IF_BATMAN_HOP_PENALTY}" + [ "${IF_BATMAN_GW_MODE}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" gw_mode "${IF_BATMAN_GW_MODE}" +} + +# +# Functions to manage B.A.T.M.A.N. adv. underlying interfaces +set_iface_penalty () { + ${MOCK} batctl hardif "${IFACE}" hop_penalty "${IF_BATMAN_IFACE_PENALTY}" +} + + +case "${PHASE}" in + depend) + if [ "${IF_BATMAN_IFACES}" ]; then + echo "${IF_BATMAN_IFACES}" + fi + ;; + + pre-up) + # Main B.A.T.M.A.N. adv. interface + if [ "${IF_BATMAN_IFACES}" ]; then + batctl "${mesh_if_param}" "${IFACE}" interface create || true + batctl_if add + set_batmam_params + + # B.A.T.M.A.N. adv. underlying interface + elif [ "${IF_BATMAN_IFACE_PENALTY}" ]; then + set_iface_penalty + fi + ;; + + post-down) + if [ "${IF_BATMAN_IFACES}" ]; then + # Newer versions of batctl provide the "interface destroy" API, try to use it + if ! batctl "${mesh_if_param}" "${IFACE}" interface destroy 2>/dev/null; then + # Fall back to old style member interface removal + batctl_if del + fi + fi + ;; + + *) exit 0 + ;; +esac From 017a12760ceac40975da9d27343a7c2a84c8ea09 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 5 Sep 2020 01:52:43 +0200 Subject: [PATCH 241/530] batman executor: Only create/delete iface if (not) present. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/batman | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/executor-scripts/linux/batman b/executor-scripts/linux/batman index 886377e..dbc826b 100644 --- a/executor-scripts/linux/batman +++ b/executor-scripts/linux/batman @@ -71,7 +71,10 @@ case "${PHASE}" in pre-up) # Main B.A.T.M.A.N. adv. interface if [ "${IF_BATMAN_IFACES}" ]; then - batctl "${mesh_if_param}" "${IFACE}" interface create || true + if [ ! -d "/sys/class/net/${IFACE}" ]; then + batctl "${mesh_if_param}" "${IFACE}" interface create || true + fi + batctl_if add set_batmam_params @@ -82,7 +85,7 @@ case "${PHASE}" in ;; post-down) - if [ "${IF_BATMAN_IFACES}" ]; then + if [ "${IF_BATMAN_IFACES}" -a -d "/sys/class/net/${IFACE}" ]; then # Newer versions of batctl provide the "interface destroy" API, try to use it if ! batctl "${mesh_if_param}" "${IFACE}" interface destroy 2>/dev/null; then # Fall back to old style member interface removal @@ -91,6 +94,7 @@ case "${PHASE}" in fi ;; - *) exit 0 + *) + exit 0 ;; esac From ae1dc41c88794a1eefc9c339e25baca14138c6f7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 7 Sep 2020 13:41:11 -0600 Subject: [PATCH 242/530] lifecycle: constify lif_interface access in several functions --- libifupdown/lifecycle.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 359f533..f34041f 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -27,13 +27,13 @@ #include "libifupdown/tokenize.h" static bool -handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, const char *phase) +handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, const char *phase) { - struct lif_node *iter; + const struct lif_node *iter; LIF_DICT_FOREACH(iter, &iface->vars) { - struct lif_dict_entry *entry = iter->data; + const struct lif_dict_entry *entry = iter->data; if (strcmp(entry->key, phase)) continue; @@ -60,9 +60,9 @@ handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struc } static bool -handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, bool up, const char *phase) +handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, bool up, const char *phase) { - struct lif_node *iter; + const struct lif_node *iter; if (up) { @@ -79,14 +79,14 @@ handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp } static bool -query_dependents_from_executors(const struct lif_execute_opts *opts, char *const envp[], struct lif_interface *iface, char *buf, size_t bufsize, const char *phase) +query_dependents_from_executors(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, char *buf, size_t bufsize, const char *phase) { - struct lif_node *iter; + const struct lif_node *iter; LIF_DICT_FOREACH(iter, &iface->vars) { char resbuf[1024] = {}; - struct lif_dict_entry *entry = iter->data; + const struct lif_dict_entry *entry = iter->data; struct lif_execute_opts exec_opts = { .verbose = opts->verbose, .executor_path = opts->executor_path, @@ -111,7 +111,7 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const } static void -build_environment(char **envp[], const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname, const char *phase, const char *mode) +build_environment(char **envp[], const struct lif_execute_opts *opts, const struct lif_interface *iface, const char *lifname, const char *phase, const char *mode) { if (lifname == NULL) lifname = iface->ifname; @@ -127,12 +127,12 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, struct lif if (opts->interfaces_file) lif_environment_push(envp, "INTERFACES_FILE", opts->interfaces_file); - struct lif_node *iter; + const struct lif_node *iter; bool did_address = false, did_gateway = false; LIF_DICT_FOREACH(iter, &iface->vars) { - struct lif_dict_entry *entry = iter->data; + const struct lif_dict_entry *entry = iter->data; if (!strcmp(entry->key, "address")) { From 3b10494b407beae4262880b175e7e6ea3a3c35a4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 14:41:25 -0600 Subject: [PATCH 243/530] change lif_interface.is_up to lif_interface.refcount --- cmd/ifquery.c | 4 ++-- libifupdown/interface.h | 2 +- libifupdown/lifecycle.c | 6 +++--- libifupdown/state.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index ac07cbd..54625b1 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -63,7 +63,7 @@ print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, st if (!lif_lifecycle_query_dependents(&exec_opts, iface, iface->ifname)) return; - if (iface->is_up) + if (iface->refcount > 0) return; if (parent != NULL) @@ -87,7 +87,7 @@ print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, st struct lif_interface *child_if = lif_interface_collection_find(collection, tokenp); print_interface_dot(collection, child_if, iface); - child_if->is_up = true; + child_if->refcount++; } } diff --git a/libifupdown/interface.h b/libifupdown/interface.h index 3f2c287..a18c4b7 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -53,7 +53,7 @@ struct lif_interface { struct lif_dict vars; - bool is_up; + size_t refcount; /* >= 0 if up, else 0 */ }; #define LIF_INTERFACE_COLLECTION_FOREACH(iter, collection) \ diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index f34041f..2b77ed0 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -279,7 +279,7 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par struct lif_interface *iface = lif_interface_collection_find(collection, tokenp); /* already up or down, skip */ - if (up == iface->is_up) + if (up && iface->refcount > 0) { if (opts->verbose) fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s)\n", @@ -328,7 +328,7 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa lif_state_upsert(state, lifname, iface); - iface->is_up = true; + iface->refcount++; } else { @@ -347,7 +347,7 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa lif_state_delete(state, lifname); - iface->is_up = false; + iface->refcount--; } return true; diff --git a/libifupdown/state.c b/libifupdown/state.c index 74d0e0c..a05e3dd 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -126,7 +126,7 @@ lif_state_sync(struct lif_dict *state, struct lif_dict *if_collection) struct lif_dict_entry *entry = iter->data; struct lif_interface *iface = lif_interface_collection_find(if_collection, entry->key); - iface->is_up = true; + iface->refcount++; } return true; From 923b96fab87bceb0cd9d473c5f847abdcb588e31 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 14:46:07 -0600 Subject: [PATCH 244/530] state: use lif_next_token() when parsing ifstate files --- libifupdown/state.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libifupdown/state.c b/libifupdown/state.c index a05e3dd..f130f05 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -16,14 +16,17 @@ #include #include "libifupdown/state.h" #include "libifupdown/fgetline.h" +#include "libifupdown/tokenize.h" bool lif_state_read(struct lif_dict *state, FILE *fd) { char linebuf[4096]; + char *bufp = linebuf; + while (lif_fgetline(linebuf, sizeof linebuf, fd)) { - char *ifname = linebuf; + char *ifname = lif_next_token(&bufp); char *equals_p = strchr(linebuf, '='); if (equals_p == NULL) From 8e4eb5d00c90606f06f000c40f5ef11c11aeca75 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 14:59:58 -0600 Subject: [PATCH 245/530] state: migrate to lif_state_record from a bare dictionary containing the mapped ifs --- cmd/ifquery.c | 3 ++- libifupdown/state.c | 30 +++++++++++++++++++++++------- libifupdown/state.h | 5 +++++ 3 files changed, 30 insertions(+), 8 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 54625b1..25a09d3 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -215,7 +215,8 @@ list_state(struct lif_dict *state, struct match_options *opts) fnmatch(opts->include_pattern, entry->key, 0)) continue; - printf("%s=%s\n", entry->key, (const char *) entry->data); + struct lif_state_record *rec = entry->data; + printf("%s=%s %zu\n", entry->key, rec->mapped_if, rec->refcount); } } diff --git a/libifupdown/state.c b/libifupdown/state.c index f130f05..5ff80cc 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -27,16 +27,21 @@ lif_state_read(struct lif_dict *state, FILE *fd) while (lif_fgetline(linebuf, sizeof linebuf, fd)) { char *ifname = lif_next_token(&bufp); + char *refcount = lif_next_token(&bufp); + size_t rc = 1; char *equals_p = strchr(linebuf, '='); + if (*refcount) + rc = strtoul(refcount, NULL, 10); + if (equals_p == NULL) { - lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = ifname }); + lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = ifname, .refcount = rc }); continue; } *equals_p++ = '\0'; - lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = equals_p }); + lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = equals_p, .refcount = rc }); } return true; @@ -61,7 +66,12 @@ lif_state_read_path(struct lif_dict *state, const char *path) void lif_state_upsert(struct lif_dict *state, const char *ifname, struct lif_interface *iface) { - lif_dict_add(state, ifname, strdup(iface->ifname)); + struct lif_state_record *rec = calloc(1, sizeof(*rec)); + + rec->mapped_if = strdup(iface->ifname); + rec->refcount = iface->refcount; + + lif_dict_add(state, ifname, rec); } void @@ -72,7 +82,10 @@ lif_state_delete(struct lif_dict *state, const char *ifname) if (entry == NULL) return; - free(entry->data); + struct lif_state_record *rec = entry->data; + free(rec->mapped_if); + free(rec); + lif_dict_delete_entry(state, entry); } @@ -84,8 +97,9 @@ lif_state_write(const struct lif_dict *state, FILE *f) LIF_DICT_FOREACH(iter, state) { struct lif_dict_entry *entry = iter->data; + struct lif_state_record *rec = entry->data; - fprintf(f, "%s=%s\n", entry->key, (const char *) entry->data); + fprintf(f, "%s=%s %zu\n", entry->key, rec->mapped_if, rec->refcount); } } @@ -111,7 +125,8 @@ lif_state_lookup(struct lif_dict *state, struct lif_dict *if_collection, const c if (entry == NULL) return NULL; - struct lif_dict_entry *if_entry = lif_dict_find(if_collection, (const char *) entry->data); + struct lif_state_record *rec = entry->data; + struct lif_dict_entry *if_entry = lif_dict_find(if_collection, rec->mapped_if); if (if_entry == NULL) return NULL; @@ -127,9 +142,10 @@ lif_state_sync(struct lif_dict *state, struct lif_dict *if_collection) LIF_DICT_FOREACH(iter, state) { struct lif_dict_entry *entry = iter->data; + struct lif_state_record *rec = entry->data; struct lif_interface *iface = lif_interface_collection_find(if_collection, entry->key); - iface->refcount++; + iface->refcount = rec->refcount; } return true; diff --git a/libifupdown/state.h b/libifupdown/state.h index 584deca..8c46a63 100644 --- a/libifupdown/state.h +++ b/libifupdown/state.h @@ -19,6 +19,11 @@ #include #include "libifupdown/interface.h" +struct lif_state_record { + char *mapped_if; + size_t refcount; +}; + extern bool lif_state_read(struct lif_dict *state, FILE *f); extern bool lif_state_read_path(struct lif_dict *state, const char *path); extern void lif_state_upsert(struct lif_dict *state, const char *ifname, struct lif_interface *iface); From 865bf7cac66a5853b0eb75c23fa5bab63a2b4485 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 15:02:39 -0600 Subject: [PATCH 246/530] state: plug memory leak when upserting --- libifupdown/state.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libifupdown/state.c b/libifupdown/state.c index 5ff80cc..4509031 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -66,6 +66,8 @@ lif_state_read_path(struct lif_dict *state, const char *path) void lif_state_upsert(struct lif_dict *state, const char *ifname, struct lif_interface *iface) { + lif_state_delete(state, ifname); + struct lif_state_record *rec = calloc(1, sizeof(*rec)); rec->mapped_if = strdup(iface->ifname); From 288976f015f8f15aa34759f092949ce399e0c463 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 15:05:02 -0600 Subject: [PATCH 247/530] libifupdown: introduce lif_state_ref_if() and lif_state_unref_if(). --- libifupdown/state.c | 18 ++++++++++++++++++ libifupdown/state.h | 2 ++ 2 files changed, 20 insertions(+) diff --git a/libifupdown/state.c b/libifupdown/state.c index 4509031..f3a4260 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -63,6 +63,24 @@ lif_state_read_path(struct lif_dict *state, const char *path) return ret; } +void +lif_state_ref_if(struct lif_dict *state, const char *ifname, struct lif_interface *iface) +{ + iface->refcount++; + lif_state_upsert(state, ifname, iface); +} + +void +lif_state_unref_if(struct lif_dict *state, const char *ifname, struct lif_interface *iface) +{ + iface->refcount--; + + if (iface->refcount) + lif_state_upsert(state, ifname, iface); + else + lif_state_delete(state, ifname); +} + void lif_state_upsert(struct lif_dict *state, const char *ifname, struct lif_interface *iface) { diff --git a/libifupdown/state.h b/libifupdown/state.h index 8c46a63..bec039c 100644 --- a/libifupdown/state.h +++ b/libifupdown/state.h @@ -27,6 +27,8 @@ struct lif_state_record { extern bool lif_state_read(struct lif_dict *state, FILE *f); extern bool lif_state_read_path(struct lif_dict *state, const char *path); extern void lif_state_upsert(struct lif_dict *state, const char *ifname, struct lif_interface *iface); +extern void lif_state_ref_if(struct lif_dict *state, const char *ifname, struct lif_interface *iface); +extern void lif_state_unref_if(struct lif_dict *state, const char *ifname, struct lif_interface *iface); extern void lif_state_delete(struct lif_dict *state, const char *ifname); extern void lif_state_write(const struct lif_dict *state, FILE *f); extern bool lif_state_write_path(const struct lif_dict *state, const char *path); From 6603ff1000281c525b9391f5dd0d3c6e5c5173c6 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 15:28:36 -0600 Subject: [PATCH 248/530] lifecycle: use refcounting to defer interface teardown --- libifupdown/lifecycle.c | 44 +++++++++++++++++++++++++++++++++-------- libifupdown/state.c | 3 +++ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 2b77ed0..81f8587 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -261,6 +261,31 @@ handle_error: return false; } +/* this function returns true if we can skip processing the interface for now, + * otherwise false. + */ +static bool +handle_refcounting(struct lif_dict *state, struct lif_interface *iface, bool up) +{ + size_t orig_refcount = iface->refcount; + + if (up) + lif_state_ref_if(state, iface->ifname, iface); + else + lif_state_unref_if(state, iface->ifname, iface); + + /* if going up and orig_refcount > 0 -- we're already configured. */ + if (up && orig_refcount > 0) + return true; + + /* if going down and iface->refcount > 0 -- we still have other dependents. */ + if (!up && iface->refcount > 0) + return true; + + /* we can change this interface -- no blocking dependents. */ + return false; +} + static bool handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *parent, struct lif_dict *collection, struct lif_dict *state, bool up) { @@ -278,12 +303,17 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par { struct lif_interface *iface = lif_interface_collection_find(collection, tokenp); - /* already up or down, skip */ - if (up && iface->refcount > 0) + /* if handle_refcounting returns true, it means we've already + * configured the interface, or it is too soon to deconfigure + * the interface. + */ + if (handle_refcounting(state, iface, up)) { if (opts->verbose) - fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s)\n", - iface->ifname, parent->ifname); + fprintf(stderr, "ifupdown: skipping dependent interface %s (of %s) -- %s\n", + iface->ifname, parent->ifname, + up ? "already configured" : "transient dependencies still exist"); + continue; } @@ -328,7 +358,7 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa lif_state_upsert(state, lifname, iface); - iface->refcount++; + lif_state_ref_if(state, lifname, iface); } else { @@ -345,9 +375,7 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa if (!handle_dependents(opts, iface, collection, state, up)) return false; - lif_state_delete(state, lifname); - - iface->refcount--; + lif_state_unref_if(state, lifname, iface); } return true; diff --git a/libifupdown/state.c b/libifupdown/state.c index f3a4260..c2a1a99 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -73,6 +73,9 @@ lif_state_ref_if(struct lif_dict *state, const char *ifname, struct lif_interfac void lif_state_unref_if(struct lif_dict *state, const char *ifname, struct lif_interface *iface) { + if (iface->refcount == 0) + return; + iface->refcount--; if (iface->refcount) From ca07082ff45bca9dca827a515d4b346a2b006a6c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 15:37:35 -0600 Subject: [PATCH 249/530] state: fix parsing interface names in ifstate files --- libifupdown/state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/state.c b/libifupdown/state.c index c2a1a99..06a3f1e 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -22,10 +22,10 @@ bool lif_state_read(struct lif_dict *state, FILE *fd) { char linebuf[4096]; - char *bufp = linebuf; while (lif_fgetline(linebuf, sizeof linebuf, fd)) { + char *bufp = linebuf; char *ifname = lif_next_token(&bufp); char *refcount = lif_next_token(&bufp); size_t rc = 1; From f139bc2416628ab9638e6863f9a9ba3e26714996 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 15:50:32 -0600 Subject: [PATCH 250/530] lifecycle: consider an interface eligible for takedown if it has only one dependent (itself) --- libifupdown/lifecycle.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 81f8587..681ab02 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -274,12 +274,17 @@ handle_refcounting(struct lif_dict *state, struct lif_interface *iface, bool up) else lif_state_unref_if(state, iface->ifname, iface); +#ifdef DEBUG_REFCOUNTING + fprintf(stderr, "handle_refcounting(): orig_refcount=%zu, refcount=%zu, direction=%s\n", + orig_refcount, iface->refcount, up ? "UP" : "DOWN"); +#endif + /* if going up and orig_refcount > 0 -- we're already configured. */ if (up && orig_refcount > 0) return true; - /* if going down and iface->refcount > 0 -- we still have other dependents. */ - if (!up && iface->refcount > 0) + /* if going down and iface->refcount > 1 -- we still have other dependents. */ + if (!up && iface->refcount > 1) return true; /* we can change this interface -- no blocking dependents. */ From 8de83fdd9abaee8aca14203770420601a6ffe690 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 16:02:24 -0600 Subject: [PATCH 251/530] tests: add tests for deferred interface teardown (refcounting) --- tests/fixtures/deferred-teardown-1.ifstate | 6 ++++ tests/fixtures/deferred-teardown-1.interfaces | 9 ++++++ tests/fixtures/deferred-teardown-2.ifstate | 5 ++++ tests/fixtures/deferred-teardown-2.interfaces | 11 +++++++ tests/ifdown_test | 30 +++++++++++++++++++ 5 files changed, 61 insertions(+) create mode 100644 tests/fixtures/deferred-teardown-1.ifstate create mode 100644 tests/fixtures/deferred-teardown-1.interfaces create mode 100644 tests/fixtures/deferred-teardown-2.ifstate create mode 100644 tests/fixtures/deferred-teardown-2.interfaces diff --git a/tests/fixtures/deferred-teardown-1.ifstate b/tests/fixtures/deferred-teardown-1.ifstate new file mode 100644 index 0000000..188647b --- /dev/null +++ b/tests/fixtures/deferred-teardown-1.ifstate @@ -0,0 +1,6 @@ +lo=lo 1 +br0=br0 1 +bond0=bond0 2 +eth0=eth0 3 +eth1=eth1 2 +tun0=tun0 1 diff --git a/tests/fixtures/deferred-teardown-1.interfaces b/tests/fixtures/deferred-teardown-1.interfaces new file mode 100644 index 0000000..61930e2 --- /dev/null +++ b/tests/fixtures/deferred-teardown-1.interfaces @@ -0,0 +1,9 @@ +auto br0 +iface br0 + requires bond0 + +iface bond0 + requires eth0 eth1 + +iface tun0 + requires eth0 diff --git a/tests/fixtures/deferred-teardown-2.ifstate b/tests/fixtures/deferred-teardown-2.ifstate new file mode 100644 index 0000000..23f77d7 --- /dev/null +++ b/tests/fixtures/deferred-teardown-2.ifstate @@ -0,0 +1,5 @@ +eth0=eth0 5 +tun0=tun0 1 +tun1=tun1 1 +tun2=tun2 1 +tun3=tun3 1 diff --git a/tests/fixtures/deferred-teardown-2.interfaces b/tests/fixtures/deferred-teardown-2.interfaces new file mode 100644 index 0000000..b7ecc98 --- /dev/null +++ b/tests/fixtures/deferred-teardown-2.interfaces @@ -0,0 +1,11 @@ +iface tun0 + requires eth0 + +iface tun1 + requires eth0 + +iface tun2 + requires eth0 + +iface tun3 + requires eth0 diff --git a/tests/ifdown_test b/tests/ifdown_test index 3a8510a..8f2e7bf 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -19,6 +19,9 @@ tests_init \ learned_dependency_2 \ learned_executor \ implicit_vlan \ + deferred_teardown_1 \ + deferred_teardown_2 \ + deferred_teardown_3 \ regress_opt_f noargs_body() { @@ -142,6 +145,33 @@ implicit_vlan_body() { ifdown -n -S $FIXTURES/vlan.ifstate -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 } +deferred_teardown_1_body() { + atf_check -s exit:0 -o ignore \ + -e match:"skipping dependent interface eth0 \\(of bond0\\) -- transient dependencies still exist" \ + -e match:"changing state of dependent interface eth1 \\(of bond0\\) to down" \ + ifdown -n -S $FIXTURES/deferred-teardown-1.ifstate -E $EXECUTORS \ + -i $FIXTURES/deferred-teardown-1.interfaces br0 +} + +deferred_teardown_2_body() { + atf_check -s exit:0 -o ignore \ + -e match:"skipping dependent interface eth0 \\(of tun0\\) -- transient dependencies still exist" \ + -e match:"skipping dependent interface eth0 \\(of tun1\\) -- transient dependencies still exist" \ + -e match:"skipping dependent interface eth0 \\(of tun2\\) -- transient dependencies still exist" \ + ifdown -n -S $FIXTURES/deferred-teardown-2.ifstate -E $EXECUTORS \ + -i $FIXTURES/deferred-teardown-2.interfaces tun0 tun1 tun2 +} + +deferred_teardown_3_body() { + atf_check -s exit:0 -o ignore \ + -e match:"skipping dependent interface eth0 \\(of tun0\\) -- transient dependencies still exist" \ + -e match:"skipping dependent interface eth0 \\(of tun1\\) -- transient dependencies still exist" \ + -e match:"skipping dependent interface eth0 \\(of tun2\\) -- transient dependencies still exist" \ + -e match:"changing state of dependent interface eth0 \\(of tun3\\) to down" \ + ifdown -n -S $FIXTURES/deferred-teardown-2.ifstate -E $EXECUTORS \ + -i $FIXTURES/deferred-teardown-2.interfaces tun0 tun1 tun2 tun3 +} + regress_opt_f_body() { atf_check -s exit:0 -o ignore -e ignore \ ifdown -n -S $FIXTURES/vlan.ifstate -E $EXECUTORS -i $FIXTURES/vlan.interfaces -f eth0.8 From efe9b60e371ec4c7420ce2ee65171f8145fe7ee0 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 19:10:20 -0600 Subject: [PATCH 252/530] ifupdown: skip interface config/deconfig based on refcounts --- cmd/ifupdown.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index bd9a68e..9124320 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -93,6 +93,26 @@ acquire_state_lock(const char *state_path, const char *lifname) return fd; } +bool +skip_interface(struct lif_interface *iface, const char *ifname) +{ + if (up && iface->refcount > 0) + { + fprintf(stderr, "%s: skipping %s (already configured), use --force to force configuration\n", + argv0, ifname); + return true; + } + + if (!up && iface->refcount == 0) + { + fprintf(stderr, "%s: skipping %s (already deconfigured), use --force to force deconfiguration\n", + argv0, ifname); + return true; + } + + return false; +} + bool change_interface(struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *ifname) { @@ -104,6 +124,14 @@ change_interface(struct lif_interface *iface, struct lif_dict *collection, struc return false; } + if (skip_interface(iface, ifname)) + { + if (lockfd != -1) + close(lockfd); + + return true; + } + if (exec_opts.verbose) { fprintf(stderr, "%s: changing state of interface %s to '%s'\n", From b514d31c2662d8bbbd2eb37a5f3c39576ebf9985 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 19:17:00 -0600 Subject: [PATCH 253/530] ifupdown: implement --force --- cmd/ifupdown.c | 3 +++ cmd/multicall-exec-options.c | 5 +++-- libifupdown/execute.h | 1 + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 9124320..6405cbf 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -96,6 +96,9 @@ acquire_state_lock(const char *state_path, const char *lifname) bool skip_interface(struct lif_interface *iface, const char *ifname) { + if (exec_opts.force) + return false; + if (up && iface->refcount > 0) { fprintf(stderr, "%s: skipping %s (already configured), use --force to force configuration\n", diff --git a/cmd/multicall-exec-options.c b/cmd/multicall-exec-options.c index cd57a22..f56228c 100644 --- a/cmd/multicall-exec-options.c +++ b/cmd/multicall-exec-options.c @@ -68,13 +68,14 @@ set_no_lock(const char *opt_arg) } static void -no_op(const char *opt_arg) +set_force(const char *opt_arg) { (void) opt_arg; + exec_opts.force = true; } static struct if_option exec_options[] = { - {'f', "force", NULL, "force (de)configuration", false, no_op}, + {'f', "force", NULL, "force (de)configuration", false, set_force}, {'i', "interfaces", "interfaces FILE", "use FILE for interface definitions", true, set_interfaces_file}, {'l', "no-lock", NULL, "do not use a lockfile to serialize state changes", false, set_no_lock}, {'n', "no-act", NULL, "do not actually run any commands", false, set_no_act}, diff --git a/libifupdown/execute.h b/libifupdown/execute.h index fa4af78..89b9815 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -23,6 +23,7 @@ struct lif_execute_opts { bool verbose; bool mock; bool no_lock; + bool force; const char *executor_path; const char *interfaces_file; const char *state_file; From 3b178131bd927c46e3ac3a835af869b77ad61159 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 19:25:00 -0600 Subject: [PATCH 254/530] state: sync refcounts using mapped interface name, not physical interface name --- libifupdown/state.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/state.c b/libifupdown/state.c index 06a3f1e..344a417 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -166,7 +166,7 @@ lif_state_sync(struct lif_dict *state, struct lif_dict *if_collection) { struct lif_dict_entry *entry = iter->data; struct lif_state_record *rec = entry->data; - struct lif_interface *iface = lif_interface_collection_find(if_collection, entry->key); + struct lif_interface *iface = lif_interface_collection_find(if_collection, rec->mapped_if); iface->refcount = rec->refcount; } From 910985cd225b2a78bee0eb3880a57f1930815fe9 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 8 Sep 2020 19:25:50 -0600 Subject: [PATCH 255/530] tests: supply --force where appropriate --- tests/ifdown_test | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/ifdown_test b/tests/ifdown_test index 8f2e7bf..2ca83c3 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -30,56 +30,56 @@ noargs_body() { lo_always_auto_body() { atf_check -s exit:0 -e ignore -o match:'executors/link' \ - ifdown -S/dev/null -E $EXECUTORS -i/dev/null -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i/dev/null -n -a } dual_stack_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/static' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0.interfaces -n -a } static_ipv4_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/static' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4.interfaces -n -a } static_ipv4_netmask_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/static' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v4-netmask.interfaces -n -a } static_ipv6_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/static' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6.interfaces -n -a } static_ipv6_netmask_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/static' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/static-eth0-v6-netmask.interfaces -n -a } inet_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/dhcp' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/dhcp-eth0.interfaces -n -a } use_dhcp_body() { atf_check -s exit:0 -e ignore \ -o match:'executors/link' \ -o match:'executors/dhcp' \ - ifdown -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a + ifdown -f -S/dev/null -E $EXECUTORS -i $FIXTURES/use-dhcp-eth0.interfaces -n -a } alias_eth0_home_body() { From c021b9420f2d0d2465b564ebbda1f6b407aa7fe9 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 11:56:19 -0600 Subject: [PATCH 256/530] state: ensure rc is set to 1 if strtoul() fails --- libifupdown/state.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libifupdown/state.c b/libifupdown/state.c index 344a417..6421aaa 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -32,8 +32,13 @@ lif_state_read(struct lif_dict *state, FILE *fd) char *equals_p = strchr(linebuf, '='); if (*refcount) + { rc = strtoul(refcount, NULL, 10); + if (rc == 0 || rc == ULONG_MAX) + rc = 1; + } + if (equals_p == NULL) { lif_state_upsert(state, ifname, &(struct lif_interface){ .ifname = ifname, .refcount = rc }); From 6999a125c88dfbd73ec8da59413de777816edceb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 13:27:34 -0600 Subject: [PATCH 257/530] state: include limits.h --- libifupdown/state.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libifupdown/state.c b/libifupdown/state.c index 6421aaa..ed4f344 100644 --- a/libifupdown/state.c +++ b/libifupdown/state.c @@ -13,6 +13,7 @@ * from the use of this software. */ +#include #include #include "libifupdown/state.h" #include "libifupdown/fgetline.h" From 885126174d32a2d565619c9907fdd8fc08b4eb3e Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 14:18:16 -0600 Subject: [PATCH 258/530] ifupdown: consistently update the state file when exiting --- cmd/ifupdown.c | 37 ++++++++++++++++++++++++++----------- 1 file changed, 26 insertions(+), 11 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 6405cbf..bc8b657 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -186,6 +186,27 @@ change_auto_interfaces(struct lif_dict *collection, struct lif_dict *state, stru return true; } +int +update_state_file_and_exit(int rc, struct lif_dict *state) +{ + if (exec_opts.mock) + { + exit(rc); + return rc; + } + + if (!lif_state_write_path(state, exec_opts.state_file)) + { + fprintf(stderr, "%s: could not update %s\n", argv0, exec_opts.state_file); + + exit(EXIT_FAILURE); + return EXIT_FAILURE; + } + + exit(rc); + return rc; +} + int ifupdown_main(int argc, char *argv[]) { @@ -217,9 +238,9 @@ ifupdown_main(int argc, char *argv[]) if (match_opts.is_auto) { if (!change_auto_interfaces(&collection, &state, &match_opts)) - return EXIT_FAILURE; + return update_state_file_and_exit(EXIT_FAILURE, &state); - return EXIT_SUCCESS; + return update_state_file_and_exit(EXIT_SUCCESS, &state); } else if (optind >= argc) generic_usage(self_applet, EXIT_FAILURE); @@ -248,23 +269,17 @@ ifupdown_main(int argc, char *argv[]) if (entry == NULL) { fprintf(stderr, "%s: unknown interface %s\n", argv0, argv[idx]); - return EXIT_FAILURE; + return update_state_file_and_exit(EXIT_FAILURE, &state); } iface = entry->data; } if (!change_interface(iface, &collection, &state, ifname)) - return EXIT_FAILURE; + return update_state_file_and_exit(EXIT_FAILURE, &state); } - if (!exec_opts.mock && !lif_state_write_path(&state, exec_opts.state_file)) - { - fprintf(stderr, "%s: could not update %s\n", argv0, exec_opts.state_file); - return EXIT_FAILURE; - } - - return EXIT_SUCCESS; + return update_state_file_and_exit(EXIT_SUCCESS, &state); } struct if_applet ifup_applet = { From 00da19a3810d8662aca25e6411b1c5bd9a86af68 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 14:36:07 -0600 Subject: [PATCH 259/530] lifecycle: add create/destroy phases --- libifupdown/lifecycle.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 681ab02..19982bb 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -352,6 +352,9 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa * but, right now neither debian ifupdown or busybox ifupdown do any recovery, * so we wont right now. */ + if (!lif_lifecycle_run_phase(opts, iface, "create", lifname, up)) + return false; + if (!lif_lifecycle_run_phase(opts, iface, "pre-up", lifname, up)) return false; @@ -376,6 +379,9 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa if (!lif_lifecycle_run_phase(opts, iface, "post-down", lifname, up)) return false; + if (!lif_lifecycle_run_phase(opts, iface, "destroy", lifname, up)) + return false; + /* when going up, dependents go down last. */ if (!handle_dependents(opts, iface, collection, state, up)) return false; From ce6954d62879c3532697a5b0cd800a506fae9da6 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 14:39:40 -0600 Subject: [PATCH 260/530] ifupdown-executor man page: add create/destroy phases --- doc/ifupdown-executor.scd | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/ifupdown-executor.scd b/doc/ifupdown-executor.scd index 2064b4b..05de8fa 100644 --- a/doc/ifupdown-executor.scd +++ b/doc/ifupdown-executor.scd @@ -12,7 +12,7 @@ protocol documented in this man page. # PHASES -Executors are run to react to seven different phases and are not +Executors are run to react to nine different phases and are not required to take any specific action. These phases are: *depend* @@ -24,6 +24,10 @@ required to take any specific action. These phases are: any dependencies, it may simply exit 0 without doing anything. +*create* + Called before *pre-up*, to explicitly allow for interface + creation if necessary. + *pre-up* Called before the interface is going to be brought up. @@ -42,6 +46,10 @@ required to take any specific action. These phases are: *post-down* Called after the interface was successfully taken down. +*destroy* + Called after *post-down* to allow for explicitly + destroying an interface if necessary. + # ENVIRONMENT Executors are guaranteed to run with a core set of environment From 5a0b53cd7312deafb07421b0544016a0c628f5d5 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 15:50:16 -0600 Subject: [PATCH 261/530] libifupdown: add interface being run for each executor --- libifupdown/execute.c | 8 ++++---- libifupdown/execute.h | 4 ++-- libifupdown/lifecycle.c | 10 +++++----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/libifupdown/execute.c b/libifupdown/execute.c index d5b7bda..69af1c0 100644 --- a/libifupdown/execute.c +++ b/libifupdown/execute.c @@ -140,10 +140,10 @@ lif_file_is_executable(const char *path) } bool -lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor, const char *phase) +lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor, const char *phase, const char *lifname) { if (opts->verbose) - fprintf(stderr, "ifupdown: attempting to run %s executor for phase %s\n", executor, phase); + fprintf(stderr, "ifupdown: %s: attempting to run %s executor for phase %s\n", lifname, executor, phase); char pathbuf[4096]; @@ -156,10 +156,10 @@ lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], } bool -lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize, const char *phase) +lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize, const char *phase, const char *lifname) { if (opts->verbose) - fprintf(stderr, "ifupdown: attempting to run %s executor for phase %s\n", executor, phase); + fprintf(stderr, "ifupdown: %s: attempting to run %s executor for phase %s\n", lifname, executor, phase); char pathbuf[4096]; diff --git a/libifupdown/execute.h b/libifupdown/execute.h index 89b9815..5a871a9 100644 --- a/libifupdown/execute.h +++ b/libifupdown/execute.h @@ -32,7 +32,7 @@ struct lif_execute_opts { extern bool lif_execute_fmt(const struct lif_execute_opts *opts, char *const envp[], const char *fmt, ...); extern bool lif_execute_fmt_with_result(const struct lif_execute_opts *opts, char *buf, size_t bufsize, char *const envp[], const char *fmt, ...); extern bool lif_file_is_executable(const char *path); -extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor, const char *phase); -extern bool lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize, const char *phase); +extern bool lif_maybe_run_executor(const struct lif_execute_opts *opts, char *const envp[], const char *executor, const char *phase, const char *lifname); +extern bool lif_maybe_run_executor_with_result(const struct lif_execute_opts *opts, char *const envp[], const char *executor, char *buf, size_t bufsize, const char *phase, const char *lifname); #endif diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 19982bb..96c895b 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -47,13 +47,13 @@ handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[ } static inline bool -handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struct lif_execute_opts *opts, char *const envp[], const char *phase) +handle_single_executor_for_phase(const struct lif_dict_entry *entry, const struct lif_execute_opts *opts, char *const envp[], const char *phase, const char *lifname) { if (strcmp(entry->key, "use")) return true; const char *cmd = entry->data; - if (!lif_maybe_run_executor(opts, envp, cmd, phase)) + if (!lif_maybe_run_executor(opts, envp, cmd, phase, lifname)) return false; return true; @@ -67,12 +67,12 @@ handle_executors_for_phase(const struct lif_execute_opts *opts, char *const envp if (up) { LIF_DICT_FOREACH(iter, &iface->vars) - handle_single_executor_for_phase(iter->data, opts, envp, phase); + handle_single_executor_for_phase(iter->data, opts, envp, phase, iface->ifname); } else { LIF_DICT_FOREACH_REVERSE(iter, &iface->vars) - handle_single_executor_for_phase(iter->data, opts, envp, phase); + handle_single_executor_for_phase(iter->data, opts, envp, phase, iface->ifname); } return true; @@ -97,7 +97,7 @@ query_dependents_from_executors(const struct lif_execute_opts *opts, char *const continue; const char *cmd = entry->data; - if (!lif_maybe_run_executor_with_result(&exec_opts, envp, cmd, resbuf, sizeof resbuf, phase)) + if (!lif_maybe_run_executor_with_result(&exec_opts, envp, cmd, resbuf, sizeof resbuf, phase, iface->ifname)) return false; if (!*resbuf) From e6c6f49143e4aa119c30e4d27035dcd83e8fe542 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 16:00:53 -0600 Subject: [PATCH 262/530] lifecycle: remove redundant lif_state_upsert() call this will be handled by lif_state_ref_if(), which also updates the refcounting. --- libifupdown/lifecycle.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 96c895b..5d50248 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -364,8 +364,6 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa if (!lif_lifecycle_run_phase(opts, iface, "post-up", lifname, up)) return false; - lif_state_upsert(state, lifname, iface); - lif_state_ref_if(state, lifname, iface); } else From 35e03475e44c8db1275b6b3436e8d990a1431fde Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 10 Sep 2020 00:40:57 +0200 Subject: [PATCH 263/530] batman executor: Use create/destroy phases Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/batman | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/batman b/executor-scripts/linux/batman index dbc826b..87ae989 100644 --- a/executor-scripts/linux/batman +++ b/executor-scripts/linux/batman @@ -68,13 +68,18 @@ case "${PHASE}" in fi ;; - pre-up) + create) # Main B.A.T.M.A.N. adv. interface if [ "${IF_BATMAN_IFACES}" ]; then if [ ! -d "/sys/class/net/${IFACE}" ]; then batctl "${mesh_if_param}" "${IFACE}" interface create || true fi + fi + ;; + pre-up) + # Main B.A.T.M.A.N. adv. interface + if [ "${IF_BATMAN_IFACES}" ]; then batctl_if add set_batmam_params @@ -84,7 +89,7 @@ case "${PHASE}" in fi ;; - post-down) + destroy) if [ "${IF_BATMAN_IFACES}" -a -d "/sys/class/net/${IFACE}" ]; then # Newer versions of batctl provide the "interface destroy" API, try to use it if ! batctl "${mesh_if_param}" "${IFACE}" interface destroy 2>/dev/null; then From af94d760d03e6621d0c35ca03f35b067b6d1254e Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 10 Sep 2020 00:48:35 +0200 Subject: [PATCH 264/530] Update executors to reflect new create/destroy phase. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/bridge | 13 +++++++++++-- executor-scripts/linux/gre | 4 ++-- executor-scripts/linux/link | 4 ++-- executor-scripts/linux/ppp | 14 +++++++++++--- executor-scripts/linux/tunnel | 4 ++-- executor-scripts/linux/vrf | 10 +++++----- executor-scripts/linux/wireguard | 6 ++++-- 7 files changed, 37 insertions(+), 18 deletions(-) diff --git a/executor-scripts/linux/bridge b/executor-scripts/linux/bridge index 3a4a41c..144b75f 100755 --- a/executor-scripts/linux/bridge +++ b/executor-scripts/linux/bridge @@ -4,6 +4,7 @@ set -e # Copyright (C) 2012, 2020 Natanael Copa # Copyright (C) 2020 Ariadne Conill +# Copyright (C) 2020 Maximilian Wilhelm # # Permission to use, copy, modify, and/or distribute this software for any # purpose with or without fee is hereby granted, provided that the above @@ -134,8 +135,12 @@ esac [ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit case "$PHASE" in +create) + if [ ! -d "/sys/class/net/${IFACE}" ]; then + brctl addbr "${IFACE}" + fi + ;; pre-up) - brctl addbr $IFACE || exit 1 wait_ports set_bridge_opts add_ports @@ -144,6 +149,10 @@ pre-up) post-down) del_ports ip link set dev $IFACE down - brctl delbr $IFACE || exit 1 + ;; +destroy) + if [ -d "/sys/class/net/${IFACE}" ]; then + brctl delbr "${IFACE}" + fi ;; esac diff --git a/executor-scripts/linux/gre b/executor-scripts/linux/gre index 40b96e8..c226963 100755 --- a/executor-scripts/linux/gre +++ b/executor-scripts/linux/gre @@ -19,10 +19,10 @@ PARAMS="mode $IF_GRE_MODE local '$IF_GRE_LOCAL' remote '$IF_GRE_REMOTE'" [ -n "$PARAMS" ] || exit 0 case "$PHASE" in -pre-up) +create) ${MOCK} eval ip $FAMILY $COMMAND add $IFACE $PARAMS ;; -post-down) +destroy) ${MOCK} ip $FAMILY $COMMAND del $IFACE ;; depend) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 7211d70..02633ef 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -28,7 +28,7 @@ is_vlan() { } case "$PHASE" in -pre-up) +create) if [ "${IF_LINK_TYPE}" = "dummy" ]; then if [ -d "/sys/class/net/${IFACE}" ]; then iface_type=$(ip -d link show dev "${IFACE}" | head -n3 | tail -n1 | awk '{ print $1 }') @@ -76,7 +76,7 @@ up) down) ${MOCK} ip link set down dev "${IFACE}" ;; -post-down) +destroy) if [ "${IF_LINK_TYPE}" = "dummy" ] || is_vlan; then if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then exit 0 diff --git a/executor-scripts/linux/ppp b/executor-scripts/linux/ppp index 3ba001b..c608a4e 100755 --- a/executor-scripts/linux/ppp +++ b/executor-scripts/linux/ppp @@ -1,8 +1,16 @@ #!/bin/sh set -e + [ -z "$IF_PPP_PROVIDER" ] && exit 0 + case "$PHASE" in -pre-up) ${MOCK} pon $IF_PPP_PROVIDER ;; -post-down) ${MOCK} poff $IF_PPP_PROVIDER ;; -depend) echo "$IF_PPP_PHYSDEV" ;; +create) + ${MOCK} pon $IF_PPP_PROVIDER + ;; +destroy) + ${MOCK} poff $IF_PPP_PROVIDER + ;; +depend) + echo "$IF_PPP_PHYSDEV" + ;; esac diff --git a/executor-scripts/linux/tunnel b/executor-scripts/linux/tunnel index e370b2a..a39eb34 100755 --- a/executor-scripts/linux/tunnel +++ b/executor-scripts/linux/tunnel @@ -37,10 +37,10 @@ PARAMS=$(set | sed -E ' [ "$PARAMS" ] || exit 0 case "$PHASE" in -pre-up) +create) ${MOCK} eval ip $FAMILY $COMMAND add $IFACE $PARAMS ;; -post-down) +destroy) ${MOCK} ip $FAMILY $COMMAND del $IFACE ;; depend) diff --git a/executor-scripts/linux/vrf b/executor-scripts/linux/vrf index c42b000..d9b4373 100755 --- a/executor-scripts/linux/vrf +++ b/executor-scripts/linux/vrf @@ -14,14 +14,14 @@ handle_member() { [ -n "$VERBOSE" ] && set -x case "$PHASE" in -pre-up) +create) [ -n "$IF_VRF_TABLE" ] && handle_init "add" - [ -n "$IF_VRF_MEMBER" ] && handle_member - exit 0 ;; -post-down) +pre-up) + [ -n "$IF_VRF_MEMBER" ] && handle_member + ;; +destroy) [ -n "$IF_VRF_TABLE" ] && handle_init "del" - exit 0 ;; depend) echo "$IF_VRF_MEMBER" diff --git a/executor-scripts/linux/wireguard b/executor-scripts/linux/wireguard index fa4a059..3ab56e3 100755 --- a/executor-scripts/linux/wireguard +++ b/executor-scripts/linux/wireguard @@ -6,11 +6,13 @@ set -e [ -z "$IF_WIREGUARD_CONFIG_PATH" ] && IF_WIREGUARD_CONFIG_PATH="/etc/wireguard/$IFACE.conf" case "$PHASE" in -pre-up) +create) ${MOCK} ip link add $IFACE type wireguard + ;; +pre-up) ${MOCK} wg setconf $IFACE $IF_WIREGUARD_CONFIG_PATH ;; -post-down) +destroy) ${MOCK} ip link delete dev $IFACE ;; esac From d9e78e14fb87ad36124f1e31b7449c456cf8042e Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Wed, 9 Sep 2020 23:36:11 +0200 Subject: [PATCH 265/530] tests: Update tests to reflect create/destroy phase. Signed-off-by: Maximilian Wilhelm --- tests/linux/gre_test | 6 +++--- tests/linux/link_test | 30 +++++++++++++++--------------- tests/linux/ppp_test | 4 ++-- tests/linux/tunnel_test | 4 ++-- tests/linux/vrf_test | 4 ++-- tests/linux/wireguard_test | 16 +++++++++++----- 6 files changed, 35 insertions(+), 29 deletions(-) diff --git a/tests/linux/gre_test b/tests/linux/gre_test index 1803253..688717a 100755 --- a/tests/linux/gre_test +++ b/tests/linux/gre_test @@ -9,7 +9,7 @@ tests_init \ flags_bringup basic_bringup_body() { - export MOCK=echo IFACE=tun0 PHASE=pre-up \ + export MOCK=echo IFACE=tun0 PHASE=create \ IF_GRE_LOCAL=1.2.3.4 IF_GRE_REMOTE=5.6.7.8 \ IF_GRE_TTL=255 atf_check -s exit:0 \ @@ -22,7 +22,7 @@ basic_bringup_body() { } basic_teardown_body() { - export MOCK=echo IFACE=tun0 PHASE=post-down \ + export MOCK=echo IFACE=tun0 PHASE=destroy \ IF_GRE_LOCAL=1.2.3.4 IF_GRE_REMOTE=5.6.7.8 \ IF_GRE_TTL=255 atf_check -s exit:0 \ @@ -31,7 +31,7 @@ basic_teardown_body() { } flags_bringup_body() { - export MOCK=echo IFACE=tun0 PHASE=pre-up \ + export MOCK=echo IFACE=tun0 PHASE=create \ IF_GRE_LOCAL=1.2.3.4 IF_GRE_REMOTE=5.6.7.8 \ IF_GRE_TTL=255 IF_GRE_FLAGS="nopmtudisc ignore-df" atf_check -s exit:0 \ diff --git a/tests/linux/link_test b/tests/linux/link_test index db3e787..7d570d8 100755 --- a/tests/linux/link_test +++ b/tests/linux/link_test @@ -8,13 +8,13 @@ tests_init \ down \ mtu \ hwaddress \ - vlan_explicit_pre_up \ - vlan_explicit_post_down \ - vlan_guessed_pre_up \ - vlan_guessed_post_down \ + vlan_explicit_create \ + vlan_explicit_destroy \ + vlan_guessed_create \ + vlan_guessed_destroy \ vlan_explicit_depend \ vlan_guessed_depend \ - dummy_pre_up + dummy_create up_body() { export IFACE=lo PHASE=up MOCK=echo @@ -40,28 +40,28 @@ hwaddress_body() { ${EXECUTOR} } -vlan_explicit_pre_up_body() { - export IFACE=servers PHASE=pre-up MOCK=echo \ +vlan_explicit_create_body() { + export IFACE=servers PHASE=create MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link add link eth0 name servers type vlan id 123' \ ${EXECUTOR} } -vlan_explicit_post_down_body() { - export IFACE=servers PHASE=post-down MOCK=echo \ +vlan_explicit_destroy_body() { + export IFACE=servers PHASE=destroy MOCK=echo \ IF_VLAN_RAW_DEVICE="eth0" IF_VLAN_ID="123" atf_check -s exit:0 -o match:'ip link del servers' \ ${EXECUTOR} } -vlan_guessed_pre_up_body() { - export IFACE=eth0.8 PHASE=pre-up MOCK=echo +vlan_guessed_create_body() { + export IFACE=eth0.8 PHASE=create MOCK=echo atf_check -s exit:0 -o match:'ip link add link eth0 name eth0.8 type vlan id 8' \ ${EXECUTOR} } -vlan_guessed_post_down_body() { - export IFACE=eth0.8 PHASE=post-down MOCK=echo +vlan_guessed_destroy_body() { + export IFACE=eth0.8 PHASE=destroy MOCK=echo atf_check -s exit:0 -o match:'ip link del eth0.8' \ ${EXECUTOR} } @@ -79,8 +79,8 @@ vlan_guessed_depend_body() { ${EXECUTOR} } -dummy_pre_up_body() { - export IFACE=yolo IF_LINK_TYPE=dummy PHASE=pre-up MOCK=echo +dummy_create_body() { + export IFACE=yolo IF_LINK_TYPE=dummy PHASE=create MOCK=echo atf_check -s exit:0 -o match:'ip link add yolo type dummy' \ ${EXECUTOR} } diff --git a/tests/linux/ppp_test b/tests/linux/ppp_test index 46bb0e0..1b9e18c 100755 --- a/tests/linux/ppp_test +++ b/tests/linux/ppp_test @@ -8,14 +8,14 @@ tests_init \ teardown \ bringup_body() { - export MOCK=echo IFACE=ppp0 PHASE=pre-up IF_PPP_PROVIDER=someisp + export MOCK=echo IFACE=ppp0 PHASE=create IF_PPP_PROVIDER=someisp atf_check -s exit:0 \ -o match:'pon someisp' \ ${EXECUTOR} } teardown_body() { - export MOCK=echo IFACE=ppp0 PHASE=post-down IF_PPP_PROVIDER=someisp + export MOCK=echo IFACE=ppp0 PHASE=destroy IF_PPP_PROVIDER=someisp atf_check -s exit:0 \ -o match:'poff someisp' \ ${EXECUTOR} diff --git a/tests/linux/tunnel_test b/tests/linux/tunnel_test index 8bf9534..de86105 100755 --- a/tests/linux/tunnel_test +++ b/tests/linux/tunnel_test @@ -8,7 +8,7 @@ tests_init \ tunnel_teardown tunnel_bringup_body() { - export MOCK=echo IFACE=tun0 PHASE=pre-up IF_TUNNEL_MODE=gre \ + export MOCK=echo IFACE=tun0 PHASE=create IF_TUNNEL_MODE=gre \ IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8 \ IF_TUNNEL_TTL=255 atf_check -s exit:0 \ @@ -21,7 +21,7 @@ tunnel_bringup_body() { } tunnel_teardown_body() { - export MOCK=echo IFACE=tun0 PHASE=post-down IF_TUNNEL_MODE=gre \ + export MOCK=echo IFACE=tun0 PHASE=destroy IF_TUNNEL_MODE=gre \ IF_TUNNEL_LOCAL=1.2.3.4 IF_TUNNEL_REMOTE=5.6.7.8 \ IF_TUNNEL_TTL=255 atf_check -s exit:0 \ diff --git a/tests/linux/vrf_test b/tests/linux/vrf_test index 942a539..97756f0 100755 --- a/tests/linux/vrf_test +++ b/tests/linux/vrf_test @@ -9,7 +9,7 @@ tests_init \ member_bringup leader_bringup_body() { - export MOCK=echo IFACE=vrf-red PHASE=pre-up IF_VRF_TABLE=1 IF_VRF_MEMBER= + export MOCK=echo IFACE=vrf-red PHASE=create IF_VRF_TABLE=1 IF_VRF_MEMBER= atf_check -s exit:0 \ -o match:'ip link add vrf-red type vrf table 1' \ -o match:'ip rule add iif vrf-red table 1' \ @@ -18,7 +18,7 @@ leader_bringup_body() { } leader_teardown_body() { - export MOCK=echo IFACE=vrf-red PHASE=post-down IF_VRF_TABLE=1 IF_VRF_MEMBER= + export MOCK=echo IFACE=vrf-red PHASE=destroy IF_VRF_TABLE=1 IF_VRF_MEMBER= atf_check -s exit:0 \ -o match:'ip link del vrf-red type vrf table 1' \ -o match:'ip rule del iif vrf-red table 1' \ diff --git a/tests/linux/wireguard_test b/tests/linux/wireguard_test index ca6e19e..8b5f709 100755 --- a/tests/linux/wireguard_test +++ b/tests/linux/wireguard_test @@ -4,14 +4,21 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/wireguard" tests_init \ + create \ pre_up \ pre_up_specified_config \ - post_down + destroy + +create_body() { + export IFACE=wg0 PHASE=create MOCK=echo + atf_check -s exit:0 \ + -o match:'ip link add wg0 type wireguard' \ + ${EXECUTOR} +} pre_up_body() { export IFACE=wg0 PHASE=pre-up MOCK=echo atf_check -s exit:0 \ - -o match:'ip link add wg0 type wireguard' \ -o match:'wg setconf wg0 /etc/wireguard/wg0.conf' \ ${EXECUTOR} } @@ -20,13 +27,12 @@ pre_up_specified_config_body() { export IFACE=wg0 PHASE=pre-up MOCK=echo \ IF_WIREGUARD_CONFIG_PATH=/etc/wireguard/vpn.conf atf_check -s exit:0 \ - -o match:'ip link add wg0 type wireguard' \ -o match:'wg setconf wg0 /etc/wireguard/vpn.conf' \ ${EXECUTOR} } -post_down_body() { - export IFACE=wg0 PHASE=post-down MOCK=echo +destroy_body() { + export IFACE=wg0 PHASE=destroy MOCK=echo atf_check -s exit:0 \ -o match:'ip link delete dev wg0' \ ${EXECUTOR} From e02e495257a90e58262b66df764235fe752d67d3 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 10 Sep 2020 00:05:32 +0200 Subject: [PATCH 266/530] bridge executor: Add depend phase Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/bridge | 3 +++ 1 file changed, 3 insertions(+) diff --git a/executor-scripts/linux/bridge b/executor-scripts/linux/bridge index 144b75f..5d92061 100755 --- a/executor-scripts/linux/bridge +++ b/executor-scripts/linux/bridge @@ -135,6 +135,9 @@ esac [ -z "$PORTS" ] && ! env | grep -q "^IF_BRIDGE" && exit case "$PHASE" in +depend) + echo "$PORTS" + ;; create) if [ ! -d "/sys/class/net/${IFACE}" ]; then brctl addbr "${IFACE}" From 0674a70c351892525ff1a0ddce0ea372dd1adf16 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Thu, 10 Sep 2020 00:42:35 +0200 Subject: [PATCH 267/530] batman executor: Fix typo Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/batman | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/executor-scripts/linux/batman b/executor-scripts/linux/batman index 87ae989..c041634 100644 --- a/executor-scripts/linux/batman +++ b/executor-scripts/linux/batman @@ -6,7 +6,7 @@ # This executor is responsible for setting up the main B.A.T.M.A.N. adv. interface (eg. bat0) # as well as managing settings of the underlying interfaces (hardifs). # -# Know options for the main interface are: +# Known options for the main interface are: # IF_BATMAN_IFACES Space separated list of interfaces to be part of this B.A.T.M.A.N. adv. instance # IF_BATMAN_IFACES_IGNORE_REGEX Interfaces to ignore when verifying configuration (regexp) # IF_BATMAN_DISTRIBUTED_ARP_TABLE 'enable' or 'disable' DAT of this B.A.T.M.A.N. adv. instance @@ -47,7 +47,7 @@ batctl_if () { done } -set_batmam_params () { +set_batman_params () { [ "${IF_BATMAN_DISTRIBUTED_ARP_TABLE}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" distributed_arp_table "${IF_BATMAN_DISTRIBUTED_ARP_TABLE}" [ "${IF_BATMAN_MULTICAST_MODE}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" multicast_mode "${IF_BATMAN_MULTICAST_MODE}" [ "${IF_BATMAN_HOP_PENALTY}" ] && ${MOCK} batctl "${mesh_if_param}" "${IFACE}" hop_penalty "${IF_BATMAN_HOP_PENALTY}" @@ -81,7 +81,7 @@ case "${PHASE}" in # Main B.A.T.M.A.N. adv. interface if [ "${IF_BATMAN_IFACES}" ]; then batctl_if add - set_batmam_params + set_batman_params # B.A.T.M.A.N. adv. underlying interface elif [ "${IF_BATMAN_IFACE_PENALTY}" ]; then From 67dce280d78f07d5a66c0ea5336cea09d5f34cc2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 17:13:11 -0600 Subject: [PATCH 268/530] interface: add lif_interface.rdepends_count --- libifupdown/interface.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/libifupdown/interface.h b/libifupdown/interface.h index a18c4b7..d627610 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -53,7 +53,8 @@ struct lif_interface { struct lif_dict vars; - size_t refcount; /* >= 0 if up, else 0 */ + size_t refcount; /* > 0 if up, else 0 */ + size_t rdepends_count; /* > 0 if any reverse dependency */ }; #define LIF_INTERFACE_COLLECTION_FOREACH(iter, collection) \ From a5eebda391e00b3b2f9db080aade68dadd0e96a4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 17:14:58 -0600 Subject: [PATCH 269/530] ifquery: include reverse dependency count in dot output --- cmd/ifquery.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 25a09d3..8968d86 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -67,9 +67,9 @@ print_interface_dot(struct lif_dict *collection, struct lif_interface *iface, st return; if (parent != NULL) - printf("\"%s\" -> ", parent->ifname); + printf("\"%s (%zu)\" -> ", parent->ifname, parent->rdepends_count); - printf("\"%s\"", iface->ifname); + printf("\"%s (%zu)\"", iface->ifname, iface->rdepends_count); printf("\n"); From 2569503afa6fa8edb45433be62bff38406d9c0d8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 17:39:26 -0600 Subject: [PATCH 270/530] lifecycle: add lif_lifecycle_count_rdepends(), which calculates reverse dependency depth --- cmd/ifquery.c | 6 +++++ cmd/ifupdown.c | 6 +++++ libifupdown/lifecycle.c | 55 +++++++++++++++++++++++++++++++++++++++++ libifupdown/lifecycle.h | 1 + 4 files changed, 68 insertions(+) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 8968d86..855cbb0 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -290,6 +290,12 @@ ifquery_main(int argc, char *argv[]) return EXIT_FAILURE; } + if (!lif_lifecycle_count_rdepends(&exec_opts, &collection)) + { + fprintf(stderr, "%s: could not validate dependency tree\n", argv0); + return EXIT_FAILURE; + } + /* --list --state is not allowed */ if (listing && listing_stat) generic_usage(self_applet, EXIT_FAILURE); diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index bc8b657..18bf8eb 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -229,6 +229,12 @@ ifupdown_main(int argc, char *argv[]) return EXIT_FAILURE; } + if (!lif_lifecycle_count_rdepends(&exec_opts, &collection)) + { + fprintf(stderr, "%s: could not validate dependency tree\n", argv0); + return EXIT_FAILURE; + } + if (!lif_state_sync(&state, &collection)) { fprintf(stderr, "%s: could not sync state\n", argv0); diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 5d50248..75f5743 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -389,3 +389,58 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa return true; } + +static bool +count_interface_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection, struct lif_interface *parent, size_t depth) +{ + /* query our dependents if we don't have them already */ + if (!lif_lifecycle_query_dependents(opts, parent, parent->ifname)) + return false; + + /* set rdepends_count to depth, dependents will be depth + 1 */ + parent->rdepends_count = depth; + + struct lif_dict_entry *requires = lif_dict_find(&parent->vars, "requires"); + + /* no dependents, nothing to worry about */ + if (requires == NULL) + return true; + + /* walk any dependents */ + char require_ifs[4096] = {}; + strlcpy(require_ifs, requires->data, sizeof require_ifs); + char *bufp = require_ifs; + + for (char *tokenp = lif_next_token(&bufp); *tokenp; tokenp = lif_next_token(&bufp)) + { + struct lif_interface *iface = lif_interface_collection_find(collection, tokenp); + + if (!count_interface_rdepends(opts, collection, iface, depth + 1)) + return false; + } + + return true; +} + +bool +lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection) +{ + struct lif_node *iter; + + LIF_DICT_FOREACH(iter, collection) + { + struct lif_dict_entry *entry = iter->data; + struct lif_interface *iface = entry->data; + + /* start depth at interface's rdepends_count, which will be 0 for the root, + * but will be more if additional rdepends are found... + */ + if (!count_interface_rdepends(opts, collection, iface, iface->rdepends_count)) + { + fprintf(stderr, "ifupdown: dependency graph is broken for interface %s\n", iface->ifname); + return false; + } + } + + return true; +} diff --git a/libifupdown/lifecycle.h b/libifupdown/lifecycle.h index aebbf6e..1dcf2e9 100644 --- a/libifupdown/lifecycle.h +++ b/libifupdown/lifecycle.h @@ -22,6 +22,7 @@ extern bool lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname); extern bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up); extern bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up); +extern bool lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection); #endif From 8c8727e30f8386b41bb5d380d819509d128c28cd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 17:40:57 -0600 Subject: [PATCH 271/530] lifecycle: drop redundant lif_lifecycle_query_dependents(). since we now precompile the full dependency tree, including depths, we no longer need to re-query each leaf for dependency information. --- libifupdown/lifecycle.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 75f5743..7f0b032 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -339,9 +339,6 @@ lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *ifa if (lifname == NULL) lifname = iface->ifname; - if (!lif_lifecycle_query_dependents(opts, iface, lifname)) - return false; - if (up) { /* when going up, dependents go up first. */ From 258e2e8a526c7d1ef3d42ba4c4a426e6d5433665 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 18:11:10 -0600 Subject: [PATCH 272/530] lifecycle: return the maximum tree depth for the dependency tree when counting depth --- cmd/ifquery.c | 2 +- cmd/ifupdown.c | 2 +- libifupdown/lifecycle.c | 18 +++++++++++++++--- libifupdown/lifecycle.h | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 855cbb0..fb91883 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -290,7 +290,7 @@ ifquery_main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!lif_lifecycle_count_rdepends(&exec_opts, &collection)) + if (lif_lifecycle_count_rdepends(&exec_opts, &collection) == -1) { fprintf(stderr, "%s: could not validate dependency tree\n", argv0); return EXIT_FAILURE; diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 18bf8eb..0b09d67 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -229,7 +229,7 @@ ifupdown_main(int argc, char *argv[]) return EXIT_FAILURE; } - if (!lif_lifecycle_count_rdepends(&exec_opts, &collection)) + if (lif_lifecycle_count_rdepends(&exec_opts, &collection) == -1) { fprintf(stderr, "%s: could not validate dependency tree\n", argv0); return EXIT_FAILURE; diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 7f0b032..87e0d0a 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -419,7 +419,7 @@ count_interface_rdepends(const struct lif_execute_opts *opts, struct lif_dict *c return true; } -bool +ssize_t lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection) { struct lif_node *iter; @@ -435,9 +435,21 @@ lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dic if (!count_interface_rdepends(opts, collection, iface, iface->rdepends_count)) { fprintf(stderr, "ifupdown: dependency graph is broken for interface %s\n", iface->ifname); - return false; + return -1; } } - return true; + /* figure out the max depth */ + size_t maxdepth = 0; + + LIF_DICT_FOREACH(iter, collection) + { + struct lif_dict_entry *entry = iter->data; + struct lif_interface *iface = entry->data; + + if (iface->rdepends_count > maxdepth) + maxdepth = iface->rdepends_count; + } + + return maxdepth; } diff --git a/libifupdown/lifecycle.h b/libifupdown/lifecycle.h index 1dcf2e9..fecf9fe 100644 --- a/libifupdown/lifecycle.h +++ b/libifupdown/lifecycle.h @@ -22,7 +22,7 @@ extern bool lif_lifecycle_query_dependents(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *lifname); extern bool lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interface *iface, const char *phase, const char *lifname, bool up); extern bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up); -extern bool lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection); +extern ssize_t lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dict *collection); #endif From a6e022ad99a9a1e5d4c31bc859803b37e98cb277 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 19:21:41 -0600 Subject: [PATCH 273/530] lifecycle: re-sort the interface collection by hand --- libifupdown/lifecycle.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 87e0d0a..9004e3f 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -451,5 +451,37 @@ lif_lifecycle_count_rdepends(const struct lif_execute_opts *opts, struct lif_dic maxdepth = iface->rdepends_count; } + /* move the collection to a temporary list so we can reorder it */ + struct lif_list temp_list = {}; + struct lif_node *iter_next; + + LIF_LIST_FOREACH_SAFE(iter, iter_next, collection->list.head) + { + void *data = iter->data; + + lif_node_delete(iter, &collection->list); + memset(iter, 0, sizeof *iter); + + lif_node_insert(iter, data, &temp_list); + } + + /* walk backwards from maxdepth to 0, readding nodes */ + for (ssize_t curdepth = maxdepth; curdepth > -1; curdepth--) + { + LIF_LIST_FOREACH_SAFE(iter, iter_next, temp_list.head) + { + struct lif_dict_entry *entry = iter->data; + struct lif_interface *iface = entry->data; + + if ((ssize_t) iface->rdepends_count != curdepth) + continue; + + lif_node_delete(iter, &temp_list); + memset(iter, 0, sizeof *iter); + + lif_node_insert(iter, entry, &collection->list); + } + } + return maxdepth; } From ceb82f4fd209a14d6a442a485e6bd390db8f3312 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 19:38:29 -0600 Subject: [PATCH 274/530] ifupdown: only display skip messages in verbose mode --- cmd/ifupdown.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 0b09d67..ad20df4 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -101,15 +101,17 @@ skip_interface(struct lif_interface *iface, const char *ifname) if (up && iface->refcount > 0) { - fprintf(stderr, "%s: skipping %s (already configured), use --force to force configuration\n", - argv0, ifname); + if (exec_opts.verbose) + fprintf(stderr, "%s: skipping auto interface %s (already configured), use --force to force configuration\n", + argv0, ifname); return true; } if (!up && iface->refcount == 0) { - fprintf(stderr, "%s: skipping %s (already deconfigured), use --force to force deconfiguration\n", - argv0, ifname); + if (exec_opts.verbose) + fprintf(stderr, "%s: skipping auto interface %s (already deconfigured), use --force to force deconfiguration\n", + argv0, ifname); return true; } From e754e836afc03be71bc9826562c04e9d87fecd86 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 9 Sep 2020 20:46:50 -0600 Subject: [PATCH 275/530] tests: add tests for auto interface skipping --- tests/fixtures/teardown-dep-ordering.ifstate | 3 +++ tests/fixtures/teardown-dep-ordering.interfaces | 13 +++++++++++++ tests/ifdown_test | 9 +++++++++ tests/ifup_test | 10 +++++++++- 4 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 tests/fixtures/teardown-dep-ordering.ifstate create mode 100644 tests/fixtures/teardown-dep-ordering.interfaces diff --git a/tests/fixtures/teardown-dep-ordering.ifstate b/tests/fixtures/teardown-dep-ordering.ifstate new file mode 100644 index 0000000..aef421a --- /dev/null +++ b/tests/fixtures/teardown-dep-ordering.ifstate @@ -0,0 +1,3 @@ +dummy=dummy 2 +bat=bat 2 +br=br 1 diff --git a/tests/fixtures/teardown-dep-ordering.interfaces b/tests/fixtures/teardown-dep-ordering.interfaces new file mode 100644 index 0000000..551ad3d --- /dev/null +++ b/tests/fixtures/teardown-dep-ordering.interfaces @@ -0,0 +1,13 @@ +auto dummy +iface dummy + link-type dummy + +auto bat +iface bat + link-type dummy + requires dummy + +auto br +iface br + link-type dummy + requires bat diff --git a/tests/ifdown_test b/tests/ifdown_test index 2ca83c3..5aafc86 100755 --- a/tests/ifdown_test +++ b/tests/ifdown_test @@ -22,6 +22,7 @@ tests_init \ deferred_teardown_1 \ deferred_teardown_2 \ deferred_teardown_3 \ + teardown_dep_ordering \ regress_opt_f noargs_body() { @@ -172,6 +173,14 @@ deferred_teardown_3_body() { -i $FIXTURES/deferred-teardown-2.interfaces tun0 tun1 tun2 tun3 } +teardown_dep_ordering_body() { + atf_check -s exit:0 -o ignore \ + -e match:"skipping auto interface bat" \ + -e match:"skipping auto interface dummy" \ + ifdown -n -i $FIXTURES/teardown-dep-ordering.interfaces \ + -S $FIXTURES/teardown-dep-ordering.ifstate -E $EXECUTORS -a +} + regress_opt_f_body() { atf_check -s exit:0 -o ignore -e ignore \ ifdown -n -S $FIXTURES/vlan.ifstate -E $EXECUTORS -i $FIXTURES/vlan.interfaces -f eth0.8 diff --git a/tests/ifup_test b/tests/ifup_test index 594ab11..a5ef49b 100755 --- a/tests/ifup_test +++ b/tests/ifup_test @@ -18,7 +18,8 @@ tests_init \ learned_dependency \ learned_dependency_2 \ learned_executor \ - implicit_vlan + implicit_vlan \ + teardown_dep_ordering noargs_body() { atf_check -s exit:1 -e ignore ifup -S/dev/null @@ -131,3 +132,10 @@ implicit_vlan_body() { -e match:"attempting to run link executor" \ ifup -n -S/dev/null -E $EXECUTORS -i $FIXTURES/vlan.interfaces eth0.8 } + +teardown_dep_ordering_body() { + atf_check -s exit:0 -o ignore \ + -e match:"skipping auto interface bat" \ + -e match:"skipping auto interface dummy" \ + ifup -n -i $FIXTURES/teardown-dep-ordering.interfaces -E $EXECUTORS -a +} From a7e27ffa2ceff4d26d74b968f0596e9c1d5d1953 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 11 Sep 2020 02:31:22 -0600 Subject: [PATCH 276/530] dhcp: support IF_HOSTNAME, IF_SCRIPT and IF_CLIENT for udhcpc --- executor-scripts/linux/dhcp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/dhcp b/executor-scripts/linux/dhcp index 783f6e1..0a2b04c 100755 --- a/executor-scripts/linux/dhcp +++ b/executor-scripts/linux/dhcp @@ -24,8 +24,11 @@ start() { ${MOCK} /usr/sbin/dhclient -pf /var/run/dhclient.$IFACE.pid $IFACE ;; udhcpc) - UDHCPC_OPTS=$(eval echo $IF_UDHCPC_OPTS) - ${MOCK} /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE $UDHCPC_OPTS + optargs=$(eval echo $IF_UDHCPC_OPTS) + [ -n "$IF_HOSTNAME" ] && optargs="$optargs -x hostname:$IF_HOSTNAME" + [ -n "$IF_CLIENT" ] && optargs="$optargs -c $IF_CLIENT" + [ -n "$IF_SCRIPT" ] && optargs="$optargs -s $IF_SCRIPT" + ${MOCK} /sbin/udhcpc -b -R -p /var/run/udhcpc.$IFACE.pid -i $IFACE $optargs ;; *) ;; From 5d4e3699b29b1ce9d83626ebb5723587a32d523f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 11 Sep 2020 02:33:54 -0600 Subject: [PATCH 277/530] dhcp: evaluate IF_HOSTNAME for shell fragments --- executor-scripts/linux/dhcp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/executor-scripts/linux/dhcp b/executor-scripts/linux/dhcp index 0a2b04c..82ae793 100755 --- a/executor-scripts/linux/dhcp +++ b/executor-scripts/linux/dhcp @@ -2,6 +2,9 @@ set -e +# some users provide a shell fragment for the hostname property. +[ -n "$IF_HOSTNAME" ] && IF_HOSTNAME=$(eval echo $IF_HOSTNAME) + determine_implementation() { [ -n "$IF_DHCP_PROGRAM" ] && echo "$IF_DHCP_PROGRAM" && return [ -x /sbin/dhcpcd ] && echo "dhcpcd" && return From b4b0889c7a3f1b03661c4edc73fa71b9ba1b0e25 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 11 Sep 2020 02:43:32 -0600 Subject: [PATCH 278/530] tests: add test for hostname subshell --- tests/linux/dhcp_test | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/linux/dhcp_test b/tests/linux/dhcp_test index c451e74..57d988f 100755 --- a/tests/linux/dhcp_test +++ b/tests/linux/dhcp_test @@ -8,7 +8,8 @@ tests_init udhcpc_up \ dhcpcd_down \ dhclient_up \ udhcpc_opts_up \ - udhcpc_opts_up_subshell + udhcpc_opts_up_subshell \ + hostname_subshell udhcpc_up_body() { export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc @@ -45,3 +46,9 @@ udhcpc_opts_up_subshell_body() { atf_check -s exit:0 -o match:'/sbin/udhcpc -b -R -p /var/run/udhcpc.eth0.pid -i eth0 -O search -x hostname:test' \ ${EXECUTOR} } + +hostname_subshell_body() { + export IFACE=eth0 PHASE=up MOCK=echo IF_DHCP_PROGRAM=udhcpc IF_HOSTNAME="\$(echo test)" + atf_check -s exit:0 -o match:'/sbin/udhcpc -b -R -p /var/run/udhcpc.eth0.pid -i eth0 -x hostname:test' \ + ${EXECUTOR} +} From f9d0fbb4c3c1f3e02052e80d4f0b6ff149890e96 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 11 Sep 2020 02:46:28 -0600 Subject: [PATCH 279/530] ifupdown-ng 0.9.0. --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 538f1da..048c960 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ LIBBSD_CFLAGS = LIBBSD_LIBS = PACKAGE_NAME := ifupdown-ng -PACKAGE_VERSION := 0.8.1 +PACKAGE_VERSION := 0.9.0 PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new From 537a56414aa28446440cba4c2f5206be0088faa7 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 16:50:31 -0600 Subject: [PATCH 280/530] tokenize: consider = to be equivalent to whitespace --- libifupdown/tokenize.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index 751c2f2..288f9a1 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -23,11 +23,11 @@ lif_next_token(char **buf) { char *out = *buf; - while (*out && isspace(*out)) + while (*out && (isspace(*out) || *out == '=')) out++; char *end = out; - while (*end && !isspace(*end)) + while (*end && !isspace(*end) && *out != '=') end++; *end++ = '\0'; From fafa5ed7f979cdf15f05e4f2edf39eb58bb7a863 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:01:42 -0600 Subject: [PATCH 281/530] libifupdown: add abstract config parser implementation --- Makefile | 3 +- libifupdown/config-parser.c | 84 +++++++++++++++++++++++++++++++++++++ libifupdown/config-parser.h | 32 ++++++++++++++ 3 files changed, 118 insertions(+), 1 deletion(-) create mode 100644 libifupdown/config-parser.c create mode 100644 libifupdown/config-parser.h diff --git a/Makefile b/Makefile index 048c960..6d51562 100644 --- a/Makefile +++ b/Makefile @@ -34,7 +34,8 @@ LIBIFUPDOWN_SRC = \ libifupdown/state.c \ libifupdown/environment.c \ libifupdown/execute.c \ - libifupdown/lifecycle.c + libifupdown/lifecycle.c \ + libifupdown/config-parser.c LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o} LIBIFUPDOWN_LIB = libifupdown.a diff --git a/libifupdown/config-parser.c b/libifupdown/config-parser.c new file mode 100644 index 0000000..0e16b70 --- /dev/null +++ b/libifupdown/config-parser.c @@ -0,0 +1,84 @@ +/* + * libifupdown/config-parser.c + * Purpose: config parsing + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include +#include +#include +#include +#include +#include "libifupdown/config-parser.h" +#include "libifupdown/fgetline.h" +#include "libifupdown/tokenize.h" + +static int +handler_cmp(const void *a, const void *b) +{ + const char *key = a; + const struct lif_config_handler *hdl = b; + + return strcmp(key, hdl->key); +} + +bool +lif_config_parse_file(FILE *fd, const char *filename, struct lif_config_handler *handlers, size_t handler_count) +{ + char linebuf[4096]; + size_t lineno = 0; + + while (lif_fgetline(linebuf, sizeof linebuf, fd)) + { + char *bufp = linebuf; + char *key = lif_next_token(&bufp); + char *value = lif_next_token(&bufp); + + lineno++; + + if (!*key || !*value) + continue; + + struct lif_config_handler *hdl = bsearch(key, handlers, handler_count, sizeof(*handlers), + handler_cmp); + + if (hdl == NULL) + { + fprintf(stderr, "ifupdown-ng: %s:%zu: warning: unknown config setting %s\n", + filename, lineno, key); + continue; + } + + if (!hdl->handle(key, value, hdl->opaque)) + { + fclose(fd); + return false; + } + } + + fclose(fd); + return true; +} + +bool +lif_config_parse(const char *filename, struct lif_config_handler *handlers, size_t handler_count) +{ + FILE *f = fopen(filename, "r"); + + if (f == NULL) + { + fprintf(stderr, "ifupdown-ng: unable to parse %s: %s\n", filename, strerror(errno)); + return false; + } + + return lif_config_parse_file(f, filename, handlers, handler_count); +} diff --git a/libifupdown/config-parser.h b/libifupdown/config-parser.h new file mode 100644 index 0000000..86c1762 --- /dev/null +++ b/libifupdown/config-parser.h @@ -0,0 +1,32 @@ +/* + * libifupdown/config-parser.h + * Purpose: config parsing + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#ifndef LIBIFUPDOWN__CONFIG_PARSER_H +#define LIBIFUPDOWN__CONFIG_PARSER_H + +#include +#include +#include + +struct lif_config_handler { + const char *key; + bool (*handle)(const char *key, const char *value, void *opaque); + void *opaque; +}; + +extern bool lif_config_parse_file(FILE *f, const char *filename, struct lif_config_handler *handlers, size_t handler_count); +extern bool lif_config_parse(const char *filename, struct lif_config_handler *handlers, size_t handler_count); + +#endif From 02d044c391d6e3c257f4658464f63723b9c28fdb Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:15:18 -0600 Subject: [PATCH 282/530] libifupdown: add config file loader --- Makefile | 3 +- libifupdown/config-file.c | 61 +++++++++++++++++++++++++++++++++++++++ libifupdown/config-file.h | 29 +++++++++++++++++++ libifupdown/libifupdown.h | 2 ++ 4 files changed, 94 insertions(+), 1 deletion(-) create mode 100644 libifupdown/config-file.c create mode 100644 libifupdown/config-file.h diff --git a/Makefile b/Makefile index 6d51562..a6fa3ff 100644 --- a/Makefile +++ b/Makefile @@ -35,7 +35,8 @@ LIBIFUPDOWN_SRC = \ libifupdown/environment.c \ libifupdown/execute.c \ libifupdown/lifecycle.c \ - libifupdown/config-parser.c + libifupdown/config-parser.c \ + libifupdown/config-file.c LIBIFUPDOWN_OBJ = ${LIBIFUPDOWN_SRC:.c=.o} LIBIFUPDOWN_LIB = libifupdown.a diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c new file mode 100644 index 0000000..7f2b299 --- /dev/null +++ b/libifupdown/config-file.c @@ -0,0 +1,61 @@ +/* + * libifupdown/config-file.c + * Purpose: config file loading + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#include +#include +#include +#include "libifupdown/libifupdown.h" + +struct lif_config_file lif_config = { + .allow_addon_scripts = true, +}; + +static bool +set_bool_value(const char *key, const char *value, void *opaque) +{ + (void) key; + + if (*value == '1' || + *value == 'Y' || *value == 'y' || + *value == 'T' || *value == 't') + *(bool *) opaque = true; + else if (*value == '0' || + *value == 'N' || *value == 'n' || + *value == 'F' || *value == 'f') + *(bool *) opaque = false; + else + return false; + + return true; +} + +static struct lif_config_handler handlers[] = { + {"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts}, +}; + +bool +lif_config_load(const char *filename) +{ + FILE *fd = fopen(filename, "r"); + + if (fd == NULL) + { + fprintf(stderr, "ifupdown-ng: cannot open config %s: %s\n", + filename, strerror(errno)); + return false; + } + + return lif_config_parse_file(fd, filename, handlers, ARRAY_SIZE(handlers)); +} diff --git a/libifupdown/config-file.h b/libifupdown/config-file.h new file mode 100644 index 0000000..a528636 --- /dev/null +++ b/libifupdown/config-file.h @@ -0,0 +1,29 @@ +/* + * libifupdown/config-file.h + * Purpose: config file loading + * + * Copyright (c) 2020 Ariadne Conill + * + * Permission to use, copy, modify, and/or distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * This software is provided 'as is' and without any warranty, express or + * implied. In no event shall the authors be liable for any damages arising + * from the use of this software. + */ + +#ifndef LIBIFUPDOWN__CONFIG_FILE_H +#define LIBIFUPDOWN__CONFIG_FILE_H + +#include + +struct lif_config_file { + bool allow_addon_scripts; +}; + +extern struct lif_config_file lif_config; + +extern bool lif_config_load(const char *filename); + +#endif diff --git a/libifupdown/libifupdown.h b/libifupdown/libifupdown.h index 33da802..6459c6a 100644 --- a/libifupdown/libifupdown.h +++ b/libifupdown/libifupdown.h @@ -27,6 +27,8 @@ #include "libifupdown/execute.h" #include "libifupdown/lifecycle.h" #include "libifupdown/tokenize.h" +#include "libifupdown/config-file.h" +#include "libifupdown/config-parser.h" #ifndef ARRAY_SIZE # define ARRAY_SIZE(x) (sizeof(x) / sizeof(*x)) From 5b27d8408c4bcdf31b5c0356097fc9ca66cf1c9d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:17:03 -0600 Subject: [PATCH 283/530] config file: don't print warning if config file cannot be opened --- dist/ifupdown-ng.conf.example | 10 ++++++++++ libifupdown/config-file.c | 2 ++ 2 files changed, 12 insertions(+) create mode 100644 dist/ifupdown-ng.conf.example diff --git a/dist/ifupdown-ng.conf.example b/dist/ifupdown-ng.conf.example new file mode 100644 index 0000000..1e5443c --- /dev/null +++ b/dist/ifupdown-ng.conf.example @@ -0,0 +1,10 @@ +# This is an example configuration file for ifupdown-ng, which allows +# the system administrator to configure the behaviour of ifupdown-ng. +# +# The settings specified here are the defaults of ifupdown-ng. + +# allow_addon_scripts: +# Enable support for /etc/if-X.d addon scripts. These are used for +# compatibility with legacy setups, and may be disabled for performance +# improvements in setups where only ifupdown-ng executors are used. +allow_addon_scripts = 1 diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index 7f2b299..1844875 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -52,8 +52,10 @@ lif_config_load(const char *filename) if (fd == NULL) { +#if 0 fprintf(stderr, "ifupdown-ng: cannot open config %s: %s\n", filename, strerror(errno)); +#endif return false; } From b4e35c442e26e85c4ba9b7c73c833923291b2aed Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:18:45 -0600 Subject: [PATCH 284/530] multicall: load config file data as early as possible --- Makefile | 3 +++ cmd/multicall.c | 2 ++ 2 files changed, 5 insertions(+) diff --git a/Makefile b/Makefile index a6fa3ff..4c57959 100644 --- a/Makefile +++ b/Makefile @@ -10,6 +10,7 @@ PACKAGE_BUGREPORT := https://github.com/ifupdown-ng/ifupdown-ng/issues/new INTERFACES_FILE := /etc/network/interfaces STATE_FILE := /run/ifstate +CONFIG_FILE := /etc/network/ifupdown-ng.conf EXECUTOR_PATH := /usr/libexec/ifupdown-ng CFLAGS ?= -ggdb3 -Os @@ -18,6 +19,7 @@ CFLAGS += ${LIBBSD_CFLAGS} CPPFLAGS = -I. CPPFLAGS += -DINTERFACES_FILE=\"${INTERFACES_FILE}\" CPPFLAGS += -DSTATE_FILE=\"${STATE_FILE}\" +CPPFLAGS += -DCONFIG_FILE=\"${CONFIG_FILE}\" CPPFLAGS += -DPACKAGE_NAME=\"${PACKAGE_NAME}\" CPPFLAGS += -DPACKAGE_VERSION=\"${PACKAGE_VERSION}\" CPPFLAGS += -DPACKAGE_BUGREPORT=\"${PACKAGE_BUGREPORT}\" @@ -127,6 +129,7 @@ install: all for i in ${EXECUTOR_SCRIPTS_STUB}; do \ install -D -m755 executor-scripts/stub/$$i ${DESTDIR}${EXECUTOR_PATH}/$$i; \ done + install -D -m644 dist/ifupdown-ng.conf.example ${DESTDIR}${CONFIG_FILE}.example .scd.1 .scd.2 .scd.3 .scd.4 .scd.5 .scd.6 .scd.7 .scd.8: ${SCDOC} < $< > $@ diff --git a/cmd/multicall.c b/cmd/multicall.c index 0c041ad..705000f 100644 --- a/cmd/multicall.c +++ b/cmd/multicall.c @@ -72,6 +72,8 @@ main(int argc, char *argv[]) argv0 = basename(argv[0]); const struct if_applet **app; + lif_config_load(CONFIG_FILE); + app = bsearch(argv0, applet_table, ARRAY_SIZE(applet_table), sizeof(*applet_table), applet_cmp); From c1c9115e5dff7d031ba713da17e51b5557f47b67 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:24:44 -0600 Subject: [PATCH 285/530] tokenize: fix tokenization of equals --- libifupdown/tokenize.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index 288f9a1..fc7e61f 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -27,7 +27,7 @@ lif_next_token(char **buf) out++; char *end = out; - while (*end && !isspace(*end) && *out != '=') + while (*end && !isspace(*end) && *end != '=') end++; *end++ = '\0'; From 4b30dc457304ab5bcb1cad604551d103c7a04cdf Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:26:45 -0600 Subject: [PATCH 286/530] lifecycle: if lif_config.allow_addon_scripts is disabled, don't run addon scripts --- libifupdown/lifecycle.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 9004e3f..d8ab8c5 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -25,6 +25,7 @@ #include "libifupdown/lifecycle.h" #include "libifupdown/state.h" #include "libifupdown/tokenize.h" +#include "libifupdown/config-file.h" static bool handle_commands_for_phase(const struct lif_execute_opts *opts, char *const envp[], const struct lif_interface *iface, const char *phase) @@ -240,6 +241,10 @@ lif_lifecycle_run_phase(const struct lif_execute_opts *opts, struct lif_interfac if (!handle_commands_for_phase(opts, envp, iface, phase)) goto handle_error; + /* if we don't need to support /etc/if-X.d we're done here */ + if (!lif_config.allow_addon_scripts) + goto out_free; + /* Check if scripts dir for this phase is present and bail out if it isn't */ struct stat dir_stat; char dir_path[4096]; From 27a383cfa7aa88b29604ca4c86faf6d99b858039 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 14 Sep 2020 17:34:44 -0600 Subject: [PATCH 287/530] tokenizer: split out equals-as-delimiter tokenizer to its own function --- libifupdown/config-parser.c | 4 ++-- libifupdown/tokenize.h | 20 +++++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/libifupdown/config-parser.c b/libifupdown/config-parser.c index 0e16b70..f533cfb 100644 --- a/libifupdown/config-parser.c +++ b/libifupdown/config-parser.c @@ -40,8 +40,8 @@ lif_config_parse_file(FILE *fd, const char *filename, struct lif_config_handler while (lif_fgetline(linebuf, sizeof linebuf, fd)) { char *bufp = linebuf; - char *key = lif_next_token(&bufp); - char *value = lif_next_token(&bufp); + char *key = lif_next_token_eq(&bufp); + char *value = lif_next_token_eq(&bufp); lineno++; diff --git a/libifupdown/tokenize.h b/libifupdown/tokenize.h index fc7e61f..f0aed3d 100644 --- a/libifupdown/tokenize.h +++ b/libifupdown/tokenize.h @@ -19,7 +19,7 @@ #include static inline char * -lif_next_token(char **buf) +lif_next_token_eq(char **buf) { char *out = *buf; @@ -36,4 +36,22 @@ lif_next_token(char **buf) return out; } +static inline char * +lif_next_token(char **buf) +{ + char *out = *buf; + + while (*out && isspace(*out)) + out++; + + char *end = out; + while (*end && !isspace(*end)) + end++; + + *end++ = '\0'; + *buf = end; + + return out; +} + #endif From d814aa754f6771e479632c0fcf4aadcd2b2e0f0c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Tue, 15 Sep 2020 05:48:54 -0600 Subject: [PATCH 288/530] config parser: explicitly skip over comments --- libifupdown/config-parser.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libifupdown/config-parser.c b/libifupdown/config-parser.c index f533cfb..45005c6 100644 --- a/libifupdown/config-parser.c +++ b/libifupdown/config-parser.c @@ -48,6 +48,9 @@ lif_config_parse_file(FILE *fd, const char *filename, struct lif_config_handler if (!*key || !*value) continue; + if (*key == '#') + continue; + struct lif_config_handler *hdl = bsearch(key, handlers, handler_count, sizeof(*handlers), handler_cmp); From f35242e5c7c00188158eb595b7fd954ca74270dd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Sep 2020 09:14:06 -0600 Subject: [PATCH 289/530] admin guide: s/multi-homing/multiple addresses/ --- doc/ADMIN-GUIDE.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/ADMIN-GUIDE.md b/doc/ADMIN-GUIDE.md index 13504ba..6885367 100644 --- a/doc/ADMIN-GUIDE.md +++ b/doc/ADMIN-GUIDE.md @@ -98,11 +98,11 @@ iface eth0 gateway 203.0.113.1 ``` -### Multi-homing +### Multiple Addresses -A typical scenario on servers is multi-homing, where a server -has multiple IP addresses on a single interface. In this case -you simply add additional `address` lines like this: +A typical scenario on servers is where a server has multiple +IP addresses on a single interface. In this case you simply +add additional `address` lines like this: ``` auto eth0 From 27e11adac63fad85284ca096f596583bcbee8be1 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Sep 2020 07:58:51 -0600 Subject: [PATCH 290/530] interface-file: remap properties used by both debian and ifupdown2 ethtool addons to the ethtool- namespace --- libifupdown/interface-file.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 7589841..0828826 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -27,13 +27,38 @@ struct remap_token { /* this list must be in alphabetical order for bsearch */ static const struct remap_token tokens[] = { + {"driver-message-level", "ethtool-msglvl"}, /* Debian ethtool integration */ {"endpoint", "tunnel-remote"}, /* legacy ifupdown */ + {"ethernet-autoneg", "ethtool-ethernet-autoneg"}, /* Debian ethtool integration */ + {"ethernet-pause-autoneg", "ethtool-pause-autoneg"}, /* Debian ethtool integration */ + {"ethernet-pause-rx", "ethtool-pause-rx"}, /* Debian ethtool integration */ + {"ethernet-pause-tx", "ethtool-pause-tx"}, /* Debian ethtool integration */ + {"ethernet-port", "ethtool-ethernet-port"}, /* Debian ethtool integration */ + {"ethernet-wol", "ethtool-ethernet-wol"}, /* Debian ethtool integration */ + {"gro-offload", "ethtool-offload-gro"}, /* ifupdown2 */ + {"gso-offload", "ethtool-offload-gso"}, /* ifupdown2 */ + {"link-duplex", "ethtool-link-duplex"}, /* Debian ethtool integration */ + {"link-fec", "ethtool-link-fec"}, /* ifupdown2 */ + {"link-speed", "ethtool-link-speed"}, /* Debian ethtool integration */ {"local", "tunnel-local"}, /* legacy ifupdown */ + {"lro-offload", "ethtool-offload-lro"}, /* ifupdown2 */ {"mode", "tunnel-mode"}, /* legacy ifupdown */ + {"offload-gro", "ethtool-offload-gro"}, /* Debian ethtool integration */ + {"offload-gso", "ethtool-offload-gso"}, /* Debian ethtool integration */ + {"offload-lro", "ethtool-offload-lro"}, /* Debian ethtool integration */ + {"offload-rx", "ethtool-offload-rx"}, /* Debian ethtool integration */ + {"offload-sg", "ethtool-offload-sg"}, /* Debian ethtool integration */ + {"offload-tso", "ethtool-offload-tso"}, /* Debian ethtool integration */ + {"offload-tx", "ethtool-offload-tx"}, /* Debian ethtool integration */ + {"offload-ufo", "ethtool-offload-ufo"}, /* Debian ethtool integration */ {"provider", "ppp-provider"}, /* legacy ifupdown, ifupdown2 */ + {"rx-offload", "ethtool-offload-rx"}, /* ifupdown2 */ + {"tso-offload", "ethtool-offload-tso"}, /* ifupdown2 */ {"ttl", "tunnel-ttl"}, /* legacy ifupdown */ {"tunnel-endpoint", "tunnel-remote"}, /* ifupdown2 */ {"tunnel-physdev", "tunnel-dev"}, /* ifupdown2 */ + {"tx-offload", "ethtool-offload-tx"}, /* ifupdown2 */ + {"ufo-offload", "ethtool-offload-ufo"}, /* ifupdown2 */ {"vrf", "vrf-member"}, /* ifupdown2 */ }; From a8fcf5502f453a910f5de895e6a0ddb024f1c348 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Sat, 19 Sep 2020 08:07:32 -0600 Subject: [PATCH 291/530] add a missing translation --- libifupdown/interface-file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 0828826..5441abd 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -37,6 +37,7 @@ static const struct remap_token tokens[] = { {"ethernet-wol", "ethtool-ethernet-wol"}, /* Debian ethtool integration */ {"gro-offload", "ethtool-offload-gro"}, /* ifupdown2 */ {"gso-offload", "ethtool-offload-gso"}, /* ifupdown2 */ + {"link-autoneg", "ethtool-ethernet-autoneg"}, /* ifupdown2 */ {"link-duplex", "ethtool-link-duplex"}, /* Debian ethtool integration */ {"link-fec", "ethtool-link-fec"}, /* ifupdown2 */ {"link-speed", "ethtool-link-speed"}, /* Debian ethtool integration */ From 63ec8d4b3b4786ca21863c63725539bc2d905575 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:04:10 -0600 Subject: [PATCH 292/530] begin ethtool executor-script (as part of EXECUTOR_SCRIPTS_OPT). --- Makefile | 3 ++- executor-scripts/linux/ethtool | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) create mode 100755 executor-scripts/linux/ethtool diff --git a/Makefile b/Makefile index 4c57959..cb4fa94 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,8 @@ EXECUTOR_SCRIPTS_OPT ?= \ vrf \ tunnel \ gre \ - wireguard + wireguard \ + ethtool EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool new file mode 100755 index 0000000..d37118b --- /dev/null +++ b/executor-scripts/linux/ethtool @@ -0,0 +1,2 @@ +#!/bin/sh +set -e From eac42c104bf8350a48040d5f8ce17be8648ba7bd Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:05:18 -0600 Subject: [PATCH 293/530] build: add batman executor to EXECUTOR_SCRIPTS_OPT --- Makefile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4c57959..0ef3ab1 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,8 @@ EXECUTOR_SCRIPTS_OPT ?= \ vrf \ tunnel \ gre \ - wireguard + wireguard \ + batman EXECUTOR_SCRIPTS ?= ${EXECUTOR_SCRIPTS_CORE} ${EXECUTOR_SCRIPTS_OPT} From b0480a3343a72be08639491df89c742d8b25b22a Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:20:43 -0600 Subject: [PATCH 294/530] ethtool: add pre-up settings to the executor --- executor-scripts/linux/ethtool | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index d37118b..30b4f5c 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -1,2 +1,13 @@ #!/bin/sh set -e + +case "$PHASE" in +pre-up) + settings= + [ -n "$IF_ETHTOOL_ETHERNET_PORT" ] && settings="port $IF_ETHTOOL_ETHERNET_PORT" + [ -n "$IF_ETHTOOL_MSGLVL" ] && settings="msglvl $IF_ETHTOOL_MSGLVL" + [ -z "$settings" ] || ethtool --change "$IFACE" $settings + ;; +up) + ;; +esac From 72277e51e235fde07273c58bed99f52c6b8ff87f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:31:20 -0600 Subject: [PATCH 295/530] ethtool: add support for basic ethernet link settings --- executor-scripts/linux/ethtool | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 30b4f5c..20ec63f 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -3,11 +3,34 @@ set -e case "$PHASE" in pre-up) - settings= - [ -n "$IF_ETHTOOL_ETHERNET_PORT" ] && settings="port $IF_ETHTOOL_ETHERNET_PORT" - [ -n "$IF_ETHTOOL_MSGLVL" ] && settings="msglvl $IF_ETHTOOL_MSGLVL" - [ -z "$settings" ] || ethtool --change "$IFACE" $settings + settings="\ + ${IF_ETHTOOL_ETHERNET_PORT:+ port $IF_ETHTOOL_ETHERNET_PORT} + ${IF_ETHTOOL_MSGLVL:+ msglvl $IF_ETHTOOL_MSGLVL} + " + [ -z "$settings" ] || $MOCK ethtool --change "$IFACE" $settings ;; up) + # first do the link settings. + link_settings="\ + ${IF_ETHTOOL_LINK_SPEED:+ speed $IF_ETHTOOL_LINK_SPEED} + ${IF_ETHTOOL_LINK_DUPLEX:+ duplex $IF_ETHTOOL_LINK_DUPLEX} + " + + # ethernet-wol can have a second arg (key), split into $1 and $2 + set -- $IF_ETHTOOL_ETHERNET_WOL + link_settings="$link_settings${1:+ wol $1}${2:+ sopass $2}" + + # handle ethtool-ethernet-autoneg like Debian would + case "$IF_ETHTOOL_ETHERNET_AUTONEG" in + on|off) + link_settings="$link_settings autoneg $IF_ETHTOOL_ETHERNET_AUTONEG" + ;; + *) + link_settings="$link_settings autoneg on advertise $IF_ETHTOOL_ETHERNET_AUTONEG" + ;; + esac + + [ -z "$link_settings" ] || $MOCK ethtool --change "$IFACE" $link_settings + ;; esac From e4b4d8b70ab99c3bbd3e3b100f12786cb5588653 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:36:34 -0600 Subject: [PATCH 296/530] ethtool: add pause and offload settings support --- executor-scripts/linux/ethtool | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 20ec63f..4f735b5 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -1,6 +1,20 @@ #!/bin/sh set -e +# gather params for a given prefix, based on executor-scripts/linux/tunnel. +gather_params() { + set | sed -E " + s/^IF_${1}_([A-Z0-9_]+)=(.+)/\1\n\2/ + ta + d + :a + h + y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ + P + g + s/.*\n//" +} + case "$PHASE" in pre-up) settings="\ @@ -32,5 +46,10 @@ up) [ -z "$link_settings" ] || $MOCK ethtool --change "$IFACE" $link_settings + pause_settings=$(gather_params IF_ETHTOOL_ETHERNET_PAUSE) + [ -z "$pause_settings" ] || $MOCK ethtool --pause "$IFACE" $pause_settings + + offload_settings=$(gather_params IF_ETHTOOL_OFFLOAD) + [ -z "$offload_settings" ] || $MOCK ethtool --offload "$IFACE" $offload_settings ;; esac From 0a58383ed8df6aa00c2d6b28302233f0185fdc5b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:55:20 -0600 Subject: [PATCH 297/530] tests: ethtool: add tests for basic link settings, wol and autoneg --- tests/linux/Kyuafile | 1 + tests/linux/ethtool_test | 84 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) create mode 100755 tests/linux/ethtool_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 050c55d..4e1c304 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -11,3 +11,4 @@ atf_test_program{name='ppp_test'} atf_test_program{name='tunnel_test'} atf_test_program{name='gre_test'} atf_test_program{name='wireguard_test'} +atf_test_program{name='ethtool_test'} diff --git a/tests/linux/ethtool_test b/tests/linux/ethtool_test new file mode 100755 index 0000000..584eaad --- /dev/null +++ b/tests/linux/ethtool_test @@ -0,0 +1,84 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/ethtool" + +tests_init \ + pre_up_msglvl \ + pre_up_ethernet_port \ + up_speed \ + up_duplex \ + up_wol \ + up_wol_sopass \ + up_autoneg_simple \ + up_autoneg_mask + +pre_up_msglvl_body() { + export IFACE="eth0" PHASE="pre-up" IF_ETHTOOL_MSGLVL="debug on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'msglvl debug on' \ + ${EXECUTOR} +} + +pre_up_ethernet_port_body() { + export IFACE="eth0" PHASE="pre-up" IF_ETHTOOL_ETHERNET_PORT="4" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'port 4' \ + ${EXECUTOR} +} + +up_speed_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_LINK_SPEED="1000" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'speed 1000' \ + ${EXECUTOR} +} + +up_duplex_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_LINK_DUPLEX="full" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'duplex full' \ + ${EXECUTOR} +} + +up_wol_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_ETHERNET_WOL="g" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'wol g' \ + ${EXECUTOR} +} + +up_wol_sopass_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_ETHERNET_WOL="s abc123" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'wol s sopass abc123' \ + ${EXECUTOR} +} + +up_autoneg_simple_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_ETHERNET_AUTONEG="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'autoneg on' \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_ETHERNET_AUTONEG="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'autoneg off' \ + ${EXECUTOR} +} + +up_autoneg_mask_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_ETHERNET_AUTONEG="1000/full" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --change eth0' \ + -o match:'autoneg on advertise 1000/full' \ + ${EXECUTOR} +} From 4e78d7e5d5d7e8445462c04b0a91f4fa7a9489af Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 08:59:13 -0600 Subject: [PATCH 298/530] ethtool: pause parameters are IF_ETHTOOL_PAUSE_FOO, not IF_ETHTOOL_ETHERNET_PAUSE_FOO. --- executor-scripts/linux/ethtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 4f735b5..562493b 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -46,7 +46,7 @@ up) [ -z "$link_settings" ] || $MOCK ethtool --change "$IFACE" $link_settings - pause_settings=$(gather_params IF_ETHTOOL_ETHERNET_PAUSE) + pause_settings=$(gather_params IF_ETHTOOL_PAUSE) [ -z "$pause_settings" ] || $MOCK ethtool --pause "$IFACE" $pause_settings offload_settings=$(gather_params IF_ETHTOOL_OFFLOAD) From 6ae3414329ff3372ff804cf88d779311c8e03196 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:08:17 -0600 Subject: [PATCH 299/530] ethtool: fix up gather_params() calls a bit --- executor-scripts/linux/ethtool | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 562493b..f3dad2d 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -25,10 +25,7 @@ pre-up) ;; up) # first do the link settings. - link_settings="\ - ${IF_ETHTOOL_LINK_SPEED:+ speed $IF_ETHTOOL_LINK_SPEED} - ${IF_ETHTOOL_LINK_DUPLEX:+ duplex $IF_ETHTOOL_LINK_DUPLEX} - " + link_settings="${IF_ETHTOOL_LINK_SPEED:+ speed $IF_ETHTOOL_LINK_SPEED}${IF_ETHTOOL_LINK_DUPLEX:+ duplex $IF_ETHTOOL_LINK_DUPLEX}" # ethernet-wol can have a second arg (key), split into $1 and $2 set -- $IF_ETHTOOL_ETHERNET_WOL @@ -36,6 +33,8 @@ up) # handle ethtool-ethernet-autoneg like Debian would case "$IF_ETHTOOL_ETHERNET_AUTONEG" in + '') + ;; on|off) link_settings="$link_settings autoneg $IF_ETHTOOL_ETHERNET_AUTONEG" ;; @@ -46,10 +45,10 @@ up) [ -z "$link_settings" ] || $MOCK ethtool --change "$IFACE" $link_settings - pause_settings=$(gather_params IF_ETHTOOL_PAUSE) + pause_settings=$(gather_params ETHTOOL_PAUSE) [ -z "$pause_settings" ] || $MOCK ethtool --pause "$IFACE" $pause_settings - offload_settings=$(gather_params IF_ETHTOOL_OFFLOAD) + offload_settings=$(gather_params ETHTOOL_OFFLOAD) [ -z "$offload_settings" ] || $MOCK ethtool --offload "$IFACE" $offload_settings ;; esac From e8a2aab7e173c760e945a9f77417ad998c6b8730 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:10:01 -0600 Subject: [PATCH 300/530] tests: ethtool: add tests for pause parameters --- tests/linux/ethtool_test | 47 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/tests/linux/ethtool_test b/tests/linux/ethtool_test index 584eaad..4486923 100755 --- a/tests/linux/ethtool_test +++ b/tests/linux/ethtool_test @@ -11,7 +11,10 @@ tests_init \ up_wol \ up_wol_sopass \ up_autoneg_simple \ - up_autoneg_mask + up_autoneg_mask \ + up_pause_autoneg \ + up_pause_tx \ + up_pause_rx pre_up_msglvl_body() { export IFACE="eth0" PHASE="pre-up" IF_ETHTOOL_MSGLVL="debug on" MOCK="echo" @@ -82,3 +85,45 @@ up_autoneg_mask_body() { -o match:'autoneg on advertise 1000/full' \ ${EXECUTOR} } + +up_pause_autoneg_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_AUTONEG="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --pause eth0' \ + -o match:"autoneg 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_AUTONEG="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --pause eth0' \ + -o match:"autoneg 'off'" \ + ${EXECUTOR} +} + +up_pause_tx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_TX="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --pause eth0' \ + -o match:"tx 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_TX="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --pause eth0' \ + -o match:"tx 'off'" \ + ${EXECUTOR} +} + +up_pause_rx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_RX="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --pause eth0' \ + -o match:"rx 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_RX="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --pause eth0' \ + -o match:"rx 'off'" \ + ${EXECUTOR} +} From c19def376484a2c0fa87d6ffd71dd273aa12560d Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:18:08 -0600 Subject: [PATCH 301/530] tests: ethtool: add offload tests --- tests/linux/ethtool_test | 122 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 121 insertions(+), 1 deletion(-) diff --git a/tests/linux/ethtool_test b/tests/linux/ethtool_test index 4486923..3d7f219 100755 --- a/tests/linux/ethtool_test +++ b/tests/linux/ethtool_test @@ -14,7 +14,15 @@ tests_init \ up_autoneg_mask \ up_pause_autoneg \ up_pause_tx \ - up_pause_rx + up_pause_rx \ + up_offload_gro \ + up_offload_gso \ + up_offload_lro \ + up_offload_rx \ + up_offload_sg \ + up_offload_tso \ + up_offload_tx \ + up_offload_ufo pre_up_msglvl_body() { export IFACE="eth0" PHASE="pre-up" IF_ETHTOOL_MSGLVL="debug on" MOCK="echo" @@ -127,3 +135,115 @@ up_pause_rx_body() { -o match:"rx 'off'" \ ${EXECUTOR} } + +up_offload_gro_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GRO="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"gro 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GRO="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"gro 'off'" \ + ${EXECUTOR} +} + +up_offload_gso_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GSO="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"gso 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GSO="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"gso 'off'" \ + ${EXECUTOR} +} + +up_offload_lro_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_LRO="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"lro 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_LRO="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"lro 'off'" \ + ${EXECUTOR} +} + +up_offload_rx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_RX="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"rx 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_RX="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"rx 'off'" \ + ${EXECUTOR} +} + +up_offload_sg_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_SG="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"sg 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_SG="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"sg 'off'" \ + ${EXECUTOR} +} + +up_offload_tso_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TSO="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"tso 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TSO="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"tso 'off'" \ + ${EXECUTOR} +} + +up_offload_tx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TX="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"tx 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TX="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"tx 'off'" \ + ${EXECUTOR} +} + +up_offload_ufo_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_UFO="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"ufo 'on'" \ + ${EXECUTOR} + + export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_UFO="off" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --offload eth0' \ + -o match:"ufo 'off'" \ + ${EXECUTOR} +} From 2078f63e62ac8af66af6334a6c06c68eeb63118c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:30:12 -0600 Subject: [PATCH 302/530] interface-file: remap debian hardware DMA ring terms to ethtool-dma namespace --- libifupdown/interface-file.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 5441abd..084e2b2 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -37,6 +37,10 @@ static const struct remap_token tokens[] = { {"ethernet-wol", "ethtool-ethernet-wol"}, /* Debian ethtool integration */ {"gro-offload", "ethtool-offload-gro"}, /* ifupdown2 */ {"gso-offload", "ethtool-offload-gso"}, /* ifupdown2 */ + {"hardware-dma-ring-rx", "ethtool-dma-ring-rx"}, /* Debian ethtool integration */ + {"hardware-dma-ring-rx-jumbo", "ethtool-dma-ring-rx-jumbo"}, /* Debian ethtool integration */ + {"hardware-dma-ring-rx-mini", "ethtool-dma-ring-rx-mini"}, /* Debian ethtool integration */ + {"hardware-dma-ring-tx", "ethtool-dma-ring-tx"}, /* Debian ethtool integration */ {"link-autoneg", "ethtool-ethernet-autoneg"}, /* ifupdown2 */ {"link-duplex", "ethtool-link-duplex"}, /* Debian ethtool integration */ {"link-fec", "ethtool-link-fec"}, /* ifupdown2 */ From 3e7125aca0284ffd09666fbe18cc4aa451fd4c94 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:32:37 -0600 Subject: [PATCH 303/530] ethtool: add support for the ethtool-dma namespace --- executor-scripts/linux/ethtool | 3 +++ 1 file changed, 3 insertions(+) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index f3dad2d..3f8d284 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -50,5 +50,8 @@ up) offload_settings=$(gather_params ETHTOOL_OFFLOAD) [ -z "$offload_settings" ] || $MOCK ethtool --offload "$IFACE" $offload_settings + + dma_settings=$(gather_params ETHTOOL_DMA_RING) + [ -z "$dma_settings" ] || $MOCK ethtool --set-ring "$IFACE" $dma_settings ;; esac From a69c81b6be126a8d38fdec300e68a92e75f1f01c Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:38:39 -0600 Subject: [PATCH 304/530] tests: ethtool: add dma ring tests --- executor-scripts/linux/ethtool | 2 +- tests/linux/ethtool_test | 38 +++++++++++++++++++++++++++++++++- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 3f8d284..8ad8593 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -12,7 +12,7 @@ gather_params() { y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ P g - s/.*\n//" + s/.*\n//" | sed -E "s/_/-/g" } case "$PHASE" in diff --git a/tests/linux/ethtool_test b/tests/linux/ethtool_test index 3d7f219..197ca2e 100755 --- a/tests/linux/ethtool_test +++ b/tests/linux/ethtool_test @@ -22,7 +22,11 @@ tests_init \ up_offload_sg \ up_offload_tso \ up_offload_tx \ - up_offload_ufo + up_offload_ufo \ + up_dma_ring_rx \ + up_dma_ring_rx_jumbo \ + up_dma_ring_rx_mini \ + up_dma_ring_tx pre_up_msglvl_body() { export IFACE="eth0" PHASE="pre-up" IF_ETHTOOL_MSGLVL="debug on" MOCK="echo" @@ -247,3 +251,35 @@ up_offload_ufo_body() { -o match:"ufo 'off'" \ ${EXECUTOR} } + +up_dma_ring_rx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_RX="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --set-ring eth0' \ + -o match:"rx '1024'" \ + ${EXECUTOR} +} + +up_dma_ring_rx_jumbo_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_RX_JUMBO="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --set-ring eth0' \ + -o match:"rx-jumbo '1024'" \ + ${EXECUTOR} +} + +up_dma_ring_rx_mini_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_RX_MINI="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --set-ring eth0' \ + -o match:"rx-mini '1024'" \ + ${EXECUTOR} +} + +up_dma_ring_tx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_TX="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --set-ring eth0' \ + -o match:"tx '1024'" \ + ${EXECUTOR} +} From f96cb273a03790adfc8b91f4c7805765fe5c33f0 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 09:56:48 -0600 Subject: [PATCH 305/530] interface-file: remap hardware-irq-coalesce- namespace to ethtool-coalesce- namespace --- libifupdown/interface-file.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 084e2b2..32f7a7c 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -41,6 +41,28 @@ static const struct remap_token tokens[] = { {"hardware-dma-ring-rx-jumbo", "ethtool-dma-ring-rx-jumbo"}, /* Debian ethtool integration */ {"hardware-dma-ring-rx-mini", "ethtool-dma-ring-rx-mini"}, /* Debian ethtool integration */ {"hardware-dma-ring-tx", "ethtool-dma-ring-tx"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-adaptive-rx", "ethtool-coalesce-adaptive-rx"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-adaptive-tx", "ethtool-coalesce-adaptive-tx"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-pkt-rate-high", "ethtool-coalesce-pkt-rate-high"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-pkt-rate-low", "ethtool-coalesce-pkt-rate-low"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-frames", "ethtool-coalesce-rx-frames"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-frames-high", "ethtool-coalesce-rx-frames-high"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-frames-irq", "ethtool-coalesce-rx-frames-irq"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-frames-low", "ethtool-coalesce-rx-frames-low"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-usecs", "ethtool-coalesce-rx-usecs"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-usecs-high", "ethtool-coalesce-rx-usecs-high"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-usecs-irq", "ethtool-coalesce-rx-usecs-irq"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-rx-usecs-low", "ethtool-coalesce-rx-usecs-low"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-sample-interval", "ethtool-coalesce-sample-interval"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-stats-block-usecs", "ethtool-coalesce-stats-block-usecs"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-frames", "ethtool-coalesce-tx-frames"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-frames-high", "ethtool-coalesce-tx-frames-high"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-frames-irq", "ethtool-coalesce-tx-frames-irq"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-frames-low", "ethtool-coalesce-tx-frames-low"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-usecs", "ethtool-coalesce-tx-usecs"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-usecs-high", "ethtool-coalesce-tx-usecs-high"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-usecs-irq", "ethtool-coalesce-tx-usecs-irq"}, /* Debian ethtool integration */ + {"hardware-irq-coalesce-tx-usecs-low", "ethtool-coalesce-tx-usecs-low"}, /* Debian ethtool integration */ {"link-autoneg", "ethtool-ethernet-autoneg"}, /* ifupdown2 */ {"link-duplex", "ethtool-link-duplex"}, /* Debian ethtool integration */ {"link-fec", "ethtool-link-fec"}, /* ifupdown2 */ From 3cb635b4431d84f7b0d93c9978f8465f9a06d0e8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 10:06:58 -0600 Subject: [PATCH 306/530] ethtool: set coalesce settings from ethtool-coalesce- term namespace --- executor-scripts/linux/ethtool | 3 +++ 1 file changed, 3 insertions(+) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 8ad8593..55ad32a 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -53,5 +53,8 @@ up) dma_settings=$(gather_params ETHTOOL_DMA_RING) [ -z "$dma_settings" ] || $MOCK ethtool --set-ring "$IFACE" $dma_settings + + coalesce_settings=$(gather_params ETHTOOL_COALESCE) + [ -z "$coalesce_settings" ] || $MOCK ethtool --coalesce "$IFACE" $coalesce_settings ;; esac From 566732321db5e719a22aee2d93cc726bcb0b2981 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Mon, 21 Sep 2020 10:21:43 -0600 Subject: [PATCH 307/530] tests: ethtool: add tests for coalesce settings --- tests/linux/ethtool_test | 200 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 199 insertions(+), 1 deletion(-) diff --git a/tests/linux/ethtool_test b/tests/linux/ethtool_test index 197ca2e..a9e27cd 100755 --- a/tests/linux/ethtool_test +++ b/tests/linux/ethtool_test @@ -26,7 +26,29 @@ tests_init \ up_dma_ring_rx \ up_dma_ring_rx_jumbo \ up_dma_ring_rx_mini \ - up_dma_ring_tx + up_dma_ring_tx \ + up_coalesce_adaptive_rx \ + up_coalesce_adaptive_tx \ + up_coalesce_pkt_rate_low \ + up_coalesce_pkt_rate_high \ + up_coalesce_sample_interval \ + up_coalesce_stats_block_usecs \ + up_coalesce_rx_frames \ + up_coalesce_rx_frames_low \ + up_coalesce_rx_frames_irq \ + up_coalesce_rx_frames_high \ + up_coalesce_rx_usecs \ + up_coalesce_rx_usecs_low \ + up_coalesce_rx_usecs_irq \ + up_coalesce_rx_usecs_high \ + up_coalesce_tx_frames \ + up_coalesce_tx_frames_low \ + up_coalesce_tx_frames_irq \ + up_coalesce_tx_frames_high \ + up_coalesce_tx_usecs \ + up_coalesce_tx_usecs_low \ + up_coalesce_tx_usecs_irq \ + up_coalesce_tx_usecs_high pre_up_msglvl_body() { export IFACE="eth0" PHASE="pre-up" IF_ETHTOOL_MSGLVL="debug on" MOCK="echo" @@ -283,3 +305,179 @@ up_dma_ring_tx_body() { -o match:"tx '1024'" \ ${EXECUTOR} } + +up_coalesce_adaptive_rx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_ADAPTIVE_RX="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"adaptive-rx 'on'" \ + ${EXECUTOR} +} + +up_coalesce_adaptive_tx_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_ADAPTIVE_TX="on" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"adaptive-tx 'on'" \ + ${EXECUTOR} +} + +up_coalesce_pkt_rate_low_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_PKT_RATE_LOW="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"pkt-rate-low '1024'" \ + ${EXECUTOR} +} + +up_coalesce_pkt_rate_high_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_PKT_RATE_HIGH="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"pkt-rate-high '1024'" \ + ${EXECUTOR} +} + +up_coalesce_sample_interval_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_SAMPLE_INTERVAL="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"sample-interval '1024'" \ + ${EXECUTOR} +} + +up_coalesce_stats_block_usecs_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_STATS_BLOCK_USECS="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"stats-block-usecs '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_frames_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-frames '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_frames_low_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES_LOW="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-frames-low '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_frames_irq_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES_IRQ="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-frames-irq '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_frames_high_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES_HIGH="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-frames-high '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_usecs_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-usecs '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_usecs_low_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS_LOW="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-usecs-low '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_usecs_irq_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS_IRQ="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-usecs-irq '1024'" \ + ${EXECUTOR} +} + +up_coalesce_rx_usecs_high_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS_HIGH="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"rx-usecs-high '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_frames_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-frames '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_frames_low_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES_LOW="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-frames-low '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_frames_irq_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES_IRQ="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-frames-irq '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_frames_high_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES_HIGH="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-frames-high '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_usecs_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-usecs '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_usecs_low_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS_LOW="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-usecs-low '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_usecs_irq_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS_IRQ="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-usecs-irq '1024'" \ + ${EXECUTOR} +} + +up_coalesce_tx_usecs_high_body() { + export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS_HIGH="1024" MOCK="echo" + atf_check -s exit:0 \ + -o match:'ethtool --coalesce eth0' \ + -o match:"tx-usecs-high '1024'" \ + ${EXECUTOR} +} From 2e81234df15e9fa4be139585562214f45fd01fb7 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Wed, 23 Sep 2020 01:24:56 +0200 Subject: [PATCH 308/530] ethtool: Call 'env' instead of 'set' to get environment 'set' will output environment variables with ' around them which will confuse ethtool. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/ethtool | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/executor-scripts/linux/ethtool b/executor-scripts/linux/ethtool index 55ad32a..ef0dde9 100755 --- a/executor-scripts/linux/ethtool +++ b/executor-scripts/linux/ethtool @@ -3,7 +3,7 @@ set -e # gather params for a given prefix, based on executor-scripts/linux/tunnel. gather_params() { - set | sed -E " + env | sed -E " s/^IF_${1}_([A-Z0-9_]+)=(.+)/\1\n\2/ ta d From 0a0252d21899d82e4c2660a2ac023926df010b03 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Wed, 23 Sep 2020 01:43:25 +0200 Subject: [PATCH 309/530] ethtool: Fix tests Signed-off-by: Maximilian Wilhelm --- tests/linux/ethtool_test | 96 ++++++++++++++++++++-------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/tests/linux/ethtool_test b/tests/linux/ethtool_test index a9e27cd..d12d64a 100755 --- a/tests/linux/ethtool_test +++ b/tests/linux/ethtool_test @@ -124,13 +124,13 @@ up_pause_autoneg_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_AUTONEG="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --pause eth0' \ - -o match:"autoneg 'on'" \ + -o match:"autoneg on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_AUTONEG="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --pause eth0' \ - -o match:"autoneg 'off'" \ + -o match:"autoneg off" \ ${EXECUTOR} } @@ -138,13 +138,13 @@ up_pause_tx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_TX="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --pause eth0' \ - -o match:"tx 'on'" \ + -o match:"tx on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_TX="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --pause eth0' \ - -o match:"tx 'off'" \ + -o match:"tx off" \ ${EXECUTOR} } @@ -152,13 +152,13 @@ up_pause_rx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_RX="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --pause eth0' \ - -o match:"rx 'on'" \ + -o match:"rx on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_PAUSE_RX="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --pause eth0' \ - -o match:"rx 'off'" \ + -o match:"rx off" \ ${EXECUTOR} } @@ -166,13 +166,13 @@ up_offload_gro_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GRO="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"gro 'on'" \ + -o match:"gro on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GRO="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"gro 'off'" \ + -o match:"gro off" \ ${EXECUTOR} } @@ -180,13 +180,13 @@ up_offload_gso_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GSO="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"gso 'on'" \ + -o match:"gso on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_GSO="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"gso 'off'" \ + -o match:"gso off" \ ${EXECUTOR} } @@ -194,13 +194,13 @@ up_offload_lro_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_LRO="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"lro 'on'" \ + -o match:"lro on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_LRO="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"lro 'off'" \ + -o match:"lro off" \ ${EXECUTOR} } @@ -208,13 +208,13 @@ up_offload_rx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_RX="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"rx 'on'" \ + -o match:"rx on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_RX="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"rx 'off'" \ + -o match:"rx off" \ ${EXECUTOR} } @@ -222,13 +222,13 @@ up_offload_sg_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_SG="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"sg 'on'" \ + -o match:"sg on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_SG="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"sg 'off'" \ + -o match:"sg off" \ ${EXECUTOR} } @@ -236,13 +236,13 @@ up_offload_tso_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TSO="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"tso 'on'" \ + -o match:"tso on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TSO="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"tso 'off'" \ + -o match:"tso off" \ ${EXECUTOR} } @@ -250,13 +250,13 @@ up_offload_tx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TX="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"tx 'on'" \ + -o match:"tx on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_TX="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"tx 'off'" \ + -o match:"tx off" \ ${EXECUTOR} } @@ -264,13 +264,13 @@ up_offload_ufo_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_UFO="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"ufo 'on'" \ + -o match:"ufo on" \ ${EXECUTOR} export IFACE="eth0" PHASE="up" IF_ETHTOOL_OFFLOAD_UFO="off" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --offload eth0' \ - -o match:"ufo 'off'" \ + -o match:"ufo off" \ ${EXECUTOR} } @@ -278,7 +278,7 @@ up_dma_ring_rx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_RX="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --set-ring eth0' \ - -o match:"rx '1024'" \ + -o match:"rx 1024" \ ${EXECUTOR} } @@ -286,7 +286,7 @@ up_dma_ring_rx_jumbo_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_RX_JUMBO="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --set-ring eth0' \ - -o match:"rx-jumbo '1024'" \ + -o match:"rx-jumbo 1024" \ ${EXECUTOR} } @@ -294,7 +294,7 @@ up_dma_ring_rx_mini_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_RX_MINI="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --set-ring eth0' \ - -o match:"rx-mini '1024'" \ + -o match:"rx-mini 1024" \ ${EXECUTOR} } @@ -302,7 +302,7 @@ up_dma_ring_tx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_DMA_RING_TX="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --set-ring eth0' \ - -o match:"tx '1024'" \ + -o match:"tx 1024" \ ${EXECUTOR} } @@ -310,7 +310,7 @@ up_coalesce_adaptive_rx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_ADAPTIVE_RX="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"adaptive-rx 'on'" \ + -o match:"adaptive-rx on" \ ${EXECUTOR} } @@ -318,7 +318,7 @@ up_coalesce_adaptive_tx_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_ADAPTIVE_TX="on" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"adaptive-tx 'on'" \ + -o match:"adaptive-tx on" \ ${EXECUTOR} } @@ -326,7 +326,7 @@ up_coalesce_pkt_rate_low_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_PKT_RATE_LOW="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"pkt-rate-low '1024'" \ + -o match:"pkt-rate-low 1024" \ ${EXECUTOR} } @@ -334,7 +334,7 @@ up_coalesce_pkt_rate_high_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_PKT_RATE_HIGH="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"pkt-rate-high '1024'" \ + -o match:"pkt-rate-high 1024" \ ${EXECUTOR} } @@ -342,7 +342,7 @@ up_coalesce_sample_interval_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_SAMPLE_INTERVAL="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"sample-interval '1024'" \ + -o match:"sample-interval 1024" \ ${EXECUTOR} } @@ -350,7 +350,7 @@ up_coalesce_stats_block_usecs_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_STATS_BLOCK_USECS="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"stats-block-usecs '1024'" \ + -o match:"stats-block-usecs 1024" \ ${EXECUTOR} } @@ -358,7 +358,7 @@ up_coalesce_rx_frames_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-frames '1024'" \ + -o match:"rx-frames 1024" \ ${EXECUTOR} } @@ -366,7 +366,7 @@ up_coalesce_rx_frames_low_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES_LOW="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-frames-low '1024'" \ + -o match:"rx-frames-low 1024" \ ${EXECUTOR} } @@ -374,7 +374,7 @@ up_coalesce_rx_frames_irq_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES_IRQ="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-frames-irq '1024'" \ + -o match:"rx-frames-irq 1024" \ ${EXECUTOR} } @@ -382,7 +382,7 @@ up_coalesce_rx_frames_high_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_FRAMES_HIGH="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-frames-high '1024'" \ + -o match:"rx-frames-high 1024" \ ${EXECUTOR} } @@ -390,7 +390,7 @@ up_coalesce_rx_usecs_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-usecs '1024'" \ + -o match:"rx-usecs 1024" \ ${EXECUTOR} } @@ -398,7 +398,7 @@ up_coalesce_rx_usecs_low_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS_LOW="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-usecs-low '1024'" \ + -o match:"rx-usecs-low 1024" \ ${EXECUTOR} } @@ -406,7 +406,7 @@ up_coalesce_rx_usecs_irq_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS_IRQ="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-usecs-irq '1024'" \ + -o match:"rx-usecs-irq 1024" \ ${EXECUTOR} } @@ -414,7 +414,7 @@ up_coalesce_rx_usecs_high_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_RX_USECS_HIGH="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"rx-usecs-high '1024'" \ + -o match:"rx-usecs-high 1024" \ ${EXECUTOR} } @@ -422,7 +422,7 @@ up_coalesce_tx_frames_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-frames '1024'" \ + -o match:"tx-frames 1024" \ ${EXECUTOR} } @@ -430,7 +430,7 @@ up_coalesce_tx_frames_low_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES_LOW="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-frames-low '1024'" \ + -o match:"tx-frames-low 1024" \ ${EXECUTOR} } @@ -438,7 +438,7 @@ up_coalesce_tx_frames_irq_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES_IRQ="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-frames-irq '1024'" \ + -o match:"tx-frames-irq 1024" \ ${EXECUTOR} } @@ -446,7 +446,7 @@ up_coalesce_tx_frames_high_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_FRAMES_HIGH="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-frames-high '1024'" \ + -o match:"tx-frames-high 1024" \ ${EXECUTOR} } @@ -454,7 +454,7 @@ up_coalesce_tx_usecs_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-usecs '1024'" \ + -o match:"tx-usecs 1024" \ ${EXECUTOR} } @@ -462,7 +462,7 @@ up_coalesce_tx_usecs_low_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS_LOW="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-usecs-low '1024'" \ + -o match:"tx-usecs-low 1024" \ ${EXECUTOR} } @@ -470,7 +470,7 @@ up_coalesce_tx_usecs_irq_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS_IRQ="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-usecs-irq '1024'" \ + -o match:"tx-usecs-irq 1024" \ ${EXECUTOR} } @@ -478,6 +478,6 @@ up_coalesce_tx_usecs_high_body() { export IFACE="eth0" PHASE="up" IF_ETHTOOL_COALESCE_TX_USECS_HIGH="1024" MOCK="echo" atf_check -s exit:0 \ -o match:'ethtool --coalesce eth0' \ - -o match:"tx-usecs-high '1024'" \ + -o match:"tx-usecs-high 1024" \ ${EXECUTOR} } From eb70e48eceecb565f8c37b0a4ec09759626278e4 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:26:28 -0600 Subject: [PATCH 310/530] interface-file: add interface and template keywords as alias for iface --- libifupdown/interface-file.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 32f7a7c..f9d70dc 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -336,7 +336,9 @@ static const struct parser_keyword keywords[] = { {"gateway", handle_gateway}, {"iface", handle_iface}, {"inherit", handle_inherit}, + {"interface", handle_iface}, {"source", handle_source}, + {"template", handle_iface}, {"use", handle_use}, }; From a3987b46c8045e5a1b044d6879147eede72a75c6 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:29:01 -0600 Subject: [PATCH 311/530] interface-file: mark interface as template if `template` keyword is used --- libifupdown/interface-file.c | 6 ++++++ libifupdown/interface.h | 1 + 2 files changed, 7 insertions(+) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index f9d70dc..d75e53e 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -236,6 +236,12 @@ handle_iface(struct lif_dict *collection, const char *filename, size_t lineno, c return false; } + /* mark the cur_iface as a template iface if `template` keyword + * is used. + */ + if (!strcmp(token, "template")) + cur_iface->is_template = true; + /* in original ifupdown config, we can have "inet loopback" * or "inet dhcp" or such to designate hints. lets pick up * those hints here. diff --git a/libifupdown/interface.h b/libifupdown/interface.h index d627610..c36690d 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -50,6 +50,7 @@ struct lif_interface { bool is_auto; bool is_bridge; bool is_bond; + bool is_template; struct lif_dict vars; From 5c5c316ebf8843a10f3da6e2860c28183c390ca2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:34:35 -0600 Subject: [PATCH 312/530] interface: add config setting to restrict inheritance to template interfaces --- dist/ifupdown-ng.conf.example | 7 +++++++ libifupdown/config-file.c | 2 ++ libifupdown/config-file.h | 1 + libifupdown/interface.c | 4 ++++ 4 files changed, 14 insertions(+) diff --git a/dist/ifupdown-ng.conf.example b/dist/ifupdown-ng.conf.example index 1e5443c..56d1d3f 100644 --- a/dist/ifupdown-ng.conf.example +++ b/dist/ifupdown-ng.conf.example @@ -8,3 +8,10 @@ # compatibility with legacy setups, and may be disabled for performance # improvements in setups where only ifupdown-ng executors are used. allow_addon_scripts = 1 + +# allow_any_iface_as_template: +# Enable any interface to act as a template for another interface. +# This is presently the default, but is deprecated. An admin may choose +# to disable this setting in order to require inheritance from specified +# templates. +allow_any_iface_as_template = 1 diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index 1844875..e4f28b8 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -20,6 +20,7 @@ struct lif_config_file lif_config = { .allow_addon_scripts = true, + .allow_any_iface_as_template = true, }; static bool @@ -43,6 +44,7 @@ set_bool_value(const char *key, const char *value, void *opaque) static struct lif_config_handler handlers[] = { {"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts}, + {"allow_any_iface_as_template", set_bool_value, &lif_config.allow_any_iface_as_template}, }; bool diff --git a/libifupdown/config-file.h b/libifupdown/config-file.h index a528636..775e566 100644 --- a/libifupdown/config-file.h +++ b/libifupdown/config-file.h @@ -20,6 +20,7 @@ struct lif_config_file { bool allow_addon_scripts; + bool allow_any_iface_as_template; }; extern struct lif_config_file lif_config; diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 4164eab..10e55f4 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -16,6 +16,7 @@ #include #include #include "libifupdown/interface.h" +#include "libifupdown/config-file.h" bool lif_address_parse(struct lif_address *address, const char *presentation) @@ -239,6 +240,9 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic if (parent == NULL) return false; + if (!lif_config.allow_any_iface_as_template && !parent->is_template) + return false; + lif_dict_add(&interface->vars, "inherit", strdup(ifname)); interface->is_bond = parent->is_bond; interface->is_bridge = parent->is_bridge; From 41a71173d1ac5349367147697cbb963acd8ad685 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:35:27 -0600 Subject: [PATCH 313/530] ifquery: display template interfaces as templates, not as iface --- cmd/ifquery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index fb91883..6576457 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -30,7 +30,7 @@ print_interface(struct lif_interface *iface) if (iface->is_auto) printf("auto %s\n", iface->ifname); - printf("iface %s\n", iface->ifname); + printf("%s %s\n", iface->is_template ? "template" : "iface", iface->ifname); struct lif_node *iter; LIF_DICT_FOREACH(iter, &iface->vars) From 94f00b2fdcf7e6cb0092000e1af73eec07251af8 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:38:29 -0600 Subject: [PATCH 314/530] interface-file: do not allow templates to be set as automatic --- libifupdown/interface-file.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index d75e53e..e6a4d09 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -162,7 +162,9 @@ handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, ch return false; } - cur_iface->is_auto = true; + if (!cur_iface->is_template) + cur_iface->is_auto = true; + return true; } @@ -240,7 +242,10 @@ handle_iface(struct lif_dict *collection, const char *filename, size_t lineno, c * is used. */ if (!strcmp(token, "template")) + { + cur_iface->is_auto = false; cur_iface->is_template = true; + } /* in original ifupdown config, we can have "inet loopback" * or "inet dhcp" or such to designate hints. lets pick up From 580f054d7eb0354b989c7374c7fca767efdcca29 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:39:45 -0600 Subject: [PATCH 315/530] lifecycle: do not allow lif_lifecycle_run() on a template --- libifupdown/lifecycle.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index d8ab8c5..bb59a02 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -341,6 +341,9 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par bool lif_lifecycle_run(const struct lif_execute_opts *opts, struct lif_interface *iface, struct lif_dict *collection, struct lif_dict *state, const char *lifname, bool up) { + if (iface->is_template) + return false; + if (lifname == NULL) lifname = iface->ifname; From f9683c2242e84cb24fa35d9f4cf3d24a9a6c4069 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:42:09 -0600 Subject: [PATCH 316/530] ifupdown: complain to the user if they try to bring up or tear down a template interface --- cmd/ifupdown.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index ad20df4..e08feee 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -96,6 +96,9 @@ acquire_state_lock(const char *state_path, const char *lifname) bool skip_interface(struct lif_interface *iface, const char *ifname) { + if (iface->is_template) + fprintf(stderr, "%s: cannot change state on %s (template interface)\n", argv0, ifname); + if (exec_opts.force) return false; From f224c04804f0280844c31f3cf66513479375593f Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:46:52 -0600 Subject: [PATCH 317/530] interface: explicitly convert any inherited interface into a template --- libifupdown/interface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libifupdown/interface.c b/libifupdown/interface.c index 10e55f4..a9b0f2b 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -243,6 +243,9 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic if (!lif_config.allow_any_iface_as_template && !parent->is_template) return false; + /* explicitly convert any interface we are inheriting from into a template */ + parent->is_template = true; + lif_dict_add(&interface->vars, "inherit", strdup(ifname)); interface->is_bond = parent->is_bond; interface->is_bridge = parent->is_bridge; From 243a9b92ce19f2acc08de9f15776b69f458a3f4b Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 11:52:22 -0600 Subject: [PATCH 318/530] ifupdown: skip over template interfaces at warning time instead of letting lif_lifecycle_run() fail --- cmd/ifupdown.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index e08feee..0a09e06 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -97,7 +97,10 @@ bool skip_interface(struct lif_interface *iface, const char *ifname) { if (iface->is_template) + { fprintf(stderr, "%s: cannot change state on %s (template interface)\n", argv0, ifname); + return false; + } if (exec_opts.force) return false; From 60d0ed34b8fd3920566e8c1f950c2b0d6358a673 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Wed, 23 Sep 2020 19:07:52 -0600 Subject: [PATCH 319/530] interface: make interface-to-template conversion a config option (defaulting to enabled) --- dist/ifupdown-ng.conf.example | 8 ++++++++ libifupdown/config-file.c | 1 + libifupdown/config-file.h | 1 + libifupdown/interface.c | 5 +++-- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/dist/ifupdown-ng.conf.example b/dist/ifupdown-ng.conf.example index 56d1d3f..339f568 100644 --- a/dist/ifupdown-ng.conf.example +++ b/dist/ifupdown-ng.conf.example @@ -15,3 +15,11 @@ allow_addon_scripts = 1 # to disable this setting in order to require inheritance from specified # templates. allow_any_iface_as_template = 1 + +# implicit_template_conversion: +# In some legacy configs, a template may be declared as an iface, and +# ifupdown-ng automatically converts those declarations to a proper +# template. If this setting is disabled, inheritance will continue to +# work against non-template interfaces without converting them to a +# template. +implicit_template_conversion = 1 diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index e4f28b8..2628118 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -45,6 +45,7 @@ set_bool_value(const char *key, const char *value, void *opaque) static struct lif_config_handler handlers[] = { {"allow_addon_scripts", set_bool_value, &lif_config.allow_addon_scripts}, {"allow_any_iface_as_template", set_bool_value, &lif_config.allow_any_iface_as_template}, + {"implicit_template_conversion", set_bool_value, &lif_config.implicit_template_conversion}, }; bool diff --git a/libifupdown/config-file.h b/libifupdown/config-file.h index 775e566..2d05c8f 100644 --- a/libifupdown/config-file.h +++ b/libifupdown/config-file.h @@ -21,6 +21,7 @@ struct lif_config_file { bool allow_addon_scripts; bool allow_any_iface_as_template; + bool implicit_template_conversion; }; extern struct lif_config_file lif_config; diff --git a/libifupdown/interface.c b/libifupdown/interface.c index a9b0f2b..feb8b2f 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -243,8 +243,9 @@ lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dic if (!lif_config.allow_any_iface_as_template && !parent->is_template) return false; - /* explicitly convert any interface we are inheriting from into a template */ - parent->is_template = true; + /* maybe convert any interface we are inheriting from into a template */ + if (lif_config.implicit_template_conversion) + parent->is_template = true; lif_dict_add(&interface->vars, "inherit", strdup(ifname)); interface->is_bond = parent->is_bond; From a55ef8577674c5a96f2a705c8a78443bd78d2c72 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 24 Sep 2020 15:19:53 -0600 Subject: [PATCH 320/530] doc: interfaces: describe template inheritance --- doc/interfaces.scd | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 17bc5aa..f8ba926 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -47,6 +47,10 @@ with an address of *203.0.113.2* and gateway of *203.0.113.1*. associated with the declaration will be stored inside _object_. +*template* _object_ + Begins a new declaration for _object_, like *iface*, except + that _object_ is defined as a *template*. + # SUPPORTED KEYWORDS FOR OBJECT TRIPLES Any keyword may be used inside an interface declaration block, but @@ -79,9 +83,10 @@ the system will only respond to certain keywords by default: Interfaces associated with the parent are taken down at the same time as the parent. -*inherit* _interface_ - Designates that the parent interface should inherit - configuration data from _interface_. +*inherit* _object_ + Designates that the configured interface should inherit + configuration data from _object_. Normally _object_ + must be a *template*. *use* _option_ Designates that an option should be used. See _OPTIONS_ From fafce2f262e9572c1d5e4b9ba09ab154fea66eab Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Thu, 24 Sep 2020 15:36:22 -0600 Subject: [PATCH 321/530] config-file: add missing default for implicit_template_conversion --- libifupdown/config-file.c | 1 + 1 file changed, 1 insertion(+) diff --git a/libifupdown/config-file.c b/libifupdown/config-file.c index 2628118..ced67f1 100644 --- a/libifupdown/config-file.c +++ b/libifupdown/config-file.c @@ -21,6 +21,7 @@ struct lif_config_file lif_config = { .allow_addon_scripts = true, .allow_any_iface_as_template = true, + .implicit_template_conversion = true, }; static bool From 8dc229500643b85310b275e697b69a7c100cc8a2 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 25 Sep 2020 02:15:16 +0200 Subject: [PATCH 322/530] ifupdown: Don't configure errornous interfaces. Do not configure interfaces which have a configuration know to be broken. Currently this only happens when using "inherit" to an non-existing iface or to an iface and not a template, and having allow_any_iface_as_template set to 0. In those cases broken ifaces will not be configured unless ifup/ifdown is invoked with --force. Signed-off-by: Maximilian Wilhelm --- cmd/ifupdown.c | 7 +++++ libifupdown/interface-file.c | 61 ++++++++++++++++++++++++++++-------- libifupdown/interface.c | 13 ++------ libifupdown/interface.h | 5 ++- libifupdown/lifecycle.c | 14 +++++++++ 5 files changed, 76 insertions(+), 24 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 0a09e06..904eb5b 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -3,6 +3,7 @@ * Purpose: bring interfaces up or down * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -105,6 +106,12 @@ skip_interface(struct lif_interface *iface, const char *ifname) if (exec_opts.force) return false; + if (iface->has_config_error) + { + fprintf(stderr, "%s: skipping interface %s due to config errors\n", argv0, ifname); + return true; + } + if (up && iface->refcount > 0) { if (exec_opts.verbose) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index e6a4d09..dc2beb7 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -3,6 +3,7 @@ * Purpose: /etc/network/interfaces parser * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -137,7 +138,8 @@ handle_address(struct lif_dict *collection, const char *filename, size_t lineno, if (cur_iface == NULL) { report_error(filename, lineno, "%s '%s' without interface", token, addr); - return false; + /* Ignore this address, but don't fail hard */ + return true; } lif_interface_address_add(cur_iface, addr); @@ -154,7 +156,10 @@ handle_auto(struct lif_dict *collection, const char *filename, size_t lineno, ch char *ifname = lif_next_token(&bufp); if (!*ifname && cur_iface == NULL) - return false; + { + report_error(filename, lineno, "auto without interface"); + return true; + } else { cur_iface = lif_interface_collection_find(collection, ifname); @@ -179,7 +184,8 @@ handle_gateway(struct lif_dict *collection, const char *filename, size_t lineno, if (cur_iface == NULL) { report_error(filename, lineno, "%s '%s' without interface", token, addr); - return false; + /* Ignore this gateway, but don't fail hard */ + return true; } lif_interface_use_executor(cur_iface, "static"); @@ -228,7 +234,8 @@ handle_iface(struct lif_dict *collection, const char *filename, size_t lineno, c if (!*ifname) { report_error(filename, lineno, "%s without any other tokens", token); - return false; + /* This is broken but not fatal */ + return true; } cur_iface = lif_interface_collection_find(collection, ifname); @@ -278,19 +285,44 @@ handle_inherit(struct lif_dict *collection, const char *filename, size_t lineno, if (cur_iface == NULL) { report_error(filename, lineno, "%s '%s' without interface", token, target); - return false; + /* This is broken but not fatal */ + return true; } if (!*target) { - report_error(filename, lineno, "%s: unspecified interface"); - return false; + report_error(filename, lineno, "iface %s: unspecified inherit target", cur_iface->ifname); + /* Mark this interface as errornous but carry on */ + cur_iface->has_config_error = true; + return true; } - if (!lif_interface_collection_inherit(cur_iface, collection, target)) + struct lif_interface *parent = lif_interface_collection_find(collection, target); + if (parent == NULL) { - report_error(filename, lineno, "could not inherit %s", target); - return false; + report_error(filename, lineno, "iface %s: could not inherit from %s: not found", + cur_iface->ifname, target); + /* Mark this interface as errornous but carry on */ + cur_iface->has_config_error = true; + return true; + + } + + if (!lif_config.allow_any_iface_as_template && !parent->is_template) + { + report_error(filename, lineno, "iface %s: could not inherit from %ss: inheritence from interface not allowed", + cur_iface->ifname, target); + /* Mark this interface as errornous but carry on */ + cur_iface->has_config_error = true; + return true; + } + + if (!lif_interface_collection_inherit(cur_iface, parent)) + { + report_error(filename, lineno, "iface %s: could not inherit from %s", cur_iface->ifname, target); + /* Mark this interface as errornous but carry on */ + cur_iface->has_config_error = true; + return true; } return true; @@ -305,14 +337,16 @@ handle_source(struct lif_dict *collection, const char *filename, size_t lineno, if (!*source_filename) { report_error(filename, lineno, "missing filename to source"); - return false; + /* Broken but not fatal */ + return true; } if (!strcmp(filename, source_filename)) { report_error(filename, lineno, "attempt to source %s would create infinite loop", source_filename); - return false; + /* Broken but not fatal */ + return true; } return lif_interface_file_parse(collection, source_filename); @@ -328,7 +362,8 @@ handle_use(struct lif_dict *collection, const char *filename, size_t lineno, cha if (cur_iface == NULL) { report_error(filename, lineno, "%s '%s' without interface", token, executor); - return false; + /* Broken but not fatal */ + return true; } lif_interface_use_executor(cur_iface, executor); diff --git a/libifupdown/interface.c b/libifupdown/interface.c index feb8b2f..175bae2 100644 --- a/libifupdown/interface.c +++ b/libifupdown/interface.c @@ -3,6 +3,7 @@ * Purpose: interface management * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -233,21 +234,13 @@ lif_interface_collection_delete(struct lif_dict *collection, struct lif_interfac } bool -lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dict *collection, const char *ifname) +lif_interface_collection_inherit(struct lif_interface *interface, struct lif_interface *parent) { - struct lif_interface *parent = lif_interface_collection_find(collection, ifname); - - if (parent == NULL) - return false; - - if (!lif_config.allow_any_iface_as_template && !parent->is_template) - return false; - /* maybe convert any interface we are inheriting from into a template */ if (lif_config.implicit_template_conversion) parent->is_template = true; - lif_dict_add(&interface->vars, "inherit", strdup(ifname)); + lif_dict_add(&interface->vars, "inherit", strdup(parent->ifname)); interface->is_bond = parent->is_bond; interface->is_bridge = parent->is_bridge; diff --git a/libifupdown/interface.h b/libifupdown/interface.h index c36690d..eeaa898 100644 --- a/libifupdown/interface.h +++ b/libifupdown/interface.h @@ -3,6 +3,7 @@ * Purpose: interface management * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -52,6 +53,8 @@ struct lif_interface { bool is_bond; bool is_template; + bool has_config_error; /* error found in interface configuration */ + struct lif_dict vars; size_t refcount; /* > 0 if up, else 0 */ @@ -74,7 +77,7 @@ extern void lif_interface_collection_init(struct lif_dict *collection); extern void lif_interface_collection_fini(struct lif_dict *collection); extern struct lif_interface *lif_interface_collection_find(struct lif_dict *collection, const char *ifname); extern struct lif_interface *lif_interface_collection_upsert(struct lif_dict *collection, struct lif_interface *interface); -extern bool lif_interface_collection_inherit(struct lif_interface *interface, struct lif_dict *collection, const char *ifname); +extern bool lif_interface_collection_inherit(struct lif_interface *interface, struct lif_interface *parent); extern void lif_interface_collection_delete(struct lif_dict *collection, struct lif_interface *interface); #endif diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index bb59a02..2721642 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -3,6 +3,7 @@ * Purpose: management of interface lifecycle (bring up, takedown, reload) * * Copyright (c) 2020 Ariadne Conill + * Copyright (c) 2020 Maximilian Wilhelm * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -313,6 +314,19 @@ handle_dependents(const struct lif_execute_opts *opts, struct lif_interface *par { struct lif_interface *iface = lif_interface_collection_find(collection, tokenp); + if (iface->has_config_error) + { + if (opts->force) + fprintf (stderr, "ifupdown: (de)configuring dependent interface %s (of %s) despite config errors\n", + iface->ifname, parent->ifname); + else + { + fprintf (stderr, "ifupdown: skipping dependent interface %s (of %s) as it has config errors\n", + iface->ifname, parent->ifname); + continue; + } + } + /* if handle_refcounting returns true, it means we've already * configured the interface, or it is too soon to deconfigure * the interface. From a3d11ded4306808b7630dbee3d35197d575729f4 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 25 Sep 2020 02:26:21 +0200 Subject: [PATCH 323/530] ifupdown: Be consistent in error messages. Signed-off-by: Maximilian Wilhelm --- cmd/ifupdown.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/cmd/ifupdown.c b/cmd/ifupdown.c index 904eb5b..8723310 100644 --- a/cmd/ifupdown.c +++ b/cmd/ifupdown.c @@ -103,15 +103,23 @@ skip_interface(struct lif_interface *iface, const char *ifname) return false; } - if (exec_opts.force) - return false; - if (iface->has_config_error) { - fprintf(stderr, "%s: skipping interface %s due to config errors\n", argv0, ifname); - return true; + if (exec_opts.force) + { + fprintf(stderr, "%s: (de)configuring interface %s despite config errors\n", argv0, ifname); + return false; + } + else + { + fprintf(stderr, "%s: skipping interface %s due to config errors\n", argv0, ifname); + return true; + } } + if (exec_opts.force) + return false; + if (up && iface->refcount > 0) { if (exec_opts.verbose) From 88f25e41c6b68583b3f571c6d440d0acd2a7c50a Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 25 Sep 2020 02:28:05 +0200 Subject: [PATCH 324/530] ifupdown: More specific error message. Signed-off-by: Maximilian Wilhelm --- libifupdown/interface-file.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index dc2beb7..31971aa 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -310,7 +310,7 @@ handle_inherit(struct lif_dict *collection, const char *filename, size_t lineno, if (!lif_config.allow_any_iface_as_template && !parent->is_template) { - report_error(filename, lineno, "iface %s: could not inherit from %ss: inheritence from interface not allowed", + report_error(filename, lineno, "iface %s: could not inherit from %ss: inheritence from non-template interface not allowed", cur_iface->ifname, target); /* Mark this interface as errornous but carry on */ cur_iface->has_config_error = true; From 5615c30fd063f5e1dd71aaf43c72936cb85c43b2 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 25 Sep 2020 08:43:26 -0600 Subject: [PATCH 325/530] ifquery: don't build the dependency tree when querying for an interface's properties --- cmd/ifquery.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/ifquery.c b/cmd/ifquery.c index 6576457..9eb1f58 100644 --- a/cmd/ifquery.c +++ b/cmd/ifquery.c @@ -290,7 +290,7 @@ ifquery_main(int argc, char *argv[]) return EXIT_FAILURE; } - if (lif_lifecycle_count_rdepends(&exec_opts, &collection) == -1) + if (match_opts.property == NULL && lif_lifecycle_count_rdepends(&exec_opts, &collection) == -1) { fprintf(stderr, "%s: could not validate dependency tree\n", argv0); return EXIT_FAILURE; From f708bb1465f60bd80fb0722671ce7010d601b3b0 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 25 Sep 2020 22:04:53 +0200 Subject: [PATCH 326/530] link executor: Add support for veth interfaces Signed-off-by: Maximilian Wilhelm --- doc/interfaces.scd | 7 +++++++ executor-scripts/linux/link | 15 ++++++++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index f8ba926..8600b4e 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -73,6 +73,13 @@ the system will only respond to certain keywords by default: *link-type* _link-type_ Denotes the link-type of the interface. When set to _dummy_, the interface is created as a virtual dummy interfaces. + When set to _veth_ the interface is created as virtual veth + interface (pair). + +*veth-peer-name* _peer-name_ + Denotes the name of the veth peer interfaces. If not set + the kernel will name the veth peer interface as _vethN_ + with N being an integer number. *alias* _alias_ Sets the given alias on the interface. diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 02633ef..24db96f 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -39,9 +39,18 @@ create) fi ${MOCK} ip link add "${IFACE}" type dummy - fi - if is_vlan; then + elif [ "${IF_LINK_TYPE}" = "veth" ]; then + if [ ! -d "/sys/class/net/${IFACE}" ]; then + ARGS="" + if [ "${IF_VETH_PEER_NAME}" ]; then + ARGS="peer ${IF_VETH_PEER_NAME}" + fi + + ${MOCK} ip link add "${IFACE}" type veth ${ARGS} + fi + + elif is_vlan; then if [ -d "/sys/class/net/${IFACE}" ]; then exit 0 fi @@ -77,7 +86,7 @@ down) ${MOCK} ip link set down dev "${IFACE}" ;; destroy) - if [ "${IF_LINK_TYPE}" = "dummy" ] || is_vlan; then + if [ "${IF_LINK_TYPE}" = "dummy" ] || [ "${IF_LINK_TYPE}" = "veth" ] || is_vlan; then if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then exit 0 fi From 3035627c93c1d29cef7f6fb9b98d83f05964931c Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 25 Sep 2020 22:07:10 +0200 Subject: [PATCH 327/530] link executor: Add dependency between veth pairs Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 24db96f..c8c05ce 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -28,6 +28,17 @@ is_vlan() { } case "$PHASE" in +depend) + # vlan-raw-device + if is_vlan; then + echo "$IF_VLAN_RAW_DEVICE" + + # veth-peer-name + elif [ "${IF_LINK_TYPE}" = "veth" -a "${IF_VETH_PEER_NAME}" ]; then + echo "${IF_VETH_PEER_NAME}" + fi + ;; + create) if [ "${IF_LINK_TYPE}" = "dummy" ]; then if [ -d "/sys/class/net/${IFACE}" ]; then @@ -94,9 +105,4 @@ destroy) ${MOCK} ip link del "${IFACE}" fi ;; -depend) - if is_vlan; then - echo "$IF_VLAN_RAW_DEVICE" - fi - ;; esac From bd8ad91de60c812b51ef9d018ebf9bb3cacc4954 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 00:55:34 +0200 Subject: [PATCH 328/530] Add files required for Debian packaging * Systemd unit file for networking.service * Small wrapper script called by networking.service * Defaults file for networking.service Signed-off-by: Maximilian Wilhelm --- dist/debian/ifupdown-ng.networking.service | 15 +++++ dist/debian/networking | 68 ++++++++++++++++++++++ dist/debian/networking.default | 13 +++++ 3 files changed, 96 insertions(+) create mode 100644 dist/debian/ifupdown-ng.networking.service create mode 100644 dist/debian/networking create mode 100644 dist/debian/networking.default diff --git a/dist/debian/ifupdown-ng.networking.service b/dist/debian/ifupdown-ng.networking.service new file mode 100644 index 0000000..5aad2f9 --- /dev/null +++ b/dist/debian/ifupdown-ng.networking.service @@ -0,0 +1,15 @@ +[Unit] +Description=ifupdown-ng networking initialization +Documentation=man:interfaces(5) man:ifup(8) man:ifdown(8) + +[Service] +Type=oneshot +RemainAfterExit=yes +SyslogIdentifier=networking +TimeoutStopSec=30s +ExecStart=/usr/share/ifupdown-ng/sbin/networking start +ExecStop=/usr/share/ifupdown-ng/sbin/networking stop +ExecRestart=/usr/share/ifupdown-ng/sbin/networking restart + +[Install] +WantedBy=basic.target network.target multi-user.target network-online.target diff --git a/dist/debian/networking b/dist/debian/networking new file mode 100644 index 0000000..327e08d --- /dev/null +++ b/dist/debian/networking @@ -0,0 +1,68 @@ +#!/bin/sh +# +# Wrapper script for networking set up and teardown via unit file +# +# Thu, 01 Oct 2020 22:47:43 +0200 +# -- Maximilian Wilhelm +# + +STATE_DIR="/run/ifsate" + +# Make sure the state dir is present +if [ ! -d "${STATE_DIR}" ]; then + mkdir "${STATE_DIR}" +fi + +# Check for require binaries +if [ ! -x /sbin/ifup -o ! -x /sbin/ifdown ]; then + echo "ifup and/or ifdown not found!" >&2 + exit 1 +fi + +# Apply defaults if present (verbose mode, kill switch, etc.) +CONFIGURE_INTERFACES=yes + +if [ -f /etc/default/networking ]; then + . /etc/default/networking +fi + +ARGS="" +if [ "${VERBOSE}" = yes ]; then + ARGS="-v" +fi + +# Let's go +case "$1" in + start) + if [ "${CONFIGURE_INTERFACES}" = no ]; then + echo "Not configuring network interfaces, see /etc/default/networking" + exit 0 + fi + + ifup -a ${ARGS} + ;; + + stop) + if [ "${SKIP_DOWN_AT_SYSRESET}" = "yes" ] && systemctl list-jobs | egrep -q '(shutdown|reboot|halt|poweroff)\.target'; then + echo ${NAME}':' "Skipping deconfiguring network interfaces" + exit 0 + fi + + ifdown -a ${ARGS} + ;; + + restart) + ifupdown_init + ifdown -a ${ARGS} + ifup -a ${ARGS} + ;; + + # reload missing here! + + *) + echo "Usage: $0 {start|stop|restart}" + exit 1 + ;; +esac + +exit 0 diff --git a/dist/debian/networking.default b/dist/debian/networking.default new file mode 100644 index 0000000..8c6e6f7 --- /dev/null +++ b/dist/debian/networking.default @@ -0,0 +1,13 @@ +# +# Defaults for ifupdown-ng networking service +# + +# Change the below to "yes" if you want ifup/ifdown and it's executors to be +# verbose about what's going on +VERBOSE="no" + +# Set to "yes" if you want to skip deconfiguring all interfaces during system +# reboot and shutdown. This might be of interest in large scale deployments, +# where you might not want to wait for interface deconfiguration to speed up +# shutdown/reboot. +SKIP_DOWN_AT_SYSRESET="yes" From 3f67b2137ded8b17b1684162c04c087d00af20a8 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 02:20:10 +0200 Subject: [PATCH 329/530] Add VXLAN support Add a vxlan exectutor as well as mappings from ifupdown2 parameters to ours. Closes #75 Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/vxlan | 88 ++++++++++++++++++++++++++++++++++++ libifupdown/interface-file.c | 3 ++ 2 files changed, 91 insertions(+) create mode 100755 executor-scripts/linux/vxlan diff --git a/executor-scripts/linux/vxlan b/executor-scripts/linux/vxlan new file mode 100755 index 0000000..4ee96ea --- /dev/null +++ b/executor-scripts/linux/vxlan @@ -0,0 +1,88 @@ +#!/bin/sh +# +# This executor is responsible for setting up the Virtual Extensible LAN (VXLA) overlay interfaces. +# +# Fri, 02 Oct 2020 01:10:29 +0200 +# -- Maximilian Wilhelm +# +# Known options for the main interface are: +# +# IF_VXLAN_ID The VXLAN Network Identifier (VNI) +# IF_VXLAN_PHYSDEV Specifies the physical device to use for tunnel endpoint communication +# IF_VXLAN_LOCAL_IP Specifies the source IP address to use in outgoing packets +# IF_VXLAN_REMOTE_IP IP of the remote VTEP endpoint (for ptp mode) +# IF_VXLAN_REMOTE_GROUP Multicast group to use for this VNI (for ptmp mode) +# IF_VXLAN_LEARNING Wether to activate MAC learning on this instance (on/off) +# IF_VXLAN_AGEING Specifies the lifetime in seconds of FDB entries learnt by the kernel +# IF_VXLAN_DSTPORT UDP destination port to communicate to the remote VXLAN tunnel endpoint (default 4789) +# + +set -e + +[ -n "$VERBOSE" ] && set -x + +# No VNI, nuthin' to do for us +if [ ! "${IF_VXLAN_ID}" ]; then + exit 0 +fi + +case "$PHASE" in + depend) + if [ "${IF_VXLAN_PHYSDEV}" ]; then + echo "${IF_VXLAN_PHYSDEV}" + fi + ;; + + create) + if [ -d "/sys/class/net/${IFACE}" ]; then + iface_type=$(ip -d link show dev "${IFACE}" | head -n3 | tail -n1 | awk '{ print $1 }') + if [ "${iface_type}" != 'dummy' ]; then + echo "Interface ${IFACE} exists but is of type ${iface_type} instead of dummy" + exit 1 + fi + + exit 0 + fi + + # Input validation + if [ "${IF_VXLAN_REMOTE_IP}" -a "${IF_VXLAN_REMOTE_GROUP}" ]; then + echo "Error on ${IFACE} (vxlan): Only one of 'remote' and 'group' can be given!" >&2 + exit 1 + fi + + # Gather arguments + ARGS="" + [ "${IF_VXLAN_PHYSDEV}" ] && ARGS="${ARGS} dev ${IF_VXLAN_PHYSDEV}" + [ "${IF_VXLAN_LOCAL_IP}" ] && ARGS="${ARGS} local ${IF_VXLAN_LOCAL_IP}" + [ "${IF_VXLAN_REMOTE_IP}" ] && ARGS="${ARGS} remote ${IF_VXLAN_REMOTE_IP}" + [ "${IF_VXLAN_REMOTE_GROUP}" ] && ARGS="${ARGS} group ${IF_VXLAN_REMOTE_GROUP}" + [ "${IF_VXLAN_AGEING}" ] && ARGS="${ARGS} ageing ${IF_VXLAN_AGEING}" + + # Linux uses non-standard default port - WTF? + if [ "${IF_VXLAN_DSTPORT}" ]; then + ARGS="${ARGS} dstport ${IF_VXLAN_DSTPORT}" + else + ARGS="${ARGS} dstport 4789" + fi + + case "${IF_VXLAN_LEARNING}" in + on|yes) + ARGS="${ARGS} learning" + ;; + + off|no) + ARGS="${ARGS} nolearning" + ;; + esac + + ${MOCK} ip link add "${IFACE}" type vxlan id "${IF_VXLAN_ID}" ${ARGS} + ;; + + destroy) + if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then + exit 0 + fi + + ${MOCK} ip link del "${IFACE}" + ;; +esac diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index 31971aa..fbaaa96 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -88,6 +88,9 @@ static const struct remap_token tokens[] = { {"tx-offload", "ethtool-offload-tx"}, /* ifupdown2 */ {"ufo-offload", "ethtool-offload-ufo"}, /* ifupdown2 */ {"vrf", "vrf-member"}, /* ifupdown2 */ + {"vxlan-local-tunnelip", "vxlan-local-ip"}, /* ifupdown2 */ + {"vxlan-remoteip", "vxlan-remote-ip"}, /* ifupdown2 */ + {"vxlan-svcnodeip", "vxlan-remote-group"}, /* ifupdown2 */ }; static int From ee582ac9b0bb8bdde8faae8305bb8c22dd80038f Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 02:19:13 +0200 Subject: [PATCH 330/530] vxlan: Add tests Signed-off-by: Maximilian Wilhelm --- tests/linux/Kyuafile | 1 + tests/linux/vxlan_test | 55 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) create mode 100755 tests/linux/vxlan_test diff --git a/tests/linux/Kyuafile b/tests/linux/Kyuafile index 4e1c304..82b8e78 100644 --- a/tests/linux/Kyuafile +++ b/tests/linux/Kyuafile @@ -12,3 +12,4 @@ atf_test_program{name='tunnel_test'} atf_test_program{name='gre_test'} atf_test_program{name='wireguard_test'} atf_test_program{name='ethtool_test'} +atf_test_program{name='vxlan_test'} diff --git a/tests/linux/vxlan_test b/tests/linux/vxlan_test new file mode 100755 index 0000000..011a856 --- /dev/null +++ b/tests/linux/vxlan_test @@ -0,0 +1,55 @@ +#!/usr/bin/env atf-sh + +. $(atf_get_srcdir)/../test_env.sh +EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/vxlan" + +tests_init \ + create_simple \ + create_ucast \ + create_mcast \ + create_physdev \ + create_dstport \ + create_nolearning \ + destroy \ + +create_simple_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dstport 4789' \ + ${EXECUTOR} +} + +create_ucast_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_IP=192.2.0.42 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 remote 192.2.0.42' \ + ${EXECUTOR} +} + +create_mcast_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_REMOTE_GROUP=225.0.8.15 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 group 225.0.8.15' \ + ${EXECUTOR} +} + +create_physdev_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_PHYSDEV=eth0 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dev eth0' \ + ${EXECUTOR} +} + +create_dstport_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_DSTPORT=1234 + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dstport 1234' \ + ${EXECUTOR} +} + +create_nolearning_body() { + export IFACE=vx_foo PHASE=create MOCK=echo IF_VXLAN_ID=2342 IF_VXLAN_LEARNING=no + atf_check -s exit:0 -o match:'ip link add vx_foo type vxlan id 2342 dstport 4789 nolearning' \ + ${EXECUTOR} +} + +destroy_body() { + export IFACE=vx_foo PHASE=destroy MOCK=echo IF_VXLAN_ID=2342 + atf_check -s exit:0 -o match:'ip link del vx_foo' \ + ${EXECUTOR} +} From c6faf452b9fb84d7cf61df02ddcd169d337441e1 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 02:29:04 +0200 Subject: [PATCH 331/530] link executor: Don't complain about a vanished interface when downing it Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 02633ef..7ede189 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -74,6 +74,11 @@ up) fi ;; down) + # Don't complain about a vanished interface when downing it + if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then + exit 0 + fi + ${MOCK} ip link set down dev "${IFACE}" ;; destroy) From fef7c55270e990094f617f37c62afd8c289d9279 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 02:29:39 +0200 Subject: [PATCH 332/530] link exectutor: Don't re-create dummy interface when present. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/link | 2 ++ 1 file changed, 2 insertions(+) diff --git a/executor-scripts/linux/link b/executor-scripts/linux/link index 7ede189..9df5294 100755 --- a/executor-scripts/linux/link +++ b/executor-scripts/linux/link @@ -36,6 +36,8 @@ create) echo "Interface ${IFACE} exists but is of type ${iface_type} instead of dummy" exit 1 fi + + exit 0 fi ${MOCK} ip link add "${IFACE}" type dummy From 1f1d4f5baded98828b551006bd8449a89a87f48b Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 03:05:30 +0200 Subject: [PATCH 333/530] man: Add documentation for VXLAN parameters. Signed-off-by: Maximilian Wilhelm --- doc/interfaces.scd | 51 ++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/doc/interfaces.scd b/doc/interfaces.scd index f8ba926..06708a8 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -110,8 +110,51 @@ the system will only respond to certain keywords by default: *post-up* _command_ Runs _command_ after bringing the interface up. -Additional packages such as *bonding*, *bridge*, *tunnel* and -*vrf* add additional keywords to this vocabulary. +Additional packages such as *bonding*, *bridge*, *tunnel*, *vrf* and +*vxlan* add additional keywords to this vocabulary. + +# VXLAN INTERFACE CONFIGURATION + +A VXLAN Virtual Tunnel Endpoint (VTEP) interface must an ID set. All +other options are optional. + +*vxlan-id* _VNI ID_ + Denotes the VXLAN Network Identifier (VNI) ID for this interface. + This parameter is required for a VXLAN interface. + +*vxlan-physdev* _interface_ + Specifies the physical device to use for tunnel endpoint + communication. + +*vxlan-local-ip* _address_ + Specifies the source IP address to use in outgoing packets. + For compatiblity with ifupdown2 _vxlan-local-tunnelip_ is an + alias for this parameter. + +*vxlan-remote-ip* _address_ + Specifies the unicast destination IP address to use in outgoing + packets when the destination link layer address is not known in + the VXLAN device forwarding database. This parameter cannot be + specified with the _vxlan-remote-group_ parameter. + For compatiblity with ifupdown2 _vxlan-remoteip_ is an alias for + this parameter. + +*vxlan-remote-group* _multicast group_ + Specifies the multicast IP address to join. This parameter cannot + be specified with the _vxlan-remote-ip_ parameter. + For compatibility with ifupdown2 _vxlan-svcnodeip_ is an alias for + this parameter. + +*vxlan-learning* _on/off_ + Specifies if unknown source link layer addresses and IP addresses + are entered into the VXLAN device forwarding database. + +*vxlan-ageing* _seconds_ + Specifies the lifetime in seconds of FDB entries learnt by the kernel. + +*vxlan-dstport* _port_ + Specifies the UDP destination port to communicate to the remote VXLAN + tunnel endpoint. The default is 4789. # OPTIONS @@ -144,6 +187,10 @@ most common options are: The interface is a VRF. Configuration of VRFs requires the *vrf* package to be installed. +*vxlan* + The interface is a Virtual Extensible LAN (VXLAN) tunnel + endpoint. + # EXAMPLES Configure a bridge interface *br0* with *bond0* attached to it, From 12b0872349fb4d580f1d0961d36aecaeed85d34a Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 03:06:22 +0200 Subject: [PATCH 334/530] vxlan executor: Fix typo and remove code copied from link executor. Signed-off-by: Maximilian Wilhelm --- executor-scripts/linux/vxlan | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/executor-scripts/linux/vxlan b/executor-scripts/linux/vxlan index 4ee96ea..67db07b 100755 --- a/executor-scripts/linux/vxlan +++ b/executor-scripts/linux/vxlan @@ -1,6 +1,6 @@ #!/bin/sh # -# This executor is responsible for setting up the Virtual Extensible LAN (VXLA) overlay interfaces. +# This executor is responsible for setting up the Virtual Extensible LAN (VXLAN) overlay interfaces. # # Fri, 02 Oct 2020 01:10:29 +0200 # -- Maximilian Wilhelm @@ -35,12 +35,6 @@ case "$PHASE" in create) if [ -d "/sys/class/net/${IFACE}" ]; then - iface_type=$(ip -d link show dev "${IFACE}" | head -n3 | tail -n1 | awk '{ print $1 }') - if [ "${iface_type}" != 'dummy' ]; then - echo "Interface ${IFACE} exists but is of type ${iface_type} instead of dummy" - exit 1 - fi - exit 0 fi From 704b2feecb30bc1f0a758b612ee845499f2f4264 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 21:24:21 +0200 Subject: [PATCH 335/530] doc: Move VXLAN documentation into own man page. Signed-off-by: Maximilian Wilhelm --- doc/interfaces-vxlan.scd | 99 ++++++++++++++++++++++++++++++++++++++++ doc/interfaces.scd | 47 ++----------------- 2 files changed, 103 insertions(+), 43 deletions(-) create mode 100644 doc/interfaces-vxlan.scd diff --git a/doc/interfaces-vxlan.scd b/doc/interfaces-vxlan.scd new file mode 100644 index 0000000..a7f2ca6 --- /dev/null +++ b/doc/interfaces-vxlan.scd @@ -0,0 +1,99 @@ +interfaces-vxlan(5) + +# NAME + +*interfaces-vxlan* - VXLAN extensions for the interfaces(5) file format + +# DESCRIPTION + +Virtual eXtensible LAN (VXLAN) is an overlay network to carry Layer 2 over +an IP network while accommodating a very large number of tenants. It is +defined in RFC 7348. + +Beware that VXLAN encapsulation adds an overhead of 50 bytes from witin +the overlay to the underlay (inner Ethernet frame + VXLAN + UDP + IP +haeder). Consider this when setting up underlay an overlay. + +The following options allow to set up VXLAN Tunnel EndPoints (VTEPs) +interfaces with ifupdown-ng. + +See https://www.kernel.org/doc/Documentation/networking/vxlan.rst and/or +https://vincent.bernat.ch/en/blog/2017-vxlan-linux for more information. + +# VXLAN-RELATED OPTIONS + +A VXLAN Virtual Tunnel Endpoint (VTEP) interface must an ID set. All +other options are optional. + +*vxlan-id* _VNI ID_ + Denotes the VXLAN Network Identifier (VNI) ID for this interface. + This parameter is required for a VXLAN interface. + +*vxlan-physdev* _interface_ + Specifies the physical device to use for tunnel endpoint + communication. + +*vxlan-local-ip* _address_ + Specifies the source IP address to use in outgoing packets. + For compatiblity with ifupdown2 _vxlan-local-tunnelip_ is an + alias for this parameter. + +*vxlan-remote-ip* _address_ + Specifies the unicast destination IP address to use in outgoing + packets when the destination link layer address is not known in + the VXLAN device forwarding database. This parameter cannot be + specified with the _vxlan-remote-group_ parameter. + For compatiblity with ifupdown2 _vxlan-remoteip_ is an alias for + this parameter. + +*vxlan-remote-group* _multicast group_ + Specifies the multicast IP address to join. This parameter cannot + be specified with the _vxlan-remote-ip_ parameter. + For compatibility with ifupdown2 _vxlan-svcnodeip_ is an alias for + this parameter. + +*vxlan-learning* _on/off_ + Specifies if unknown source link layer addresses and IP addresses + are entered into the VXLAN device forwarding database. + +*vxlan-ageing* _seconds_ + Specifies the lifetime in seconds of FDB entries learnt by the kernel. + +*vxlan-dstport* _port_ + Specifies the UDP destination port to communicate to the remote VXLAN + tunnel endpoint. The default is 4789. + +# EXAMPLES + +A VTEP with multiple peers addressed via a multicast group: + +... +auto vx_v1001_padcty +iface vx_v1001_padcty + vxlan-id 655617 + vxlan-physdev vlan1001 + vxlan-remote-group 225.10.1.1 + # + hwaddress f2:00:c1:01:10:01 + mtu 1560 +... + +Note that the underlay must have an MTU of at least 1610 to +carry the encapsulated packets. + + +A VTEP with one peer (point-to-point configuration): + +... +auto vx_ptp1 +iface vx_ptp1 + vxlan-id 2342 + vxlan-local-ip 192.0.2.42 + vxlan-remote-ip 198.51.100.23 + # + hwaddress f2:00:c1:01:10:01 +... + +# AUTHORS + +Maximilian Wilhelm diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 06708a8..6e01c74 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -113,49 +113,6 @@ the system will only respond to certain keywords by default: Additional packages such as *bonding*, *bridge*, *tunnel*, *vrf* and *vxlan* add additional keywords to this vocabulary. -# VXLAN INTERFACE CONFIGURATION - -A VXLAN Virtual Tunnel Endpoint (VTEP) interface must an ID set. All -other options are optional. - -*vxlan-id* _VNI ID_ - Denotes the VXLAN Network Identifier (VNI) ID for this interface. - This parameter is required for a VXLAN interface. - -*vxlan-physdev* _interface_ - Specifies the physical device to use for tunnel endpoint - communication. - -*vxlan-local-ip* _address_ - Specifies the source IP address to use in outgoing packets. - For compatiblity with ifupdown2 _vxlan-local-tunnelip_ is an - alias for this parameter. - -*vxlan-remote-ip* _address_ - Specifies the unicast destination IP address to use in outgoing - packets when the destination link layer address is not known in - the VXLAN device forwarding database. This parameter cannot be - specified with the _vxlan-remote-group_ parameter. - For compatiblity with ifupdown2 _vxlan-remoteip_ is an alias for - this parameter. - -*vxlan-remote-group* _multicast group_ - Specifies the multicast IP address to join. This parameter cannot - be specified with the _vxlan-remote-ip_ parameter. - For compatibility with ifupdown2 _vxlan-svcnodeip_ is an alias for - this parameter. - -*vxlan-learning* _on/off_ - Specifies if unknown source link layer addresses and IP addresses - are entered into the VXLAN device forwarding database. - -*vxlan-ageing* _seconds_ - Specifies the lifetime in seconds of FDB entries learnt by the kernel. - -*vxlan-dstport* _port_ - Specifies the UDP destination port to communicate to the remote VXLAN - tunnel endpoint. The default is 4789. - # OPTIONS The *use* keyword designates that an _option_ should be used. @@ -221,6 +178,10 @@ iface eth0 use dhcp ``` +# SEE ALSO + +*interfaces-vxlan*(5) + # AUTHORS Ariadne Conill From 7cf353dd223af60acc4cdb1032e251b163875488 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Fri, 2 Oct 2020 22:29:01 +0200 Subject: [PATCH 336/530] doc: Polish VXLAN related documentation. Thanks-to: Blake W. Signed-off-by: Maximilian Wilhelm --- doc/interfaces-vxlan.scd | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/doc/interfaces-vxlan.scd b/doc/interfaces-vxlan.scd index a7f2ca6..81da9c5 100644 --- a/doc/interfaces-vxlan.scd +++ b/doc/interfaces-vxlan.scd @@ -10,14 +10,15 @@ Virtual eXtensible LAN (VXLAN) is an overlay network to carry Layer 2 over an IP network while accommodating a very large number of tenants. It is defined in RFC 7348. -Beware that VXLAN encapsulation adds an overhead of 50 bytes from witin -the overlay to the underlay (inner Ethernet frame + VXLAN + UDP + IP -haeder). Consider this when setting up underlay an overlay. +Be aware that VXLAN encapsulation adds 50 bytes of overhead to the IP packet +header (inner Ethernet header + VXLAN + UDP + IP). This should be taken into +consideration when setting up overlay networks, particularly on underlay +networks with a conventional 1500 byte MTU. -The following options allow to set up VXLAN Tunnel EndPoints (VTEPs) -interfaces with ifupdown-ng. +The following options set up VXLAN Tunnel EndPoints (VTEP) interfaces with +ifupdown-ng. -See https://www.kernel.org/doc/Documentation/networking/vxlan.rst and/or +See https://www.kernel.org/doc/Documentation/networking/vxlan.rst and https://vincent.bernat.ch/en/blog/2017-vxlan-linux for more information. # VXLAN-RELATED OPTIONS @@ -27,11 +28,11 @@ other options are optional. *vxlan-id* _VNI ID_ Denotes the VXLAN Network Identifier (VNI) ID for this interface. - This parameter is required for a VXLAN interface. + This parameter is required for VTEP interfaces. *vxlan-physdev* _interface_ - Specifies the physical device to use for tunnel endpoint - communication. + Specifies the physical ("underlay") device to use for tunnel + endpoint communication. *vxlan-local-ip* _address_ Specifies the source IP address to use in outgoing packets. @@ -47,8 +48,8 @@ other options are optional. this parameter. *vxlan-remote-group* _multicast group_ - Specifies the multicast IP address to join. This parameter cannot - be specified with the _vxlan-remote-ip_ parameter. + Specifies the multicast group IP address to join. This parameter + cannot be specified with the _vxlan-remote-ip_ parameter. For compatibility with ifupdown2 _vxlan-svcnodeip_ is an alias for this parameter. @@ -60,8 +61,8 @@ other options are optional. Specifies the lifetime in seconds of FDB entries learnt by the kernel. *vxlan-dstport* _port_ - Specifies the UDP destination port to communicate to the remote VXLAN - tunnel endpoint. The default is 4789. + Specifies the UDP destination port of the remote VXLAN tunnel endpoint. + The default is 4789. # EXAMPLES From 74b6f9487c8226aebd3e6ea13d056ccc8a995386 Mon Sep 17 00:00:00 2001 From: Ariadne Conill Date: Fri, 2 Oct 2020 15:41:12 -0600 Subject: [PATCH 337/530] static: always associate default routes with $IFACE Hetzner uses link-local addressing for their default IPv6 route, accordingly we should specify the device a route is associated with so that it will use the correct interface. Thanks to Devin Brown for reporting this issue. --- executor-scripts/linux/static | 2 +- tests/linux/static_test | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index aa99533..ed6bd10 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -27,7 +27,7 @@ configure_addresses() { configure_gateways() { for i in $(ifquery -p gateway -i $INTERFACES_FILE $IFACE); do addrfam=$(addr_family $i) - ${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE $METRIC + ${MOCK} ip $addrfam route $1 default via $i $VRF_TABLE $METRIC dev $IFACE done } diff --git a/tests/linux/static_test b/tests/linux/static_test index d8bdab2..04c5e8f 100755 --- a/tests/linux/static_test +++ b/tests/linux/static_test @@ -11,8 +11,8 @@ up_body() { atf_check -s exit:0 \ -o match:'addr add 203.0.113.2/24 dev eth0' \ -o match:'addr add 2001:db8:1000:2::2/64 dev eth0' \ - -o match:'route add default via 203.0.113.1' \ - -o match:'route add default via 2001:db8:1000:2::1' \ + -o match:'route add default via 203.0.113.1 metric 1 dev eth0' \ + -o match:'route add default via 2001:db8:1000:2::1 metric 1 dev eth0' \ ${EXECUTOR} } @@ -21,8 +21,8 @@ down_body() { atf_check -s exit:0 \ -o match:'addr del 203.0.113.2/24 dev eth0' \ -o match:'addr del 2001:db8:1000:2::2/64 dev eth0' \ - -o match:'route del default via 203.0.113.1' \ - -o match:'route del default via 2001:db8:1000:2::1' \ + -o match:'route del default via 203.0.113.1 metric 1 dev eth0' \ + -o match:'route del default via 2001:db8:1000:2::1 metric 1 dev eth0' \ ${EXECUTOR} } From 67163c65611abc50daf7f4403de921c0e37c68e8 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sat, 3 Oct 2020 04:26:23 +0200 Subject: [PATCH 338/530] static executor: Add support for IPv4 'pointopoint' addresses. Closes #96 Signed-off-by: Maximilian Wilhelm --- doc/interfaces.scd | 5 +++++ executor-scripts/linux/static | 12 +++++++++--- tests/fixtures/static-eth0-ptp.interfaces | 7 +++++++ tests/linux/static_test | 20 +++++++++++++++++++- 4 files changed, 40 insertions(+), 4 deletions(-) create mode 100644 tests/fixtures/static-eth0-ptp.interfaces diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 6e01c74..318c71f 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -70,6 +70,11 @@ the system will only respond to certain keywords by default: is for backwards compatibility and should not be used in new deployments. +*pointopoint* + Sets the given IPv4 address as the peer address on the interface. + This setting only takes effect for the IPv4 address familiy and + only makes sense in combination with as /32 netmask. + *link-type* _link-type_ Denotes the link-type of the interface. When set to _dummy_, the interface is created as a virtual dummy interfaces. diff --git a/executor-scripts/linux/static b/executor-scripts/linux/static index ed6bd10..81f77ec 100755 --- a/executor-scripts/linux/static +++ b/executor-scripts/linux/static @@ -2,6 +2,8 @@ set -e +[ -z "$VERBOSE" ] || set -x + [ -z "$IF_METRIC" ] && IF_METRIC="1" [ -n "$IF_VRF_TABLE" ] && VRF_TABLE="table $IF_VRF_TABLE" [ -n "$IF_VRF_MEMBER" ] && VRF_TABLE="vrf $IF_VRF_MEMBER" @@ -20,7 +22,13 @@ addr_family() { configure_addresses() { for i in $(ifquery -p address -i $INTERFACES_FILE $IFACE); do addrfam=$(addr_family $i) - ${MOCK} ip $addrfam addr $1 $i dev $IFACE + if [ "${IF_POINTOPOINT}" -a "${addrfam}" = "-4" ]; then + PEER="peer ${IF_POINTOPOINT}" + else + PEER="" + fi + + ${MOCK} ip $addrfam addr $1 $i $PEER dev $IFACE done } @@ -31,8 +39,6 @@ configure_gateways() { done } -[ -z "$VERBOSE" ] || set -x - case "$PHASE" in up) configure_addresses add diff --git a/tests/fixtures/static-eth0-ptp.interfaces b/tests/fixtures/static-eth0-ptp.interfaces new file mode 100644 index 0000000..c9b5c77 --- /dev/null +++ b/tests/fixtures/static-eth0-ptp.interfaces @@ -0,0 +1,7 @@ +auto eth0 +iface eth0 + address 203.0.113.2/32 + pointopoint 192.0.2.1 + gateway 192.0.2.1 + address 2001:db8:1000:2::2/64 + gateway 2001:db8:1000:2::1 diff --git a/tests/linux/static_test b/tests/linux/static_test index 04c5e8f..b02915e 100755 --- a/tests/linux/static_test +++ b/tests/linux/static_test @@ -4,7 +4,14 @@ EXECUTOR="$(atf_get_srcdir)/../../executor-scripts/linux/static" FIXTURES="$(atf_get_srcdir)/../fixtures" -tests_init up down vrf_up vrf_down metric_up metric_down +tests_init \ + up \ + up_ptp \ + down \ + vrf_up \ + vrf_down \ + metric_up \ + metric_down up_body() { export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" @@ -16,6 +23,17 @@ up_body() { ${EXECUTOR} } +up_ptp_body() { + export IFACE=eth0 PHASE=up MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0-ptp.interfaces" \ + IF_POINTOPOINT="192.0.2.1" + atf_check -s exit:0 \ + -o match:'addr add 203.0.113.2/32 peer 192.0.2.1 dev eth0' \ + -o match:'route add default via 192.0.2.1 metric 1 dev eth0' \ + -o match:'addr add 2001:db8:1000:2::2/64 dev eth0' \ + -o match:'route add default via 2001:db8:1000:2::1 metric 1 dev eth0' \ + ${EXECUTOR} +} + down_body() { export IFACE=eth0 PHASE=down MOCK=echo INTERFACES_FILE="$FIXTURES/static-eth0.interfaces" atf_check -s exit:0 \ From 9ee3a874d4714a6a56d78d29b83eb1f258618a8c Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Sun, 4 Oct 2020 01:35:41 +0200 Subject: [PATCH 339/530] Add support for bonding / LAGs. * Add a bond executor * Add mappings from ifupdown1/2 * Add a detailed man page * Remove legacy compatiblity glue for setups with 'requires' only The current implementation has to work around the fact that member interfaces will be already up then the bond is created. This is simply done by downing them, adding them to the bundle and upping them again. This can possible be done in a nicer way after revisiting the ordering of plugin execution (#12). Closes #91 Signed-off-by: Maximilian Wilhelm --- Makefile | 3 +- doc/interfaces-bond.scd | 204 +++++++++++++++++++++++++++++++++++ doc/interfaces.scd | 1 + executor-scripts/linux/bond | 64 +++++++++++ libifupdown/interface-file.c | 2 + libifupdown/lifecycle.c | 3 - 6 files changed, 273 insertions(+), 4 deletions(-) create mode 100644 doc/interfaces-bond.scd create mode 100755 executor-scripts/linux/bond diff --git a/Makefile b/Makefile index 36c5ecb..81172d2 100644 --- a/Makefile +++ b/Makefile @@ -143,7 +143,8 @@ MANPAGES_8 = \ doc/ifctrstat.8 MANPAGES_5 = \ - doc/interfaces.5 + doc/interfaces.5 \ + doc/interfaces-bond.5 MANPAGES_7 = \ doc/ifupdown-executor.7 diff --git a/doc/interfaces-bond.scd b/doc/interfaces-bond.scd new file mode 100644 index 0000000..d09e9db --- /dev/null +++ b/doc/interfaces-bond.scd @@ -0,0 +1,204 @@ +interfaces-bond(5) + +# NAME + +*interfaces-bond* - Bonding/LAG extensions for the interfaces(5) file format + +# DESCRIPTION + +The Linux implementation for Ling Aggregation Groups (LAGs) is called +_bonding_, whereas a LAG interface is called _bond_. The Linux bonding +implementation supports active/passive setups, classical EtherChannels +as well as LACP (802.3ad). + +The following options set up bonding/LAG interfaces with ifupdown-ng. + +See https://www.kernel.org/doc/Documentation/networking/bonding.rst and +for more information. + +# BOND-RELATED OPTIONS + +A bond interface must have at least one member port set. All other +options are optional. + +*bond-members* _list of interfaces_ + Denotes the physical member interfaces to form this LAG. For + compatiblity to ifupdown1 and ifupdown2 _slaves_ as well as + _bond-slaves_ are an alias for this option. This option is + required. + +*bond-mode* _mode_ + Denotes the mode for this LAG. The _mode_ can be given as string + or as numerical value. Valid values are _balance-rr_ (0), + _active-backup_ (1), _balance-xor_ (2), _broadcast_ (3), + _802.3ad_ (4), _balance-tlb_ (5), _balance-alb_ (6). + The default is _balance-rr_. + +*bond-xmit-hash-policy* _policy_ + Denotes the hash policy/algorithm used to distribute packets + across the physical links. This only applies for modes + _balance-alb_, _balance-tlb_, _balance-xor_, and _802.3ad_. + The _policy_ can be given as string or as numerical value. + Valid values are _layer2_ (0), _layer3+4_ (1), _layer2+3_ (2), + _encap2+3_ (3), and _encap3+4_ (4). The default is _layer2_. + +*bond-min-links* _number_ + Denotes the minimum number of available links before turning on + carrier. + +*bond-miimon* _interval_ + Denotes the MII link monitoring frequency in milliseconds. + This determines how often the link state of each slave is + inspected for link failures. A value of zero disables MII + link monitoring. The default is 0. + +*bond-use-carrier* _bool_ + Denotes wether miimon uses MII or ethtool ioctls vs. the + netif_carrier_ok() call to determine member link status. + A value of 1 enables the use of netif_carrier_ok(), a value of + 0 will use the deprecated MII / ETHTOOL ioctls. The default + is 1. + +*bond-updelay* _delay_ + Denotes the delay in milliseconds before considering link up, + in milliseconds. The default is 0. + +*bond-downdelay* _delay_ + Denotes the delay in milliseconds before considering link down, + in milliseconds. The default is 0. + +*bond-all-slaves-active* _bool_ + Denotes wether duplicate frames (received on inactive ports) + should be dropped (0) or delivered (1). The default is 0. + +*bond-packets-per-slave* _num_packets_ + Denotes the number of packets to transmit through a member + before moving to the next one. When set to 0 then a slave is + chosen at random. The valid range is 0 - 65535; the default + value is 1. This option has effect only in balance-rr mode. + +*bond-lp-interval* _interval_ + Denotes the interval in seconds between sending learning packets + to each members peer switch. The valid range is 1 - 0x7fffffff; + the default value is 1. This option has effect only in modes + balance-tlb and balance-alb. + +*bond-resend-igmp* _number_ + Denotes the number of IGMP membership reports to send after a + link failover happend. The valid range is 0 - 255; a value of + 0 prevents the IGMP membership report from being issued in + response to the failover event. The default is 1. + This option is useful for bonding modes balance-rr, active-backup + balance-tlb and balance-alb, in which a failover can switch the + IGMP traffic from one slave to another. + +# LACP-RELATED OPTIONS + +The following options are only valid in LACP (802.3ad) mode. + +*bond-lacp-rate* _rate_ + Denotes the _rate_ of LACPDU requested from the peer. The _rate_ + can be given as string or as numerical value. Valid values are + slow (0) and fast (1). The default is slow. + +*bond-ad-select* _mode_ + Denotes the 802.3ad aggregation selection logic. The _mode_ can + be given as string or as numerical value. Valid values are + _stable_ (0), _bandwidth_ (1) and _cound_ (2). The default is + _stable_. + +*bond-ad-actor-sys-prio* _priority_ + Denotes the LACP system priority. The allowed range is 1 - 65535. + The default value is 65535. + +*bond-ad-user-port-key* _key_ + Denotes the upper 10 bits of the port-key. he values can be from + 0 - 1023. The default is 0. + + +# ACTIVE/BACKUP-RELATED OPTIONS + +The following options are only valid in active/passive setups. + +*bond-primary* _interface_ + Denotes the primary member interface The specified device will + always be the active slave while it is available. The primary + option is only valid for active-backup, balance-tlb and + balance-alb mode. + +*bond-primary-reselect* _policy_ + Denotes the reselection policy for the primary member interface. + Valid values are _always_ (0), _better_ (1), and _failure_ (2). + The default is _always_. + +*bond-fail-over-mac* _mode_ + Denotes whether active-backup mode should set all member + interfaces to the same MAC address at enslavement (the + traditional behavior), or, when enabled, perform special + handling of the bond's MAC address in accordance with the + selected policy. Valid values are _none_ (0), _active_ (1), + _follow_ (2). The default is _none_. + +*bond-num-grat-arp* _count_ + Denotes the number of peer notifications (gratuitous ARPs and + unsolicited IPv6 Neighbor Advertisements) to be issued after a + failover event. The valid range is 0 - 255; the default is 1. + +*bond-num-unsol-na* _count_ + This is an alias for _bond-num-grat-arp_ + +*bond-peer-notif-delay* _interval_ + Denotes the interval in milliseconds, between each peer + notification (gratuitous ARP and unsolicited IPv6 Neighbor + Advertisement) issued after a failover event. The default + is 0 which means to match the value of the link monitor + interval. + +# ARP-RELATED OPTIONS + +The following options configure ARP link monitoring. +The ARP monitor works by periodically checking the slave +devices to determine whether they have sent or received +traffic recently. Regular traffic is generated via ARP +probes issued for the addresses specified by the +_bond-arp-ip-target_ option. + +*bond-arp-interval* _interval_ + Denotes the frequency in milliseconds to send ARP probes. + +*bond-arp-ip-target* _IPv4 address_ + Denotes the IP addresses to use as ARP monitoring peers when + _bond-arp-interval_ is > 0. + +*bond-arp-validate* _mode_ + Specifies whether or not ARP probes and replies should be + validated in any mode that supports arp monitoring, or whether + non-ARP traffic should be filtered (disregarded) for link + monitoring purposes. Valid values are _none_ (0), _active_ (1), + _backup_ (2), _all_ (3), _filter_ (4), _filter_active_ (5), and + _filter_backup_ (6). The default is _none_. + +*bond-arp-all-targets* _mode_ + Denotes the number of _bond-arp-ip-targets_ that have to be + reachable to consider the member interface to be up. Valid + options are _any_ (0) and _all_ (1). The default is _any_. + +# EXAMPLES + +A bond using two links and LACP (802.3ad): + +``` +auto bond0 +iface bond0 + bond-members eth0 eth1 + bond-mode 802.3ad + bond-xmit-hash-policy layer3+4 + bond-min-links 1 + # + address 192.0.2.42/24 + address 2001:db8::42/64 +``` + +# AUTHORS + +Maximilian Wilhelm diff --git a/doc/interfaces.scd b/doc/interfaces.scd index 6e01c74..8d15b3b 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -180,6 +180,7 @@ iface eth0 # SEE ALSO +*interfaces-bond*(5) *interfaces-vxlan*(5) # AUTHORS diff --git a/executor-scripts/linux/bond b/executor-scripts/linux/bond new file mode 100755 index 0000000..27d1353 --- /dev/null +++ b/executor-scripts/linux/bond @@ -0,0 +1,64 @@ +#!/bin/sh +# +# This executor is responsible for setting up bond/LAG interfaces. +# +# Sat, 03 Oct 2020 20:42:19 +0200 +# -- Maximilian Wilhelm +# + +set -e + +[ -n "$VERBOSE" ] && set -x + +get_bond_options() { + env | while IFS="=" read opt value; do + # We only care for options of format IF_BOND_ + if ! echo "${opt}" | grep -q '^IF_BOND_[A-Z0-9_]\+$'; then + continue + fi + + # Members are handled seperately + if [ "${opt}" = "IF_BOND_MEMBERS" ]; then + continue + fi + + # Convert options for the actual name + real_opt=$(echo "${opt}" | sed -e 's/^IF_BOND_\([A-Z0-9_]\+\)/\1/' | tr '[A-Z]' '[a-z]') + + echo -n " ${real_opt} ${value}" + done +} + +case "$PHASE" in + depend) + echo "${IF_BOND_MEMBERS}" + ;; + + create) + if [ -d "/sys/class/net/${IFACE}" ]; then + exit 0 + fi + + # Gather bonding options for this interface + options=$(get_bond_options) + + # Create bond + ${MOCK} ip link add "${IFACE}" type bond ${options} + + # Add members to bundle + for member_iface in ${IF_BOND_MEMBERS}; do + # Work around the current execution order + ip link set "${member_iface}" down + ip link set master "${IFACE}" "${member_iface}" + ip link set "${member_iface}" up + done + ;; + + destroy) + if [ -z "${MOCK}" -a ! -d "/sys/class/net/${IFACE}" ]; then + exit 0 + fi + + ${MOCK} ip link del "${IFACE}" + ;; +esac diff --git a/libifupdown/interface-file.c b/libifupdown/interface-file.c index fbaaa96..f2123fa 100644 --- a/libifupdown/interface-file.c +++ b/libifupdown/interface-file.c @@ -28,6 +28,8 @@ struct remap_token { /* this list must be in alphabetical order for bsearch */ static const struct remap_token tokens[] = { + {"bond-ad-sys-priority", "bond-ad-actor-sys-prio"}, /* ifupdown2 */ + {"bond-slaves", "bond-members"}, /* legacy ifupdown, ifupdown2 */ {"driver-message-level", "ethtool-msglvl"}, /* Debian ethtool integration */ {"endpoint", "tunnel-remote"}, /* legacy ifupdown */ {"ethernet-autoneg", "ethtool-ethernet-autoneg"}, /* Debian ethtool integration */ diff --git a/libifupdown/lifecycle.c b/libifupdown/lifecycle.c index 2721642..5910804 100644 --- a/libifupdown/lifecycle.c +++ b/libifupdown/lifecycle.c @@ -163,9 +163,6 @@ build_environment(char **envp[], const struct lif_execute_opts *opts, const stru { if (iface->is_bridge) lif_environment_push(envp, "IF_BRIDGE_PORTS", (const char *) entry->data); - - if (iface->is_bond) - lif_environment_push(envp, "IF_BOND_SLAVES", (const char *) entry->data); } char envkey[4096] = "IF_"; From 48c87e34c175c934de558fb43f6d042f18eb3345 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 6 Oct 2020 03:35:42 +0200 Subject: [PATCH 340/530] tests: Use tabs not spaces. Signed-off-by: Maximilian Wilhelm --- tests/fixtures/static-eth0-ptp.interfaces | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/fixtures/static-eth0-ptp.interfaces b/tests/fixtures/static-eth0-ptp.interfaces index c9b5c77..e6a3f53 100644 --- a/tests/fixtures/static-eth0-ptp.interfaces +++ b/tests/fixtures/static-eth0-ptp.interfaces @@ -4,4 +4,4 @@ iface eth0 pointopoint 192.0.2.1 gateway 192.0.2.1 address 2001:db8:1000:2::2/64 - gateway 2001:db8:1000:2::1 + gateway 2001:db8:1000:2::1 From 3d1d384a6bef6a24cfadb7b6289f25b7b6157b33 Mon Sep 17 00:00:00 2001 From: Maximilian Wilhelm Date: Tue, 6 Oct 2020 03:55:09 +0200 Subject: [PATCH 341/530] doc: Add man page for VRF related parameters Signed-off-by: Maximilian Wilhelm --- doc/interfaces-vrf.scd | 58 ++++++++++++++++++++++++++++++++++++++++++ doc/interfaces.scd | 6 ++++- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 doc/interfaces-vrf.scd diff --git a/doc/interfaces-vrf.scd b/doc/interfaces-vrf.scd new file mode 100644 index 0000000..c808cf0 --- /dev/null +++ b/doc/interfaces-vrf.scd @@ -0,0 +1,58 @@ +interfaces-vrf(5) + +# NAME + +*interfaces-vrf* - VRF extensions for the interfaces(5) file format + +# DESCRIPTION + +Linux has support for Virtual Routing and Forwarding (VRF) instances +since Kernel >= 4.4. The following options allow to set up VRFs and +adding configured interfaces to VRFs. + +Note that in the Linux Kernel VRFs are represented as network interfaces, +too. See https://www.kernel.org/doc/Documentation/networking/vrf.rst for +more details. + +# VRF-RELATED OPTIONS + +*vrf-table* _table id_ + The _id_ of the kernel routing table associated with this + VRF interface. This parameter indicates that the interface + where it is specified shall be a VRF. + +*vrf* _vrf interface_ + The _vrf_ the interface should be assigned to. This parameter + is specified on regular interfaces which should be within the + given _vrf_. + +# EXAMPLES + +A VRF interface: + +``` +auto vrf_external +iface vrf_external + vrf-table 1023 +``` + +A regular interface which should be within a VRF: + +``` +auto eth0 +iface eth0 + address 192.2.0.42/24 + address 2001:db8::42/64 + gateway 192.2.0.1 + gateway 2001:db::1 + vrf vrf_external +``` + +# SEE ALSO + +*ip-vrf*(8) +*ip-link*(8) + +# AUTHORS + +Maximilian Wilhelm diff --git a/doc/interfaces.scd b/doc/interfaces.scd index c8be881..9cf9dfe 100644 --- a/doc/interfaces.scd +++ b/doc/interfaces.scd @@ -155,6 +155,9 @@ most common options are: The interface is a Virtual Extensible LAN (VXLAN) tunnel endpoint. +Check *interfaces-