Merge lp:~ptman/hipl/nonetwork into lp:hipl

Proposed by Paul Tötterman
Status: Merged
Merged at revision: 6413
Proposed branch: lp:~ptman/hipl/nonetwork
Merge into: lp:hipl
Diff against target: 576 lines (+237/-228)
5 files modified
debian/hipl-dnsproxy.config (+3/-3)
debian/hipl-dnsproxy.postinst (+0/-14)
tools/hipdnsproxy/dnsproxy.py (+223/-204)
tools/hipdnsproxy/resolvconf.py (+2/-3)
tools/hipdnsproxy/resolvconf_test.py (+9/-4)
To merge this branch: bzr merge lp:~ptman/hipl/nonetwork
Reviewer Review Type Date Requested Status
Miika Komu Approve
Review via email: mp+165785@code.launchpad.net

Description of the change

Fixes problems with hipdnsproxy when network is not present or changes.

Please comment before Friday 31st.

To post a comment you must log in.
Revision history for this message
Miika Komu (miika-iki) wrote :

As described in related the bug report, I have tested the branch. I suggest merging it on Friday unless there are other comments.

Writing of the main loop should be a separate task for somebody. The DNS proxy has been defunctional for far too long on Ubuntu systems, so this should be merged asap.

Thanks for the great work!

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'debian/hipl-dnsproxy.config'
2--- debian/hipl-dnsproxy.config 2013-03-06 14:07:36 +0000
3+++ debian/hipl-dnsproxy.config 2013-05-26 15:39:25 +0000
4@@ -2,7 +2,7 @@
5
6 . /usr/share/debconf/confmodule
7
8-if pidof dnsmasq; then
9- db_input high hipl-dnsproxy/dnsmasq
10- db_go
11+if pidof dnsmasq > /dev/null; then
12+ db_input high hipl-dnsproxy/dnsmasq || true
13+ db_go || true
14 fi
15
16=== modified file 'debian/hipl-dnsproxy.postinst'
17--- debian/hipl-dnsproxy.postinst 2013-02-22 15:16:12 +0000
18+++ debian/hipl-dnsproxy.postinst 2013-05-26 15:39:25 +0000
19@@ -8,18 +8,4 @@
20 # Default run level (20) is problematic with hipl-dnsproxy in Ubuntu Lucid.
21 # Note: $bind did not entirely solve the problem (see lp:845677).
22 update-rc.d hipl-dnsproxy defaults 40 60 >/dev/null
23-
24- if [ "$1" = "configure" ] || [ "$1" = "abort-upgrade" ]; then
25- if [ -e /var/run/hipdnsproxy.pid ]; then
26- ACTION=restart
27- else
28- ACTION=start
29- fi
30-
31- if [ -x /usr/sbin/invoke-rc.d ] ; then
32- invoke-rc.d hipl-dnsproxy $ACTION || true
33- else
34- /etc/init.d/hipl-dnsproxy $ACTION || true
35- fi
36- fi
37 fi
38
39=== modified file 'tools/hipdnsproxy/dnsproxy.py'
40--- tools/hipdnsproxy/dnsproxy.py 2013-02-22 15:16:12 +0000
41+++ tools/hipdnsproxy/dnsproxy.py 2013-05-26 15:39:25 +0000
42@@ -310,7 +310,8 @@
43 logging.error('Error opening pid file: %s', ioe)
44 sys.exit(1)
45 ifile.readline()
46- myid = ifile.readline().rstrip()
47+ global MYID
48+ MYID = ifile.readline().rstrip()
49 ifile.close()
50 self.resolvconf.restore()
51
52@@ -458,9 +459,13 @@
53
54 self.parameter_defaults()
55
56+ if self.server_ip is None:
57+ logging.critical('No upstream DNS server, exiting...')
58+ return
59+
60 # Default virtual interface and address for dnsproxy to
61 # avoid problems with other dns forwarders (e.g. dnsmasq)
62- os.system("ifconfig lo:53 %s" % (self.bind_ip,))
63+ os.system('ifconfig lo:53 %s' % (self.bind_ip,))
64
65 servsock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
66 try:
67@@ -487,224 +492,238 @@
68
69 self.write_local_hits_to_hosts()
70
71+ query_id = 1
72+
73 util.init_wantdown()
74- util.init_wantdown_int() # Keyboard interrupts
75-
76- if self.server_ip.find(':') == -1:
77- server_family = socket.AF_INET
78- else:
79- server_family = socket.AF_INET6
80- clisock = socket.socket(server_family, socket.SOCK_DGRAM)
81- clisock.settimeout(self.dns_timeout)
82- try:
83- clisock.connect((self.server_ip, self.server_port))
84- connected = True
85- except socket.error:
86- connected = False
87-
88- query_id = 1
89+ util.init_wantdown_int() # Keyboard interrupts
90
91 while not util.wantdown():
92+ logging.info('Connecting to upstream DNS server...')
93+ if ':' not in self.server_ip:
94+ server_family = socket.AF_INET
95+ else:
96+ server_family = socket.AF_INET6
97+ clisock = socket.socket(server_family, socket.SOCK_DGRAM)
98+ clisock.settimeout(self.dns_timeout)
99 try:
100- self.hosts_recheck()
101-
102- if connected:
103- rlist, _, _ = select.select([servsock, clisock], [], [],
104- 5.0)
105- else:
106- rlist, _, _ = select.select([servsock], [], [], 5.0)
107- self.clean_queries()
108- if servsock in rlist: # Incoming DNS request
109- inbuf, from_a = servsock.recvfrom(2048)
110-
111- packet = DeSerialize(inbuf).get_dict()
112- qtype = packet['questions'][0][1]
113-
114- sent_answer = False
115-
116- if qtype in (1, 28, 12):
117- if self.hip_cache_lookup(packet):
118+ clisock.connect((self.server_ip, self.server_port))
119+ connected = True
120+ logging.debug('... connected!')
121+ except socket.error:
122+ logging.error('Connecting to upstream DNS server failed!')
123+ time.sleep(3)
124+ connected = False
125+
126+ while connected and (not util.wantdown()):
127+ try:
128+ self.hosts_recheck()
129+
130+ if connected:
131+ rlist, _, _ = select.select([servsock, clisock], [], [],
132+ 5.0)
133+ else:
134+ rlist, _, _ = select.select([servsock], [], [], 5.0)
135+ self.clean_queries()
136+ if servsock in rlist: # Incoming DNS request
137+ inbuf, from_a = servsock.recvfrom(2048)
138+
139+ packet = DeSerialize(inbuf).get_dict()
140+ qtype = packet['questions'][0][1]
141+
142+ sent_answer = False
143+
144+ if qtype in (1, 28, 12):
145+ if self.hip_cache_lookup(packet):
146+ try:
147+ outbuf = Serialize(packet).get_packet()
148+ servsock.sendto(outbuf, from_a)
149+ sent_answer = True
150+ except socket.error:
151+ logging.exception('Exception:')
152+ elif (self.prefix and
153+ packet['questions'][0][0].startswith(
154+ self.prefix)):
155+ # Query with HIP prefix for unsupported RR type.
156+ # Send empty response.
157+ packet['qr'] = 1
158 try:
159 outbuf = Serialize(packet).get_packet()
160 servsock.sendto(outbuf, from_a)
161 sent_answer = True
162 except socket.error:
163 logging.exception('Exception:')
164- elif (self.prefix and
165- packet['questions'][0][0].startswith(self.prefix)):
166- # Query with HIP prefix for unsupported RR type.
167- # Send empty response.
168- packet['qr'] = 1
169- try:
170- outbuf = Serialize(packet).get_packet()
171- servsock.sendto(outbuf, from_a)
172- sent_answer = True
173- except socket.error:
174- logging.exception('Exception:')
175-
176- if connected and not sent_answer:
177- logging.info('Query type %d for %s from %s',
178- qtype, packet['questions'][0][0],
179- (self.server_ip, self.server_port))
180-
181- query = (packet, from_a[0], from_a[1], qtype)
182- # FIXME: Should randomize for security
183- query_id = (query_id % 65535) + 1
184- pckt = copy.copy(packet)
185- pckt['id'] = query_id
186- if ((qtype == 28 or
187- (qtype == 1 and not self.disable_lsi)) and not
188- is_reverse_hit_query(packet['questions'][0][0])):
189-
190- if not self.prefix:
191- pckt['questions'][0][1] = 55
192- if (self.prefix and
193- pckt['questions'][0][0].startswith(
194- self.prefix)):
195- pckt['questions'][0][0] = pckt[
196- 'questions'][0][0][len(self.prefix):]
197- pckt['questions'][0][1] = 55
198-
199- if qtype == 12 and not self.disable_lsi:
200+
201+ if connected and not sent_answer:
202+ logging.info('Query type %d for %s from %s',
203+ qtype, packet['questions'][0][0],
204+ (self.server_ip, self.server_port))
205+
206+ query = (packet, from_a[0], from_a[1], qtype)
207+ # FIXME: Should randomize for security
208+ query_id = (query_id % 65535) + 1
209+ pckt = copy.copy(packet)
210+ pckt['id'] = query_id
211+ if ((qtype == 28 or
212+ (qtype == 1 and not self.disable_lsi)) and not
213+ is_reverse_hit_query(
214+ packet['questions'][0][0])):
215+
216+ if not self.prefix:
217+ pckt['questions'][0][1] = 55
218+ if (self.prefix and
219+ pckt['questions'][0][0].startswith(
220+ self.prefix)):
221+ pckt['questions'][0][0] = pckt[
222+ 'questions'][0][0][len(self.prefix):]
223+ pckt['questions'][0][1] = 55
224+
225+ if qtype == 12 and not self.disable_lsi:
226+ qname = packet['questions'][0][0]
227+ addr_str = hosts.ptr_to_addr(qname)
228+ if (addr_str is not None and
229+ hosts.valid_lsi(addr_str)):
230+ query = (packet, from_a[0], from_a[1],
231+ qname)
232+ hit_str = lsi_to_hit(addr_str)
233+ if hit_str is not None:
234+ pckt['questions'][0][0] = \
235+ hosts.addr_to_ptr(hit_str)
236+
237+ outbuf = Serialize(pckt).get_packet()
238+ clisock.sendto(outbuf, (self.server_ip,
239+ self.server_port))
240+
241+ self.add_query(self.server_ip, self.server_port,
242+ query_id, query)
243+
244+ if connected and clisock in rlist: # Incoming DNS reply
245+ inbuf, from_a = clisock.recvfrom(2048)
246+ logging.info('Packet from DNS server %d bytes from %s',
247+ len(inbuf), from_a)
248+ packet = DeSerialize(inbuf).get_dict()
249+
250+ # Find original query
251+ query_id_o = packet['id']
252+ query_o = self.find_query(from_a[0], from_a[1],
253+ query_id_o)
254+ if query_o:
255 qname = packet['questions'][0][0]
256- addr_str = hosts.ptr_to_addr(qname)
257- if (addr_str is not None and
258- hosts.valid_lsi(addr_str)):
259- query = (packet, from_a[0], from_a[1], qname)
260- hit_str = lsi_to_hit(addr_str)
261- if hit_str is not None:
262- pckt['questions'][0][0] = \
263- hosts.addr_to_ptr(hit_str)
264-
265- outbuf = Serialize(pckt).get_packet()
266- clisock.sendto(outbuf, (self.server_ip,
267- self.server_port))
268-
269- self.add_query(self.server_ip, self.server_port,
270- query_id, query)
271-
272- if connected and clisock in rlist: # Incoming DNS reply
273- inbuf, from_a = clisock.recvfrom(2048)
274- logging.info('Packet from DNS server %d bytes from %s',
275- len(inbuf), from_a)
276- packet = DeSerialize(inbuf).get_dict()
277-
278- # Find original query
279- query_id_o = packet['id']
280- query_o = self.find_query(from_a[0], from_a[1], query_id_o)
281- if query_o:
282- qname = packet['questions'][0][0]
283- qtype = packet['questions'][0][1]
284- send_reply = True
285- query_again = False
286- hit_found = False
287- packet_o = query_o[0]
288- # Replace with the original query id
289- packet['id'] = packet_o['id']
290-
291- if qtype == 55 and query_o[3] in (1, 28):
292- # Restore qtype
293- packet['questions'][0][1] = query_o[3]
294- self.hip_lookup(packet)
295- if packet['ancount'] > 0:
296- hit_found = True
297- if (not self.prefix or
298- (hit_found and not (self.getaaaa(qname) or
299- self.geta(qname)))):
300- query_again = True
301- send_reply = False
302- elif self.prefix:
303- hit_found = True
304- packet['questions'][0][0] = (
305- self.prefix + packet['questions'][0][0])
306- for answer in packet['answers']:
307- answer[0] = self.prefix + answer[0]
308-
309- elif qtype in (1, 28):
310- hit = self.getaaaa_hit(qname)
311- ip6 = self.getaaaa(qname)
312- ip4 = self.geta(qname)
313- for answer in packet['answers']:
314- if answer[1] in (1, 28):
315- self.cache_name(qname, answer[4],
316- answer[3])
317- if hit is not None:
318- for answer in packet['answers']:
319- if (answer[1] == 1 or
320- (answer[1] == 28 and not
321- hosts.valid_hit(answer[4]))):
322- add_hit_ip_map(hit[0], answer[4])
323- # Reply with HIT/LSI once it's been mapped to
324- # an IP
325- if ip6 is None and ip4 is None:
326- if (packet_o['ancount'] == 0 and
327- not self.prefix):
328- # No LSI available. Return IPv4
329- tmp = packet['answers']
330- packet = packet_o
331- packet['answers'] = tmp
332- packet['ancount'] = len(
333- packet['answers'])
334- else:
335- packet = packet_o
336- if self.prefix:
337- packet['questions'][0][0] = \
338+ qtype = packet['questions'][0][1]
339+ send_reply = True
340+ query_again = False
341+ hit_found = False
342+ packet_o = query_o[0]
343+ # Replace with the original query id
344+ packet['id'] = packet_o['id']
345+
346+ if qtype == 55 and query_o[3] in (1, 28):
347+ # Restore qtype
348+ packet['questions'][0][1] = query_o[3]
349+ self.hip_lookup(packet)
350+ if packet['ancount'] > 0:
351+ hit_found = True
352+ if (not self.prefix or
353+ (hit_found and not (self.getaaaa(qname) or
354+ self.geta(qname)))):
355+ query_again = True
356+ send_reply = False
357+ elif self.prefix:
358+ hit_found = True
359+ packet['questions'][0][0] = (
360+ self.prefix + packet['questions'][0][0])
361+ for answer in packet['answers']:
362+ answer[0] = self.prefix + answer[0]
363+
364+ elif qtype in (1, 28):
365+ hit = self.getaaaa_hit(qname)
366+ ip6 = self.getaaaa(qname)
367+ ip4 = self.geta(qname)
368+ for answer in packet['answers']:
369+ if answer[1] in (1, 28):
370+ self.cache_name(qname, answer[4],
371+ answer[3])
372+ if hit is not None:
373+ for answer in packet['answers']:
374+ if (answer[1] == 1 or
375+ (answer[1] == 28 and not
376+ hosts.valid_hit(answer[4]))):
377+ add_hit_ip_map(hit[0], answer[4])
378+ # Reply with HIT/LSI once it's been mapped
379+ # to an IP
380+ if ip6 is None and ip4 is None:
381+ if (packet_o['ancount'] == 0 and
382+ not self.prefix):
383+ # No LSI available. Return IPv4
384+ tmp = packet['answers']
385+ packet = packet_o
386+ packet['answers'] = tmp
387+ packet['ancount'] = len(
388+ packet['answers'])
389+ else:
390+ packet = packet_o
391+ if self.prefix:
392+ packet['questions'][0][0] = \
393 (self.prefix +
394 packet['questions'][0][0])
395- for answer in packet['answers']:
396- answer[0] = (self.prefix +
397- answer[0])
398- else:
399+ for answer in packet['answers']:
400+ answer[0] = (self.prefix +
401+ answer[0])
402+ else:
403+ send_reply = False
404+ elif query_o[3] == 0:
405+ # Prefix is in use
406+ # IP was queried for cache only
407 send_reply = False
408- elif query_o[3] == 0:
409- # Prefix is in use
410- # IP was queried for cache only
411- send_reply = False
412-
413- elif qtype == 12 and isinstance(query_o[3], str):
414- packet['questions'][0][0] = query_o[3]
415- for answer in packet['answers']:
416- answer[0] = query_o[3]
417-
418- if query_again:
419- if hit_found:
420- qtypes = [28, 1]
421- pckt = copy.deepcopy(packet)
422- else:
423- qtypes = [query_o[3]]
424- pckt = copy.copy(packet)
425- pckt['qr'] = 0
426- pckt['answers'] = []
427- pckt['ancount'] = 0
428- pckt['nslist'] = []
429- pckt['nscount'] = 0
430- pckt['additional'] = []
431- pckt['arcount'] = 0
432- for qtype in qtypes:
433- if self.prefix:
434- query = (packet, query_o[1], query_o[2], 0)
435+
436+ elif qtype == 12 and isinstance(query_o[3], str):
437+ packet['questions'][0][0] = query_o[3]
438+ for answer in packet['answers']:
439+ answer[0] = query_o[3]
440+
441+ if query_again:
442+ if hit_found:
443+ qtypes = [28, 1]
444+ pckt = copy.deepcopy(packet)
445 else:
446- query = (packet, query_o[1], query_o[2],
447- qtype)
448- query_id = (query_id % 65535) + 1
449- pckt['id'] = query_id
450- pckt['questions'][0][1] = qtype
451- outbuf = Serialize(pckt).get_packet()
452- clisock.sendto(outbuf, (self.server_ip,
453- self.server_port))
454- self.add_query(self.server_ip,
455- self.server_port,
456- query_id, query)
457- packet['questions'][0][1] = query_o[3]
458+ qtypes = [query_o[3]]
459+ pckt = copy.copy(packet)
460+ pckt['qr'] = 0
461+ pckt['answers'] = []
462+ pckt['ancount'] = 0
463+ pckt['nslist'] = []
464+ pckt['nscount'] = 0
465+ pckt['additional'] = []
466+ pckt['arcount'] = 0
467+ for qtype in qtypes:
468+ if self.prefix:
469+ query = (packet, query_o[1], query_o[2],
470+ 0)
471+ else:
472+ query = (packet, query_o[1], query_o[2],
473+ qtype)
474+ query_id = (query_id % 65535) + 1
475+ pckt['id'] = query_id
476+ pckt['questions'][0][1] = qtype
477+ outbuf = Serialize(pckt).get_packet()
478+ clisock.sendto(outbuf, (self.server_ip,
479+ self.server_port))
480+ self.add_query(self.server_ip,
481+ self.server_port,
482+ query_id, query)
483+ packet['questions'][0][1] = query_o[3]
484
485- if send_reply:
486- outbuf = Serialize(packet).get_packet()
487- servsock.sendto(outbuf, (query_o[1], query_o[2]))
488- except (select.error, OSError), exc:
489- if exc[0] == errno.EINTR:
490- pass
491- else:
492- logging.exception('Exception:')
493+ if send_reply:
494+ outbuf = Serialize(packet).get_packet()
495+ servsock.sendto(outbuf, (query_o[1],
496+ query_o[2]))
497+ except (select.error, OSError), exc:
498+ if exc[0] == errno.EINTR:
499+ pass
500+ else:
501+ logging.exception('Exception:')
502+ except socket.error, exc:
503+ logging.info('Connection to upstream DNS server lost')
504+ connected = False
505
506 logging.info('Wants down')
507 self.resolvconf.restore()
508
509=== modified file 'tools/hipdnsproxy/resolvconf.py'
510--- tools/hipdnsproxy/resolvconf.py 2013-03-24 10:07:13 +0000
511+++ tools/hipdnsproxy/resolvconf.py 2013-05-26 15:39:25 +0000
512@@ -93,7 +93,7 @@
513 self.mtime = None
514 self.config = None
515
516- if isinstance(ResolvConf.FRAGMENT_DIR, list):
517+ if self.using_resolvconf and isinstance(ResolvConf.FRAGMENT_DIR, list):
518 ResolvConf.FRAGMENT_DIR = filter(os.path.exists,
519 ResolvConf.FRAGMENT_DIR)[0]
520
521@@ -242,8 +242,7 @@
522 ResolvConf.DEFAULT_BIND_ADDR]
523 if nameservers:
524 return nameservers[0]
525- else:
526- return '8.8.8.8' # Google Public DNS, fallback
527+ return '8.8.8.8' # Google Public DNS, fallback
528
529 @nameserver.setter
530 def nameserver(self, nameserver):
531
532=== modified file 'tools/hipdnsproxy/resolvconf_test.py'
533--- tools/hipdnsproxy/resolvconf_test.py 2012-12-31 14:54:20 +0000
534+++ tools/hipdnsproxy/resolvconf_test.py 2013-05-26 15:39:25 +0000
535@@ -33,8 +33,8 @@
536 # resolv.conf
537 domain example.com
538 search example.com
539+nameserver 8.8.4.4
540 nameserver 8.8.8.8
541-nameserver 8.8.4.4
542 '''
543
544 INVALID_RESOLV_CONF = '''
545@@ -54,7 +54,7 @@
546 conf = rc.config
547 self.assertEqual(conf['domain'], 'example.com')
548 self.assertEqual(conf['search'], ['example.com'])
549- self.assertEqual(conf['nameserver'], ['8.8.8.8', '8.8.4.4'])
550+ self.assertEqual(conf['nameserver'], ['8.8.4.4', '8.8.8.8'])
551
552 def dont_test_parse_invalid_file(self):
553 rc = resolvconf.ResolvConf()
554@@ -76,15 +76,20 @@
555 rc.resolvconf = True
556 rc.config = {'domain': 'example.com',
557 'search': ['example.com', 'example.net'],
558- 'nameserver': ['8.8.8.8', '8.8.4.4']}
559+ 'nameserver': ['8.8.4.4', '8.8.8.8']}
560 rc.resolvconf_add = lambda x: None
561 ofile = StringIO.StringIO()
562 rc.write_file(ofile)
563 out = ofile.getvalue()
564 self.assertTrue('domain example.com' in out)
565 self.assertTrue('search example.com example.net' in out)
566+ self.assertTrue('nameserver 8.8.4.4' in out)
567 self.assertTrue('nameserver 8.8.8.8' in out)
568- self.assertTrue('nameserver 8.8.4.4' in out)
569+
570+ def test_prop_nameserver_noconfig(self):
571+ rc = resolvconf.ResolvConf()
572+ rc.parse_file(StringIO.StringIO(''))
573+ self.assertEqual(rc.nameserver, '8.8.8.8')
574
575
576 if __name__ == '__main__':

Subscribers

People subscribed via source and target branches