Closed birarda closed 11 years ago
That is extremely odd. It should always sends back a XOR_MAPPED_ADDRESS. But this should be easy enough to resolve with a few questions and a network trace if needed.
How are you determining that there is no XOR_MAPPED_ADDRESS in the response? Your own code? Some other tool/app?
Where did you download the code from? What was the version number in the .tgz file that you likely downloaded?
Can you provide a network trace? (e.g. wireshark, NetMon, or equivalent tool)
jrs
From: Stephen Birarda Sent: Wednesday, October 16, 2013 4:02 PM To: jselbie/stunserver
Probably a silly mistake on my end, but I can't get the stunserver to send me back a XOR_MAPPED_ADDRESS, only a MAPPED_ADDRESS.
I'd assume since the stunserver is RFC 3859 compliant it is possible to get the XOR address?
— Reply to this email directly or view it on GitHub.
This was against an install from stunserver-1.2.5.tgz.
I'm using the following code to check for the presence of a XOR_MAPPED_ADDRESS attr.
// check the cookie to make sure this is actually a STUN response
// and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS
const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4;
const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0020);
if (memcmp(packetData + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH,
&RFC_5389_MAGIC_COOKIE_NETWORK_ORDER,
sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0
&& memcmp(packetData + NUM_BYTES_STUN_HEADER, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) {
I deduced it was sending MAPPED_ADDRESS_TYPE by changing the second line to
const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0001);
I see the stunserver returning 56 bytes to the client but it fails on memcmp(packetData + NUM_BYTES_STUN_HEADER, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0
.
The same code works with an instance of turnserver (although that's more bloated than we'd like to be).
Hi Stephen,
There is nothing in the RFC for STUN that dictates that the first attribute be the XOR_MAPPED_ADDRESS. Stuntman sends back the XOR_MAPPED_ADDRESS typically as the last attribute. As a matter of fact, there was good reason for this and it is documented in the code. I suspected there were existing clients hardcoded to the ordering of attributes, the code mimicks the order of attributes that the Vovida server sends back.
I would not recommend you parse a network protocol with hardcoded assumptions about the placement of fields. I would recommend that you actually parse the attributes out one at a time with proper validation. Making hardcoded assumptions like this creates interoperability problems down the road.
But if you want a quick fix such that your client code works, you could simply swap the ordering of the following two lines of code. Look at stuncore/messagehandler.cpp around line 323. Exchange the placement of the “builder.AddMappedAddress” call with the line of code a few rows down that calls “builder.AddXorMappedAddress”. These lines of code are highlighted below.
// paranoia - just to be consistent with Vovida, send the attributes back in the same order it does
// I suspect there are clients out there that might be hardcoded to the ordering
// MAPPED-ADDRESS
// SOURCE-ADDRESS (RESPONSE-ORIGIN)
// CHANGED-ADDRESS (OTHER-ADDRESS)
// XOR-MAPPED-ADDRESS (XOR-MAPPED_ADDRESS-OPTIONAL)
builder.AddMappedAddress(_pMsgIn->addrRemote);
if (fSendOriginAddress) { builder.AddResponseOriginAddress(addrOrigin); // pass true to send back SOURCE_ADDRESS, otherwise, pass false to send back RESPONSE-ORIGIN }
if (fSendOtherAddress) { builder.AddOtherAddress(addrOther); // pass true to send back CHANGED-ADDRESS, otherwise, pass false to send back OTHER-ADDRESS }
// send back the XOR-MAPPED-ADDRESS (encoded as an optional message for legacy clients) builder.AddXorMappedAddress(_pMsgIn->addrRemote);
I hope this helps. Let me know if this works and/or if there is something in the RFC that I missed about the ordering of attributes.
jrs
PS:
If you can use C++ in your code base, you could use the stuntman code library “stuncore” to do all the parsing for you. Example:
StunReader reader; CSocketAddress mapped_address;
reader.AddBytes(packetData, packetLength);
if (reader.GetState == CStunMessageReader::BodyValidated) { HRESULT hr = reader.GetXorMappedAddress(&mapped_address); if (hr != 0) { hr = reader.GetMappedAddress(&mapped_address); } }
From: Stephen Birarda Sent: Wednesday, October 16, 2013 5:09 PM To: jselbie/stunserver Cc: John Selbie
This was against an install from stunserver-1.2.5.tgz.
I'm using the following code to check for the presence of a XOR_MAPPED_ADDRESS attr. // check the cookie to make sure this is actually a STUN response // and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4; const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0020);
if (memcmp(packetData + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0 && memcmp(packetData + NUM_BYTES_STUN_HEADER, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) {
I deduced it was sending MAPPED_ADDRESS_TYPE by changing the second line to const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0001);
— Reply to this email directly or view it on GitHub.
duh, should have assumed you might be sending both and checked if it came after.
Will enumerate the sent attributes to look for it. Thanks!
This can be closed.
On Wed, Oct 16, 2013 at 7:47 PM, John Selbie notifications@github.com wrote:
Hi Stephen, There is nothing in the RFC for STUN that dictates that the first attribute be the XOR_MAPPED_ADDRESS. Stuntman sends back the XOR_MAPPED_ADDRESS typically as the last attribute. As a matter of fact, there was good reason for this and it is documented in the code. I suspected there were existing clients hardcoded to the ordering of attributes, the code mimicks the order of attributes that the Vovida server sends back. I would not recommend you parse a network protocol with hardcoded assumptions about the placement of fields. I would recommend that you actually parse the attributes out one at a time with proper validation. Making hardcoded assumptions like this creates interoperability problems down the road. But if you want a quick fix such that your client code works, you could simply swap the ordering of the following two lines of code. Look at stuncore/messagehandler.cpp around line 323. Exchange the placement of the “builder.AddMappedAddress” call with the line of code a few rows down that calls “builder.AddXorMappedAddress”. These lines of code are highlighted below. // paranoia - just to be consistent with Vovida, send the attributes back in the same order it does // I suspect there are clients out there that might be hardcoded to the ordering
// MAPPED-ADDRESS // SOURCE-ADDRESS (RESPONSE-ORIGIN) // CHANGED-ADDRESS (OTHER-ADDRESS) // XOR-MAPPED-ADDRESS (XOR-MAPPED_ADDRESS-OPTIONAL) builder.AddMappedAddress(_pMsgIn->addrRemote); if (fSendOriginAddress) { builder.AddResponseOriginAddress(addrOrigin); // pass true to send back SOURCE_ADDRESS, otherwise, pass false to send back RESPONSE-ORIGIN } if (fSendOtherAddress) { builder.AddOtherAddress(addrOther); // pass true to send back CHANGED-ADDRESS, otherwise, pass false to send back OTHER-ADDRESS } // send back the XOR-MAPPED-ADDRESS (encoded as an optional message for legacy clients) builder.AddXorMappedAddress(_pMsgIn->addrRemote); I hope this helps. Let me know if this works and/or if there is something in the RFC that I missed about the ordering of attributes. jrs PS: If you can use C++ in your code base, you could use the stuntman code library “stuncore” to do all the parsing for you. Example: StunReader reader; CSocketAddress mapped_address; reader.AddBytes(packetData, packetLength); if (reader.GetState == CStunMessageReader::BodyValidated) { HRESULT hr = reader.GetXorMappedAddress(&mapped_address); if (hr != 0) { hr = reader.GetMappedAddress(&mapped_address); } } From: Stephen Birarda Sent: Wednesday, October 16, 2013 5:09 PM To: jselbie/stunserver Cc: John Selbie This was against an install from stunserver-1.2.5.tgz. I'm using the following code to check for the presence of a XOR_MAPPED_ADDRESS attr. // check the cookie to make sure this is actually a STUN response // and read the first attribute and make sure it is a XOR_MAPPED_ADDRESS const int NUM_BYTES_MESSAGE_TYPE_AND_LENGTH = 4; const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0020); if (memcmp(packetData + NUM_BYTES_MESSAGE_TYPE_AND_LENGTH, &RFC_5389_MAGIC_COOKIE_NETWORK_ORDER, sizeof(RFC_5389_MAGIC_COOKIE_NETWORK_ORDER)) == 0 && memcmp(packetData + NUM_BYTES_STUN_HEADER, &XOR_MAPPED_ADDRESS_TYPE, sizeof(XOR_MAPPED_ADDRESS_TYPE)) == 0) { I deduced it was sending MAPPED_ADDRESS_TYPE by changing the second line to const uint16_t XOR_MAPPED_ADDRESS_TYPE = htons(0x0001); —Reply to this email directly or view it on GitHub.
Reply to this email directly or view it on GitHub: https://github.com/jselbie/stunserver/issues/7#issuecomment-26475685
No problem.
Probably a silly mistake on my end, but I can't get the stunserver to send me back a XOR_MAPPED_ADDRESS, only a MAPPED_ADDRESS.
I'd assume since the stunserver is RFC 3859 compliant it is possible to get the XOR address?