[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#605723: New approach to wrapper.



After staring at the output of $(strings /sbin/ifup | grep route),
I was able to make two observation that in turn lead me to a fully
new approach to the wrapper script. The outcome should be superior
to the previous patch by the order of a magnitude.

The new script is attached in its entirety with this message,
so I will discuss the ideas behind this rewrite. The main idea
is a simple intention:

  1. Do not modify command line arguments. Pass almost everything
     to /lib/freebsd/route.

The strings in "ifup" lead to two initial observations:

  2. We need to support a single Debian native option: "-A inet6".
     This must go between "route" and the command "add".

By the way, only commands "add" and "del" are generated from
ifupdown, all other command calls can be passed verbatim.

  3. When ifup/ifdown passes a non-elementary route, there
     is a GNU/Linux native keyword "gw" present.

If either of these markers is missing, then the string from ifupdown
could equally well pass for a FreeBSD-versioned command.


So, what happens with the keyword "gw" present?

   4. The keyword "gw" must not be passed to /lib/freebsd/route.

One issue creeps up: What if a host or a network is named "gw"?
The present script disregards this possibility. A TODO for later!

A command call from ifup/ifdown containing "gw" can thus be used
as a state in a finite machine. It entails two further principles:

   5. In gw-state, any use of "metric $num" must be discarded.
      No immediate counterpart present in FreeBSD.

   6. Ifup/ifdown appends an interface name at the end, which
      affects gw-state. Since the meaning of "dev $name" in
      GNU/Linux and "-interface $name" do not carry identical
      connotations, the appended name must be dropped.

That is it. My wrapper proposal implements these six observations.

It works like a charm on my machine. Although a single homed
system, it is fun to use "route get" for viewing routes, teasing
with options and the like.

I suggest dropping all tests of the initial patch, instead commencing
the evaluation of the wrapper proposal.


Best regards,

Mats E A
#!/bin/sh
#
# /sbin/route
#
# Wrapper script around /lib/freebsd/route
# crafted to catch the routing commands issued
# by /sbin/ifup and /sbin/ifdown, translating
# them into valid FreeBSD commands, at the same
# time preserving all BSD native routing input.
#
# Authors: Axel Beckert, Mats Erik Andersson

set -e

if [ $# = 0 ] ; then
  # Issue usage info
  /lib/freebsd/route
fi

args=""

# Capture all options first. Save them for later.
# One Debian endemic addition: -A family.
# Typically: -A inet6
#
opts=""
af=""

while [ $# -gt 0 ]; do
  case "$1" in
    -*)
      # One Debian addition.
      if [ "$1" = "-A" ] ; then
        shift
        if [ -n "$1" ] ; then
          af="-$1"
          shift
          continue
        fi
        # Incorrect usage, call for help
        /lib/freebsd/route
      fi
      # A native option remains
      opts="${opts} $1"
      shift
      ;;
    *)
     # Must be the beginning of a command mode line.
     break ;;
  esac
done

cmd="$1"
shift

# Command originating from ifudown can only be
# either for "add" or for "del".
#
# The commands from "ifupdown" are acceptable
# as long as they do not contain the keyword "gw".
# In case the command does so, then the very last
# command line argument is the name of the interface.
# We ignore it for now, since an interface specification
# do not carry the same connotation in FreeBSD as it
# does in GNU/Linux.
#
# The keyword "metric" seems unknown for FreeBSD,
# so it is filtered off.

if [ "$cmd" = "add" -o "$cmd" = "del" ] ; then
  # Our simple state machine
  HAVE_SEEN_GW=""

  while [ $# -gt 0 ]; do
    if [ -n "$HAVE_SEEN_GW" ] ; then
      if [ $# -eq 1 ] ; then
        # We have reach the end. An interface name
        # appears as last argument, since we are in
        # a state caused by a call from ifupdown.
        # We simply discard the interface name.
        break
      fi
      if [ "$1" = "metric" ] ; then
        # Ignored, together with its argument
        shift
      else
        args="${args} $1"
      fi
    else
      if [ "$1" = "gw" ] ; then
        # Change state and discard "gw",
        # hoping that no administrator ever
        # names a host or a network as "gw".
        HAVE_SEEN_GW="YES"
      else
        # This ingredient is important. Add it.
        args="${args} $1"
      fi
    fi
    shift
  done
else
  # Must have a native command, whatever the content.
  args="$@"
fi

exec /lib/freebsd/route ${opts} ${cmd} ${af} ${args}

Attachment: signature.asc
Description: Digital signature


Reply to: