On Mon, Nov 21, 2022 at 04:56:07PM +0100, Martijn van Duren wrote: > On Sun, 2022-11-20 at 19:35 -0700, Theo de Raadt wrote: > > Steve Litt <sl...@troubleshooters.com> wrote: > > > > > Vitaliy Makkoveev said on Mon, 21 Nov 2022 03:48:21 +0300 > > > > > > > > On 20 Nov 2022, at 18:06, Odd Martin Baanrud <mar...@lb7ye.net> > > > > > wrote: > > > > > > > > > > Hello, > > > > > > > > > > I have a Raspberry Pi 4 with 2 USB NIC’s attached. > > > > > One via USB3 (ure0), and the other via USB2 (ure1). > > > > > Since they are connected to different USB interfaces, I thaught they > > > > > would get configured the same way on reboot. But that’s not the case. > > > > > They became swapped on reboot. > > > > > Is there a way to “lock” the configuration I want? > > > > > So the USB3 NIC always become ure0, and the USB2 ure1. > > > > > > > > > > Regards, Martin > > > > > > > > > > > > > You could parse ifconfig(8) output to determine which names network > > > > interfaces received. But unfortunately, you can’t rename interfaces. > > > > > > During your parsing you could assign each one to an environment > > > variable such that, for instance, $lan contains the network card name > > > of the LAN one, and $wan contains the network name of the one going to > > > the Internet. Unfortunately, this would probably mean changing a lot of > > > existing shellscripts, but it's doable. > > > > But that is not the problem. > > > > hostname.* installs addresses on an interface, based upon the name of that > > interface. > > > > So it is too late for what you suggest. > > > > Unless the suggestion is have each hostname.* do a !command to a script > > which > > does the assigning. That is pretty crazy. > > > > pf.conf is not the problem either, because that can be entirely written > > using > > egress and groups. > > > > > > > > There is a problem with device attachment -> naming a device at that > > moment -> using that name in netstart.. but I am not sure how we could > > solve this without creating bigger problems for everyone else in the > > other non-hot-plug configurations, which is the majority of users with > > > 1 network device. > > > > We also hit this problem with disks, and we worked around it with the > > DUID subsystem. > > > > > > I suppose there is some argument that we should support hostname.MAC > > files > > > I don't have a usecase for this myself, but it seemed like a nice > exercise and might get the ball rolling. I also don't have much > experience with our rc/netstart shellcode, so I'm expecting this diff > should be taken as a starting-point iff we want something like this. > > I've chosen to error out on missing lladdr, duplicate lladdr and when > there's a hostname.if for both the lladdr and the if variant. This means > that there's smaller chance for order confusion or doubly applied > configs. Downside is that if someone decided to backup their hostname.if > to hostname.lladdr that will break their setup. However, I don't expect > people to backup their config files in this manner, but you never know. > > Errors: > On duplicate lladdr (in this case em0 and iwx0 in trunk0): > $ doas sh /usr/src/etc/netstart 88:a4:c2:fb:84:77 > netstart: /etc/hostname.88:a4:c2:fb:84:77: unique if for lladdr not found. > > On missing lladdr: > $ doas sh /usr/src/etc/netstart 88:a4:c2:fb:84:76 > netstart: /etc/hostname.88:a4:c2:fb:84:76: unique if for lladdr not found. > > And having both hostname.if and hostname.lladdr installed: > $ doas sh ./netstart 00:11:22:33:44:55 > netstart: /etc/hostname.00:11:22:33:44:55: duplicate config found in > /etc/hostname.vio0. > $ doas sh ./netstart vio0 > netstart: /etc/hostname.vio0: duplicate config found in > /etc/hostname.00:11:22:33:44:55. > > Two omissions I considered but didn't implement: > 1) I didn't test if the lladdr is owned by one of `ifconfig -C` > interfaces. Not sure if this is an upside or downside. > 2) Allowing /etc/netstart if1 and parsing the hostname.lladdr1 and vice > versa.
I got interested in this, and looked at it a bit. My diff is also a bit preliminary, but a couple of things. First, I only parse ifconfig output once and save the LLADDR_MAP to look up later. This makes the lookup functions a bit simpler. Also, the glob now uses xdigit, which seems more correct, unless there's something I am missing about mac addresses. I also thought the error message for `netstart $lladdr` when /etc/hostname.$lladdr doesn't exist, but /etc/hostname.$if does was poor (it claimed duplicate configs which wasn't true) so I thought the easiest solution was to implement your #2 there and allow it to start the $if when you specify the $lladdr. Unfortunately, I then looked at the clock and realized it's time for bed, but I figured you might be interested in another take, even if it's probably incomplete. In any case, tomorrow is dinner with friends, so it will be Wednesday before I again have a chance to think on this. Index: etc/netstart =================================================================== RCS file: /cvs/src/etc/netstart,v retrieving revision 1.229 diff -u -p -r1.229 netstart --- etc/netstart 5 Nov 2022 12:06:05 -0000 1.229 +++ etc/netstart 22 Nov 2022 05:55:40 -0000 @@ -92,6 +92,49 @@ parse_hn_line() { set +o noglob } +LLGLOB='[[:xdigit:]][[:xdigit:]]:[[:xdigit:]][[:xdigit:]]' +LLGLOB="$LLGLOB:$LLGLOB:$LLGLOB" + +set -A LLADDR_MAP -- $( + ifconfig | while IFS= read -- _line; do + if [[ "$_line" = +([[:alpha:]])+([[:digit:]]):* ]]; then + _if=${_line%:*} + elif [[ -n "$_if" + && "$_line" = +([[:space:]])lladdr\ $LLGLOB ]]; then + print "$_if,${_line#*lladdr }" + _if= + fi + done +) + +# Find if for lladdr +# Usage: lladdr2if xx:xx:xx:xx:xx:xx +# Duplicate lladdrs result in error. +lladdr2if() { + local _lladdr=$1 _if="" + for m in "${LLADDR_MAP[@]}"; do + if [[ "$_lladdr" = "${m#*,}" ]]; then + [[ -n "$_if" ]] && return 1 + _if="${m%,*}" + fi + done + print -- "$_if" + return 0 +} + +# Find lladdr for if +# Usage: if2lladdr if1 +if2lladdr() { + local _if=$1 + for m in "${LLADDR_MAP[@]}"; do + if [[ "$_if" = "${m%,*}" ]]; then + print -- "${m#*,}" + break + fi + done + return 0 +} + # Create interface $1 if it does not yet exist. # Usage: ifcreate if1 ifcreate() { @@ -132,15 +175,37 @@ vifscreate() { # Start a single interface. # Usage: ifstart if1 ifstart() { - local _if=$1 _hn=/etc/hostname.$1 _cmds _i=0 _line _stat + local _if=$1 _hn _cmds _i=0 _line _stat _lladdr set -A _cmds + if [[ "$_if" = $LLGLOB ]]; then + _lladdr=$_if + if ! _if="$(lladdr2if "$_if")"; then + print -u2 "${0##*/}: unique if for lladdr $_lladdr not found." + return + fi + else + _lladdr="$(if2lladdr "$_if")" + fi + # Interface names must be alphanumeric only. We check to avoid # configuring backup or temp files, and to catch the "*" case. [[ $_if != +([[:alpha:]])+([[:digit:]]) ]] && return - if [[ ! -f $_hn ]]; then - print -u2 "${0##*/}: $_hn: No such file or directory." + if [[ -n "$_if" && -e "/etc/hostname.$_if" ]]; then + _hn="/etc/hostname.$_if" + fi + + if [[ -n "$_lladdr" && -e "/etc/hostname.$_lladdr" ]]; then + if [[ -n "$_hn" ]]; then + print -u2 "${0##*/}: duplicate configs found in $_hn and /etc/hostname.$_lladdr." + return + fi + _hn="/etc/hostname.$_lladdr" + fi + + if [[ -z "$_hn" ]]; then + print -u2 "${0##*/}: /etc/hostname.$1: No such file or directory." return fi @@ -180,7 +245,7 @@ ifstart() { # Start "$1" interfaces in order or all interfaces if empty. # Don't start "$2" interfaces. "$2" is optional. ifmstart() { - local _sifs=$1 _xifs=$2 _hn _if _sif _xif + local _sifs=$1 _xifs=$2 _hn _if _sif _xif _lladdr for _sif in ${_sifs:-ALL}; do for _hn in /etc/hostname.+([[:alpha:]])+([[:digit:]]); do @@ -194,6 +259,13 @@ ifmstart() { # Start wanted ifs. [[ $_sif == @(ALL|${_if%%[0-9]*}) ]] && ifstart $_if + done + for _hn in /etc/hostname.$LLGLOB; do + [[ -f $_hn ]] || continue + _lladdr=${_hn#/etc/hostname.} + + # Start wanted ifs. + [[ $_sif == @(ALL|${_lladdr}) ]] && ifstart $_lladdr done done }