added files
[bcm963xx.git] / userapps / opensource / net-snmp / apps / snmpvacm.c
1 /*
2  * snmpvacm.c - send snmp SET requests to a network entity to change the
3  *             vacm database
4  *
5  */
6 #include <net-snmp/net-snmp-config.h>
7
8 #if HAVE_STDLIB_H
9 #include <stdlib.h>
10 #endif
11 #if HAVE_UNISTD_H
12 #include <unistd.h>
13 #endif
14 #if HAVE_STRING_H
15 #include <string.h>
16 #else
17 #include <strings.h>
18 #endif
19 #include <sys/types.h>
20 #if HAVE_NETINET_IN_H
21 #include <netinet/in.h>
22 #endif
23 #include <stdio.h>
24 #include <ctype.h>
25 #if TIME_WITH_SYS_TIME
26 # ifdef WIN32
27 #  include <sys/timeb.h>
28 # else
29 #  include <sys/time.h>
30 # endif
31 # include <time.h>
32 #else
33 # if HAVE_SYS_TIME_H
34 #  include <sys/time.h>
35 # else
36 #  include <time.h>
37 # endif
38 #endif
39 #if HAVE_SYS_SELECT_H
40 #include <sys/select.h>
41 #endif
42 #if HAVE_WINSOCK_H
43 #include <winsock.h>
44 #endif
45 #if HAVE_NETDB_H
46 #include <netdb.h>
47 #endif
48 #if HAVE_ARPA_INET_H
49 #include <arpa/inet.h>
50 #endif
51
52 #include <net-snmp/net-snmp-includes.h>
53
54 int             main(int, char **);
55
56 #define CMD_CREATESEC2GROUP_NAME    "createSec2Group"
57 #define CMD_CREATESEC2GROUP         1
58 #define CMD_DELETESEC2GROUP_NAME    "deleteSec2Group"
59 #define CMD_DELETESEC2GROUP         2
60 #define CMD_CREATEACCESS_NAME           "createAccess"
61 #define CMD_CREATEACCESS                3
62 #define CMD_DELETEACCESS_NAME           "deleteAccess"
63 #define CMD_DELETEACCESS                4
64 #define CMD_CREATEVIEW_NAME             "createView"
65 #define CMD_CREATEVIEW                  5
66 #define CMD_DELETEVIEW_NAME             "deleteView"
67 #define CMD_DELETEVIEW                  6
68
69 #define CMD_NUM    6
70
71 static const char *successNotes[CMD_NUM] = {
72     "Sec2group successfully created.",
73     "Sec2group successfully deleted.",
74     "Access successfully created.",
75     "Access successfully deleted.",
76     "View successfully created.",
77     "View successfully deleted."
78 };
79
80 #define                   SEC2GROUP_OID_LEN     11
81 #define                   ACCESS_OID_LEN        11
82 #define                   VIEW_OID_LEN          12
83
84 static oid      vacmGroupName[MAX_OID_LEN] =
85     { 1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 3 },
86     vacmSec2GroupStorageType[MAX_OID_LEN] = {
87 1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 4}, vacmSec2GroupStatus[MAX_OID_LEN] = {
88 1, 3, 6, 1, 6, 3, 16, 1, 2, 1, 5}, vacmAccessContextMatch[MAX_OID_LEN] = {
89 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 4}, vacmAccessReadViewName[MAX_OID_LEN] = {
90 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 5}, vacmAccessWriteViewName[MAX_OID_LEN] = {
91 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 6}, vacmAccessNotifyViewName[MAX_OID_LEN] = {
92 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 7}, vacmAccessStorageType[MAX_OID_LEN] = {
93 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 8}, vacmAccessStatus[MAX_OID_LEN] = {
94 1, 3, 6, 1, 6, 3, 16, 1, 4, 1, 9}, vacmViewTreeFamilyMask[MAX_OID_LEN] = {
95 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 3}, vacmViewTreeFamilyType[MAX_OID_LEN] = {
96 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 4},
97     vacmViewTreeFamilyStorageType[MAX_OID_LEN] = {
98 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 5},
99     vacmViewTreeFamilyStatus[MAX_OID_LEN] = {
100 1, 3, 6, 1, 6, 3, 16, 1, 5, 2, 1, 6}
101
102 ;
103
104 int             viewTreeFamilyType = 1;
105
106 void
107 usage(void)
108 {
109     fprintf(stderr, "Usage: snmpvacm ");
110     snmp_parse_args_usage(stderr);
111     fprintf(stderr, " COMMAND\n\n");
112     snmp_parse_args_descriptions(stderr);
113     fprintf(stderr, "\nsnmpvacm commands:\n");
114     fprintf(stderr,
115             "  createAccess  GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL CONTEXTMATCH READVIEWNAME WRITEVIEWNAME NOTIFYVIEWNAME\n");
116     fprintf(stderr,
117             "  deleteAccess  GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL\n");
118     fprintf(stderr, "  createSec2Group  MODEL SECURITYNAME  GROUPNAME\n");
119     fprintf(stderr, "  deleteSec2Group  MODEL SECURITYNAME\n");
120     fprintf(stderr, "  createView  [-Ce] NAME SUBTREE MASK\n");
121     fprintf(stderr, "  deleteView  NAME SUBTREE\n");
122 }
123
124
125 void
126 access_oid(oid * it, size_t * len, const char *groupName,
127            const char *prefix, int model, int level)
128 {
129     int             i;
130
131     int             itIndex = ACCESS_OID_LEN;
132
133     *len = itIndex + 4 + +strlen(groupName);
134
135     it[itIndex++] = strlen(groupName);
136     for (i = 0; i < (int) strlen(groupName); i++)
137         it[itIndex++] = groupName[i];
138
139     if (prefix) {
140         *len += strlen(prefix);
141         it[itIndex++] = strlen(prefix);
142         for (i = 0; i < (int) strlen(prefix); i++)
143             it[itIndex++] = prefix[i];
144     } else
145         it[itIndex++] = 0;
146
147     it[itIndex++] = model;
148     it[itIndex++] = level;
149 }
150
151
152 void
153 sec2group_oid(oid * it, size_t * len, int model, const char *name)
154 {
155     int             i;
156
157     int             itIndex = SEC2GROUP_OID_LEN;
158
159     *len = itIndex + 2 + strlen(name);
160
161     it[itIndex++] = model;
162
163     it[itIndex++] = strlen(name);
164     for (i = 0; i < (int) strlen(name); i++)
165         it[itIndex++] = name[i];
166 }
167
168 void
169 view_oid(oid * it, size_t * len, const char *viewName, char *viewSubtree)
170 {
171     int             i;
172     oid             c_oid[SPRINT_MAX_LEN];
173     size_t          c_oid_length = SPRINT_MAX_LEN;
174
175     int             itIndex = VIEW_OID_LEN;
176
177     if (!read_objid(viewSubtree, c_oid, &c_oid_length)) {
178         printf("Error parsing subtree\n");
179         exit(1);
180     }
181
182     *len = itIndex + 2 + strlen(viewName) + c_oid_length;
183
184     it[itIndex++] = strlen(viewName);
185     for (i = 0; i < (int) strlen(viewName); i++)
186         it[itIndex++] = viewName[i];
187
188     
189     it[itIndex++] = c_oid_length;
190     for (i = 0; i < (int) c_oid_length; i++)
191         it[itIndex++] = c_oid[i];
192
193     /*
194      * sprint_objid(c_oid, it, *len); 
195      */
196 }
197
198 static void
199 optProc(int argc, char *const *argv, int opt)
200 {
201     switch (opt) {
202     case 'C':
203         while (*optarg) {
204             switch (*optarg++) {
205             case 'e':
206                 viewTreeFamilyType = 2;
207                 break;
208
209             default:
210                 fprintf(stderr,
211                         "Unknown flag passed to -C: %c\n", optarg[-1]);
212                 exit(1);
213             }
214         }
215         break;
216     }
217 }
218
219
220 int
221 main(int argc, char *argv[])
222 {
223     netsnmp_session session, *ss;
224     netsnmp_pdu    *pdu = NULL, *response = NULL;
225 #ifdef notused
226     netsnmp_variable_list *vars;
227 #endif
228
229     int             arg;
230 #ifdef notused
231     int             count;
232     int             current_name = 0;
233     int             current_type = 0;
234     int             current_value = 0;
235     char           *names[128];
236     char            types[128];
237     char           *values[128];
238     oid             name[MAX_OID_LEN];
239 #endif
240     size_t          name_length;
241     int             status;
242     int             exitval = 0;
243     int             command = 0;
244     long            longvar;
245     int             secModel, secLevel, contextMatch, val, i = 0;
246     char           *mask, *groupName, *prefix;
247     u_char          viewMask[VACMSTRINGLEN];
248
249
250     /*
251      * get the common command line arguments 
252      */
253     switch (arg = snmp_parse_args(argc, argv, &session, "C:", optProc)) {
254     case -2:
255         exit(0);
256     case -1:
257         usage();
258         exit(1);
259     default:
260         break;
261     }
262
263
264     SOCK_STARTUP;
265
266     /*
267      * open an SNMP session 
268      */
269     /*
270      * Note:  this wil obtain the engineID needed below 
271      */
272     ss = snmp_open(&session);
273     if (ss == NULL) {
274         /*
275          * diagnose snmp_open errors with the input netsnmp_session pointer 
276          */
277         snmp_sess_perror("snmpvacm", &session);
278         exit(1);
279     }
280
281     /*
282      * create PDU for SET request and add object names and values to request 
283      */
284     pdu = snmp_pdu_create(SNMP_MSG_SET);
285
286     if (arg >= argc) {
287         fprintf(stderr, "Please specify a opreation to perform.\n");
288         usage();
289         exit(1);
290     }
291
292     if (strcmp(argv[arg], CMD_DELETEVIEW_NAME) == 0)
293         /*
294          * deleteView: delete a view
295          *
296          * deleteView NAME SUBTREE
297          *
298          */
299     {
300         if (++arg + 2 != argc) {
301             fprintf(stderr, "You must specify the view to delete\n");
302             usage();
303             exit(1);
304         }
305
306         command = CMD_DELETEVIEW;
307         name_length = VIEW_OID_LEN;
308         view_oid(vacmViewTreeFamilyStatus, &name_length, argv[arg],
309                  argv[arg + 1]);
310         longvar = RS_DESTROY;
311         snmp_pdu_add_variable(pdu, vacmViewTreeFamilyStatus, name_length,
312                               ASN_INTEGER, (u_char *) & longvar,
313                               sizeof(longvar));
314     } else if (strcmp(argv[arg], CMD_CREATEVIEW_NAME) == 0)
315         /*
316          * createView: create a view
317          *
318          * createView NAME SUBTREE MASK
319          *
320          */
321     {
322         if (++arg + 3 > argc) {
323             fprintf(stderr, "You must specify name, subtree and mask\n");
324             usage();
325             exit(1);
326         }
327         command = CMD_CREATEVIEW;
328         name_length = VIEW_OID_LEN;
329         view_oid(vacmViewTreeFamilyStatus, &name_length, argv[arg],
330                  argv[arg + 1]);
331         longvar = RS_CREATEANDGO;
332         snmp_pdu_add_variable(pdu, vacmViewTreeFamilyStatus, name_length,
333                               ASN_INTEGER, (u_char *) & longvar,
334                               sizeof(longvar));
335
336         /*
337          * Mask
338          */
339         mask = argv[arg + 2];
340         for (mask = strtok(mask, ".:"); mask; mask = strtok(NULL, ".:")) {
341             if (i >= sizeof(viewMask)) {
342                 printf("MASK too long\n");
343                 exit(1);
344             }
345             if (sscanf(mask, "%x", &val) == 0) {
346                 printf("invalid MASK\n");
347                 exit(1);
348             }
349             viewMask[i] = val;
350             i++;
351         }
352         view_oid(vacmViewTreeFamilyMask, &name_length, argv[arg],
353                  argv[arg + 1]);
354         snmp_pdu_add_variable(pdu, vacmViewTreeFamilyMask, name_length,
355                               ASN_OCTET_STR, viewMask, i);
356
357         view_oid(vacmViewTreeFamilyType, &name_length, argv[arg],
358                  argv[arg + 1]);
359         snmp_pdu_add_variable(pdu, vacmViewTreeFamilyType, name_length,
360                               ASN_INTEGER, (u_char *) & viewTreeFamilyType,
361                               sizeof(viewTreeFamilyType));
362
363     } else if (strcmp(argv[arg], CMD_DELETESEC2GROUP_NAME) == 0)
364         /*
365          * deleteSec2Group: delete security2group
366          *
367          * deleteSec2Group  MODEL SECURITYNAME
368          *
369          */
370     {
371         if (++arg + 2 != argc) {
372             fprintf(stderr, "You must specify the sec2group to delete\n");
373             usage();
374             exit(1);
375         }
376
377         command = CMD_DELETESEC2GROUP;
378         name_length = SEC2GROUP_OID_LEN;
379         if (sscanf(argv[arg], "%d", &secModel) == 0) {
380             printf("invalid security model\n");
381             usage();
382             exit(1);
383         }
384         sec2group_oid(vacmSec2GroupStatus, &name_length, secModel,
385                       argv[arg + 1]);
386         longvar = RS_DESTROY;
387         snmp_pdu_add_variable(pdu, vacmSec2GroupStatus, name_length,
388                               ASN_INTEGER, (u_char *) & longvar,
389                               sizeof(longvar));
390     } else if (strcmp(argv[arg], CMD_CREATESEC2GROUP_NAME) == 0)
391         /*
392          * createSec2Group: create a security2group
393          *
394          * createSec2Group  MODEL SECURITYNAME GROUPNAME
395          *
396          */
397     {
398         if (++arg + 3 != argc) {
399             fprintf(stderr,
400                     "You must specify model, security name and group name\n");
401             usage();
402             exit(1);
403         }
404
405         command = CMD_CREATESEC2GROUP;
406         name_length = SEC2GROUP_OID_LEN;
407         if (sscanf(argv[arg], "%d", &secModel) == 0) {
408             printf("invalid security model\n");
409             usage();
410             exit(1);
411         }
412         sec2group_oid(vacmSec2GroupStatus, &name_length, secModel,
413                       argv[arg + 1]);
414         longvar = RS_CREATEANDGO;
415         snmp_pdu_add_variable(pdu, vacmSec2GroupStatus, name_length,
416                               ASN_INTEGER, (u_char *) & longvar,
417                               sizeof(longvar));
418         sec2group_oid(vacmGroupName, &name_length, secModel,
419                       argv[arg + 1]);
420         snmp_pdu_add_variable(pdu, vacmGroupName, name_length,
421                               ASN_OCTET_STR, (u_char *) argv[arg + 2],
422                               strlen(argv[arg + 2]));
423     } else if (strcmp(argv[arg], CMD_DELETEACCESS_NAME) == 0)
424         /*
425          * deleteAccess: delete access entry
426          *
427          * deleteAccess  GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL
428          *
429          */
430     {
431         if (++arg + 3 > argc) {
432             fprintf(stderr,
433                     "You must specify the access entry to delete\n");
434             usage();
435             exit(1);
436         }
437
438         command = CMD_DELETEACCESS;
439         name_length = ACCESS_OID_LEN;
440         groupName = argv[arg];
441         if (arg + 4 == argc)
442             prefix = argv[++arg];
443         else
444             prefix = NULL;
445
446         if (sscanf(argv[arg + 1], "%d", &secModel) == 0) {
447             printf("invalid security model\n");
448             usage();
449             exit(1);
450         }
451         if (sscanf(argv[arg + 2], "%d", &secLevel) == 0) {
452             printf("invalid security level\n");
453             usage();
454             exit(1);
455         }
456         access_oid(vacmAccessStatus, &name_length, groupName, prefix,
457                    secModel, secLevel);
458         longvar = RS_DESTROY;
459         snmp_pdu_add_variable(pdu, vacmAccessStatus, name_length,
460                               ASN_INTEGER, (u_char *) & longvar,
461                               sizeof(longvar));
462     } else if (strcmp(argv[arg], CMD_CREATEACCESS_NAME) == 0)
463         /*
464          * createAccess: create access entry
465          *
466          * createAccess  GROUPNAME [CONTEXTPREFIX] SECURITYMODEL SECURITYLEVEL CONTEXTMATCH READVIEWNAME WRITEVIEWNAME NOTIFYVIEWNAME
467          *
468          */
469     {
470         if (++arg + 7 > argc) {
471             fprintf(stderr,
472                     "You must specify the access entry to create\n");
473             usage();
474             exit(1);
475         }
476
477         command = CMD_CREATEACCESS;
478         name_length = ACCESS_OID_LEN;
479         groupName = argv[arg];
480         if (arg + 8 == argc)
481             prefix = argv[++arg];
482         else
483             prefix = NULL;
484
485         if (sscanf(argv[arg + 1], "%d", &secModel) == 0) {
486             printf("invalid security model\n");
487             usage();
488             exit(1);
489         }
490         if (sscanf(argv[arg + 2], "%d", &secLevel) == 0) {
491             printf("invalid security level\n");
492             usage();
493             exit(1);
494         }
495         access_oid(vacmAccessStatus, &name_length, groupName, prefix,
496                    secModel, secLevel);
497         longvar = RS_CREATEANDGO;
498         snmp_pdu_add_variable(pdu, vacmAccessStatus, name_length,
499                               ASN_INTEGER, (u_char *) & longvar,
500                               sizeof(longvar));
501
502         access_oid(vacmAccessContextMatch, &name_length, groupName, prefix,
503                    secModel, secLevel);
504         if (sscanf(argv[arg + 3], "%d", &contextMatch) == 0) {
505             printf("invalid contextMatch\n");
506             usage();
507             exit(1);
508         }
509         snmp_pdu_add_variable(pdu, vacmAccessContextMatch, name_length,
510                               ASN_INTEGER, (u_char *) & contextMatch,
511                               sizeof(contextMatch));
512
513         access_oid(vacmAccessReadViewName, &name_length, groupName, prefix,
514                    secModel, secLevel);
515         snmp_pdu_add_variable(pdu, vacmAccessReadViewName, name_length,
516                               ASN_OCTET_STR, (u_char *) argv[arg + 4],
517                               strlen(argv[arg + 4]));
518
519         access_oid(vacmAccessWriteViewName, &name_length, groupName,
520                    prefix, secModel, secLevel);
521         snmp_pdu_add_variable(pdu, vacmAccessWriteViewName, name_length,
522                               ASN_OCTET_STR, (u_char *) argv[arg + 5],
523                               strlen(argv[arg + 5]));
524
525         access_oid(vacmAccessNotifyViewName, &name_length, groupName,
526                    prefix, secModel, secLevel);
527         snmp_pdu_add_variable(pdu, vacmAccessNotifyViewName, name_length,
528                               ASN_OCTET_STR, (u_char *) argv[arg + 6],
529                               strlen(argv[arg + 6]));
530     } else {
531         printf("Unknown command\n");
532         usage();
533         exit(1);
534     }
535
536     /*
537      * do the request 
538      */
539     status = snmp_synch_response(ss, pdu, &response);
540     if (status == STAT_SUCCESS) {
541         if (response) {
542             if (response->errstat == SNMP_ERR_NOERROR) {
543                 fprintf(stderr, "%s\n", successNotes[command - 1]);
544             } else {
545                 fprintf(stderr, "Error in packet.\nReason: %s\n",
546                         snmp_errstring(response->errstat));
547                 if (response->errindex != 0){
548                     int count;
549                     struct variable_list *vars = response->variables;
550                     fprintf(stderr, "Failed object: ");
551                     for(count = 1; vars && (count != response->errindex);
552                             vars = vars->next_variable, count++)
553                         ;
554                     if (vars)
555                         fprint_objid(stderr, vars->name, vars->name_length);
556                     fprintf(stderr, "\n");
557                 }
558                 exitval = 2;
559             }
560         }
561     } else if (status == STAT_TIMEOUT) {
562         fprintf(stderr, "Timeout: No Response from %s\n",
563                 session.peername);
564         exitval = 1;
565     } else {
566         snmp_sess_perror("snmpset", ss);
567         exitval = 1;
568     }
569
570     if (response)
571         snmp_free_pdu(response);
572
573     snmp_close(ss);
574     SOCK_CLEANUP;
575     return exitval;
576 }