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>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <sys/socket.h>
40 #include <netinet/in_systm.h>
41 #include <netinet/ip.h>
42 #include <sys/ioctl.h>
44 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__)
46 #include <net/route.h>
50 #include <sys/sockio.h>
55 ASTERISK_FILE_VERSION(__FILE__
, "$Revision$")
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 struct ast_netsock_list
*res
;
90 res
= calloc(1, sizeof(*res
));
95 int ast_netsock_init(struct ast_netsock_list
*list
)
97 memset(list
, 0, sizeof(*list
));
98 ASTOBJ_CONTAINER_INIT(list
);
103 int ast_netsock_release(struct ast_netsock_list
*list
)
105 ASTOBJ_CONTAINER_DESTROYALL(list
, ast_netsock_destroy
);
106 ASTOBJ_CONTAINER_DESTROY(list
);
111 struct ast_netsock
*ast_netsock_find(struct ast_netsock_list
*list
,
112 struct sockaddr_in
*sa
)
114 struct ast_netsock
*sock
= NULL
;
116 ASTOBJ_CONTAINER_TRAVERSE(list
, !sock
, {
117 ASTOBJ_RDLOCK(iterator
);
118 if (!inaddrcmp(&iterator
->bindaddr
, sa
))
120 ASTOBJ_UNLOCK(iterator
);
126 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
)
130 char iabuf
[INET_ADDRSTRLEN
];
132 struct ast_netsock
*ns
;
134 /* Make a UDP socket */
135 netsocket
= socket(AF_INET
, SOCK_DGRAM
, IPPROTO_IP
);
138 ast_log(LOG_ERROR
, "Unable to create network socket: %s\n", strerror(errno
));
141 if (bind(netsocket
,(struct sockaddr
*)bindaddr
, sizeof(struct sockaddr_in
))) {
142 ast_log(LOG_ERROR
, "Unable to bind to %s port %d: %s\n", ast_inet_ntoa(iabuf
, sizeof(iabuf
), bindaddr
->sin_addr
), ntohs(bindaddr
->sin_port
), strerror(errno
));
146 if (option_verbose
> 1)
147 ast_verbose(VERBOSE_PREFIX_2
"Using TOS bits %d\n", tos
);
149 if (setsockopt(netsocket
, IPPROTO_IP
, IP_TOS
, &tos
, sizeof(tos
)))
150 ast_log(LOG_WARNING
, "Unable to set TOS to %d\n", tos
);
152 ns
= malloc(sizeof(struct ast_netsock
));
154 /* Establish I/O callback for socket read */
155 ioref
= ast_io_add(ioc
, netsocket
, callback
, AST_IO_IN
, ns
);
157 ast_log(LOG_WARNING
, "Out of memory!\n");
165 ns
->sockfd
= netsocket
;
167 memcpy(&ns
->bindaddr
, bindaddr
, sizeof(ns
->bindaddr
));
168 ASTOBJ_CONTAINER_LINK(list
, ns
);
170 ast_log(LOG_WARNING
, "Out of memory!\n");
177 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
)
179 struct sockaddr_in sin
;
185 memset(&sin
, 0, sizeof(sin
));
186 sin
.sin_family
= AF_INET
;
187 sin
.sin_port
= htons(defaultport
);
188 tmp
= ast_strdupa(bindinfo
);
190 ast_log(LOG_WARNING
, "Out of memory!\n");
194 host
= strsep(&tmp
, ":");
197 if (port
&& ((portno
= atoi(port
)) > 0))
198 sin
.sin_port
= htons(portno
);
200 inet_aton(host
, &sin
.sin_addr
);
202 return ast_netsock_bindaddr(list
, ioc
, &sin
, tos
, callback
, data
);
205 int ast_netsock_sockfd(const struct ast_netsock
*ns
)
207 return ns
? ns
-> sockfd
: -1;
210 const struct sockaddr_in
*ast_netsock_boundaddr(const struct ast_netsock
*ns
)
212 return &(ns
->bindaddr
);
215 void *ast_netsock_data(const struct ast_netsock
*ns
)
220 void ast_netsock_unref(struct ast_netsock
*ns
)
222 ASTOBJ_UNREF(ns
, ast_netsock_destroy
);