2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2005, Digium, Inc.
6 * Kevin P. Fleming <kpfleming@digium.com>
7 * Mark Spencer <markster@digium.com>
9 * See http://www.asterisk.org for more information about
10 * the Asterisk project. Please do not directly contact
11 * any of the maintainers of this project for assistance;
12 * the project provides a web site, mailing lists and IRC
13 * channels for your use.
15 * This program is free software, distributed under the terms of
16 * the GNU General Public License Version 2. See the LICENSE file
17 * at the top of the source tree.
22 * \brief Network socket handling
24 * \author Kevin P. Fleming <kpfleming@digium.com>
25 * \author Mark Spencer <markster@digium.com>
30 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
39 #include <netinet/in.h>
40 #include <arpa/inet.h>
41 #include <sys/socket.h>
44 #include <netinet/in_systm.h>
45 #include <netinet/ip.h>
46 #include <sys/ioctl.h>
48 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
50 #include <net/route.h>
54 #include <sys/sockio.h>
57 #include "asterisk/netsock.h"
58 #include "asterisk/logger.h"
59 #include "asterisk/channel.h"
60 #include "asterisk/options.h"
61 #include "asterisk/utils.h"
62 #include "asterisk/lock.h"
63 #include "asterisk/srv.h"
66 ASTOBJ_COMPONENTS(struct ast_netsock
);
67 struct sockaddr_in bindaddr
;
70 struct io_context
*ioc
;
74 struct ast_netsock_list
{
75 ASTOBJ_CONTAINER_COMPONENTS(struct ast_netsock
);
76 struct io_context
*ioc
;
79 static void ast_netsock_destroy(struct ast_netsock
*netsock
)
81 ast_io_remove(netsock
->ioc
, netsock
->ioref
);
82 close(netsock
->sockfd
);
86 struct ast_netsock_list
*ast_netsock_list_alloc(void)
88 return ast_calloc(1, sizeof(struct ast_netsock_list
));
91 int ast_netsock_init(struct ast_netsock_list
*list
)
93 memset(list
, 0, sizeof(*list
));
94 ASTOBJ_CONTAINER_INIT(list
);
99 int ast_netsock_release(struct ast_netsock_list
*list
)
101 ASTOBJ_CONTAINER_DESTROYALL(list
, ast_netsock_destroy
);
102 ASTOBJ_CONTAINER_DESTROY(list
);
107 struct ast_netsock
*ast_netsock_find(struct ast_netsock_list
*list
,
108 struct sockaddr_in
*sa
)
110 struct ast_netsock
*sock
= NULL
;
112 ASTOBJ_CONTAINER_TRAVERSE(list
, !sock
, {
113 ASTOBJ_RDLOCK(iterator
);
114 if (!inaddrcmp(&iterator
->bindaddr
, sa
))
116 ASTOBJ_UNLOCK(iterator
);
122 struct ast_netsock
*ast_netsock_bindaddr(struct ast_netsock_list
*list
, struct io_context
*ioc
, struct sockaddr_in
*bindaddr
, int tos
, ast_io_cb callback
, void *data
)
127 struct ast_netsock
*ns
;
128 const int reuseFlag
= 1;
130 /* Make a UDP socket */
131 netsocket
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
134 ast_log(LOG_ERROR
, "Unable to create network socket: %s\n", strerror(errno
));
137 if (setsockopt(netsocket
, SOL_SOCKET
, SO_REUSEADDR
, (char *)&reuseFlag
, sizeof reuseFlag
) < 0) {
138 ast_log(LOG_WARNING
, "Error setting SO_REUSEADDR on sockfd '%d'\n", netsocket
);
140 if (bind(netsocket
,(struct sockaddr
*)bindaddr
, sizeof(struct sockaddr_in
))) {
141 ast_log(LOG_ERROR
, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(bindaddr
->sin_addr
), ntohs(bindaddr
->sin_port
), strerror(errno
));
145 if (option_verbose
> 1)
146 ast_verbose(VERBOSE_PREFIX_2
"Using TOS bits %d\n", tos
);
148 if (setsockopt(netsocket
, IPPROTO_IP
, IP_TOS
, &tos
, sizeof(tos
)))
149 ast_log(LOG_WARNING
, "Unable to set TOS to %d\n", tos
);
151 ast_enable_packet_fragmentation(netsocket
);
153 if (!(ns
= ast_calloc(1, sizeof(struct ast_netsock
)))) {
158 /* Establish I/O callback for socket read */
159 if (!(ioref
= ast_io_add(ioc
, netsocket
, callback
, AST_IO_IN
, ns
))) {
167 ns
->sockfd
= netsocket
;
169 memcpy(&ns
->bindaddr
, bindaddr
, sizeof(ns
->bindaddr
));
170 ASTOBJ_CONTAINER_LINK(list
, ns
);
175 struct ast_netsock
*ast_netsock_bind(struct ast_netsock_list
*list
, struct io_context
*ioc
, const char *bindinfo
, int defaultport
, int tos
, ast_io_cb callback
, void *data
)
177 struct sockaddr_in sin
;
183 memset(&sin
, 0, sizeof(sin
));
184 sin
.sin_family
= AF_INET
;
185 sin
.sin_port
= htons(defaultport
);
186 tmp
= ast_strdupa(bindinfo
);
188 host
= strsep(&tmp
, ":");
191 if (port
&& ((portno
= atoi(port
)) > 0))
192 sin
.sin_port
= htons(portno
);
194 inet_aton(host
, &sin
.sin_addr
);
196 return ast_netsock_bindaddr(list
, ioc
, &sin
, tos
, callback
, data
);
199 int ast_netsock_sockfd(const struct ast_netsock
*ns
)
201 return ns
? ns
-> sockfd
: -1;
204 const struct sockaddr_in
*ast_netsock_boundaddr(const struct ast_netsock
*ns
)
206 return &(ns
->bindaddr
);
209 void *ast_netsock_data(const struct ast_netsock
*ns
)
214 void ast_netsock_unref(struct ast_netsock
*ns
)
216 ASTOBJ_UNREF(ns
, ast_netsock_destroy
);