aboutsummaryrefslogtreecommitdiff
path: root/net.Linux
diff options
context:
space:
mode:
authorRoy Marples <roy@marples.name>2007-04-05 11:18:42 +0000
committerRoy Marples <roy@marples.name>2007-04-05 11:18:42 +0000
commit5af58b45146ab5253ca964738f4e45287bf963d4 (patch)
tree68d3a9a61fa55dd7fe273db776c375f797edaa5b /net.Linux
Rewrite the core parts in C. We now provide librc so other programs can
query runlevels, services and state without using bash. We also provide libeinfo so other programs can easily use our informational functions. As such, we have dropped the requirement of using bash as the init script shell. We now use /bin/sh and have strived to make the scripts as portable as possible. Shells that work are bash and dash. busybox works provided you disable s-s-d. If you have WIPE_TMP set to yes in conf.d/bootmisc you should disable find too. zsh and ksh do not work at this time. Networking support is currently being re-vamped also as it was heavily bash array based. As such, a new config format is available like so config_eth0="1.2.3.4/24 5.6.7.8/16" or like so config_eth0="'1.2.3.4 netmask 255.255.255.0' '5.6.7.8 netmask 255.255.0.0'" We will still support the old bash array format provided that /bin/sh IS a link it bash. ChangeLog for baselayout-1 can be found in our SVN repo.
Diffstat (limited to 'net.Linux')
-rw-r--r--net.Linux/Makefile8
-rw-r--r--net.Linux/adsl.sh71
-rw-r--r--net.Linux/apipa.sh46
-rw-r--r--net.Linux/arping.sh111
-rw-r--r--net.Linux/bonding.sh100
-rw-r--r--net.Linux/br2684ctl.sh50
-rw-r--r--net.Linux/bridge.sh113
-rw-r--r--net.Linux/ccwgroup.sh66
-rw-r--r--net.Linux/clip.sh212
-rw-r--r--net.Linux/ifconfig.sh239
-rw-r--r--net.Linux/ifplugd.sh91
-rw-r--r--net.Linux/ip6to4.sh97
-rw-r--r--net.Linux/ipppd.sh47
-rw-r--r--net.Linux/iproute2.sh185
-rw-r--r--net.Linux/iwconfig.sh710
-rw-r--r--net.Linux/macchanger.sh88
-rw-r--r--net.Linux/netplugd.sh93
-rw-r--r--net.Linux/pppd.sh219
-rw-r--r--net.Linux/pump.sh60
-rw-r--r--net.Linux/tuntap.sh57
-rw-r--r--net.Linux/udhcpc.sh102
-rw-r--r--net.Linux/vlan.sh108
22 files changed, 2873 insertions, 0 deletions
diff --git a/net.Linux/Makefile b/net.Linux/Makefile
new file mode 100644
index 00000000..3059f1e4
--- /dev/null
+++ b/net.Linux/Makefile
@@ -0,0 +1,8 @@
+DIR = /$(LIB)/rcscripts/net
+FILES = adsl.sh apipa.sh arping.sh bonding.sh br2684ctl.sh bridge.sh \
+ ccwgroup.sh clip.sh ifconfig.sh ifplugd.sh ip6to4.sh ipppd.sh \
+ iproute2.sh iwconfig.sh netplugd.sh pppd.sh pump.sh tuntap.sh \
+ udhcpc.sh vlan.sh
+
+TOPDIR = ..
+include $(TOPDIR)/default.mk
diff --git a/net.Linux/adsl.sh b/net.Linux/adsl.sh
new file mode 100644
index 00000000..a6e74c9d
--- /dev/null
+++ b/net.Linux/adsl.sh
@@ -0,0 +1,71 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+adsl_depend() {
+ program /usr/sbin/adsl-start /usr/sbin/pppoe-start
+ before dhcp
+}
+
+adsl_setup_vars() {
+ local startstop="$2" cfgexe=
+
+ if [ -x /usr/sbin/pppoe-start ]; then
+ exe="/usr/sbin/pppoe-${startstop}"
+ cfgexe=pppoe-setup
+ else
+ exe="/usr/sbin/adsl-${startstop}"
+ cfgexe=adsl-setup
+ fi
+
+ # Decide which configuration to use. Hopefully there is an
+ # interface-specific one
+ cfgfile="/etc/ppp/pppoe-${IFACE}.conf"
+ [ -f "${cfgfile}" ] || cfgfile="/etc/ppp/pppoe.conf"
+
+ if [ ! -f "${cfgfile}" ]; then
+ eerror "no pppoe.conf file found!"
+ eerror "Please run ${cfgexe} to create one"
+ return 1
+ fi
+
+ return 0
+}
+
+adsl_start() {
+ local exe= cfgfile= user=
+
+ adsl_setup_vars start || return 1
+
+ # Might or might not be set in conf.d/net
+ eval user=\$adsl_user_${IFVAR}
+
+ # Start ADSL with the cfgfile, but override ETH and PIDFILE
+ einfo "Starting ADSL for ${IFACE}"
+ (
+ cat "${cfgfile}";
+ echo "ETH=${IFACE}";
+ echo "PIDFILE=/var/run/rp-pppoe-${IFACE}.pid";
+ [ -n "${user}" ] && echo "USER=${user}";
+ ) | ${exe} >/dev/null
+ eend $?
+}
+
+adsl_stop() {
+ local exe= cfgfile=
+
+ [ ! -f /var/run/rp-pppoe-"${IFACE}".pid ] && return 0
+
+ adsl_setup_vars stop || return 1
+
+ einfo "Stopping ADSL for ${IFACE}"
+ (
+ cat "${cfgfile}";
+ echo "ETH=${IFACE}";
+ echo "PIDFILE=/var/run/rp-pppoe-${IFACE}.pid";
+ ) | ${exe} >/dev/null
+ eend $?
+
+ return 0
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/apipa.sh b/net.Linux/apipa.sh
new file mode 100644
index 00000000..2a71b608
--- /dev/null
+++ b/net.Linux/apipa.sh
@@ -0,0 +1,46 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+apipa_depend() {
+ program /sbin/arping
+}
+
+_random() {
+ if [ -n "${BASH}" ] ; then
+ echo "${RANDOM}"
+ else
+ uuidgen | sed -n -e 's/[^[:digit:]]//g' -e 's/\(^.\{1,7\}\).*/\1/p'
+ fi
+}
+
+apipa_start() {
+ local iface="$1" i1= i2= addr= i=0
+
+ _exists true || return 1
+
+ einfo "Searching for free addresses in 169.254.0.0/16"
+ eindent
+
+ while [ ${i} -lt 64516 ]; do
+ i1=$((($(_random) % 255) + 1))
+ i2=$((($(_random) % 255) + 1))
+
+ addr="169.254.${i1}.${i2}"
+ vebegin "${addr}/16"
+ if ! arping_address "${addr}" ; then
+ eval config_${config_index}="\"${addr}/16 broadcast 169.254.255.255\""
+ config_index=$((${config_index} - 1))
+ veend 0
+ eoutdent
+ return 0
+ fi
+
+ i=$((${i} + 1))
+ done
+
+ eerror "No free address found!"
+ eoutdent
+ return 1
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/arping.sh b/net.Linux/arping.sh
new file mode 100644
index 00000000..763cb4ce
--- /dev/null
+++ b/net.Linux/arping.sh
@@ -0,0 +1,111 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+arping_depend() {
+ program /sbin/arping
+ before interface
+}
+
+arping_address() {
+ local ip=${1%%/*} mac="$2" foundmac= i= w= opts=
+
+ # We only handle IPv4 addresses
+ case "${ip}" in
+ 0.0.0.0|0) return 1 ;;
+ *.*.*.*) ;;
+ *) return 1 ;;
+ esac
+
+ # We need to bring the interface up to test
+ _exists "${iface}" || return 1
+ _up "${iface}"
+
+ eval w=\$arping_wait_${IFVAR}
+ [ -z "${w}" ] && w=${arping_wait:-5}
+
+ [ -z "$(_get_inet_address)" ] && opts="${opts} -D"
+
+ foundmac="$(arping -w "${w}" ${opts} -f -I "${IFACE}" "${ip}" 2>/dev/null | \
+ sed -n -e 'y/abcdef/ABCDEF/' -e 's/.*\[\([^]]*\)\].*/\1/p')"
+ [ -z "${foundmac}" ] && return 1
+
+ if [ -n "${mac}" ] ; then
+ if [ "${mac}" != "${foundmac}" ] ; then
+ vewarn "Found ${ip} but MAC ${foundmac} does not match"
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+arping_start() {
+ local gateways= x= conf= i=
+ einfo "Pinging gateways on ${IFACE} for configuration"
+
+ eval $(_get_array "gateways_${IFVAR}")
+ if [ -z "$@" ] ; then
+ eerror "No gateways have been defined (gateways_${IFVAR}=\"...\")"
+ return 1
+ fi
+
+ eindent
+
+ for x in "$@"; do
+ eval set -- "${x}"
+ local ip=$1 mac=$2 extra=
+
+ if [ -n "${mac}" ] ; then
+ mac="$(echo "${mac}" | tr '[:lower:]' '[:upper:]')"
+ extra="(MAC ${mac})"
+ fi
+
+ vebegin "${ip} ${extra}"
+ if arping_address "${ip}" "${mac}" ; then
+ local OIFS=$IFS SIFS=${IFS-y}
+ IFS=.
+ for i in ${ip} ; do
+ if [ "${#i}" = "2" ] ; then
+ conf="${conf}0${i}"
+ elif [ "${#i}" = "1" ] ; then
+ conf="${conf}00${i}"
+ else
+ conf="${conf}${i}"
+ fi
+ done
+ if [ "${SIFS}" = "y" ] ; then
+ IFS=$OFIS
+ else
+ unset IFS
+ fi
+ [ -n "${mac}" ] && conf="${conf}_$(echo "${mac}" | sed -e 's/://g')"
+
+ veend 0
+ eoutdent
+ veinfo "Configuring ${IFACE} for ${ip} ${extra}"
+ _configure_variables "${conf}"
+
+ # Call the system module as we've aleady passed it by ....
+ # And it *has* to be pre_start for other things to work correctly
+ system_pre_start
+
+ # Ensure that we have a valid config - ie arping is no longer there
+ eval $(_get_array "config_${IFVAR}")
+ for i in "$@" ; do
+ if [ "${i}" = "arping" ] ; then
+ veend 1 "No config found for ${ip} (config_${conf}=\"...\")"
+ continue 2
+ fi
+ done
+
+ _load_config
+ return 0
+ fi
+ veend 1
+ done
+
+ eoutdent
+ return 1
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/bonding.sh b/net.Linux/bonding.sh
new file mode 100644
index 00000000..36be943f
--- /dev/null
+++ b/net.Linux/bonding.sh
@@ -0,0 +1,100 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+bonding_depend() {
+ before interface macchanger
+ program /sbin/ifenslave
+}
+
+_config_vars="$_config_vars slaves"
+
+_is_bond() {
+ [ -f "/proc/net/bonding/${IFACE}" ]
+}
+
+bonding_pre_start() {
+ local s= slaves=
+
+ eval $(_get_array "slaves_${IFACE}")
+ [ $# = "0" ] && return 0
+
+ # Load the kernel module if required
+ if [ ! -d /proc/net/bonding ] ; then
+ if ! modprobe bonding ; then
+ eerror "Cannot load the bonding module"
+ return 1
+ fi
+ fi
+
+ # We can create the interface name we like now, but this
+ # requires sysfs
+ if ! _exists && [ -d /sys/class/net ] ; then
+ echo "+${IFACE}" > /sys/class/net/bonding_masters
+ fi
+ _exists true || return 1
+
+ if ! _is_bond ; then
+ eerror "${IFACE} is not capable of bonding"
+ return 1
+ fi
+
+ ebegin "Adding slaves to ${IFACE}"
+ eindent
+ einfo "$@"
+
+ # Check that our slaves exist
+ (
+ for IFACE in "$@" ; do
+ _exists true || return 1
+ done
+
+ # Must force the slaves to a particular state before adding them
+ for IFACE in "$@" ; do
+ _delete_addresses
+ _up
+ done
+ )
+
+ # now force the master to up
+ _up
+
+ # finally add in slaves
+ eoutdent
+ /sbin/ifenslave "${IFACE}" $@ >/dev/null
+ eend $?
+
+ return 0 #important
+}
+
+bonding_stop() {
+ _is_bond || return 0
+
+ local slaves= s=
+ slaves=$( \
+ sed -n -e 's/^Slave Interface: //p' "/proc/net/bonding/${IFACE}" \
+ | tr '\n' ' ' \
+ )
+ [ -z "${slaves}" ] && return 0
+
+ # remove all slaves
+ ebegin "Removing slaves from ${IFACE}"
+ eindent
+ einfo "${slaves}"
+ eoutdent
+ /sbin/ifenslave -d "${IFACE}" ${slaves}
+
+ # reset all slaves
+ (
+ for IFACE in ${slaves}; do
+ if _exists ; then
+ _delete_addresses
+ _down
+ fi
+ done
+ )
+
+ eend 0
+ return 0
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/br2684ctl.sh b/net.Linux/br2684ctl.sh
new file mode 100644
index 00000000..928473b3
--- /dev/null
+++ b/net.Linux/br2684ctl.sh
@@ -0,0 +1,50 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+br2684ctl_depend() {
+ before ppp
+ program start /sbin/br2684ctl
+}
+
+_config_vars="$_config_vars bridge bridge_add brctl"
+
+br2684ctl_pre_start() {
+ local opts=
+ eval opts=\$br2684ctl_${IFVAR}
+ [ -z "${opts}" ] && return 0
+
+ if [ "${IFACE#nas[0-9]*}" = "${IFACE}" ] ; then
+ eerror "Interface must be called nas[0-9] for RFC 2684 Bridging"
+ return 1
+ fi
+
+ case " ${opts} " in
+ *" -b "*|*" -c "*)
+ eerror "The -b and -c options are not allowed for br2684ctl_${IVAR}"
+ return 1
+ ;;
+ *" -a "*) ;;
+ *)
+ eerror "-a option (VPI and VCI) is required in br2684ctl_${IFVAR}"
+ return 1
+ ;;
+ esac
+
+ einfo "Starting RFC 2684 Bridge control on ${IFACE}"
+ start-stop-daemon --start --exec /sbin/br2684ctl --background \
+ --make-pidfile --pidfile "/var/run/br2684ctl-${IFACE}.pid" \
+ -- -c "${IFACE#nas*}" ${opts}
+ eend $?
+}
+
+br2684ctl_post_stop() {
+ local pidfile="/var/run/br2684ctl-${IFACE}.pid"
+ [ -e "${pidfile}" ] || return 0
+
+ einfo "Stopping RFC 2684 Bridge control on ${IFACE}"
+ start-stop-daemon --stop --quiet \
+ --exec /sbin/br2684ctl --pidfile "${pidfile}"
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/bridge.sh b/net.Linux/bridge.sh
new file mode 100644
index 00000000..89d5687e
--- /dev/null
+++ b/net.Linux/bridge.sh
@@ -0,0 +1,113 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+bridge_depend() {
+ before interface macnet
+ program /sbin/brctl
+}
+
+_config_vars="$_config_vars bridge bridge_add brctl"
+
+_is_bridge() {
+ brctl show 2>/dev/null | grep -q "^${IFACE}[[:space:]]"
+}
+
+bridge_pre_start() {
+ local ports= brif= opts= iface="${IFACE}" e= x=
+ eval $(_get_array "bridge_${IFVAR}")
+ ports="$@"
+ eval brif=\$bridge_add_${IFVAR}
+ eval $(_get_array "brctl_${IFVAR}")
+ opts="$@"
+ [ -z "${ports}" -a -z "${brif}" -a -z "${opts}" ] && return 0
+
+ [ -n "${ports}" ] && bridge_post_stop
+
+ (
+ if [ -z "${ports}" -a -n "${brif}" ] ; then
+ ports="${IFACE}"
+ IFACE="${brif}"
+ else
+ ports="${ports}"
+ metric=1000
+ fi
+
+ if ! _is_bridge ; then
+ ebegin "Creating bridge ${IFACE}"
+ if ! brctl addbr "${IFACE}" ; then
+ eend 1
+ return 1
+ fi
+
+ eval set -- ${opts}
+ for x in "$@" ; do
+ case " ${x} " in
+ *" ${IFACE} "*) ;;
+ *) x="${x} ${IFACE}" ;;
+ esac
+ brctl ${x}
+ done
+ fi
+
+ if [ -n "${ports}" ] ; then
+ einfo "Adding ports to ${IFACE}"
+ eindent
+
+ eval set -- ${ports}
+ for x in "$@" ; do
+ ebegin "${x}"
+ if ! ifconfig "${x}" promisc up && brctl addif "${IFACE}" "${x}" ; then
+ ifconfig "${x}" -promisc 2>/dev/null
+ eend 1
+ return 1
+ fi
+ eend 0
+ done
+ eoutdent
+ fi
+ )
+}
+
+bridge_post_stop() {
+ local port= ports= delete=false extra=
+
+ if _is_bridge ; then
+ ebegin "Destroying bridge ${IFACE}"
+ _down
+ ports="$( brctl show 2>/dev/null | \
+ sed -n -e '/^'"${IFACE}"'[[:space:]]/,/^\S/ { /^\('"${IFACE}"'[[:space:]]\|\t\)/s/^.*\t//p }')"
+ delete=true
+ iface=${IFACE}
+ eindent
+ else
+ # Work out if we're added to a bridge for removal or not
+ eval set -- $(brctl show 2>/dev/null | sed -e "s/'/'\\\\''/g" -e "s/$/'/g" -e "s/^/'/g")
+ local line=
+ for line in "$@" ; do
+ set -- ${line}
+ if [ "$3" = "${IFACE}" ] ; then
+ iface=$1
+ break
+ fi
+ done
+ [ -z "${iface}" ] && return 0
+ extra=" from ${iface}"
+ fi
+
+ for port in ${ports} ; do
+ ebegin "Removing port ${port}${extra}"
+ ifconfig "${port}" -promisc
+ brctl delif "${iface}" "${port}"
+ eend $?
+ done
+
+ if ${delete} ; then
+ eoutdent
+ brctl delbr "${iface}"
+ eend $?
+ fi
+
+ return 0
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/ccwgroup.sh b/net.Linux/ccwgroup.sh
new file mode 100644
index 00000000..1cba04cb
--- /dev/null
+++ b/net.Linux/ccwgroup.sh
@@ -0,0 +1,66 @@
+# Copyright 2006-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# Contributed by Roy Marples (uberlord@gentoo.org)
+
+_config_vars="$_config_vars ccwgroup"
+
+ccwgroup_depend() {
+ before interface
+}
+
+ccwgroup_pre_start() {
+ eval $(_get_array "ccwgroup_${IFVAR}")
+ [ $# = "0" ] && return 0
+
+ if [ ! -d /sys/bus/ccwgroup ] ; then
+ modprobe qeth
+ if [ ! -d /sys/bus/ccwgroup ] ; then
+ eerror "ccwgroup support missing in kernel"
+ return 1
+ fi
+ fi
+
+ einfo "Enabling ccwgroup on ${IFACE}"
+ local x= ccw= first= layer2=
+ for x in "$@" ; do
+ [ -z "${first}" ] && first=${x}
+ ccw="${ccw}${ccw:+,}${x}"
+ done
+ if [ -e /sys/devices/qeth/"${first}" ] ; then
+ echo "0" > /sys/devices/qeth/"${first}"/online
+ else
+ echo "${ccw}" > /sys/bus/ccwgroup/drivers/qeth/group
+ fi
+ eval layer2=\$qeth_layer2_${IFVAR}
+ echo "${layer2:-0}" > /sys/devices/qeth/"${first}"/layer2
+ echo "1" > /sys/devices/qeth/"${first}"/online
+ eend $?
+}
+
+ccwgroup_pre_stop() {
+ # Erase any existing ccwgroup to be safe
+ save_options ccwgroup_device ""
+
+ [ ! -L /sys/class/net/"${FACE}"/driver ] && return 0
+ local driver="$(readlink /sys/class/net/"${IFACE}"/driver)"
+ case "${diver}" in
+ */bus/ccwgroup/*) ;;
+ *) return 0 ;;
+ esac
+
+ local device="$(readlink /sys/class/net/"${IFACE}"/device)"
+ device=${device##*/}
+ save_options ccwgroup_device "${device}"
+}
+
+ccwgroup_post_stop() {
+ local device="$(get_options ccwgroup_device)"
+ [ -z "${device}" ] && return 0
+
+ einfo "Disabling ccwgroup on ${iface}"
+ echo "0" > /sys/devices/qeth/"${device}"/online
+ echo "1" > /sys/devices/qeth/"${device}"/ungroup
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/clip.sh b/net.Linux/clip.sh
new file mode 100644
index 00000000..d3ec4fd8
--- /dev/null
+++ b/net.Linux/clip.sh
@@ -0,0 +1,212 @@
+# Copyright 2005-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+clip_depend() {
+ program /usr/sbin/atmsigd
+ before interface
+}
+
+_config_vars="$_config_vars clip"
+
+# This starts a service. Albeit atmsigd, ilmid and atmarpd do allow for back-
+# grounding through the -b option, its usage causes them to be sensible to
+# SIGHUP, which is sent to all daemons when console detaches right after
+# startup. This is probably due to the fact that these programs don't detach
+# themself from the controlling terminal when backgrounding... The only way I
+# see to overcame this is to use the --background option in start-stop-daemon,
+# which is reported as a "last resort" method, but it acts correctly about this.
+atmclip_svc_start() {
+ ebegin "Starting $2 Daemon ($1)"
+ start-stop-daemon --start \
+ --background \
+ --make-pidfile --pidfile "/var/run/$1.pid" \
+ --exec "/usr/sbin/$1" -- -l syslog
+ eend $?
+}
+
+atmclip_svcs_start() {
+ einfo "First CLIP instance: starting ATM CLIP daemons"
+ eindent
+
+ if [ "${clip_full:-yes}" = "yes" ]; then
+ atmclip_svc_start atmsigd "Signaling" && \
+ atmclip_svc_start ilmid "Integrated Local Management Interface" && \
+ atmclip_svc_start atmarpd "Address Resolution Protocol"
+ else
+ atmclip_svc_start atmarpd "Address Resolution Protocol"
+ fi
+
+ local r=$?
+
+ eoutdent
+ return ${r}
+}
+
+atmclip_svc_stop() {
+ ebegin "Stopping $2 Daemon ($1)"
+ start-stop-daemon --stop --quiet \
+ --pidfile "/var/run/$1.pid" \
+ --exec "/usr/sbin/$1"
+ eend $?
+}
+
+atmclip_svcs_stop() {
+ einfo "Last CLIP instance: stopping ATM CLIP daemons"
+ eindent
+
+ # Heartake operation!
+ sync
+
+ atmclip_svc_stop atmarpd "Address Resolution Protocol"
+ if [ "${clip_full:-yes}" = "yes" ]; then
+ atmclip_svc_stop ilmid "Integrated Local Management Interface"
+ atmclip_svc_stop atmsigd "Signaling"
+ fi
+
+ eoutdent
+}
+
+are_atmclip_svcs_running() {
+ is_daemon_running atmarpd || return 1
+ if [[ ${clip_full:-yes} == "yes" ]]; then
+ is_daemon_running ilmid || return 1
+ is_daemon_running atmsigd || return 1
+ fi
+
+ return 0
+}
+
+atmarp() {
+ /usr/sbin/atmarp "$@"
+}
+
+clip_pre_start() {
+ eval $(_get_array "clip_${IFVAR}")
+ [ -z "$@" ] && return 0
+
+ if [ ! -r /proc/net/atm/arp ] ; then
+ modprobe clip && sleep 2
+ if [ ! -r /proc/net/atm/arp ] ; then
+ eerror "You need first to enable kernel support for ATM CLIP"
+ return 1
+ fi
+ fi
+
+ local started_here=
+ if ! are_atmclip_svcs_running ; then
+ atmclip_svcs_start || return 1
+ started_here=1
+ fi
+
+ if ! _exists ; then
+ ebegin "Creating CLIP interface ${IFACE}"
+ atmarp -c "${IFACE}"
+ if ! eend $? ; then
+ [ -z "${started_here}" ] && atmclip_svcs_stop
+ return 1
+ fi
+ fi
+
+ return 0
+}
+
+clip_post_start() {
+ eval $(_get_array "clip_${IFVAR}")
+ [ -z "$@" ] && return 0
+
+ are_atmclip_svcs_running || return 1
+
+ # The atm tools (atmarpd?) are silly enough that they would not work with
+ # iproute2 interface setup as opposed to the ifconfig one.
+ # The workaround is to temporarily toggle the interface state from up
+ # to down and then up again, without touching its address. This (should)
+ # work with both iproute2 and ifconfig.
+ _down
+ _up
+
+ # Now the real thing: create a PVC with our peer(s).
+ # There are cases in which the ATM interface is not yet
+ # ready to establish new VCCs. In that cases, atmarp would
+ # fail. Here we allow 10 retries to happen every 2 seconds before
+ # reporting problems. Also, when no defined VC can be established,
+ # we stop the ATM daemons.
+ local has_failures= i=
+ for i in "$@" ; do
+ set -- ${i}
+ local peerip="$1"; shift
+ local ifvpivci="$1"; shift
+ ebegin "Creating PVC ${ifvpivci} for peer ${peerip}"
+
+ local nleftretries=10 emsg= ecode=
+ while [ ${nleftretries} -gt 0 ] ; do
+ nleftretries=$((${nleftretries} - 1))
+ emsg="$(atmarp -s "${peerip}" "${ifvpivci}" "$@" 2>&1)"
+ ecode=$? && break
+ sleep 2
+ done
+
+ if ! eend ${ecode} ; then
+ eerror "Creation failed for PVC ${ifvpivci}: ${emsg}"
+ has_failures=1
+ fi
+ done
+
+ if [ -n "${has_failures}" ]; then
+ clip_pre_stop "${iface}"
+ clip_post_stop "${iface}"
+ return 1
+ else
+ return 0
+ fi
+}
+
+clip_pre_stop() {
+ are_atmclip_svcs_running || return 0
+
+ # We remove all the PVCs which may have been created by
+ # clip_post_start for this interface. This shouldn't be
+ # needed by the ATM stack, but sometimes I got a panic
+ # killing CLIP daemons without previously vacuuming
+ # every active CLIP PVCs.
+ # The linux 2.6's ATM stack is really a mess...
+ local itf= t= encp= idle= ipaddr= left=
+ einfo "Removing PVCs on this interface"
+ eindent
+ {
+ read left && \
+ while read itf t encp idle ipaddr left ; do
+ if [ "${itf}" = "${IFACE}" ]]; then
+ ebegin "Removing PVC to ${ipaddr}"
+ atmarp -d "${ipaddr}"
+ eend $?
+ fi
+ done
+ } < /proc/net/atm/arp
+ eoutdent
+}
+
+# Here we should teorically delete the interface previously created in the
+# clip_pre_start function, but there is no way to "undo" an interface creation.
+# We can just leave the interface down. "ifconfig -a" will still list it...
+# Also, here we can stop the ATM CLIP daemons if there is no other CLIP PVC
+# outstanding. We check this condition by inspecting the /proc/net/atm/arp file.
+clip_post_stop() {
+ are_atmclip_svcs_running || return 0
+
+ local itf= left= hasothers=
+ {
+ read left && \
+ while read itf left ; do
+ if [ "${itf}" != "${IFACE}" ] ; then
+ hasothers=1
+ break
+ fi
+ done
+ } < /proc/net/atm/arp
+
+ if [ -z "${hasothers}" ] ; then
+ atmclip_svcs_stop || return 1
+ fi
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/ifconfig.sh b/net.Linux/ifconfig.sh
new file mode 100644
index 00000000..637c42f5
--- /dev/null
+++ b/net.Linux/ifconfig.sh
@@ -0,0 +1,239 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+ifconfig_depend() {
+ program /sbin/ifconfig
+ provide interface
+}
+
+_get_mac_address() {
+ local mac=$(LC_ALL=C ifconfig "${IFACE}" | \
+ sed -n -e 's/.* HWaddr \(..:..:..:..:..:..\).*/\1/p')
+
+
+ case "${mac}" in
+ 00:00:00:00:00:00) ;;
+ 44:44:44:44:44:44) ;;
+ FF:FF:FF:FF:FF:FF) ;;
+ "") ;;
+ *) echo "${mac}"; return 0 ;;
+ esac
+
+ return 1
+}
+
+_up() {
+ ifconfig "${IFACE}" up
+}
+
+_down() {
+ ifconfig "${IFACE}" down
+}
+
+_exists() {
+ grep -Eq "^[[:space:]]*${IFACE}:[[:space:]]*" /proc/net/dev
+}
+
+_ifindex() {
+ local line= i=-2
+ while read line ; do
+ i=$((${i} + 1))
+ [ ${i} -lt 1 ] && continue
+ case "${line}" in
+ "${IFACE}: "*) echo "${i}"; return 0;;
+ esac
+ done < /proc/net/dev
+ return 1
+}
+
+_is_wireless() {
+ # Support new sysfs layout
+ [ -d /sys/class/net/"${IFACE}"/wireless ] && return 0
+
+ [ ! -e /proc/net/wireless ] && return 1
+ grep -Eq "^[[:space:]]*${IFACE}:[[:space:]]+" /proc/net/wireless
+}
+
+_get_inet_address() {
+ set -- $(LC_ALL=C ifconfig "${IFACE}" |
+ sed -n -e 's/.*inet addr:\([^ ]*\).*Mask:\([^ ]*\).*/\1 \2/p')
+ echo -n "$1"
+ shift
+ echo "/$(_netmask2cidr "$1")"
+}
+
+_get_inet_addresses() {
+ local iface=${IFACE} i=0
+ local addrs="$(_get_inet_address)"
+
+ while true ; do
+ local IFACE="${iface}:${i}"
+ _exists || break
+ local addr="$(_get_inet_address)"
+ [ -n "${addr}" ] && addrs="${addrs}${addrs:+ }${addr}"
+ i=$((${i} + 1))
+ done
+ echo "${addrs}"
+}
+
+_cidr2netmask() {
+ local cidr="$1" netmask="" done=0 i=0 sum=0 cur=128
+ local octets= frac=
+
+ local octets=$((${cidr} / 8))
+ local frac=$((${cidr} % 8))
+ while [ ${octets} -gt 0 ] ; do
+ netmask="${netmask}.255"
+ octets=$((${octets} - 1))
+ done=$((${done} + 1))
+ done
+
+ if [ ${done} -lt 4 ] ; then
+ while [ ${i} -lt ${frac} ] ; do
+ sum=$((${sum} + ${cur}))
+ cur=$((${cur} / 2))
+ i=$((i + 1))
+ done
+ netmask="${netmask}.${sum}"
+ done=$((${done} + 1))
+
+ while [ ${done} -lt 4 ] ; do
+ netmask="${netmask}.0"
+ done=$((${done} + 1))
+ done
+ fi
+
+ echo "${netmask#.*}"
+}
+
+_add_address() {
+ if [ "$1" = "127.0.0.1/8" -a "${IFACE}" = "lo" ] ; then
+ ifconfig "${IFACE}" "$@" 2>/dev/null
+ return 0
+ fi
+
+ case "$1" in
+ *:*) ifconfig "${IFACE}" inet6 add "$@"; return $?;;
+ esac
+
+ # IPv4 is tricky - ifconfig requires an aliased device
+ # for multiple addresses
+ local iface="${IFACE}"
+ if LC_ALL=C ifconfig "${iface}" | grep -Eq "\<inet addr:.*" ; then
+ # Get the last alias made for the interface and add 1 to it
+ i=$(ifconfig | sed '1!G;h;$!d' | grep -m 1 -o "^${iface}:[0-9]*" \
+ | sed -n -e 's/'"${iface}"'://p')
+ i=$((${i:-0} + 1))
+ iface="${iface}:${i}"
+ fi
+
+ # ifconfig doesn't like CIDR addresses
+ local ip="${1%%/*}" cidr="${1##*/}" netmask=
+ if [ -n "${cidr}" -a "${cidr}" != "${ip}" ]; then
+ netmask="$(_cidr2netmask "${cidr}")"
+ shift
+ set -- "${ip}" netmask "${netmask}" "$@"
+ fi
+
+# # Support iproute2 style config where possible
+# r="${config[@]}"
+# config=( ${r//brd +/} )
+# config=( "${config[@]//brd/broadcast}" )
+# config=( "${config[@]//peer/pointopoint}" )
+# fi
+
+ ifconfig "${iface}" "$@"
+}
+
+_add_route() {
+ if [ $# -eq 3 ] ; then
+ set -- "$1" "$2" gw "$3"
+ elif [ "$3" = "via" ] ; then
+ local one=$1 two=$2
+ shift ; shift; shift
+ set -- "${one}" "${two}" gw "$@"
+ fi
+
+ if [ -n "${metric}" ] ; then
+ set -- "$@" metric ${metric}
+ fi
+
+ route add "$@"
+}
+
+_delete_addresses() {
+ # We don't remove addresses from aliases
+ case "${IFACE}" in
+ *:*) return 0 ;;
+ esac
+
+ einfo "Removing addresses"
+ eindent
+ # iproute2 can add many addresses to an iface unlike ifconfig ...
+ # iproute2 added addresses cause problems for ifconfig
+ # as we delete an address, a new one appears, so we have to
+ # keep polling
+ while true ; do
+ local addr=$(LC_ALL=C ifconfig "${IFACE}" |
+ sed -n -e 's/.*inet addr:\([^ ]*\).*/\1/p')
+
+ [ -z "${addr}" ] && break
+
+ if [ "${addr}" = "127.0.0.1/8" ] ; then
+ # Don't delete the loopback address
+ [ "${IFACE}" = "lo" -o "${IFACE}" = "lo0" ] && break
+ fi
+ ifconfig "${IFACE}" 0.0.0.0 || break
+ done
+
+ # Remove IPv6 addresses
+ local addr=
+ for addr in $(LC_ALL=C ifconfig "${IFACE}" | \
+ sed -n -e 's/^.*inet6 addr: \([^ ]*\) Scope:[^L].*/\1/p') ; do
+ [ "${addr}" = "::1/128" -a "${IFACE}" = "lo" ] && continue
+ einfo "${addr}"
+ ifconfig "${IFACE}" inet6 del "${addr}"
+ done
+
+ return 0
+}
+
+_has_carrier() {
+ return 0
+}
+
+_tunnel() {
+ iptunnel "$@"
+}
+
+ifconfig_pre_start() {
+ # MTU support
+ local mtu=
+ eval mtu=\$mtu_${IFVAR}
+ [ -n "${mtu}" ] && ifconfig "${IFACE}" mtu "${mtu}"
+
+ local tunnel=
+
+ eval tunnel=\$iptunnel_${IFVAR}
+ [ -z "${tunnel}" ] && return 0
+
+ # Set our base metric to 1000
+ metric=1000
+
+ ebegin "Creating tunnel ${IFVAR}"
+ iptunnel add "${tunnel}"
+ eend $?
+}
+
+ifconfig_post_stop() {
+ # Don't delete sit0 as it's a special tunnel
+ [ "${IFACE}" = "sit0" ] && return 0
+
+ [ -z "$(iptunnel show "${IFACE}" 2>/dev/null)" ] && return 0
+
+ ebegin "Destroying tunnel ${IFACE}"
+ iptunnel del "${IFACE}"
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/ifplugd.sh b/net.Linux/ifplugd.sh
new file mode 100644
index 00000000..23dc48cc
--- /dev/null
+++ b/net.Linux/ifplugd.sh
@@ -0,0 +1,91 @@
+# Copyright 2005-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+_config_vars="$_config_vars plug_timeout"
+
+ifplugd_depend() {
+ program start /usr/sbin/ifplugd
+ after macnet rename
+ before interface
+ provide plug
+}
+
+ifplugd_pre_start() {
+ local pidfile="/var/run/ifplugd.${IFACE}.pid" timeout= args=
+
+ # We don't start netplug if we're being called from the background
+ ${IN_BACKGROUND} && return 0
+
+ _exists || return 0
+
+ # We need a valid MAC address
+ # It's a basic test to ensure it's not a virtual interface
+ if ! _get_mac_address >/dev/null 2>/dev/null ; then
+ vewarn "netplug only works on interfaces with a valid MAC address"
+ return 0
+ fi
+
+ # We don't work on bonded, bridges, tun/tap, vlan or wireless
+ for f in bond bridge tuntap vlan wireless ; do
+ if type "_is_${f}" >/dev/null 2>/dev/null ; then
+ if _is_${f} ; then
+ veinfo "netplug does not work with" "${f}"
+ return 0
+ fi
+ fi
+ done
+
+ ebegin "Starting ifplugd on" "${IFACE}"
+
+ eval args=\$ifplugd_${IFVAR}
+
+ # Mark the us as inactive so netplug can restart us
+ mark_service_inactive "${SVCNAME}"
+
+ # Start ifplugd
+ eval start-stop-daemon --start --exec /usr/sbin/ifplugd \
+ --pidfile "${pidfile}" -- "${args}" --iface="${IFACE}"
+ eend "$?" || return 1
+
+ eindent
+
+ eval timeout=\$plug_timeout_${IFVAR}
+ [ -z "${timeout}" ] && timeout=-1
+ if [ ${timeout} -eq 0 ] ; then
+ ewarn "WARNING: infinite timeout set for" "${IFACE}" "to come up"
+ elif [ ${timeout} -lt 0 ] ; then
+ einfo "Backgrounding ..."
+ exit 1
+ fi
+
+ veinfo "Waiting for" "${IFACE}" "to be marked as started"
+
+ local i=0
+ while true ; do
+ if service_started "${SVCNAME}" ; then
+ _show_address
+ exit 0
+ fi
+ sleep 1
+ [ ${timeout} -eq 0 ]] && continue
+ i=$((${i} + 1))
+ [ ${i} -ge ${timeout} ] && break
+ done
+
+ eend 1 "Failed to configure" "${IFACE}" "in the background"
+ exit 1
+}
+
+ifplugd_stop() {
+ ${IN_BACKGROUND} && return 0
+
+ local pidfile="/var/run/ifplugd.${IFACE}.pid"
+ [ ! -e "${pidfile}" ] && return 0
+
+ ebegin "Stopping ifplugd on" "${IFACE}"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/ifplugd \
+ --pidfile "${pidfile}" --signal QUIT
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/ip6to4.sh b/net.Linux/ip6to4.sh
new file mode 100644
index 00000000..03d4fac3
--- /dev/null
+++ b/net.Linux/ip6to4.sh
@@ -0,0 +1,97 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+_config_vars="$_config_vars link suffix relay"
+
+ip6to4_depend() {
+ after interface
+}
+
+ip6to4_start() {
+ case " ${MODULES} " in
+ *" ifconfig "*)
+ if [ "${IFACE}" != "sit0" ] ; then
+ eerror "ip6to4 can only work on the sit0 interface using ifconfig"
+ eerror "emerge sys-apps/iproute2 to use other interfaces"
+ return 1
+ fi
+ esac
+
+ local host= suffix= relay= addr= iface=${IFACE} new=
+ eval host=\$link_${IFVAR}
+ if [ -z "${host}" ] ; then
+ eerror "link_${IFVAR} not set"
+ return 1
+ fi
+
+ eval suffix=\${suffix_${IFVAR}:-1}
+ eval relay=\${relay_${IFVAR}:-192.88.99.1}
+
+ IFACE=${host}
+ addrs=$(_get_inet_addresses)
+ IFACE=${iface}
+ if [ -z "${addrs}" ] ; then
+ eerror "${host} is not configured with an IPv4 address"
+ return 1
+ fi
+
+ for addr in ${addrs} ; do
+ # Strip the subnet
+ local ip="${addr%/*}" subnet="${addr#*/}"
+ # We don't work on private IPv4 addresses
+ case "${ip}" in
+ 127.*) continue ;;
+ 10.*) continue ;;
+ 192.168.*) continue ;;
+ 172.*)
+ local i=16
+ while [ ${i} -lt 32 ] ; do
+ case "${ip}" in
+ 172.${i}.*) break ;;
+ esac
+ i=$((${i} + 1))
+ done
+ [ ${i} -lt 32 ] && continue
+ ;;
+ esac
+
+ veinfo "IPv4 address on ${host}: ${ip}/${subnet}"
+ local OIFS=$IFS SIFS=${IFS-y} ipa= ip6=
+ IFS="${IFS}."
+ for i in ${ip} ; do
+ ipa="${ipa} ${i}"
+ done
+ if [ "${SIFS}" = "y" ] ; then
+ IFS=$OIFS
+ else
+ unset IFS
+ fi
+ eval ip6="$(printf "2002:%02x%02x:%02x%02x::%s" ${ipa} ${suffix})"
+ veinfo "Derived IPv6 address: ${ip6}"
+
+ # Now apply our IPv6 address to our config
+ new="${new}${new:+ }${ip6}/16"
+ done
+
+ if [ -z "${new}" ] ; then
+ eerror "No global IPv4 addresses found on interface ${host}"
+ return 1
+ fi
+
+ if [ "${IFACE}" != "sit0" ] ; then
+ ebegin "Creating 6to4 tunnel on ${IFACE}"
+ _tunnel add "${IFACE}" mode sit ttl 255 remote any local "${ip}"
+ eend $? || return 1
+ _up
+ fi
+
+ # Now apply our config
+ eval config_${config_index}=\'"${new}"\'
+ config_index=$((${config_index} - 1))
+
+ # Add a route for us, ensuring we don't delete anything else
+ eval $(_get_array "routes_${IFVAR}")
+ eval routes_${IFVAR}="\"$@ '2003::/3 via ::${relay} metric 2147483647'\""
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/ipppd.sh b/net.Linux/ipppd.sh
new file mode 100644
index 00000000..faf0cda0
--- /dev/null
+++ b/net.Linux/ipppd.sh
@@ -0,0 +1,47 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+ipppd_depend() {
+ program start /usr/sbin/ipppd
+ after macnet
+ before interface
+ provide isdn
+}
+
+_config_vars="$_config_vars ipppd"
+
+ipppd_pre_start() {
+ local opts= pidfile="/var/run/ipppd-${IFACE}.pid"
+
+ # Check that we are a valid ippp interface
+ case "${IFACE}" in
+ ippp[0-9]*) ;;
+ *) return 0 ;;
+ esac
+
+ # Check that the interface exists
+ _exists || return 1
+
+ # Might or might not be set in conf.d/net
+ eval opts=\$ipppd_${IFVAR}
+
+ einfo "Starting ipppd for ${IFACE}"
+ start-stop-daemon --start --exec /usr/sbin/ipppd \
+ --pidfile "${pidfile}" \
+ -- ${opts} pidfile "${pidfile}" \
+ file "/etc/ppp/options.${IFACE}" >/dev/null
+ eend $?
+}
+
+ipppd_post_stop() {
+ local pidfile="/var/run/ipppd-${IFACE}.pid"
+
+ [ ! -f "${pidfile}" ] && return 0
+
+ einfo "Stopping ipppd for ${IFACE}"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/ipppd \
+ --pidfile "${pidfile}"
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/iproute2.sh b/net.Linux/iproute2.sh
new file mode 100644
index 00000000..1b1b70fa
--- /dev/null
+++ b/net.Linux/iproute2.sh
@@ -0,0 +1,185 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+iproute2_depend() {
+ program /sbin/ip
+ provide interface
+ after ifconfig
+}
+
+_get_mac_address() {
+ local mac=$(LC_ALL=C ip link show "${IFACE}" | sed -n \
+ -e 'y/abcdef/ABCDEF/' \
+ -e '/link\// s/^.*\<\(..:..:..:..:..:..\)\>.*/\1/p')
+
+ case "${mac}" in
+ 00:00:00:00:00:00) ;;
+ 44:44:44:44:44:44) ;;
+ FF:FF:FF:FF:FF:FF) ;;
+ "") ;;
+ *) echo "${mac}"; return 0 ;;
+ esac
+
+ return 1
+}
+
+_up() {
+ ip link set up dev "${IFACE}"
+}
+
+_down() {
+ ip link set down dev "${IFACE}"
+}
+
+_exists() {
+ grep -Eq "^[[:space:]]*${IFACE}:[[:space:]]*" /proc/net/dev
+}
+
+_ifindex() {
+ local line= i=-2
+ while read line ; do
+ i=$((${i} + 1))
+ [ ${i} -lt 1 ] && continue
+ case "${line}" in
+ "${IFACE}: "*) echo "${i}"; return 0;;
+ esac
+ done < /proc/net/dev
+ return 1
+}
+
+_is_wireless() {
+ # Support new sysfs layout
+ [ -d /sys/class/net/"${IFACE}"/wireless ] && return 0
+
+ [ ! -e /proc/net/wireless ] && return 1
+ grep -Eq "^[[:space:]]*${IFACE}:[[:space:]]+" /proc/net/wireless
+}
+
+_get_inet_addresses() {
+ LC_ALL=C ip -family inet addr show "${IFACE}" | \
+ sed -n -e 's/.*inet \([^ ]*\).*/\1/p'
+}
+
+_get_inet_address() {
+ set -- $(_get_inet_addresses)
+ [ $# = "0" ] && return 1
+ echo "$1"
+}
+
+_add_address() {
+ if [ "$1" = "127.0.0.1/8" -a "${IFACE}" = "lo" ] ; then
+ ip addr add "$@" dev "${IFACE}" 2>/dev/null
+ return 0
+ fi
+
+ # Convert an ifconfig line to iproute2
+ if [ "$2" = "netmask" ] ; then
+ local one="$1" three="$3"
+ shift ; shift ; shift
+ set -- "${one}/$(_netmask2cidr "${three}")" "$@"
+ fi
+
+ #config=( "${config[@]//pointopoint/peer}" )
+
+ # Always scope lo addresses as host unless specified otherwise
+ if [ "${IFACE}" = "lo" ] ; then
+ set -- "$@" "scope" "host"
+ fi
+
+ # IPv4 specifics
+ case "$1" in
+ *.*.*.*)
+ case "$@" in
+ *" brd "*) ;;
+ *" broadcast "*) ;;
+ *) set -- "$@" brd + ;;
+ esac
+ ;;
+ esac
+
+ ip addr add dev "${IFACE}" "$@"
+}
+
+_add_route() {
+ if [ $# -eq 3 ] ; then
+ set -- "$1" "$2" via "$3"
+ elif [ "$3" = "gw" ] ; then
+ local one=$1 two=$2
+ shift ; shift; shift
+ set -- "${one}" "${two}" gw "$@"
+ fi
+
+ local cmd= have_metric=false
+ while [ -n "$1" ] ; do
+ case "$1" in
+ metric) cmd="${cmd} $1"; have_metric=true ;;
+ netmask) cmd="${cmd}/$(_netmask2cidr "$2")"; shift ;;
+ -net) ;;
+ -A) [ "$2" = "inet6" ] && shift ;;
+ -host) cmd="${cmd} scope host" ;;
+ *) cmd="${cmd} $1" ;;
+ esac
+ shift
+ done
+
+ if ! ${have_metric} && [ -n "${metric}" ] ; then
+ cmd="${cmd} metric ${metric}"
+ fi
+
+ ip route append ${cmd} dev "${IFACE}"
+ eend $?
+}
+
+_delete_addresses() {
+ ip addr flush dev "${IFACE}" scope global 2>/dev/null
+ ip addr flush dev "${IFACE}" scope site 2>/dev/null
+ if [ "${IFACE}" != "lo" ] ; then
+ ip addr flush dev "${IFACE}" scope host 2>/dev/null
+ fi
+ return 0
+}
+
+_has_carrier() {
+ return 0
+}
+
+_tunnel() {
+ ip tunnel "$@"
+}
+
+iproute2_pre_start() {
+ # MTU support
+ local mtu=
+ eval mtu=\$mtu_${IFVAR}
+ [ -n "${mtu}" ] && ip link set mtu "${mtu}" dev "${IFACE}"
+
+ local tunnel=
+ eval tunnel=\$iptunnel_${IFVAR}
+ if [ -n "${tunnel}" ] ; then
+ # Set our base metric to 1000
+ metric=1000
+
+ ebegin "Creating tunnel ${IFVAR}"
+ ip tunnel add "${tunnel}"
+ eend $? || return 1
+ fi
+
+ return 0
+}
+
+iproute2_post_start() {
+ ip route flush cache dev "${IFACE}"
+}
+
+iproute2_post_stop() {
+ # Don't delete sit0 as it's a special tunnel
+ if [ "${IFACE}" != "sit0" ] ; then
+ if [ -n "$(ip tunnel show "${IFACE}" 2>/dev/null)" ] ; then
+ ebegin "Destroying tunnel ${IFACE}"
+ ip tunnel del "${IFACE}"
+ eend $?
+ fi
+ fi
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/iwconfig.sh b/net.Linux/iwconfig.sh
new file mode 100644
index 00000000..bed13a54
--- /dev/null
+++ b/net.Linux/iwconfig.sh
@@ -0,0 +1,710 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+# Many thanks to all the people in the Gentoo forums for their ideas and
+# motivation for me to make this and keep on improving it
+
+_config_vars="$_config_vars essid mode associate_timeout sleep_scan preferred_aps blacklist_aps"
+
+iwconfig_depend() {
+ program /sbin/iwconfig
+ after plug
+ before interface
+ provide wireless
+}
+
+iwconfig_get_wep_status() {
+ local mode= status="disabled"
+
+ # No easy way of doing this grep in bash regex :/
+ if LC_ALL=C iwconfig "${IFACE}" | grep -qE "^ +Encryption key:[*0-9,A-F]" ; then
+ status="enabled"
+ mode=$(LC_ALL=C iwconfig "${IFACE}" | sed -n -e 's/^.*Security mode:\(.*[^ ]\).*/\1/p')
+ [ -n "${mode}" ] && mode=" - ${mode}"
+ fi
+
+ echo "(WEP ${status}${mode})"
+}
+
+_get_ssid() {
+ local i=5 ssid=
+
+ while [ ${i} -gt 0 ] ; do
+ ssid=$(iwgetid --raw "${IFACE}")
+ if [ -n "${ssid}" ] ; then
+ echo "${ssid}"
+ return 0
+ fi
+ sleep 1
+ i=$((${i} + 1))
+ done
+
+ return 1
+}
+
+_get_ap_mac_address() {
+ local mac="$(iwgetid --raw --ap "${IFACE}")"
+ case "${mac}" in
+ "00:00:00:00:00:00") return 1 ;;
+ "44:44:44:44:44:44") return 1 ;;
+ "FF:00:00:00:00:00") return 1 ;;
+ "FF:FF:FF:FF:FF:FF") return 1 ;;
+ *) echo "${mac}" ;;
+ esac
+}
+
+iwconfig_get_mode() {
+ LC_ALL=C iwgetid --mode "${IFACE}" | \
+ sed -n -e 's/^.*Mode:\(.*\)/\1/p' | \
+ tr '[:upper:]' '[:lower:]'
+}
+
+iwconfig_set_mode() {
+ local mode="$1"
+ [ "${mode}" = "$(iwconfig_get_mode)" ] && return 0
+
+ # Devicescape stack requires the interface to be down
+ _down
+ iwconfig "${IFACE}" mode "${mode}" || return 1
+ _up
+}
+
+iwconfig_get_type() {
+ LC_ALL=C iwconfig "${IFACE}" | sed -n -e 's/^'"$1"' *\([^ ]* [^ ]*\).*/\1/p'
+}
+
+iwconfig_report() {
+ local mac= m="connected to"
+ local ssid="$(_get_ssid)"
+ local wep_status="$(iwconfig_get_wep_status)"
+ local channel="$(iwgetid --raw --channel "${iface}")"
+ [ -n "${channel}" ] && channel="on channel ${channel} "
+ local mode="$(iwconfig_get_mode)"
+ if [ "${mode}" = "master" ]; then
+ m="configured as"
+ else
+ mac="$(_get_ap_mac_address)"
+ [ -n "${mac}" ] && mac=" at ${mac}"
+ fi
+
+ eindent
+ einfo "${IFACE} ${m} SSID \"${SSID}\"${mac}"
+ einfo "in ${mode} mode ${channel}${wep_status}"
+ eoutdent
+}
+
+iwconfig_get_wep_key() {
+ local mac="$1" key=
+ [ -n "${mac}" ] && mac="$(echo "${mac}" | sed -e 's/://g')"
+ eval key=\$mac_key_${mac}
+ [ -z "${key}" ] && eval key=\$key_${SSIDVAR}
+ if [ -z "${key}" ] ; then
+ echo "off"
+ else
+ set -- ${key}
+ local x= e=false
+ for x in "$@" ; do
+ if [ "${x}" = "enc" ] ; then
+ e=true
+ break
+ fi
+ done
+ ${e} || key="${key} enc open"
+ echo "${key}"
+ fi
+}
+
+iwconfig_user_config() {
+ local conf= var=${SSIDVAR}
+ [ -z "${var}" ] && var=${IFVAR}
+
+ eval "$(_get_array "iwconfig_${var}")"
+ for conf in "$@" ; do
+ if ! eval iwconfig "${IFACE}" "${conf}" ; then
+ ewarn "${IFACE} does not support the following configuration commands"
+ ewarn " ${conf}"
+ fi
+ done
+
+ eval "$(_get_array "iwpriv_${var}")"
+ for conf in "$@" ; do
+ if ! eval iwpriv "${IFACE}" "${conf}" ; then
+ ewarn "${IFACE} does not support the following private ioctls"
+ ewarn " ${conf}"
+ fi
+ done
+}
+
+iwconfig_setup_specific() {
+ local mode="$1" channel=
+ if [ -z "${SSID}" ]; then
+ eerror "${IFACE} requires an SSID to be set to operate in ${mode} mode"
+ eerror "adjust the ssid_${IFVAR} setting in /etc/conf.d/net"
+ return 1
+ fi
+ SSIDVAR=$(_shell_var "${SSID}")
+ local key=$(iwconfig_get_wep_key)
+
+ iwconfig_set_mode "${mode}"
+
+ # Now set the key
+ if ! eval iwconfig "${IFACE}" key "${key}" ; then
+ if [ "${key}" != "off" ]; then
+ ewarn "${IFACE} does not support setting keys"
+ ewarn "or the parameter \"mac_key_${SSIDVAR}\" or \"key_${SSIDVAR}\" is incorrect"
+ fi
+ fi
+
+ # Then set the SSID
+ if ! eval iwconfig "${IFACE}" essid "${SSID}" ; then
+ eerror "${IFACE} does not support setting SSID to \"${ESSID}\""
+ return 1
+ fi
+
+ eval channel=\$channel_${SSIDVAR}
+ [ -z "${channel}" ] && eval channel=\$channel_${IFVAR}
+ # We default the channel to 3
+ if ! iwconfig "${IFACE}" channel "${channel:-3}" ; then
+ ewarn "${IFACE} does not support setting the channel to \"${channel:-3}\""
+ return 1
+ fi
+
+ # Finally apply the user Config
+ iwconfig_user_config
+
+ iwconfig_report
+ return 0
+}
+
+iwconfig_wait_for_association() {
+ local timeout= i=0
+ eval timeout=\$associate_timeout_${IFVAR}
+ timeout=${timeout:-10}
+
+ [ ${timeout} -eq 0 ] \
+ && vewarn "WARNING: infinite timeout set for association on ${IFACE}"
+
+ while true; do
+ # Use sysfs if we can
+ if [ -e /sys/class/net/"${IFACE}"/carrier ] ; then
+ if [ "$(cat /sys/class/net/"${IFACE}"/carrier)" = "1" ] ; then
+ # Double check we have an essid. This is mainly for buggy
+ # prism54 drivers that always set their carrier on :/
+ [ -n "$(iwgetid --raw "${IFACE}")" ] && return 0
+ fi
+ else
+ local atest=
+ eval atest=\$associate_test_${IFVAR}
+ atest=${atest:-mac}
+ if [ "${atest}" = "mac" -o "${atest}" = "all" ] ; then
+ [ -n "$(_get_ap_mac_address)" ] && return 0
+ fi
+ if [ "${atest}" = "quality" -o "${atest}" = "all" ] ; then
+ [ "$(sed -n -e 's/^.*'"${IFACE}"': *[0-9]* *\([0-9]*\).*/\1/p' \
+ /proc/net/wireless)" != "0" ] && return 0
+ fi
+ fi
+
+ sleep 1
+ [ ${timeout} -eq 0 ] && continue
+ i=$((${i} + 1))
+ [ ${i} -ge ${timeout} ] && return 1
+ done
+ return 1
+}
+
+iwconfig_associate() {
+ local mode="${1:-managed}" mac="$2" wep_required="$3" freq="$4" chan="$5"
+ local w="(WEP Disabled)" key=
+
+ iwconfig_set_mode "${mode}"
+
+ if [ "${SSID}" = "any" ]; then
+ iwconfig "${IFACE}" ap any 2>/dev/null
+ unset ESSIDVAR
+ else
+ SSIDVAR=$(_shell_var "${SSID}")
+ key="$(iwconfig_get_wep_key "${mac}")"
+ if [ "${wep_required}" = "on" -a "${key}" = "off" ] ; then
+ ewarn "WEP key is not set for \"${SSID}\" - not connecting"
+ return 1
+ fi
+ if [ "${wep_required}" = "off" -a "${key}" != "off" ] ; then
+ key="off"
+ ewarn "\"${SSID}\" is not WEP enabled - ignoring setting"
+ fi
+
+ if ! eval iwconfig "${IFACE}" key "${key}" ; then
+ if [ "${key}" != "off" ] ; then
+ ewarn "${IFACE} does not support setting keys"
+ ewarn "or the parameter \"mac_key_${SSIDVAR}\" or \"key_${SSIDVAR}\" is incorrect"
+ return 1
+ fi
+ fi
+ [ "${key}" != "off" ] && w="$(iwconfig_get_wep_status "${iface}")"
+ fi
+
+ if ! eval iwconfig "${IFACE}" essid "${SSID}" ; then
+ if [ "${SSID}" != "any" ] ; then
+ ewarn "${IFACE} does not support setting ESSID to \"${SSID}\""
+ fi
+ fi
+
+ # Only use channel or frequency
+ if [ -n "${chan}" ] ; then
+ iwconfig "${IFACE}" channel "${chan}"
+ elif [ -n "${freq}" ] ; then
+ iwconfig "${IFACE}" freq "${freq}"
+ fi
+ [ -n "${mac}" ] && iwconfig "${IFACE}" ap "${mac}"
+
+ # Finally apply the user Config
+ iwconfig_user_config
+
+ ebegin "Connecting to \"${SSID}\" in ${mode} mode ${w}"
+
+ if [ "${SSID}" != "any" ] && type preassociate >/dev/null 2>/dev/null ; then
+ veinfo "Running preassociate function"
+ veindent
+ ( preassociate )
+ local e=$?
+ veoutdent
+ if [ ${e} -eq 0 ] ; then
+ veend 1 "preassociate \"${SSID}\" on ${IFACE} failed"
+ return 1
+ fi
+ fi
+
+ if ! iwconfig_wait_for_association ; then
+ eend 1
+ return 1
+ fi
+ eend 0
+
+ if [ "${SSID}" = "any" ]; then
+ SSID="$(_get_ssid)"
+ iwconfig_associate
+ return $?
+ fi
+
+ iwconfig_report
+
+ if type postassociate >/dev/null 2>/dev/null ; then
+ veinfo "Running postassociate function"
+ veindent
+ ( postassociate )
+ veoutdent
+ fi
+
+ return 0
+}
+
+iwconfig_scan() {
+ local x= i=0 scan=
+ einfo "Scanning for access points"
+ eindent
+
+ # Sleep if required
+ eval x=\$sleep_scan_${IFVAR}
+ [ -n "${x}" ] && sleep "${x}"
+
+ while [ ${i} -lt 3 ] ; do
+ scan="${scan} $(iwlist "${IFACE}" scan 2>/dev/null | sed -e "s/'/'\\\\''/g" -e "s/$/'/g" -e "s/^/'/g")"
+ i=$((${i} + 1))
+ done
+
+ if [ -z "${scan}" ] ; then
+ ewarn "${iface} does not support scanning"
+ eoutdent
+ eval x=\$adhoc_essid_${IFVAR}
+ [ -n "${x}" ] && return 0
+ if [ -n "${preferred_aps}" ] ; then
+ [ "${associate_order}" = "forcepreferred" ] || \
+ [ "${associate_order}" = "forcepreferredonly" ] && return 0
+ fi
+ eerror "You either need to set a preferred_aps list in /etc/conf.d/wireless"
+ eerror " preferred_aps=\"SSID1 SSID2\""
+ eerror " and set associate_order_${IFVAR}=\"forcepreferred\""
+ eerror " or set associate_order_${IFVAR}=\"forcepreferredonly\""
+ eerror "or hardcode the SSID to \"any\" and let the driver find an Access Point"
+ eerror " ssid_${IFVAR}=\"any\""
+ eerror "or configure defaulting to Ad-Hoc when Managed fails"
+ eerror " adhoc_essid_${IFVAR}=\"WLAN\""
+ eerror "or hardcode the ESSID against the interface (not recommended)"
+ eerror " essid_${IFVAR}=\"ESSID\""
+ return 1
+ fi
+
+ local OIFS=$IFS
+ APS=-1
+ eval set -- ${scan}
+ for line in "$@" ; do
+ case "${line}" in
+ *Address:*)
+ APS=$((${APS} + 1))
+ eval MAC_${APS}=\""$(echo "${line#*: }" | tr '[:lower:]' '[:upper:]')"\"
+ eval QUALITY_${APS}=0
+ ;;
+ *ESSID:*)
+ x=${line#*\"}
+ x=${x%*\"}
+ eval SSID_${APS}=\$x
+ ;;
+ *Mode:*)
+ x="$(echo "${line#*:}" | tr '[:upper:]' '[:lower:]')"
+ if [ "${x}" = "master" ] ; then
+ eval MODE_${APS}=\"managed\"
+ else
+ eval MODE_${APS}=\$x
+ fi
+ ;;
+ *'Encryption key:'*)
+ x=${line#*:}
+ eval ENC_${APS}=\$x
+ ;;
+ #*Frequency:*)
+ # freq[i]="${line#*:}"
+ # x="${freq[i]#* }"
+ # freq[i]="${freq[i]%% *}${x:0:1}"
+ # ;;
+ *Channel:*)
+ x=${line#*:}
+ x=${x%% *}
+ eval CHAN_${APS}=\$x
+ ;;
+ *Quality*)
+ x=${line#*:}
+ x=${x%/*}
+ x="$(echo "${x}" | sed -e 's/[^[:digit:]]//g')"
+ x=${x:-0}
+ eval QUALITY_${APS}=\$x
+ ;;
+ esac
+ done
+
+ if [ -z "${MAC_0}" ]; then
+ ewarn "no access points found"
+ eoutdent
+ return 1
+ fi
+
+ # Sort based on quality
+ local i=0 k=1 a= b= x= t=
+ while [ ${i} -lt ${APS} ] ; do
+ k=$((${i} + 1))
+ while [ ${k} -le ${APS} ] ; do
+ eval a=\$QUALITY_${i}
+ [ -z "${a}" ] && break
+ eval b=\$QUALITY_${k}
+ if [ -n "${b}" -a "${a}" -lt "${b}" ] ; then
+ for x in MAC SSID CHAN QUALITY ENC ; do
+ eval t=\$${x}_${i}
+ eval ${x}_${i}=\$${x}_${k}
+ eval ${x}_${k}=\$t
+ done
+ fi
+ k=$((${k} + 1))
+ done
+ i=$((${i} + 1))
+ done
+
+ # Strip any duplicates
+ local i=0 k=1 a= b=
+ while [ ${i} -lt ${APS} ] ; do
+ k=$((${i} + 1))
+ while [ ${k} -le ${APS} ] ; do
+ eval a=\$MAC_${i}
+ eval b=\$MAC_${k}
+ if [ "${a}" = "${b}" ] ; then
+ eval a=\$QUALITY_${i}
+ eval b=\$QUALITY_${k}
+ if [ -n "${a}" -a -n "${b}" ] ; then
+ if [ ${a} -ge ${b} ] ; then
+ unset MAC_${k} SSID_${k} CHAN_${k} QUALITY_${k} ENC_${k}
+ else
+ unset MAC_${i} SSID_${i} CHAN_${i} QUALITY_${i} ENC_${i}
+ fi
+ else
+ unset MAC_${k} SSID_${k} CHAN_${k} QUALITY_${k} ENC_${k}
+ fi
+ fi
+ k=$((${k} + 1))
+ done
+ i=$((${i} + 1))
+ done
+
+ local i=0 e= m= black= s=
+ eval "$(_get_array "blacklist_aps")"
+ black="$@"
+
+ while [ ${i} -le ${APS} ] ; do
+ eval x=\$MAC_${i}
+ if [ -z "${x}" ] ; then
+ i=$((${i} + 1))
+ continue
+ fi
+
+ eval m=\$MODE_${i}
+ eval s=\$SSID_${i}
+ eval q=\$QUALITY_${i}
+ eval e=\$ENC_${i}
+ if [ -n "${e}" -a "${e}" != "off" ] ; then
+ e=", encrypted"
+ else
+ e=""
+ fi
+ if [ -z "${s}" ] ; then
+ einfo "Found ${x}, ${m}${e}"
+ else
+ einfo "Found \"${s}\" at ${x}, ${m}${e}"
+ fi
+
+ x="$(echo "${x}" | sed -e 's/://g')"
+ eval x=\$mac_ssid_${x}
+ if [ -n "${x}" ] ; then
+ eval SSID_${i}=\$x
+ s=${x}
+ eindent
+ einfo "mapping to \"${x}\""
+ eoutdent
+ fi
+
+ eval "$(_get_array "blacklist_aps")"
+ for x in "$@" ; do
+ if [ "${x}" = "${s}" ] ; then
+ ewarn "${s} has been blacklisted - not connecting"
+ unset SSID_${i} MAC_${i} CHAN_${i} QUALITY_${i} ENC_${i}
+ fi
+ done
+ i=$((${i} + 1))
+ done
+ eoutdent
+}
+
+iwconfig_force_preferred() {
+ [ -z "${preferred_aps}" ] && return 1
+
+ ewarn "Trying to force preferred in case they are hidden"
+ eval "(_get_array "preferred_aps")"
+ local ssid=
+ for ssid in "$@"; do
+ local found_AP=false i=0 e=
+ while [ ${i} -le ${APS} ] ; do
+ eval e=\$SSID_${i}
+ if [ "${e}" = "${ssid}" ] ; then
+ found_AP=true
+ break
+ fi
+ i=$((${i} + 1))
+ done
+ if ! ${found_AP} ; then
+ SSID=${e}
+ iwconfig_associate && return 0
+ fi
+ done
+
+ ewarn "Failed to associate with any preferred access points on ${IFACE}"
+ return 1
+}
+
+iwconfig_connect_preferred() {
+ local essid= i=0 mode= mac= enc= freq= chan=
+
+ eval "$(_get_array preferred_aps)"
+ for essid in "$@"; do
+ while [ ${i} -le ${APS} ] ; do
+ eval e=\$SSID_${i}
+ if [ "${e}" = "${essid}" ] ; then
+ SSID=${e}
+ eval mode=\$MODE_${i}
+ eval mac=\$MAC_${i}
+ eval enc=\$ENC_${i}
+ eval freq=\$FREQ_${i}
+ eval chan=\$CHAN_${i}
+ iwconfig_associate "${mode}" "${mac}" "${enc}" "${freq}" \
+ "${chan}" && return 0
+ fi
+ i=$((${i} + 1))
+ done
+ done
+
+ return 1
+}
+
+iwconfig_connect_not_preferred() {
+ local essid= i=0 mode= mac= enc= freq= chan= pref=false
+
+ while [ ${i} -le ${APS} ] ; do
+ eval e=\$SSID_${i}
+ eval "$(_get_array preferred_aps)"
+ for essid in "$@" ; do
+ if [ "${e}" = "${essid}" ] ; then
+ pref=true
+ break
+ fi
+ done
+
+ if ! ${pref} ; then
+ SSID=${e}
+ eval mode=\$MODE_${i}
+ eval mac=\$MAC_${i}
+ eval enc=\$ENC_${i}
+ eval freq=\$FREQ_${i}
+ eval chan=\$CHAN_${i}
+ iwconfig_associate "${mode}" "${mac}" "${enc}" "${freq}" \
+ "${chan}" && return 0
+ fi
+ i=$((${i} + 1))
+ done
+
+ return 1
+}
+
+iwconfig_defaults() {
+ local x=
+ for x in txpower rate rts frag ; do
+ iwconfig "${IFACE}" "${x}" auto 2>/dev/null
+ done
+
+ # Release the AP forced
+ # Must do ap and then essid otherwise scanning borks
+ iwconfig "${IFACE}" ap off 2>/dev/null
+ iwconfig "${IFACE}" essid off 2>/dev/null
+}
+
+iwconfig_configure() {
+ local x APS
+ eval ESSID=\$ssid_${IFVAR}
+
+ # Setup ad-hoc mode?
+ eval x=\$mode_${IFVAR}
+ x=${x:-managed}
+ if [ "${x}" = "ad-hoc" -o "${x}" = "master" ] ; then
+ iwconfig_setup_specific "${x}"
+ return $?
+ fi
+
+ if [ "${x}" != "managed" -a "${x}" != "auto" ] ; then
+ eerror "Only managed, ad-hoc, master and auto modes are supported"
+ return 1
+ fi
+
+ # Has an ESSID been forced?
+ if [ -n "${ESSID}" ]; then
+ iwconfig_set_mode "${x}"
+ iwconfig_associate && return 0
+ [ "${ESSID}" = "any" ] && iwconfig_force_preferred && return 0
+
+ eval ESSID=\$adhoc_essid_${IFVAR}
+ if [ -n "${ESSID}" ]; then
+ iwconfig_setup_specific ad-hoc
+ return $?
+ fi
+ return 1
+ fi
+
+ # Do we have a preferred Access Point list specific to the interface?
+# x="preferred_aps_${ifvar}[@]"
+# [[ -n ${!x} ]] && preferred_aps=( "${!x}" )
+
+# # Do we have a blacklist Access Point list specific to the interface?
+# x="blacklist_aps_${ifvar}[@]"
+# [[ -n ${!x} ]] && blacklist_aps=( "${!x}" )
+
+ # Are we forcing preferred only?
+ eval x=\$associate_order_${IFVAR}
+ [ -n "${x}" ] && associate_order=${x}
+ associate_order=${associate_order:-any}
+ if [ "${associate_order}" = "forcepreferredonly" ]; then
+ iwconfig_force_preferred && return 0
+ else
+ iwconfig_scan || return 1
+ iwconfig_connect_preferred && return 0
+ [ "${associate_order}" = "forcepreferred" ] || \
+ [ "${associate_order}" = "forceany" ] && \
+ iwconfig_force_preferred && return 0
+ [ "${associate_order}" = "any" ] || \
+ [ "${associate_order}" = "forceany" ] && \
+ iwconfig_connect_not_preferred && return 0
+ fi
+
+ e="associate with"
+ [ -z "${MAC_0}" ] && e="find"
+ [ "${preferred_aps}" = "force" ] || \
+ [ "${preferred_aps}" = "forceonly" ] && \
+ e="force"
+ e="Couldn't ${e} any access points on ${IFACE}"
+
+ eval SSID=\$adhoc_ssid_${IFVAR}
+ if [ -n "${SSID}" ]; then
+ ewarn "${e}"
+ iwconfig_setup_specific ad-hoc
+ return $?
+ fi
+
+ eerror "${e}"
+ return 1
+}
+
+iwconfig_pre_start() {
+ # We don't configure wireless if we're being called from
+ # the background
+ ${IN_BACKGROUND} && return 0
+
+ save_options "SSID" ""
+ _exists || return 0
+
+ if ! _is_wireless ; then
+ veinfo "Wireless extensions not found for ${IFACE}"
+ return 0
+ fi
+
+ iwconfig_defaults
+ iwconfig_user_config
+
+ # Set the base metric to be 2000
+ metric=2000
+
+ # Check for rf_kill - only ipw supports this at present, but other
+ # cards may in the future.
+ if [ -e /sys/class/net/"${IFACE}"/device/rf_kill ] ; then
+ if [ $(cat /sys/class/net/"${IFACE}"/device/rf_kill) != "0" ] ; then
+ eerror "Wireless radio has been killed for interface ${IFACE}"
+ return 1
+ fi
+ fi
+
+ einfo "Configuring wireless network for ${IFACE}"
+
+ # Are we a proper IEEE device?
+ # Most devices reutrn IEEE 802.11b/g - but intel cards return IEEE
+ # in lower case and RA cards return RAPCI or similar
+ # which really sucks :(
+ # For the time being, we will test prism54 not loading firmware
+ # which reports NOT READY!
+ x="$(iwconfig_get_type)"
+ if [ "${x}" = "NOT READY!" ]; then
+ eerror "Looks like there was a probem loading the firmware for ${IFACE}"
+ return 1
+ fi
+
+ if iwconfig_configure ; then
+ save_options "ESSID" "${ESSID}"
+ return 0
+ fi
+
+ eerror "Failed to configure wireless for ${IFACE}"
+ iwconfig_defaults
+ iwconfig "${IFACE}" txpower off 2>/dev/null
+ unset ESSID ESSIDVAR
+ _down
+ return 1
+}
+
+iwconfig_post_stop() {
+ ${IN_BACKGROUND} && return 0
+ _exists || return 0
+ iwconfig_defaults
+ iwconfig "${IFACE}" txpower off 2>/dev/null
+}
+
+# vim: set ts=4
diff --git a/net.Linux/macchanger.sh b/net.Linux/macchanger.sh
new file mode 100644
index 00000000..9d71513f
--- /dev/null
+++ b/net.Linux/macchanger.sh
@@ -0,0 +1,88 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+macchanger_depend() {
+ before macnet
+}
+
+_config_vars="$_config_vars mac"
+
+macchanger_pre_start() {
+ # We don't change MAC addresses from background
+ ${IN_BACKGROUND} && return 0
+
+ local mac= opts=
+
+ eval mac=\$mac_${IFVAR}
+ [ -z "${mac}" ] && return 0
+
+ _exists true || return 1
+
+ ebegin "Changing MAC address of ${IFACE}"
+
+ # The interface needs to be up for macchanger to work most of the time
+ _down
+
+ mac=$(echo "${mac}" | sed -e 'y/ABCDEF/abcdef')
+ case "${mac}" in
+ # specific mac-addr, i wish there were a shorter way to specify this
+ [0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f])
+ # We don't need macchanger to change to a specific mac address
+ _set_mac_address "${mac}"
+ if eend "$?" ; then
+ mac=$(_get_mac_address)
+ eindent
+ einfo "changed to ${mac}"
+ eoutdent
+ return 0
+ fi
+ ;;
+
+ # increment MAC address, default macchanger behavior
+ increment) opts="${opts}" ;;
+
+ # randomize just the ending bytes
+ random-ending) opts="${opts} -e" ;;
+
+ # keep the same kind of physical layer (eg fibre, copper)
+ random-samekind) opts="${opts} -a" ;;
+
+ # randomize to any known vendor of any physical layer type
+ random-anykind) opts="${opts} -A" ;;
+
+ # fully random bytes
+ random-full|random) opts="${opts} -r" ;;
+
+ # default case is just to pass on all the options
+ *) opts="${opts} ${mac}" ;;
+ esac
+
+ if [ ! -x /sbin/macchanger ] ; then
+ eerror "For changing MAC addresses, emerge net-analyzer/macchanger"
+ return 1
+ fi
+
+ mac=$(LC_ALL=C macchanger ${opts} "${IFACE}" \
+ | sed -n -e 's/^Faked MAC:.*\<\(..:..:..:..:..:..\)\>.*/\1/p' )
+ _up
+
+ # Sometimes the interface needs to be up ....
+ if [ -z "${mac}" ] ; then
+ mac=$(LC_ALL=C macchanger ${opts} "${IFACE}" \
+ | sed -n -e 's/^Faked MAC:.*\<\(..:..:..:..:..:..\)\>.*/\1/p' )
+ fi
+
+ if [ -z "${mac}" ] ; then
+ eend 1 "Failed to set MAC address"
+ return 1
+ fi
+
+ eend 0
+ eindent
+ einfo "changed to" "${mac}"
+ eoutdent
+
+ return 0
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/netplugd.sh b/net.Linux/netplugd.sh
new file mode 100644
index 00000000..170e3a8d
--- /dev/null
+++ b/net.Linux/netplugd.sh
@@ -0,0 +1,93 @@
+# Copyright 2005-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+_config_vars="$_config_vars plug_timeout"
+
+netplugd_depend() {
+ program start /sbin/netplugd
+ after macnet rename
+ before interface
+ provide plug
+
+ # Prefer us to ifplugd
+ after ifplugd
+}
+
+netplugd_pre_start() {
+ local pidfile="/var/run/netplugd-${IFACE}.pid" timeout=
+
+ # We don't start netplug if we're being called from the background
+ ${IN_BACKGROUND} && return 0
+
+ _exists || return 0
+
+ # We need a valid MAC address
+ # It's a basic test to ensure it's not a virtual interface
+ if ! _get_mac_address >/dev/null 2>/dev/null ; then
+ vewarn "netplug only works on interfaces with a valid MAC address"
+ return 0
+ fi
+
+ # We don't work on bonded, bridges, tun/tap, vlan or wireless
+ for f in bond bridge tuntap vlan wireless ; do
+ if type "_is_${f}" >/dev/null 2>/dev/null ; then
+ if _is_${f} ; then
+ veinfo "netplug does not work with" "${f}"
+ return 0
+ fi
+ fi
+ done
+
+ ebegin "Starting netplug on" "${IFACE}"
+
+ # Mark the us as inactive so netplug can restart us
+ mark_service_inactive "${SVCNAME}"
+
+ # Start netplug
+ start-stop-daemon --start --exec /sbin/netplugd \
+ --pidfile "${pidfile}" \
+ -- -i "${IFACE}" -P -p "${pidfile}" -c /dev/null
+ eend "$?" || return 1
+
+ eindent
+
+ eval timeout=\$plug_timeout_${IFVAR}
+ [ -z "${timeout}" ] && timeout=-1
+ if [ ${timeout} -eq 0 ] ; then
+ ewarn "WARNING: infinite timeout set for" "${IFACE}" "to come up"
+ elif [ ${timeout} -lt 0 ] ; then
+ einfo "Backgrounding ..."
+ exit 1
+ fi
+
+ veinfo "Waiting for" "${IFACE}" "to be marked as started"
+
+ local i=0
+ while true ; do
+ if service_started "${SVCNAME}" ; then
+ _show_address
+ exit 0
+ fi
+ sleep 1
+ [ ${timeout} -eq 0 ]] && continue
+ i=$((${i} + 1))
+ [ ${i} -ge ${timeout} ] && break
+ done
+
+ eend 1 "Failed to configure" "${IFACE}" "in the background"
+ exit 1
+}
+
+netplugd_stop() {
+ ${IN_BACKGROUND} && return 0
+
+ local pidfile="/var/run/netplugd-${IFACE}.pid"
+ [ ! -e "${pidfile}" ] && return 0
+
+ ebegin "Stopping netplug on" "${IFACE}"
+ start-stop-daemon --stop --quiet --exec /sbin/netplugd \
+ --pidfile "${pidfile}"
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/pppd.sh b/net.Linux/pppd.sh
new file mode 100644
index 00000000..72a8e7d4
--- /dev/null
+++ b/net.Linux/pppd.sh
@@ -0,0 +1,219 @@
+# Copyright 2005-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+pppd_depend() {
+ program /usr/sbin/pppd
+ after interface
+ before dhcp
+ provide ppp
+}
+
+is_ppp() {
+ [ -e /var/run/ppp-"${IFACE}".pid ]
+}
+
+requote() {
+ printf "'%s' " "$@"
+}
+
+pppd_start() {
+ ${IN_BACKGROUND} && return 0
+
+ if [ "${iface%%[0-9]*}" != "ppp" ] ; then
+ eerror "PPP can only be invoked from net.ppp[0-9]"
+ return 1
+ fi
+
+ local link= i= opts= unit="${IFACE#ppp}" mtu=
+ if [ -z "${unit}" ] ; then
+ eerror $"PPP requires a unit - use net.ppp[0-9] instead of net.ppp"
+ return 1
+ fi
+
+ # PPP requires a link to communicate over - normally a serial port
+ # PPPoE communicates over Ethernet
+ # PPPoA communicates over ATM
+ # In all cases, the link needs to be available before we start PPP
+ eval link=\$link_${IFVAR}
+ if [ -z "${link}" ] ; then
+ eerror "link_${IFVAR} has not been set in /etc/conf.d/net"
+ return 1
+ fi
+
+ case "${link}" in
+ /*)
+ if [ ! -e "${link}" ] ; then
+ eerror "${link} does not exist"
+ eerror "Please verify hardware or kernel module (driver)"
+ return 1
+ fi
+ ;;
+ esac
+
+ eval $(_get_array "pppd_${IFVAR}")
+ opts="$@"
+
+ # We don't work with these options set by the user
+ for i in "$@" ; do
+ set -- ${i}
+ case "$1" in
+ unit|nodetach|linkname)
+ eerror "The option \"$1\" is not allowed in pppd_${IFVAR}"
+ return 1
+ ;;
+ esac
+ done
+
+ # Might be set in conf.d/net
+ local username= password= passwordset=
+ eval username=\$username_${IFVAR}
+ eval password=\$password_${IFVAR}
+ eval passwordset=\${password_${IFVAR}-x}
+ if [ -n "${username}" ] \
+ && [ -n "${password}" -o -z "${passwordset}" ] ; then
+ opts="${opts} plugin passwordfd.so passwordfd 0"
+ fi
+
+ # Check for mtu/mru
+ local mtu= hasmtu=false hasmru=false hasmaxfail=false haspersits=false
+ loal hasupdetach=false
+ eval mtu=\$mtu_${IFVAR}
+ for i in ${opts} ; do
+ case "${i}" in
+ mtu" "*) hasmtu=true ;;
+ mru" "*) hasmru=true ;;
+ maxfail" "*) hasmaxfail=true ;;
+ persist) haspersist=true ;;
+ updetach) hasupdetach=true;
+ esac
+ done
+ ! ${hasmtu} && opts="${opts} mtu ${mtu}"
+ ! ${hasmru} && opts="${opts} mru ${mtu}"
+ ! ${hasmailfail} && opts="${opts} maxfail 0"
+ ! ${haspersist} && opts="${opts} persist"
+
+ # Set linkname because we need /var/run/ppp-${linkname}.pid
+ # This pidfile has the advantage of being there, even if ${iface} interface was never started
+ opts="linkname ${IFACE} ${opts}"
+
+ # Setup auth info
+ if [ -n "${username}" ] ; then
+ opts="user '"${username}"' remotename ${IFACE} ${opts}"
+ fi
+
+ # Load a custom interface configuration file if it exists
+ [ -f "/etc/ppp/options.${IFACE}" ] \
+ && opts="${opts} file /etc/ppp/options.${IFACE}"
+
+ # Set unit
+ opts="unit ${unit} ${opts}"
+
+ # Setup connect script
+ local chatopts="/usr/sbin/chat -e -E -v"
+ eval $(_get_array "phone_number_${IFVAR}")
+ [ -n "$1" ] && chatopts="${chatopts} -T '$1'"
+ [ -n "$2" ] && chatopts="${chatopts} -U '$2'"
+ eval $(_get_array "chat_${IFVAR}")
+ if [ -n "$@" ] ; then
+ opts="${opts} connect $(printf "'%s' " "${chatopts} $(printf "'%s' " "$@")")"
+ fi
+
+ # Add plugins
+ local haspppoa=false haspppoe=false
+ eval $(_get_array "plugins_${IFVAR}")
+ for i in "$@" ; do
+ set -- ${i}
+ case "${i}" in
+ passwordfd) continue;;
+ pppoa) shift; set -- "rp-pppoe" "$@" ;;
+ pppoe) shift; set -- "pppoatm" "$@" ;;
+ capi) shift; set -- "capiplugin" "$@" ;;
+ esac
+ case "${i}" in
+ rp-pppoe) haspppoe=true ;;
+ pppoatm) haspppoa=true ;;
+ esac
+ if [ "$1" = "rp-pppoe" ] || [ "$1" = "pppoatm" -a "${link}" != "/dev/null" ] ; then
+ opts="${opts} connect true"
+ set -- "$@" "${link}"
+ fi
+ opts="${opts} plugin $1.so"
+ shift
+ opts="${opts} $@"
+ done
+
+ #Specialized stuff. Insert here actions particular to connection type (pppoe,pppoa,capi)
+ local insert_link_in_opts=1
+ if ${haspppoe} ; then
+ if [ ! -e /proc/net/pppoe ] ; then
+ # Load the PPPoE kernel module
+ if ! modprobe pppoe ; then
+ eerror "kernel does not support PPPoE"
+ return 1
+ fi
+ fi
+
+ # Ensure that the link exists and is up
+ ( IFACE="${link}" ; _exists true && _up ) || return 1
+ insert_link_in_opts=0
+ fi
+
+ if ${haspppoa} ; then
+ if [ ! -d /proc/net/atm ] ; then
+ # Load the PPPoA kernel module
+ if ! modprobe pppoatm ; then
+ eerror "kernel does not support PPPoATM"
+ return 1
+ fi
+ fi
+
+ if [ "${link}" != "/dev/null" ] ; then
+ insert_link_in_opts=0
+ else
+ ewarn "WARNING: An [itf.]vpi.vci ATM address was expected in link_${IFVAR}"
+ fi
+
+ fi
+ [ "${insert_link_in_opts}" == "0" ] || opts="${link} ${opts}"
+
+ ebegin "Starting pppd in ${IFACE}"
+ mark_service_inactive "${SVCNAME}"
+ if [ -n "${username}" ] \
+ && [ -n "${password}" -o -z "${passwordset}" ] ; then
+ echo "${password}" | sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' | \
+ eval start-stop-daemon --start --exec /usr/sbin/pppd \
+ --pidfile "/var/run/ppp-${IFACE}.pid" -- "${opts}" >/dev/null
+ else
+ eval start-stop-daemon --start --exec /usr/sbin/pppd \
+ --pidfile "/var/run/ppp-${IFACE}.pid" -- "${opts}" >/dev/null
+ fi
+
+ if ! eend $? $"Failed to start PPP" ; then
+ mark_service_starting "net.${iface}"
+ return 1
+ fi
+
+ if ${hasupdetach} ; then
+ _show_address
+ else
+ einfo "Backgrounding ..."
+ fi
+
+ # pppd will re-call us when we bring the interface up
+ exit 0
+}
+
+pppd_stop() {
+ ${IN_BACKGROUND} && return 0
+ local pidfile="/var/run/ppp-${IFACE}.pid"
+
+ [ ! -s "${pidfile}" ] && return 0
+
+ # Give pppd at least 30 seconds do die, #147490
+ einfo "Stopping pppd on ${IFACE}"
+ start-stop-daemon --stop --quiet --exec /usr/sbin/pppd \
+ --pidfile "${pidfile}" --retry 30
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/pump.sh b/net.Linux/pump.sh
new file mode 100644
index 00000000..fd57fcda
--- /dev/null
+++ b/net.Linux/pump.sh
@@ -0,0 +1,60 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+pump_depend() {
+ program /sbin/pump
+ after interface
+ provide dhcp
+}
+
+_config_vars="$_config_vars dhcp pump"
+
+pump_start() {
+ local args= opt= opts=
+
+ _wait_for_carrier || return 1
+
+ # Get our options
+ eval opts=\$dhcp_${IFVAR}
+ [ -z "${opts}" ] && opts=${dhcp}
+
+ # Map some generic options to dhcpcd
+ for opt in ${opts} ; do
+ case "${opt}" in
+ nodns) args="${args} --no-dns" ;;
+ nontp) args="${args} --no-ntp" ;;
+ nogateway) args="${args} --no-gateway" ;;
+ esac
+ done
+
+ # Add our route metric
+ [ "${metric:-0}" != "0" ] && args="${args} --route-metric ${metric}"
+
+ args="${args} --win-client-ident"
+ args="${args} --keep-up --interface ${IFACE}"
+
+ ebegin "Running pump"
+ eval pump "${args}"
+ eend $? || return 1
+
+ _show_address
+ return 0
+}
+
+pump_stop() {
+ # We check for a pump process first as querying for status
+ # causes pump to spawn a process
+ start-stop-daemon --quiet --test --stop --exec /sbin/pump || return 0
+
+ # Check that pump is running on the interface
+ if ! pump --status --interface "${IFACE}" >/dev/null 2>/dev/null ; then
+ return 0
+ fi
+
+ # Pump always releases the lease
+ ebegin "Stopping pump on ${IFACE}"
+ pump --release --interface "${IFACE}"
+ eend $? "Failed to stop pump"
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/tuntap.sh b/net.Linux/tuntap.sh
new file mode 100644
index 00000000..829bf138
--- /dev/null
+++ b/net.Linux/tuntap.sh
@@ -0,0 +1,57 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+tuntap_depend() {
+ before bridge interface macchanger
+}
+
+_config_vars="$_config_vars tunctl"
+
+_is_tuntap() {
+ [ -n "$(get_options tuntap "${SVCNAME}")" ]
+}
+
+tuntap_pre_start() {
+ local tuntap=
+ eval tuntap=\$tuntap_${IFVAR}
+
+ [ -z "${tuntap}" ] && return 0
+
+ if [ ! -a /dev/net/tun ] ; then
+ modprobe tun && sleep 1
+ if [ ! -a /dev/net/tun ] ; then
+ eerror "TUN/TAP support is not present in this kernel"
+ return 1
+ fi
+ fi
+
+ ebegin "Creating Tun/Tap interface ${IFACE}"
+
+ # Set the base metric to 1000
+ metric=1000
+
+ if [ -x /usr/sbin/openvpn ] ; then
+ openvpn --mktun --dev-type "${tuntap}" --dev "${IFACE}" > /dev/null
+ else
+ local opts=
+ eval opts=\$tunctl_${IFVAR}
+ tunctl ${opts} -t "${IFACE}" >/dev/null
+ fi
+ eend $? && save_options tuntap "${tuntap}"
+}
+
+tuntap_post_stop() {
+ _is_tuntap || return 0
+
+ ebegin "Destroying Tun/Tap interface ${IFACE}"
+ if [ -x /usr/sbin/openvpn ] ; then
+ openvpn --rmtun \
+ --dev-type "$(get_options tuntap)" \
+ --dev "${IFACE}" > /dev/null
+ else
+ tunctl -d "${IFACE}" >/dev/null
+ fi
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/udhcpc.sh b/net.Linux/udhcpc.sh
new file mode 100644
index 00000000..e59d0049
--- /dev/null
+++ b/net.Linux/udhcpc.sh
@@ -0,0 +1,102 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+udhcpc_depend() {
+ program start /sbin/udhcpc
+ after interface
+ provide dhcp
+}
+
+_config_vars="$_config_vars dhcp udhcpc"
+
+udhcpc_start() {
+ local args= opt= opts= pidfile="/var/run/udhcpc-${IFACE}.pid"
+ local sendhost=true cachefile="/var/cache/udhcpc-${IFACE}.lease"
+
+ _wait_for_carrier || return 1
+
+ eval args=\$udhcpc_${IFVAR}
+
+ # Get our options
+ eval opts=\$dhcp_${IFVAR}
+ [ -z "${opts}" ] && opts=${dhcp}
+
+ # Map some generic options to dhcpcd
+ for opt in ${opts} ; do
+ case "${opt}" in
+ nodns) args="${args} --env PEER_DNS=no" ;;
+ nontp) args="${args} --env PEER_NTP=no" ;;
+ nogateway) args="${args} --env PEER_ROUTERS=no" ;;
+ nosendhost) sendhost=false;
+ esac
+ done
+
+ [ "${metric:-0}" != "0" ] && args="${args} --env IF_METRIC=${metric}"
+
+ ebegin "Running udhcpc"
+
+ # Try and load the cache if it exists
+ if [ -f "${cachefile}" ]; then
+ case "$ {args} " in
+ *" --request="*|*" -r "*) ;;
+ *)
+ local x=$(cat "${cachefile}")
+ # Check for a valid ip
+ case "${x}" in
+ *.*.*.*) args="${args} --request=${x}" ;;
+ esac
+ ;;
+ esac
+ fi
+
+ case " ${args} " in
+ *" --quit "*|*" -q "*) x="/sbin/udhcpc" ;;
+ *) x="start-stop-daemon --start --exec /sbin/udhcpc \
+ --pidfile \"${pidfile}\" --" ;;
+ esac
+
+ case " ${args} " in
+ *" --hosname="*|*" -h "*|*" -H "*) ;;
+ *)
+ if ${sendhost} ; then
+ local hname="$(hostname)"
+ if [ "${hname}" != "(none)" ] && [ "${hname}" != "localhost" ]; then
+ args="${args} --hostname='${hname}'"
+ fi
+ fi
+ ;;
+ esac
+
+ eval "${x}" "${args}" --interface="${IFACE}" --now \
+ --script="${RC_LIBDIR}"/sh/udhcpc.sh \
+ --pidfile="${pidfile}" >/dev/null
+ eend $? || return 1
+
+ _show_address
+ return 0
+}
+
+udhcpc_stop() {
+ local pidfile="/var/run/udhcpc-${IFACE}.pid" opts= sig="TERM"
+ [ ! -f "${pidfile}" ] && return 0
+
+ # Get our options
+ eval opts=\$dhcp_${IFVAR}
+ [ -z "${opts}" ] && opts=${dhcp}
+
+ ebegin "Stopping udhcpc on ${IFACE}"
+ case " ${opts} " in
+ *" release "*)
+ sig="USR2"
+ if [ -f /var/cache/udhcpc-"${IFACE}".lease ] ; then
+ rm -f /var/cache/udhcpc-"${IFACE}".lease
+ fi
+ ;;
+ esac
+
+ start-stop-daemon --stop --quiet --signal "${sig}" \
+ --exec /sbin/udhcpc --pidfile "${pidfile}"
+ eend $?
+}
+
+# vim: set ts=4 :
diff --git a/net.Linux/vlan.sh b/net.Linux/vlan.sh
new file mode 100644
index 00000000..fef4f2c5
--- /dev/null
+++ b/net.Linux/vlan.sh
@@ -0,0 +1,108 @@
+# Copyright 2004-2007 Gentoo Foundation
+# Distributed under the terms of the GNU General Public License v2
+
+vlan_depend() {
+ program /sbin/vconfig
+ after interface
+ before dhcp
+}
+
+_config_vars="$_config_vars vlans"
+
+_is_vlan() {
+ [ ! -d /proc/net/vlan ] && return 1
+ grep -q "^${IFACE}[[:space:]]+" /proc/net/vlan/config
+}
+
+_get_vlans() {
+ [ -e /proc/net/vlan/config ] || return 1
+ sed -n -e 's/^\(.*[0-9]\) \(.* \) .*'"${IFACE}"'$/\1/p' /proc/net/vlan/config
+}
+
+_check_vlan() {
+ if [ ! -d /proc/net/vlan ] ; then
+ modprobe 8021q
+ if [ ! -d /proc/net/vlan ] ; then
+ eerror "VLAN (802.1q) support is not present in this kernel"
+ return 1
+ fi
+ fi
+}
+
+vlan_pre_start() {
+ eval $(_get_array "vconfig_${IFVAR}")
+ [ $# = "0" ] && return 0
+
+ _check_vlan || return 1
+ _exists || return 1
+
+ local v= x= e=
+ for v in "$@" ; do
+ case "${v}" in
+ set_name_type" "*) x=${v} ;;
+ *) x="$(echo "${v}" | sed -e "s/ / ${IFACE} /g")"
+ [ "${x}" = "${v}" ] && x="${x} ${IFACE}"
+ ;;
+ esac
+
+ set -x
+ e="$(vconfig ${x} 2>&1 1>/dev/null)"
+ set +x
+ [ -z "${e}" ] && continue
+ eerror "${e}"
+ return 1
+ done
+}
+
+vlan_post_start() {
+ eval $(_get_array "vlans_${IFVAR}")
+ [ $# = "0" ] && return 0
+
+ _check_vlan || return 1
+ _exists || return 1
+
+ local vlan= e= s=
+ for vlan in "$@" ; do
+ einfo "Adding VLAN ${vlan} to ${IFACE}"
+ e="$(vconfig add "${IFACE}" "${vlan}" 2>&1 1>/dev/null)"
+ if [ -n "${e}" ] ; then
+ eend 1 "${e}"
+ continue
+ fi
+
+ # We may not want to start the vlan ourselves
+ eval s=\$vlan_start_${IFVAR}
+ [ "${s:-yes}" != "yes" ] && continue
+
+ # We need to work out the interface name of our new vlan id
+ local ifname="$( \
+ sed -n -e 's/^\([^ \t]*\) *| '"${vlan}"' *| .*'"${iface}"'$/\1/p' \
+ /proc/net/vlan/config )"
+ mark_service_started "net.${ifname}"
+ (
+ export SVCNAME="net.${ifname}"
+ start
+ ) || mark_service_stopped "net.${ifname}"
+ done
+
+ return 0
+}
+
+vlan_post_stop() {
+ local vlan=
+
+ for vlan in $(_get_vlans) ; do
+ einfo "Removing VLAN ${vlan##*.} from ${IFACE}"
+ (
+ export SVCNAME="net.${vlan}"
+ stop
+ ) && {
+ mark_service_stopped "net.${vlan}"
+ vconfig rem "${vlan}" >/dev/null
+ }
+ done
+
+ return 0
+}
+
+# vim: set ts=4 :