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 |