atm_sys.c revision 302408
1/*
2 * Copyright (c) 2001-2002
3 *	Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4 *	All rights reserved.
5 * Copyright (c) 2003-2004
6 *	Hartmut Brandt.
7 *	All rights reserved.
8 *
9 * Author: Hartmut Brandt <harti@freebsd.org>
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 *    notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 *    notice, this list of conditions and the following disclaimer in the
18 *    documentation and/or other materials provided with the distribution.
19 *
20 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 *
32 * $FreeBSD: stable/11/usr.sbin/bsnmpd/modules/snmp_atm/atm_sys.c 133391 2004-08-09 16:36:04Z harti $
33 *
34 * SNMP module for ATM hardware interfaces - FreeBSD/Ng specific part.
35 */
36
37#include "atm.h"
38#include "atm_tree.h"
39#include "atm_oid.h"
40
41#include <stdlib.h>
42#include <syslog.h>
43#include <string.h>
44
45#include <net/if_atm.h>
46
47#include <bsnmp/snmp_netgraph.h>
48#include <netgraph/ng_message.h>
49#include <netgraph/atm/ng_atm.h>
50
51static const struct hwinfo {
52	const char *device;
53	const char *vendor;
54} hwinfo[] = {
55	ATM_DEVICE_NAMES
56};
57
58struct atmif_sys {
59	ng_ID_t		atm_node;
60	void		*regc;	/* cookie registration */
61};
62
63/*
64 * Find the interface for a given node
65 */
66struct atmif *
67atm_node2if(u_int node)
68{
69	struct atmif_priv *aif;
70
71	if (node != 0)
72		TAILQ_FOREACH(aif, &atmif_list, link)
73			if (aif->sys->atm_node == node)
74				return (&aif->pub);
75	return (NULL);
76}
77
78u_int
79atm_if2node(struct atmif *pub)
80{
81	struct atmif_priv *aif = (struct atmif_priv *)pub;
82
83	return (aif->sys->atm_node);
84}
85
86/*
87 * Destroy system dependend stuff.
88 */
89void
90atmif_sys_destroy(struct atmif_priv *aif)
91{
92
93	ng_unregister_cookie(aif->sys->regc);
94	free(aif->sys);
95	free(aif->pub.mib);
96}
97
98/*
99 * Handle a message from the ATM node
100 */
101static void
102handle_atm_message(const struct ng_mesg *mesg, const char *path __unused,
103    ng_ID_t node, void *uarg)
104{
105	struct atmif_priv *aif = uarg;
106	enum atmif_carrier_state ost;
107
108	switch (mesg->header.cmd) {
109
110	  case NGM_ATM_IF_CHANGE:
111	    {
112		const struct ngm_atm_if_change *arg;
113
114		ost = aif->pub.carrier;
115		if (mesg->header.arglen != sizeof(*arg)) {
116			syslog(LOG_ERR, "ATM_IF_CHANGE: wrong size");
117			atmif_check_carrier(aif);
118			return;
119		}
120		arg = (const struct ngm_atm_if_change *)
121		    (const void *)mesg->data;
122
123		if (arg->carrier)
124			aif->pub.carrier = ATMIF_CARRIER_ON;
125		else
126			aif->pub.carrier = ATMIF_CARRIER_OFF;
127
128		if (ost != aif->pub.carrier)
129			atmif_send_notification(aif, ATMIF_NOTIFY_CARRIER,
130			    (uintptr_t)ost);
131		return;
132	    }
133
134	  case NGM_ATM_VCC_CHANGE:
135	    {
136		const struct ngm_atm_vcc_change *arg;
137
138		if (mesg->header.arglen != sizeof(*arg)) {
139			syslog(LOG_ERR, "ATM_VCC_CHANGE: wrong size");
140			return;
141		}
142		arg = (const struct ngm_atm_vcc_change *)
143		    (const void *)mesg->data;
144		atmif_send_notification(aif, ATMIF_NOTIFY_VCC,
145		    (uintptr_t)(((arg->vpi & 0xff) << 24) |
146		    ((arg->vci & 0xffff) << 8) | (arg->state & 1)));
147		return;
148	    }
149	}
150	syslog(LOG_WARNING, "spurious message %u from node [%x]",
151	    mesg->header.cmd, node);
152}
153
154/*
155 * Attach to an ATM interface
156 */
157int
158atmif_sys_attach_if(struct atmif_priv *aif)
159{
160	struct ng_mesg *resp, *resp1;
161	struct namelist *list;
162	u_int i;
163
164	if ((aif->sys = malloc(sizeof(*aif->sys))) == NULL) {
165		syslog(LOG_CRIT, "out of memory");
166		return (-1);
167	}
168	memset(aif->sys, 0, sizeof(*aif->sys));
169
170	if ((aif->pub.mib = malloc(sizeof(*aif->pub.mib))) == NULL) {
171		free(aif->sys);
172		syslog(LOG_CRIT, "out of memory");
173		return (-1);
174	}
175
176	atmif_sys_fill_mib(aif);
177
178	/*
179	 * Get ATM node Id. Must do it the hard way by scanning all nodes
180	 * because the name may be wrong.
181	 */
182	if ((resp = ng_dialog_id(snmp_node, NGM_GENERIC_COOKIE, NGM_LISTNODES,
183	    NULL, 0)) == NULL) {
184		syslog(LOG_ERR, "cannot fetch node list: %m");
185		free(aif->sys);
186		return (-1);
187	}
188	list = (struct namelist *)(void *)resp->data;
189
190	for (i = 0; i < list->numnames; i++) {
191		if (strcmp(list->nodeinfo[i].type, NG_ATM_NODE_TYPE) != 0)
192			continue;
193		if ((resp1 = ng_dialog_id(list->nodeinfo[i].id,
194		    NGM_ATM_COOKIE, NGM_ATM_GET_IFNAME, NULL, 0)) == NULL)
195			continue;
196		if (strcmp(resp1->data, aif->pub.ifp->name) == 0) {
197			free(resp1);
198			break;
199		}
200		free(resp1);
201	}
202	if (i == list->numnames)
203		aif->sys->atm_node = 0;
204	else
205		aif->sys->atm_node = list->nodeinfo[i].id;
206
207	free(resp);
208
209	if ((aif->sys->regc = ng_register_cookie(module, NGM_ATM_COOKIE,
210	    aif->sys->atm_node, handle_atm_message, aif)) == NULL) {
211		syslog(LOG_ERR, "cannot register cookie: %m");
212		free(aif->sys);
213		return (-1);
214	}
215	return (0);
216}
217
218/*
219 * Table of all ATM interfaces - Ng part
220 */
221int
222op_atmif_ng(struct snmp_context *ctx __unused, struct snmp_value *value,
223    u_int sub, u_int vindex __unused, enum snmp_op op)
224{
225	struct atmif_priv *aif;
226	int err;
227
228	if ((err = atmif_get_aif(value, sub, op, &aif)) != SNMP_ERR_NOERROR)
229		return (err);
230
231	if (op == SNMP_OP_SET) {
232		switch (value->var.subs[sub - 1]) {
233
234		  default:
235			return (SNMP_ERR_NOT_WRITEABLE);
236		}
237	}
238
239	switch (value->var.subs[sub - 1]) {
240
241	  case LEAF_begemotAtmIfNodeId:
242		value->v.uint32 = aif->sys->atm_node;
243		return (SNMP_ERR_NOERROR);
244	}
245	abort();
246}
247
248/*
249 * Get vendor string
250 */
251int
252atm_sys_get_hw_vendor(struct atmif_priv *aif, struct snmp_value *value)
253{
254
255	if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0]))
256		return (string_get(value, "unknown", -1));
257	return (string_get(value, hwinfo[aif->pub.mib->device].vendor, -1));
258}
259
260/*
261 * Get device string
262 */
263int
264atm_sys_get_hw_device(struct atmif_priv *aif, struct snmp_value *value)
265{
266
267	if (aif->pub.mib->device >= sizeof(hwinfo) / sizeof(hwinfo[0]))
268		return (string_get(value, "unknown", -1));
269	return (string_get(value, hwinfo[aif->pub.mib->device].device, -1));
270}
271
272/*
273 * Extract the ATM MIB from the interface's private MIB
274 */
275void
276atmif_sys_fill_mib(struct atmif_priv *aif)
277{
278	struct ifatm_mib *mib;
279
280	if (aif->pub.ifp->specmiblen != sizeof(struct ifatm_mib)) {
281		syslog(LOG_ERR, "atmif MIB has wrong size %zu",
282		    aif->pub.ifp->specmiblen);
283		memset(aif->pub.mib, 0, sizeof(*aif->pub.mib));
284		aif->pub.mib->version = 0;
285		return;
286	}
287	mib = (struct ifatm_mib *)aif->pub.ifp->specmib;
288
289	aif->pub.mib->device = mib->device;
290	aif->pub.mib->serial = mib->serial;
291	aif->pub.mib->hw_version = mib->hw_version;
292	aif->pub.mib->sw_version = mib->sw_version;
293	aif->pub.mib->media = mib->media;
294
295	memcpy(aif->pub.mib->esi, mib->esi, 6);
296	aif->pub.mib->pcr = mib->pcr;
297	aif->pub.mib->vpi_bits = mib->vpi_bits;
298	aif->pub.mib->vci_bits = mib->vci_bits;
299	aif->pub.mib->max_vpcs = mib->max_vpcs;
300	aif->pub.mib->max_vccs = mib->max_vccs;
301}
302