base-files: ipcalc.sh: Add some commentary, etc.
[openwrt/openwrt.git] / package / base-files / files / lib / functions / ipv4.sh
1 uint_max=4294967295
2
3 # check that $1 is only base 10 digits, and that it doesn't
4 # exceed 2^32-1
5 assert_uint32() {
6 local __n="$1"
7
8 if [ -z "$__n" -o -n "${__n//[0-9]/}" ]; then
9 printf "Not a decimal integer (%s)\n" "$__n ">&2
10 return 1
11 fi
12
13 if [ "$__n" -gt $uint_max ]; then
14 printf "Out of range (%s)\n" "$__n" >&2
15 return 1
16 fi
17
18 if [ "$((__n + 0))" != "$__n" ]; then
19 printf "Not normalized notation (%s)\n" "$__n" >&2
20 return 1
21 fi
22
23 return 0
24 }
25
26 # return a count of the number of bits set in $1
27 bitcount() {
28 local __var="$1" __c="$2"
29 assert_uint32 "$__c" || return 1
30
31 __c=$((((__c >> 1) & 0x55555555) + (__c & 0x55555555)))
32 __c=$((((__c >> 2) & 0x33333333) + (__c & 0x33333333)))
33 __c=$((((__c >> 4) & 0x0f0f0f0f) + (__c & 0x0f0f0f0f)))
34 __c=$((((__c >> 8) & 0x00ff00ff) + (__c & 0x00ff00ff)))
35 __c=$((((__c >> 16) & 0x0000ffff) + (__c & 0x0000ffff)))
36
37 export -- "$__var=$__c"
38 }
39
40 # tedious but portable with busybox's limited shell
41 # we check each octet to be in the range of 0..255,
42 # and also make sure there's no extaneous characters.
43 str2ip() {
44 local __var="$1" __ip="$2" __n __val=0
45
46 case "$__ip" in
47 [0-9].*)
48 __n="${__ip:0:1}"
49 __ip="${__ip:2}"
50 ;;
51 [1-9][0-9].*)
52 __n="${__ip:0:2}"
53 __ip="${__ip:3}"
54 ;;
55 1[0-9][0-9].*|2[0-4][0-9].*|25[0-5].*)
56 __n="${__ip:0:3}"
57 __ip="${__ip:4}"
58 ;;
59 *)
60 printf "Not a dotted quad (%s)\n" "$2" >&2
61 return 1
62 ;;
63 esac
64
65 __val=$((__n << 24))
66
67 case "$__ip" in
68 [0-9].*)
69 __n="${__ip:0:1}"
70 __ip="${__ip:2}"
71 ;;
72 [1-9][0-9].*)
73 __n="${__ip:0:2}"
74 __ip="${__ip:3}"
75 ;;
76 1[0-9][0-9].*|2[0-4][0-9].*|25[0-5].*)
77 __n="${__ip:0:3}"
78 __ip="${__ip:4}"
79 ;;
80 *)
81 printf "Not a dotted quad (%s)\n" "$2" >&2
82 return 1
83 ;;
84 esac
85
86 __val=$((__val + (__n << 16)))
87
88 case "$__ip" in
89 [0-9].*)
90 __n="${__ip:0:1}"
91 __ip="${__ip:2}"
92 ;;
93 [1-9][0-9].*)
94 __n="${__ip:0:2}"
95 __ip="${__ip:3}"
96 ;;
97 1[0-9][0-9].*|2[0-4][0-9].*|25[0-5].*)
98 __n="${__ip:0:3}"
99 __ip="${__ip:4}"
100 ;;
101 *)
102 printf "Not a dotted quad (%s)\n" "$2" >&2
103 return 1
104 ;;
105 esac
106
107 __val=$((__val + (__n << 8)))
108
109 case "$__ip" in
110 [0-9])
111 __n="${__ip:0:1}"
112 __ip="${__ip:1}"
113 ;;
114 [1-9][0-9])
115 __n="${__ip:0:2}"
116 __ip="${__ip:2}"
117 ;;
118 1[0-9][0-9]|2[0-4][0-9]|25[0-5])
119 __n="${__ip:0:3}"
120 __ip="${__ip:3}"
121 ;;
122 *)
123 printf "Not a dotted quad (%s)\n" "$2" >&2
124 return 1
125 ;;
126 esac
127
128 __val=$((__val + __n))
129
130 if [ -n "$__ip" ]; then
131 printf "Not a dotted quad (%s)\n" "$2" >&2
132 return 1
133 fi
134
135 export -- "$__var=$__val"
136 return 0
137 }
138
139 # convert back from an integer to dotted-quad.
140 ip2str() {
141 local __var="$1" __n="$2"
142 assert_uint32 "$__n" || return 1
143
144 export -- "$__var=$((__n >> 24)).$(((__n >> 16) & 255)).$(((__n >> 8) & 255)).$((__n & 255))"
145 }
146