|
@@ -3,11 +3,23 @@
|
|
|
#include <string.h>
|
|
|
#include "../str.h"
|
|
|
|
|
|
+/* ser compat defs */
|
|
|
+
|
|
|
#define DBG printf
|
|
|
#define LOG(lev, fmt, args...) printf(fmt, ## args)
|
|
|
|
|
|
+#define EXTRA_DEBUG
|
|
|
+#define ZSW(s) ((s)?(s):"")
|
|
|
+#define E_BAD_URI -100
|
|
|
+
|
|
|
+int ser_error=0;
|
|
|
+
|
|
|
+
|
|
|
enum {PROTO_NONE, PROTO_UDP, PROTO_TCP, PROTO_TLS, PROTO_SCTP };
|
|
|
|
|
|
+enum _uri_type{ERROR_URI_T=0, SIP_URI_T, SIPS_URI_T, TEL_URI_T};
|
|
|
+typedef enum _uri_type uri_type;
|
|
|
+
|
|
|
struct sip_uri {
|
|
|
str user; /* Username */
|
|
|
str passwd; /* Password */
|
|
@@ -17,6 +29,7 @@ struct sip_uri {
|
|
|
str headers;
|
|
|
unsigned short port_no;
|
|
|
unsigned short proto; /* from transport */
|
|
|
+ uri_type type; /* uri scheme */
|
|
|
/* parameters */
|
|
|
str transport;
|
|
|
str ttl;
|
|
@@ -24,16 +37,20 @@ struct sip_uri {
|
|
|
str maddr;
|
|
|
str method;
|
|
|
str lr;
|
|
|
+ str r2; /* ser specific rr parameter */
|
|
|
/* values */
|
|
|
str transport_val;
|
|
|
str ttl_val;
|
|
|
str user_param_val;
|
|
|
str maddr_val;
|
|
|
str method_val;
|
|
|
+ str lr_val; /* lr value placeholder for lr=on a.s.o*/
|
|
|
+ str r2_val;
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
+
|
|
|
int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
{
|
|
|
enum states { URI_INIT, URI_USER, URI_PASSWORD, URI_PASSWORD_ALPHA,
|
|
@@ -53,7 +70,10 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
/* maddr */
|
|
|
PMA_A, PMA_D, PMA_D2, PMA_R, PMA_eq,
|
|
|
/* lr */
|
|
|
- PLR_L, PLR_R_FIN,
|
|
|
+ PLR_L, PLR_R_FIN, PLR_eq,
|
|
|
+ /* r2 */
|
|
|
+ PR2_R, PR2_2_FIN, PR2_eq,
|
|
|
+
|
|
|
/* transport values */
|
|
|
/* udp */
|
|
|
VU_U, VU_D, VU_P_FIN,
|
|
@@ -78,6 +98,11 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
char* pass;
|
|
|
int found_user;
|
|
|
int error_headers;
|
|
|
+ unsigned int scheme;
|
|
|
+
|
|
|
+#define SIP_SCH 0x3a706973
|
|
|
+#define SIPS_SCH 0x73706973
|
|
|
+#define TEL_SCH 0x3a6c6574
|
|
|
|
|
|
#define case_port( ch, var) \
|
|
|
case ch: \
|
|
@@ -297,14 +322,22 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
port_no=0;
|
|
|
state=URI_INIT;
|
|
|
memset(uri, 0, sizeof(struct sip_uri)); /* zero it all, just to be sure*/
|
|
|
- /*look for sip:*/
|
|
|
- if (len<4) goto error_too_short;
|
|
|
- if (! ( ((buf[0]|0x20)=='s')&&((buf[1]|0x20)=='i')&&((buf[2]|0x20)=='p')&&
|
|
|
- (buf[3]==':') ) ) goto error_bad_uri;
|
|
|
+ /*look for sip:, sips: or tel:*/
|
|
|
+ if (len<5) goto error_too_short;
|
|
|
+ scheme=buf[0]+(buf[1]<<8)+(buf[2]<<16)+(buf[3]<<24);
|
|
|
+ scheme|=0x20202020;
|
|
|
+ if (scheme==SIP_SCH){
|
|
|
+ uri->type=SIP_URI_T;
|
|
|
+ }else if(scheme==SIPS_SCH){
|
|
|
+ if(buf[4]==':'){ p++; uri->type=SIPS_URI_T;}
|
|
|
+ else goto error_bad_uri;
|
|
|
+ }else if (scheme==TEL_SCH){
|
|
|
+ uri->type=TEL_URI_T;
|
|
|
+ }else goto error_bad_uri;
|
|
|
|
|
|
s=p;
|
|
|
for(;p<end; p++){
|
|
|
- switch(state){
|
|
|
+ switch((unsigned char)state){
|
|
|
case URI_INIT:
|
|
|
switch(*p){
|
|
|
case '[':
|
|
@@ -535,13 +568,17 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
b=p;
|
|
|
state=PLR_L;
|
|
|
break;
|
|
|
+ case 'r':
|
|
|
+ case 'R':
|
|
|
+ b=p;
|
|
|
+ state=PR2_R;
|
|
|
default:
|
|
|
state=URI_PARAM_P;
|
|
|
}
|
|
|
break;
|
|
|
case URI_PARAM_P: /* ignore current param */
|
|
|
/* supported params:
|
|
|
- * maddr, transport, ttl, lr, user, method */
|
|
|
+ * maddr, transport, ttl, lr, user, method, r2 */
|
|
|
switch(*p){
|
|
|
param_common_cases;
|
|
|
};
|
|
@@ -677,6 +714,9 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
case '@':
|
|
|
still_at_user;
|
|
|
break;
|
|
|
+ case '=':
|
|
|
+ state=PLR_eq;
|
|
|
+ break;
|
|
|
semicolon_case;
|
|
|
uri->lr.s=b;
|
|
|
uri->lr.len=(p-b);
|
|
@@ -691,7 +731,52 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
state=URI_PARAM_P;
|
|
|
}
|
|
|
break;
|
|
|
-
|
|
|
+ /* handle lr=something case */
|
|
|
+ case PLR_eq:
|
|
|
+ param=&uri->lr;
|
|
|
+ param_val=&uri->lr_val;
|
|
|
+ switch(*p){
|
|
|
+ param_common_cases;
|
|
|
+ default:
|
|
|
+ v=p;
|
|
|
+ state=URI_VAL_P;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ /* r2 */
|
|
|
+ param_switch1(PR2_R, '2', PR2_2_FIN);
|
|
|
+ case PR2_2_FIN:
|
|
|
+ switch(*p){
|
|
|
+ case '@':
|
|
|
+ still_at_user;
|
|
|
+ break;
|
|
|
+ case '=':
|
|
|
+ state=PR2_eq;
|
|
|
+ break;
|
|
|
+ semicolon_case;
|
|
|
+ uri->r2.s=b;
|
|
|
+ uri->r2.len=(p-b);
|
|
|
+ break;
|
|
|
+ question_case;
|
|
|
+ uri->r2.s=b;
|
|
|
+ uri->r2.len=(p-b);
|
|
|
+ break;
|
|
|
+ colon_case;
|
|
|
+ break;
|
|
|
+ default:
|
|
|
+ state=URI_PARAM_P;
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ /* handle lr=something case */
|
|
|
+ case PR2_eq:
|
|
|
+ param=&uri->r2;
|
|
|
+ param_val=&uri->r2_val;
|
|
|
+ switch(*p){
|
|
|
+ param_common_cases;
|
|
|
+ default:
|
|
|
+ v=p;
|
|
|
+ state=URI_VAL_P;
|
|
|
+ }
|
|
|
+ break;
|
|
|
|
|
|
|
|
|
case URI_HEADERS:
|
|
@@ -800,16 +885,25 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
case PM_D:
|
|
|
case PM_eq:
|
|
|
case PLR_L: /* lr */
|
|
|
+ case PR2_R: /* r2 */
|
|
|
uri->params.s=s;
|
|
|
uri->params.len=p-s;
|
|
|
break;
|
|
|
/* fin param states */
|
|
|
case PLR_R_FIN:
|
|
|
+ case PLR_eq:
|
|
|
uri->params.s=s;
|
|
|
uri->params.len=p-s;
|
|
|
uri->lr.s=b;
|
|
|
uri->lr.len=p-b;
|
|
|
break;
|
|
|
+ case PR2_2_FIN:
|
|
|
+ case PR2_eq:
|
|
|
+ uri->params.s=s;
|
|
|
+ uri->params.len=p-s;
|
|
|
+ uri->r2.s=b;
|
|
|
+ uri->r2.len=p-b;
|
|
|
+ break;
|
|
|
case URI_VAL_P:
|
|
|
/* intermediate value states */
|
|
|
case VU_U:
|
|
@@ -858,74 +952,88 @@ int parse_uri(char* buf, int len, struct sip_uri* uri)
|
|
|
default:
|
|
|
goto error_bug;
|
|
|
}
|
|
|
-
|
|
|
+ if (uri->type==TEL_URI_T){
|
|
|
+ /* fix tel uris, move the number in uri and empty the host */
|
|
|
+ uri->user=uri->host;
|
|
|
+ uri->host.s="";
|
|
|
+ uri->host.len=0;
|
|
|
+ }
|
|
|
+#ifdef EXTRA_DEBUG
|
|
|
/* do stuff */
|
|
|
- DBG("parsed uri:\n user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n host=<%.*s>(%d)\n"
|
|
|
- " port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n headers=<%.*s>(%d)\n",
|
|
|
- uri->user.len, uri->user.s, uri->user.len,
|
|
|
- uri->passwd.len, uri->passwd.s, uri->passwd.len,
|
|
|
- uri->host.len, uri->host.s, uri->host.len,
|
|
|
- uri->port.len, uri->port.s, uri->port.len, uri->port_no,
|
|
|
- uri->params.len, uri->params.s, uri->params.len,
|
|
|
- uri->headers.len, uri->headers.s, uri->headers.len
|
|
|
+ DBG("parsed uri:\n type=%d user=<%.*s>(%d)\n passwd=<%.*s>(%d)\n"
|
|
|
+ " host=<%.*s>(%d)\n port=<%.*s>(%d): %d\n params=<%.*s>(%d)\n"
|
|
|
+ " headers=<%.*s>(%d)\n",
|
|
|
+ uri->type,
|
|
|
+ uri->user.len, ZSW(uri->user.s), uri->user.len,
|
|
|
+ uri->passwd.len, ZSW(uri->passwd.s), uri->passwd.len,
|
|
|
+ uri->host.len, ZSW(uri->host.s), uri->host.len,
|
|
|
+ uri->port.len, ZSW(uri->port.s), uri->port.len, uri->port_no,
|
|
|
+ uri->params.len, ZSW(uri->params.s), uri->params.len,
|
|
|
+ uri->headers.len, ZSW(uri->headers.s), uri->headers.len
|
|
|
);
|
|
|
DBG(" uri params:\n transport=<%.*s>, val=<%.*s>, proto=%d\n",
|
|
|
- uri->transport.len, uri->transport.s, uri->transport_val.len,
|
|
|
- uri->transport_val.s, uri->proto);
|
|
|
+ uri->transport.len, ZSW(uri->transport.s), uri->transport_val.len,
|
|
|
+ ZSW(uri->transport_val.s), uri->proto);
|
|
|
DBG(" user-param=<%.*s>, val=<%.*s>\n",
|
|
|
- uri->user_param.len, uri->user_param.s, uri->user_param_val.len,
|
|
|
- uri->user_param_val.s);
|
|
|
+ uri->user_param.len, ZSW(uri->user_param.s),
|
|
|
+ uri->user_param_val.len, ZSW(uri->user_param_val.s));
|
|
|
DBG(" method=<%.*s>, val=<%.*s>\n",
|
|
|
- uri->method.len, uri->method.s, uri->method_val.len,
|
|
|
- uri->method_val.s);
|
|
|
+ uri->method.len, ZSW(uri->method.s),
|
|
|
+ uri->method_val.len, ZSW(uri->method_val.s));
|
|
|
DBG(" ttl=<%.*s>, val=<%.*s>\n",
|
|
|
- uri->ttl.len, uri->ttl.s, uri->ttl_val.len,
|
|
|
- uri->ttl_val.s);
|
|
|
+ uri->ttl.len, ZSW(uri->ttl.s),
|
|
|
+ uri->ttl_val.len, ZSW(uri->ttl_val.s));
|
|
|
DBG(" maddr=<%.*s>, val=<%.*s>\n",
|
|
|
- uri->maddr.len, uri->maddr.s, uri->maddr_val.len,
|
|
|
- uri->maddr_val.s);
|
|
|
- DBG(" lr=<%.*s>\n", uri->lr.len, uri->lr.s);
|
|
|
+ uri->maddr.len, ZSW(uri->maddr.s),
|
|
|
+ uri->maddr_val.len, ZSW(uri->maddr_val.s));
|
|
|
+ DBG(" lr=<%.*s>\n", uri->lr.len, ZSW(uri->lr.s));
|
|
|
+#endif
|
|
|
return 0;
|
|
|
|
|
|
error_too_short:
|
|
|
LOG(L_ERR, "ERROR: parse_uri: uri too short: <%.*s> (%d)\n",
|
|
|
- len, buf, len);
|
|
|
- return -1;
|
|
|
+ len, ZSW(buf), len);
|
|
|
+ ser_error=E_BAD_URI;
|
|
|
+ return E_BAD_URI;
|
|
|
error_bad_char:
|
|
|
LOG(L_ERR, "ERROR: parse_uri: bad char '%c' in state %d"
|
|
|
" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
|
|
|
- *p, state, (p-buf), buf, (p-buf), len, buf, len);
|
|
|
- return -1;
|
|
|
+ *p, state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
|
|
|
+ return E_BAD_URI;
|
|
|
error_bad_host:
|
|
|
LOG(L_ERR, "ERROR: parse_uri: bad host in uri (error at char %c in"
|
|
|
" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
|
|
|
- *p, state, (p-buf), buf, (p-buf), len, buf, len);
|
|
|
- return -1;
|
|
|
+ *p, state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
|
|
|
+ ser_error=E_BAD_URI;
|
|
|
+ return E_BAD_URI;
|
|
|
error_bad_port:
|
|
|
LOG(L_ERR, "ERROR: parse_uri: bad port in uri (error at char %c in"
|
|
|
" state %d) parsed: <%.*s>(%d) /<%.*s> (%d)\n",
|
|
|
- *p, state, (p-buf), buf, (p-buf), len, buf, len);
|
|
|
- return -1;
|
|
|
+ *p, state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
|
|
|
+ ser_error=E_BAD_URI;
|
|
|
+ return E_BAD_URI;
|
|
|
error_bad_uri:
|
|
|
LOG(L_ERR, "ERROR: parse_uri: bad uri, state %d"
|
|
|
" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
|
|
|
- state, (p-buf), buf, (p-buf), len, buf, len);
|
|
|
- return -1;
|
|
|
+ state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
|
|
|
+ ser_error=E_BAD_URI;
|
|
|
+ return E_BAD_URI;
|
|
|
error_headers:
|
|
|
LOG(L_ERR, "ERROR: parse_uri: bad uri headers: <%.*s>(%d)"
|
|
|
" / <%.*s>(%d)\n",
|
|
|
- uri->headers.len, uri->headers.s, uri->headers.len,
|
|
|
- len, buf, len);
|
|
|
- return -1;
|
|
|
+ uri->headers.len, ZSW(uri->headers.s), uri->headers.len,
|
|
|
+ len, ZSW(buf), len);
|
|
|
+ ser_error=E_BAD_URI;
|
|
|
+ return E_BAD_URI;
|
|
|
error_bug:
|
|
|
LOG(L_CRIT, "BUG: parse_uri: bad state %d"
|
|
|
" parsed: <%.*s> (%d) / <%.*s> (%d)\n",
|
|
|
- state, (p-buf), buf, (p-buf), len, buf, len);
|
|
|
- return -1;
|
|
|
+ state, (int)(p-buf), ZSW(buf), (int)(p-buf), len, ZSW(buf), len);
|
|
|
+ ser_error=E_BAD_URI;
|
|
|
+ return E_BAD_URI;
|
|
|
}
|
|
|
|
|
|
|
|
|
-
|
|
|
int main (int argc, char** argv)
|
|
|
{
|
|
|
|