Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_network_tbl.c
107769 views
1
/*-
2
* Copyright (c) 2005-2006 The FreeBSD Project
3
* All rights reserved.
4
*
5
* Author: Victor Cruceru <[email protected]>
6
*
7
* Redistribution of this software and documentation and use in source and
8
* binary forms, with or without modification, are permitted provided that
9
* the following conditions are met:
10
*
11
* 1. Redistributions of source code or documentation must retain the above
12
* copyright notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
/*
31
* Host Resources MIB implementation for SNMPd: instrumentation for
32
* hrNetworkTable
33
*/
34
35
#include <sys/types.h>
36
#include <sys/ioctl.h>
37
#include <sys/socket.h>
38
#include <sys/sysctl.h>
39
40
#include <net/if.h>
41
#include <net/if_mib.h>
42
43
#include <assert.h>
44
#include <ctype.h>
45
#include <err.h>
46
#include <errno.h>
47
#include <ifaddrs.h>
48
#include <stdarg.h>
49
#include <stdlib.h>
50
#include <string.h>
51
#include <syslog.h>
52
#include <unistd.h>
53
54
#include "hostres_snmp.h"
55
#include "hostres_oid.h"
56
#include "hostres_tree.h"
57
58
#include <bsnmp/snmp_mibII.h>
59
60
/*
61
* This structure is used to hold a SNMP table entry
62
* for HOST-RESOURCES-MIB's hrNetworkTable
63
*/
64
struct network_entry {
65
int32_t index;
66
int32_t ifIndex;
67
TAILQ_ENTRY(network_entry) link;
68
#define HR_NETWORK_FOUND 0x001
69
uint32_t flags;
70
71
};
72
TAILQ_HEAD(network_tbl, network_entry);
73
74
/* the head of the list with hrNetworkTable's entries */
75
static struct network_tbl network_tbl = TAILQ_HEAD_INITIALIZER(network_tbl);
76
77
/* last (agent) tick when hrNetworkTable was updated */
78
static uint64_t network_tick;
79
80
/* maximum number of ticks between updates of network table */
81
uint32_t network_tbl_refresh = HR_NETWORK_TBL_REFRESH * 100;
82
83
/* Constants */
84
static const struct asn_oid OIDX_hrDeviceNetwork_c = OIDX_hrDeviceNetwork;
85
86
/**
87
* Create a new entry into the network table
88
*/
89
static struct network_entry *
90
network_entry_create(const struct device_entry *devEntry)
91
{
92
struct network_entry *entry;
93
94
assert(devEntry != NULL);
95
if (devEntry == NULL)
96
return (NULL);
97
98
if ((entry = malloc(sizeof(*entry))) == NULL) {
99
syslog(LOG_WARNING, "%s: %m", __func__);
100
return (NULL);
101
}
102
103
memset(entry, 0, sizeof(*entry));
104
entry->index = devEntry->index;
105
INSERT_OBJECT_INT(entry, &network_tbl);
106
107
return (entry);
108
}
109
110
/**
111
* Delete an entry in the network table
112
*/
113
static void
114
network_entry_delete(struct network_entry* entry)
115
{
116
117
TAILQ_REMOVE(&network_tbl, entry, link);
118
free(entry);
119
}
120
121
/**
122
* Fetch the interfaces from the mibII module, get their real name from the
123
* kernel and try to find it in the device table.
124
*/
125
static void
126
network_get_interfaces(void)
127
{
128
struct device_entry *dev;
129
struct network_entry *net;
130
struct mibif *ifp;
131
int name[6];
132
size_t len;
133
char *dname;
134
135
name[0] = CTL_NET;
136
name[1] = PF_LINK;
137
name[2] = NETLINK_GENERIC;
138
name[3] = IFMIB_IFDATA;
139
name[5] = IFDATA_DRIVERNAME;
140
141
for (ifp = mib_first_if(); ifp != NULL; ifp = mib_next_if(ifp)) {
142
HRDBG("%s %s", ifp->name, ifp->descr);
143
144
name[4] = ifp->sysindex;
145
146
/* get the original name */
147
len = 0;
148
if (sysctl(name, 6, NULL, &len, 0, 0) < 0) {
149
syslog(LOG_ERR, "sysctl(net.link.ifdata.%d."
150
"drivername): %m", ifp->sysindex);
151
continue;
152
}
153
if ((dname = malloc(len)) == NULL) {
154
syslog(LOG_ERR, "malloc: %m");
155
continue;
156
}
157
if (sysctl(name, 6, dname, &len, 0, 0) < 0) {
158
syslog(LOG_ERR, "sysctl(net.link.ifdata.%d."
159
"drivername): %m", ifp->sysindex);
160
free(dname);
161
continue;
162
}
163
164
HRDBG("got device %s (%s)", ifp->name, dname);
165
166
if ((dev = device_find_by_name(dname)) == NULL) {
167
HRDBG("%s not in hrDeviceTable", dname);
168
free(dname);
169
continue;
170
}
171
HRDBG("%s found in hrDeviceTable", dname);
172
173
dev->type = &OIDX_hrDeviceNetwork_c;
174
dev->flags |= HR_DEVICE_IMMUTABLE;
175
176
free(dname);
177
178
/* Then check hrNetworkTable for this device */
179
TAILQ_FOREACH(net, &network_tbl, link)
180
if (net->index == dev->index)
181
break;
182
183
if (net == NULL && (net = network_entry_create(dev)) == NULL)
184
continue;
185
186
net->flags |= HR_NETWORK_FOUND;
187
net->ifIndex = ifp->index;
188
}
189
190
network_tick = this_tick;
191
}
192
193
/**
194
* Finalization routine for hrNetworkTable.
195
* It destroys the lists and frees any allocated heap memory.
196
*/
197
void
198
fini_network_tbl(void)
199
{
200
struct network_entry *n1;
201
202
while ((n1 = TAILQ_FIRST(&network_tbl)) != NULL) {
203
TAILQ_REMOVE(&network_tbl, n1, link);
204
free(n1);
205
}
206
}
207
208
/**
209
* Get the interface list from mibII only at this point to be sure that
210
* it is there already.
211
*/
212
void
213
start_network_tbl(void)
214
{
215
216
mib_refresh_iflist();
217
network_get_interfaces();
218
}
219
220
/**
221
* Refresh the table.
222
*/
223
static void
224
refresh_network_tbl(void)
225
{
226
struct network_entry *entry, *entry_tmp;
227
228
if (this_tick - network_tick < network_tbl_refresh) {
229
HRDBG("no refresh needed");
230
return;
231
}
232
233
/* mark each entry as missing */
234
TAILQ_FOREACH(entry, &network_tbl, link)
235
entry->flags &= ~HR_NETWORK_FOUND;
236
237
network_get_interfaces();
238
239
/*
240
* Purge items that disappeared
241
*/
242
TAILQ_FOREACH_SAFE(entry, &network_tbl, link, entry_tmp) {
243
if (!(entry->flags & HR_NETWORK_FOUND))
244
network_entry_delete(entry);
245
}
246
247
HRDBG("refresh DONE");
248
}
249
250
/*
251
* This is the implementation for a generated (by our SNMP tool)
252
* function prototype, see hostres_tree.h
253
* It handles the SNMP operations for hrNetworkTable
254
*/
255
int
256
op_hrNetworkTable(struct snmp_context *ctx __unused, struct snmp_value *value,
257
u_int sub, u_int iidx __unused, enum snmp_op curr_op)
258
{
259
struct network_entry *entry;
260
261
refresh_network_tbl();
262
263
switch (curr_op) {
264
265
case SNMP_OP_GETNEXT:
266
if ((entry = NEXT_OBJECT_INT(&network_tbl,
267
&value->var, sub)) == NULL)
268
return (SNMP_ERR_NOSUCHNAME);
269
value->var.len = sub + 1;
270
value->var.subs[sub] = entry->index;
271
goto get;
272
273
case SNMP_OP_GET:
274
if ((entry = FIND_OBJECT_INT(&network_tbl,
275
&value->var, sub)) == NULL)
276
return (SNMP_ERR_NOSUCHNAME);
277
goto get;
278
279
case SNMP_OP_SET:
280
if ((entry = FIND_OBJECT_INT(&network_tbl,
281
&value->var, sub)) == NULL)
282
return (SNMP_ERR_NO_CREATION);
283
return (SNMP_ERR_NOT_WRITEABLE);
284
285
case SNMP_OP_ROLLBACK:
286
case SNMP_OP_COMMIT:
287
abort();
288
}
289
abort();
290
291
get:
292
switch (value->var.subs[sub - 1]) {
293
294
case LEAF_hrNetworkIfIndex:
295
value->v.integer = entry->ifIndex;
296
return (SNMP_ERR_NOERROR);
297
298
}
299
abort();
300
}
301
302