]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - contrib/ipfilter/lib/save_v2trap.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / contrib / ipfilter / lib / save_v2trap.c
1 #include "ipf.h"
2 #include "netinet/ipl.h"
3 #include "ipmon.h"
4 #include <ctype.h>
5
6 static u_char sysuptime[] = { 6, 8, 0x2b, 6, 1, 2, 1, 1, 3, 0 };
7 /*
8  * Enterprise number OID:
9  * 1.3.6.1.4.1.9932
10  */
11 static u_char ipf_trap0_1[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 1 };
12 static u_char ipf_trap0_2[] = { 6, 10, 0x2b, 6, 1, 4, 1, 0xcd, 0x4c, 1, 1, 2 };
13
14 static int writeint __P((u_char *, int));
15 static int writelength __P((u_char *, u_int));
16 static int maketrap_v2 __P((char *, u_char *, int, u_char *, int));
17 static void snmpv2_destroy __P((void *));
18 static void *snmpv2_dup __P((void *));
19 static int snmpv2_match __P((void *, void *));
20 static void *snmpv2_parse __P((char **));
21 static void snmpv2_print __P((void *));
22 static int snmpv2_send __P((void *, ipmon_msg_t *));
23
24
25 int sendtrap_v2_0 __P((int, char *, char *, int));
26
27 static char def_community[] = "public"; /* ublic */
28
29 typedef struct snmpv2_opts_s {
30         char                    *community;
31         char                    *server;
32         int                     fd;
33         int                     v6;
34         int                     ref;
35 #ifdef USE_INET6
36         struct sockaddr_in6     sin6;
37 #endif
38         struct sockaddr_in      sin;
39 } snmpv2_opts_t;
40
41 ipmon_saver_t snmpv2saver = {
42         "snmpv2",
43         snmpv2_destroy,
44         snmpv2_dup,             /* dup */
45         snmpv2_match,           /* match */
46         snmpv2_parse,
47         snmpv2_print,
48         snmpv2_send
49 };
50
51
52 static int
53 snmpv2_match(ctx1, ctx2)
54         void *ctx1, *ctx2;
55 {
56         snmpv2_opts_t *s1 = ctx1, *s2 = ctx2;
57
58         if (s1->v6 != s2->v6)
59                 return 1;
60
61         if (strcmp(s1->community, s2->community))
62                 return 1;
63
64 #ifdef USE_INET6
65         if (s1->v6 == 1) {
66                 if (memcmp(&s1->sin6, &s2->sin6, sizeof(s1->sin6)))
67                         return 1;
68         } else
69 #endif
70         {
71                 if (memcmp(&s1->sin, &s2->sin, sizeof(s1->sin)))
72                         return 1;
73         }
74
75         return 0;
76 }
77
78
79 static void *
80 snmpv2_dup(ctx)
81         void *ctx;
82 {
83         snmpv2_opts_t *s = ctx;
84
85         s->ref++;
86         return s;
87 }
88
89
90 static void
91 snmpv2_print(ctx)
92         void *ctx;
93 {
94         snmpv2_opts_t *snmpv2 = ctx;
95
96         printf("%s ", snmpv2->community);
97 #ifdef USE_INET6
98         if (snmpv2->v6 == 1) {
99                 char buf[80];
100
101                 printf("%s", inet_ntop(AF_INET6, &snmpv2->sin6.sin6_addr, buf,
102                                        sizeof(snmpv2->sin6.sin6_addr)));
103         } else
104 #endif
105         {
106                 printf("%s", inet_ntoa(snmpv2->sin.sin_addr));
107         }
108 }
109
110
111 static void *
112 snmpv2_parse(char **strings)
113 {
114         snmpv2_opts_t *ctx;
115         int result;
116         char *str;
117         char *s;
118
119         if (strings[0] == NULL || strings[0][0] == '\0')
120                 return NULL;
121         if (strchr(*strings, ' ') == NULL)
122                 return NULL;
123
124         str = strdup(*strings);
125
126         ctx = calloc(1, sizeof(*ctx));
127         if (ctx == NULL)
128                 return NULL;
129
130         ctx->fd = -1;
131
132         s = strchr(str, ' ');
133         *s++ = '\0';
134         ctx->community = str;
135
136         while (ISSPACE(*s))
137                 s++;
138         if (!*s) {
139                 free(str);
140                 free(ctx);
141                 return NULL;
142         }
143
144 #ifdef USE_INET6
145         if (strchr(s, ':') == NULL) {
146                 result = inet_pton(AF_INET, s, &ctx->sin.sin_addr);
147                 if (result == 1) {
148                         ctx->fd = socket(AF_INET, SOCK_DGRAM, 0);
149                         if (ctx->fd >= 0) {
150                                 ctx->sin.sin_family = AF_INET;
151                                 ctx->sin.sin_port = htons(162);
152                                 if (connect(ctx->fd,
153                                             (struct sockaddr *)&ctx->sin,
154                                             sizeof(ctx->sin)) != 0) {
155                                                 snmpv2_destroy(ctx);
156                                                 return NULL;
157                                 }
158                         }
159                 }
160         } else {
161                 result = inet_pton(AF_INET6, s, &ctx->sin6.sin6_addr);
162                 if (result == 1) {
163                         ctx->v6 = 1;
164                         ctx->fd = socket(AF_INET6, SOCK_DGRAM, 0);
165                         if (ctx->fd >= 0) {
166                                 ctx->sin6.sin6_family = AF_INET6;
167                                 ctx->sin6.sin6_port = htons(162);
168                                 if (connect(ctx->fd,
169                                             (struct sockaddr *)&ctx->sin6,
170                                             sizeof(ctx->sin6)) != 0) {
171                                                 snmpv2_destroy(ctx);
172                                                 return NULL;
173                                 }
174                         }
175                 }
176         }
177 #else
178         result = inet_aton(s, &ctx->sin.sin_addr);
179         if (result == 1) {
180                 ctx->fd = socket(AF_INET, SOCK_DGRAM, 0);
181                 if (ctx->fd >= 0) {
182                         ctx->sin.sin_family = AF_INET;
183                         ctx->sin.sin_port = htons(162);
184                         if (connect(ctx->fd, &ctx->sin,
185                                     sizeof(ctx->sin)) != 0) {
186                                         snmpv2_destroy(ctx);
187                                         return NULL;
188                         }
189                 }
190         }
191 #endif
192
193         if (result != 1) {
194                 free(str);
195                 free(ctx);
196                 return NULL;
197         }
198
199         ctx->ref = 1;
200
201         return ctx;
202 }
203
204
205 static void
206 snmpv2_destroy(ctx)
207         void *ctx;
208 {
209         snmpv2_opts_t *v2 = ctx;
210
211         v2->ref--;
212         if (v2->ref > 0)
213                 return;
214
215         if (v2->community)
216                 free(v2->community);
217         if (v2->fd >= 0)
218                 close(v2->fd);
219         free(v2);
220 }
221
222
223 static int
224 snmpv2_send(ctx, msg)
225         void *ctx;
226         ipmon_msg_t *msg;
227 {
228         snmpv2_opts_t *v2 = ctx;
229
230         return sendtrap_v2_0(v2->fd, v2->community,
231                              msg->imm_msg, msg->imm_msglen);
232 }
233 static int
234 writelength(buffer, value)
235         u_char *buffer;
236         u_int value;
237 {
238         u_int n = htonl(value);
239         int len;
240
241         if (value < 128) {
242                 *buffer = value;
243                 return 1;
244         }
245         if (value > 0xffffff)
246                 len = 4;
247         else if (value > 0xffff)
248                 len = 3;
249         else if (value > 0xff)
250                 len = 2;
251         else
252                 len = 1;
253
254         *buffer = 0x80 | len;
255
256         bcopy((u_char *)&n + 4 - len, buffer + 1, len);
257
258         return len + 1;
259 }
260
261
262 static int
263 writeint(buffer, value)
264         u_char *buffer;
265         int value;
266 {
267         u_char *s = buffer;
268         u_int n = value;
269
270         if (value == 0) {
271                 *buffer = 0;
272                 return 1;
273         }
274
275         if (n >  4194304) {
276                 *s++ = 0x80 | (n / 4194304);
277                 n -= 4194304 * (n / 4194304);
278         }
279         if (n >  32768) {
280                 *s++ = 0x80 | (n / 32768);
281                 n -= 32768 * (n / 327678);
282         }
283         if (n > 128) {
284                 *s++ = 0x80 | (n / 128);
285                 n -= (n / 128) * 128;
286         }
287         *s++ = (u_char)n;
288
289         return s - buffer;
290 }
291
292
293
294 /*
295  * First style of traps is:
296  * 1.3.6.1.4.1.9932.1.1
297  */
298 static int
299 maketrap_v2(community, buffer, bufsize, msg, msglen)
300         char *community;
301         u_char *buffer;
302         int bufsize;
303         u_char *msg;
304         int msglen;
305 {
306         u_char *s = buffer, *t, *pdulen;
307         u_char *varlen;
308         int basesize = 77;
309         u_short len;
310         int trapmsglen;
311         int pdulensz;
312         int varlensz;
313         int baselensz;
314         int n;
315
316         if (community == NULL || *community == '\0')
317                 community = def_community;
318         basesize += strlen(community) + msglen;
319
320         if (basesize + 8 > bufsize)
321                 return 0;
322
323         memset(buffer, 0xff, bufsize);
324         *s++ = 0x30;            /* Sequence */
325
326         if (basesize - 1 >= 128) {
327                 baselensz = 2;
328                 basesize++;
329         } else {
330                 baselensz = 1;
331         }
332         s += baselensz;
333         *s++ = 0x02;            /* Integer32 */
334         *s++ = 0x01;            /* length 1 */
335         *s++ = 0x01;            /* version 2 */
336         *s++ = 0x04;            /* octet string */
337         *s++ = strlen(community);               /* length of "public" */
338         bcopy(community, s, s[-1]);
339         s += s[-1];
340         *s++ = 0xA7;            /* PDU(7) */
341         pdulen = s++;
342         if (basesize - (s - buffer) >= 128) {
343                 pdulensz = 2;
344                 basesize++;
345                 s++;
346         } else {
347                 pdulensz = 1;
348         }
349         /* request id */
350         *s++ = 0x2;     /* integer */
351         *s++ = 0x4;     /* len 4 */
352         *s++ = 0x0;     /* noError */
353         *s++ = 0x0;     /* noError */
354         *s++ = 0x0;     /* noError */
355         *s++ = 0x0;     /* noError */
356
357         /* error status */
358         *s++ = 0x2;     /* integer */
359         *s++ = 0x1;     /* len 1 */
360         *s++ = 0x0;     /* noError */
361
362         /* error-index */
363         *s++ = 0x2;     /* integer */
364         *s++ = 0x1;     /* len 1 */
365         *s++ = 0x0;     /* noError */
366
367         *s++ = 0x30;    /* sequence */
368         varlen = s++;
369         if (basesize - (s - buffer) >= 128) {
370                 varlensz = 2;
371                 basesize++;
372                 s++;
373         } else {
374                 varlensz = 1;
375         }
376
377         *s++ = 0x30;    /* sequence */
378         *s++ = sizeof(sysuptime) + 6;
379
380         bcopy(sysuptime, s, sizeof(sysuptime));
381         s += sizeof(sysuptime);
382
383         *s++ = 0x43;    /* Timestamp */
384         *s++ = 0x04;    /* TimeTicks */
385         *s++ = 0x0;
386         *s++ = 0x0;
387         *s++ = 0x0;
388         *s++ = 0x0;
389
390         *s++ = 0x30;
391         t = s + 1;
392         bcopy(ipf_trap0_1, t, sizeof(ipf_trap0_1));
393         t += sizeof(ipf_trap0_1);
394
395         *t++ = 0x2;             /* Integer */
396         n = writeint(t + 1, IPFILTER_VERSION);
397         *t = n;
398         t += n + 1;
399
400         len = t - s - 1;
401         writelength(s, len);
402
403         s = t;
404         *s++ = 0x30;
405         if (msglen < 128) {
406                 if (msglen + 1 + 1 + sizeof(ipf_trap0_2) >= 128)
407                         trapmsglen = 2;
408                 else
409                         trapmsglen = 1;
410         } else {
411                 if (msglen + 2 + 1 + sizeof(ipf_trap0_2) >= 128)
412                         trapmsglen = 2;
413                 else
414                         trapmsglen = 1;
415         }
416         t = s + trapmsglen;
417         bcopy(ipf_trap0_2, t, sizeof(ipf_trap0_2));
418         t += sizeof(ipf_trap0_2);
419
420         *t++ = 0x4;             /* Octet string */
421         n = writelength(t, msglen);
422         t += n;
423         bcopy(msg, t, msglen);
424         t += msglen;
425
426         len = t - s - trapmsglen;
427         writelength(s, len);
428
429         len = t - varlen - varlensz;
430         writelength(varlen, len);               /* pdu length */
431
432         len = t - pdulen - pdulensz;
433         writelength(pdulen, len);               /* pdu length */
434
435         len = t - buffer - baselensz - 1;
436         writelength(buffer + 1, len);   /* length of trap */
437
438         return t - buffer;
439 }
440
441
442 int
443 sendtrap_v2_0(fd, community, msg, msglen)
444         int fd;
445         char *community, *msg;
446         int msglen;
447 {
448
449         u_char buffer[1500];
450         int n;
451
452         n = maketrap_v2(community, buffer, sizeof(buffer),
453                         (u_char *)msg, msglen);
454         if (n > 0) {
455                 return send(fd, buffer, n, 0);
456         }
457
458         return 0;
459 }