Sat, 08 May 2004 23:34:30 +0000
[gaim-migrate @ 9677]
" Fixes a few warnings on 64bit machines. Also fixes
yahoo auth on 64bit machines which would have taken me
awhile if marv didn't point me in the right direction.
I've applied to my local 32bit copy and everything
seems to be working fine." --Gary Kramlich
committer: Luke Schierer <lschiere@pidgin.im>
| 8231 | 1 | /** |
| 2 | * @file network.c Network Implementation | |
| 3 | * @ingroup core | |
| 4 | * | |
| 5 | * gaim | |
| 6 | * | |
| 7 | * Gaim is the legal property of its developers, whose names are too numerous | |
| 8 | * to list here. Please refer to the COPYRIGHT file distributed with this | |
| 9 | * source distribution. | |
| 10 | * | |
| 11 | * This program is free software; you can redistribute it and/or modify | |
| 12 | * it under the terms of the GNU General Public License as published by | |
| 13 | * the Free Software Foundation; either version 2 of the License, or | |
| 14 | * (at your option) any later version. | |
| 15 | * | |
| 16 | * This program is distributed in the hope that it will be useful, | |
| 17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| 18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| 19 | * GNU General Public License for more details. | |
| 20 | * | |
| 21 | * You should have received a copy of the GNU General Public License | |
| 22 | * along with this program; if not, write to the Free Software | |
| 23 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
| 24 | */ | |
| 25 | ||
|
8245
c1397ca0a619
[gaim-migrate @ 8968]
Herman Bloggs <herman@bluedigits.com>
parents:
8240
diff
changeset
|
26 | #include "internal.h" |
| 8231 | 27 | |
| 28 | #include "debug.h" | |
| 29 | #include "account.h" | |
| 30 | #include "network.h" | |
| 31 | #include "prefs.h" | |
| 32 | ||
|
8838
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
33 | const unsigned char * |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
34 | gaim_network_ip_atoi(const char *ip) |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
35 | { |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
36 | static unsigned char ret[4]; |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
37 | gchar delimiter = '.'; |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
38 | gchar **split; |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
39 | int i; |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
40 | |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
41 | g_return_val_if_fail(ip != NULL, NULL); |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
42 | |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
43 | split = g_strsplit(ip, &delimiter, 4); |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
44 | for (i = 0; split[i] != NULL; i++) |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
45 | ret[i] = atoi(split[i]); |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
46 | g_strfreev(split); |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
47 | |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
48 | /* i should always be 4 */ |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
49 | if (i != 4) |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
50 | return NULL; |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
51 | |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
52 | return ret; |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
53 | } |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
54 | |
| 8231 | 55 | void |
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
56 | gaim_network_set_public_ip(const char *ip) |
| 8231 | 57 | { |
| 58 | g_return_if_fail(ip != NULL); | |
| 59 | ||
|
8838
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
60 | /* XXX - Ensure the IP address is valid */ |
|
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
61 | |
| 8231 | 62 | gaim_prefs_set_string("/core/network/public_ip", ip); |
| 63 | } | |
| 64 | ||
| 65 | const char * | |
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
66 | gaim_network_get_public_ip(void) |
| 8231 | 67 | { |
| 68 | const char *ip; | |
| 69 | ||
| 70 | ip = gaim_prefs_get_string("/core/network/public_ip"); | |
| 71 | ||
| 72 | if (ip == NULL || *ip == '\0') | |
| 73 | return NULL; | |
| 74 | ||
| 75 | return ip; | |
| 76 | } | |
| 77 | ||
| 78 | static const char * | |
| 79 | gaim_network_get_local_ip_from_fd(int fd) | |
| 80 | { | |
| 81 | struct sockaddr_in addr; | |
| 82 | socklen_t len; | |
| 83 | static char ip[16]; | |
| 84 | const char *tmp; | |
| 85 | ||
|
8840
414e20c7c010
[gaim-migrate @ 9607]
Mark Doliner <markdoliner@pidgin.im>
parents:
8838
diff
changeset
|
86 | g_return_val_if_fail(fd >= 0, NULL); |
| 8231 | 87 | |
| 88 | len = sizeof(addr); | |
| 89 | if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
| 90 | gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
| 91 | return NULL; | |
| 92 | } | |
| 93 | ||
| 94 | tmp = inet_ntoa(addr.sin_addr); | |
| 95 | strncpy(ip, tmp, sizeof(ip)); | |
|
8838
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
96 | |
| 8231 | 97 | return ip; |
| 98 | } | |
| 99 | ||
| 100 | const char * | |
| 101 | gaim_network_get_local_system_ip(int fd) | |
| 102 | { | |
| 103 | struct hostent *host; | |
| 104 | char localhost[129]; | |
| 105 | long unsigned add; | |
| 106 | static char ip[46]; | |
| 107 | const char *tmp = NULL; | |
| 108 | ||
|
8840
414e20c7c010
[gaim-migrate @ 9607]
Mark Doliner <markdoliner@pidgin.im>
parents:
8838
diff
changeset
|
109 | if (fd >= 0) |
| 8231 | 110 | tmp = gaim_network_get_local_ip_from_fd(fd); |
| 111 | ||
| 112 | if (tmp) | |
| 113 | return tmp; | |
| 114 | ||
| 115 | if (gethostname(localhost, 128) < 0) | |
| 116 | return NULL; | |
| 117 | ||
| 118 | if ((host = gethostbyname(localhost)) == NULL) | |
| 119 | return NULL; | |
| 120 | ||
| 121 | memcpy(&add, host->h_addr_list[0], 4); | |
| 122 | add = htonl(add); | |
| 123 | ||
| 124 | g_snprintf(ip, 16, "%lu.%lu.%lu.%lu", | |
| 125 | ((add >> 24) & 255), | |
| 126 | ((add >> 16) & 255), | |
| 127 | ((add >> 8) & 255), | |
| 128 | add & 255); | |
| 129 | ||
| 130 | return ip; | |
| 131 | } | |
| 132 | ||
| 133 | const char * | |
|
8838
c23227da7b4a
[gaim-migrate @ 9604]
Mark Doliner <markdoliner@pidgin.im>
parents:
8834
diff
changeset
|
134 | gaim_network_get_my_ip(int fd) |
| 8231 | 135 | { |
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
136 | const char *ip = NULL; |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
137 | |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
138 | /* Check if the user specified an IP manually */ |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
139 | if (!gaim_prefs_get_bool("/core/network/auto_ip")) { |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
140 | ip = gaim_network_get_public_ip(); |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
141 | if (ip != NULL) |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
142 | return ip; |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
143 | } |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
144 | |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
145 | /* Just fetch the IP of the local system */ |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
146 | return gaim_network_get_local_system_ip(fd); |
| 8231 | 147 | } |
| 148 | ||
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
149 | static int |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
150 | gaim_network_do_listen(unsigned short port) |
| 8231 | 151 | { |
| 152 | #if HAVE_GETADDRINFO | |
| 153 | int listenfd; | |
| 154 | const int on = 1; | |
| 155 | struct addrinfo hints, *res, *ressave; | |
| 156 | char serv[5]; | |
| 157 | ||
|
8251
091ca9b900c1
[gaim-migrate @ 8974]
Mark Doliner <markdoliner@pidgin.im>
parents:
8250
diff
changeset
|
158 | snprintf(serv, sizeof(serv), "%d", port); |
| 8231 | 159 | memset(&hints, 0, sizeof(struct addrinfo)); |
| 160 | hints.ai_flags = AI_PASSIVE; | |
| 161 | hints.ai_family = AF_UNSPEC; | |
| 162 | hints.ai_socktype = SOCK_STREAM; | |
| 163 | if (getaddrinfo(NULL /* any IP */, serv, &hints, &res) != 0) { | |
| 164 | gaim_debug_warning("network", "getaddrinfo: %s\n", strerror(errno)); | |
| 165 | return -1; | |
| 166 | } | |
| 167 | ressave = res; | |
| 168 | do { | |
| 169 | listenfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
| 170 | if (listenfd < 0) | |
| 171 | continue; | |
| 172 | setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)); | |
| 173 | if (bind(listenfd, res->ai_addr, res->ai_addrlen) == 0) | |
| 174 | break; /* success */ | |
| 175 | close(listenfd); | |
| 176 | } while ( (res = res->ai_next) ); | |
| 177 | ||
| 178 | if (!res) | |
| 179 | return -1; | |
| 180 | ||
| 181 | freeaddrinfo(ressave); | |
| 182 | #else | |
| 183 | int listenfd; | |
| 184 | const int on = 1; | |
| 185 | struct sockaddr_in sockin; | |
| 186 | ||
| 187 | if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { | |
| 188 | gaim_debug_warning("network", "socket: %s\n", strerror(errno)); | |
| 189 | return -1; | |
| 190 | } | |
| 191 | ||
| 192 | if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0) { | |
| 193 | gaim_debug_warning("network", "setsockopt: %s\n", strerror(errno)); | |
| 194 | close(listenfd); | |
| 195 | return -1; | |
| 196 | } | |
| 197 | ||
| 198 | memset(&sockin, 0, sizeof(struct sockaddr_in)); | |
| 199 | sockin.sin_family = AF_INET; | |
|
8251
091ca9b900c1
[gaim-migrate @ 8974]
Mark Doliner <markdoliner@pidgin.im>
parents:
8250
diff
changeset
|
200 | sockin.sin_port = htons(port); |
| 8231 | 201 | |
| 202 | if (bind(listenfd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0) { | |
| 203 | gaim_debug_warning("network", "bind: %s\n", strerror(errno)); | |
| 204 | close(listenfd); | |
| 205 | return -1; | |
| 206 | } | |
| 207 | #endif | |
| 208 | ||
| 209 | if (listen(listenfd, 4) != 0) { | |
| 210 | gaim_debug_warning("network", "listen: %s\n", strerror(errno)); | |
| 211 | close(listenfd); | |
| 212 | return -1; | |
| 213 | } | |
| 214 | fcntl(listenfd, F_SETFL, O_NONBLOCK); | |
| 215 | ||
| 216 | gaim_debug_info("network", "Listening on port: %hu\n", gaim_network_get_port_from_fd(listenfd)); | |
| 217 | return listenfd; | |
| 218 | } | |
| 219 | ||
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
220 | int |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
221 | gaim_network_listen(unsigned short port) |
|
8246
c83c0421149a
[gaim-migrate @ 8969]
Mark Doliner <markdoliner@pidgin.im>
parents:
8245
diff
changeset
|
222 | { |
|
8250
e855dcce1fa0
[gaim-migrate @ 8973]
Mark Doliner <markdoliner@pidgin.im>
parents:
8248
diff
changeset
|
223 | g_return_val_if_fail(port != 0, -1); |
|
e855dcce1fa0
[gaim-migrate @ 8973]
Mark Doliner <markdoliner@pidgin.im>
parents:
8248
diff
changeset
|
224 | |
|
8246
c83c0421149a
[gaim-migrate @ 8969]
Mark Doliner <markdoliner@pidgin.im>
parents:
8245
diff
changeset
|
225 | return gaim_network_do_listen(port); |
|
c83c0421149a
[gaim-migrate @ 8969]
Mark Doliner <markdoliner@pidgin.im>
parents:
8245
diff
changeset
|
226 | } |
|
c83c0421149a
[gaim-migrate @ 8969]
Mark Doliner <markdoliner@pidgin.im>
parents:
8245
diff
changeset
|
227 | |
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
228 | int |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
229 | gaim_network_listen_range(unsigned short start, unsigned short end) |
| 8231 | 230 | { |
|
8240
2e5f97ed575d
[gaim-migrate @ 8963]
Mark Doliner <markdoliner@pidgin.im>
parents:
8239
diff
changeset
|
231 | int ret = -1; |
| 8231 | 232 | |
|
8250
e855dcce1fa0
[gaim-migrate @ 8973]
Mark Doliner <markdoliner@pidgin.im>
parents:
8248
diff
changeset
|
233 | if (gaim_prefs_get_bool("/core/network/ports_range_use")) { |
|
8239
d19f1c66720c
[gaim-migrate @ 8962]
Mark Doliner <markdoliner@pidgin.im>
parents:
8231
diff
changeset
|
234 | start = gaim_prefs_get_int("/core/network/ports_range_start"); |
|
d19f1c66720c
[gaim-migrate @ 8962]
Mark Doliner <markdoliner@pidgin.im>
parents:
8231
diff
changeset
|
235 | end = gaim_prefs_get_int("/core/network/ports_range_end"); |
|
8250
e855dcce1fa0
[gaim-migrate @ 8973]
Mark Doliner <markdoliner@pidgin.im>
parents:
8248
diff
changeset
|
236 | } else { |
|
e855dcce1fa0
[gaim-migrate @ 8973]
Mark Doliner <markdoliner@pidgin.im>
parents:
8248
diff
changeset
|
237 | if (end < start) |
|
e855dcce1fa0
[gaim-migrate @ 8973]
Mark Doliner <markdoliner@pidgin.im>
parents:
8248
diff
changeset
|
238 | end = start; |
|
8239
d19f1c66720c
[gaim-migrate @ 8962]
Mark Doliner <markdoliner@pidgin.im>
parents:
8231
diff
changeset
|
239 | } |
| 8231 | 240 | |
| 241 | for (; start <= end; start++) { | |
| 242 | ret = gaim_network_do_listen(start); | |
| 243 | if (ret >= 0) | |
| 244 | break; | |
| 245 | } | |
| 246 | ||
| 247 | return ret; | |
| 248 | } | |
| 249 | ||
|
8834
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
250 | unsigned short |
|
0a798e3d2b84
[gaim-migrate @ 9598]
Mark Doliner <markdoliner@pidgin.im>
parents:
8251
diff
changeset
|
251 | gaim_network_get_port_from_fd(int fd) |
| 8231 | 252 | { |
| 253 | struct sockaddr_in addr; | |
| 254 | socklen_t len; | |
| 255 | ||
| 256 | g_return_val_if_fail(fd > 0, 0); | |
| 257 | ||
| 258 | len = sizeof(addr); | |
| 259 | if (getsockname(fd, (struct sockaddr *) &addr, &len) == -1) { | |
| 260 | gaim_debug_warning("network", "getsockname: %s\n", strerror(errno)); | |
| 261 | return 0; | |
| 262 | } | |
| 263 | ||
| 264 | return ntohs(addr.sin_port); | |
| 265 | } | |
| 266 | ||
| 267 | void | |
| 268 | gaim_network_init(void) | |
| 269 | { | |
| 270 | gaim_prefs_add_none ("/core/network"); | |
| 271 | gaim_prefs_add_bool ("/core/network/auto_ip", TRUE); | |
| 272 | gaim_prefs_add_string("/core/network/public_ip", ""); | |
| 273 | gaim_prefs_add_bool ("/core/network/ports_range_use", FALSE); | |
| 274 | gaim_prefs_add_int ("/core/network/ports_range_start", 1024); | |
| 275 | gaim_prefs_add_int ("/core/network/ports_range_end", 2048); | |
| 276 | } |