Gentoo Archives: gentoo-commits

From: Lars Wendler <polynomial-c@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] proj/netifrc:master commit in: net/
Date: Tue, 02 Feb 2021 08:28:42
Message-Id: 1612254422.b60fd3319a254dfacf0051dc0e5343a8fe6e87f1.polynomial-c@OpenRC
1 commit: b60fd3319a254dfacf0051dc0e5343a8fe6e87f1
2 Author: Kerin Millar <kfm <AT> plushkava <DOT> net>
3 AuthorDate: Tue Feb 2 03:47:13 2021 +0000
4 Commit: Lars Wendler <polynomial-c <AT> gentoo <DOT> org>
5 CommitDate: Tue Feb 2 08:27:02 2021 +0000
6 URL: https://gitweb.gentoo.org/proj/netifrc.git/commit/?id=b60fd331
7
8 net/apipa.sh: Simplify and address the remaining portability issues
9
10 Re-factor the over-generalised seeding function into a _random_uint16
11 function. Have it use a simpler, faster method to collect entropy, with
12 the aid of od(1). Shorten the previously rambling comment.
13
14 Simplify the _random_apipa_octets function. Clamp the seed to the range
15 0-32767 for maximal portability. Convey the seed as a formal parameter,
16 rather then inject it. Use a simpler method to produce the octets, running
17 awk(1) only once. Format the random float, so that awk(1) is prevented
18 from using scientific notation to represent certain numbers.
19
20 Change a variable name in the subshell responsible for reading the list of
21 octet pairs, so as to be less confusing to future readers.
22
23 Note that the portability issue mentioned by commit 31a05f1 is addressed.
24 The code should now be fully POSIX-compliant, save for the continued use
25 of the local keyword, upon which it does not rely.
26
27 Signed-off-by: Kerin Millar <kfm <AT> plushkava.net>
28 Signed-off-by: Lars Wendler <polynomial-c <AT> gentoo.org>
29
30 net/apipa.sh | 63 ++++++++++++++++++++++++++++--------------------------------
31 1 file changed, 29 insertions(+), 34 deletions(-)
32
33 diff --git a/net/apipa.sh b/net/apipa.sh
34 index 41274fa..a124b84 100644
35 --- a/net/apipa.sh
36 +++ b/net/apipa.sh
37 @@ -6,47 +6,42 @@ apipa_depend()
38 program /sbin/arping /bin/arping
39 }
40
41 -_random_bytes_as_int()
42 +_random_uint16()
43 {
44 - local hex num_bytes="$1"
45 -
46 - # While POSIX does not require that /dev/urandom exist, it is a
47 - # de-facto standard. Therefore, the following approach should be
48 - # highly portable in practice. In the case of Linux, and unlike BSD
49 - # this interface does not block in the event that the CSRNG has not
50 - # yet been seeded. Still, this is acceptable because we do not
51 - # require a guarantee that the entropy be cryptographically secure.
52 - # It's also worth noting that Linux >=5.4 is faster at seeding in
53 - # the absence of RDRAND/RDSEED than previous versions were.
54 + # While POSIX does not require that /dev/urandom exist, it is a de-facto
55 + # standard. In the case of Linux, and unlike BSD, this interface does
56 + # not block in the event that the CSRNG has not yet been seeded.
57 + # Still, this is acceptable because we do not require a guarantee that
58 + # the entropy be cryptographically secure.
59 test -e /dev/urandom &&
60 - hex=$(
61 - LC_ALL=C tr -dc '[:xdigit:]' < /dev/urandom |
62 - dd bs="$(( num_bytes * 2 ))" count=1 2>/dev/null) &&
63 - test "${#hex}" = "$(( num_bytes * 2 ))" &&
64 - printf '%d\n' "0x${hex}"
65 + printf %d 0x"$(LC_ALL=C od -vAn -N2 -tx1 /dev/urandom | tr -d '[:space:]')"
66 }
67
68 _random_apipa_octets()
69 {
70 local seed
71
72 - # Obtain a highly random 16-bit seed for use by awk's RNG. In the
73 - # unlikely event that the seed ends up being empty, awk will seed
74 - # based on the time of day, with a granularity of one second.
75 - seed=$(_random_bytes_as_int 2)
76 + # Attempt to generate a random uint16 to seed awk's RNG. The maximum
77 + # value of RAND_MAX known to be portable is 32767. Clamp accordingly by
78 + # discarding one bit's worth of data. Should the seed turn out to be
79 + # empty, we instruct awk to seed based on the time of day, in seconds.
80 + seed=$(_random_uint16) && : $(( seed >>= 1 ))
81
82 # For APIPA (RFC 3927), the 169.254.0.0/16 address block is
83 # reserved. This provides 65024 addresses, having accounted for the
84 # fact that the first and last /24 are reserved for future use.
85 - awk "BEGIN {
86 - srand($seed)
87 - for (i=256; i<65280; i++) print rand() \" \" i
88 - }" |
89 - sort -k 1,1 -n |
90 - POSIXLY_CORRECT=1 awk '{
91 - hex = sprintf("%04x",$2)
92 - printf("%d %d\n", "0x" substr(hex,1,2), "0x" substr(hex,3,2))
93 - }'
94 + awk -v seed="$seed" 'BEGIN {
95 + if (seed != "") {
96 + srand(seed)
97 + } else {
98 + srand()
99 + }
100 + for (i = 1; i < 255; i++) {
101 + for (j = 0; j < 256; j++) {
102 + printf("%f %d %d\n", rand(), i, j)
103 + }
104 + }
105 + }' | sort -k 1,1 -n
106 }
107
108 apipa_start()
109 @@ -62,11 +57,11 @@ apipa_start()
110 addr=$(
111 _random_apipa_octets |
112 {
113 - while read -r i1 i2; do
114 - addr="169.254.${i1}.${i2}"
115 - vebegin "${addr}/16" >&3
116 - if ! arping_address "${addr}" >&3; then
117 - printf '%s\n' "${addr}"
118 + while read -r f1 f2 f3; do
119 + next_addr="169.254.$f2.$f3"
120 + vebegin "$next_addr/16" >&3
121 + if ! arping_address "$next_addr" >&3; then
122 + printf %s "$next_addr"
123 exit 0
124 fi
125 done