1258331Smarkj#include "ipf.h" 2266991Skevlo#include "netinet/ipl.h" 3258331Smarkj#include "ipmon.h" 4258331Smarkj#include <ctype.h> 5258331Smarkj 6258331Smarkj#define IPF_ENTERPRISE 9932 7258331Smarkj/* 8258331Smarkj * Enterprise number OID: 9258331Smarkj * 1.3.6.1.4.1.9932 10258331Smarkj */ 11258331Smarkjstatic u_char ipf_enterprise[] = { 6, 7, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c }; 12258331Smarkjstatic u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 }; 13258331Smarkjstatic u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 }; 14258331Smarkj 15258331Smarkjstatic int writeint __P((u_char *, int)); 16258331Smarkjstatic int writelength __P((u_char *, u_int)); 17258331Smarkjstatic int maketrap_v1 __P((char *, u_char *, int, u_char *, int, u_32_t, 18258331Smarkj time_t)); 19258331Smarkjstatic void snmpv1_destroy __P((void *)); 20258331Smarkjstatic void *snmpv1_dup __P((void *)); 21258331Smarkjstatic int snmpv1_match __P((void *, void *)); 22258331Smarkjstatic void *snmpv1_parse __P((char **)); 23258331Smarkjstatic void snmpv1_print __P((void *)); 24258331Smarkjstatic int snmpv1_send __P((void *, ipmon_msg_t *)); 25258331Smarkj 26258331Smarkjtypedef struct snmpv1_opts_s { 27258331Smarkj char *community; 28258331Smarkj int fd; 29258331Smarkj int v6; 30258331Smarkj int ref; 31258331Smarkj#ifdef USE_INET6 32258331Smarkj struct sockaddr_in6 sin6; 33258331Smarkj#endif 34258331Smarkj struct sockaddr_in sin; 35258331Smarkj} snmpv1_opts_t; 36258331Smarkj 37258331Smarkjipmon_saver_t snmpv1saver = { 38258331Smarkj "snmpv1", 39258331Smarkj snmpv1_destroy, 40258331Smarkj snmpv1_dup, /* dup */ 41258331Smarkj snmpv1_match, /* match */ 42258331Smarkj snmpv1_parse, 43258331Smarkj snmpv1_print, 44258331Smarkj snmpv1_send 45258331Smarkj}; 46258331Smarkj 47258331Smarkj 48258331Smarkjstatic int 49258331Smarkjsnmpv1_match(ctx1, ctx2) 50258331Smarkj void *ctx1, *ctx2; 51258331Smarkj{ 52258331Smarkj snmpv1_opts_t *s1 = ctx1, *s2 = ctx2; 53258331Smarkj 54258331Smarkj if (s1->v6 != s2->v6) 55258331Smarkj return 1; 56258331Smarkj 57258331Smarkj if (strcmp(s1->community, s2->community)) 58258331Smarkj return 1; 59258331Smarkj 60258331Smarkj#ifdef USE_INET6 61258331Smarkj if (s1->v6 == 1) { 62258331Smarkj if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6))) 63258331Smarkj return 1; 64258331Smarkj } else 65258331Smarkj#endif 66258331Smarkj { 67258331Smarkj if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin))) 68258331Smarkj return 1; 69266991Skevlo } 70266991Skevlo 71258331Smarkj return 0; 72258331Smarkj} 73258331Smarkj 74258331Smarkj 75266991Skevlostatic void * 76266991Skevlosnmpv1_dup(ctx) 77266991Skevlo void *ctx; 78266991Skevlo{ 79266991Skevlo snmpv1_opts_t *s = ctx; 80268737Shselasky 81266991Skevlo s->ref++; 82266991Skevlo return s; 83266991Skevlo} 84266991Skevlo 85258331Smarkj 86258331Smarkjstatic void 87258331Smarkjsnmpv1_print(ctx) 88258331Smarkj void *ctx; 89258331Smarkj{ 90258331Smarkj snmpv1_opts_t *snmpv1 = ctx; 91258331Smarkj 92258331Smarkj printf("%s ", snmpv1->community); 93258331Smarkj#ifdef USE_INET6 94258331Smarkj if (snmpv1->v6 == 1) { 95258331Smarkj char buf[80]; 96258331Smarkj 97258331Smarkj printf("%s", inet_ntop(AF_INET6, &snmpv1->sin6.sin6_addr, buf, 98258331Smarkj sizeof(snmpv1->sin6.sin6_addr))); 99258331Smarkj } else 100258331Smarkj#endif 101258331Smarkj { 102258331Smarkj printf("%s", inet_ntoa(snmpv1->sin.sin_addr)); 103258331Smarkj } 104258331Smarkj} 105258331Smarkj 106258331Smarkj 107258331Smarkjstatic void * 108258331Smarkjsnmpv1_parse(char **strings) 109258331Smarkj{ 110258331Smarkj snmpv1_opts_t *ctx; 111258331Smarkj int result; 112266991Skevlo char *str; 113258331Smarkj char *s; 114258331Smarkj 115258331Smarkj if (strings[0] == NULL || strings[0][0] == '\0') 116266991Skevlo return NULL; 117258331Smarkj 118258331Smarkj if (strchr(*strings, ' ') == NULL) 119258331Smarkj return NULL; 120258331Smarkj 121258331Smarkj str = strdup(*strings); 122258331Smarkj 123258331Smarkj ctx = calloc(1, sizeof(*ctx)); 124258331Smarkj if (ctx == NULL) 125258331Smarkj return NULL; 126268219Shselasky 127268219Shselasky ctx->fd = -1; 128266991Skevlo 129258331Smarkj s = strchr(str, ' '); 130258331Smarkj *s++ = '\0'; 131258331Smarkj ctx->community = str; 132258331Smarkj 133258331Smarkj while (ISSPACE(*s)) 134258331Smarkj s++; 135258331Smarkj if (!*s) { 136258331Smarkj free(str); 137258331Smarkj free(ctx); 138258331Smarkj return NULL; 139258331Smarkj } 140258331Smarkj 141258331Smarkj#ifdef USE_INET6 142258331Smarkj if (strchr(s, ':') == NULL) { 143258331Smarkj result = inet_pton(AF_INET, s, &ctx->sin.sin_addr); 144258331Smarkj if (result == 1) { 145258331Smarkj ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); 146258331Smarkj if (ctx->fd >= 0) { 147266991Skevlo ctx->sin.sin_family = AF_INET; 148258331Smarkj ctx->sin.sin_port = htons(162); 149258331Smarkj if (connect(ctx->fd, 150258331Smarkj (struct sockaddr *)&ctx->sin, 151258331Smarkj sizeof(ctx->sin)) != 0) { 152258331Smarkj snmpv1_destroy(ctx); 153258331Smarkj return NULL; 154258331Smarkj } 155258331Smarkj } 156268737Shselasky } 157258331Smarkj } else { 158258331Smarkj result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr); 159258331Smarkj if (result == 1) { 160258331Smarkj ctx->v6 = 1; 161258331Smarkj ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0); 162258331Smarkj if (ctx->fd >= 0) { 163258331Smarkj ctx->sin6.sin6_family = AF_INET6; 164258331Smarkj ctx->sin6.sin6_port = htons(162); 165258331Smarkj if (connect(ctx->fd, 166258331Smarkj (struct sockaddr *)&ctx->sin6, 167258331Smarkj sizeof(ctx->sin6)) != 0) { 168258331Smarkj snmpv1_destroy(ctx); 169258331Smarkj return NULL; 170258331Smarkj } 171258331Smarkj } 172258331Smarkj } 173258331Smarkj } 174258331Smarkj#else 175258331Smarkj result = inet_aton(s, &ctx->sin.sin_addr); 176258331Smarkj if (result == 1) { 177258331Smarkj ctx->fd = socket(AF_INET, SOCK_DGRAM, 0); 178258331Smarkj if (ctx->fd >= 0) { 179258331Smarkj ctx->sin.sin_family = AF_INET; 180258331Smarkj ctx->sin.sin_port = htons(162); 181258331Smarkj if (connect(ctx->fd, (struct sockaddr *)&ctx->sin, 182258331Smarkj sizeof(ctx->sin)) != 0) { 183258331Smarkj snmpv1_destroy(ctx); 184258331Smarkj return NULL; 185258331Smarkj } 186258331Smarkj } 187258331Smarkj } 188258331Smarkj#endif 189258331Smarkj 190258331Smarkj if (result != 1) { 191258331Smarkj free(str); 192258331Smarkj free(ctx); 193258331Smarkj return NULL; 194258331Smarkj } 195258331Smarkj 196258331Smarkj ctx->ref = 1; 197258331Smarkj 198258331Smarkj return ctx; 199258331Smarkj} 200258331Smarkj 201258331Smarkj 202258331Smarkjstatic void 203258331Smarkjsnmpv1_destroy(ctx) 204258331Smarkj void *ctx; 205258331Smarkj{ 206258331Smarkj snmpv1_opts_t *v1 = ctx; 207258331Smarkj 208258331Smarkj v1->ref--; 209258331Smarkj if (v1->ref > 0) 210258331Smarkj return; 211258331Smarkj 212258331Smarkj if (v1->community) 213258331Smarkj free(v1->community); 214258331Smarkj if (v1->fd >= 0) 215258331Smarkj close(v1->fd); 216258331Smarkj free(v1); 217258331Smarkj} 218258331Smarkj 219258331Smarkj 220258331Smarkjstatic int 221258331Smarkjsnmpv1_send(ctx, msg) 222258331Smarkj void *ctx; 223258331Smarkj ipmon_msg_t *msg; 224258331Smarkj{ 225258331Smarkj snmpv1_opts_t *v1 = ctx; 226258331Smarkj 227258331Smarkj return sendtrap_v1_0(v1->fd, v1->community, 228258331Smarkj msg->imm_msg, msg->imm_msglen, msg->imm_when); 229258331Smarkj} 230258331Smarkj 231258331Smarkjstatic char def_community[] = "public"; /* ublic */ 232258331Smarkj 233258331Smarkjstatic int 234258331Smarkjwritelength(buffer, value) 235258331Smarkj u_char *buffer; 236258331Smarkj u_int value; 237258331Smarkj{ 238258331Smarkj u_int n = htonl(value); 239258331Smarkj int len; 240258331Smarkj 241258331Smarkj if (value < 128) { 242266991Skevlo *buffer = value; 243266991Skevlo return 1; 244266991Skevlo } 245266991Skevlo if (value > 0xffffff) 246266991Skevlo len = 4; 247266991Skevlo else if (value > 0xffff) 248266991Skevlo len = 3; 249266991Skevlo else if (value > 0xff) 250266991Skevlo len = 2; 251258331Smarkj else 252258331Smarkj len = 1; 253258331Smarkj 254258331Smarkj *buffer = 0x80 | len; 255258331Smarkj 256258331Smarkj bcopy((u_char *)&n + 4 - len, buffer + 1, len); 257258331Smarkj 258258331Smarkj return len + 1; 259258331Smarkj} 260258331Smarkj 261258331Smarkj 262266991Skevlostatic int 263258331Smarkjwriteint(buffer, value) 264266991Skevlo u_char *buffer; 265258331Smarkj int value; 266258331Smarkj{ 267258331Smarkj u_char *s = buffer; 268258331Smarkj u_int n = value; 269258331Smarkj 270258331Smarkj if (value == 0) { 271258331Smarkj *buffer = 0; 272258331Smarkj return 1; 273258331Smarkj } 274258331Smarkj 275258331Smarkj if (n > 4194304) { 276258331Smarkj *s++ = 0x80 | (n / 4194304); 277258331Smarkj n -= 4194304 * (n / 4194304); 278258331Smarkj } 279258331Smarkj if (n > 32768) { 280258331Smarkj *s++ = 0x80 | (n / 32768); 281258331Smarkj n -= 32768 * (n / 327678); 282258331Smarkj } 283258331Smarkj if (n > 128) { 284258331Smarkj *s++ = 0x80 | (n / 128); 285258331Smarkj n -= (n / 128) * 128; 286258331Smarkj } 287258331Smarkj *s++ = (u_char)n; 288258331Smarkj 289258331Smarkj return s - buffer; 290258331Smarkj} 291258331Smarkj 292258331Smarkj 293258331Smarkj 294258331Smarkj/* 295258331Smarkj * First style of traps is: 296258331Smarkj * 1.3.6.1.4.1.9932.1.1 297258331Smarkj */ 298258331Smarkjstatic int 299258331Smarkjmaketrap_v1(community, buffer, bufsize, msg, msglen, ipaddr, when) 300258331Smarkj char *community; 301258331Smarkj u_char *buffer; 302258331Smarkj int bufsize; 303258331Smarkj u_char *msg; 304258331Smarkj int msglen; 305258331Smarkj u_32_t ipaddr; 306258331Smarkj time_t when; 307258331Smarkj{ 308258331Smarkj u_char *s = buffer, *t, *pdulen, *varlen; 309258331Smarkj int basesize = 73; 310258331Smarkj u_short len; 311258331Smarkj int trapmsglen; 312258331Smarkj int pdulensz; 313258331Smarkj int varlensz; 314258331Smarkj int baselensz; 315258331Smarkj int n; 316258331Smarkj 317258331Smarkj if (community == NULL || *community == '\0') 318258331Smarkj community = def_community; 319258331Smarkj basesize += strlen(community) + msglen; 320258331Smarkj 321258331Smarkj if (basesize + 8 > bufsize) 322258331Smarkj return 0; 323258331Smarkj 324266991Skevlo memset(buffer, 0xff, bufsize); 325258331Smarkj *s++ = 0x30; /* Sequence */ 326258331Smarkj if (basesize - 1 >= 128) { 327258331Smarkj baselensz = 2; 328258331Smarkj basesize++; 329258331Smarkj } else { 330258331Smarkj baselensz = 1; 331258331Smarkj } 332258331Smarkj s += baselensz; 333258331Smarkj *s++ = 0x02; /* Integer32 */ 334258331Smarkj *s++ = 0x01; /* length 1 */ 335258331Smarkj *s++ = 0x00; /* version 1 */ 336258331Smarkj *s++ = 0x04; /* octet string */ 337258331Smarkj *s++ = strlen(community); /* length of "public" */ 338258331Smarkj bcopy(community, s, s[-1]); 339258331Smarkj s += s[-1]; 340258331Smarkj *s++ = 0xA4; /* PDU(4) */ 341258331Smarkj pdulen = s++; 342258331Smarkj if (basesize - (s - buffer) >= 128) { 343258331Smarkj pdulensz = 2; 344258331Smarkj basesize++; 345258331Smarkj s++; 346258331Smarkj } else { 347258331Smarkj pdulensz = 1; 348258331Smarkj } 349258331Smarkj 350258331Smarkj /* enterprise */ 351258331Smarkj bcopy(ipf_enterprise, s, sizeof(ipf_enterprise)); 352258331Smarkj s += sizeof(ipf_enterprise); 353258331Smarkj 354258331Smarkj /* Agent address */ 355258331Smarkj *s++ = 0x40; 356258331Smarkj *s++ = 0x4; 357266991Skevlo bcopy(&ipaddr, s, 4); 358266991Skevlo s += 4; 359258331Smarkj 360258331Smarkj /* Generic Trap code */ 361266991Skevlo *s++ = 0x2; 362258331Smarkj n = writeint(s + 1, 6); 363266991Skevlo if (n == 0) 364258331Smarkj return 0; 365266991Skevlo *s = n; 366258331Smarkj s += n + 1; 367266991Skevlo 368258331Smarkj /* Specific Trap code */ 369258331Smarkj *s++ = 0x2; 370266991Skevlo n = writeint(s + 1, 0); 371266991Skevlo if (n == 0) 372266991Skevlo return 0; 373266991Skevlo *s = n; 374266991Skevlo s += n + 1; 375266991Skevlo 376266991Skevlo /* Time stamp */ 377266991Skevlo *s++ = 0x43; /* TimeTicks */ 378258331Smarkj *s++ = 0x04; /* TimeTicks */ 379266991Skevlo s[0] = when >> 24; 380266991Skevlo s[1] = when >> 16; 381266991Skevlo s[2] = when >> 8; 382266991Skevlo s[3] = when & 0xff; 383266991Skevlo s += 4; 384266991Skevlo 385258331Smarkj /* 386266991Skevlo * The trap0 message is "ipfilter_version" followed by the message 387258331Smarkj */ 388258331Smarkj *s++ = 0x30; 389266991Skevlo varlen = s; 390266991Skevlo if (basesize - (s - buffer) >= 128) { 391266991Skevlo varlensz = 2; 392258331Smarkj basesize++; 393258331Smarkj } else { 394258331Smarkj varlensz = 1; 395258331Smarkj } 396258331Smarkj s += varlensz; 397258331Smarkj 398258331Smarkj *s++ = 0x30; 399258331Smarkj t = s + 1; 400258331Smarkj bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1)); 401266991Skevlo t += sizeof(ipf_trap0_1); 402266991Skevlo 403258331Smarkj *t++ = 0x2; /* Integer */ 404266991Skevlo n = writeint(t + 1, IPFILTER_VERSION); 405258331Smarkj *t = n; 406258331Smarkj t += n + 1; 407258331Smarkj 408258331Smarkj len = t - s - 1; 409258331Smarkj writelength(s, len); 410258331Smarkj 411258331Smarkj s = t; 412258331Smarkj *s++ = 0x30; 413258331Smarkj if (basesize - (s - buffer) >= 128) { 414258331Smarkj trapmsglen = 2; 415258331Smarkj basesize++; 416258331Smarkj } else { 417258331Smarkj trapmsglen = 1; 418258331Smarkj } 419258331Smarkj t = s + trapmsglen; 420258331Smarkj bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2)); 421258331Smarkj t += sizeof(ipf_trap0_2); 422258331Smarkj 423258331Smarkj *t++ = 0x4; /* Octet string */ 424258331Smarkj n = writelength(t, msglen); 425258331Smarkj t += n; 426258331Smarkj bcopy(msg, t, msglen); 427258331Smarkj t += msglen; 428258331Smarkj 429258331Smarkj len = t - s - trapmsglen; 430258331Smarkj writelength(s, len); 431258331Smarkj 432258331Smarkj len = t - varlen - varlensz; 433258331Smarkj writelength(varlen, len); /* pdu length */ 434258331Smarkj 435258331Smarkj len = t - pdulen - pdulensz; 436258331Smarkj writelength(pdulen, len); /* pdu length */ 437258331Smarkj 438258331Smarkj len = t - buffer - baselensz - 1; 439266991Skevlo writelength(buffer + 1, len); /* length of trap */ 440258331Smarkj 441258331Smarkj return t - buffer; 442258331Smarkj} 443258331Smarkj 444258331Smarkj 445258331Smarkjint 446258331Smarkjsendtrap_v1_0(fd, community, msg, msglen, when) 447258331Smarkj int fd; 448258331Smarkj char *community, *msg; 449258331Smarkj int msglen; 450258331Smarkj time_t when; 451258331Smarkj{ 452258331Smarkj 453258331Smarkj u_char buffer[1500]; 454258331Smarkj int n; 455258331Smarkj 456258331Smarkj n = maketrap_v1(community, buffer, sizeof(buffer), 457258331Smarkj (u_char *)msg, msglen, 0, when); 458258331Smarkj if (n > 0) { 459258331Smarkj return send(fd, buffer, n, 0); 460258331Smarkj } 461258331Smarkj 462258331Smarkj return 0; 463258331Smarkj} 464258331Smarkj