snmp.c revision 1.11 1 1.11 itojun /* $NetBSD: snmp.c,v 1.11 2003/05/16 18:10:38 itojun Exp $ */
2 1.10 wiz
3 1.10 wiz /*
4 1.10 wiz * Copyright (c) 1992, 2001 Xerox Corporation. All rights reserved.
5 1.10 wiz *
6 1.10 wiz * Redistribution and use in source and binary forms, with or without modification,
7 1.10 wiz * are permitted provided that the following conditions are met:
8 1.10 wiz *
9 1.10 wiz * Redistributions of source code must retain the above copyright notice,
10 1.10 wiz * this list of conditions and the following disclaimer.
11 1.10 wiz *
12 1.10 wiz * Redistributions in binary form must reproduce the above copyright notice,
13 1.10 wiz * this list of conditions and the following disclaimer in the documentation
14 1.10 wiz * and/or other materials provided with the distribution.
15 1.10 wiz *
16 1.10 wiz * Neither name of the Xerox, PARC, nor the names of its contributors may be used
17 1.10 wiz * to endorse or promote products derived from this software
18 1.10 wiz * without specific prior written permission.
19 1.10 wiz *
20 1.10 wiz * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
21 1.10 wiz * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 1.10 wiz * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
23 1.10 wiz * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE XEROX CORPORATION OR CONTRIBUTORS
24 1.10 wiz * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25 1.10 wiz * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26 1.10 wiz * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
27 1.10 wiz * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
28 1.10 wiz * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 1.10 wiz * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 1.10 wiz * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 1.10 wiz */
32 1.1 mycroft
33 1.1 mycroft #include "defs.h"
34 1.3 mycroft #include <netinet/in_var.h>
35 1.1 mycroft #include "snmp.h"
36 1.3 mycroft #include "snmplib/asn1.h"
37 1.3 mycroft #include "snmplib/party.h"
38 1.3 mycroft #include "snmplib/snmp_impl.h"
39 1.3 mycroft #define MROUTED
40 1.3 mycroft #include "snmpd/snmp_vars.h"
41 1.3 mycroft
42 1.7 itojun in_port_t dest_port = 0;
43 1.3 mycroft int sdlen = 0;
44 1.3 mycroft
45 1.3 mycroft struct addrCache {
46 1.3 mycroft u_long addr;
47 1.3 mycroft int status;
48 1.3 mycroft #define UNUSED 0
49 1.3 mycroft #define USED 1
50 1.3 mycroft #define OLD 2
51 1.3 mycroft };
52 1.1 mycroft
53 1.3 mycroft static struct addrCache addrCache[10];
54 1.1 mycroft
55 1.3 mycroft /*
56 1.3 mycroft * Initialize the SNMP part of mrouted
57 1.3 mycroft */
58 1.3 mycroft int /* returns: 0 on success, true on error */
59 1.3 mycroft snmp_init(dest_port)
60 1.7 itojun in_port_t dest_port;
61 1.3 mycroft {
62 1.3 mycroft u_long myaddr;
63 1.3 mycroft int ret;
64 1.3 mycroft struct partyEntry *pp;
65 1.3 mycroft struct sockaddr_in me;
66 1.3 mycroft int index, sd, portlist[32];
67 1.3 mycroft
68 1.3 mycroft init_snmp();
69 1.3 mycroft /* init_mib(); why was this here? */
70 1.3 mycroft if (read_party_database("/etc/party.conf") > 0){
71 1.3 mycroft fprintf(stderr, "Couldn't read party database from /etc/party.conf\n");
72 1.3 mycroft exit(0);
73 1.3 mycroft }
74 1.3 mycroft if (read_context_database("/etc/context.conf") > 0){
75 1.3 mycroft fprintf(stderr, "Couldn't read context database from /etc/context.conf\n");
76 1.3 mycroft exit(0);
77 1.3 mycroft }
78 1.3 mycroft if (read_acl_database("/etc/acl.conf") > 0){
79 1.3 mycroft fprintf(stderr, "Couldn't read acl database from /etc/acl.conf\n");
80 1.3 mycroft exit(0);
81 1.3 mycroft }
82 1.3 mycroft if (read_view_database("/etc/view.conf") > 0){
83 1.3 mycroft fprintf(stderr, "Couldn't read view database from /etc/view.conf\n");
84 1.3 mycroft exit(0);
85 1.3 mycroft }
86 1.3 mycroft
87 1.3 mycroft myaddr = get_myaddr();
88 1.3 mycroft if (ret = agent_party_init(myaddr, ".1.3.6.1")){
89 1.3 mycroft if (ret == 1){
90 1.3 mycroft fprintf(stderr, "Conflict found with initial noAuth/noPriv parties... continuing\n");
91 1.3 mycroft } else if (ret == -1){
92 1.3 mycroft fprintf(stderr, "Error installing initial noAuth/noPriv parties, exiting\n");
93 1.3 mycroft exit(1);
94 1.3 mycroft } else {
95 1.3 mycroft fprintf(stderr, "Unknown error, exiting\n");
96 1.3 mycroft exit(2);
97 1.3 mycroft }
98 1.3 mycroft }
99 1.1 mycroft
100 1.3 mycroft printf("Opening port(s): ");
101 1.3 mycroft fflush(stdout);
102 1.3 mycroft party_scanInit();
103 1.3 mycroft for(pp = party_scanNext(); pp; pp = party_scanNext()){
104 1.3 mycroft if ((pp->partyTDomain != DOMAINSNMPUDP)
105 1.3 mycroft || bcmp((char *)&myaddr, pp->partyTAddress, 4))
106 1.3 mycroft continue; /* don't listen for non-local parties */
107 1.3 mycroft
108 1.3 mycroft dest_port = 0;
109 1.3 mycroft bcopy(pp->partyTAddress + 4, &dest_port, 2);
110 1.3 mycroft for(index = 0; index < sdlen; index++)
111 1.3 mycroft if (dest_port == portlist[index])
112 1.3 mycroft break;
113 1.3 mycroft if (index < sdlen) /* found a hit before the end of the list */
114 1.3 mycroft continue;
115 1.3 mycroft printf("%u ", dest_port);
116 1.3 mycroft fflush(stdout);
117 1.3 mycroft /* Set up connections */
118 1.3 mycroft sd = socket(AF_INET, SOCK_DGRAM, 0);
119 1.3 mycroft if (sd < 0){
120 1.3 mycroft perror("socket");
121 1.3 mycroft return 1;
122 1.3 mycroft }
123 1.5 itojun memset(&me, 0, sizeof(me));
124 1.3 mycroft me.sin_family = AF_INET;
125 1.3 mycroft me.sin_addr.s_addr = INADDR_ANY;
126 1.3 mycroft /* already in network byte order (I think) */
127 1.3 mycroft me.sin_port = dest_port;
128 1.3 mycroft if (bind(sd, (struct sockaddr *)&me, sizeof(me)) != 0){
129 1.3 mycroft perror("bind");
130 1.3 mycroft return 2;
131 1.3 mycroft }
132 1.3 mycroft register_input_handler(sd, snmp_read_packet);
133 1.3 mycroft portlist[sdlen] = dest_port;
134 1.3 mycroft if (++sdlen == 32){
135 1.3 mycroft printf("No more sockets... ignoring rest of file\n");
136 1.3 mycroft break;
137 1.3 mycroft }
138 1.3 mycroft }
139 1.3 mycroft printf("\n");
140 1.3 mycroft bzero((char *)addrCache, sizeof(addrCache));
141 1.3 mycroft }
142 1.1 mycroft
143 1.1 mycroft /*
144 1.3 mycroft * Place an IP address into an OID starting at element n
145 1.1 mycroft */
146 1.1 mycroft void
147 1.3 mycroft put_address(name, addr, n)
148 1.3 mycroft oid *name;
149 1.1 mycroft u_long addr;
150 1.1 mycroft int n;
151 1.1 mycroft {
152 1.1 mycroft int i;
153 1.1 mycroft
154 1.1 mycroft for (i=n+3; i>=n+0; i--) {
155 1.3 mycroft name[i] = addr & 0xFF;
156 1.1 mycroft addr >>= 8;
157 1.1 mycroft }
158 1.1 mycroft }
159 1.1 mycroft
160 1.1 mycroft /* Get an IP address from an OID starting at element n */
161 1.1 mycroft int
162 1.3 mycroft get_address(name, length, addr, n)
163 1.3 mycroft oid *name;
164 1.3 mycroft int length;
165 1.1 mycroft u_long *addr;
166 1.1 mycroft int n;
167 1.1 mycroft {
168 1.1 mycroft int i;
169 1.1 mycroft int ok = 1;
170 1.1 mycroft
171 1.1 mycroft (*addr) = 0;
172 1.1 mycroft
173 1.3 mycroft if (length < n+4)
174 1.1 mycroft return 0;
175 1.1 mycroft
176 1.1 mycroft for (i=n; i<n+4; i++) {
177 1.1 mycroft (*addr) <<= 8;
178 1.3 mycroft if (i >= length)
179 1.1 mycroft ok = 0;
180 1.1 mycroft else
181 1.3 mycroft (*addr) |= name[i];
182 1.1 mycroft }
183 1.1 mycroft return ok;
184 1.1 mycroft }
185 1.1 mycroft
186 1.1 mycroft /*
187 1.3 mycroft * Implements scalar objects from DVMRP and Multicast MIBs
188 1.1 mycroft */
189 1.3 mycroft u_char *
190 1.3 mycroft o_scalar(vp, name, length, exact, var_len, write_method)
191 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
192 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
193 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
194 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
195 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
196 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
197 1.3 mycroft {
198 1.3 mycroft int result;
199 1.3 mycroft
200 1.3 mycroft *write_method = 0;
201 1.3 mycroft result = compare(name, *length, vp->name, (int)vp->namelen);
202 1.3 mycroft if ((exact && (result != 0)) || (!exact && (result >= 0)))
203 1.3 mycroft return NULL;
204 1.3 mycroft
205 1.3 mycroft bcopy((char *)vp->name, (char *)name,
206 1.3 mycroft (int)vp->namelen * sizeof(oid));
207 1.3 mycroft *length = vp->namelen;
208 1.3 mycroft *var_len = sizeof(long);
209 1.3 mycroft
210 1.3 mycroft switch (vp->magic) {
211 1.3 mycroft
212 1.3 mycroft case ipMRouteEnable:
213 1.3 mycroft long_return = 1;
214 1.3 mycroft return (u_char *) &long_return;
215 1.3 mycroft
216 1.3 mycroft case dvmrpVersion: {
217 1.3 mycroft static char buff[15];
218 1.3 mycroft
219 1.11 itojun snprintf(buff, sizeof(buff), "mrouted%d.%d", PROTOCOL_VERSION,
220 1.11 itojun MROUTED_VERSION);
221 1.3 mycroft *var_len = strlen(buff);
222 1.3 mycroft return (u_char *)buff;
223 1.3 mycroft }
224 1.1 mycroft
225 1.3 mycroft case dvmrpGenerationId:
226 1.3 mycroft long_return = dvmrp_genid;
227 1.3 mycroft return (u_char *) &long_return;
228 1.1 mycroft
229 1.3 mycroft default:
230 1.3 mycroft ERROR("");
231 1.1 mycroft }
232 1.3 mycroft return NULL;
233 1.1 mycroft }
234 1.1 mycroft
235 1.3 mycroft /*
236 1.1 mycroft * Find if a specific scoped boundary exists on a Vif
237 1.1 mycroft */
238 1.1 mycroft struct vif_acl *
239 1.1 mycroft find_boundary(vifi, addr, mask)
240 1.3 mycroft vifi_t vifi;
241 1.3 mycroft u_long addr;
242 1.3 mycroft u_long mask;
243 1.1 mycroft {
244 1.1 mycroft struct vif_acl *n;
245 1.1 mycroft
246 1.1 mycroft for (n = uvifs[vifi].uv_acl; n != NULL; n = n->acl_next) {
247 1.1 mycroft if (addr == n->acl_addr && mask==n->acl_mask)
248 1.1 mycroft return n;
249 1.1 mycroft }
250 1.1 mycroft return NULL;
251 1.1 mycroft }
252 1.1 mycroft
253 1.1 mycroft /*
254 1.3 mycroft * Find the lowest boundary >= (V,A,M) spec
255 1.1 mycroft */
256 1.1 mycroft struct vif_acl *
257 1.1 mycroft next_boundary(vifi, addr, mask)
258 1.3 mycroft vifi_t *vifi;
259 1.3 mycroft u_long addr;
260 1.3 mycroft u_long mask;
261 1.1 mycroft {
262 1.1 mycroft struct vif_acl *bestn, *n;
263 1.1 mycroft int i;
264 1.1 mycroft
265 1.1 mycroft for (i = *vifi; i < numvifs; i++) {
266 1.1 mycroft bestn = NULL;
267 1.1 mycroft for (n = uvifs[i].uv_acl; n; n=n->acl_next) {
268 1.3 mycroft if ((i > *vifi || n->acl_addr > addr
269 1.3 mycroft || (n->acl_addr == addr && n->acl_mask >= mask))
270 1.3 mycroft && (!bestn || n->acl_addr < bestn->acl_addr
271 1.1 mycroft || (n->acl_addr==bestn->acl_addr && n->acl_mask<bestn->acl_mask)))
272 1.1 mycroft bestn = n;
273 1.1 mycroft }
274 1.1 mycroft if (bestn) {
275 1.1 mycroft *vifi = i;
276 1.1 mycroft return bestn;
277 1.1 mycroft }
278 1.1 mycroft }
279 1.1 mycroft return NULL;
280 1.1 mycroft }
281 1.1 mycroft
282 1.1 mycroft /*
283 1.1 mycroft * Implements the Boundary Table portion of the DVMRP MIB
284 1.1 mycroft */
285 1.3 mycroft u_char *
286 1.3 mycroft o_dvmrpBoundaryTable(vp, name, length, exact, var_len, write_method)
287 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
288 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
289 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
290 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
291 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
292 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
293 1.3 mycroft {
294 1.3 mycroft vifi_t vifi;
295 1.3 mycroft u_long addr, mask;
296 1.1 mycroft struct vif_acl *bound;
297 1.3 mycroft oid newname[MAX_NAME_LEN];
298 1.3 mycroft int len;
299 1.1 mycroft
300 1.3 mycroft /* Copy name OID to new OID */
301 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
302 1.3 mycroft
303 1.3 mycroft if (exact) {
304 1.3 mycroft if (*length != vp->namelen + 9)
305 1.3 mycroft return NULL;
306 1.3 mycroft
307 1.3 mycroft if ((vifi = name[vp->namelen]) >= numvifs)
308 1.3 mycroft return NULL;
309 1.3 mycroft
310 1.3 mycroft if (!get_address(name, *length, &addr, vp->namelen+1)
311 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+5))
312 1.3 mycroft return NULL;
313 1.1 mycroft
314 1.1 mycroft if (!(bound = find_boundary(vifi, addr, mask)))
315 1.3 mycroft return NULL;
316 1.1 mycroft
317 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
318 1.3 mycroft } else {
319 1.3 mycroft len = *length;
320 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
321 1.3 mycroft len = vp->namelen;
322 1.3 mycroft
323 1.3 mycroft if (len < vp->namelen + 9) { /* get first entry */
324 1.3 mycroft
325 1.3 mycroft if (len == vp->namelen) {
326 1.3 mycroft vifi = addr = mask = 0;
327 1.3 mycroft } else {
328 1.3 mycroft vifi = name[vp->namelen];
329 1.3 mycroft get_address(name, len, &addr, vp->namelen+1);
330 1.3 mycroft get_address(name, len, &mask, vp->namelen+5);
331 1.3 mycroft }
332 1.1 mycroft
333 1.3 mycroft bound = next_boundary(&vifi,addr,mask);
334 1.3 mycroft if (!bound)
335 1.3 mycroft return NULL;
336 1.3 mycroft
337 1.3 mycroft newname[vp->namelen] = vifi;
338 1.3 mycroft put_address(newname, bound->acl_addr, vp->namelen+1);
339 1.3 mycroft put_address(newname, bound->acl_mask, vp->namelen+5);
340 1.1 mycroft } else { /* get next entry given previous */
341 1.3 mycroft vifi = name[vp->namelen];
342 1.3 mycroft get_address(name, *length, &addr, vp->namelen+1);
343 1.3 mycroft get_address(name, *length, &mask, vp->namelen+5);
344 1.1 mycroft
345 1.1 mycroft if (!(bound = next_boundary(&vifi,addr,mask+1)))
346 1.3 mycroft return NULL;
347 1.1 mycroft
348 1.3 mycroft newname[vp->namelen] = vifi;
349 1.3 mycroft put_address(newname, bound->acl_addr, vp->namelen+1);
350 1.3 mycroft put_address(newname, bound->acl_mask, vp->namelen+5);
351 1.1 mycroft }
352 1.3 mycroft }
353 1.1 mycroft
354 1.3 mycroft /* Save new OID */
355 1.3 mycroft *length = vp->namelen + 9;
356 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
357 1.3 mycroft *write_method = 0;
358 1.3 mycroft *var_len = sizeof(long);
359 1.1 mycroft
360 1.3 mycroft switch (vp->magic) {
361 1.1 mycroft
362 1.1 mycroft case dvmrpBoundaryVifIndex:
363 1.3 mycroft long_return = vifi;
364 1.3 mycroft return (u_char *) &long_return;
365 1.1 mycroft
366 1.3 mycroft default:
367 1.3 mycroft ERROR("");
368 1.1 mycroft }
369 1.3 mycroft return NULL;
370 1.1 mycroft }
371 1.1 mycroft
372 1.3 mycroft /*
373 1.3 mycroft * Find the lowest neighbor >= (V,A) spec
374 1.1 mycroft */
375 1.1 mycroft struct listaddr *
376 1.1 mycroft next_neighbor(vifi, addr)
377 1.3 mycroft vifi_t *vifi;
378 1.3 mycroft u_long addr;
379 1.1 mycroft {
380 1.1 mycroft struct listaddr *bestn, *n;
381 1.1 mycroft int i;
382 1.1 mycroft
383 1.1 mycroft for (i = *vifi; i < numvifs; i++) {
384 1.1 mycroft bestn = NULL;
385 1.1 mycroft for (n = uvifs[i].uv_neighbors; n; n=n->al_next) {
386 1.3 mycroft if ((i > *vifi || n->al_addr >= addr)
387 1.1 mycroft && (!bestn || n->al_addr < bestn->al_addr))
388 1.1 mycroft bestn = n;
389 1.1 mycroft }
390 1.1 mycroft if (bestn) {
391 1.1 mycroft *vifi = i;
392 1.1 mycroft return bestn;
393 1.1 mycroft }
394 1.1 mycroft }
395 1.1 mycroft return NULL;
396 1.1 mycroft }
397 1.1 mycroft
398 1.1 mycroft /*
399 1.1 mycroft * Find a neighbor, if it exists off a given Vif
400 1.1 mycroft */
401 1.1 mycroft struct listaddr *
402 1.1 mycroft find_neighbor(vifi, addr)
403 1.3 mycroft vifi_t vifi;
404 1.3 mycroft u_long addr;
405 1.1 mycroft {
406 1.1 mycroft struct listaddr *n;
407 1.1 mycroft
408 1.1 mycroft for (n = uvifs[vifi].uv_neighbors; n != NULL; n = n->al_next) {
409 1.1 mycroft if (addr == n->al_addr)
410 1.1 mycroft return n;
411 1.1 mycroft }
412 1.1 mycroft return NULL;
413 1.1 mycroft }
414 1.1 mycroft
415 1.3 mycroft u_char *
416 1.3 mycroft o_dvmrpNeighborTable(vp, name, length, exact, var_len, write_method)
417 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
418 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
419 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
420 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
421 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
422 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
423 1.3 mycroft {
424 1.3 mycroft vifi_t vifi;
425 1.3 mycroft u_long addr, mask;
426 1.1 mycroft struct listaddr *neighbor;
427 1.3 mycroft oid newname[MAX_NAME_LEN];
428 1.3 mycroft int len;
429 1.1 mycroft
430 1.3 mycroft /* Copy name OID to new OID */
431 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
432 1.1 mycroft
433 1.3 mycroft if (exact) {
434 1.3 mycroft if (*length != vp->namelen + 5)
435 1.3 mycroft return NULL;
436 1.1 mycroft
437 1.3 mycroft if ((vifi = name[vp->namelen]) >= numvifs)
438 1.3 mycroft return NULL;
439 1.3 mycroft
440 1.3 mycroft if (!get_address(name, *length, &addr, vp->namelen+1))
441 1.3 mycroft return NULL;
442 1.1 mycroft
443 1.1 mycroft if (!(neighbor = find_neighbor(vifi, addr)))
444 1.3 mycroft return NULL;
445 1.1 mycroft
446 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
447 1.3 mycroft } else {
448 1.3 mycroft len = *length;
449 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
450 1.3 mycroft len = vp->namelen;
451 1.3 mycroft
452 1.3 mycroft if (len < vp->namelen + 5) { /* get first entry */
453 1.3 mycroft
454 1.3 mycroft if (len == vp->namelen) {
455 1.3 mycroft vifi = addr = 0;
456 1.3 mycroft } else {
457 1.3 mycroft vifi = name[vp->namelen];
458 1.3 mycroft get_address(name, len, &addr, vp->namelen+1);
459 1.3 mycroft }
460 1.1 mycroft
461 1.3 mycroft neighbor = next_neighbor(&vifi,addr);
462 1.3 mycroft if (!neighbor)
463 1.3 mycroft return NULL;
464 1.1 mycroft
465 1.3 mycroft newname[vp->namelen] = vifi;
466 1.3 mycroft put_address(newname, neighbor->al_addr, vp->namelen+1);
467 1.1 mycroft } else { /* get next entry given previous */
468 1.3 mycroft vifi = name[vp->namelen];
469 1.3 mycroft get_address(name, *length, &addr, vp->namelen+1);
470 1.1 mycroft
471 1.1 mycroft if (!(neighbor = next_neighbor(&vifi,addr+1)))
472 1.3 mycroft return NULL;
473 1.1 mycroft
474 1.3 mycroft newname[vp->namelen] = vifi;
475 1.3 mycroft put_address(newname, neighbor->al_addr, vp->namelen+1);
476 1.1 mycroft }
477 1.3 mycroft }
478 1.1 mycroft
479 1.3 mycroft /* Save new OID */
480 1.3 mycroft *length = vp->namelen + 5;
481 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
482 1.3 mycroft *write_method = 0;
483 1.3 mycroft *var_len = sizeof(long);
484 1.1 mycroft
485 1.3 mycroft switch (vp->magic) {
486 1.1 mycroft
487 1.1 mycroft case dvmrpNeighborUpTime: {
488 1.1 mycroft time_t currtime;
489 1.1 mycroft time(&currtime);
490 1.3 mycroft long_return = (currtime - neighbor->al_ctime)*100;
491 1.3 mycroft return (u_char *) &long_return;
492 1.1 mycroft }
493 1.1 mycroft
494 1.3 mycroft case dvmrpNeighborExpiryTime:
495 1.3 mycroft long_return = (NEIGHBOR_EXPIRE_TIME - neighbor->al_timer
496 1.3 mycroft + secs_remaining_offset()) * 100;
497 1.3 mycroft return (u_char *) &long_return;
498 1.1 mycroft
499 1.1 mycroft case dvmrpNeighborVersion: {
500 1.1 mycroft static char buff[15];
501 1.1 mycroft
502 1.11 itojun snprintf(buff, sizeof(buff), "%d.%d", neighbor->al_pv, neighbor->al_mv);
503 1.3 mycroft *var_len = strlen(buff);
504 1.3 mycroft return (u_char *)buff;
505 1.1 mycroft }
506 1.1 mycroft
507 1.3 mycroft case dvmrpNeighborGenerationId:
508 1.3 mycroft long_return = neighbor->al_genid;
509 1.3 mycroft return (u_char *) &long_return;
510 1.3 mycroft
511 1.3 mycroft default:
512 1.3 mycroft ERROR("");
513 1.3 mycroft }
514 1.3 mycroft return NULL;
515 1.3 mycroft }
516 1.3 mycroft
517 1.3 mycroft /* Look up ifIndex given uvifs[ifnum].uv_lcl_addr */
518 1.3 mycroft struct in_ifaddr * /* returns: in_ifaddr structure, or null on error */
519 1.3 mycroft ipaddr_to_ifindex(ipaddr, ifIndex)
520 1.3 mycroft u_long ipaddr;
521 1.3 mycroft int *ifIndex;
522 1.3 mycroft {
523 1.3 mycroft int interface;
524 1.3 mycroft static struct in_ifaddr in_ifaddr;
525 1.3 mycroft
526 1.3 mycroft Interface_Scan_Init();
527 1.3 mycroft for (;;) {
528 1.3 mycroft if (Interface_Scan_Next(&interface, (char *)0, NULL, &in_ifaddr) == 0)
529 1.3 mycroft return NULL;
530 1.3 mycroft
531 1.3 mycroft if (((struct sockaddr_in *) &(in_ifaddr.ia_addr))->sin_addr.s_addr
532 1.3 mycroft == ipaddr) {
533 1.3 mycroft *ifIndex = interface;
534 1.3 mycroft return &in_ifaddr;
535 1.3 mycroft }
536 1.3 mycroft }
537 1.3 mycroft }
538 1.3 mycroft
539 1.3 mycroft /*
540 1.3 mycroft * Find if a specific scoped boundary exists on a Vif
541 1.3 mycroft */
542 1.3 mycroft struct listaddr *
543 1.3 mycroft find_cache(grp, vifi)
544 1.3 mycroft u_long grp;
545 1.3 mycroft vifi_t vifi;
546 1.3 mycroft {
547 1.3 mycroft struct listaddr *n;
548 1.3 mycroft
549 1.3 mycroft for (n = uvifs[vifi].uv_groups; n != NULL; n = n->al_next) {
550 1.3 mycroft if (grp == n->al_addr)
551 1.3 mycroft return n;
552 1.3 mycroft }
553 1.3 mycroft return NULL;
554 1.3 mycroft }
555 1.3 mycroft
556 1.3 mycroft /*
557 1.3 mycroft * Find the next group cache entry >= (A,V) spec
558 1.3 mycroft */
559 1.3 mycroft struct listaddr *
560 1.3 mycroft next_cache(addr, vifi)
561 1.3 mycroft u_long addr;
562 1.3 mycroft vifi_t *vifi;
563 1.3 mycroft {
564 1.3 mycroft struct listaddr *bestn=NULL, *n;
565 1.3 mycroft int i, besti;
566 1.3 mycroft
567 1.3 mycroft /* Step through all entries looking for the next one */
568 1.3 mycroft for (i = 0; i < numvifs; i++) {
569 1.3 mycroft for (n = uvifs[i].uv_groups; n; n=n->al_next) {
570 1.3 mycroft if ((n->al_addr > addr || (n->al_addr == addr && i >= *vifi))
571 1.3 mycroft && (!bestn || n->al_addr < bestn->al_addr
572 1.3 mycroft || (n->al_addr == bestn->al_addr && i < besti))) {
573 1.3 mycroft bestn = n;
574 1.3 mycroft besti = i;
575 1.3 mycroft }
576 1.3 mycroft }
577 1.3 mycroft }
578 1.3 mycroft
579 1.3 mycroft if (bestn) {
580 1.3 mycroft *vifi = besti;
581 1.3 mycroft return bestn;
582 1.3 mycroft }
583 1.3 mycroft return NULL;
584 1.3 mycroft }
585 1.3 mycroft
586 1.3 mycroft /*
587 1.3 mycroft * Implements the IGMP Cache Table portion of the IGMP MIB
588 1.3 mycroft */
589 1.3 mycroft u_char *
590 1.3 mycroft o_igmpCacheTable(vp, name, length, exact, var_len, write_method)
591 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
592 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
593 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
594 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
595 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
596 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
597 1.3 mycroft {
598 1.3 mycroft vifi_t vifi;
599 1.3 mycroft u_long grp;
600 1.3 mycroft int ifIndex;
601 1.3 mycroft struct listaddr *cache;
602 1.3 mycroft oid newname[MAX_NAME_LEN];
603 1.3 mycroft int len;
604 1.3 mycroft struct in_ifaddr *in_ifaddr;
605 1.3 mycroft struct in_multi in_multi, *inm;
606 1.3 mycroft
607 1.3 mycroft /* Copy name OID to new OID */
608 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
609 1.3 mycroft
610 1.3 mycroft if (exact) {
611 1.3 mycroft if (*length != vp->namelen + 5)
612 1.3 mycroft return NULL;
613 1.3 mycroft
614 1.3 mycroft if ((vifi = name[vp->namelen+4]) >= numvifs)
615 1.3 mycroft return NULL;
616 1.3 mycroft
617 1.3 mycroft if (!get_address(name, *length, &grp, vp->namelen))
618 1.3 mycroft return NULL;
619 1.3 mycroft
620 1.3 mycroft if (!(cache = find_cache(grp, vifi)))
621 1.3 mycroft return NULL;
622 1.3 mycroft
623 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
624 1.3 mycroft } else {
625 1.3 mycroft len = *length;
626 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
627 1.3 mycroft len = vp->namelen;
628 1.3 mycroft
629 1.3 mycroft if (len < vp->namelen + 5) { /* get first entry */
630 1.3 mycroft
631 1.3 mycroft if (len == vp->namelen) {
632 1.3 mycroft vifi = grp = 0;
633 1.3 mycroft } else {
634 1.3 mycroft get_address(name, len, &grp, vp->namelen);
635 1.3 mycroft vifi = name[vp->namelen+4];
636 1.3 mycroft }
637 1.3 mycroft
638 1.3 mycroft cache = next_cache(grp,&vifi);
639 1.3 mycroft if (!cache)
640 1.3 mycroft return NULL;
641 1.3 mycroft
642 1.3 mycroft put_address(newname, cache->al_addr, vp->namelen);
643 1.3 mycroft newname[vp->namelen+4] = vifi;
644 1.3 mycroft } else { /* get next entry given previous */
645 1.3 mycroft get_address(name, *length, &grp, vp->namelen);
646 1.3 mycroft vifi = name[vp->namelen+4]+1;
647 1.3 mycroft
648 1.3 mycroft if (!(cache = next_cache(grp,&vifi)))
649 1.3 mycroft return NULL;
650 1.3 mycroft
651 1.3 mycroft put_address(newname, cache->al_addr, vp->namelen);
652 1.3 mycroft newname[vp->namelen+4] = vifi;
653 1.3 mycroft }
654 1.3 mycroft }
655 1.3 mycroft
656 1.3 mycroft /* Save new OID */
657 1.3 mycroft *length = vp->namelen + 5;
658 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
659 1.3 mycroft *write_method = 0;
660 1.3 mycroft *var_len = sizeof(long);
661 1.3 mycroft
662 1.3 mycroft /* Look up ifIndex given uvifs[vifi].uv_lcl_addr */
663 1.3 mycroft in_ifaddr = ipaddr_to_ifindex(uvifs[vifi].uv_lcl_addr, &ifIndex);
664 1.3 mycroft
665 1.3 mycroft switch (vp->magic) {
666 1.3 mycroft
667 1.3 mycroft case igmpCacheSelf:
668 1.3 mycroft inm = in_ifaddr->ia_multiaddrs;
669 1.3 mycroft while (inm) {
670 1.3 mycroft klookup( (int)inm, (char *)&in_multi, sizeof(in_multi));
671 1.3 mycroft
672 1.3 mycroft if (in_multi.inm_addr.s_addr == cache->al_addr) {
673 1.3 mycroft long_return = 1; /* true */
674 1.3 mycroft return (u_char *) &long_return;
675 1.3 mycroft }
676 1.3 mycroft
677 1.3 mycroft inm = in_multi.inm_next;
678 1.3 mycroft }
679 1.3 mycroft long_return = 2; /* false */
680 1.3 mycroft return (u_char *) &long_return;
681 1.3 mycroft
682 1.3 mycroft case igmpCacheLastReporter:
683 1.3 mycroft return (u_char *) &cache->al_genid;
684 1.3 mycroft
685 1.3 mycroft case igmpCacheUpTime: {
686 1.3 mycroft time_t currtime;
687 1.3 mycroft time(&currtime);
688 1.3 mycroft long_return = (currtime - cache->al_ctime)*100;
689 1.3 mycroft return (u_char *) &long_return;
690 1.3 mycroft }
691 1.3 mycroft
692 1.3 mycroft case igmpCacheExpiryTime:
693 1.3 mycroft long_return = secs_remaining(cache->al_timerid)*100;
694 1.3 mycroft return (u_char *) &long_return;
695 1.3 mycroft
696 1.3 mycroft case igmpCacheStatus:
697 1.3 mycroft long_return = 1;
698 1.3 mycroft return (u_char *) &long_return;
699 1.3 mycroft
700 1.3 mycroft default:
701 1.3 mycroft ERROR("");
702 1.3 mycroft }
703 1.3 mycroft return NULL;
704 1.3 mycroft }
705 1.3 mycroft
706 1.3 mycroft /*
707 1.3 mycroft * Implements the IGMP Interface Table portion of the IGMP MIB
708 1.3 mycroft */
709 1.3 mycroft u_char *
710 1.3 mycroft o_igmpInterfaceTable(vp, name, length, exact, var_len, write_method)
711 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
712 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
713 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
714 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
715 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
716 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
717 1.3 mycroft {
718 1.3 mycroft oid newname[MAX_NAME_LEN];
719 1.6 wiz int ifnum;
720 1.3 mycroft int result;
721 1.3 mycroft static struct sioc_vif_req v_req;
722 1.3 mycroft
723 1.3 mycroft /* Copy name OID to new OID */
724 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
725 1.3 mycroft
726 1.3 mycroft /* find "next" interface */
727 1.3 mycroft for(ifnum = 0; ifnum < numvifs; ifnum++){
728 1.3 mycroft if (!(uvifs[ifnum].uv_flags & VIFF_QUERIER))
729 1.3 mycroft continue;
730 1.3 mycroft newname[vp->namelen] = (oid)ifnum;
731 1.3 mycroft result = compare(name, *length, newname, (int)vp->namelen + 1);
732 1.3 mycroft if ((exact && (result == 0)) || (!exact && (result < 0)))
733 1.3 mycroft break;
734 1.3 mycroft }
735 1.3 mycroft if (ifnum >= numvifs)
736 1.3 mycroft return NULL;
737 1.3 mycroft
738 1.3 mycroft /* Save new OID */
739 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
740 1.3 mycroft *length = vp->namelen + 1;
741 1.3 mycroft *write_method = 0;
742 1.3 mycroft *var_len = sizeof(long);
743 1.3 mycroft
744 1.3 mycroft switch (vp->magic){
745 1.3 mycroft
746 1.3 mycroft case igmpInterfaceQueryInterval:
747 1.3 mycroft long_return = GROUP_QUERY_INTERVAL;
748 1.3 mycroft return (u_char *) &long_return;
749 1.3 mycroft
750 1.3 mycroft case igmpInterfaceStatus:
751 1.3 mycroft long_return = 1; /* active */
752 1.3 mycroft return (u_char *) &long_return;
753 1.1 mycroft
754 1.1 mycroft default:
755 1.3 mycroft ERROR("");
756 1.1 mycroft }
757 1.3 mycroft return NULL;
758 1.1 mycroft }
759 1.1 mycroft
760 1.1 mycroft /*
761 1.1 mycroft * Given a virtual interface number, make sure we have the current
762 1.1 mycroft * kernel information for that Vif.
763 1.1 mycroft */
764 1.1 mycroft refresh_vif(v_req, ifnum)
765 1.1 mycroft struct sioc_vif_req *v_req;
766 1.1 mycroft int ifnum;
767 1.1 mycroft {
768 1.1 mycroft static int lastq = -1;
769 1.1 mycroft
770 1.1 mycroft if (quantum!=lastq || v_req->vifi != ifnum) {
771 1.1 mycroft lastq = quantum;
772 1.1 mycroft v_req->vifi = ifnum;
773 1.4 hwr if (ioctl(igmp_socket, SIOCGETVIFCNT, (char *)v_req) < 0)
774 1.1 mycroft v_req->icount = v_req->ocount = v_req->ibytes = v_req->obytes = 0;
775 1.1 mycroft }
776 1.1 mycroft }
777 1.1 mycroft
778 1.1 mycroft /*
779 1.1 mycroft * Implements the Multicast Routing Interface Table portion of the Multicast MIB
780 1.1 mycroft */
781 1.3 mycroft u_char *
782 1.3 mycroft o_ipMRouteInterfaceTable(vp, name, length, exact, var_len, write_method)
783 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
784 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
785 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
786 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
787 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
788 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
789 1.3 mycroft {
790 1.3 mycroft oid newname[MAX_NAME_LEN];
791 1.6 wiz int ifnum;
792 1.3 mycroft int result;
793 1.1 mycroft static struct sioc_vif_req v_req;
794 1.1 mycroft
795 1.3 mycroft /* Copy name OID to new OID */
796 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
797 1.1 mycroft
798 1.3 mycroft /* find "next" interface */
799 1.3 mycroft for(ifnum = 0; ifnum < numvifs; ifnum++){
800 1.3 mycroft newname[vp->namelen] = (oid)ifnum;
801 1.3 mycroft result = compare(name, *length, newname, (int)vp->namelen + 1);
802 1.3 mycroft if ((exact && (result == 0)) || (!exact && (result < 0)))
803 1.1 mycroft break;
804 1.1 mycroft }
805 1.3 mycroft if (ifnum >= numvifs)
806 1.3 mycroft return NULL;
807 1.1 mycroft
808 1.3 mycroft /* Save new OID */
809 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)vp->namelen + 1) * sizeof(oid));
810 1.3 mycroft *length = vp->namelen + 1;
811 1.3 mycroft *write_method = 0;
812 1.3 mycroft *var_len = sizeof(long);
813 1.3 mycroft
814 1.3 mycroft switch (vp->magic){
815 1.3 mycroft
816 1.3 mycroft case ipMRouteInterfaceTtl:
817 1.3 mycroft long_return = uvifs[ifnum].uv_threshold;
818 1.3 mycroft return (u_char *) &long_return;
819 1.1 mycroft
820 1.3 mycroft case dvmrpVInterfaceType:
821 1.1 mycroft if (uvifs[ifnum].uv_flags & VIFF_SRCRT)
822 1.3 mycroft long_return = 2;
823 1.1 mycroft else if (uvifs[ifnum].uv_flags & VIFF_TUNNEL)
824 1.3 mycroft long_return = 1;
825 1.1 mycroft else if (uvifs[ifnum].uv_flags & VIFF_QUERIER)
826 1.3 mycroft long_return = 3;
827 1.1 mycroft else /* SUBNET */
828 1.3 mycroft long_return = 4;
829 1.3 mycroft return (u_char *) &long_return;
830 1.1 mycroft
831 1.3 mycroft case dvmrpVInterfaceState:
832 1.1 mycroft if (uvifs[ifnum].uv_flags & VIFF_DISABLED)
833 1.3 mycroft long_return = 3;
834 1.3 mycroft else if ((uvifs[ifnum].uv_flags & VIFF_DOWN)
835 1.3 mycroft || ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) && (uvifs[ifnum].uv_neighbors==NULL)))
836 1.3 mycroft long_return = 2;
837 1.1 mycroft else /* UP */
838 1.3 mycroft long_return = 1;
839 1.3 mycroft return (u_char *) &long_return;
840 1.1 mycroft
841 1.3 mycroft case dvmrpVInterfaceLocalAddress:
842 1.3 mycroft return (u_char *) &uvifs[ifnum].uv_lcl_addr;
843 1.1 mycroft
844 1.3 mycroft case dvmrpVInterfaceRemoteAddress:
845 1.3 mycroft return (u_char *) ((uvifs[ifnum].uv_flags & VIFF_TUNNEL) ?
846 1.3 mycroft &uvifs[ifnum].uv_rmt_addr :
847 1.3 mycroft &uvifs[ifnum].uv_subnet);
848 1.1 mycroft
849 1.3 mycroft case dvmrpVInterfaceRemoteSubnetMask:
850 1.3 mycroft return (u_char *) &uvifs[ifnum].uv_subnetmask;
851 1.1 mycroft
852 1.3 mycroft case dvmrpVInterfaceMetric:
853 1.3 mycroft long_return = uvifs[ifnum].uv_metric;
854 1.3 mycroft return (u_char *) &long_return;
855 1.1 mycroft
856 1.3 mycroft case dvmrpVInterfaceRateLimit:
857 1.3 mycroft long_return = uvifs[ifnum].uv_rate_limit;
858 1.3 mycroft return (u_char *) &long_return;
859 1.1 mycroft
860 1.3 mycroft case dvmrpVInterfaceInPkts:
861 1.1 mycroft refresh_vif(&v_req, ifnum);
862 1.3 mycroft long_return = v_req.icount;
863 1.3 mycroft return (u_char *) &long_return;
864 1.1 mycroft
865 1.3 mycroft case dvmrpVInterfaceOutPkts:
866 1.1 mycroft refresh_vif(&v_req, ifnum);
867 1.3 mycroft long_return = v_req.ocount;
868 1.3 mycroft return (u_char *) &long_return;
869 1.1 mycroft
870 1.3 mycroft case dvmrpVInterfaceInOctets:
871 1.1 mycroft refresh_vif(&v_req, ifnum);
872 1.3 mycroft long_return = v_req.ibytes;
873 1.3 mycroft return (u_char *) &long_return;
874 1.1 mycroft
875 1.3 mycroft case dvmrpVInterfaceOutOctets:
876 1.1 mycroft refresh_vif(&v_req, ifnum);
877 1.3 mycroft long_return = v_req.obytes;
878 1.3 mycroft return (u_char *) &long_return;
879 1.1 mycroft
880 1.1 mycroft default:
881 1.3 mycroft ERROR("");
882 1.1 mycroft }
883 1.3 mycroft return NULL;
884 1.1 mycroft }
885 1.1 mycroft
886 1.1 mycroft /*
887 1.3 mycroft * Implements the DVMRP Route Table portion of the DVMRP MIB
888 1.1 mycroft */
889 1.3 mycroft u_char *
890 1.3 mycroft o_dvmrpRouteTable(vp, name, length, exact, var_len, write_method)
891 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
892 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
893 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
894 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
895 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
896 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
897 1.3 mycroft {
898 1.3 mycroft u_long src, mask;
899 1.3 mycroft oid newname[MAX_NAME_LEN];
900 1.3 mycroft int len;
901 1.3 mycroft struct rtentry *rt = NULL;
902 1.1 mycroft
903 1.3 mycroft /* Copy name OID to new OID */
904 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
905 1.1 mycroft
906 1.3 mycroft if (exact) {
907 1.3 mycroft if (*length != vp->namelen + 8)
908 1.3 mycroft return NULL;
909 1.3 mycroft
910 1.3 mycroft if (!get_address(name, *length, &src, vp->namelen)
911 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+4))
912 1.3 mycroft return NULL;
913 1.3 mycroft
914 1.3 mycroft if (!(rt = snmp_find_route(src, mask)))
915 1.3 mycroft return NULL;
916 1.3 mycroft
917 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
918 1.3 mycroft } else {
919 1.3 mycroft len = *length;
920 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
921 1.3 mycroft len = vp->namelen;
922 1.3 mycroft
923 1.3 mycroft if (len < vp->namelen + 8) { /* get first entry */
924 1.3 mycroft
925 1.3 mycroft if (len == vp->namelen) {
926 1.3 mycroft src = mask = 0;
927 1.3 mycroft } else {
928 1.3 mycroft get_address(name, len, &src, vp->namelen);
929 1.3 mycroft get_address(name, len, &mask, vp->namelen+4);
930 1.3 mycroft }
931 1.1 mycroft
932 1.3 mycroft if (!next_route(&rt,src,mask)) /* Get first entry */
933 1.3 mycroft return NULL;
934 1.1 mycroft
935 1.3 mycroft put_address(newname, rt->rt_origin , vp->namelen);
936 1.3 mycroft put_address(newname, rt->rt_originmask, vp->namelen+4);
937 1.3 mycroft } else { /* get next entry given previous */
938 1.3 mycroft get_address(name, *length, &src, vp->namelen);
939 1.3 mycroft get_address(name, *length, &mask, vp->namelen+4);
940 1.1 mycroft
941 1.3 mycroft if (!next_route(&rt, src,mask))
942 1.3 mycroft return NULL;
943 1.1 mycroft
944 1.3 mycroft put_address(newname, rt->rt_origin, vp->namelen);
945 1.3 mycroft put_address(newname, rt->rt_originmask, vp->namelen+4);
946 1.3 mycroft }
947 1.1 mycroft }
948 1.1 mycroft
949 1.3 mycroft /* Save new OID */
950 1.3 mycroft *length = vp->namelen + 8;
951 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
952 1.3 mycroft *write_method = 0;
953 1.3 mycroft *var_len = sizeof(long);
954 1.1 mycroft
955 1.3 mycroft switch (vp->magic) {
956 1.1 mycroft
957 1.3 mycroft case dvmrpRouteUpstreamNeighbor:
958 1.3 mycroft return (u_char *) &rt->rt_gateway;
959 1.1 mycroft
960 1.1 mycroft case dvmrpRouteInVifIndex:
961 1.3 mycroft long_return = rt->rt_parent;
962 1.3 mycroft return (u_char *) &long_return;
963 1.1 mycroft
964 1.1 mycroft case dvmrpRouteMetric:
965 1.3 mycroft long_return = rt->rt_metric;
966 1.3 mycroft return (u_char *) &long_return;
967 1.1 mycroft
968 1.1 mycroft case dvmrpRouteExpiryTime:
969 1.3 mycroft long_return = (ROUTE_EXPIRE_TIME - rt->rt_timer
970 1.3 mycroft + secs_remaining_offset()) * 100;
971 1.3 mycroft return (u_char *) &long_return;
972 1.1 mycroft
973 1.3 mycroft default:
974 1.3 mycroft ERROR("");
975 1.3 mycroft }
976 1.3 mycroft return NULL;
977 1.1 mycroft }
978 1.1 mycroft
979 1.3 mycroft /*
980 1.3 mycroft * Implements the DVMRP Routing Next Hop Table portion of the DVMRP MIB
981 1.1 mycroft */
982 1.3 mycroft u_char *
983 1.3 mycroft o_dvmrpRouteNextHopTable(vp, name, length, exact, var_len, write_method)
984 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
985 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
986 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
987 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
988 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
989 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
990 1.1 mycroft {
991 1.3 mycroft u_long src, mask;
992 1.3 mycroft vifi_t vifi;
993 1.1 mycroft struct rtentry *rt = NULL;
994 1.3 mycroft oid newname[MAX_NAME_LEN];
995 1.3 mycroft int len;
996 1.3 mycroft
997 1.3 mycroft /* Copy name OID to new OID */
998 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
999 1.1 mycroft
1000 1.3 mycroft if (exact) {
1001 1.3 mycroft if (*length != vp->namelen + 9)
1002 1.3 mycroft return NULL;
1003 1.1 mycroft
1004 1.3 mycroft if (!get_address(name, *length, &src, vp->namelen)
1005 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+4)
1006 1.1 mycroft || (!(rt=snmp_find_route(src,mask))))
1007 1.3 mycroft return NULL;
1008 1.1 mycroft
1009 1.3 mycroft vifi = name[vp->namelen+8];
1010 1.1 mycroft if (!(VIFM_ISSET(vifi, rt->rt_children)))
1011 1.3 mycroft return NULL;
1012 1.1 mycroft
1013 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1014 1.3 mycroft } else {
1015 1.3 mycroft len = *length;
1016 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
1017 1.3 mycroft len = vp->namelen;
1018 1.1 mycroft
1019 1.3 mycroft if (len < vp->namelen + 9) { /* get first entry */
1020 1.1 mycroft
1021 1.3 mycroft get_address(name, len, &src, vp->namelen);
1022 1.3 mycroft get_address(name, len, &mask, vp->namelen+4);
1023 1.1 mycroft
1024 1.1 mycroft /* Find first child vif */
1025 1.1 mycroft vifi=0;
1026 1.1 mycroft if (!next_route_child(&rt, src, mask, &vifi))
1027 1.3 mycroft return NULL;
1028 1.1 mycroft
1029 1.3 mycroft put_address(newname, rt->rt_origin, vp->namelen);
1030 1.3 mycroft put_address(newname, rt->rt_originmask, vp->namelen+4);
1031 1.3 mycroft newname[vp->namelen+8] = vifi;
1032 1.3 mycroft } else { /* get next entry given previous */
1033 1.3 mycroft vifi = name[vp->namelen+8] + 1;
1034 1.3 mycroft if (!get_address(name, *length, &src, vp->namelen)
1035 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+4)
1036 1.1 mycroft || !next_route_child(&rt, src, mask, &vifi))
1037 1.3 mycroft return NULL;
1038 1.1 mycroft
1039 1.3 mycroft put_address(newname, rt->rt_origin, vp->namelen);
1040 1.3 mycroft put_address(newname, rt->rt_originmask, vp->namelen+4);
1041 1.3 mycroft newname[vp->namelen+8] = vifi;
1042 1.3 mycroft }
1043 1.3 mycroft }
1044 1.1 mycroft
1045 1.3 mycroft /* Save new OID */
1046 1.3 mycroft *length = vp->namelen + 9;
1047 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1048 1.3 mycroft *write_method = 0;
1049 1.3 mycroft *var_len = sizeof(long);
1050 1.3 mycroft
1051 1.3 mycroft switch (vp->magic) {
1052 1.3 mycroft
1053 1.3 mycroft case dvmrpRouteNextHopType:
1054 1.3 mycroft long_return = (VIFM_ISSET(vifi, rt->rt_leaves))? 1 : 2;
1055 1.3 mycroft return (u_char *) &long_return;
1056 1.1 mycroft
1057 1.3 mycroft default:
1058 1.3 mycroft ERROR("");
1059 1.3 mycroft }
1060 1.3 mycroft return NULL;
1061 1.1 mycroft }
1062 1.1 mycroft
1063 1.3 mycroft /*
1064 1.3 mycroft * Implements the IP Multicast Route Table portion of the Multicast MIB
1065 1.1 mycroft */
1066 1.3 mycroft u_char *
1067 1.3 mycroft o_ipMRouteTable(vp, name, length, exact, var_len, write_method)
1068 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
1069 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
1070 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
1071 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
1072 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
1073 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
1074 1.1 mycroft {
1075 1.1 mycroft u_long src, grp, mask;
1076 1.1 mycroft struct gtable *gt = NULL;
1077 1.1 mycroft struct stable *st = NULL;
1078 1.1 mycroft static struct sioc_sg_req sg_req;
1079 1.3 mycroft oid newname[MAX_NAME_LEN];
1080 1.3 mycroft int len;
1081 1.1 mycroft
1082 1.3 mycroft /* Copy name OID to new OID */
1083 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1084 1.3 mycroft
1085 1.3 mycroft if (exact) {
1086 1.3 mycroft if (*length != vp->namelen + 12)
1087 1.3 mycroft return NULL;
1088 1.3 mycroft
1089 1.3 mycroft if (!get_address(name, *length, &grp, vp->namelen)
1090 1.3 mycroft || !get_address(name, *length, &src, vp->namelen+4)
1091 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+8)
1092 1.1 mycroft || (mask != 0xFFFFFFFF) /* we keep sources now, not subnets */
1093 1.1 mycroft || !(gt = find_grp(grp))
1094 1.1 mycroft || !(st = find_grp_src(gt,src)))
1095 1.3 mycroft return NULL;
1096 1.1 mycroft
1097 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1098 1.3 mycroft } else {
1099 1.3 mycroft len = *length;
1100 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
1101 1.3 mycroft len = vp->namelen;
1102 1.3 mycroft
1103 1.3 mycroft if (len < vp->namelen + 12) { /* get first entry */
1104 1.3 mycroft
1105 1.3 mycroft get_address(name, len, &grp, vp->namelen);
1106 1.3 mycroft get_address(name, len, &src, vp->namelen+4);
1107 1.3 mycroft get_address(name, len, &mask, vp->namelen+8);
1108 1.1 mycroft
1109 1.3 mycroft if (!next_grp_src_mask(>,&st,grp,src,mask)) /* Get first entry */
1110 1.3 mycroft return NULL;
1111 1.1 mycroft
1112 1.3 mycroft put_address(newname, gt->gt_mcastgrp, vp->namelen);
1113 1.3 mycroft put_address(newname, st->st_origin, vp->namelen+4);
1114 1.3 mycroft put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1115 1.3 mycroft } else { /* get next entry given previous */
1116 1.3 mycroft get_address(name, *length, &grp , vp->namelen);
1117 1.3 mycroft get_address(name, *length, &src , vp->namelen+4);
1118 1.3 mycroft get_address(name, *length, &mask, vp->namelen+8);
1119 1.1 mycroft
1120 1.1 mycroft if (!next_grp_src_mask(>, &st, grp,src,mask))
1121 1.3 mycroft return NULL;
1122 1.3 mycroft
1123 1.3 mycroft put_address(newname, gt->gt_mcastgrp, vp->namelen);
1124 1.3 mycroft put_address(newname, st->st_origin, vp->namelen+4);
1125 1.3 mycroft put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1126 1.3 mycroft }
1127 1.3 mycroft }
1128 1.1 mycroft
1129 1.3 mycroft /* Save new OID */
1130 1.3 mycroft *length = vp->namelen + 12;
1131 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1132 1.3 mycroft *write_method = 0;
1133 1.3 mycroft *var_len = sizeof(long);
1134 1.1 mycroft
1135 1.3 mycroft switch (vp->magic) {
1136 1.1 mycroft
1137 1.3 mycroft case ipMRouteUpstreamNeighbor:
1138 1.3 mycroft return (u_char *) >->gt_route->rt_gateway;
1139 1.1 mycroft
1140 1.1 mycroft case ipMRouteInIfIndex:
1141 1.3 mycroft long_return = gt->gt_route->rt_parent;
1142 1.3 mycroft return (u_char *) &long_return;
1143 1.1 mycroft
1144 1.1 mycroft case ipMRouteUpTime: {
1145 1.1 mycroft time_t currtime;
1146 1.1 mycroft time(&currtime);
1147 1.3 mycroft long_return = (currtime - gt->gt_ctime)*100;
1148 1.3 mycroft return (u_char *) &long_return;
1149 1.1 mycroft }
1150 1.1 mycroft
1151 1.1 mycroft case ipMRouteExpiryTime:
1152 1.3 mycroft long_return = 5*((gt->gt_timer+4)/5); /* round up to nearest 5 */
1153 1.3 mycroft long_return = (long_return + secs_remaining_offset()) * 100;
1154 1.3 mycroft return (u_char *) &long_return;
1155 1.1 mycroft
1156 1.1 mycroft case ipMRoutePkts:
1157 1.1 mycroft refresh_sg(&sg_req, gt, st);
1158 1.3 mycroft long_return = sg_req.pktcnt;
1159 1.3 mycroft return (u_char *) &long_return;
1160 1.3 mycroft
1161 1.1 mycroft case ipMRouteOctets:
1162 1.1 mycroft refresh_sg(&sg_req, gt, st);
1163 1.3 mycroft long_return = sg_req.bytecnt;
1164 1.3 mycroft return (u_char *) &long_return;
1165 1.1 mycroft
1166 1.1 mycroft case ipMRouteDifferentInIfIndexes:
1167 1.1 mycroft refresh_sg(&sg_req, gt, st);
1168 1.3 mycroft long_return = sg_req.wrong_if;
1169 1.3 mycroft return (u_char *) &long_return;
1170 1.1 mycroft
1171 1.1 mycroft case ipMRouteProtocol:
1172 1.3 mycroft long_return = 4;
1173 1.3 mycroft return (u_char *) &long_return;
1174 1.1 mycroft
1175 1.3 mycroft default:
1176 1.3 mycroft ERROR("");
1177 1.3 mycroft }
1178 1.3 mycroft return NULL;
1179 1.1 mycroft }
1180 1.1 mycroft
1181 1.3 mycroft /*
1182 1.1 mycroft * Implements the IP Multicast Routing Next Hop Table portion of the Multicast
1183 1.3 mycroft * MIB
1184 1.1 mycroft */
1185 1.3 mycroft u_char *
1186 1.3 mycroft o_ipMRouteNextHopTable(vp, name, length, exact, var_len, write_method)
1187 1.6 wiz struct variable *vp; /* IN - pointer to variable entry that points here */
1188 1.6 wiz oid *name; /* IN/OUT - input name requested, output name found */
1189 1.6 wiz int *length; /* IN/OUT - length of input and output oid's */
1190 1.3 mycroft int exact; /* IN - TRUE if an exact match was requested. */
1191 1.3 mycroft int *var_len; /* OUT - length of variable or 0 if function returned. */
1192 1.3 mycroft int (**write_method)(); /* OUT - pointer to function to set variable, otherwise 0 */
1193 1.1 mycroft {
1194 1.1 mycroft u_long src, grp, mask, addr;
1195 1.1 mycroft vifi_t vifi;
1196 1.1 mycroft struct gtable *gt;
1197 1.1 mycroft struct stable *st;
1198 1.3 mycroft oid newname[MAX_NAME_LEN];
1199 1.3 mycroft int len;
1200 1.1 mycroft
1201 1.3 mycroft /* Copy name OID to new OID */
1202 1.3 mycroft bcopy((char *)vp->name, (char *)newname, (int)vp->namelen * sizeof(oid));
1203 1.3 mycroft
1204 1.3 mycroft if (exact) {
1205 1.3 mycroft if (*length != vp->namelen + 17)
1206 1.3 mycroft return NULL;
1207 1.3 mycroft
1208 1.3 mycroft if (!get_address(name, *length, &grp, vp->namelen)
1209 1.3 mycroft || !get_address(name, *length, &src, vp->namelen+4)
1210 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+8)
1211 1.3 mycroft || !get_address(name, *length, &addr, vp->namelen+13)
1212 1.1 mycroft || grp!=addr
1213 1.1 mycroft || mask!=0xFFFFFFFF
1214 1.1 mycroft || (!(gt=find_grp(grp)))
1215 1.1 mycroft || (!(st=find_grp_src(gt,src))))
1216 1.3 mycroft return NULL;
1217 1.1 mycroft
1218 1.3 mycroft vifi = name[vp->namelen+12];
1219 1.1 mycroft if (!(VIFM_ISSET(vifi, gt->gt_route->rt_children)))
1220 1.3 mycroft return NULL;
1221 1.1 mycroft
1222 1.3 mycroft bcopy((char *)name, (char *)newname, ((int)*length) * sizeof(oid));
1223 1.3 mycroft } else {
1224 1.3 mycroft len = *length;
1225 1.3 mycroft if (compare(name, *length, vp->name, vp->namelen) < 0)
1226 1.3 mycroft len = vp->namelen;
1227 1.3 mycroft
1228 1.3 mycroft if (len < vp->namelen + 17) { /* get first entry */
1229 1.3 mycroft
1230 1.3 mycroft get_address(name, len, &grp, vp->namelen);
1231 1.3 mycroft get_address(name, len, &src, vp->namelen+4);
1232 1.3 mycroft get_address(name, len, &mask, vp->namelen+8);
1233 1.1 mycroft
1234 1.1 mycroft /* Find first child vif */
1235 1.1 mycroft vifi=0;
1236 1.1 mycroft if (!next_child(>, &st, grp, src, mask, &vifi))
1237 1.3 mycroft return NULL;
1238 1.3 mycroft
1239 1.3 mycroft put_address(newname, gt->gt_mcastgrp, vp->namelen);
1240 1.3 mycroft put_address(newname, st->st_origin, vp->namelen+4);
1241 1.3 mycroft put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1242 1.3 mycroft newname[vp->namelen+12] = vifi;
1243 1.3 mycroft put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
1244 1.1 mycroft
1245 1.3 mycroft } else { /* get next entry given previous */
1246 1.3 mycroft vifi = name[vp->namelen+12]+1;
1247 1.3 mycroft if (!get_address(name, *length, &grp, vp->namelen)
1248 1.3 mycroft || !get_address(name, *length, &src, vp->namelen+4)
1249 1.3 mycroft || !get_address(name, *length, &mask, vp->namelen+8)
1250 1.1 mycroft || !next_child(>, &st, grp, src, mask, &vifi))
1251 1.3 mycroft return NULL;
1252 1.1 mycroft
1253 1.3 mycroft put_address(newname, gt->gt_mcastgrp, vp->namelen);
1254 1.3 mycroft put_address(newname, st->st_origin, vp->namelen+4);
1255 1.3 mycroft put_address(newname, 0xFFFFFFFF, vp->namelen+8);
1256 1.3 mycroft newname[vp->namelen+12] = vifi;
1257 1.3 mycroft put_address(newname, gt->gt_mcastgrp, vp->namelen+13);
1258 1.3 mycroft }
1259 1.3 mycroft }
1260 1.1 mycroft
1261 1.3 mycroft /* Save new OID */
1262 1.3 mycroft *length = vp->namelen + 17;
1263 1.3 mycroft bcopy((char *)newname, (char *)name, ((int)*length) * sizeof(oid));
1264 1.3 mycroft *write_method = 0;
1265 1.3 mycroft *var_len = sizeof(long);
1266 1.1 mycroft
1267 1.3 mycroft switch (vp->magic) {
1268 1.1 mycroft
1269 1.1 mycroft case ipMRouteNextHopState:
1270 1.3 mycroft long_return = (VIFM_ISSET(vifi, gt->gt_grpmems))? 2 : 1;
1271 1.3 mycroft return (u_char *) &long_return;
1272 1.1 mycroft
1273 1.1 mycroft /* Currently equal to ipMRouteUpTime */
1274 1.1 mycroft case ipMRouteNextHopUpTime: {
1275 1.1 mycroft time_t currtime;
1276 1.1 mycroft time(&currtime);
1277 1.3 mycroft long_return = (currtime - gt->gt_ctime)*100;
1278 1.3 mycroft return (u_char *) &long_return;
1279 1.1 mycroft }
1280 1.1 mycroft
1281 1.1 mycroft case ipMRouteNextHopExpiryTime:
1282 1.3 mycroft long_return = 5*((gt->gt_prsent_timer+4)/5); /* round up to nearest 5*/
1283 1.3 mycroft long_return = (long_return + secs_remaining_offset()) * 100;
1284 1.3 mycroft return (u_char *) &long_return;
1285 1.1 mycroft
1286 1.1 mycroft case ipMRouteNextHopClosestMemberHops:
1287 1.3 mycroft long_return = 0;
1288 1.3 mycroft return (u_char *) &long_return;
1289 1.1 mycroft
1290 1.1 mycroft case ipMRouteNextHopProtocol:
1291 1.3 mycroft long_return = 4;
1292 1.3 mycroft return (u_char *) &long_return;
1293 1.3 mycroft
1294 1.3 mycroft default:
1295 1.3 mycroft ERROR("");
1296 1.3 mycroft }
1297 1.3 mycroft return NULL;
1298 1.3 mycroft }
1299 1.3 mycroft
1300 1.3 mycroft /* sync_timer is called by timer() every TIMER_INTERVAL seconds.
1301 1.3 mycroft * Its job is to record this time so that we can compute on demand
1302 1.3 mycroft * the approx # seconds remaining until the next timer() call
1303 1.3 mycroft */
1304 1.3 mycroft static time_t lasttimer;
1305 1.3 mycroft
1306 1.3 mycroft void
1307 1.3 mycroft sync_timer()
1308 1.3 mycroft {
1309 1.3 mycroft time(&lasttimer);
1310 1.3 mycroft }
1311 1.3 mycroft
1312 1.3 mycroft int /* in range [-TIMER_INTERVAL..0] */
1313 1.3 mycroft secs_remaining_offset()
1314 1.3 mycroft {
1315 1.3 mycroft time_t tm;
1316 1.1 mycroft
1317 1.3 mycroft time(&tm);
1318 1.3 mycroft return lasttimer-tm;
1319 1.1 mycroft }
1320