diff options
Diffstat (limited to 'erts/epmd')
-rw-r--r-- | erts/epmd/src/epmd.c | 14 | ||||
-rw-r--r-- | erts/epmd/src/epmd_cli.c | 5 | ||||
-rw-r--r-- | erts/epmd/src/epmd_int.h | 9 | ||||
-rw-r--r-- | erts/epmd/src/epmd_srv.c | 23 | ||||
-rw-r--r-- | erts/epmd/test/epmd_SUITE.erl | 139 |
5 files changed, 115 insertions, 75 deletions
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c index c503c8c8cf..2267f9b12b 100644 --- a/erts/epmd/src/epmd.c +++ b/erts/epmd/src/epmd.c @@ -2,7 +2,7 @@ /* * %CopyrightBegin% * - * Copyright Ericsson AB 1998-2010. All Rights Reserved. + * Copyright Ericsson AB 1998-2011. All Rights Reserved. * * The contents of this file are subject to the Erlang Public License, * Version 1.1, (the "License"); you may not use this file except in @@ -324,7 +324,11 @@ static void run_daemon(EpmdVars *g) } /* move cwd to root to make sure we are not on a mounted filesystem */ - chdir("/"); + if (chdir("/") < 0) + { + dbg_perror(g,"epmd: chdir() failed"); + epmd_cleanup_exit(g,1); + } umask(0); @@ -497,8 +501,8 @@ static void dbg_gen_printf(int onsyslog,int perr,int from_level, (int) strlen(timestr)-1, timestr); len = strlen(buf); erts_vsnprintf(buf + len, DEBUG_BUFFER_SIZE - len, format, args); - if (perr == 1) - perror(buf); + if (perr != 0) + fprintf(stderr,"%s: %s\r\n",buf,strerror(perr)); else fprintf(stderr,"%s\r\n",buf); } @@ -509,7 +513,7 @@ void dbg_perror(EpmdVars *g,const char *format,...) { va_list args; va_start(args, format); - dbg_gen_printf(1,1,0,g,format,args); + dbg_gen_printf(1,errno,0,g,format,args); va_end(args); } diff --git a/erts/epmd/src/epmd_cli.c b/erts/epmd/src/epmd_cli.c index ac55ba6bb6..2377c0dfe7 100644 --- a/erts/epmd/src/epmd_cli.c +++ b/erts/epmd/src/epmd_cli.c @@ -104,7 +104,10 @@ void epmd_call(EpmdVars *g,int what) fd = conn_to_epmd(g); put_int16(1,buf); buf[2] = what; - write(fd,buf,3); + if (write(fd, buf, 3) != 3) { + printf("epmd: Can't write to epmd\n"); + epmd_cleanup_exit(g,1); + } if (read(fd,(char *)&i,4) != 4) { if (!g->silent) printf("epmd: no response from local epmd\n"); diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h index 2a0de4df9c..a2d7559f9d 100644 --- a/erts/epmd/src/epmd_int.h +++ b/erts/epmd/src/epmd_int.h @@ -240,6 +240,14 @@ #define put_int16(i, s) {((unsigned char*)(s))[0] = ((i) >> 8) & 0xff; \ ((unsigned char*)(s))[1] = (i) & 0xff;} +#if defined(__GNUC__) +# define EPMD_INLINE __inline__ +#elif defined(__WIN32__) +# define EPMD_INLINE __inline +#else +# define EPMD_INLINE +#endif + /* ************************************************************************ */ /* Stuctures used by server */ @@ -295,6 +303,7 @@ typedef struct { unsigned delay_write; int max_conn; int active_conn; + int select_fd_top; char *progname; Connection *conn; Nodes nodes; diff --git a/erts/epmd/src/epmd_srv.c b/erts/epmd/src/epmd_srv.c index 4d9b454f97..da575affa1 100644 --- a/erts/epmd/src/epmd_srv.c +++ b/erts/epmd/src/epmd_srv.c @@ -80,6 +80,13 @@ static int reply(EpmdVars*,int,char *,int); static void dbg_print_buf(EpmdVars*,char *,int); static void print_names(EpmdVars*); +static EPMD_INLINE void select_fd_set(EpmdVars* g, int fd) +{ + FD_SET(fd, &g->orig_read_mask); + if (fd >= g->select_fd_top) { + g->select_fd_top = fd + 1; + } +} void run(EpmdVars *g) { @@ -95,7 +102,8 @@ void run(EpmdVars *g) dbg_printf(g,2,"try to initiate listening port %d", g->port); - if (g->addresses != NULL) + if (g->addresses != NULL && /* String contains non-separator characters if: */ + g->addresses[strspn(g->addresses," ,")] != '\000') { char *tmp; char *token; @@ -171,6 +179,7 @@ void run(EpmdVars *g) g->max_conn -= num_sockets; FD_ZERO(&g->orig_read_mask); + g->select_fd_top = 0; for (i = 0; i < num_sockets; i++) { @@ -232,14 +241,14 @@ void run(EpmdVars *g) dbg_perror(g,"failed to listen on socket"); epmd_cleanup_exit(g,1); } - FD_SET(listensock[i],&g->orig_read_mask); + select_fd_set(g, listensock[i]); } dbg_tty_printf(g,2,"entering the main select() loop"); select_again: while(1) - { + { fd_set read_mask = g->orig_read_mask; struct timeval timeout; int ret; @@ -251,7 +260,8 @@ void run(EpmdVars *g) timeout.tv_sec = (g->packet_timeout < IDLE_TIMEOUT) ? 1 : IDLE_TIMEOUT; timeout.tv_usec = 0; - if ((ret = select(g->max_conn,&read_mask,(fd_set *)0,(fd_set *)0,&timeout)) < 0) { + if ((ret = select(g->select_fd_top, + &read_mask, (fd_set *)0,(fd_set *)0,&timeout)) < 0) { dbg_perror(g,"error in select "); switch (errno) { case EAGAIN: @@ -821,7 +831,7 @@ static int conn_open(EpmdVars *g,int fd) s = &g->conn[i]; /* From now on we want to know if there are data to be read */ - FD_SET(fd, &g->orig_read_mask); + select_fd_set(g, fd); s->fd = fd; s->open = EPMD_TRUE; @@ -886,6 +896,7 @@ int epmd_conn_close(EpmdVars *g,Connection *s) dbg_tty_printf(g,2,"closing connection on file descriptor %d",s->fd); FD_CLR(s->fd,&g->orig_read_mask); + /* we don't bother lowering g->select_fd_top */ close(s->fd); /* Sometimes already closed but close anyway */ s->open = EPMD_FALSE; if (s->buf != NULL) { /* Should never be NULL but test anyway */ @@ -1115,7 +1126,7 @@ static Node *node_reg2(EpmdVars *g, node->extralen = extralen; memcpy(node->extra,extra,extralen); strcpy(node->symname,name); - FD_SET(fd,&g->orig_read_mask); + select_fd_set(g, fd); if (highvsn == 0) { dbg_tty_printf(g,1,"registering '%s:%d', port %d", diff --git a/erts/epmd/test/epmd_SUITE.erl b/erts/epmd/test/epmd_SUITE.erl index 72c890503d..6889ec0b34 100644 --- a/erts/epmd/test/epmd_SUITE.erl +++ b/erts/epmd/test/epmd_SUITE.erl @@ -780,42 +780,43 @@ no_nonlocal_register(suite) -> no_nonlocal_register(doc) -> ["Ensure that we cannot register throug a nonlocal connection"]; no_nonlocal_register(Config) when is_list(Config) -> + ?line case {os:find_executable("ssh"),ct:get_config(ssh_proxy_host)} of + {SSH,Name} when is_list(Name), is_list(SSH) -> + do_no_nonlocal_register(Config,Name); + {false,_} -> + {skip, "No ssh command found to create proxy"}; + _ -> + {skip, "No ssh_proxy_host configured in ts.config"} + end. +do_no_nonlocal_register(Config,SSHHost) when is_list(Config) -> ?line ok = epmdrun(), - ?line {ok,Ifs} = inet:getiflist(), - ?line Addr0 = [ inet:ifget(I, [addr]) || I <- Ifs ], - ?line Addr1 = [ A || {ok,[{addr,A}]} <- Addr0], - ?line Addr = lists:filter(fun({127,_,_,_}) -> - false; - (_) -> - true - end,Addr1), - %% Now we should have all non loopback interface addresses, - %% none should accept a alive2 registration. - ?line Res = lists:map(fun(Ad={A1,A2,A3,A4}) -> - try - Name = "gurka_"++ - integer_to_list(A1)++"_"++ - integer_to_list(A2)++"_"++ - integer_to_list(A3)++"_"++ - integer_to_list(A4), - Bname = list_to_binary(Name), - NameS = byte_size(Bname), - ?line Bin= <<$x:8,4747:16,$M:8,0:8,5:16, - 5:16,NameS:16,Bname/binary, - 0:16>>, - ?line S = size(Bin), - {ok, E} = connect(Ad), - gen_tcp:send(E,[<<S:16>>,Bin]), - closed = recv(E,1), - gen_tcp:close(E), - true - catch - _:_ -> - false - end - end, Addr), - erlang:display(Res), - ?line true = alltrue(Res), + ?line ProxyPort = proxy_port(), + ?line ok = ssh_proxy(SSHHost,ProxyPort), + Res = try + ?line Name = "gurka_" + %++ + %integer_to_list(A1)++"_"++ + %integer_to_list(A2)++"_"++ + %integer_to_list(A3)++"_"++ + %integer_to_list(A4) + , + ?line Bname = list_to_binary(Name), + ?line NameS = byte_size(Bname), + ?line Bin= <<$x:8,4747:16,$M:8,0:8,5:16, + 5:16,NameS:16,Bname/binary, + 0:16>>, + ?line S = size(Bin), + ?line {ok, E} = connect("localhost",ProxyPort,passive), + ?line gen_tcp:send(E,[<<S:16>>,Bin]), + ?line closed = recv(E,1), + ?line gen_tcp:close(E), + true + catch + _:_ -> + false + end, + %erlang:display(Res), + true = Res, ok. no_nonlocal_kill(suite) -> @@ -823,35 +824,34 @@ no_nonlocal_kill(suite) -> no_nonlocal_kill(doc) -> ["Ensure that we cannot kill through nonlocal connection"]; no_nonlocal_kill(Config) when is_list(Config) -> + ?line case {os:find_executable("ssh"),ct:get_config(ssh_proxy_host)} of + {SSH,Name} when is_list(Name), is_list(SSH) -> + do_no_nonlocal_kill(Config,Name); + {false,_} -> + {skip, "No ssh command found to create proxy"}; + _ -> + {skip, "No ssh_proxy_host configured in ts.config"} + end. +do_no_nonlocal_kill(Config,SSHHost) when is_list(Config) -> ?line ok = epmdrun(), - ?line {ok,Ifs} = inet:getiflist(), - ?line Addr0 = [ inet:ifget(I, [addr]) || I <- Ifs ], - ?line Addr1 = [ A || {ok,[{addr,A}]} <- Addr0], - ?line Addr = lists:filter(fun({127,_,_,_}) -> - false; - (_) -> - true - end,Addr1), - %% Now we should have all non loopback interface addresses, - %% none should accept a alive2 registration. - ?line Res = lists:map(fun(Ad) -> - try - {ok, E} = connect(Ad), - M = [?EPMD_KILL_REQ], - send(E, [size16(M), M]), - closed = recv(E,2), - gen_tcp:close(E), - sleep(?MEDIUM_PAUSE), - {ok, E2} = connect(Ad), - gen_tcp:close(E2), - true - catch - _:_ -> - false - end - end, Addr), - erlang:display(Res), - ?line true = alltrue(Res), + ?line ProxyPort = proxy_port(), + ?line ok = ssh_proxy(SSHHost,ProxyPort), + Res = try + {ok, E} = connect("localhost",ProxyPort,passive), + M = [?EPMD_KILL_REQ], + send(E, [size16(M), M]), + closed = recv(E,2), + gen_tcp:close(E), + sleep(?MEDIUM_PAUSE), + {ok, E2} = connect("localhost",ProxyPort,passive), + gen_tcp:close(E2), + true + catch + _:_ -> + false + end, + %erlang:display(Res), + true = Res, ok. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% no_live_killing(doc) -> @@ -896,6 +896,19 @@ cleanup() -> true end. +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +% Start an ssh channel to simulate remote access + +proxy_port() -> + ?PORT+1. + +ssh_proxy(SSHHost,ProxyPort) -> + ?line Host = lists:nth(2,string:tokens(atom_to_list(node()),"@")), + % Requires proxy to be a unix host with the command 'read' accessible + ?line osrun("ssh -L "++integer_to_list(ProxyPort)++":"++Host++":" + ++integer_to_list(?PORT)++" "++SSHHost++" read"). + + %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% % Normal debug start of epmd |