mirror of https://github.com/wb2osz/direwolf.git
Issue 84. IGate was truncating packets that contained nul character
in the information/comment part.
This commit is contained in:
parent
785c8deffa
commit
b6254da203
17
CHANGES.md
17
CHANGES.md
|
@ -2,6 +2,23 @@
|
|||
# Revision History #
|
||||
|
||||
|
||||
## Version 1.4 -- Development snapshot H -- March 2017 ##
|
||||
|
||||
**This is beta test quality. If no significant issues are reported this will be the version 1.4 release.**
|
||||
|
||||
### New Features: ###
|
||||
|
||||
- Take advantage of new 'gpio' group and new /sys/class/gpio ownership in Raspbian Jessie.
|
||||
|
||||
- Handle more complicated gpio naming for CubieBoard, etc.
|
||||
|
||||
|
||||
### Bugs Fixed: ###
|
||||
|
||||
- IGate did not retain nul characters in the information part of a packet. This should never happen with a valid APRS packet but there are a couple cases where it has. If we encounter these malformed packets, pass them along as-is, rather than truncating.
|
||||
|
||||
- Don't digipeat packets when the source is my call.
|
||||
|
||||
----------
|
||||
|
||||
## Version 1.4 -- Development snapshot G -- January 2017 ##
|
||||
|
|
136
ax25_pad.c
136
ax25_pad.c
|
@ -335,9 +335,18 @@ void ax25_delete (packet_t this_p)
|
|||
* Purpose: Parse a frame in human-readable monitoring format and change
|
||||
* to internal representation.
|
||||
*
|
||||
* Input: monitor - "TNC-2" format of a monitored packet. i.e.
|
||||
* Input: monitor - "TNC-2" monitor format for packet. i.e.
|
||||
* source>dest[,repeater1,repeater2,...]:information
|
||||
*
|
||||
* The information part can have non-printable characters
|
||||
* in the form of <0xff>. This will be converted to single
|
||||
* bytes. e.g. <0x0d> is carriage return.
|
||||
* In version 1.4H we will allow nul characters which means
|
||||
* we have to maintain a length rather than using strlen().
|
||||
* I maintain that it violates the spec but want to handle it
|
||||
* because it does happen and we want to preserve it when
|
||||
* acting as an IGate rather than corrupting it.
|
||||
*
|
||||
* strict - True to enforce rules for packets sent over the air.
|
||||
* False to be more lenient for packets from IGate server.
|
||||
*
|
||||
|
@ -369,17 +378,11 @@ packet_t ax25_from_text (char *monitor, int strict)
|
|||
char *pa;
|
||||
char *saveptr; /* Used with strtok_r because strtok is not thread safe. */
|
||||
|
||||
static int first_time = 1;
|
||||
static regex_t unhex_re;
|
||||
int e;
|
||||
char emsg[100];
|
||||
#define MAXMATCH 1
|
||||
regmatch_t match[MAXMATCH];
|
||||
int keep_going;
|
||||
char temp[512];
|
||||
int ssid_temp, heard_temp;
|
||||
char atemp[AX25_MAX_ADDR_LEN];
|
||||
|
||||
char info_part[AX25_MAX_INFO_LEN+1];
|
||||
int info_len;
|
||||
|
||||
packet_t this_p = ax25_new ();
|
||||
|
||||
|
@ -392,58 +395,15 @@ packet_t ax25_from_text (char *monitor, int strict)
|
|||
|
||||
/* Is it possible to have a nul character (zero byte) in the */
|
||||
/* information field of an AX.25 frame? */
|
||||
/* Yes, but it would be difficult in the from-text case. */
|
||||
/* At this point, we have a normal C string. */
|
||||
/* It is possible that will convert <0x00> to a nul character later. */
|
||||
/* There we need to maintain a separate length and not use normal C string functions. */
|
||||
|
||||
strlcpy (stuff, monitor, sizeof(stuff));
|
||||
|
||||
/*
|
||||
* Translate hexadecimal values like <0xff> to non-printing characters.
|
||||
* MIC-E message type uses 5 different non-printing characters.
|
||||
*/
|
||||
|
||||
if (first_time)
|
||||
{
|
||||
e = regcomp (&unhex_re, "<0x[0-9a-fA-F][0-9a-fA-F]>", 0);
|
||||
if (e) {
|
||||
regerror (e, &unhex_re, emsg, sizeof(emsg));
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("%s:%d: %s\n", __FILE__, __LINE__, emsg);
|
||||
}
|
||||
|
||||
first_time = 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("BEFORE: %s\n", stuff);
|
||||
ax25_safe_print (stuff, -1, 0);
|
||||
dw_printf ("\n");
|
||||
#endif
|
||||
keep_going = 1;
|
||||
while (keep_going) {
|
||||
if (regexec (&unhex_re, stuff, MAXMATCH, match, 0) == 0) {
|
||||
int n;
|
||||
char *p;
|
||||
|
||||
stuff[match[0].rm_so + 5] = '\0';
|
||||
n = strtol (stuff + match[0].rm_so + 3, &p, 16);
|
||||
stuff[match[0].rm_so] = n;
|
||||
strlcpy (temp, stuff + match[0].rm_eo, sizeof(temp));
|
||||
strlcpy (stuff + match[0].rm_so + 1, temp, sizeof(stuff)-match[0].rm_so-1);
|
||||
}
|
||||
else {
|
||||
keep_going = 0;
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("AFTER: %s\n", stuff);
|
||||
ax25_safe_print (stuff, -1, 0);
|
||||
dw_printf ("\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Initialize the packet with two addresses and control/pid
|
||||
* Initialize the packet structure with two addresses and control/pid
|
||||
* for APRS.
|
||||
*/
|
||||
memset (this_p->frame_data + AX25_DESTINATION*7, ' ' << 1, 6);
|
||||
|
@ -473,12 +433,6 @@ packet_t ax25_from_text (char *monitor, int strict)
|
|||
*pinfo = '\0';
|
||||
pinfo++;
|
||||
|
||||
if (strlen(pinfo) > AX25_MAX_INFO_LEN) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Warning: Information part truncated to %d characters.\n", AX25_MAX_INFO_LEN);
|
||||
pinfo[AX25_MAX_INFO_LEN] = '\0';
|
||||
}
|
||||
|
||||
/*
|
||||
* Separate the addresses.
|
||||
* Note that source and destination order is swappped.
|
||||
|
@ -535,7 +489,6 @@ packet_t ax25_from_text (char *monitor, int strict)
|
|||
*/
|
||||
while (( pa = strtok_r (NULL, ",", &saveptr)) != NULL && this_p->num_addr < AX25_MAX_ADDRS ) {
|
||||
|
||||
//char *last;
|
||||
int k;
|
||||
|
||||
k = this_p->num_addr;
|
||||
|
@ -561,11 +514,61 @@ packet_t ax25_from_text (char *monitor, int strict)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Finally, process the information part.
|
||||
*
|
||||
* Translate hexadecimal values like <0xff> to single bytes.
|
||||
* MIC-E format uses 5 different non-printing characters.
|
||||
* We might want to manually generate UTF-8 characters such as degree.
|
||||
*/
|
||||
|
||||
//#define DEBUG14H 1
|
||||
|
||||
#if DEBUG14H
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("BEFORE: %s\nSAFE: ", pinfo);
|
||||
ax25_safe_print (pinfo, -1, 0);
|
||||
dw_printf ("\n");
|
||||
#endif
|
||||
|
||||
info_len = 0;
|
||||
while (*pinfo != '\0' && info_len < AX25_MAX_INFO_LEN) {
|
||||
|
||||
if (strlen(pinfo) >= 6 &&
|
||||
pinfo[0] == '<' &&
|
||||
pinfo[1] == '0' &&
|
||||
pinfo[2] == 'x' &&
|
||||
isxdigit(pinfo[3]) &&
|
||||
isxdigit(pinfo[4]) &&
|
||||
pinfo[5] == '>') {
|
||||
|
||||
char *p;
|
||||
|
||||
info_part[info_len] = strtol (pinfo + 3, &p, 16);
|
||||
info_len++;
|
||||
pinfo += 6;
|
||||
}
|
||||
else {
|
||||
info_part[info_len] = *pinfo;
|
||||
info_len++;
|
||||
pinfo++;
|
||||
}
|
||||
}
|
||||
info_part[info_len] = '\0';
|
||||
|
||||
#if DEBUG14H
|
||||
text_color_set(DW_COLOR_DEBUG);
|
||||
dw_printf ("AFTER: %s\nSAFE: ", info_part);
|
||||
ax25_safe_print (info_part, info_len, 0);
|
||||
dw_printf ("\n");
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Append the info part.
|
||||
*/
|
||||
strlcpy ((char*)(this_p->frame_data+this_p->frame_len), pinfo, sizeof(this_p->frame_data)-this_p->frame_len);
|
||||
this_p->frame_len += strlen(pinfo);
|
||||
memcpy ((char*)(this_p->frame_data+this_p->frame_len), info_part, info_len);
|
||||
this_p->frame_len += info_len;
|
||||
|
||||
return (this_p);
|
||||
}
|
||||
|
@ -2536,7 +2539,7 @@ unsigned short ax25_m_m_crc (packet_t pp)
|
|||
*
|
||||
* Inputs: pstr - Pointer to string.
|
||||
*
|
||||
* len - Maximum length if not -1.
|
||||
* len - Number of bytes. If < 0 we use strlen().
|
||||
*
|
||||
* ascii_only - Restrict output to only ASCII.
|
||||
* Normally we allow UTF-8.
|
||||
|
@ -2587,7 +2590,6 @@ void ax25_safe_print (char *pstr, int len, int ascii_only)
|
|||
if (len > MAXSAFE)
|
||||
len = MAXSAFE;
|
||||
|
||||
//while (len > 0 && *pstr != '\0')
|
||||
while (len > 0)
|
||||
{
|
||||
ch = *((unsigned char *)pstr);
|
||||
|
|
|
@ -199,6 +199,33 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet)
|
|||
ax25_get_addr_with_ssid (pp, AX25_SOURCE, A->g_src);
|
||||
ax25_get_addr_with_ssid (pp, AX25_DESTINATION, dest);
|
||||
|
||||
/*
|
||||
* Report error if the information part contains a nul character.
|
||||
* There are two known cases where this can happen.
|
||||
*
|
||||
* - The Kenwood TM-D710A sometimes sends packets like this:
|
||||
*
|
||||
* VA3AJ-9>T2QU6X,VE3WRC,WIDE1,K8UNS,WIDE2*:4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00>`nW<0x1f>oS8>/]"6M}driving fast=
|
||||
* K4JH-9>S5UQ6X,WR4AGC-3*,WIDE1*:4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00>`jP}l"&>/]"47}QRV from the EV =
|
||||
*
|
||||
* Notice that the data type indicator of "4" is not valid. If we remove
|
||||
* 4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00> we are left with a good MIC-E format.
|
||||
* This same thing has been observed from others and is intermittent.
|
||||
*
|
||||
* - AGW Tracker can send UTF-16 if an option is selected. This can introduce nul bytes.
|
||||
* This is wrong, it should be using UTF-8.
|
||||
*/
|
||||
|
||||
if ( ( ! A->g_quiet ) && ( (int)strlen((char*)pinfo) != info_len) ) {
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("'nul' character found in Information part. This should never happen.\n");
|
||||
dw_printf("It seems that %s is transmitting with defective software.\n", A->g_src);
|
||||
|
||||
if (strcmp((char*)pinfo, "4P") == 0) {
|
||||
dw_printf("The TM-D710 will do this intermittently. A firmware upgrade is needed to fix it.\n");
|
||||
}
|
||||
}
|
||||
|
||||
switch (*pinfo) { /* "DTI" data type identifier. */
|
||||
|
||||
|
@ -3907,7 +3934,7 @@ static void substr_se (char *dest, const char *src, int start, int endp1)
|
|||
* clen - Length of comment or -1 to take it all.
|
||||
*
|
||||
* Outputs: A->g_telemetry - Base 91 telemetry |ss1122|
|
||||
* A->g_altitude_ft - from /A=123456
|
||||
* A->g_altitude_ft - from /A=123456
|
||||
* A->g_lat - Might be adjusted from !DAO!
|
||||
* A->g_lon - Might be adjusted from !DAO!
|
||||
* A->g_aprstt_loc - Private extension to !DAO!
|
||||
|
@ -3938,6 +3965,49 @@ static void substr_se (char *dest, const char *src, int start, int endp1)
|
|||
*
|
||||
* /A=123456 Altitude
|
||||
*
|
||||
* What can appear in a comment?
|
||||
*
|
||||
* Chapter 5 of the APRS spec ( http://www.aprs.org/doc/APRS101.PDF ) says:
|
||||
*
|
||||
* "The comment may contain any printable ASCII characters (except | and ~,
|
||||
* which are reserved for TNC channel switching)."
|
||||
*
|
||||
* "Printable" would exclude character values less than space (00100000), e.g.
|
||||
* tab, carriage return, line feed, nul. Sometimes we see carriage return
|
||||
* (00001010) at the end of APRS packets. This would be in violation of the
|
||||
* specification.
|
||||
*
|
||||
* The base 91 telemetry format (http://he.fi/doc/aprs-base91-comment-telemetry.txt ),
|
||||
* which is not part of the APRS spec, uses the | character in the comment to delimit encoded
|
||||
* telemetry data. This would be in violation of the original spec.
|
||||
*
|
||||
* The APRS Spec Addendum 1.2 Proposals ( http://www.aprs.org/aprs12/datum.txt)
|
||||
* adds use of UTF-8 (https://en.wikipedia.org/wiki/UTF-8 )for the free form text in
|
||||
* messages and comments. It can't be used in the fixed width fields.
|
||||
*
|
||||
* Non-ASCII characters are represented by multi-byte sequences. All bytes in these
|
||||
* multi-byte sequences have the most significant bit set to 1. Using UTF-8 would not
|
||||
* add any nul (00000000) bytes to the stream.
|
||||
*
|
||||
* There are two known cases where we can have a nul character value.
|
||||
*
|
||||
* * The Kenwood TM-D710A sometimes sends packets like this:
|
||||
*
|
||||
* VA3AJ-9>T2QU6X,VE3WRC,WIDE1,K8UNS,WIDE2*:4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00>`nW<0x1f>oS8>/]"6M}driving fast=
|
||||
* K4JH-9>S5UQ6X,WR4AGC-3*,WIDE1*:4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00>`jP}l"&>/]"47}QRV from the EV =
|
||||
*
|
||||
* Notice that the data type indicator of "4" is not valid. If we remove
|
||||
* 4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00> we are left with a good MIC-E format.
|
||||
* This same thing has been observed from others and is intermittent.
|
||||
*
|
||||
* * AGW Tracker can send UTF-16 if an option is selected. This can introduce nul bytes.
|
||||
* This is wrong. It should be using UTF-8 and I'm not going to accomodate it here.
|
||||
*
|
||||
*
|
||||
* The digipeater and IGate functions should pass along anything exactly the
|
||||
* we received it, even if it is invalid. If different implementations try to fix it up
|
||||
* somehow, like changing unprintable characters to spaces, we will only make things
|
||||
* worse and thwart the duplicate detection.
|
||||
*
|
||||
*------------------------------------------------------------------*/
|
||||
|
||||
|
|
|
@ -260,7 +260,7 @@ int main (int argc, char *argv[])
|
|||
text_color_init(t_opt);
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
//dw_printf ("Dire Wolf version %d.%d (%s) Beta Test\n", MAJOR_VERSION, MINOR_VERSION, __DATE__);
|
||||
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "G", __DATE__);
|
||||
dw_printf ("Dire Wolf DEVELOPMENT version %d.%d %s (%s)\n", MAJOR_VERSION, MINOR_VERSION, "H", __DATE__);
|
||||
//dw_printf ("Dire Wolf version %d.%d\n", MAJOR_VERSION, MINOR_VERSION);
|
||||
|
||||
#if defined(ENABLE_GPSD) || defined(USE_HAMLIB)
|
||||
|
|
169
igate.c
169
igate.c
|
@ -118,7 +118,7 @@ static packet_t dp_queue_head;
|
|||
|
||||
static void satgate_delay_packet (packet_t pp, int chan);
|
||||
static void send_packet_to_server (packet_t pp, int chan);
|
||||
static void send_msg_to_server (const char *msg);
|
||||
static void send_msg_to_server (const char *msg, int msg_len);
|
||||
static void maybe_xmit_packet_from_igate (char *message, int chan);
|
||||
|
||||
static void rx_to_ig_init (void);
|
||||
|
@ -266,7 +266,7 @@ int main (int argc, char *argv[])
|
|||
SLEEP_SEC (20);
|
||||
text_color_set(DW_COLOR_INFO);
|
||||
dw_printf ("Send received packet\n");
|
||||
send_msg_to_server ("W1ABC>APRS:?");
|
||||
send_msg_to_server ("W1ABC>APRS:?", strlen("W1ABC>APRS:?");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
|
@ -797,7 +797,7 @@ static void * connnect_thread (void *arg)
|
|||
strlcat (stemp, " filter ", sizeof(stemp));
|
||||
strlcat (stemp, save_igate_config_p->t2_filter, sizeof(stemp));
|
||||
}
|
||||
send_msg_to_server (stemp);
|
||||
send_msg_to_server (stemp, strlen(stemp));
|
||||
|
||||
/* Delay until it is ok to start sending packets. */
|
||||
|
||||
|
@ -827,7 +827,7 @@ static void * connnect_thread (void *arg)
|
|||
strlcpy (heartbeat, "#", sizeof(heartbeat));
|
||||
|
||||
/* This will close the socket if any error. */
|
||||
send_msg_to_server (heartbeat);
|
||||
send_msg_to_server (heartbeat, strlen(heartbeat));
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -861,7 +861,9 @@ static void * connnect_thread (void *arg)
|
|||
*
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
#define IGATE_MAX_MSG 520 /* Message to IGate max 512 characters. */
|
||||
#define IGATE_MAX_MSG 512 /* "All 'packets' sent to APRS-IS must be in the TNC2 format terminated */
|
||||
/* by a carriage return, line feed sequence. No line may exceed 512 bytes */
|
||||
/* including the CR/LF sequence." */
|
||||
|
||||
void igate_send_rec_packet (int chan, packet_t recv_pp)
|
||||
{
|
||||
|
@ -993,6 +995,7 @@ void igate_send_rec_packet (int chan, packet_t recv_pp)
|
|||
|
||||
/*
|
||||
* Cut the information part at the first CR or LF.
|
||||
* Do NOT trim trailing spaces.
|
||||
*/
|
||||
|
||||
info_len = ax25_get_info (pp, &pinfo);
|
||||
|
@ -1074,13 +1077,13 @@ static void send_packet_to_server (packet_t pp, int chan)
|
|||
|
||||
|
||||
info_len = ax25_get_info (pp, &pinfo);
|
||||
(void)(info_len);
|
||||
|
||||
/*
|
||||
* We will often see the same packet multiple times close together due to digipeating.
|
||||
* The consensus seems to be that we should just send the first and drop the later duplicates.
|
||||
* There is some dissent on this issue. http://www.tapr.org/pipermail/aprssig/2016-July/045907.html
|
||||
* There could be some value to sending them all to provide information about digipeater paths.
|
||||
* However, the servers should drop all duplicates so we wasting everyone's time but sending duplicates.
|
||||
* If you feel strongly about this issue, you could remove the following section.
|
||||
* Currently rx_to_ig_allow only checks for recent duplicates.
|
||||
*/
|
||||
|
@ -1132,9 +1135,74 @@ static void send_packet_to_server (packet_t pp, int chan)
|
|||
|
||||
strlcat (msg, save_audio_config_p->achan[chan].mycall, sizeof(msg));
|
||||
strlcat (msg, ":", sizeof(msg));
|
||||
strlcat (msg, (char*)pinfo, sizeof(msg));
|
||||
|
||||
send_msg_to_server (msg);
|
||||
|
||||
|
||||
// It was reported that APRS packets, containing a nul byte in the information part,
|
||||
// are being truncated. https://github.com/wb2osz/direwolf/issues/84
|
||||
//
|
||||
// One might argue that the packets are invalid and the proper behavior would be
|
||||
// to simply discard them, the same way we do if the CRC is bad. One might argue
|
||||
// that we should simply pass along whatever we receive even if we don't like it.
|
||||
// We really shouldn't modify it and make the situation even worse.
|
||||
//
|
||||
// Chapter 5 of the APRS spec ( http://www.aprs.org/doc/APRS101.PDF ) says:
|
||||
//
|
||||
// "The comment may contain any printable ASCII characters (except | and ~,
|
||||
// which are reserved for TNC channel switching)."
|
||||
//
|
||||
// "Printable" would exclude character values less than space (00100000), e.g.
|
||||
// tab, carriage return, line feed, nul. Sometimes we see carriage return
|
||||
// (00001010) at the end of APRS packets. This would be in violation of the
|
||||
// specification.
|
||||
//
|
||||
// The MIC-E position format can have non printable characters (0x1c ... 0x1f, 0x7f)
|
||||
// in the information part. An unfortunate decision, but it is not in the comment part.
|
||||
//
|
||||
// The base 91 telemetry format (http://he.fi/doc/aprs-base91-comment-telemetry.txt ),
|
||||
// which is not part of the APRS spec, uses the | character in the comment to delimit encoded
|
||||
// telemetry data. This would be in violation of the original spec. No one cares.
|
||||
//
|
||||
// The APRS Spec Addendum 1.2 Proposals ( http://www.aprs.org/aprs12/datum.txt)
|
||||
// adds use of UTF-8 (https://en.wikipedia.org/wiki/UTF-8 )for the free form text in
|
||||
// messages and comments. It can't be used in the fixed width fields.
|
||||
//
|
||||
// Non-ASCII characters are represented by multi-byte sequences. All bytes in these
|
||||
// multi-byte sequences have the most significant bit set to 1. Using UTF-8 would not
|
||||
// add any nul (00000000) bytes to the stream.
|
||||
//
|
||||
// Based on all of that, we would not expect to see a nul character in the information part.
|
||||
//
|
||||
// There are two known cases where we can have a nul character value.
|
||||
//
|
||||
// * The Kenwood TM-D710A sometimes sends packets like this:
|
||||
//
|
||||
// VA3AJ-9>T2QU6X,VE3WRC,WIDE1,K8UNS,WIDE2*:4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00>`nW<0x1f>oS8>/]"6M}driving fast=
|
||||
// K4JH-9>S5UQ6X,WR4AGC-3*,WIDE1*:4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00>`jP}l"&>/]"47}QRV from the EV =
|
||||
//
|
||||
// Notice that the data type indicator of "4" is not valid. If we remove
|
||||
// 4P<0x00><0x0f>4T<0x00><0x0f>4X<0x00><0x0f>4\<0x00> we are left with a good MIC-E format.
|
||||
// This same thing has been observed from others and is intermittent.
|
||||
//
|
||||
// * AGW Tracker can send UTF-16 if an option is selected. This can introduce nul bytes.
|
||||
// This is wrong, it should be using UTF-8.
|
||||
//
|
||||
// Rather than using strlcat here, we need to use memcpy and maintain our
|
||||
// own lengths, being careful to avoid buffer overflow.
|
||||
|
||||
int msg_len = strlen(msg); // What we have so far before info part.
|
||||
|
||||
if (info_len > IGATE_MAX_MSG - msg_len - 2) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Rx IGate: Too long. Truncating.\n");
|
||||
info_len = IGATE_MAX_MSG - msg_len - 2;
|
||||
}
|
||||
if (info_len > 0) {
|
||||
memcpy (msg + msg_len, pinfo, info_len);
|
||||
msg_len += info_len;
|
||||
}
|
||||
|
||||
send_msg_to_server (msg, msg_len);
|
||||
stats_uplink_packets++;
|
||||
|
||||
/*
|
||||
|
@ -1152,58 +1220,74 @@ static void send_packet_to_server (packet_t pp, int chan)
|
|||
*
|
||||
* Name: send_msg_to_server
|
||||
*
|
||||
* Purpose: Send to the IGate server.
|
||||
* Purpose: Send something to the IGate server.
|
||||
* This one function should be used for login, hearbeats,
|
||||
* and packets.
|
||||
*
|
||||
* Inputs: imsg - Message. We will add CR/LF.
|
||||
* Inputs: imsg - Message. We will add CR/LF here.
|
||||
*
|
||||
* imsg_len - Length of imsg in bytes.
|
||||
* It could contain nul characters so we can't
|
||||
* use the normal C string functions.
|
||||
*
|
||||
* Description: Send message to IGate Server if connected.
|
||||
* Disconnect from server, and notify user, if any error.
|
||||
* Should use a word other than message because that has
|
||||
* a specific meaning for APRS.
|
||||
*
|
||||
*--------------------------------------------------------------------*/
|
||||
|
||||
|
||||
static void send_msg_to_server (const char *imsg)
|
||||
static void send_msg_to_server (const char *imsg, int imsg_len)
|
||||
{
|
||||
int err;
|
||||
char stemp[IGATE_MAX_MSG];
|
||||
char stemp[IGATE_MAX_MSG+1];
|
||||
int stemp_len;
|
||||
|
||||
if (igate_sock == -1) {
|
||||
return; /* Silently discard if not connected. */
|
||||
}
|
||||
|
||||
strlcpy(stemp, imsg, sizeof(stemp));
|
||||
stemp_len = imsg_len;
|
||||
if (stemp_len + 2 > IGATE_MAX_MSG) {
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("Rx IGate: Too long. Truncating.\n");
|
||||
stemp_len = IGATE_MAX_MSG - 2;
|
||||
}
|
||||
|
||||
memcpy (stemp, imsg, stemp_len);
|
||||
|
||||
if (s_debug >= 1) {
|
||||
text_color_set(DW_COLOR_XMIT);
|
||||
dw_printf ("[rx>ig] ");
|
||||
ax25_safe_print (stemp, strlen(stemp), 0);
|
||||
ax25_safe_print (stemp, stemp_len, 0);
|
||||
dw_printf ("\n");
|
||||
}
|
||||
|
||||
strlcat (stemp, "\r\n", sizeof(stemp));
|
||||
stemp[stemp_len++] = '\r';
|
||||
stemp[stemp_len++] = '\n';
|
||||
stemp[stemp_len] = '\0';
|
||||
|
||||
stats_uplink_bytes += stemp_len;
|
||||
|
||||
stats_uplink_bytes += strlen(stemp);
|
||||
|
||||
#if __WIN32__
|
||||
err = send (igate_sock, stemp, strlen(stemp), 0);
|
||||
err = send (igate_sock, stemp, stemp_len, 0);
|
||||
if (err == SOCKET_ERROR)
|
||||
{
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("\nError %d sending message to IGate server. Closing connection.\n\n", WSAGetLastError());
|
||||
dw_printf ("\nError %d sending to IGate server. Closing connection.\n\n", WSAGetLastError());
|
||||
//dw_printf ("DEBUG: igate_sock=%d, line=%d\n", igate_sock, __LINE__);
|
||||
closesocket (igate_sock);
|
||||
igate_sock = -1;
|
||||
WSACleanup();
|
||||
}
|
||||
#else
|
||||
err = write (igate_sock, stemp, strlen(stemp));
|
||||
err = write (igate_sock, stemp, stemp_len);
|
||||
if (err <= 0)
|
||||
{
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf ("\nError sending message to IGate server. Closing connection.\n\n");
|
||||
dw_printf ("\nError sending to IGate server. Closing connection.\n\n");
|
||||
close (igate_sock);
|
||||
igate_sock = -1;
|
||||
}
|
||||
|
@ -1295,7 +1379,7 @@ static void * igate_recv_thread (void *arg)
|
|||
#endif
|
||||
{
|
||||
unsigned char ch;
|
||||
unsigned char message[1000]; // Spec says max 500 or so.
|
||||
unsigned char message[1000]; // Spec says max 512.
|
||||
int len;
|
||||
|
||||
|
||||
|
@ -1313,14 +1397,27 @@ static void * igate_recv_thread (void *arg)
|
|||
ch = get1ch();
|
||||
stats_downlink_bytes++;
|
||||
|
||||
if (len < (int)(sizeof(message)))
|
||||
{
|
||||
message[len] = ch;
|
||||
// I never expected to see a nul character but it can happen.
|
||||
// If found, change it to <0x00> and ax25_from_text will change it back to a single byte.
|
||||
// Along the way we can use the normal C string handling.
|
||||
|
||||
if (ch == 0 && len < (int)(sizeof(message)) - 5) {
|
||||
message[len++] = '<';
|
||||
message[len++] = '0';
|
||||
message[len++] = 'x';
|
||||
message[len++] = '0';
|
||||
message[len++] = '0';
|
||||
message[len++] = '>';
|
||||
}
|
||||
else if (len < (int)(sizeof(message)))
|
||||
{
|
||||
message[len++] = ch;
|
||||
}
|
||||
len++;
|
||||
|
||||
} while (ch != '\n');
|
||||
|
||||
message[sizeof(message)-1] = '\0';
|
||||
|
||||
/*
|
||||
* We have a complete message terminated by LF.
|
||||
*
|
||||
|
@ -1335,10 +1432,13 @@ static void * igate_recv_thread (void *arg)
|
|||
* I've seen a case where the original RF packet had a trailing CR but
|
||||
* after someone else sent it to the server and it came back to me, that
|
||||
* CR was now a trailing space.
|
||||
*
|
||||
* At first I was tempted to trim a trailing space as well.
|
||||
* By fixing this one case it might corrupt the data in other cases.
|
||||
* We compensate for this by ignoring trailing spaces when performing
|
||||
* the duplicate detection and removal.
|
||||
*
|
||||
* We need to transmit exactly as we get it.
|
||||
*/
|
||||
|
||||
/*
|
||||
|
@ -1384,6 +1484,19 @@ static void * igate_recv_thread (void *arg)
|
|||
ax25_safe_print ((char *)message, len, 0);
|
||||
dw_printf ("\n");
|
||||
|
||||
if ((int)strlen((char*)message) != len) {
|
||||
|
||||
// Invalid. Either drop it or pass it along as-is. Don't change.
|
||||
|
||||
text_color_set(DW_COLOR_ERROR);
|
||||
dw_printf("'nul' character found in packet from IS. This should never happen.\n");
|
||||
dw_printf("The source station is probably transmitting with defective software.\n");
|
||||
|
||||
//if (strcmp((char*)pinfo, "4P") == 0) {
|
||||
// dw_printf("The TM-D710 will do this intermittently. A firmware upgrade is needed to fix it.\n");
|
||||
//}
|
||||
}
|
||||
|
||||
/*
|
||||
* Record that we heard from the source address.
|
||||
*/
|
||||
|
@ -2038,10 +2151,12 @@ static int rx_to_ig_allow (packet_t pp)
|
|||
* At first I thought duplicate removal was broken but it turns out they
|
||||
* are not exactly the same.
|
||||
*
|
||||
* The receive IGate spec says a packet should be cut at a CR.
|
||||
* >>> The receive IGate spec says a packet should be cut at a CR. <<<
|
||||
*
|
||||
* In one case it is removed as expected In another case, it is replaced by a trailing
|
||||
* space character. Maybe someone thought non printable characters should be
|
||||
* replaced by spaces???
|
||||
* replaced by spaces??? (I have since been told someone thought it would be a good
|
||||
* idea to replace unprintable characters with spaces. How's that working out for MIC-E position???)
|
||||
*
|
||||
* At first I was tempted to remove any trailing spaces to make up for the other
|
||||
* IGate adding it. Two wrongs don't make a right. Trailing spaces are not that
|
||||
|
|
Loading…
Reference in New Issue