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 <[email protected]> wrote:
> >
> > > Vitaliy Makkoveev said on Mon, 21 Nov 2022 03:48:21 +0300
> > >
> > > > > On 20 Nov 2022, at 18:06, Odd Martin Baanrud <[email protected]>
> > > > > 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
}