1 /* GNet - Networking library
2 * Copyright (C) 2000-2003 David Helder
3 * Copyright (C) 2000-2003 Andrew Lanoix
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library General Public
7 * License as published by the Free Software Foundation; either
8 * version 2 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
19 */
20
21 #include "gnet-private.h"
22 #include "udp.h"
23
24 #define GNET_UDP_SOCKET_TYPE(s) (((GUdpSocket*)(s))->type)
25 #define GNET_IS_UDP_SOCKET(s) ((s) && (GNET_UDP_SOCKET_TYPE(s) == GNET_UDP_SOCKET_TYPE_COOKIE \
26 || GNET_UDP_SOCKET_TYPE(s) == GNET_MCAST_SOCKET_TYPE_COOKIE))
27
28 /**
29 * gnet_udp_socket_new
30 *
31 * Creates a #GUdpSocket bound to all interfaces and an arbitrary
32 * port.
33 *
34 * Returns: a new #GUdpSocket; NULL on error.
35 *
36 **/
37 GUdpSocket*
gnet_udp_socket_new(void)38 gnet_udp_socket_new (void)
39 {
40 return gnet_udp_socket_new_full (NULL, 0);
41 }
42
43
44 /**
45 * gnet_udp_socket_new_with_port:
46 * @port: port to bind to (0 for an arbitrary port)
47 *
48 * Creates a #GUdpSocket bound to all interfaces and port @port. If
49 * @port is 0, an arbitrary port will be used.
50 *
51 * Returns: a new #GUdpSocket; NULL on error.
52 *
53 **/
54 GUdpSocket*
gnet_udp_socket_new_with_port(gint port)55 gnet_udp_socket_new_with_port (gint port)
56 {
57 return gnet_udp_socket_new_full (NULL, port);
58 }
59
60
61 /**
62 * gnet_udp_socket_new_full
63 * @iface: interface to bind to (NULL for all interfaces)
64 * @port: port to bind to (0 for an arbitrary port)
65 *
66 * Creates a #GUdpSocket bound to interface @iface and port @port.
67 * If @iface is NULL, all interfaces will be used. If @port is 0, an
68 * arbitrary port will be used.
69 *
70 * Returns: a new #GUdpSocket; NULL on error.
71 *
72 **/
73 GUdpSocket*
gnet_udp_socket_new_full(const GInetAddr * iface,gint port)74 gnet_udp_socket_new_full (const GInetAddr* iface, gint port)
75 {
76 SOCKET sockfd;
77 struct sockaddr_storage sa;
78 GUdpSocket* s;
79 const int on = 1;
80
81 /* Create sockfd and address */
82 sockfd = _gnet_create_listen_socket (SOCK_DGRAM, iface, port, &sa);
83 if (!GNET_IS_SOCKET_VALID(sockfd))
84 {
85 g_warning ("socket() failed");
86 return NULL;
87 }
88
89 /* Set broadcast option. This allows the user to broadcast packets.
90 It has no effect otherwise. */
91 if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,
92 (void*) &on, sizeof(on)) != 0)
93 {
94 g_warning ("setsockopt() failed");
95 GNET_CLOSE_SOCKET(sockfd);
96 return NULL;
97 }
98
99 /* Bind to the socket to some local address and port */
100 if (bind(sockfd, &GNET_SOCKADDR_SA(sa), GNET_SOCKADDR_LEN(sa)) != 0)
101 {
102 GNET_CLOSE_SOCKET(sockfd);
103 return NULL;
104 }
105
106 /* Create UDP socket */
107 s = g_new0 (GUdpSocket, 1);
108 s->type = GNET_UDP_SOCKET_TYPE_COOKIE;
109 s->sockfd = sockfd;
110 s->sa = sa;
111 s->ref_count = 1;
112
113 return s;
114 }
115
116
117
118 /**
119 * gnet_udp_socket_delete:
120 * @socket: a #GUdpSocket, or NULL
121 *
122 * Deletes a #GUdpSocket. Does nothing if @socket is NULL.
123 *
124 **/
125 void
gnet_udp_socket_delete(GUdpSocket * socket)126 gnet_udp_socket_delete (GUdpSocket* socket)
127 {
128 if (socket != NULL) {
129 g_return_if_fail (GNET_IS_UDP_SOCKET (socket));
130
131 gnet_udp_socket_unref (socket);
132 }
133 }
134
135
136
137 /**
138 * gnet_udp_socket_ref
139 * @socket: #GUdpSocket to reference
140 *
141 * Adds a reference to a #GUdpSocket.
142 *
143 **/
144 void
gnet_udp_socket_ref(GUdpSocket * socket)145 gnet_udp_socket_ref (GUdpSocket* socket)
146 {
147 g_return_if_fail (socket != NULL);
148 g_return_if_fail (GNET_IS_UDP_SOCKET (socket));
149
150 g_atomic_int_inc (&socket->ref_count);
151 }
152
153
154 /**
155 * gnet_udp_socket_unref
156 * @socket: a #GUdpSocket
157 *
158 * Removes a reference from a #GUdpScoket. A #GUdpSocket is deleted
159 * when the reference count reaches 0.
160 *
161 **/
162 void
gnet_udp_socket_unref(GUdpSocket * socket)163 gnet_udp_socket_unref (GUdpSocket* socket)
164 {
165 g_return_if_fail (socket != NULL);
166 g_return_if_fail (GNET_IS_UDP_SOCKET (socket));
167
168 if (g_atomic_int_dec_and_test (&socket->ref_count)) {
169 GNET_CLOSE_SOCKET (socket->sockfd); /* Don't care if this fails... */
170
171 if (socket->iochannel)
172 g_io_channel_unref (socket->iochannel);
173
174 socket->type = 0;
175 g_free (socket);
176 }
177 }
178
179
180
181 /**
182 * gnet_udp_socket_get_io_channel
183 * @socket: a #GUdpSocket
184 *
185 * Gets the #GIOChannel of a #GUdpSocket.
186 *
187 * Use the channel with g_io_add_watch() to check if the socket is
188 * readable or writable. If the channel is readable, call
189 * gnet_udp_socket_receive() to receive a packet. If the channel is
190 * writable, call gnet_udp_socket_send() to send a packet. This is
191 * not a normal giochannel - do not read from or write to it.
192 *
193 * Every #GUdpSocket has one and only one #GIOChannel. If you ref
194 * the channel, then you must unref it eventually. Do not close the
195 * channel. The channel is closed by GNet when the socket is
196 * deleted.
197 *
198 * Before deleting the UDP socket, make sure to remove any watches you have
199 * added with g_io_add_watch() again with g_source_remove() using the integer
200 * id returned by g_io_add_watch(). You may find your program stuck in a busy
201 * loop at 100% CPU utilisation if you forget to do this.
202 *
203 * Returns: a #GIOChannel.
204 *
205 **/
206 GIOChannel*
gnet_udp_socket_get_io_channel(GUdpSocket * socket)207 gnet_udp_socket_get_io_channel (GUdpSocket* socket)
208 {
209 g_return_val_if_fail (socket != NULL, NULL);
210 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), NULL);
211
212 if (socket->iochannel == NULL)
213 socket->iochannel = _gnet_io_channel_new (socket->sockfd);
214
215 return socket->iochannel;
216 }
217
218
219
220 /**
221 * gnet_udp_socket_get_local_inetaddr
222 * @socket: a #GUdpSocket
223 *
224 * Gets the local host's address from a #GUdpSocket.
225 *
226 * Returns: a #GInetAddr.
227 *
228 **/
229 GInetAddr*
gnet_udp_socket_get_local_inetaddr(const GUdpSocket * socket)230 gnet_udp_socket_get_local_inetaddr (const GUdpSocket* socket)
231 {
232 socklen_t socklen;
233 struct sockaddr_storage sa;
234 GInetAddr* ia;
235
236 g_return_val_if_fail (socket, NULL);
237 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), NULL);
238
239 socklen = sizeof(sa);
240 if (getsockname(socket->sockfd, &GNET_SOCKADDR_SA(sa), &socklen) != 0)
241 return NULL;
242
243 ia = g_new0(GInetAddr, 1);
244 ia->ref_count = 1;
245 ia->sa = sa;
246
247 return ia;
248 }
249
250
251 /**
252 * gnet_udp_socket_send
253 * @socket: a #GUdpSocket
254 * @buffer: buffer to send
255 * @length: length of @buffer
256 * @dst: destination address
257 *
258 * Sends data to a host using a #GUdpSocket.
259 *
260 * Returns: 0 if successful; something else on error.
261 *
262 **/
263 gint
gnet_udp_socket_send(GUdpSocket * socket,const gchar * buffer,gint length,const GInetAddr * dst)264 gnet_udp_socket_send (GUdpSocket* socket,
265 const gchar* buffer, gint length,
266 const GInetAddr* dst)
267 {
268 gint bytes_sent;
269 struct sockaddr_storage sa;
270
271 g_return_val_if_fail (socket != NULL, -1);
272 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), -1);
273 g_return_val_if_fail (dst != NULL, -1);
274 g_return_val_if_fail (buffer != NULL, -1);
275
276 /* Address of dst must be address of socket */
277 #ifdef HAVE_IPV6
278 if (GNET_INETADDR_FAMILY(dst) != GNET_SOCKADDR_FAMILY(socket->sa))
279 {
280 /* If dst is IPv4, map to IPv6 */
281 if (GNET_INETADDR_FAMILY(dst) == AF_INET &&
282 GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET6)
283 {
284 GNET_SOCKADDR_FAMILY(sa) = AF_INET6;
285 GNET_SOCKADDR_SET_SS_LEN(sa);
286 GNET_SOCKADDR_PORT_SET(sa, GNET_INETADDR_PORT(dst));
287 GNET_SOCKADDR_ADDR32_SET(sa, 0, 0);
288 GNET_SOCKADDR_ADDR32_SET(sa, 1, 0);
289 GNET_SOCKADDR_ADDR32_SET(sa, 2, g_htonl(0xffff));
290 GNET_SOCKADDR_ADDR32_SET(sa, 3, GNET_INETADDR_ADDR32(dst, 0));
291 }
292
293 /* If dst is IPv6, map to IPv4 if possible */
294 else if (GNET_INETADDR_FAMILY(dst) == AF_INET6 &&
295 GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET &&
296 IN6_IS_ADDR_V4MAPPED(&GNET_INETADDR_SA6(dst).sin6_addr))
297 {
298 GNET_SOCKADDR_FAMILY(sa) = AF_INET;
299 GNET_SOCKADDR_SET_SS_LEN(sa);
300 GNET_SOCKADDR_PORT_SET(sa, GNET_INETADDR_PORT(dst));
301 GNET_SOCKADDR_ADDR32_SET(sa, 0, GNET_INETADDR_ADDR32(dst, 3));
302 }
303 else
304 return -1;
305
306 }
307 /* Addresses match - just copy the address */
308 else
309 #endif
310 {
311 sa = dst->sa;
312 }
313
314
315 bytes_sent = sendto (socket->sockfd,
316 (void*) buffer, length, 0,
317 (struct sockaddr*) &sa, GNET_SOCKADDR_LEN(sa));
318
319 if (bytes_sent != length)
320 return -1;
321
322 return 0;
323 }
324
325
326
327 /**
328 * gnet_udp_socket_receive
329 * @socket: a #GUdpSocket
330 * @buffer: buffer to write to
331 * @length: length of @buffer
332 * @src: pointer to source address (optional)
333 *
334 * Receives data using a #GUdpSocket. If @src is set, the source
335 * address is stored in the location @src points to. The address is
336 * caller owned.
337 *
338 * Returns: the number of bytes received, -1 on error.
339 *
340 **/
341 gint
gnet_udp_socket_receive(GUdpSocket * socket,gchar * buffer,gint length,GInetAddr ** src)342 gnet_udp_socket_receive (GUdpSocket* socket,
343 gchar* buffer, gint length,
344 GInetAddr** src)
345 {
346 gint bytes_received;
347 struct sockaddr_storage sa;
348 socklen_t sa_len = sizeof (struct sockaddr_storage);
349
350 g_return_val_if_fail (socket != NULL, -1);
351 g_return_val_if_fail (buffer != NULL, -1);
352 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), -1);
353
354 bytes_received = recvfrom (socket->sockfd,
355 (void*) buffer, length,
356 0, (struct sockaddr*) &sa, &sa_len);
357
358 if (bytes_received == -1)
359 return -1;
360
361 if (src)
362 {
363 (*src) = g_new0 (GInetAddr, 1);
364 (*src)->sa = sa;
365 (*src)->ref_count = 1;
366 }
367
368 return bytes_received;
369 }
370
371
372 #ifndef GNET_WIN32 /*********** Unix code ***********/
373
374
375 /**
376 * gnet_udp_socket_has_packet
377 * @socket: a #GUdpSocket
378 *
379 * Tests if a #GUdpSocket has a packet waiting to be received.
380 *
381 * Returns: TRUE if there is packet waiting, FALSE otherwise.
382 *
383 **/
384 gboolean
gnet_udp_socket_has_packet(const GUdpSocket * socket)385 gnet_udp_socket_has_packet (const GUdpSocket* socket)
386 {
387 fd_set readfds;
388 struct timeval timeout = {0, 0};
389
390 g_return_val_if_fail (socket != NULL, FALSE);
391 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), FALSE);
392
393 FD_ZERO (&readfds);
394 FD_SET (socket->sockfd, &readfds);
395 if ((select(socket->sockfd + 1, &readfds, NULL, NULL, &timeout)) == 1)
396 {
397 return TRUE;
398 }
399
400 return FALSE;
401 }
402
403
404 #else /*********** Windows code ***********/
405
406
407 gboolean
gnet_udp_socket_has_packet(const GUdpSocket * socket)408 gnet_udp_socket_has_packet (const GUdpSocket* socket)
409 {
410 gint bytes_received;
411 gchar data[1];
412 guint packetlength;
413 u_long arg;
414 gint error;
415
416 g_return_val_if_fail (socket != NULL, FALSE);
417 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), FALSE);
418
419 arg = 1;
420 ioctlsocket(socket->sockfd, FIONBIO, &arg); /* set to non-blocking mode */
421
422 packetlength = 1;
423 bytes_received = recvfrom(socket->sockfd, (void*) data, packetlength,
424 MSG_PEEK, NULL, NULL);
425
426 error = WSAGetLastError();
427
428 arg = 0;
429 ioctlsocket(socket->sockfd, FIONBIO, &arg); /* set blocking mode */
430
431 if (bytes_received == SOCKET_ERROR)
432 {
433 if (WSAEMSGSIZE != error)
434 {
435 return FALSE;
436 }
437 /* else, the buffer was not big enough, which is fine since we
438 just want to see if a packet is there..*/
439 }
440
441 if (bytes_received)
442 return TRUE;
443
444 return FALSE;
445 }
446
447 #endif /*********** End Windows code ***********/
448
449
450
451 /**
452 * gnet_udp_socket_get_ttl
453 * @socket: a #GUdpSocket
454 *
455 * Gets the time-to-live (TTL) default of a #GUdpSocket. All UDP
456 * packets have a TTL field. This field is decremented by a router
457 * before it forwards the packet. If the TTL reaches zero, the
458 * packet is discarded. The default value is sufficient for most
459 * applications.
460 *
461 * Returns: the TTL (an integer between 0 and 255), -1 if the kernel
462 * default is being used, or an integer less than -1 on error.
463 *
464 **/
465 gint
gnet_udp_socket_get_ttl(const GUdpSocket * socket)466 gnet_udp_socket_get_ttl (const GUdpSocket* socket)
467 {
468 int ttl;
469 socklen_t ttl_size;
470 int rv = -2;
471
472 g_return_val_if_fail (socket != NULL, FALSE);
473 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), FALSE);
474
475 ttl_size = sizeof(ttl);
476
477 /* Get the IPv4 TTL if it's bound to an IPv4 address */
478 if (GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET)
479 {
480 rv = getsockopt(socket->sockfd, IPPROTO_IP, IP_TTL,
481 (void*) &ttl, &ttl_size);
482 }
483
484 /* Or, get the IPv6 TTL if it's bound to an IPv6 address */
485 #ifdef HAVE_IPV6
486 else if (GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET6)
487 {
488 rv = getsockopt(socket->sockfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
489 (void*) &ttl, &ttl_size);
490 }
491 #endif
492 else
493 g_assert_not_reached();
494
495
496 if (rv == -1)
497 return -2;
498
499 return ttl;
500 }
501
502
503 /**
504 * gnet_udp_socket_set_ttl
505 * @socket: a #GUdpSocket
506 * @ttl: value to set TTL to
507 *
508 * Sets the time-to-live (TTL) default of a #GUdpSocket. Set the TTL
509 * to -1 to use the kernel default. The default value is sufficient
510 * for most applications.
511 *
512 * Returns: 0 if successful.
513 *
514 **/
515 gint
gnet_udp_socket_set_ttl(GUdpSocket * socket,gint ttl)516 gnet_udp_socket_set_ttl (GUdpSocket* socket, gint ttl)
517 {
518 int rv1, rv2;
519 #ifdef HAVE_IPV6
520 GIPv6Policy policy;
521 #endif
522
523 g_return_val_if_fail (socket != NULL, FALSE);
524 g_return_val_if_fail (GNET_IS_UDP_SOCKET (socket), FALSE);
525
526 rv1 = -1;
527 rv2 = -1;
528
529 /* If the bind address is anything IPv4 *or* the bind address is
530 0::0 IPv6 and IPv6 policy allows IPv4, set IP_TTL. In the latter case,
531 if we bind to 0::0 and the host is dual-stacked, then all IPv4
532 interfaces will be bound to also. */
533 if (GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET
534 #ifdef HAVE_IPV6
535 || (GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET6 &&
536 IN6_IS_ADDR_UNSPECIFIED(&GNET_SOCKADDR_SA6(socket->sa).sin6_addr) &&
537 ((policy = gnet_ipv6_get_policy()) == GIPV6_POLICY_IPV4_THEN_IPV6 ||
538 policy == GIPV6_POLICY_IPV6_THEN_IPV4))
539 #endif
540 )
541 {
542 rv1 = setsockopt(socket->sockfd, IPPROTO_IP, IP_TTL,
543 (void*) &ttl, sizeof(ttl));
544 }
545
546
547 /* If the bind address is IPv6, set IPV6_UNICAST_HOPS */
548 #ifdef HAVE_IPV6
549 if (GNET_SOCKADDR_FAMILY(socket->sa) == AF_INET6)
550 {
551 rv2 = setsockopt(socket->sockfd, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
552 (void*) &ttl, sizeof(ttl));
553 }
554 #endif
555
556 if (rv1 == -1 && rv2 == -1)
557 return -1;
558
559 return 0;
560 }
561