3 W&_E@s\dZddlZddlZddlZddlZddlZddlZddlZddlm Z m Z m Z ddl Z yddl mZeZ Wnddl Z YnXGdddeZGdd d eZGd d d eZGd d d eZGdddeZGdddeZddlmZdde je jddddgd ad&ddZddZddZddZGd d!d!ZGd"d#d#ee jZ d$d%Z!dS)'u< $Id$ This file is part of the py3dns project. Homepage: https://launchpad.net/py3dns This code is covered by the standard Python License. See LICENSE for details. Changes for Python3 port © 2011-14 Scott Kitterman Base functionality. Request and Response classes, that sort of thing. N)TypeClassOpcode) SystemRandomc@s eZdZdS)DNSErrorN)__name__ __module__ __qualname__r r /usr/lib/python3.6/Base.pyrsrc@s eZdZdS) ArgumentErrorN)rr r r r r r r sr c@s eZdZdS) SocketErrorN)rr r r r r r r!src@s eZdZdS) TimeoutErrorN)rr r r r r r r"src@seZdZddZdS) ServerErrorcCstj|||||_||_dS)N)r__init__messagercode)selfrrr r r r%szServerError.__init__N)rr r rr r r r r$src@s eZdZdS)IncompleteReplyErrorN)rr r r r r r r*sr)Libudp5) protocolportopcodeqtyperdZtimingtimeout server_rotateserver/etc/resolv.confcCsRyt|d }t|SQRXWn.tk rL}ztjt|dSd}~XnXdS)zCparses the /etc/resolv.conf file and sets defaults for name serversrN)openParseResolvConfFromIterableFileNotFoundErrorwarningswarnstr)Z resolv_pathstreamer r r ParseResolvConf3s  r,cCsx|D]}|j}| s|ddks|ddkr2q|j}t|dkrHq|ddkrlt|dkrl|dtd<|ddkrx|ddkr|dd kr|dd krtd j|dqWd S) zHparses a resolv.conf formatted stream and sets defaults for name serversr;#ZdomainrsearchZoptionsZsortlistZ nameserverr!N)stripsplitlendefaultsappend)lineslineZfieldsr r r r%<s       r%cCsHddl}|jdkr,ddlm}|jtd<n|jdkr>tntSdS) Nrwin32ntr)win32dnsr!darwin)r8r9)sysplatformr:ZRegistryResolver4ParseOSXSysConfigr,)r<r:r r r _DiscoverNameServersQs   r@cCsdS)zbDon't call, only here for backward compatability. We do discovery for you automatically. Nr r r r r DiscoverNameServers[srAc@sxeZdZdZddZddZddZdd Zd d Zd d Z ddZ ddZ ddZ ddZ ddZddZddZdS) DnsRequestz high level Request object cOsPd|_d|_i|_|j|||j|_d|_d|_t|jddkrLtddS)Nrr>r!z"No working name servers discovered) donefuncpy3asyncr4argparseargstid resulttyper3r)rnamerFr r r rcs zDnsRequest.__init__cCs| rd|jkr|jd|d<t|tks6t|tkr@||d<n t|dkr`|dr`|d|d<tdrttdtjkrtdddtdddtd<xBttjD]2}||kr||jkr|j|||<qt|||<qWt|dtkst|dtkr|dg|d<||_ dS)NrIrrr r!) r4typebytesr)r3typesZListTypelistkeysrF)rrIrFir r r rEns$   $ $zDnsRequest.argparsecCstj|||_dS)N)sockets)rabr r r socketInitszDnsRequest.socketInitcCsh|jdkr6tj|jggg|j\}}}t|s6td|jjd\|_|_tj|_ |j |j d<|j S)NrTimeoutir!) rselectrQr3rZrecvfromreply from_addresstime time_finishnsrF processReply)rr#wr+r r r processUDPReplys   zDnsRequest.processUDPReplycCs|j|}x|t||kr|jdkrR|j|jtj}|dkrFtd|jj||j|t|}|s|tdt||f||7}q W|S)NrrUz incomplete reply - %d of %d read)readr3r time_startrYrrQ settimeout)rfcountresZrembufr r r _readalls    zDnsRequest._readallc Cs|jdkr|jj|jn |jjd|jjd}z(|j|d}tj|}|j|||_Wd|jXt j |_ |j |j d<|j S)Nrrbr/r!)rrQramakefilerfrZ unpack16bitrWcloserYrZr[rFr\)rrbheaderrcr r r processTCPReplys        zDnsRequest.processTCPReplycCs|j|jd|jd<|js*tj|j}nn|jdkrBtj|j}nV|jdkrZtj|j}n>|jdkrrtj |j}n&|jdkrtj |j}nt d|jtj ||j}|j|_|S)NielapseddefaultZbinarytextZintegerzUnknown resulttype: ) rZr`rFrHrZ MunpackerrWZMunpackerDefaultZMunpackerBinaryZ MunpackerTextZMunpackerInteger SyntaxErrorZ DnsResult)rur#r r r r\s    zDnsRequest.processReplycCs`xZy"tjdd}|jjd|fPWqtjk rV}z|jtjkrFWYdd}~XqXqWdS)zN)randomrandintrQZbindrPerrorerrnoZ EADDRINUSE)rZ source_portmsgr r r getSources  zDnsRequest.getSourcecCs |j|jj|j|jfdS)N)rvrQconnectr[r)rr r r connszDnsRequest.connc Os|j|||jd}|jd|_tjdd|_|jd|_|jd}|jd}|jd}d |jkrr|jd |_nd |_t|jd t kst|jd t kryt t t |jd j }Wqtk rtd YqXn |jd }d |jkrt|jtd|jd }|t jkr*|dkr*tdd}tj} | j|jd|dd|ddddddd | j||tj| j|_y$|dkr|j|n |j|Wn.tjk r} zt| WYdd} ~ XnX|jrdS|j SdS)aW Request function for the DnsRequest class. In addition to standard DNS args, the special pydns arg 'resulttype' can optionally be passed. Valid resulttypes are 'default', 'text', 'decimal', and 'binary'. Defaults are configured to be compatible with pydns: AAAA: decimal Others: text rrrirrrr!rHrmrzunknown query typerIznothing to lookuptcpz'Query type AXFR, protocol forced to TCPrrN)!rErFrrqrrrGrrHrJrKr)getattrrupperAttributeErrorr printAXFRrMpacker addHeader addQuestionrINgetbufrequestsendUDPRequestsendTCPRequestrPrsrrDresponse) rrIrFrrrr!rqnamemreasonr r r qrysN        $        zDnsRequest.qryc Os|j||y"|jdr,tdj|jdWn YnX|jd}|jd|_tjdd|_|jd|_|jd}|jd }|jd }t |jd t kst |jd t kryt t t |jd j}Wqtk rtd YqXn |jd }d |jkrt|jtd|jd }|t jkr>|dkr>tdd}tj} | j|jd|dd|ddddddd | j||tj| j|_y$|dkr|j|n |j|Wn.tjk r} zt| WYdd} ~ XnX|jrdS|j SdS)z needs a refactoring rHzERestulttype {0} set with DNS.req, use DNS.qry to specify result type.rrrirrrr!rzunknown query typerIznothing to lookupryz'Query type AXFR, protocol forced to TCPrrN)!rErFr formatrrqrrrGrrJrKr)rzrr{r|r}r~rrrrrrrrrrrPrsrrDr) rrIrFrrrr!rrrrr r r reqsR        $        zDnsRequest.reqcCs^d}d|_x8|D].|_y|jjdrNttdrJtjrJ|jtjtjq^wn|jtj tjzft j |_ |j |j s|jj|j|j}x,|jd|jks|jd|jkr|j}qW||_Wd|j s|jjXWn^tjk r }z|p|}wWYdd}~Xn0tk r8}z|p$|}wWYdd}~XnX|jrPqW|j rZ|rZ|dS)z refactor meN:has_ipv6idr)rr[rchasattrrPrrTAF_INET6Z SOCK_DGRAMAF_INETrYr`rxrDrQsendrr^rjrGrXrrirsr)rr!first_socket_errorr#r+tr r r rRs>     zDnsRequest.sendUDPRequestcCsVd}d|_x0|D]&|_y|jjdrNttdrJtjrJ|jtjtjq^wn|jtj tjzdt j |_ |j t jt|j|j}|jjd|jj||j}|jd|jkr||_PWd|jjXWn^tjk r}z|p|}wWYdd}~Xn0tk r0}z|p|}wWYdd}~XnX|jrPqW|j rR|rR|dS)z& do the work of sending a TCP request Nrrrr)rr[rcrrPrrTrZ SOCK_STREAMrrYr`rxrZ pack16bitr3rrQZ setblockingZsendallrkrjrGrirsr)rr!rrer#r+rr r r rs<     zDnsRequest.sendTCPRequestN)rr r __doc__rrErTr^rfrkr\rvrxrrrrr r r r rBas  % ;4-rBc@sHeZdZdZddZddZddZdd Zd d Zd d Z ddZ dS)DnsAsyncRequestz> an asynchronous request object. out of date, probably broken cOs@tj|f||d|kr.|dr.|d|_n|j|_d|_dS)Ndoner)rBrrC showResultrD)rrIrFr r r rs  zDnsAsyncRequest.__init__cCsH|j|j|j|jftj|_d|jkrD|jdrDtjj |dS)Nstart) rvrwr[rrYr`rFasyncore dispatcherZgo)rr r r rxs  zDnsAsyncRequest.conncCs"|j||tjj|||_dS)N)Z create_socketrrrrQ)rrRrSr r r rTs  zDnsAsyncRequest.socketInitcCs.|jddkr*|j|_|jr*|j|fdS)Nrr)rFr^rrC)rr r r handle_reads zDnsAsyncRequest.handle_readcCs|j|jdS)N)rr)rr r r handle_connectszDnsAsyncRequest.handle_connectcCsdS)Nr )rr r r handle_writeszDnsAsyncRequest.handle_writecGs|jjdS)N)rZshow)rrQr r r rszDnsAsyncRequest.showResultN) rr r rrrxrTrrrrr r r r rs rcCsddl}ddl}|jdd}|jd}g}d}xn|j}|s>P|j}t|dks`|dtjkrfd}q0|j |}|r0|dkrg}|j ||j |j dq0W|j x|D]}t dj|qWdS)zMRetrieves the current Mac OS X resolver settings using the scutil(8) command.rNz/usr/sbin/scutil --dnsr#z$^\s+nameserver[]0-9[]*\s*\:\s*(\S+)$rr!)osrepopencompilereadlinerstripr3stringZ whitespacematchr5grouprir4extend)rrZscutilZres_reZsetsZ currentsetlrr r r r?s,     r?)r")"rrPrrLrYrVr'rtr>rrrrrqr Exceptionrr rrrrrZQUERYAr4r,r%r@rArBZdispatcher_with_sendrr?r r r r  s80      K!