Example #1
0
    def test_get_call_args(self):
        data = readbytes('dummy.hex')  # any dump would do
        packet = Sequence(Integer(Version.V2C), OctetString('public'),
                          BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3)))
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.return_value = data
            mck().get_request_id.return_value = 0

            # we need to wrap this in a list to consume the generator.
            list(bulkwalk('::1', 'public', ['1.2.3'], bulk_size=2))
            mck.assert_called_with(timeout=6)
            mck().send.assert_called_with('::1', 161, to_bytes(packet))
Example #2
0
 def test_get_call_args(self):
     data = readbytes('dummy.hex')  # any dump would do
     packet = Sequence(
         Integer(Version.V2C), OctetString('public'),
         BulkGetRequest(0, 1, 2, ObjectIdentifier(1, 2, 3),
                        ObjectIdentifier(1, 2, 4)))
     with patch('puresnmp.api.raw.Transport') as mck:
         mck().send.return_value = data
         mck().get_request_id.return_value = 0
         bulkget('::1', 'public', ['1.2.3'], ['1.2.4'], max_list_size=2)
         mck.assert_called_with(timeout=6)
         mck().send.assert_called_with('::1', 161, to_bytes(packet))
Example #3
0
    def test_multiwalk_non_containment(self):
        '''
        Running a multiwalk should raise an exception if the agent returns OIDs
        which are not properly increasing.
        '''
        from puresnmp.pdu import GetResponse
        OID = ObjectIdentifier.from_string

        # First case: Returned OIDs are the same
        response = Sequence(
            Integer(1), OctetString(b'public'),
            GetResponse(123, [
                VarBind(oid=OID('1.2.3'), value=Integer(30)),
                VarBind(oid=OID('2.3.4'), value=Integer(40)),
            ]))
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = [to_bytes(response)]
            mck().get_request_id.return_value = 0
            with self.assertRaises(FaultySNMPImplementation):
                list(multiwalk('::1', 'public', [
                    '1.2.3',
                    '2.3.4',
                ]))

        # Second case: Returned OIDs are smaller
        response = Sequence(
            Integer(1), OctetString(b'public'),
            GetResponse(123, [
                VarBind(oid=OID('1.2.2'), value=Integer(30)),
                VarBind(oid=OID('2.3.3'), value=Integer(40)),
            ]))
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = [to_bytes(response)]
            mck().get_request_id.return_value = 0
            with self.assertRaises(FaultySNMPImplementation):
                list(multiwalk('::1', 'public', [
                    '1.2.3',
                    '2.3.4',
                ]))
Example #4
0
    async def test_get_call_args(self):
        data = readbytes('dummy.hex')  # any dump would do
        packet = Sequence(Integer(Version.V2C), OctetString('public'),
                          BulkGetRequest(0, 0, 2, ObjectIdentifier(1, 2, 3)))
        with patch('puresnmp.aio.api.raw.send', new_callable=AsyncMock) as mck, \
                patch('puresnmp.aio.api.raw.get_request_id') as mck2:
            mck2.return_value = 0
            mck.return_value = data

            # we need to wrap this in a list to consume the generator.
            async for x in bulkwalk('::1', 'public', ['1.2.3'], bulk_size=2):
                pass
            mck.assert_called_with('::1', 161, to_bytes(packet), timeout=6)
Example #5
0
 async def test_get_call_args(self):
     data = readbytes('dummy.hex')  # any dump would do
     packet = Sequence(
         Integer(Version.V2C), OctetString('public'),
         BulkGetRequest(0, 1, 2, ObjectIdentifier(1, 2, 3),
                        ObjectIdentifier(1, 2, 4)))
     with patch('puresnmp.aio.api.raw.send', new_callable=AsyncMock) as mck, \
             patch('puresnmp.aio.api.raw.get_request_id') as mck2:
         mck2.return_value = 0
         mck.return_value = data
         await bulkget('::1',
                       'public', ['1.2.3'], ['1.2.4'],
                       max_list_size=2)
         mck.assert_called_with('::1', 161, to_bytes(packet), timeout=6)
Example #6
0
 async def test_get_call_args(self):
     data = readbytes('dummy.hex')  # any dump would do
     packet = Sequence(
         Integer(Version.V2C),
         OctetString('public'),
         GetNextRequest(0, ObjectIdentifier(1, 2, 3))
     )
     with patch('puresnmp.aio.api.raw.Transport') as mck:
         mck().send = AsyncMock()
         mck().get_request_id.return_value = 0
         mck().send.return_value = data
         await getnext('::1', 'public', '1.2.3')
         mck.assert_called_with(timeout=6)
         mck().send.assert_called_with(
             '::1', 161, to_bytes(packet))
Example #7
0
    def test_getnext_increasing_oid_strict(self):
        '''
        When running "getnext" we expect a different OID than the one we passed
        in. If not, this can cause endless-loops in the worst case. Faulty SNMP
        implementations may behave this way!
        '''
        requested_oid = ObjectIdentifier(1, 2, 3, 4)
        response_object = Sequence(
            Integer(1), OctetString(b'public'),
            GetResponse(234, [VarBind(requested_oid, Integer(123))]))
        response_bytes = to_bytes(response_object)

        with patch('puresnmp.api.raw.send') as mck:
            mck.return_value = response_bytes
            with self.assertRaises(FaultySNMPImplementation):
                getnext('::1', 'private', '1.2.3.4')
Example #8
0
    def test_walk_endless_loop(self):
        '''
        In rare cases, some devices fall into an endless loop by returning the
        requested OID on a "getnext" call during a "walk" operation. A SNMP
        client behaving according to the SNMP spec will fall into an endless
        loop. This test fakes such a case and revents the loop.
        '''
        response_binds = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),  # same OID
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),  # same OID
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),  # same OID
        ]
        response_packets = [
            Sequence(Integer(1), OctetString(b'public'),
                     GetResponse(234, [bind])) for bind in response_binds
        ]
        response_bytes = [to_bytes(packet) for packet in response_packets]

        handler = CapturingHandler()
        logger = getLogger('puresnmp')
        logger.addHandler(handler)
        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = response_bytes
            mck().get_request_id.return_value = 0
            result = list(walk('::1', 'private', '1.2', errors='warn'))
        logger.removeHandler(handler)

        # The last OID in the mocked responses is decreasing so we want to read
        # just up to that point.
        expected = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
        ]
        self.assertEqual(result, expected)

        # We also want to make sure that we have a proper warning about this
        handler.assertContains(WARNING, r'.*1.2.5.*')
Example #9
0
    def test_walk_increasing_oid_lenient(self):
        '''
        We want to be able to allow faulty SNMP implementations to at least try
        to fetch the values in a walk which are not increasing. It should read
        up to the values which are no longer increasing and emit a warning.
        '''
        logger = getLogger('puresnmp')
        handler = CapturingHandler()
        logger.addHandler(handler)

        response_binds = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
            VarBind(ObjectIdentifier(1, 2, 1), Integer(121)),  # non-increasing
        ]
        response_packets = [
            Sequence(Integer(1), OctetString(b'public'),
                     GetResponse(234, [bind])) for bind in response_binds
        ]
        response_bytes = [to_bytes(packet) for packet in response_packets]

        with patch('puresnmp.api.raw.Transport') as mck:
            mck().send.side_effect = response_bytes
            mck().get_request_id.return_value = 0
            result = list(walk('::1', 'private', '1.2', errors='warn'))

        # The last OID in the mocked responses is decreasing so we want to read
        # just up to that point.
        expected = [
            VarBind(ObjectIdentifier(1, 2, 3), Integer(123)),
            VarBind(ObjectIdentifier(1, 2, 4), Integer(124)),
            VarBind(ObjectIdentifier(1, 2, 5), Integer(125)),
        ]
        self.assertEqual(result, expected)

        # We also want to make sure that we have a proper warning about this
        handler.assertContains(WARNING, r'.*1.2.1.*1.2.5.*')
        logger.removeHandler(handler)