aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'net/apipa.sh')
-rw-r--r--net/apipa.sh63
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