Bug in Kamikaze, dnsmasq init.d script ignoring notinterface directive from /etc/config/dhcp config file

(yes I know it’s a long title, I’m hoping to put enough data in the title to help people find this fix with a google search)

For what it’s worth, I have found a bug in dnsmasq 2.47 on Kamikaze 8.09.1 (r16278). This bug may be on earlier Kamikaze releases as well. I have a correction for the bug.

I’ve beat my head on the wall, so you don’t have too. There may be only 2 or 3 other people in the universe who find this information useful. To you who do, greetings.

The Bug has to do with the DHCP server side of dnsmasq. By default, dnsmasq hands out IP address confirmation information on all interfaces. For 99.999% of the world this is fine, because naturally most people want their computer to get an IP address from the router regardless of how they are hooked to it (i.e. wired or wirless).

I discovered the Bug when I hooked two wrt54gl up with a bridged VPN. (using openvpn)

Just for reference here is my setup.

Office 1

IP range: 192.168.77.0/24

Gateway (and wrt54gl-1): 192.168.77.1

Office 2

IP range: 192.168.78.0/24

Gateway (and wrt54gl-2): 192.168.78.1

We chose to have a “bridged” VPN because we wanted mdns and bonjour services to advertise across both networks when the VPN was up. Rather than requiring one office to route ALL IP traffic over the VPN, we set it up so that only 192.168.78.0 or 192.168.77.0 traffic stayed in the network, and the rest was routed to the gateway local to the office.

The act of bridging via VPN creates a new interface called “tap0″, and naturally dnsmasq wants to have DHCP server services over this interface. Because of this there now was the odd situation of having two competing DHCP servers on the same lan. Some machines in Office 1 were getting 192.168.78.0 addresses and routing ALL their traffic over the VPN bridge, and likewise with Office 2 getting 192.168.77.0 address. Those machines with incorrect IP addresses for their location still worked, but did so very, very slowly.

Our short term solution was to just do Manual IP address assignment. However the problem still presented, and confusion reigned for things like network appliances, iPhones, and the break room PS3 (we gatta have out GTA IV!!)

Anyway, looking at the docs for dnsmasq (http://wiki.openwrt.org/doc/uci/dhcp) there IS an option for “notinterface” which should tell dnsmasq to ignore DHCP queries on listed interfaces, like tap0. But it seems that there is a bug in the init script for dnsmasq which did not pick up this option from the config file.

/etc/config/dhcp from Office 2

config ‘dnsmasq’

option ‘domainneeded’ ‘1′

option ‘boguspriv’ ‘1′

option ‘filterwin2k’ ‘0′

option ‘localise_queries’ ‘1′

option ‘local’ ‘/lan/’

option ‘domain’ ‘lan’

option ‘expandhosts’ ‘1′

option ‘nonegcache’ ‘0′

option ‘authoritative’ ‘1′

option ‘readethers’ ‘1′

option ‘leasefile’ ‘/tmp/dhcp.leases’

option ‘resolvfile’ ‘/tmp/resolv.conf.auto’

list ‘notinterface’     ‘tap0′

config ‘dhcp’ ‘lan’

option ‘interface’ ‘lan’

option ’start’ ‘192.168.78.150′

option ‘limit’ ‘50′

option ‘leasetime’ ‘12h’

list ‘dhcp_option’ ‘6,,8.8.8.8′

According to the docs (http://wiki.openwrt.org/doc/uci/dhcp), “list ‘notinterface’     ‘tap0′” should tell dnsmasq to ignore interface tap0. This is the same as the switch “-I” from the command line. However looking at the init script at /etc/init.d/dnsmasq there was no option to pick up “notinterface” from the /etc/config/dhcp config file. Ergo,  “notinterface” was just ignored during startup.

THE FIX

The solution was to simply add a couple of lines of script to /etc/init.d/dnsmasq to make it pick up the “notinterface” config.

First, backup, backup, back

cp /etc/init.d/dnsmasq /etc/init.d/dnsmasq.hold

Next we are going to edit the init script. Don;t worry it wont bite you (much)

vi /etc/init.d/dnsmasq

Look for 3 lines like this

append_interface() {

append args “-i $1″

}

This the is function call out to add an “interface” to the dnsmasq command on startup based on the /etc/config/dhcp config file. Drop below it and ADD these 3 lines.

append_notinterface() {

append args “-I $1″

}

For educational purposes the only differences in the two block are the function name (append_interface vs append_notinterface) and the command line switch (-i vs -l, that’s a lover case i vs and upper case i). Both blocks are needed for dnsmasq to work.

Once you have the function call setup, you need only add a line to tell the init script to run it. Look several lines down for the following:

config_list_foreach “$cfg” “interface” append_interface

This is the script line to add interfaces based on the first function call above, we need to add a line to ignore interfaces based on the function call we just added. Add a line just below the over line, and add this text:

config_list_foreach “$cfg” “notinterface” append_notinterface

Again like the additional function call above this new additional line simply duplicates the function to add an interface except in this new case we are looking for the phrase “notinterface” to give us a list of interfaces to ignore.

Now save the file.

Type esc then

:wq

Finally you need to add the “notinterface” config directive to the /etc/config/dhcp file

vi /etc/config/dhcp

Anywere in the “config ‘dnsmasq’” area, add this line

list ‘notinterface’     ‘tap0′

You can make the interface anything you want (no DHCP for you crummy WIFI users!!), but ignoring the VPN tap0 interface is most likely what you are after. For security I guess you could also add the WAN interface to the ignore list, but I’m not sure how getting an address from the WAN harms anything.

Leave a Reply