0

I am trying to extract the Acknowledgment number from a TCP/IP packet in my Android app. I have the raw data in bytes stored as a ByteBuffer.

As an example, lets look at the following TCP/IP packet: (This is the raw TCP data in bytes)

140 174 20 102 249 178 241 231 **238 84 109 14** 128 24 1 91 240 54 0 0 1 1 8 10 0 43 86 97 209 144 51 108 0 0 35

The bytes in bold represent the Acknowledgment number but when i try to convert it to an int or long, i get a negative number. This is what i tried initially where a, b, c, and d are the 4 bytes representing the Acknowledgment number:

this.ackNumber = ((a & 0xFF) << 24) + ((b & 0xFF) << 16) + ((c & 0xFF) << 8) + (d & 0xFF);

After seeing that that didn't work, i tried to do it step by step like this:

byte a = packet.get(); // -18
byte b = packet.get(); // 84
byte c = packet.get(); // 109
byte d = packet.get(); // 14

Log.e(TAG, "A: " + a + " B: " + b + " C: " + c + " D: " + d);

int ia = a & 0xFF; // 238
int ib = b & 0xFF; // 84
int ic = c & 0xFF; // 109
int id = d & 0xFF; // 14

Log.e(TAG, "IA: " + ia + " IB: " + ib + " IC: " + ic + " ID: " + id);

ia = ia << 24; // -301989888
ib = ib << 16; // 5505024
ic = ic << 8;  // 27904
id = id << 0;  // 14

Log.e(TAG, "LIA: " + ia + " LIB: " + ib + " LIC: " + ic + " LID: " + id);

long la = (long)ia & 0x00000000FF000000; // -301989888
long lb = ib & 0x00FF0000;               // 5505024
long lc = ic & 0x0000FF00;               // 27904
long ld = id & 0x000000FF;               // 14

Log.e(TAG, "ALIA: " + la + " ALIB: " + lb + " ALIC: " + lc + " ALID: " + ld);

This code is still returning the incorrect number. What am i doing wrong?

Edit:

I managed to get the correct numbers simply by adding an L after the hexadecimal like this:

long la = (long)ia & 0x00000000FF000000L;

Merging them either way like this works:

Log.e(TAG, "Ack: " + (la + lb + lc + ld) + " Ack: " + (la | lb | lc | ld));

TychoTheTaco
  • 664
  • 1
  • 7
  • 28
  • There's no reason why a TCP sequence number can't be negative. This one is. – user207421 Jul 08 '16 at 06:17
  • Sequence numbers cannot be lower than zero. Based on the answer in this question http://stackoverflow.com/a/2672750/4893507 when they hit maximum, they reset to 0. – TychoTheTaco Jul 08 '16 at 06:28
  • The maximum is 2^32-1, not 2^31-1. TCP sequence numbers [occupy an unsigned 32-bit space](https://tools.ietf.org/html/rfc793#page-24). This one starts with 0x80000000 so *in terms of a Java `int`* it is negative. – user207421 Jul 08 '16 at 07:38

1 Answers1

0

If you're trying to merge the masked and shifted bytes into an int or long you should be using the logical OR operator |, not logical AND &.

Also, the version using int will produce a negative number because ints are signed in Java and the high-order byte is > 127 and therefore has its most significant bit set to 1, which makes the entire int negative in twos-complement.

Jim Garrison
  • 85,615
  • 20
  • 155
  • 190