Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/bsnmp/snmp_mibII/mibII_interfaces.c
39478 views
1
/*
2
* Copyright (c) 2001-2003
3
* Fraunhofer Institute for Open Communication Systems (FhG Fokus).
4
* All rights reserved.
5
*
6
* Author: Harti Brandt <[email protected]>
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* 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 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 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
* $Begemot: bsnmp/snmp_mibII/mibII_interfaces.c,v 1.17 2006/02/14 09:04:19 brandt_h Exp $
30
*
31
* Interfaces group.
32
*/
33
#include "mibII.h"
34
#include "mibII_oid.h"
35
36
/*
37
* This structure catches all changes to a interface entry
38
*/
39
struct ifchange {
40
struct snmp_dependency dep;
41
42
u_int ifindex;
43
44
uint32_t set;
45
int promisc;
46
int admin;
47
int traps;
48
49
uint32_t rb;
50
int rb_flags;
51
int rb_traps;
52
};
53
#define IFC_PROMISC 0x0001
54
#define IFC_ADMIN 0x0002
55
#define IFC_TRAPS 0x0004
56
#define IFRB_FLAGS 0x0001
57
#define IFRB_TRAPS 0x0002
58
59
static const struct asn_oid
60
oid_ifTable = OIDX_ifTable;
61
62
/*
63
* This function handles all changes to the interface table and interface
64
* extension table.
65
*/
66
static int
67
ifchange_func(struct snmp_context *ctx __unused, struct snmp_dependency *dep,
68
enum snmp_depop op)
69
{
70
struct ifchange *ifc = (struct ifchange *)dep;
71
struct mibif *ifp;
72
struct ifreq ifr, ifr1;
73
74
if ((ifp = mib_find_if(ifc->ifindex)) == NULL)
75
return (SNMP_ERR_NO_CREATION);
76
77
switch (op) {
78
79
case SNMP_DEPOP_COMMIT:
80
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
81
if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr) == -1) {
82
syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
83
return (SNMP_ERR_GENERR);
84
}
85
if (ifc->set & IFC_PROMISC) {
86
ifr.ifr_flags &= ~IFF_PROMISC;
87
if (ifc->promisc)
88
ifr.ifr_flags |= IFF_PROMISC;
89
ifc->rb |= IFRB_FLAGS;
90
}
91
if (ifc->set & IFC_ADMIN) {
92
ifr.ifr_flags &= ~IFF_UP;
93
if (ifc->admin)
94
ifr.ifr_flags |= IFF_UP;
95
ifc->rb |= IFRB_FLAGS;
96
}
97
if (ifc->rb & IFRB_FLAGS) {
98
strlcpy(ifr1.ifr_name, ifp->name, sizeof(ifr1.ifr_name));
99
if (ioctl(mib_netsock, SIOCGIFFLAGS, &ifr1) == -1) {
100
syslog(LOG_ERR, "GIFFLAGS(%s): %m", ifp->name);
101
return (SNMP_ERR_GENERR);
102
}
103
ifc->rb_flags = ifr1.ifr_flags;
104
if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
105
syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
106
return (SNMP_ERR_GENERR);
107
}
108
(void)mib_fetch_ifmib(ifp);
109
}
110
if (ifc->set & IFC_TRAPS) {
111
ifc->rb |= IFRB_TRAPS;
112
ifc->rb_traps = ifp->trap_enable;
113
ifp->trap_enable = ifc->traps;
114
}
115
return (SNMP_ERR_NOERROR);
116
117
case SNMP_DEPOP_ROLLBACK:
118
if (ifc->rb & IFRB_FLAGS) {
119
strlcpy(ifr.ifr_name, ifp->name, sizeof(ifr.ifr_name));
120
ifr.ifr_flags = ifc->rb_flags;
121
if (ioctl(mib_netsock, SIOCSIFFLAGS, &ifr) == -1) {
122
syslog(LOG_ERR, "SIFFLAGS(%s): %m", ifp->name);
123
return (SNMP_ERR_UNDO_FAILED);
124
}
125
(void)mib_fetch_ifmib(ifp);
126
}
127
if (ifc->rb & IFRB_TRAPS)
128
ifp->trap_enable = ifc->rb_traps;
129
return (SNMP_ERR_NOERROR);
130
131
case SNMP_DEPOP_FINISH:
132
return (SNMP_ERR_NOERROR);
133
134
}
135
abort();
136
}
137
138
/*
139
* Return difference to daemon start time in ticks truncated to a
140
* 32-bit value. If the timeval is 0 then return 0.
141
*/
142
static uint32_t
143
ticks_get_timeval(struct timeval *tv)
144
{
145
uint64_t v;
146
147
if (tv->tv_sec != 0 || tv->tv_usec != 0) {
148
v = 100ULL * tv->tv_sec + tv->tv_usec / 10000ULL;
149
if (v > start_tick)
150
return (v - start_tick);
151
}
152
return (0);
153
}
154
155
/*
156
* Scalars
157
*/
158
int
159
op_interfaces(struct snmp_context *ctx __unused, struct snmp_value *value,
160
u_int sub, u_int idx __unused, enum snmp_op op)
161
{
162
switch (op) {
163
164
case SNMP_OP_GETNEXT:
165
abort();
166
167
case SNMP_OP_GET:
168
break;
169
170
case SNMP_OP_SET:
171
return (SNMP_ERR_NOT_WRITEABLE);
172
173
case SNMP_OP_ROLLBACK:
174
case SNMP_OP_COMMIT:
175
abort();
176
}
177
178
switch (value->var.subs[sub - 1]) {
179
180
case LEAF_ifNumber:
181
value->v.integer = mib_if_number;
182
break;
183
}
184
return (SNMP_ERR_NOERROR);
185
}
186
187
/*
188
* Iftable entry
189
*/
190
int
191
op_ifentry(struct snmp_context *ctx, struct snmp_value *value,
192
u_int sub, u_int iidx __unused, enum snmp_op op)
193
{
194
struct mibif *ifp = NULL;
195
int ret;
196
struct ifchange *ifc;
197
struct asn_oid idx;
198
199
switch (op) {
200
201
case SNMP_OP_GETNEXT:
202
if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
203
return (SNMP_ERR_NOSUCHNAME);
204
value->var.len = sub + 1;
205
value->var.subs[sub] = ifp->index;
206
break;
207
208
case SNMP_OP_GET:
209
if (value->var.len - sub != 1)
210
return (SNMP_ERR_NOSUCHNAME);
211
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
212
return (SNMP_ERR_NOSUCHNAME);
213
break;
214
215
case SNMP_OP_SET:
216
if (value->var.len - sub != 1)
217
return (SNMP_ERR_NO_CREATION);
218
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
219
return (SNMP_ERR_NO_CREATION);
220
if (value->var.subs[sub - 1] != LEAF_ifAdminStatus)
221
return (SNMP_ERR_NOT_WRITEABLE);
222
223
idx.len = 1;
224
idx.subs[0] = ifp->index;
225
226
if (value->v.integer != 1 && value->v.integer != 2)
227
return (SNMP_ERR_WRONG_VALUE);
228
229
if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
230
&oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
231
return (SNMP_ERR_RES_UNAVAIL);
232
ifc->ifindex = ifp->index;
233
234
if (ifc->set & IFC_ADMIN)
235
return (SNMP_ERR_INCONS_VALUE);
236
ifc->set |= IFC_ADMIN;
237
ifc->admin = (value->v.integer == 1) ? 1 : 0;
238
239
return (SNMP_ERR_NOERROR);
240
241
case SNMP_OP_ROLLBACK:
242
case SNMP_OP_COMMIT:
243
return (SNMP_ERR_NOERROR);
244
}
245
246
if (ifp->mibtick < this_tick)
247
(void)mib_fetch_ifmib(ifp);
248
249
ret = SNMP_ERR_NOERROR;
250
switch (value->var.subs[sub - 1]) {
251
252
case LEAF_ifIndex:
253
value->v.integer = ifp->index;
254
break;
255
256
case LEAF_ifDescr:
257
ret = string_get(value, ifp->descr, -1);
258
break;
259
260
case LEAF_ifType:
261
value->v.integer = ifp->mib.ifmd_data.ifi_type;
262
break;
263
264
case LEAF_ifMtu:
265
value->v.integer = ifp->mib.ifmd_data.ifi_mtu;
266
break;
267
268
case LEAF_ifSpeed:
269
value->v.integer = ifp->mib.ifmd_data.ifi_baudrate;
270
break;
271
272
case LEAF_ifPhysAddress:
273
ret = string_get(value, ifp->physaddr,
274
ifp->physaddrlen);
275
break;
276
277
case LEAF_ifAdminStatus:
278
value->v.integer =
279
(ifp->mib.ifmd_flags & IFF_UP) ? 1 : 2;
280
break;
281
282
case LEAF_ifOperStatus:
283
/*
284
* According to RFC 2863 the state should be Up if the
285
* interface is ready to transmit packets. We takes this to
286
* mean that the interface should be running and should have
287
* a carrier. If it is running and has no carrier we interpret
288
* this as 'waiting for an external event' (plugging in the
289
* cable) and hence return 'dormant'.
290
*/
291
if (ifp->mib.ifmd_flags & IFF_RUNNING) {
292
if (ifp->mib.ifmd_data.ifi_link_state != LINK_STATE_UP)
293
value->v.integer = 5; /* state dormant */
294
else
295
value->v.integer = 1; /* state up */
296
} else
297
value->v.integer = 2; /* state down */
298
break;
299
300
case LEAF_ifLastChange:
301
value->v.uint32 =
302
ticks_get_timeval(&ifp->mib.ifmd_data.ifi_lastchange);
303
break;
304
305
case LEAF_ifInOctets:
306
value->v.uint32 = ifp->mib.ifmd_data.ifi_ibytes;
307
break;
308
309
case LEAF_ifInUcastPkts:
310
value->v.uint32 = ifp->mib.ifmd_data.ifi_ipackets -
311
ifp->mib.ifmd_data.ifi_imcasts;
312
break;
313
314
case LEAF_ifInNUcastPkts:
315
value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
316
break;
317
318
case LEAF_ifInDiscards:
319
value->v.uint32 = ifp->mib.ifmd_data.ifi_iqdrops;
320
break;
321
322
case LEAF_ifInErrors:
323
value->v.uint32 = ifp->mib.ifmd_data.ifi_ierrors;
324
break;
325
326
case LEAF_ifInUnknownProtos:
327
value->v.uint32 = ifp->mib.ifmd_data.ifi_noproto;
328
break;
329
330
case LEAF_ifOutOctets:
331
value->v.uint32 = ifp->mib.ifmd_data.ifi_obytes;
332
break;
333
334
case LEAF_ifOutUcastPkts:
335
value->v.uint32 = ifp->mib.ifmd_data.ifi_opackets -
336
ifp->mib.ifmd_data.ifi_omcasts;
337
break;
338
339
case LEAF_ifOutNUcastPkts:
340
value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
341
break;
342
343
case LEAF_ifOutDiscards:
344
value->v.uint32 = ifp->mib.ifmd_snd_drops;
345
break;
346
347
case LEAF_ifOutErrors:
348
value->v.uint32 = ifp->mib.ifmd_data.ifi_oerrors;
349
break;
350
351
case LEAF_ifOutQLen:
352
value->v.uint32 = ifp->mib.ifmd_snd_len;
353
break;
354
355
case LEAF_ifSpecific:
356
value->v.oid = ifp->spec_oid;
357
break;
358
}
359
return (ret);
360
}
361
362
/*
363
* IfXtable entry
364
*/
365
int
366
op_ifxtable(struct snmp_context *ctx, struct snmp_value *value,
367
u_int sub, u_int iidx __unused, enum snmp_op op)
368
{
369
struct mibif *ifp = NULL;
370
int ret;
371
struct ifchange *ifc;
372
struct asn_oid idx;
373
374
switch (op) {
375
376
case SNMP_OP_GETNEXT:
377
if ((ifp = NEXT_OBJECT_INT(&mibif_list, &value->var, sub)) == NULL)
378
return (SNMP_ERR_NOSUCHNAME);
379
value->var.len = sub + 1;
380
value->var.subs[sub] = ifp->index;
381
break;
382
383
case SNMP_OP_GET:
384
if (value->var.len - sub != 1)
385
return (SNMP_ERR_NOSUCHNAME);
386
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
387
return (SNMP_ERR_NOSUCHNAME);
388
break;
389
390
case SNMP_OP_SET:
391
if (value->var.len - sub != 1)
392
return (SNMP_ERR_NO_CREATION);
393
if ((ifp = mib_find_if(value->var.subs[sub])) == NULL)
394
return (SNMP_ERR_NO_CREATION);
395
396
idx.len = 1;
397
idx.subs[0] = ifp->index;
398
399
if ((ifc = (struct ifchange *)snmp_dep_lookup(ctx,
400
&oid_ifTable, &idx, sizeof(*ifc), ifchange_func)) == NULL)
401
return (SNMP_ERR_RES_UNAVAIL);
402
ifc->ifindex = ifp->index;
403
404
switch (value->var.subs[sub - 1]) {
405
406
case LEAF_ifLinkUpDownTrapEnable:
407
if (value->v.integer != 1 && value->v.integer != 2)
408
return (SNMP_ERR_WRONG_VALUE);
409
if (ifc->set & IFC_TRAPS)
410
return (SNMP_ERR_INCONS_VALUE);
411
ifc->set |= IFC_TRAPS;
412
ifc->traps = (value->v.integer == 1) ? 1 : 0;
413
return (SNMP_ERR_NOERROR);
414
415
case LEAF_ifPromiscuousMode:
416
if (value->v.integer != 1 && value->v.integer != 2)
417
return (SNMP_ERR_WRONG_VALUE);
418
if (ifc->set & IFC_PROMISC)
419
return (SNMP_ERR_INCONS_VALUE);
420
ifc->set |= IFC_PROMISC;
421
ifc->promisc = (value->v.integer == 1) ? 1 : 0;
422
return (SNMP_ERR_NOERROR);
423
}
424
return (SNMP_ERR_NOT_WRITEABLE);
425
426
case SNMP_OP_ROLLBACK:
427
case SNMP_OP_COMMIT:
428
return (SNMP_ERR_NOERROR);
429
}
430
431
if (ifp->mibtick < this_tick)
432
(void)mib_fetch_ifmib(ifp);
433
434
ret = SNMP_ERR_NOERROR;
435
switch (value->var.subs[sub - 1]) {
436
437
case LEAF_ifName:
438
ret = string_get(value, ifp->name, -1);
439
break;
440
441
case LEAF_ifInMulticastPkts:
442
value->v.uint32 = ifp->mib.ifmd_data.ifi_imcasts;
443
break;
444
445
case LEAF_ifInBroadcastPkts:
446
value->v.uint32 = 0;
447
break;
448
449
case LEAF_ifOutMulticastPkts:
450
value->v.uint32 = ifp->mib.ifmd_data.ifi_omcasts;
451
break;
452
453
case LEAF_ifOutBroadcastPkts:
454
value->v.uint32 = 0;
455
break;
456
457
case LEAF_ifHCInOctets:
458
value->v.counter64 = MIBIF_PRIV(ifp)->hc_inoctets;
459
break;
460
461
case LEAF_ifHCInUcastPkts:
462
value->v.counter64 = MIBIF_PRIV(ifp)->hc_ipackets -
463
MIBIF_PRIV(ifp)->hc_imcasts;
464
break;
465
466
case LEAF_ifHCInMulticastPkts:
467
value->v.counter64 = MIBIF_PRIV(ifp)->hc_imcasts;
468
break;
469
470
case LEAF_ifHCInBroadcastPkts:
471
value->v.counter64 = 0;
472
break;
473
474
case LEAF_ifHCOutOctets:
475
value->v.counter64 = MIBIF_PRIV(ifp)->hc_outoctets;
476
break;
477
478
case LEAF_ifHCOutUcastPkts:
479
value->v.counter64 = MIBIF_PRIV(ifp)->hc_opackets -
480
MIBIF_PRIV(ifp)->hc_omcasts;
481
break;
482
483
case LEAF_ifHCOutMulticastPkts:
484
value->v.counter64 = MIBIF_PRIV(ifp)->hc_omcasts;
485
break;
486
487
case LEAF_ifHCOutBroadcastPkts:
488
value->v.counter64 = 0;
489
break;
490
491
case LEAF_ifLinkUpDownTrapEnable:
492
value->v.integer = ifp->trap_enable ? 1 : 2;
493
break;
494
495
case LEAF_ifHighSpeed:
496
value->v.integer =
497
(ifp->mib.ifmd_data.ifi_baudrate + 499999) / 1000000;
498
break;
499
500
case LEAF_ifPromiscuousMode:
501
value->v.integer =
502
(ifp->mib.ifmd_flags & IFF_PROMISC) ? 1 : 2;
503
break;
504
505
case LEAF_ifConnectorPresent:
506
value->v.integer = ifp->has_connector ? 1 : 2;
507
break;
508
509
case LEAF_ifAlias:
510
ret = string_get(value, ifp->alias, ifp->alias_size - 1);
511
break;
512
513
case LEAF_ifCounterDiscontinuityTime:
514
if (ifp->counter_disc > start_tick)
515
value->v.uint32 = ifp->counter_disc - start_tick;
516
else
517
value->v.uint32 = 0;
518
break;
519
}
520
return (ret);
521
}
522
523