Module: sip-router Branch: master Commit: 6335d07c4c77ed60fb8c2b5acc84d7c4b503221c URL: http://git.sip-router.org/cgi-bin/gitweb.cgi/sip-router/?a=commit;h=6335d07c...
Author: Daniel-Constantin Mierla miconda@gmail.com Committer: Daniel-Constantin Mierla miconda@gmail.com Date: Wed Jul 17 12:22:31 2013 +0200
core: helper functions to lookup local socket from proto:host:port
---
main.c | 2 +- socket_info.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ socket_info.h | 10 ++++++ 3 files changed, 105 insertions(+), 1 deletions(-)
diff --git a/main.c b/main.c index 05f45b5..24d3dc8 100644 --- a/main.c +++ b/main.c @@ -924,7 +924,7 @@ error:
/* returns -1 on error, 0 on success * sets proto */ -static int parse_proto(unsigned char* s, long len, int* proto) +int parse_proto(unsigned char* s, long len, int* proto) { #define PROTO2UINT3(a, b, c) (( (((unsigned int)(a))<<16)+ \ (((unsigned int)(b))<<8)+ \ diff --git a/socket_info.c b/socket_info.c index b489c8e..3314014 100644 --- a/socket_info.c +++ b/socket_info.c @@ -2057,3 +2057,97 @@ void init_proto_order() }
+/** + * parse '[port:]host[:port]' string to a broken down structure + */ +int parse_protohostport(str* ins, sr_phostp_t *r) +{ + char* first; /* first ':' occurrence */ + char* second; /* second ':' occurrence */ + char* p; + int bracket; + char* tmp; + + first=second=0; + bracket=0; + memset(r, 0, sizeof(sr_phostp_t)); + + /* find the first 2 ':', ignoring possible ipv6 addresses + * (substrings between []) + */ + for(p=ins->s; p<ins->s+ins->len; p++){ + switch(*p){ + case '[': + bracket++; + if (bracket>1) goto error_brackets; + break; + case ']': + bracket--; + if (bracket<0) goto error_brackets; + break; + case ':': + if (bracket==0){ + if (first==0) first=p; + else if( second==0) second=p; + else goto error_colons; + } + break; + } + } + if (p==ins->s) return -1; + if (*(p-1)==':') goto error_colons; + + if (first==0) { /* no ':' => only host */ + r->host.s=ins->s; + r->host.len=(int)(p-ins->s); + goto end; + } + if (second) { /* 2 ':' found => check if valid */ + if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0) + goto error_proto; + r->port=strtol(second+1, &tmp, 10); + if ((tmp==0)||(*tmp)||(tmp==second+1)) goto error_port; + r->host.s=first+1; + r->host.len=(int)(second-r->host.s); + goto end; + } + /* only 1 ':' found => it's either proto:host or host:port */ + r->port=strtol(first+1, &tmp, 10); + if ((tmp==0)||(*tmp)||(tmp==first+1)){ + /* invalid port => it's proto:host */ + if (parse_proto((unsigned char*)ins->s, first-ins->s, &r->proto)<0) + goto error_proto; + r->host.s=first+1; + r->host.len=(int)(p-r->host.s); + }else{ + /* valid port => its host:port */ + r->host.s=ins->s; + r->host.len=(int)(first-r->host.s); + } +end: + return 0; +error_brackets: + LOG(L_ERR, "too many brackets in %.*s\n", ins->len, ins->s); + return -1; +error_colons: + LOG(L_ERR, "too many colons in %.*s\n", ins->len, ins->s); + return -1; +error_proto: + LOG(L_ERR, "bad protocol in %.*s\n", ins->len, ins->s); + return -1; +error_port: + LOG(L_ERR, "bad port number in %.*s\n", ins->len, ins->s); + return -1; +} + +/** + * lookup a local socket by '[port:]host[:port]' string + */ +struct socket_info* lookup_local_socket(str *phostp) +{ + sr_phostp_t r; + if(parse_protohostport(phostp, &r)<0) + return NULL; + return grep_sock_info(&r.host, (unsigned short)r.port, + (unsigned short)r.proto); +} diff --git a/socket_info.h b/socket_info.h index 926b317..ea0ab8b 100644 --- a/socket_info.h +++ b/socket_info.h @@ -105,6 +105,8 @@ struct socket_info** get_sock_info_list(unsigned short proto); int parse_phostport(char* s, char** host, int* hlen, int* port, int* proto);
+int parse_proto(unsigned char* s, long len, int* proto); + char* get_valid_proto_name(unsigned short proto);
/* helper function: @@ -142,5 +144,13 @@ inline static struct socket_info* get_first_socket(void) return 0; }
+/* structure to break down 'proto:host:port' */ +typedef struct _sr_phostp { + int proto; + str host; + int port; +} sr_phostp_t; + +struct socket_info* lookup_local_socket(str *phostp);
#endif