# Setting routes with a dynamic IP



## macfreek (Sep 6, 2014)

Hi,

I have a multihomed FreeBSD router (Internet and IPTV). Both interfaces get a dynamic IP using DHCP. I like to set a route on one of the interfaces, e.g.:


```
route add 12.34.56.78/24 10.0.53.1
```

where 10.0.53.1 is the IP of the gateway of my ISP that I learned about from the DHCP offer. This IP may change and I am a bit reluctant to hard code a dynamic IP in my config (even though in practice it may stay stable for a prolonged period of time).

I haven't found a way to do this in rc.conf using a dynamic IP address of the gateway? (only with a static IP)

The only alternative I can think of is to use /etc/dhclient-exit-hooks, as mentioned in dhclient-script().

Am I on the right track here? Or is there an option in rc.conf that I missed?


----------



## SirDice (Sep 8, 2014)

macfreek said:
			
		

> The only alternative I can think of is to use /etc/dhclient-exit-hooks, as mentioned in dhclient-script().


That would be the way to do it.


----------



## macfreek (Sep 10, 2014)

*[solved] Setting routes with a dynamic IP*

FYI, it works for me now. 

This is how my /etc/dhclient-enter-hooks looks like:


```
case "$reason" in
    BOUND|RENEW|REBIND|REBOOT|TIMEOUT)
        # Add static routes on em1
        if [ "$interface" = "em1" -a -n "$new_routers" ]
        then
            # Determine gateway from routers
            # extract first IP address and replace all . with " "
            gateway=`echo "${new_routers%% *}" | sed 's/\./ /g'`
            # route 192.2.0.128/25 and 10.0.0.0/8 to the gateway IP.
            new_classless_routes="25 192 0 2 128 $gateway 8 10 $gateway"
        fi
        
        # Do not set default route on any interface except em0
        if [ "$interface" != "em0" ]
        then
            unset new_routers
        fi
    ;;
esac
```

This script performs two actions:

 If em1 is configured, add two routes
 if any other interface than em0 is configured, do not set a default route.

This ensures that only em0 has a default route (the standard behaviour is that a default route is set only if none exists yet).

Rather than calling `route` directly, the script uses the classless-routes DHCP option to tell the dhclient-script() to add a certain route in the routing table. Note that the encoding is a bit odd: the size of the subnet determines how many octets of the IP address are encoded in the DHCP option, and thus in the `new_classless_routes` variable.


If you use the ISC dhclient instead of the OpenBSD dhclient (which is the FreeBSD standard), note that the FreeBSD dhclient-script supports the classless-routes, but the ISC dhclient-script only supports the older static-routes DHCP option, not the newer classless-routes, and will not set any routes. As a work-around, you can set new_static_routes instead of new_classless_routes (see code below). Officially, this bad syntax (static-routes is supposed the work on individual IP addresses, not IP ranges), but in practise it should work fine for the ISC dhclient-script. (Caveat: I have not tested it with the ISC DHCP client!)

```
gateway=${new_routers%% *} # select first IP address
    new_static_routes=192.2.0.128/25 $gateway 10.0.0.0/8 $gateway
```

In case you are wondering why I used sed instead of the following parameter expansion: the second line is a bash-construct, and does not work in sh, which is used by dhclient-script.

```
gateway=${new_routers%% *} # extract first IP address
            gateway=${gateway//./ } # replace all . with " "
```


----------

