dhcpcd-discuss

Re: Configuration help -- use IA_NA, but get IA_PD without assigning to interfaces

Neal P. Murphy

Thu Oct 05 04:14:48 2017

On Wed, 4 Oct 2017 14:13:27 -0700
Jeff Kletsky <jmk@xxxxxxxxxx> wrote:

> Great support, thanks!
> 
> No further questions -- just a couple notes for the record of the next 
> person that finds this in the archives.
> 
> Jeff

If it helps, this is the .conf I use on my perimeter Smoothwall Express for IPv6 only (testing/experimentation). It works pretty well with Comcrash; each NIC (including RED) gets its own /64; the received /128 is the IP6 to which Comcrash routes all packets for the /60. With RED having a /64, I can defined 2^64 public domain names for use with NAT6 port forwards; sans NAT6, RED's /64 may be generally unused.

Following the .conf is rc.updatered, the 'callback' that handles the info that dhcpcd gathers and 'reports'; this was morphed from the stock rc.updatered used for IPv4. And after that is the include file with the versatile echolog() function.

Not all of this will apply to your system, but it should give you a few good clues. I hope it's commented well enough. Note that you'll want to you your own ia_id and ia_na values.

Also note that this only deals with the dhcpcd-side of things. I haven't integrated it with ISC dhcpd (or dnsmasq which I plan to migrate Smoothwall Express to some day). But enough information is stored so that I can modify one or more SWE scripts to write desired dhcpd/dnsmasq configs so that internal clients will receive proper public IPv6 addresses. I'm also pondering a way to allow the F/W admin to specify leases and F/W rules in IPv4-ish and have the system 'use' those data on the IPv6 side. the sticky part is determining whether or not NAT6 is used; this means using port forwards (with NAT) or plain 'allow' rules (sans NAT). In short, you're on your own to make the necessary info available to your internal dhcpd/dnsmasq.

(Finally on Smoothwall Express, GREEN is the protected internal LAN/zone, the ORANGE LAN/zone contains public-facing servers, PURPLE is the WiFi LAN/zone, and RED is the INTERNET zone.)

------ dhcpcd6.conf ------
# Use the hardware address of the interface for the Client ID.
#clientid
# or
# Use the same DUID + IAID as set in DHCPv6 for DHCPv4 ClientID as per RFC4361.
# Some non-RFC compliant DHCP servers do not reply with this set.
# In this case, comment out duid and enable clientid above.
duid

# Persist interface configuration when dhcpcd exits.
persistent

# Rapid commit support.
# Safe to enable by default because it requires the equivalent option set
# on the server to actually work.
option rapid_commit

# A list of options to request from the DHCP server.
option domain_name_servers, domain_name, domain_search, host_name
option classless_static_routes
# Most distributions have NTP support.
option ntp_servers
# Respect the network MTU.
# Some interface drivers reset when changing the MTU so disabled by default.
#option interface_mtu

# A ServerID is required by RFC2131.
require dhcp_server_identifier

# Generate Stable Private IPv6 Addresses instead of hardware based ones
slaac private

# A hook script is provided to lookup the hostname if not set by the DHCP
# server, but it should not be run by default.
nohook lookup-hostname, hostname, resolv.conf, ntp.conf, timezone, wpa_supplicant

# Use smoothie's script
script /etc/rc.d/rc.update6red

allowinterfaces eth0 eth1 eth2 eth3
denyinterfaces lo ipsec0 ipsec1
debug
ipv6only
ipv6ra_own
ipv6ra_own_default
leasetime 31622400
nodhcp
nodhcp6
noipv6rs
#logfile /var/log/dhcpcd6.log

interface eth0
iaid 4b:17:f2:7a

interface eth1
iaid 4b:17:f2:7b

interface eth2
iaid 4b:17:f2:7c

interface eth3
dhcp6
ipv6rs
iaid 4b:17:f2:7d
ia_na 4b:17:f2:7d
ia_pd 4b:17:f2:7a/::/60 eth0/1/64 eth1/2/64 eth2/3/64
------------



------ rc.update6red ------
#!/bin/bash

# Like nearly everything in SWE, the file is covered by the project's
#   umbrella GPL license.

# Tweaks to handle DHCP changes by Neal Murphy and Stan Prescott, 4/2013
# Re-arranged a little and ip-up merged in; Neal Murphy, 7/2013
# Console output expanded to dump to console, syslog (smoothwall) and/or
#   syslog (dhcpcd debugging); Murphy/Jones, 2015

# In addition to execution trace debugging, it is possible to dump this script's
#   environment as passed from dhcpcd.
#
# To enable dhcpcd environment logging, create the debug_dhcpcdenv flag file:
#   touch "/var/run/debug-dhcpcdenv"
# To disable this logging, delete the file:
#   rm -f "/var/run/debug-dhcpcdenv"


# A bit of shorthand
ethDIR="/var/smoothwall/ethernet"
pppDIR="/var/smoothwall/ppp"
redDIR="/var/smoothwall/red"

. /etc/rc.d/inc.rc-functions

dns1ENV=$DNS1
dns2ENV=$DNS2
. ${ethDIR}/settings


# readRED6: read the data files in .../red/*
function readRED6 {
        case $RED_TYPE in
          DHCP)
            RED6_INTERFACE=`cat $redDIR/iface6`
            RED6_ADDRESS=`cat $redDIR/local6-ipaddress`
            RED6_GATEWAY=`cat $redDIR/remote6-ipaddress`
            RED6_NETMASK=`cat $redDIR/dhcp6-netmask`
            RED6_DNS1=`cat $redDIR/dns61`
            RED6_DNS2=`cat $redDIR/dns62`

            RED_DNS1=`cat $redDIR/dns1`
            RED_DNS2=`cat $redDIR/dns2`
            ;;
          *)
            echolog "" "s" "$DEBUG_DHCPCD" "..readRED6 called for invalid red type '$RED_TYPE'"
            exit 0
            ;;
        esac
}

# writeRED: write the data files in .../red/*
function writeRED6 {
        echo -n $1 >$redDIR/iface6
        echo -n $2 >$redDIR/local6-ipaddress
        echo -n $3 >$redDIR/remote6-ipaddress
        echo -n $4 >$redDIR/dhcp6-netmask
        echo -n $5 >$redDIR/dns61
        echo -n $6 >$redDIR/dns62
        > $redDIR/active6
        chown nobody:nobody $redDIR/*
}


if [ "$reason" != "ROUTERADVERT" ]; then
  echolog "$crDEBUG" "" "$DEBUG_DHCPCD" "..enter rc.update6red ($reason) [`date`]"

  # Drop a trace
  echolog "$crDEBUG" "s" "$crDEBUG_DHCPCD" "..Update6 RED"
fi


if [ "$RED_TYPE" == "DHCP" ]; then
        # First up; when RED is DHCP

        # We only care about BOUND, REBOOT, RENEW, STOPPED and STOP; we ignore the rest:
        #   EXPIRE*|EXPIRE6*|NAK*|FAIL*|CARRIER*|NOCARRIER*|PREINIT*|DEPARTED*|TIMEOUT*
        # If new reasons appear, we'll see them in the log.

        if [ "$reason" != "ROUTERADVERT" ]; then
                echolog "$crDEBUG" "s" "$DEBUG_DHCPCD" "..RED6 is DHCP"
        fi

        # Special dhcpcd debug: maybe dump the environment to syslog (debug.log)
        if [ -e "/var/run/debug-dhcpcd6env" ]; then
                (
                echo -e "\n======\nAs of `date`"
                echo "Second Param: " $2
                echo "env reason: " $reason
                echo
                echo "Positional params"
                for i in "$@"; do echo "  '$i'";done

                echo "environment"
                set
                ) |& logger -t dhcpcd6env -p local6.debug
        fi
        # end dhcpcd environment debug logging block


        # Why did you call me?
        case $reason in
          STOPPED)
            # Nothing to do; either the system is going down or networking is
            #   being stopped for restart. *Technically*, it might be more correct
            #   to stop the various services; but since they are re-started soon
            #   enough or the system halts, it might not matter.

            echolog "" "s" "" "..DHCP6 stopped on $interface"
            echolog "$crDEBUG" "" \
                    "$DEBUG_DHCPCD" "..DHCP6 stopped on $interface; rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            #echo -e "\n$reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log
            for i in $old_dhcp6_name_servers; do
                    sed -i -e "/$i/d" /etc/resolv.conf
            done

            # This might could get annoying if the lease changes often
            [ "$interface" == "$RED_DEV" ] && /usr/bin/sounds/offlinesound
            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..DHCP6 stopped; exit rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            echolog "" "s" "" "..DHCP6 stopped, reason: ($reason)"

            # Clear the v6 files and mark IPv6 not active on RED
            writeRED6
            rm /var/smoothwall/red/active6

            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..exit rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            exit 0
            ;;

          BOUND6|REBOOT6)
            # New lease bound; all new.

            # Log some stuff
            #echo -e "\n$reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log

            # Clear the old DNS server addresses in resolv.conf, if any
            for i in $old_dhcp6_name_servers; do
              sed -i -e '/$i/d' /etc/resolv.conf
            done >> /etc/resolv.conf

            # Put the new IPv6 DNS addresses in resolv.conf
            for i in $new_dhcp6_name_servers; do
                    sed -i -e '/$i/d' /etc/resolv.conf
                    echo "nameserver $i" >> /etc/resolv.conf
            done

            # Log lease received and address bound
            echolog "E" "s" "" "..DHCP6 lease bound ($reason) and prefix delegated; update RED6 info"
            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" "..DHCP6 new lease bound ($reason) and prefix delegated; update RED6 info. rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"

            # Log some environment
            #echo $reason >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log

            # Save the address
            sed -i -e '/^IP6_ADDRESS/d' /var/lib/dhcpcd/dhcpcd6-$interface.info
            echo "IP6_ADDRESS=$new_dhcp6_ia_na1_ia_addr1/128" >> /var/lib/dhcpcd/dhcpcd6-$interface.info
            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" "..DHCP6 new address: $new_dhcp6_ia_na1_ia_addr1/128 [$RED_TYPE] ($reason) [`date`]"

            # Did we get a prefix?
            if [ ! -z "$new_dhcp6_ia_pd1_prefix1" ]; then

              # Save the delegated net
              echo "IP6_NET=$new_dhcp6_ia_pd1_prefix1/$new_dhcp6_ia_pd1_prefix1_length" > /var/lib/dhcpcd/dhcpcd6-delegated.info
              echolog "$crDEBUG" "" "$DEBUG_DHCPCD" "..DHCP6 delegated prefix: $new_dhcp6_ia_pd1_prefix1/$new_dhcp6_ia_pd1_prefix1_length [$RED_TYPE] ($reason) [`date`]"

              # Clear the old prefix address, if any, from RED
              if [ ! -z "$old_dhcp6_ia_pd1_prefix1" ]; then
                ip -6 addr del ${old_dhcp6_ia_pd1_prefix1}1/64 dev $RED_DEV #>/dev/null 2>&1
              fi

              # And assign 'subnet 0'::1 to RED
              RED6_IP="${new_dhcp6_ia_pd1_prefix1}1"
              ip -6 addr add ${new_dhcp6_ia_pd1_prefix1}1/64 dev $RED_DEV

              # dhcpcd assigns 'subnet 1', 'subnet 2' and 'subnet 3' to GREEN, ORANGE and PURPLE, respectively.
            fi

            # Save the available RED info
            readRED6
            writeRED6 "$interface" "$new_dhcp6_ia_na1_ia_addr1" "$RED6_GATEWAY" \
                     "/128" $new_dhcp6_name_servers

            # We may want to restart daemons &cet, so don't exit.
            ;;

          RELEASE6)
            # Log some stuff
            #echo -e "\n$reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log

            # Remove IPv6 from resolv.conf
            for i in $old_dhcp6_name_servers; do
                    sed -i -e "/$i/d" /etc/resolv.conf
            done

            # Clear the RED6 files
            writeRED6
            rm -f $redDIR/active6

            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..exit rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            exit 0
            ;;

          EXPIRE6)
            # Lease expired; clean up.
            #echo -e "\n$reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log

            writeRED6
            rm -f $redDIR/active6

            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..DHCP6 lease expired ($old_dhcp6_ia_na1_ia_addr1; old_dhcp6_ia_pd1_prefix1) $interface [$RED_TYPE] ($reason) [`date`]"

            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..exit rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            exit 0
            ;;

          DELEGATED6)
            # IP addrs have been fetched and delegated to internal IFs. Record them.
            # Eventually, rewrite dhcp.conf and/or restart dhcpd (the server daemon)
            #   so that correct addresses will be fed to internal hosts.
            #echo -e "\n$reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log
            sed -i -e '/^IP6_ADDRESS/d' /var/lib/dhcpcd/dhcpcd6-$interface.info
            echo "IP6_ADDRESS=$new_delegated_dhcp6_prefix" >> /var/lib/dhcpcd/dhcpcd6-$interface.info
            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..DHCP6 $new_delegated_dhcp6_prefix delegated to $interface [$RED_TYPE] ($reason) [`date`]"

            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..exit rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            exit 0
            ;;

          ROUTERADVERT)
            # Our default gateway. These arrive 'forever', so minimize logging.

            # Log some stuff
            #echo -e "\n$reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log

            # Get current RED params, store and log if changed.
            readRED6
            if [ "$RED6_GATEWAY" != "$nd1_from" ]; then
              echolog "$crDEBUG" "" "$DEBUG_DHCPCD" "..enter rc.update6red ($reason) [`date`]"
              echolog "$crDEBUG" "s" "$crDEBUG_DHCPCD" "..Update6 RED"

              writeRED6 "$interface" "$RED6_ADDRESS" "$nd1_from" \
                        "$RED6_NETMASK" "$RED6_DNS1" "$RED6_DNS2"

              echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                      "..DHCP6 $nd1_from assigned as default gateway [$RED_TYPE] ($reason) [`date`]"
              echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                      "..exit rc.updatered RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            fi
            exit 0
            ;;

          *)
            # Ignore all other reasons, known or not. If important, we'll code it up.
            echolog "$crDEBUG" "s" "$DEBUG_DHCPCD" \
                    "..Ignore DHCPCD6 unknown callback reason '$reason'"
            echolog "$crDEBUG" "" "$DEBUG_DHCPCD" \
                    "..exit rc.update6red RED_TYPE [$RED_TYPE] ($reason) [`date`]"
            #echo -e "\nUNKNOWN $reason" >> /var/log/dhcpcdtmp.log
            #set | egrep "^[a-z]" >> /var/log/dhcpcdtmp.log
            exit 0
            ;;
        esac


fi

#####################
# For now, do nothing when IPv6 changes
#####################

exit 0
------------



------ inc.rc-functions ------
# inc.rc-functions
#
# This file contains some functions commonly useful in RC scripts.

# Enable/disable optional output
if [ -f /var/run/debug-bootup ]; then
  export DEBUG="e"
  export crDEBUG="E"
else
  export DEBUG=""
  export crDEBUG=""
fi
if [ -f /var/run/debug-dhcpcd ]; then
  export DEBUG="e"
  export crDEBUG="E"
  export DEBUG_DHCPCD="d"
else
  # Don't clear DEBUG/crDEBUG in case they were explicitly requested.
  export DEBUG_DHCPCD=""
fi

# Function echolog() directs feedback to any of three locations

function echolog () {
  [ "$1" == "e" ] && echo "$4"
  [ "$1" == "E" ] && echo -e "$4\r"
  [ "$2" == "s" ] && logger -t smoothwall "$4"
  [ "$3" == "d" ] && logger -t dhcpcd -p local6.debug "$4"

  return 0
}
------------

References:
Configuration help -- use IA_NA, but get IA_PD without assigning to interfacesJeff Kletsky
Re: Configuration help -- use IA_NA, but get IA_PD without assigning to interfacesRoy Marples
Re: Configuration help -- use IA_NA, but get IA_PD without assigning to interfacesJeff Kletsky
Archive administrator: postmaster@marples.name