0

I am trying to do SNMP Set from host Linux to target system. But, instead of correct values, wrong values are getting set. After a bit of research, I made this table:

Hex representation of decimal value in Linux snmp

0 - 0x80 - 1000 0000 - 0 is converted to 128
1 - 0x40 - 0100 0000 - 1 is converted to 64
2   0x20 - 0010 0000 - 2 is converted to 32
3   0x10 - 0001 0000 - 3 is converted to 16
4   0x08 - 0000 1000 - 4 is converted to 8
5   0x04 - 0000 0100 - 5 is converted to 4
6   0x02 - 0000 0010 - 6 is converted to 2
7   0x01 - 0000 0001 - is converted to 1

Hex representation of decimal value in target system

0 - 0x00 - 0000 0000
1 - 0x01 - 0000 0001
2   0x02 - 0000 0010
3   0x03 - 0000 0011
4   0x04 - 0000 0100
5   0x05 - 0000 0101
6   0x06 - 0000 0110
7   0x07 - 0000 0111

I have two questions:

  1. What could be the reason behind this issue?
  2. Does anyone know how I can convert those Linux values to correct target values in a C program?
phuclv
  • 37,963
  • 15
  • 156
  • 475
  • 1
    wild guess: reverse the values bitwise and get the position of the "1" bit, and substract 1 => you'll get your number. – Jean-François Fabre Sep 18 '17 at 12:16
  • 2
    I'm sorry, but I don't have a clue what you're asking here. Can you create a [mcve] to illustrate where your code is producing incorrect results? – r3mainer Sep 18 '17 at 12:16
  • All your values do seem correct. 0x80 _is_ 128 decimal, etc. So what is "wrong"? What do you expect the values to be? – Paul Ogilvie Sep 18 '17 at 12:24
  • An XY-problem ...? – alk Sep 18 '17 at 12:28
  • 1
    Can you elaborate the circumstances a bit? How do you set the values? With the snmpset cli tool? What is the oid and the data type of the object? How do you check which values were set? – Ctx Sep 18 '17 at 12:31
  • Please explain who told you that 0x80 is zero? It is not 1 complement. I think you vjust do not understand how negative numbers are represented – 0___________ Sep 18 '17 at 12:42
  • @PeterJ_01 There are eight possible values, numbered 0-7. In order, they go from 0x80, the first one, to 0x01, the last one. Nothing here is about ones' complement or negative numbers, they're just bit patterns. We're semi-implicitly talking about them as though they were unsigned binary numbers, even when that's not the intended meaning. – Josh Lee Sep 18 '17 at 13:36
  • What I meant in the question is that if I am giving input as 1, then I am expected hex output as 0x01, instead I am getting 0x40 i.e. value is getting converted to 64, or some binary conversion is happening due to which I am getting 64, – misswordsworth Sep 19 '17 at 05:40

2 Answers2

3

If I understand your question correctly, you receive a byte that encode 8 values (0 to 7) using a one-hot encoding. See https://en.wikipedia.org/wiki/One-hot (notice: your bit order seems reversed though).

If you simply put a one-hot encoded bit pattern into a byte variable on your target system, you'll not get the original value as your target system uses another encoding (probably 2's complement). In other words - a given bit pattern has different meanings in one-hot encoding and 2's complement encoding.

So the task is to convert the one-hot encoded values to equivalent values on your target system.

You could go for a simple switch-statement - like:

int main(void)
{
  unsigned char linux_snmp_value = 0x20;
  unsigned char target_value = 255;
  switch(linux_snmp_value)
  {
    case 0x80:
        target_value = 0;
        break;
    case 0x40:
        target_value = 1;
        break;
    case 0x20:
        target_value = 2;
        break;

    // Add the remaining cases here

    default:
        // Illegal value
        // Add some error handling
        break;
  }
  printf("Target value %d\n", target_value);
  return 0;
}

If you prefer a loop, it could be something like:

int main(void)
{
  unsigned char linux_snmp_value = 0x01;
  unsigned char target_value = 0;
  unsigned char mask = 0x80;
  while (mask)
  {
    if (mask == linux_snmp_value) break;
    ++target_value;
    mask = mask >> 1;
  }
  if (mask == 0)
  {
    // Illegal value
    // Add some error handling
    printf("ERROR\n");
    return -1;
  }
  printf("Target value %d\n", target_value);
  return 0;
}
Support Ukraine
  • 42,271
  • 4
  • 38
  • 63
  • Thanks for the answer. Although it is decidedly the perfect solution, I am afraid it won't work in my case. Regardless, thanks for the answer all the same. :) – misswordsworth Sep 19 '17 at 10:28
0

If the portability is not the issue (for example you do not play to compile on the VAX or AVR8 machine) you can use machine instructions for it

asm (“bsrl %1, %0” : “=r” (position) : “r” (number));

you can also wrap it into nice inline function. Similar instructions are available on ARM, MIPS, PIC and many other.

0___________
  • 60,014
  • 4
  • 34
  • 74