Skip to content

Instantly share code, notes, and snippets.

@raspi
Created May 26, 2019 10:45
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raspi/102a7721f95c0a72d4b848f3477e7568 to your computer and use it in GitHub Desktop.
Save raspi/102a7721f95c0a72d4b848f3477e7568 to your computer and use it in GitHub Desktop.
Generate SystemD .network files for network interface automatically
#!/bin/bash -e
# Generate SystemD .network files for network interface automatically
# (c) Pekka Järvinen 2019-
# Check that there are arguments given
if [ "$#" -eq 0 ]; then
echo "No arguments were given. See $0 --help or $0 -h for usage instructions." 1>&2
exit 1
fi
generatedwith=$@
beverbose=no
interface=none
dhcp="yes"
address=""
gateway=""
dns=""
match="iface"
priority=10
matchmac=""
# Get current default gateway IP
read _ _ currentgateway _ < <(ip route list match 0/0)
# options may be followed by one colon to indicate they have a required argument
if ! options=$(getopt -o hv:i:a:d:m:g:n:p: -l help,verbose,interface:,address:,dhcp:,match:,gateway:,dns:,priority: -- "$@")
then
# something went wrong, getopt will put out an error message for us
exit 1
fi
set -- $options
# Parse arguments
while [ $# -gt 0 ]
do
case $1 in
-h|--help)
echo "Usage: $0"
echo " -i --interface <interface> Required. for example: eno1"
echo " -p --priority 0-n Priority. Defaults to 10. "
echo ""
echo "Match type (defaults to iface):"
echo " -m --match <iface|mac> [Match] definition for example: iface for Name="
echo ""
echo "Use DHCP (default: yes):"
echo " -d --dhcp <no|yes|ipv4|ipv6> For example: ipv4"
echo ""
echo "Use static IP address:"
echo " -a --address <IPv4|IPv6 with CIDR> For example: 192.168.1.19/24"
echo " -g --gateway <Gateway IP Address> Defaults to current GW. For example: 192.168.1.1"
echo " -n --dns <DNS IP Address> For example: 192.168.1.1"
echo ""
echo "Other:"
echo " -v --verbose be verbose"
echo " -h --help this help"
echo ""
echo "Examples:"
echo " Use static IP:"
echo " $0 -i eno1 -d no -a 192.168.1.10/24 --gateway 192.168.1.1 --dns 192.168.1.1"
echo " DHCP IPv4:"
echo " $0 -i eno1 -d ipv4"
echo ""
exit 0
;;
-v|--verbose) beverbose="yes" ;;
-f|--force) force="yes" ;;
# for options with required arguments, an additional shift is required
-i|--interface) interface="${2//\'/}" ; shift;;
-a|--address) address="${2//\'/}" ; shift;;
-d|--dhcp) dhcp="${2//\'/}" ; shift;;
-m|--match) match="${2//\'/}" ; shift;;
-g|--gateway) gateway="${2//\'/}" ; shift;;
-n|--dns) dns="${2//\'/}" ; shift;;
-p|--priority) priority="${2//\'/}" ; shift;;
(--) shift; break;;
(-*) echo "$0: error - unrecognized option $1" 1>&2; exit 1;;
(*) break;;
esac
shift
done
# Check arguments for conflicts and errors
macfile=/sys/class/net/$interface/address
if [ -f "$macfile" ]; then
# Get MAC Address of given interface
matchmac=$(< $macfile)
else
echo "Unknown interface: $interface ($macfile)" 1>&2
exit 1
fi
case $dhcp in
yes|no|ipv6|ipv4) ;;
*) echo "Unknown DHCP type: $dhcp. Use yes|no|ipv6|ipv4" 1>&2; exit 1;;
esac
if [ "$dhcp" != "no" -a "$address" != "" ]; then
echo "Can't mix DHCP and static IP config" 1>&2
exit 1
fi
if [ "$address" != "" -a ! -z "${address##*/*}" ]; then
echo "No CIDR in static IP $address. Use for example 'IP/24' which is 255.255.255.0." 1>&2
exit 1
fi
case $match in
mac|iface) ;;
*) echo "Unknown match type: $match. Use mac|iface." 1>&2; exit 1;;
esac
# Output the .network file contents to temporary file
ofn=$priority-$interface.network
ofile=$(mktemp -d "${TMPDIR:-/tmp/}$(basename $0).XXXXXXXXXXXX")/$ofn
echo "# sudo cp -i $ofile /etc/systemd/network/$ofn" > $ofile
echo "# -- Generated with $0 $generatedwith" >> $ofile
echo -n "# -- At " >> $ofile
date --iso-8601=seconds >> $ofile
echo "#" >> $ofile
# Match
echo "[Match]" >> $ofile
echo "# Match MAC Address" >> $ofile
if [ "$match" != "mac" ]; then
echo -n "#" >> $ofile
fi
echo "MACAddress=$matchmac" >> $ofile
echo "# Match name" >> $ofile
if [ "$match" != "iface" ]; then
echo -n "#" >> $ofile
fi
echo "Name=${interface}" >> $ofile
echo "" >> $ofile
# Network
echo "[Network]" >> $ofile
echo "Description=Interface $interface (network)" >> $ofile
echo "# DHCP no|yes|ipv4|ipv6" >> $ofile
if [ "$dhcp" == "no" ]; then
echo -n "#" >> $ofile
fi
echo "DHCP=$dhcp" >> $ofile
echo "# Static IPv4 or IPv6 address with CIDR" >> $ofile
if [ "$dhcp" != "no" ]; then
echo -n "#" >> $ofile
fi
echo "Address=$address" >> $ofile
echo "# Generated automatically from current configuration:" >> $ofile
for addr in $(ip address show dev $interface | awk '/inet/{print $2}')
do
echo "#Address=$addr" >> $ofile
done
echo "# Gateway IP Address" >> $ofile
if [ "$gateway" == "" ]; then
gateway=$currentgateway
fi
if [ "$dhcp" != "no" ]; then
echo -n "#" >> $ofile
fi
echo "Gateway=$gateway" >> $ofile
echo "# DNS server address" >> $ofile
if [ "$dns" == "" ]; then
dns=$gateway
echo -n "#" >> $ofile
fi
echo "DNS=$dns" >> $ofile
echo "#Domains=home.lan" >> $ofile
echo "#DNSDefaultRoute=" >> $ofile
echo "# NTP time keeping server" >> $ofile
echo "#NTP=$gateway" >> $ofile
echo "# Forward packets (req for NAT)" >> $ofile
echo "#IPForward=no" >> $ofile
echo "#IPMasquerade=" >> $ofile
echo "# VLAN ID" >> $ofile
echo "#VLAN=1234" >> $ofile
echo "#LinkLocalAddressing=no" >> $ofile
echo "#LLMNR=no" >> $ofile
echo "#LLDP=" >> $ofile
echo "# Send LLDP packets" >> $ofile
echo "EmitLLDP=nearest-bridge" >> $ofile
echo "" >> $ofile
# Link
echo "[Link]" >> $ofile
echo "# Override MAC (spoof)" >> $ofile
echo "#MACAddress=" >> $ofile
echo "#ARP=no" >> $ofile
echo "#Multicast=no" >> $ofile
echo "#Unmanaged=no" >> $ofile
echo "#RequiredForOnline=yes" >> $ofile
echo ""
cat $ofile
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment