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