diff options
author | Matthias Wachs <wachs@net.in.tum.de> | 2012-01-31 13:12:17 +0000 |
---|---|---|
committer | Matthias Wachs <wachs@net.in.tum.de> | 2012-01-31 13:12:17 +0000 |
commit | 3ffd428d7ba9a10dd052ff515979a9ced1582964 (patch) | |
tree | 84ca21db132978f337ee72a9c87153030acae216 /src/util/os_network.c | |
parent | 59c94448ae4c2b5f44f6c7a5e518d3608fd0160d (diff) | |
download | gnunet-3ffd428d7ba9a10dd052ff515979a9ced1582964.tar.gz gnunet-3ffd428d7ba9a10dd052ff515979a9ced1582964.zip |
ifconfig parsing
Shum's patch
bugs fixed in patch:
- IPv4 loopback address was not included: added line 179
- stack allocated strings were not zeroed out, so last value was used if value was not included in current line
- IPv4 netmask was passed as broadcast address (patch line 81)
- IPv4 netmask was passed as IPv6 netmask, caused invalid address conversion (patch line 113)
Diffstat (limited to 'src/util/os_network.c')
-rw-r--r-- | src/util/os_network.c | 82 |
1 files changed, 75 insertions, 7 deletions
diff --git a/src/util/os_network.c b/src/util/os_network.c index 7449f8068..01fe5f7dc 100644 --- a/src/util/os_network.c +++ b/src/util/os_network.c | |||
@@ -101,17 +101,26 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | |||
101 | freeifaddrs (ifa_first); | 101 | freeifaddrs (ifa_first); |
102 | } | 102 | } |
103 | #else | 103 | #else |
104 | int i; | ||
104 | char line[1024]; | 105 | char line[1024]; |
106 | char *replace; | ||
105 | const char *start; | 107 | const char *start; |
106 | char ifc[12]; | 108 | char ifc[12]; |
107 | char addrstr[128]; | 109 | char addrstr[128]; |
108 | char bcstr[128]; | 110 | char bcstr[128]; |
111 | char netmaskstr[128]; | ||
109 | FILE *f; | 112 | FILE *f; |
110 | int have_ifc; | 113 | int have_ifc; |
111 | struct sockaddr_in a4; | 114 | struct sockaddr_in a4; |
112 | struct sockaddr_in6 a6; | 115 | struct sockaddr_in6 a6; |
113 | struct in_addr v4; | 116 | struct in_addr v4; |
114 | struct in6_addr v6; | 117 | struct in6_addr v6; |
118 | struct sockaddr_in bcaddr; | ||
119 | struct sockaddr_in netmask; | ||
120 | struct sockaddr_in6 netmask6; | ||
121 | struct sockaddr *pass_bcaddr; | ||
122 | struct sockaddr *pass_netmask; | ||
123 | int prefixlen; | ||
115 | 124 | ||
116 | if (system ("ifconfig -a > /dev/null 2> /dev/null")) | 125 | if (system ("ifconfig -a > /dev/null 2> /dev/null")) |
117 | if (system ("/sbin/ifconfig -a > /dev/null 2> /dev/null") == 0) | 126 | if (system ("/sbin/ifconfig -a > /dev/null 2> /dev/null") == 0) |
@@ -146,12 +155,29 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | |||
146 | } | 155 | } |
147 | if (!have_ifc) | 156 | if (!have_ifc) |
148 | continue; /* strange input, hope for the best */ | 157 | continue; /* strange input, hope for the best */ |
158 | |||
159 | /* make parsing of ipv6 addresses easier */ | ||
160 | for (replace = line; *replace != '\0'; replace++) | ||
161 | { | ||
162 | if (*replace == '/') | ||
163 | *replace = ' '; | ||
164 | } | ||
165 | prefixlen = -1; | ||
166 | |||
149 | start = line; | 167 | start = line; |
150 | while (('\0' != *start) && (isspace (*start))) | 168 | while (('\0' != *start) && (isspace (*start))) |
151 | start++; | 169 | start++; |
152 | if ( /* Linux */ | 170 | |
153 | (2 == SSCANF (start, "inet addr:%127s Bcast:%127s", addrstr, bcstr)) || | 171 | /* Zero-out stack allocated values */ |
154 | (1 == SSCANF (start, "inet6 addr:%127s", addrstr)) || | 172 | memset (addrstr, 0, 128); |
173 | memset (netmaskstr, 0, 128); | ||
174 | memset (bcstr, 0, 128); | ||
175 | prefixlen = 0; | ||
176 | |||
177 | if ( /* Linux */ | ||
178 | (3 == SSCANF (start, "inet addr:%127s Bcast:%127s Mask:%127s", addrstr, bcstr, netmaskstr)) || | ||
179 | (2 == SSCANF (start, "inet addr:%127s Mask:%127s", addrstr, netmaskstr)) || | ||
180 | (2 == SSCANF (start, "inet6 addr:%127s %d", addrstr, &prefixlen)) || | ||
155 | /* Solaris, OS X */ | 181 | /* Solaris, OS X */ |
156 | (1 == SSCANF (start, "inet %127s", addrstr)) || | 182 | (1 == SSCANF (start, "inet %127s", addrstr)) || |
157 | (1 == SSCANF (start, "inet6 %127s", addrstr))) | 183 | (1 == SSCANF (start, "inet6 %127s", addrstr))) |
@@ -165,11 +191,35 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | |||
165 | a4.sin_len = (u_char) sizeof (struct sockaddr_in); | 191 | a4.sin_len = (u_char) sizeof (struct sockaddr_in); |
166 | #endif | 192 | #endif |
167 | a4.sin_addr = v4; | 193 | a4.sin_addr = v4; |
194 | |||
195 | pass_bcaddr = NULL; | ||
196 | pass_netmask = NULL; | ||
197 | if (1 == inet_pton (AF_INET, bcstr, &v4)) | ||
198 | { | ||
199 | memset (&bcaddr, 0, sizeof (bcaddr)); | ||
200 | bcaddr.sin_family = AF_INET; | ||
201 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
202 | bcaddr.sin_len = (u_char) sizeof (struct sockaddr_in); | ||
203 | #endif | ||
204 | bcaddr.sin_addr = v4; | ||
205 | pass_bcaddr = (struct sockaddr *) &bcaddr; | ||
206 | } | ||
207 | if (1 == inet_pton (AF_INET, netmaskstr, &v4)) | ||
208 | { | ||
209 | memset (&netmask, 0, sizeof (netmask)); | ||
210 | netmask.sin_family = AF_INET; | ||
211 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
212 | netmask.sin_len = (u_char) sizeof (struct sockaddr_in); | ||
213 | #endif | ||
214 | netmask.sin_addr = v4; | ||
215 | pass_netmask = (struct sockaddr *) &netmask; | ||
216 | } | ||
217 | |||
218 | |||
168 | if (GNUNET_OK != | 219 | if (GNUNET_OK != |
169 | proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE), | 220 | proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE), |
170 | (const struct sockaddr *) &a4, | 221 | (const struct sockaddr *) &a4, |
171 | /* TODO broadcast and netmask */ | 222 | pass_bcaddr, pass_netmask, sizeof (a4))) |
172 | NULL, NULL, sizeof (a4))) | ||
173 | break; | 223 | break; |
174 | continue; | 224 | continue; |
175 | } | 225 | } |
@@ -182,11 +232,29 @@ GNUNET_OS_network_interfaces_list (GNUNET_OS_NetworkInterfaceProcessor proc, | |||
182 | a6.sin6_len = (u_char) sizeof (struct sockaddr_in6); | 232 | a6.sin6_len = (u_char) sizeof (struct sockaddr_in6); |
183 | #endif | 233 | #endif |
184 | a6.sin6_addr = v6; | 234 | a6.sin6_addr = v6; |
235 | |||
236 | pass_netmask = NULL; | ||
237 | if (prefixlen != -1) | ||
238 | { | ||
239 | memset (v6.s6_addr, 0, sizeof (v6.s6_addr)); | ||
240 | for (i = 0; i < prefixlen; i++) | ||
241 | { | ||
242 | v6.s6_addr[i >> 3] |= 1 << (i & 7); | ||
243 | } | ||
244 | memset (&netmask6, 0, sizeof (netmask6)); | ||
245 | netmask6.sin6_family = AF_INET6; | ||
246 | #if HAVE_SOCKADDR_IN_SIN_LEN | ||
247 | netmask6.sin6_len = (u_char) sizeof (struct sockaddr_in6); | ||
248 | #endif | ||
249 | netmask6.sin6_addr = v6; | ||
250 | |||
251 | pass_netmask = (struct sockaddr *) &netmask6; | ||
252 | } | ||
253 | |||
185 | if (GNUNET_OK != | 254 | if (GNUNET_OK != |
186 | proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE), | 255 | proc (proc_cls, ifc, 0 == strcmp (ifc, GNUNET_DEFAULT_INTERFACE), |
187 | (const struct sockaddr *) &a6, | 256 | (const struct sockaddr *) &a6, |
188 | /* TODO broadcast and netmask */ | 257 | NULL, pass_netmask, sizeof (a6))) |
189 | NULL, NULL, sizeof (a6))) | ||
190 | break; | 258 | break; |
191 | continue; | 259 | continue; |
192 | } | 260 | } |