Mercurial > pidgin
comparison libpurple/proxy.c @ 25480:e859785b49d8
Implement support for resolving DNS via the SOCKS4 proxy in use.
Currently this relies on a global preference, which I'm not super happy about.
Ideally, we'd just try to always do this and fall back to a local DNS lookup
when the SOCKS4 server doesn't like it, but I don't think we can reliably detect
that.
Fixes #3230
author | Daniel Atallah <daniel.atallah@gmail.com> |
---|---|
date | Tue, 17 Feb 2009 23:42:49 +0000 |
parents | 8fa011906ac3 |
children | 4b8c4870b13a |
comparison
equal
deleted
inserted
replaced
25479:8fa011906ac3 | 25480:e859785b49d8 |
---|---|
1199 /* Discard the length... */ | 1199 /* Discard the length... */ |
1200 hosts = g_slist_delete_link(hosts, hosts); | 1200 hosts = g_slist_delete_link(hosts, hosts); |
1201 addr = hosts->data; | 1201 addr = hosts->data; |
1202 hosts = g_slist_delete_link(hosts, hosts); | 1202 hosts = g_slist_delete_link(hosts, hosts); |
1203 | 1203 |
1204 packet[0] = 4; | 1204 packet[0] = 0x04; |
1205 packet[1] = 1; | 1205 packet[1] = 0x01; |
1206 packet[2] = connect_data->port >> 8; | 1206 packet[2] = connect_data->port >> 8; |
1207 packet[3] = connect_data->port & 0xff; | 1207 packet[3] = connect_data->port & 0xff; |
1208 memcpy(packet + 4, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); | 1208 memcpy(packet + 4, &((struct sockaddr_in *)addr)->sin_addr.s_addr, 4); |
1209 packet[8] = 0; | 1209 packet[8] = 0x00; |
1210 | 1210 |
1211 g_free(addr); | 1211 g_free(addr); |
1212 | 1212 |
1213 /* We could try the other hosts, but hopefully that shouldn't be necessary */ | 1213 /* We could try the other hosts, but hopefully that shouldn't be necessary */ |
1214 while (hosts != NULL) { | 1214 while (hosts != NULL) { |
1250 purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); | 1250 purple_proxy_connect_data_disconnect(connect_data, g_strerror(error)); |
1251 return; | 1251 return; |
1252 } | 1252 } |
1253 | 1253 |
1254 /* | 1254 /* |
1255 * The socks4 spec doesn't include support for doing host name | 1255 * The socks4 spec doesn't include support for doing host name lookups by |
1256 * lookups by the proxy. Some socks4 servers do this via | 1256 * the proxy. Many socks4 servers do this via the "socks4a" extension to |
1257 * extensions to the protocol. Since we don't know if a | 1257 * the protocol. There doesn't appear to be a way to detect if a server |
1258 * server supports this, it would need to be implemented | 1258 * supports this, so we require that the user set a global option. |
1259 * with an option, or some detection mechanism - in the | |
1260 * meantime, stick with plain old SOCKS4. | |
1261 */ | 1259 */ |
1262 connect_data->query_data = purple_dnsquery_a(connect_data->host, | 1260 if (purple_prefs_get_bool("/purple/proxy/socks4_remotedns")) { |
1263 connect_data->port, s4_host_resolved, connect_data); | 1261 unsigned char packet[9]; |
1264 | 1262 int len; |
1265 if (connect_data->query_data == NULL) { | 1263 |
1266 purple_debug_error("proxy", "dns query failed unexpectedly.\n"); | 1264 purple_debug_info("socks4 proxy", "Attempting to use remote DNS.\n"); |
1267 purple_proxy_connect_data_destroy(connect_data); | 1265 |
1266 packet[0] = 0x04; | |
1267 packet[1] = 0x01; | |
1268 packet[2] = connect_data->port >> 8; | |
1269 packet[3] = connect_data->port & 0xff; | |
1270 packet[4] = 0x00; | |
1271 packet[5] = 0x00; | |
1272 packet[6] = 0x00; | |
1273 packet[7] = 0x01; | |
1274 packet[8] = 0x00; | |
1275 | |
1276 len = sizeof(packet) + strlen(connect_data->host) + 1; | |
1277 | |
1278 connect_data->write_buffer = g_malloc0(len); | |
1279 memcpy(connect_data->write_buffer, packet, sizeof(packet)); | |
1280 memcpy(connect_data->write_buffer + sizeof(packet), connect_data->host, strlen(connect_data->host)); | |
1281 connect_data->write_buf_len = len; | |
1282 connect_data->written_len = 0; | |
1283 connect_data->read_cb = s4_canread; | |
1284 | |
1285 connect_data->inpa = purple_input_add(connect_data->fd, PURPLE_INPUT_WRITE, proxy_do_write, connect_data); | |
1286 | |
1287 proxy_do_write(connect_data, connect_data->fd, PURPLE_INPUT_WRITE); | |
1288 } else { | |
1289 connect_data->query_data = purple_dnsquery_a(connect_data->host, | |
1290 connect_data->port, s4_host_resolved, connect_data); | |
1291 | |
1292 if (connect_data->query_data == NULL) { | |
1293 purple_debug_error("proxy", "dns query failed unexpectedly.\n"); | |
1294 purple_proxy_connect_data_destroy(connect_data); | |
1295 } | |
1268 } | 1296 } |
1269 } | 1297 } |
1270 | 1298 |
1271 static void | 1299 static void |
1272 proxy_connect_socks4(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) | 1300 proxy_connect_socks4(PurpleProxyConnectData *connect_data, struct sockaddr *addr, socklen_t addrlen) |
2321 purple_prefs_add_string("/purple/proxy/type", "none"); | 2349 purple_prefs_add_string("/purple/proxy/type", "none"); |
2322 purple_prefs_add_string("/purple/proxy/host", ""); | 2350 purple_prefs_add_string("/purple/proxy/host", ""); |
2323 purple_prefs_add_int("/purple/proxy/port", 0); | 2351 purple_prefs_add_int("/purple/proxy/port", 0); |
2324 purple_prefs_add_string("/purple/proxy/username", ""); | 2352 purple_prefs_add_string("/purple/proxy/username", ""); |
2325 purple_prefs_add_string("/purple/proxy/password", ""); | 2353 purple_prefs_add_string("/purple/proxy/password", ""); |
2354 purple_prefs_add_bool("/purple/proxy/socks4_remotedns", FALSE); | |
2326 | 2355 |
2327 /* Setup callbacks for the preferences. */ | 2356 /* Setup callbacks for the preferences. */ |
2328 handle = purple_proxy_get_handle(); | 2357 handle = purple_proxy_get_handle(); |
2329 purple_prefs_connect_callback(handle, "/purple/proxy/type", proxy_pref_cb, | 2358 purple_prefs_connect_callback(handle, "/purple/proxy/type", proxy_pref_cb, |
2330 NULL); | 2359 NULL); |