Asterisk - The Open Source Telephony Project  18.5.0
Functions
config_parser.h File Reference

sip.conf parser header file More...

#include "sip.h"
Include dependency graph for config_parser.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

void sip_config_parser_register_tests (void)
 register config parsing tests More...
 
void sip_config_parser_unregister_tests (void)
 unregister config parsing tests More...
 
int sip_parse_host (char *line, int lineno, char **hostname, int *portnum, enum ast_transport *transport)
 parses a config line for a host with a transport More...
 
void sip_parse_nat_option (const char *value, struct ast_flags *mask, struct ast_flags *flags)
 Parse the comma-separated nat= option values. More...
 
int sip_parse_register_line (struct sip_registry *reg, int default_expiry, const char *value, int lineno)
 Parse register=> line in sip.conf. More...
 

Detailed Description

sip.conf parser header file

Definition in file config_parser.h.

Function Documentation

◆ sip_config_parser_register_tests()

void sip_config_parser_register_tests ( void  )

register config parsing tests

register config parsing tests

Definition at line 913 of file config_parser.c.

References AST_TEST_REGISTER.

Referenced by sip_register_tests().

914 {
915  AST_TEST_REGISTER(sip_parse_register_line_test);
916  AST_TEST_REGISTER(sip_parse_host_line_test);
917  AST_TEST_REGISTER(sip_parse_nat_test);
918 }
#define AST_TEST_REGISTER(cb)
Definition: test.h:127

◆ sip_config_parser_unregister_tests()

void sip_config_parser_unregister_tests ( void  )

unregister config parsing tests

unregister config parsing tests

Definition at line 921 of file config_parser.c.

References AST_TEST_UNREGISTER.

Referenced by sip_unregister_tests().

922 {
923  AST_TEST_UNREGISTER(sip_parse_register_line_test);
924  AST_TEST_UNREGISTER(sip_parse_host_line_test);
925  AST_TEST_UNREGISTER(sip_parse_nat_test);
926 }
#define AST_TEST_UNREGISTER(cb)
Definition: test.h:128

◆ sip_parse_host()

int sip_parse_host ( char *  line,
int  lineno,
char **  hostname,
int *  portnum,
enum ast_transport transport 
)

parses a config line for a host with a transport

An example input would be: tls://www.google.com:8056

Return values
0on success
-1on failure

Definition at line 647 of file config_parser.c.

References ast_log, ast_sockaddr_split_hostport(), ast_strlen_zero, AST_TRANSPORT_TCP, AST_TRANSPORT_TLS, AST_TRANSPORT_UDP, hostname, LOG_NOTICE, LOG_WARNING, NULL, STANDARD_SIP_PORT, and STANDARD_TLS_PORT.

Referenced by AST_TEST_DEFINE(), and proxy_from_config().

648 {
649  char *port;
650 
651  if (ast_strlen_zero(line)) {
652  *hostname = NULL;
653  return -1;
654  }
655  if ((*hostname = strstr(line, "://"))) {
656  *hostname += 3;
657 
658  if (!strncasecmp(line, "tcp", 3)) {
659  *transport = AST_TRANSPORT_TCP;
660  } else if (!strncasecmp(line, "tls", 3)) {
661  *transport = AST_TRANSPORT_TLS;
662  } else if (!strncasecmp(line, "udp", 3)) {
663  *transport = AST_TRANSPORT_UDP;
664  } else if (lineno) {
665  ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno);
666  } else {
667  ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type in sip config. defaulting to udp.\n", line);
668  }
669  } else {
670  *hostname = line;
671  *transport = AST_TRANSPORT_UDP;
672  }
673 
674  if ((line = strrchr(*hostname, '@')))
675  line++;
676  else
677  line = *hostname;
678 
679  if (ast_sockaddr_split_hostport(line, hostname, &port, 0) == 0) {
680  if (lineno) {
681  ast_log(LOG_WARNING, "Cannot parse host '%s' on line %d of sip.conf.\n",
682  line, lineno);
683  } else {
684  ast_log(LOG_WARNING, "Cannot parse host '%s' in sip config.\n", line);
685  }
686  return -1;
687  }
688 
689  if (port) {
690  if (!sscanf(port, "%5d", portnum)) {
691  if (lineno) {
692  ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno);
693  } else {
694  ast_log(LOG_NOTICE, "'%s' is not a valid port number in sip config. using default.\n", port);
695  }
696  port = NULL;
697  }
698  }
699 
700  if (!port) {
701  if (*transport & AST_TRANSPORT_TLS) {
702  *portnum = STANDARD_TLS_PORT;
703  } else {
704  *portnum = STANDARD_SIP_PORT;
705  }
706  }
707 
708  return 0;
709 }
#define LOG_WARNING
Definition: logger.h:274
#define NULL
Definition: resample.c:96
#define ast_strlen_zero(foo)
Definition: strings.h:52
#define ast_log
Definition: astobj2.c:42
#define STANDARD_TLS_PORT
Standard SIP TLS port from RFC 3261. DO NOT CHANGE THIS.
Definition: sip.h:178
int ast_sockaddr_split_hostport(char *str, char **host, char **port, int flags)
Splits a string into its host and port components.
Definition: netsock2.c:164
#define STANDARD_SIP_PORT
Standard SIP unsecure port for UDP and TCP from RFC 3261. DO NOT CHANGE THIS.
Definition: sip.h:176
#define LOG_NOTICE
Definition: logger.h:263
static struct ast_str * hostname
Definition: cdr_mysql.c:77

◆ sip_parse_nat_option()

void sip_parse_nat_option ( const char *  value,
struct ast_flags mask,
struct ast_flags flags 
)

Parse the comma-separated nat= option values.

Parameters
valueThe comma-separated value
maskAn array of ast_flags that will be set by this function and used as a mask for copying the flags later
flagsAn array of ast_flags that will be set by this function
Note
The nat-related values in both mask and flags are assumed to empty. This function will treat the first "yes" or "no" value in a list of values as overiding all other values and will stop parsing. Auto values will override their non-auto counterparts.

Definition at line 794 of file config_parser.c.

References ast_clear_flag, ast_false(), ast_log, ast_set_flag, ast_strdupa, ast_test_flag, LOG_WARNING, parse(), SIP_NAT_FORCE_RPORT, SIP_PAGE2_SYMMETRICRTP, SIP_PAGE3_NAT_AUTO_COMEDIA, SIP_PAGE3_NAT_AUTO_RPORT, and strsep().

Referenced by AST_TEST_DEFINE(), and handle_common_options().

795 {
796  char *parse, *this;
797 
798  if (!(parse = ast_strdupa(value))) {
799  return;
800  }
801 
802  /* Since we need to completely override the general settings if we are being called
803  * later for a peer, always set the flags for all options on the mask */
808 
809  while ((this = strsep(&parse, ","))) {
810  if (ast_false(this)) {
815  break; /* It doesn't make sense to have no + something else */
816  } else if (!strcasecmp(this, "yes")) {
817  ast_log(LOG_WARNING, "nat=yes is deprecated, use nat=force_rport,comedia instead\n");
818  ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT);
822  break; /* It doesn't make sense to have yes + something else */
823  } else if (!strcasecmp(this, "force_rport") && !ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
824  ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT);
825  } else if (!strcasecmp(this, "comedia") && !ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
827  } else if (!strcasecmp(this, "auto_force_rport")) {
829  /* In case someone did something dumb like nat=force_rport,auto_force_rport */
831  } else if (!strcasecmp(this, "auto_comedia")) {
833  /* In case someone did something dumb like nat=comedia,auto_comedia*/
835  }
836  }
837 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define LOG_WARNING
Definition: logger.h:274
#define SIP_NAT_FORCE_RPORT
Definition: sip.h:283
int value
Definition: syslog.c:37
#define SIP_PAGE2_SYMMETRICRTP
Definition: sip.h:327
#define ast_log
Definition: astobj2.c:42
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:300
#define SIP_PAGE3_NAT_AUTO_RPORT
Definition: sip.h:386
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1872
#define ast_clear_flag(p, flag)
Definition: utils.h:77
#define SIP_PAGE3_NAT_AUTO_COMEDIA
Definition: sip.h:387
char * strsep(char **str, const char *delims)
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"...
Definition: main/utils.c:1968

◆ sip_parse_register_line()

int sip_parse_register_line ( struct sip_registry reg,
int  default_expiry,
const char *  value,
int  lineno 
)

Parse register=> line in sip.conf.

Return values
0on success
-1on failure

register => [peer?][transport://]user[][:secret[:authuser]][:port][/extension][~expiry] becomes userpart => [peer?][transport://]user[][:secret[:authuser]] hostpart => host[:port][/extension][~expiry]

pre1.peer => peer pre1.userpart => [transport://]user[][:secret[:authuser]] hostpart => host[:port][/extension][~expiry]

pre1.peer => peer pre2.transport = transport pre2.userpart => user[][:secret[:authuser]] hostpart => host[:port][/extension][~expiry]

pre1.peer => peer pre2.transport = transport user1.userpart => user[] user1.secret => secret user1.authuser => authuser hostpart => host[:port][/extension][~expiry]

pre1.peer => peer pre2.transport = transport user1.userpart => user[] user1.secret => secret user1.authuser => authuser host1.hostpart => host[:port][/extension] host1.expiry => [expiry]

pre1.peer => peer pre2.transport = transport user1.userpart => user[] user1.secret => secret user1.authuser => authuser host2.hostpart => host[:port] host2.extension => [extension] host1.expiry => [expiry]

pre1.peer => peer pre2.transport = transport user1.userpart => user[] user1.secret => secret user1.authuser => authuser host3.host => host host3.port => port host2.extension => extension host1.expiry => expiry

pre1.peer => peer pre2.transport = transport user2.user => user user2.domain => domain user1.secret => secret user1.authuser => authuser host3.host => host host3.port => port host2.extension => extension host1.expiry => expiry

pre1.peer => peer pre2.transport = transport user2.user => user user2.domain => domain user1.secret => secret user3.authuser => authuser user3.domainport => domainport host3.host => host host3.port => port host2.extension => extension host1.expiry => expiry

Definition at line 37 of file config_parser.c.

References AST_APP_ARG, ast_copy_string(), AST_DECLARE_APP_ARGS, ast_log, AST_NONSTANDARD_RAW_ARGS, ast_string_field_set, ast_strip_quoted(), ast_strlen_zero, AST_TRANSPORT_TCP, AST_TRANSPORT_TLS, AST_TRANSPORT_UDP, buf, sip_registry::callid_valid, sip_registry::configured_expiry, default_expiry, sip_registry::expire, sip_registry::expiry, FALSE, host, hostname, INITIAL_CSEQ, LOG_NOTICE, LOG_WARNING, NULL, sip_registry::ocseq, port_str2int(), sip_registry::portno, sip_registry::refresh, sip_registry::regdomainport, S_OR, STANDARD_SIP_PORT, STANDARD_TLS_PORT, sip_registry::timeout, and sip_registry::transport.

Referenced by AST_TEST_DEFINE(), and sip_register().

38 {
39  int portnum = 0;
40  int domainport = 0;
41  enum ast_transport transport = AST_TRANSPORT_UDP;
42  char buf[256] = "";
43  char *userpart = NULL, *hostpart = NULL;
44  /* register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] */
46  AST_APP_ARG(peer);
47  AST_APP_ARG(userpart);
48  );
50  AST_APP_ARG(transport);
51  AST_APP_ARG(blank);
52  AST_APP_ARG(userpart);
53  );
55  AST_APP_ARG(userpart);
56  AST_APP_ARG(secret);
57  AST_APP_ARG(authuser);
58  );
62  );
64  AST_APP_ARG(authuser);
65  AST_APP_ARG(domainport);
66  );
68  AST_APP_ARG(hostpart);
69  AST_APP_ARG(expiry);
70  );
72  AST_APP_ARG(hostpart);
74  );
77  AST_APP_ARG(port);
78  );
79 
80  if (!reg) {
81  return -1;
82  }
83 
84  reg->expire = -1;
85  reg->timeout = -1;
86 
87  if (!value) {
88  return -1;
89  }
90 
91  ast_copy_string(buf, value, sizeof(buf));
92 
93  /*! register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
94  * becomes
95  * userpart => [peer?][transport://]user[@domain][:secret[:authuser]]
96  * hostpart => host[:port][/extension][~expiry]
97  */
98  if ((hostpart = strrchr(buf, '@'))) {
99  *hostpart++ = '\0';
100  userpart = buf;
101  }
102 
103  if (ast_strlen_zero(userpart) || ast_strlen_zero(hostpart)) {
104  ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
105  return -1;
106  }
107 
108  /*!
109  * pre1.peer => peer
110  * pre1.userpart => [transport://]user[@domain][:secret[:authuser]]
111  * hostpart => host[:port][/extension][~expiry]
112  */
113  AST_NONSTANDARD_RAW_ARGS(pre1, userpart, '?');
114  if (ast_strlen_zero(pre1.userpart)) {
115  pre1.userpart = pre1.peer;
116  pre1.peer = NULL;
117  }
118 
119  /*!
120  * pre1.peer => peer
121  * pre2.transport = transport
122  * pre2.userpart => user[@domain][:secret[:authuser]]
123  * hostpart => host[:port][/extension][~expiry]
124  */
125  AST_NONSTANDARD_RAW_ARGS(pre2, pre1.userpart, '/');
126  if (ast_strlen_zero(pre2.userpart)) {
127  pre2.userpart = pre2.transport;
128  pre2.transport = NULL;
129  } else {
130  pre2.transport[strlen(pre2.transport) - 1] = '\0'; /* Remove trailing : */
131  }
132 
133  if (!ast_strlen_zero(pre2.blank)) {
134  ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
135  return -1;
136  }
137 
138  /*!
139  * pre1.peer => peer
140  * pre2.transport = transport
141  * user1.userpart => user[@domain]
142  * user1.secret => secret
143  * user1.authuser => authuser
144  * hostpart => host[:port][/extension][~expiry]
145  */
146  AST_NONSTANDARD_RAW_ARGS(user1, pre2.userpart, ':');
147 
148  /*!
149  * pre1.peer => peer
150  * pre2.transport = transport
151  * user1.userpart => user[@domain]
152  * user1.secret => secret
153  * user1.authuser => authuser
154  * host1.hostpart => host[:port][/extension]
155  * host1.expiry => [expiry]
156  */
157  AST_NONSTANDARD_RAW_ARGS(host1, hostpart, '~');
158 
159  /*!
160  * pre1.peer => peer
161  * pre2.transport = transport
162  * user1.userpart => user[@domain]
163  * user1.secret => secret
164  * user1.authuser => authuser
165  * host2.hostpart => host[:port]
166  * host2.extension => [extension]
167  * host1.expiry => [expiry]
168  */
169  AST_NONSTANDARD_RAW_ARGS(host2, host1.hostpart, '/');
170 
171  /*!
172  * pre1.peer => peer
173  * pre2.transport = transport
174  * user1.userpart => user[@domain]
175  * user1.secret => secret
176  * user1.authuser => authuser
177  * host3.host => host
178  * host3.port => port
179  * host2.extension => extension
180  * host1.expiry => expiry
181  */
182  AST_NONSTANDARD_RAW_ARGS(host3, host2.hostpart, ':');
183 
184  /*!
185  * pre1.peer => peer
186  * pre2.transport = transport
187  * user2.user => user
188  * user2.domain => domain
189  * user1.secret => secret
190  * user1.authuser => authuser
191  * host3.host => host
192  * host3.port => port
193  * host2.extension => extension
194  * host1.expiry => expiry
195  */
196  AST_NONSTANDARD_RAW_ARGS(user2, user1.userpart, '@');
197 
198  /*!
199  * pre1.peer => peer
200  * pre2.transport = transport
201  * user2.user => user
202  * user2.domain => domain
203  * user1.secret => secret
204  * user3.authuser => authuser
205  * user3.domainport => domainport
206  * host3.host => host
207  * host3.port => port
208  * host2.extension => extension
209  * host1.expiry => expiry
210  */
211  AST_NONSTANDARD_RAW_ARGS(user3, user1.authuser, ':');
212 
213  /* Reordering needed due to fields being [(:secret[:username])|(:regdomainport:secret:username)]
214  but parsing being [secret[:username[:regdomainport]]] */
215  if (user3.argc == 2) {
216  char *reorder = user3.domainport;
217  user3.domainport = user1.secret;
218  user1.secret = user3.authuser;
219  user3.authuser = reorder;
220  }
221 
222  if (host3.port) {
223  if (!(portnum = port_str2int(host3.port, 0))) {
224  ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", host3.port, lineno);
225  }
226  }
227  if (user3.domainport) {
228  if (!(domainport = port_str2int(user3.domainport, 0))) {
229  ast_log(LOG_NOTICE, "'%s' is not a valid domain port number on line %d of sip.conf. using default.\n", user3.domainport, lineno);
230  }
231  }
232 
233  /* set transport type */
234  if (!pre2.transport) {
235  transport = AST_TRANSPORT_UDP;
236  } else if (!strncasecmp(pre2.transport, "tcp", 3)) {
237  transport = AST_TRANSPORT_TCP;
238  } else if (!strncasecmp(pre2.transport, "tls", 3)) {
239  transport = AST_TRANSPORT_TLS;
240  } else if (!strncasecmp(pre2.transport, "udp", 3)) {
241  transport = AST_TRANSPORT_UDP;
242  } else {
243  transport = AST_TRANSPORT_UDP;
244  ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", pre2.transport, lineno);
245  }
246 
247  /* if no portnum specified, set default for transport */
248  if (!portnum) {
249  if (transport == AST_TRANSPORT_TLS) {
250  portnum = STANDARD_TLS_PORT;
251  } else {
252  portnum = STANDARD_SIP_PORT;
253  }
254  }
255 
256  /* copy into sip_registry object */
257  ast_string_field_set(reg, callback, ast_strip_quoted(S_OR(host2.extension, "s"), "\"", "\""));
258  ast_string_field_set(reg, username, ast_strip_quoted(S_OR(user2.user, ""), "\"", "\""));
259  ast_string_field_set(reg, hostname, ast_strip_quoted(S_OR(host3.host, ""), "\"", "\""));
260  ast_string_field_set(reg, authuser, ast_strip_quoted(S_OR(user3.authuser, ""), "\"", "\""));
261  ast_string_field_set(reg, secret, ast_strip_quoted(S_OR(user1.secret, ""), "\"", "\""));
262  ast_string_field_set(reg, peername, ast_strip_quoted(S_OR(pre1.peer, ""), "\"", "\""));
263  ast_string_field_set(reg, regdomain, ast_strip_quoted(S_OR(user2.domain, ""), "\"", "\""));
264 
265  reg->transport = transport;
266  reg->portno = portnum;
267  reg->regdomainport = domainport;
268  reg->callid_valid = FALSE;
269  reg->ocseq = INITIAL_CSEQ;
270  reg->refresh = reg->expiry = reg->configured_expiry = (host1.expiry ? atoi(ast_strip_quoted(host1.expiry, "\"", "\"")) : default_expiry);
271 
272  return 0;
273 }
#define FALSE
Definition: app_minivm.c:521
int expire
Definition: sip.h:1418
int portno
Definition: sip.h:1416
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
ast_transport
Definition: netsock2.h:59
#define LOG_WARNING
Definition: logger.h:274
int configured_expiry
Definition: sip.h:1419
#define NULL
Definition: resample.c:96
Domain data structure.
Definition: sip.h:888
int value
Definition: syslog.c:37
#define ast_strlen_zero(foo)
Definition: strings.h:52
int regdomainport
Definition: sip.h:1417
char * ast_strip_quoted(char *s, const char *beg_quotes, const char *end_quotes)
Strip leading/trailing whitespace and quotes from a string.
Definition: main/utils.c:1639
#define ast_log
Definition: astobj2.c:42
#define STANDARD_TLS_PORT
Standard SIP TLS port from RFC 3261. DO NOT CHANGE THIS.
Definition: sip.h:178
static char host[256]
Definition: muted.c:77
#define STANDARD_SIP_PORT
Standard SIP unsecure port for UDP and TCP from RFC 3261. DO NOT CHANGE THIS.
Definition: sip.h:176
structure to hold extensions
uint32_t ocseq
Definition: sip.h:1428
int callid_valid
Definition: sip.h:1427
#define AST_NONSTANDARD_RAW_ARGS(args, parse, sep)
static int default_expiry
Definition: chan_sip.c:669
#define LOG_NOTICE
Definition: logger.h:263
#define INITIAL_CSEQ
Definition: sip.h:117
structure to hold users read from users.conf
int expiry
Definition: sip.h:1420
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:79
unsigned int port_str2int(const char *pt, unsigned int standard)
converts ascii port to int representation. If no pt buffer is provided or the pt has errors when bein...
Definition: chan_sip.c:3538
int timeout
Definition: sip.h:1422
static struct ast_str * hostname
Definition: cdr_mysql.c:77
enum ast_transport transport
Definition: sip.h:1415
int refresh
Definition: sip.h:1423
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application's arguments.
#define AST_APP_ARG(name)
Define an application argument.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:514