| 190 mib[3] = 0; /* address family - 0 for all addres families */ |
190 mib[3] = 0; /* address family - 0 for all addres families */ |
| 191 mib[4] = NET_RT_DUMP; |
191 mib[4] = NET_RT_DUMP; |
| 192 mib[5] = 0; |
192 mib[5] = 0; |
| 193 |
193 |
| 194 /* Determine the buffer side needed to get the full routing table */ |
194 /* Determine the buffer side needed to get the full routing table */ |
| 195 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) |
195 if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0) |
| 196 { |
196 { |
| 197 purple_debug_warning("nat-pmp", "sysctl: net.route.0.0.dump estimate\n"); |
197 purple_debug_warning("nat-pmp", "sysctl: net.route.0.0.dump estimate\n"); |
| 198 return NULL; |
198 return NULL; |
| 199 } |
199 } |
| 200 |
200 |
| 203 purple_debug_warning("nat-pmp", "Failed to malloc %i\n", needed); |
203 purple_debug_warning("nat-pmp", "Failed to malloc %i\n", needed); |
| 204 return NULL; |
204 return NULL; |
| 205 } |
205 } |
| 206 |
206 |
| 207 /* Read the routing table into buf */ |
207 /* Read the routing table into buf */ |
| 208 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) |
208 if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) |
| 209 { |
209 { |
| 210 purple_debug_warning("nat-pmp", "sysctl: net.route.0.0.dump\n"); |
210 purple_debug_warning("nat-pmp", "sysctl: net.route.0.0.dump\n"); |
| 211 return NULL; |
211 return NULL; |
| 212 } |
212 } |
| 213 |
213 |
| 214 lim = buf + needed; |
214 lim = buf + needed; |
| 215 |
215 |
| 216 for (next = buf; next < lim; next += rtm->rtm_msglen) |
216 for (next = buf; next < lim; next += rtm->rtm_msglen) |
| 217 { |
217 { |
| 218 rtm = (struct rt_msghdr *)next; |
218 rtm = (struct rt_msghdr *)next; |
| 219 sa = (struct sockaddr *)(rtm + 1); |
219 sa = (struct sockaddr *)(rtm + 1); |
| 220 |
220 |
| 221 if (sa->sa_family == AF_INET) |
221 if (sa->sa_family == AF_INET) |
| 222 { |
222 { |
| 223 sin = (struct sockaddr_in*) sa; |
223 sin = (struct sockaddr_in*) sa; |
| 224 |
224 |
| 225 if ((rtm->rtm_flags & RTF_GATEWAY) && sin->sin_addr.s_addr == INADDR_ANY) |
225 if ((rtm->rtm_flags & RTF_GATEWAY) && sin->sin_addr.s_addr == INADDR_ANY) |
| 226 { |
226 { |
| 238 |
238 |
| 239 if (rtm->rtm_addrs & RTA_NETMASK) |
239 if (rtm->rtm_addrs & RTA_NETMASK) |
| 240 memcpy(&mask, rti_info[RTAX_NETMASK], sizeof(mask)); |
240 memcpy(&mask, rti_info[RTAX_NETMASK], sizeof(mask)); |
| 241 |
241 |
| 242 if (rtm->rtm_addrs & RTA_GATEWAY && |
242 if (rtm->rtm_addrs & RTA_GATEWAY && |
| 243 is_default_route(&addr, &mask)) |
243 is_default_route(&addr, &mask)) |
| 244 { |
244 { |
| 245 if (rti_info[RTAX_GATEWAY]) { |
245 if (rti_info[RTAX_GATEWAY]) { |
| 246 struct sockaddr_in *rti_sin = (struct sockaddr_in *)rti_info[RTAX_GATEWAY]; |
246 struct sockaddr_in *rti_sin = (struct sockaddr_in *)rti_info[RTAX_GATEWAY]; |
| 247 sin = g_new0(struct sockaddr_in, 1); |
247 sin = g_new0(struct sockaddr_in, 1); |
| 248 sin->sin_family = rti_sin->sin_family; |
248 sin->sin_family = rti_sin->sin_family; |
| 261 |
261 |
| 262 return (found ? sin : NULL); |
262 return (found ? sin : NULL); |
| 263 } |
263 } |
| 264 |
264 |
| 265 /*! |
265 /*! |
| 266 * purple_pmp_get_public_ip() will return the publicly facing IP address of the |
266 * purple_pmp_get_public_ip() will return the publicly facing IP address of the |
| 267 * default NAT gateway. The function will return NULL if: |
267 * default NAT gateway. The function will return NULL if: |
| 268 * - The gateway doesn't support NAT-PMP |
268 * - The gateway doesn't support NAT-PMP |
| 269 * - The gateway errors in some other spectacular fashion |
269 * - The gateway errors in some other spectacular fashion |
| 270 */ |
270 */ |
| 271 char * |
271 char * |
| 276 socklen_t len; |
276 socklen_t len; |
| 277 |
277 |
| 278 PurplePmpIpRequest req; |
278 PurplePmpIpRequest req; |
| 279 PurplePmpIpResponse resp; |
279 PurplePmpIpResponse resp; |
| 280 int sendfd; |
280 int sendfd; |
| 281 |
281 |
| 282 if (pmp_info.status == PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER) |
282 if (pmp_info.status == PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER) |
| 283 return NULL; |
283 return NULL; |
| 284 |
284 |
| 285 if ((pmp_info.status == PURPLE_PMP_STATUS_DISCOVERED) && (pmp_info.publicip != NULL)) |
285 if ((pmp_info.status == PURPLE_PMP_STATUS_DISCOVERED) && (pmp_info.publicip != NULL)) |
| 286 { |
286 { |
| 287 #ifdef PMP_DEBUG |
287 #ifdef PMP_DEBUG |
| 288 purple_debug_info("nat-pmp", "Returning cached publicip %s\n",pmp_info.publicip); |
288 purple_debug_info("nat-pmp", "Returning cached publicip %s\n",pmp_info.publicip); |
| 289 #endif |
289 #endif |
| 316 req.opcode = 0; |
316 req.opcode = 0; |
| 317 |
317 |
| 318 /* The NAT-PMP spec says we should attempt to contact the gateway 9 times, doubling the time we wait each time. |
318 /* The NAT-PMP spec says we should attempt to contact the gateway 9 times, doubling the time we wait each time. |
| 319 * Even starting with a timeout of 0.1 seconds, that means that we have a total waiting of 204.6 seconds. |
319 * Even starting with a timeout of 0.1 seconds, that means that we have a total waiting of 204.6 seconds. |
| 320 * With the recommended timeout of 0.25 seconds, we're talking 511.5 seconds (8.5 minutes). |
320 * With the recommended timeout of 0.25 seconds, we're talking 511.5 seconds (8.5 minutes). |
| 321 * |
321 * |
| 322 * This seems really silly... if this were nonblocking, a couple retries might be in order, but it's not at present. |
322 * This seems really silly... if this were nonblocking, a couple retries might be in order, but it's not at present. |
| 323 */ |
323 */ |
| 324 #ifdef PMP_DEBUG |
324 #ifdef PMP_DEBUG |
| 325 purple_debug_info("nat-pmp", "Attempting to retrieve the public ip address for the NAT device at: %s\n", inet_ntoa(gateway->sin_addr)); |
325 purple_debug_info("nat-pmp", "Attempting to retrieve the public ip address for the NAT device at: %s\n", inet_ntoa(gateway->sin_addr)); |
| 326 purple_debug_info("nat-pmp", "\tTimeout: %ds %dus\n", req_timeout.tv_sec, req_timeout.tv_usec); |
326 purple_debug_info("nat-pmp", "\tTimeout: %ds %dus\n", req_timeout.tv_sec, req_timeout.tv_usec); |
| 327 #endif |
327 #endif |
| 328 |
328 |
| 329 /* TODO: Non-blocking! */ |
329 /* TODO: Non-blocking! */ |
| 330 |
330 |
| 331 if (sendto(sendfd, &req, sizeof(req), 0, (struct sockaddr *)(gateway), sizeof(struct sockaddr)) < 0) |
331 if (sendto(sendfd, &req, sizeof(req), 0, (struct sockaddr *)(gateway), sizeof(struct sockaddr)) < 0) |
| 332 { |
332 { |
| 333 purple_debug_info("nat-pmp", "There was an error sending the NAT-PMP public IP request! (%s)\n", g_strerror(errno)); |
333 purple_debug_info("nat-pmp", "There was an error sending the NAT-PMP public IP request! (%s)\n", g_strerror(errno)); |
| 334 g_free(gateway); |
334 g_free(gateway); |
| 335 pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER; |
335 pmp_info.status = PURPLE_PMP_STATUS_UNABLE_TO_DISCOVER; |
| 435 req.lifetime = htonl(lifetime); |
435 req.lifetime = htonl(lifetime); |
| 436 |
436 |
| 437 /* The NAT-PMP spec says we should attempt to contact the gateway 9 times, doubling the time we wait each time. |
437 /* The NAT-PMP spec says we should attempt to contact the gateway 9 times, doubling the time we wait each time. |
| 438 * Even starting with a timeout of 0.1 seconds, that means that we have a total waiting of 204.6 seconds. |
438 * Even starting with a timeout of 0.1 seconds, that means that we have a total waiting of 204.6 seconds. |
| 439 * With the recommended timeout of 0.25 seconds, we're talking 511.5 seconds (8.5 minutes). |
439 * With the recommended timeout of 0.25 seconds, we're talking 511.5 seconds (8.5 minutes). |
| 440 * |
440 * |
| 441 * This seems really silly... if this were nonblocking, a couple retries might be in order, but it's not at present. |
441 * This seems really silly... if this were nonblocking, a couple retries might be in order, but it's not at present. |
| 442 * XXX Make this nonblocking. |
442 * XXX Make this nonblocking. |
| 443 * XXX This code looks like the pmp_get_public_ip() code. Can it be consolidated? |
443 * XXX This code looks like the pmp_get_public_ip() code. Can it be consolidated? |
| 444 */ |
444 */ |
| 445 #ifdef PMP_DEBUG |
445 #ifdef PMP_DEBUG |