# Copyright (C) 2005, 2006, 2008, 2009 Martin Michlmayr # Copyright (C) 2008 Matthew Palmer # Copyright (C) 2009 Stephen Gran # This code is covered by the GNU General Public License (version 2 # or higher) # Reading # Check if a file exists and exit if it doesn't # $1 = file check_file() { if [ ! -e $1 ]; then log "$1 does not exist" exit fi } # Returns the mtd device with the specified name (without leading /dev) # $1 = name of mtd device get_mtd() { grep "\b$1\b\"*$" /proc/mtd | cut -d : -f 1 } # Returns the mtd block device with the specified name (without leading /dev) # $1 = name of mtd device get_mtdblock() { echo $(get_mtd "$1") | sed 's/mtd/mtdblock/' } # Parsing # Parse a standard Unix tree (i.e. configs found in /etc) # $1 = root path parse_unix_tree() { log "Parsing Unix tree at $1" ETC=$1/etc if [ -e $ETC/network/interfaces ]; then parse_network_interfaces $ETC/network/interfaces "eth0" fi if [ -e $ETC/resolv.conf ]; then for i in $(grep "^nameserver" $ETC/resolv.conf | sed 's/^.* //'); do var_add NAMESERVERS "$i" done fi if [ -e $ETC/hostname ]; then HOSTNAME=$(cat $ETC/hostname | cut -d . -f 1) fi if [ -e $ETC/domainname ]; then DOMAIN=$(cat $ETC/domainname) fi } # LEAF is a distro based on LRP (Linux Router Project) # $1 = root path parse_leaf_tree() { log "Parsing LEAF tree at $1" ETC=$1/etc if [ -e $ETC/resolv.static1 ]; then var_add NAMESERVERS "$(grep "^nameserver" $ETC/resolv.static1 | sed 's/^.* //' | head -n 1)" fi if [ -e $ETC/resolv.static2 ]; then var_add NAMESERVERS "$(grep "^nameserver" $ETC/resolv.static2 | sed 's/^.* //' | head -n 1)" fi } # Parse a /etc/network/interfaces file # $1 = file # $2 = interface parse_network_interfaces() { log "Parsing $1 to find network interface $2" # Find the interface we're interested in if ! $(grep -q "^iface $2\b" $1); then return fi iface=$(grep -n "^iface $2\b" $1) if $(echo "$iface" | grep -q "inet static"); then n=$(echo "$iface" | cut -d : -f 1) # line number NET_CONFIG=static stanza=$(tail -n +$(($n+1)) $1) # Find the next interface and ignore lines from there on n=$(echo "$stanza" | grep -n "^iface\b" | cut -d : -f 1) if [ $n ]; then stanza=$(echo "$stanza" | head -n $(($n-1))) fi INTERFACE=$2 IPADDRESS=$(echo "$stanza" | grep "address" | sed 's/.*address //') GATEWAY=$(echo "$stanza" | grep "gateway" | sed 's/.*gateway //') fi } # Parse a set of ifconfig/route/etc commands # $1 = ifconfig et al. commands parse_ifconfig() { # UGH! IPADDRESS=$(grep "ifconfig [-[:alpha:][:digit:]]* [[:digit:].]" $1 | sed 's/.*ifconfig [-[:alpha:][:digit:]]* \([.[:digit:]]*\) .*/\1/') NETMASK=$(grep '\bnetmask\b' $1 | sed 's/.*netmask\s*//' | sed 's/\s.*//') GATEWAY=$(grep "route add default gw" $1 | sed 's/.*gw\s*//') } # Get the value from a string in the form of var=value # $1 = string # $2 = var get_var() { echo "$1" | grep -a "^$2=" | sed "s/^$2=//" } # Get the value from a string in the form of var = "value" from a file. # Named for the sib.conf file on the D-Link DNS-323 that this function # was originally written for. # $1 = file to read # $2 = var to read get_sib_var() { grep "^$2[[:space:]]*=" $1 | sed "s/^$2[[:space:]]*=[[:space:]]*\"\(.*\)\"[[:space:]]*$/\1/" } # Add a string to a variable; deals with the fact when a string is empty # $1 = variable name # $2 = string var_add() { if [ -n "$2" ]; then value="$(eval echo \"$`echo $1`\")" if [ -n "$value" ]; then x="$value $2" else x="$2" fi eval "`echo $1`=\"$x\"" fi } # Return the value of a XML/HTML like value staetment. remove_xml() { echo "$1" | sed 's/[^>]*> *//' | sed 's/ *<.*//' } # Parse the sib.conf file, as found in the D-Link DNS-323 # $1 = path to sib.conf parse_sib_conf() { if [ "$(get_sib_var "$1" "CF-IP-DHCP-ENABLE")" = "0" ]; then NET_CONFIG=static fi IPADDRESS="$(get_sib_var "$1" "CF-IP-STATIC-IP")" NETMASK="$(get_sib_var "$1" "CF-IP-STATIC-IP-NETMASK")" GATEWAY="$(get_sib_var "$1" "CF-IP-STATIC-IP-GATEWAY")" var_add NAMESERVERS "$(get_sib_var "$1" "CF-IP-DNS1")" var_add NAMESERVERS "$(get_sib_var "$1" "CF-IP-DNS2")" HOSTNAME="$(get_sib_var "$1" "CF-SYS-MODEL-STR")" } # Generating # Output a variable to a preseed file if the variable has a value # $1 = file name (stdout if this is empty) # $2 = debconf variable name # $3 = debconf variable type # $4 = variable add() { if [ -n "$4" -o "$3" = "note" ]; then if [ -n "$1" ]; then echo "d-i $2 $3 $4" | sed 's/ *$//' >> "$1" else echo "d-i $2 $3 $4" | sed 's/ *$//' fi fi } # Output a variable to a preseed file or, iv the variable is empty, mark # the debconf variable as seen. # $1 = file name (stdout if this is empty) # $2 = debconf variable name # $3 = debconf variable type # $4 = variable add_or_set_seen() { if [ -z "$4" -a "$NONINTERACTIVE" = "yes" ]; then add "$1" "$2" "seen" "true" else add "$1" "$2" "$3" "$4" fi } # Write a static network configuration to the preseed file # $1 = file name (stdout if this is empty) write_static_network() { add "$1" "netcfg/get_ipaddress" "string" "$IPADDRESS" add_or_set_seen "$1" "netcfg/get_netmask" "string" "$NETMASK" if [ -z "$GATEWAY" ]; then GATEWAY=none fi add "$1" "netcfg/get_gateway" "string" "$GATEWAY" add "$1" "netcfg/get_nameservers" "string" "$NAMESERVERS" } # Fall back to a static address if DHCP fails # $1 = file name (stdout if this is empty) dhcp_fallback() { add "$1" "netcfg/dhcp_failed" "note" add "$1" "netcfg/dhcp_options" "select" "Configure network manually" write_static_network "$1" } # Generate a preseed file # $1 = filename generate_preseed_file() { add "$1" "netcfg/choose_interface" "select" "$INTERFACE" if [ "$NET_CONFIG" = "static" ]; then write_static_network "$1" add "$1" "netcfg/confirm_static" "boolean" "true" add "$1" "netcfg/disable_autoconfig" "boolean" "true" else add "$1" "netcfg/use_dhcp" "boolean" "true" fi if [ "$NONINTERACTIVE" = "yes" -o "$HOSTNAME" != "$DEFAULT_HOSTNAME" ]; then if verify_hostname "$HOSTNAME"; then add "$1" "netcfg/get_hostname" "string" "$HOSTNAME" fi fi add "$1" "netcfg/get_domain" "string" "$DOMAIN" } # Misc # Unset a variable if it has a particular value # $1 = variable # $2 = value unset_matching_var() { if [ "$(eval echo $`echo $1`)" = "$2" ]; then unset $1 fi } # Check the hostname for RFC 1123 compliance. verify_hostname() { t=$(echo "$1" | tr -d 'a-zA-Z0-9.-') if [ -n "$t" ]; then return 1 fi if echo "$1" | grep -q "^-"; then return 1 fi if echo "$1" | grep -q -- "-$"; then return 1 fi l=$(($(echo "$1" | wc -c) - 1)) if [ $l -lt 2 -o $l -gt 63 ]; then return 1 fi return 0 } # Convert an IP address (like 127.0.0.1) to bits. make_bit_address () { addr=$1 first=$(( $(echo $addr | cut -d. -f1) << 24)) second=$(( $(echo $addr | cut -d. -f2) << 16)) third=$(( $(echo $addr | cut -d. -f3) << 8)) fourth=$(echo $addr | cut -d. -f4) echo $(( $first + $second + $third + $fourth )) } # Check if two IP addresses are on the same network. address_is_in () { addr=$1 addr2=$2 netmask=$3 bitaddr=$(make_bit_address $addr) bitaddr2=$(make_bit_address $addr2) bitmask=$(make_bit_address $netmask) [ "$(( $bitaddr & $bitmask ))" = "$(( $bitaddr2 & $bitmask))" ] } # Sanity checks for static IP configuration sanity_check_static_config() { # netcfg will prompt for an IP address and nameserver if they are # not set, so use DHCP in that case. if [ "$NONINTERACTIVE" = "yes" ] && [ -z "$IPADDRESS" -o -z "$NAMESERVERS" ]; then NET_CONFIG=dhcp fi # Replicate the "gateway is unreachable" check from netcfg. if [ -n "$IPADDRESS" -a -n "$GATEWAY" ]; then if [ -n "$NETMASK" ]; then LOCAL_NETMASK="$NETMASK" else # Use same default as netcfg. LOCAL_NETMASK=255.255.255.0 fi if ! address_is_in "$IPADDRESS" "$GATEWAY" "$LOCAL_NETMASK"; then NET_CONFIG=dhcp fi fi }