From 7539724294c08201d7d6a5be5dcd17a52b0a86c1 Mon Sep 17 00:00:00 2001 From: vados-dev Date: Mon, 2 Mar 2026 22:10:12 +0300 Subject: [PATCH] Backup for MikroMaster sucessfully creatd at Mar 02 22:10:12. --- .../20260302/20260302221005-Binary.backup | Bin 0 -> 289700 bytes .../20260302/20260302221005-Config.rsc | 3971 +++++++++++++++++ .../20260302/20260302221005-Diff-Config.rsc | 4 + 3 files changed, 3975 insertions(+) create mode 100644 MikroMaster/20260302/20260302221005-Binary.backup create mode 100644 MikroMaster/20260302/20260302221005-Config.rsc create mode 100644 MikroMaster/history/20260302/20260302221005-Diff-Config.rsc diff --git a/MikroMaster/20260302/20260302221005-Binary.backup b/MikroMaster/20260302/20260302221005-Binary.backup new file mode 100644 index 0000000000000000000000000000000000000000..d35065e821b6d279c8125ecb0b3879e0bb221ae7 GIT binary patch literal 289700 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�WBCglbVs!L{bqmfut5mw@EOX6M%wW4%gI__U8rz>d92(Y)PWdi)yNI@&|iP z^A(LUsmR$xf6Zr7{esT-Q4kwgmP*wFIylsc7 zabvHUb>f%vy(vNLe^7NE6`7)BWxQ0C;?D8lV$Mh_OK^|VL^ac$Y%V4Tu04)aWRPP@rx9X$ zoq;pwz^pqDyCVoOR?-oI+U{oXBzN7D@Kd0rsxp?QOd19AhCESDcxnhOl%21!eIa-N z8yuVKKt`shij;`k$`7Z&t~OC8#>Xq;qrkYP!(9M}#CWAF)-z5ePt^HLFcHCg02>?| zp&&MubOm7A0p=tvRsfQw&?bDog)CM{#DkOfTOJ!sdhiyar%V#5)Myfk8vn##0KyT7 z53w@};7wkxCE^ldCE6PI?z>lmtw>(2kr4@zp8&C`7x7RQ3SwW=^T0WT&;^8Gv`JoAX@t-*7-bz#kS;8+1@$DrbqXP-BQOT#Ec^tX zK$l@x0=w%v&Z#biA7!w+0`t@vFvmZ8gCdN}=kPEtTLc7Fs}g}pJQd1Vt&U@V$C(BS z7<#JpT=6^oYCka{R;khcw)+mWjwiI961iNhF?dm4dZL1ZU}%HMYU$+qbLt)~nS@u@eZ zLIno27zH-P@ae@Ul#6k$*&0K1_YrUR2@_TpuyF=Z9?hai&7# zjN`)bRAn@fI)|I>Uqj0iYd5-*!}!|7;V*lLA{;*1L$r;HW11$zmT;9v4V{5fvmLpi-bgt0|=iAZ^wNO^?_!wiNK`YjPg8^QqgJQ2M{ zgs}#;Gi^~wd7X&Pp!n$93c(pc&leNj zs1UtaO!OUv=q82eW(86N|4R>jS0UQ2FfpN96`j*>Q;6ER*3FVi0)O0 z?o&v)Um^OQLUg-A^ngP2Lxt!;h3FxL=tm0Cj}@XHC`7+1CVE&QdPE`mnL_laLiB_} z%3})A3&ljgE+*(_!jjBW3enRF(K}wE9bTe$y+oUd=shpd@&fV=CGymQk!Ijhhf6&! z4Uof`L~3Cppjo&aM&uhhndopLb<+`e>qwkovQnX=h}2p(V9g~`N6jN*zQp+uYfM7H zX$yd2A@svy{Im&|CAcib`{xCF+nG4!IR~l1)J_6&ra}vdAOduaF|jBV_M~3Mp2Zggjy#u*#$%k54GFOk#Y%IKgF7 z5oMCGN3E{yzd1wyemXa?^qst#m}H*grL<&vY$a3m4v<)?R+-F05`E3b`MicOvOnzQ z5$1_i9-04{IYx(NlE=|Z9<8FNVpvo$^Kc=I$7Aks^pXXuGD;;3wPD8xq9JWV)q<8) z{zZY#aAYHs)lf1O4Wu@CF{On%Osh$&NM=!#`-D+Yko_r)j1vYz7`?W_$W+2!FOM1Z zqb`qn-eh51f&(wRIIKs6z$wMo}&Y&@RQC zkFqVAQfFYnSsiJa|8(%1-skZTpJ{a zT9Ab>1X)N$ka-JC(bUCMuupZ%b)RtdapnxPaEeZxeicrLpsjGK%4b6|-N_@HDZ0{< z&XYtzIIVKYgw-OPx+^9Ju{+DuiMkN!ni1YU{O_ahn4fev={x3!5$w=@({~m<=f)3X z>N)7RT>LOD?NIn&9P}MqIIq_O7hcTIHR^*W-Bz%C@T-5;WebLQx#^3+A8&fe2Ofox z;X9KCWKn+38c>+|8K!93M{1F`J3uLG#TFitlu32IzsS znf-V2hVEq&m~CZ3Qf8lD351;4OCVOTK9>@xu7HiYVxVMCG!O;xVRj_5DCL3Xw_s2`dk#)?>c5 zew^jOwPG)A(1g1|+VWX(u+wttO32vC{*f`mh-7+>xmpBq!1T@=jdx~JXQB*>qIs-o zMC#_FtinG3MkE}JSZv=#hh`r&X1ACJ+ zBzc74xkVHaJhvzpqJprhg3v~+q9DA{E>ZyzM2H@`Oi9m*u`+{Im#dWYsth895FKPU zSQ(K)mf5dqdt;Ra10AA*FaRO?0FgY1KoD$h)5D8sAS2=c9$a{IvC;ysZU3op)jpy} zJt&VsM+)LO797787fbMtbF>Z{G+0E=E{q%{%+_Hew7YdhHgsS-8MPo0i~E~mQEg)! z=4>FiPD>;a1~9~O6KcIAp3r#g=^Y+pnLlms8g}k(;#_n6A_M0tnK;)i$AVjZ)MLi6 zVcU=$=Ry*86ZaO_tIWcF=HCAUAD@Ivdcn^HA7^4=GpaN5qCrubg)ti|jIFCmbb&*4 z$ijUmipzP7nT6RL3o{eV$=mn*D4RF0<~quPXN`3JsCQ4J)S~-sKS;2*!Y_I}Y{@s{>{f6xp+DK|izW z9v@bV)~_=dl7lwfXvRro9a!)E92)_&vUEK@vy4eb7{#J zjY|im^kLT(uin3JMBNi3YKc9s4%+K@_4ruV>aJGJVx}?^fIor>Flb|}E7jGixnkM7 z_p$7rVA(z-iOQhRnS`=YU{+TI@TNV($F zTlaD5p5W9ndrlqvMdMT-GXknwwXAM{eM9OVVbsC)j5_3t#;EGXlv{_@J^O~#Ju##X zvFFsGUo=h~qT8zL!yzr^$^_Wwy4oZBI@F$Dhkeobbx?aU6-b4Hu6Xr3lqiLUhK1?hHH-Zir7J^DG`Ws~EM zuwAtclz!aLxW7H`PS~4xSDHCxvkitOJ5%wh&OkU)CCt$Z`b23=3;$kVSBd+0XD%N+|}r}=hR94%&B`|S7S~i?2yFF z#;UetGF~OHFj(69z{2&9d;#ZTxpJ(LhNYjg9!#?5+=>C?+;oDK-L`Ms!fjy4vOqjs z6>6;v$0gU7eB1Si`^>%(*PNYY+Br5r{99qmzxf_8;4X2;9$?{|hT)-L?vxhM*go@E zqMgm)n4xQZViApBn*(uQ1LAY$6f={pTGP$&cM-{K%5g7kI^=y z5`kn@yOxRv+O=d{)6(k{VCGCOSa=%l2i^GH$J4uca6Z_cr;EO@JUuuPj&^OR3U#g1 zsqSpzFu?pru`7&{oYhn+i$NC*X4&~Wgk)|#r!?T}F96vZ!--QiTQqcRYTRBF*w zBCNSS^b?uZ7>00XJffZ2rFFUgt&vnNq^-w6qe!-f{B?Ca@fpsBGvE#)s^e$avea`I z5S8)c#1!gbdGFX^wrl6MpaqLVT3av{ZFBk!@U!16lYfImb?h9|cocc(kmv3MUL<^< zK+Uyf)PqxGSd{XV6cTj3yJKE zG9v-sJN&muz;_RaMIs?YG<(NE1TDGtEGByrucUD4!eu=!mUA8Q3^{7l~&Da^4&Y9o~EoY$^xjb2}K4!1i63a#@ed=uPWjTYPPtr4tmX&<8ob3+; zgIYZ0*OI9~Yb2cP&_dG^8cymCP3wxL5=i?Of;uV;N8?>7X27)uLMMge>lV1^b5}n~_AOaH{0)(7;5C#PPm7Iw)MKQ2?*g^7O7q8t(@9EN^W~0oSg^<87 z99TI*91=))_+AJ#XgeCKvSFCT?(Qjqdb0lAL z7E#Yx?6jM#hfg6-u(gIbWEdU7YFU7jwuYItEX-cZ3D#P!S+K$n#$pL0wQ|L<&UclG z^x97H5c}`us4b(mH!7q+?}`12T4RhWVHGy(UuagnD0|hbtyN#pG=IhVhRXSouog}E z;|Z-TyulyBL_LrS$D&mb`5rj zwQZIhz3{GntE!cU&4L!Apfk))^kpyTSZhJU@uU{?&uzMU;7jX6X=}~Ws@Y3B&c3t@ zSFL!w--?S9xD8G)8&)-Sp<F3NRFmSiSfV?S2<2`X+&Q52NZSCVW+lqpRKng0 zc>Di}cxOc%-g|B>*vC>{DizbFiCoPL>%b4s$D&^mm6-9sbrp$e&CE{V=tVciFVN z`mY+u0FL5+k4v;!jlpI$hV(}@Ldg`X20LuiFdzG`8W`<=!g~U}0=oH@AR9r!ZI8n!)G`uo3@8XvB(Hs%c;1#j?war=L`JOgI_SRu9K6NOlle#*al6jC?$;&Qx))Y?jg z)HzkaIUR3TE2NIBQONfXFFXI)^c~-rXTdxJRj{F2s)KpB!P4+<=UYNAN?0%eO*gbV zoX{d#GHI0X<~-Z5044MeKnX`AH%5aUiC8q&Wft;=JPTPkP|Y}`BbG|WV`e{ZcV9q7 z5D_0l6J;zMfQB3%51v}t6_3OMA)~Wzbze-6SWJu>169nCC}t?u9Tf|Di~E9#Lyiwa z8VXuG0PQ&<7L9DI>uFuRy}jnbDi(yJft1^y z8SBX5c&f595N(fWP`6N}XYu7nsM4!AjHShkIgF*nZ*Uk(i{IlgmJ?6pFqRXq<1jm` zi^Et3+{9sViSIx^=w^;x7MA$f>CiSydci|miTbymbk?Az6$8n5gZyo;|$42At{Em(8&l8MVuw1bm7b&1`HSVmz#j;pvcl<`KhibAV z!ku37L4L4yrLPm3^8z{#_bwn(Hz82K#mPqp_FW=W^|QRP?R3d_WNpc6Et&Es!znEZ zUrYi1v;>=6WgfAa&O+c}%kr36>LFD9EQyM65}ooJBKj@So{~f*(~hq!lBn!PNmPup zRR>5CGn~@ySiX-h4$E=D` zF;2jR_Umu0nBf4be9lYTJ7v)r3)wM&c`HWa*dPe70b69-6vb~yqL|i=y1vvyjrU>= zX|+`y!_fp=b+>BBffUIMr)=eu@on!ENhXShT;?y5{1^`=lJ=*4m?HT-NhFQLL%Sr3 z3ZhVvitblL^a74;){jkwc2r&=B18!7Deahxk;!DL zMW?AE7L&08YebClsiV?dKq>+n2SP(;I72L-)0uJ=$Mk;ObbRS&YTjrFVfqYRNRyeF z!@X<{J$6OQNiDIH76p>2)rbmZhAd3l;$v5|R0bju7`r2nU9f6NG~jQGCH!+E5q+YW zNsXSkYck7@WY59XlZ(tMf~!YCG>kC|4^)TNRR`xih$W=sOCL=<3NJvx?os(s1wK zNc7zxvn-aykX6Pj{g{U&{}ZXSLhM86QHz%mmdwbVe0tbf>nsR7EuYR(`IeV_p+b^l zzP|!5jS=|m#+$Pd3)V%Y_*oe)!w`Zp919$XKJhbejv@8>26dXwE z9%~$K6`!p~bx$ZhK{~O{VM?c}Z*r=`SiUPeoidymlFu39xrrlNib(6gU9?fNuW7j0 z_B7E+3%>28zJ?}5u&OzbSm%cv24m5v7Q|+Wq(2q&Ya4=*u8^jORhzb{MTqlJu7g0a z5~l5<)tlUHJM51&$|SZAY^*{6MX zDGuloq@hCD9KrOySmX^7YbGvbmMT-RMk>=>^`=HEcM9T@*nLsJN7{*+_5iaDCHv zkLqO$y4cuVuy$@s%@Mi$w!r*t5erwT&FR;LmS4}v>DSoIsnEQToANL$s!ibqIB`^ZvMTI zf1i#w&%ot8T+YYk0$k7*#TNl$2>>nx#Bv1up^#KsP(;3I3emzMQkC!G*>+s+z~xR{ z?!x76Tv&Pl-W*bT06jh@pU56PL&O4w@i6^>N8W(@jVK@V#wGkdk^|hpVMOzs&0#T` z2b=m&;rH35ehx!U3>cgG*YNve2%Goyu0zs?GdMhsh#ufDB6qIfFkC7Zau_b2D>*zt zh(?-7L{IShaMPa0;c@~0Bq9p)`v(bioJ@o*;OsMnh%V#r97;t0$Kh#2)XZTqN@@D> zXv1BKQp#n1O+svhD|hqjTuiP|^n?U(UuB9?f_0C!wnQoQvEbp-#Wq2rFP{ zOf)xW@lEvMsI+BNbc-RlP+t>Dhc*q6TWqfp+gwE!;))$I$RCo6$QqVqKT2(eby_u# z>{Geg@RsZ&c^UFHvZ|a5mvUNGnFYoS4oBCsE~acyWPazgjEd3$Y4Tg8Db|IZo7nKK z@4#l}eA@~we|P1HB-2pb75agacS7s4QbApoUhtnEP2L%}07^)f{d z#f5Uqq|^ju=9pE-qRbpaZtqh_xnI$hStf}v)@j60TPQI@fjyzg1zC^8qAMH>6T4>p+P0FrfR?g742(gD84@RwOMhnu3=7D%R8W}aOX#v2@j z(T*u0pkPc0DVTGhW9`ALd0Mf#2)<+dlGPubj}#Tq=2%) zx*rYJ43QG~9DuyX1yoh~MMaiKGt9IJ%f?1`lS^iv+D$28@Y*Mef!ON_?+{7RH*K)H zz(T7b3!P~gvu+GK7`!~_P%`c=Q}nf3Blr+H(%83_$tX4qz&wp(*E%v!<5)3_W5Y1E z7^+GpLlxeh{??QB5fr;6zPJA^RUgD~v!jyqW}iXYh@p|NlIh7^ltinVwWLKtPB4}@ zYwg??mP~8Gs?{xXS8JhDKI0ZFPY5f95Yn!M5N7bhW}CX2sqT#_>Ok!jHKcbSq%y-f z>l1f_H)l77P^7&%N~S=_+zqnXpOZ?}!)#W&E!$WX(en`J+(IB$Rdotj@*j><+SXk(zEe%T+IZ$$3i0Na^I%!LBF$TU@(HCnhd^qJj>2FOr z%3ks&f8Hc-my?_5Gs?6>$4EG6Xw0;VOsm6Ol_1Uw(T&!$3&(>{ZuVb~0T6^MQvmNk z370kCKA&k~AHnJmf#Oaa%(x9y7e_+~ z*}Tw@L}qLBt2hc1%?C{3OUJ$ynQ6U(eq#Uc@)7&5>&t%Djk#=Y*j(AartT2|*56kw+v)9IrjfCco`k;MLQ8cFPbh;RyNi0FED-OR36 zv+FJFdXJI452rR!f6qasKsqCU&Iq0xz@+bz02_-R7LA&7m;n5<2;~udw3we-w^HW1 z@L}hl^=%?jkntVg$oP(LWPHbWp39IE?8SI@lWW}66cSW*!Zp+lXg7D5Wg*ffQWjgcouP5ECW9B>KWCAJbNMom?7#y&xS#JA# zFNoh>2tQX@ZOU(s=0Jr4n64 z69~>9=JYY-(X>?4Dsd?H=&TJVw8dS4guWXRDL=c_SQ+~Y#m zALoM&hzfLyjoZ~}qLJ)pylj~$+YotS8YvX3$aNf-R~OiAbWw^ zy$LV-Ei=b12%Mgj!_aF?;F#sfG+f%)bhmy8JJXOTOcTq^9JTC>glH^^9J69pTLjhh zIcy*kWuWArGRVK1)lIkZZ=R?!z>1dnj0YmM-4t87 z-(BhA`&HNWQ%t%f`b_F~ZJsI0f2FM~9>09e>NWEg+6ts`^3ng9z8`&_iPaGgi_FH^ zJ-Vju=XkwbC+YLtWZgj+^XPp^?W*xUY=WPTFUZ7^K z?a~sZuReZ8d^*GD3R~?g+wtT-(L?RiW8|vfhi^=`L-V4`wB~G z&%O(Q$Rb=*4Cp?48ewb72PvjdrmgoSy?I&cQRF8WOFFubuL>@ny=~*Im&d+hj!%{J` z+LrU*Ab%6Qgeo0FgkEKzl>)p_fENhxe4?TMK7ROIg^1=64ZUsnzW`$9W#U;Tz)J+U zNr0yi4L$40l`OmeWTK(J+KTk$L~lj+E@YY-bSB%N)LE0?OZ9+d+zgd8(q2qE>iF@x_iP zpi)v)?_s2iNo++rqcBu zDxzRVARMjc-!-KwW&`-3-h*u4DUsfp;G#U+SKfe*(j_;g$$ z+6inC;V# zXgCZ%n&TtYb2x4vfy-Q6uJ(~{NH5V=ANi03VdvW=tk5uJ3K+pR~Eq*~SG5yL%YVV7<{c9ho-j{HB885to%d2?s zTU>sJ%kOdd11_)m^zr$R{QFP1`Dc*$i;vVzAySyG(Ma(fRYdexJZ>k&_nwdFZ}{UM zDC$3Pc@uxW?Z|OQ`B_n z2`Aq$#HUhub!Q+ryLv-Cs4Kxxr$|HHzz=YPFui^8qO>r^04ej62t)@E5=r$Cio2P#993^e4c`>#r%v76H1XIoTNpEkj zX|0v9GplO+mHstREj5&sa&NW2o(*?3jkDWAvuD=LZqR1eH_oo9W5ZpayFOB;{;0XO zv;gNQ83qhY8AvYdM;Np3dr83`Fs}dYCFLU=Uh-dD{)fxQxP0OzwYV53>iTf0Lb*lF zcSI5C*1~8!9$P?a;g|wam2m~S;>T=`_QP$c#-0jdnWa4w@b(8@Qaw!VjQunfJ#Hk^ z2>TDaW-nP-|KaY(ziZvQ*zfn~}D;2tF zr5U`HX4tk;gKaA{d>&hAbh?#BgSEWN7Pg43Rph3%>UeAEc868uX4UnGFlTK@EHQKgT|q>>+{#`p`*LX?WGaw|Xvt(% zqU)b%!9Np~kDOIqS6@>%qkcyHtm?Xk8THk5wXQq>UfL?qOz)&ZUg&b?_d6*hUarWJhf6Vh}sq7!*K~SzwHAA<O)r&CJFV-O6}`O^f28)7G^_ zyXy}BCw{PSdBgEdf!gj>-HnIF5;cd0lZ%$ursgM?EM0R-|+pJb8EnKgqI+%!_-CX;Y7e25d)LeT|Z;v__J#@z~^1S0^mZoVv=H7Zc zyfoF*T>G~E^`@5$2DoDwDeuCapttf9f*0X*lsdap)T*Cm+3KfR@FHmYya+jZ5&Fkd zpk#H5Dh^K3A*Rou*S%A;pwLIE&y`2C*ri8Q$>tGNM2{#uqpm%oYWyyEHf48cZ-2Q% zm5lCC&*#$}N^pl}bQlQp(sBLaFsNxWI7i?>mYN^Vk zmP&=A?MeI;A8@hpeIPiD^vD#2e;Y9wb%zrg=Jd&ExUEe~7^sjy8y`K9HVYtN zt%A@Buu1`9hl+7wtGzgy7(O3$WD!xhx3;bwu@{k8dnLFjiHIx&EllTF;rlmWw6y_a zEx>@$!7KUuWeV;$*LqmG7=?^=Ktv-Tj1bI)60xWp#S7nr^>vW3eI2dQ_jQ!e_I0oA z>nOPObq`pvfW5v_D!YfZAljphdRQ1FoD(R20h5bDqVjQvAW~clogVB6MBBB{=?Sef zwq6VQ4`B!qu@VV}Qn9XJM`b+Ft}z~P!#*e}xXvxRp&z>=!K8*^5kwh(9lUiau$OAQkhw#DoI9^K+k%HQVAi>CH08vbY172=mvgp3-FGnB#z9t5Xu zUa5e!ku+^3;|)Y-Do}@m4gv!mh>L=q)XX_}tl>-cEknAz7A+OZiW(m#l_u(O7Sy3= zvZ_56YmaD9vcncLurd@)`j@O&U+1rJL!*F=T3(ZeCpQ|kU$UzQhC{Q7PJHAiY%uki zG!&V}plGtDsw=9cs=AqL)rXbp$^|W}n(c5~oBt%Vk!s>DFP2N}Y(ZV(;|grx>THZ00G z2Qi$-YmrE-o1tCm25mXejy2G#2bz^G3UnehE5mfW8%z^`X`G2^l8I?ZXE+kk5>?Eg zuS&3WgQDgo%a$!XW`!HXtcc@H#1$su(#~kRgw zu@3i}m>T8c73sas_@~7UI@T@aCc3d^!AkTlFooF_HdeSvCN_T>o6dQrG`nZP3KQG@ zCbrVfc9~z?m5$Z*Koj416JLqWf|Uuaowc0ACoGQ&H<-;4wq$~i?GO{&p>ju*CSpmM z`6O|6M0%)+bdHR4XeXAvQWnG;v-Y!s5A~=sO~kWg#QPa`XH_r~>k73+0tu$os)Dgj zw8*IWxV=cf9qZuA&IMs2M!3-=JhLAN*S6W!Ski#1igoE8b(TqZwoJGTn*7wRKxkG~ zRAbr7hR(-df-bkEBI&{_d`a-~uW4?tGE#yEG5NyRHu85Y|R4uwzCLNdcy zC(-*!W^6DPZ40vr3O=`RGY#LjP;>1VHgPN=y2V4obz_=YM_3NTCw;G=K)+XjnVT|< zi1h>PUKrk&Vp9$*H*CVeJ^^gHfgz4fH$x}0O*d)?J8nh}#|6<1p^-$s3r4W*0xI?j zV4A9v$JE5%mVby4!RxMNX@m@NhT(XeA;U!+Irecq(03g zAG2|0o5$nv=}9e^&{78Ghj|m>`(bLXMO4QrM9MlnoPbpqzxO?I%NzxJkRG{Zj)zV5 zOF$Aw5gmnEe>iGtfbEh(IETLV1M~|S{UJoceG_zJo&g6yO0SPU>kq+TaA(#`>BCCLE|>JP~UPM>J!ib{wWrd`k3X4u9W6bez&$ zJBl&H2zH&s64jnh><_w-h%O?ci;3uKM05$8r;`F}A2Zc;*g8Z+DI)5^JeJQ85CMbU z!FI;l^puk&L1u;)Yc_}%_KC1NWBK}TDd5tCeMvv%zG_+cANNWppMN)NW)ET(2#y?c(jcEcr3~w+N z9Sw*b2{py0kG{M++Es=Bv2UX?7n#tmDl&hwcFf$U{nMDkd1F>;(O_a@JQa>bccEPy z(86|&i_rl*uEk@)4#+S*xM_T=)Le^OrOYQ#KYhKHNQPrkOnAZj#;cgj8!&th28@X} zP+$~M`U1xG&h?2lL%fWkNu2V+PmW>AONhEC;XX)sji5S-f<P5nJCt_Xja!&7RZI4gqPAJr9HLpCrSM#9}*hfIbAZN;W|FrVb*7kTMPb<&n zhRiW#NWcNqGj)tUsAsa`hj7AiD#BoBF+*xREjP--~0u1uk+ z#m%*odVAE8KEEw+`fZ`~TP%W@jh!a0P>&DQ0GU!w2K3?apE^W{!9iK{&4O7#+vzqdyftG5x8X)9VV zq=6IY&=qKL55tMl@(8fYHyrf>>MLPqP0K|ST0Yp;4nYDV8*Y2>lp&7T+YA>z>ecFD zZa2?~9#WtF5-wl%7z!4W3ZIbz9heA&)?4g{Am=lD2dTMs2(yh0pZOpn96_&OBP3kP z&|h%89Ou!^9p**V2VCY#HPpY)SIqQ-Xn8QB1EWhc6*tBwgKP1PCM{)}wuC9#0wSe| z4GL_-rlJxlL%7Msj2i4;UWZM=uqI$lVM#>Arb}i(@toTrl?->DWL*m}ytMei&qclB; z;e5f?x${z8$E}&A78d|<>4Qu zL*|Z;YQqpu#{~#~QUNyb0cS(q@wN2}*PO6&WvX%E5^e6%;}&GEpq(fpX$+gOxUdYq!j8d5^E1f(a>;kqp|UUhu?tpPH3)$<#qbASBKGx zfPYf*-7tErn=Kw#rW@~aMEHJ}ul0DC&l!n(_G8Kr+i;l>p?84^?rrQW#;#(*j6%W1 zgNqlJ0$d7lDZ&Lq4f$|UaVfzCBM(Z?n3_o~40cE_TaX)u$;$g))JZKE4>9wx=xlvp z)Ke*)jbB?*O`MN=FbUOet+kR>ScP3O+Q#U^xD!pqE3tH;CD=+InsXj+5wy7hV-eYa zVNVz^c>E~-ev^XxZ0V9Ib7t&8nHRv0Ey5sE!g^OBnmSgGO&(TVmFTL9$6}GHXewS6 zOSIc!D0IM3;|fEO1BO~x7>XS*%&=lOD%}pSzx2U&m<#NczDYHGziWfJnsHv~6k51N&>kAa~9X%HW8m9!I;HhQdHm&C1KCkH( z9bQv)zup3EeR-d^blVMY6*PxeAFHo8iq!N8IbPsS)xNJ3nT6(l`@XLfr(e-My;WvO z(722t%vXlVeV)`(eQT$hZ}ZibWeZ#SzNO1NYXfsl<{*=@(ddIrT>8>T%bNLpYfx&w zRMg4NjhoU3Pnr3OxEwOI&wGQ-_eu|+G@l)4Ep1pr?6O3FH*_mlBni5=|;4swmY>UugHK zr9|hH5}jL0bY3aZ`K6@TosAa6Q1aLy!&&p>AX4cGTnxp|YW4UaDyN^}@(3;u<6_mQ z%x>fg5s9FauA>kHO&SU(w4iIF2@+|j;6Sj$wUGuL6N;s3Hcana7l2BGqX@{*A6S6K z2jAmaFZWG$yVGBkOP4}kb!>R?iMu0IPHe$$T2ymTOPep`J zy>P!lfM*JDqX5qm;MoFvm^VG3&k^n)F2F|!@R0(1lmO2a;CTW(Uw{_~@InDzB*2RW zxJiJQ2=Gz?K3ag632?Ijw+QfZ0bU`%D+Tx%0bV7*s|9$C03R#BYX$f?0X|-UPY~b} z1^7z>{AB_DKLI{TfZGJPU4T0TI4r=Y2=F=qjtFq407nHlCctq4K2?Ad0-O}!lmK@L z@OlC67T^s6yitHp6X351@aY14h5&z6fHw*7W&u7^fX@=(vjzAZ0X|oN&lBMD1^5C1 zzEFTK65xvk_-g`ui2#3HfG_nD&1I5LbeS*?Y!Tqg1^62Re1!mCDZt+p;Hw1qY60FV zz~2(!YXx|l0ADA--xlEO1^5O5zEOa`BfvKa@XZ4JT>;)Mz_$qStpa?T0N*aacL?yE z0(_SM-z~uR2=KiEe4hZ{FTmdu;O`6Y0|NX50sf%?KPbQt3Gj~u_{ReL69N9I06#3i zj|lM31o%+_eoTNL7vLuZ_(=hNN`T?aL7F^#o)O?@1^DLz{Qm^_7XtiC0e((^pBLa4 z1o&41{GtH=T7X{?;FksX6#;%#fPW*vzZKx$3GnX)_zwd7ngIV%fL|BjKMC-k1^6!l z{8s_~n*hHdz<(EDdKe}()1^QJ@gKK2rF2C|R(PC8U@*gNTP!qLM0{ohH47S4VrZBrfo z4j~^P`* zfAwHXJo~)(R}X!I!@vHkhc4ytOMmsyc^tmuZyvUgh|isW^O)g;cm2&n*YJ1l{#*LD zqu=n*R(^lX8y>o!!(-p@u_6#u)DJzhjo&Z%&_mzn z@RpA}bSsB1|Hwl(arhe_dDx5xpDRA{nCtbWs+TRe;!~!2=|Kh&4OYFhox`C)Ub79g zL0&ko*ypA}UNf{aIyC*xe@1%gC;XicM|$Z_4u3S#YqrUOqtovnJlbov|K!nLx{kj; zWpug>Q%8I0W`6&W(djZ*j`q^E{C?GFFOETFpC1eO?-`S(b?+E2TWH4T+Ob}`L4TdL zjrHQdRQ8!QF8%)OabCKD-#=`e*W`f{{ONbzJ~$1BCVT1I{C#b5y1pw8Nx#!OEe%tp z*X$RiGF{&-jp=u8n3aZM^l#$$OO8(8e|AM09<ZJg`|C6YfPU7%K(e!U8#M1Dg0(`ju{~(@z z=QRO-_|)|M*9G{xMEd^20$iR<-(M-f=L_&p1o(TY^!qOg@UdO#`{xMobprf|0RKM$ z9=AUI+XVu=QGh=Y;0@jB_Yc^Zh94B*RbNTpfBf_`Tz^IyUc4y{M+ErI&FTB4XQttW zXQknj1vo0e*9-9Av(xX77vK{Gc#8n5=cnI4;=(li9|2x|N&5b%OVjY*1^646rSJPL zPs2YK;131(=5MCox$deo{D}bn;o9{5aKi!&!-+eX>U+~K`eA)|X_>C9S@Yt8r z@US=1@cn;J!?Cy1@V);|!{gsi!*2`l`yZt5H-DIh&;K|*HeT?tmj(CW^Y*9dcM5vF zW(>hihZdMRW&06n`0-U~IJT+4#Pi~&0(0zrdRn15#y&Hx(A0N_OfNKXUN}Du|9X0{ zNw={&4c|OTHT6;Dg{nEGRb8mkclfw5<3iOO4@W(%nqzhO=n_*eyzxSb`Ocjmm6`V+ z_^8ah|I$ZgrcQkG&B1g#$N%1&gU#~4-7|!);`a}lGs5&=&HmB|Q_r4z^$2s^`{3#k zrmgkUt?Bol6yT=>_~nO3n7Y;f9oTZswQ#DHljp!C z!k#l9-Rfi3tXjQr0drki5U~~Q2Ny4D5fQ;rCnCagSBQ`aMnnWJpNI(0-6Fb8La7r2o5Rf;trn+hd`&Uz4U0GXS4{QZTFIlk4 zuDP)&gP=x)GMN1a-=={Q{pRx(FmJwb@`(c?pM(gGQ5g}!Fne4en)F8r5xlArqDjxY zL{#ydga|HK2~ou(?huW6`$!29{JA2cF>hD9MD+2uB}8xrONc(++!qm+@T}4{Nnrsf zX0O4MEFe-RxoYW29vKUK&;l0UBoAUbTy)tauOih84r~dL*EJ%qgb3bm8Ijj*iDb5h z>s&_UlC39she#!Y-(5!JlC39sCrXImw3iVLbz3!=8{zSn5&7LB+9Z_-%LOu`qg)~? zmiY*44HBXPx7|NPMude536ak&qKPshta3<*hPp*`q>KnlBoZROTSS{=L|9*u5FOR7pjQke!i0SK!=j5tk9Zf>?wA&K>QAUJCI0@17 zZV|mJBf<)vgy?m*h(44NVfjx&w9_S`SznV8VeL>vH0x_F75`B~Jm|#tk+)&yW#ejaWpq^bD76)bTAD5f+$5 zL>Z)BDW)C$2&4ZVrg4K^o~o0T(@0DgmrNd(Yoz!5#1+O4U6g$qWfI- zTI4X9Au){+5k(GL;Z8&%x5*{Ka=wJ;7mWUaga{!FGNOCjHTDIgACwRw{y|3cL$`sM zBiHTkuKORkU#=P=sU$@AxvbjH9+G_{2*VN){p=x^zLBR6{FcN=h~W|uJ$2wU?yC0G zf!9ii5CA44y4EG4N0JgEM2|^`9&y=gPyO*-2@yiiBt(Dwhr1Fz_eWXNB5qAY^xPj^ zYTD=L%8iYnHxbeEbFX$+qURUHq^coePC~RG;u6tH+4MuWorGxRk6j|_k~tf(dJ>{8 zmt*z|Yh*+S^b--iu*T(>{pxI49U)3kMD*%xm!{vVOJrjdA%+s7B`%H8SKpPreuz($ z5WQ_jzvd5f*K73SUV`H4achzU2Mf*wU%U=Df%ovV8vkD&JXVr5g{VdK!gtaNi>-Xv?l^Ak%uj+s`~rZiKq}zDWbx2m#FTa^O#gB#AAx6@Z2S;Z99J}Jlh4T%A*dIMgYX3il{1&n&P%p z^L{T++7ZesqMG;n%iN+`c%(d>AQDzYweU#Yym3*%g}2M&00LdsGGv*`VE9+TP%AJ6#}S5RR3?tNVllA?R@%3ap*(*wTKGOT@Er2&iS2$3gO!#Dm-_I>df;dmWri9 z^fyp7@Kt;~cZq7=%AcPjqC)VvhzieLqI&T7-%6!I?74^v&t0OLST;{;D}=6#sPNn+ zs?|g0-Y8ZOk?$fZJa>s|!MxY^7f~T_UPOiGE>UgU`KeSv#NCUi@Z2S;Rd)?~T`U#C z_C-{9?h@6uoobzk3Q_+eDm-_M>Jv#jW7B|)>JzuxdE3s%q_)DI0~yt0Zrf^N*s^!gH4uoON0B5wWeX<3U7)=Pprg+xf{b5fwH}h^X+~C92g!<^@Dl*l!`C!gH6X zesfDvxrhqeHAGZ+?h@6+vQ<*EW4DKh3eR1l+P3pw5;I`4h=>Z$U7|Ykyb02Hg}o*s zDm-_I>cQiGC!xYt6%iGlyF|5Z=O;)3ZpMsYr;CUR&t0Q>Mrtc;l#x+A8lt^D~D zVyUptMnr|@E=zU)oW~?)z&0Hb6`s39HE-q5i^Wo5myd`F&t0N=b;_ivA}VYW5>er~ zOH|u-J}Wgl_85t%@Z2@3ze%XDMM*~WH}|MMkx*fWlZ@&Ux2PtTHPwr4g$+_7Dm-^t z!P6r{CFOs|+s+TAQektL zhzieLqk2<9g}r4msyE%EdP_out!Xl)#=*`u5fz@htf1AMgN<<_D#M-Q zVm4uQF=1bwh{|v=xj^+~Se|)dTb_vO$?#6Mvk9x)8@u{MREFEzMX9VleQXL8Q5imc z7pSZ&XxLLIqB2&{T%fWpp<+v-h{{+(b%AQ_2Ty!WltJuh6j9;1OTMxO2w+2`h{^~M za8W92gb4Oiil~eT5f`Yo?PNK+Ohu3Fm?A1XcUi%0J9kLpjNP0vsvT~{dE3q%lHHEY zpcYi_?RJt%g}tOQDso?{*CkZgiYlXeJqJ`$1+kOWg35gbKR!@oQEY^jQGI-%>mK}6 zG9a;!Rz~%ydjs;*3b9n!hHF7p;kr~i%0yJy#Ve!QQRW_1qlgNdfGwyR-J`l&M1?)X z7F2h;L^bQO_$4ALY(W-L;kipx+jf3DM?{4k%pxj0caLhbhzc8^EvPoTMzy0*M1}p+ zGO8Vgu2Fp|F$1<=%cwqe&kUbRrNZuQ3o7@e+JPj><|vBI-!iHl9@iDzagc}#d&e!P z4swm^W2u7JdM=~-*nI^*o+OqEJJ&6!*fs(e8fVsJab$%w+X@@sMO1k1x`I0zL{!)} zFQVGEb4PUgU`MNZ=BWHk!3eR1m+98z+DFf02Tf|Z!*@K7*&s~@5 zW2vo>D?&uIZRf{!ZDkj(ewDWR+hVDZYC=SX=O|V2>h5sLIDf`z%Nz1j7znUzT^4Um zR;9Ybo$W}Z*asC(HnDD=Lef&POh|KKpu_?;p6iIxTNR6rU9f6NG;oX!x)L8ri$chh zA)+fWHmwNg)U}KKIz}Yh6$>a940$$yY4Y%8tgfZubzRA-xRwm^g?e90?ATB;91UPs zp7azaAZ0>}lpR2Ozz7{}aU`~0v%_dSa4I8megIiBM^@S%OLiqAUF~5zjM7satdyyY zNFM^U7jd*IlBuTxb~w|ItPCi&C327e;j!cNN|&r>4QDWo)RNTXP%gJ2C8i<{4!oki! zG|;Xk&>B?^gsXz7NGMVzl?t@0LRuueUQ2A0i*%_&k&wIxMfzb%Z^r4lp>`_em<*`S zb0`k-2Z_a*n$SYwM3vFdNxhA8Y%be=`kF&2khut@_}K$`qg1qOu_}xLRiRi_C>hU@ zzTf)u&bZt`IDknUMZlY7OD{e^bSslpU25&mw7*ShBHNO>NzbnN^{xz`8(ZAdFIE zD?(NFB8auw>d;WgTZQ5r@|4akHKA}a9tms=22wcRxH1v1>J0U1dXyDsS7j0Pi88W2 zXzq6?7?Nm-1)H6SR|aFzWLKw_Kq}Z!rHs6?U5j-Fa^>!73zDqWJ>8+m$n_-_d0aA* zG^Jl0W}OC}@ySRsm>x95pIziY8@a_q+Ed#jtyQ3}OMWnr%0u?YW~zYGD2U8vD9NFm zqb9UzGla3-GI}^Q#l$vkMlg~2w@zY)oN8hzSbGG!cdb1RaIA{cpp3L`QgPa}TA`Qo zQw`%~BqFO^>A)&TD<_tvHWcfQMq+`GYn|-WY2!0v`=&#okl#)$6s(K3JgkeF%;W_| z5}WEmhf*Qao>;1}sbrg$qXL~G{wCQGh=-%?Oct%8aHB&(kme5snZ|``Hd7O!WMyz> zO-*%Wxs=n^Jznmdz zUL+wzNqcG|Ox5GL14&)gH`dfT>gI1bGz~Hxf}k=Z!c={|V-+$mfm5p-;E3=7hoT|z zB8v8dBlMz;3CwJmiN5b{sORcFn+lzhxi^@KPj-b<%wDkVo2zCYC-x1JKcYMbp33{? zs@cc6=$mTCzS-u`0LU;2f@hqjH^6LDgGa(aEt(8R+baX>lC^<#$z3or#+%6c$kg{8 z3Wt=JDBLDqxEUrI-M(l`#GdvaArX=tcxs0t;6?Oc7hnJv!Gr92txYo}eNEL`>z zkvWm#7sZ`1sgr4bJkP3K8fu+q<>xrG5Aq0u;G9W1m+jx$F1RKz8EgwAQ<1DQ`iV1~ z%^sXOE=nXjyGyJ&k{F{Plc%zpt1MJ2gWrvvlx@N0o3ij|DGVB!kb&^ZbBv}unuS4U zz{&k3H8UI)^-nC-5Nm*R%OLo_$MvQ>ij57)wt*N5>-3>e+mM0<5Q`?=(7Ds0@W>C1 z!uRmPAEc|AWHOTH$f)aq{A=$t`$7V16jpgcZ|Tv2+UglIAk&5iD4R*xp!ZF7O_JR} zEL(cfdms@P*YpWbnFb5bF{2&Bn#rT4lRaM^eD`IyfD@6T5P?Ra2(eq zbHzbgu@I0A*JTc6Lu!1K?Ezl4v06>_jG5Ird9J6sD1%rZJG-Oq9}kQY2Q8%ON4b7k z7S%lt|9D`OLo?{gvcAUI?yw^~Wl{4U zh(P(SYmD(Fv9A|pWuAuWnU2hJg+qhj6bcZ$wK2w+XPTp1ORkX9urjgM*?M+bwZLf@ zDAS$1OryDjEa-adJv4_}*vWL=wO?5+b_>qrK#AUdOYasu&)O}GHI0tlVn=w&!j>M9 zFb)6#;k!4-`Ru8sCoAEGEWWvKJMaTe83Dl)uZlB%m|5rCj~UDqN7l%K(#cN7!6zu* z$-H=@gOSSiNU(KQ^~_nd^;PY`P_!x-bE4jmg?fex*>zUk_U$pTvv3j%3fKL%-dT8_ zwX^E8be0|ADGL`JDiX%AFCaXm=~T`oiw@07xS`g0V(8=|!`U(*IIHPY#wAC&UCqeQ zx=tPDdZon4G{ylqDDV-yz!OtR-IJ?DLpiS89Jz~iweQfQKN33>XY`=B8_rGe4n6v# z>>XOukjHqlR2t}TAP@*Yaf?BCY4(Axp~g8RW0S*pgHwk<@WekP7$=QMhLSmU$V9{` zbq5k!rMW7SUik{fGBo(o6=H+qz#|mnxnq*N!I!RZ(crmTi*{Oad-^L54UQw6KycK;6l?JPLy=%*vLl>p1kz~x#&(JUz==^HeE=uDpH@@b zFtbLqzT9{&C)rcZHbEHqqnXlf2Ao-i(p>aiz2))TMa$=|)9bcx|GU`bI3NpzFIm~8 zclq}1f6q#|K8qXAZd9q;{+bkLkJGq7_>qV~_%#-1@900Q&tkFd@v^k2MHHdIc5AUJ>wB|DCn4DnVo>Kk*KwN~X;8>e{_&Ok$PT6u9A2VkwqpADx| zqyY|QLjl+E0ve95{MMLeW-CetGhvIvxQ656P{J;wM*}sD^;i|jVOhO8Te+-rVSA~& z=@U`hadsUFc4GN@F77vdl3m=ZbJyi%OD~i*M&Y155WeeCoiLtfC7eyDoWvcc@qyqE z9$jyUdwu_jdp1-~i+wm75G7mmzFx9=!GF*%%le1yf}_KpiLSp>WFj1BhzcD4UN>i= z>+j6km-W@oP9;0SQx-K}Ari*vi6Gpy{{}`F&$AQG!xF9A{`6Nx!Z@lCgfBfrCyeLW z31{(y*wwgh`}V^`!Z;TagnxOYL3sONE(qst7fe~W><*DI4xt3$H{-mi7cRRaE8&J( z=Qx~ImLU^y*vCA3;}1o`IPnsMH{GBU#&ZxZXo;;|j9mfpMuc_?N)Z(f%mk{I-{)PvXc^m_o5dn?w*Ku1 zmo0s$TdW@rDh1(RJgXDN^X$Bq#T2w7TzBt14~c|vDk=!S^ny+p&$AM)&%)$(gr_W8 zwx38CN3eo$?Wbl_@0Xo$mYJ;`;kxbDOU@ab_X@%{oV3vxy0bfH>Z_fdGj@cVt|^X+ zHOAqxAbfA9P8iR#*0{08*_UibxNPayeIj9;WDCN|_jJN|o|SMzUR-^VV)w; zdsEjsFU{K#E?au((;{J*$XpG17$i;C6t{{s z#);7&{L^R58nIQQ9U(>2A? zo_ZW94#JNeZW3mD>K(bdF-uTU2Ii8o#NqsM5KhfA39~G5SqSHDb2VL4+%7gX4oe5& zr`k-y?b(|;kL97JYl?@8gmE%E2;X;_NqA^>!ue>YMa}n$gmDZ!2p@R4P8iR#60Xm~ z0;$`6leCP1Gv`70FE{Cg@!SRB+|^>!HN|1E#yH>}gq5F}O&!ikINLs#3|uW8jBvn4 zo$$xYPd7#`b})i7SLb1K)&1j!W5gOi$O$j|rcM~ov(~siKRJ$wgjanNh#z zEfwtG6UQ3oV^=qAsgUHj^h}-bZ$2^!XP4uKd`7M<6_PkDJWD71@yJbjA8)D1E>78k z%WX%lEfvy`c`_$FsKO+ieaOrf;*x>zsbU{TIpN4OlkllonJXV3NYj>zlt}n`PPp<& zlQ7E^l7+c)UuL)m;p_%|KJ(+IEfoo|#^X8RinC3^2^USB``oE% zONBIBJdqQ=@fMSC_Ss@SffP+!DkLj&3n$$Cv`IL-m6RAiqmHsmvR+FE$H*wo*+Os}!O=v<@5hi7l<{0N^d62>uMFzDa*CwzR`I2qfID;HZ&X=3N zsW-*DR{23KeI z`sC@o4T(*C!7p{f=iKpiqsF1EP2HHs0(#Td!ZSs}r@f#Pe&*Us4dyyCE8+Tle3@Gd z&l3s1@uE)nsou*B!slftoX>1=YvB^4Hud`-=r#VtyVW3^%-Yo10%2?kZ!Nq)B;5R=PWZ9E za>82+FUU$bTa19yPN(xf)(O_eu4UmeQ{r8TU`HUS?Lyw0acLZuj4$Uq1iW0pOVY?o zGES?hsjjV=RTan~r^G=SNoNbrZrWNX9l7%Mr+UM5|7M#ZZS2SuXUiyy!(g?g{)i}Q z+FB?b!%)zx6Rx`OI)gAfh9LuC+q?};TMMNlLvA{>fXyMkU;Z5fCp$7E15UmbHJ>%M zt%cI*4cm{<3Af#LlR=oB-jIcG9)|6f3dvLb_$r<7(ob*I32&*$?y1hUjnRpHW1Dn> zvp)I>6QpvM-6R=Wmrq`q1I!=WC6#fK=NEY~4(G)f%X72jl9*+xBXv=boc8fOJ*|-O zT-TAmWDPPi%O;r&5!X%|v$E~GaY|VA3@_f9ym*J0dphEYWK!P0!v~<#G?r4?sYDI= zRnk^9Y^jizKn|I%w`cLv=M9d|z66p_OjFa=!gEEPbm4rR@L#)sWytWkE_9OfQl{NV z_|o^}6YYOJy_j*()errd5q{}=`hm())MLrORj!{|8EDIOgI~7%v`+gZDlgOvb^C=M zutL=u8nIIAO2p#Yu5EjtY+%b`9(>25=)^9l;w8L`mvCxSs|=jR8qdI9*_ms?+#2(z zZma3Ek6;Eb;%mH!l{uxVauALKu{}5&GN*m7qn_5g_uzZ~$GTTf3FIOXK<>HrjMQ-1 zkvnbgFCSgPgk;(ipRfXt4%Ez=#d3wY%_~$dUEDLuq zo-No!)Ot=GJSjUWr`EdjqcYZ7zkPW>R!JWe0nSm+ZjT^pf%HU@kIHFGo5Uu_jpk+=S39~ndO%^Q_l{Xr9>I( zdX+<)zTGo~wQ2oBlUbV{n(C~KhucE>4y*RoNM*McZtuwTXo!kJR!{B)~cyo)Da&T!#5T1`Bx z$QBVkBBCcbq64Ssi12ZVs6aY->?w|@!9-NRP9Bp=Z_e2=8&T7`OixL-&;?8v+_BI@q$o}P>a*CnS1f)Ter z93uU&E2$-tZhwkwlu<1;{nS`;dTPU|ClirELPN4u732-qHm2*5k z0X|s4Z<}jT-C`mYhAT6;RAms6s+8hSg?dzlzopON_w@0TS{6@&N%t z9*_rc<2=X>5E4Q{?ECwldUj8bq+JN{_x--McQn&gb?VfqQ>RXyI(5p*wMoO;Z0EvB zFDut(o$I1*(MG}^;h#jKF5ZT3l*`V5Yvx6UEhYmfxU@7_I1g5MDvJ0Kuk$z_K-p&0 zs`DP%tw&^cpewJJ-@$=b$nQVvICKTlQ$OUqtcyDK;tx45+vvR5ahwO`zirOr&J`bW zwr-#XY z+*>Ylx+zfW=D8M+lVOqBu`&|_ZqS*xGMZuq7q)~+t*Y<(*6 z!AAVt%$zNkUy70Uc(=2OIo;d#mUa!7cMS~>iJp#mWpEDn5MIQbEjz zC%j}HBREBz%DflcEcx-x7HQOXjK~M%dq{H(Z#OG{n%752Je4iY2Ug-SdCg<7C zE_$J}Wz!3tE!SV=IGg3)_S6$H6@S}Pt1=aT+f$ciD*mDiHoVXgGDM7J zPy(`J{LUv2dK(QZX!H&|AgQ-8r;Tu*0QK;Xr@l$1;;*95i-EvK%_*A( zj}(qQ_(QD!C8&Rst{?Nl_?VyJ;IdHfW7^1~y4Q6vEFvL%oD>2}7{TJziqHl9raBQoZf*aNh%w%`rFLNdbH$Ea} z*UgVWw|vCey7`hvoUIpadc^5=ps_>mfHAk`>*?>`Fz-1I_4tGG``OKo^KTm_2cPXc z{+2GM+i8TYAZdnvkg(H9qgjh*SmG`4fX%Kj`uzgOaemctoL_SsXV7sREC+syR5z!q z;y4cUFw8Wscbu*_IF9r4j^n)1ak{{6pKu_Y#4HIV=S7a=oRG@_=#M|!jYQUxJ*3aI9q=GDULHC6W{7MTd%%VzPwGoJT3oz7?XD>!97#{eUAKl zjpJ;AKERNv8y~Jr*&+Y-$iK_-?>S^TD}VH&_$CLM5Mg^A5PUo7eTb9nI*e5~Ljpn`89AXN*cH?6hA3O1JEk642@uOBdpYAx_ z6UE{{mD5ci1I@aZ)WWENrSHIqR~s2Am5Qx+c3{LS;VD*^DnkRy^A*1^U#S*LMX!~F z1HgTtTqr-oak@9*$JOc!Nv{Vb=R3{?vNcIj$<{QpZg(Dc)?n+chi#s|=m*NvTQ9l> z9QZ@!W=FHK10GiV+?kbs>6d;rN z5RwwhBClGFcpMk7QrlgZIywI00kKZY@0igcX7OM~ugdS3(bad%=r#Es_5t-B7M8o^ zd(1I+$?s=3I!--f&V@b2b|Kl?1?TrYn?78-$U#fe59a^iXaw4b&*uGZ~<-P4PzEDY)^EUy-3*8*dg<}22<{gL(75>{vnz(XkcYy>B8 z@3ZY%U@^05G4nH?wzgcR+j4yBz|9i}@5&*SeXxG(RvY{ckK0Yi0e`6mzk4trs%IPa4n@wd;J9NZwas4HO|fsq)Q(2k2vhK1Wt93$a^u^$J1 zt;Qo|$N8d!gTG&NCI`RZIKSvPpQFz|r_Vp5&p)NlKcLSq)907y^YiriC-nKp4y-;` zlOc|T6f8f3*id=mi6@@;6y^COeSU&Izet~dM4!J;pPwNJ7Yhhmw?Kvg=g&G0S#qv& zoUW${Ik)9+02fmmdi9mBbevD)#~>#ca6>OFXD`fmDlH>FU$2aiqL`LG|01sqxqwl1S9 zG|4YUWgpq-WJt~qMBGa_Yb;d#h}BvF-FLylfMIhvX*E%M-$1+)C%hp$ghj1@RjAzE zRPJt7ZXfW z#wQEYJQ0}>1&cYzZb^-<=jP+NmCXjq6y$gh&=Tk^f2#nohR3{!lYZ7uZ2O14wXg( z;Zmv1DHzzqs)UV(7gWLJL73>i!m>#xHF>2T&iR2V2l`d#E6o9~&Ldq1x|iNo>OKz= zr4i6hyY>F=ut|3l>2$KC0b0cC-im&$E1}n_YOok(7A+o_^@FM(=oV#@MO_*uw!iGs zBKhu^8*H->L_Hb;_Ks`_i#(`?n((wn^y3B18bp&YDKAT+sAf>(=slQOy+v^jF{zZv z|0YxL7gsx6>^NI)-2hEWuncXrcVAiIL9;MlUuqPZ^U-XfT3NgodexPrp~QZ8qhC?C zk8gCG?&p%v%!FY`ydVeuj8Efd6_0=CjsF;RP+7aATW9Q9h%Qs;#@Y(*8WdjnLT^WtU{)_em5 zRm??Ra~^90EU5Mil^(($&f|>vL@Xm^yPe*#LX}fz*JiyZd3xv6JOa= zD2XaAVE=TkkWIQ(qL)G+skW}ky5QZ!e?iz zdxnQcN_)zCc(qa<9v&JVDeWC9jSTJPmB@j^2zI0H!TRd4jm}oAShiL|tgiycDZ}8^ z?JPJ>_l-k)2WKn1GE%AXp^?(=U3_fYVuN@;J+tLz;a*}ZpU#4C-=R?4*z zueN*7?Cw3YyQ;hQmTEQMaV~%F|9UCS{qv4f`o&G97jJsUhAwBri@Um`y3K6d<;10Om1mEzCr zEr-bQ`1|*NJU;aP8;vw>ytrlJ9pCzuUwhF{9Dl(3)<5(2e>3>k8?Sxk z>z?tf&u{+Ck9=Y1e|+KVzyGU0|D(lk-LdJZFB-W0FCY9y-2415cm3n{Zh7=wo6g)? zI&k&N_CC7vE1!DfkH78oKVA21&QJ{?y~W|N6+ezu43G&L>}e zQTO})?v`60edf|_zw*xR-+OE8>34nSwZqpH-|_HWZ#cQ-s(=2QKmK(2U4Q#4FT3}d z0~iigO=%?LBY$uAh9}2e*B}yY)jKz3++3-}jU^{N0Nm{>97R|6`v! z)I0gmsQZ^c`}LO(U3u!?KM+3m`la`r{r0Oq{E1I|@!x;`o&WT`9q)a`>?^l^dFWD? zpL_A|ee18LdvCvV{~P#ge|`R6-ux?n@j(BL$H#y5fmi(ZpZu3o@8s8fY}03d^qt>+ z_vh}}-}T9_9{lwKe{^lvh6f*XKK&1WQoj4o|MwmK8|PkG`tYl#E?Ru^hZjHkv!^b* z?XhqE(u+3SaLLDC^|r%5@yh4?>vJFY>NEfCy9dww$HN~Tc>kfBjz8rao4x;d2eC?t8AHL(N z)6Gx*c_n1KV7`{^au7Hddqd6*naWQzNzG;?|JC8ANbgZ zmY?%iSN-YM-+$nqr(X4IuYJZ--&%5i=XL+_*{^PR@PViQ-@D&2|MaJR=NEo;TlZr} z@BQ%||I}*z;hyNOFFsVd{(+!B4#U#;-nF?7IKu&+Pl{zy5&#Rp%w2`rS+VzxutY z8(#JAZ+rOo&phXfKl;{P_dN2!KkV!J_6x>87(Vw)m)}r$<<)yPJorG@*)M(gD_`jE z-+AWa?-^@4_kHHKDnpkZx}|pQ^l0tM(XYPXPd@sF4}a;lKlu1}e}Bu@ul$AQ%}jpf z{%3scQ#XFT93)-*4KoGdcCd8<#JC_xN3}sE>Z<@&9r5s(-od-hU~5 z>GeHZmOuC2%ikKm=fOjN_m#H{fBDo;f9+dW{L%8AzxsTU+mX#>~t^ zAO7akuekNDpZQ$neINUYi{cIApZxA`zWy5%Z~NJo{>MMQ<_oX**x8R9eCH>hc<=ju z{((dHf9tYedCKnPrGJ=tL)SB__uu}KKdL{p@y&m>`=sUjl?{|-XqJPuxTzcp8 zH(ZZpMmL!gXeMZQm8PXYVkT(tcphq*mgBH81zyr@H1)g=RYGkm7*&=sVzVJi>F;<| zNg5$cTPNk#!wxYAkd+Ibfp{?EsQ1`?Z$9${aqdHagpQ$X_Enn6})AknW zbqC8;R~I%#Ye}<5XF24+-X|RM$hd_po8T(DL+82VS(HaOUBQ`!!1z(+S^Ci7gvmt&tl6}&y>>$ylZz=& zl*CQU^B^#vO$rsS&h-jOCBPP!O2E6t3ssYBoWu@1g3u!T3oJs z!N6j|o4O2mCg2H~Lx1z7%NGyn21st1MhFQUHQQ@Yq3r z&WE8(8FZ$?FkuJA*GAhWljC#|>4=C#&UxOHQ>Ld*=z#-Eo)QZUes5_K(=|Ccshj%cGYq) zIlcxar$6!=tSU< z$^)6NIpBF(;z33=o6UjxVA6zRZp8IM4^BhPW;5gk7&Lrqg$W#*Ni$`LARO?{*rBkN zfk>7H5rqX-XVLILqgjs!qIj`6(Dc%aTWjAfjGMIqFESE3voA;KIC|s-6)ku3@&q{B zG;7Q*Sfpm_iM(J=1HmfV%FvpfYo@FiKax(b`SpZH1F(O!0zc6!LfG>xFftooP6};V zaps~uYu$_HczfmydJ?WNkiu-$4y%cb3t2XGgS0rKW?KmY@HSenJ3{9 z3=*opGo)_%jkrOORE7)`nW0uGB#owCw&y~bjU&BA&rn1_sTi#)H$67#7ztKeDq&N1 zA`Bu{Qq2nzFV?AG^JsWruF)*q6B;WJ)B>xJF9NRfrs$aIb4t!o zF;h3Pcr7#fav)>}jzo_}@9bQ2v02xcOA1p`y()0C$EBnQrKjvJ*@A+b4Jl>cYrrBs zY-tX%MGDny^ItYGWkt*;Qgc;T$bQ%LrtOR{;V3y~oB!-mB;QilK$BFZC^czm%P7&- ztNJaBv`W~p78z8TS6!?QG$UT~)n>M!DZQ76Fcj`s07PLU)W9L2HCMj5#QlI^$8Hfah&a^x}5vB!sqpgw_q_MP#sP0hGR{D7A`o>mium5n6Ep|mT$)k z^R&>w2Jl_&TVdF&%5180$6%9i|Oo{^P2@fX66FCCl4`qNw^BM$WtIjwJwU>A@QVQF6=0YxMwpDS(#JUJZCfR z%CsvF*f4X0MCu;UZdQl5o4HG^IPnsNWgf^q%te+=44W)+Bh1al56EWO%iN_kpp;9@ zjqCX_1+0tivXIMV<}QX&!k3FxFY#7yba_x^E-d-MdI}6Nx5fu^10Ae})GkT5^_68{ z&~lux#BXqHbO$`@XBFCo_G>AoWPXe_kaVS}vS!2={je3+SC|)&cOv6K68SXzm@hWl zHRx9C&0);=HP*{c5BN=1^CQ0G)$6Jf@}gliKd7>$c^+{Z31dBKc+Ide=DK~X8jhVM z#-C$LUKIGj9CMG6T+oA^w)uP1*r|oBpvt5R2(n9T@l~Gk6PT}1xirSCSS&I~1a~`V zC5Po#>91&oL z^iY7rRYeF~Sg-R+!WwWL16VA(;_cf;YhlE_$~^O#AB<7ISA&>U$d!ot8X50*dsR#C zlV1kamm&3Km-;fSzU)?C_NXr->dRjBrCieAH0-hlUe?gdyZT)Ayyvl=WTna3{mi|q zcl^Eskn4SCdR#Um`HsfR5uUJ#6ATQ1`K1Z&B+amWvdJeR9Ic`3e!z|%Kf=UBCk28Z)I!$lia8Z^t&FlB zyAFx5+ou4ISF7ks*&-fO?}1RNHjyw2e*d$`lswh+Vk-oEV|>>Tc)Wv|h! zlV-r~IK_mILJUN}aL_+ywf1#|(!R#4)xpJT><6B$dHv?fGHG6;Z(AnK>tbkL!}*%m zHUk1$*JpkxTGv_{6>iRj4)udlqu{$;sPiE4icu>&pARxOT*!Gp#N5RNsiW*jDQ1{! zGZ*s$+iadZWh|X(O$92Qy^{u&&ec(cN@vU0q0)Ksm8f){^=na?a%-qjncVBpqcSDd ztw?3c{r{TOf0ibt<-bvYet3%1lR}k(Koh>6{}r0lx>TL?oJxMudQPo$o>tMa|9S;! zv>whWb)YpbB0_ zrz=Q8&(&1TgH4gTj%J&ds?tzVCm+H;w%mu zd?4UU1GTVT*l%#wL8VFBk=fSKjmyde#AK*O(DCG;YT7FfL6PwTu` zE~=^!FGl#dbd&|_;WH8~bu2|Js<&@bKKBs& z$QP}i=L~_GSksGRVM9zp*23zLF(!4;fG-`U_Ol)s5k%S!w#0YV>nJVy!oUn!#IYO6 zcoc;ZYw#F$8%d>xx5B*0M`v19P|nGC&H^t9Ca`NI%wsWPEa3=`SOr#DC}zwuWo*r%bl?B#gTHkwm zw9W(T%?vBBa^FlJtV#pgtOO`{Mq>`9P_%1@SLz5+pmNU8x)U+HgorWA=lp=oSm#NS z0Zo&2kR+!Cv~0hCrk7b8Ewha#E8l7C{%~XD88h86!@6x_o+P@Ux?(5h?lc8rqfr`68aQBAW>$5UaDmo@8E-odN3&qjn^r6b+Ksgz+Eg zlq_n#8^7di^ACG!e;)^%}ymBG{i5 zS&wQ7Od|?u64XAnEMO1;ZG_Yml<>oV&EvpzAZ5-D_ChZ%EPC}8e<7KN5n~jG_L5d? zLPS|va`iv@f-_-0`;W@kbZZ7r^tr#0ydt3Bn<1U zMnoD|^4Fy{8yL~$AXrraJ$X_r-75t+uuO2tyC95dB2#WNbSv9l@u0l7RsF*Yv{ zRu}+roG}SmJRdHxR+GhKT8cRH<6tL*WaL#iQxvI$LDeT33+iLm!vra33QT2W+Djth zq-sbrUP8v#Sq`%+b(jJtI}S#|O49P`^%XVKi5!woDhOc1O0tnkptcQV*Km-VG5@JS z2}6I60JndP4VRSVUS+_ugL$=tM{Kynu4ScSITn`A7<1~*n9Xt?uwfQ+&?4@aJ7KCS!JK6Y@Q0%fu%U%|aH2Ntx+o44+;PN;6*Mq_e7jLAk= z<-%u?MxpXvta$MMi;Go%&c`>{;0Ba8pg462U%&(7#Y&VEo4m1a`?djOlxJ-Re2hHo zDb;xaQeC?e<`pJAsyQEdF&}fm1p-4UHZB~+BZDW8PESpbPv1N~IJ|qXG*~(?UM`d` z5a%_ZwKZagIAp9^lS^-!Rp2hV4uT&UI(c;Z(18QfH;)gE>}qR`dwxBz1~k^z99UQ7 zDcJFbJR5r|s_)yrZHMrIH0D>hj2^?rf_voTbODS~m@0!y(6>8QVZYuU8#HD}VnZ=a zDySHmJ62~lowuzOJ7~BoP&R_Qp6m$T`6NNmhx1y%;nvVEWE4Z@bAOlCPm7~EajJ-Ta8sU$u|%jNPqs)X@qY^I?mj4S&$Wi69r>eQO!w@Io0O^W zQl;YwKfSW8*L~ofuONNy*~&PW34jCp;Ki~WbhsC764RzS5QD&LhLu)#&|ifcZFhZr zZb9jJ=Y8sfm0dO;#)%pXT9fOD^?%_J6*j1mrJ=Dlvet=|^f?4j&OZCI#<`GO`W_j~ z9N~~>M9e`Ti7wc5q&V_qM^{l-j;bFpy1C~~R%hTNLm2{#lPPWV-CLypp8NK_@ARuvX)r-iJeGm^>nmW$=RgT?a5-r^uhJvvb@{EjnXjSeg-hvU5mUPH^( zhw85(@pcWw+aKpISEYCxgm`<#<{hwosRhOa#a>Kq_h2W~%Z{nAmGJ1M(2J_{8kQ!~ zo~#6R`ZODDdQr@ot3nLH3!X=_C^s<26PL}*WNb*L3NB+?WGYavbHU5R4zR5Ti1m2} zwtSff84kVP93K!a$ZNwtu`qY4S)CSEKNp)pH9z20n$e_{Nz}$pE84VIL7D`t9np%~ z{23EuPJ!>0fv^hu$y>M;yM5<`4QXt!RBFVm;Vq91+on2VOyFVMM^E>do@PB(Hwq-M zfw5{9&^CiE1?eMB&gfwa7RfnSKb4VDHDYMhM#zP*7exmt%n`vWchq(FF_&z%^!?mESsdy~Z%?XtVZUop$L-7GmK-)GF3u3B z19-`X`JmgmL<}M_sErNhlFG8)^}2_!r{(s62X?U2qe2( zm%dvR0Epk@${kXO9-n3+gqyJNj3W9P)uVQh4}{H?2zQ{d-bx=EER}`}gQdaUjN%?K z5%}mv3V&3LTKk0qARG{vLRM-hSBb=KR{hFnnvuA@d3nOltFirdG+R?=)GW3+{=q#~Os z?04ZAP5!$(&Y?#^am0QUt^z!2_<>gk?K?J2@sezph~Y=uF^DI1{*BVs(-e7CE!3R# zv?d2-S|JLoPP5S@tVH!1J1tzqElvKxeVJ&(%RSA5K%)2pBnNw_3KumWFWl2?McVLk+k37EHdMmHL!q zq#ZhFXzm2<^+1WTz{AT%3$1d7@E%#JfP zM!nZkjkuJleL=k|n4(hKMphaWJb>(-E20WEVDo8i%{(>3>M*UMTmgM*X5I>7EYSF>BEaxWheSFHheSCU5!#vA8?sr< zlr{pV?elAtoW;mhLt7n;k^~%=@fY2t4bubC!>oWPA|^7F3h7f+i8mVlBO^ z+R>CHC30=$vU)*UC%9mJ0OqRP!KBd9UBK2cg$f2Eng4^~eF&O1a%&c~#0;+Yfy;*_ zxvV}=vzleH1-IU`a^RR85Hy;l(xj5a%fn_kQeF%eY9Yxyc(dx@%+|<|MX5X~rBXSJsSG*& zGAz8rNHF%OCXP`f>9}%s9VOGufHm@8&lGeVSE>T!;wc2ZnGe!KO)$t%Dc+aq;WgC> zBEZZ(soM^x0LaTgI>R{Q-YptO)5jSoPI*Jv&V)PmjNGuBN!BCPP65Vnt3t($JR7Kc ze&cPZ6n7YKDWh|SN8B^P#Lh*|s$swx$Ne7U$=Oe%E(n*{#Lfmw{D@Z(kN`jG+{2;% zBJ1lr6PzRmT^&;-kPeHpydEy$2sq9sAbLa8@ajcz`Wa4z7!=>)xX;7kewiuL&&vDuo%Apq?gyhc`7 zkj3qIDUbj|^xS=wqNhGTl+mATnx4Eu>{q>Um!RqMLDPb5F~v<2LVXkK8c;X;4kpyM zU%8_@iYw4Z$rK8sk}%mHpO)ND##9>?@(6*e7=2W!ilQ=^ihON$*FEdAyWSxpb&Rru zVSq3`t;)RMN*w6v&Kj9e?GyzvP%?T4W9-ZTB(*$;Sj7PmvYAP(_Ec0STcEf}L>Xb> zZcR)GfszQ;c>)Nfa|#*1~Kc!JqrDdu0s$< zeiF`LI&U@Mu-m7ikhE~F$&1+%uh)w}cLILy2tpI#3{ZmyRo05J^5vEJkQL}elQ;nmC7kLd+^GW&UWVpbCi7InPhW3_5c8?4V?iw8*KQeT8wLD+DeQI!Wck{^j z+`(ISzhH6xINx>4-aWxe*jz$0R2vnj1M^-2NQH8#G_-rDJXG3S+C79uxVwgT?J5oJ z+BHn_mz`3_*Kno+tY9NcL*Fy(OudF7KNp3qCi*s8@yU4vPeIi~B~<}fOSKvoz9)1H zW8Pb&Lx)0;faxi)7^VBwnDv4~sUH07?gNFxNF0a5vNbNUBftUyTk7Ew@Tan5K9e`L zve<95>WLR{3b9n|M5y?rtesR`i$u_PvqTi{hRcJyc8v^8PU9Uk1fYtQhWp#xal`w#hAquhN zHOLboD@40UR0wocf1o;n?8$I$4#z;D<|H9*P^1Hr@k(PhtRom)nlmg~+EvDP_{sdV zEF%{YrZr+?=|ETyqvNzSrLq|O5AuXpl8Gk5v>fC$uT@XXoPp~p%|H(q=V_-z!MBSZ zmVuK^S+D6A{ia`ADTdLU++o?VLoJu(26B;|2;*o; z2&Es)^@GiLJ!~S%lxczRN;n{Pq|JUbWR2DlGPli<_SMgt*}8>x*N=h%>hYk$SwSHk z;+GdQH^j|Eer?4iO&6u?cTnwEFGW!j9YA}1Vtq0#Cdx@g$KzA1IFySs_iHibkxE4>lJZ4%^Z~0wgnCe2_1~O=Kdd)LT_P zaYC`N;>1k%5_L@{*|UyCfP5e)yf|J8qbhSx@OZ(ChDmM{D;++0Le|7?m*<%g6iTiG z1P)VPPz@UgDF7A@q@`0&HS3{QrRg-T(V0k(?xiyu+%3wH8fF5pEQ+JkJrh+PBz}T9 zI}bjZz})sV3uI5W#5518H~9e~ePyJFs21smmgzuJ$8=jS@0=?~`4cN;T;c20#d%f5 zwjdLxF~7!wP^=5vN!>U~1tnhSBJo0C4tI$#VF&$)SCTMVK_I+TS5aolCe zA#pd31d}bLQmtC2c@X=Fj|1QVt}CY#m=NF+kt_)0x64zf3L zixm~3#H!Km(DcHj7kG0#>QEW7OnO18H7DmeJJ_mr!jF>d))R%Xy-Bk$CsyyLHKkXG zdDFuUbybEq5y2evA>n-$*5oS^bruXV}zAGiA)QZiVFwi&ZtTy&sc(ssIG|9P()?lOWnq_6 z6SxdGBE3e8-Ktwy=mm#L13EdVDvRq?(rlHou>Hf|D68RB$_lIPe&BiAW_aKG-br@Y zk1YtB;R|3h9J6hP+f!v>F-*UKy|DT>=|0BD$+Z`XAqymsMY6NphtlRkJrLIEa5-28 zuvHu``;9SQyQ&>p_LJkc>WQb#$t>&RrdOooo;cMCZV6{u&oo37wkK#HiPo{2zYMDz zy`u01@&&q6RH#Lc9#S=bSyICf))s>IyVtr(aAgJv_FOtS`0@Eyv9;yIpwYvhonl z7@69XzHZJA_)>!>fdK0YIcCcqRoSQK5eGm8!BKBniIqo?-N3K%MLOC+J6HOAf_=Dx z(Gd>vPP1!LGFq3h+=mG@EM+qV4z!~2s4{QLr0Vga%DfMYLMsx{3))L7D(Om70HkNL zXy6XB&`KG=)B6hWRyD*p*>3f))=6!~Xe-UOXGl{>hg4uAHYs9osJwHqx$JUL) zL6OZqkYvG^C(K2+7-lxLh-oA3qhgC9)95^=D*$~{p# zInRSb!pmK~oE*Q?$}%|t|2&m;bF1M6nBrhB6rfGwM0~haudf^sAp}2>rnvY_H<7P=MZ{iweswN z_|=CP#m2o|1S*jeh_wuEKj)`*f|Q3jEnza{yT@2h3T?Hb!4f=sNK>s)(p6D73c2Yt zmIii?$-|hP&#j`KTw-9uL|_&x=qw3GGw2%MC5C++O(rqTu1+2(!n%MWsC9x^ox~L0 zdAUf+YGh$)y-}dxtS$@NsEL!%Cl=;1hoL*rfy4tWq%cNHg1|FRV3qA6V(lJNMXz28 zq&sau9L`(E(PNyk6CoRMmRcO(ArHV+J2jVDXDq}di)&0}bBIUvOXNbZKDlzCXoYHv zPOW9B#rF6T#u%pV$H~bcjMO3sUk5}}041*WI~!d&XuHP*U>vkc=IgGcX(|_!XToWWi!GvT`Z|w=1A>fYxI^AY)B)f*oGH!|D%5}N z2g_5ZqR-=4vtZ5hJNyl_M8vB#@Hh*!(h}6&$1*aNEFu>KQqJ1$K3fXW9jSGX^+bHN}D&X$O-dvIWAql_B+B;Qq(Uwa@a z$7&HO6Y2o8&eV!lYXo`><*bJ>7NyPiH0#M`pra=wY*MqTbg&mlklQUS^MFMg1RVfe z4P>P^kRpTXrDe-DREbWrQm{b8T361IIw?Ks&p!eJjT;^CqD-YBelv%#b4_U28f^Zdz_R@RMcpuqw4|MVg<)B%-#!wNR0<{$cMF%9c{ERp=U% z)s{ahFGhro2kY%o1?8FNDjmC0N){DJH(0hUUD60rL1xsGF2+vxSVU(%=~M;O?RA;k z=Q6oANY$_MtPc>Q@FALSe#1(cV@BcO1f8sCphq z>r%ELXe$|$L9q~!MbRoQ=6|v|YDv*nSVf7f`B7uZi!|eD{ejABY0_3+I{4<57n-k7 zFK82BjJXZJ8P9S$c%Mn}qDH1WtpRFmt=9S{Z~H-??xn|`G}Y5C2F-}gLX=}@f(U|w_D~Y<&05h1QEvKZq49I3$mJt zJv*rz$?a>ShZtM4)<6_1v?)r2^A6U71XGUQsxr3Z$|l&;sFmNSEY?eVDz;zS+XqIw z$=g6MsVDr|x?d6Axjcq41{y1<#=NF_+)h;+hUu5K1=&DK*`}=t5LZu#^6Q;EmBf~j z-3&Li&z&;sbkJy$3->+oOa!I;hd@&b8q&dDyEFlEJbWOLT1o*^C&I-?O~Ho&TL`K9J;L9PNv8eYgJ3* z4gIG!@2HrL*OK3L$ZQ5*d#|~|gptaH&J`pwUBgy|pPJ7_xEF(18*6}uqJ$UkzWUc00mhLOyW{GB1IlJLlF5*S?AkWC3o-`{C=?LNoZN@ zBu8WffSTas0>{8K(yW35=}pg9D16 zxS)~vdQ;@{8btuf6*$@Qa;A5g<-VtuaWgRZ3jIiiB$3?JV{Zm34J?+7MIOykQK$Jc zKQqj+(8e&s=IvUy>0s6txY(t^HCCtDXcScABw}?Q%q8<Pk^4Recw@po-JazjWcRv3G-fX4HYjgAdJqz_l5H|0P z;-s~>w7l}7Qh9J_*YNH=BYQ>kB0(2vh_c-3ur-G^S+7h}gw`W{s~}qQcd~ zIUo8F)o85(;Ln#?EHK6R=t{H2YI;)n*6HxbV)vDaP!o2fLMx`|6z;VLFM?2J;gJGj zsu0XFK^Gp<#f4gtK8iV+^_JLm7LN~#@oJQCy_sxWO-!PhHd36ILdDk9CxR*u5~&Jn z1Fh1zPedFiz1ulj=OC{fNU+gF@cf|R7P%InMp+FSGC3r*b&D(y8B8v!Ga;GV@-Qf5 zy*&c_wQNwzUy6#>BM~n$x3FL6ZG@=U=@R2dV0Ut*$&VxOq~hov(J`sT#Zevr9T{*g zFNY)`W;C0if=OAAtVJR#Vbk`YOhH^h#OqBNLi7;7m9O**Li@p(tlspMG$iz>^^E$` zK2Ok0lSU9>l3CBKd_|KIS99s9%&0hm09mFNSgBsPj(R~5S?;A}3@4d3$4QiG@%c2R zo!E7b`3{|>2(3_2yNtS*PqR@96ex+=>z)B3BEFUzwAu|)QeaTLY>OG?5X``FRUkY( zN_a{8=PD?OH6C3#_kE!NI2asCY-=1ODyd$;WtB>2w0CySqbu6DUPRoc_u7ttK`gE* zl>?0JXCoy`{i4;6yxUY{DX~3!1SgV@fFkltTlZ4C#HdyqWMVKValC_dcXyM=wsL_L zA!870!KCY(j>1LHO{2GnDi<_l;uwFmXDBDjMH*Bp7bhoqOiU)UTye+ zA16E_S2!cXt!*(aXH&5iaAvyURTg!2b*xp?M~X|Dzl;HJNkmW)jzh}13T`6u_(U}o zk5HU0QcfdyWT+|29;jJeNcr1|QeZ(lwhkypv1378gwmAU2O5>w2+lHya2cybYNq-X z*NJ+lE7}d7*>hY}c?u!n$701^%n34mDynO=0t8f20i>x`Jch0!eg_#=aay6_RhZxz z#r+FGxI{-#5qNsmi@BkyIKE^7OLfv=I^hN5EJdX?knKZXx)UUM+*Tke6i5h`MWiNs z%a~lZ^{6w0BH!zts4uk$JBQ_YZ)Zu3EaAwcM;KL%@CGS9k_-e6>9H#?j{k6pZ+9>A zW-IERgEC#zFlg-si?C&Lp}dLOJttYw8fKlkFg@0fd3hn#qEXhSakNMlmV zLzylXBSNDhi;h|x%Jk``S0M*(EvDrvhk}op*`aN9NQ|y#24y)CFU8Uy%U)=xDh=8t zy({ll3pCLLfdaC&RYF>}Drc?gl%@;nNE<)sCVEpZ(~w$Z?x^Gp;)iU>UIo3t24!4$ z!e0ZCU-Vi}_qIg4Wbi|@PJ0!sd>lcKc6jZ8EL;?tve=ARFiPlYjuKf?>|}eRWcX=1 zk>S zOsab?Y@hOMLT>nLh}8)IssBmSlwig3iU)ZS(EC1*6ZHYE5e1`M_R~zH1pnv&=7rRdffCy z7(_2!c#OGJM45eY=b6-Gj)rrBR@n;2m`fGdWuy+aS{b0@%Ik_u=nB%Hs2()}DNV1E zj)rslguvH0yE0MAi*$ovhY>9zpL@ZbDNcax36{__!x@s~(LJ@g%Ck-wh83d%n@#en z8DrDU4CGTWPEd9l%F3o|u2ohm`c;OcETn`>Dkn`B*#n?b&5@|sqqs-Dvu@{80~QoF zI~}&C39Ch%7v`(gLJW?{8A>8GJA`ic=+vb(-f7b}wJEzwHw!T>&x{D(zTK-A_PgE!Z2@CWBS)0{ zH2ZB#B~q+uNtezYfpTLuAX#kLufXSDR2Ouoac>+Qa2*zFnMiFa5*C#d=_s{}SkQt}q zX*EV0>#DgKVTlvJO)gdd@)(7f&Fw9ewN1ceHlF8Rl}Ck|&+FB(-m}ox+USW{VTPTv zb_7-EG1JvR3IvD;NN(zO6qTEk$tpVDy7s{2&g__wv$qV=z;rIb(3a7DRaHjXZ{vpLLd?wtROdrl*dG z4ZJ(cIT!kf$1tp1JwXXo;TTd3O80Ukd6PCCB`J)Ghll1UJU=u(VhAXU9}izMbjq$u70>`2N}6-Dy<*e2yS~pjm{ib#J65O6tzY zG_}(wR`X~?f^uEThdp%C3!t_RN$FUfZYsRL*S#w%*xb8MmkN7lu7f>9u4X!Rhc&aU zZ*E|5g1EA+K&#cJH`+(1&>q#@j;KsJ9$Isfy+FVzinW`hbpV#qYSh%6m0aYMNOfD( zmxK`ru0#LOz%%;Cq?aIMopxr^h7V=bP;+HUHAqkXQj-C7U~K3>n_dh1u^v%x7^SZ) z)o(#anTZt9l4Va*rg*BbjqQx6PL11RA#0$i*?FoKwgStuLXpx4XhGo|Wi8dt)%qxv z5z42)oSF!|R#7-5QsqjcW6!GKTgrbh+pnu`E2Q@Vv`HEgfDG+=EvxExQwD!&pH~}F zQ1~Z=KXMr}1c3mX*~WLvM-K-5wYN-!UXzNaMnH3%N@VXyO$g$i_*n#`HXJSb@EBjh zvRmwh$vr&A3=t&X;|?LZsVsA{OjIII#>?=cM%lf9b7$aUc~_|RDoTyD_5f4a`iu&g zD!7h?fwF0*%C+gKsZ<$w&EQ}h-ctF}B0^HNed(DhqckdYgeH}k4f}=IUIvR!(Y;KL zwg_G(Niu}Fh)H$2m=kR~i|!+waR?LKOTN0-R|k1yFLx|~DP6t#St1-0WH?K;qLE60 zo{>b)laH+8ekI?v3Z<0c)x&wKnAW*g1k(ny@E@;|&L8k4b+?qT>_Mm%P%>X6_kV+hh=~SSmwy}5zriO$gPTIvgs*!xTrD zGf~!>1!Sr?AdACxn4~2|v!{WD=+-(_Pi6q8wm8HROG4Kf?Fc_97b%$$&MqC6iu1g( z5Vsm}5qdglR{3JUbdc#>xtoNw4aoqSD-}SoL~BJVOcuQIWCzHd34{J==$vNNfDr3) z-H>)iTzf5TEh^4`S-l=#EUjSLYXFNTDJ25o=w&o1it(2SQmE=AHRMlC5Gf5) z^)Re&xmRUkzVlD{jc8_&5rXSZo!FieDF01)U zJaXx+cU7!us_|o#7uogLZzoel~>XRe!zuR zBn}6Uu@ZJL(p{jCm${yVcsh*O3)8;DqnoY21q z>7qz`%RbXCivio_YfFY{kf$PbCFv?aQ@q*+R$ghUW(+(j?LuK)R0lMLWYj_$vE@mG zYh3KX)`9L?t+4r1(ZZ^rk9L7pRXH@eQ#{7ieBXy=!G5s1h1QCca1$7sK%CGaYB&fp z&(*O}BjcnprKeo6mL*}K;lMD9;bhgM9O}&-IFemEc7-_4Ktl+Mp4}rUv7~!^r+w1F zAS}!VP>rzpNj)rAF~TAzqK~p&rCn|FY3?}|JbGv;66VNBP%*ts$bsL14=M6LT3u~5 z8Y@Mdi41YCl#CQW!AWk&NW+ZUB`ul~Gm9SUZIs52LtPU<*MsE}*7u&Jj5 zZO5xsIM>W`#ZnC~XyKUE4QzVBZ>k`;f;n~ywPXx)%uYl>k~(O1DzX^D`r65+ub5L# zEuukYM77xr@tD?FbLz2BqT4p9b`)A^%-6(FtU3j5bVoFqt}0Qz#%zo=e~Hnity9W% z5*kZyE>0MfnQKAF-)`;92#1jNNW>!$FvJ|oK+;+a;^XdJt+KmtZLP5^dC{#T$ zV~E;W)u-!&Df09jFOr9FSflI7V+wekgmCjZobD`!TNM>uEE8X6^};?R->JvMlgnP` z*C-J^n&E0>-IgR|?X6gAgjn)bu3UA;8XtJI}Q>zrSk3+2yx~s9{0-6_Wp^C{7=(^WEGdQG-a#E6wvdm1KmP$6nT)EUqG~sw- z%yFv_-H5EsaDuRki!I73ohpnJYA7hD{n@a((yz!)dm?b_hhCLW-p;d}b`DlTm>yda zr*YFp2WmZ}MrI`;nqXz?9z&L6o>RECUutAV?MU79+EwK9+hV%ij2y)3YS|ll#o&} z+)}ZGB{WIO&P!>-5-HhEQix=D9)sIMpsgWk-)!-uFe@^*pDoS%kZ>`%!ZvuqW>?rs z*h0k2IPvO2RWEjsQk^CNQCX&U4o-qd?K@QK=o@PXKy{BEQnHpw;p}*DGG*I0J2{8B zhnwN7peL#q4^E~Gp=SQj0n*H_L}7oA1O)r(7;|y^iS$R!&(+a#LbAugx<`NShbtRl zYgo@34qE%LWxgqG9}hHA_Xo#bRX@fxHq|`#Li~Tf!V7c{eND6>7Q)PUK_@{M$tWEn= zztI}aTK>$mSpcZtQw9qn1V&@tIxK~i0%oagsdBU=%bc))x?-D0L~Y`znXV88aqIJa zjj-A`P|R7@fw-y7&y?9$4(ik<8NH(q(d1O=b_2d)YO{$fihzxzgMd1oBiI{$z%_LP zn3ag@_Genvik>#g6g%+MtIa zSx&Ksm?dJTUF-eIf@|$t+hW6@);2$pl@$nSR_urc4r?T#z`hMr z8-iOj;Xs)eu&`d`k*Zr+)+AF2?r8%jx9hLZ!NzX5>UL8eK}*GLYZx2t>Gq9lltXA~ zqS(=J?tr+^j*`UQgtCYMuFQ}(jmg|?5bn{j5cZJZVk$sCMyB{afE4cH47Sp|W*4)%>!aoRco}#7cE!`Wr6vYH5ean=? zgEasoi%|SFIG!1(D)489#G9n*2m{G$2n>SQ29WrEpr(q{EWzB>rUJKL z-I<%Is^P7$fb%M@&=!u5ei)z{YXV~Ki8>}HhMPk85-9@G{3#TLf|%3_;UbUf-bz3A z8v+*b0;cd(7Na)g@JuTFZ|dZ}8QQcPVkC>4U2>%rbf{d4=hXw!o(awb65yz1d-%^0 zd!nM0%#(GmCh;zyO_{!=2f<6|g4N6gtjuk;;`yc@xXis4c8H>y`5!R-{w01cWA{ zyv2K6+&5dG3ui~!q`we_iN7EYuqjA|{rVm!k}=ecRw4}Be!?p-iWJ0>M#~3zFM(`J zk+}n6*SQxig7N6UfY(5b$>O3{4dY_e8ra7go*xVh?JDmb7~;IVch5+vkH#ByndlMN z@|C(En=OKJl402ddlKVTj#ioRgqI{-1o6%U1m zwiFLprQCzagb&TYr+XtrkY?Pj${YToI3Z8CrHC$ZeSpiDc2O;EG z$n}oTA0RUNvb!*Owri? z?I*$|dx<7DGE8V~v3DbXL&uij^gi3kMzc)Ow-5p5T2?NV03Kj-at^ZI9x5<^j8+cX z%{|#@4zm5ASt(5rDl~}sMj}#VJvaG*Sq3Sl(;3}jT1gS!5~4ALfTAPSIYT3Xv&P;deXb%^GR z0c~|bM^ zi)Z*DSCA=LN*7K*@R5JM6a*&BRZ48KU4wgf?cKd+aPKgvZwuimFQ|r%gS_sw9YQ;yo2dk8kdCmU+@P-|Rx?_=v_MhGK3;wM6l#Tk|3P+akv{BRge z@wr3Grq{$U6+O0}_U zFaHUGLGIKO4suk>@rhZI1`3V|kY0#iN-k4!r=ddqFS=K9d1|;&*+a{IA}-y_h)pCM zzcr8If?gCqVwK3A0;p9!8_6%LI!L}vpOho!m8if^)T_tpvUDNk%vwkY9ubZXd~Dzo z;|fVeSeF>?>KJ1#ovF5F8y8k?y0wi-ZzQn>bESU{m8MWceA!R9bm^puGjn04{_b8Z zPQr-Y&)mCu?}N0xPwaJxFn7IbxkkDAXl|947o;Y+Nk8xpdI`snn@+rj(b1V+id5>M zj`J(~YO(4ioSnvL5PVY#hDxPzOsV*mO|6EtnsuGBTk7A{Kit2kf26-$Qa8OSP?M9G zJXB~&QEhJzfhg=B>@(ko`ZCo}L8^w7&&f%hPAnim-A^H`2a5Q=SZs4}C5CRpcTa!0 z++Xe=>fhDBTjNV}9EO&tw^s(tbeEUCfX{kSGxAniL95=H%|W%oXGGvSucNwVSaK4ND5O-qSs3Czhh8!8r7{S`~k9zFGWjG{oOH zwr;-y16UDxvLaB2lhD&n+xcmfHuE~6*fw>OW(rs*yhPlvtz=#9l1fk9z|KNJ9F13S zOjHkLZV+NwXdY@FPtD01*Fo6p$|VF@2TSf1ENL&QBc4PnOe>N(aYtxwA;y%wU~Q19 z!1p}@nTEGKRxXLjsLfWZqKC=F!f9ETbxscE4l8sDw292Q84GiE{1*1tU_H*bfz+?>fmVdL6u3WD2kw@ zrKsI8ra{5}uW=A8A-F0G1W=q@IV;AyI@2LRuDa>p2*m-C)vys8UDg(BJ|<~-V$54I zn$h`>pzo7|5OYZ|j~W0e?vbnxQ7bEI7tO>!D&r55fuIAYplb#~G-1^lBBHRYKb<39 zNNG{IEQW%TyYSU0!J555q8!d5>{5&+boMlRDVTDCK>y~Vp@%eT%f)9+1|x(z@z>-+ zj(ozDy^3(^Jhh`$S+PYDPz<+D!aa8pB*fI@!pTOn7V80^wTSEtp(dA;jpktrj$8HP z1$#z~>tQmM5HRf2%db+Z6FXU^yTf8eDGLo%bfC&4Ak*X^D%0+Un1mqWQl;#DaDPMBr`s%2a?NzcDYt}Gnw&F+6fiY#jJ}|0u9CD4C`K9-SUG^Q$}7DV94F)#y+F8F zn`83fnqIUf{7G*CPG?%?$!P{)Q{oygva@|IGQ#N)%s@_u8gL51TvW{b@72Ziay0#0 z?3CXwHS&a|f{-dP7#PP?C#PtGNd@LQDHbwn-1qZ23z3x6 z1;&#T$5Mr_UuR)?S1>GfUM1oG-;GPATc|F=%&2G635CqaQSZg1CW{@8LU|uc-X%dY z(;a?lF4p!$1&J<>R$RCKdLEtyl` zaw5dMD~-Cj0zr{kvqiB{8H@XbKOs5k067 z5n~C9dSKG-M3J$R_mnZLN_{8+JDT9bd|)uPDYlT3ydBzpR*G$CJ6M9tGM2(xTyZ1}gZzxY~UF|J3#+;Biz(!fz}el8q0paD;@`SQrVbHHU87 zGS+2mY}sJhfsMyFJu^Ksjb^&X-9018#t_IwmVmR#CL}gHy?XVkbVqmORT1b*=&xkt zGffp6j1QAlURH@&q)ddqITjJZeMHRi#6`v)zi8ldek5>H!wVU2jPs;Qwa#AdN-i)F z3<}B$o^8|JtYX$r(1jsBPY}mkDUxi57RtMSWFQ66qPtF|GKA{w9p?JAo90-%?8qE&>#Z|NiQd@Tc7Y3#H%{4 zhghWjp|*%_G5o-f8GXJRF{uJo?T8w%%>Ww*jH{~wj20HHjcr7pnR}J8G-#X$1f4}L zJ<(PvabsovRFA*W6!X9)o>{8NcY{Ld$w`Ag5tWEX+=tT==V&&DWS2?^d7uVMs(Q3$ ziOfKLtF@_A@EBMlpo~ER7k7z7dU+zz24Bt1TE3XmE=cOGc7dI`AdzTmf%FS1;#PU` zucWoxWU<%$0!Qp23Oly&Zp9AIkR23y>4I#M!3PO}!3^wYdmz_4ZWguFn3mNe)RGua z@$40;o>uw0n81^8N~(x_zOl$>lA0$@j8Ftuq?KHgZnumkAOb)i+;n5`uP}e@6js9Y zSuMSem2Yg>xxur3JXLAdTm|f|ndj$)Yn)kK_Sa3K46k1M)sPOWaqVvOwF^-Ic zA_RE=upI$BNHaLQhiawsP_5XhL$=W!XoIaVzR)O-JJ@v88YJ6P!Auh|-_jz+i)cB> zbWjrXwm86_w8haErW>u)Sa3BnCpO-`gu*Y~Q~1_pxFZ^KdszL(SQuW#qp+O&^I}^% zjJ?f+b+et;nf^I|)Ib?V@0JU`(AfM@qC~s}OA8T>V$I(+fBXx`LIBj&tULB7zh*ZF zs~PB$V)jfcIfzlTIENKd8=IBNbEtR96#_h0$I=}qa=w-H>CVx;gYeMIMMw?A@r~p#al|ph zeUMU?$cI}gnR_ZEUek|La8AZ^8ml)dOYZ^n1|>j>oc?tB@G;wu#y-;G;Ij51G0T)@ zfCGvZzH>3Km>vu?Oa~)NzBRL5vUX8*HE6S1l&1bP4JL}aA2nT#MGM|t5b~fyx6_9$ z)tpd7y-dV-1*soCrfL1d!8E7g_375bAY&1sFR(%cYfx7=txvZAJ}8L(*__F|tQTjM zT64k(xdN%EJ}edKu%zovPDBS|4F~6#9BGGvG5;RMm#cpv`{}0Inx)6?T1amR?qY#X z;a(R61uA?Rc@cvcn&p{MhY~2O3ro#A;;}8P!kCJols>caiN94(tNq-s7nowD*@=s_ zfp;~2I~VV)#2y0#c@~AWNo?1=Eg0ybq1j|{aA>GR84$yPSNx`7O8)N-4g{qQx~cJ| zcEAgn?bQI3*F{xSjaas>xF`TPiks6+4iAHwc|PMk0rpzKx18?69khhG8Iz7@_$vu4 z)dEZfC6|gVdSsF<6mY+#yYwZ4B!Mbjj8g;qWkvZwnt0`)q`Tg9b-S!Vga%Hs5hcza zveDfOGSG;U7om+Xu7!!1y_)(W7sr3J^7hFU72qIEA^rLM#BAqFIymvGYRtPl@nZcU zP!fD99RMFPKiF||LKr5`laS9=!%PMO8?7&%bj@+hgnoUySq0`0LI}wP>T!=fvvMp~ zmV&$?&7@^-^+=caY$;c+Ysb}Wu(vPZ@`7b$nJEm9z=$EBSMq3Pl_07XC5&&D;mDO% ztdgsYYt(}wJnaCZdHR45wLf58jsxN&WS<`quO%=%y zOwh88tYP*wMOP|LDS5u0a{HQME0u!oI9gWkYl^P~->qYPP31@i_zFg=8_n z?=C=;0OxM(wFWfVf?C6>aHy*jVN^58;G_ag--2k- z_^U3wx)z#jh8cciMu~|f`s`PEBJIl=o^WlAmZsd1r7O)$x(;heEmd;Dec{B~Xrgy* zqQ5)Q&mP$-pq+^=c!3+LMqgq=xO%~nZqT}FNlFaW4(cL%-cpqxgM`v z-YTUTxV=4zo|ut0@ON21>wW+rbH zi<2rCj7de}i2-jGvO2}ma6Hl5pXl{Qm4jY6w7qhxIU}1>%U0givbyRRSw26#{fT~W zOc*lSFte&|mi4?-lq7_7Bzir%0{*H({4Uin$JC;ZKvDYb?MU>j6^($&o76~q zqSu?0f|Uf~D&{Ox2DUvh;30@R(C|@}H|b8wa2(6V4V$D`axF7klA7=B z@qtp*?6JHqjY67vr>N_xoSM|~dCQXV98dI1qj3d=_75d`z1e1FT0s(&3VI1S+@Lb5cF zs`;)3fKhZqL?PBt6HZ&VaokmY0%$|*i5Sk5)Rlnu^xQe zCr$J1%D((+#wfmRUTzt5aGnB-BOxG9axef-tnII`##=fC(MMcG$z7J6HTWq zJGHsxwB@ZUR<7z>efpa1iNuccKDFn9y%%zsoe55*q@(On!ly+0;g<50=n#Izqx36A zzvA?(oql!DuTJ{aMZd%@hM({$@gADqOTTFA@d5g;LHuf`iS0D8oh4EL+J|WovFEX7 zJ1AhCv`#0j(@E=e(mGwVNH;CgO^bBXBHhD+v;2kLs#CP`OJia10#{THf3=R2UwOO0 zD^XpR=Sv6F98e#4Nht}8gq7sC3pG{)eFTr4`IuMb1NVSOzX17ycS}Fb`#6bTP_JSv z4TeDIjIue*(8K$~o*+~wIIe(R(81YW?~+@9B3n&Jhv83XdG6O3gA>UQr`Tm2M1z5i{2QY_XFd@`FaQRDx;HTiY5#Fh!1=qBpi1&Eo`77Z*L}* z*a$1eBig7O3C|kTAW~tCv1|by-zFCVD02%gZ=kehRf9|bgkqZFf!|J=ZZVR|8@lPD zv_zl8q;Z5$#iy@2XiXN73Kym`X{K_vWg5FHLUG|btbmxIiE^+2?jR8%7u(^sB3^fU z(w^_dONr*z;vin%9F-Ji|5YVj80^BLN|h!G1I~g69w3P2fD*4ty;Vv(i#*6jiNxoP zFDt~da8p!)H%+EnROk$WTAI5Z*3+#@vgC?T3xM)AE}{mIEC%X_x(W#Z8)YQWXIgA@ zOz#-?F2)W~b5iFwXud&WbJb`tZ=`h7p{8Ry)Yaj)T1w9V7YAi1w#8d#z~Bpjr3yT80wZbH zf!A}If`=e{q{&{vpgY2ipl*Oik)CRgi)m<4LDgtNie%d`l{hdeA4GW;`OKdL%SY1y zh#c<~VE!=V256jW-a|)a4@+8 z6k{y4!V{%0x7uZkuR!oX!&>!ACoB=4vHEIPK0BpPseOgua$>Dz!wm6o?^HI^Qw+6! zk2*9W9wJ@x%M&)Ouo9ls9aLgiC09+^d2Ud+6kEi}WHG~iK6;wG9C%uT{59MnrlUCw zaVq*yo)RTnxc!aXHk-z3jnk~^&0|FE0+#4w3S-(2t;F@kJ1F7coKy1TPwt!PQ%v;i z39nP&;snW>-I?HT=GBKWm?rw@m_M;cmLN$rbT{*^N+b(n7O)ar5wq8;%+EpPAs-vW z$)-%4Ld~CDE6t*J@Er>H^#cz!xozOTjpkG%Rz9kw5!bTv5ky;+aOM)tU@-EuXRqv9hD9O+VId0bNh2E`d*Ae4N-&0+JN?MhPy>2Swh5gECf zh|gHEy#AZR@<0JGVxRMq-FBITsPzD+>*g5|oDyyU?2G2Zl|kZhMR+U_4*VrM-`6bD zFpM1u7%su2=Bh($rS%}JRn{K%6aeo-m_B-_gHOd2(kZ|Pg)Hv8G$~R&aFe-R&f_xW zQko@Cp2tfLPOyklT6mkCZ}DiiSvW9g`7nl0L6r}OoK;91TJkW_$=vukQYiYgS3rKAvn}>7!NB!qW}rbRJ!Uy->;_dq6<EgBr#gfEl~ic5tR8fVt*WvLyws8M?MO!DrErkrH9ikpj%yiq~L-GJ!hhG zDw$ew=c-0uoVt99pM~?6GKb^Juvs>2%Y?X=N-D2wcAK)z0e>#ciT$uyW>$GyL0uAV zV?rzSSMKGCV?UkBw6&!$Y?cqAI-(8GP0HD3Q;QE)JD6Hkp2I^a?*~K{0MLI}@K!LD z48j4Z!x-JbaJaz~IBd~%SRM&%EfK~;5*`5T0!CQ?Pd+-2Kcq{@D{Hm^p~M_dz!1ns zN7R&OQ$X;9K!X5sPxEyBQsVN)&%@bxDQwm`C3K2^bM1LqgK&3!+xcOZnLWv{7Hz|H z1&LF&`az1bK{q#*HCtUBZZpy%T1zDuY_5XS%Y{5K)jqWz7euN}(2!+H&x>l~)W@0F z*$Yf}F)WlZ!RO2YB~&S|+Y9I8ZU+&l70ZtBVia(%7(3lD%G_)Ymtm=d{peEm_@hD9 z4iTm7g(DGbjYpsikLqrz$h(%8BxtJX1fp9NwkcGYF|r|5STaHku~FR>WDoDd;8-nL z5qbmRjeu(lbShU_n+HwfF;mew93Z5xiDL#$kx&WHhd)c8(t}GbrZR9Q9ak?z#5ADl zpk`0hq?C8(asA3>U=yg>i~#tsU;z(!IO{0&@sYlNV0b$MSrnS3NTxK39Jl5b=&3=a zHA*9G0Veotg!y`;3}ihGgGp-MBFq)k#)g0j}K{SX{JaiVg= z*M9|#R?fAbLaQ}VL8z5vsTj=kvM-jdH8l(8!$B#f?=HCjug8>*6u+`Faq)3z2fObD$O3ALNYbi>z6`bKPJgae9pzHv6)D~S! zQxA?HCxA;!CWr)z!2ar~^SH@yGh^3GLq=Wsp+_HpLD{ZiDC#pgyga2SB09rzTiU*<{lMHjErKq%(oB_ zKQe7b4Pr{Tau-Z(d8VKyp2^u`1DR@E!Zua@UfKECl9BjHWO{#y97iY^D`2N`avStX zXMLe)*={|VA}%3hjF9@-+rDOm$W+7j0wE1#7a{epjfF^-kj5p!YME+@Iw8u^CH{Ey zK!kka87fvlI7c54P>Avu&QVq<6g|%KNxfuH-8KAM(Mk|p$~97GS_TaaTE$7* z$mU$7In|=XqtQ+^9*uV?pMZcf$|{UIvxY~XS-o)nQm9lB0J)Vvf$!^Xi}hkD#+ulo z;PTJR*L{E?i1|g4a%Kzxtj2@n;V}!LmVwhjO|D_t9${dVq^c~09^{dQ_#S!F>A}S; zuL5Ky-S&=7Kz$|K6h!U6cjEFd z)TxkpIeasP5Qjre>hWil7dtamgHZP+X#AAc9o;sxJZL@;jcGk^6u@~-9|WYrAR1|> ztXM_xr|-b;wqjm0Oi(!R=N~W?jm^v}in=-qYCXrvsd_rz*%|AleoJYmQm*Z2{)oNa zG1xaXqoeB(``o7^#evrxB7*rabxK8G%6fXHs90;5S=~Mh4w@rFoj^M&%Phkk6b?P9 zIeJ%z;@X<&fE{jMA>9eFg>w3Y;te>~64V+&M&kSwG-sb)9O5p36qBsX-DXnDIr z$p!ESd|Rd)pd&^%f@LYqWBR0u0i-W%q9HddI9O*a_D>qABj9Sg2C6{=2OEa8Pc)AV zb*@0^u3`iNhHwkupLy2uu&)?;x+SfEwD0B~A`h9ViYDLhTFk ztE-!?(}$!7wOW-L1V)vB)wQyee^&5+B}jQ}dtn#eFb>dDO7M8}h)v4O)pN{BO-CPPmmGBY0ZWOY=yrHaUh{W=@*RD)nV8t;E5iU$Z>VT2UR5kmiGfJ6Y;%{FdkVz#*w!ppDgeJ z1xiGv2x$va2j^!qX3`&2X9CI!^?e=ik069lNng!dS;HjkGnb~jsUlBlfRsYg$!WIk z@WgtW2ovc~V^V4pAtXcy`6m1!gv=s@TmydyA$5e1>sk6!bD+#f{3tTj5SmL!J+wTJ zkcL?egfxUec@mmWNMrlxy8d`)*NVwp*S6$_-ZR&4+BMXB&N{7k?Z)Vtz1?SQ94cfs z#@*b+7QJ^Y+CEYo?eCinDizz&P*MTSMKl(R)e+J-2bC5fLSg_{^f-WJ9zbq88o(C< z&_f||-Ii;b!mn*z(b(o{AG_z5Puwu^F?CUD{GUJjH_x8@kC&Y^r*Yp`zH{DZ{&dB? zFa4jy^=F>_{81M!TR8Bww-!I$xF>ty^R1s;_N}ceZ@uKo%-qng?|l8pmm(K^<8QZZ zym9BPXO6#6j6G0)^{bCP@OS5b;Rny((esrj&b_<-+#i4AyMJ@v-38;$MV8_P%YZf1qZ>+c;fzk1j5``=rCMbndCt^e&8!h1LW=;+}; zUw3NpxfB5zt`?r0n{a2U&-}C?brw4v*_5XRtAD&xs zWBTrY82-ke9$9nb)w^GL{h z@r(a(>2vp%a+eIeOi5O_fL;qGhsjQ%wIip=h6HABnM`bwi+|ME@eeEw6%jAjx~-AIrThL~mOq*T#{#4iKXr^;l&qQYV8OsNfo5mx{mk*gE=MJ9riShD8s=q&znLJC= zI*>MxEkH2uok?wMO)T2hj{o%_=V%Z)9);H89@l*F#TUy@-?O7-(c)cA+2;LAU-*3M z@#nq%eQouBKlsbW$PKc1{x^o3hy*WdV9{JVcB{{NfK8rKuO z=RRA$>i&W9d8%6X$lEJ_`|W3%?^<^MDS)5q3Pp~-ZJO3 z3&M?KFTC`VS>L&5=YOvGuRX7A+J94T_j?;w{-`DW-j5$T`^T4D|MhpCzbH2nJK>gp zPzSDAcfn^5Jl621(_fmk_~a$9ML0RNXd7kC)lqptHvmEwV4hoyIJ#ZdZJxZ45aMRs z;!fr_MU-C*8MckI>!KP>cy|^GZwre z8cbyb`k`96z*Glrb)~0`ojR zJ|1zb)R+_T(*TGl z3f|lU4y|(0WJK%0zhUv;!Yae}Eo3DA7$M|k0Zhlt$)kictokLSJWfbM-4pQV zN%-f#!Jj2$s__VbOr^^y2I3%jm5@gA3PA$&eSSemZ0^)0H%wgd*`o;|?1`8i$yoNd z2CgI>pjjB%0IN4OJw1IS`#p;3Bk?*yZVHk4WF)RkPt}J)q0lTs_9G3!sOj+LkSTzF z8X%mP%sa(4%|+mjBqQ+REVTqPm(`d?!^FGE7zqG}OGYk5-oBjmgDe+CAi8p9L+Yg3de5 zoAP4_%UGr!w@jUvII*&oqHVdBza3a;USCd5D|&0w4+l)2YB*LNFD7{}emJm9Uf00! zH80`sp=jle)FjX2bVbR)wM*t0&jLF40K;k?WL0_%lV31R^ zEl?kEz<^@`V2~xX#fQm~aUt+3oFsXkA;?&6te8ph3c!(Z@K#zc?9@sVJYznd_ng4q z34B*8xz^5%t?%Mn3@~r_z;`_^a}uiH#g(j`Z4k(*H4V;T_&J8L_ChJ|8Y3O#l8rGOu9MLs^h7a_XUG26!T6&gZopS3OyukBc0Wy%?0pB z6V*cATadtBc(P*`gZq3iJ8cy-!&|28?47d21j6KkNswly!B7lT%VJT(Fp3tqBQA^(iU6*H|TMH8Z4Z2E>(=! zU^>%fTO~si zRPBg$rqyIT8dp2oyJKA)o!#wS(RSEjkKAh6_9#l!ta{bGb{=AycLoNwPLyrU36h7F4Z+s*8A4D%?TsBest29NfHVZDsW}ta=?(pN%FpygHy5ZpC=_ zTQ_gnvU6zt7GL-6tp031&(Or|o@j3rs?FOvy7R2fTekYD_{p#U{*ndaHb{u$$O6P| zWa+X5^%5augAZ{JgQhA7{?7<$JT`)q!BENv22jn0e;^_`CMY7IDR~Z{l_kDb@>Ujy zmAA53f1`v+6xN`Lz+6BpNBdf#bA%10GT0EzY=v0o#~H1}H;N&K8~7d~Bk}eS3B^OC zk;LFn6#hg)q_G}R;1-H)A=0=QULrXwB9Uw^1^DqInEk%Bj*v4#Bk}o!><^K}Bw2D`oRMfW2LFQ$zZiJLT%nF!KxOjjg^&ywTpLrP zN^`1&RF|Jrig`F!q?L(vgX@)bmgAyM8$3|ycB@jft+J8U9VO6H3*hoYYN~;d#<|gn zXfzrJel#~a5leR^fmzK_;%(9B9AH}=JyGCOizjj^L(QeqZP7N^%YkhjQw{W4kg*YX zoYL9W)z+@?iXmt%rbgFQMPs}=8fR6aG5!J3h&@p>emG5eXl$=QV>?6R?9OQP!^C4; zjfSh@5y&wv$PxCdx(XDoj;XO~lsIUYcI&pXR!iw_O$v-7>ONo-3}v02-CYc2(e9oY zr@WYt@{Z{k>}-!kqp_}Nv?CUaMSD6sqdKu%W@AzPMMnJ?d z%xpw27lp(IO@jn&ri->UF)2>6Aje8oO37@|*A1L3P@*apQKEBPTPvzyHNk-cfz8z1 zVnK`>#L29!6(O2K#DS}}2>2P~6{=)|K8t6=U`^c}*W6T&rva2G!%-0>VpB7(E*RCD z)6>&jCV+3)z!#FK&}_UbnW~5U5FrhlVa66VH4koFKfGz{&XNAX7Tjlmzs;wPGjs)0e`9()6XXk*m*Tocv-!2-xP%A`8g4 zVJ58!wY{yQy^*+Zf_JjbG_hp`HCz>%-QFH(fJ=oS;mjcfu?_MiKm?$Ia14_495Nl6 zN2co+ktwo(OxI6MH;|8#>4wk}GTkt1E}3qaeKeVd6D<2oPtX7O$CLBPG`n{CU&~XL AaR2}S literal 0 HcmV?d00001 diff --git a/MikroMaster/20260302/20260302221005-Config.rsc b/MikroMaster/20260302/20260302221005-Config.rsc new file mode 100644 index 0000000..cb32e19 --- /dev/null +++ b/MikroMaster/20260302/20260302221005-Config.rsc @@ -0,0 +1,3971 @@ +# 2026-03-02 22:10:05 by RouterOS 7.21.2 +# software id = 2961-C4ZZ +# +# model = RBD52G-5HacD2HnD +# serial number = HCX084RAVFA +/interface bridge +add admin-mac=48:8F:5A:60:A1:0B auto-mac=no name=Bridge-LAN port-cost-mode=\ + short +/interface ethernet +set [ find default-name=ether1 ] comment="WAN - Unet" mac-address=\ + F6:BE:9D:85:53:F5 name="ether1 - Unet" +set [ find default-name=ether3 ] comment=LEN +set [ find default-name=ether4 ] comment=NUC +/interface l2tp-server +add comment=Server disabled=yes name=l2tp-in1 user=vados +/interface l2tp-client +add comment="Starless 2 MikroSPb" connect-to=176.53.203.171 name=l2tp-EoIP \ + user=vados +add allow=mschap2 allow-fast-path=yes comment=Starless connect-to=\ + vpn.starless.ru max-mru=1280 name=l2tp-vpn use-ipsec=yes use-peer-dns=yes \ + user=vados +/interface wireless +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set [ find default-name=wlan1 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 2ghz-b/g/n basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps basic-rates-b=\ + 1Mbps,2Mbps,5.5Mbps,11Mbps channel-width=20/40mhz-XX country=belarus \ + disabled=no frequency=auto hw-protection-mode=rts-cts mode=ap-bridge \ + rate-set=configured skip-dfs-channels=10min-cac ssid=vados \ + station-roaming=enabled wds-default-bridge=Bridge-LAN wds-mode=\ + dynamic-mesh wireless-protocol=802.11 wmm-support=enabled wps-mode=\ + disabled +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set [ find default-name=wlan2 ] ampdu-priorities=0,1,2,3,4,5,6,7 band=\ + 5ghz-a/n/ac basic-rates-a/g=\ + 6Mbps,9Mbps,12Mbps,18Mbps,24Mbps,36Mbps,48Mbps,54Mbps channel-width=\ + 20/40/80mhz-XXXX country=belarus disabled=no frequency=auto \ + hw-protection-mode=rts-cts mode=ap-bridge rate-set=configured \ + skip-dfs-channels=10min-cac ssid=vados5g station-roaming=enabled \ + wds-default-bridge=Bridge-LAN wds-mode=dynamic-mesh wireless-protocol=\ + 802.11 wmm-support=enabled wps-mode=disabled +/interface wireguard +add listen-port=13231 mtu=1280 name=WG +/interface wireless nstreme +# managed by CAPsMAN +# channel: 2422/20-Ce/gn(17dBm), SSID: vados, local forwarding +set wlan1 enable-nstreme=yes +# managed by CAPsMAN +# channel: 5200/20-eCee/ac/P(20dBm), SSID: vados5g, local forwarding +set wlan2 enable-nstreme=yes +/caps-man security +add authentication-types=wpa-psk,wpa2-psk encryption=aes-ccm \ + group-encryption=aes-ccm name=security +/caps-man configuration +add channel.band=2ghz-b/g/n .control-channel-width=20mhz .extension-channel=\ + XX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-2ghz security=security ssid=vados +add channel.band=5ghz-a/n/ac .control-channel-width=20mhz .extension-channel=\ + XXXX country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-ac security=security ssid=vados5g +add channel.band=5ghz-a/n .control-channel-width=20mhz .extension-channel=XX \ + country=belarus datapath.client-to-client-forwarding=yes \ + .local-forwarding=yes name=cfg-5ghz-an security=security ssid=vados5g +/disk +add media-interface=lo slot=tmpfs tmpfs-max-size=44739242 type=tmpfs +# mountpoint [tmpfs] taken by tmpfs +set usb1 mount-point-template="[tmpfs]" +/interface list +add comment=defconf name=WAN +add comment=defconf name=LAN +/interface lte apn +set [ find default=yes ] ip-type=ipv4 use-network-apn=no +/interface wifi channel +add band=5ghz-ax disabled=no frequency=5180,5200,5220,5240 name=5G-AX +add band=5ghz-ac disabled=no frequency=5180,5200,5220,5240 name=5G-AC +add band=2ghz-n disabled=no frequency=2422,2442,2462 name=2G-N +add band=2ghz-ax disabled=no frequency=2422,2442,2462 name=2G-AX +add band=2ghz-g disabled=no frequency=2422,2442,2462 name=2G-G +add band=5ghz-n disabled=no frequency=5180,5200,5220,5240 name=5G-AN +/interface wifi datapath +add bridge=Bridge-LAN disabled=no interface-list=all name=xs-DataPath +/interface wifi security +add authentication-types=wpa2-psk,wpa3-psk disabled=no group-encryption=ccmp \ + group-key-update=1h management-protection=allowed name=sec2g +add authentication-types=wpa3-psk disable-pmkid=yes disabled=no \ + group-encryption=ccmp group-key-update=5m management-encryption=cmac \ + management-protection=required name=sec5G +/interface wifi configuration +add channel=2G-AX datapath=xs-DataPath disabled=no mode=ap name=2G-AX \ + security=sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=2G-N datapath=xs-DataPath disabled=no mode=ap name=2G-N security=\ + sec2g security.ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AX disabled=no mode=ap name=5G-AX security=sec5G security.ft=\ + yes .ft-over-ds=yes ssid=vados +add channel=5G-AC datapath=xs-DataPath disabled=no mode=ap name=5G-AC \ + security=sec5G security.authentication-types="" .ft=yes .ft-over-ds=yes \ + ssid=vados +add channel=2G-G datapath=xs-DataPath disabled=no mode=ap name=2G-G security=\ + sec2g security.authentication-types="" .ft=yes .ft-over-ds=yes ssid=vados +add channel=5G-AN disabled=no mode=ap name=5G-AN security=sec5G ssid=vados +/interface wireless security-profiles +set [ find default=yes ] authentication-types=wpa-psk,wpa2-psk mode=\ + dynamic-keys supplicant-identity=MikroTik +/ip dhcp-server option +add code=12 name=HostName +add code=119 force=yes name=domain-search-list value="0x03'WORKGROUP'0x00" +/ip dhcp-server option sets +add name=HP1505n options=HostName +add name=StartLife1 options=HostName +add name=amsterDev options=HostName +add name=MiTV options=HostName +add name=miller options=HostName +add name=amster options=HostName +add name=garage options=HostName +add name=domain-search-set options=domain-search-list +add name=VADOS-LEN options=HostName +add name=VADOS-NUC options=HostName +add name=MikroNUC options=HostName +add name=master options=HostName +add name=MikroYellow options=HostName +add name="=\"Client ID\"" options=HostName +/ip dns forwarders +add dns-servers=1.1.1.1 name=blsp.at verify-doh-cert=no +/ip ipsec proposal +set [ find default=yes ] disabled=yes +/ip pool +add name=dhcp ranges=10.30.30.150-10.30.30.200 +/ip dhcp-server +add add-arp=yes address-pool=dhcp always-broadcast=yes bootp-support=none \ + dhcp-option-set=domain-search-set interface=Bridge-LAN lease-time=10m \ + name=masterDHCP server-address=10.30.30.81 use-reconfigure=yes +/ip hotspot user profile +set [ find default=yes ] address-pool=dhcp +/ip smb users +set [ find default=yes ] disabled=yes +add disabled=yes name=vados +/ppp profile +set *FFFFFFFE use-upnp=no +/routing bgp template +set default disabled=no output.network=bgp-networks +/routing table +add disabled=no fib name=To-VPN +/snmp community +set [ find default=yes ] addresses=10.30.30.0/24 read-access=no security=\ + private +/system logging action +add email-start-tls=yes email-to=vados@vados.ru name=email target=email +/user group +add name=backup policy="telnet,ssh,ftp,read,write,policy,test,sniff,sensitive,\ + !local,!reboot,!winbox,!password,!web,!api,!romon,!rest-api" +/caps-man manager +set enabled=yes +/caps-man provisioning +add action=create-dynamic-enabled hw-supported-modes=gn master-configuration=\ + cfg-2ghz name-format=prefix-identity name-prefix=2ghz +add action=create-dynamic-enabled hw-supported-modes=ac master-configuration=\ + cfg-5ghz-ac name-format=prefix-identity name-prefix=5ghz-ac +add action=create-dynamic-enabled hw-supported-modes=an master-configuration=\ + cfg-5ghz-an name-format=prefix-identity name-prefix=5ghz-an +/certificate settings +set builtin-trust-store=fetch crl-store=system +/disk settings +set auto-media-interface=lo default-mount-point-template="[tmpfs]" +/ip smb +set comment=MikroVados domain=WORKGROUP enabled=yes interfaces=Bridge-LAN +/interface bridge port +add bridge=Bridge-LAN ingress-filtering=no interface=ether2 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=LEN ingress-filtering=no interface=ether3 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN comment=NUC ingress-filtering=no interface=ether4 \ + internal-path-cost=10 path-cost=10 +add bridge=Bridge-LAN ingress-filtering=no interface=ether5 \ + internal-path-cost=10 path-cost=10 +/ip firewall connection tracking +set udp-timeout=10s +/ip neighbor discovery-settings +set discover-interface-list=LAN +/ip settings +set max-neighbor-entries=8192 secure-redirects=no +/ipv6 settings +set disable-ipv6=yes max-neighbor-entries=8192 +/interface detect-internet +set detect-interface-list=WAN internet-interface-list=WAN lan-interface-list=\ + LAN wan-interface-list=WAN +/interface l2tp-server server +set authentication=mschap2 use-ipsec=yes +/interface list member +add comment=WAN interface="ether1 - Unet" list=WAN +add interface=Bridge-LAN list=LAN +/interface ovpn-server server +add auth=sha1,md5 mac-address=FE:82:A5:78:8E:84 name=ovpn-server1 +/interface wifi cap +set caps-man-addresses=10.30.30.10 certificate=request discovery-interfaces=\ + wlan1,wlan2 lock-to-caps-man=no slaves-static=no +/interface wifi capsman +set package-path="" require-peer-certificate=no upgrade-policy=none +/interface wifi provisioning +add action=create-dynamic-enabled disabled=no master-configuration=2G-N \ + name-format=2G-%I slave-configurations=2G-G supported-bands=\ + 2ghz-n,2ghz-g,2ghz-g +add action=create-dynamic-enabled disabled=no master-configuration=5G-AC \ + name-format=5G-%I supported-bands=5ghz-ac,5ghz-ac +/interface wireguard peers +add allowed-address=10.8.0.2/32,0.0.0.0/0 client-allowed-address=0.0.0.0/0 \ + endpoint-address=89.110.101.17 endpoint-port=29185 interface=WG name=\ + MikroVados persistent-keepalive=10s public-key=\ + "64Y25EUZQQt8EIeAJYD8qWt+te8qvGEepnswdBgmzlY=" +/interface wireless cap +# +set bridge=Bridge-LAN caps-man-certificate-common-names=CAPsMAN-A2A7DF3D5EE6 \ + certificate=CAP-18FD746E5814 discovery-interfaces=Bridge-LAN enabled=yes \ + interfaces=wlan1,wlan2 lock-to-caps-man=yes +/interface wireless sniffer +set file-name=24g +/ip address +add address=10.30.30.81/24 interface=Bridge-LAN network=10.30.30.0 +add address=10.8.0.2/24 interface=WG network=10.8.0.0 +/ip dhcp-client +add add-default-route=special-classless default-route-distance=2 \ + default-route-tables=main interface="ether1 - Unet" use-peer-dns=no +/ip dhcp-server config +set accounting=no +/ip dhcp-server lease +add address=10.30.30.101 client-id=1:48:8f:5a:8e:ee:a8 mac-address=\ + 48:8F:5A:8E:EE:A8 server=masterDHCP +add address=10.30.30.107 client-id=1:f0:de:f1:91:d:1e mac-address=\ + F0:DE:F1:91:0D:1E server=masterDHCP +add address=10.30.30.83 client-id=1:0:80:77:ec:43:86 mac-address=\ + 00:80:77:EC:43:86 server=masterDHCP +add address=10.30.30.70 dhcp-option=domain-search-list,HostName \ + dhcp-option-set=HP1505n mac-address=00:1E:0B:1A:88:8D server=masterDHCP +add address=10.30.30.50 client-id=1:4:7c:16:36:f5:37 mac-address=\ + 04:7C:16:36:F5:37 server=masterDHCP +add address=10.30.30.71 client-id=1:10:2d:41:2c:20:c2 mac-address=\ + 10:2D:41:2C:20:C2 server=masterDHCP +add address=10.30.30.61 client-id=1:10:8:c1:81:59:5f mac-address=\ + 10:08:C1:81:59:5F server=masterDHCP +add address=10.30.30.72 client-id=1:10:38:1f:d2:5f:13 mac-address=\ + 10:38:1F:D2:5F:13 server=masterDHCP +add address=10.30.30.99 client-id=1:10:b1:df:e9:d0:d5 mac-address=\ + 10:B1:DF:E9:D0:D5 server=masterDHCP +add address=10.30.30.111 client-id=1:fe:2:52:be:3f:16 mac-address=\ + FE:02:52:BE:3F:16 server=masterDHCP +add address=10.30.30.92 client-id=1:d4:6d:6d:fd:e5:49 mac-address=\ + D4:6D:6D:FD:E5:49 server=masterDHCP +add address=10.30.30.93 client-id=1:7e:8b:1e:cb:b8:cb mac-address=\ + CC:42:10:12:46:94 server=masterDHCP +add address=10.30.30.94 client-id=1:50:cc:f8:85:96:a mac-address=\ + 50:CC:F8:85:96:0A server=masterDHCP +add address=10.30.30.82 client-id=1:e4:18:6b:58:34:ab mac-address=\ + E4:18:6B:58:34:AB server=masterDHCP +add address=10.30.30.75 client-id=1:0:27:15:41:97:a9 mac-address=\ + 00:27:15:41:97:A9 server=masterDHCP +add address=10.30.30.77 dhcp-option=HostName dhcp-option-set=StartLife1 \ + mac-address=C4:82:E1:03:49:10 server=masterDHCP +add address=10.30.30.73 client-id=1:10:38:1f:82:81:f2 mac-address=\ + 10:38:1F:82:81:F2 server=masterDHCP +add address=10.30.30.95 client-id=1:88:ae:dd:60:39:54 dhcp-option=HostName \ + dhcp-option-set=VADOS-NUC mac-address=88:AE:DD:60:39:54 server=masterDHCP +add address=10.30.30.98 client-id=1:c8:5b:76:d8:cc:bf dhcp-option=HostName \ + dhcp-option-set=VADOS-LEN mac-address=C8:5B:76:D8:CC:BF server=masterDHCP +add address=10.30.30.96 client-id=iPhone mac-address=4A:91:ED:0E:1F:39 \ + server=masterDHCP +add address=10.30.30.74 client-id=MiTV dhcp-option=HostName dhcp-option-set=\ + MiTV mac-address=20:72:A9:D3:34:36 server=masterDHCP +add address=10.30.30.30 dhcp-option=HostName dhcp-option-set=miller \ + mac-address=F0:75:5D:1E:5F:71 server=masterDHCP +add address=10.30.30.100 client-id=iVados dhcp-option=HostName \ + dhcp-option-set="=\"Client ID\"" mac-address=DE:4D:72:F3:1A:9F server=\ + masterDHCP +/ip dhcp-server network +add address=10.30.30.0/24 caps-manager=10.30.30.10 dhcp-option=\ + domain-search-list dhcp-option-set=domain-search-set dns-server=\ + 10.30.30.81,10.30.30.10 domain=WORKGROUP gateway=10.30.30.81 netmask=24 \ + ntp-server=10.30.30.81,10.30.30.10 wins-server=10.30.30.95,10.30.30.98 +/ip dns +set allow-remote-requests=yes cache-max-ttl=1d doh-max-concurrent-queries=100 \ + doh-max-server-connections=20 servers=8.8.8.8,8.8.4.4 verify-doh-cert=yes +/ip dns static +add address=10.30.30.33 comment=AMSTER name=amster.vados.ru type=A +add address=10.30.30.33 name=AMSTER-NUC type=A +add address=10.30.30.33 name=amster type=A +add address=10.30.30.33 name=amster-reg type=A +add address=10.30.30.33 name=mng.vados.ru type=A +add address=10.30.30.33 name=mgr.vados.ru type=A +add address=10.30.30.33 name=prt.vados.ru type=A +add address=10.30.30.33 name=reg.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=ros.vados.ru type=A +add address=10.30.30.33 match-subdomain=yes name=mikrots.vados.ru type=A +add address=10.30.30.33 name=oxidized.vados.ru type=A +add address=8.8.4.4 comment="Google-dns IPv4 2" name=dns.google type=A +add address=8.8.8.8 comment="Google-dns IPv4 1" name=dns.google type=A +add address=10.30.30.30 comment=MILLER name=miller.vados.ru type=A +add address=10.30.30.30 name=MILLER-LEN type=A +add address=10.30.30.30 name=miller type=A +add address=1.0.0.1 comment="CloudFlare-doh IPv4 2" name=\ + security.cloudflare-dns.com type=A +add address=1.1.1.1 comment="CloudFlare-doh IPv4 1" name=\ + security.cloudflare-dns.com type=A +add address=9.9.9.9 comment="Cuad9-dns IPv4 1" disabled=yes name=\ + dns.quad9.net type=A +add address=149.112.112.112 comment="Cuad9-dns IPv4 2" name=dns.quad9.net \ + type=A +add address=91.192.189.2 comment=Unet-DNS disabled=yes name=ns1.unet.ws type=\ + A +add address=10.30.30.81 comment=LocalNet name=MikroVados type=A +add address=10.30.30.85 name=MikroMic type=A +add address=10.30.30.95 name=VADOS-NUC type=A +add address=10.30.30.98 name=VADOS-LEN type=A +add address=10.30.30.20 name=garage type=A +add address=10.30.30.86 name=MikroYellow type=A +/ip firewall address-list +add address=91.215.120.206 list=TRUSTED +add address=185.71.70.78 disabled=yes list=TRUSTED +add address=176.53.203.171 disabled=yes list=TRUSTED +add address=176.53.203.170 disabled=yes list=TRUSTED +add address=176.53.202.194 disabled=yes list=TRUSTED +add address=10.30.30.100-255 list=KIDS +add address=8.8.4.0/24 list=YouTube +add address=8.8.8.0/24 list=YouTube +add address=8.34.208.0/20 list=YouTube +add address=8.35.192.0/20 list=YouTube +add address=23.236.48.0/20 list=YouTube +add address=23.251.128.0/19 list=YouTube +add address=34.0.0.0/15 list=YouTube +add address=34.2.0.0/16 list=YouTube +add address=34.3.0.0/23 list=YouTube +add address=34.3.3.0/24 list=YouTube +add address=34.3.4.0/24 list=YouTube +add address=34.3.8.0/21 list=YouTube +add address=34.3.16.0/20 list=YouTube +add address=34.3.32.0/19 list=YouTube +add address=34.3.64.0/18 list=YouTube +add address=34.4.0.0/14 list=YouTube +add address=34.8.0.0/13 list=YouTube +add address=34.16.0.0/12 list=YouTube +add address=34.32.0.0/11 list=YouTube +add address=34.64.0.0/10 list=YouTube +add address=34.128.0.0/10 list=YouTube +add address=35.184.0.0/13 list=YouTube +add address=35.192.0.0/14 list=YouTube +add address=35.196.0.0/15 list=YouTube +add address=35.198.0.0/16 list=YouTube +add address=35.199.0.0/17 list=YouTube +add address=35.199.128.0/18 list=YouTube +add address=35.200.0.0/13 list=YouTube +add address=35.208.0.0/12 list=YouTube +add address=35.224.0.0/12 list=YouTube +add address=35.240.0.0/13 list=YouTube +add address=57.140.192.0/18 list=YouTube +add address=64.15.112.0/20 list=YouTube +add address=64.233.160.0/19 list=YouTube +add address=66.22.228.0/23 list=YouTube +add address=66.102.0.0/20 list=YouTube +add address=66.249.64.0/19 list=YouTube +add address=70.32.128.0/19 list=YouTube +add address=72.14.192.0/18 list=YouTube +add address=74.125.0.0/16 list=YouTube +add address=104.154.0.0/15 list=YouTube +add address=104.196.0.0/14 list=YouTube +add address=104.237.160.0/19 list=YouTube +add address=107.167.160.0/19 list=YouTube +add address=107.178.192.0/18 list=YouTube +add address=108.59.80.0/20 list=YouTube +add address=108.170.192.0/18 list=YouTube +add address=108.177.0.0/17 list=YouTube +add address=130.211.0.0/16 list=YouTube +add address=136.22.160.0/20 list=YouTube +add address=136.22.176.0/21 list=YouTube +add address=136.22.184.0/23 list=YouTube +add address=136.22.186.0/24 list=YouTube +add address=142.250.0.0/15 list=YouTube +add address=146.148.0.0/17 list=YouTube +add address=152.65.208.0/22 list=YouTube +add address=152.65.214.0/23 list=YouTube +add address=152.65.218.0/23 list=YouTube +add address=152.65.222.0/23 list=YouTube +add address=152.65.224.0/19 list=YouTube +add address=162.120.128.0/17 list=YouTube +add address=162.216.148.0/22 list=YouTube +add address=162.222.176.0/21 list=YouTube +add address=172.110.32.0/21 list=YouTube +add address=172.217.0.0/16 list=YouTube +add address=172.253.0.0/16 list=YouTube +add address=173.194.0.0/16 list=YouTube +add address=173.255.112.0/20 list=YouTube +add address=192.158.28.0/22 list=YouTube +add address=192.178.0.0/15 list=YouTube +add address=193.186.4.0/24 list=YouTube +add address=199.36.154.0/23 list=YouTube +add address=199.36.156.0/24 list=YouTube +add address=199.192.112.0/22 list=YouTube +add address=199.223.232.0/21 list=YouTube +add address=207.223.160.0/20 list=YouTube +add address=208.65.152.0/22 list=YouTube +add address=208.68.108.0/22 list=YouTube +add address=208.81.188.0/22 list=YouTube +add address=208.117.224.0/19 list=YouTube +add address=209.85.128.0/17 list=YouTube +add address=216.58.192.0/19 list=YouTube +add address=216.73.80.0/20 list=YouTube +add address=216.239.32.0/19 list=YouTube +add address=2ip.ru list=Test +add address=157.240.247.174 list=Instagram +add address=46.53.178.107 list=Instagram +add address=179.60.195.174 list=Instagram +add address=157.240.205.174 list=Instagram +add address=31.13.24.0/21 list=Instagram +add address=31.13.64.0/18 list=Instagram +add address=45.64.40.0/22 list=Instagram +add address=66.220.144.0/20 list=Instagram +add address=69.63.176.0/20 list=Instagram +add address=69.171.224.0/19 list=Instagram +add address=74.119.76.0/22 list=Instagram +add address=103.4.96.0/22 list=Instagram +add address=129.134.0.0/16 list=Instagram +add address=157.240.0.0/16 list=Instagram +add address=173.252.64.0/18 list=Instagram +add address=179.60.192.0/22 list=Instagram +add address=185.60.216.0/22 list=Instagram +add address=204.15.20.0/22 list=Instagram +add address=157.240.200.63 list=Instagram +add address=185.60.219.63 list=Instagram +add address=129.134.31.12 list=Instagram +add address=66.81.203.132 list=Instagram +add address=185.89.218.12 list=Instagram +add address=31.13.66.63 list=Instagram +add address=84.15.65.162 list=Instagram +add address=68.66.224.28 list=Instagram +add address=157.240.253.63 list=Instagram +add address=83.174.11.224 list=Instagram +add address=157.240.9.52 list=Instagram +add address=157.240.252.174 list=Instagram +add address=157.240.195.63 list=Instagram +add address=31.13.71.52 list=Instagram +add address=57.144.110.192 list=Instagram +add address=157.240.252.17 list=Instagram +add address=84.15.66.97 list=Instagram +add address=217.168.6.33 list=Instagram +add address=31.13.83.52 list=Instagram +add address=157.240.241.63 list=Instagram +add address=129.134.30.12 list=Instagram +add address=185.89.219.12 list=Instagram +add address=157.240.252.10 list=Instagram +add address=157.240.201.63 list=Instagram +add address=66.81.203.197 list=Instagram +add address=179.60.195.52 list=Instagram +add address=66.81.203.7 list=Instagram +add address=216.40.34.41 list=Instagram +add address=157.240.202.63 list=Instagram +add address=157.240.229.63 list=Instagram +add address=157.240.252.63 list=Instagram +add address=31.13.72.53 list=Instagram +add address=124.108.16.224 list=Instagram +add address=157.240.205.63 list=Instagram +add address=92.46.37.96 list=Instagram +add address=157.240.247.63 list=Instagram +add address=157.240.234.63 list=Instagram +add address=157.240.235.63 list=Instagram +add address=87.245.208.97 list=Instagram +add address=216.58.192.0/19 list=Instagram +add address=209.85.128.0/17 list=Instagram +add address=198.105.240.0/20 list=Instagram +add address=173.194.0.0/16 list=Instagram +add address=172.217.0.0/16 list=Instagram +add address=142.250.0.0/15 list=Instagram +add address=108.177.0.0/17 list=Instagram +add address=87.245.197.140 list=Instagram +add address=74.125.0.0/16 list=Instagram +add address=64.233.160.0/19 list=Instagram +add address=157.240.0.1 list=Instagram +add address=157.240.238.63 list=Instagram +add address=157.240.238.174 list=Instagram +add address=157.240.0.63 list=Instagram +add address=157.240.224.63 list=Instagram +add address=157.240.224.174 list=Instagram +add address=157.240.251.36 list=Instagram +add address=157.240.253.12 list=Instagram +add address=157.240.253.35 list=Instagram +add address=157.240.238.13 list=Instagram +add address=157.240.238.56 list=Instagram +add address=157.240.238.175 list=Instagram +add address=57.144.112.141 list=Instagram +add address=157.240.251.60 list=Instagram +add address=157.240.251.128 list=Instagram +add address=157.240.238.5 list=Instagram +add address=157.240.253.13 list=Instagram +add address=157.240.253.5 list=Instagram +add address=157.240.238.2 list=Instagram +add address=157.240.238.37 list=Instagram +add address=157.240.251.5 list=Instagram +add address=157.240.251.34 list=Instagram +add address=57.144.112.1 list=Instagram +add address=157.240.238.54 list=Instagram +add address=129.134.26.123 list=Instagram +add address=157.240.252.3 list=Instagram +add address=31.13.84.4 list=Instagram +add address=157.240.224.12 list=Instagram +add address=157.240.238.4 list=Instagram +add address=157.240.0.13 list=Instagram +add address=3.33.139.32 list=Instagram +add address=157.240.0.35 list=Instagram +add address=157.240.238.14 list=Instagram +add address=157.240.238.60 list=Instagram +add address=57.144.112.145 list=Instagram +add address=157.240.251.35 list=Instagram +add address=151.101.84.159 list=Twitter +add address=pbs.twimg.com list=Twitter +add address=89.110.101.17 comment=VDSIna list=TRUSTED +add address=10.8.0.0/24 comment="WG VDSIna" list=TRUSTED +add address=ikus.pesc.ru comment=ikus.pesc.ru list=NoVdsina +add address=love.ru comment=love.ru list=NoVdsina +add address=gosuslugi.ru comment=gosuslugi.ru list=NoVdsina +add address=pochta.ru comment=pochta.ru list=NoVdsina +add address=vdsina.com list=NoVdsina +add address=vdsina.ru list=NoVdsina +add address=youla.ru list=NoVdsina +add address=kupiprodai.ru list=NoVdsina +add address=myip.ru list=Test +add address=geoip.co list=NoVdsina +add address=x.com list=Twitter +add address=facebook.com list=facebook +add address=fbcd.net list=facebook +add address=comp-lenta.ru list=NoVdsina +add address=128.85.102.70 comment=update.microsoft.com list=\ + windowsupdateslist +add address=wu-b-net.trafficmanager.net. comment=\ + ctldl.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=ctldl.windowsupdate.com.delivery.microsoft.com. comment=\ + ctldl.windowsupdate.com list=windowsupdateslist +add address=redir.update.msft.com.trafficmanager.net. comment=\ + update.microsoft.com list=windowsupdateslist +add address=geo.prod.do.dsp.trafficmanager.net. comment=\ + geo.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=13.74.139.29 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12437.d.akamaiedge.net. comment=\ + kv801.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=displaycatalog-rp.md.mp.microsoft.com.akadns.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=rp-consumer-prod-displaycatalog-geomap.trafficmanager.net. \ + comment=displaycatalog-rp.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=sls.update.microsoft.com. comment=slscr.update.microsoft.com \ + list=windowsupdateslist +add address=glb.sls.prod.dcat.dsp.trafficmanager.net. comment=\ + sls.update.microsoft.com list=windowsupdateslist +add address=fe3.delivery.mp.microsoft.com. comment=\ + fe3cr.delivery.mp.microsoft.com list=windowsupdateslist +add address=glb.cws.prod.dcat.dsp.trafficmanager.net. comment=\ + fe3.delivery.mp.microsoft.com list=windowsupdateslist +add address=fe2cr.update.msft.com.trafficmanager.net. comment=\ + fe2cr.update.microsoft.com list=windowsupdateslist +add address=download.windowsupdate.com.delivery.microsoft.com. comment=\ + download.windowsupdate.com list=windowsupdateslist +add address=wu-f-net.trafficmanager.net. comment=\ + download.windowsupdate.com.delivery.microsoft.com list=windowsupdateslist +add address=tsfe.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=edge.ds-c7110-microsoft.global.dns.qwilted-cds.cqloud.com. \ + comment=9.au.download.windowsupdate.com list=windowsupdateslist +add address=52.158.227.125 comment=array812.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dspw65.akamai.net. comment=\ + download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.151.58.88 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net. \ + comment=licensing.mp.microsoft.com list=windowsupdateslist +add address=licensing-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-licensing-aks2aks.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-nlu-net.trafficmanager.net. comment=\ + star.f.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.b.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-tlu-net.trafficmanager.net. comment=\ + star.b.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=storeedgefd.xbetservices.akadns.net. comment=\ + storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net. \ + comment=storeedgefd.dsx.mp.microsoft.com.edgekey.net list=\ + windowsupdateslist +add address=e16646.dscg.akamaiedge.net. comment=\ + storeedgefd.dsx.mp.microsoft.com.edgekey.net.globalredir.akadns.net list=\ + windowsupdateslist +add address=40.69.76.189 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=bg.microsoft.map.fastly.net. comment=\ + 3.au.download.windowsupdate.com list=windowsupdateslist +add list=windowsupdateslist +add address=40.69.75.33 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sf.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=cdp-f-ssl-tlu-net.trafficmanager.net. comment=\ + star.sf.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a2033.dscd.akamai.net. comment=\ + star.sb.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.138.242 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-nlu-net.trafficmanager.net. comment=\ + dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=1D.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-b-tlu-net.trafficmanager.net. comment=\ + 1d.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a122.dscg3.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=windowsupdateslist +add address=geover.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e10370.d.akamaiedge.net. comment=\ + geover.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=52.232.182.21 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.95 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=a1683.dscd.akamai.net. comment=\ + dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net. \ + comment=collections.mp.microsoft.com list=windowsupdateslist +add address=a1847.dscd.akamai.net. comment=\ + wildcard.f.tlu.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=13.74.142.6 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=au.download.windowsupdate.com.edgesuite.net. comment=\ + 2.au.download.windowsupdate.com list=windowsupdateslist +add address=a767.dscg3.akamai.net. comment=\ + au.download.windowsupdate.com.edgesuite.net list=windowsupdateslist +add address=52.156.123.84 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.78.254 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=4.au.download.windowsupdate.com.delivery.microsoft.com. comment=\ + 4.au.download.windowsupdate.com list=windowsupdateslist +add address=cl-glcb907925.gcdn.co. comment=\ + 4.au.download.windowsupdate.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.111 comment=array510.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.69.70.43 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com. \ + comment=tsfe.trafficshaping.dsp.mp.microsoft.com list=windowsupdateslist +add address=ts-frontend.trafficmanager.net. comment=\ + tsfe.trafficshaping.dsp.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=40.69.75.248 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.74.84 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=sds.trafficmanager.net. comment=software-download.microsoft.com \ + list=windowsupdateslist +add address=40.69.74.80 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.175.242.182 comment=array804.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=dlc-shim.trafficmanager.net. comment=download.microsoft.com list=\ + windowsupdateslist +add address=e12671.dscd.akamaiedge.net. comment=\ + download.microsoft.com.edgekey.net list=windowsupdateslist +add address=20.187.55.34 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.231 comment=array513.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.222.13 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=e12358.d.akamaiedge.net. comment=\ + kv601.prod.do.dsp.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. comment=\ + tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=dcat-f-tlu-net.trafficmanager.net. comment=\ + tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=a1856.dspw65.akamai.net. comment=\ + tlu.dl.delivery.mp.microsoft.com-c.edgesuite.net list=windowsupdateslist +add address=52.167.164.252 comment=array506.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=13.74.137.54 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=kv501.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + kv501.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=collections-prod-frontdoor-geomap.trafficmanager.net. comment=\ + consumer-collections-aks2eap.md.mp.microsoft.com.akadns.net list=\ + windowsupdateslist +add address=52.167.160.173 comment=array509.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.77.148 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.200.126 comment=array507.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=52.167.167.59 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.172 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=82.202.162.184 comment=comp-lenta.ru list=NoWG +add address=smtp.mail.me.com.akadns.net. comment=smtp.mail.me.com list=NoWG +add address=17.57.155.37 comment=smtp.mail.me.com.akadns.net list=NoWG +add address=smtp.mail.me.com comment=smtp.mail.me.com list=NoVdsina +add address=40.70.76.5 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.186.119 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.177.176.186 comment=array520.prod.do.dsp.mp.microsoft.com \ + list=windowsupdateslist +add address=40.70.76.27 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.160.43 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.110 comment=array817.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.142.8 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.138.254 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.167.96 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.69.76.215 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.143.200 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.111 comment=array818.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.112 comment=array819.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=13.74.137.53 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.98 comment=array805.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.96 comment=array803.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.104 comment=array811.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.101 comment=array808.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.99 comment=array806.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.17 comment=array802.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.97 comment=array804.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.103 comment=array810.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.16 comment=array801.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=40.70.77.177 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.164.84 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.105 comment=array812.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.107 comment=array814.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.232.161.82 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.108 comment=array815.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=52.167.161.91 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.102 comment=array809.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.109 comment=array816.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.106 comment=array813.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.117 comment=array622.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.107 comment=array612.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.108 comment=array613.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.105 comment=array610.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.113 comment=array618.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.116 comment=array621.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.98 comment=array603.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.114 comment=array619.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.111 comment=array616.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.97 comment=array602.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.106 comment=array611.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.110 comment=array615.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.119 comment=array624.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.135 comment=array514.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.97 comment=array503.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.99 comment=array604.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.61 comment=array504.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.131 comment=array510.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.132 comment=array511.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.96 comment=array601.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.104 comment=array609.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.138 comment=array517.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.60 comment=array501.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.139 comment=array518.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.118 comment=array623.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.113 comment=array820.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.103 comment=array608.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.154.7.100 comment=array807.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.129 comment=array508.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.134 comment=array513.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.62 comment=array505.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.137 comment=array516.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.101 comment=array606.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.96 comment=array502.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.130 comment=array509.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.112 comment=array617.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.100 comment=array605.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.115 comment=array620.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.136 comment=array515.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=purchase.md.mp.microsoft.com.akadns.net. comment=\ + purchase.mp.microsoft.com list=windowsupdateslist +add address=e110219.a.akamaiedge.net. comment=\ + purchase.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=72.153.5.140 comment=array519.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.141 list=windowsupdateslist +add address=72.153.5.63 comment=array506.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.128 comment=array507.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.102 comment=array607.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=storesdk.xbetservices.akadns.net. comment=\ + storesdk.dsx.mp.microsoft.com list=windowsupdateslist +add address=e16646.g.akamaiedge.net. comment=\ + storesdk.dsx.mp.microsoft.com.edgekey.net list=windowsupdateslist +add address=software-download.microsoft.com.delivery.microsoft.com. comment=\ + software-download.microsoft.com list=windowsupdateslist +add address=download.prss.microsoft.com.akamaized.net. comment=\ + software-download.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=72.145.35.109 comment=array614.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=72.153.5.133 comment=array512.prod.do.dsp.mp.microsoft.com list=\ + windowsupdateslist +add address=213.180.192.0/19 comment=YandexDisk list=NoVdsina +add address=87.250.250.50 comment=YandexDisk list=NoVdsina +add address=consumer-prod-bcfd-v7-afd.trafficmanager.net. comment=\ + displaycatalog.mp.microsoft.com list=windowsupdateslist +add address=purchase-europeeap.md.mp.microsoft.com.akadns.net. comment=\ + purchase.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=ne-az-conspurchase-mp.trafficmanager.net. comment=\ + purchase-europeeap.md.mp.microsoft.com.akadns.net list=windowsupdateslist +add address=storeedgefd.dsx.mp.microsoft.com.edgekey.net. comment=\ + cdn.storeedgefd.dsx.mp.microsoft.com list=windowsupdateslist +add address=star.f.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.f.tlu.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=a1996.dscd.akamai.net. comment=\ + wildcard.f.dl.delivery.mp.microsoft.com.edgesuite.net list=\ + windowsupdateslist +add address=cp801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=glb.tas02.sls-prod.dcat.dsp.mp.microsoft.com. comment=\ + tas02.sls.update.microsoft.com list=windowsupdateslist +add address=cp601.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + cp601.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +add address=star.sb.tlu.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedgeextensions.sb.tlu.dl.delivery.mp.microsoft.com list=\ + windowsupdateslist +add address=star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com. \ + comment=msedge.sf.dl.delivery.mp.microsoft.com list=windowsupdateslist +add address=cdp-f-ssl-nlu-net.trafficmanager.net. comment=\ + star.sf.dl.delivery.mp.microsoft.com.delivery.microsoft.com list=\ + windowsupdateslist +add address=tm-pifd-prod-gbl-weight.trafficmanager.net. comment=\ + paymentinstruments.mp.microsoft.com list=windowsupdateslist +add address=10.30.30.33 comment=NUC list=NoWG +add address=10.30.30.10 comment=MikroNUC list=NoWG +add address=89.110.101.17 comment=!!!VDSINA!!!! list=NoWG +add address=89.110.101.17 list=VPN-Server +add address=80.85.244.9 list=TRUSTED +add address=8.8.8.8 list=TRUSTED +add address=8.8.4.4 list=TRUSTED +add address=disc801.prod.do.dsp.mp.microsoft.com.edgekey.net. comment=\ + disc801.prod.do.dsp.mp.microsoft.com list=windowsupdateslist +/ip firewall filter +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=12h chain=input comment="block honeypot DNS" \ + connection-state=new disabled=yes dst-port=53 in-interface=\ + "ether1 - Unet" protocol=udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input connection-state=new dst-port=53 \ + in-interface="ether1 - Unet" protocol=tcp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment=\ + "block honeypot ssh rdp winbox" connection-state=new dst-port=\ + 22,8291,2222 in-interface="ether1 - Unet" protocol=tcp src-address-list=\ + !TRUSTED +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=4w2d chain=input comment="block honeypot asterisk" \ + connection-state=new dst-port=5060 in-interface="ether1 - Unet" protocol=\ + udp +add action=add-src-to-address-list address-list="Honeypot Hacker" \ + address-list-timeout=5d chain=input comment="block honeypot NTP" \ + connection-state=new dst-port=123 in-interface="ether1 - Unet" protocol=\ + udp src-address=!10.30.30.0/24 +add action=accept chain=input comment=\ + "accept NTP clients on local area network" dst-port=123 in-interface=\ + Bridge-LAN in-interface-list=LAN protocol=udp +add action=accept chain=input comment="accept WireGuard" dst-port=13231 \ + in-interface="ether1 - Unet" protocol=udp src-address-list=VPN-Server +add action=accept chain=input disabled=yes dst-port=443 in-interface=\ + "ether1 - Unet" protocol=tcp +add action=accept chain=output disabled=yes protocol=tcp src-port=443 +add action=fasttrack-connection chain=forward comment=\ + "FastTrack for non-VPN connections" connection-mark=!VPN_No_FastTrack \ + connection-state=established,related,new disabled=yes +add action=fasttrack-connection chain=forward comment="defconf: fasttrack" \ + connection-state=established,related,new disabled=yes routing-mark=\ + !To-VPN +add action=accept chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMP" disabled=yes \ + protocol=icmp +add action=accept chain=input comment=\ + "defconf: accept to local loopback (for CAPsMAN)" disabled=yes \ + dst-address=127.0.0.1 +add action=accept chain=output disabled=yes src-address=127.0.0.1 +add action=accept chain=forward comment="defconf: accept in ipsec policy" \ + ipsec-policy=in,ipsec +add action=accept chain=forward comment="defconf: accept out ipsec policy" \ + ipsec-policy=out,ipsec +add action=accept chain=forward comment=\ + "defconf: accept established,related, untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop all from WAN not DSTNATed" connection-nat-state=!dstnat \ + connection-state=new in-interface="ether1 - Unet" +add action=accept chain=input connection-state=established disabled=yes +add action=accept chain=input connection-state=related disabled=yes +add action=drop chain=input disabled=yes in-interface-list=!LAN +add action=drop chain=forward comment=\ + "Filter Rule to block FB address LIST : )" disabled=yes dst-address-list=\ + facebook +add action=drop chain=forward comment=\ + "Filter Rule to block YOUTUBE address LIST : )" disabled=yes \ + dst-address-list=YouTube +/ip firewall mangle +add action=mark-connection chain=prerouting comment=\ + "Mark VPN connections to exclude from FastTrack" in-interface=WG \ + log-prefix=Mark-VPN-FT new-connection-mark=VPN_No_FastTrack +add action=mark-routing chain=prerouting comment="Test sites" disabled=yes \ + dst-address=!10.30.30.0/24 dst-address-list=Test new-routing-mark=To-VPN \ + passthrough=no src-address=10.30.30.0/24 +add action=mark-routing chain=prerouting comment=Instagram dst-address=\ + !10.30.30.0/24 dst-address-list=Instagram new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=Twitter dst-address=\ + !10.30.30.0/24 dst-address-list=Twitter new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=YouTube dst-address=\ + !10.30.30.0/24 dst-address-list=YouTube new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment=facebook dst-address=\ + !10.30.30.0/24 dst-address-list=facebook new-routing-mark=To-VPN \ + src-address=10.30.30.0/24 src-address-list=!NoWG +add action=mark-routing chain=prerouting comment="VDSIna for All sites" \ + dst-address=!10.30.30.0/24 dst-address-list=!NoVdsina log-prefix=VPN-all \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +add action=change-mss chain=forward comment="MSS on WG" new-mss=1380 \ + out-interface=WG protocol=tcp tcp-flags=syn tcp-mss=1381-65535 +add action=mark-routing chain=prerouting comment="VPN Network" dst-address=\ + 10.8.0.0/24 dst-address-list=!NoVdsina log=yes log-prefix=VPN-Net \ + new-routing-mark=To-VPN src-address=10.30.30.0/24 src-address-list=!NoWG +/ip firewall nat +add action=redirect chain=dstnat comment=\ + "FORCE DNS TO LOCAL MIKROTIK DNS SERVER" dst-port=53 in-interface-list=\ + LAN protocol=tcp to-ports=53 +add action=redirect chain=dstnat dst-port=53 in-interface-list=LAN protocol=\ + udp +add action=masquerade chain=srcnat comment="masquerade Default" ipsec-policy=\ + out,none out-interface="ether1 - Unet" routing-mark=!To-VPN +add action=masquerade chain=srcnat comment=WG dst-address-list=!NoVdsina \ + in-interface=Bridge-LAN log-prefix=WG-nat out-interface=WG routing-mark=\ + To-VPN +add action=dst-nat chain=dstnat comment=npm dst-port=81 in-interface=\ + "ether1 - Unet" protocol=tcp to-addresses=10.30.30.33 to-ports=81 +add action=dst-nat chain=dstnat comment=amster.vados.ruhttps disabled=yes \ + dst-port=443 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=443 +add action=dst-nat chain=dstnat comment="amster.vados.ru For Certbot HTTP" \ + dst-port=80 in-interface="ether1 - Unet" protocol=tcp to-addresses=\ + 10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat dst-port=80 in-interface="ether1 - Unet" \ + protocol=tcp to-addresses=10.30.30.33 to-ports=80 +add action=dst-nat chain=dstnat comment="Yandex.DNS Family" disabled=yes \ + dst-port=53 in-interface=Bridge-LAN protocol=udp src-address-list=KIDS \ + time=6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +add action=dst-nat chain=dstnat disabled=yes dst-port=53 in-interface=\ + Bridge-LAN protocol=tcp src-address-list=KIDS time=\ + 6h-15m,sun,mon,tue,wed,thu,fri,sat to-addresses=77.88.8.3 +/ip firewall raw +add action=drop chain=prerouting comment="Drop Honeypot Hackers" \ + in-interface="ether1 - Unet" src-address-list="Honeypot Hacker" +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + extras.getpagespeed.com content=extras.getpagespeed.com disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=linux.duke.edu \ + content=linux.duke.edu disabled=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=vk.com \ + content=vk.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=ok.ru content=\ + ok.ru +add action=add-dst-to-address-list address-list=Instagram \ + address-list-timeout=none-dynamic chain=prerouting comment=Instagram \ + content=instagram.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting comment=Twitter content=twimg.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=x.com +add action=add-dst-to-address-list address-list=Twitter address-list-timeout=\ + none-dynamic chain=prerouting content=twitter.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting comment=YouTube content=youtube.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleapis.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ggpht.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=youtu.be +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=ytimg.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googlevideo.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=gstatic.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=googleusercontent.com +add action=add-dst-to-address-list address-list=YouTube address-list-timeout=\ + none-dynamic chain=prerouting content=nhacmp3youtube.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=rutube.ru \ + content=rutube.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=me.com \ + content=me.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=icloud.com \ + content=icloud.com +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting comment=facebook \ + content=fbcd.net +add action=add-dst-to-address-list address-list=facebook \ + address-list-timeout=none-dynamic chain=prerouting content=facebook.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=comp-lenta.ru \ + content=comp-lenta.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + smtp.mail.me.com content=smtp.mail.me.com log=yes +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=gov.ru \ + content=gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + r78.fssp.gov.ru content=r78.fssp.gov.ru +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=api.db-ip.com \ + content=api.db-ip.com +add action=add-dst-to-address-list address-list=NoVdsina \ + address-list-timeout=none-dynamic chain=prerouting comment=\ + api.telegram.org content=api.telegram.org +/ip firewall service-port +set ftp disabled=yes +set tftp disabled=yes +set irc disabled=no +set sip disabled=yes +set pptp disabled=yes +set rtsp disabled=no +/ip hotspot walled-garden +add server=*1 +/ip ipsec settings +set accounting=no +/ip ipsec policy +set 0 disabled=yes dst-address=0.0.0.0/0 src-address=0.0.0.0/0 +/ip ipsec profile +set [ find default=yes ] dpd-interval=2m dpd-maximum-failures=5 +/ip proxy +set cache-administrator="" max-cache-size=none port=80,443 src-address=\ + 0.0.0.0 +/ip route +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=3 dst-address=192.168.0.0/24 gateway=l2tp-vpn +add disabled=no distance=4 dst-address=192.168.5.0/24 gateway=l2tp-vpn +add disabled=no distance=1 dst-address=0.0.0.0/0 gateway=WG routing-table=\ + To-VPN scope=30 target-scope=10 +add disabled=no distance=2 dst-address=0.0.0.0/0 gateway=146.120.64.209 \ + routing-table=main scope=30 target-scope=10 +/ip service +set ftp disabled=yes +set telnet disabled=yes +set ssh address=10.30.30.0/24 port=2222 +set winbox address=10.30.30.0/24 +set api address=10.30.30.0/24 disabled=yes +set api-ssl address=10.30.30.0/24 +set www-ssl port=18443 +set www address=10.30.30.0/24 disabled=yes port=18880 +/ip service webserver +set acme-plain=no crl-plain=no graphs-plain=no graphs-secure=no index-plain=\ + no index-secure=no rest-plain=no rest-secure=no scep-plain=no \ + webfig-plain=no webfig-secure=no +/ip ssh +set forwarding-enabled=both publickey-authentication-options=verify-required \ + strong-crypto=yes +/ip upnp +set enabled=yes +/ip upnp interfaces +add interface=Bridge-LAN type=internal +add interface="ether1 - Unet" type=external +/ipv6 firewall address-list +add address=::/128 comment="defconf: unspecified address" list=bad_ipv6 +add address=::1/128 comment="defconf: lo" list=bad_ipv6 +add address=fec0::/10 comment="defconf: site-local" list=bad_ipv6 +add address=::ffff:0.0.0.0/96 comment="defconf: ipv4-mapped" list=bad_ipv6 +add address=::/96 comment="defconf: ipv4 compat" list=bad_ipv6 +add address=100::/64 comment="defconf: discard only " list=bad_ipv6 +add address=2001:db8::/32 comment="defconf: documentation" list=bad_ipv6 +add address=2001:10::/28 comment="defconf: ORCHID" list=bad_ipv6 +add address=3ffe::/16 comment="defconf: 6bone" list=bad_ipv6 +/ipv6 firewall filter +add action=add-src-to-address-list address-list=bad_ipv6 \ + address-list-timeout=none-dynamic chain=input comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked in-interface=WG in-interface-list=WAN \ + src-address-list="" +add action=drop chain=input comment="defconf: drop invalid" connection-state=\ + invalid +add action=accept chain=input comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=input comment="defconf: accept UDP traceroute" \ + dst-port=33434-33534 protocol=udp +add action=accept chain=input comment=\ + "defconf: accept DHCPv6-Client prefix delegation." dst-port=546 protocol=\ + udp src-address=fe80::/10 +add action=accept chain=input comment="defconf: accept IKE" dst-port=500,4500 \ + protocol=udp +add action=accept chain=input comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=input comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=input comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=input comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +add action=accept chain=forward comment=\ + "defconf: accept established,related,untracked" connection-state=\ + established,related,untracked +add action=drop chain=forward comment="defconf: drop invalid" \ + connection-state=invalid +add action=drop chain=forward comment=\ + "defconf: drop packets with bad src ipv6" src-address-list=bad_ipv6 +add action=drop chain=forward comment=\ + "defconf: drop packets with bad dst ipv6" dst-address-list=bad_ipv6 +add action=drop chain=forward comment="defconf: rfc4890 drop hop-limit=1" \ + hop-limit=equal:1 protocol=icmpv6 +add action=accept chain=forward comment="defconf: accept ICMPv6" protocol=\ + icmpv6 +add action=accept chain=forward comment="defconf: accept HIP" protocol=139 +add action=accept chain=forward comment="defconf: accept IKE" dst-port=\ + 500,4500 protocol=udp +add action=accept chain=forward comment="defconf: accept ipsec AH" protocol=\ + ipsec-ah +add action=accept chain=forward comment="defconf: accept ipsec ESP" protocol=\ + ipsec-esp +add action=accept chain=forward comment=\ + "defconf: accept all that matches ipsec policy" ipsec-policy=in,ipsec +add action=drop chain=forward comment=\ + "defconf: drop everything else not coming from LAN" in-interface-list=\ + !LAN +/ipv6 nd +set [ find default=yes ] advertise-dns=yes +/ppp secret +add local-address=192.168.60.1 name=vados remote-address=192.168.60.2 \ + service=l2tp +/routing bfd configuration +add disabled=no +/snmp +set contact=@AmsterNL enabled=yes engine-id-suffix=MikroMaster location=NL \ + src-address=10.30.30.81 trap-interfaces=Bridge-LAN,WG trap-target=\ + 10.30.30.10 +/system clock +set time-zone-autodetect=no time-zone-name=Europe/Moscow +/system clock manual +set time-zone=+03:00 +/system identity +set name=MikroMaster +/system logging +add action=email disabled=yes regex="* added|changed|removed *" topics=\ + system,info +/system ntp client +set enabled=yes +/system ntp server +set enabled=yes manycast=yes multicast=yes use-local-clock=yes +/system ntp client servers +add address=0.ru.pool.ntp.org +add address=1.ru.pool.ntp.org +add address=2.ru.pool.ntp.org +add address=3.ru.pool.ntp.org +add address=time.google.com disabled=yes +/system scheduler +add comment="Windows Update script" interval=2d5m name=WU-script-run-schedule \ + on-event=WU-add-to-list policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2014-02-11 start-time=00:00:00 +add comment="Backup Every Week" disabled=yes interval=1w name=BackupEveryWeek \ + on-event=BackupAndUpdate policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-07-07 start-time=03:41:27 +add comment="DoH Cache Flush" interval=1d name="DNS Cache Flush" on-event=\ + DNS_Flush_Cache policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2019-12-06 start-time=05:30:00 +add comment="Create mkdir function on startup" name=\ + create_mkdir_function_on_startup on-event=\ + "/system script run create_mkdir_function;" policy=read,write,policy,test \ + start-time=startup +add comment="Scheduler for Update Certificates CloudFlare Quad9" interval=1w \ + name="Update Certificates CloudFlare Quad9" on-event=\ + "/system/script { run Update-Certificates; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2025-11-28 start-time=05:45:40 +add comment="Scheduler for Amster-Backup-UpdateEmail" disabled=yes interval=\ + 1w name=Amster-Backup-UpdateEmail on-event=\ + "/system/script { run Amster-Backup-UpdateEmail; }" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-date=2026-02-13 start-time=03:41:27 +add comment="Setup Global Environment for scripts" name=AM-SetGlobalEnv \ + on-event="/system/script { run AM-GlobalConfig; run AM-GlobalFunc; }" \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +add comment="Every Day Check For Update Scripts" interval=1d name=\ + AM-ScriptInstallUpdate on-event=\ + ":global ScriptInstallUpdate; \$ScriptInstallUpdate;" policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + start-time=startup +/system script +add comment="Example add WU servers to AddrList" dont-require-permissions=no \ + name=WU-add-to-list owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# Syed Jahanzaib / aacable@hotmail.com\r\ + \n# List name\r\ + \n:local LISTNAME \"windowsupdateslist\"\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"update.microsoft.com\"\r\ + \n:local TARGET2 \"download.windowsupdate.com\"\r\ + \n:local TARGET3 \"download.microsoft.com\"\r\ + \n:local TARGET4 \"windowsupdate.com\"\r\ + \n:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n:local TARGET6 \"wustat.windows.com\"\r\ + \n:local TARGET7 \"stats.microsoft.com\"\r\ + \n:local TARGET8 \"mp.microsoft.com\"\r\ + \n:local TARGET9 \"ws.microsoft.com\"\r\ + \n:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n \r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n \r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4|\$TARGET5|\$TARGET6|\$TARGET7|\$TARGET8|\$TARGET9|\$TARGET10|\$T\ + ARGET11|\$TARGET12|\$TARGET13|\$TARGET14)\" && \$type ~ \"^(A|CNAME)\\\$\"\ + \_] do={\r\ + \n \r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n \r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Add Hosts DNS names to NoWG addres list" \ + dont-require-permissions=no name=Add2vdsina owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_Script to add target web sites DNS IP addresses into address list\r\ + \n# Tested with Mikrotik 6.4x\r\ + \n# \r\ + \n# List name\r\ + \n:local LISTNAME \"NoWG\"\r\ + \n#\r\ + \n# Web site names which will be added in address list\r\ + \n:local TARGET1 \"comp-lenta.ru\"\r\ + \n:local TARGET2 \"ok.ru\"\r\ + \n:local TARGET3 \"vk.com\"\r\ + \n#:local TARGET4 \"smtp.mail.me.com\"\r\ + \n#:local TARGET4 \"windowsupdate.com\"\r\ + \n#:local TARGET5 \"ntservicepack.microsoft.com\"\r\ + \n#:local TARGET6 \"wustat.windows.com\"\r\ + \n#:local TARGET7 \"stats.microsoft.com\"\r\ + \n#:local TARGET8 \"mp.microsoft.com\"\r\ + \n#:local TARGET9 \"ws.microsoft.com\"\r\ + \n#:local TARGET10 \"sls.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET11 \"vortex.data.microsoft.com\"\r\ + \n#:local TARGET12 \"vortex-win.data.microsoft.com\"\r\ + \n#:local TARGET13 \"fe2.update.microsoft.com.akadns.net\"\r\ + \n#:local TARGET14 \"statsfe2.update.microsoft.com.akadns.net\"\r\ + \n \r\ + \n# 1st time runner, check if address list is not created previously and a\ + dd entries in it for 1st time usage\r\ + \n:if ( [/ip firewall address-list find where list=\$LISTNAME] = \"\") do=\ + {\r\ + \n:log warning \"No address list for \$TARGET1 found ! creating and adding\ + \_resolved entry for 1st time usage ... zaib\"\r\ + \n\r\ + \n:local FirstAddr [resolve \$TARGET1];\r\ + \n\r\ + \n/ip firewall address-list add address=\$FirstAddr list=\$LISTNAME commen\ + t=\$TARGET1;\r\ + \n\r\ + \n} else={\r\ + \n:log warning \"Previous List for \$LISTNAME found ! moving forward and c\ + hecking if DNS entries can be added in it ...\"\r\ + \n}\r\ + \n\r\ + \n# Check DNS entries and collect matching names\r\ + \n:foreach i in=[/ip dns cache find name~\"(\$TARGET1|\$TARGET2|\$TARGET3|\ + \$TARGET4)\" && \$type ~ \"^(A|CNAME)\\\$\" ] do={\r\ + \n\r\ + \n:log info (\"start entry: \$c \$sitednsname \$Buffer\");\r\ + \n\r\ + \n# Get IP Address from the names and hold it in temporary buffer\r\ + \n:local Buffer [/ip dns cache get \$i data];\r\ + \ndelay delay-time=10ms\r\ + \n:log info (\"1: \$Buffer\"); \r\ + \n\r\ + \n# Check if entry is already not exists, then OK, otherwise ignore duplic\ + ation\r\ + \n:if ( [/ip firewall address-list find where address=\$Buffer] = \"\") do\ + ={\r\ + \n\r\ + \n:log info (\"2: \$Buffer\"); \r\ + \n \r\ + \n# Fetch DNS names for the entries\r\ + \n:local sitednsname [/ip dns cache get \$i name] ;\r\ + \n \r\ + \n# Print name in LOG window\r\ + \n:log info (\"added entry: \$i \$sitednsname \$Buffer\");\r\ + \n \r\ + \n# Add IP addresses and there names to the address list\r\ + \n/ip firewall address-list add address=\$Buffer list=\$LISTNAME comment=\ + \$sitednsname;\r\ + \n}\r\ + \n}" +add comment="Flush DNS Cache" dont-require-permissions=no name=\ + DNS_Flush_Cache owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source=\ + "/ip dns cache flush" +add dont-require-permissions=no name=create_mkdir_function owner=vados \ + policy=read,write source="# Written by Phillip Stromberg in 2019\r\ + \n# Distributed under the MIT license\r\ + \n# \r\ + \n# \r\ + \n# this creates a function called \$mkdir\r\ + \n# from the command line you will be able to just type \"\$mkdir some/new\ + /folder\"\r\ + \n# and all the folders that need to be created will be\r\ + \n# if the folder already existed, it is ignored\r\ + \n\r\ + \n:log info \"Creating \\\$mkdir function...\"\r\ + \n\r\ + \n:global mkdir do={\r\ + \n # \$1 refers to the input variable the user passed in to us\r\ + \n :local newFolder \$1;\r\ + \n\r\ + \n # we'll use this variable to report error messages that may arise\r\ + \n :local errorMsg;\r\ + \n\r\ + \n # if the user put a slash on the end of the new folder name, remove \ + it\r\ + \n # i.e. \"some/test/\" becomes \"some/test\"\r\ + \n :while (([:pick \$newFolder ([:len \$newFolder] - 1)]) = \"/\") do={\ + \r\ + \n :set newFolder [:pick \$newFolder 0 ([:len \$newFolder] - 1)]\r\ + \n }\r\ + \n\r\ + \n # if the user put a slash at the beginning of the new folder name, r\ + emove it\r\ + \n # i.e. \"/some/test\" becomes \"some/test\"\r\ + \n :while ([:pick \$newFolder 0] = \"/\") do={\r\ + \n :set newFolder [:pick \$newFolder 1 [:len \$newFolder]]\r\ + \n }\r\ + \n\r\ + \n :if ([/file find name=\$newFolder] != \"\") do={\r\ + \n :set errorMsg \"'\$newFolder' already exists.\";\r\ + \n :log debug \"mkdir: \$errorMsg\";\r\ + \n :return \$newFolder;\r\ + \n }\r\ + \n\r\ + \n # the name of the temp file to create\r\ + \n :local tempfile \"mkdir_temp_file.txt\";\r\ + \n\r\ + \n # port 0 is unlikely to be open to HTTP requests...\r\ + \n :local fakeURL \"http://127.0.0.1:0/should-not-exist.txt\";\r\ + \n\r\ + \n :local fullTempPath (\$newFolder . \"/\" . \$tempfile);\r\ + \n\r\ + \n # this is where the folder creation happens\r\ + \n # `as-value` prevents status messages from printing\r\ + \n # wrapping in a `:do {...} on-error` prevents error messages from pr\ + inting.\r\ + \n :do {\r\ + \n /tool fetch dst-path=\"\$fullTempPath\" url=\"\$fakeURL\" durati\ + on=0.001s as-value;\r\ + \n } on-error={}\r\ + \n\r\ + \n # this waits for the temporary dir to show up so there isn't a race \ + \r\ + \n # condition where you call mkdir and then try to do something before\ + \_the \r\ + \n # folder is actually created\r\ + \n :local count 0;\r\ + \n :while ([/file find name=\"\$newFolder\"] = \"\") do={\r\ + \n :if (\$count >= 50) do={\r\ + \n # after 50 * 0.1s delays, it's been 5 seconds, which should \ + be long enough\r\ + \n :set errorMsg \"New folder could not be created at \$newFold\ + er\";\r\ + \n :log error \"mkdir: \$errorMsg\"\r\ + \n :error \$errorMsg\r\ + \n }\r\ + \n :delay 0.1s;\r\ + \n :set count (\$count + 1);\r\ + \n }\r\ + \n\r\ + \n :return \$newFolder;\r\ + \n}\r\ + \n\r\ + \n:log info \"Created function \\\$mkdir\"\r\ + \n" +add comment="Certificates CloudFlare, Quad9 " dont-require-permissions=no \ + name=Update-Certificates owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_CloudFlare\r\ + \n/tool/fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalRo\ + otCA.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalRootCA.crt.pem passphrase=\"\ + \";\r\ + \n/tool/ fetch mode=https url=https://cacerts.digicert.com/DigiCertGlobalG\ + 2TLSRSASHA2562020CA1-1.crt.pem;\r\ + \n/certificate/import file-name=DigiCertGlobalG2TLSRSASHA2562020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n# Quad9\r\ + \n/tool/fetch mode=https url=\"https://cacerts.digicert.com/DigiCertGlobal\ + G3TLSECCSHA3842020CA1-1.crt.pem\"\r\ + \n/certificate/import file-name=DigiCertGlobalG3TLSECCSHA3842020CA1-1.crt.\ + pem passphrase=\"\";\r\ + \n\r\ + \n#:global AmScriptsUrl;\r\ + \n#google\r\ + \n#:local CertName \"GTS-Root-R1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-R4.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"GTS-Root-RX.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#internet\r\ + \n#:set CertName \"ISRG-Root-X1.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"ISRG-Root-X2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n#:set CertName \"Starfield-Root-Certificate-Authority-G2.pem\";\r\ + \n#/tool/fetch mode=https url=(\$AmScriptsUrl . \"certs/\" . \$CertName);\ + \r\ + \n#/certificate/import file-name=\$CertName passphrase=\"\";\r\ + \n\r\ + \n#/ip/dns/set allow-remote-requests=yes doh-max-concurrent-queries=100 do\ + h-max-server-connections=20 use-doh-server=https://security.cloudflare-dns\ + .com/dns-query verify-doh-cert=yes;\r\ + \n#/ip/dns/static remove [find where address=1.1.1.1];\r\ + \n#/ip/dns/static add address=1.1.1.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 1\";\r\ + \n#/ip/dns/ static remove [find where address=1.0.0.1];\r\ + \n#/ip/dns/static add address=1.0.0.1 name=security.cloudflare-dns.com com\ + ment=\"cloudflare-dns IPv4 2\"\r\ + \n#/ip dns static add address=2606:4700:4700::1111 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip dns static add address=2606:4700:4700::1001 name=security.cloudflar\ + e-dns.com type=AAAA\r\ + \n#/ip/dns set servers=\"1.0.0.1, 8.8.4.4\";\r\ + \n#/ip/dns set servers=\"\";" +add dont-require-permissions=no name=script1 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="/\ + tool/netwatch/add comment=\"doh-fallback, doh-url=https://security.cloudfl\ + are-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Clou\ + dFlare-doh IPv4 1\" host=1.1.1.1;\r\ + \n/tool/netwatch/add comment=\"doh, doh-url=https://security.cloudflare-dn\ + s.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=CloudFlare\ + -doh IPv4 2\" host=1.0.0.1;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 1\" host=8.8.8.8;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.google/dns-query, doh-cert=DigiCert Global Root G2, notify, name=Goog\ + le-doh IPv4 2\" host=8.8.4.4;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 1\" host=9.9.9.9;\r\ + \n/tool/netwatch/add comment=\"doh-fallback, dns-fallback, doh-url=https:/\ + /dns.quad9.net/dns-query, doh-cert=DigiCert Global Root G3, notify, name=C\ + uad9-doh IPv4 2\" host=149.112.112.112;\r\ + \n\r\ + \n/tool/netwatch/add comment=\"dns, notify, name=ns1.unet.ws\" host=91.192\ + .189.2;" +add dont-require-permissions=no name=script2 owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \r\ + \n\r\ + \n:global InspectVar;\r\ + \n#:global RouterBoard;\r\ + \n#:do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on-erro\ + r={}\r\ + \n#:global Resources;\r\ + \n#:do {:set Resources [[ :parse \"/system/resource/get\" ]]} on-error={}\ + \r\ + \n\r\ + \n#:global Updates;\r\ + \n#:do {:set Updates [[ :parse \"/system/package/update/get\" ]]} on-error\ + ={}\r\ + \n\r\ + \n#:global PkgUpdStatus \"undefined\";\r\ + \n#:local Update [/system/package/update/get];\r\ + \n#:retry command={:set PkgUpdStatus (\$Update->\"status\")} delay=200ms m\ + ax=5 on-error={};\r\ + \n\r\ + \n#:log warning [\$InspectVar \$RouterBoard];\r\ + \n#:put [\$InspectVar \$RouterBoard];\r\ + \n\r\ + \n#:retry command={/system/package/update check-for-updates without-paging\ + \_as-value} delay=300ms max=5 on-error={};\r\ + \n\r\ + \n#:global arrDeviceInfo ({});\r\ + \n#:local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};});\ + \r\ + \n#:set (\$arrDeviceInfo->\"RouterBoard\") [[ :parse \"/system/routerboard\ + /get\" ]];\r\ + \n#:retry command={:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system\ + /package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"Error\ + \")};\r\ + \n# [:toarray {\"section\"={\"key\"=\"\"; \"value\"=\"\";} }];\r\ + \n# [:toarray \"\"];\r\ + \n:local arrDeviceInfo ({});\r\ + \n\r\ + \n:set (\$arrDeviceInfo->\"devUpdates\") {\"channel\"; \"stable\";};\r\ + \n#:do {:set (arrDeviceInfo->\"Updates\") [[ :parse \"/system/package/upda\ + te/get\" ]]} on-error={:log error (\$error)}\r\ + \n\$InspectVar \$arrDeviceInfo;\r\ + \n" +add dont-require-permissions=no name=AM-setup owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + \_RouterOS Setup Script: AM-setup\r\ + \n# \r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n# requires device-mode, fetch\r\ + \n\r\ + \n## Additional commands:\r\ + \n#\r\ + \n# For scripts:\r\ + \n#:if ([ :len [ /system/script/find where name=\$ScriptName ]] = 0 ) do={\ + \r\ + \n# :local ScriptName [ :jobname ];\r\ + \n# :global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n# /system/script/add name=\$ScriptName owner=\$ScriptName source=([ /too\ + l/fetch check-certificate=yes-without-crl (\$GlobalScriptsUrl . \$ScriptNa\ + me . \".rsc\") output=user as-value ]->\"data\");\r\ + \n#}\r\ + \n# For run from terminal:\r\ + \n# /system/script/add name=AM-setup owner=AM-Setup source=([ /tool/fetch \ + check-certificate=yes-without-crl \"https://ros.vados.ru/AM-setup.rsc\" ou\ + tput=user as-value ]->\"data\");\r\ + \n#\r\ + \n# /system/script/set source=[ :tocrlf [ get \$ScriptName source ] ] \$Sc\ + riptName;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n\r\ + \n:local RemoveThisScript false;\r\ + \n\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n\r\ + \n{\r\ + \n :local ScriptName;\r\ + \n :local RemoveThisScript;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local AllDone;\r\ + \n :local CertCommonName \"Root YE\";\r\ + \n :local CertFileName \"Root-YE.pem\";\r\ + \n :local CertFingerprint \"e14ffcad5b0025731006caa43a121a22d8e9700f4fb9c\ + f852f02a708aa5d5666\";\r\ + \n\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (!(((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \ + \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \"fetch\" || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CertComm\ + onName ] ] > 0)) do={\r\ + \n :put \"Importing certificate...\";\r\ + \n:log warning (\"\\n\\\$GlobalScriptsUrl = \" . \$GlobalScriptsUrl);\r\ + \n /tool/fetch (\$GlobalScriptsUrl . \"certs/\" . \$CertFileName) dst-p\ + ath=\$CertFileName as-value;\r\ + \n :delay 1s;\r\ + \n /certificate/import file-name=\$CertFileName passphrase=\"\";\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint \ + ] ] != 1) do={\r\ + \n :error \"Something is wrong with your certificates!\";\r\ + \n };\r\ + \n :delay 1s;\r\ + \n };\r\ + \n :put \"Renaming AM-GlobalConfig, if exists...\";\r\ + \n :local ConfOldName (\"AM-GlobalConfig-\" . [ /system/clock/get date ] \ + . [ /system/clock/get time ] . \".rsc\");\r\ + \n /system/script/set name=\$ConfOldName [ find where name=\"AM-GlobalCon\ + fig\" ];\r\ + \n :foreach Script in={ \"AM-GlobalConfig\"; \"AM-GlobalFunc\" } do={\r\ + \n :put \"Installing \$Script...\";\r\ + \n /system/script/remove [ find where name=\$Script ];\r\ + \n /system/script/add name=\$Script owner=\$Script source=([ /tool/fetc\ + h check-certificate=yes-without-crl url=(\$GlobalScriptsUrl . \$Script . \ + \".rsc\") output=user as-value ]->\"data\");\r\ + \n };\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where fingerprint=\$CertFingerprint ] \ + ] > 0) do={\r\ + \n :put \"Renaming certificate by its common-name...\";\r\ + \n :global CertificateNameByCN;\r\ + \n \$CertificateNameByCN \$CertFingerprint;\r\ + \n };\r\ + \n\r\ + \n :put \"Add Schedulers...\";\r\ + \n :delay 1;\r\ + \n :put \"Add Global scheduler...\";\r\ + \n :local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFu\ + nc; }\";\r\ + \n :local Comment \"Setup Global Environment for scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] \ + ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-\ + event=\$OnEvent start-time=startup;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Commen\ + t) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n }\r\ + \n :if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEve\ + nt) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n }\r\ + \n :delay 1;\r\ + \n :put \"Add Update Script scheduler\";\r\ + \n :set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\"\ + ;\r\ + \n :set Comment \"Every Day Check For Update Scripts\";\r\ + \n :if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpda\ + te\" ] ] = 0) do={\r\ + \n /system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Commen\ + t start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n }\r\ + \n\r\ + \n :delay 1;\r\ + \n :put \"Loading configuration and functions...\";\r\ + \n :do { \r\ + \n /system/script { run AM-GlobalConfig; run AM-GlobalFunc; };\r\ + \n :global ScriptInstallUpdate; \$ScriptInstallUpdate;\r\ + \n :set AllDone true;\r\ + \n } on-error={\r\ + \n :set AllDone false;\r\ + \n :local ErrorMsg \"Loading configuration and functions error!\";\r\ + \n :log error (\$ScriptName . \$ErrorMsg . :error);\r\ + \n :error \$ErrorMsg;\r\ + \n }\r\ + \n\r\ + \n :delay 5s;\r\ + \n :if (\$AllDone = true && \$RemoveThisScript = true) do={\r\ + \n :put \"Add Scheduler for remove this script...\";\r\ + \n :set OnEvent \":delay 30s; /system/script/remove [ find where name=\$S\ + criptName ]; :delay5s; /system/scheduler/remove [ find where name=\\\"_Rem\ + oveSetup\\\" ];\";\r\ + \n :set Comment \"_RemoveSetup tmp scheduler for remove setup script.\";\ + \r\ + \n /system/scheduler/add name=\"_RemoveSetup\" comment=\$Comment start-ti\ + me=startup interval=30s on-event=\$OnEvent;\r\ + \n :log warning (\$ScriptName . \"\\nI've done everything, and now I'm ti\ + red... I'm leaving. ))\\nThere will be an error below, this is normal.\");\ + \r\ + \n }\r\ + \n};\r\ + \n" +add dont-require-permissions=no name=fetchCustom owner=vados policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="\ + \r\ + \n#root.mnuc.backuper\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n/tool/fetch mode=https url=(\$GlobalScriptsUrl . \".bak/mikro_bak_rsa@10\ + .30.30.81.pub\") dst-path=\"/mikro_bak_rsa@10.30.30.81.pub\";\r\ + \n#/usb1/mikro_bak_rsa.pub" +add comment="Global Config Script" dont-require-permissions=no name=\ + AM-GlobalConfig owner=AM-GlobalConfig policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GlobalConfig\r\ + \n# Script comment: Global Config Script\r\ + \n# Copyright (c) 2007-2026 Vados \r\ + \n#\r\ + \n#\r\ + \n# Warning: Dont touch this line!\r\ + \n:global GlobalConfReady false;\r\ + \n# \\/ start edit\r\ + \n#\r\ + \n# Global Url For Amster scripts to fetch\r\ + \n# most be defined in Amster-Init-Script\r\ + \n:global GlobalScriptsUrl \"https://ros.vados.ru/\";\r\ + \n:global ScriptsUrlSuffix \"\";\r\ + \n:global CheckSumsVerify true;\r\ + \n\r\ + \n:global ScriptUpdatesCRLF true;\r\ + \n:global CommentsInScripts true;\r\ + \n\r\ + \n# Debug output:\r\ + \n:global PrintDebug true; #false;\r\ + \n\r\ + \n# Debug output for specific script:\r\ + \n:set (\$PrintDebugOverride->\"AM-GlobalFunc\") true;\r\ + \n\r\ + \n# Debug logs\r\ + \n# Other actions (disk, email, remote or support) can be used as well.\r\ + \n# I do not recommend using echo - use debug output instead (https://rsc.\ + eworm.de/main/DEBUG.html#debug-output).\r\ + \n#/system/logging/add topics=script,debug action=memory;\r\ + \n\r\ + \n:global MikrotikUpgradeUrl \"https://upgrade.mikrotik.com/routeros\";\r\ + \n:global Domain \"WORKGROUP\";\r\ + \n\r\ + \n:global EmailGeneralTo \"vados@vados.ru\"; #:global EmailGeneralCc \"\";\ + \r\ + \n\r\ + \n# \$ScriptInstallUpdate mod/notification-telegram\r\ + \n:global TelegramTokenId \"8390868324:AAG3_d1hfVR2M6pGAgDK6ZvhOe4J97nyopw\ + \";\r\ + \n:global TelegramChatId \"-1003631309063\"; #\"454403445\";\r\ + \n# Use this to send notifications to a specific topic in group.\r\ + \n#:global TelegramThreadId \"30\";\r\ + \n# Using telegram-chat you have to define trusted chat ids (not group ids\ + !)\r\ + \n# or user names. Groups allow to chat with devices simultaneously.\r\ + \n:global TelegramChatIdsTrusted {\r\ + \n \"454403445\"\r\ + \n \"-1003631309063\"\r\ + \n \"-5124482807\"\r\ + \n \"1087968824\";\r\ + \n};\r\ + \n# \"-5294757340\";\r\ + \n\r\ + \n:global TelegramChatGroups \"(all)\";\r\ + \n#:global TelegramChatGroups \"(all|home|office)\";\r\ + \n\r\ + \n:global NotificationFunctions {\r\ + \n \"email\"\r\ + \n \"telegram\";\r\ + \n};\r\ + \n# Toggle this to disable symbols in notifications.\r\ + \n:global NotificationsWithSymbols true;\r\ + \n:global TerminalColorOutput true;\r\ + \n\r\ + \n:global DetectIpAddrDefault \"https://ipv4.mikrotik.ovh/\";\r\ + \n:global DetectIpAddrFallback \"https://api.ipify.org/\";\r\ + \n\r\ + \n## Update channel. Possible values: stable, long-term, testing, developm\ + ent\r\ + \n:global updateChannel \"stable\";\r\ + \n\r\ + \n# Script BackupAndUpdate mode, possible values: backup,\r\ + \n# updateOnce - Update once as \"osnotify\" and back \"osnotify\" mode (i\ + n terminal run :set OSUpdateMode updateOnce; \$OSUpdateMode;). \r\ + \n# osupdate - Update if available and creates backups before/after update\ + \_(ignores `forceBackup`)\r\ + \n# Set `forceBackup` to true to always create backups, even\ + \_without updates\r\ + \n# osnotify - Set `forceBackup` to always create backups on every run\r\ + \n:global DevInfoIncludeIP true;\r\ + \n:global BackupAndUpdateMode \"osnotify\"\r\ + \n\r\ + \n:global forceBackup true;\r\ + \n:global BackupPassword \"Peskar55\";\r\ + \n\r\ + \n# SFTP Backup Variables\r\ + \n:global BackupRandomDelay 0;\r\ + \n:global BackupUploadUrl \"sftp://amster.vados.ru/upload/\";\r\ + \n:global BackupUploadUser \$Identity;\r\ + \n:global BackupUploadPass \"root.mnuc.backuper\";\r\ + \n\r\ + \n:global BackupSendBinary true;\r\ + \n:global BackupSendExport true;\r\ + \n:global BackupSendGlobalConfig true;\r\ + \n:global BackupSendScripts true;\r\ + \n\r\ + \n# Remove local file after uploading if no errors\r\ + \n:global BackupRmLocal true;\r\ + \n\r\ + \n# Local Backups Root Directory \r\ + \n:global BackupLocalRoot \"tmpfs\";\r\ + \n\r\ + \n# Encrypt Backup\r\ + \n:global BackupEncrypt true;\r\ + \n\r\ + \n# Sensitive information in Backups\r\ + \n:global BackupSens true;\r\ + \n\r\ + \n# User Export\r\ + \n:global BackupUser true;\r\ + \n\r\ + \n# License Export (not for CHR, will silently skip)\r\ + \n:global BackupLicense false;\r\ + \n\r\ + \n# SSH Keys\r\ + \n:global BackupSshKeys true;\r\ + \n\r\ + \n# Certificate Export\r\ + \n:global BackupCerts true;\r\ + \n\r\ + \n# Certificate Password\r\ + \n:global BackupCertsPasswd \"\";\r\ + \n\r\ + \n# User-Manager Export\r\ + \n:global BackupUserMan false;\r\ + \n\r\ + \n# The Dude Export\r\ + \n:global BackupDude false;\r\ + \n\r\ + \n# User Files to export, comma-separated string or array of strings\r\ + \n# User Files are not removed on backup\r\ + \n# Any directory paths will be removed (/ -> _) on remote file\r\ + \n# Nonpresent files are silently skipped\r\ + \n:global BackupUserList \"autosupout.rif,autosupout.old.rif\";\r\ + \n\r\ + \n# load functions and any custom scripts\r\ + \n# [ /system/script/find where name=\"global-config-ov\ + erlay\" ], \\\r\ + \n# [ /system/script/find where name~\"^global-config-o\ + verlay\\\\.d/.\" ]\r\ + \n#\r\ + \n#:foreach Script in=([ /system/script/find where name=\"Amster-TGglobalV\ + ars\" ], [ /system/script/find where name=\"Amster-TGglobalFunc\" ]) do={\ + \r\ + \n# :onerror Err {\r\ + \n# /system/script/run \$Script;\r\ + \n# } do={\r\ + \n# :log error (\"Loading configuration from configs and functions\"\ + \_. [ /system/script/get \$Script name ] . \" failed: \" . \$Err);\r\ + \n# }\r\ + \n#}\r\ + \n#:log info \"\\ndevMode = \$devMode\";\r\ + \n#:log info \"\\ndevRunning = \$devRunning\";\r\ + \n:foreach Script in=[ /system/script/find where source~\"^#!rsc by Vados \ + GlobalRUN\\r\?\\n\" ] do={\r\ + \n :onerror Err {\r\ + \n /system/script/run \$Script;\r\ + \n } do={\r\ + \n :log error (\"Run script \" . [ /system/script/get \$Script name \ + ] . \" width marker \\\" GlobalRUN\\\" failed: \" . \$Err);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalConfReady true;\r\ + \n:while (\$GlobalConfReady != true) do={:delay 500ms};\r\ + \n" +add comment="Global functions" dont-require-permissions=no name=AM-GlobalFunc \ + owner=AM-GlobalFunc policy=\ + ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon source="#\ + !rsc by Vados\r\ + \n# RouterOS script: AM-GglobalFunc\r\ + \n# Script comment: Global functions\r\ + \n#\r\ + \n#\r\ + \n# requires RouterOS, version=7.21\r\ + \n# requires device-mode, fetch, scheduler\r\ + \n:local ExitOK false;\r\ + \n:local ScriptName [ :jobname ];\r\ + \n#:global checkRunJob \$SriptName;\r\ + \n#:global fixCRLF;\r\ + \n#:if (\$fixCRLF != false) do={\r\ + \n#:foreach fixScript in=([ /system/script/find where name~\"*\" ]) do={/s\ + ystem/script/set source=[ :tocrlf [ get \$fixScript source ] ] \$fixScript\ + }\r\ + \n#:if (\$fixCRLF != \"LF\") do={ /system/script/set source=[ :tocrlf [ g\ + et \$fixScript source ] ] \$fixScript};};\r\ + \n#}\r\ + \n:global GlobalFuncReady false;\r\ + \n\r\ + \n# The variables are received right here.\r\ + \n:global GlobalConfVersion 138;\r\ + \n\r\ + \n:global Identity [/system/identity/get name];\r\ + \n:global IdentityShort [:pick \$Identity 0 18];\r\ + \n\r\ + \n:global devBoardName [/system/resource/get board-name];\r\ + \n:global devMode [/system/device-mode/get mode];\r\ + \n:global devCurArch [/system/resource/get architecture-name];\r\ + \n:global devCurVersion [/system/resource/get version];\r\ + \n\r\ + \n# Variables defined in AM-GlobalConfig.rsc\r\ + \n:global TerminalColorOutput;\r\ + \n:global CommentsInScripts;\r\ + \n:global DetectIpAddrDefault;\r\ + \n:global DetectIpAddrFallback;\r\ + \n:global updateChannel;\r\ + \n:global Domain;\r\ + \n:global EmailGeneralTo;\r\ + \n:global BackupAndUpdateMode;\r\ + \n\r\ + \n# Single functions, without nested functions.\r\ + \n:global GlobalEnvRemove;\r\ + \n:global MiniDateTimeStamp;\r\ + \n\r\ + \n# Include globals \$PrintDebug and \$PrintDebugOverride\r\ + \n:global LogPrint;\r\ + \n\r\ + \n# DeviceInfo and Updates\r\ + \n:global IsCheckUpdates;\r\ + \n:global WaitCheckUpdates;\r\ + \n:global GetPubIp;\r\ + \n\r\ + \n:global GetArrDeviceInfo;\r\ + \n:global WaitArrDeviceInfo;\r\ + \n\r\ + \n:global devModel;\r\ + \n:global devRunningMode;\r\ + \n\r\ + \n:global devRbRevision;\r\ + \n:global devRbSerialNumber;\r\ + \n:global devRbVerAvail;\r\ + \n\r\ + \n:global runningChannelVersion;\r\ + \n:global runningChannel;\r\ + \n:global runningVersion;\r\ + \n\r\ + \n:global devBuildTime;\r\ + \n#:global ROsVerAvail;\r\ + \n:global PkgUpdStatus;\r\ + \n:global currentUpdateChannel;\r\ + \n\r\ + \n:global ScriptInstallUpdate;\r\ + \n\r\ + \n:global DeviceInfo;\r\ + \n\r\ + \n:global OldMode;\r\ + \n\r\ + \n:global ParseKeyValueStore;\r\ + \n:global RandomDelay;\r\ + \n:global GetRandomNumber;\r\ + \n:global EscapeForRegEx;\r\ + \n:global ExitError;\r\ + \n:global CleanFilePath;\r\ + \n:global CleanName;\r\ + \n:global CharacterReplace;\r\ + \n:global CharacterMultiply;\r\ + \n:global EitherOr;\r\ + \n:global FormatLine;\r\ + \n:global GetRandom20CharAlNum;\r\ + \n:global Grep;\r\ + \n:global IfThenElse;\r\ + \n:global MAX;\r\ + \n:global MIN;\r\ + \n:global HumanReadableNum;\r\ + \n\r\ + \n:global IsFullyConnected;\r\ + \n:global IsDNSResolving;\r\ + \n:global IsTimeSync;\r\ + \n:global IsTimeSyncCached;\r\ + \n:global IsTimeSyncResetNtp;\r\ + \n\r\ + \n:global WaitDNSResolving;\r\ + \n:global WaitFullyConnected;\r\ + \n:global WaitTimeSync;\r\ + \n:global MkDir;\r\ + \n:global RmDir;\r\ + \n:global RmFile;\r\ + \n:global FileGet;\r\ + \n:global Unix2Dos;\r\ + \n:global UrlEncode;\r\ + \n:global WaitForFile;\r\ + \n:global ScriptLock;\r\ + \n:global SendTelegram;\r\ + \n:global NotificationFunctions;\r\ + \n:global SendNotification;\r\ + \n:global SendNotification2;\r\ + \n:global SymbolForNotification;\r\ + \n:global SymbolByUnicodeName;\r\ + \n:global ValidateSyntax;\r\ + \n:global CheckSumsVerify;\r\ + \n:global GlobalConfChanges;\r\ + \n:global GlobalConfMigration;\r\ + \n:global VersionToNum;\r\ + \n:global RequiredRouterOS;\r\ + \n:global FetchLargeFiles;\r\ + \n:global FetchUserAgentStr;\r\ + \n:global CertificateAvailable;\r\ + \n:global CertificateDownload;\r\ + \n:global CertificateNameByCN;\r\ + \n:global CharacterMultiply;\r\ + \n\r\ + \n:global InspectVar;\r\ + \n:global InspectVarRet;\r\ + \n:global ParseCustom;\r\ + \n\r\ + \n:set IsCheckUpdates do={\r\ + \n :local isInfo [:tobool \$1];\r\ + \n :global LogPrint;\r\ + \n :global updateChannel;\r\ + \n :global PkgUpdStatus;\r\ + \n \$LogPrint debug \$0 (\"\\\$isInfo = \" . \$isInfo); \r\ + \n :local CurrentChannel [ /system/package/update/get channel ];\r\ + \n :if (\$CurrentChannel != \$updateChannel) do={\r\ + \n :retry command={/system/package/update set channel=\$updateChannel} \ + \_delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"Set updates channel to: \$updateChannel\");\ + \r\ + \n }\r\ + \n \r\ + \n :local Update [ /system/package/update/get ];\r\ + \n :local Channel (\$Update->\"channel\");\r\ + \n \$LogPrint debug \$0 (\"Update Channel: \" . \$Channel . \".\");\r\ + \n \r\ + \n :local StatusPkg \"undefined\";\r\ + \n \$LogPrint debug \$0 (\"Checking for updates...\");\r\ + \n :retry command={:set \$StatusPkg ([/system/package/update/check-for-up\ + dates without-paging as-value]->\"status\")} \\\r\ + \n delay=300ms max=5 on-error={};\r\ + \n \$LogPrint debug \$0 (\"\\\$StatusPkg = \" . \$StatusPkg);\r\ + \n :if (\$StatusPkg = \"New version is available\") do={ :set PkgUpdStatu\ + s true; } else={ :set PkgUpdStatus false; }\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if (\$isInfo != false || \$PkgUpdStatus = true) do={\r\ + \n \$LogPrint debug \$0 (\"\\\$PkgUpdStatus = \" . \$PkgUpdStatus);\r\ + \n :if ([:len \$arrDeviceInfo] = 0) do={\r\ + \n :global arrDeviceInfo ({});\r\ + \n :local arrDeviceInfo ({\"section\":{\"key\":\"\"; \"value\":\"\";};}\ + );\r\ + \n }\r\ + \n # else={:local arrDeviceInfo ({})}\r\ + \n :retry command={:set (\$arrDeviceInfo->\"devUpdates\") [[ :parse \"/\ + system/package/update/get\" ]]} delay=500ms max=5 on-error={:log error (\"\ + Error\")};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannel\"; \$Cu\ + rrentChannel;};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentVersion\"; (\$U\ + pdate->\"installed-version\");};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devCurrentChannelVersion\ + \"; [/system/resource/get version];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateChannel\"; [\$up\ + dateChannel];};\r\ + \n #:set (\$arrDeviceInfo->\"devUpdates\") {\"devUpdateVersion\"; (\$Up\ + date->\"latest-version\");};\r\ + \n } else={\r\ + \n :return \$PkgUpdStatus;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set WaitArrDeviceInfo do={\r\ + \n :global GetArrDeviceInfo;\r\ + \n :while ([ \$GetArrDeviceInfo ] = false) do={\r\ + \n :delay 1s;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetArrDeviceInfo do={\r\ + \n :global LogPrint;\r\ + \n\r\ + \n :global devBoardName;\r\ + \n :global devModel;\r\ + \n \r\ + \n :global arrDeviceInfo [:toarray {\"section\"={\"key\"=\"\"; \"value\"\ + =\"\";} }];\r\ + \n #:do {:set (\$arrDeviceInfo->\"Updates\") [[ :parse \"/system/package\ + /update/get\" ]]} on-error={}\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global devRbCurrentFw;\r\ + \n :global devRbUpgradeFw;\r\ + \n \r\ + \n :global devRunning;\r\ + \n :global devCurArch;\r\ + \n :global ROsVerCurrent;\r\ + \n :global ROsChannelCurrent;\r\ + \n :global ROsVerAvail;\r\ + \n\r\ + \n :global ParseCustom;\r\ + \n :global runningChannelVersion;\r\ + \n :global runningChannel;\r\ + \n :global runningVersion;\r\ + \n :global devBuildTime;\r\ + \n :global GetPubIp;\r\ + \n \r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :set devBuildTime (\$Resource->\"build-time\");\r\ + \n :set runningChannelVersion (\$Resource->\"version\");\r\ + \n :set runningChannel [\$ParseCustom \$runningChannelVersion \"(\" \")\ + \" 1];\r\ + \n :set runningVersion [\$ParseCustom \$runningChannelVersion \" \"];\r\ + \n \r\ + \n :do {\r\ + \n :if ([:pick \$devBoardName 0 3] != \"CHR\" or [:pick \$devBoardName 0\ + \_3] != \"x86\") do={\r\ + \n :local RouterBoard;\r\ + \n :do {:set RouterBoard [[ :parse \"/system/routerboard/get\" ]]} on\ + -error={}\r\ + \n :set devModel (\$RouterBoard->\"model\");\r\ + \n :set devRbRevision (\$RouterBoard->\"revision\");\r\ + \n :set devRbSerialNumber (\$RouterBoard->\"serial-number\");\r\ + \n #:set devRbCurrentFw (\$RouterBoard->\"current-firmware\");\r\ + \n #:set devRbUpgradeFw (\$RouterBoard->\"upgrade-firmware\");\r\ + \n :if (\$devCurArch = \"mipsbe\" || \$devCurArch = \"arm\") do={\r\ + \n :global devRunning [ /system/device-mode/get mode ];\r\ + \n } else={\r\ + \n :global devRunning [/system/device-mode/get running];}\r\ + \n } else={\r\ + \n :set devModel \$devBoardName;\r\ + \n \r\ + \n :set devRbRevision false;\r\ + \n :set devRbSerialNumber false;\r\ + \n# :set devRbCurrentFw false;\r\ + \n# :set devRbUpgradeFw false;\r\ + \n #:set devCurrentFw \$runningVersion;#:set devUpgradeFw \$ROsVerAvail\ + ;\r\ + \n :set devRunning [/system/device-mode/get running];\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Error in Function getDevice!\");\r\ + \n :return false;\r\ + \n }\r\ + \n:return true;\r\ + \n}\r\ + \n\r\ + \n:set DeviceInfo do={\r\ + \n :global WaitArrDeviceInfo;\r\ + \n # \$WaitDeviceInfo;\r\ + \n :global devBoardName;\r\ + \n :global devCurArch;\r\ + \n :global devModel;\r\ + \n :global devRunning;\r\ + \n :global devRbRevision;\r\ + \n :global devRbSerialNumber;\r\ + \n :global PiblicIpAddress;\r\ + \n\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global IfThenElse;\r\ + \n :global FormatLine;\r\ + \n :local Return;\r\ + \n :local License [/system/license/get];\r\ + \n :local Resource [/system/resource/get];\r\ + \n :local Snmp [ /snmp/get ];\r\ + \n :local Update [ /system/package/update/get ];\r\ + \n \r\ + \n :set Return ([ \$FormatLine \"Hostname:\" \$Identity ] . \"\\n\" . \\\ + \r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"location\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Location:\" (\$Snmp->\"location\") ] . \"\\n\") \ + ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$Snmp->\"contact\") ] > 0) \\\r\ + \n ([ \$FormatLine \"Contact:\" (\$Snmp->\"contact\") ] . \"\\n\") ] \ + . \\\r\ + \n \"Hardware:\\n\" . \\\r\ + \n [ \$FormatLine \" Board:\" . \$devBoardName ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Arch:\" . \$devCurArch ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Model:\" \$devModel ] . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbRevision ] > 0) \\\r\ + \n (\" \" . \$devRbRevision) ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len \$devRbSerialNumber ] > 0) \\\r\ + \n ([ \$FormatLine \" Serial:\" . \$devRbSerialNumber ] . \"\\n\"\ + ) ] . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"nlevel\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"nleve\ + l\")) ] . \"\\n\") ] . \"RouterOS:\\n\" . \\\r\ + \n [ \$IfThenElse ([ :len (\$License->\"level\") ] > 0) \\\r\ + \n ([ \$FormatLine \" License:\" (\"level \" . (\$License->\"level\ + \")) ] . \"\\n\") ] . \\\r\ + \n [ \$FormatLine \"Running Channel\" \$runningChannel ] . \"\\n\" . \\\ + \r\ + \n [ \$FormatLine \" Installed:\" (\$Update->\"installed-version\") \ + ] . \"\\n\" . \\\r\ + \n [ \$IfThenElse ([ :typeof (\$Update->\"latest-version\") ] != \"noth\ + ing\" && \\\r\ + \n \$Update->\"installed-version\" != \$Update->\"latest-version\")\ + \_\\\r\ + \n ([ \$FormatLine \" Available\" (\$Update->\"latest-version\") ]\ + \_. \"\\n\") ] . \\\r\ + \n [ \$IfThenElse (\$RouterBoard->\"routerboard\" = true && \\\r\ + \n \$RouterBoard->\"current-firmware\" != \$RouterBoard->\"upgrade-\ + firmware\") \\\r\ + \n ([ \$FormatLine \" Firmware\" (\$RouterBoard->\"current-firmwar\ + e\") ] . \"\\n\") ] . \\ \r\ + \n \"RouterOS-Scripts:\\n\" . \\\r\ + \n [ \$FormatLine \" Commit\" [ \$CommitBrief ] ] . \"\\n\" . \\\r\ + \n [ \$FormatLine \" Version\" \$GlobalConfVersion ]);\r\ + \n}\r\ + \n\r\ + \n:if ([ :typeof \$NotificationFunctions ] != \"array\") do={:set Notifica\ + tionFunctions ({})}\r\ + \n:set GetRandom20CharAlNum do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndstr length=[ \$EitherOr [ :tonum \$1 ] 20 ] from=\"ABCDE\ + FGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789\" ];\r\ + \n}\r\ + \n\r\ + \n:global checkRunJob;\r\ + \n:set checkRunJob do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLock; \r\ + \n :if ([ \$ScriptLock \$Script ] = false) do={:return false}\r\ + \n :foreach Job in=[ /system/script/job/find where script=\$Script ] do={\ + :set Job [ /system/script/job/get \$Job ];\r\ + \n :while ([ :typeof (\$Job->\"parent\") ] = \"id\") do={:set Job [ /sy\ + stem/script/job/get [ find where .id=(\$Job->\"parent\") ] ]}\r\ + \n :if ((\$Job->\"type\") = \"login\") do={:return true};}; :return fa\ + lse; \r\ + \n}\r\ + \n\r\ + \n:set InspectVar do={\r\ + \n :global InspectVarRet;\r\ + \n :put [ :tocrlf [ \$InspectVarRet \$1 ] ];\r\ + \n}\r\ + \n\r\ + \n:set InspectVarRet do={\r\ + \n :local Input \$1;\r\ + \n :local Level (0 + [ :tonum \$2 ]);\r\ + \n :global CharacterReplace;\r\ + \n :global IfThenElse;\r\ + \n :global InspectVarRet;\r\ + \n :local IndentReturn do={\r\ + \n :local Prefix [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Level [ :tonum \$3 ];\r\ + \n :global CharacterMultiply;\r\ + \n :return ([ \$CharacterMultiply \" \" (\$Level * 2) ] . \"-\" . \$Pre\ + fix . \"-> \" . \$Value);\r\ + \n }\r\ + \n :local TypeOf [ :typeof \$Input ];\r\ + \n :local Len [ :len \$Input ];\r\ + \n :local Return [ \$IndentReturn \"type\" \$TypeOf \$Level ];\r\ + \n :if (\$TypeOf = \"array\") do={\r\ + \n :foreach Key,Value in=\$Input do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"key\" \$Key (\$Level + 1) ] . \"\\n\" . \\\r\ + \n [ \$InspectVarRet \$Value (\$Level + 2) ]);\r\ + \n }\r\ + \n } else={\r\ + \n :if (\$TypeOf = \"str\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"len\" \$Len \$Level ]);\r\ + \n :if ([ :typeof [ :find \$Input (\"\\r\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\r\") \"\" ];\r\ + \n }\r\ + \n :if ([ :typeof [ :find \$Input (\"\\n\") ] ] = \"num\") do={\r\ + \n :set Input [ \$CharacterReplace \$Input (\"\\n\") \" \" ];\r\ + \n }\r\ + \n }\r\ + \n :if (\$TypeOf != \"nothing\") do={\r\ + \n :set \$Return (\$Return . \"\\n\" . \\\r\ + \n [ \$IndentReturn \"value\" [ \$IfThenElse ([ :len \$Input ] > 80)\ + \_\\\r\ + \n ([ :pick \$Input 0 77 ] . \"...\") \$Input ] \$Level ]);\r\ + \n }\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# !!! The function is not ready !!!\r\ + \n:global FetchHttpInfo do={\r\ + \n :local Mac [ :tostr \$1 ];\r\ + \n :global CertificateAvailable;\r\ + \n :global IsMacLocallyAdministered;\r\ + \n :global LogPrint;\r\ + \n :local Url \"https://api.macvendors.com/\";\r\ + \n :if ([ \$IsMacLocallyAdministered \$Mac ] = true) do={:return \"locall\ + y administered\";}\r\ + \n :do {\r\ + \n :if ([ \$CertificateAvailable \"GTS Root R4\" \"fetch\" ] = false) d\ + o={\r\ + \n \$LogPrint warning \$0 (\"Downloading required certificate failed.\ + \");\r\ + \n :error false;\r\ + \n }\r\ + \n :local Vendor ([ /tool/fetch \r\ + \n (\$Url . [ :pick \$Mac 0 8 ]) output=user as-value ]->\"data\");\r\ + \n :return \$Vendor;\r\ + \n } on-error={\r\ + \n :onerror Err {\r\ + \n /tool/fetch check-certificate=yes-without-crl (\$Url) output=none \ + as-value;\r\ + \n \$LogPrint debug \$0 (\"The mac vendor is not known in database.\"\ + );\r\ + \n } do={ \$LogPrint warning \$0 (\"Failed getting mac vendor: \" . \$E\ + rr); }\r\ + \n :return \"unknown vendor\";\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set GetPubIp do={\r\ + \n :global DetectIpAddrDefault;\r\ + \n :global DetectIpAddrFallback;\r\ + \n :global LogPrint;\r\ + \n \r\ + \n :local PubIpAddr false;\r\ + \n :local Url \$DetectIpAddrDefault;\r\ + \n\r\ + \n# :retry command={abc} delay=1 max=2 on-error={:put \"got error\"} \r\ + \n :do {\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using default s\ + ervice: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=50ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fail\ + ed to detect public IP using default service: \" . \$Url . \".\")}\r\ + \n #:error \"Failed to detect public IP using default service: \$Url\ + .\"};\r\ + \n } on-error={\r\ + \n \$LogPrint error \$0 (\"Failed to detect public IP using default s\ + ervice: \" . \$Url . \".\");\r\ + \n :set Url \$DetectIpAddrFallBack;\r\ + \n \$LogPrint debug \$0 (\"Trying to detect public IP using fallback \ + service: \" . \$Url . \"...\");\r\ + \n :retry command={:set PubIpAddr ([ /tool/fetch http-method=\"get\"\ + \_check-certificate=yes-without-crl \$Url output=user as-value ]->\"data\"\ + )} \\\r\ + \n delay=200ms max=5 on-error={\$LogPrint error [ :jobname ] (\"Fai\ + led to detect public IP using fallback service: \" . \$Url . \".\")}\r\ + \n };\r\ + \n :if (\$PubIpAddr = false) do={\r\ + \n :set PubIpAddr \"not-detected\";\r\ + \n } else={\r\ + \n :set PubIpAddr [ :pick \$PubIpAddr 0 15];\r\ + \n }\r\ + \n :return \$PubIpAddr;\r\ + \n}\r\ + \n\r\ + \n:set FormatLine do={\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local Value [ :tostr \$2 ];\r\ + \n :local Indent [ :tonum \$3 ];\r\ + \n :local Spaces;\r\ + \n :local Return \"\";\r\ + \n :global CharacterMultiply;\r\ + \n :global EitherOr;\r\ + \n :set Indent [ \$EitherOr \$Indent 16 ];\r\ + \n :local Spaces [ \$CharacterMultiply \" \" \$Indent ];\r\ + \n :if ([ :len \$Key ] > 0) do={ :set Return (\$Key . \":\")}\r\ + \n :if ([ :len \$Key ] > (\$Indent - 2)) do={:set Return (\$Return . \"\\\ + n\" . [ :pick \$Spaces 0 \$Indent ] . \$Value);\r\ + \n } else={:set Return (\$Return . [ :pick \$Spaces 0 (\$Indent - [ :len \ + \$Return ]) ] . \$Value)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ParseCustom do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Start [:find [ \$Str ] [:tostr \$2]];\r\ + \n :local End [ :tostr \$3 ];\r\ + \n :local Num [ :tonum \$4 ];\r\ + \n :local Return;\r\ + \n :if ([:len \$Num] = 0) do={:set Num \"0\"}\r\ + \n :local rest [:pick \$Str (\$Start+\$Num) [:len \$Str]]; \r\ + \n :if ([:len \$End ] = 0) do={:set Return [:pick \$Str \$Num \$Start]} e\ + lse={\r\ + \n :set End [:find \$rest \$End];\r\ + \n :set Return [:pick \$rest 0 \$End];\r\ + \n }\r\ + \n:return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set LogPrint do={\r\ + \n :local Severity [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Message [ :tostr \$3 ];\r\ + \n :global PrintDebug;\r\ + \n :global PrintDebugOverride;\r\ + \n :global EitherOr;\r\ + \n :local Debug [ \$EitherOr (\$PrintDebugOverride->\$Name) \$PrintDebug \ + ];\r\ + \n :local PrintSeverity do={\r\ + \n :global TerminalColorOutput;\r\ + \n :if (\$TerminalColorOutput != true) do={:return \$1}\r\ + \n :local Color { debug=96; info=97; warning=93; error=91 };\r\ + \n :return (\"\\1B[\" . \$Color->\$1 . \"m\" . \$1 . \"\\1B[0m\");\r\ + \n}\r\ + \n :local Log ([ \$EitherOr \$Name \"\" ] . \": \" . \$Message);\ + \r\ + \n :if (\$Severity ~ (\"^(custom|debug|error|info)\\\$\")) do={\r\ + \n :if (\$Severity = \"debug\") do={:log debug \$Log}\r\ + \n :if (\$Severity = \"error\") do={:log error \$Log}\r\ + \n :if (\$Severity = \"info\" ) do={:log info \$Log}\r\ + \n } else={:log warning \$Log; :set Severity \"warning\"}\r\ + \n :if (\$Severity != \"debug\" || \$Debug = true) do={:put ([ \$PrintSev\ + erity \$Severity ] . \": \" . \$Message)}\r\ + \n}\r\ + \n\r\ + \n:set CertificateAvailable do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :local UseFor [ :tostr \$2 ];\r\ + \n :global CertificateDownload;\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :set UseFor [ \$EitherOr \$UseFor \"undefined\" ];\r\ + \n :if ([ /system/resource/get free-hdd-space ] < 8388608 && \\\r\ + \n [ /certificate/settings/get crl-download ] = true && \\\r\ + \n [ /certificate/settings/get crl-store ] = \"system\") do={\r\ + \n \$LogPrint warning \$0 (\"This system has low free flash space but \ + \" . \\\r\ + \n \"is configured to download certificate CRLs to system!\");\r\ + \n }\r\ + \n :if ([ :len \$CommonName ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No CommonName given!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CertSettings [ /certificate/settings/get ];\r\ + \n :if (((\$CertSettings->\"builtin-trust-anchors\") = \"trusted\" || \\\ + \r\ + \n (\$CertSettings->\"builtin-trust-store\") ~ \$UseFor || \\\r\ + \n (\$CertSettings->\"builtin-trust-store\") = \"all\") && \\\r\ + \n [ :len [ /certificate/builtin/find where common-name=\$CommonName\ + \_] ] > 0) do={\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n \$LogPrint info \$0 (\"Certificate with CommonName '\" . \$CommonNam\ + e . \"' not available.\");\r\ + \n :if ([ \$CertificateDownload \$CommonName ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] > 1\ + ) do={\r\ + \n \$LogPrint info \$0 (\"There are \" . \$CertCount . \" Certificates \ + with CommonName '\" . \$CommonName . \"'. Should be ok.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :local CertVal [ /certificate/get [ find where common-name=\$CommonNam\ + e ] ];\r\ + \n :while ((\$CertVal->\"akid\") != \"\" && (\$CertVal->\"akid\") != (\$C\ + ertVal->\"skid\")) do={\r\ + \n :if ([ :len [ /certificate/find where skid=(\$CertVal->\"akid\") ] ]\ + \_= 0) do={\r\ + \n :local IssuerCN ([ \$ParseKeyValueStore (\$CertVal->\"issuer\") ]-\ + >\"CN\");\r\ + \n \$LogPrint info \$0 (\"Certificate chain for '\" . \$CommonName . \ + \"' is incomplete, missing '\" . \$IssuerCN . \"'.\");\r\ + \n :if ([ \$CertificateDownload \$IssuerCN ] = false) do={:return fal\ + se}\r\ + \n }\r\ + \n :set CertVal [ /certificate/get [ find where skid=(\$CertVal->\"akid\ + \") ] ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateDownload do={\r\ + \n :local CommonName [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global CertificateNameByCN;\r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global LogPrint;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n \r\ + \n \$LogPrint info \$0 (\"Downloading and importing certificate with Comm\ + onName '\" . \$CommonName . \"'.\");\r\ + \n \r\ + \n :local FileName ([ \$CleanName \$CommonName ] . \".pem\");\r\ + \n :do {\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({ [\ + \_\$FetchUserAgentStr \$0 ] }) \\\r\ + \n (\$GlobalScriptsUrl . \"certs/\" . \$FileName . \$GlobalScriptsUrl\ + Suffix) dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Common\ + Name '\" . \$CommonName . \\\r\ + \n \"' from repository! Trying fallback to mkcert.org...\");\r\ + \n :do {\r\ + \n :if ([ :len [ /certificate/find where common-name=\"ISRG Root X1\"\ + \_] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"Required certificate is not available.\"\ + );\r\ + \n :return false;\r\ + \n }\r\ + \n /tool/fetch check-certificate=yes-without-crl http-header-field=({\ + \_[ \$FetchUserAgentStr \$0 ] }) \\\r\ + \n \"https://mkcert.org/generate/\" http-data=[ :serialize to=json \ + ({ \$CommonName }) ] \\\r\ + \n dst-path=\$FileName as-value;\r\ + \n \$WaitForFile \$FileName;\r\ + \n :if ([ /file/get \$FileName size ] = 0) do={\r\ + \n \$RmFile \$FileName;\r\ + \n :error false;\r\ + \n }\r\ + \n } on-error={\r\ + \n \$LogPrint warning \$0 (\"Failed downloading certificate with Comm\ + onName '\" . \$CommonName . \"'!\");\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n /certificate/import file-name=\$FileName passphrase=\"\" as-value;\r\ + \n :delay 1s;\r\ + \n \$RmFile \$FileName;\r\ + \n\r\ + \n :if ([ :len [ /certificate/find where common-name=\$CommonName ] ] = 0\ + ) do={\r\ + \n /certificate/remove [ find where name~(\"^\" . \$FileName . \"_[0-9]\ + +\\\$\") ];\r\ + \n \$LogPrint warning \$0 (\"Certificate with CommonName '\" . \$Common\ + Name . \"' still unavailable!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :foreach Cert in=[ /certificate/find where name~(\"^\" . \$FileName . \ + \"_[0-9]+\\\$\") ] do={\r\ + \n \$CertificateNameByCN [ /certificate/get \$Cert common-name ];\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CertificateNameByCN do={\r\ + \n :local Match [ :tostr \$1 ];\r\ + \n :global CleanName;\r\ + \n :global LogPrint;\r\ + \n :local Cert ([ /certificate/find where (common-name=\$Match or fingerp\ + rint=\$Match or name=\$Match) ]->0);\r\ + \n :if ([ :len \$Cert ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No matching certificate found.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local CommonName [ /certificate/get \$Cert common-name ];\r\ + \n /certificate/set \$Cert name=[ \$CleanName \$CommonName ];\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set ScriptInstallUpdate do={ :onerror Err {\r\ + \n :local Scripts [ :toarray \$1 ];\r\ + \n :local NewComment [ :tostr \$2 ];\r\ + \n :global InitSetup;\r\ + \n\r\ + \n :global ScriptUpdatesCRLF;\r\ + \n :global GlobalConfVersion;\r\ + \n :global Identity;\r\ + \n :global CertificateAvailable;\r\ + \n :global CheckSumsVerify;\r\ + \n :global GlobalScriptsUrl;\r\ + \n :global GlobalScriptsUrlSuffix;\r\ + \n :global EitherOr;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global Grep;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global RequiredRouterOS;\r\ + \n :global SendNotification2;\r\ + \n :global SymbolForNotification;\r\ + \n :global ValidateSyntax;\r\ + \n :global CommentsInScripts;\r\ + \n\r\ + \n :if ([ \$CertificateAvailable \"Root YE\" \"fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, trying wit\ + hout.\");\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=\$Scripts do={\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\ + \r\ + \n \$LogPrint info \$0 (\"Adding new script: \" . \$Script);\r\ + \n /system/script/add name=\$Script owner=\$Script source=\"#!rsc by \ + Vados\\n\" comment=\$NewComment;\r\ + \n }\r\ + \n }\r\ + \n \r\ + \n :local GlobalConfVersionBefore \$GlobalConfVersion;\r\ + \n :local ReloadGlobal false;\r\ + \n :local DeviceMode [ /system/device-mode/get ];\r\ + \n \r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSums ({});\r\ + \n :do {\r\ + \n :local Url (\$GlobalScriptsUrl . \"checksums.json\" . \$GlobalScrip\ + tsUrlSuffix);\r\ + \n \$LogPrint debug \$0 (\"Fetching checksums from url: \" . \$Url);\ + \r\ + \n :set CheckSums [ :deserialize from=json ([ /tool/fetch check-certi\ + ficate=yes-without-crl \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url output\ + =user as-value ]->\"data\") ];\r\ + \n } on-error={ \$LogPrint warning \$0 (\"Err = \" . \$Err); }\r\ + \n }\r\ + \n\r\ + \n :foreach Script in=[ /system/script/find where source~\"^#!rsc by Vado\ + s\" ] do={\r\ + \n :local ScriptVal [ /system/script/get \$Script ];\r\ + \n :local ScriptInfo [ \$ParseKeyValueStore (\$ScriptVal->\"comment\") \ + ];\r\ + \n :local SourceNew;\r\ + \n\r\ + \n :foreach Scheduler in=[ /system/scheduler/find where on-event~(\"\\\ + \\b\" . \$ScriptVal->\"name\" . \"\\\\b\") ] do={\r\ + \n :local SchedulerVal [ /system/scheduler/get \$Scheduler ];\r\ + \n :if (\$ScriptVal->\"policy\" != \$SchedulerVal->\"policy\") do={\r\ + \n \$LogPrint warning \$0 (\"Policies differ for script '\" . \$Scr\ + iptVal->\"name\" . \"' and its scheduler '\" . \$SchedulerVal->\"name\" . \ + \"'!\");\r\ + \n }\r\ + \n }\r\ + \n :do {\r\ + \n :if (\$ScriptInfo->\"ignore\" = true) do={\r\ + \n \$LogPrint debug \$0 (\"Ignoring script '\" . \$ScriptVal->\"nam\ + e\" . \"', as requested.\");\r\ + \n :error true;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :local CheckSum (\$CheckSums->(\$ScriptVal->\"name\"));\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Scri\ + ptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :convert transform=md5 to=hex [ :tolf (\$ScriptVal->\"sou\ + rce\") ] ] = \$CheckSum) do={\r\ + \n \$LogPrint debug \$0 (\"Checksum for script '\" . \$ScriptVal-\ + >\"name\" . \"' matches, ignoring.\");\r\ + \n :error true;\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len (\$ScriptInfo->\"certificate\") ] > 0) do={\r\ + \n :if ([ \$CertificateAvailable (\$ScriptInfo->\"certificate\") \"\ + fetch\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Downloading certificate failed, tryi\ + ng without.\");\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n :local BaseUrl [ \$EitherOr (\$ScriptInfo->\"base-url\") \$Globa\ + lScriptsUrl ];\r\ + \n :local UrlSuffix [ \$EitherOr (\$ScriptInfo->\"url-suffix\") \$G\ + lobalScriptsUrlSuffix ];\r\ + \n :local Url (\$BaseUrl . \$ScriptVal->\"name\" . \".rsc\" . \$Url\ + Suffix);\r\ + \n \$LogPrint warning \$0 (\"Fetching script '\" . (\$ScriptVal->\"\ + name\") . \"' from url: \" . \$Url);\r\ + \n :local Result [ /tool/fetch check-certificate=yes-without-crl \\\ + \r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$0 ] }) \$Url outp\ + ut=user as-value ];\r\ + \n :if (\$Result->\"status\" = \"finished\") do={\r\ + \n :set SourceNew [ :tolf (\$Result->\"data\") ];\r\ + \n } \r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed fetching script '\" . \$ScriptV\ + al->\"name\" . \"': \" . \$Err);\r\ + \n :if (\$Err != \"Fetch failed with status 404\") do={\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$ScriptVal->\"source\" = \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Removing dummy. Typo on installation\ + \?\");\r\ + \n /system/script/remove \$Script;\r\ + \n :error false;\r\ + \n }\r\ + \n :if (\$CheckSumsVerify = true) do={\r\ + \n :if ([ :len (\$ScriptInfo->\"base-url\") ] = 0 && [ :len (\$Sc\ + riptInfo->\"url-suffix\") ] = 0 && \\\r\ + \n [ :len \$CheckSum ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Added the script manually\? Skip u\ + pdates with 'ignore=true' in comment.\");\r\ + \n }\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ :len \$SourceNew ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"No update for script '\" . (\$ScriptVal-\ + >\"name\") . \"'.\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :local SourceCRLF [ :tocrlf \$SourceNew ];\r\ + \n :if (\$InitSetup != true && ((\$ScriptVal->\"name\") != \"AM-Globa\ + lConfig\" || (\$ScriptVal->\"name\") != \"AM-GlobalFunc\")) do={\r\ + \n :if (\$SourceNew = (\$ScriptVal->\"source\") || \$SourceCRLF = (\ + \$ScriptVal->\"source\")) do={\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\") \ + . \"' source did not change. End of lines set to CRLF.\");\r\ + \n if (\$ScriptUpdatesCRLF = false) do={\r\ + \n :put [ :tolf \$SourceNew ];\r\ + \n \$LogPrint debug \$0 (\"Script '\" . (\$ScriptVal->\"name\"\ + ) . \"' source update end of lines to LF.\");\r\ + \n }\r\ + \n :error false;\r\ + \n }\r\ + \n }\r\ + \n\r\ + \n :if ([ :pick \$SourceNew 0 14 ] != \"#!rsc by Vados\") do={\r\ + \n \$LogPrint warning \$0 (\"Looks like new script '\" . \$ScriptVa\ + l->\"name\" . \"' is not valid (missing shebang = '\$shebang') Ignoring!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if (\$CommentsInScripts = true) do={\r\ + \n :local CommentLine [ \$Grep \$SourceNew (\"\\23 Script comment:\ + \_\") ];\r\ + \n :if ([ :len \$CommentLine ] = 0) do={\r\ + \n \$LogPrint debug \$0 (\"The search in new script '\" . (\$Scr\ + iptVal->\"name\") . \"' for comment in script body, is not found result Ig\ + noring!\");\r\ + \n :error false;\r\ + \n } else={\r\ + \n :if ([ :len (\$ScriptVal->\"comment\")] = 0 || [ :len (\$Scri\ + ptVal->\"comment\")] != [ :pick \$CommentLine ([ :find \$CommentLine \":\"\ + ] + 2) [ :len \$CommentLine] ]) do={\r\ + \n \$LogPrint debug \$0 (\"Exsiting comment for script '\" . (\ + \$ScriptVal->\"name\") . \"' is '\" . (\$ScriptVal->\"comment\") . \"'.\")\ + ;\r\ + \n :set (\$ScriptVal->\"comment\") [ :pick \$CommentLine ([ :f\ + ind \$CommentLine \":\"] + 2) [ :len \$CommentLine] ];\r\ + \n \$LogPrint debug \$0 (\"New comment (\" . (\$ScriptVal->\"c\ + omment\") . \") for script '\" . (\$ScriptVal->\"name\") . \"' has been ad\ + ded!\");\r\ + \n } else={\r\ + \n \$LogPrint debug \$0 (\"Comment for script '\" . (\$ScriptV\ + al->\"name\") . \"' did not change.\");\r\ + \n :error false;\r\ + \n }\r\ + \n } \r\ + \n }\r\ + \n\r\ + \n :local RequiredROS ([ \$ParseKeyValueStore [ \$Grep \$SourceNew (\ + \"\\23 requires RouterOS, \") ] ]->version);\r\ + \n :if ([ \$RequiredRouterOS \$0 [ \$EitherOr \$RequiredROS \"0.0\" ]\ + \_false ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires RouterOS \" . \\\r\ + \n \$RequiredROS . \", which is not met by your installation. I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :local RequiredDM [ \$ParseKeyValueStore [ \$Grep \$SourceNew (\"\ + \\23 requires device-mode, \") ] ];\r\ + \n :local MissingDM ({});\r\ + \n :foreach Feature,Value in=\$RequiredDM do={\r\ + \n :if ([ :typeof (\$DeviceMode->\$Feature) ] = \"bool\" && (\$Devi\ + ceMode->\$Feature) = false) do={\r\ + \n :set MissingDM (\$MissingDM, \$Feature);\r\ + \n }\r\ + \n }\r\ + \n :if ([ :len \$MissingDM ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The script '\" . (\$ScriptVal->\"name\ + \") . \"' requires disabled \" . \\\r\ + \n \"device-mode features (\" . [ :tostr \$MissingDM ] . \"). I\ + gnoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n\r\ + \n :if ([ \$ValidateSyntax \$SourceNew ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Syntax validation for script '\" . (\$\ + ScriptVal->\"name\") . \"' failed! Ignoring!\");\r\ + \n :error false;\r\ + \n }\r\ + \n \r\ + \n :log info (\"Updating script: \" . (\$ScriptVal->\"name\") . \" Sc\ + ript comment: \" . (\$ScriptVal->\"comment\"));\r\ + \n\r\ + \n /system/script/set owner=(\$ScriptVal->\"name\") comment=(\$Script\ + Val->\"comment\") \\\r\ + \n source=[ \$IfThenElse (\$ScriptUpdatesCRLF = true) \$SourceCRL\ + F \$SourceNew ] \$Script;\r\ + \n :if (\$ScriptVal->\"name\" = \"AM-GlobalConfig\" || \\\r\ + \n \$ScriptVal->\"name\" = \"AM-GlobalFunc\" || \\\r\ + \n \$ScriptVal->\"name\" ~ (\"^(AM-GlobalFunc\\\\.d|mod)/.\")) d\ + o={\r\ + \n :set ReloadGlobal true;\r\ + \n }\r\ + \n } on-error={ }\r\ + \n }\r\ + \n :if (\$ReloadGlobal = true) do={\r\ + \n \$LogPrint info \$0 (\"Reloading global configuration and functions.\ + \");\r\ + \n :onerror Err {\r\ + \n :global InitSetup (a);\r\ + \n /system/script {run AM-GlobalConfig; run AM-GlobalFunc;};\r\ + \n } do={\$LogPrint error \$0 (\"Reloading global configuration and fun\ + ctions failed! \" . \$Err)}\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore > \$GlobalConfVersion) do={\r\ + \n \$LogPrint warning \$0 (\"The configuration version decreased from \ + \" . \\\r\ + \n \$GlobalConfVersionBefore . \" to \" . \$GlobalConfVersion . \\\r\ + \n \". Installed an older version\?\");\r\ + \n }\r\ + \n :if (\$GlobalConfVersionBefore < \$GlobalConfVersion) do={\r\ + \n :global GlobalConfChanges;\r\ + \n :global GlobalConfMigration;\r\ + \n :local ChangeLogCode;\r\ + \n :if ([ :len \$ChangeLogCode ] > 0) do={\r\ + \n :if ([ \$ValidateSyntax \$ChangeLogCode ] = true) do={\r\ + \n :onerror Err {\r\ + \n [ :parse \$ChangeLogCode ];\r\ + \n } do={\$LogPrint warning \$0 (\"The changelog failed to run: \" \ + . \$Err)}\r\ + \n } else={\$LogPrint warning \$0 (\"The changelog failed syntax vali\ + dation!\")}\r\ + \n }\r\ + \n :if ([ :len \$GlobalConfMigration ] > 0) do={\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Migration (\$GlobalConfMigration->[ :tostr \$I ]);\r\ + \n :do {\r\ + \n :if ([ :typeof \$Migration ] != \"str\") do={\r\ + \n \$LogPrint debug \$0 (\"Migration code for change \" . \$I .\ + \_\" is not available.\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$ValidateSyntax \$Migration ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Migration code for change \" . \$I\ + \_. \" failed syntax validation!\");\r\ + \n :error false}\r\ + \n \$LogPrint info \$0 (\"Applying migration for change \" . \$I \ + . \": \" . \$Migration);\r\ + \n :onerror Err {\r\ + \n [ :parse \$Migration ];\r\ + \n } do={\$LogPrint warning \$0 (\"Migration code for change \" .\ + \_\$I . \" failed to run: \" . \$Err)}\r\ + \n } on-error={ }\r\ + \n }\r\ + \n }\r\ + \n :local NotificationMessage (\"The configuration version on \" . \$Id\ + entity . \" increased \" . \\\r\ + \n \"to \" . \$GlobalConfVersion . \", current configuration may nee\ + d modification. \" . \\\r\ + \n \"Please review and update global-config-overlay, then re-run glo\ + bal-config.\");\r\ + \n \$LogPrint info \$0 (\$NotificationMessage);\r\ + \n :if ([ :len \$GlobalConfChanges ] > 0) do={\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n\\nChanges:\ + \");\r\ + \n :for I from=(\$GlobalConfVersionBefore + 1) to=\$GlobalConfVersion\ + \_do={\r\ + \n :local Change (\$GlobalConfChanges->[ :tostr \$I ]);\r\ + \n :set NotificationMessage (\$NotificationMessage . \"\\n \" . \\\ + \r\ + \n [ \$SymbolForNotification \"pushpin\" \"*\" ] . \$Change);\r\ + \n \$LogPrint info \$0 (\"Change \" . \$I . \": \" . \$Change);\r\ + \n }\r\ + \n } else={:set NotificationMessage (\$NotificationMessage . \"\\n\\nNe\ + ws and changes are not available.\")}\r\ + \n\r\ + \n :set GlobalConfChanges;\r\ + \n :set GlobalConfMigration;\r\ + \n }\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n\r\ + \n:set FetchUserAgentStr do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :global IfThenElse;\r\ + \n :local Resource [ /system/resource/get ];\r\ + \n :return (\"User-Agent: Mikrotik/\" . \$Resource->\"version\" . \" \" .\ + \_\$Resource->\"architecture-name\" . \\\r\ + \n \" \" . \$Caller . \"/Fetch (https://amster.vados.ru/; main/3419/3ee\ + 19780)\");\r\ + \n}\r\ + \n\r\ + \n:set Grep do={\r\ + \n :local Input ([ :tostr \$1 ] . \"\\n\");\r\ + \n :local Pattern [ :tostr \$2 ];\r\ + \n :if ([ :typeof [ :find \$Input \$Pattern ] ] = \"nil\") do={:return []\ + }\r\ + \n :do {\r\ + \n :local Line [ :pick \$Input 0 [ :find \$Input \"\\n\" ] ];\r\ + \n :if ([ :typeof [ :find \$Line \$Pattern ] ] = \"num\") do={:return \ + \$Line}\r\ + \n :set Input [ :pick \$Input ([ :find \$Input \"\\n\" ] + 1) [ :len \$\ + Input ] ];\r\ + \n } while=([ :len \$Input ] > 0);\r\ + \n :return [];\r\ + \n}\r\ + \n\r\ + \n:set HumanReadableNum do={\r\ + \n :local Input [ :tonum \$1 ];\r\ + \n :local Base [ :tonum \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global IfThenElse;\r\ + \n :local Prefix \"kMGTPE\";\r\ + \n :local Pow 1;\r\ + \n :set Base [ \$EitherOr \$Base 1024 ];\r\ + \n :local Bin [ \$IfThenElse (\$Base = 1024) \"i\" \"\" ];\r\ + \n :if (\$Input < \$Base) do={:return \$Input}\r\ + \n :for I from=0 to=[ :len \$Prefix ] do={\r\ + \n :set Pow (\$Pow * \$Base);\r\ + \n :if (\$Input / \$Base < \$Pow) do={\r\ + \n :set Prefix [ :pick \$Prefix \$I ];\r\ + \n :local Tmp1 (\$Input * 100 / \$Pow);\r\ + \n :local Tmp2 (\$Tmp1 / 100);\r\ + \n :if (\$Tmp2 >= 100) do={:return (\$Tmp2 . \$Prefix . \$Bin)}\r\ + \n :return (\$Tmp2 . \".\" . \\\r\ + \n [ :pick \$Tmp1 [ :len \$Tmp2 ] ([ :len \$Tmp1 ] - [ :len \$Tmp\ + 2 ] + 1) ] . \\\r\ + \n \$Prefix . \$Bin);\r\ + \n }\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set CleanName do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Return \"\";\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :typeof [ find \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqr\ + stuvwxyz0123456789\" \$Char ] ] = \"nil\") do={\r\ + \n :do {:if ([ :len \$Return ] = 0) do={:error true};\r\ + \n :if ([ :pick \$Return ([ :len \$Return ] - 1) ] = \"-\") do={:er\ + ror true}; :set Char \"-\"} on-error={:set Char \"\"}; \r\ + \n };\r\ + \n :set Return (\$Return . \$Char)};\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set GetRandomNumber do={\r\ + \n :global EitherOr;\r\ + \n :return [ :rndnum from=0 to=[ \$EitherOr [ :tonum \$1 ] 4294967295 ] ]\ + \r\ + \n}\r\ + \n\r\ + \n:set RandomDelay do={\r\ + \n :local Time [ :tonum \$1 ];\r\ + \n :local Unit [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global GetRandomNumber;\r\ + \n :global MAX;\r\ + \n :if (\$Time = 0) do={:return false}\r\ + \n :delay ([ \$MAX 10 [ \$GetRandomNumber ([ :tonsec [ :totime (\$Time . \ + [ \$EitherOr \$Unit \"s\" ]) ] ] / 1000000) ] ] . \"ms\");\r\ + \n}\r\ + \n\r\ + \n:set EscapeForRegEx do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"^.[]\\\$()|*+\?{}\\\\\");\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :if ([ :find \$Chars \$Char ]) do={:set Char (\"\\\\\" . \$Char)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ExitError do={\r\ + \n :local ExitOK [ :tostr \$1 ];\r\ + \n :local Name [ :tostr \$2 ];\r\ + \n :local Error [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :if (\$ExitOK = \"false\") do={\r\ + \n \$LogPrint error \$Name ([ \$IfThenElse ([ :pick \$Name 0 1 ] = \"\\\ + \$\") \\\r\ + \n \"Function\" \"Script\" ] . \" '\" . \$Name . \"' exited with er\ + ror\" . \\\r\ + \n [ \$IfThenElse (!(\$Error ~ \"^(|true|false)\\\$\")) (\": \" . \ + \$Error) \".\" ]);\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n:set MiniDateTimeStamp do={\r\ + \n /system/clock;\r\ + \n :local vdate [get date];\r\ + \n :local vtime [get time];\r\ + \n :local vdoff [:toarray \"0,4,5,7,8,10\"];\r\ + \n :local MM [:pick \$vdate (\$vdoff->2) (\$vdoff->3)];\r\ + \n :local M [:tonum \$MM];\r\ + \n :if (\$vdate ~ \".../../....\") do={\r\ + \n :set vdoff [:toarray \"7,11,1,3,4,6\"];\r\ + \n :set M ([:find \"xxanebarprayunulugepctovecANEBARPRAYUNULUGE\ + PCTOVEC\" [:pick \$vdate (\$vdoff->2) (\$vdoff->3)] -1] / 2);\r\ + \n :if (\$M>12) do={:set M (\$M - 12)}\r\ + \n :set MM [:pick (100 + \$M) 1 3];\r\ + \n }\r\ + \n :local yyyy [:pick \$vdate (\$vdoff->0) (\$vdoff->1)];\r\ + \n :local dd [:pick \$vdate (\$vdoff->4) (\$vdoff->5)];\r\ + \n :local HH [:pick \$vtime 0 2];\r\ + \n :local mm [:pick \$vtime 3 5];\r\ + \n :local ss [:pick \$vtime 6 8];\r\ + \n :return ([\$yyyy] . [\$MM] . [\$dd] . [\$HH] . [\$mm] . [\$ss]);\r\ + \n}\r\ + \n\r\ + \n:set WaitForFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local WaitTime [ :totime \$2 ];\r\ + \n :global CleanFilePath;\r\ + \n :global EitherOr;\r\ + \n :global MAX;\r\ + \n :set FileName [ \$CleanFilePath \$FileName ];\r\ + \n :local Delay ([ \$MAX [ \$EitherOr \$WaitTime 2s ] 100ms ] / 9);\r\ + \n :do {\r\ + \n :retry {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } delay=\$Delay max=10;\r\ + \n } on-error={ }\r\ + \n :while ([ :len [ /file/find where name=\$FileName ] ] > 0) do={\r\ + \n :do {\r\ + \n /file/get \$FileName;\r\ + \n :return true;\r\ + \n } on-error={ }\r\ + \n :delay \$Delay;\r\ + \n :set Delay (\$Delay * 3 / 2);\r\ + \n }\r\ + \n :return false;\r\ + \n}\r\ + \n\r\ + \n:set FileGet do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global WaitForFile;\r\ + \n :if ([ \$WaitForFile \$FileName 0s ] = false) do={:return false}\r\ + \n :local FileVal false;\r\ + \n :do {:set FileVal [ /file/get \$FileName ];\r\ + \n } on-error={ }\r\ + \n :return \$FileVal;\r\ + \n}\r\ + \n\r\ + \n:set RmDir do={\r\ + \n :local DirName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing directory: \". \$DirName);\r\ + \n :local DirVal [ \$FileGet \$DirName ];\r\ + \n :if (\$DirVal = false) do={\$LogPrint debug \$0 (\"... which does not \ + exist.\"); :return true};\r\ + \n :if (\$DirVal->\"type\" != \"directory\") do={\$LogPrint error \$0 (\"\ + Directory '\" . \$DirName . \"' is not a directory.\"); :return false};\r\ + \n :onerror Err {/file/remove \$DirName} do={\$LogPrint error \$0 (\"Remo\ + ving directory '\" . \$DirName . \"' failed: \" . \$Err); :return false};\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set RmFile do={\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :global FileGet;\r\ + \n :global LogPrint;\r\ + \n \$LogPrint debug \$0 (\"Removing file: \". \$FileName);\r\ + \n :local FileVal [ \$FileGet \$FileName ];\r\ + \n :if (\$FileVal = false) do={\$LogPrint debug \$0 (\"... which does not\ + \_exist.\"); :return true}\r\ + \n :if (\$FileVal->\"type\" = \"directory\" || \$FileVal->\"type\" = \"di\ + sk\") do={\r\ + \n \$LogPrint error \$0 (\"File '\" . \$FileName . \"' is not a file.\"\ + ); :return false}\r\ + \n :onerror Err {\r\ + \n /file/remove \$FileName;\r\ + \n } do={\$LogPrint error \$0 (\"Removing file '\" . \$FileName . \"' fai\ + led: \" . \$Err); :return false}\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MkDir do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CleanFilePath;\r\ + \n :global FileGet;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :global LogPrint;\r\ + \n :local MkTmpfs do={\r\ + \n :global WaitForFile;\r\ + \n :local TmpFs [ /disk/find where slot=tmpfs type=tmpfs ];\r\ + \n :if ([ :len \$TmpFs ] = 1) do={\r\ + \n :if ([ /disk/get \$TmpFs disabled ] = true) do={\r\ + \n \$LogPrint info \$0 (\"The tmpfs is disabled, enabling.\");\r\ + \n /disk/enable \$TmpFs;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint info \$0 (\"Creating disk of type tmpfs.\");\r\ + \n \$RmDir \"tmpfs\";\r\ + \n :onerror Err {\r\ + \n /disk/add slot=tmpfs type=tmpfs tmpfs-max-size=([ /system/resource\ + /get total-memory ] / 3);\r\ + \n \$WaitForFile \"tmpfs\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Creating disk of type tmpfs failed: \" .\ + \_\$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n }\r\ + \n :set Path [ \$CleanFilePath \$Path ];\r\ + \n :if (\$Path = \"\") do={\r\ + \n :return true;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Making directory: \" . \$Path);\r\ + \n :local PathVal [ \$FileGet \$Path ];\r\ + \n :if (\$PathVal->\"type\" = \"directory\") do={\r\ + \n \$LogPrint debug \$0 (\"... which already exists.\");\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ :pick \$Path 0 5 ] = \"tmpfs\") do={\r\ + \n :if ([ \$MkTmpfs ] = false) do={\r\ + \n :return false;\r\ + \n }\r\ + \n }\r\ + \n :onerror Err {\r\ + \n /file/add type=\"directory\" name=\$Path;\r\ + \n \$WaitForFile \$Path;\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Making directory '\" . \$Path . \"' failed\ + : \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n:set MAX do={:if (\$1 > \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n:set MIN do={:if (\$1 < \$2) do={:return \$1}\r\ + \n :return \$2;\r\ + \n}\r\ + \n\r\ + \n:set CharacterMultiply do={\r\ + \n :local Str [ :tostr \$1 ];\r\ + \n :local Num [ :tonum \$2 ];\r\ + \n :if (\$Num = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :for I from=1 to=\$Num do={:set Return (\$Return . \$Str)}\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n:set CharacterReplace do={\r\ + \n :local String [ :tostr \$1 ];\r\ + \n :local ReplaceFrom [ :tostr \$2 ];\r\ + \n :local ReplaceWith [ :tostr \$3 ];\r\ + \n :local Return \"\";\r\ + \n :if (\$ReplaceFrom = \"\") do={:return \$String}\r\ + \n :while ([ :typeof [ :find \$String \$ReplaceFrom ] ] != \"nil\") do={\ + \r\ + \n :local Pos [ :find \$String \$ReplaceFrom ];\r\ + \n :set Return (\$Return . [ :pick \$String 0 \$Pos ] . \$ReplaceWith);\ + \r\ + \n :set String [ :pick \$String (\$Pos + [ :len \$ReplaceFrom ]) [ :len\ + \_\$String ] ];\r\ + \n }\r\ + \n :return (\$Return . \$String);\r\ + \n}\r\ + \n\r\ + \n:set CleanFilePath do={\r\ + \n :local Path [ :tostr \$1 ];\r\ + \n :global CharacterReplace;\r\ + \n :while (\$Path ~ \"//\") do={:set \$Path [ \$CharacterReplace \$Path \ + \"//\" \"/\" ]};\r\ + \n :if ([ :pick \$Path 0 ] = \"/\") do={:set Path [ :pick \$Path 1 [ :len\ + \_\$Path ] ]};\r\ + \n :if ([ :pick \$Path ([ :len \$Path ] - 1) ] = \"/\") do={:set Path [ :\ + pick \$Path 0 ([ :len \$Path ] - 1) ]};\r\ + \n :return \$Path;\r\ + \n}\r\ + \n\r\ + \n:set IfThenElse do={\r\ + \n :if ([ :tostr \$1 ] = \"true\" || [ :tobool \$1 ] = true) do={:return \ + \$2};\r\ + \n :return \$3;\r\ + \n}\r\ + \n\r\ + \n:set EitherOr do={\r\ + \n :global IfThenElse;\r\ + \n :if ([ :typeof \$1 ] = \"num\") do={:return [ \$IfThenElse (\$1 != 0) \ + \$1 \$2 ]}\r\ + \n :if ([ :typeof \$1 ] = \"time\") do={:return [ \$IfThenElse (\$1 > 0s)\ + \_\$1 \$2 ]}\r\ + \n# this works for boolean values, literal ones with parentheses\r\ + \n :return [ \$IfThenElse ([ :len [ :tostr \$1 ] ] > 0) \$1 \$2 ];\r\ + \n}\r\ + \n\r\ + \n:set ParseKeyValueStore do={\r\ + \n :local Source \$1;\r\ + \n :if ([ :pick \$Source 0 1 ] = \"{\") do={\r\ + \n :do {\r\ + \n :return [ :deserialize from=json \$Source ];\r\ + \n } on-error={ }\r\ + \n } \r\ + \n :if ([ :typeof \$Source ] != \"array\") do={:set Source [ :tostr \$1 ]\ + }\r\ + \n :local Result ({});\r\ + \n :foreach KeyValue in=[ :toarray \$Source ] do={\r\ + \n :if ([ :find \$KeyValue \"=\" ]) do={\r\ + \n :local Key [ :pick \$KeyValue 0 [ :find \$KeyValue \"=\" ] ];\r\ + \n :local Value [ :pick \$KeyValue ([ :find \$KeyValue \"=\" ] + 1) [\ + \_:len \$KeyValue ] ];\r\ + \n :if (\$Value=\"true\") do={:set Value true}\r\ + \n :if (\$Value=\"false\") do={:set Value false}\r\ + \n :set (\$Result->\$Key) \$Value;\r\ + \n } else={:set (\$Result->\$KeyValue) true}\r\ + \n }\r\ + \n :return \$Result;\r\ + \n}\r\ + \n:set RequiredRouterOS do={\r\ + \n :local Caller [ :tostr \$1 ];\r\ + \n :local Required [ :tostr \$2 ];\r\ + \n :local Warn [ :tostr \$3 ];\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global VersionToNum;\r\ + \n :if (!(\$Required ~ \"^\\\\d+\\\\.\\\\d+((alpha|beta|rc|\\\\.)\\\\d+|)\ + \\\$\")) do={\r\ + \n \$LogPrint error \$0 (\"No valid RouterOS version: \" . \$Required);\ + \r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$VersionToNum \$Required ] > [ \$VersionToNum [ /system/packag\ + e/update/get installed-version ] ]) do={\r\ + \n :if (\$Warn = \"true\") do={\r\ + \n \$LogPrint warning \$0 (\"This \" . [ \$IfThenElse ([ :pick \$Call\ + er 0 ] = (\"\\\$\")) \"function\" \"script\" ] . \\\r\ + \n \" '\" . \$Caller . \"' (at least specific functionality) requir\ + es RouterOS \" . \$Required . \". Please update!\");\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set VersionToNum do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :local Multi 0x1000000;\r\ + \n :local Return 0;\r\ + \n :global CharacterReplace;\r\ + \n :set Input [ \$CharacterReplace \$Input \".\" \",\" ];\r\ + \n :foreach I in={ \"zero\"; \"alpha\"; \"beta\"; \"rc\" } do={\r\ + \n :set Input [ \$CharacterReplace \$Input \$I (\",\" . \$I . \",\") ];\ + \r\ + \n }\r\ + \n :foreach Value in=([ :toarray \$Input ], 0) do={\r\ + \n :local Num [ :tonum \$Value ];\r\ + \n :if (\$Multi = 0x100) do={\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={\r\ + \n :set Return (\$Return + 0xff00);\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n } else={\r\ + \n :if (\$Value = \"zero\") do={ }\r\ + \n :if (\$Value = \"alpha\") do={ :set Return (\$Return + 0x3f00); \ + }\r\ + \n :if (\$Value = \"beta\") do={ :set Return (\$Return + 0x5f00); }\ + \r\ + \n :if (\$Value = \"rc\") do={ :set Return (\$Return + 0x7f00); }\r\ + \n }\r\ + \n }\r\ + \n :if ([ :typeof \$Num ] = \"num\") do={ :set Return (\$Return + (\$Va\ + lue * \$Multi)); }\r\ + \n :set Multi (\$Multi / 0x100);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ScriptLock do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local WaitMax [ :totime \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global ScriptLockOrder;\r\ + \n :if ([ :typeof \$ScriptLockOrder ] = \"nothing\") do={\r\ + \n :set ScriptLockOrder ({});\r\ + \n }\r\ + \n :if ([ :typeof (\$ScriptLockOrder->\$Script) ] = \"nothing\") do={\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :local JobCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :return [ :len [ /system/script/job/find where script=\$Script ] ];\ + \r\ + \n }\r\ + \n :local TicketCount do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :local Count 0;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:set Count (\$Count \ + + 1)}\r\ + \n }\r\ + \n :return \$Count;\r\ + \n }\r\ + \n :local IsFirstTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Check [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if (\$Ticket = \$Check) do={:return true}\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\" && \$Ticket != \$Check) d\ + o={:return false}\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :local AddTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Add [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :while (true) do={\r\ + \n :local Pos [ :len (\$ScriptLockOrder->\$Script) ];\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Pos) \$Add;\r\ + \n :delay 10ms;\r\ + \n :if ((\$ScriptLockOrder->\$Script->\$Pos) = \$Add) do={:return tru\ + e}\r\ + \n }\r\ + \n }\r\ + \n :local RemoveTicket do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :local Remove [ :tostr \$2 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Id,Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :while ((\$ScriptLockOrder->\$Script->\$Id) = \$Remove) do={\r\ + \n :set (\$ScriptLockOrder->\$Script->\$Id);\r\ + \n :delay 10ms;\r\ + \n }\r\ + \n }\r\ + \n }\r\ + \n :local CleanupTickets do={\r\ + \n :local Script [ :tostr \$1 ];\r\ + \n :global ScriptLockOrder;\r\ + \n :foreach Ticket in=(\$ScriptLockOrder->\$Script) do={\r\ + \n :if ([ :typeof \$Ticket ] != \"nothing\") do={:return false}\r\ + \n }\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n }\r\ + \n :if ([ :typeof \$WaitMax ] = \"nil\" ) do={:set WaitMax 0s}\r\ + \n :if ([ :len [ /system/script/find where name=\$Script ] ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"A script named '\" . \$Script . \"' does not\ + \_exist!\");\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$JobCount \$Script ] = 0) do={\r\ + \n \$LogPrint error \$0 (\"No script '\" . \$Script . \"' is running!\"\ + );\r\ + \n :error false;\r\ + \n }\r\ + \n :if ([ \$TicketCount \$Script ] >= [ \$JobCount \$Script ]) do={\r\ + \n \$LogPrint error \$0 (\"More tickets than running scripts '\" . \$Sc\ + ript . \"', resetting!\");\r\ + \n :set (\$ScriptLockOrder->\$Script) ({});\r\ + \n /system/script/job/remove [ find where script=\$Script ];\r\ + \n }\r\ + \n :local MyTicket [ \$GetRandom20CharAlNum 6 ];\r\ + \n \$AddTicket \$Script \$MyTicket;\r\ + \n :local WaitInterval (\$WaitMax / 20);\r\ + \n :local WaitTime \$WaitMax;\r\ + \n :while (\$WaitTime > 0 && \\\r\ + \n ([ \$IsFirstTicket \$Script \$MyTicket ] = false || \\\r\ + \n [ \$TicketCount \$Script ] < [ \$JobCount \$Script ])) do={\r\ + \n :set WaitTime (\$WaitTime - \$WaitInterval);\r\ + \n :delay \$WaitInterval;\r\ + \n }\r\ + \n :if ([ \$IsFirstTicket \$Script \$MyTicket ] = true && \\\r\ + \n [ \$TicketCount \$Script ] = [ \$JobCount \$Script ]) do={\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$CleanupTickets \$Script;\r\ + \n :return true;\r\ + \n }\r\ + \n \$RemoveTicket \$Script \$MyTicket;\r\ + \n \$LogPrint debug \$0 (\"Script '\" . \$Script . \"' started more than \ + once\" . \\\r\ + \n [ \$IfThenElse (\$WaitTime < \$WaitMax) \" and timed out waiting for\ + \_lock\" \"\" ] . \"...\");\r\ + \n :return false;\r\ + \n}\r\ + \n:set SendNotification do={ :onerror Err {\r\ + \n :global SendNotification2;\r\ + \n \$SendNotification2 ({ origin=\$0; subject=\$1; message=\$2; link=\$3;\ + \_silent=\$4 });\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err}\r\ + \n}\r\ + \n:set SendNotification2 do={\r\ + \n :local Notification \$1;\r\ + \n :global NotificationFunctions;\r\ + \n :foreach FunctionName,Discard in=\$NotificationFunctions do={\r\ + \n (\$NotificationFunctions->\$FunctionName) (\"\\\$NotificationFunctio\ + ns->\\\"\" . \$FunctionName . \"\\\"\") \$Notification;\r\ + \n }\r\ + \n}\r\ + \n:set SymbolByUnicodeName do={\r\ + \n :local Name [ :tostr \$1 ];\r\ + \n :global EitherOr;\r\ + \n :global LogPrint;\r\ + \n :global SymbolsExtra;\r\ + \n :local Symbols ({\r\ + \n \"abacus\"=\"\\F0\\9F\\A7\\AE\";\r\ + \n \"alarm-clock\"=\"\\E2\\8F\\B0\";\r\ + \n \"arrow-down\"=\"\\E2\\AC\\87\";\r\ + \n \"arrow-up\"=\"\\E2\\AC\\86\";\r\ + \n \"calendar\"=\"\\F0\\9F\\93\\85\";\r\ + \n \"card-file-box\"=\"\\F0\\9F\\97\\83\";\r\ + \n \"chart-decreasing\"=\"\\F0\\9F\\93\\89\";\r\ + \n \"chart-increasing\"=\"\\F0\\9F\\93\\88\";\r\ + \n \"cloud\"=\"\\E2\\98\\81\";\r\ + \n \"cross-mark\"=\"\\E2\\9D\\8C\";\r\ + \n \"earth\"=\"\\F0\\9F\\8C\\8D\";\r\ + \n \"fire\"=\"\\F0\\9F\\94\\A5\";\r\ + \n \"floppy-disk\"=\"\\F0\\9F\\92\\BE\";\r\ + \n \"gear\"=\"\\E2\\9A\\99\";\r\ + \n \"heart\"=\"\\E2\\99\\A5\";\r\ + \n \"high-voltage-sign\"=\"\\E2\\9A\\A1\";\r\ + \n \"incoming-envelope\"=\"\\F0\\9F\\93\\A8\";\r\ + \n \"information\"=\"\\E2\\84\\B9\";\r\ + \n \"large-orange-circle\"=\"\\F0\\9F\\9F\\A0\";\r\ + \n \"large-red-circle\"=\"\\F0\\9F\\94\\B4\";\r\ + \n \"link\"=\"\\F0\\9F\\94\\97\";\r\ + \n \"lock-with-ink-pen\"=\"\\F0\\9F\\94\\8F\";\r\ + \n \"memo\"=\"\\F0\\9F\\93\\9D\";\r\ + \n \"mobile-phone\"=\"\\F0\\9F\\93\\B1\";\r\ + \n \"pushpin\"=\"\\F0\\9F\\93\\8C\";\r\ + \n \"scissors\"=\"\\E2\\9C\\82\";\r\ + \n \"scroll\"=\"\\F0\\9F\\93\\9C\";\r\ + \n \"smiley-partying-face\"=\"\\F0\\9F\\A5\\B3\";\r\ + \n \"smiley-smiling-face\"=\"\\E2\\98\\BA\";\r\ + \n \"smiley-winking-face-with-tongue\"=\"\\F0\\9F\\98\\9C\";\r\ + \n \"sparkles\"=\"\\E2\\9C\\A8\";\r\ + \n \"speech-balloon\"=\"\\F0\\9F\\92\\AC\";\r\ + \n \"star\"=\"\\E2\\AD\\90\";\r\ + \n \"warning-sign\"=\"\\E2\\9A\\A0\";\r\ + \n \"white-heavy-check-mark\"=\"\\E2\\9C\\85\"\r\ + \n }, \$SymbolsExtra);\r\ + \n :local Magic [ :pick [ /system/clock/get date ] 4 10 ];\r\ + \n :local Special {\r\ + \n \"information-04-01\"=\"\\F0\\9F\\9A\\BB\";\r\ + \n \"large-orange-circle-04-01\"=\"\\F0\\9F\\8D\\8A\";\r\ + \n \"large-orange-circle-10-31\"=\"\\F0\\9F\\8E\\83\";\r\ + \n \"large-red-circle-04-01\"=\"\\F0\\9F\\8D\\92\" };\r\ + \n :if ([ :len (\$Symbols->\$Name) ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"No symbol available for name '\" . \$Name \ + . \"'!\");\r\ + \n :return \"\";\r\ + \n }\r\ + \n :return ([ \$EitherOr (\$Special->(\$Name . \$Magic)) (\$Symbols->\$Na\ + me) ] . \"\\EF\\B8\\8F\");\r\ + \n}\r\ + \n:set SymbolForNotification do={\r\ + \n :global NotificationsWithSymbols;\r\ + \n :global SymbolByUnicodeName;\r\ + \n :global IfThenElse;\r\ + \n :if (\$NotificationsWithSymbols != true) do={:return [ \$IfThenElse ([\ + \_:len \$2 ] > 0) ([ :tostr \$2 ] . \" \") \"\" ]}\r\ + \n :local Return \"\";\r\ + \n :foreach Symbol in=[ :toarray \$1 ] do={:set Return (\$Return . [ \$Sy\ + mbolByUnicodeName \$Symbol ])}\r\ + \n :return (\$Return . \" \");\r\ + \n}\r\ + \n:set Unix2Dos do={:return [ :tocrlf [ :tostr \$1 ] ]}\r\ + \n:set UrlEncode do={\r\ + \n :local Input [ :tostr \$1 ];\r\ + \n :if ([ :len \$Input ] = 0) do={:return \"\"}\r\ + \n :local Return \"\";\r\ + \n :local Chars (\"\\n\\r !\\\"#\\\$%&'()*+,:;<=>\?@[\\\\]^`{|}~\");\r\ + \n :local Subs { \"%0A\"; \"%0D\"; \"%20\"; \"%21\"; \"%22\"; \"%23\"; \"\ + %24\"; \"%25\"; \"%26\"; \"%27\";\r\ + \n \"%28\"; \"%29\"; \"%2A\"; \"%2B\"; \"%2C\"; \"%3A\"; \"%3B\"; \ + \"%3C\"; \"%3D\"; \"%3E\"; \"%3F\";\r\ + \n \"%40\"; \"%5B\"; \"%5C\"; \"%5D\"; \"%5E\"; \"%60\"; \"%7B\"; \ + \"%7C\"; \"%7D\"; \"%7E\" };\r\ + \n :for I from=0 to=([ :len \$Input ] - 1) do={\r\ + \n :local Char [ :pick \$Input \$I ];\r\ + \n :local Replace [ :find \$Chars \$Char ];\r\ + \n :if ([ :typeof \$Replace ] = \"num\") do={:set Char (\$Subs->\$Repla\ + ce)}\r\ + \n :set Return (\$Return . \$Char);\r\ + \n }\r\ + \n :return \$Return;\r\ + \n}\r\ + \n:set ValidateSyntax do={\r\ + \n :local Code [ :tostr \$1 ];\r\ + \n :global LogPrint;\r\ + \n :onerror Err {\r\ + \n [ :parse (\":local Validate do={\\n\" . \$Code . \"\\n}\") ];\r\ + \n } do={\r\ + \n \$LogPrint debug \$0 (\"Valdation failed: \" . \$Err);\r\ + \n :return false;\r\ + \n }\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsDNSResolving do={\r\ + \n :do {:resolve \"api.telegram.org\"} on-error={:return false}\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsFullyConnected do={\r\ + \n :global IsDNSResolving;\r\ + \n :global IsTimeSync;\r\ + \n :if ([ \$IsDNSResolving ] = false) do={:return false};\r\ + \n :if ([ \$IsTimeSync ] = false) do={:return false};\r\ + \n :return true;\r\ + \n}\r\ + \n:set IsTimeSync do={\r\ + \n :global IsTimeSyncCached;\r\ + \n :global IsTimeSyncResetNtp;\r\ + \n :if (\$IsTimeSyncCached = true) do={:return true}\r\ + \n :if ([ /system/ntp/client/get enabled ] = true) do={\r\ + \n :if ([ /system/ntp/client/get status ] = \"synchronized\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :local Uptime [ /system/resource/get uptime ];\r\ + \n :if ([ :typeof \$IsTimeSyncResetNtp ] = \"nothing\") do={\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n }\r\ + \n :if (\$Uptime - \$IsTimeSyncResetNtp < 3m) do={:return false}\r\ + \n :log warning \"\$0 The ntp client is configured, but did not sync.\"\ + ;\r\ + \n :set IsTimeSyncResetNtp \$Uptime;\r\ + \n /system/ntp/client/set enabled=no;\r\ + \n :delay 20ms;\r\ + \n /system/ntp/client/set enabled=yes;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ /system/license/get ]->\"level\" = \"free\" || \\\r\ + \n [ /system/resource/get ]->\"board-name\" = \"x86\") do={\r\ + \n :log debug \"\$0 No ntp client configured, relying on RTC for CHR fr\ + ee license and x86.\";\r\ + \n :return true;\r\ + \n }\r\ + \n :if ([ /ip/cloud/get update-time ] = true) do={\r\ + \n :if ([ :typeof [ /ip/cloud/get public-address ] ] = \"ip\") do={\r\ + \n :set IsTimeSyncCached true;\r\ + \n :return true;\r\ + \n }\r\ + \n :return false;\r\ + \n }\r\ + \n :log debug \"\$0 No time source configured! Returning gracefully...\";\ + \r\ + \n :return true;\r\ + \n}\r\ + \n\r\ + \n# read parts of a large file\r\ + \n:set FetchLargeFiles do={\r\ + \n :local ScriptName [:tostr \$1];\r\ + \n :local fetchUrl [:tostr \$2];\r\ + \n :local CheckCert [:tostr \$3];\r\ + \n :local fetchMode [:tostr \$4];\r\ + \n :local fetchMethod [:tostr \$5];\r\ + \n :local FetchString \"undefined\";\r\ + \n \r\ + \n :global CleanName;\r\ + \n :global FetchUserAgentStr;\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global IfThenElse;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global RmFile;\r\ + \n :global WaitForFile;\r\ + \n\r\ + \n :set CheckCert [ \$IfThenElse (\$CheckCert = \"false\") \"no\" \"yes-w\ + ithout-crl\" ];\r\ + \n #:set fetchMode [ \$IfThenElse (\$fetchMode != \"false\") [:tostr (\"m\ + ode=\" . \$fetchMode)] ];\r\ + \n #:set fetchMethod [\$IfThenElse (\$fetchMethod != \"false\") [:tostr (\ + \"http-method=\\\"\" . \$fetchMethod . \"\\\"\") ]];\r\ + \n \r\ + \n :local DirName (\"tmpfs/\" . [ \$CleanName \$ScriptName ]);\r\ + \n :if ([ \$MkDir \$DirName ] = false) do={\r\ + \n \$LogPrint error \$0 (\"Failed creating directory!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\$DirName . \"/\" . [ \$CleanName \$0 ] . \"-\" . [ \ + \$GetRandom20CharAlNum ]);\r\ + \n #/tool/fetch check-certificate=\$CheckCert \$Url dst-path=\$FileName h\ + ttp-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-value;\r\ + \n #:log warning (\"\\\$fUrl =\" . \$2 . ({[ \$fMode ]}));\r\ + \n :onerror Err {\r\ + \n :set FetchString (\"/tool/fetch \" . \\\r\ + \n [\$IfThenElse ([\$fetchMethod] != \"false\") (\"http-method=\\\"\"\ + \_. \$fetchMethod . \"\\\" \")] . \\\r\ + \n \"check-certificate=\" . \$CheckCert . \" url=(\\\"\" . \$fetchUrl\ + \_. \"\\\") \" . \\\r\ + \n [\$IfThenElse ([\$fetchMode] != \"false\") (\"mode=\" . \$fetchMod\ + e . \" \")] . \\\r\ + \n http-header-field=({ [ \$FetchUserAgentStr \$ScriptName ] }) as-va\ + lue);\r\ + \n :log warning (\"\\\$FetchSring = \" . \$FetchString);\r\ + \n :put [\$FetchString];\r\ + \n #:put [/tool/fetch \$fetchMode check-certificate=\$CheckCert url=(\$\ + fetchUrl) dst-path=(\$FileName) http-header-field=({ [ \$FetchUserAgentStr\ + \_\$ScriptName ] }) as-value];\r\ + \n } do={\r\ + \n :if ([ \$WaitForFile \$FileName 500ms ] = true) do={\r\ + \n \$RmFile \$FileName;\r\ + \n }\r\ + \n \$LogPrint debug \$0 (\"Failed downloading from \" . \$fetchUrl . \"\ + \_- \" . \$Err);\r\ + \n \$RmDir \$DirName;\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$WaitForFile \$FileName 5s ] = false) do={\r\ + \n \$LogPrint debug \$0 (\"The file downloaded from \" . \$fetchUrl . \ + \" did not show up.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileSize [ /file/get \$FileName size ];\r\ + \n :local Return \"\";\r\ + \n :local VarSize 0;\r\ + \n :while (\$VarSize != \$FileSize) do={\r\ + \n :set Return (\$Return . ([ /file/read offset=\$VarSize chunk-size=32\ + 768 file=\$FileName as-value ]->\"data\"));\r\ + \n :set FileSize [ /file/get \$FileName size ];\r\ + \n :set VarSize [ :len \$Return ];\r\ + \n :if (\$VarSize > \$FileSize) do={\r\ + \n :delay 100ms;\r\ + \n }\r\ + \n }\r\ + \n \$RmDir \$DirName;\r\ + \n :return \$Return;\r\ + \n}\r\ + \n\r\ + \n# Global Environment clear. Use: \"\$GlobalEnvRemove True;\".\r\ + \n:set GlobalEnvRemove do={\r\ + \n :local doRmEnv [ :tostr \$1 ];\r\ + \n :global GlobalScriptsUrl;\r\ + \n :local ScriptsUrl;\r\ + \n :global LogPrint;\r\ + \n :if (\$doRmEnv != \"True\") do={\r\ + \n \$LogPrint error \"GlobalEnvRemove\" (\"This script is needed \\\"T\ + rue\\\" for confirm to remove global environment variables!\");\r\ + \n :return [];\r\ + \n :error true; \r\ + \n } else={\r\ + \n :set ScriptsUrl \$GlobalScriptsUrl;\r\ + \n :delay 5;\r\ + \n :foreach var in=[/system/script/environment print as-value] do={/sy\ + stem/script/environment remove (\$var->\".id\")}\r\ + \n :delay 5;\r\ + \n :global GlobalScriptsUrl \$ScriptsUrl;\r\ + \n \$LogPrint warning \"GlobalEnvRemove\" (\"Done!\");\r\ + \n :return [];\r\ + \n :error false;\r\ + \n }\r\ + \n}\r\ + \n\r\ + \n# Add and fix global scheduler\r\ + \n:put \"Add or/and fix Global scheduler...\";\r\ + \n:local OnEvent \"/system/script { run AM-GlobalConfig; run AM-GlobalFunc\ + ; }\";\r\ + \n:local Comment \"Setup Global Environment for scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-SetGlobalEnv\" ] ] \ + = 0) do={\r\ + \n /system/scheduler/add name=\"AM-SetGlobalEnv\" comment=\$Comment on-ev\ + ent=\$OnEvent start-time=startup;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" comment ] != \$Comment)\ + \_do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" comment=\$Comment;\r\ + \n}\r\ + \n:if ([ /system/scheduler/get \"AM-SetGlobalEnv\" on-event ] != \$OnEvent\ + ) do={\r\ + \n /system/scheduler/set \"AM-SetGlobalEnv\" on-event=\$OnEvent;\r\ + \n}\r\ + \n# Add Update Script scheduler\r\ + \n:put \"Add or/and fix Update Script scheduler\";\r\ + \n:set OnEvent \":global ScriptInstallUpdate; \\\$ScriptInstallUpdate;\";\ + \r\ + \n:set Comment \"Every Day Check For Update Scripts\";\r\ + \n:if ([ :len [ /system/scheduler/find where name=\"AM-ScriptInstallUpdate\ + \" ] ] = 0) do={\r\ + \n/system/scheduler/add name=\"AM-ScriptInstallUpdate\" comment=\$Comment \ + start-time=startup interval=1d on-event=\$OnEvent;\r\ + \n}\r\ + \n\r\ + \n#:local Resource [ /system/resource/get ];\r\ + \n#:log info (\$ScriptName . \" Loaded on \" . \$Resource->\"board-name\" \ + . \" with RouterOS \" . \$Resource->\"version\" . \" and Architecture \" .\ + \".\");\r\ + \n\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady;\r\ + \n :retry { :if (\$GlobalConfReady != true) do={ :error (\"Global configs\ + \_not ready.\"); }; } delay=100ms max=5;\r\ + \n\r\ + \n# signal we are ready\r\ + \n:set GlobalFuncReady true;\r\ + \n:set ExitOK true;\r\ + \n:log warning (\"This script \$ScriptName Loaded on \" . \$devBoardName .\ + \_\"\\nRouterOS: \" . \$devCurVersion . \"\\nArchitecture: \" . \$devCurAr\ + ch . \"\\nIdentity: \" . \$Identity);\r\ + \n} do={:global ExitOnError; \$ExitOnError \$0 \$Err;}\r\ + \n\r\ + \n#} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n# log the successful load of the script, or an error if it failed\r\ + \n#:if ([\$GlobalFuncReady] = true && [\$GlobalConfReady] = true) do={\r\ + \n" +add comment="Import ssh keys for public key authentication" \ + dont-require-permissions=no name=AM-SshKeysImport owner=AM-SshKeysImport \ + policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ + source="#!rsc by Vados\r\ + \n# RouterOS script: AM-SshKeysImport\r\ + \n# Script comment: Import ssh keys for public key authentication\r\ + \n# Copyright (c) 2005-2026 Vados \r\ + \n#\r\ + \n# requires RouterOS, version=7.19\r\ + \n#\r\ + \n:local ExitOK false;\r\ + \n:onerror Err {\r\ + \n :global GlobalConfReady; :global GlobalFuncReady;\r\ + \n :retry { :if (\$GlobalConfReady != true || \$GlobalFuncReady != true) \ + \\\r\ + \n do={ :error (\"Global configs or functions not ready.\"); }; } del\ + ay=500ms max=50;\r\ + \n :local ScriptName [ :jobname ];\r\ + \n\r\ + \n:global SSHKeysImport;\r\ + \n:global SSHKeysImportFile;\r\ + \n\r\ + \n# import single key passed as string\r\ + \n:set SSHKeysImport do={ :onerror Err {\r\ + \n :local Key [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global GetRandom20CharAlNum;\r\ + \n :global LogPrint;\r\ + \n :global MkDir;\r\ + \n :global RmDir;\r\ + \n :global WaitForFile;\r\ + \n :if ([ :len \$Key ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass key and u\ + ser!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ :len [ /user/find where name=\$User ] ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"User '\" . \$User . \"' does not exist.\")\ + ;\r\ + \n :return false;\r\ + \n }\r\ + \n :local KeyVal ([ :deserialize \$Key delimiter=\" \" from=dsv options=d\ + sv.plain ]->0);\r\ + \n :if (!(\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\")) do\ + ={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' is\ + \_not supported.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FingerPrintMD5 [ :convert from=base64 transform=md5 to=hex (\$K\ + eyVal->1) ];\r\ + \n :local RegEx (\"\\\\bmd5=\" . \$FingerPrintMD5 . \"\\\\b\");\r\ + \n :if ([ :len [ /user/ssh-keys/find where user=\$User \\\r\ + \n (key-owner~\$RegEx or info~\$RegEx) ] ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"The ssh public key (MD5:\" . \$FingerPrint\ + MD5 . \\\r\ + \n \") is already available for user '\" . \$User . \"'.\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$MkDir \"tmpfs/ssh-keys-import\" ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Creating directory 'tmpfs/ssh-keys-import'\ + \_failed!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local FileName (\"tmpfs/ssh-keys-import/key-\" . [ \$GetRandom20CharA\ + lNum 6 ] . \".pub\");\r\ + \n /file/add name=\$FileName contents=(\$Key . \", md5=\" . \$FingerPrint\ + MD5);\r\ + \n \$WaitForFile \$FileName;\r\ + \n :onerror Err {\r\ + \n /user/ssh-keys/import public-key-file=\$FileName user=\$User;\r\ + \n \$LogPrint info \$0 (\"Imported ssh public key (\" . \$KeyVal->2 . \ + \", \" . \$KeyVal->0 . \", \" . \\\r\ + \n \"MD5:\" . \$FingerPrintMD5 . \") for user '\" . \$User . \"'.\");\ + \r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n } do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key: \" . \$Err);\r\ + \n \$RmDir \"tmpfs/ssh-keys-import\";\r\ + \n :return false;\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n\r\ + \n# import keys from a file\r\ + \n:set SSHKeysImportFile do={ :onerror Err {\r\ + \n :local FileName [ :tostr \$1 ];\r\ + \n :local User [ :tostr \$2 ];\r\ + \n :global EitherOr;\r\ + \n :global FileExists;\r\ + \n :global LogPrint;\r\ + \n :global ParseKeyValueStore;\r\ + \n :global SSHKeysImport;\r\ + \n :if ([ :len \$FileName ] = 0 || [ :len \$User ] = 0) do={\r\ + \n \$LogPrint warning \$0 (\"Missing argument(s), please pass file name\ + \_and user!\");\r\ + \n :return false;\r\ + \n }\r\ + \n :if ([ \$FileExists \$FileName ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"File '\" . \$FileName . \"' does not exist\ + .\");\r\ + \n :return false;\r\ + \n }\r\ + \n :local Keys [ :tolf [ /file/get \$FileName contents ] ];\r\ + \n :foreach KeyVal in=[ :deserialize \$Keys delimiter=\" \" from=dsv opti\ + ons=dsv.plain ] do={\r\ + \n :local Continue false;\r\ + \n :if (\$KeyVal->0 = \"ssh-ed25519\" || \$KeyVal->0 = \"ssh-rsa\") do=\ + {\r\ + \n :if ([ \$SSHKeysImport (\$KeyVal->0 . \" \" . \$KeyVal->1 . \" \" \ + . \$KeyVal->2) \$User ] = false) do={\r\ + \n \$LogPrint warning \$0 (\"Failed importing key for user '\" . \$\ + User . \"'.\");\r\ + \n }\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && \$KeyVal->0 = \"#\") do={\r\ + \n :set User [ \$EitherOr ([ \$ParseKeyValueStore (\$KeyVal->1) ]->\"\ + user\") \$User ];\r\ + \n :set Continue true;\r\ + \n }\r\ + \n :if (\$Continue = false && [ :len (\$KeyVal->0) ] > 0) do={\r\ + \n \$LogPrint warning \$0 (\"SSH key of type '\" . \$KeyVal->0 . \"' \ + is not supported.\");\r\ + \n }\r\ + \n }\r\ + \n} do={\r\ + \n :global ExitOnError; \$ExitOnError \$0 \$Err;\r\ + \n} }\r\ + \n} do={:global ExitError; \$ExitError \$ExitOK [ :jobname ] \$Err}\r\ + \n" +/system watchdog +set watchdog-timer=no +/tool e-mail +set certificate-verification=no from=MikroVados port=587 \ + server=smtp.mail.me.com tls=starttls user=vadossio@icloud.com +/tool mac-server +set allowed-interface-list=LAN +/tool mac-server mac-winbox +set allowed-interface-list=LAN +/tool netwatch +add comment="doh, doh-url=https://security.cloudflare-dns.com/dns-query, notif\ + y, name=CloudFlare-doh IPv4 1" disabled=yes down-script="" host=1.1.1.1 \ + http-codes="" test-script="" type=simple up-script="" +add check-certificate=no comment="doh-fallback, doh-url=https://security.cloud\ + flare-dns.com/dns-query, doh-cert=DigiCert Global Root CA, notify, name=Cl\ + oudFlare-doh IPv4" disabled=yes down-script="" host=1.0.0.1 http-codes="" \ + port=443 test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=Google-DNS IPv4" disabled=yes \ + down-script="" host=8.8.8.8 http-codes="" test-script="" type=simple \ + up-script="" +add comment="doh-fallback, doh-url=https://dns.google/dns-query, doh-cert=GTS \ + Root R1, notify, name=Google-DOH IPv4" disabled=yes down-script="" host=\ + 8.8.4.4 http-codes="" test-script="" type=simple up-script="" +add comment="dns, notify, name=Cuad9-DOH IPv4" disabled=yes down-script="" \ + host=9.9.9.9 http-codes="" test-script="" type=simple up-script="" +add comment="doh-fallback, doh-url=https://dns.quad9.net/dns-query, name=Cuad9\ + -DOH IPv4" disabled=yes down-script="" host=149.112.112.112 http-codes="" \ + test-script="" type=simple up-script="" +add comment="dns-fallback, notify, name=ns1.unet.ws" disabled=yes \ + down-script="" host=91.192.189.2 http-codes="" test-script="" type=simple \ + up-script="" +/tool sniffer +set filter-interface=Bridge-LAN filter-src-ip-address=10.30.30.50/32 +/user aaa +set accounting=no diff --git a/MikroMaster/history/20260302/20260302221005-Diff-Config.rsc b/MikroMaster/history/20260302/20260302221005-Diff-Config.rsc new file mode 100644 index 0000000..2e891b2 --- /dev/null +++ b/MikroMaster/history/20260302/20260302221005-Diff-Config.rsc @@ -0,0 +1,4 @@ +1c1 +< # 2026-03-02 22:10:05 by RouterOS 7.21.2 +--- +> # 2026-03-02 22:00:04 by RouterOS 7.21.2 -- 2.52.0