1133488Sharti/*
2133488Sharti * Copyright (c) 2001-2002
3133488Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4133488Sharti *	All rights reserved.
5133488Sharti * Copyright (c) 2003-2004
6133488Sharti *	Hartmut Brandt.
7133488Sharti *	All rights reserved.
8133488Sharti *
9133488Sharti * Author: Hartmut Brandt <harti@freebsd.org>
10133488Sharti *
11133488Sharti * Redistribution and use in source and binary forms, with or without
12133488Sharti * modification, are permitted provided that the following conditions
13133488Sharti * are met:
14133488Sharti * 1. Redistributions of source code must retain the above copyright
15133488Sharti *    notice, this list of conditions and the following disclaimer.
16133488Sharti * 2. Redistributions in binary form must reproduce the above copyright
17133488Sharti *    notice, this list of conditions and the following disclaimer in the
18133488Sharti *    documentation and/or other materials provided with the distribution.
19133488Sharti *
20133488Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21133488Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22133488Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23133488Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24133488Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25133488Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26133488Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27133488Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28133488Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29133488Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30133488Sharti * SUCH DAMAGE.
31133488Sharti *
32146532Sharti * $Begemot: libunimsg/snmp_atm/snmp_atm.c,v 1.3 2005/05/23 11:46:46 brandt_h Exp $
33133488Sharti *
34133488Sharti * SNMP module for ATM hardware interfaces.
35133488Sharti */
36133488Sharti
37133488Sharti#include "atm.h"
38133488Sharti#include "atm_tree.h"
39133488Sharti#include "atm_oid.h"
40133488Sharti
41133488Sharti#include <sys/ioctl.h>
42133488Sharti
43133488Sharti#include <stdio.h>
44133488Sharti#include <stdlib.h>
45133488Sharti#include <string.h>
46133488Sharti#include <errno.h>
47133488Sharti#include <syslog.h>
48133488Sharti#include <net/if_types.h>
49133488Sharti#include <net/if_media.h>
50133488Sharti#include <net/if_atm.h>
51133488Sharti
52133488Shartistruct lmodule *module;
53133488Sharti
54133488Sharti/* list of all (known) ATM interfaces */
55133488Shartistruct atmif_list atmif_list = TAILQ_HEAD_INITIALIZER(atmif_list);
56133488Sharti
57133488Sharti/* whether we are started or not */
58133488Shartistatic int started;
59133488Sharti
60133488Sharti/* last time table was changed */
61146532Shartistatic uint64_t last_change;
62133488Sharti
63133488Sharti/* for the registration */
64133488Shartistatic const struct asn_oid oid_begemotAtm = OIDX_begemotAtm;
65133488Sharti
66133488Sharti/* the registration */
67133488Shartistatic u_int reg_atm;
68133488Sharti
69133488Sharti/*
70133488Sharti * Find an ATM interface by name
71133488Sharti */
72133488Shartistruct atmif *
73133488Shartiatm_find_if_name(const char *name)
74133488Sharti{
75133488Sharti	struct atmif_priv *aif;
76133488Sharti
77133488Sharti	TAILQ_FOREACH(aif, &atmif_list, link)
78133488Sharti		if (strcmp(aif->pub.ifp->name, name) == 0)
79133488Sharti			return (&aif->pub);
80133488Sharti	return (NULL);
81133488Sharti}
82133488Sharti
83133488Sharti/*
84133488Sharti * get the interface from the interface index
85133488Sharti */
86133488Shartistruct atmif *
87133488Shartiatm_find_if(u_int ifindex)
88133488Sharti{
89133488Sharti	struct atmif_priv *aif;
90133488Sharti
91133488Sharti	TAILQ_FOREACH(aif, &atmif_list, link)
92133488Sharti		if (aif->index == ifindex)
93133488Sharti			return (&aif->pub);
94133488Sharti	return (NULL);
95133488Sharti}
96133488Sharti
97133488Sharti/*
98133488Sharti * Send notification to all listeners.
99133488Sharti */
100133488Shartivoid
101133488Shartiatmif_send_notification(struct atmif_priv *aif, enum atmif_notify code,
102133488Sharti    uintptr_t arg)
103133488Sharti{
104133488Sharti	struct atmif_reg *r0, *r1;
105133488Sharti
106133488Sharti	r0 = TAILQ_FIRST(&aif->notify);
107133488Sharti	while (r0 != NULL) {
108133488Sharti		r1 = TAILQ_NEXT(r0, link);
109133488Sharti		r0->func(&aif->pub, code, arg, r0->data);
110133488Sharti		r0 = r1;
111133488Sharti	}
112133488Sharti}
113133488Sharti
114133488Sharti/*
115133488Sharti * Destroy an interface
116133488Sharti */
117133488Shartistatic void
118133488Shartiatmif_destroy(struct atmif_priv *aif)
119133488Sharti{
120133488Sharti	struct atmif_reg *r0;
121133488Sharti
122133488Sharti	atmif_send_notification(aif, ATMIF_NOTIFY_DESTROY,
123133488Sharti	    (uintptr_t)0);
124133488Sharti
125133488Sharti	atmif_sys_destroy(aif);
126133488Sharti
127133488Sharti	if (aif->ifpreg != NULL)
128133488Sharti		mibif_unnotify(aif->ifpreg);
129133488Sharti
130133488Sharti	while ((r0 = TAILQ_FIRST(&aif->notify)) != NULL) {
131133488Sharti		TAILQ_REMOVE(&aif->notify, r0, link);
132133488Sharti		free(r0);
133133488Sharti	}
134133488Sharti
135133488Sharti	TAILQ_REMOVE(&atmif_list, aif, link);
136133488Sharti	free(aif);
137133488Sharti
138133488Sharti	last_change = this_tick;
139133488Sharti}
140133488Sharti
141133488Sharti/*
142133488Sharti * Function gets called from the MIB-II module for events on that interface
143133488Sharti */
144133488Shartistatic void
145133488Shartiatmif_notify(struct mibif *ifp __unused, enum mibif_notify event, void *data)
146133488Sharti{
147133488Sharti	struct atmif_priv *aif = data;
148133488Sharti
149133488Sharti	switch (event) {
150133488Sharti
151133488Sharti	  case MIBIF_NOTIFY_DESTROY:
152133488Sharti		atmif_destroy(aif);
153133488Sharti		break;
154133488Sharti	}
155133488Sharti}
156133488Sharti
157133488Sharti/*
158133488Sharti * Check the carrier state of the interface
159133488Sharti */
160133488Shartivoid
161133488Shartiatmif_check_carrier(struct atmif_priv *aif)
162133488Sharti{
163133488Sharti	struct ifmediareq ifmr;
164133488Sharti	enum atmif_carrier_state ost = aif->pub.carrier;
165133488Sharti
166133488Sharti	memset(&ifmr, 0, sizeof(ifmr));
167133488Sharti	strcpy(ifmr.ifm_name, aif->pub.ifp->name);
168133488Sharti
169133488Sharti	if (ioctl(mib_netsock, SIOCGIFMEDIA, &ifmr) == -1) {
170133488Sharti		aif->pub.carrier = ATMIF_CARRIER_UNKNOWN;
171133488Sharti		return;
172133488Sharti	}
173133488Sharti	if (!ifmr.ifm_status & IFM_AVALID) {
174133488Sharti		aif->pub.carrier = ATMIF_CARRIER_UNKNOWN;
175133488Sharti		return;
176133488Sharti	}
177133488Sharti	if (ifmr.ifm_status & IFM_ACTIVE)
178133488Sharti		aif->pub.carrier = ATMIF_CARRIER_ON;
179133488Sharti	else
180133488Sharti		aif->pub.carrier = ATMIF_CARRIER_OFF;
181133488Sharti
182133488Sharti	if (ost != aif->pub.carrier)
183133488Sharti		atmif_send_notification(aif, ATMIF_NOTIFY_CARRIER,
184133488Sharti		    (uintptr_t)ost);
185133488Sharti}
186133488Sharti
187133488Sharti/*
188133488Sharti * Retrieve the SUNI mode
189133488Sharti */
190133488Shartistatic int
191133488Shartiatmif_get_mode(struct atmif_priv *aif)
192133488Sharti{
193133488Sharti	struct ifmediareq ifmr;
194133488Sharti
195133488Sharti	memset(&ifmr, 0, sizeof(ifmr));
196133488Sharti	strcpy(ifmr.ifm_name, aif->pub.ifp->name);
197133488Sharti
198133488Sharti	if (ioctl(mib_netsock, SIOCGIFMEDIA, &ifmr) < 0) {
199133488Sharti		syslog(LOG_ERR, "SIOCGIFMEDIA: %m");
200133488Sharti		aif->pub.mode = ATMIF_SUNI_MODE_UNKNOWN;
201133488Sharti		return (SNMP_ERR_GENERR);
202133488Sharti	}
203133488Sharti	if (ifmr.ifm_current & IFM_ATM_SDH)
204133488Sharti		aif->pub.mode = ATMIF_SUNI_MODE_SDH;
205133488Sharti	else
206133488Sharti		aif->pub.mode = ATMIF_SUNI_MODE_SONET;
207133488Sharti
208133488Sharti	return (SNMP_ERR_NOERROR);
209133488Sharti}
210133488Sharti
211133488Sharti/*
212133488Sharti * Change the SUNI mod
213133488Sharti */
214133488Shartistatic int
215133488Shartiatmif_set_mode(struct atmif_priv *aif, int newmode)
216133488Sharti{
217133488Sharti	struct ifmediareq ifmr;
218133488Sharti	struct ifreq ifr;
219133488Sharti
220133488Sharti	memset(&ifmr, 0, sizeof(ifmr));
221133488Sharti	strcpy(ifmr.ifm_name, aif->pub.ifp->name);
222133488Sharti
223133488Sharti	/* get current mode */
224133488Sharti	if (ioctl(mib_netsock, SIOCGIFMEDIA, &ifmr) < 0) {
225133488Sharti		syslog(LOG_ERR, "SIOCGIFMEDIA: %m");
226133488Sharti		return (SNMP_ERR_GENERR);
227133488Sharti	}
228133488Sharti
229133488Sharti	memset(&ifr, 0, sizeof(ifr));
230133488Sharti	strcpy(ifr.ifr_name, aif->pub.ifp->name);
231133488Sharti
232133488Sharti	ifr.ifr_media = ifmr.ifm_current;
233133488Sharti	if (newmode == ATMIF_SUNI_MODE_SDH)
234133488Sharti		ifr.ifr_media |= IFM_ATM_SDH;
235133488Sharti	else
236133488Sharti		ifr.ifr_media &= ~IFM_ATM_SDH;
237133488Sharti
238133488Sharti	if (ioctl(mib_netsock, SIOCSIFMEDIA, &ifr) < 0) {
239133488Sharti		syslog(LOG_ERR, "SIOCSIFMEDIA: %m");
240133488Sharti		return (SNMP_ERR_GENERR);
241133488Sharti	}
242133488Sharti
243133488Sharti	aif->pub.mode = newmode;
244133488Sharti	return (SNMP_ERR_NOERROR);
245133488Sharti}
246133488Sharti
247133488Sharti/*
248133488Sharti * Attach to an ATM interface
249133488Sharti */
250133488Shartistatic void
251133488Shartiattach_if(struct mibif *ifp)
252133488Sharti{
253133488Sharti	struct atmif_priv *aif;
254133488Sharti
255133488Sharti	/* we should not know it */
256133488Sharti	TAILQ_FOREACH(aif, &atmif_list, link)
257133488Sharti		if (aif->pub.ifp == ifp) {
258133488Sharti			syslog(LOG_CRIT, "new ATM if already known '%s'",
259133488Sharti			    ifp->name);
260133488Sharti			return;
261133488Sharti		}
262133488Sharti
263133488Sharti	/*
264133488Sharti	 * tap it
265133488Sharti	 */
266133488Sharti	if ((aif = malloc(sizeof(*aif))) == NULL) {
267133488Sharti		syslog(LOG_ERR, "new atmif: %m");
268133488Sharti		return;
269133488Sharti	}
270133488Sharti	memset(aif, 0, sizeof(*aif));
271133488Sharti
272133488Sharti	aif->pub.ifp = ifp;
273133488Sharti	aif->index = ifp->index;
274146532Sharti	TAILQ_INIT(&aif->notify);
275133488Sharti
276133488Sharti	if (atmif_sys_attach_if(aif)) {
277133488Sharti		free(aif);
278133488Sharti		return;
279133488Sharti	}
280133488Sharti
281133488Sharti	aif->ifpreg = mibif_notify(ifp, module, atmif_notify, aif);
282133488Sharti
283133488Sharti	aif->pub.carrier = ATMIF_CARRIER_UNKNOWN;
284133488Sharti	atmif_check_carrier(aif);
285133488Sharti	(void)atmif_get_mode(aif);
286133488Sharti
287133488Sharti	INSERT_OBJECT_INT(aif, &atmif_list);
288133488Sharti
289133488Sharti	last_change = this_tick;
290133488Sharti
291133488Sharti	return;
292133488Sharti}
293133488Sharti
294133488Sharti/*
295133488Sharti * Function gets called when a new interface is created. If this is an
296133488Sharti * ATM interface, hook in. Claim the interface in any case even when
297133488Sharti * the creation of our data structures fails.
298133488Sharti */
299133488Shartistatic int
300133488Shartinew_if(struct mibif *ifp)
301133488Sharti{
302133488Sharti	if (!started || ifp->mib.ifmd_data.ifi_type != IFT_ATM ||
303133488Sharti	    ifp->xnotify != NULL)
304133488Sharti		return (0);
305133488Sharti
306133488Sharti	attach_if(ifp);
307133488Sharti	return (1);
308133488Sharti}
309133488Sharti
310133488Sharti/*
311133488Sharti * Start the module
312133488Sharti */
313133488Shartistatic void
314133488Shartiatm_start(void)
315133488Sharti{
316133488Sharti	struct mibif *ifp;
317133488Sharti
318133488Sharti	reg_atm = or_register(&oid_begemotAtm,
319133488Sharti	    "The Begemot MIB for ATM interfaces.", module);
320133488Sharti
321133488Sharti	started = 1;
322133488Sharti	for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp))
323133488Sharti		if (ifp->mib.ifmd_data.ifi_type == IFT_ATM &&
324133488Sharti		    ifp->xnotify == NULL)
325133488Sharti			attach_if(ifp);
326133488Sharti}
327133488Sharti
328133488Sharti/*
329133488Sharti * Called when modules is loaded
330133488Sharti */
331133488Shartistatic int
332133488Shartiatm_init(struct lmodule *mod, int argc __unused, char *argv[] __unused)
333133488Sharti{
334133488Sharti	module = mod;
335133488Sharti
336133488Sharti	/* register to get creation messages for ATM interfaces */
337133488Sharti	if (mib_register_newif(new_if, module)) {
338133488Sharti		syslog(LOG_ERR, "cannot register newif function: %m");
339133488Sharti		return (-1);
340133488Sharti	}
341133488Sharti
342133488Sharti	return (0);
343133488Sharti}
344133488Sharti
345133488Sharti/*
346133488Sharti * Called when module gets unloaded - free all resources
347133488Sharti */
348133488Shartistatic int
349133488Shartiatm_fini(void)
350133488Sharti{
351133488Sharti	struct atmif_priv *aif;
352133488Sharti
353133488Sharti	while ((aif = TAILQ_FIRST(&atmif_list)) != NULL)
354133488Sharti		atmif_destroy(aif);
355133488Sharti
356133488Sharti	mib_unregister_newif(module);
357133488Sharti	or_unregister(reg_atm);
358133488Sharti
359133488Sharti	return (0);
360133488Sharti}
361133488Sharti
362133488Sharti/*
363133488Sharti * Other module unloaded/loaded
364133488Sharti */
365133488Shartistatic void
366133488Shartiatm_loading(const struct lmodule *mod, int loading)
367133488Sharti{
368133488Sharti	struct atmif_priv *aif;
369133488Sharti	struct atmif_reg *r0, *r1;
370133488Sharti
371133488Sharti	if (!loading) {
372133488Sharti		/* remove notifications for this module */
373133488Sharti		TAILQ_FOREACH(aif, &atmif_list, link)
374133488Sharti			TAILQ_FOREACH_SAFE(r0, &aif->notify, link, r1) {
375133488Sharti				if (r0->mod == mod) {
376133488Sharti					TAILQ_REMOVE(&aif->notify, r0, link);
377133488Sharti					free(r0);
378133488Sharti				}
379133488Sharti			}
380133488Sharti	}
381133488Sharti}
382133488Sharti
383133488Sharticonst struct snmp_module config = {
384133488Sharti	.comment = "This module implements a private MIB for ATM interfaces.",
385133488Sharti	.init =		atm_init,
386133488Sharti	.fini =		atm_fini,
387133488Sharti	.start =	atm_start,
388133488Sharti	.tree =		atm_ctree,
389133488Sharti	.tree_size =	atm_CTREE_SIZE,
390133488Sharti	.loading =	atm_loading
391133488Sharti};
392133488Sharti
393133488Sharti/*
394133488Sharti * Get the interface point for a table access
395133488Sharti */
396133488Shartiint
397133488Shartiatmif_get_aif(struct snmp_value *value, u_int sub, enum snmp_op op,
398133488Sharti    struct atmif_priv **aifp)
399133488Sharti{
400133488Sharti	switch (op) {
401133488Sharti
402133488Sharti	  case SNMP_OP_GETNEXT:
403133488Sharti		if ((*aifp = NEXT_OBJECT_INT(&atmif_list,
404133488Sharti		    &value->var, sub)) == NULL)
405133488Sharti			return (SNMP_ERR_NOSUCHNAME);
406133488Sharti		value->var.len = sub + 1;
407133488Sharti		value->var.subs[sub] = (*aifp)->index;
408133488Sharti		break;
409133488Sharti
410133488Sharti	  case SNMP_OP_GET:
411133488Sharti		if ((*aifp = FIND_OBJECT_INT(&atmif_list,
412133488Sharti		    &value->var, sub)) == NULL)
413133488Sharti			return (SNMP_ERR_NOSUCHNAME);
414133488Sharti		break;
415133488Sharti
416133488Sharti	  case SNMP_OP_SET:
417133488Sharti		if ((*aifp = FIND_OBJECT_INT(&atmif_list,
418133488Sharti		    &value->var, sub)) == NULL)
419133488Sharti			return (SNMP_ERR_NO_CREATION);
420133488Sharti		break;
421133488Sharti
422133488Sharti	  case SNMP_OP_ROLLBACK:
423133488Sharti	  case SNMP_OP_COMMIT:
424133488Sharti		if ((*aifp = FIND_OBJECT_INT(&atmif_list,
425133488Sharti		    &value->var, sub)) == NULL)
426133488Sharti			abort();
427133488Sharti		return (SNMP_ERR_NOERROR);
428133488Sharti	}
429133488Sharti
430133488Sharti	if ((*aifp)->pub.mib->pcr == 0) {
431133488Sharti		mib_fetch_ifmib((*aifp)->pub.ifp);
432133488Sharti		atmif_sys_fill_mib(*aifp);
433133488Sharti		atmif_check_carrier(*aifp);
434133488Sharti	}
435133488Sharti
436133488Sharti	return (SNMP_ERR_NOERROR);
437133488Sharti}
438133488Sharti
439133488Sharti/*
440133488Sharti * Table of all ATM interfaces
441133488Sharti */
442133488Shartiint
443133488Shartiop_atmif(struct snmp_context *ctx __unused, struct snmp_value *value,
444133488Sharti    u_int sub, u_int vindex __unused, enum snmp_op op)
445133488Sharti{
446133488Sharti	struct atmif_priv *aif;
447133488Sharti	int err;
448133488Sharti
449133488Sharti	if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR)
450133488Sharti		return (err);
451133488Sharti
452133488Sharti	if (op == SNMP_OP_SET) {
453133488Sharti		switch (value->var.subs[sub - 1]) {
454133488Sharti
455133488Sharti		  default:
456133488Sharti			return (SNMP_ERR_NOT_WRITEABLE);
457133488Sharti
458133488Sharti		  case LEAF_begemotAtmIfMode:
459133488Sharti			if ((err = atmif_get_mode(aif)) != SNMP_ERR_NOERROR)
460133488Sharti				return (err);
461133488Sharti			if (aif->pub.mode == ATMIF_SUNI_MODE_UNKNOWN)
462133488Sharti				return (SNMP_ERR_INCONS_VALUE);
463133488Sharti			if (value->v.integer != ATMIF_SUNI_MODE_SONET &&
464133488Sharti			    value->v.integer != ATMIF_SUNI_MODE_SDH)
465133488Sharti				return (SNMP_ERR_WRONG_VALUE);
466133488Sharti			if ((u_int)value->v.integer == aif->pub.mode)
467133488Sharti				return (SNMP_ERR_NOERROR);
468133488Sharti			return (atmif_set_mode(aif, value->v.integer));
469133488Sharti		}
470133488Sharti		abort();
471133488Sharti	}
472133488Sharti
473133488Sharti	switch (value->var.subs[sub - 1]) {
474133488Sharti
475133488Sharti	  case LEAF_begemotAtmIfName:
476133488Sharti		return (string_get(value, aif->pub.ifp->name, -1));
477133488Sharti
478133488Sharti	  case LEAF_begemotAtmIfPcr:
479133488Sharti		value->v.uint32 = aif->pub.mib->pcr;
480133488Sharti		return (SNMP_ERR_NOERROR);
481133488Sharti
482133488Sharti	  case LEAF_begemotAtmIfMedia:
483133488Sharti		value->v.integer = aif->pub.mib->media;
484133488Sharti		return (SNMP_ERR_NOERROR);
485133488Sharti
486133488Sharti	  case LEAF_begemotAtmIfVpiBits:
487133488Sharti		value->v.uint32 = aif->pub.mib->vpi_bits;
488133488Sharti		return (SNMP_ERR_NOERROR);
489133488Sharti
490133488Sharti	  case LEAF_begemotAtmIfVciBits:
491133488Sharti		value->v.uint32 = aif->pub.mib->vci_bits;
492133488Sharti		return (SNMP_ERR_NOERROR);
493133488Sharti
494133488Sharti	  case LEAF_begemotAtmIfMaxVpcs:
495133488Sharti		value->v.uint32 = aif->pub.mib->max_vpcs;
496133488Sharti		return (SNMP_ERR_NOERROR);
497133488Sharti
498133488Sharti	  case LEAF_begemotAtmIfMaxVccs:
499133488Sharti		value->v.uint32 = aif->pub.mib->max_vccs;
500133488Sharti		return (SNMP_ERR_NOERROR);
501133488Sharti
502133488Sharti	  case LEAF_begemotAtmIfEsi:
503133488Sharti		return (string_get(value, aif->pub.mib->esi, 6));
504133488Sharti
505133488Sharti	  case LEAF_begemotAtmIfCarrierStatus:
506133488Sharti		value->v.integer = aif->pub.carrier;
507133488Sharti		return (SNMP_ERR_NOERROR);
508133488Sharti
509133488Sharti	  case LEAF_begemotAtmIfMode:
510133488Sharti		if ((err = atmif_get_mode(aif)) != SNMP_ERR_NOERROR)
511133488Sharti			return (err);
512133488Sharti		value->v.integer = aif->pub.mode;
513133488Sharti		return (SNMP_ERR_NOERROR);
514133488Sharti	}
515133488Sharti	abort();
516133488Sharti}
517133488Sharti
518133488Sharti/*
519133488Sharti * Hardware table
520133488Sharti */
521133488Shartiint
522133488Shartiop_atmhw(struct snmp_context *ctx __unused, struct snmp_value *value,
523133488Sharti    u_int sub, u_int vindex __unused, enum snmp_op op)
524133488Sharti{
525133488Sharti	struct atmif_priv *aif;
526133488Sharti	int err;
527133488Sharti
528133488Sharti	if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR)
529133488Sharti		return (err);
530133488Sharti	if (op == SNMP_OP_SET)
531133488Sharti		return (SNMP_ERR_NOT_WRITEABLE);
532133488Sharti
533133488Sharti	switch (value->var.subs[sub - 1]) {
534133488Sharti
535133488Sharti	  case LEAF_begemotAtmHWVendor:
536133488Sharti		return (atm_sys_get_hw_vendor(aif, value));
537133488Sharti
538133488Sharti	  case LEAF_begemotAtmHWDevice:
539133488Sharti		return (atm_sys_get_hw_device(aif, value));
540133488Sharti
541133488Sharti	  case LEAF_begemotAtmHWSerial:
542133488Sharti		value->v.uint32 = aif->pub.mib->serial;
543133488Sharti		return (SNMP_ERR_NOERROR);
544133488Sharti
545133488Sharti	  case LEAF_begemotAtmHWVersion:
546133488Sharti		value->v.uint32 = aif->pub.mib->hw_version;
547133488Sharti		return (SNMP_ERR_NOERROR);
548133488Sharti
549133488Sharti	  case LEAF_begemotAtmHWSoftVersion:
550133488Sharti		value->v.uint32 = aif->pub.mib->sw_version;
551133488Sharti		return (SNMP_ERR_NOERROR);
552133488Sharti
553133488Sharti	}
554133488Sharti	abort();
555133488Sharti}
556133488Sharti
557133488Sharti/*
558133488Sharti * Scalars
559133488Sharti */
560133488Shartiint
561133488Shartiop_atm(struct snmp_context *ctx __unused, struct snmp_value *value,
562133488Sharti    u_int sub, u_int vindex __unused, enum snmp_op op)
563133488Sharti{
564133488Sharti	switch (op) {
565133488Sharti
566133488Sharti	  case SNMP_OP_GETNEXT:
567133488Sharti		abort();
568133488Sharti
569133488Sharti	  case SNMP_OP_GET:
570133488Sharti		switch (value->var.subs[sub - 1]) {
571133488Sharti
572133488Sharti		  case LEAF_begemotAtmIfTableLastChange:
573133488Sharti			value->v.uint32 =
574133488Sharti			    (last_change == 0 ? 0 : last_change - start_tick);
575133488Sharti			return (SNMP_ERR_NOERROR);
576133488Sharti		}
577133488Sharti		abort();
578133488Sharti
579133488Sharti	  case SNMP_OP_SET:
580133488Sharti		return (SNMP_ERR_NOT_WRITEABLE);
581133488Sharti
582133488Sharti	  case SNMP_OP_ROLLBACK:
583133488Sharti	  case SNMP_OP_COMMIT:
584133488Sharti		abort();
585133488Sharti	}
586133488Sharti	abort();
587133488Sharti}
588133488Sharti
589133488Sharti/*
590133488Sharti * Register for interface notifications
591133488Sharti */
592133488Shartivoid *
593133488Shartiatm_notify_aif(struct atmif *pub, const struct lmodule *mod,
594133488Sharti    atmif_event_f func, void *arg)
595133488Sharti{
596133488Sharti	struct atmif_priv *aif = (struct atmif_priv *)pub;
597133488Sharti	struct atmif_reg *r0;
598133488Sharti
599133488Sharti	if ((r0 = malloc(sizeof(*r0))) == NULL) {
600133488Sharti		syslog(LOG_CRIT, "out of memory");
601133488Sharti		return (NULL);
602133488Sharti	}
603133488Sharti	r0->func = func;
604133488Sharti	r0->mod = mod;
605133488Sharti	r0->data = arg;
606133488Sharti	r0->aif = aif;
607133488Sharti
608133488Sharti	TAILQ_INSERT_TAIL(&aif->notify, r0, link);
609133488Sharti
610133488Sharti	return (r0);
611133488Sharti}
612133488Sharti
613133488Sharti/*
614133488Sharti * Unregister it
615133488Sharti */
616133488Shartivoid
617133488Shartiatm_unnotify_aif(void *arg)
618133488Sharti{
619133488Sharti	struct atmif_reg *r0 = arg;
620133488Sharti
621133488Sharti	TAILQ_REMOVE(&r0->aif->notify, r0, link);
622133488Sharti	free(r0);
623133488Sharti}
624