]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - usr.sbin/bsnmpd/modules/snmp_atm/atm_sys.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / usr.sbin / bsnmpd / modules / snmp_atm / atm_sys.c
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$
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
51 static const struct hwinfo {
52         const char *device;
53         const char *vendor;
54 } hwinfo[] = {
55         ATM_DEVICE_NAMES
56 };
57
58 struct 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  */
66 struct atmif *
67 atm_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
78 u_int
79 atm_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  */
89 void
90 atmif_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  */
101 static void
102 handle_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  */
157 int
158 atmif_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  */
221 int
222 op_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  */
251 int
252 atm_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  */
263 int
264 atm_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  */
275 void
276 atmif_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 }