diff --git a/src/dbpmda/src/dbpmda.h b/src/dbpmda/src/dbpmda.h index 4c62f90..6e35cdf 100644 --- a/src/dbpmda/src/dbpmda.h +++ b/src/dbpmda/src/dbpmda.h @@ -1,4 +1,5 @@ /* + * Copyright (c) 2013 Red Hat. * Copyright (c) 1997 Silicon Graphics, Inc. All Rights Reserved. * * This program is free software; you can redistribute it and/or modify it @@ -10,10 +11,6 @@ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "pmapi.h" @@ -53,7 +50,9 @@ extern void openpmda(char *); extern void closepmda(void); extern void dopmda(int); extern void watch(char *); -extern void opensocket(char *); +extern void open_unix_socket(char *); +extern void open_inet_socket(int); +extern void open_ipv6_socket(int); /* * connection states diff --git a/src/dbpmda/src/gram.y b/src/dbpmda/src/gram.y index b9a6267..b9a83a6 100644 --- a/src/dbpmda/src/gram.y +++ b/src/dbpmda/src/gram.y @@ -110,7 +110,7 @@ fix_dynamic_pmid(char *name, pmID *pmidp) OPEN CLOSE DESC GETDESC FETCH INSTANCE PROFILE HELP WATCH DBG QUIT STATUS STORE INFO TIMER NAMESPACE WAIT PMNS_NAME PMNS_PMID PMNS_CHILDREN PMNS_TRAVERSE ATTR - DSO PIPE SOCK + DSO PIPE SOCK UNIX INET IPV6 ADD DEL ALL NONE INDOM ON OFF PLUS EOL @@ -121,6 +121,7 @@ fix_dynamic_pmid(char *name, pmID *pmidp) debug raw_pmid attribute + servport %type fname @@ -137,12 +138,24 @@ stmt : OPEN EOL { opendso($3, $4, $5); stmt_type = OPEN; YYACCEPT; } - | OPEN PIPE fname arglist { + | OPEN PIPE fname arglist { openpmda($3); stmt_type = OPEN; YYACCEPT; } | OPEN SOCK fname { - opensocket($3); + open_unix_socket($3); + stmt_type = OPEN; YYACCEPT; + } + | OPEN SOCK UNIX fname { + open_unix_socket($4); + stmt_type = OPEN; YYACCEPT; + } + | OPEN SOCK INET servport { + open_inet_socket($4); + stmt_type = OPEN; YYACCEPT; + } + | OPEN SOCK IPV6 servport { + open_ipv6_socket($4); stmt_type = OPEN; YYACCEPT; } | CLOSE EOL { @@ -488,6 +501,20 @@ attribute : NUMBER { } ; +servport : NUMBER { $$ = $1; } + | STRING { + struct servent *srv = getservbyname($1, NULL); + if (srv == NULL) { + sprintf(warnStr, "Failed to map (%s) to a port number", $1); + yyerror(warnStr); + YYERROR; + } + sprintf(warnStr, "Mapped %s to port number %d", $1, srv->s_port); + yywarn(warnStr); + $$ = srv->s_port; + } + ; + metric : NUMBER { pmid.whole = $1; sts = pmNameID(pmid.whole, &str); diff --git a/src/dbpmda/src/lex.l b/src/dbpmda/src/lex.l index aa7132f..2a9cebf 100644 --- a/src/dbpmda/src/lex.l +++ b/src/dbpmda/src/lex.l @@ -76,7 +76,9 @@ fetch { return FETCH; } getdesc { return GETDESC; } help { return HELP; } indom { return INDOM; } +inet { return INET; } instance { return INSTANCE; } +ipv6 { return IPV6; } name { return PMNS_NAME; } namespace { BEGIN FNAME; return NAMESPACE; } none { return NONE; } @@ -94,6 +96,7 @@ store { return STORE; } text { return INFO; } timer { return TIMER; } traverse { return PMNS_TRAVERSE; } +unix { return UNIX; } wait { return WAIT; } watch { BEGIN FNAME; return WATCH; } \? { return HELP; } diff --git a/src/dbpmda/src/pmda.c b/src/dbpmda/src/pmda.c index 7a3eac9..7b9b00a 100644 --- a/src/dbpmda/src/pmda.c +++ b/src/dbpmda/src/pmda.c @@ -177,7 +177,7 @@ openpmda(char *fname) #ifdef HAVE_SYS_UN_H void -opensocket(char *fname) +open_unix_socket(char *fname) { int fd; struct stat buf; @@ -222,12 +222,69 @@ opensocket(char *fname) } #else void -opensocket(char *fname) +open_unix_socket(char *fname) { - __pmNotifyErr(LOG_CRIT, "UNIX domain sockets unsupported\n"); + __pmNotifyErr(LOG_CRIT, "UNIX domain sockets unsupported\n"); } #endif +static void +open_socket(int port, int family, const char *protocol) +{ + __pmSockAddr *addr; + int fd, sts; + char socket[64]; + + fd = (family == AF_INET) ? __pmCreateSocket() : __pmCreateIPv6Socket(); + if (fd < 0) { + fprintf(stderr, "opensocket: socket: %s\n", netstrerror()); + return; + } + + addr = __pmLoopBackAddress(family); + if (addr == NULL) { + fprintf(stderr, "opensocket: loopback: %s\n", netstrerror()); + __pmCloseSocket(fd); + return; + } + + closepmda(); + + sts = __pmConnectTo(fd, addr, port); + __pmSockAddrFree(addr); + + if (sts < 0) { + fprintf(stderr, "opensocket: connect: %s\n", netstrerror()); + __pmCloseSocket(fd); + return; + } + + infd = fd; + outfd = fd; + + sprintf(socket, "%s port %d", protocol, port); + printf("Connect to PMDA on %s\n", socket); + + connmode = CONN_DAEMON; + reset_profile(); + if (myPmdaName != NULL) + free(myPmdaName); + myPmdaName = strdup(socket); + pmdaversion(); +} + +void +open_inet_socket(int port) +{ + open_socket(port, AF_INET, "inet"); +} + +void +open_ipv6_socket(int port) +{ + open_socket(port, AF_INET6, "ipv6"); +} + void closepmda(void) { diff --git a/src/dbpmda/src/util.c b/src/dbpmda/src/util.c index 7b8a9f0..c81832a 100644 --- a/src/dbpmda/src/util.c +++ b/src/dbpmda/src/util.c @@ -284,7 +284,9 @@ dohelp(int command, int full) case OPEN: puts("open dso dsoname init_routine [ domain# ]"); puts("open pipe execname [ arg ... ]"); - puts("open socket sockname"); + puts("open socket unix sockname"); + puts("open socket inet port#|service"); + puts("open socket ipv6 port#|service"); break; case PMNS_CHILDREN: puts("children metric-name"); @@ -378,12 +380,14 @@ dohelp(int command, int full) break; case OPEN: puts( -"Open a PMDA as either a DSO, via UNIX domain socket (named pipe), or as a\n" +"Open a PMDA as either a DSO, via a network socket (unix/inet/ipv6), or as a\n" "daemon (connected with a pipe). The 'dsoname' and 'execname' fields are\n" -"the path to the PMDA shared object file or executable. The 'sockname'\n" -"field is the path of a named pipe where a PMDA is listening for connections.\n" +"the path to the PMDA shared object file or executable. The first socket PMDA\n" +"field is the type - either unix (if supported), inet or ipv6. The 'sockname'\n" +"argument for unix sockets is a path of a named pipe where a PMDA is listening\n" +"for connections. The 'port' argument is a port number, 'serv' a service name\n" +"typically defined in /etc/services (resolved to a port via getservent(3)).\n" "The arguments to this command are similar to a line in the pmcd.conf file.\n"); - break; case PMNS_CHILDREN: puts( diff --git a/src/include/pcp/pmda.h b/src/include/pcp/pmda.h index 224b281..e01a8cd 100644 --- a/src/include/pcp/pmda.h +++ b/src/include/pcp/pmda.h @@ -36,7 +36,7 @@ extern "C" { /* * Type of I/O connection to PMCD (pmdaUnknown defaults to pmdaPipe) */ -typedef enum {pmdaPipe, pmdaInet, pmdaIPv6, pmdaUnix, pmdaUnknown} pmdaIoType; +typedef enum {pmdaPipe, pmdaInet, pmdaUnix, pmdaUnknown, pmdaIPv6} pmdaIoType; /* * Instance description: index and name