1 /*
2 * Interface MIB architecture support for Solaris
3 */
4 #include <net-snmp/net-snmp-config.h>
5 #include <net-snmp/net-snmp-features.h>
6 #include <net-snmp/net-snmp-includes.h>
7 #include "if-mib/ifTable/ifTable_constants.h"
8 #include "kernel_sunos5.h"
9 #include "mibII/mibII_common.h"
10
11 #include <net-snmp/agent/net-snmp-agent-includes.h>
12
13 #include <net-snmp/data_access/interface.h>
14 #include "if-mib/data_access/interface.h"
15 #include "interface_private.h"
16 #include <sys/ioctl.h>
17 #include <sys/sockio.h>
18 #include <strings.h>
19 #include <string.h>
20
21 netsnmp_feature_child_of(interface_arch_set_admin_status, interface_all);
22
23 static int _set_ip_flags_v4(netsnmp_interface_entry *, mib2_ifEntry_t *);
24 static int _match_ifname_v4addr(void *ifname, void *ipaddr);
25 static int _get_v4addr(mib2_ifEntry_t *ife, mib2_ipAddrEntry_t *e);
26
27 static int _set_ip_flags_v6(netsnmp_interface_entry *, mib2_ifEntry_t *);
28 #ifdef SOLARIS_HAVE_IPV6_MIB_SUPPORT
29 static int _get_v6addr(mib2_ifEntry_t *ife, mib2_ipv6AddrEntry_t *ipv6e);
30 static int _match_ifname_v6addr(void *ifname, void *ipaddr);
31 #endif
32
33 void
netsnmp_arch_interface_init(void)34 netsnmp_arch_interface_init(void)
35 {
36 init_kernel_sunos5();
37 }
38
39 /*
40 * find the ifIndex for an interface name
41 *
42 * @retval 0 : no index found
43 * @retval >0: ifIndex for interface
44 */
45 oid
netsnmp_arch_interface_index_find(const char * name)46 netsnmp_arch_interface_index_find(const char *name)
47 {
48 #if defined(HAVE_IF_NAMETOINDEX)
49 return if_nametoindex(name);
50 #else /* use GIFINDEX */
51 return solaris2_if_nametoindex(name, strlen(name));
52 #endif /* defined(HAVE_IF_NAMETOINDEX) */
53 }
54
55 /*
56 * @retval 0 success
57 * @retval -1 no container specified
58 * @retval -2 could not create entry (probably malloc)
59 */
60 int
netsnmp_arch_interface_container_load(netsnmp_container * container,u_int l_flags)61 netsnmp_arch_interface_container_load(netsnmp_container* container,
62 u_int l_flags)
63 {
64 netsnmp_interface_entry *entry = NULL;
65 mib2_ifEntry_t ife;
66 int rc;
67 req_e req = GET_FIRST;
68 int error = 0;
69
70 DEBUGMSGTL(("access:interface:container:arch", "load (flags %u)\n",
71 l_flags));
72
73 if (container == NULL) {
74 snmp_log(LOG_ERR,
75 "no container specified/found for interface\n");
76 return -1;
77 }
78
79 while ((rc = getMibstat(MIB_INTERFACES, &ife, sizeof(ife), req,
80 &Get_everything, NULL)) == 0) {
81
82 req = GET_NEXT;
83
84 DEBUGMSGTL(("access:interface:container:arch",
85 "processing '%s'\n", ife.ifDescr.o_bytes));
86 entry =
87 netsnmp_access_interface_entry_create(ife.ifDescr.o_bytes,
88 ife.ifIndex);
89 if (entry == NULL) {
90 error = 1;
91 break;
92 }
93 entry->ns_flags = 0;
94
95 if (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP4_ONLY &&
96 _set_ip_flags_v4(entry, &ife) == 0) {
97 netsnmp_access_interface_entry_free(entry);
98 continue;
99 } else if (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_IP6_ONLY &&
100 _set_ip_flags_v6(entry, &ife) == 0) {
101 netsnmp_access_interface_entry_free(entry);
102 continue;
103 } else {
104 (void) _set_ip_flags_v4(entry, &ife);
105 (void) _set_ip_flags_v6(entry, &ife);
106 }
107
108 /*
109 * collect the information needed by IF-MIB
110 */
111 entry->paddr = (char*)malloc(ife.ifPhysAddress.o_length);
112 if (entry->paddr == NULL) {
113 netsnmp_access_interface_entry_free(entry);
114 error = 1;
115 break;
116 }
117 entry->paddr_len = ife.ifPhysAddress.o_length;
118 (void)memcpy(entry->paddr, ife.ifPhysAddress.o_bytes,
119 ife.ifPhysAddress.o_length);
120
121 entry->type = ife.ifType;
122 entry->mtu = ife.ifMtu;
123 entry->speed = ife.ifSpeed;
124 entry->speed_high = entry->speed / 1000000;
125 entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_HAS_HIGH_SPEED;
126 entry->oper_status = ife.ifOperStatus;
127 entry->admin_status = ife.ifAdminStatus;
128
129 if (ife.flags & IFF_PROMISC)
130 entry->promiscuous = 1;
131
132 entry->ns_flags |= NETSNMP_INTERFACE_FLAGS_ACTIVE;
133
134 /*
135 * Interface Stats.
136 */
137 if (! (l_flags & NETSNMP_ACCESS_INTERFACE_LOAD_NO_STATS)) {
138 entry->ns_flags |=
139 NETSNMP_INTERFACE_FLAGS_HAS_BYTES |
140 NETSNMP_INTERFACE_FLAGS_HAS_DROPS |
141 NETSNMP_INTERFACE_FLAGS_HAS_MCAST_PKTS;
142 if (ife.ifHCInOctets > 0 || ife.ifHCOutOctets > 0) {
143 /*
144 * We make the assumption that if we have
145 * a 64-bit Octet counter, then the other
146 * counters are 64-bit as well.
147 */
148 DEBUGMSGTL(("access:interface:container:arch",
149 "interface '%s' have 64-bit stat counters\n",
150 entry->name));
151 entry->ns_flags |=
152 NETSNMP_INTERFACE_FLAGS_HAS_HIGH_BYTES |
153 NETSNMP_INTERFACE_FLAGS_HAS_HIGH_PACKETS;
154 /* in stats */
155 entry->stats.ibytes.low = ife.ifHCInOctets & 0xffffffff;
156 entry->stats.ibytes.high = ife.ifHCInOctets >> 32;
157 entry->stats.iucast.low = ife.ifHCInUcastPkts & 0xffffffff;
158 entry->stats.iucast.high = ife.ifHCInUcastPkts >> 32;
159 entry->stats.imcast.low = ife.ifHCInMulticastPkts & 0xffffffff;
160 entry->stats.imcast.high = ife.ifHCInMulticastPkts >> 32;
161 entry->stats.ibcast.low = ife.ifHCInBroadcastPkts & 0xffffffff;
162 entry->stats.ibcast.high = ife.ifHCInBroadcastPkts >> 32;
163 /* out stats */
164 entry->stats.obytes.low = ife.ifHCOutOctets & 0xffffffff;
165 entry->stats.obytes.high = ife.ifHCOutOctets >> 32;
166 entry->stats.oucast.low = ife.ifHCOutUcastPkts & 0xffffffff;
167 entry->stats.oucast.high = ife.ifHCOutUcastPkts >> 32;
168 entry->stats.omcast.low = ife.ifHCOutMulticastPkts & 0xffffffff;
169 entry->stats.omcast.high = ife.ifHCOutMulticastPkts >> 32;
170 entry->stats.obcast.low = ife.ifHCOutBroadcastPkts & 0xffffffff;
171 entry->stats.obcast.high = ife.ifHCOutBroadcastPkts >> 32;
172 } else {
173 DEBUGMSGTL(("access:interface:container:arch",
174 "interface '%s' have 32-bit stat counters\n",
175 entry->name));
176 /* in stats */
177 entry->stats.ibytes.low = ife.ifInOctets;
178 entry->stats.iucast.low = ife.ifInUcastPkts;
179 entry->stats.imcast.low = ife.ifHCInMulticastPkts & 0xffffffff;
180 entry->stats.ibcast.low = ife.ifHCInBroadcastPkts & 0xffffffff;
181 /* out stats */
182 entry->stats.obytes.low = ife.ifOutOctets;
183 entry->stats.oucast.low = ife.ifOutUcastPkts;
184 entry->stats.omcast.low = ife.ifHCOutMulticastPkts & 0xffffffff;
185 entry->stats.obcast.low = ife.ifHCOutBroadcastPkts & 0xffffffff;
186 }
187 /* in stats */
188 entry->stats.ierrors = ife.ifInErrors;
189 entry->stats.idiscards = ife.ifInDiscards;
190 entry->stats.iunknown_protos = ife.ifInUnknownProtos;
191 entry->stats.inucast = ife.ifInNUcastPkts;
192 /* out stats */
193 entry->stats.oerrors = ife.ifOutErrors;
194 entry->stats.odiscards = ife.ifOutDiscards;
195 entry->stats.onucast = ife.ifOutNUcastPkts;
196 entry->stats.oqlen = ife.ifOutQLen;
197
198 /* other stats */
199 entry->stats.collisions = ife.ifCollisions;
200 }
201
202 netsnmp_access_interface_entry_overrides(entry);
203
204 /*
205 * add to container
206 */
207 CONTAINER_INSERT(container, entry);
208 }
209 DEBUGMSGTL(("access:interface:container:arch", "rc = %d\n", rc));
210
211 if (error) {
212 DEBUGMSGTL(("access:interface:container:arch",
213 "error %d, free container\n", error));
214 netsnmp_access_interface_container_free(container,
215 NETSNMP_ACCESS_INTERFACE_FREE_NOFLAGS);
216 return -2;
217 }
218
219 return 0;
220 }
221 /**
222 * @internal
223 */
224 static int
_set_ip_flags_v4(netsnmp_interface_entry * entry,mib2_ifEntry_t * ife)225 _set_ip_flags_v4(netsnmp_interface_entry *entry, mib2_ifEntry_t *ife)
226 {
227 mib2_ipAddrEntry_t ipv4e;
228
229 if (_get_v4addr(ife, &ipv4e) > 0) {
230 entry->reasm_max_v4 = ipv4e.ipAdEntReasmMaxSize;
231 entry->ns_flags |=
232 NETSNMP_INTERFACE_FLAGS_HAS_IPV4 |
233 NETSNMP_INTERFACE_FLAGS_HAS_V4_REASMMAX;
234 #if defined( SOLARIS_HAVE_RFC4293_SUPPORT )
235 entry->retransmit_v4 = ipv4e.ipAdEntRetransmitTime;
236 entry->ns_flags |=
237 NETSNMP_INTERFACE_FLAGS_HAS_V4_RETRANSMIT;
238 #endif
239 return (1);
240 }
241 return (0);
242 }
243
244 /**
245 * @internal
246 */
247 static int
_set_ip_flags_v6(netsnmp_interface_entry * entry,mib2_ifEntry_t * ife)248 _set_ip_flags_v6(netsnmp_interface_entry *entry, mib2_ifEntry_t *ife)
249 {
250 #ifdef SOLARIS_HAVE_IPV6_MIB_SUPPORT
251 mib2_ipv6AddrEntry_t ipv6e;
252
253 if (_get_v6addr(ife, &ipv6e) > 0) {
254 entry->ns_flags |=
255 NETSNMP_INTERFACE_FLAGS_HAS_IPV6;
256 #if defined( SOLARIS_HAVE_RFC4293_SUPPORT )
257 if (ipv6e.ipv6AddrIdentifierLen <= sizeof(entry->v6_if_id)) {
258 entry->v6_if_id_len = ipv6e.ipv6AddrIdentifierLen;
259 (void)memcpy(&entry->v6_if_id, &ipv6e.ipv6AddrIdentifier,
260 entry->v6_if_id_len);
261 entry->ns_flags |=
262 NETSNMP_INTERFACE_FLAGS_HAS_V6_IFID;
263 }
264 entry->reasm_max_v6 = ipv6e.ipv6AddrReasmMaxSize;
265 entry->retransmit_v6 = ipv6e.ipv6AddrRetransmitTime;
266 entry->reachable_time = ipv6e.ipv6AddrReachableTime;
267 entry->ns_flags |=
268 NETSNMP_INTERFACE_FLAGS_HAS_V6_REASMMAX |
269 NETSNMP_INTERFACE_FLAGS_HAS_V6_RETRANSMIT |
270 NETSNMP_INTERFACE_FLAGS_HAS_V6_REACHABLE;
271
272 /* XXX forwarding info missing */
273 #else
274 /* XXX Don't have this info, 1500 is the minimum */
275 entry->reasm_max_v6 = 1500;
276 entry->ns_flags |=
277 NETSNMP_INTERFACE_FLAGS_HAS_V6_REASMMAX; /* ??? */
278 #endif /* SOLARIS_HAVE_RFC4293_SUPPORT */
279 return (1);
280 }
281 #endif /* SOLARIS_HAVE_IPV6_MIB_SUPPORT */
282 return (0);
283 }
284
285 /**
286 * @internal
287 */
288 static int
_match_ifname_v4addr(void * ifname,void * ipaddr)289 _match_ifname_v4addr(void *ifname, void *ipaddr)
290 {
291 DeviceName *devname = &((mib2_ipAddrEntry_t *)ipaddr)->ipAdEntIfIndex;
292
293 return (strncmp((char *)ifname, devname->o_bytes, devname->o_length));
294
295 }
296
297 /**
298 * @internal
299 *
300 * Search for address entry that belongs to the IF entry.
301 * Returns 1 if an address was found, in which case the entry
302 * will be stored in ipv4e. If not entry was found, 0 is returned.
303 *
304 */
305 static int
_get_v4addr(mib2_ifEntry_t * ife,mib2_ipAddrEntry_t * ipv4e)306 _get_v4addr(mib2_ifEntry_t *ife, mib2_ipAddrEntry_t *ipv4e)
307 {
308 int rc;
309
310 if ((rc = getMibstat(MIB_IP_ADDR, ipv4e, sizeof(*ipv4e), GET_EXACT,
311 &_match_ifname_v4addr, &ife->ifDescr.o_bytes)) == 0)
312 return (1);
313 memset(ipv4e, '\0', sizeof(*ipv4e));
314 return (0);
315 }
316
317 #ifdef SOLARIS_HAVE_IPV6_MIB_SUPPORT
318 /**
319 * @internal
320 */
321 static int
_match_ifname_v6addr(void * ifname,void * ipaddr)322 _match_ifname_v6addr(void *ifname, void *ipaddr)
323 {
324 DeviceName *devname = &((mib2_ipv6AddrEntry_t*)ipaddr)->ipv6AddrIfIndex;
325
326 return (strncmp((char *)ifname, devname->o_bytes, devname->o_length));
327
328 }
329
330 /**
331 * @internal
332 *
333 * Search for address entry that belongs to the IF entry.
334 * Returns 1 if an address was found, in which case the entry
335 * will be stored in ipv4e. If not entry was found, 0 is returned.
336 *
337 */
338 static int
_get_v6addr(mib2_ifEntry_t * ife,mib2_ipv6AddrEntry_t * ipv6e)339 _get_v6addr(mib2_ifEntry_t *ife, mib2_ipv6AddrEntry_t *ipv6e)
340 {
341 int rc;
342
343 if ((rc = getMibstat(MIB_IP6_ADDR, ipv6e, sizeof(*ipv6e), GET_EXACT,
344 &_match_ifname_v6addr, &ife->ifDescr.o_bytes)) == 0) {
345 return (1);
346 }
347 memset(ipv6e, '\0', sizeof(*ipv6e));
348 return (0);
349 }
350 #endif /* SOLARIS_HAVE_IPV6_MIB_SUPPORT */
351
352 #ifndef NETSNMP_FEATURE_REMOVE_INTERFACE_ARCH_SET_ADMIN_STATUS
353 int
netsnmp_arch_set_admin_status(netsnmp_interface_entry * entry,int ifAdminStatus_val)354 netsnmp_arch_set_admin_status(netsnmp_interface_entry * entry,
355 int ifAdminStatus_val)
356 {
357 DEBUGMSGTL(("access:interface:arch", "set_admin_status\n"));
358
359 /*
360 * XXX Not supported yet
361 */
362 return (-1);
363 }
364 #endif /* NETSNMP_FEATURE_REMOVE_INTERFACE_ARCH_SET_ADMIN_STATUS */
365