1 /*
2    This file is part of GNU Radius SNMP Library.
3    Copyright (C) 2001,2007 Free Software Foundation, Inc.
4    Written by Sergey Poznyakoff
5 
6    This library is free software; you can redistribute it and/or
7    modify it under the terms of the GNU Lesser General Public License as
8    published by the Free Software Foundation; either version 3 of the
9    License, or (at your option) any later version.
10 
11    This library is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14    Lesser General Public License for more details.
15 
16    You should have received a copy of the GNU Lesser General Public
17    License along with this library; see the file COPYING.LIB.  If not,
18    write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19    Boston, MA 02111-1307, USA.  */
20 
21 #include <sys/types.h>
22 #include <sys/socket.h>
23 #include <netinet/in.h>
24 #include <string.h>
25 
26 typedef u_int ip_addr_t;
27 
28 #define SNMP_PORT 161
29 #define SNMP_PACKET_LENGTH 4500
30 
31 /* error definitions */
32 #define E_ASN_ENCODE       1
33 #define E_ASN_DECODE       2
34 #define E_SNMP_NOMEM       3
35 #define E_SNMP_BAD_OID     4
36 #define E_SNMP_BAD_ADDRESS 5
37 #define E_SNMP_SOCKET      6
38 #define E_SNMP_BIND        7
39 #define E_SNMP_SEND        8
40 #define E_SNMP_NOT_SUPPORTED 9
41 #define E_SNMP_DECODE      10
42 #define E_SNMP_BAD_VERSION 11
43 #define E_SNMP_UNKNOWN_REQ 12
44 #define E_SNMP_BAD_VARTYPE 13
45 
46 extern int * __snmp_errno_location();
47 #define snmp_errno (*__snmp_errno_location())
48 #define SNMP_SET_ERRNO(e) snmp_errno = (e)
49 
50 #define SMI_INTEGER     ASN_INTEGER
51 #define SMI_STRING      ASN_OCTET_STR
52 #define SMI_OBJID       ASN_OBJECT_ID
53 #define SMI_NULLOBJ     ASN_NULL
54 #define SMI_IPADDRESS   ASN_IPADDRESS
55 #define SMI_COUNTER32   ASN_COUNTER
56 #define SMI_GAUGE32     ASN_GAUGE
57 #define SMI_UNSIGNED32  SMI_GAUGE32
58 #define SMI_TIMETICKS   ASN_TIMETICKS
59 #define SMI_OPAQUE      ASN_OPAQUE
60 #define SMI_COUNTER64   ASN_COUNTER64
61 
62 /* PDU types */
63 #define SNMP_PDU_GET        (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x0)
64 #define SNMP_PDU_GETNEXT    (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x1)
65 #define SNMP_PDU_RESPONSE   (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x2)
66 #define SNMP_PDU_SET        (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x3)
67 #define SNMP_MSG_TRAP       (ASN_CONTEXT | ASN_CONSTRUCTOR | 0x4)
68 
69 /* PDU error values */
70 #define SNMP_ERR_NOERROR             0x0
71 #define SNMP_ERR_TOOBIG              0x1
72 #define SNMP_ERR_NOSUCHNAME          0x2
73 #define SNMP_ERR_BADVALUE            0x3
74 #define SNMP_ERR_READONLY            0x4
75 #define SNMP_ERR_GENERR              0x5
76 #define SNMP_ERR_NOACCESS            0x6
77 #define SNMP_ERR_WRONGTYPE           0x7
78 #define SNMP_ERR_WRONGLENGTH         0x8
79 #define SNMP_ERR_WRONGENCODING       0x9
80 #define SNMP_ERR_WRONGVALUE          0x10
81 #define SNMP_ERR_NOCREATION          0x11
82 #define SNMP_ERR_INCONSISTENTVALUE   0x12
83 #define SNMP_ERR_RESOURCEUNAVAILABLE 0x13
84 #define SNMP_ERR_COMMITFAILED        0x14
85 #define SNMP_ERR_UNDOFAILED          0x15
86 #define SNMP_ERR_AUTHORIZATIONERROR  0x16
87 #define SNMP_ERR_NOTWRITABLE         0x17
88 #define SNMP_ERR_INCONSISTENTNAME    0x18
89 
90 /* Versions */
91 #define SNMP_VERSION_1 0
92 
93 /* variable */
94 struct snmp_var {
95         struct snmp_var *next;
96         oid_t name;
97         int val_length;
98         u_char type;
99         union {
100                 int i;
101                 u_char *s;
102                 oid_t o;
103         } v;
104 #define var_int v.i
105 #define var_str v.s
106 #define var_oid v.o
107 };
108 
109 struct snmp_pdu {
110         u_char type;
111         struct sockaddr_in peer_sin; /*??*/
112         int req_id;
113         int err_stat;
114         int err_ind;
115         struct snmp_var *var;
116 };
117 
118 /* request list */
119 struct snmp_request {
120         struct snmp_request *next;
121         int retries;           /* number of retries this request already
122                                   suffered */
123         int timeout;           /* timeout for next retry */
124         struct timeval expire; /* when this request will expire */
125         struct snmp_pdu *pdu;  /* PDU of the request */
126 };
127 
128 #define SNMP_CONV_TIMEOUT            0
129 #define SNMP_CONV_RECV_MSG           1
130 #define SNMP_CONV_COMMUNITY_MISMATCH 2
131 
132 struct snmp_session;
133 
134 typedef int (*snmp_cfn)(int type, struct snmp_session *sp, struct snmp_pdu *pdu, void *closure);
135 
136 struct snmp_session {
137         struct snmp_session *next;
138 
139         int version;
140         struct {
141                 u_char *str;
142                 int len;
143         } community;
144         int retries;
145         int timeout;
146         char *remote_host;
147         u_short remote_port;
148         u_short local_port;
149         int sd;
150         struct sockaddr_in local_sin;
151         struct sockaddr_in remote_sin;
152 
153         snmp_cfn converse;
154         void *app_closure;
155 
156         struct snmp_pdu *pdu;
157         struct snmp_request *request_list;  /* list of outstanding requests */
158 };
159 
160 typedef void *(*snmp_alloc_t)(size_t);
161 typedef void *(*snmp_free_t)(void*);
162 
163 void *snmp_alloc(size_t);
164 void snmp_free(void*);
165 char *snmp_strdup(char *str);
166 
167 void snmp_init(int retries, int timeout,
168                snmp_alloc_t memalloc, snmp_free_t memfree);
169 
170 oid_t oid_dup(oid_t oid);
171 oid_t oid_create(int len);
172 oid_t oid_create_from_string(char *str);
173 oid_t oid_create_from_subid(int len, subid_t *subid);
174 int oid_cmp(oid_t a, oid_t b);
175 
176 char * sprint_oid(char *buf, int buflen, oid_t oid);
177 
178 struct snmp_pdu *snmp_pdu_create(int type);
179 void snmp_pdu_free(struct snmp_pdu *pdu);
180 void snmp_pdu_add_var(struct snmp_pdu *pdu, struct snmp_var *var);
181 u_char *snmp_pdu_encode(u_char *data, int *length, struct snmp_pdu *pdu);
182 u_char *snmp_pdu_decode(u_char *data, int *length, struct snmp_pdu *pdu);
183 
184 int snmp_send(struct snmp_session *sess, struct snmp_pdu *pdu);
185 int snmp_request_xmit(struct snmp_session *sess, struct snmp_request *req);
186 
187 int snmp_req_id(void);
188 struct snmp_session *snmp_session_create(char *community, char *host,
189                                          int port, snmp_cfn cfn,
190                                          void *closure);
191 int snmp_session_open(struct snmp_session *sp, ip_addr_t local_ip,
192                       int local_port, int timeout, int retries);
193 void snmp_session_close(struct snmp_session *sess);
194 void snmp_session_free(struct snmp_session *sess);
195 
196 void snmp_var_free(struct snmp_var *var);
197 void snmp_var_free_list(struct snmp_var *var);
198 struct snmp_var *snmp_var_create(oid_t oid);
199 struct snmp_var *snmp_var_dup(struct snmp_var *src);
200 struct snmp_var *snmp_var_dup_list(struct snmp_var *var);
201 u_char *snmp_var_encode(u_char *data, int *length, struct snmp_var *var,
202                         int version);
203 u_char *snmp_var_decode(u_char *data, int *length, struct snmp_var **var,
204                         int version);
205 
206 int snmp_encode_request(struct snmp_session *sess, struct snmp_pdu *pdu,
207                         u_char *packet_buf, int  *length);
208 int snmp_decode_request(struct snmp_session *sess, struct snmp_pdu *pdu,
209                         u_char *packet, int length, char *comm, int *comm_len);
210 
211 void snmp_poll(struct snmp_session *sess);
212 int snmp_query(struct snmp_session *sess, struct snmp_pdu *pdu);
213 void snmp_timeout(struct snmp_session *sess);
214 void snmp_read(struct snmp_session *sess, fd_set *fdset);
215 
216 char *snmp_strerror(int en);
217