mirror of
https://github.com/Stichting-MINIX-Research-Foundation/netbsd.git
synced 2025-09-12 16:46:33 -04:00
462 lines
8.0 KiB
C
462 lines
8.0 KiB
C
/* $NetBSD: save_v2trap.c,v 1.2 2014/12/20 13:15:48 prlw1 Exp $ */
|
|
|
|
#include "ipf.h"
|
|
#include "netinet/ipl.h"
|
|
#include "ipmon.h"
|
|
#include <ctype.h>
|
|
|
|
static u_char sysuptime[] = { 6, 8, 0x2b, 6, 1, 2, 1, 1, 3, 0 };
|
|
/*
|
|
* Enterprise number OID:
|
|
* 1.3.6.1.4.1.9932
|
|
*/
|
|
static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 };
|
|
static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 };
|
|
|
|
static int writeint __P((u_char *, int));
|
|
static int writelength __P((u_char *, u_int));
|
|
static int maketrap_v2 __P((char *, u_char *, int, u_char *, int));
|
|
static void snmpv2_destroy __P((void *));
|
|
static void *snmpv2_dup __P((void *));
|
|
static int snmpv2_match __P((void *, void *));
|
|
static void *snmpv2_parse __P((char **));
|
|
static void snmpv2_print __P((void *));
|
|
static int snmpv2_send __P((void *, ipmon_msg_t *));
|
|
|
|
|
|
int sendtrap_v2_0 __P((int, char *, char *, int));
|
|
|
|
static char def_community[] = "public"; /* ublic */
|
|
|
|
typedef struct snmpv2_opts_s {
|
|
char *community;
|
|
char *server;
|
|
int fd;
|
|
int v6;
|
|
int ref;
|
|
#ifdef USE_INET6
|
|
struct sockaddr_in6 sin6;
|
|
#endif
|
|
struct sockaddr_in sin;
|
|
} snmpv2_opts_t;
|
|
|
|
ipmon_saver_t snmpv2saver = {
|
|
"snmpv2",
|
|
snmpv2_destroy,
|
|
snmpv2_dup, /* dup */
|
|
snmpv2_match, /* match */
|
|
snmpv2_parse,
|
|
snmpv2_print,
|
|
snmpv2_send
|
|
};
|
|
|
|
|
|
static int
|
|
snmpv2_match(ctx1, ctx2)
|
|
void *ctx1, *ctx2;
|
|
{
|
|
snmpv2_opts_t *s1 = ctx1, *s2 = ctx2;
|
|
|
|
if (s1->v6 != s2->v6)
|
|
return 1;
|
|
|
|
if (strcmp(s1->community, s2->community))
|
|
return 1;
|
|
|
|
#ifdef USE_INET6
|
|
if (s1->v6 == 1) {
|
|
if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6)))
|
|
return 1;
|
|
} else
|
|
#endif
|
|
{
|
|
if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin)))
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void *
|
|
snmpv2_dup(ctx)
|
|
void *ctx;
|
|
{
|
|
snmpv2_opts_t *s = ctx;
|
|
|
|
s->ref++;
|
|
return s;
|
|
}
|
|
|
|
|
|
static void
|
|
snmpv2_print(ctx)
|
|
void *ctx;
|
|
{
|
|
snmpv2_opts_t *snmpv2 = ctx;
|
|
|
|
printf("%s ", snmpv2->community);
|
|
#ifdef USE_INET6
|
|
if (snmpv2->v6 == 1) {
|
|
char buf[80];
|
|
|
|
printf("%s", inet_ntop(AF_INET6, &snmpv2->sin6.sin6_addr, buf,
|
|
sizeof(snmpv2->sin6.sin6_addr)));
|
|
} else
|
|
#endif
|
|
{
|
|
printf("%s", inet_ntoa(snmpv2->sin.sin_addr));
|
|
}
|
|
}
|
|
|
|
|
|
static void *
|
|
snmpv2_parse(char **strings)
|
|
{
|
|
snmpv2_opts_t *ctx;
|
|
int result;
|
|
char *str;
|
|
char *s;
|
|
|
|
if (strings[0] == NULL || strings[0][0] == '\0')
|
|
return NULL;
|
|
if (strchr(*strings, ' ') == NULL)
|
|
return NULL;
|
|
|
|
str = strdup(*strings);
|
|
|
|
ctx = calloc(1, sizeof(*ctx));
|
|
if (ctx == NULL)
|
|
return NULL;
|
|
|
|
ctx->fd = -1;
|
|
|
|
s = strchr(str, ' ');
|
|
*s++ = '\0';
|
|
ctx->community = str;
|
|
|
|
while (ISSPACE(*s))
|
|
s++;
|
|
if (!*s) {
|
|
free(str);
|
|
free(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
#ifdef USE_INET6
|
|
if (strchr(s, ':') == NULL) {
|
|
result = inet_pton(AF_INET, s, &ctx->sin.sin_addr);
|
|
if (result == 1) {
|
|
ctx->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
if (ctx->fd >= 0) {
|
|
ctx->sin.sin_family = AF_INET;
|
|
ctx->sin.sin_port = htons(162);
|
|
if (connect(ctx->fd,
|
|
(struct sockaddr *)&ctx->sin,
|
|
sizeof(ctx->sin)) != 0) {
|
|
snmpv2_destroy(ctx);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr);
|
|
if (result == 1) {
|
|
ctx->v6 = 1;
|
|
ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0);
|
|
if (ctx->fd >= 0) {
|
|
ctx->sin6.sin6_family = AF_INET6;
|
|
ctx->sin6.sin6_port = htons(162);
|
|
if (connect(ctx->fd,
|
|
(struct sockaddr *)&ctx->sin6,
|
|
sizeof(ctx->sin6)) != 0) {
|
|
snmpv2_destroy(ctx);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#else
|
|
result = inet_aton(s, &ctx->sin.sin_addr);
|
|
if (result == 1) {
|
|
ctx->fd = socket(AF_INET, SOCK_DGRAM, 0);
|
|
if (ctx->fd >= 0) {
|
|
ctx->sin.sin_family = AF_INET;
|
|
ctx->sin.sin_port = htons(162);
|
|
if (connect(ctx->fd, (struct sockaddr *)&ctx->sin,
|
|
sizeof(ctx->sin)) != 0) {
|
|
snmpv2_destroy(ctx);
|
|
return NULL;
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (result != 1) {
|
|
free(str);
|
|
free(ctx);
|
|
return NULL;
|
|
}
|
|
|
|
ctx->ref = 1;
|
|
|
|
return ctx;
|
|
}
|
|
|
|
|
|
static void
|
|
snmpv2_destroy(ctx)
|
|
void *ctx;
|
|
{
|
|
snmpv2_opts_t *v2 = ctx;
|
|
|
|
v2->ref--;
|
|
if (v2->ref > 0)
|
|
return;
|
|
|
|
if (v2->community)
|
|
free(v2->community);
|
|
if (v2->fd >= 0)
|
|
close(v2->fd);
|
|
free(v2);
|
|
}
|
|
|
|
|
|
static int
|
|
snmpv2_send(ctx, msg)
|
|
void *ctx;
|
|
ipmon_msg_t *msg;
|
|
{
|
|
snmpv2_opts_t *v2 = ctx;
|
|
|
|
return sendtrap_v2_0(v2->fd, v2->community,
|
|
msg->imm_msg, msg->imm_msglen);
|
|
}
|
|
static int
|
|
writelength(buffer, value)
|
|
u_char *buffer;
|
|
u_int value;
|
|
{
|
|
u_int n = htonl(value);
|
|
int len;
|
|
|
|
if (value < 128) {
|
|
*buffer = value;
|
|
return 1;
|
|
}
|
|
if (value > 0xffffff)
|
|
len = 4;
|
|
else if (value > 0xffff)
|
|
len = 3;
|
|
else if (value > 0xff)
|
|
len = 2;
|
|
else
|
|
len = 1;
|
|
|
|
*buffer = 0x80 | len;
|
|
|
|
bcopy((u_char *)&n + 4 - len, buffer + 1, len);
|
|
|
|
return len + 1;
|
|
}
|
|
|
|
|
|
static int
|
|
writeint(buffer, value)
|
|
u_char *buffer;
|
|
int value;
|
|
{
|
|
u_char *s = buffer;
|
|
u_int n = value;
|
|
|
|
if (value == 0) {
|
|
*buffer = 0;
|
|
return 1;
|
|
}
|
|
|
|
if (n > 4194304) {
|
|
*s++ = 0x80 | (n / 4194304);
|
|
n -= 4194304 * (n / 4194304);
|
|
}
|
|
if (n > 32768) {
|
|
*s++ = 0x80 | (n / 32768);
|
|
n -= 32768 * (n / 327678);
|
|
}
|
|
if (n > 128) {
|
|
*s++ = 0x80 | (n / 128);
|
|
n -= (n / 128) * 128;
|
|
}
|
|
*s++ = (u_char)n;
|
|
|
|
return s - buffer;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* First style of traps is:
|
|
* 1.3.6.1.4.1.9932.1.1
|
|
*/
|
|
static int
|
|
maketrap_v2(community, buffer, bufsize, msg, msglen)
|
|
char *community;
|
|
u_char *buffer;
|
|
int bufsize;
|
|
u_char *msg;
|
|
int msglen;
|
|
{
|
|
u_char *s = buffer, *t, *pdulen;
|
|
u_char *varlen;
|
|
int basesize = 77;
|
|
u_short len;
|
|
int trapmsglen;
|
|
int pdulensz;
|
|
int varlensz;
|
|
int baselensz;
|
|
int n;
|
|
|
|
if (community == NULL || *community == '\0')
|
|
community = def_community;
|
|
basesize += strlen(community) + msglen;
|
|
|
|
if (basesize + 8 > bufsize)
|
|
return 0;
|
|
|
|
memset(buffer, 0xff, bufsize);
|
|
*s++ = 0x30; /* Sequence */
|
|
|
|
if (basesize - 1 >= 128) {
|
|
baselensz = 2;
|
|
basesize++;
|
|
} else {
|
|
baselensz = 1;
|
|
}
|
|
s += baselensz;
|
|
*s++ = 0x02; /* Integer32 */
|
|
*s++ = 0x01; /* length 1 */
|
|
*s++ = 0x01; /* version 2 */
|
|
*s++ = 0x04; /* octet string */
|
|
*s++ = strlen(community); /* length of "public" */
|
|
bcopy(community, s, s[-1]);
|
|
s += s[-1];
|
|
*s++ = 0xA7; /* PDU(7) */
|
|
pdulen = s++;
|
|
if (basesize - (s - buffer) >= 128) {
|
|
pdulensz = 2;
|
|
basesize++;
|
|
s++;
|
|
} else {
|
|
pdulensz = 1;
|
|
}
|
|
/* request id */
|
|
*s++ = 0x2; /* integer */
|
|
*s++ = 0x4; /* len 4 */
|
|
*s++ = 0x0; /* noError */
|
|
*s++ = 0x0; /* noError */
|
|
*s++ = 0x0; /* noError */
|
|
*s++ = 0x0; /* noError */
|
|
|
|
/* error status */
|
|
*s++ = 0x2; /* integer */
|
|
*s++ = 0x1; /* len 1 */
|
|
*s++ = 0x0; /* noError */
|
|
|
|
/* error-index */
|
|
*s++ = 0x2; /* integer */
|
|
*s++ = 0x1; /* len 1 */
|
|
*s++ = 0x0; /* noError */
|
|
|
|
*s++ = 0x30; /* sequence */
|
|
varlen = s++;
|
|
if (basesize - (s - buffer) >= 128) {
|
|
varlensz = 2;
|
|
basesize++;
|
|
s++;
|
|
} else {
|
|
varlensz = 1;
|
|
}
|
|
|
|
*s++ = 0x30; /* sequence */
|
|
*s++ = sizeof(sysuptime) + 6;
|
|
|
|
bcopy(sysuptime, s, sizeof(sysuptime));
|
|
s += sizeof(sysuptime);
|
|
|
|
*s++ = 0x43; /* Timestamp */
|
|
*s++ = 0x04; /* TimeTicks */
|
|
*s++ = 0x0;
|
|
*s++ = 0x0;
|
|
*s++ = 0x0;
|
|
*s++ = 0x0;
|
|
|
|
*s++ = 0x30;
|
|
t = s + 1;
|
|
bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1));
|
|
t += sizeof(ipf_trap0_1);
|
|
|
|
*t++ = 0x2; /* Integer */
|
|
n = writeint(t + 1, IPFILTER_VERSION);
|
|
*t = n;
|
|
t += n + 1;
|
|
|
|
len = t - s - 1;
|
|
writelength(s, len);
|
|
|
|
s = t;
|
|
*s++ = 0x30;
|
|
if (msglen < 128) {
|
|
if (msglen + 1 + 1 + sizeof(ipf_trap0_2) >= 128)
|
|
trapmsglen = 2;
|
|
else
|
|
trapmsglen = 1;
|
|
} else {
|
|
if (msglen + 2 + 1 + sizeof(ipf_trap0_2) >= 128)
|
|
trapmsglen = 2;
|
|
else
|
|
trapmsglen = 1;
|
|
}
|
|
t = s + trapmsglen;
|
|
bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2));
|
|
t += sizeof(ipf_trap0_2);
|
|
|
|
*t++ = 0x4; /* Octet string */
|
|
n = writelength(t, msglen);
|
|
t += n;
|
|
bcopy(msg, t, msglen);
|
|
t += msglen;
|
|
|
|
len = t - s - trapmsglen;
|
|
writelength(s, len);
|
|
|
|
len = t - varlen - varlensz;
|
|
writelength(varlen, len); /* pdu length */
|
|
|
|
len = t - pdulen - pdulensz;
|
|
writelength(pdulen, len); /* pdu length */
|
|
|
|
len = t - buffer - baselensz - 1;
|
|
writelength(buffer + 1, len); /* length of trap */
|
|
|
|
return t - buffer;
|
|
}
|
|
|
|
|
|
int
|
|
sendtrap_v2_0(fd, community, msg, msglen)
|
|
int fd;
|
|
char *community, *msg;
|
|
int msglen;
|
|
{
|
|
|
|
u_char buffer[1500];
|
|
int n;
|
|
|
|
n = maketrap_v2(community, buffer, sizeof(buffer),
|
|
(u_char *)msg, msglen);
|
|
if (n > 0) {
|
|
return send(fd, buffer, n, 0);
|
|
}
|
|
|
|
return 0;
|
|
}
|