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.
martijn@
Index: etc/netstart
===================================================================
RCS file: /cvs/src/etc/netstart,v
retrieving revision 1.219
diff -u -p -r1.219 netstart
--- etc/netstart 3 Jul 2022 12:14:36 -0000 1.219
+++ etc/netstart 21 Nov 2022 15:40:23 -0000
@@ -92,6 +92,40 @@ parse_hn_line() {
set +o noglob
}
+# Find if for lladdr
+# Usage: lladdr2if xx:xx:xx:xx:xx:xx
+# Duplicate lladdrs result in error.
+LLADDR_GLOB='[[:alnum:]][[:alnum:]]:[[:alnum:]][[:alnum:]]:'
+LLADDR_GLOB=$LLADDR_GLOB'[[:alnum:]][[:alnum:]]:[[:alnum:]][[:alnum:]]:'
+LLADDR_GLOB=$LLADDR_GLOB'[[:alnum:]][[:alnum:]]:[[:alnum:]][[:alnum:]]'
+lladdr2if() {
+ local _line _if _lladdr="$1"
+
+ _if="$(ifconfig | while IFS= read -- _line; do
+ [[ -n "${_line%%[[:space:]]*}" ]] && _if="${_line%%:*}"
+ if [[ -z "${_line%%[[:space:]]lladdr $LLADDR_GLOB}" && \
+ "${_line##* }" = "$_lladdr" ]]; then
+ print -n -- "$_if "
+ fi
+ done)"
+ [[ -z "$_if" || -n "${_if#* }" ]] && return 1
+ print -- $_if
+}
+
+# Find lladdr for if
+# Usage: if2lladdr if1
+if2lladdr() {
+ local _line _if="$1"
+
+ ifconfig $_if 2>/dev/null | while IFS= read -- _line; do
+ if [[ -z "${_line%%[[:space:]]lladdr $LLADDR_GLOB}" ]]; then
+ print -n -- "${_line##* }"
+ break
+ fi
+ done
+ return 0
+}
+
# Create interface $1 if it does not yet exist.
# Usage: ifcreate if1
ifcreate() {
@@ -132,9 +166,26 @@ 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=/etc/hostname.$1 _cmds _i=0 _line _stat _lladdr
set -A _cmds
+ if [[ -z "${_if%$LLADDR_GLOB}" ]]; then
+ if ! _if=$(lladdr2if $_if); then
+ print -u2 "${0##*/}: $_hn: unique if for lladdr not
found."
+ return
+ fi
+ if [[ -e /etc/hostname.$_if ]]; then
+ print -u2 "${0##*/}: $_hn: duplicate config found in
/etc/hostname.$_if."
+ return
+ fi
+ else
+ _lladdr="$(if2lladdr $_if)"
+ if [[ -n "$_lladdr" && -e /etc/hostname.$_lladdr ]]; then
+ print -u2 "${0##*/}: $_hn: duplicate config found in
/etc/hostname.$_lladdr."
+ return
+ fi
+ 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
@@ -180,7 +231,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 +245,13 @@ ifmstart() {
# Start wanted ifs.
[[ $_sif == @(ALL|${_if%%[0-9]*}) ]] && ifstart $_if
+ done
+ for _hn in /etc/hostname.$LLADDR_GLOB; do
+ [[ -f $_hn ]] || continue
+ _lladdr=${_hn#/etc/hostname.}
+
+ # Start wanted ifs.
+ [[ $_sif == @(ALL|${_lladdr}) ]] && ifstart $_lladdr
done
done
}
Index: share/man/man5/hostname.if.5
===================================================================
RCS file: /cvs/src/share/man/man5/hostname.if.5,v
retrieving revision 1.79
diff -u -p -r1.79 hostname.if.5
--- share/man/man5/hostname.if.5 26 Jul 2022 00:36:54 -0000 1.79
+++ share/man/man5/hostname.if.5 21 Nov 2022 15:40:23 -0000
@@ -44,6 +44,10 @@ One file should exist for each interface
.Pa hostname.fxp0
or
.Pa hostname.bridge0 .
+Additionally the interface name can be replaced with the interface's lladdr,
+given that the lladdr is unique across the system and no
+.Nm
+exists for the interface name.
A configuration file is not needed for lo0.
.Pp
The configuration information is expressed in a line-by-line packed format