int _set(ng_netdev_t *dev, netopt_t opt, void *value, size_t value_len) { (void)dev; switch (opt) { case NETOPT_ADDRESS: return _set_address(value, value_len); case NETOPT_CHANNEL: return _set_channel(value, value_len); case NETOPT_NID: return _set_pan(value, value_len); case NETOPT_TX_POWER: return _set_txpower(value, value_len); case NETOPT_STATE: return _set_state(value, value_len); default: return -ENOTSUP; } }
/* * Print a description of the network interfaces. */ void intpr(int interval) { oid ifcol_oid[] = { 1,3,6,1,2,1,2,2,1,0 }; size_t ifcol_len = OID_LENGTH( ifcol_oid ); struct _if_info *if_head, *if_tail, *cur_if; netsnmp_variable_list *var, *vp; /* * Track maximum field widths, expanding as necessary * This is one reason why results can't be * displayed immediately they are retrieved. */ int max_name = 4, max_ip = 7, max_route = 7, max_outq = 5; int max_ipkts = 5, max_ierrs = 5, max_opkts = 5, max_oerrs = 5; int max_ibytes = 6, max_obytes = 6; int i; if (interval) { sidewaysintpr((unsigned)interval); return; } /* * The traditional "netstat -i" output combines information * from two SNMP tables: * ipAddrTable (for the IP address/network) * ifTable (for the interface statistics) * * The previous approach was to retrieve (and save) the * address information first. Then walk the main ifTable, * add the relevant stored addresses, and saving the * full information for each interface, before displaying * the results as a separate pass. * * This code reverses this general structure, by first retrieving * (and storing) the interface statistics for the whole table, * then inserting the address information obtained from the * ipAddrTable, and finally displaying the results. * Such an arrangement should make it easier to extend this * to handle non-IP interfaces (hence not in ipAddrTable) */ if_head = NULL; if_tail = NULL; var = NULL; #define ADD_IFVAR( x ) ifcol_oid[ ifcol_len-1 ] = x; \ snmp_varlist_add_variable( &var, ifcol_oid, ifcol_len, ASN_NULL, NULL, 0) ADD_IFVAR( 2 ); /* ifName */ ADD_IFVAR( 4 ); /* ifMtu */ ADD_IFVAR( 8 ); /* ifOperStatus */ /* * The Net/Open-BSD behaviour is to display *either* byte * counts *or* packet/error counts (but not both). FreeBSD * integrates the byte counts into the traditional display. * * The previous 'snmpnetstat' implementation followed the * separatist model. This re-write offers an opportunity * to adopt the (more useful, IMO) Free-BSD approach. * * Or we could perhaps support both styles? :-) */ if (bflag || oflag) { ADD_IFVAR( 10 ); /* ifInOctets */ ADD_IFVAR( 16 ); /* ifOutOctets */ } if (!oflag) { ADD_IFVAR( 11 ); /* ifInUcastPkts */ ADD_IFVAR( 12 ); /* ifInNUcastPkts */ ADD_IFVAR( 14 ); /* ifInErrors */ ADD_IFVAR( 17 ); /* ifOutUcastPkts */ ADD_IFVAR( 18 ); /* ifOutNUcastPkts */ ADD_IFVAR( 20 ); /* ifOutErrors */ ADD_IFVAR( 21 ); /* ifOutQLen */ } #if 0 if (tflag) { ADD_IFVAR( XX ); /* ??? */ } #endif if (dflag) { ADD_IFVAR( 19 ); /* ifOutDiscards */ } #undef ADD_IFVAR /* * Now walk the ifTable, creating a list of interfaces */ while ( 1 ) { if (netsnmp_query_getnext( var, ss ) != SNMP_ERR_NOERROR) break; ifcol_oid[ ifcol_len-1 ] = 2; /* ifDescr */ if ( snmp_oid_compare( ifcol_oid, ifcol_len, var->name, ifcol_len) != 0 ) break; /* End of Table */ cur_if = SNMP_MALLOC_TYPEDEF( struct _if_info ); if (!cur_if) break; cur_if->ifindex = var->name[ var->name_length-1 ]; for ( vp=var; vp; vp=vp->next_variable ) { if ( ! vp->val.integer ) continue; if ( var->name[ var->name_length-1 ] != cur_if->ifindex ) { /* * Inconsistent index information * XXX - Try to recover ? */ SNMP_FREE( cur_if ); cur_if = NULL; break; /* not for now, no */ } switch ( vp->name[ var->name_length-2 ] ) { case 2: /* ifDescr */ if (vp->val_len >= sizeof(cur_if->name)) vp->val_len = sizeof(cur_if->name)-1; memmove( cur_if->name, vp->val.string, vp->val_len ); cur_if->name[vp->val_len] = 0; if ((i = strlen(cur_if->name) + 1) > max_name) max_name = i; break; case 4: /* ifMtu */ cur_if->mtu = *vp->val.integer; break; case 8: /* ifOperStatus */ cur_if->operstatus = *vp->val.integer; /* XXX - any special processing ?? */ break; case 10: /* ifInOctets */ sprintf(cur_if->s_ibytes, "%lu", *vp->val.integer); i = strlen(cur_if->s_ibytes); if (i > max_ibytes) max_ibytes = i; break; case 11: /* ifInUcastPkts */ cur_if->ipkts += *vp->val.integer; sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts); i = strlen(cur_if->s_ipkts); if (i > max_ipkts) max_ipkts = i; break; case 12: /* ifInNUcastPkts */ cur_if->ipkts += *vp->val.integer; sprintf(cur_if->s_ipkts, "%lu", cur_if->ipkts); i = strlen(cur_if->s_ipkts); if (i > max_ipkts) max_ipkts = i; break; case 14: /* ifInErrors */ sprintf(cur_if->s_ierrs, "%lu", *vp->val.integer); i = strlen(cur_if->s_ierrs); if (i > max_ierrs) max_ierrs = i; break; case 16: /* ifOutOctets */ sprintf(cur_if->s_obytes, "%lu", *vp->val.integer); i = strlen(cur_if->s_obytes); if (i > max_obytes) max_obytes = i; break; case 17: /* ifOutUcastPkts */ cur_if->opkts += *vp->val.integer; sprintf(cur_if->s_opkts, "%lu", cur_if->opkts); i = strlen(cur_if->s_opkts); if (i > max_opkts) max_opkts = i; break; case 18: /* ifOutNUcastPkts */ cur_if->opkts += *vp->val.integer; sprintf(cur_if->s_opkts, "%lu", cur_if->opkts); i = strlen(cur_if->s_opkts); if (i > max_opkts) max_opkts = i; break; case 19: /* ifOutDiscards */ cur_if->drops = *vp->val.integer; break; case 20: /* ifOutErrors */ sprintf(cur_if->s_oerrs, "%lu", *vp->val.integer); i = strlen(cur_if->s_oerrs); if (i > max_oerrs) max_oerrs = i; break; case 21: /* ifOutQLen */ sprintf(cur_if->s_outq, "%lu", *vp->val.integer); i = strlen(cur_if->s_outq); if (i > max_outq) max_outq = i; break; } } /* * XXX - Perhaps query ifXTable for additional info ?? * (ifName/ifAlias, or HC counters) */ /* * If we're to monitor a particular interface, then * ignore all others. It would be more efficient * to check this earlier (as part of processing * the varbind list). But performing this test here * means we can recognise ifXTable names as well) */ if ( intrface && strcmp( cur_if->name, intrface ) != 0) { SNMP_FREE( cur_if ); cur_if = NULL; } /* * Insert the IP address and network settings, and * add the new _if_stat structure to the list. */ if ( cur_if ) { _set_address( cur_if ); i = strlen(cur_if->ip); if (i > max_ip) max_ip = i; i = strlen(cur_if->route); if (i > max_route) max_route = i; if ( if_tail ) { if_tail->next = cur_if; if_tail = cur_if; } else { if_head = cur_if; if_tail = cur_if; } } } /* while (1) */ /* * Now display the specified results (in Free-BSD format) * setting the field widths appropriately.... */ printf("%*.*s %5.5s %*.*s %*.*s", -max_name, max_name, "Name", "Mtu", -max_route, max_route, "Network", -max_ip, max_ip, "Address"); if (oflag) { printf(" %*s %*s", max_ibytes, "Ibytes", max_obytes, "Obytes"); } else { printf(" %*s %*s", max_ipkts, "Ipkts", max_ierrs, "Ierrs"); if (bflag) printf(" %*s", max_ibytes, "Ibytes"); printf(" %*s %*s", max_opkts, "Opkts", max_oerrs, "Oerrs"); if (bflag) printf(" %*s", max_obytes, "Obytes"); printf(" %*s", max_outq, "Queue"); } /* if (tflag) printf(" %s", "Time"); */ if (dflag) printf(" %s", "Drop"); putchar('\n'); for (cur_if = if_head; cur_if; cur_if=cur_if->next) { if (cur_if->name[0] == 0) continue; printf( "%*.*s %5d", -max_name, max_name, cur_if->name, cur_if->mtu); printf(" %*.*s", -max_route, max_route, cur_if->route); printf(" %*.*s", -max_ip, max_ip, cur_if->ip); if (oflag) { printf(" %*s %*s", max_ibytes, cur_if->s_ibytes, max_obytes, cur_if->s_obytes); } else { printf(" %*s %*s", max_ipkts, cur_if->s_ipkts, max_ierrs, cur_if->s_ierrs); if (bflag) printf(" %*s", max_ibytes, cur_if->s_ibytes); printf(" %*s %*s", max_opkts, cur_if->s_opkts, max_oerrs, cur_if->s_oerrs); if (bflag) printf(" %*s", max_obytes, cur_if->s_obytes); printf(" %*s", max_outq, cur_if->s_outq); } /* if (tflag) printf(" %4d", cur_if->???); */ if (dflag) printf(" %4d", cur_if->drops); putchar('\n'); } /* * ... and tidy up. */ for (cur_if = if_head; cur_if; cur_if=if_head) { if_head=cur_if->next; cur_if->next = NULL; SNMP_FREE( cur_if ); } }