From 36586d64b566677a47ab2e5ed91d831e8136371f Mon Sep 17 00:00:00 2001 From: Razvan Crainea Date: Thu, 19 Feb 2015 17:09:31 +0200 Subject: [PATCH] net: bind protocols and default port before mod_init --- cfg.y | 11 +- main.c | 14 ++- modules/proto_tls/proto_tls.c | 7 ++ net/api_proto.h | 2 + net/proto_tcp/proto_tcp.c | 8 ++ net/proto_udp/proto_udp.c | 9 ++ net/trans.c | 198 ++++++++++++---------------------- net/trans.h | 6 +- socket_info.c | 7 +- sr_module.c | 62 +++++++++++ 10 files changed, 178 insertions(+), 146 deletions(-) diff --git a/cfg.y b/cfg.y index 58c8d817bcc..8799bed3408 100644 --- a/cfg.y +++ b/cfg.y @@ -482,12 +482,7 @@ statements: statements statement {} | statements error { yyerror(""); YYABORT;} ; -statement: assign_stm { - /* FIXME add the temporary listening interfaces */ - if (fix_tmp_listeners() < 0) { - LM_WARN("cannot fix command line listeners\n"); - } - } +statement: assign_stm | module_stm | {rt=REQUEST_ROUTE;} route_stm | {rt=FAILURE_ROUTE;} failure_route_stm @@ -540,10 +535,6 @@ proto: ID { yyerrorf("cannot handle protocol <%s>\n", $1); YYABORT; } - if (trans_load_proto($1, i_tmp) < 0) { - yyerrorf("cannot load protocol <%s>\n", $1); - YYABORT; - } $$ = i_tmp; } ; diff --git a/main.c b/main.c index d74613649ad..2fbbe1f7563 100644 --- a/main.c +++ b/main.c @@ -919,7 +919,7 @@ int main(int argc, char** argv) } tmp[tmp_len]=0; /* null terminate the host */ /* add a new addr. to our address list */ - if (add_tmp_listener(tmp, port, proto)!=0){ + if (add_cmd_listener(tmp, port, proto)!=0){ LM_ERR("failed to add new listen address\n"); goto error00; } @@ -1122,6 +1122,18 @@ int main(int argc, char** argv) /* init the resolver, before fixing the config */ resolv_init(); + /* fix temporary listeners added in the cmd line */ + if (fix_cmd_listeners() < 0) { + LM_ERR("cannot add temproray listeners\n"); + return ret; + } + + /* load transport protocols */ + if (trans_load() < 0) { + LM_ERR("cannot load transport protocols\n"); + goto error; + } + /* fix parameters */ if (port_no<=0) port_no=SIP_PORT; diff --git a/modules/proto_tls/proto_tls.c b/modules/proto_tls/proto_tls.c index 2f12d931ba1..338f693ef9d 100644 --- a/modules/proto_tls/proto_tls.c +++ b/modules/proto_tls/proto_tls.c @@ -57,6 +57,7 @@ static int tls_port_no = SIPS_PORT; static char *tls_domain_avp = NULL; static int mod_init(void); +static int proto_tls_init(void); static void mod_destroy(void); static int proto_tls_api_bind(struct api_proto *proto_binds, struct api_proto_net *net_binds, unsigned short *port); @@ -129,6 +130,7 @@ struct module_exports exports = { }; static struct api_proto tls_proto_binds = { + .init = proto_tls_init, .init_listener = proto_tls_init_listener, .send = proto_tls_send, }; @@ -986,6 +988,11 @@ static void mod_destroy(void) } +static int proto_tls_init(void) +{ + /* TODO - implement this */ + return 0; +} static int proto_tls_api_bind(struct api_proto *proto_api, struct api_proto_net *net_binds, unsigned short *port) { diff --git a/net/api_proto.h b/net/api_proto.h index ac0db98d16b..b0153e6b1b3 100644 --- a/net/api_proto.h +++ b/net/api_proto.h @@ -31,11 +31,13 @@ #define PROTO_PREFIX "proto_" +typedef int (*proto_init_f)(void); typedef int (*proto_init_listener_f)(struct socket_info *si); typedef int (*proto_send_f)(struct socket_info *si, char* buf,unsigned int len, union sockaddr_union* to, int id); struct api_proto { + proto_init_f init; proto_init_listener_f init_listener; proto_send_f send; }; diff --git a/net/proto_tcp/proto_tcp.c b/net/proto_tcp/proto_tcp.c index 566eac0bf46..00406831a5f 100644 --- a/net/proto_tcp/proto_tcp.c +++ b/net/proto_tcp/proto_tcp.c @@ -39,6 +39,7 @@ #include "proto_tcp_handler.h" static int mod_init(void); +static int proto_tcp_init(void); static int proto_tcp_api_bind(struct api_proto *proto_binds, struct api_proto_net *net_binds, unsigned short *port); static int proto_tcp_init_listener(struct socket_info *si); @@ -156,6 +157,7 @@ struct module_exports proto_tcp_exports = { }; static struct api_proto tcp_proto_binds = { + .init = proto_tcp_init, .init_listener = proto_tcp_init_listener, .send = proto_tcp_send, }; @@ -189,6 +191,12 @@ static int mod_init(void) return 0; } +static int proto_tcp_init(void) +{ + /* TODO - port fixing */ + return 0; +} + static int proto_tcp_api_bind(struct api_proto *proto_api, struct api_proto_net *net_binds, unsigned short *port) diff --git a/net/proto_udp/proto_udp.c b/net/proto_udp/proto_udp.c index 49ae1316db5..dd73fc0e00f 100644 --- a/net/proto_udp/proto_udp.c +++ b/net/proto_udp/proto_udp.c @@ -41,6 +41,7 @@ static int mod_init(void); +static int proto_udp_init(void); static int proto_udp_api_bind(struct api_proto *proto_binds, struct api_proto_net *net_binds, unsigned short *port); static int proto_udp_init_listener(struct socket_info *si); @@ -83,6 +84,7 @@ struct module_exports proto_udp_exports = { }; static struct api_proto udp_proto_binds = { + .init = proto_udp_init, .init_listener = proto_udp_init_listener, .send = proto_udp_send, }; @@ -103,6 +105,13 @@ static int mod_init(void) } +static int proto_udp_init(void) +{ + /* TODO - port fixing */ + return 0; +} + + static int proto_udp_api_bind(struct api_proto *proto_api, struct api_proto_net *net_binds, unsigned short *port) { diff --git a/net/trans.c b/net/trans.c index 8dd4e542d8c..a18f25042d2 100644 --- a/net/trans.c +++ b/net/trans.c @@ -37,7 +37,7 @@ * are developed. Since this is done only once, it's not that bad */ struct proto_info *protos; -static struct socket_id *tmp_listeners; +static struct socket_id *cmd_listeners; int trans_init(void) @@ -67,91 +67,60 @@ void trans_destroy(void) #define PROTO_PREFIX_LEN (sizeof(PROTO_PREFIX) - 1) -int trans_load_proto(char *name, enum sip_protos proto) +int trans_load(void) { - int len = strlen(name); - char name_buf[/* PROTO_PREFIX */ PROTO_PREFIX_LEN + len + /* '\0' */ 1]; - int i; - api_proto_bind proto_api; - - if (proto == PROTO_NONE) { - LM_ERR("unknown protocol %s\n", name); - goto error; - } - if (protos[proto].id != PROTO_NONE) { - if (proto != protos[proto].id) { - LM_BUG("inconsistent protocol id\n"); - goto error; - } - return 0; - } - - /* load the protocol */ - memcpy(name_buf, PROTO_PREFIX, PROTO_PREFIX_LEN); - memcpy(name_buf + PROTO_PREFIX_LEN, name, len); - name_buf[len + PROTO_PREFIX_LEN] = '\0'; - - /* lowercase the protocol */ - for (i = PROTO_PREFIX_LEN; i < PROTO_PREFIX_LEN + len; i++) - name_buf[i] |= 0x20; - - - /* check built-in protocols */ - switch (proto) { - case PROTO_TCP: - if (register_module(&proto_tcp_exports, "net/proto", 0) < 0) { - LM_ERR("cannot load static TCP protocol\n"); - return -1; - } - break; - case PROTO_UDP: - if (register_module(&proto_udp_exports, "net/proto", 0) < 0) { - LM_ERR("cannot load static UDP protocol\n"); - return -1; - } - default: - - /* load module if not already loaded from script */ - if (!module_loaded(name_buf)) { + struct sr_module *mod; + cmd_export_t *cmd; + char * proto_name; + int proto = PROTO_NONE; + api_proto_bind abind; + + /* go through all protocol modules loaded and load only the ones + * that are prefixed with the PROTO_PREFIX token */ + for (mod=modules; mod; mod = mod->next) { + if (strncmp(PROTO_PREFIX, mod->exports->name, PROTO_PREFIX_LEN) == 0) { + proto_name = mod->exports->name + PROTO_PREFIX_LEN; + if (parse_proto((unsigned char *)proto_name, + strlen(proto_name), &proto) < 0) { + LM_ERR("don't know any protocol <%s>\n", proto_name); + return -1; + } - char module_buf[/* PROTO_PREFIX */ PROTO_PREFIX_LEN + len + - /* .so */ 3 + /* '\0' */ 1]; - strcpy(module_buf, name_buf); - strcat(module_buf, ".so"); + /* check if we have any listeners for that protocol */ + if (!protos[proto].listeners) { + LM_WARN("protocol %s loaded, but no listeners defined! " + "Skipping ...", proto_name); + goto next; + } - if (load_module(module_buf) < 0) { - LM_ERR("cannot load module %s\n", name_buf); - goto error; + for (cmd = mod->exports->cmds; cmd && cmd->name; cmd++) { + if (strcmp("proto_bind_api", cmd->name)==0) { + abind = (api_proto_bind)cmd->function; + if (abind(&protos[proto].tran, + &protos[proto].net, + &protos[proto].default_port) < 0) { + LM_ERR("cannot load protocol's functions for %s\n", + proto_name); + return -1; + } + /* initialize the protocol */ + if (protos[proto].tran.init() < 0) { + LM_ERR("cannot initi protocol %s\n", proto_name); + return -1; + } + /* everything was fine, return */ + protos[proto].id = proto; + protos[proto].name = proto_name; + goto next; + } } + LM_ERR("No binding found for protocol %s\n", proto_name); + return -1; } - break; - } - - proto_api = (api_proto_bind)find_mod_export(name_buf, - "proto_bind_api", 0, 0); - if (!proto_api) { - LM_ERR("cannot find transport API for protocol %s\n", name); - goto error; - } - if (proto_api(&protos[proto].tran, - &protos[proto].net, &protos[proto].default_port) < 0) { - LM_ERR("cannot bind transport API for protocol %s\n", name); - goto error; - } - protos[proto].name = pkg_malloc(len + 1); - if (!protos[proto].name) { - LM_ERR("cannot allocate space for protocol's name\n"); - goto error; +next: + ; } - memcpy(protos[proto].name, name_buf + PROTO_PREFIX_LEN, len + 1); - - protos[proto].id = proto; - - LM_DBG("Loaded <%s> protocol handlers\n", protos[proto].name); - return 0; -error: - return -1; } #undef PROTO_PREFIX_LEN @@ -163,66 +132,49 @@ int add_listener(struct socket_id *sock, enum si_flags flags) * otherwise UDP will be assumed */ enum sip_protos proto = sock->proto; - struct proto_info *pi; - int port; /* validate the protocol */ if (proto < PROTO_FIRST || proto >= PROTO_LAST) { LM_BUG("invalid protocol number %d\n", proto); return -1; } - pi = &protos[proto]; - if (pi->id == PROTO_NONE) { - LM_BUG("protocol %d not registered\n", proto); - return -1; - } - /* fix the socket's protocol */ - port = sock->port ? sock->port : pi->default_port; /* convert to socket_info */ - if (new_sock2list(sock->name, port, sock->proto, sock->adv_name, sock->adv_port, - sock->children, flags, &pi->listeners) < 0) { + if (new_sock2list(sock->name, sock->port, sock->proto, sock->adv_name, sock->adv_port, + sock->children, flags, &protos[proto].listeners) < 0) { LM_ERR("cannot add socket to the list\n"); return -1; } -/* - * TODO: can't add them right away because we first have to resolve the hosts - * and the resolver is not yet initialized - * - if (protos[proto - 1].binds.add_listener && - protos[proto - 1].binds.add_listener(sock->name, port) < 0) { - LM_ERR("cannot add socket"); - return -1; - } -*/ return 0; } -int add_tmp_listener(char *name, int port, int proto) +int add_cmd_listener(char *name, int port, int proto) { struct socket_id *tmp = pkg_malloc(sizeof(struct socket_id)); if (!tmp) { - LM_ERR("no more pkg memory\n"); + fprintf(stderr, "no more pkg memory\n"); return -1; } memset(tmp, 0, sizeof(struct socket_id)); tmp->name = name; tmp->port = port; tmp->proto = proto; - tmp->next = tmp_listeners; - tmp_listeners = tmp; + tmp->next = cmd_listeners; + cmd_listeners = tmp; return 0; } -int fix_tmp_listeners(void) +int fix_cmd_listeners(void) { struct socket_id *si, *prev; - for (si = tmp_listeners; si;) { + for (si = cmd_listeners; si;) { + if (si->proto == PROTO_NONE) + si->proto = PROTO_UDP; if (add_listener(si, 0) < 0) - LM_ERR("cannot add socket <%s>, skipping...\n", si->name); + LM_ERR("Cannot add socket <%s>, skipping...\n", si->name); prev = si; si = si->next; pkg_free(prev); @@ -230,18 +182,6 @@ int fix_tmp_listeners(void) return 0; } -#if 0 -int add_all_listeners(struct socket_info *si, proto_add_listener_f add_func) -{ - for (; si; si = si->next) - if (add_func(si) < 0) { - LM_ERR("cannot add listener %.*s\n", si->name.len, si->name.s); - return -1; - } - return 0; -} -#endif - /* * return 0 on success, -1 on error */ @@ -249,6 +189,8 @@ int fix_all_socket_lists(void) { int i; int found = 0; + static char buf[5 /* currently sctp\0 is the largest protocol */]; + char *p; #if 0 /* TODO: decide what to do with this */ struct utsname myname; @@ -289,23 +231,25 @@ int fix_all_socket_lists(void) } #endif - for (i = PROTO_FIRST; i < PROTO_LAST; i++) + for (i = PROTO_FIRST; i < PROTO_LAST; i++) { if (protos[i].id != PROTO_NONE) { if (fix_socket_list(&protos[i].listeners)!=0) { LM_ERR("fix_socket_list for %d failed\n", protos[i].id); goto error; } - /* add all sockets to the protocol list - FIXME - why do we need this ?? - if (add_all_listeners(protos[i].listeners, protos[i].api.add_listener)!=0) { - LM_ERR("cannot add listeners for proto %d\n", protos[i].id); + found++; + } else if (protos[i].listeners) { + p = proto2str(i, buf); + if (p == NULL) goto error; - } - */ + *p = '\0'; - found++; + LM_ERR("listeners found for protocol %s, but no module " + "can handle it\n", buf); + goto error; } + } if (!found){ LM_ERR("no listening sockets\n"); diff --git a/net/trans.h b/net/trans.h index 2ec95c7add5..4e319250a56 100644 --- a/net/trans.h +++ b/net/trans.h @@ -69,7 +69,7 @@ void trans_destroy(void); /* * loads the transport protocol */ -int trans_load_proto(char *name, enum sip_protos proto); +int trans_load(void); /* * adds a new listener @@ -79,12 +79,12 @@ int add_listener(struct socket_id *sock, enum si_flags flags); /* * adds a temporary listener */ -int add_tmp_listener(char *name, int port, int proto); +int add_cmd_listener(char *name, int port, int proto); /* * fixes temporary listeners */ -int fix_tmp_listeners(void); +int fix_cmd_listeners(void); /* * fixes all socket lists diff --git a/socket_info.c b/socket_info.c index 21809830f23..aa6c06f00e2 100644 --- a/socket_info.c +++ b/socket_info.c @@ -524,12 +524,9 @@ int fix_socket_list(struct socket_info **list) /* fix the number of processes per interface */ if (!si->children && protos[si->proto].net.flags&PROTO_NET_USE_UDP) si->children = children_no; - /* fix port number, port_no should be !=0 here */ - /* XXX: we should not have port 0 here */ - if (si->port_no==0){ - LM_WARN("Port 0 for socket <%.*s>\n", si->name.len, si->name.s); + if (si->port_no==0) si->port_no= protos[si->proto].default_port; - } + tmp=int2str(si->port_no, &len); if (len>=MAX_PORT_LEN){ LM_ERR("bad port number: %d\n", si->port_no); diff --git a/sr_module.c b/sr_module.c index 9402ce362f7..cebe892c6e3 100644 --- a/sr_module.c +++ b/sr_module.c @@ -54,6 +54,9 @@ #include #include +#include "net/proto_udp/proto_udp_handler.h" +#include "net/proto_tcp/proto_tcp_handler.h" + struct sr_module* modules=0; @@ -276,12 +279,71 @@ int sr_load_module(char* path) return -1; } +/* built-in modules with static exports */ +struct static_modules { + str name; + struct module_exports *exp; +}; + +struct static_modules static_modules[] = { + { str_init(PROTO_PREFIX "udp"), &proto_udp_exports }, + { str_init(PROTO_PREFIX "tcp"), &proto_tcp_exports }, +}; + +static int load_static_module(char *path) +{ + int len = strlen(path); + char *end = path + len; + struct sr_module* t; + unsigned int i; + + /* eliminate the .so, if found */ + if (len > 3 && strncmp(end - 3, ".so", 3)==0) { + end -= 3; + len -= 3; + } + /* we check whether the protocol is found within the static_modules */ + for (i = 0; i < (sizeof(static_modules)/sizeof(static_modules[0])); i++) { + if (len >= static_modules[i].name.len && + /* the path ends in the module's name */ + memcmp(end - static_modules[i].name.len, + static_modules[i].name.s, static_modules[i].name.len) == 0 && + /* check if the previous char is '/' or nothing */ + (len == static_modules[i].name.len || (*(end-len-1) == '/'))) { + + /* yey, found the module - check if it was loaded twice */ + for(t=modules;t; t=t->next){ + if (t->handle==static_modules[i].exp){ + LM_WARN("attempting to load the same module twice (%s)\n", path); + return 0; + } + } + + /* version control */ + if (!version_control(static_modules[i].exp, path)) { + exit(0); + } + + /* launch register */ + if (register_module(static_modules[i].exp, path, static_modules[i].exp)<0) + return -1; + return 0; + } + } + + return -1; +} + /* returns 0 on success , <0 on error */ int load_module(char* name) { int i_tmp; struct stat statf; + /* if this is a static module, load it directly */ + if (load_static_module(name) == 0) + return 0; + if(*name!='/' && mpath!=NULL && strlen(name)+mpath_len<255) {