|
Packit |
fcad23 |
#include <net-snmp/net-snmp-config.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmpSTDDomain.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <stdio.h>
|
|
Packit |
fcad23 |
#include <sys/types.h>
|
|
Packit |
fcad23 |
#include <signal.h>
|
|
Packit |
fcad23 |
#include <errno.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if HAVE_STRING_H
|
|
Packit |
fcad23 |
#include <string.h>
|
|
Packit |
fcad23 |
#else
|
|
Packit |
fcad23 |
#include <strings.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#if HAVE_STDLIB_H
|
|
Packit |
fcad23 |
#include <stdlib.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#if HAVE_UNISTD_H
|
|
Packit |
fcad23 |
#include <unistd.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#if HAVE_DMALLOC_H
|
|
Packit |
fcad23 |
#include <dmalloc.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/types.h>
|
|
Packit |
fcad23 |
#include <net-snmp/output_api.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/library/snmp_transport.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/tools.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
oid netsnmp_snmpSTDDomain[] = { TRANSPORT_DOMAIN_STD_IP };
|
|
Packit |
fcad23 |
static netsnmp_tdomain stdDomain;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Return a string representing the address in data, or else the "far end"
|
|
Packit |
fcad23 |
* address if data is NULL.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static char *
|
|
Packit |
fcad23 |
netsnmp_std_fmtaddr(netsnmp_transport *t, const void *data, int len)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std","formatting addr. data=%p\n",t->data));
|
|
Packit |
fcad23 |
if (t->data) {
|
|
Packit |
fcad23 |
netsnmp_std_data *data = (netsnmp_std_data*)t->data;
|
|
Packit |
fcad23 |
char *buf;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (asprintf(&buf, "STD:%s", data->prog) < 0)
|
|
Packit |
fcad23 |
buf = NULL;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std"," formatted:=%s\n",buf));
|
|
Packit |
fcad23 |
return buf;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return strdup("STDInOut");
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static void
|
|
Packit |
fcad23 |
netsnmp_std_get_taddr(netsnmp_transport *t, void **addr, size_t *addr_len)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
*addr_len = t->remote_length;
|
|
Packit |
fcad23 |
*addr = netsnmp_memdup(t->remote, *addr_len);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* You can write something into opaque that will subsequently get passed back
|
|
Packit |
fcad23 |
* to your send function if you like. For instance, you might want to
|
|
Packit |
fcad23 |
* remember where a PDU came from, so that you can send a reply there...
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
netsnmp_std_recv(netsnmp_transport *t, void *buf, int size,
|
|
Packit |
fcad23 |
void **opaque, int *olength)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int rc = -1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std","recv on sock %d. data=%p\n",t->sock, t->data));
|
|
Packit |
fcad23 |
while (rc < 0) {
|
|
Packit |
fcad23 |
rc = read(t->sock, buf, size);
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std"," bytes: %d.\n", rc));
|
|
Packit |
fcad23 |
if (rc < 0 && errno != EINTR) {
|
|
Packit |
fcad23 |
DEBUGMSGTL(("netsnmp_std", " read on fd %d failed: %d (\"%s\")\n",
|
|
Packit |
fcad23 |
t->sock, errno, strerror(errno)));
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
if (rc == 0) {
|
|
Packit |
fcad23 |
/* 0 input is probably bad since we selected on it */
|
|
Packit |
fcad23 |
return -1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
DEBUGMSGTL(("netsnmp_std", "read on stdin got %d bytes\n", rc));
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return rc;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
netsnmp_std_send(netsnmp_transport *t, const void *buf, int size,
|
|
Packit |
fcad23 |
void **opaque, int *olength)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
int rc = -1;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std","send on sock. data=%p\n", t->data));
|
|
Packit |
fcad23 |
while (rc < 0) {
|
|
Packit |
fcad23 |
if (t->data) {
|
|
Packit |
fcad23 |
netsnmp_std_data *data = (netsnmp_std_data*)t->data;
|
|
Packit |
fcad23 |
rc = write(data->outfd, buf, size);
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
/* straight to stdout */
|
|
Packit |
fcad23 |
rc = write(1, buf, size);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
if (rc < 0 && errno != EINTR) {
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return rc;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
netsnmp_std_close(netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std","close. data=%p\n", t->data));
|
|
Packit |
fcad23 |
if (t->data) {
|
|
Packit |
fcad23 |
netsnmp_std_data *data = (netsnmp_std_data*)t->data;
|
|
Packit |
fcad23 |
close(data->outfd);
|
|
Packit |
fcad23 |
close(t->sock);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* kill the child too */
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std"," killing %d\n", data->childpid));
|
|
Packit |
fcad23 |
kill(data->childpid, SIGTERM);
|
|
Packit |
fcad23 |
sleep(1);
|
|
Packit |
fcad23 |
kill(data->childpid, SIGKILL);
|
|
Packit |
fcad23 |
/* XXX: set an alarm to kill harder the child */
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
/* close stdout/in */
|
|
Packit |
fcad23 |
close(STDOUT_FILENO);
|
|
Packit |
fcad23 |
close(STDIN_FILENO);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
static int
|
|
Packit |
fcad23 |
netsnmp_std_accept(netsnmp_transport *t)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std"," accept data=%p\n", t->data));
|
|
Packit |
fcad23 |
/* nothing to do here */
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Open a STDIN/STDOUT -based transport for SNMP.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_std_transport(const char *instring, size_t instring_len,
|
|
Packit |
fcad23 |
const char *default_target)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
netsnmp_transport *t;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
t = SNMP_MALLOC_TYPEDEF(netsnmp_transport);
|
|
Packit |
fcad23 |
if (t == NULL) {
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
t->domain = netsnmp_snmpSTDDomain;
|
|
Packit |
fcad23 |
t->domain_length =
|
|
Packit |
fcad23 |
sizeof(netsnmp_snmpSTDDomain) / sizeof(netsnmp_snmpSTDDomain[0]);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
t->sock = -1;
|
|
Packit |
fcad23 |
t->flags = NETSNMP_TRANSPORT_FLAG_STREAM | NETSNMP_TRANSPORT_FLAG_TUNNELED;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Message size is not limited by this transport (hence msgMaxSize
|
|
Packit |
fcad23 |
* is equal to the maximum legal size of an SNMP message).
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
t->msgMaxSize = SNMP_MAX_PACKET_LEN;
|
|
Packit |
fcad23 |
t->f_recv = netsnmp_std_recv;
|
|
Packit |
fcad23 |
t->f_send = netsnmp_std_send;
|
|
Packit |
fcad23 |
t->f_close = netsnmp_std_close;
|
|
Packit |
fcad23 |
t->f_accept = netsnmp_std_accept;
|
|
Packit |
fcad23 |
t->f_fmtaddr = netsnmp_std_fmtaddr;
|
|
Packit |
fcad23 |
t->f_get_taddr = netsnmp_std_get_taddr;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* if instring is not null length, it specifies a path to a prog
|
|
Packit |
fcad23 |
* XXX: plus args
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (instring_len == 0 && default_target != NULL) {
|
|
Packit |
fcad23 |
instring = default_target;
|
|
Packit |
fcad23 |
instring_len = strlen(default_target);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (instring_len != 0) {
|
|
Packit |
fcad23 |
int infd[2], outfd[2]; /* sockets to and from the client */
|
|
Packit |
fcad23 |
int childpid;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (pipe(infd) || pipe(outfd)) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR,
|
|
Packit |
fcad23 |
"Failed to create needed pipes for a STD transport");
|
|
Packit |
fcad23 |
netsnmp_transport_free(t);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
childpid = fork();
|
|
Packit |
fcad23 |
/* parentpid => childpid */
|
|
Packit |
fcad23 |
/* infd[1] => infd[0] */
|
|
Packit |
fcad23 |
/* outfd[0] <= outfd[1] */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (childpid) {
|
|
Packit |
fcad23 |
netsnmp_std_data *data;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* we're in the parent */
|
|
Packit |
fcad23 |
close(infd[0]);
|
|
Packit |
fcad23 |
close(outfd[1]);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
data = SNMP_MALLOC_TYPEDEF(netsnmp_std_data);
|
|
Packit |
fcad23 |
if (!data) {
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "snmpSTDDomain: malloc failed");
|
|
Packit |
fcad23 |
netsnmp_transport_free(t);
|
|
Packit |
fcad23 |
return NULL;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
t->data = data;
|
|
Packit |
fcad23 |
t->data_length = sizeof(netsnmp_std_data);
|
|
Packit |
fcad23 |
t->sock = outfd[0];
|
|
Packit |
fcad23 |
data->prog = strdup(instring);
|
|
Packit |
fcad23 |
data->outfd = infd[1];
|
|
Packit |
fcad23 |
data->childpid = childpid;
|
|
Packit |
fcad23 |
DEBUGMSGTL(("domain:std","parent. data=%p\n", t->data));
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
/* we're in the child */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
dup2(infd[0], STDIN_FILENO);
|
|
Packit |
fcad23 |
dup2(outfd[1], STDOUT_FILENO);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* close all the pipes themselves */
|
|
Packit |
fcad23 |
close(infd[0]);
|
|
Packit |
fcad23 |
close(infd[1]);
|
|
Packit |
fcad23 |
close(outfd[0]);
|
|
Packit |
fcad23 |
close(outfd[1]);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* call exec */
|
|
Packit |
fcad23 |
system(instring);
|
|
Packit |
fcad23 |
/* XXX: TODO: use exec form instead; needs args */
|
|
Packit |
fcad23 |
/* execv(instring, NULL); */
|
|
Packit |
fcad23 |
exit(0);
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/* ack... we should never ever get here */
|
|
Packit |
fcad23 |
snmp_log(LOG_ERR, "STD transport returned after execv()\n");
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return t;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_std_create_tstring(const char *instring, int local,
|
|
Packit |
fcad23 |
const char *default_target)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return netsnmp_std_transport(instring, strlen(instring), default_target);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_transport *
|
|
Packit |
fcad23 |
netsnmp_std_create_ostring(const void *o, size_t o_len, int local)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
return netsnmp_std_transport(o, o_len, NULL);
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
void
|
|
Packit |
fcad23 |
netsnmp_std_ctor(void)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
stdDomain.name = netsnmp_snmpSTDDomain;
|
|
Packit |
fcad23 |
stdDomain.name_length = sizeof(netsnmp_snmpSTDDomain) / sizeof(oid);
|
|
Packit |
fcad23 |
stdDomain.prefix = (const char **)calloc(2, sizeof(char *));
|
|
Packit |
fcad23 |
stdDomain.prefix[0] = "std";
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
stdDomain.f_create_from_tstring = NULL;
|
|
Packit |
fcad23 |
stdDomain.f_create_from_tstring_new = netsnmp_std_create_tstring;
|
|
Packit |
fcad23 |
stdDomain.f_create_from_ostring = netsnmp_std_create_ostring;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
netsnmp_tdomain_register(&stdDomain);
|
|
Packit |
fcad23 |
}
|