PNG  IHDRX cHRMz&u0`:pQ<bKGD pHYsodtIME MeqIDATxw]Wug^Qd˶ 6`!N:!@xI~)%7%@Bh&`lnjVF29gΨ4E$|>cɚ{gk= %,a KX%,a KX%,a KX%,a KX%,a KX%,a KX%, b` ǟzeאfp]<!SJmɤY޲ڿ,%c ~ع9VH.!Ͳz&QynֺTkRR.BLHi٪:l;@(!MԴ=žI,:o&N'Kù\vRmJ雵֫AWic H@" !: Cé||]k-Ha oݜ:y F())u]aG7*JV@J415p=sZH!=!DRʯvɱh~V\}v/GKY$n]"X"}t@ xS76^[bw4dsce)2dU0 CkMa-U5tvLƀ~mlMwfGE/-]7XAƟ`׮g ewxwC4\[~7@O-Q( a*XGƒ{ ՟}$_y3tĐƤatgvێi|K=uVyrŲlLӪuܿzwk$m87k( `múcE)"@rK( z4$D; 2kW=Xb$V[Ru819קR~qloѱDyįݎ*mxw]y5e4K@ЃI0A D@"BDk_)N\8͜9dz"fK0zɿvM /.:2O{ Nb=M=7>??Zuo32 DLD@D| &+֎C #B8ַ`bOb $D#ͮҪtx]%`ES`Ru[=¾!@Od37LJ0!OIR4m]GZRJu$‡c=%~s@6SKy?CeIh:[vR@Lh | (BhAMy=݃  G"'wzn޺~8ԽSh ~T*A:xR[ܹ?X[uKL_=fDȊ؂p0}7=D$Ekq!/t.*2ʼnDbŞ}DijYaȲ(""6HA;:LzxQ‘(SQQ}*PL*fc\s `/d'QXW, e`#kPGZuŞuO{{wm[&NBTiiI0bukcA9<4@SӊH*؎4U/'2U5.(9JuDfrޱtycU%j(:RUbArLֺN)udA':uGQN"-"Is.*+k@ `Ojs@yU/ H:l;@yyTn}_yw!VkRJ4P)~y#)r,D =ě"Q]ci'%HI4ZL0"MJy 8A{ aN<8D"1#IJi >XjX֔#@>-{vN!8tRݻ^)N_╗FJEk]CT՟ YP:_|H1@ CBk]yKYp|og?*dGvzنzӴzjֺNkC~AbZƷ`.H)=!QͷVTT(| u78y֮}|[8-Vjp%2JPk[}ԉaH8Wpqhwr:vWª<}l77_~{s۴V+RCģ%WRZ\AqHifɤL36: #F:p]Bq/z{0CU6ݳEv_^k7'>sq*+kH%a`0ԣisqにtү04gVgW΂iJiS'3w.w}l6MC2uԯ|>JF5`fV5m`Y**Db1FKNttu]4ccsQNnex/87+}xaUW9y>ͯ骵G{䩓Գ3+vU}~jJ.NFRD7<aJDB1#ҳgSb,+CS?/ VG J?|?,2#M9}B)MiE+G`-wo߫V`fio(}S^4e~V4bHOYb"b#E)dda:'?}׮4繏`{7Z"uny-?ǹ;0MKx{:_pÚmFמ:F " .LFQLG)Q8qN q¯¯3wOvxDb\. BKD9_NN &L:4D{mm o^tֽ:q!ƥ}K+<"m78N< ywsard5+вz~mnG)=}lYݧNj'QJS{S :UYS-952?&O-:W}(!6Mk4+>A>j+i|<<|;ر^߉=HE|V#F)Emm#}/"y GII웻Jі94+v뾧xu~5C95~ūH>c@덉pʃ1/4-A2G%7>m;–Y,cyyaln" ?ƻ!ʪ<{~h~i y.zZB̃/,雋SiC/JFMmBH&&FAbϓO^tubbb_hZ{_QZ-sύodFgO(6]TJA˯#`۶ɟ( %$&+V'~hiYy>922 Wp74Zkq+Ovn錄c>8~GqܲcWꂎz@"1A.}T)uiW4="jJ2W7mU/N0gcqܗOO}?9/wìXžΏ0 >֩(V^Rh32!Hj5`;O28؇2#ݕf3 ?sJd8NJ@7O0 b־?lldщ̡&|9C.8RTWwxWy46ah嘦mh٤&l zCy!PY?: CJyв]dm4ǜҐR޻RլhX{FƯanшQI@x' ao(kUUuxW_Ñ줮[w8 FRJ(8˼)_mQ _!RJhm=!cVmm ?sFOnll6Qk}alY}; "baӌ~M0w,Ggw2W:G/k2%R,_=u`WU R.9T"v,<\Ik޽/2110Ӿxc0gyC&Ny޽JҢrV6N ``یeA16"J³+Rj*;BϜkZPJaÍ<Jyw:NP8/D$ 011z֊Ⱳ3ι֘k1V_"h!JPIΣ'ɜ* aEAd:ݺ>y<}Lp&PlRfTb1]o .2EW\ͮ]38؋rTJsǏP@芎sF\> P^+dYJLbJ C-xϐn> ι$nj,;Ǖa FU *择|h ~izť3ᤓ`K'-f tL7JK+vf2)V'-sFuB4i+m+@My=O҈0"|Yxoj,3]:cо3 $#uŘ%Y"y죯LebqtҢVzq¼X)~>4L׶m~[1_k?kxֺQ`\ |ٛY4Ѯr!)N9{56(iNq}O()Em]=F&u?$HypWUeB\k]JɩSع9 Zqg4ZĊo oMcjZBU]B\TUd34ݝ~:7ڶSUsB0Z3srx 7`:5xcx !qZA!;%͚7&P H<WL!džOb5kF)xor^aujƍ7 Ǡ8/p^(L>ὴ-B,{ۇWzֺ^k]3\EE@7>lYBȝR.oHnXO/}sB|.i@ɥDB4tcm,@ӣgdtJ!lH$_vN166L__'Z)y&kH;:,Y7=J 9cG) V\hjiE;gya~%ks_nC~Er er)muuMg2;֫R)Md) ,¶ 2-wr#F7<-BBn~_(o=KO㭇[Xv eN_SMgSҐ BS헃D%g_N:/pe -wkG*9yYSZS.9cREL !k}<4_Xs#FmҶ:7R$i,fi!~' # !6/S6y@kZkZcX)%5V4P]VGYq%H1!;e1MV<!ϐHO021Dp= HMs~~a)ަu7G^];git!Frl]H/L$=AeUvZE4P\.,xi {-~p?2b#amXAHq)MWǾI_r`S Hz&|{ +ʖ_= (YS(_g0a03M`I&'9vl?MM+m~}*xT۲(fY*V4x@29s{DaY"toGNTO+xCAO~4Ϳ;p`Ѫ:>Ҵ7K 3}+0 387x\)a"/E>qpWB=1 ¨"MP(\xp߫́A3+J] n[ʼnӼaTbZUWb={~2ooKױӰp(CS\S筐R*JغV&&"FA}J>G֐p1ٸbk7 ŘH$JoN <8s^yk_[;gy-;߉DV{c B yce% aJhDȶ 2IdйIB/^n0tNtџdcKj4϶v~- CBcgqx9= PJ) dMsjpYB] GD4RDWX +h{y`,3ꊕ$`zj*N^TP4L:Iz9~6s) Ga:?y*J~?OrMwP\](21sZUD ?ܟQ5Q%ggW6QdO+\@ ̪X'GxN @'4=ˋ+*VwN ne_|(/BDfj5(Dq<*tNt1х!MV.C0 32b#?n0pzj#!38}޴o1KovCJ`8ŗ_"]] rDUy޲@ Ȗ-;xџ'^Y`zEd?0„ DAL18IS]VGq\4o !swV7ˣι%4FѮ~}6)OgS[~Q vcYbL!wG3 7띸*E Pql8=jT\꘿I(z<[6OrR8ºC~ډ]=rNl[g|v TMTղb-o}OrP^Q]<98S¤!k)G(Vkwyqyr޽Nv`N/e p/~NAOk \I:G6]4+K;j$R:Mi #*[AȚT,ʰ,;N{HZTGMoּy) ]%dHء9Պ䠬|<45,\=[bƟ8QXeB3- &dҩ^{>/86bXmZ]]yޚN[(WAHL$YAgDKp=5GHjU&99v簪C0vygln*P)9^͞}lMuiH!̍#DoRBn9l@ xA/_v=ȺT{7Yt2N"4!YN`ae >Q<XMydEB`VU}u]嫇.%e^ánE87Mu\t`cP=AD/G)sI"@MP;)]%fH9'FNsj1pVhY&9=0pfuJ&gޤx+k:!r˭wkl03׼Ku C &ѓYt{.O.zҏ z}/tf_wEp2gvX)GN#I ݭ߽v/ .& и(ZF{e"=V!{zW`, ]+LGz"(UJp|j( #V4, 8B 0 9OkRrlɱl94)'VH9=9W|>PS['G(*I1==C<5"Pg+x'K5EMd؞Af8lG ?D FtoB[je?{k3zQ vZ;%Ɠ,]E>KZ+T/ EJxOZ1i #T<@ I}q9/t'zi(EMqw`mYkU6;[t4DPeckeM;H}_g pMww}k6#H㶏+b8雡Sxp)&C $@'b,fPߑt$RbJ'vznuS ~8='72_`{q纶|Q)Xk}cPz9p7O:'|G~8wx(a 0QCko|0ASD>Ip=4Q, d|F8RcU"/KM opKle M3#i0c%<7׿p&pZq[TR"BpqauIp$ 8~Ĩ!8Սx\ւdT>>Z40ks7 z2IQ}ItԀ<-%S⍤};zIb$I 5K}Q͙D8UguWE$Jh )cu4N tZl+[]M4k8֦Zeq֮M7uIqG 1==tLtR,ƜSrHYt&QP윯Lg' I,3@P'}'R˪e/%-Auv·ñ\> vDJzlӾNv5:|K/Jb6KI9)Zh*ZAi`?S {aiVDԲuy5W7pWeQJk֤#5&V<̺@/GH?^τZL|IJNvI:'P=Ϛt"¨=cud S Q.Ki0 !cJy;LJR;G{BJy޺[^8fK6)=yʊ+(k|&xQ2`L?Ȓ2@Mf 0C`6-%pKpm')c$׻K5[J*U[/#hH!6acB JA _|uMvDyk y)6OPYjœ50VT K}cǻP[ $:]4MEA.y)|B)cf-A?(e|lɉ#P9V)[9t.EiQPDѠ3ϴ;E:+Օ t ȥ~|_N2,ZJLt4! %ա]u {+=p.GhNcŞQI?Nd'yeh n7zi1DB)1S | S#ًZs2|Ɛy$F SxeX{7Vl.Src3E℃Q>b6G ўYCmtկ~=K0f(=LrAS GN'ɹ9<\!a`)֕y[uՍ[09` 9 +57ts6}b4{oqd+J5fa/,97J#6yν99mRWxJyѡyu_TJc`~W>l^q#Ts#2"nD1%fS)FU w{ܯ R{ ˎ󅃏џDsZSQS;LV;7 Od1&1n$ N /.q3~eNɪ]E#oM~}v֯FڦwyZ=<<>Xo稯lfMFV6p02|*=tV!c~]fa5Y^Q_WN|Vs 0ҘދU97OI'N2'8N֭fgg-}V%y]U4 峧p*91#9U kCac_AFңĪy뚇Y_AiuYyTTYЗ-(!JFLt›17uTozc. S;7A&&<ԋ5y;Ro+:' *eYJkWR[@F %SHWP 72k4 qLd'J "zB6{AC0ƁA6U.'F3:Ȅ(9ΜL;D]m8ڥ9}dU "v!;*13Rg^fJyShyy5auA?ɩGHRjo^]׽S)Fm\toy 4WQS@mE#%5ʈfFYDX ~D5Ϡ9tE9So_aU4?Ѽm%&c{n>.KW1Tlb}:j uGi(JgcYj0qn+>) %\!4{LaJso d||u//P_y7iRJ߬nHOy) l+@$($VFIQ9%EeKʈU. ia&FY̒mZ=)+qqoQn >L!qCiDB;Y<%} OgBxB!ØuG)WG9y(Ą{_yesuZmZZey'Wg#C~1Cev@0D $a@˲(.._GimA:uyw֬%;@!JkQVM_Ow:P.s\)ot- ˹"`B,e CRtaEUP<0'}r3[>?G8xU~Nqu;Wm8\RIkբ^5@k+5(By'L&'gBJ3ݶ!/㮻w҅ yqPWUg<e"Qy*167΃sJ\oz]T*UQ<\FԎ`HaNmڜ6DysCask8wP8y9``GJ9lF\G g's Nn͵MLN֪u$| /|7=]O)6s !ĴAKh]q_ap $HH'\1jB^s\|- W1:=6lJBqjY^LsPk""`]w)󭃈,(HC ?䔨Y$Sʣ{4Z+0NvQkhol6C.婧/u]FwiVjZka&%6\F*Ny#8O,22+|Db~d ~Çwc N:FuuCe&oZ(l;@ee-+Wn`44AMK➝2BRՈt7g*1gph9N) *"TF*R(#'88pm=}X]u[i7bEc|\~EMn}P瘊J)K.0i1M6=7'_\kaZ(Th{K*GJyytw"IO-PWJk)..axӝ47"89Cc7ĐBiZx 7m!fy|ϿF9CbȩV 9V-՛^pV̌ɄS#Bv4-@]Vxt-Z, &ֺ*diؠ2^VXbs֔Ìl.jQ]Y[47gj=幽ex)A0ip׳ W2[ᎇhuE^~q흙L} #-b۸oFJ_QP3r6jr+"nfzRJTUqoaۍ /$d8Mx'ݓ= OՃ| )$2mcM*cЙj}f };n YG w0Ia!1Q.oYfr]DyISaP}"dIӗթO67jqR ҊƐƈaɤGG|h;t]䗖oSv|iZqX)oalv;۩meEJ\!8=$4QU4Xo&VEĊ YS^E#d,yX_> ۘ-e\ "Wa6uLĜZi`aD9.% w~mB(02G[6y.773a7 /=o7D)$Z 66 $bY^\CuP. (x'"J60׿Y:Oi;F{w佩b+\Yi`TDWa~|VH)8q/=9!g߆2Y)?ND)%?Ǐ`k/sn:;O299yB=a[Ng 3˲N}vLNy;*?x?~L&=xyӴ~}q{qE*IQ^^ͧvü{Huu=R|>JyUlZV, B~/YF!Y\u_ݼF{_C)LD]m {H 0ihhadd nUkf3oٺCvE\)QJi+֥@tDJkB$1!Đr0XQ|q?d2) Ӣ_}qv-< FŊ߫%roppVBwü~JidY4:}L6M7f٬F "?71<2#?Jyy4뷢<_a7_=Q E=S1И/9{+93֮E{ǂw{))?maÆm(uLE#lïZ  ~d];+]h j?!|$F}*"4(v'8s<ŏUkm7^7no1w2ؗ}TrͿEk>p'8OB7d7R(A 9.*Mi^ͳ; eeUwS+C)uO@ =Sy]` }l8^ZzRXj[^iUɺ$tj))<sbDJfg=Pk_{xaKo1:-uyG0M ԃ\0Lvuy'ȱc2Ji AdyVgVh!{]/&}}ċJ#%d !+87<;qN޼Nفl|1N:8ya  8}k¾+-$4FiZYÔXk*I&'@iI99)HSh4+2G:tGhS^繿 Kتm0 вDk}֚+QT4;sC}rՅE,8CX-e~>G&'9xpW,%Fh,Ry56Y–hW-(v_,? ; qrBk4-V7HQ;ˇ^Gv1JVV%,ik;D_W!))+BoS4QsTM;gt+ndS-~:11Sgv!0qRVh!"Ȋ(̦Yl.]PQWgٳE'`%W1{ndΗBk|Ž7ʒR~,lnoa&:ü$ 3<a[CBݮwt"o\ePJ=Hz"_c^Z.#ˆ*x z̝grY]tdkP*:97YľXyBkD4N.C_[;F9`8& !AMO c `@BA& Ost\-\NX+Xp < !bj3C&QL+*&kAQ=04}cC!9~820G'PC9xa!w&bo_1 Sw"ܱ V )Yl3+ס2KoXOx]"`^WOy :3GO0g;%Yv㐫(R/r (s } u B &FeYZh0y> =2<Ϟc/ -u= c&׭,.0"g"7 6T!vl#sc>{u/Oh Bᾈ)۴74]x7 gMӒ"d]U)}" v4co[ ɡs 5Gg=XR14?5A}D "b{0$L .\4y{_fe:kVS\\O]c^W52LSBDM! C3Dhr̦RtArx4&agaN3Cf<Ԉp4~ B'"1@.b_/xQ} _߃҉/gٓ2Qkqp0շpZ2fԫYz< 4L.Cyυι1t@鎫Fe sYfsF}^ V}N<_`p)alٶ "(XEAVZ<)2},:Ir*#m_YӼ R%a||EƼIJ,,+f"96r/}0jE/)s)cjW#w'Sʯ5<66lj$a~3Kʛy 2:cZ:Yh))+a߭K::N,Q F'qB]={.]h85C9cr=}*rk?vwV렵ٸW Rs%}rNAkDv|uFLBkWY YkX מ|)1!$#3%y?pF<@<Rr0}: }\J [5FRxY<9"SQdE(Q*Qʻ)q1E0B_O24[U'],lOb ]~WjHޏTQ5Syu wq)xnw8~)c 쫬gٲߠ H% k5dƝk> kEj,0% b"vi2Wس_CuK)K{n|>t{P1򨾜j>'kEkƗBg*H%'_aY6Bn!TL&ɌOb{c`'d^{t\i^[uɐ[}q0lM˕G:‚4kb祔c^:?bpg… +37stH:0}en6x˟%/<]BL&* 5&fK9Mq)/iyqtA%kUe[ڛKN]Ě^,"`/ s[EQQm?|XJ߅92m]G.E΃ח U*Cn.j_)Tѧj̿30ڇ!A0=͜ar I3$C^-9#|pk!)?7.x9 @OO;WƝZBFU keZ75F6Tc6"ZȚs2y/1 ʵ:u4xa`C>6Rb/Yм)^=+~uRd`/|_8xbB0?Ft||Z\##|K 0>>zxv8۴吅q 8ĥ)"6>~\8:qM}#͚'ĉ#p\׶ l#bA?)|g g9|8jP(cr,BwV (WliVxxᡁ@0Okn;ɥh$_ckCgriv}>=wGzβ KkBɛ[˪ !J)h&k2%07δt}!d<9;I&0wV/ v 0<H}L&8ob%Hi|޶o&h1L|u֦y~󛱢8fٲUsւ)0oiFx2}X[zVYr_;N(w]_4B@OanC?gĦx>мgx>ΛToZoOMp>40>V Oy V9iq!4 LN,ˢu{jsz]|"R޻&'ƚ{53ўFu(<٪9:΋]B;)B>1::8;~)Yt|0(pw2N%&X,URBK)3\zz&}ax4;ǟ(tLNg{N|Ǽ\G#C9g$^\}p?556]/RP.90 k,U8/u776s ʪ_01چ|\N 0VV*3H鴃J7iI!wG_^ypl}r*jɤSR 5QN@ iZ#1ٰy;_\3\BQQ x:WJv츟ٯ$"@6 S#qe딇(/P( Dy~TOϻ<4:-+F`0||;Xl-"uw$Цi󼕝mKʩorz"mϺ$F:~E'ҐvD\y?Rr8_He@ e~O,T.(ފR*cY^m|cVR[8 JҡSm!ΆԨb)RHG{?MpqrmN>߶Y)\p,d#xۆWY*,l6]v0h15M˙MS8+EdI='LBJIH7_9{Caз*Lq,dt >+~ّeʏ?xԕ4bBAŚjﵫ!'\Ը$WNvKO}ӽmSşذqsOy?\[,d@'73'j%kOe`1.g2"e =YIzS2|zŐƄa\U,dP;jhhhaxǶ?КZ՚.q SE+XrbOu%\GتX(H,N^~]JyEZQKceTQ]VGYqnah;y$cQahT&QPZ*iZ8UQQM.qo/T\7X"u?Mttl2Xq(IoW{R^ ux*SYJ! 4S.Jy~ BROS[V|žKNɛP(L6V^|cR7i7nZW1Fd@ Ara{詑|(T*dN]Ko?s=@ |_EvF]׍kR)eBJc" MUUbY6`~V޴dJKß&~'d3i5h-3LL

HOME


5h-3LL 1.0
DIR: /usr/lib/python2.7/dist-packages/samba/netcmd
/usr/lib/python2.7/dist-packages/samba/netcmd/
Upload File:
Current File : /usr/lib/python2.7/dist-packages/samba/netcmd/dns.py
# DNS management tool
#
# Copyright (C) Amitay Isaacs 2011-2012
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

import samba.getopt as options
from struct import pack
from socket import inet_ntoa
from socket import inet_ntop
from socket import AF_INET
from socket import AF_INET6
import shlex

from samba.netcmd import (
    Command,
    CommandError,
    Option,
    SuperCommand,
    )
from samba.dcerpc import dnsp, dnsserver


def dns_connect(server, lp, creds):
    if server.lower() == 'localhost':
        server = '127.0.0.1'
    binding_str = "ncacn_ip_tcp:%s[sign]" % server
    dns_conn = dnsserver.dnsserver(binding_str, lp, creds)
    return dns_conn


def bool_string(flag):
    if flag == 0:
        ret = 'FALSE'
    elif flag == 1:
        ret = 'TRUE'
    else:
        ret = 'UNKNOWN (0x%x)' % flag
    return ret


def enum_string(module, enum_defs, value):
    ret = None
    for e in enum_defs:
        if value == getattr(module, e):
            ret = e
            break
    if not ret:
        ret = 'UNKNOWN (0x%x)' % value
    return ret


def bitmap_string(module, bitmap_defs, value):
    ret = ''
    for b in bitmap_defs:
        if value & getattr(module, b):
            ret += '%s ' % b
    if not ret:
        ret = 'NONE'
    return ret


def boot_method_string(boot_method):
    enum_defs = [ 'DNS_BOOT_METHOD_UNINITIALIZED', 'DNS_BOOT_METHOD_FILE',
                    'DNS_BOOT_METHOD_REGISTRY', 'DNS_BOOT_METHOD_DIRECTORY' ]
    return enum_string(dnsserver, enum_defs, boot_method)


def name_check_flag_string(check_flag):
    enum_defs = [ 'DNS_ALLOW_RFC_NAMES_ONLY', 'DNS_ALLOW_NONRFC_NAMES',
                    'DNS_ALLOW_MULTIBYTE_NAMES', 'DNS_ALLOW_ALL_NAMES' ]
    return enum_string(dnsserver, enum_defs, check_flag)


def zone_type_string(zone_type):
    enum_defs = [ 'DNS_ZONE_TYPE_CACHE', 'DNS_ZONE_TYPE_PRIMARY',
                    'DNS_ZONE_TYPE_SECONDARY', 'DNS_ZONE_TYPE_STUB',
                    'DNS_ZONE_TYPE_FORWARDER', 'DNS_ZONE_TYPE_SECONDARY_CACHE' ]
    return enum_string(dnsp, enum_defs, zone_type)


def zone_update_string(zone_update):
    enum_defs = [ 'DNS_ZONE_UPDATE_OFF', 'DNS_ZONE_UPDATE_UNSECURE',
                    'DNS_ZONE_UPDATE_SECURE' ]
    return enum_string(dnsp, enum_defs, zone_update)


def zone_secondary_security_string(security):
    enum_defs = [ 'DNS_ZONE_SECSECURE_NO_SECURITY', 'DNS_ZONE_SECSECURE_NS_ONLY',
                    'DNS_ZONE_SECSECURE_LIST_ONLY', 'DNS_ZONE_SECSECURE_NO_XFER' ]
    return enum_string(dnsserver, enum_defs, security)


def zone_notify_level_string(notify_level):
    enum_defs = [ 'DNS_ZONE_NOTIFY_OFF', 'DNS_ZONE_NOTIFY_ALL_SECONDARIES',
                    'DNS_ZONE_NOTIFY_LIST_ONLY' ]
    return enum_string(dnsserver, enum_defs, notify_level)


def dp_flags_string(dp_flags):
    bitmap_defs = [ 'DNS_DP_AUTOCREATED', 'DNS_DP_LEGACY', 'DNS_DP_DOMAIN_DEFAULT',
                'DNS_DP_FOREST_DEFAULT', 'DNS_DP_ENLISTED', 'DNS_DP_DELETED' ]
    return bitmap_string(dnsserver, bitmap_defs, dp_flags)


def zone_flags_string(flags):
    bitmap_defs = [ 'DNS_RPC_ZONE_PAUSED', 'DNS_RPC_ZONE_SHUTDOWN',
                    'DNS_RPC_ZONE_REVERSE', 'DNS_RPC_ZONE_AUTOCREATED',
                    'DNS_RPC_ZONE_DSINTEGRATED', 'DNS_RPC_ZONE_AGING',
                    'DNS_RPC_ZONE_UPDATE_UNSECURE', 'DNS_RPC_ZONE_UPDATE_SECURE',
                    'DNS_RPC_ZONE_READONLY']
    return bitmap_string(dnsserver, bitmap_defs, flags)


def ip4_array_string(array):
    ret = []
    if not array:
        return ret
    for i in xrange(array.AddrCount):
        addr = inet_ntop(AF_INET, pack('I', array.AddrArray[i]))
        ret.append(addr)
    return ret


def dns_addr_array_string(array):
    ret = []
    if not array:
        return ret
    for i in xrange(array.AddrCount):
        if array.AddrArray[i].MaxSa[0] == 0x02:
            x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[4:8]
            addr = inet_ntop(AF_INET, x)
        elif array.AddrArray[i].MaxSa[0] == 0x17:
            x = "".join([chr(b) for b in array.AddrArray[i].MaxSa])[8:24]
            addr = inet_ntop(AF_INET6, x)
        else:
            addr = 'UNKNOWN'
        ret.append(addr)
    return ret


def dns_type_flag(rec_type):
    rtype = rec_type.upper()
    if rtype == 'A':
        record_type = dnsp.DNS_TYPE_A
    elif rtype == 'AAAA':
        record_type = dnsp.DNS_TYPE_AAAA
    elif rtype == 'PTR':
        record_type = dnsp.DNS_TYPE_PTR
    elif rtype == 'NS':
        record_type = dnsp.DNS_TYPE_NS
    elif rtype == 'CNAME':
        record_type = dnsp.DNS_TYPE_CNAME
    elif rtype == 'SOA':
        record_type = dnsp.DNS_TYPE_SOA
    elif rtype == 'MX':
        record_type = dnsp.DNS_TYPE_MX
    elif rtype == 'SRV':
        record_type = dnsp.DNS_TYPE_SRV
    elif rtype == 'TXT':
        record_type = dnsp.DNS_TYPE_TXT
    elif rtype == 'ALL':
        record_type = dnsp.DNS_TYPE_ALL
    else:
        raise CommandError('Unknown type of DNS record %s' % rec_type)
    return record_type


def dns_client_version(cli_version):
    version = cli_version.upper()
    if version == 'W2K':
        client_version = dnsserver.DNS_CLIENT_VERSION_W2K
    elif version == 'DOTNET':
        client_version = dnsserver.DNS_CLIENT_VERSION_DOTNET
    elif version == 'LONGHORN':
        client_version = dnsserver.DNS_CLIENT_VERSION_LONGHORN
    else:
        raise CommandError('Unknown client version %s' % cli_version)
    return client_version


def print_serverinfo(outf, typeid, serverinfo):
    outf.write('  dwVersion                   : 0x%x\n' % serverinfo.dwVersion)
    outf.write('  fBootMethod                 : %s\n' % boot_method_string(serverinfo.fBootMethod))
    outf.write('  fAdminConfigured            : %s\n' % bool_string(serverinfo.fAdminConfigured))
    outf.write('  fAllowUpdate                : %s\n' % bool_string(serverinfo.fAllowUpdate))
    outf.write('  fDsAvailable                : %s\n' % bool_string(serverinfo.fDsAvailable))
    outf.write('  pszServerName               : %s\n' % serverinfo.pszServerName)
    outf.write('  pszDsContainer              : %s\n' % serverinfo.pszDsContainer)

    if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO:
        outf.write('  aipServerAddrs              : %s\n' %
                    ip4_array_string(serverinfo.aipServerAddrs))
        outf.write('  aipListenAddrs              : %s\n' %
                    ip4_array_string(serverinfo.aipListenAddrs))
        outf.write('  aipForwarders               : %s\n' %
                    ip4_array_string(serverinfo.aipForwarders))
    else:
        outf.write('  aipServerAddrs              : %s\n' %
                    dns_addr_array_string(serverinfo.aipServerAddrs))
        outf.write('  aipListenAddrs              : %s\n' %
                    dns_addr_array_string(serverinfo.aipListenAddrs))
        outf.write('  aipForwarders               : %s\n' %
                    dns_addr_array_string(serverinfo.aipForwarders))

    outf.write('  dwLogLevel                  : %d\n' % serverinfo.dwLogLevel)
    outf.write('  dwDebugLevel                : %d\n' % serverinfo.dwDebugLevel)
    outf.write('  dwForwardTimeout            : %d\n' % serverinfo.dwForwardTimeout)
    outf.write('  dwRpcPrototol               : 0x%x\n' % serverinfo.dwRpcProtocol)
    outf.write('  dwNameCheckFlag             : %s\n' % name_check_flag_string(serverinfo.dwNameCheckFlag))
    outf.write('  cAddressAnswerLimit         : %d\n' % serverinfo.cAddressAnswerLimit)
    outf.write('  dwRecursionRetry            : %d\n' % serverinfo.dwRecursionRetry)
    outf.write('  dwRecursionTimeout          : %d\n' % serverinfo.dwRecursionTimeout)
    outf.write('  dwMaxCacheTtl               : %d\n' % serverinfo.dwMaxCacheTtl)
    outf.write('  dwDsPollingInterval         : %d\n' % serverinfo.dwDsPollingInterval)
    outf.write('  dwScavengingInterval        : %d\n' % serverinfo.dwScavengingInterval)
    outf.write('  dwDefaultRefreshInterval    : %d\n' % serverinfo.dwDefaultRefreshInterval)
    outf.write('  dwDefaultNoRefreshInterval  : %d\n' % serverinfo.dwDefaultNoRefreshInterval)
    outf.write('  fAutoReverseZones           : %s\n' % bool_string(serverinfo.fAutoReverseZones))
    outf.write('  fAutoCacheUpdate            : %s\n' % bool_string(serverinfo.fAutoCacheUpdate))
    outf.write('  fRecurseAfterForwarding     : %s\n' % bool_string(serverinfo.fRecurseAfterForwarding))
    outf.write('  fForwardDelegations         : %s\n' % bool_string(serverinfo.fForwardDelegations))
    outf.write('  fNoRecursion                : %s\n' % bool_string(serverinfo.fNoRecursion))
    outf.write('  fSecureResponses            : %s\n' % bool_string(serverinfo.fSecureResponses))
    outf.write('  fRoundRobin                 : %s\n' % bool_string(serverinfo.fRoundRobin))
    outf.write('  fLocalNetPriority           : %s\n' % bool_string(serverinfo.fLocalNetPriority))
    outf.write('  fBindSecondaries            : %s\n' % bool_string(serverinfo.fBindSecondaries))
    outf.write('  fWriteAuthorityNs           : %s\n' % bool_string(serverinfo.fWriteAuthorityNs))
    outf.write('  fStrictFileParsing          : %s\n' % bool_string(serverinfo.fStrictFileParsing))
    outf.write('  fLooseWildcarding           : %s\n' % bool_string(serverinfo.fLooseWildcarding))
    outf.write('  fDefaultAgingState          : %s\n' % bool_string(serverinfo.fDefaultAgingState))

    if typeid != dnsserver.DNSSRV_TYPEID_SERVER_INFO_W2K:
        outf.write('  dwRpcStructureVersion       : 0x%x\n' % serverinfo.dwRpcStructureVersion)
        outf.write('  aipLogFilter                : %s\n' % dns_addr_array_string(serverinfo.aipLogFilter))
        outf.write('  pwszLogFilePath             : %s\n' % serverinfo.pwszLogFilePath)
        outf.write('  pszDomainName               : %s\n' % serverinfo.pszDomainName)
        outf.write('  pszForestName               : %s\n' % serverinfo.pszForestName)
        outf.write('  pszDomainDirectoryPartition : %s\n' % serverinfo.pszDomainDirectoryPartition)
        outf.write('  pszForestDirectoryPartition : %s\n' % serverinfo.pszForestDirectoryPartition)

        outf.write('  dwLocalNetPriorityNetMask   : 0x%x\n' % serverinfo.dwLocalNetPriorityNetMask)
        outf.write('  dwLastScavengeTime          : %d\n' % serverinfo.dwLastScavengeTime)
        outf.write('  dwEventLogLevel             : %d\n' % serverinfo.dwEventLogLevel)
        outf.write('  dwLogFileMaxSize            : %d\n' % serverinfo.dwLogFileMaxSize)
        outf.write('  dwDsForestVersion           : %d\n' % serverinfo.dwDsForestVersion)
        outf.write('  dwDsDomainVersion           : %d\n' % serverinfo.dwDsDomainVersion)
        outf.write('  dwDsDsaVersion              : %d\n' % serverinfo.dwDsDsaVersion)

    if typeid == dnsserver.DNSSRV_TYPEID_SERVER_INFO:
        outf.write('  fReadOnlyDC                 : %s\n' % bool_string(serverinfo.fReadOnlyDC))


def print_zoneinfo(outf, typeid, zoneinfo):
    outf.write('  pszZoneName                 : %s\n' % zoneinfo.pszZoneName)
    outf.write('  dwZoneType                  : %s\n' % zone_type_string(zoneinfo.dwZoneType))
    outf.write('  fReverse                    : %s\n' % bool_string(zoneinfo.fReverse))
    outf.write('  fAllowUpdate                : %s\n' % zone_update_string(zoneinfo.fAllowUpdate))
    outf.write('  fPaused                     : %s\n' % bool_string(zoneinfo.fPaused))
    outf.write('  fShutdown                   : %s\n' % bool_string(zoneinfo.fShutdown))
    outf.write('  fAutoCreated                : %s\n' % bool_string(zoneinfo.fAutoCreated))
    outf.write('  fUseDatabase                : %s\n' % bool_string(zoneinfo.fUseDatabase))
    outf.write('  pszDataFile                 : %s\n' % zoneinfo.pszDataFile)
    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
        outf.write('  aipMasters                  : %s\n' %
                    ip4_array_string(zoneinfo.aipMasters))
    else:
        outf.write('  aipMasters                  : %s\n' %
                    dns_addr_array_string(zoneinfo.aipMasters))
    outf.write('  fSecureSecondaries          : %s\n' % zone_secondary_security_string(zoneinfo.fSecureSecondaries))
    outf.write('  fNotifyLevel                : %s\n' % zone_notify_level_string(zoneinfo.fNotifyLevel))
    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
        outf.write('  aipSecondaries              : %s\n' %
                    ip4_array_string(zoneinfo.aipSecondaries))
        outf.write('  aipNotify                   : %s\n' %
                    ip4_array_string(zoneinfo.aipNotify))
    else:
        outf.write('  aipSecondaries              : %s\n' %
                    dns_addr_array_string(zoneinfo.aipSecondaries))
        outf.write('  aipNotify                   : %s\n' %
                    dns_addr_array_string(zoneinfo.aipNotify))
    outf.write('  fUseWins                    : %s\n' % bool_string(zoneinfo.fUseWins))
    outf.write('  fUseNbstat                  : %s\n' % bool_string(zoneinfo.fUseNbstat))
    outf.write('  fAging                      : %s\n' % bool_string(zoneinfo.fAging))
    outf.write('  dwNoRefreshInterval         : %d\n' % zoneinfo.dwNoRefreshInterval)
    outf.write('  dwRefreshInterval           : %d\n' % zoneinfo.dwRefreshInterval)
    outf.write('  dwAvailForScavengeTime      : %d\n' % zoneinfo.dwAvailForScavengeTime)
    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
        outf.write('  aipScavengeServers          : %s\n' %
                    ip4_array_string(zoneinfo.aipScavengeServers))
    else:
        outf.write('  aipScavengeServers          : %s\n' %
                    dns_addr_array_string(zoneinfo.aipScavengeServers))

    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO_W2K:
        outf.write('  dwRpcStructureVersion       : 0x%x\n' % zoneinfo.dwRpcStructureVersion)
        outf.write('  dwForwarderTimeout          : %d\n' % zoneinfo.dwForwarderTimeout)
        outf.write('  fForwarderSlave             : %d\n' % zoneinfo.fForwarderSlave)
        if typeid != dnsserver.DNSSRV_TYPEID_ZONE_INFO:
            outf.write('  aipLocalMasters             : %s\n' %
                        ip4_array_string(zoneinfo.aipLocalMasters))
        else:
            outf.write('  aipLocalMasters             : %s\n' %
                        dns_addr_array_string(zoneinfo.aipLocalMasters))
        outf.write('  dwDpFlags                   : %s\n' % dp_flags_string(zoneinfo.dwDpFlags))
        outf.write('  pszDpFqdn                   : %s\n' % zoneinfo.pszDpFqdn)
        outf.write('  pwszZoneDn                  : %s\n' % zoneinfo.pwszZoneDn)
        outf.write('  dwLastSuccessfulSoaCheck    : %d\n' % zoneinfo.dwLastSuccessfulSoaCheck)
        outf.write('  dwLastSuccessfulXfr         : %d\n' % zoneinfo.dwLastSuccessfulXfr)

    if typeid == dnsserver.DNSSRV_TYPEID_ZONE_INFO:
        outf.write('  fQueuedForBackgroundLoad    : %s\n' % bool_string(zoneinfo.fQueuedForBackgroundLoad))
        outf.write('  fBackgroundLoadInProgress   : %s\n' % bool_string(zoneinfo.fBackgroundLoadInProgress))
        outf.write('  fReadOnlyZone               : %s\n' % bool_string(zoneinfo.fReadOnlyZone))
        outf.write('  dwLastXfrAttempt            : %d\n' % zoneinfo.dwLastXfrAttempt)
        outf.write('  dwLastXfrResult             : %d\n' % zoneinfo.dwLastXfrResult)


def print_zone(outf, typeid, zone):
    outf.write('  pszZoneName                 : %s\n' % zone.pszZoneName)
    outf.write('  Flags                       : %s\n' % zone_flags_string(zone.Flags))
    outf.write('  ZoneType                    : %s\n' % zone_type_string(zone.ZoneType))
    outf.write('  Version                     : %s\n' % zone.Version)

    if typeid != dnsserver.DNSSRV_TYPEID_ZONE_W2K:
        outf.write('  dwDpFlags                   : %s\n' % dp_flags_string(zone.dwDpFlags))
        outf.write('  pszDpFqdn                   : %s\n' % zone.pszDpFqdn)


def print_enumzones(outf, typeid, zones):
    outf.write('  %d zone(s) found\n' % zones.dwZoneCount)
    for zone in zones.ZoneArray:
        outf.write('\n')
        print_zone(outf, typeid, zone)


def print_dns_record(outf, rec):
    if rec.wType == dnsp.DNS_TYPE_A:
        mesg = 'A: %s' % (rec.data)
    elif rec.wType == dnsp.DNS_TYPE_AAAA:
        mesg = 'AAAA: %s' % (rec.data)
    elif rec.wType == dnsp.DNS_TYPE_PTR:
        mesg = 'PTR: %s' % (rec.data.str)
    elif rec.wType == dnsp.DNS_TYPE_NS:
        mesg = 'NS: %s' % (rec.data.str)
    elif rec.wType == dnsp.DNS_TYPE_CNAME:
        mesg = 'CNAME: %s' % (rec.data.str)
    elif rec.wType == dnsp.DNS_TYPE_SOA:
        mesg = 'SOA: serial=%d, refresh=%d, retry=%d, expire=%d, minttl=%d, ns=%s, email=%s' % (
                    rec.data.dwSerialNo,
                    rec.data.dwRefresh,
                    rec.data.dwRetry,
                    rec.data.dwExpire,
                    rec.data.dwMinimumTtl,
                    rec.data.NamePrimaryServer.str,
                    rec.data.ZoneAdministratorEmail.str)
    elif rec.wType == dnsp.DNS_TYPE_MX:
        mesg = 'MX: %s (%d)' % (rec.data.nameExchange.str, rec.data.wPreference)
    elif rec.wType == dnsp.DNS_TYPE_SRV:
        mesg = 'SRV: %s (%d, %d, %d)' % (rec.data.nameTarget.str, rec.data.wPort,
                                         rec.data.wPriority, rec.data.wWeight)
    elif rec.wType == dnsp.DNS_TYPE_TXT:
        slist = ['"%s"' % name.str for name in rec.data.str]
        mesg = 'TXT: %s' % ','.join(slist)
    else:
        mesg = 'Unknown: '
    outf.write('    %s (flags=%x, serial=%d, ttl=%d)\n' % (
                mesg, rec.dwFlags, rec.dwSerial, rec.dwTtlSeconds))


def print_dnsrecords(outf, records):
    for rec in records.rec:
        outf.write('  Name=%s, Records=%d, Children=%d\n' % (
                    rec.dnsNodeName.str,
                    rec.wRecordCount,
                    rec.dwChildCount))
        for dns_rec in rec.records:
                print_dns_record(outf, dns_rec)


#
# Always create a copy of strings when creating DNS_RPC_RECORDs
# to overcome the bug in pidl generated python bindings.
#

class ARecord(dnsserver.DNS_RPC_RECORD):
    def __init__(self, ip_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
                    node_flag=0):
        super(ARecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_A
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._ip_addr = ip_addr[:]
        self.data = self._ip_addr


class AAAARecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, ip6_addr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
                    node_flag=0):
        super(AAAARecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_AAAA
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._ip6_addr = ip6_addr[:]
        self.data = self._ip6_addr


class PTRRecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, ptr, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
                 node_flag=0):
        super(PTRRecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_PTR
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._ptr = ptr[:]
        ptr_name = dnsserver.DNS_RPC_NAME()
        ptr_name.str = self._ptr
        ptr_name.len = len(ptr)
        self.data = ptr_name


class CNameRecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, cname, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
                    node_flag=0):
        super(CNameRecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_CNAME
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._cname = cname[:]
        cname_name = dnsserver.DNS_RPC_NAME()
        cname_name.str = self._cname
        cname_name.len = len(cname)
        self.data = cname_name


class NSRecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, dns_server, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
                    node_flag=0):
        super(NSRecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_NS
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._dns_server = dns_server[:]
        ns = dnsserver.DNS_RPC_NAME()
        ns.str = self._dns_server
        ns.len = len(dns_server)
        self.data = ns


class MXRecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, mail_server, preference, serial=1, ttl=900,
                 rank=dnsp.DNS_RANK_ZONE, node_flag=0):
        super(MXRecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_MX
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._mail_server = mail_server[:]
        mx = dnsserver.DNS_RPC_RECORD_NAME_PREFERENCE()
        mx.wPreference = preference
        mx.nameExchange.str = self._mail_server
        mx.nameExchange.len = len(mail_server)
        self.data = mx


class SOARecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, mname, rname, serial=1, refresh=900, retry=600,
                 expire=86400, minimum=3600, ttl=3600, rank=dnsp.DNS_RANK_ZONE,
                 node_flag=dnsp.DNS_RPC_FLAG_AUTH_ZONE_ROOT):
        super(SOARecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_SOA
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._mname = mname[:]
        self._rname = rname[:]
        soa = dnsserver.DNS_RPC_RECORD_SOA()
        soa.dwSerialNo = serial
        soa.dwRefresh = refresh
        soa.dwRetry = retry
        soa.dwExpire = expire
        soa.dwMinimumTtl = minimum
        soa.NamePrimaryServer.str = self._mname
        soa.NamePrimaryServer.len = len(mname)
        soa.ZoneAdministratorEmail.str = self._rname
        soa.ZoneAdministratorEmail.len = len(rname)
        self.data = soa


class SRVRecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, target, port, priority=0, weight=100, serial=1, ttl=900,
                rank=dnsp.DNS_RANK_ZONE, node_flag=0):
        super(SRVRecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_SRV
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._target = target[:]
        srv = dnsserver.DNS_RPC_RECORD_SRV()
        srv.wPriority = priority
        srv.wWeight = weight
        srv.wPort = port
        srv.nameTarget.str = self._target
        srv.nameTarget.len = len(target)
        self.data = srv


class TXTRecord(dnsserver.DNS_RPC_RECORD):

    def __init__(self, slist, serial=1, ttl=900, rank=dnsp.DNS_RANK_ZONE,
                node_flag=0):
        super(TXTRecord, self).__init__()
        self.wType = dnsp.DNS_TYPE_TXT
        self.dwFlags = rank | node_flag
        self.dwSerial = serial
        self.dwTtlSeconds = ttl
        self._slist = []
        for s in slist:
            self._slist.append(s[:])
        names = []
        for s in self._slist:
            name = dnsserver.DNS_RPC_NAME()
            name.str = s
            name.len = len(s)
            names.append(name)
        txt = dnsserver.DNS_RPC_RECORD_STRING()
        txt.count = len(slist)
        txt.str = names
        self.data = txt


# Convert data into a dns record
def data_to_dns_record(record_type, data):
    if record_type == dnsp.DNS_TYPE_A:
        rec = ARecord(data)
    elif record_type == dnsp.DNS_TYPE_AAAA:
        rec = AAAARecord(data)
    elif record_type == dnsp.DNS_TYPE_PTR:
        rec = PTRRecord(data)
    elif record_type == dnsp.DNS_TYPE_CNAME:
        rec = CNameRecord(data)
    elif record_type == dnsp.DNS_TYPE_NS:
        rec = NSRecord(data)
    elif record_type == dnsp.DNS_TYPE_MX:
        tmp = data.split(' ')
        if len(tmp) != 2:
            raise CommandError('Data requires 2 elements - mail_server, preference')
        mail_server = tmp[0]
        preference = int(tmp[1])
        rec = MXRecord(mail_server, preference)
    elif record_type == dnsp.DNS_TYPE_SRV:
        tmp = data.split(' ')
        if len(tmp) != 4:
            raise CommandError('Data requires 4 elements - server, port, priority, weight')
        server = tmp[0]
        port = int(tmp[1])
        priority = int(tmp[2])
        weight = int(tmp[3])
        rec = SRVRecord(server, port, priority=priority, weight=weight)
    elif record_type == dnsp.DNS_TYPE_SOA:
        tmp = data.split(' ')
        if len(tmp) != 7:
            raise CommandError('Data requires 7 elements - nameserver, email, serial, '
                               'refresh, retry, expire, minimumttl')
        nameserver = tmp[0]
        email = tmp[1]
        serial = int(tmp[2])
        refresh = int(tmp[3])
        retry = int(tmp[4])
        expire = int(tmp[5])
        minimum = int(tmp[6])
        rec = SOARecord(nameserver, email, serial=serial, refresh=refresh,
                        retry=retry, expire=expire, minimum=minimum)
    elif record_type == dnsp.DNS_TYPE_TXT:
        slist = shlex.split(data)
        rec = TXTRecord(slist)
    else:
        raise CommandError('Unsupported record type')
    return rec


# Match dns name (of type DNS_RPC_NAME)
def dns_name_equal(n1, n2):
    return n1.str.rstrip('.').lower() == n2.str.rstrip('.').lower()


# Match a dns record with specified data
def dns_record_match(dns_conn, server, zone, name, record_type, data):
    urec = data_to_dns_record(record_type, data)

    select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA

    try:
        buflen, res = dns_conn.DnssrvEnumRecords2(
            dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name, None,
            record_type, select_flags, None, None)
    except RuntimeError, e:
        return None

    if not res or res.count == 0:
        return None

    rec_match = None
    for rec in res.rec[0].records:
        if rec.wType != record_type:
            continue

        found = False
        if record_type == dnsp.DNS_TYPE_A:
            if rec.data == urec.data:
                found = True
        elif record_type == dnsp.DNS_TYPE_AAAA:
            if rec.data == urec.data:
                found = True
        elif record_type == dnsp.DNS_TYPE_PTR:
            if dns_name_equal(rec.data, urec.data):
                found = True
        elif record_type == dnsp.DNS_TYPE_CNAME:
            if dns_name_equal(rec.data, urec.data):
                found = True
        elif record_type == dnsp.DNS_TYPE_NS:
            if dns_name_equal(rec.data, urec.data):
                found = True
        elif record_type == dnsp.DNS_TYPE_MX:
            if dns_name_equal(rec.data.nameExchange, urec.data.nameExchange) and \
               rec.data.wPreference == urec.data.wPreference:
                found = True
        elif record_type == dnsp.DNS_TYPE_SRV:
            if rec.data.wPriority == urec.data.wPriority and \
               rec.data.wWeight == urec.data.wWeight and \
               rec.data.wPort == urec.data.wPort and \
               dns_name_equal(rec.data.nameTarget, urec.data.nameTarget):
                found = True
        elif record_type == dnsp.DNS_TYPE_SOA:
            if rec.data.dwSerialNo == urec.data.dwSerialNo and \
               rec.data.dwRefresh == urec.data.dwRefresh and \
               rec.data.dwRetry == urec.data.dwRetry and \
               rec.data.dwExpire == urec.data.dwExpire and \
               rec.data.dwMinimumTtl == urec.data.dwMinimumTtl and \
               dns_name_equal(rec.data.NamePrimaryServer,
                              urec.data.NamePrimaryServer) and \
               dns_name_equal(rec.data.ZoneAdministratorEmail,
                              urec.data.ZoneAdministratorEmail):
                found = True
        elif record_type == dnsp.DNS_TYPE_TXT:
            if rec.data.count == urec.data.count:
                found = True
                for i in xrange(rec.data.count):
                    found = found and \
                            (rec.data.str[i].str == urec.data.str[i].str)

        if found:
            rec_match = rec
            break

    return rec_match


class cmd_serverinfo(Command):
    """Query for Server information."""

    synopsis = '%prog <server> [options]'

    takes_args = [ 'server' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    takes_options = [
        Option('--client-version', help='Client Version',
                default='longhorn', metavar='w2k|dotnet|longhorn',
                choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
    ]

    def run(self, server, cli_ver, sambaopts=None, credopts=None,
            versionopts=None):
        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        client_version = dns_client_version(cli_ver)

        typeid, res = dns_conn.DnssrvQuery2(client_version, 0, server,
                                            None, 'ServerInfo')
        print_serverinfo(self.outf, typeid, res)


class cmd_zoneinfo(Command):
    """Query for zone information."""

    synopsis = '%prog <server> <zone> [options]'

    takes_args = [ 'server', 'zone' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    takes_options = [
        Option('--client-version', help='Client Version',
                default='longhorn', metavar='w2k|dotnet|longhorn',
                choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
    ]

    def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
            versionopts=None):
        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        client_version = dns_client_version(cli_ver)

        typeid, res = dns_conn.DnssrvQuery2(client_version, 0, server, zone,
                                            'ZoneInfo')
        print_zoneinfo(self.outf, typeid, res)


class cmd_zonelist(Command):
    """Query for zones."""

    synopsis = '%prog <server> [options]'

    takes_args = [ 'server' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    takes_options = [
        Option('--client-version', help='Client Version',
                default='longhorn', metavar='w2k|dotnet|longhorn',
                choices=['w2k','dotnet','longhorn'], dest='cli_ver'),
        Option('--primary', help='List primary zones (default)',
                action='store_true', dest='primary'),
        Option('--secondary', help='List secondary zones',
                action='store_true', dest='secondary'),
        Option('--cache', help='List cached zones',
                action='store_true', dest='cache'),
        Option('--auto', help='List automatically created zones',
                action='store_true', dest='auto'),
        Option('--forward', help='List forward zones',
                action='store_true', dest='forward'),
        Option('--reverse', help='List reverse zones',
                action='store_true', dest='reverse'),
        Option('--ds', help='List directory integrated zones',
                action='store_true', dest='ds'),
        Option('--non-ds', help='List non-directory zones',
                action='store_true', dest='nonds')
    ]

    def run(self, server, cli_ver, primary=False, secondary=False, cache=False,
                auto=False, forward=False, reverse=False, ds=False, nonds=False,
                sambaopts=None, credopts=None, versionopts=None):
        request_filter = 0

        if primary:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_PRIMARY
        if secondary:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_SECONDARY
        if cache:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_CACHE
        if auto:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_AUTO
        if forward:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_FORWARD
        if reverse:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_REVERSE
        if ds:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_DS
        if nonds:
            request_filter |= dnsserver.DNS_ZONE_REQUEST_NON_DS

        if request_filter == 0:
            request_filter = dnsserver.DNS_ZONE_REQUEST_PRIMARY

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        client_version = dns_client_version(cli_ver)

        typeid, res = dns_conn.DnssrvComplexOperation2(client_version,
                                                        0, server, None,
                                                        'EnumZones',
                                                        dnsserver.DNSSRV_TYPEID_DWORD,
                                                        request_filter)

        if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
            typeid = dnsserver.DNSSRV_TYPEID_ZONE_W2K
        else:
            typeid = dnsserver.DNSSRV_TYPEID_ZONE
        print_enumzones(self.outf, typeid, res)


class cmd_zonecreate(Command):
    """Create a zone."""

    synopsis = '%prog <server> <zone> [options]'

    takes_args = [ 'server', 'zone' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    takes_options = [
        Option('--client-version', help='Client Version',
                default='longhorn', metavar='w2k|dotnet|longhorn',
                choices=['w2k','dotnet','longhorn'], dest='cli_ver')
    ]

    def run(self, server, zone, cli_ver, sambaopts=None, credopts=None,
            versionopts=None):

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        zone = zone.lower()

        client_version = dns_client_version(cli_ver)
        if client_version == dnsserver.DNS_CLIENT_VERSION_W2K:
            typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_W2K
            zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_W2K()
            zone_create_info.pszZoneName = zone
            zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
            zone_create_info.fAging = 0
            zone_create_info.fDsIntegrated = 1
            zone_create_info.fLoadExisting = 1
        elif client_version == dnsserver.DNS_CLIENT_VERSION_DOTNET:
            typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE_DOTNET
            zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_DOTNET()
            zone_create_info.pszZoneName = zone
            zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
            zone_create_info.fAging = 0
            zone_create_info.fDsIntegrated = 1
            zone_create_info.fLoadExisting = 1
            zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT
        else:
            typeid = dnsserver.DNSSRV_TYPEID_ZONE_CREATE
            zone_create_info = dnsserver.DNS_RPC_ZONE_CREATE_INFO_LONGHORN()
            zone_create_info.pszZoneName = zone
            zone_create_info.dwZoneType = dnsp.DNS_ZONE_TYPE_PRIMARY
            zone_create_info.fAging = 0
            zone_create_info.fDsIntegrated = 1
            zone_create_info.fLoadExisting = 1
            zone_create_info.dwDpFlags = dnsserver.DNS_DP_DOMAIN_DEFAULT

        res = dns_conn.DnssrvOperation2(client_version, 0, server, None,
                                        0, 'ZoneCreate', typeid,
                                        zone_create_info)

        typeid = dnsserver.DNSSRV_TYPEID_NAME_AND_PARAM
        name_and_param = dnsserver.DNS_RPC_NAME_AND_PARAM()
        name_and_param.pszNodeName = 'AllowUpdate'
        name_and_param.dwParam = dnsp.DNS_ZONE_UPDATE_SECURE

        res = dns_conn.DnssrvOperation2(client_version, 0, server, zone,
                                        0, 'ResetDwordProperty', typeid,
                                        name_and_param)
        self.outf.write('Zone %s created successfully\n' % zone)


class cmd_zonedelete(Command):
    """Delete a zone."""

    synopsis = '%prog <server> <zone> [options]'

    takes_args = [ 'server', 'zone' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    def run(self, server, zone, sambaopts=None, credopts=None,
            versionopts=None):

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        zone = zone.lower()
        res = dns_conn.DnssrvOperation2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
                                        0, server, zone, 0, 'DeleteZoneFromDs',
                                        dnsserver.DNSSRV_TYPEID_NULL,
                                        None)
        self.outf.write('Zone %s delete successfully\n' % zone)


class cmd_query(Command):
    """Query a name."""

    synopsis = '%prog <server> <zone> <name> <A|AAAA|CNAME|MX|NS|SOA|SRV|TXT|ALL> [options]'

    takes_args = [ 'server', 'zone', 'name', 'rtype' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    takes_options = [
        Option('--authority', help='Search authoritative records (default)',
                action='store_true', dest='authority'),
        Option('--cache', help='Search cached records',
                action='store_true', dest='cache'),
        Option('--glue', help='Search glue records',
                action='store_true', dest='glue'),
        Option('--root', help='Search root hints',
                action='store_true', dest='root'),
        Option('--additional', help='List additional records',
                action='store_true', dest='additional'),
        Option('--no-children', help='Do not list children',
                action='store_true', dest='no_children'),
        Option('--only-children', help='List only children',
                action='store_true', dest='only_children')
    ]

    def run(self, server, zone, name, rtype, authority=False, cache=False,
            glue=False, root=False, additional=False, no_children=False,
            only_children=False, sambaopts=None, credopts=None,
            versionopts=None):
        record_type = dns_type_flag(rtype)

        if name.find('*') != -1:
            raise CommandError('Wildcard searches not supported. To dump entire zone use "@"')

        select_flags = 0
        if authority:
            select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA
        if cache:
            select_flags |= dnsserver.DNS_RPC_VIEW_CACHE_DATA
        if glue:
            select_flags |= dnsserver.DNS_RPC_VIEW_GLUE_DATA
        if root:
            select_flags |= dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA
        if additional:
            select_flags |= dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA
        if no_children:
            select_flags |= dnsserver.DNS_RPC_VIEW_NO_CHILDREN
        if only_children:
            select_flags |= dnsserver.DNS_RPC_VIEW_ONLY_CHILDREN

        if select_flags == 0:
            select_flags = dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA

        if select_flags == dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA:
            self.outf.write('Specify either --authority or --root along with --additional.\n')
            self.outf.write('Assuming --authority.\n')
            select_flags |= dnsserver.DNS_RPC_VIEW_AUTHORITY_DATA

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        buflen, res = dns_conn.DnssrvEnumRecords2(
                dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, zone, name,
                None, record_type, select_flags, None, None)
        print_dnsrecords(self.outf, res)


class cmd_roothints(Command):
    """Query root hints."""

    synopsis = '%prog <server> [<name>] [options]'

    takes_args = [ 'server', 'name?' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    def run(self, server, name='.', sambaopts=None, credopts=None,
            versionopts=None):
        record_type = dnsp.DNS_TYPE_NS
        select_flags = (dnsserver.DNS_RPC_VIEW_ROOT_HINT_DATA |
                        dnsserver.DNS_RPC_VIEW_ADDITIONAL_DATA)

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        buflen, res = dns_conn.DnssrvEnumRecords2(
            dnsserver.DNS_CLIENT_VERSION_LONGHORN, 0, server, '..RootHints',
            name, None, record_type, select_flags, None, None)
        print_dnsrecords(self.outf, res)


class cmd_add_record(Command):
    """Add a DNS record

       For each type data contents are as follows:
         A      ipv4_address_string
         AAAA   ipv6_address_string
         PTR    fqdn_string
         CNAME  fqdn_string
         NS     fqdn_string
         MX     "fqdn_string preference"
         SRV    "fqdn_string port priority weight"
         TXT    "'string1' 'string2' ..."
    """

    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'

    takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    def run(self, server, zone, name, rtype, data, sambaopts=None,
            credopts=None, versionopts=None):

        if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
            raise CommandError('Adding record of type %s is not supported' % rtype)

        record_type = dns_type_flag(rtype)
        rec = data_to_dns_record(record_type, data)

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
                data)
        if rec_match is not None:
            raise CommandError('Record already exists')

        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
        add_rec_buf.rec = rec

        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
                                     0, server, zone, name, add_rec_buf, None)
        self.outf.write('Record added successfully\n')


class cmd_update_record(Command):
    """Update a DNS record

       For each type data contents are as follows:
         A      ipv4_address_string
         AAAA   ipv6_address_string
         PTR    fqdn_string
         CNAME  fqdn_string
         NS     fqdn_string
         MX     "fqdn_string preference"
         SOA    "fqdn_dns fqdn_email serial refresh retry expire minimumttl"
         SRV    "fqdn_string port priority weight"
         TXT    "'string1' 'string2' ..."
    """

    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SOA|SRV|TXT> <olddata> <newdata>'

    takes_args = [ 'server', 'zone', 'name', 'rtype', 'olddata', 'newdata' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    def run(self, server, zone, name, rtype, olddata, newdata,
                sambaopts=None, credopts=None, versionopts=None):

        if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SOA','SRV','TXT'):
            raise CommandError('Updating record of type %s is not supported' % rtype)

        record_type = dns_type_flag(rtype)
        rec = data_to_dns_record(record_type, newdata)

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        rec_match = dns_record_match(dns_conn, server, zone, name, record_type,
                olddata)
        if not rec_match:
            raise CommandError('Record does not exist')

        # Copy properties from existing record to new record
        rec.dwFlags = rec_match.dwFlags
        rec.dwSerial = rec_match.dwSerial
        rec.dwTtlSeconds = rec_match.dwTtlSeconds
        rec.dwTimeStamp = rec_match.dwTimeStamp

        add_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
        add_rec_buf.rec = rec

        del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
        del_rec_buf.rec = rec_match

        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
                                        0,
                                        server,
                                        zone,
                                        name,
                                        add_rec_buf,
                                        del_rec_buf)
        self.outf.write('Record updated successfully\n')


class cmd_delete_record(Command):
    """Delete a DNS record

       For each type data contents are as follows:
         A      ipv4_address_string
         AAAA   ipv6_address_string
         PTR    fqdn_string
         CNAME  fqdn_string
         NS     fqdn_string
         MX     "fqdn_string preference"
         SRV    "fqdn_string port priority weight"
         TXT    "'string1' 'string2' ..."
    """

    synopsis = '%prog <server> <zone> <name> <A|AAAA|PTR|CNAME|NS|MX|SRV|TXT> <data>'

    takes_args = [ 'server', 'zone', 'name', 'rtype', 'data' ]

    takes_optiongroups = {
        "sambaopts": options.SambaOptions,
        "versionopts": options.VersionOptions,
        "credopts": options.CredentialsOptions,
    }

    def run(self, server, zone, name, rtype, data, sambaopts=None, credopts=None, versionopts=None):

        if rtype.upper() not in ('A','AAAA','PTR','CNAME','NS','MX','SRV','TXT'):
            raise CommandError('Deleting record of type %s is not supported' % rtype)

        record_type = dns_type_flag(rtype)

        self.lp = sambaopts.get_loadparm()
        self.creds = credopts.get_credentials(self.lp)
        dns_conn = dns_connect(server, self.lp, self.creds)

        rec_match = dns_record_match(dns_conn, server, zone, name, record_type, data)
        if not rec_match:
            raise CommandError('Record does not exist')

        del_rec_buf = dnsserver.DNS_RPC_RECORD_BUF()
        del_rec_buf.rec = rec_match

        dns_conn.DnssrvUpdateRecord2(dnsserver.DNS_CLIENT_VERSION_LONGHORN,
                                        0,
                                        server,
                                        zone,
                                        name,
                                        None,
                                        del_rec_buf)
        self.outf.write('Record deleted successfully\n')


class cmd_dns(SuperCommand):
    """Domain Name Service (DNS) management."""

    subcommands = {}
    subcommands['serverinfo'] = cmd_serverinfo()
    subcommands['zoneinfo'] = cmd_zoneinfo()
    subcommands['zonelist'] = cmd_zonelist()
    subcommands['zonecreate'] = cmd_zonecreate()
    subcommands['zonedelete'] = cmd_zonedelete()
    subcommands['query'] = cmd_query()
    subcommands['roothints'] = cmd_roothints()
    subcommands['add'] = cmd_add_record()
    subcommands['update'] = cmd_update_record()
    subcommands['delete'] = cmd_delete_record()