If you are compiling Asterisk on a Kirkwood Arm (SheevaPlug, GuruPlug, Dockstar, etc.), or possibly on any other ARM cpu, this posting is for you.
These issues appeared in 1.8.1.1 and 1.8.2.2 on a SheevaPlug (Kirkwood ARM).
Problems appeared in SIP, such as:
[ul]
[li]“ERROR[23208]: rtp_engine.c:325 ast_rtp_instance_new: No RTP engine was found. Do you have one loaded?
[Nov 9 13:06:32] ERROR[23208]: chan_sip.c :8078 process_sdp: Got SDP but have no RTP session allocated.”[/li]
[li]The inability to use a secret.[/li]
[li]“Peer not found”[/li]
[li]Issues with the deny/permit IP address ranges[/li][/ul]
Problems appeared in IAX:
[ul][li]Failure to validate with RSA keys (could not find the keys)[/li]
[li]Failure to find the context and number when dialing into the pbx from outside.[/li]
[li]Inability to use deny/permit to restrict by IP address[/li][/ul]
In my experience, the various problems would present, or not present, depending on the sequence of actions taken. Because of the ultimate cause, there are probably many other problems which may appear, depending upon any given pbx’s configuration files and the sequence of events.
All of these problem were/are caused because of an ARM alignment problem in the dynamic string allocation code. All of the issues (on my machine) were resolved by fixing that problem.
Technical Cause:
The actual error occurs in a defined macro on line 304 of [Asterisk-sources]/include/asterisk/stringfields.h
#define AST_STRING_FIELD_ALLOCATION(x) *((ast_string_field_allocation *) (x - sizeof(ast_string_field_allocation)))
The purpose of the macro is to calculate the address which is ast_string_field_allocation in front of the string storage address (the passed-in value, x). The definition of ast_string_field_allocation is a uint16_t. Because of the pointer cast, the calculated result will be treated as a uint16_t (that is, a 2-byte half-word)
The problem is that the ARM needs uint16_t’s to be aligned to word, half-word, or byte, depending upon the value being stored [unless cast as (char *)]. So, if (x - sizeof(ast_string_field_allocation)) does not align with the first byte of the memory half-word, attempting to store a half-word into the address will actually store it in the previous byte and the addressed byte.
The result is, for about half of the dynamically-allocated strings, every time a string value is set [using ast_string_field_set()], which calls AST_STRING_FIELD_ALLOCATION(), the string-terminating NULL value in the preceeding string in the memory region will be over-written with some number (the length of the string value being set).
Often the number which gets “concatenated” to the other string will be unprintable; or sometimes in CLI, it will appear as if some string is one character shorter than it should be. On verbose settings, the bogus chars can be seen in the log file.
Resolution:
Actually, this same issue exists for SPARC chips, and the code to dynamically adjust for WORD alignment already exist. It just needs to be included in the ARM compile with a few pre-compiler changes in [Asterisk-Sources]main/utils.c .
A short-term patch for the ARM (at least Kirkwoods) would look like the following.
(Caution: these are unofficial and unsanctioned changes. This is what worked on my machine, but each person has the responsibility for their own understanding and actions.)
main/utils.c
@@ +63,3 -63,0
#include "asterisk/config.h"
+
+ /* Temporary declaration for ARM cpus ONLY (this belongs in the make environment) */
+ #define __arm__ 1
@@ +1635,1 -1635,1 @@
- #ifdef __sparc__
+ #if defined(__sparc__) || defined(__arm__)
@@ +1716,1 -1716,1 @@
- #ifdef __sparc__
+ #if defined(__sparc__) || defined(__arm__)
After the changes, the entire system will need to be re-made and re-installed (make clean, make menuselect [save], make, make install). No need to reinstall the samples.
When building my system, I saw a message that PROC type arm was not recognized. That seems to indicate that ARM processors are not supported by Asterisk developers. My initial impression, after making the changes mentioned on this page, is that the code will run reliably on a Kirkwood ARM.
Frankly, I’m somewhat inexperienced with the ins and outs of make, so am not certain where the variable “arm” should be entered. Obviously, it belongs in the environment, not in this individual file. However, this seems to be the only place in the code where the #ifdef sparc is used for the string alignment. So for a temporary patch for ARM users, just adding #define arm to the top of this file should be fine.
(There is some sparc-related code in include/asterisk/unaligned.h, but that appears to be byte swapping for endian issues.)
On a slightly related note, on the SheevaPlug (maybe others in the series), make sure that PROC=arm in makeopts before trying to make codec_gsm. “armv5tel” does not work.