1133391Sharti/*
2133391Sharti * Copyright (c) 2001-2002
3133391Sharti *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4133391Sharti *	All rights reserved.
5133391Sharti * Copyright (c) 2003-2004
6133391Sharti *	Hartmut Brandt.
7133391Sharti *	All rights reserved.
8133391Sharti *
9133391Sharti * Author: Hartmut Brandt <harti@freebsd.org>
10133391Sharti *
11133391Sharti * Redistribution and use in source and binary forms, with or without
12133391Sharti * modification, are permitted provided that the following conditions
13133391Sharti * are met:
14133391Sharti * 1. Redistributions of source code must retain the above copyright
15133391Sharti *    notice, this list of conditions and the following disclaimer.
16133391Sharti * 2. Redistributions in binary form must reproduce the above copyright
17133391Sharti *    notice, this list of conditions and the following disclaimer in the
18133391Sharti *    documentation and/or other materials provided with the distribution.
19133391Sharti *
20133391Sharti * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21133391Sharti * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22133391Sharti * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23133391Sharti * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24133391Sharti * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25133391Sharti * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26133391Sharti * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27133391Sharti * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28133391Sharti * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29133391Sharti * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30133391Sharti * SUCH DAMAGE.
31133391Sharti *
32133391Sharti * $FreeBSD$
33133391Sharti *
34133391Sharti * SNMP module for ATM hardware interfaces - FreeBSD/Ng specific part.
35133391Sharti */
36133391Sharti
37133391Sharti#include "atm.h"
38133391Sharti#include "atm_tree.h"
39133391Sharti#include "atm_oid.h"
40133391Sharti
41133391Sharti#include <stdlib.h>
42133391Sharti#include <syslog.h>
43133391Sharti#include <string.h>
44133391Sharti
45133391Sharti#include <net/if_atm.h>
46133391Sharti
47133391Sharti#include <bsnmp/snmp_netgraph.h>
48133391Sharti#include <netgraph/ng_message.h>
49133391Sharti#include <netgraph/atm/ng_atm.h>
50133391Sharti
51133391Shartistatic const struct hwinfo {
52133391Sharti	const char *device;
53133391Sharti	const char *vendor;
54133391Sharti} hwinfo[] = {
55133391Sharti	ATM_DEVICE_NAMES
56133391Sharti};
57133391Sharti
58133391Shartistruct atmif_sys {
59133391Sharti	ng_ID_t		atm_node;
60133391Sharti	void		*regc;	/* cookie registration */
61133391Sharti};
62133391Sharti
63133391Sharti/*
64133391Sharti * Find the interface for a given node
65133391Sharti */
66133391Shartistruct atmif *
67133391Shartiatm_node2if(u_int node)
68133391Sharti{
69133391Sharti	struct atmif_priv *aif;
70133391Sharti
71133391Sharti	if (node != 0)
72133391Sharti		TAILQ_FOREACH(aif, &atmif_list, link)
73133391Sharti			if (aif->sys->atm_node == node)
74133391Sharti				return (&aif->pub);
75133391Sharti	return (NULL);
76133391Sharti}
77133391Sharti
78133391Shartiu_int
79133391Shartiatm_if2node(struct atmif *pub)
80133391Sharti{
81133391Sharti	struct atmif_priv *aif = (struct atmif_priv *)pub;
82133391Sharti
83133391Sharti	return (aif->sys->atm_node);
84133391Sharti}
85133391Sharti
86133391Sharti/*
87133391Sharti * Destroy system dependend stuff.
88133391Sharti */
89133391Shartivoid
90133391Shartiatmif_sys_destroy(struct atmif_priv *aif)
91133391Sharti{
92133391Sharti
93133391Sharti	ng_unregister_cookie(aif->sys->regc);
94133391Sharti	free(aif->sys);
95133391Sharti	free(aif->pub.mib);
96133391Sharti}
97133391Sharti
98133391Sharti/*
99133391Sharti * Handle a message from the ATM node
100133391Sharti */
101133391Shartistatic void
102133391Shartihandle_atm_message(const struct ng_mesg *mesg, const char *path __unused,
103133391Sharti    ng_ID_t node, void *uarg)
104133391Sharti{
105133391Sharti	struct atmif_priv *aif = uarg;
106133391Sharti	enum atmif_carrier_state ost;
107133391Sharti
108133391Sharti	switch (mesg->header.cmd) {
109133391Sharti
110133391Sharti	  case NGM_ATM_IF_CHANGE:
111133391Sharti	    {
112133391Sharti		const struct ngm_atm_if_change *arg;
113133391Sharti
114133391Sharti		ost = aif->pub.carrier;
115133391Sharti		if (mesg->header.arglen != sizeof(*arg)) {
116133391Sharti			syslog(LOG_ERR, "ATM_IF_CHANGE: wrong size");
117133391Sharti			atmif_check_carrier(aif);
118133391Sharti			return;
119133391Sharti		}
120133391Sharti		arg = (const struct ngm_atm_if_change *)
121133391Sharti		    (const void *)mesg->data;
122133391Sharti
123133391Sharti		if (arg->carrier)
124133391Sharti			aif->pub.carrier = ATMIF_CARRIER_ON;
125133391Sharti		else
126133391Sharti			aif->pub.carrier = ATMIF_CARRIER_OFF;
127133391Sharti
128133391Sharti		if (ost != aif->pub.carrier)
129133391Sharti			atmif_send_notification(aif, ATMIF_NOTIFY_CARRIER,
130133391Sharti			    (uintptr_t)ost);
131133391Sharti		return;
132133391Sharti	    }
133133391Sharti
134133391Sharti	  case NGM_ATM_VCC_CHANGE:
135133391Sharti	    {
136133391Sharti		const struct ngm_atm_vcc_change *arg;
137133391Sharti
138133391Sharti		if (mesg->header.arglen != sizeof(*arg)) {
139133391Sharti			syslog(LOG_ERR, "ATM_VCC_CHANGE: wrong size");
140133391Sharti			return;
141133391Sharti		}
142133391Sharti		arg = (const struct ngm_atm_vcc_change *)
143133391Sharti		    (const void *)mesg->data;
144133391Sharti		atmif_send_notification(aif, ATMIF_NOTIFY_VCC,
145133391Sharti		    (uintptr_t)(((arg->vpi & 0xff) << 24) |
146133391Sharti		    ((arg->vci & 0xffff) << 8) | (arg->state & 1)));
147133391Sharti		return;
148133391Sharti	    }
149133391Sharti	}
150133391Sharti	syslog(LOG_WARNING, "spurious message %u from node [%x]",
151133391Sharti	    mesg->header.cmd, node);
152133391Sharti}
153133391Sharti
154133391Sharti/*
155133391Sharti * Attach to an ATM interface
156133391Sharti */
157133391Shartiint
158133391Shartiatmif_sys_attach_if(struct atmif_priv *aif)
159133391Sharti{
160133391Sharti	struct ng_mesg *resp, *resp1;
161133391Sharti	struct namelist *list;
162133391Sharti	u_int i;
163133391Sharti
164133391Sharti	if ((aif->sys = malloc(sizeof(*aif->sys))) == NULL) {
165133391Sharti		syslog(LOG_CRIT, "out of memory");
166133391Sharti		return (-1);
167133391Sharti	}
168133391Sharti	memset(aif->sys, 0, sizeof(*aif->sys));
169133391Sharti
170133391Sharti	if ((aif->pub.mib = malloc(sizeof(*aif->pub.mib))) == NULL) {
171133391Sharti		free(aif->sys);
172133391Sharti		syslog(LOG_CRIT, "out of memory");
173133391Sharti		return (-1);
174133391Sharti	}
175133391Sharti
176133391Sharti	atmif_sys_fill_mib(aif);
177133391Sharti
178133391Sharti	/*
179133391Sharti	 * Get ATM node Id. Must do it the hard way by scanning all nodes
180133391Sharti	 * because the name may be wrong.
181133391Sharti	 */
182133391Sharti	if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES,
183133391Sharti	    NULL, 0)) == NULL) {
184133391Sharti		syslog(LOG_ERR, "cannot fetch node list: %m");
185133391Sharti		free(aif->sys);
186133391Sharti		return (-1);
187133391Sharti	}
188133391Sharti	list = (struct namelist *)(void *)resp->data;
189133391Sharti
190133391Sharti	for (i = 0; i < list->numnames; i++) {
191133391Sharti		if (strcmp(list->nodeinfo[i].type, NG_ATM_NODE_TYPE) != 0)
192133391Sharti			continue;
193133391Sharti		if ((resp1 = ng_dialog_id(list->nodeinfo[i].id,
194133391Sharti		    NGM_ATM_COOKIE, NGM_ATM_GET_IFNAME, NULL, 0)) == NULL)
195133391Sharti			continue;
196133391Sharti		if (strcmp(resp1->data, aif->pub.ifp->name) == 0) {
197133391Sharti			free(resp1);
198133391Sharti			break;
199133391Sharti		}
200133391Sharti		free(resp1);
201133391Sharti	}
202133391Sharti	if (i == list->numnames)
203133391Sharti		aif->sys->atm_node = 0;
204133391Sharti	else
205133391Sharti		aif->sys->atm_node = list->nodeinfo[i].id;
206133391Sharti
207133391Sharti	free(resp);
208133391Sharti
209133391Sharti	if ((aif->sys->regc = ng_register_cookie(module, NGM_ATM_COOKIE,
210133391Sharti	    aif->sys->atm_node, handle_atm_message, aif)) == NULL) {
211133391Sharti		syslog(LOG_ERR, "cannot register cookie: %m");
212133391Sharti		free(aif->sys);
213133391Sharti		return (-1);
214133391Sharti	}
215133391Sharti	return (0);
216133391Sharti}
217133391Sharti
218133391Sharti/*
219133391Sharti * Table of all ATM interfaces - Ng part
220133391Sharti */
221133391Shartiint
222133391Shartiop_atmif_ng(struct snmp_context *ctx __unused, struct snmp_value *value,
223133391Sharti    u_int sub, u_int vindex __unused, enum snmp_op op)
224133391Sharti{
225133391Sharti	struct atmif_priv *aif;
226133391Sharti	int err;
227133391Sharti
228133391Sharti	if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR)
229133391Sharti		return (err);
230133391Sharti
231133391Sharti	if (op == SNMP_OP_SET) {
232133391Sharti		switch (value->var.subs[sub - 1]) {
233133391Sharti
234133391Sharti		  default:
235133391Sharti			return (SNMP_ERR_NOT_WRITEABLE);
236133391Sharti		}
237133391Sharti	}
238133391Sharti
239133391Sharti	switch (value->var.subs[sub - 1]) {
240133391Sharti
241133391Sharti	  case LEAF_begemotAtmIfNodeId:
242133391Sharti		value->v.uint32 = aif->sys->atm_node;
243133391Sharti		return (SNMP_ERR_NOERROR);
244133391Sharti	}
245133391Sharti	abort();
246133391Sharti}
247133391Sharti
248133391Sharti/*
249133391Sharti * Get vendor string
250133391Sharti */
251133391Shartiint
252133391Shartiatm_sys_get_hw_vendor(struct atmif_priv *aif, struct snmp_value *value)
253133391Sharti{
254133391Sharti
255133391Sharti	if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0]))
256133391Sharti		return (string_get(value, "unknown", -1));
257133391Sharti	return (string_get(value, hwinfo[aif->pub.mib->device].vendor, -1));
258133391Sharti}
259133391Sharti
260133391Sharti/*
261133391Sharti * Get device string
262133391Sharti */
263133391Shartiint
264133391Shartiatm_sys_get_hw_device(struct atmif_priv *aif, struct snmp_value *value)
265133391Sharti{
266133391Sharti
267133391Sharti	if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0]))
268133391Sharti		return (string_get(value, "unknown", -1));
269133391Sharti	return (string_get(value, hwinfo[aif->pub.mib->device].device, -1));
270133391Sharti}
271133391Sharti
272133391Sharti/*
273133391Sharti * Extract the ATM MIB from the interface's private MIB
274133391Sharti */
275133391Shartivoid
276133391Shartiatmif_sys_fill_mib(struct atmif_priv *aif)
277133391Sharti{
278133391Sharti	struct ifatm_mib *mib;
279133391Sharti
280133391Sharti	if (aif->pub.ifp->specmiblen != sizeof(struct ifatm_mib)) {
281133391Sharti		syslog(LOG_ERR, "atmif MIB has wrong size %zu",
282133391Sharti		    aif->pub.ifp->specmiblen);
283133391Sharti		memset(aif->pub.mib, 0, sizeof(*aif->pub.mib));
284133391Sharti		aif->pub.mib->version = 0;
285133391Sharti		return;
286133391Sharti	}
287133391Sharti	mib = (struct ifatm_mib *)aif->pub.ifp->specmib;
288133391Sharti
289133391Sharti	aif->pub.mib->device = mib->device;
290133391Sharti	aif->pub.mib->serial = mib->serial;
291133391Sharti	aif->pub.mib->hw_version = mib->hw_version;
292133391Sharti	aif->pub.mib->sw_version = mib->sw_version;
293133391Sharti	aif->pub.mib->media = mib->media;
294133391Sharti
295133391Sharti	memcpy(aif->pub.mib->esi, mib->esi, 6);
296133391Sharti	aif->pub.mib->pcr = mib->pcr;
297133391Sharti	aif->pub.mib->vpi_bits = mib->vpi_bits;
298133391Sharti	aif->pub.mib->vci_bits = mib->vci_bits;
299133391Sharti	aif->pub.mib->max_vpcs = mib->max_vpcs;
300133391Sharti	aif->pub.mib->max_vccs = mib->max_vccs;
301133391Sharti}
302