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
void sip_config_parser_unregister_tests (void)
 unregister config parsing tests
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
void sip_parse_nat_option (const char *value, struct ast_flags *mask, struct ast_flags *flags)
 Parse the comma-separated nat= option values.
int sip_parse_register_line (struct sip_registry *reg, int default_expiry, const char *value, int lineno)
 Parse register=> line in sip.conf.


Detailed Description

sip.conf parser header file

Definition in file config_parser.h.


Function Documentation

void sip_config_parser_register_tests ( void   ) 

register config parsing tests

Definition at line 905 of file config_parser.c.

References AST_TEST_REGISTER.

Referenced by sip_register_tests().

00906 {
00907    AST_TEST_REGISTER(sip_parse_register_line_test);
00908    AST_TEST_REGISTER(sip_parse_host_line_test);
00909    AST_TEST_REGISTER(sip_parse_nat_test);
00910 }

void sip_config_parser_unregister_tests ( void   ) 

unregister config parsing tests

Definition at line 913 of file config_parser.c.

References AST_TEST_UNREGISTER.

Referenced by sip_unregister_tests().

00914 {
00915    AST_TEST_UNREGISTER(sip_parse_register_line_test);
00916    AST_TEST_UNREGISTER(sip_parse_host_line_test);
00917    AST_TEST_UNREGISTER(sip_parse_nat_test);
00918 }

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:
0 on success
-1 on failure

Definition at line 644 of file config_parser.c.

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

Referenced by AST_TEST_DEFINE(), and proxy_from_config().

00645 {
00646    char *port;
00647 
00648    if (ast_strlen_zero(line)) {
00649       *hostname = NULL;
00650       return -1;
00651    }
00652    if ((*hostname = strstr(line, "://"))) {
00653       *hostname += 3;
00654 
00655       if (!strncasecmp(line, "tcp", 3)) {
00656          *transport = AST_TRANSPORT_TCP;
00657       } else if (!strncasecmp(line, "tls", 3)) {
00658          *transport = AST_TRANSPORT_TLS;
00659       } else if (!strncasecmp(line, "udp", 3)) {
00660          *transport = AST_TRANSPORT_UDP;
00661       } else if (lineno) {
00662          ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", line, lineno);
00663       } else {
00664          ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type in sip config. defaulting to udp.\n", line);
00665       }
00666    } else {
00667       *hostname = line;
00668       *transport = AST_TRANSPORT_UDP;
00669    }
00670 
00671    if ((line = strrchr(*hostname, '@')))
00672       line++;
00673    else
00674       line = *hostname;
00675 
00676    if (ast_sockaddr_split_hostport(line, hostname, &port, 0) == 0) {
00677       if (lineno) {
00678          ast_log(LOG_WARNING, "Cannot parse host '%s' on line %d of sip.conf.\n",
00679             line, lineno);
00680       } else {
00681          ast_log(LOG_WARNING, "Cannot parse host '%s' in sip config.\n", line);
00682       }
00683       return -1;
00684    }
00685 
00686    if (port) {
00687       if (!sscanf(port, "%5d", portnum)) {
00688          if (lineno) {
00689             ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", port, lineno);
00690          } else {
00691             ast_log(LOG_NOTICE, "'%s' is not a valid port number in sip config. using default.\n", port);
00692          }
00693          port = NULL;
00694       }
00695    }
00696 
00697    if (!port) {
00698       if (*transport & AST_TRANSPORT_TLS) {
00699          *portnum = STANDARD_TLS_PORT;
00700       } else {
00701          *portnum = STANDARD_SIP_PORT;
00702       }
00703    }
00704 
00705    return 0;
00706 }

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

Parse the comma-separated nat= option values.

Parameters:
value The comma-separated value
mask An array of ast_flags that will be set by this function and used as a mask for copying the flags later
flags An 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 789 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().

00790 {
00791    char *parse, *this;
00792 
00793    if (!(parse = ast_strdupa(value))) {
00794       return;
00795    }
00796 
00797    /* Since we need to completely override the general settings if we are being called
00798     * later for a peer, always set the flags for all options on the mask */
00799    ast_set_flag(&mask[0], SIP_NAT_FORCE_RPORT);
00800    ast_set_flag(&mask[1], SIP_PAGE2_SYMMETRICRTP);
00801    ast_set_flag(&mask[2], SIP_PAGE3_NAT_AUTO_RPORT);
00802    ast_set_flag(&mask[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
00803 
00804    while ((this = strsep(&parse, ","))) {
00805       if (ast_false(this)) {
00806          ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT);
00807          ast_clear_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
00808          ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
00809          ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
00810          break; /* It doesn't make sense to have no + something else */
00811       } else if (!strcasecmp(this, "yes")) {
00812          ast_log(LOG_WARNING, "nat=yes is deprecated, use nat=force_rport,comedia instead\n");
00813          ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT);
00814          ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
00815          ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
00816          ast_clear_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
00817          break; /* It doesn't make sense to have yes + something else */
00818       } else if (!strcasecmp(this, "force_rport") && !ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT)) {
00819          ast_set_flag(&flags[0], SIP_NAT_FORCE_RPORT);
00820       } else if (!strcasecmp(this, "comedia") && !ast_test_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA)) {
00821          ast_set_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
00822       } else if (!strcasecmp(this, "auto_force_rport")) {
00823          ast_set_flag(&flags[2], SIP_PAGE3_NAT_AUTO_RPORT);
00824          /* In case someone did something dumb like nat=force_rport,auto_force_rport */
00825          ast_clear_flag(&flags[0], SIP_NAT_FORCE_RPORT);
00826       } else if (!strcasecmp(this, "auto_comedia")) {
00827          ast_set_flag(&flags[2], SIP_PAGE3_NAT_AUTO_COMEDIA);
00828          /* In case someone did something dumb like nat=comedia,auto_comedia*/
00829          ast_clear_flag(&flags[1], SIP_PAGE2_SYMMETRICRTP);
00830       }
00831    }
00832 }

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:
0 on success
-1 on 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 39 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, 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().

00040 {
00041    int portnum = 0;
00042    int domainport = 0;
00043    enum ast_transport transport = AST_TRANSPORT_UDP;
00044    char buf[256] = "";
00045    char *userpart = NULL, *hostpart = NULL;
00046    /* register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] */
00047    AST_DECLARE_APP_ARGS(pre1,
00048       AST_APP_ARG(peer);
00049       AST_APP_ARG(userpart);
00050    );
00051    AST_DECLARE_APP_ARGS(pre2,
00052       AST_APP_ARG(transport);
00053       AST_APP_ARG(blank);
00054       AST_APP_ARG(userpart);
00055    );
00056    AST_DECLARE_APP_ARGS(user1,
00057       AST_APP_ARG(userpart);
00058       AST_APP_ARG(secret);
00059       AST_APP_ARG(authuser);
00060    );
00061    AST_DECLARE_APP_ARGS(user2,
00062       AST_APP_ARG(user);
00063       AST_APP_ARG(domain);
00064    );
00065    AST_DECLARE_APP_ARGS(user3,
00066       AST_APP_ARG(authuser);
00067       AST_APP_ARG(domainport);
00068    );
00069    AST_DECLARE_APP_ARGS(host1,
00070       AST_APP_ARG(hostpart);
00071       AST_APP_ARG(expiry);
00072    );
00073    AST_DECLARE_APP_ARGS(host2,
00074       AST_APP_ARG(hostpart);
00075       AST_APP_ARG(extension);
00076    );
00077    AST_DECLARE_APP_ARGS(host3,
00078       AST_APP_ARG(host);
00079       AST_APP_ARG(port);
00080    );
00081 
00082    if (!value) {
00083       return -1;
00084    }
00085 
00086    if (!reg) {
00087       return -1;
00088    }
00089    ast_copy_string(buf, value, sizeof(buf));
00090 
00091    /*! register => [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry]
00092     * becomes
00093     *   userpart => [peer?][transport://]user[@domain][:secret[:authuser]]
00094     *   hostpart => host[:port][/extension][~expiry]
00095     */
00096    if ((hostpart = strrchr(buf, '@'))) {
00097       *hostpart++ = '\0';
00098       userpart = buf;
00099    }
00100 
00101    if (ast_strlen_zero(userpart) || ast_strlen_zero(hostpart)) {
00102       ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
00103       return -1;
00104    }
00105 
00106    /*!
00107     * pre1.peer => peer
00108     * pre1.userpart => [transport://]user[@domain][:secret[:authuser]]
00109     * hostpart => host[:port][/extension][~expiry]
00110     */
00111    AST_NONSTANDARD_RAW_ARGS(pre1, userpart, '?');
00112    if (ast_strlen_zero(pre1.userpart)) {
00113       pre1.userpart = pre1.peer;
00114       pre1.peer = NULL;
00115    }
00116 
00117    /*!
00118     * pre1.peer => peer
00119     * pre2.transport = transport
00120     * pre2.userpart => user[@domain][:secret[:authuser]]
00121     * hostpart => host[:port][/extension][~expiry]
00122     */
00123    AST_NONSTANDARD_RAW_ARGS(pre2, pre1.userpart, '/');
00124    if (ast_strlen_zero(pre2.userpart)) {
00125       pre2.userpart = pre2.transport;
00126       pre2.transport = NULL;
00127    } else {
00128       pre2.transport[strlen(pre2.transport) - 1] = '\0'; /* Remove trailing : */
00129    }
00130 
00131    if (!ast_strlen_zero(pre2.blank)) {
00132       ast_log(LOG_WARNING, "Format for registration is [peer?][transport://]user[@domain][:secret[:authuser]]@host[:port][/extension][~expiry] at line %d\n", lineno);
00133       return -1;
00134    }
00135 
00136    /*!
00137     * pre1.peer => peer
00138     * pre2.transport = transport
00139     * user1.userpart => user[@domain]
00140     * user1.secret => secret
00141     * user1.authuser => authuser
00142     * hostpart => host[:port][/extension][~expiry]
00143     */
00144    AST_NONSTANDARD_RAW_ARGS(user1, pre2.userpart, ':');
00145 
00146    /*!
00147     * pre1.peer => peer
00148     * pre2.transport = transport
00149     * user1.userpart => user[@domain]
00150     * user1.secret => secret
00151     * user1.authuser => authuser
00152     * host1.hostpart => host[:port][/extension]
00153     * host1.expiry => [expiry]
00154     */
00155    AST_NONSTANDARD_RAW_ARGS(host1, hostpart, '~');
00156 
00157    /*!
00158     * pre1.peer => peer
00159     * pre2.transport = transport
00160     * user1.userpart => user[@domain]
00161     * user1.secret => secret
00162     * user1.authuser => authuser
00163     * host2.hostpart => host[:port]
00164     * host2.extension => [extension]
00165     * host1.expiry => [expiry]
00166     */
00167    AST_NONSTANDARD_RAW_ARGS(host2, host1.hostpart, '/');
00168 
00169    /*!
00170     * pre1.peer => peer
00171     * pre2.transport = transport
00172     * user1.userpart => user[@domain]
00173     * user1.secret => secret
00174     * user1.authuser => authuser
00175     * host3.host => host
00176     * host3.port => port
00177     * host2.extension => extension
00178     * host1.expiry => expiry
00179     */
00180    AST_NONSTANDARD_RAW_ARGS(host3, host2.hostpart, ':');
00181 
00182    /*!
00183      * pre1.peer => peer
00184      * pre2.transport = transport
00185      * user2.user => user
00186      * user2.domain => domain
00187      * user1.secret => secret
00188      * user1.authuser => authuser
00189      * host3.host => host
00190      * host3.port => port
00191      * host2.extension => extension
00192      * host1.expiry => expiry
00193     */
00194    AST_NONSTANDARD_RAW_ARGS(user2, user1.userpart, '@');
00195 
00196    /*!
00197      * pre1.peer => peer
00198      * pre2.transport = transport
00199      * user2.user => user
00200      * user2.domain => domain
00201      * user1.secret => secret
00202      * user3.authuser => authuser
00203      * user3.domainport => domainport
00204      * host3.host => host
00205      * host3.port => port
00206      * host2.extension => extension
00207      * host1.expiry => expiry
00208     */
00209    AST_NONSTANDARD_RAW_ARGS(user3, user1.authuser, ':');
00210 
00211    /* Reordering needed due to fields being [(:secret[:username])|(:regdomainport:secret:username)]
00212       but parsing being [secret[:username[:regdomainport]]] */
00213    if (user3.argc == 2) {
00214       char *reorder = user3.domainport;
00215       user3.domainport = user1.secret;
00216       user1.secret = user3.authuser;
00217       user3.authuser = reorder;
00218    }
00219 
00220    if (host3.port) {
00221       if (!(portnum = port_str2int(host3.port, 0))) {
00222          ast_log(LOG_NOTICE, "'%s' is not a valid port number on line %d of sip.conf. using default.\n", host3.port, lineno);
00223       }
00224    }
00225    if (user3.domainport) {
00226       if (!(domainport = port_str2int(user3.domainport, 0))) {
00227          ast_log(LOG_NOTICE, "'%s' is not a valid domain port number on line %d of sip.conf. using default.\n", user3.domainport, lineno);
00228       }
00229    }
00230 
00231    /* set transport type */
00232    if (!pre2.transport) {
00233       transport = AST_TRANSPORT_UDP;
00234    } else if (!strncasecmp(pre2.transport, "tcp", 3)) {
00235       transport = AST_TRANSPORT_TCP;
00236    } else if (!strncasecmp(pre2.transport, "tls", 3)) {
00237       transport = AST_TRANSPORT_TLS;
00238    } else if (!strncasecmp(pre2.transport, "udp", 3)) {
00239       transport = AST_TRANSPORT_UDP;
00240    } else {
00241       transport = AST_TRANSPORT_UDP;
00242       ast_log(LOG_NOTICE, "'%.3s' is not a valid transport type on line %d of sip.conf. defaulting to udp.\n", pre2.transport, lineno);
00243    }
00244 
00245    /* if no portnum specified, set default for transport */
00246    if (!portnum) {
00247       if (transport == AST_TRANSPORT_TLS) {
00248          portnum = STANDARD_TLS_PORT;
00249       } else {
00250          portnum = STANDARD_SIP_PORT;
00251       }
00252    }
00253 
00254    /* copy into sip_registry object */
00255    ast_string_field_set(reg, callback, ast_strip_quoted(S_OR(host2.extension, "s"), "\"", "\""));
00256    ast_string_field_set(reg, username, ast_strip_quoted(S_OR(user2.user, ""), "\"", "\""));
00257    ast_string_field_set(reg, hostname, ast_strip_quoted(S_OR(host3.host, ""), "\"", "\""));
00258    ast_string_field_set(reg, authuser, ast_strip_quoted(S_OR(user3.authuser, ""), "\"", "\""));
00259    ast_string_field_set(reg, secret, ast_strip_quoted(S_OR(user1.secret, ""), "\"", "\""));
00260    ast_string_field_set(reg, peername, ast_strip_quoted(S_OR(pre1.peer, ""), "\"", "\""));
00261    ast_string_field_set(reg, regdomain, ast_strip_quoted(S_OR(user2.domain, ""), "\"", "\""));
00262 
00263    reg->transport = transport;
00264    reg->timeout = reg->expire = -1;
00265    reg->portno = portnum;
00266    reg->regdomainport = domainport;
00267    reg->callid_valid = FALSE;
00268    reg->ocseq = INITIAL_CSEQ;
00269    reg->refresh = reg->expiry = reg->configured_expiry = (host1.expiry ? atoi(ast_strip_quoted(host1.expiry, "\"", "\"")) : default_expiry);
00270 
00271    return 0;
00272 }


Generated on Thu Apr 16 06:30:28 2015 for Asterisk - The Open Source Telephony Project by  doxygen 1.5.6