Asterisk - The Open Source Telephony Project  18.5.0
netsock.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Kevin P. Fleming <[email protected]>
7  * Mark Spencer <[email protected]>
8  *
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.
14  *
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.
18  */
19 
20 /*! \file
21  *
22  * \brief Network socket handling
23  *
24  * \author Kevin P. Fleming <[email protected]>
25  * \author Mark Spencer <[email protected]>
26  */
27 
28 /*** MODULEINFO
29  <support_level>core</support_level>
30  ***/
31 
32 #include "asterisk.h"
33 
34 #if !defined (__linux__) && !defined (__GNU__)
35 #if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__Darwin__) || defined(__GLIBC__)
36 #include <net/if_dl.h>
37 #endif
38 #endif
39 
40 #if defined (SOLARIS)
41 #include <sys/sockio.h>
42 #elif defined(HAVE_GETIFADDRS)
43 #include <ifaddrs.h>
44 #endif
45 
46 #include "include/netsock.h"
47 #include "asterisk/netsock2.h"
48 #include "asterisk/utils.h"
49 #include "include/astobj.h"
50 
51 struct ast_netsock {
54  int sockfd;
55  int *ioref;
56  struct io_context *ioc;
57  void *data;
58 };
59 
62  struct io_context *ioc;
63 };
64 
66 {
67  ast_io_remove(netsock->ioc, netsock->ioref);
68  close(netsock->sockfd);
69  ast_free(netsock);
70 }
71 
73 {
74  return ast_calloc(1, sizeof(struct ast_netsock_list));
75 }
76 
78 {
79  memset(list, 0, sizeof(*list));
81 
82  return 0;
83 }
84 
86 {
89  ast_free(list);
90 
91  return 0;
92 }
93 
94 struct ast_netsock *ast_netsock_find(struct ast_netsock_list *list, struct ast_sockaddr *addr)
95 {
96  struct ast_netsock *sock = NULL;
97 
98  ASTOBJ_CONTAINER_TRAVERSE(list, !sock, {
99  ASTOBJ_RDLOCK(iterator);
100  if (!ast_sockaddr_cmp(&iterator->bindaddr, addr)) {
101  sock = iterator;
102  }
103  ASTOBJ_UNLOCK(iterator);
104  });
105 
106  return sock;
107 }
108 
109 struct ast_netsock *ast_netsock_bindaddr(struct ast_netsock_list *list, struct io_context *ioc, struct ast_sockaddr *bindaddr, int tos, int cos, ast_io_cb callback, void *data)
110 {
111  int netsocket = -1;
112  int *ioref;
113 
114  struct ast_netsock *ns;
115  const int reuseFlag = 1;
116 
117  /* Make a UDP socket */
118  netsocket = socket(ast_sockaddr_is_ipv6(bindaddr) ? AST_AF_INET6 : AST_AF_INET, SOCK_DGRAM, IPPROTO_IP);
119 
120  if (netsocket < 0) {
121  ast_log(LOG_ERROR, "Unable to create network socket: %s\n", strerror(errno));
122  return NULL;
123  }
124  if (setsockopt(netsocket, SOL_SOCKET, SO_REUSEADDR, (char *)&reuseFlag, sizeof reuseFlag) < 0) {
125  ast_log(LOG_WARNING, "Error setting SO_REUSEADDR on sockfd '%d'\n", netsocket);
126  }
127  if (ast_bind(netsocket, bindaddr)) {
129  "Unable to bind to %s: %s\n",
130  ast_sockaddr_stringify(bindaddr),
131  strerror(errno));
132  close(netsocket);
133  return NULL;
134  }
135 
136  ast_set_qos(netsocket, tos, cos, "IAX2");
137 
139 
140  if (!(ns = ast_calloc(1, sizeof(*ns)))) {
141  close(netsocket);
142  return NULL;
143  }
144 
145  /* Establish I/O callback for socket read */
146  if (!(ioref = ast_io_add(ioc, netsocket, callback, AST_IO_IN, ns))) {
147  close(netsocket);
148  ast_free(ns);
149  return NULL;
150  }
151  ASTOBJ_INIT(ns);
152  ns->ioref = ioref;
153  ns->ioc = ioc;
154  ns->sockfd = netsocket;
155  ns->data = data;
156  ast_sockaddr_copy(&ns->bindaddr, bindaddr);
157  ASTOBJ_CONTAINER_LINK(list, ns);
158 
159  return ns;
160 }
161 
162 int ast_netsock_set_qos(int sockfd, int tos, int cos, const char *desc)
163 {
164  return ast_set_qos(sockfd, tos, cos, desc);
165 }
166 
167 struct ast_netsock *ast_netsock_bind(struct ast_netsock_list *list, struct io_context *ioc, const char *bindinfo, int defaultport, int tos, int cos, ast_io_cb callback, void *data)
168 {
169  struct ast_sockaddr addr;
170 
171  if (ast_sockaddr_parse(&addr, bindinfo, 0)) {
172 
173  if (!ast_sockaddr_port(&addr)) {
174  ast_sockaddr_set_port(&addr, defaultport);
175  }
176 
177  return ast_netsock_bindaddr(list, ioc, &addr, tos, cos, callback, data);
178  }
179 
180  return NULL;
181 }
182 
183 int ast_netsock_sockfd(const struct ast_netsock *ns)
184 {
185  return ns ? ns-> sockfd : -1;
186 }
187 
188 const struct ast_sockaddr *ast_netsock_boundaddr(const struct ast_netsock *ns)
189 {
190  return &ns->bindaddr;
191 }
192 
193 void *ast_netsock_data(const struct ast_netsock *ns)
194 {
195  return ns->data;
196 }
197 
199 {
201 }
void * data
Definition: netsock.c:57
unsigned int cos
Definition: chan_iax2.c:352
void ast_enable_packet_fragmentation(int sock)
Disable PMTU discovery on a socket.
Definition: main/utils.c:2221
struct ast_netsock * ast_netsock_bindaddr(struct ast_netsock_list *list, struct io_context *ioc, struct ast_sockaddr *bindaddr, int tos, int cos, ast_io_cb callback, void *data)
Definition: netsock.c:109
Asterisk main include file. File version handling, generic pbx functions.
struct io_context * ioc
Definition: netsock.c:56
int ast_sockaddr_parse(struct ast_sockaddr *addr, const char *str, int flags)
Parse an IPv4 or IPv6 address string.
Definition: netsock2.c:230
static void ast_sockaddr_copy(struct ast_sockaddr *dst, const struct ast_sockaddr *src)
Copies the data from one ast_sockaddr to another.
Definition: netsock2.h:171
int sockfd
Definition: netsock.c:54
static struct ast_netsock_list * netsock
Definition: chan_iax2.c:362
#define LOG_WARNING
Definition: logger.h:274
#define AST_IO_IN
Definition: io.h:34
static const char desc[]
Definition: cdr_mysql.c:73
int * ast_io_add(struct io_context *ioc, int fd, ast_io_cb callback, short events, void *data)
Adds an IO context.
Definition: io.c:162
int ast_netsock_sockfd(const struct ast_netsock *ns)
Definition: netsock.c:183
int * ioref
Definition: netsock.c:55
#define ASTOBJ_CONTAINER_COMPONENTS(type)
Create a container for ASTOBJs (with locking support).
Definition: astobj.h:731
#define NULL
Definition: resample.c:96
int ast_sockaddr_cmp(const struct ast_sockaddr *a, const struct ast_sockaddr *b)
Compares two ast_sockaddr structures.
Definition: netsock2.c:388
Socket address structure.
Definition: netsock2.h:97
int ast_bind(int sockfd, const struct ast_sockaddr *addr)
Wrapper around bind(2) that uses struct ast_sockaddr.
Definition: netsock2.c:590
struct ast_sockaddr bindaddr
Definition: netsock.c:53
Utility functions.
unsigned int tos
Definition: chan_iax2.c:351
#define ASTOBJ_COMPONENTS(type)
Add ASTOBJ components to a struct (with locking support).
Definition: astobj.h:175
struct ast_netsock * ast_netsock_bind(struct ast_netsock_list *list, struct io_context *ioc, const char *bindinfo, int defaultport, int tos, int cos, ast_io_cb callback, void *data)
Definition: netsock.c:167
#define ASTOBJ_CONTAINER_INIT(container)
Initialize a container.
Definition: astobj.h:754
#define ast_sockaddr_port(addr)
Get the port number of a socket address.
Definition: netsock2.h:521
static int netsocket
Definition: pbx_dundi.c:186
#define ast_log
Definition: astobj2.c:42
int(* ast_io_cb)(int *id, int fd, short events, void *cbdata)
Definition: io.h:72
Network socket handling.
Global IO variables are now in a struct in order to be made threadsafe.
Definition: io.c:71
struct io_context * ioc
Definition: netsock.c:62
void ast_netsock_unref(struct ast_netsock *ns)
Definition: netsock.c:198
#define ASTOBJ_INIT(object)
Initialize an object.
Definition: astobj.h:266
Network socket handling.
#define ASTOBJ_UNREF(object, destructor)
Decrement the reference count on an object.
Definition: astobj.h:220
#define ASTOBJ_CONTAINER_DESTROY(container)
Destroy a container.
Definition: astobj.h:767
#define LOG_ERROR
Definition: logger.h:285
#define ASTOBJ_CONTAINER_DESTROYALL(container, destructor)
Empty a container.
Definition: astobj.h:455
Object Model for Asterisk.
#define ASTOBJ_CONTAINER_LINK(container, newobj)
Add an object to a container.
Definition: astobj.h:778
#define ast_sockaddr_set_port(addr, port)
Sets the port number of a socket address.
Definition: netsock2.h:537
int ast_set_qos(int sockfd, int tos, int cos, const char *desc)
Set type of service.
Definition: netsock2.c:621
const struct ast_sockaddr * ast_netsock_boundaddr(const struct ast_netsock *ns)
Definition: netsock.c:188
int errno
static char * ast_sockaddr_stringify(const struct ast_sockaddr *addr)
Wrapper around ast_sockaddr_stringify_fmt() with default format.
Definition: netsock2.h:260
#define ASTOBJ_CONTAINER_TRAVERSE(container, continue, eval)
Iterate through the objects in a container.
Definition: astobj.h:378
#define ASTOBJ_UNLOCK(object)
Unlock a locked object.
Definition: astobj.h:111
#define ast_free(a)
Definition: astmm.h:182
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:204
int ast_netsock_set_qos(int sockfd, int tos, int cos, const char *desc)
Definition: netsock.c:162
struct ast_netsock * ast_netsock_find(struct ast_netsock_list *list, struct ast_sockaddr *addr)
Definition: netsock.c:94
int ast_io_remove(struct io_context *ioc, int *id)
Removes an IO context.
Definition: io.c:245
int ast_netsock_init(struct ast_netsock_list *list)
Definition: netsock.c:77
struct ast_netsock_list * ast_netsock_list_alloc(void)
Definition: netsock.c:72
#define ASTOBJ_RDLOCK(object)
Lock an ASTOBJ for reading.
Definition: astobj.h:102
void * ast_netsock_data(const struct ast_netsock *ns)
Definition: netsock.c:193
int ast_netsock_release(struct ast_netsock_list *list)
Definition: netsock.c:85
static void ast_netsock_destroy(struct ast_netsock *netsock)
Definition: netsock.c:65
int ast_sockaddr_is_ipv6(const struct ast_sockaddr *addr)
Determine if this is an IPv6 address.
Definition: netsock2.c:524