SNMP Mapping Mac Address to Switch Port

2019-08-15 19:06发布

问题:

I work at a datacenter and I'm in the process of writing a php tool that maps all of our devices and can tell us if what is out there is what is being billed for.

It first pulls a huge list of macs and their ips from both of the cores into a temp table. Then, it loops through all of the racks* and attempts to find which port that mac belongs to. Since there is no golden command (cue lightbulb over your head), I have to:

  1. Create a multi-array with the port as the key and the ifindex for the value.
  2. Replace the ifindex with with a bridge ID.
  3. Replace the bridge ID with the mac hash.
  4. Repalce the mac hash with the actual mac

Lastly, it takes the mac, ips, and port and populates the master table.

The problem is step one. 1.3.6.1.2.1.31.1.1.1.1 works on most of the switches but a few of the foundrys do not work. 1.3.6.1.4.1.1991.1.1.3.3.1.1.38 kinda comes close to what I'm looking for but im not entirely comfortable it's what I'm looking for. I was able to find the specific device models under foundry > products > registration, but there aren't any MIBs under that folder. So my questions are:

  1. Is there a foundry specific string that returns ports and macs? ifindexes would also work.
  2. How do I go about using device specific MIBs (enterprises.foundry.products.registration.snFWSXFamily)?

Any direction on this would be great. -Justin

*= rack models: cisco 2900xl, foundry FI4802 + variants

回答1:

You can do this (tested on HP Procurve) :

From your linux server :

$ snmpwalk -v 1 -c public xxx.xxx.xxx.xxx 1.3.6.1.2.1.17.4.3.1.2 | grep "INTEGER: 11"

(port number 11)

Will return :

SNMPv2-SMI::mib-2.17.4.3.1.2.44.118.138.64.143.95 = INTEGER: 11 SNMPv2-SMI::mib-2.17.4.3.1.2.56.170.60.108.174.57 = INTEGER: 11 SNMPv2-SMI::mib-2.17.4.3.1.2.104.181.153.172.54.237 = INTEGER: 11 SNMPv2-SMI::mib-2.17.4.3.1.2.120.172.192.143.226.236 = INTEGER: 11 SNMPv2-SMI::mib-2.17.4.3.1.2.124.195.161.20.109.76 = INTEGER: 11 SNMPv2-SMI::mib-2.17.4.3.1.2.152.75.225.59.127.180 = INTEGER: 11

Then you can do this to find which Mac Address is connected :

$ snmpwalk -v 1 -c public xxx.xxx.xxx.xxx 1.3.6.1.2.1.17.4.3.1.1 | grep "152.75.225.59.127.180"

Return mac address :

SNMPv2-SMI::mib-2.17.4.3.1.1.152.75.225.59.127.180 = Hex-STRING: 98 4B E1 3B 7F B4

You can make a script.sh to do this...



回答2:

when I needed to discover MACs and some other info from my switches, I used 'snmpwalk' and 'snmpbulkwalk' commands to examine their SNMP data contents

for example:

snmpbulkwalk -v2c 192.168.30.40 -c public 1.3.6.1.2.1.31.1.1.1.1

outputs:

IF-MIB::ifName.1 = STRING: Gi0/1
IF-MIB::ifName.2 = STRING: Gi0/2
IF-MIB::ifName.3 = STRING: Gi0/3
IF-MIB::ifName.4 = STRING: Gi0/4
IF-MIB::ifName.5 = STRING: Gi0/5
IF-MIB::ifName.6 = STRING: Gi0/6
IF-MIB::ifName.7 = STRING: Gi0/7
IF-MIB::ifName.8 = STRING: Gi0/8
IF-MIB::ifName.9 = STRING: Gi0/9
IF-MIB::ifName.10 = STRING: Gi0/10
IF-MIB::ifName.11 = STRING: Gi0/11
IF-MIB::ifName.12 = STRING: Gi0/12
IF-MIB::ifName.13 = STRING: Nu0
IF-MIB::ifName.14 = STRING: Vl1
IF-MIB::ifName.15 = STRING: Vl2
IF-MIB::ifName.16 = STRING: Vl416

and

snmpbulkwalk -v2c 192.168.30.40 -c public 1.3.6.1.2

outputs A LOT of info among which you can look for your favorite MACs or anything



回答3:

If any one you would like to do this programmatically from a Windows Server you can use the SnmpSharpNet library to accomplish the same thing. Here's an example that will create a list of all the MAC Addresses and Ports on a particular Dell Switch using the OID 1.3.6.1.2.1.17.7.1.2.2.1.2.1

    using SnmpSharpNet;

    List<KeyValuePair<string, string>> portList = new List<KeyValuePair<string, string>>();

    IPAddress ip = IPAddress.Parse("192.168.0.2");
    SnmpWalk(ip, "snmpcommunity", "1.3.6.1.2.1.17.7.1.2.2.1.2.1", "1");

    //SNMPWALK the ports on a switch or stack of switches. Ports will be labeled SwitchNum/Stack Number/Port Numbers.
    private void SnmpWalk(IPAddress ip, string snmpCommunity, string oid, string switchNum)
    {
        UdpTarget target = new UdpTarget(ip);

        // SNMP community name
        OctetString community = new OctetString(snmpCommunity);
        // Define agent parameters class
        AgentParameters param = new AgentParameters(community);
        // Set SNMP version to 1
        param.Version = SnmpVersion.Ver1;


        // Define Oid that is the root of the MIB tree you wish to retrieve
        Oid rootOid = new Oid(oid);

        // This Oid represents last Oid returned by the SNMP agent
        Oid lastOid = (Oid)rootOid.Clone();

        // Pdu class used for all requests
        Pdu pdu = new Pdu(PduType.GetNext);

        // Loop through results
        while (lastOid != null)
        {
            // When Pdu class is first constructed, RequestId is set to a random value
            // that needs to be incremented on subsequent requests made using the
            // same instance of the Pdu class.
            if (pdu.RequestId != 0)
            {
                pdu.RequestId += 1;
            }
            // Clear Oids from the Pdu class.
            pdu.VbList.Clear();
            // Initialize request PDU with the last retrieved Oid
            pdu.VbList.Add(lastOid);
            // Make SNMP request
            SnmpV1Packet result = (SnmpV1Packet)target.Request(pdu, param);
            // You should catch exceptions in the Request if using in real application.

            // If result is null then agent didn't reply or we couldn't parse the reply.
            if (result != null)
            {
                // ErrorStatus other then 0 is an error returned by 
                // the Agent - see SnmpConstants for error definitions
                if (result.Pdu.ErrorStatus != 0)
                {
                    // agent reported an error with the request
                    Console.WriteLine("Error in SNMP reply. Error {0} index {1}",
                        result.Pdu.ErrorStatus,
                        result.Pdu.ErrorIndex);
                    lastOid = null;
                    break;
                }
                else
                {
                    // Walk through returned variable bindings
                    foreach (Vb v in result.Pdu.VbList)
                    {
                        // Check that retrieved Oid is "child" of the root OID
                        if (rootOid.IsRootOf(v.Oid))
                        {
                            //Convert OID to MAC
                            string[] macs = v.Oid.ToString().Split('.');
                            string mac = "";
                            int counter = 0;
                            foreach (string chunk in macs)
                            {
                                if (counter >= macs.Length - 6)
                                {
                                    mac += string.Format("{0:X2}", int.Parse(chunk));
                                }
                                counter += 1;
                            }

                            //Assumes a 48 port switch (52 actual). You need to know these values to correctly iterate through a stack of switches.
                            int dellSwitch = 1 + int.Parse(v.Value.ToString()) / 52;
                            int port = int.Parse(v.Value.ToString()) - (52 * (dellSwitch - 1));
                            KeyValuePair<string, string> Port = new KeyValuePair<string, string>(mac, switchNum + "/" + dellSwitch.ToString() + "/" + port.ToString());
                            portList.Add(Port);

                            //Exit Loop
                            lastOid = v.Oid;
                        }
                        else
                        {
                            //End of the requested MIB tree. Set lastOid to null and exit loop
                            lastOid = null;
                        }
                    }
                }
            }
            else
            {
                Console.WriteLine("No response received from SNMP agent.");
            }
        }
        target.Close();
    }

There is an entire project utilizing this example that resolves this information back to Hostnames here



标签: php snmp