added files
[bcm963xx.git] / userapps / opensource / net-snmp / apps / snmptest.c
1 /*
2  * snmptest.c - send snmp requests to a network entity.
3  *
4  * Usage: snmptest -v 1 [-q] hostname community [objectID]
5  *
6  */
7 /***********************************************************************
8         Copyright 1988, 1989, 1991, 1992 by Carnegie Mellon University
9
10                       All Rights Reserved
11
12 Permission to use, copy, modify, and distribute this software and its
13 documentation for any purpose and without fee is hereby granted,
14 provided that the above copyright notice appear in all copies and that
15 both that copyright notice and this permission notice appear in
16 supporting documentation, and that the name of CMU not be
17 used in advertising or publicity pertaining to distribution of the
18 software without specific, written prior permission.
19
20 CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
21 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
22 CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
23 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
24 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
25 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
26 SOFTWARE.
27 ******************************************************************/
28 #include <net-snmp/net-snmp-config.h>
29
30 #if HAVE_STDLIB_H
31 #include <stdlib.h>
32 #endif
33 #if HAVE_UNISTD_H
34 #include <unistd.h>
35 #endif
36 #if HAVE_STRING_H
37 #include <string.h>
38 #else
39 #include <strings.h>
40 #endif
41 #include <sys/types.h>
42 #if HAVE_NETINET_IN_H
43 #include <netinet/in.h>
44 #endif
45 #include <stdio.h>
46 #include <ctype.h>
47 #if TIME_WITH_SYS_TIME
48 # ifdef WIN32
49 #  include <sys/timeb.h>
50 # else
51 #  include <sys/time.h>
52 # endif
53 # include <time.h>
54 #else
55 # if HAVE_SYS_TIME_H
56 #  include <sys/time.h>
57 # else
58 #  include <time.h>
59 # endif
60 #endif
61 #if HAVE_SYS_SELECT_H
62 #include <sys/select.h>
63 #endif
64 #if HAVE_WINSOCK_H
65 #include <winsock.h>
66 #endif
67 #if HAVE_NETDB_H
68 #include <netdb.h>
69 #endif
70 #if HAVE_ARPA_INET_H
71 #include <arpa/inet.h>
72 #endif
73
74 #include <net-snmp/net-snmp-includes.h>
75
76 int             command = SNMP_MSG_GET;
77
78 int             input_variable(netsnmp_variable_list *);
79
80 void
81 usage(void)
82 {
83     fprintf(stderr, "USAGE: snmptest ");
84     snmp_parse_args_usage(stderr);
85     fprintf(stderr, "\n\n");
86     snmp_parse_args_descriptions(stderr);
87 }
88
89 int
90 main(int argc, char *argv[])
91 {
92     netsnmp_session session, *ss;
93     netsnmp_pdu    *pdu = NULL, *response, *copy = NULL;
94     netsnmp_variable_list *vars, *vp;
95     netsnmp_transport *transport = NULL;
96     int             ret;
97     int             status, count;
98     char            input[128];
99     int             varcount, nonRepeaters = -1, maxRepetitions;
100
101     /*
102      * get the common command line arguments 
103      */
104     switch (snmp_parse_args(argc, argv, &session, NULL, NULL)) {
105     case -2:
106         exit(0);
107     case -1:
108         usage();
109         exit(1);
110     default:
111         break;
112     }
113
114     SOCK_STARTUP;
115
116     /*
117      * open an SNMP session 
118      */
119     ss = snmp_open(&session);
120     if (ss == NULL) {
121         /*
122          * diagnose snmp_open errors with the input netsnmp_session pointer 
123          */
124         snmp_sess_perror("snmptest", &session);
125         SOCK_CLEANUP;
126         exit(1);
127     }
128
129     varcount = 0;
130     while (1) {
131         vars = NULL;
132         for (ret = 1; ret != 0;) {
133             vp = (netsnmp_variable_list *)
134                 malloc(sizeof(netsnmp_variable_list));
135             memset(vp, 0, sizeof(netsnmp_variable_list));
136
137             while ((ret = input_variable(vp)) == -1);
138             if (ret == 1) {
139                 varcount++;
140                 /*
141                  * add it to the list 
142                  */
143                 if (vars == NULL) {
144                     /*
145                      * if first variable 
146                      */
147                     pdu = snmp_pdu_create(command);
148                     pdu->variables = vp;
149                 } else {
150                     vars->next_variable = vp;
151                 }
152                 vars = vp;
153             } else {
154                 /*
155                  * free the last (unused) variable 
156                  */
157                 if (vp->name)
158                     free((char *) vp->name);
159                 if (vp->val.string)
160                     free((char *) vp->val.string);
161                 free((char *) vp);
162
163                 if (command == SNMP_MSG_GETBULK) {
164                     if (nonRepeaters == -1) {
165                         nonRepeaters = varcount;
166                         ret = -1;       /* so we collect more variables */
167                         printf("Now input the repeating variables\n");
168                     } else {
169                         printf("What repeat count? ");
170                         fflush(stdout);
171                         fgets(input, sizeof(input), stdin);
172                         maxRepetitions = atoi(input);
173                         pdu->non_repeaters = nonRepeaters;
174                         pdu->max_repetitions = maxRepetitions;
175                     }
176                 }
177             }
178             if (varcount == 0 && ret == 0) {
179                 if (!copy) {
180                     printf("No PDU to send.\n");
181                     ret = -1;
182                 } else {
183                     pdu = snmp_clone_pdu(copy);
184                     printf("Resending last PDU.\n");
185                 }
186             }
187         }
188         copy = snmp_clone_pdu(pdu);
189         if (command == SNMP_MSG_TRAP2) {
190             /*
191              * No response needed 
192              */
193             if (!snmp_send(ss, pdu)) {
194                 snmp_free_pdu(pdu);
195                 snmp_sess_perror("snmptest", ss);
196             }
197         } else {
198             status = snmp_synch_response(ss, pdu, &response);
199             if (status == STAT_SUCCESS) {
200                 if (command == SNMP_MSG_INFORM &&
201                     response->errstat == SNMP_ERR_NOERROR) {
202                     printf("Inform Acknowledged\n");
203                 } else {
204                     switch (response->command) {
205                     case SNMP_MSG_GET:
206                         printf("Received Get Request ");
207                         break;
208                     case SNMP_MSG_GETNEXT:
209                         printf("Received Getnext Request ");
210                         break;
211                     case SNMP_MSG_RESPONSE:
212                         printf("Received Get Response ");
213                         break;
214                     case SNMP_MSG_SET:
215                         printf("Received Set Request ");
216                         break;
217                     case SNMP_MSG_TRAP:
218                         printf("Received Trap Request ");
219                         break;
220                     case SNMP_MSG_GETBULK:
221                         printf("Received Bulk Request ");
222                         break;
223                     case SNMP_MSG_INFORM:
224                         printf("Received Inform Request ");
225                         break;
226                     case SNMP_MSG_TRAP2:
227                         printf("Received SNMPv2 Trap Request ");
228                         break;
229                     }
230                     transport = snmp_sess_transport(snmp_sess_pointer(ss));
231                     if (transport != NULL && transport->f_fmtaddr != NULL) {
232                         char           *s = transport->f_fmtaddr(transport,
233                                                                  response->
234                                                                  transport_data,
235                                                                  response->
236                                                                  transport_data_length);
237                         printf("from %s\n", s);
238                     } else {
239                         printf("from <UNKNOWN>\n");
240                     }
241                     printf
242                         ("requestid 0x%lX errstat 0x%lX errindex 0x%lX\n",
243                          response->reqid, response->errstat,
244                          response->errindex);
245                     if (response->errstat == SNMP_ERR_NOERROR) {
246                         for (vars = response->variables; vars;
247                              vars = vars->next_variable)
248                             print_variable(vars->name, vars->name_length,
249                                            vars);
250                     } else {
251                         printf("Error in packet.\nReason: %s\n",
252                                snmp_errstring(response->errstat));
253                         if (response->errindex != 0) {
254                             for (count = 1, vars = response->variables;
255                                  vars && count != response->errindex;
256                                  vars = vars->next_variable, count++);
257                             if (vars) {
258                                 printf("Failed object: ");
259                                 print_objid(vars->name, vars->name_length);
260                             }
261                             printf("\n");
262                         }
263                     }
264                 }
265             } else if (status == STAT_TIMEOUT) {
266                 printf("Timeout: No Response from %s\n", session.peername);
267             } else {            /* status == STAT_ERROR */
268                 snmp_sess_perror("snmptest", ss);
269             }
270
271             if (response)
272                 snmp_free_pdu(response);
273         }
274         varcount = 0;
275         nonRepeaters = -1;
276     }
277     SOCK_CLEANUP;
278     return 0;
279 }
280
281 int
282 input_variable(netsnmp_variable_list * vp)
283 {
284     char            buf[256];
285     int             val_len;
286     u_char          value[256], ch;
287     oid             name[MAX_OID_LEN];
288
289     printf("Variable: ");
290     fflush(stdout);
291     if (!fgets(buf, sizeof(buf), stdin)) {
292         printf("Quitting,  Goobye\n");
293         SOCK_CLEANUP;
294         exit(0);
295     }
296     val_len = strlen(buf);
297
298     if (val_len == 0 || *buf == '\n') {
299         vp->name_length = 0;
300         return 0;
301     }
302     if (buf[val_len - 1] == '\n')
303         buf[--val_len] = 0;
304     if (*buf == '$') {
305         switch (toupper(buf[1])) {
306         case 'G':
307             command = SNMP_MSG_GET;
308             printf("Request type is Get Request\n");
309             break;
310         case 'N':
311             command = SNMP_MSG_GETNEXT;
312             printf("Request type is Getnext Request\n");
313             break;
314         case 'S':
315             command = SNMP_MSG_SET;
316             printf("Request type is Set Request\n");
317             break;
318         case 'B':
319             command = SNMP_MSG_GETBULK;
320             printf("Request type is Bulk Request\n");
321             printf
322                 ("Enter a blank line to terminate the list of non-repeaters\n");
323             printf("and to begin the repeating variables\n");
324             break;
325         case 'I':
326             command = SNMP_MSG_INFORM;
327             printf("Request type is Inform Request\n");
328             printf("(Are you sending to the right port?)\n");
329             break;
330         case 'T':
331             command = SNMP_MSG_TRAP2;
332             printf("Request type is SNMPv2 Trap Request\n");
333             printf("(Are you sending to the right port?)\n");
334             break;
335         case 'D':
336             if (snmp_get_dump_packet()) {
337                 snmp_set_dump_packet(0);
338                 printf("Turned packet dump off\n");
339             } else {
340                 snmp_set_dump_packet(1);
341                 printf("Turned packet dump on\n");
342             }
343             break;
344         case 'Q':
345             switch ((toupper(buf[2]))) {
346             case '\n':
347             case 0:
348                 printf("Quitting,  Goodbye\n");
349                 SOCK_CLEANUP;
350                 exit(0);
351                 break;
352             case 'P':
353                 if (snmp_get_quick_print()) {
354                     snmp_set_quick_print(0);
355                     printf("Turned quick printing off\n");
356                 } else {
357                     snmp_set_quick_print(1);
358                     printf("Turned quick printing on\n");
359                 }
360                 break;
361             }
362             break;
363         default:
364             printf("Bad command\n");
365         }
366         return -1;
367     }
368     vp->name_length = MAX_OID_LEN;
369     if (!snmp_parse_oid(buf, name, &vp->name_length)) {
370         snmp_perror(buf);
371         return -1;
372     }
373     vp->name = (oid *) malloc(vp->name_length * sizeof(oid));
374     memmove(vp->name, name, vp->name_length * sizeof(oid));
375
376     if (command == SNMP_MSG_SET || command == SNMP_MSG_INFORM
377         || command == SNMP_MSG_TRAP2) {
378         printf("Type [i|u|s|x|d|n|o|t|a]: ");
379         fflush(stdout);
380         fgets(buf, sizeof(buf), stdin);
381         ch = *buf;
382         switch (ch) {
383         case 'i':
384             vp->type = ASN_INTEGER;
385             break;
386         case 'u':
387             vp->type = ASN_UNSIGNED;
388             break;
389         case 's':
390             vp->type = ASN_OCTET_STR;
391             break;
392         case 'x':
393             vp->type = ASN_OCTET_STR;
394             break;
395         case 'd':
396             vp->type = ASN_OCTET_STR;
397             break;
398         case 'n':
399             vp->type = ASN_NULL;
400             break;
401         case 'o':
402             vp->type = ASN_OBJECT_ID;
403             break;
404         case 't':
405             vp->type = ASN_TIMETICKS;
406             break;
407         case 'a':
408             vp->type = ASN_IPADDRESS;
409             break;
410         default:
411             printf
412                 ("bad type \"%c\", use \"i\", \"u\", \"s\", \"x\", \"d\", \"n\", \"o\", \"t\", or \"a\".\n",
413                  *buf);
414             return -1;
415         }
416       getValue:
417         printf("Value: ");
418         fflush(stdout);
419         fgets(buf, sizeof(buf), stdin);
420         switch (vp->type) {
421         case ASN_INTEGER:
422             vp->val.integer = (long *) malloc(sizeof(long));
423             *(vp->val.integer) = atoi(buf);
424             vp->val_len = sizeof(long);
425             break;
426         case ASN_UNSIGNED:
427             vp->val.integer = (long *) malloc(sizeof(long));
428             *(vp->val.integer) = strtoul(buf, NULL, 0);
429             vp->val_len = sizeof(long);
430             break;
431         case ASN_OCTET_STR:
432             if (ch == 'd') {
433                 size_t          buf_len = 256;
434                 val_len = 0;
435                 if ((vp->val.string = (u_char *) malloc(buf_len)) == NULL) {
436                     printf("malloc failure\n");
437                     goto getValue;
438                 }
439                 if (!snmp_decimal_to_binary(&(vp->val.string), &buf_len,
440                                             &val_len, 1, buf)) {
441                     printf("Bad value or no sub-identifier > 255\n");
442                     free(vp->val.string);
443                     goto getValue;
444                 }
445                 vp->val_len = val_len;
446             } else if (ch == 's') {
447                 /*
448                  * -1 to omit trailing newline  
449                  */
450                 vp->val.string = (u_char *) malloc(strlen(buf) - 1);
451                 if (vp->val.string == NULL) {
452                     printf("malloc failure\n");
453                     goto getValue;
454                 }
455                 memcpy(vp->val.string, buf, strlen(buf) - 1);
456                 vp->val_len = strlen(buf) - 1;
457             } else if (ch == 'x') {
458                 size_t          buf_len = 256;
459                 val_len = 0;
460                 if ((vp->val.string = (u_char *) malloc(buf_len)) == NULL) {
461                     printf("malloc failure\n");
462                     goto getValue;
463                 }
464                 if (!snmp_hex_to_binary(&(vp->val.string), &buf_len,
465                                         &val_len, 1, buf)) {
466                     printf("Bad value (need pairs of hex digits)\n");
467                     free(vp->val.string);
468                     goto getValue;
469                 }
470                 vp->val_len = val_len;
471             }
472             break;
473         case ASN_NULL:
474             vp->val_len = 0;
475             vp->val.string = NULL;
476             break;
477         case ASN_OBJECT_ID:
478             if ('\n' == buf[strlen(buf) - 1])
479                 buf[strlen(buf) - 1] = '\0';
480             vp->val_len = MAX_OID_LEN;;
481             read_objid(buf, (oid *) value, &vp->val_len);
482             vp->val_len *= sizeof(oid);
483             vp->val.objid = (oid *) malloc(vp->val_len);
484             memmove(vp->val.objid, value, vp->val_len);
485             break;
486         case ASN_TIMETICKS:
487             vp->val.integer = (long *) malloc(sizeof(long));
488             *(vp->val.integer) = atoi(buf);
489             vp->val_len = sizeof(long);
490             break;
491         case ASN_IPADDRESS:
492             vp->val.integer = (long *) malloc(sizeof(long));
493             *(vp->val.integer) = inet_addr(buf);
494             vp->val_len = sizeof(long);
495             break;
496         default:
497             printf("Internal error\n");
498             break;
499         }
500     } else {                    /* some form of get message */
501         vp->type = ASN_NULL;
502         vp->val_len = 0;
503     }
504     return 1;
505 }