Skip to content

Instantly share code, notes, and snippets.

@Low-power
Created October 25, 2019 09:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Low-power/767a293645348bcc8e23e8b10064f8c2 to your computer and use it in GitHub Desktop.
Save Low-power/767a293645348bcc8e23e8b10064f8c2 to your computer and use it in GitHub Desktop.
Interface datalink layer configuration tool for Linux
#!/bin/sh
# Copyright 2015-2019 Rivoreo
# Permission is hereby granted, free of charge, to any person obtaining
# a copy of this software and associated documentation files (the
# "Software"), to deal in the Software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so, subject to
# the following conditions:
# The above copyright notice and this permission notice shall be
# included in all copies or substantial portions of the Software.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE
# FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# From net/if.h
IFF_UP=0x1
IFF_BROADCAST=0x2
IFF_DEBUG=0x4
IFF_LOOPBACK=0x8
IFF_POINTOPOINT=0x10
IFF_NOTRAILERS=0x20
IFF_RUNNING=0x40
IFF_NOARP=0x80
IFF_PROMISC=0x100
IFF_ALLMULTI=0x200
IFF_MASTER=0x400
IFF_SLAVE=0x800
IFF_MULTICAST=0x1000
IFF_PORTSEL=0x2000
IFF_AUTOMEDIA=0x4000
IFF_DYNAMIC=0x8000
# From net/arp.h
ARPHRD_NETROM=0
ARPHRD_ETHER=1
ARPHRD_AX25=3
ARPHRD_ARCNET=7
ARPHRD_DLCI=15
ARPHRD_ATM=19
ARPHRD_METRICOM=23
ARPHRD_EUI64=27
ARPHRD_INFINIBAND=32
ARPHRD_SLIP=256
ARPHRD_CSLIP=257
ARPHRD_SLIP6=258
ARPHRD_CSLIP6=259
ARPHRD_RSRVD=260
ARPHRD_ADAPT=264
ARPHRD_ROSE=270
ARPHRD_X25=271
ARPHRD_HWX25=272
ARPHRD_CAN=280
ARPHRD_PPP=512
ARPHRD_CISCO=513
ARPHRD_HDLC=$ARPHRD_CISCO
ARPHRD_LAPB=516
ARPHRD_DDCMP=517
ARPHRD_RAWHDLC=518
ARPHRD_TUNNEL=768
ARPHRD_TUNNEL6=769
ARPHRD_FRAD=770
ARPHRD_SKIP=771
ARPHRD_LOOPBACK=772
ARPHRD_LOCALTLK=773
ARPHRD_FDDI=774
ARPHRD_BIF=775
ARPHRD_SIT=776
ARPHRD_IPDDP=777
ARPHRD_IPGRE=778
ARPHRD_PIMREG=779
ARPHRD_HIPPI=780
ARPHRD_ASH=781
ARPHRD_ECONET=782
ARPHRD_IRDA=783
ARPHRD_FCPP=784
ARPHRD_FCAL=785
ARPHRD_FCPL=786
ARPHRD_FCFABRIC=787
ARPHRD_IEEE802_TR=800
ARPHRD_IEEE80211=801
ARPHRD_IEEE80211_PRISM=802
ARPHRD_IEEE80211_RADIOTAP=803
ARPHRD_IEEE802154=804
ARPHRD_IEEE802154_MONITOR=805
ARPHRD_PHONET=820
ARPHRD_PHONET_PIPE=821
ARPHRD_CAIF=822
ARPHRD_IP6GRE=823
ARPHRD_NETLINK=824
ARPHRD_6LOWPAN=825
flags_to_names() {
if [ $# != 1 ]; then
printf "flags_to_names: # (%s) != 1\\n" "$#" 1>&2
exit 2
fi
local flags="$1"
local names
[ $((flags&IFF_UP)) != 0 ] && names="UP"
[ $((flags&IFF_BROADCAST)) != 0 ] && names="$names,BROADCAST"
[ $((flags&IFF_DEBUG)) != 0 ] && names="$names,DEBUG"
[ $((flags&IFF_LOOPBACK)) != 0 ] && names="$names,LOOPBACK"
[ $((flags&IFF_POINTOPOINT)) != 0 ] && names="$names,POINTOPOINT"
[ $((flags&IFF_NOTRAILERS)) != 0 ] && names="$names,NOTRAILERS"
[ $((flags&IFF_RUNNING)) != 0 ] && names="$names,RUNNING"
[ $((flags&IFF_NOARP)) != 0 ] && names="$names,NOARP"
[ $((flags&IFF_PROMISC)) != 0 ] && names="$names,PROMISC"
[ $((flags&IFF_ALLMULTI)) != 0 ] && names="$names,ALLMULTI"
[ $((flags&IFF_MASTER)) != 0 ] && names="$names,MASTER"
[ $((flags&IFF_SLAVE)) != 0 ] && names="$names,SLAVE"
[ $((flags&IFF_MULTICAST)) != 0 ] && names="$names,MULTICAST"
[ $((flags&IFF_PORTSEL)) != 0 ] && names="$names,PORTSEL"
[ $((flags&IFF_AUTOMEDIA)) != 0 ] && names="$names,AUTOMEDIA"
[ $((flags&IFF_DYNAMIC)) != 0 ] && names="$names,DYNAMIC"
printf %s\\n "${names#,}"
}
type_to_name() {
if [ $# != 1 ]; then
printf "type_to_name: # (%s) != 1\\n" "$#" 1>&2
exit 2
fi
case "$1" in
$ARPHRD_NETROM)
echo netrom
;;
$ARPHRD_ETHER)
echo ether
;;
$ARPHRD_AX25)
echo ax25
;;
$ARPHRD_ARCNET)
echo arcnet
;;
$ARPHRD_DLCI)
echo dlci
;;
$ARPHRD_EUI64)
echo eui64
;;
$ARPHRD_INFINIBAND)
echo infiniband
;;
$ARPHRD_SLIP)
echo slip
;;
$ARPHRD_CSLIP)
echo cslip
;;
$ARPHRD_SLIP6)
echo slip6
;;
$ARPHRD_CSLIP6)
echo cslip6
;;
$ARPHRD_ROSE)
echo rose
;;
$ARPHRD_X25)
echo x25
;;
$ARPHRD_PPP)
echo ppp
;;
$ARPHRD_HDLC)
echo hdlc
;;
$ARPHRD_LAPB)
echo lapb
;;
$ARPHRD_TUNNEL)
echo tunnel
;;
$ARPHRD_FRAD)
echo frad
;;
$ARPHRD_LOOPBACK)
echo loop
;;
$ARPHRD_FDDI)
echo fddi
;;
$ARPHRD_SIT)
echo sit
;;
$ARPHRD_HIPPI)
echo hippi
;;
$ARPHRD_ECONET)
echo ec
;;
$ARPHRD_IRDA)
echo irda
;;
$ARPHRD_IEEE802_TR)
echo tr
;;
*)
echo unknown
;;
esac
}
human_readable() {
if [ $# != 3 ]; then
printf "human_readable: # (%s) != 3\\n" "$#" 1>&2
exit 2
fi
local n=${1}0
local unit=$2
local suffix=$3
while [ $n -ge 10240 ]; do
case "$unit" in
"")
unit=Ki
;;
Ki)
unit=Mi
;;
Mi)
unit=Gi
;;
Gi)
unit=Ti
;;
Ti)
unit=Pi
;;
Pi)
break
;;
*)
printf "human_readable: unknown unit '%s'\\n" "$unit" 1>&2
exit 2
;;
esac
n=$((n/1024))
done
i=${n%?}
[ -n "$unit" ] && n=${i}.${n#$i} || n=$i
printf "%s %s%s\\n" "$n" "$unit" "$suffix"
}
print_config() {
local d flags mtu index type address txqueuelen packets bytes speed duplex
if [ $# != 1 ]; then
printf "print_config: # (%s) != 1\\n" "$#" 1>&2
exit 2
fi
d="/sys/class/net/$1"
if [ ! -d "$d" ]; then
printf "ifconfig: interface %s doesn't exist\\n" "$1" 1>&2
return 1
fi
flags="`cat $d/flags`" || flags=0
mtu="`cat $d/mtu`" || mtu=0
printf "%s: flags=%s<%s> mtu %s" "$1" "$flags" "`flags_to_names $flags`" "$mtu"
index="`cat $d/ifindex`" && printf " index %s" "$index"
type="`cat $d/type`"
address="`cat $d/address`"
txqueuelen="`cat $d/tx_queue_len`"
printf "\\n %s %s txqueuelen %s\\n" "`type_to_name $type`" "$address" "$txqueuelen"
for i in rx tx; do
dm="`printf %s $i | sed y/rtx/RTX/`"
if packets="`cat $d/statistics/${i}_packets`" && bytes="`cat $d/statistics/${i}_bytes`"; then
printf " %s packets %s bytes %s (%s)\\n" "$dm" "$packets" "$bytes" "`human_readable $bytes '' B`"
fi
if errors="`cat $d/statistics/${i}_errors`" && dropped="`cat $d/statistics/${i}_dropped`" && overruns="`cat $d/statistics/${i}_fifo_errors`"; then
printf " %s errors %s dropped %s overruns %s\\n" "$dm" "$errors" "$dropped" "$overruns"
fi
done
#case "$type" in
# 1)
# if speed="`cat $d/speed`" && duplex="`cat $d/duplex`"; then
# fi
# ;;
#esac
}
print_config_all() {
for d in /sys/class/net/*; do
[ -d "$d" ] || continue
print_config "${d#/sys/class/net/}"
done
}
print_usage() {
printf "Usage: %s { -a | <interface> [<options>] }\\n" "$1" 1>&2
}
set_flags() {
local flags
if [ $# != 3 ]; then
printf "set_flags: # (%s) != 3\\n" "$#" 1>&2
exit 2
fi
flags="`cat \"/sys/class/net/$1/flags\"`" || return 1
if [ $((flags&$2)) = 0 ]; then
[ $3 = 0 ] && return 0
echo $((flags|$2)) > "/sys/class/net/$1/flags"
else
[ $3 = 1 ] && return 0
echo $((flags&(~$2))) > "/sys/class/net/$1/flags"
fi
}
set_mtu() {
if [ $# != 2 ]; then
printf "set_mtu: # (%s) != 2\\n" "$#" 1>&2
exit 2
fi
printf %s\\n "$2" > "/sys/class/net/$1/mtu"
}
set_txqueuelen() {
if [ $# != 2 ]; then
printf "set_txqueuelen: # (%s) != 2\\n" "$#" 1>&2
exit 2
fi
printf %s\\n "$2" > "/sys/class/net/$1/tx_queue_len"
}
end_of_options=
if [ "$1" = -- ]; then
end_of_options=1
shift
fi
if [ $# -lt 1 ]; then
print_usage "$0"
exit 255
fi
if [ -z "$end_of_options" ]; then case "$1" in
-a)
print_config_all
exit 0
;;
-h)
print_usage
exit 0
;;
-*)
printf "ifconfig: Invalid option '%s'\\n" "$1" 1>&2
exit 255
;;
esac fi
if [ $# = 1 ]; then
print_config "$1"
exit
fi
interface="$1"
shift
set -e
while [ $# -gt 0 ]; do
case "$1" in
up)
set_flags "$interface" $IFF_UP 1
;;
down)
set_flags "$interface" $IFF_UP 0
;;
mtu)
if [ $# -lt 2 ]; then
echo "ifconfig: 'mtu' needs an argument" 1>&2
return 255
fi
set_mtu "$interface" "$2"
shift
;;
txqueuelen)
if [ $# -lt 2 ]; then
echo "ifconfig: 'txqueuelen' needs an argument" 1>&2
return 255
fi
set_txqueuelen "$interface" "$2"
shift
;;
arp)
set_flags "$interface" $IFF_ARP 1
;;
noarp|-arp)
set_flags "$interface" $IFF_ARP 0
;;
promisc)
set_flags "$interface" $IFF_PROMISC 1
;;
nopromisc|-promisc)
set_flags "$interface" $IFF_PROMISC 0
;;
allmulti)
set_flags "$interface" $IFF_ALLMULTI 1
;;
noallmulti|-allmulti)
set_flags "$interface" $IFF_ALLMULTI 0
;;
multicast)
set_flags "$interface" $IFF_MULTICAST 1
;;
dynamic)
set_flags "$interface" $IFF_DYNAMIC 1
;;
nodynamic|-dynamic)
set_flags "$interface" $IFF_DYNAMIC 0
;;
*)
printf "ifconfig: unknown option '%s'\n" "$1" 1>&2
exit 255
esac
shift
done
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment