~ubuntu-branches/ubuntu/trusty/py3dns/trusty

« back to all changes in this revision

Viewing changes to DNS/Base.py

  • Committer: Bazaar Package Importer
  • Author(s): Scott Kitterman
  • Date: 2011-08-12 15:40:23 UTC
  • mfrom: (1.1.2 sid)
  • Revision ID: james.westby@ubuntu.com-20110812154023-3bpyt01o3io6dxbo
Tags: 3.0.1-1
* New upstream release
  - Update debian/copyright
* Protect for loops in debian/rules with set -e
* Bump standards version to 3.9.2 without further change

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
"""
2
 
$Id: Base.py,v 1.12.2.10 2008/08/01 03:58:03 customdesigned Exp $
 
2
$Id: Base.py,v 1.12.2.11.2.4 2011/08/04 22:53:09 customdesigned Exp $
3
3
 
4
4
This file is part of the pydns project.
5
5
Homepage: http://pydns.sourceforge.net
6
6
 
7
 
This code is covered by the standard Python License.
 
7
This code is covered by the standard Python License. See LICENSE for details.
8
8
 
9
9
    Base functionality. Request and Response classes, that sort of thing.
10
10
"""
61
61
    if sys.platform in ('win32', 'nt'):
62
62
        from . import win32dns
63
63
        defaults['server']=win32dns.RegistryResolve()
 
64
    if sys.platform == 'darwin':
 
65
        ParseOSXSysConfig()
64
66
    else:
65
67
        return ParseResolvConf()
66
68
 
89
91
            if len(name) == 1:
90
92
                if name[0]:
91
93
                    args['name']=name[0]
92
 
        if defaults['server_rotate'] and type(defaults['server']) == types.ListType:
 
94
        if defaults['server_rotate'] and \
 
95
                type(defaults['server']) == types.ListType:
93
96
            defaults['server'] = defaults['server'][1:]+defaults['server'][:1]
94
97
        for i in list(defaults.keys()):
95
98
            if i not in args:
114
117
        self.args['server']=self.ns
115
118
        return self.processReply()
116
119
 
 
120
    def _readall(self,f,count):
 
121
      res = f.read(count)
 
122
      while len(res) < count:
 
123
        if self.timeout > 0:
 
124
            # should we restart timeout everytime we get a dribble of data?
 
125
            rem = self.time_start + self.timeout - time.time()
 
126
            if rem <= 0: raise DNSError('Timeout')
 
127
            self.s.settimeout(rem)
 
128
        buf = f.read(count - len(res))
 
129
        if not buf:
 
130
          raise DNSError('incomplete reply - %d of %d read' % (len(res),count))
 
131
        res += buf
 
132
      return res
 
133
 
117
134
    def processTCPReply(self):
118
135
        if self.timeout > 0:
119
 
            r,w,e = select.select([self.s],[],[],self.timeout)
120
 
            if not len(r):
121
 
                raise DNSError('Timeout')
122
 
        f = self.s.makefile('r')
123
 
        header = f.read(2)
124
 
        if len(header) < 2:
125
 
            raise DNSError('EOF')
126
 
        count = Lib.unpack16bit(header)
127
 
        self.reply = f.read(count)
128
 
        if len(self.reply) != count:
129
 
            # FIXME: Since we are non-blocking, it could just be a large reply
130
 
            # that we need to loop and wait for.
131
 
            raise DNSError('incomplete reply')
 
136
            self.s.settimeout(self.timeout)
 
137
        else:
 
138
            self.s.settimeout(None)
 
139
        f = self.s.makefile('rb')
 
140
        try:
 
141
            header = self._readall(f,2)
 
142
            count = Lib.unpack16bit(header)
 
143
            self.reply = self._readall(f,count)
 
144
        finally:
 
145
            f.close()
132
146
        self.time_finish=time.time()
133
147
        self.args['server']=self.ns
134
148
        return self.processReply()
197
211
            print((self.args))
198
212
            raise DNSError('nothing to lookup')
199
213
        qname = self.args['name']
200
 
        if qtype == Type.AXFR:
 
214
        if qtype == Type.AXFR and protocol != 'tcp':
201
215
            print('Query type AXFR, protocol forced to TCP')
202
216
            protocol = 'tcp'
203
217
        #print('QTYPE %d(%s)' % (qtype, Type.typestr(qtype)))
278
292
                    # FIXME: throws WOULDBLOCK if request too large to fit in
279
293
                    # system buffer
280
294
                    self.s.sendall(buf)
281
 
                    self.s.shutdown(socket.SHUT_WR)
 
295
                    # SHUT_WR breaks blocking IO with google DNS (8.8.8.8)
 
296
                    #self.s.shutdown(socket.SHUT_WR)
282
297
                    r=self.processTCPReply()
283
298
                    if r.header['id'] == self.tid:
284
299
                        self.response = r
322
337
    def showResult(self,*s):
323
338
        self.response.show()
324
339
 
 
340
def ParseOSXSysConfig():
 
341
    "Retrieves the current Mac OS X resolver settings using the scutil(8) command."
 
342
    import os, re
 
343
    scutil = os.popen('scutil --dns', 'r')
 
344
    res_re = re.compile('^\s+nameserver[]0-9[]*\s*\:\s*(\S+)$')
 
345
    sets = [ ]
 
346
    currentset = None
 
347
    while True:
 
348
        l = scutil.readline()
 
349
        if not l:
 
350
            break
 
351
        l = l.rstrip()
 
352
        if len(l) < 1 or l[0] not in string.whitespace:
 
353
            currentset = None
 
354
            continue
 
355
        m = res_re.match(l)
 
356
        if m:
 
357
            if currentset is None:
 
358
                currentset = [ ]
 
359
                sets.append(currentset)
 
360
            currentset.append(m.group(1))
 
361
    scutil.close()
 
362
    # Someday: Figure out if we should do something other than simply concatenate the sets.
 
363
    for currentset in sets:
 
364
        defaults['server'].extend(currentset)
 
365
 
325
366
#
326
367
# $Log: Base.py,v $
 
368
# Revision 1.12.2.11.2.4  2011/08/04 22:53:09  customdesigned
 
369
# Add OSX support
 
370
#
 
371
# Revision 1.12.2.11.2.3  2011/05/02 16:04:32  customdesigned
 
372
# Don't complain about AXFR protocol unless actually changing it.
 
373
# Reported by Ewoud Kohl van Wijngaarden.
 
374
#
 
375
# Revision 1.12.2.11.2.2  2011/03/23 01:42:07  customdesigned
 
376
# Changes from 2.3 branch
 
377
#
 
378
# Revision 1.12.2.11.2.1  2011/02/18 19:35:22  customdesigned
 
379
# Python3 updates from Scott Kitterman
 
380
#
327
381
# Revision 1.12.2.10  2008/08/01 03:58:03  customdesigned
328
382
# Don't try to close socket when never opened.
329
383
#