]> git.ipfire.org Git - thirdparty/squid.git/blame - snmplib/snmp_api.c
gindent
[thirdparty/squid.git] / snmplib / snmp_api.c
Content-type: text/html ]> git.ipfire.org Git - thirdparty/squid.git/blame - snmplib/snmp_api.c


500 - Internal Server Error

Malformed UTF-8 character (fatal) at (eval 6) line 1, <$fd> line 837.
CommitLineData
da2d50d1 1
2
627f6d02 3/***********************************************************
4 Copyright 1989 by Carnegie Mellon University
5
6 All Rights Reserved
7
8Permission to use, copy, modify, and distribute this software and its
9documentation for any purpose and without fee is hereby granted,
10provided that the above copyright notice appear in all copies and that
11both that copyright notice and this permission notice appear in
12supporting documentation, and that the name of CMU not be
13used in advertising or publicity pertaining to distribution of the
14software without specific, written prior permission.
15
da2d50d1 16CMU DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
17ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
18CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
19ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
20WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
21ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
22SOFTWARE.
23******************************************************************/
24/*
25 * snmp_api.c - API for access to snmp.
26 */
27#define DEBUG_SNMPTRACE 0 /* set to 1 to print all SNMP actions */
28#define DEBUG_SNMPFULLDUMP 0 /* set to 1 to dump all SNMP packets */
29
30#include <stdio.h>
31#include <sys/types.h>
32#include <sys/param.h>
33#include <sys/time.h>
34#include <netinet/in.h>
35#include <sys/socket.h>
36#include <netdb.h>
37#ifdef linux
38#include <arpa/inet.h>
39#include <stdlib.h>
40#include <string.h>
41#include <unistd.h>
42#endif
43
44
45#include "asn1.h"
46#include "snmp.h"
47#include "snmp_impl.h"
48#include "snmp_api.h"
49#include "snmp_client.h"
50
51#define PACKET_LENGTH 4500
52
53#ifndef BSD4_3
54#define BSD4_2
55#endif
56
57#if !defined(BSD4_3) && !defined(linux) && !defined(sun)
58
59typedef long fd_mask;
60#define NFDBITS (sizeof(fd_mask) * NBBY) /* bits per mask */
61
62#define FD_SET(n, p) ((p)->fds_bits[(n)/NFDBITS] |= (1 << ((n) % NFDBITS)))
63#define FD_CLR(n, p) ((p)->fds_bits[(n)/NFDBITS] &= ~(1 << ((n) % NFDBITS)))
64#define FD_ISSET(n, p) ((p)->fds_bits[(n)/NFDBITS] & (1 << ((n) % NFDBITS)))
65#define FD_ZERO(p) bzero((char *)(p), sizeof(*(p)))
66#endif
67
68oid default_enterprise[] =
69{1, 3, 6, 1, 4, 1, 3, 1, 1}; /* enterprises.cmu.systems.cmuSNMP */
70
71#define DEFAULT_COMMUNITY "public"
72#define DEFAULT_REMPORT SNMP_PORT
73#define DEFAULT_ENTERPRISE default_enterprise
74#define DEFAULT_TIME 0
75#define DEFAULT_MMS 1389 /* large, randomly picked for testing purposes */
76
77/*
78 * Internal information about the state of the snmp session.
79 */
80struct snmp_internal_session {
81 int sd; /* socket descriptor for this connection */
82 ipaddr addr; /* address of connected peer */
83 struct request_list *requests; /* Info about outstanding requests */
84};
85
86/*
87 * A list of all the outstanding requests for a particular session.
88 */
89struct request_list {
90 struct request_list *next_request;
91 u_long request_id; /* request id */
92 int retries; /* Number of retries */
93 u_long timeout; /* length to wait for timeout */
94 struct timeval time; /* Time this request was made */
95 struct timeval expire; /* time this request is due to expire */
96 struct snmp_pdu *pdu; /* The pdu for this request (saved so it can be retransmitted */
97};
98
99/*
100 * The list of active/open sessions.
101 */
102struct session_list {
103 struct session_list *next;
104 struct snmp_session *session;
105 struct snmp_internal_session *internal;
106};
107
108struct session_list *Sessions = NULL;
109
110u_long Reqid = 0;
111int snmp_errno = 0;
112
113char *api_errors[4] =
114{
115 "Unknown session",
116 "Unknown host",
117 "Invalid local port",
118 "Unknown Error"
119};
120
121
122void sync_with_agent();
123int parse_app_community_string();
124void snmp_synch_setup();
125int snmp_synch_response();
126void md5Digest();
127
128
129static char *
130api_errstring(snmp_errnumber)
131 int snmp_errnumber;
132{
133 if (snmp_errnumber <= SNMPERR_BAD_SESSION && snmp_errnumber >= SNMPERR_GENERR) {
134 return api_errors[snmp_errnumber + 4];
135 } else {
136 return "Unknown Error";
137 }
138}
139
140#if 0
141/*
142 * Gets initial request ID for all transactions.
143 */
144static void
145init_snmp()
146{
147 struct timeval tv;
148
149 gettimeofday(&tv, (struct timezone *) 0);
150 srandom(tv.tv_sec ^ tv.tv_usec);
151 Reqid = random();
152}
153
154#endif
155
156
157/*
158 * Dump snmp packet to stdout:
159 */
160static void
161snmp_print_packet(packet, length, addr, code)
162 char *packet;
163 int length;
164 ipaddr addr;
165 int code;
166{
167 if (length < 0) {
168 return;
169 }
170 if (code <= 0) { /* received */
171 printf("\nReceived %4d bytes from ", length);
172 } else { /* sending */
173 printf("\nSending %4d bytes to ", length);
174 }
175 printf("%s:", inet_ntoa(addr.sin_addr));
176#if DEBUG_SNMPFULLDUMP
177 for (count = 0; count < length; count++) {
178 if ((count & 15) == 0) {
179 printf("\n ");
180 }
181 printf("%02X ", (int) (packet[count] & 255));
182 }
183#endif
184 fflush(stdout);
185}
186
187#if DEBUG_SNMPTRACE
188/*
189 * Print request
190 */
191#define TRACE_SEND (0)
192#define TRACE_RECV (1)
193#define TRACE_TIMEOUT (2)
194static void
195snmp_print_trace(slp, rp, code)
196 struct session_list *slp;
197 struct request_list *rp;
198 int code;
199{
200 int reqid = 0, retries = 1;
201 if (rp) {
202 reqid = rp->request_id;
203 retries = rp->retries;
204 }
205 printf("\n Session %2d ReqId %4d ", slp->internal->sd, reqid);
206 switch (code) {
207 case TRACE_SEND:
208 printf("send pdu (%d)", retries);
209 break;
210 case TRACE_RECV:
211 printf("recv pdu");
212 break;
213 case TRACE_TIMEOUT:
214 printf("time out");
215 break;
216 }
217 fflush(stdout);
218}
219#endif /* DEBUG_SNMPTRACE */
220
221
222
223
224/*
225 * Sets up the session with the snmp_session information provided
226 * by the user. Then opens and binds the necessary UDP port.
227 * A handle to the created session is returned (this is different than
228 * the pointer passed to snmp_open()). On any error, NULL is returned
229 * and snmp_errno is set to the appropriate error code.
230 */
231struct snmp_session *
232snmp_open(session)
233 struct snmp_session *session;
234{
235 struct session_list *slp;
236 struct snmp_internal_session *isp;
237 u_char *cp;
238 int sd;
239 u_long addr;
240 struct sockaddr_in me;
241 struct hostent *hp;
242 struct servent *servp;
243 extern int check_received_pkt();
244
245 /* Copy session structure and link into list */
246 slp = (struct session_list *) calloc(1, sizeof(struct session_list));
247 slp->internal = isp = (struct snmp_internal_session *) calloc(1, sizeof(struct snmp_internal_session));
248 bzero((char *) isp, sizeof(struct snmp_internal_session));
249 slp->internal->sd = -1; /* mark it not set */
250 slp->session = (struct snmp_session *) calloc(1, sizeof(struct snmp_session));
251 bcopy((char *) session, (char *) slp->session, sizeof(struct snmp_session));
252 session = slp->session;
253 /* now link it in. */
254 slp->next = Sessions;
255 Sessions = slp;
256
257 /*
258 * session now points to the new structure that still contains pointers to
259 * data allocated elsewhere. Some of this data is copied to space malloc'd
260 * here, and the pointer replaced with the new one.
261 */
262
263 if (session->peername != NULL) {
264 cp = (u_char *) calloc(1, (unsigned) strlen(session->peername) + 1);
265 strcpy((char *) cp, session->peername);
266 session->peername = (char *) cp;
267 }
268 if (session->retries == SNMP_DEFAULT_RETRIES)
269 session->retries = SNMP_API_DEFAULT_RETRIES;
270 if (session->timeout == SNMP_DEFAULT_TIMEOUT)
271 session->timeout = SNMP_API_DEFAULT_TIMEOUT;
272 if (session->MMS == 0)
273 session->MMS = DEFAULT_MMS;
274 isp->requests = NULL;
275
276
277 /* Fill in defaults if necessary */
278 if (session->community_len != SNMP_DEFAULT_COMMUNITY_LEN) {
279 if (*session->community == '+') {
280 session->community_len--;
281 cp = (u_char *) calloc(1, (unsigned) session->community_len);
282 bcopy((char *) session->community + 1, (char *) cp,
283 session->community_len);
284 session->version = SNMP_VERSION_2C;
285 } else {
286 cp = (u_char *) calloc(1, (unsigned) session->community_len);
287 bcopy((char *) session->community, (char *) cp,
288 session->community_len);
289 }
290
291 } else {
292 session->community_len = strlen(DEFAULT_COMMUNITY);
293 cp = (u_char *) calloc(1, (unsigned) session->community_len);
294 bcopy((char *) DEFAULT_COMMUNITY, (char *) cp, session->community_len);
295 }
296
297 /* Set up connections */
298 sd = socket(AF_INET, SOCK_DGRAM, 0);
299 if (sd < 0) {
300 perror("socket");
301 snmp_errno = SNMPERR_GENERR;
302 if (!snmp_close(session)) {
303 fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno));
304 exit(1);
305 }
306 return 0;
307 }
308 isp->sd = sd;
309
310 if (session->peername != SNMP_DEFAULT_PEERNAME) {
311 if ((addr = inet_addr(session->peername)) != -1) {
312 bcopy((char *) &addr, (char *) &isp->addr.sin_addr, sizeof(isp->addr.sin_addr));
313 } else {
314 hp = gethostbyname(session->peername);
315 if (hp == NULL) {
316 fprintf(stderr, "unknown host: %s\n", session->peername);
317 snmp_errno = SNMPERR_BAD_ADDRESS;
318 if (!snmp_close(session)) {
319 fprintf(stderr, "Couldn't abort session: %s. Exiting\n", api_errstring(snmp_errno));
320 exit(2);
321 }
322 return 0;
323 } else {
324 bcopy((char *) hp->h_addr, (char *) &isp->addr.sin_addr, hp->h_length);
325 }
326 }
327 isp->addr.sin_family = AF_INET;
328 if (session->remote_port == SNMP_DEFAULT_REMPORT) {
329 /*servp = getservbyname("snmp", "udp"); */
330 servp = NULL;
331 if (servp != NULL) {
332 isp->addr.sin_port = servp->s_port;
333 } else {
334 isp->addr.sin_port = htons(SNMP_PORT);
335 }
336 } else {
337 isp->addr.sin_port = htons(session->remote_port);
338 }
339 } else {
340 isp->addr.sin_addr.s_addr = SNMP_DEFAULT_ADDRESS;
341 }
342
343 me.sin_family = AF_INET;
344 me.sin_addr.s_addr = INADDR_ANY;
345 me.sin_port = htons(session->local_port);
346 if (bind(sd, (struct sockaddr *) &me, sizeof(me)) != 0) {
347 perror("bind");
348 snmp_errno = SNMPERR_BAD_LOCPORT;
349 if (!snmp_close(session)) {
350 fprintf(stderr, "Couldn't abort session: %s. Exiting\n",
351 api_errstring(snmp_errno));
352 exit(3);
353 }
354 return 0;
355 }
356 if (*cp == '/') {
357 session->authenticator = check_received_pkt;
358 sync_with_agent(session);
359 parse_app_community_string(session);
360 session->qoS |= USEC_QOS_GENREPORT;
361 }
362 /* replace comm pointer with pointer to new data: */
363 session->community = cp;
364
365 return session;
366}
367
368void
369sync_with_agent(session)
370 struct snmp_session *session;
371{
372 struct snmp_pdu *pdu, *response = 0;
373 int status;
374
375 session->qoS = USEC_QOS_GENREPORT;
376 session->userLen = 6;
377 session->version = SNMP_VERSION_2;
378 strcpy(session->userName, "public");
379
380 snmp_synch_setup(session);
381 pdu = snmp_pdu_create(GET_REQ_MSG);
382 status = snmp_synch_response(session, pdu, &response);
383
384 if (status == STAT_SUCCESS) {
385 memcpy(session->agentID, response->params.agentID, 12);
386
387 /* save the clocks -- even though they are not authentic */
388 session->agentBoots = response->params.agentBoots;
389 session->agentTime = response->params.agentTime;
390 session->agentClock = response->params.agentTime - time(NULL);
391
392 } else {
393 if (status == STAT_TIMEOUT) {
394 printf("No Response from %s\n", session->peername);
395 } else { /* status == STAT_ERROR */
396 printf("An error occurred, Quitting\n");
397 }
398 exit(-1);
399 }
400
401 /** freed to early:
402 snmp_free_pdu(pdu);
403 if (response) snmp_free_pdu(response);
404 **/
405}
406#if 1/***/ BUG_SNMPTRACE */cked for testing purposes */e key! replace...
407 */
408