diff options
author | Kerin Millar <kfm@plushkava.net> | 2021-02-02 03:47:13 +0000 |
---|---|---|
committer | Lars Wendler <polynomial-c@gentoo.org> | 2021-02-02 09:27:02 +0100 |
commit | b60fd3319a254dfacf0051dc0e5343a8fe6e87f1 (patch) | |
tree | c213d8dba9cc1828ea0e91fa7fcfda621a8188aa | |
parent | net/apipa.sh: Account for the first and last /24 being reserved (diff) | |
download | netifrc-b60fd3319a254dfacf0051dc0e5343a8fe6e87f1.tar.gz netifrc-b60fd3319a254dfacf0051dc0e5343a8fe6e87f1.tar.bz2 netifrc-b60fd3319a254dfacf0051dc0e5343a8fe6e87f1.zip |
net/apipa.sh: Simplify and address the remaining portability issues
Re-factor the over-generalised seeding function into a _random_uint16
function. Have it use a simpler, faster method to collect entropy, with
the aid of od(1). Shorten the previously rambling comment.
Simplify the _random_apipa_octets function. Clamp the seed to the range
0-32767 for maximal portability. Convey the seed as a formal parameter,
rather then inject it. Use a simpler method to produce the octets, running
awk(1) only once. Format the random float, so that awk(1) is prevented
from using scientific notation to represent certain numbers.
Change a variable name in the subshell responsible for reading the list of
octet pairs, so as to be less confusing to future readers.
Note that the portability issue mentioned by commit 31a05f1 is addressed.
The code should now be fully POSIX-compliant, save for the continued use
of the local keyword, upon which it does not rely.
Signed-off-by: Kerin Millar <kfm@plushkava.net>
Signed-off-by: Lars Wendler <polynomial-c@gentoo.org>
-rw-r--r-- | net/apipa.sh | 63 |
1 files changed, 29 insertions, 34 deletions
diff --git a/net/apipa.sh b/net/apipa.sh index 41274fa..a124b84 100644 --- a/net/apipa.sh +++ b/net/apipa.sh @@ -6,47 +6,42 @@ apipa_depend() program /sbin/arping /bin/arping } -_random_bytes_as_int() +_random_uint16() { - local hex num_bytes="$1" - - # While POSIX does not require that /dev/urandom exist, it is a - # de-facto standard. Therefore, the following approach should be - # highly portable in practice. In the case of Linux, and unlike BSD - # this interface does not block in the event that the CSRNG has not - # yet been seeded. Still, this is acceptable because we do not - # require a guarantee that the entropy be cryptographically secure. - # It's also worth noting that Linux >=5.4 is faster at seeding in - # the absence of RDRAND/RDSEED than previous versions were. + # While POSIX does not require that /dev/urandom exist, it is a de-facto + # standard. In the case of Linux, and unlike BSD, this interface does + # not block in the event that the CSRNG has not yet been seeded. + # Still, this is acceptable because we do not require a guarantee that + # the entropy be cryptographically secure. test -e /dev/urandom && - hex=$( - LC_ALL=C tr -dc '[:xdigit:]' < /dev/urandom | - dd bs="$(( num_bytes * 2 ))" count=1 2>/dev/null) && - test "${#hex}" = "$(( num_bytes * 2 ))" && - printf '%d\n' "0x${hex}" + printf %d 0x"$(LC_ALL=C od -vAn -N2 -tx1 /dev/urandom | tr -d '[:space:]')" } _random_apipa_octets() { local seed - # Obtain a highly random 16-bit seed for use by awk's RNG. In the - # unlikely event that the seed ends up being empty, awk will seed - # based on the time of day, with a granularity of one second. - seed=$(_random_bytes_as_int 2) + # Attempt to generate a random uint16 to seed awk's RNG. The maximum + # value of RAND_MAX known to be portable is 32767. Clamp accordingly by + # discarding one bit's worth of data. Should the seed turn out to be + # empty, we instruct awk to seed based on the time of day, in seconds. + seed=$(_random_uint16) && : $(( seed >>= 1 )) # For APIPA (RFC 3927), the 169.254.0.0/16 address block is # reserved. This provides 65024 addresses, having accounted for the # fact that the first and last /24 are reserved for future use. - awk "BEGIN { - srand($seed) - for (i=256; i<65280; i++) print rand() \" \" i - }" | - sort -k 1,1 -n | - POSIXLY_CORRECT=1 awk '{ - hex = sprintf("%04x",$2) - printf("%d %d\n", "0x" substr(hex,1,2), "0x" substr(hex,3,2)) - }' + awk -v seed="$seed" 'BEGIN { + if (seed != "") { + srand(seed) + } else { + srand() + } + for (i = 1; i < 255; i++) { + for (j = 0; j < 256; j++) { + printf("%f %d %d\n", rand(), i, j) + } + } + }' | sort -k 1,1 -n } apipa_start() @@ -62,11 +57,11 @@ apipa_start() addr=$( _random_apipa_octets | { - while read -r i1 i2; do - addr="169.254.${i1}.${i2}" - vebegin "${addr}/16" >&3 - if ! arping_address "${addr}" >&3; then - printf '%s\n' "${addr}" + while read -r f1 f2 f3; do + next_addr="169.254.$f2.$f3" + vebegin "$next_addr/16" >&3 + if ! arping_address "$next_addr" >&3; then + printf %s "$next_addr" exit 0 fi done |