NetworkManager in "shared to other computers"-mode, dnsmasq and name resolving



Hello

nm uses dnsmasq as dhcp and dns server for attached clients, handled
via nm-dnsmasq-manager[1].
it uses hard coded parameters which proved to be problematic in the
past (i stumbled upon the stand alone dnsmasq vs. nm-dnsmasq conflict
before).

my problem/use case is a lan, where i want to use hostnames instead of
ips when sshing etc. The lan has one uplink which is shared via
nm on one pc (actually different hosts, wherever the 3g stick is
attached).
this works great for resolving the _client_ names on the _client_
computers. there are two problems with the server:

1. the hostname of the server can not be resolved on the clients,
because the dnsmasq instance does not provides it.

one workaround could be to use a dispatch script that adds (prepends)
the ip of the ethernet interface (10.42.43.1) to /etc/hosts. i hacked
together such a script in python, see attachment (It was more like a
little scripting exercise...).
The problem is that dnsmasq-manager calls dnsmasq with "--no-hosts",
which prohibits dnsmasq to read the hosts file.

to fix that probably dnsmasq-manager just needs to add the local
hostname to the dnsmasq's database (e.g with
--interface-name=<hostname>,<shared interface>). another possibility
would be to use the -H parameter. it tells dnsmasq to use another hosts
file, which would e.g. allow a nm-specific host file with the gateway's
hostname<->ip only.

2. also on the server it is not possible to resolve any of the
client names, because nm does not add the dnsmasq ip to resolv.conf
(it's not that easy, because dnsmasq also reads that file to get the
upstream dns servers). this could also be useful, because it could
provide caching for the gateway.

are there any plans to implement the caching? what should i do till
it lands in my distribution (which is btw ubuntu 10.04 and 10.10 atm, so
i am using 0.8.0 and 0.8.1)?


ps: on the whole i must say that nm gets much better with time, thanks!
but the dnsmasq situation is still bad. the hard coded parameters and
ignoring a correct and working configuration file for dnsmasq restricts
the advanced user a lot (e.g. it is not possible to run a pxe
server when sharing is enabled).
instead of that wacky random file name (around line 280) it would be
easy (and nonetheless safe for normal users) to use a fixed config file
name other than "/etc/dnsmasq.conf". advanced users could then extend
the hard coded configuration.

1:
http://cgit.freedesktop.org/NetworkManager/NetworkManager/tree/src/dnsmasq-manager
command line arguments are created starting from line 269 in
nm-dnsmasq-manager.c
-- 
Kind regards/Mit freundlichen Grüßen, Stefan Tauner
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import sys, socket, re
from subprocess import PIPE
from tempfile import mkstemp
from shutil import move
from os import remove, close

gatewayIp = "10.42.43.1"
hostname = socket.gethostname()
pattern = re.compile(".*"+gatewayIp+"[\s.*|.*\s]"+hostname+"[\s.*|]")

def delete_host():
	replaceLine('/etc/hosts', pattern, "")
	return

#  name: replaceLine
#  Replaces all lines of file 'file' matching 'pattern' with 'subst'
#  @param file: String filename
#  @param pattern: a compiled re that matches lines to be replaced
#  @param subst: the string that should be written instead
#  @returns: if there were changes
def replaceLine(file, pattern, subst):
	fh, new_path = mkstemp()
	new_file = open(new_path,'w')
	old_file = open(file, 'r')
	lines = old_file.readlines()
	changed = False
	for line in lines:
		if pattern.match(line):
			changed = True
			# "" means delete matching lines
			if subst != "":
				new_file.write(subst)
		else:
			new_file.write(line)
	new_file.close()
	close(fh)
	old_file.close()
	if changed:
		move(new_path, file)
		return True
	else:
		remove(new_path)
		return False

def replace_host():
	newline = gatewayIp+"\t"+hostname+"\t# Added by NetworkManager (via a dispatcher script)\n"
	etchosts = '/etc/hosts'
	if not replaceLine(etchosts, pattern, newline):
		fh, new_path = mkstemp()
		new_file = open(new_path,'w')
		old_file = open(etchosts, 'r')
		new_file.write(newline)
		new_file.write(old_file.read())
		#close temp file
		new_file.close()
		close(fh)
		old_file.close()
		move(new_path, etchosts)
	return

def main():
	oldstdout = sys.stdout                                     
	if len(sys.argv) < 3:
		print "need at least 2 arguments!"
		return 1
	interface = sys.argv[1]
	state = sys.argv[2]
	if interface == "eth0":
		if state == "up" and os.getenv('IP4_ADDRESS_0') == "10.42.43.1/24 0.0.0.0":
			replace_host()
		elif state == "down":
			delete_host()

	return 0

if __name__ == '__main__':
	main()


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]