1 /*
2  * This file is part of the Sofia-SIP package
3  *
4  * Copyright (C) 2005,2006,2007 Nokia Corporation.
5  *
6  * Contact: Pekka Pessi <pekka.pessi@nokia.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public License
10  * as published by the Free Software Foundation; either version 2.1 of
11  * the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful, but
14  * WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
21  * 02110-1301 USA
22  *
23  */
24 
25 #ifndef SU_H
26 /** Defined when <sofia-sip/su.h> has been included. */
27 #define SU_H
28 /**@ingroup su_socket
29  * @file sofia-sip/su.h Socket and network address interface
30  *
31  * @author Pekka Pessi <Pekka.Pessi@nokia.com>
32  *
33  * @date Created: Thu Mar 18 19:40:51 1999 pessi
34  */
35 
36 /* ---------------------------------------------------------------------- */
37 /* Includes */
38 
39 #ifndef SU_CONFIG_H
40 #include <sofia-sip/su_config.h>
41 #endif
42 #ifndef SU_TYPES_H
43 #include <sofia-sip/su_types.h>
44 #endif
45 #ifndef SU_ERRNO_H
46 #include <sofia-sip/su_errno.h>
47 #endif
48 
49 #include <stdio.h>
50 #include <limits.h>
51 
52 #if SU_HAVE_BSDSOCK		/* Unix-compatible includes */
53 #include <errno.h>
54 #include <unistd.h>
55 
56 #include <fcntl.h>
57 #include <sys/types.h>
58 #include <sys/socket.h>
59 #include <sys/ioctl.h>
60 
61 #include <netinet/in.h>
62 #include <arpa/inet.h>
63 #include <netdb.h>
64 #endif
65 
66 #if SU_HAVE_WINSOCK		/* Windows includes */
67 #  include <winsock2.h>
68 #  include <ws2tcpip.h>
69 #  if SU_HAVE_IN6
70 #    if defined(IPPROTO_IPV6) || (_WIN32_WINNT >= 0x0501)
71 /*     case 1: IPv6 defined in winsock2.h/ws2tcpip.h */
72 #    else
73 /*     case 2: try to use "IPv6 Tech Preview" */
74 #      include <tpipv6.h>
75 #    endif
76 #  endif
77 #endif
78 
79 SOFIA_BEGIN_DECLS
80 
81 /* ---------------------------------------------------------------------- */
82 /* Constant definitions */
83 
84 #if SU_HAVE_BSDSOCK || DOCUMENTATION_ONLY
85 enum {
86   /** Invalid socket descriptor, error from socket() or accept() */
87   INVALID_SOCKET = -1,
88 #define INVALID_SOCKET ((su_socket_t)INVALID_SOCKET)
89   /** Error from other socket calls */
90   SOCKET_ERROR = -1,
91 #define SOCKET_ERROR SOCKET_ERROR
92   /** Return code for a successful call */
93   su_success = 0,
94   /** Return code for an unsuccessful call */
95   su_failure = -1
96 };
97 #if SYMBIAN && !defined(MSG_NOSIGNAL)
98 #define MSG_NOSIGNAL (0)
99 #endif
100 #elif SU_HAVE_WINSOCK
101 enum {
102   su_success = 0,
103   su_failure = 0xffffffffUL
104 };
105 
106 #define MSG_NOSIGNAL (0)
107 
108 #endif
109 
110 /**@HI Maximum size of host name. */
111 #define SU_MAXHOST (1025)
112 /**@HI Maximum size of service name. */
113 #define SU_MAXSERV (25)
114 
115 /**@HI Maximum size of address in text format. */
116 #define SU_ADDRSIZE (48)
117 /**@HI Maximum size of port number in text format. */
118 #define SU_SERVSIZE (16)
119 
120 #define SU_SUCCESS su_success
121 #define SU_FAILURE su_failure
122 
123 /* ---------------------------------------------------------------------- */
124 /* Type definitions */
125 
126 /** Socket descriptor type. */
127 #if SU_HAVE_BSDSOCK || DOCUMENTATION_ONLY
128 typedef int su_socket_t;
129 #elif SU_HAVE_WINSOCK
130 typedef SOCKET su_socket_t;
131 #endif
132 
133 #if !SU_HAVE_SOCKADDR_STORAGE
134 /*
135  * RFC 2553: protocol-independent placeholder for socket addresses
136  */
137 #define _SS_MAXSIZE	128
138 #define _SS_ALIGNSIZE	(sizeof(int64_t))
139 #define _SS_PAD1SIZE	(_SS_ALIGNSIZE - sizeof(u_char) * 2)
140 #define _SS_PAD2SIZE	(_SS_MAXSIZE - sizeof(u_char) * 2 - \
141 				_SS_PAD1SIZE - _SS_ALIGNSIZE)
142 
143 struct sockaddr_storage {
144 #if SU_HAVE_SOCKADDR_SA_LEN
145 	unsigned char ss_len;		/* address length */
146 	unsigned char ss_family;	/* address family */
147 #else
148 	unsigned short ss_family;	/* address family */
149 #endif
150 	char	__ss_pad1[_SS_PAD1SIZE];
151 	int64_t __ss_align;	/* force desired structure storage alignment */
152 	char	__ss_pad2[_SS_PAD2SIZE];
153 };
154 #endif
155 
156 /** Common socket address structure. */
157 union su_sockaddr_u {
158 #ifdef DOCUMENTATION_ONLY
159   uint8_t             su_len;         /**< Length of structure */
160   uint8_t             su_family;      /**< Address family. */
161   uint16_t            su_port;        /**< Port number. */
162 #else
163   short               su_dummy;	      /**< Dummy member to initialize */
164 #if SU_HAVE_SOCKADDR_SA_LEN
165 #define               su_len          su_sa.sa_len
166 #else
167 #define               su_len          su_array[0]
168 #endif
169 #define               su_family       su_sa.sa_family
170 #define               su_port         su_sin.sin_port
171 #endif
172 
173   char                su_array[32];   /**< Presented as chars */
174   uint16_t            su_array16[16]; /**< Presented as 16-bit ints */
175   uint32_t            su_array32[8];  /**< Presented as 32-bit ints */
176   struct sockaddr     su_sa;          /**< Address in struct sockaddr format */
177   struct sockaddr_in  su_sin;         /**< Address in IPv4 format */
178 #if SU_HAVE_IN6
179   struct sockaddr_in6 su_sin6;        /**< Address in IPv6 format */
180 #endif
181 #ifdef DOCUMENTATION_ONLY
182   uint32_t            su_scope_id;    /**< Scope ID. */
183 #else
184 #define               su_scope_id     su_array32[6]
185 #endif
186 };
187 
188 typedef union su_sockaddr_u su_sockaddr_t;
189 
190 #if SU_HAVE_BSDSOCK || DOCUMENTATION_ONLY
191 /**Type of @a siv_len field in #su_iovec_t.
192  *
193  * The @a siv_len field in #su_iovec_t has different types in with POSIX
194  * (size_t) and WINSOCK2 (u_long). Truncate the iovec element size to
195  * #SU_IOVECLEN_MAX, if needed, and cast using #su_ioveclen_t.
196  *
197  * @sa #su_iovec_t, #SU_IOVECLEN_MAX
198  *
199  * @since New in @VERSION_1_12_2.
200  */
201 typedef size_t su_ioveclen_t;
202 
203 /** I/O vector for scatter-gather I/O.
204  *
205  * This is the I/O vector element used with su_vsend() and su_vrecv(). It is
206  * defined like struct iovec with POSIX sockets:
207  * @code
208  * struct iovec {
209  *    void *iov_base;	// Pointer to data.
210  *    size_t iov_len;	// Length of data.
211  * };
212  * @endcode
213  *
214  * When using WINSOCK sockets it is defined as
215  * <a href="http://msdn.microsoft.com/library/en-us/winsock/winsock/wsabuf_2.asp">
216  * WSABUF</a>:
217  * @code
218  * typedef struct __WSABUF {
219  *   u_long len;
220  *   char FAR* buf;
221  * } WSABUF, *LPWSABUF;
222  * @endcode
223  *
224  * @note Ordering of the fields is reversed on Windows. Do not initialize
225  * this structure with static initializer, but assign both fields
226  * separately. Note that the type of the siv_len is #su_ioveclen_t which is
227  * defined as u_long on Windows and size_t on POSIX.
228  *
229  * For historical reasons, the structure is known as #msg_iovec_t in @msg
230  * module.
231  *
232  * @sa #su_ioveclen_t, SU_IOVECLEN_MAX, su_vsend(), su_vrecv(),
233  * #msg_iovec_t, msg_iovec(), msg_recv_iovec(),
234  * @c struct @c iovec defined in <sys/uio.h>, writev(2), readv(2),
235  * sendmsg(), recvmsg(),
236  * <a href="http://msdn.microsoft.com/library/en-us/winsock/winsock/wsabuf_2.asp">
237  * WSABUF of WinSock2</a>
238  */
239 typedef struct su_iovec_s {
240   void  *siv_base;		/**< Pointer to buffer. */
241   su_ioveclen_t siv_len;		/**< Size of buffer.  */
242 } su_iovec_t;
243 
244 /** Maximum size of buffer in a single su_iovec_t element.
245  * @sa #su_ioveclen_t, #su_iovec_t
246  *
247  * @since New in @VERSION_1_12_2.
248  * @HIDE
249  */
250 #define SU_IOVECLEN_MAX SIZE_MAX
251 #endif
252 
253 #if SU_HAVE_WINSOCK
254 typedef u_long su_ioveclen_t;
255 
256 /* This is same as WSABUF */
257 typedef struct su_iovec_s {
258   su_ioveclen_t  siv_len;
259   void   *siv_base;
260 } su_iovec_t;
261 
262 #define SU_IOVECLEN_MAX ULONG_MAX
263 #endif
264 
265 /* ---------------------------------------------------------------------- */
266 /* Socket compatibility functions */
267 
268 SOFIAPUBFUN int su_init(void);
269 SOFIAPUBFUN void su_deinit(void);
270 
271 /** Create an endpoint for communication. */
272 SOFIAPUBFUN su_socket_t su_socket(int af, int sock, int proto);
273 /** Close an socket descriptor. */
274 SOFIAPUBFUN int su_close(su_socket_t s);
275 /** Control socket. */
276 SOFIAPUBFUN int su_ioctl(su_socket_t s, int request, ...);
277 
278 /**Check for in-progress error codes.
279  *
280  * Checks if the @a errcode indicates that the socket call failed because
281  * it would have blocked.
282  *
283  * Defined as macro with POSIX sockets.
284  *
285  * @since New in @VERSION_1_12_2.
286  */
287 SOFIAPUBFUN int su_is_blocking(int errcode);
288 
289 /** Set/reset blocking option. */
290 SOFIAPUBFUN int su_setblocking(su_socket_t s, int blocking);
291 /** Set/reset address reusing option. */
292 SOFIAPUBFUN int su_setreuseaddr(su_socket_t s, int reuse);
293 /** Get the error code associated with the socket. */
294 SOFIAPUBFUN int su_soerror(su_socket_t s);
295 /** Get the socket type. */
296 SOFIAPUBFUN int su_getsocktype(su_socket_t s);
297 
298 /** Get size of message available in socket. */
299 SOFIAPUBFUN issize_t su_getmsgsize(su_socket_t s);
300 
301 /** Scatter-gather send. */
302 SOFIAPUBFUN
303 issize_t su_vsend(su_socket_t, su_iovec_t const iov[], isize_t len, int flags,
304 		  su_sockaddr_t const *su, socklen_t sulen);
305 /** Scatter-gather receive. */
306 SOFIAPUBFUN
307 issize_t su_vrecv(su_socket_t, su_iovec_t iov[], isize_t len, int flags,
308 		  su_sockaddr_t *su, socklen_t *sulen);
309 /** Return local IP address */
310 SOFIAPUBFUN int su_getlocalip(su_sockaddr_t *sin);
311 
312 #if SU_HAVE_BSDSOCK
313 #define su_ioctl  ioctl
314 /*
315  * Note: before 1.12.2, there was su_isblocking() which did not take argument
316  * and which was missing from WINSOCK
317  */
318 #define su_is_blocking(e) \
319 ((e) == EINPROGRESS || (e) == EAGAIN || (e) == EWOULDBLOCK || (e) == EINTR)
320 #endif
321 
322 #if SU_HAVE_WINSOCK
323 SOFIAPUBFUN int su_inet_pton(int af, char const *src, void *dst);
324 SOFIAPUBFUN const char *su_inet_ntop(int af, void const *src,
325 				  char *dst, size_t size);
326 SOFIAPUBFUN ssize_t
327   su_send(su_socket_t s, void *buffer, size_t length, int flags),
328   su_sendto(su_socket_t s, void *buffer, size_t length, int flags,
329 	    su_sockaddr_t const *to, socklen_t tolen),
330   su_recv(su_socket_t s, void *buffer, size_t length, int flags),
331   su_recvfrom(su_socket_t s, void *buffer, size_t length, int flags,
332 	      su_sockaddr_t *from, socklen_t *fromlen);
333 
334 static __inline
su_ntohs(uint16_t s)335 uint16_t su_ntohs(uint16_t s)
336 {
337   return (uint16_t)(((s & 255) << 8) | ((s & 0xff00) >> 8));
338 }
339 
340 static __inline
su_ntohl(uint32_t l)341 uint32_t su_ntohl(uint32_t l)
342 {
343   return ((l & 0xff) << 24) | ((l & 0xff00) << 8)
344        | ((l & 0xff0000) >> 8) | ((l & 0xff000000U) >> 24);
345 }
346 
347 #define ntohs su_ntohs
348 #define htons su_ntohs
349 #define ntohl su_ntohl
350 #define htonl su_ntohl
351 
352 #else
353 #define su_inet_pton inet_pton
354 #define su_inet_ntop inet_ntop
355 #define su_send(s,b,l,f) send((s),(b),(l),(f))
356 #define su_sendto(s,b,l,f,a,L) sendto((s),(b),(l),(f),(void const*)(a),(L))
357 #define su_recv(s,b,l,f) recv((s),(b),(l),(f))
358 #define su_recvfrom(s,b,l,f,a,L) recvfrom((s),(b),(l),(f),(void *)(a),(L))
359 #endif
360 
361 /* ---------------------------------------------------------------------- */
362 /* Other compatibility stuff */
363 
364 #if SU_HAVE_WINSOCK
365 #define getuid() (0x505)
366 #endif
367 
368 #ifndef IPPROTO_SCTP
369 #define IPPROTO_SCTP (132)
370 #endif
371 
372 /* ---------------------------------------------------------------------- */
373 /* Address manipulation macros */
374 
375 /**@HI Get pointer to address field.
376  *
377  * The macro SU_ADDR() returns pointer to the address field (sin_data,
378  * sin_addr or sin_addr6, depending on the address family).
379  */
380 #if SU_HAVE_IN6
381 #define SU_ADDR(su) \
382   ((su)->su_family == AF_INET ? (void *)&(su)->su_sin.sin_addr : \
383   ((su)->su_family == AF_INET6 ? (void *)&(su)->su_sin6.sin6_addr : \
384   (void *)&(su)->su_sa.sa_data))
385 #else
386 #define SU_ADDR(su) \
387   ((su)->su_family == AF_INET ? (void *)&(su)->su_sin.sin_addr : \
388   (void *)&(su)->su_sa.sa_data)
389 #endif
390 
391 /**@HI Get length of address field.
392  *
393  * The macro SU_ADDRLEN() returns length of the address field (sin_data,
394  * sin_addr or sin_addr6, depending on the address family).
395  */
396 #if SU_HAVE_IN6
397 #define SU_ADDRLEN(su)					\
398   ((su)->su_family == AF_INET				\
399    ? (socklen_t)sizeof((su)->su_sin.sin_addr) :		\
400    ((su)->su_family == AF_INET6				\
401     ? (socklen_t)sizeof((su)->su_sin6.sin6_addr)	\
402     : (socklen_t)sizeof((su)->su_sa.sa_data)))
403 #else
404 #define SU_ADDRLEN(su)					\
405   ((su)->su_family == AF_INET				\
406    ? (socklen_t)sizeof((su)->su_sin.sin_addr)		\
407    : (socklen_t)sizeof((su)->su_sa.sa_data))
408 #endif
409 
410 /**@HI Test if su_sockaddr_t is INADDR_ANY or IN6ADDR_ANY. */
411 #if SU_HAVE_IN6
412 #define SU_HAS_INADDR_ANY(su) \
413   ((su)->su_family == AF_INET \
414    ? ((su)->su_sin.sin_addr.s_addr == INADDR_ANY) \
415    : ((su)->su_family == AF_INET6 \
416       ? (memcmp(&(su)->su_sin6.sin6_addr, su_in6addr_any(), \
417 		sizeof(*su_in6addr_any())) == 0) : 0))
418 #else
419 #define SU_HAS_INADDR_ANY(su) \
420   ((su)->su_family == AF_INET \
421   ? ((su)->su_sin.sin_addr.s_addr == INADDR_ANY) : 0)
422 #endif
423 
424 #define SU_SOCKADDR_INADDR_ANY(su) SU_HAS_INADDR_ANY(su)
425 
426 /**@HI Calculate correct size of su_sockaddr_t structure. */
427 #if SU_HAVE_IN6
428 #define SU_SOCKADDR_SIZE(su) \
429   ((socklen_t)((su)->su_family == AF_INET ? sizeof((su)->su_sin)	  \
430 	       : ((su)->su_family == AF_INET6 ? sizeof((su)->su_sin6)	\
431 		  : sizeof(*su))))
432 #else
433 #define SU_SOCKADDR_SIZE(su) \
434   ((socklen_t)((su)->su_family == AF_INET ? sizeof((su)->su_sin)	\
435 	       : sizeof(*su)))
436 #endif
437 #define su_sockaddr_size SU_SOCKADDR_SIZE
438 
439 #if SU_HAVE_IN6
440 #if SU_HAVE_BSDSOCK
441 #define su_in6addr_any()         (&in6addr_any)
442 #define su_in6addr_loopback()    (&in6addr_loopback)
443 #define SU_IN6ADDR_ANY_INIT      IN6ADDR_ANY_INIT
444 #define SU_IN6ADDR_LOOPBACK_INIT IN6ADDR_LOOPBACK_INIT
445 #endif
446 #if SU_HAVE_WINSOCK || DOCUMENTATION_ONLY
447 SOFIAPUBVAR const struct in_addr6 *su_in6addr_any(void);
448 SOFIAPUBVAR const struct in_addr6 *su_in6addr_loopback(void);
449 #define SU_IN6ADDR_ANY_INIT      { 0 }
450 #define SU_IN6ADDR_LOOPBACK_INIT { 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,1 }
451 #endif
452 #endif /* SU_HAVE_IN6 */
453 
454 #define SU_IN6_IS_ADDR_V4MAPPED(a) \
455   (((uint32_t const *) (a))[0] == 0 &&			      \
456    ((uint32_t const *) (a))[1] == 0 &&			      \
457    ((uint32_t const *) (a))[2] == htonl(0xffff))
458 
459 #define SU_IN6_IS_ADDR_V4COMPAT(a)			      \
460   (((uint32_t const *)(a))[0] == 0 &&			      \
461    ((uint32_t const *)(a))[1] == 0 &&			      \
462    ((uint32_t const *)(a))[2] == 0 &&			      \
463    ((uint32_t const *)(a))[3] != htonl(1) &&		      \
464    ((uint32_t const *)(a))[3] != htonl(0))
465 
466 SOFIAPUBFUN int su_cmp_sockaddr(su_sockaddr_t const *a,
467 				su_sockaddr_t const *b);
468 SOFIAPUBFUN int su_match_sockaddr(su_sockaddr_t const *a,
469 				  su_sockaddr_t const *b);
470 SOFIAPUBFUN void su_canonize_sockaddr(su_sockaddr_t *su);
471 
472 #if SU_HAVE_IN6
473 #define SU_CANONIZE_SOCKADDR(su) \
474   ((su)->su_family == AF_INET6 ? su_canonize_sockaddr(su) : (void)0)
475 #else
476 #define SU_CANONIZE_SOCKADDR(su) \
477   ((void)0)
478 #endif
479 
480 SOFIA_END_DECLS
481 
482 #ifndef SU_ADDRINFO_H
483 #include <sofia-sip/su_addrinfo.h>
484 #endif
485 
486 #endif /* !defined(SU_H) */
487