mirror of https://github.com/wb2osz/direwolf.git
				
				
				
			Look past third party header for packet filtering.
This commit is contained in:
		
							parent
							
								
									f9cf42b291
								
							
						
					
					
						commit
						e84a622515
					
				| 
						 | 
					@ -30,6 +30,14 @@
 | 
				
			||||||
    > Add:     "FX25TX 1" (or 16 or 32 or 64)
 | 
					    > Add:     "FX25TX 1" (or 16 or 32 or 64)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					### Bugs Fixed: ###
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- The t/m packet filter incorrectly included bulletins.  It now allows only "messages" to specific stations.  Use of t/m is discouraged.  i/180 is the preferred filter for messages to users recently heard locally.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Packet filtering now skips over any third party header before classifying packet types.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
## Version 1.6  --  October 2020 ##
 | 
					## Version 1.6  --  October 2020 ##
 | 
				
			||||||
 | 
					
 | 
				
			||||||
### New Build Procedure: ###
 | 
					### New Build Procedure: ###
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -169,7 +169,9 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	//dw_printf ("DEBUG decode_aprs info=\"%s\"\n", pinfo);
 | 
						//dw_printf ("DEBUG decode_aprs info=\"%s\"\n", pinfo);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	memset (A, 0, sizeof (*A));
 | 
						if (third_party_src == NULL) {
 | 
				
			||||||
 | 
						  memset (A, 0, sizeof (*A));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	A->g_quiet = quiet;
 | 
						A->g_quiet = quiet;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -234,6 +236,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
	    memcpy(payload_src, (char*)pinfo+1, sizeof(payload_src)-1);
 | 
						    memcpy(payload_src, (char*)pinfo+1, sizeof(payload_src)-1);
 | 
				
			||||||
	    char *q = strchr(payload_src, '>');
 | 
						    char *q = strchr(payload_src, '>');
 | 
				
			||||||
	    if (q != NULL) *q = '\0';
 | 
						    if (q != NULL) *q = '\0';
 | 
				
			||||||
 | 
						    A->g_has_thirdparty_header = 1;
 | 
				
			||||||
	    decode_aprs (A, pp_payload, quiet, payload_src);	// 1 means used recursively
 | 
						    decode_aprs (A, pp_payload, quiet, payload_src);	// 1 means used recursively
 | 
				
			||||||
	    ax25_delete (pp_payload);
 | 
						    ax25_delete (pp_payload);
 | 
				
			||||||
	    return;
 | 
						    return;
 | 
				
			||||||
| 
						 | 
					@ -318,6 +321,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
	      {	     
 | 
						      {	     
 | 
				
			||||||
	        aprs_ll_pos (A, pinfo, info_len);
 | 
						        aprs_ll_pos (A, pinfo, info_len);
 | 
				
			||||||
	      }
 | 
						      }
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_position;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -330,10 +334,12 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
	      if (strncmp((char*)pinfo, "$ULTW", 5) == 0)
 | 
						      if (strncmp((char*)pinfo, "$ULTW", 5) == 0)
 | 
				
			||||||
	      {
 | 
						      {
 | 
				
			||||||
		aprs_ultimeter (A, (char*)pinfo, info_len);		// TODO: produce obsolete error.
 | 
							aprs_ultimeter (A, (char*)pinfo, info_len);		// TODO: produce obsolete error.
 | 
				
			||||||
 | 
						        A->g_packet_type = packet_type_weather;
 | 
				
			||||||
	      }
 | 
						      }
 | 
				
			||||||
	      else
 | 
						      else
 | 
				
			||||||
	      {
 | 
						      {
 | 
				
			||||||
	        aprs_raw_nmea (A, pinfo, info_len);
 | 
						        aprs_raw_nmea (A, pinfo, info_len);
 | 
				
			||||||
 | 
						        A->g_packet_type = packet_type_position;	        
 | 
				
			||||||
	      }
 | 
						      }
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -341,17 +347,20 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
	    case '`':		/* Current Mic-E Data (not used in TM-D700) */
 | 
						    case '`':		/* Current Mic-E Data (not used in TM-D700) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_mic_e (A, pp, pinfo, info_len);
 | 
						      aprs_mic_e (A, pp, pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_position;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case ')':		/* Item. */
 | 
						    case ')':		/* Item. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_item (A, pinfo, info_len);
 | 
						      aprs_item (A, pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_item;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	    case '/':		/* Position with timestamp (no APRS messaging) */
 | 
						    case '/':		/* Position with timestamp (no APRS messaging) */
 | 
				
			||||||
	    case '@':		/* Position with timestamp (with APRS messaging) */
 | 
						    case '@':		/* Position with timestamp (with APRS messaging) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_ll_pos_time (A, pinfo, info_len);
 | 
						      aprs_ll_pos_time (A, pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_position;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -360,42 +369,76 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
				/* Telemetry metadata. */
 | 
									/* Telemetry metadata. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_message (A, pinfo, info_len, quiet);
 | 
						      aprs_message (A, pinfo, info_len, quiet);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						      switch (A->g_message_subtype) {
 | 
				
			||||||
 | 
							case message_subtype_message:
 | 
				
			||||||
 | 
							case message_subtype_ack:
 | 
				
			||||||
 | 
							case message_subtype_rej:
 | 
				
			||||||
 | 
						          A->g_packet_type = packet_type_message;
 | 
				
			||||||
 | 
						          break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case message_subtype_nws:
 | 
				
			||||||
 | 
						           A->g_packet_type = packet_type_nws;
 | 
				
			||||||
 | 
						           break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case message_subtype_bulletin:
 | 
				
			||||||
 | 
						     	default:
 | 
				
			||||||
 | 
							  break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case message_subtype_telem_parm:
 | 
				
			||||||
 | 
							case message_subtype_telem_unit:
 | 
				
			||||||
 | 
							case message_subtype_telem_eqns:
 | 
				
			||||||
 | 
							case message_subtype_telem_bits:
 | 
				
			||||||
 | 
						          A->g_packet_type = packet_type_telemetry;
 | 
				
			||||||
 | 
						          break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							case message_subtype_directed_query:
 | 
				
			||||||
 | 
						          A->g_packet_type = packet_type_query;
 | 
				
			||||||
 | 
						          break;
 | 
				
			||||||
 | 
						      }
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case ';':		/* Object */
 | 
						    case ';':		/* Object */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_object (A, pinfo, info_len);
 | 
						      aprs_object (A, pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_object;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case '<':		/* Station Capabilities */
 | 
						    case '<':		/* Station Capabilities */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_station_capabilities (A, (char*)pinfo, info_len);
 | 
						      aprs_station_capabilities (A, (char*)pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_capabilities;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case '>':		/* Status Report */
 | 
						    case '>':		/* Status Report */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_status_report (A, (char*)pinfo, info_len);
 | 
						      aprs_status_report (A, (char*)pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_status;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    
 | 
						    
 | 
				
			||||||
	    case '?':		/* General Query */
 | 
						    case '?':		/* General Query */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_general_query (A, (char*)pinfo, info_len, quiet);
 | 
						      aprs_general_query (A, (char*)pinfo, info_len, quiet);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_query;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
		
 | 
							
 | 
				
			||||||
	    case 'T':		/* Telemetry */
 | 
						    case 'T':		/* Telemetry */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_telemetry (A, (char*)pinfo, info_len, quiet);
 | 
						      aprs_telemetry (A, (char*)pinfo, info_len, quiet);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_telemetry;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case '_':		/* Positionless Weather Report */
 | 
						    case '_':		/* Positionless Weather Report */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_positionless_weather_report (A, pinfo, info_len);
 | 
						      aprs_positionless_weather_report (A, pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_weather;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case '{':		/* user defined data */
 | 
						    case '{':		/* user defined data */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_user_defined (A, (char*)pinfo, info_len);
 | 
						      aprs_user_defined (A, (char*)pinfo, info_len);
 | 
				
			||||||
 | 
						      A->g_packet_type = packet_type_userdefined;
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 't':		/* Raw touch tone data - NOT PART OF STANDARD */
 | 
						    case 't':		/* Raw touch tone data - NOT PART OF STANDARD */
 | 
				
			||||||
| 
						 | 
					@ -404,6 +447,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
				/* Might move into user defined data, above. */
 | 
									/* Might move into user defined data, above. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_raw_touch_tone (A, (char*)pinfo, info_len);
 | 
						      aprs_raw_touch_tone (A, (char*)pinfo, info_len);
 | 
				
			||||||
 | 
						      // no packet type for t/ filter
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'm':		/* Morse Code data - NOT PART OF STANDARD */
 | 
						    case 'm':		/* Morse Code data - NOT PART OF STANDARD */
 | 
				
			||||||
| 
						 | 
					@ -413,6 +457,7 @@ void decode_aprs (decode_aprs_t *A, packet_t pp, int quiet, char *third_party_sr
 | 
				
			||||||
				/* Might move into user defined data, above. */
 | 
									/* Might move into user defined data, above. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      aprs_morse_code (A, (char*)pinfo, info_len);
 | 
						      aprs_morse_code (A, (char*)pinfo, info_len);
 | 
				
			||||||
 | 
						      // no packet type for t/ filter
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    //case '}':		/* third party header */
 | 
						    //case '}':		/* third party header */
 | 
				
			||||||
| 
						 | 
					@ -1091,7 +1136,9 @@ static void aprs_raw_nmea (decode_aprs_t *A, unsigned char *info, int ilen)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Function:	aprs_mic_e
 | 
					 * Function:	aprs_mic_e
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Purpose:	Decode MIC-E (also Kenwood D7 & D700) packet.
 | 
					 * Purpose:	Decode MIC-E (e.g. Kenwood D7 & D700) packet.
 | 
				
			||||||
 | 
					 *		This format is an overzelous quest to make the packet as short as possible.
 | 
				
			||||||
 | 
					 *		It uses non-printable characters and hacks wrapped in kludges.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Inputs:	info 	- Pointer to Information field.
 | 
					 * Inputs:	info 	- Pointer to Information field.
 | 
				
			||||||
 *		ilen 	- Information field length.
 | 
					 *		ilen 	- Information field length.
 | 
				
			||||||
| 
						 | 
					@ -1100,31 +1147,120 @@ static void aprs_raw_nmea (decode_aprs_t *A, unsigned char *info, int ilen)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Description:	
 | 
					 * Description:	
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		Destination Address Field - 
 | 
					 *		AX.25 Destination Address Field - 
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		The 7-byte Destination Address field contains
 | 
					 *		The 6-byte Destination Address field contains
 | 
				
			||||||
 *		the following encoded information:
 | 
					 *		the following encoded information:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		* The 6 latitude digits.
 | 
					 *			Byte 1: Lat digit 1, message bit A
 | 
				
			||||||
 *		* A 3-bit Mic-E message identifier, specifying one of 7 Standard Mic-E
 | 
					 *			Byte 2: Lat digit 2, message bit B
 | 
				
			||||||
 *		   Message Codes or one of 7 Custom Message Codes or an Emergency
 | 
					 *			Byte 3: Lat digit 3, message bit C
 | 
				
			||||||
 *		   Message Code.
 | 
					 *			Byte 4: Lat digit 4, N/S lat indicator
 | 
				
			||||||
 *		* The North/South and West/East Indicators.
 | 
					 *			Byte 5: Lat digit 5, Longitude offset
 | 
				
			||||||
 *		* The Longitude Offset Indicator.
 | 
					 *			Byte 6: Lat digit 6, W/E Long indicator
 | 
				
			||||||
 *		* The generic APRS digipeater path code.
 | 
					 * *
 | 
				
			||||||
 *
 | 
					 | 
				
			||||||
 *		"Although the destination address appears to be quite unconventional, it is
 | 
					 *		"Although the destination address appears to be quite unconventional, it is
 | 
				
			||||||
 *		still a valid AX.25 address, consisting only of printable 7-bit ASCII values."
 | 
					 *		still a valid AX.25 address, consisting only of printable 7-bit ASCII values."
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * References:	Mic-E TYPE CODES -- http://www.aprs.org/aprs12/mic-e-types.txt
 | 
					 *		AX.25 Information Field - Starts with ' or `
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *			This is up to date with the 24 Aug 16 version mentioning the TH-D74.
 | 
					 *			Bytes 1,2,3: Longitude
 | 
				
			||||||
 | 
					 *			Bytes 4,5,6: Speed and Course
 | 
				
			||||||
 | 
					 *			Byte 6: Symbol code
 | 
				
			||||||
 | 
					 *			Byte 7: Symbol Table ID
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		The rest of it is a complicated comment field which can hold various information
 | 
				
			||||||
 | 
					 *		and must be intrepreted in a particular order.  At this point we look for any
 | 
				
			||||||
 | 
					 *		prefix and/or suffix to identify the equipment type.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * 		References:	Mic-E TYPE CODES -- http://www.aprs.org/aprs12/mic-e-types.txt
 | 
				
			||||||
 | 
					 *				Mic-E TEST EXAMPLES -- http://www.aprs.org/aprs12/mic-e-examples.txt
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		Next, we have what Addedum 1.2 calls the "type byte."  This prefix can be
 | 
				
			||||||
 | 
					 *			space	Original MIC-E.
 | 
				
			||||||
 | 
					 *			>	Kenwood HT.
 | 
				
			||||||
 | 
					 *			]	Kenwood Mobile.
 | 
				
			||||||
 | 
					 *			none.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		We also need to look at the last byte or two
 | 
				
			||||||
 | 
					 *		for a possible suffix to distinguish equipment types.  Examples:
 | 
				
			||||||
 | 
					 *			>......		is D7
 | 
				
			||||||
 | 
					 *			>......=	is D72
 | 
				
			||||||
 | 
					 *			>......^	is D74
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		For other brands, it gets worse.  There might a 2 character suffix.
 | 
				
			||||||
 | 
					 *		The prefix indicates whether messaging-capable.  Examples:
 | 
				
			||||||
 | 
					 *			`....._.%	Yaesu FTM-400DR
 | 
				
			||||||
 | 
					 *			`......_)	Yaesu FTM-100D
 | 
				
			||||||
 | 
					 *			`......_3	Yaesu FT5D
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			'......|3	Byonics TinyTrack3
 | 
				
			||||||
 | 
					 *			'......|4	Byonics TinyTrack4
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		Any prefix and suffix must be removed before futher processsing.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		Pick one: MIC-E Telemetry Data or "Status Text" (called a comment everywhere else).
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		If the character after the symbol table id is "," (comma) or 0x1d, we have telemetry.
 | 
				
			||||||
 | 
					 *		(Is this obsoleted by the base-91 telemetry?)
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			`	Two 2-character hexadecimal numbers. (Channels 1 & 3)
 | 
				
			||||||
 | 
					 *			'	Five 2-character hexadecimal numbers.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		Anything left over is a comment which can contain various types of information.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		If present, the MIC-E compressed altitude must be first.
 | 
				
			||||||
 | 
					 *		It is three base-91 characters followed by "}".
 | 
				
			||||||
 | 
					 *		Examples:    "4T}	"4T}	]"4T}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		We can also have frequency specification  --  http://www.aprs.org/info/freqspec.tx	
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Warning:	Some Kenwood radios add CR at the end, in apparent violation of the spec.
 | 
				
			||||||
 | 
					 *		Watch out so it doesn't get included when looking for equipment type suffix.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		Mic-E TEST EXAMPLES -- http://www.aprs.org/aprs12/mic-e-examples.txt 
 | 
					 *		Mic-E TEST EXAMPLES -- http://www.aprs.org/aprs12/mic-e-examples.txt 
 | 
				
			||||||
 *		
 | 
					 *		
 | 
				
			||||||
 * Examples:	`b9Z!4y>/>"4N}Paul's_TH-D7
 | 
					 * Examples:	Observed on the air.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * TODO:	Destination SSID can contain generic digipeater path.
 | 
					 *		KB1HNZ-9>TSSP5P,W1IMD,WIDE1,KQ1L-8,N3LLO-3,WIDE2*:`b6,l}#>/]"48}449.225MHz<0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff><0xff>=<0x0d>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		`       b6,    l}#   >/     ]         "48}    449.225MHz   ......    =       <0x0d>
 | 
				
			||||||
 | 
					 *		mic-e  long.   cs    sym    prefix    alt.    freq         comment   suffix   must-ignore
 | 
				
			||||||
 | 
					 *		                            Kenwood                                  D710
 | 
				
			||||||
 | 
					 *---------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		N1JDU-9>ECCU8Y,W1MHL*,WIDE2-1:'cZ<0x7f>l#H>/]Go fly a kite!<0x0d>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		'      cZ<0x7f>   l#H     >/     ]         .....                 <0x0d>
 | 
				
			||||||
 | 
					 *		mic-e  long.      cs      sym    prefix    comment   no-suffix   must-ignore
 | 
				
			||||||
 | 
					 *		                                 Kenwood              D700
 | 
				
			||||||
 | 
					 *---------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		KC1HHO-7>T2PX5R,WA1PLE-4,WIDE1*,WIDE2-1:`c_snp(k/`"4B}official relay station NTS_(<0x0d>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		`       c_s     np(  k/     `       "4B}      .......   _(       <0x0d>
 | 
				
			||||||
 | 
					 *		mic-e  long.    cs   sym    prefix   alt      comment   suffix   must-ignore
 | 
				
			||||||
 | 
					 *		                                                         FT2D
 | 
				
			||||||
 | 
					 *---------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		N1CMD-12>T3PQ1Y,KA1GJU-3,WIDE1,WA1PLE-4*:`cP#l!Fk/'"7H}|!%&-']|!w`&!|3
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		`      cP#      l!F   k/     '       "7H}    |!%&-']|         !w`&!   |3
 | 
				
			||||||
 | 
					 *		mic-e  long.    cs   sym    prefix   alt     base91telemetry  DAO     suffix
 | 
				
			||||||
 | 
					 *		                                                                      TinyTrack3   
 | 
				
			||||||
 | 
					 *---------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		 W1STJ-3>T2UR4X,WA1PLE-4,WIDE1*,WIDE2-1:`c@&l#.-/`"5,}146.685MHz T100 -060 146.520 Simplex or Voice Alert_%<0x0d>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		`      c@&     l#.   -/     `        "5,}    146.685MHz T100 -060     ..............  _%       <0x0d>
 | 
				
			||||||
 | 
					 *		mic-e  long.    cs   sym    prefix   alt     frequency-specification     comment     suffix   must-ignore
 | 
				
			||||||
 | 
					 *		                                                                                    FTM-400DR
 | 
				
			||||||
 | 
					 *---------------
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * TODO:	Destination SSID can contain generic digipeater path.  (?)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Bugs:	Doesn't handle ambiguous position.  "space" treated as zero.
 | 
					 * Bugs:	Doesn't handle ambiguous position.  "space" treated as zero.
 | 
				
			||||||
 *		Invalid data results in a message but latitude is not set to unknown.
 | 
					 *		Invalid data results in a message but latitude is not set to unknown.
 | 
				
			||||||
| 
						 | 
					@ -1507,6 +1643,8 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
 | 
				
			||||||
// This does not change very often but I'm wondering if we could parse
 | 
					// This does not change very often but I'm wondering if we could parse
 | 
				
			||||||
// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
 | 
					// http://www.aprs.org/aprs12/mic-e-types.txt similar to how we use tocalls.txt.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO:  Use https://github.com/aprsorg/aprs-deviceid rather than hardcoding.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (isT(*pfirst)) {
 | 
						if (isT(*pfirst)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// "legacy" formats.
 | 
					// "legacy" formats.
 | 
				
			||||||
| 
						 | 
					@ -1515,6 +1653,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  else if (*pfirst == '>'                       && *plast == '=')  { strlcpy (A->g_mfr, "Kenwood TH-D72", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
						  else if (*pfirst == '>'                       && *plast == '=')  { strlcpy (A->g_mfr, "Kenwood TH-D72", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
				
			||||||
	  else if (*pfirst == '>'                       && *plast == '^')  { strlcpy (A->g_mfr, "Kenwood TH-D74", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
						  else if (*pfirst == '>'                       && *plast == '^')  { strlcpy (A->g_mfr, "Kenwood TH-D74", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
				
			||||||
 | 
						  else if (*pfirst == '>'                       && *plast == '&')  { strlcpy (A->g_mfr, "Kenwood TH-D75", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
				
			||||||
	  else if (*pfirst == '>'                                       )  { strlcpy (A->g_mfr, "Kenwood TH-D7A", sizeof(A->g_mfr)); pfirst++; }
 | 
						  else if (*pfirst == '>'                                       )  { strlcpy (A->g_mfr, "Kenwood TH-D7A", sizeof(A->g_mfr)); pfirst++; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  else if (*pfirst == ']'                       && *plast == '=')  { strlcpy (A->g_mfr, "Kenwood TM-D710", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
						  else if (*pfirst == ']'                       && *plast == '=')  { strlcpy (A->g_mfr, "Kenwood TM-D710", sizeof(A->g_mfr)); pfirst++; plast--; }
 | 
				
			||||||
| 
						 | 
					@ -1540,6 +1679,7 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ' should be used for trackers (not message capable).
 | 
					// ' should be used for trackers (not message capable).
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						  else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '5')  { strlcpy (A->g_mfr, "Anytone D578UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
 | 
				
			||||||
	  else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '8')  { strlcpy (A->g_mfr, "Anytone D878UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
 | 
						  else if (*pfirst == '\'' && *(plast-1) == '(' && *plast == '8')  { strlcpy (A->g_mfr, "Anytone D878UV", sizeof(A->g_mfr)); pfirst++; plast-=2; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  else if (*pfirst == '\'' && *(plast-1) == '|' && *plast == '3')  { strlcpy (A->g_mfr, "Byonics TinyTrack3", sizeof(A->g_mfr)); pfirst++; plast-=2; }
 | 
						  else if (*pfirst == '\'' && *(plast-1) == '|' && *plast == '3')  { strlcpy (A->g_mfr, "Byonics TinyTrack3", sizeof(A->g_mfr)); pfirst++; plast-=2; }
 | 
				
			||||||
| 
						 | 
					@ -1635,6 +1775,10 @@ static void aprs_mic_e (decode_aprs_t *A, packet_t pp, unsigned char *info, int
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Cases:	:BLNxxxxxx: ...			Bulletin.
 | 
					 * Cases:	:BLNxxxxxx: ...			Bulletin.
 | 
				
			||||||
 *		:NWSxxxxxx: ...			National Weather Service Bulletin.
 | 
					 *		:NWSxxxxxx: ...			National Weather Service Bulletin.
 | 
				
			||||||
 | 
					 *							http://www.aprs.org/APRS-docs/WX.TXT
 | 
				
			||||||
 | 
					 *		:SKYxxxxxx: ...			Need reference.
 | 
				
			||||||
 | 
					 *		:CWAxxxxxx: ...			Need reference.
 | 
				
			||||||
 | 
					 *		:BOMxxxxxx: ...			Australian version.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		:xxxxxxxxx:PARM.		Telemetry metadata, parameter name
 | 
					 *		:xxxxxxxxx:PARM.		Telemetry metadata, parameter name
 | 
				
			||||||
 *		:xxxxxxxxx:UNIT.		Telemetry metadata, unit/label
 | 
					 *		:xxxxxxxxx:UNIT.		Telemetry metadata, unit/label
 | 
				
			||||||
| 
						 | 
					@ -1768,19 +1912,36 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q
 | 
				
			||||||
	  strlcpy (A->g_comment, p->message, sizeof(A->g_comment));
 | 
						  strlcpy (A->g_comment, p->message, sizeof(A->g_comment));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#warning = double check.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Weather bulletins have addressee starting with NWS, SKY, CWA, or BOM.
 | 
				
			||||||
 | 
						// The protocol spec and http://www.aprs.org/APRS-docs/WX.TXT state that
 | 
				
			||||||
 | 
						// the 3 letter prefix must be followed by a dash.
 | 
				
			||||||
 | 
						// However, https://www.aprs-is.net/WX/ also lists the underscore
 | 
				
			||||||
 | 
						// alternative for the compressed format.  Xastir implements this.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (strlen(addressee) >= 3 && strncmp(addressee,"NWS",3) == 0) {
 | 
						else if (strlen(addressee) >= 3 && strncmp(addressee,"NWS",3) == 0) {
 | 
				
			||||||
	  // NWS-xxxxx
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	  if (strlen(addressee) >=4 && addressee[3] == '-') {
 | 
						  if (strlen(addressee) >=4 && addressee[3] == '-') {
 | 
				
			||||||
	    snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "NWS bulletin with identifier \"%s\"", addressee+4);
 | 
						    snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Weather bulletin with identifier \"%s\"", addressee+4);
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
						  else if (strlen(addressee) >=4 && addressee[3] == '_') {
 | 
				
			||||||
 | 
						    snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Compressed Weather bulletin with identifier \"%s\"", addressee+4);
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	  else {
 | 
						  else {
 | 
				
			||||||
	    snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "NWS bulletin with identifier \"%s\", missing - after NWS", addressee+3);
 | 
						    snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Weather bulletin is missing - or _ after %.3s", addressee);
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	  A->g_message_subtype = message_subtype_nws;
 | 
						  A->g_message_subtype = message_subtype_nws;
 | 
				
			||||||
	  strlcpy (A->g_comment, p->message, sizeof(A->g_comment));
 | 
						  strlcpy (A->g_comment, p->message, sizeof(A->g_comment));
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						else if (strlen(addressee) >= 3 && (strncmp(addressee,"SKY",3) == 0 || strncmp(addressee,"CWA",3) == 0 || strncmp(addressee,"BOM",3) == 0)) {
 | 
				
			||||||
 | 
						  // SKY... or CWA...   https://www.aprs-is.net/WX/
 | 
				
			||||||
 | 
						  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Weather bulletin with identifier \"%s\"", addressee+4);
 | 
				
			||||||
 | 
						  A->g_message_subtype = message_subtype_nws;
 | 
				
			||||||
 | 
						  strlcpy (A->g_comment, p->message, sizeof(A->g_comment));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 * Special message formats contain telemetry metadata.
 | 
					 * Special message formats contain telemetry metadata.
 | 
				
			||||||
| 
						 | 
					@ -1794,22 +1955,22 @@ static void aprs_message (decode_aprs_t *A, unsigned char *info, int ilen, int q
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (strncmp(p->message,"PARM.",5) == 0) {
 | 
						else if (strncmp(p->message,"PARM.",5) == 0) {
 | 
				
			||||||
	  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Parameter Name Message for \"%s\"", addressee);
 | 
						  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Parameter Name for \"%s\"", addressee);
 | 
				
			||||||
	  A->g_message_subtype = message_subtype_telem_parm;
 | 
						  A->g_message_subtype = message_subtype_telem_parm;
 | 
				
			||||||
	  telemetry_name_message (addressee, p->message+5);
 | 
						  telemetry_name_message (addressee, p->message+5);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (strncmp(p->message,"UNIT.",5) == 0) {
 | 
						else if (strncmp(p->message,"UNIT.",5) == 0) {
 | 
				
			||||||
	  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Unit/Label Message for \"%s\"", addressee);
 | 
						  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Unit/Label for \"%s\"", addressee);
 | 
				
			||||||
	  A->g_message_subtype = message_subtype_telem_unit;
 | 
						  A->g_message_subtype = message_subtype_telem_unit;
 | 
				
			||||||
	  telemetry_unit_label_message (addressee, p->message+5);
 | 
						  telemetry_unit_label_message (addressee, p->message+5);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (strncmp(p->message,"EQNS.",5) == 0) {
 | 
						else if (strncmp(p->message,"EQNS.",5) == 0) {
 | 
				
			||||||
	  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Equation Coefficients Message for \"%s\"", addressee);
 | 
						  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Equation Coefficients for \"%s\"", addressee);
 | 
				
			||||||
	  A->g_message_subtype = message_subtype_telem_eqns;
 | 
						  A->g_message_subtype = message_subtype_telem_eqns;
 | 
				
			||||||
	  telemetry_coefficents_message (addressee, p->message+5, quiet);
 | 
						  telemetry_coefficents_message (addressee, p->message+5, quiet);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	else if (strncmp(p->message,"BITS.",5) == 0) {
 | 
						else if (strncmp(p->message,"BITS.",5) == 0) {
 | 
				
			||||||
	  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Bit Sense/Project Name Message for \"%s\"", addressee);
 | 
						  snprintf (A->g_data_type_desc, sizeof(A->g_data_type_desc), "Telemetry Bit Sense/Project Name for \"%s\"", addressee);
 | 
				
			||||||
	  A->g_message_subtype = message_subtype_telem_bits;
 | 
						  A->g_message_subtype = message_subtype_telem_bits;
 | 
				
			||||||
	  telemetry_bit_sense_message (addressee, p->message+5, quiet);
 | 
						  telemetry_bit_sense_message (addressee, p->message+5, quiet);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,8 @@ typedef struct decode_aprs_s {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	int g_quiet;			/* Suppress error messages when decoding. */
 | 
						int g_quiet;			/* Suppress error messages when decoding. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        char g_src[AX25_MAX_ADDR_LEN];
 | 
					        char g_src[AX25_MAX_ADDR_LEN];	// In the case of a packet encapsulated by a 3rd party
 | 
				
			||||||
 | 
										// header, this is the encapsulated source.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        char g_dest[AX25_MAX_ADDR_LEN];
 | 
					        char g_dest[AX25_MAX_ADDR_LEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,6 +67,24 @@ typedef struct decode_aprs_s {
 | 
				
			||||||
					/* Also for Directed Station Query which is a */
 | 
										/* Also for Directed Station Query which is a */
 | 
				
			||||||
					/* special case of message. */
 | 
										/* special case of message. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// This is so pfilter.c:filt_t does not need to duplicate the same work.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						int g_has_thirdparty_header;
 | 
				
			||||||
 | 
						enum packet_type_e {
 | 
				
			||||||
 | 
								packet_type_none=0,
 | 
				
			||||||
 | 
								packet_type_position,
 | 
				
			||||||
 | 
								packet_type_weather,
 | 
				
			||||||
 | 
								packet_type_object,
 | 
				
			||||||
 | 
								packet_type_item,
 | 
				
			||||||
 | 
								packet_type_message,
 | 
				
			||||||
 | 
								packet_type_query,
 | 
				
			||||||
 | 
								packet_type_capabilities,
 | 
				
			||||||
 | 
								packet_type_status,
 | 
				
			||||||
 | 
								packet_type_telemetry,
 | 
				
			||||||
 | 
								packet_type_userdefined,
 | 
				
			||||||
 | 
								packet_type_nws
 | 
				
			||||||
 | 
							} g_packet_type;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	enum message_subtype_e { message_subtype_invalid = 0,
 | 
						enum message_subtype_e { message_subtype_invalid = 0,
 | 
				
			||||||
				message_subtype_message,
 | 
									message_subtype_message,
 | 
				
			||||||
				message_subtype_ack,
 | 
									message_subtype_ack,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										62
									
								
								src/igate.c
								
								
								
								
							
							
						
						
									
										62
									
								
								src/igate.c
								
								
								
								
							| 
						 | 
					@ -1749,9 +1749,34 @@ static void * satgate_delay_thread (void *arg)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *--------------------------------------------------------------------*/
 | 
					 *--------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: Use of "message" here is confusing because that term already
 | 
					#warning -  clean up
 | 
				
			||||||
// has a special meaning for APRS.  This could be an APRS message or
 | 
					
 | 
				
			||||||
// some other APRS data type.  Payload is already used.
 | 
					// It is unforunate that the : data type indicator (DTI) was overloaded with
 | 
				
			||||||
 | 
					// so many different meanings.  Simply looking at the DTI is not adequate for
 | 
				
			||||||
 | 
					// determining whether a packet is a message.
 | 
				
			||||||
 | 
					// We need to exclude the other special cases of telemetry metadata,
 | 
				
			||||||
 | 
					// bulletins, and weather bulletins.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int is_message_message (char *infop)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (*infop != ':') return (0);
 | 
				
			||||||
 | 
						if (strlen(infop) < 11) return (0);	// too short for : addressee :
 | 
				
			||||||
 | 
						if (strlen(infop) >= 16) {
 | 
				
			||||||
 | 
						  if (strncmp(infop+10, ":PARM.", 6) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+10, ":UNIT.", 6) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+10, ":EQNS.", 6) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+10, ":BITS.", 6) == 0) return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (strlen(infop) >= 4) {
 | 
				
			||||||
 | 
						  if (strncmp(infop+1, "BLN", 3) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+1, "NWS", 3) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+1, "SKY", 3) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+1, "CWA", 3) == 0) return (0);
 | 
				
			||||||
 | 
						  if (strncmp(infop+1, "BOM", 3) == 0) return (0);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return (1);		// message, including ack, rej
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void maybe_xmit_packet_from_igate (char *message, int to_chan)
 | 
					static void maybe_xmit_packet_from_igate (char *message, int to_chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -1843,7 +1868,7 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
 | 
				
			||||||
 * If we recently transmitted a 'message' from some station,
 | 
					 * If we recently transmitted a 'message' from some station,
 | 
				
			||||||
 * send the position of the message sender when it comes along later.
 | 
					 * send the position of the message sender when it comes along later.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Some refer to this as a courtesy posit report but I don't
 | 
					 * Some refer to this as a "courtesy posit report" but I don't
 | 
				
			||||||
 * think that is an official term.
 | 
					 * think that is an official term.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * If we have a position report, look up the sender and see if we should
 | 
					 * If we have a position report, look up the sender and see if we should
 | 
				
			||||||
| 
						 | 
					@ -1988,10 +2013,7 @@ static void maybe_xmit_packet_from_igate (char *message, int to_chan)
 | 
				
			||||||
#endif
 | 
					#endif
 | 
				
			||||||
	    stats_rf_xmit_packets++;		// Any type of packet.
 | 
						    stats_rf_xmit_packets++;		// Any type of packet.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    // TEMP TEST: metadata temporarily allowed during testing.
 | 
						    if (is_message_message(pinfo)) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	    if (*pinfo == ':' && ! is_telem_metadata(pinfo)) {
 | 
					 | 
				
			||||||
	    // temp test // if (*pinfo == ':') {
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
// We transmitted a "message."  Telemetry metadata is excluded.
 | 
					// We transmitted a "message."  Telemetry metadata is excluded.
 | 
				
			||||||
// Remember to pass along address of the sender later.
 | 
					// Remember to pass along address of the sender later.
 | 
				
			||||||
| 
						 | 
					@ -2449,6 +2471,26 @@ void ig_to_tx_remember (packet_t pp, int chan, int bydigi)
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#warning remove
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int is_message_overload (char *infop)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						if (*infop != ':') return (0);
 | 
				
			||||||
 | 
						if (strlen(infop) < 16) return (0);
 | 
				
			||||||
 | 
						if (strncmp(infop+10, ":PARM.", 6) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+10, ":UNIT.", 6) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+10, ":EQNS.", 6) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+10, ":BITS.", 6) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+1, "BLN", 3) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+1, "NWS", 3) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+1, "SKY", 3) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+1, "CWA", 3) == 0) return (1);
 | 
				
			||||||
 | 
						if (strncmp(infop+1, "BOM", 3) == 0) return (1);
 | 
				
			||||||
 | 
						return (0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ig_to_tx_allow (packet_t pp, int chan)
 | 
					static int ig_to_tx_allow (packet_t pp, int chan)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	unsigned short crc = ax25_dedupe_crc(pp);
 | 
						unsigned short crc = ax25_dedupe_crc(pp);
 | 
				
			||||||
| 
						 | 
					@ -2481,7 +2523,7 @@ static int ig_to_tx_allow (packet_t pp, int chan)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    /* We have a duplicate within some time period. */
 | 
						    /* We have a duplicate within some time period. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    if (*pinfo == ':' && ! is_telem_metadata((char*)pinfo)) {
 | 
						    if (is_message_message((char*)pinfo)) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      /* I think I want to avoid the duplicate suppression for "messages." */
 | 
						      /* I think I want to avoid the duplicate suppression for "messages." */
 | 
				
			||||||
	      /* Suppose we transmit a message from station X and it doesn't get an ack back. */
 | 
						      /* Suppose we transmit a message from station X and it doesn't get an ack back. */
 | 
				
			||||||
| 
						 | 
					@ -2530,7 +2572,7 @@ static int ig_to_tx_allow (packet_t pp, int chan)
 | 
				
			||||||
	/* the normal limit for them. */
 | 
						/* the normal limit for them. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	increase_limit = 1;
 | 
						increase_limit = 1;
 | 
				
			||||||
	if (*pinfo == ':' && ! is_telem_metadata((char*)pinfo)) {
 | 
						if (is_message_message((char*)pinfo)) {
 | 
				
			||||||
	  increase_limit = 3;
 | 
						  increase_limit = 3;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										50
									
								
								src/mheard.c
								
								
								
								
							
							
						
						
									
										50
									
								
								src/mheard.c
								
								
								
								
							| 
						 | 
					@ -336,6 +336,52 @@ void mheard_save_rf (int chan, decode_aprs_t *A, packet_t pp, alevel_t alevel, r
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hops = ax25_get_heard(pp) - AX25_SOURCE;
 | 
						hops = ax25_get_heard(pp) - AX25_SOURCE;
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 *		Consider the following scenario:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		(1) We hear AA1PR-9 by a path of 4 digipeaters.
 | 
				
			||||||
 | 
					 *		    Looking closer, it's probably only two because there are left over WIDE1-0 and WIDE2-0.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			Digipeater WIDE2 (probably N3LLO-3) audio level = 72(19/15)   [NONE]   _|||||___
 | 
				
			||||||
 | 
					 *			[0.3] AA1PR-9>APY300,K1EQX-7,WIDE1,N3LLO-3,WIDE2*,ARISS::ANSRVR   :cq hotg vt aprsthursday{01<0x0d>
 | 
				
			||||||
 | 
					 *			                             -----         -----
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		(2) APRS-IS sends a response to us.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			[ig>tx] ANSRVR>APWW11,KJ4ERJ-15*,TCPIP*,qAS,KJ4ERJ-15::AA1PR-9  :N:HOTG 161 Messages Sent{JL}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		(3) Here is our analysis of whether it should be sent to RF.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			Was message addressee AA1PR-9 heard in the past 180 minutes, with 2 or fewer digipeater hops?
 | 
				
			||||||
 | 
					 *			No, AA1PR-9 was last heard over the radio with 4 digipeater hops 0 minutes ago.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		The wrong hop count caused us to drop a packet that should have been transmitted.
 | 
				
			||||||
 | 
					 *		We could put in a hack to not count the "WIDEn-0"  addresses.
 | 
				
			||||||
 | 
					 *		That is not correct because other prefixes could be used and we don't know
 | 
				
			||||||
 | 
					 *		what they are for other digipeaters.
 | 
				
			||||||
 | 
					 *		I think the best solution is to simply ignore the hop count.
 | 
				
			||||||
 | 
					 *		Maybe next release will have a major cleanup.
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// HACK - Reduce hop count by number of used WIDEn-0 addresses.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if (hops > 1) {
 | 
				
			||||||
 | 
						  for (int k = 0; k < ax25_get_num_repeaters(pp); k++) {
 | 
				
			||||||
 | 
						    char digi[AX25_MAX_ADDR_LEN];
 | 
				
			||||||
 | 
						    ax25_get_addr_no_ssid (pp, AX25_REPEATER_1 + k, digi);
 | 
				
			||||||
 | 
						    int ssid = ax25_get_ssid (pp, AX25_REPEATER_1 + k);
 | 
				
			||||||
 | 
						    int used = ax25_get_h (pp, AX25_REPEATER_1 + k);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    //text_color_set(DW_COLOR_DEBUG);
 | 
				
			||||||
 | 
						    //dw_printf ("Examining %s-%d  used=%d.\n", digi, ssid, used);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						    if (used && strlen(digi) == 5 && strncmp(digi, "WIDE", 4) == 0 && isdigit(digi[4]) && ssid == 0) {
 | 
				
			||||||
 | 
						      hops--;
 | 
				
			||||||
 | 
						      //text_color_set(DW_COLOR_DEBUG);
 | 
				
			||||||
 | 
						      //dw_printf ("Decrease hop count to %d for problematic %s.\n", hops, digi);
 | 
				
			||||||
 | 
						    }
 | 
				
			||||||
 | 
						  }
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	mptr = mheard_ptr(source);
 | 
						mptr = mheard_ptr(source);
 | 
				
			||||||
	if (mptr == NULL) {
 | 
						if (mptr == NULL) {
 | 
				
			||||||
| 
						 | 
					@ -571,7 +617,7 @@ void mheard_save_is (char *ptext)
 | 
				
			||||||
 *					8 for RF_CNT.
 | 
					 *					8 for RF_CNT.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		time_limit	- Include only stations heard within this many minutes.
 | 
					 *		time_limit	- Include only stations heard within this many minutes.
 | 
				
			||||||
 *				  Typically 30 or 60.
 | 
					 *				  Typically 180.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Returns:	Number to be used in the statistics report.
 | 
					 * Returns:	Number to be used in the statistics report.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
| 
						 | 
					@ -649,7 +695,7 @@ int mheard_count (int max_hops, int time_limit)
 | 
				
			||||||
 *		callsign	- Callsign for station.
 | 
					 *		callsign	- Callsign for station.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		time_limit	- Include only stations heard within this many minutes.
 | 
					 *		time_limit	- Include only stations heard within this many minutes.
 | 
				
			||||||
 *				  Typically 30 or 60.
 | 
					 *				  Typically 180.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		max_hops	- Include only stations heard with this number of
 | 
					 *		max_hops	- Include only stations heard with this number of
 | 
				
			||||||
 *				  digipeater hops or less.  For reporting, we might use:
 | 
					 *				  digipeater hops or less.  For reporting, we might use:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										252
									
								
								src/pfilter.c
								
								
								
								
							
							
						
						
									
										252
									
								
								src/pfilter.c
								
								
								
								
							| 
						 | 
					@ -1,7 +1,7 @@
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//    This file is part of Dire Wolf, an amateur radio packet TNC.
 | 
					//    This file is part of Dire Wolf, an amateur radio packet TNC.
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//    Copyright (C) 2015, 2016  John Langner, WB2OSZ
 | 
					//    Copyright (C) 2015, 2016, 2023  John Langner, WB2OSZ
 | 
				
			||||||
//
 | 
					//
 | 
				
			||||||
//    This program is free software: you can redistribute it and/or modify
 | 
					//    This program is free software: you can redistribute it and/or modify
 | 
				
			||||||
//    it under the terms of the GNU General Public License as published by
 | 
					//    it under the terms of the GNU General Public License as published by
 | 
				
			||||||
| 
						 | 
					@ -546,7 +546,8 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
/* b - budlist */
 | 
					/* b - budlist */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (pf->token_str[0] == 'b' && ispunct(pf->token_str[1])) {
 | 
						else if (pf->token_str[0] == 'b' && ispunct(pf->token_str[1])) {
 | 
				
			||||||
	  /* Budlist - source address */
 | 
						  /* Budlist - AX.25 source address */
 | 
				
			||||||
 | 
						  /* Could be different than source encapsulated by 3rd party header. */
 | 
				
			||||||
	  char addr[AX25_MAX_ADDR_LEN];
 | 
						  char addr[AX25_MAX_ADDR_LEN];
 | 
				
			||||||
	  ax25_get_addr_with_ssid (pf->pp, AX25_SOURCE, addr);
 | 
						  ax25_get_addr_with_ssid (pf->pp, AX25_SOURCE, addr);
 | 
				
			||||||
	  result = filt_bodgu (pf, addr);
 | 
						  result = filt_bodgu (pf, addr);
 | 
				
			||||||
| 
						 | 
					@ -572,7 +573,7 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (pf->token_str[0] == 'd' && ispunct(pf->token_str[1])) {
 | 
						else if (pf->token_str[0] == 'd' && ispunct(pf->token_str[1])) {
 | 
				
			||||||
	  int n;
 | 
						  int n;
 | 
				
			||||||
	  // loop on all digipeaters
 | 
						  // Loop on all AX.25 digipeaters.
 | 
				
			||||||
	  result = 0;
 | 
						  result = 0;
 | 
				
			||||||
	  for (n = AX25_REPEATER_1; result == 0 && n < ax25_get_num_addr (pf->pp); n++) {
 | 
						  for (n = AX25_REPEATER_1; result == 0 && n < ax25_get_num_addr (pf->pp); n++) {
 | 
				
			||||||
	    // Consider only those with the H (has-been-used) bit set.
 | 
						    // Consider only those with the H (has-been-used) bit set.
 | 
				
			||||||
| 
						 | 
					@ -599,7 +600,7 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (pf->token_str[0] == 'v' && ispunct(pf->token_str[1])) {
 | 
						else if (pf->token_str[0] == 'v' && ispunct(pf->token_str[1])) {
 | 
				
			||||||
	  int n;
 | 
						  int n;
 | 
				
			||||||
	  // loop on all digipeaters (mnemonic Via)
 | 
						  // loop on all AX.25 digipeaters (mnemonic Via)
 | 
				
			||||||
	  result = 0;
 | 
						  result = 0;
 | 
				
			||||||
	  for (n = AX25_REPEATER_1; result == 0 && n < ax25_get_num_addr (pf->pp); n++) {
 | 
						  for (n = AX25_REPEATER_1; result == 0 && n < ax25_get_num_addr (pf->pp); n++) {
 | 
				
			||||||
	    // This is different than the previous "d" filter.
 | 
						    // This is different than the previous "d" filter.
 | 
				
			||||||
| 
						 | 
					@ -623,10 +624,15 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* g - Addressee of message. */
 | 
					/* g - Addressee of message. e.g. "BLN*" for bulletins. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (pf->token_str[0] == 'g' && ispunct(pf->token_str[1])) {
 | 
						else if (pf->token_str[0] == 'g' && ispunct(pf->token_str[1])) {
 | 
				
			||||||
	  if (ax25_get_dti(pf->pp) == ':') {
 | 
						  if (pf->decoded.g_message_subtype == message_subtype_message ||
 | 
				
			||||||
 | 
						      pf->decoded.g_message_subtype == message_subtype_ack ||
 | 
				
			||||||
 | 
						      pf->decoded.g_message_subtype == message_subtype_rej ||
 | 
				
			||||||
 | 
						      pf->decoded.g_message_subtype == message_subtype_bulletin ||
 | 
				
			||||||
 | 
						      pf->decoded.g_message_subtype == message_subtype_nws ||
 | 
				
			||||||
 | 
						      pf->decoded.g_message_subtype == message_subtype_directed_query) {
 | 
				
			||||||
	    result = filt_bodgu (pf, pf->decoded.g_addressee);
 | 
						    result = filt_bodgu (pf, pf->decoded.g_addressee);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    if (s_debug >= 2) {
 | 
						    if (s_debug >= 2) {
 | 
				
			||||||
| 
						 | 
					@ -643,7 +649,7 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* u - unproto (destination) */
 | 
					/* u - unproto (AX.25 destination) */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (pf->token_str[0] == 'u' && ispunct(pf->token_str[1])) {
 | 
						else if (pf->token_str[0] == 'u' && ispunct(pf->token_str[1])) {
 | 
				
			||||||
	  /* Probably want to exclude mic-e types */
 | 
						  /* Probably want to exclude mic-e types */
 | 
				
			||||||
| 
						 | 
					@ -668,7 +674,7 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
	  }
 | 
						  }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* t - type: position, weather, etc. */
 | 
					/* t - packet type: position, weather, telemetry, etc. */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	else if (pf->token_str[0] == 't' && ispunct(pf->token_str[1])) {
 | 
						else if (pf->token_str[0] == 't' && ispunct(pf->token_str[1])) {
 | 
				
			||||||
	  
 | 
						  
 | 
				
			||||||
| 
						 | 
					@ -728,7 +734,7 @@ static int parse_filter_spec (pfstate_t *pf)
 | 
				
			||||||
	    (void) ax25_get_info (pf->pp, (unsigned char **)(&infop));
 | 
						    (void) ax25_get_info (pf->pp, (unsigned char **)(&infop));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    text_color_set(DW_COLOR_DEBUG);
 | 
						    text_color_set(DW_COLOR_DEBUG);
 | 
				
			||||||
	    if (*infop == ':' && ! is_telem_metadata(infop)) {
 | 
						    if (pf->decoded.g_packet_type == packet_type_message) {
 | 
				
			||||||
	      dw_printf ("   %s returns %s for message to %s\n", pf->token_str, bool2text(result), pf->decoded.g_addressee);
 | 
						      dw_printf ("   %s returns %s for message to %s\n", pf->token_str, bool2text(result), pf->decoded.g_addressee);
 | 
				
			||||||
	    }
 | 
						    }
 | 
				
			||||||
	    else {
 | 
						    else {
 | 
				
			||||||
| 
						 | 
					@ -832,31 +838,17 @@ static int filt_bodgu (pfstate_t *pf, char *arg)
 | 
				
			||||||
 *		 0 = no
 | 
					 *		 0 = no
 | 
				
			||||||
 *		-1 = error detected
 | 
					 *		-1 = error detected
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Description:	The filter is based the type filtering described here:
 | 
					 * Description:	The filter is loosely based the type filtering described here:
 | 
				
			||||||
 *		http://www.aprs-is.net/javAPRSFilter.aspx
 | 
					 *		http://www.aprs-is.net/javAPRSFilter.aspx
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		Most of these simply check the first byte of the information part.
 | 
					 *		Mostly use g_packet_type and g_message_subtype from decode_aprs.
 | 
				
			||||||
 *		Trying to detect NWS information is a little trickier.
 | 
					 *
 | 
				
			||||||
 | 
					 * References:
 | 
				
			||||||
 *		http://www.aprs-is.net/WX/
 | 
					 *		http://www.aprs-is.net/WX/
 | 
				
			||||||
 *		http://wxsvr.aprs.net.au/protocol-new.html	
 | 
					 *		http://wxsvr.aprs.net.au/protocol-new.html	(has disappeared)
 | 
				
			||||||
 *		
 | 
					 *		
 | 
				
			||||||
 *------------------------------------------------------------------------------*/
 | 
					 *------------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* Telemetry metadata is a special case of message. */
 | 
					 | 
				
			||||||
/* We want to categorize it as telemetry rather than message. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
int is_telem_metadata (char *infop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	if (*infop != ':') return (0);
 | 
					 | 
				
			||||||
	if (strlen(infop) < 16) return (0);
 | 
					 | 
				
			||||||
	if (strncmp(infop+10, ":PARM.", 6) == 0) return (1);
 | 
					 | 
				
			||||||
	if (strncmp(infop+10, ":UNIT.", 6) == 0) return (1);
 | 
					 | 
				
			||||||
	if (strncmp(infop+10, ":EQNS.", 6) == 0) return (1);
 | 
					 | 
				
			||||||
	if (strncmp(infop+10, ":BITS.", 6) == 0) return (1);
 | 
					 | 
				
			||||||
	return (0);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static int filt_t (pfstate_t *pf) 
 | 
					static int filt_t (pfstate_t *pf) 
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	char src[AX25_MAX_ADDR_LEN];
 | 
						char src[AX25_MAX_ADDR_LEN];
 | 
				
			||||||
| 
						 | 
					@ -873,108 +865,60 @@ static int filt_t (pfstate_t *pf)
 | 
				
			||||||
	  switch (*f) {
 | 
						  switch (*f) {
 | 
				
			||||||
	
 | 
						
 | 
				
			||||||
	    case 'p':				/* Position */
 | 
						    case 'p':				/* Position */
 | 
				
			||||||
	      if (*infop == '!') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_position) return(1);
 | 
				
			||||||
	      if (*infop == '/') return (1);
 | 
					 | 
				
			||||||
	      if (*infop == '=') return (1);
 | 
					 | 
				
			||||||
	      if (*infop == '@') return (1);
 | 
					 | 
				
			||||||
	      if (*infop == '\'') return (1);	// MIC-E
 | 
					 | 
				
			||||||
	      if (*infop == '`') return (1);	// MIC-E
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      // What if we have "_" symbol code for weather?
 | 
					 | 
				
			||||||
	      // Still consider as position.
 | 
					 | 
				
			||||||
	      // The same packet can match more than one type here.
 | 
					 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'o':				/* Object */
 | 
						    case 'o':				/* Object */
 | 
				
			||||||
	      if (*infop == ';') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_object) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'i':				/* Item */
 | 
						    case 'i':				/* Item */
 | 
				
			||||||
	      if (*infop == ')') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_item) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'm':				/* Message */
 | 
						    case 'm':				// Any "message."
 | 
				
			||||||
	      if (*infop == ':' && ! is_telem_metadata(infop)) return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_message) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'q':				/* Query */
 | 
						    case 'q':				/* Query */
 | 
				
			||||||
	      if (*infop == '?') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_query) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'c':				/* station Capabilities - my extension */
 | 
						    case 'c':				/* station Capabilities - my extension */
 | 
				
			||||||
						/* Most often used for IGate statistics. */
 | 
											/* Most often used for IGate statistics. */
 | 
				
			||||||
	      if (*infop == '<') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_capabilities) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 's':				/* Status */
 | 
						    case 's':				/* Status */
 | 
				
			||||||
	      if (*infop == '>') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_status) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 't':				/* Telemetry */
 | 
						    case 't':				/* Telemetry data or metadata */
 | 
				
			||||||
	      if (*infop == 'T') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_telemetry) return(1);
 | 
				
			||||||
	      if (is_telem_metadata(infop)) return (1);
 | 
					 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'u':				/* User-defined */
 | 
						    case 'u':				/* User-defined */
 | 
				
			||||||
	      if (*infop == '{') return (1);
 | 
						      if (pf->decoded.g_packet_type == packet_type_userdefined) return(1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'h':				/* third party Header - my extension */
 | 
						    case 'h':				/* has third party Header - my extension */
 | 
				
			||||||
	      if (*infop == '}') return (1);
 | 
						      if (pf->decoded.g_has_thirdparty_header) return (1);
 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'w':				/* Weather */
 | 
						    case 'w':				/* Weather */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      if (*infop == '*') return (1);			// Peet Bros
 | 
						      if (pf->decoded.g_packet_type == packet_type_weather) return(1);
 | 
				
			||||||
	      if (*infop == '_') return (1);			// Weather report, no position.
 | 
					 | 
				
			||||||
	      if (strncmp(infop, "!!", 2) == 0) return(1);	// Ultimeter 2000.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      /* '$' is normally raw GPS. Check for special case. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      if (strncmp(infop, "$ULTW", 5) == 0) return (1);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      /* Positions !=/@ with symbol code _ are weather. */
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      if (strchr("!=/@", *infop) != NULL &&
 | 
					 | 
				
			||||||
			pf->decoded.g_symbol_code == '_') return (1);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						      /* Positions !=/@  with symbol code _ are weather. */
 | 
				
			||||||
	      /* Object with _ symbol is also weather.  APRS protocol spec page 66. */
 | 
						      /* Object with _ symbol is also weather.  APRS protocol spec page 66. */
 | 
				
			||||||
 | 
						      // Can't use *infop because it would not work with 3rd party header.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	      if (*infop == ';' &&
 | 
						      if ((pf->decoded.g_packet_type == packet_type_position ||
 | 
				
			||||||
			pf->decoded.g_symbol_code == '_') return (1);
 | 
						           pf->decoded.g_packet_type == packet_type_object) && pf->decoded.g_symbol_code == '_') return (1);
 | 
				
			||||||
 | 
					 | 
				
			||||||
// TODO: need more test cases at end for new weather cases.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    case 'n':				/* NWS format */
 | 
						    case 'n':				/* NWS format */
 | 
				
			||||||
/*
 | 
						      if (pf->decoded.g_packet_type == packet_type_nws) return(1);
 | 
				
			||||||
 * This is the interesting case.
 | 
					 | 
				
			||||||
 * The source must be exactly 6 upper case letters, no SSID.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
	      if (strlen(src) != 6) break;
 | 
					 | 
				
			||||||
	      if (! isupper(src[0])) break;
 | 
					 | 
				
			||||||
	      if (! isupper(src[1])) break;
 | 
					 | 
				
			||||||
	      if (! isupper(src[2])) break;
 | 
					 | 
				
			||||||
	      if (! isupper(src[3])) break;
 | 
					 | 
				
			||||||
	      if (! isupper(src[4])) break;
 | 
					 | 
				
			||||||
	      if (! isupper(src[5])) break;
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * We can have a "message" with addressee starting with NWS, SKY, or BOM (Australian version.)
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
	      if (strncmp(infop, ":NWS", 4) == 0) return (1);
 | 
					 | 
				
			||||||
	      if (strncmp(infop, ":SKY", 4) == 0) return (1);
 | 
					 | 
				
			||||||
	      if (strncmp(infop, ":BOM", 4) == 0) return (1);
 | 
					 | 
				
			||||||
/*
 | 
					 | 
				
			||||||
 * Or we can have an object.
 | 
					 | 
				
			||||||
 * It's not exactly clear how to distinguish this from other objects.
 | 
					 | 
				
			||||||
 * It looks like the first 3 characters of the source should be the same
 | 
					 | 
				
			||||||
 * as the first 3 characters of the addressee.
 | 
					 | 
				
			||||||
 */
 | 
					 | 
				
			||||||
	      if (infop[0] == ';' &&
 | 
					 | 
				
			||||||
		  infop[1] == src[0] &&
 | 
					 | 
				
			||||||
		  infop[2] == src[1] &&
 | 
					 | 
				
			||||||
		  infop[3] == src[2]) return (1);
 | 
					 | 
				
			||||||
	      break;
 | 
						      break;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	    default:
 | 
						    default:
 | 
				
			||||||
| 
						 | 
					@ -990,6 +934,7 @@ static int filt_t (pfstate_t *pf)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*------------------------------------------------------------------------------
 | 
					/*------------------------------------------------------------------------------
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Name:	filt_r
 | 
					 * Name:	filt_r
 | 
				
			||||||
| 
						 | 
					@ -1327,8 +1272,36 @@ static int filt_s (pfstate_t *pf)
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		IMHO, the rules here are too restrictive.
 | 
					 *		IMHO, the rules here are too restrictive.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *		(1) The APRS-IS would send a "message" to my IGate only if the addressee
 | 
					 *		    The APRS-IS would send a "message" to my IGate only if the addressee
 | 
				
			||||||
 *		    has been heard nearby recently.  180 minutes, I believe.
 | 
					 *		    has been heard nearby recently.  180 minutes, I believe.
 | 
				
			||||||
 | 
					 *		    Why would I not want to transmit it?
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * Discussion:	In retrospect, I think this is far too complicated.
 | 
				
			||||||
 | 
					 *		In a future release, I think at options other than time should be removed.
 | 
				
			||||||
 | 
					 *		Messages have more value than most packets.  Why reduce the chance of successful delivery?
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		Consider the following scenario:
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		(1) We hear AA1PR-9 by a path of 4 digipeaters.
 | 
				
			||||||
 | 
					 *		    Looking closer, it's probably only two because there are left over WIDE1-0 and WIDE2-0.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			Digipeater WIDE2 (probably N3LLO-3) audio level = 72(19/15)   [NONE]   _|||||___
 | 
				
			||||||
 | 
					 *			[0.3] AA1PR-9>APY300,K1EQX-7,WIDE1,N3LLO-3,WIDE2*,ARISS::ANSRVR   :cq hotg vt aprsthursday{01<0x0d>
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		(2) APRS-IS sends a response to us.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			[ig>tx] ANSRVR>APWW11,KJ4ERJ-15*,TCPIP*,qAS,KJ4ERJ-15::AA1PR-9  :N:HOTG 161 Messages Sent{JL}
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		(3) Here is our analysis of whether it should be sent to RF.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *			Was message addressee AA1PR-9 heard in the past 180 minutes, with 2 or fewer digipeater hops?
 | 
				
			||||||
 | 
					 *			No, AA1PR-9 was last heard over the radio with 4 digipeater hops 0 minutes ago.
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 *		The wrong hop count caused us to drop a packet that should have been transmitted.
 | 
				
			||||||
 | 
					 *		We could put in a hack to not count the "WIDE*-0"  addresses.
 | 
				
			||||||
 | 
					 *		That is not correct because other prefixes could be used and we don't know
 | 
				
			||||||
 | 
					 *		what they are for other digipeaters.
 | 
				
			||||||
 | 
					 *		I think the best solution is to simply ignore the hop count.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 *------------------------------------------------------------------------------*/
 | 
					 *------------------------------------------------------------------------------*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1357,9 +1330,9 @@ static int filt_i (pfstate_t *pf)
 | 
				
			||||||
	double km = G_UNKNOWN;
 | 
						double km = G_UNKNOWN;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	char src[AX25_MAX_ADDR_LEN];
 | 
						//char src[AX25_MAX_ADDR_LEN];
 | 
				
			||||||
	char *infop = NULL;
 | 
						//char *infop = NULL;
 | 
				
			||||||
	int info_len;
 | 
						//int info_len;
 | 
				
			||||||
	//char *f;
 | 
						//char *f;
 | 
				
			||||||
	//char addressee[AX25_MAX_ADDR_LEN];
 | 
						//char addressee[AX25_MAX_ADDR_LEN];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1433,20 +1406,7 @@ static int filt_i (pfstate_t *pf)
 | 
				
			||||||
 * Get source address and info part.
 | 
					 * Get source address and info part.
 | 
				
			||||||
 * Addressee has already been extracted into pf->decoded.g_addressee.
 | 
					 * Addressee has already been extracted into pf->decoded.g_addressee.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
						if (pf->decoded.g_packet_type != packet_type_message) return(0);
 | 
				
			||||||
	memset (src, 0, sizeof(src));
 | 
					 | 
				
			||||||
	ax25_get_addr_with_ssid (pf->pp, AX25_SOURCE, src);
 | 
					 | 
				
			||||||
	info_len = ax25_get_info (pf->pp, (unsigned char **)(&infop));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (infop == NULL) return (0);
 | 
					 | 
				
			||||||
	if (info_len < 1) return (0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
// Determine packet type.  We are interested only in "message."
 | 
					 | 
				
			||||||
// Telemetry metadata is not considered a message.
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (*infop != ':') return (0);
 | 
					 | 
				
			||||||
	if (is_telem_metadata(infop)) return (0);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#if defined(PFTEST) || defined(DIGITEST)	// TODO: test functionality too, not just syntax.
 | 
					#if defined(PFTEST) || defined(DIGITEST)	// TODO: test functionality too, not just syntax.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1486,7 +1446,7 @@ static int filt_i (pfstate_t *pf)
 | 
				
			||||||
 * the past minute, rather than the usual 180 minutes for the addressee.
 | 
					 * the past minute, rather than the usual 180 minutes for the addressee.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	was_heard = mheard_was_recently_nearby ("source", src, 1, 0, G_UNKNOWN, G_UNKNOWN, G_UNKNOWN);
 | 
						was_heard = mheard_was_recently_nearby ("source", pf->decoded.g_src, 1, 0, G_UNKNOWN, G_UNKNOWN, G_UNKNOWN);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (was_heard) return (0);
 | 
						if (was_heard) return (0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1640,24 +1600,29 @@ int main ()
 | 
				
			||||||
	pftest (112, "t/t", "WM1X>APU25N:@210147z4235.39N/07106.58W_359/000g000t027r000P000p000h89b10234/WX REPORT {UIV32N}<0x0d>", 0);
 | 
						pftest (112, "t/t", "WM1X>APU25N:@210147z4235.39N/07106.58W_359/000g000t027r000P000p000h89b10234/WX REPORT {UIV32N}<0x0d>", 0);
 | 
				
			||||||
	pftest (113, "t/w", "WM1X>APU25N:@210147z4235.39N/07106.58W_359/000g000t027r000P000p000h89b10234/WX REPORT {UIV32N}<0x0d>", 1);
 | 
						pftest (113, "t/w", "WM1X>APU25N:@210147z4235.39N/07106.58W_359/000g000t027r000P000p000h89b10234/WX REPORT {UIV32N}<0x0d>", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Telemetry metadata is a special case of message. */
 | 
						/* Telemetry metadata should not be classified as message. */
 | 
				
			||||||
	pftest (114, "t/t", "KJ4SNT>APMI04::KJ4SNT   :PARM.Vin,Rx1h,Dg1h,Eff1h,Rx10m,O1,O2,O3,O4,I1,I2,I3,I4", 1);
 | 
						pftest (114, "t/t", "KJ4SNT>APMI04::KJ4SNT   :PARM.Vin,Rx1h,Dg1h,Eff1h,Rx10m,O1,O2,O3,O4,I1,I2,I3,I4", 1);
 | 
				
			||||||
	pftest (115, "t/m", "KJ4SNT>APMI04::KJ4SNT   :PARM.Vin,Rx1h,Dg1h,Eff1h,Rx10m,O1,O2,O3,O4,I1,I2,I3,I4", 0);
 | 
						pftest (115, "t/m", "KJ4SNT>APMI04::KJ4SNT   :PARM.Vin,Rx1h,Dg1h,Eff1h,Rx10m,O1,O2,O3,O4,I1,I2,I3,I4", 0);
 | 
				
			||||||
	pftest (116, "t/t", "KB1GKN-10>APRX27,UNCAN,WIDE1*:T#491,4.9,0.3,25.0,0.0,1.0,00000000", 1);
 | 
						pftest (116, "t/t", "KB1GKN-10>APRX27,UNCAN,WIDE1*:T#491,4.9,0.3,25.0,0.0,1.0,00000000", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Bulletins should not be considered to be messages.  Was bug in 1.6. */
 | 
				
			||||||
 | 
						pftest (117, "t/m", "A>B::W1AW     :test", 1);
 | 
				
			||||||
 | 
						pftest (118, "t/m", "A>B::BLN      :test", 0);
 | 
				
			||||||
 | 
						pftest (119, "t/m", "A>B::NWS      :test", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pftest (120, "t/p", "CWAPID>APRS::NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", 0);
 | 
						// https://www.aprs-is.net/WX/
 | 
				
			||||||
 | 
						pftest (121, "t/p", "CWAPID>APRS::NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", 0);
 | 
				
			||||||
	pftest (122, "t/p", "CWAPID>APRS::SKYCWA   :DDHHMMz,ADVISETYPE,zcs{seq#", 0);
 | 
						pftest (122, "t/p", "CWAPID>APRS::SKYCWA   :DDHHMMz,ADVISETYPE,zcs{seq#", 0);
 | 
				
			||||||
	pftest (123, "t/p", "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", 0);
 | 
						pftest (123, "t/p", "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", 0);
 | 
				
			||||||
	pftest (124, "t/n", "CWAPID>APRS::NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", 1);
 | 
						pftest (124, "t/n", "CWAPID>APRS::NWS-TTTTT:DDHHMMz,ADVISETYPE,zcs{seq#", 1);
 | 
				
			||||||
	pftest (125, "t/n", "CWAPID>APRS::SKYCWA   :DDHHMMz,ADVISETYPE,zcs{seq#", 1);
 | 
						pftest (125, "t/n", "CWAPID>APRS::SKYCWA   :DDHHMMz,ADVISETYPE,zcs{seq#", 1);
 | 
				
			||||||
	pftest (126, "t/n", "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", 1);
 | 
						//pftest (126, "t/n", "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", 1);
 | 
				
			||||||
	pftest (127, "t/",  "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", 0);
 | 
						pftest (127, "t/",  "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pftest (128, "t/c",  "S0RCE>DEST:<stationcapabilities", 1);
 | 
						pftest (128, "t/c",  "S0RCE>DEST:<stationcapabilities", 1);
 | 
				
			||||||
	pftest (129, "t/h",  "S0RCE>DEST:<stationcapabilities", 0);
 | 
						pftest (129, "t/h",  "S0RCE>DEST:<stationcapabilities", 0);
 | 
				
			||||||
	pftest (130, "t/h",  "S0RCE>DEST:}thirdpartyheaderwhatever", 1);
 | 
						pftest (130, "t/h",  "S0RCE>DEST:}WB2OSZ-5>APDW12,DIGI1,DIGI2*,DIGI3,DIGI4:!4237.14NS07120.83W#PHG7140Chelmsford MA", 1);
 | 
				
			||||||
	pftest (131, "t/c",  "S0RCE>DEST:}thirdpartyheaderwhatever", 0);
 | 
						pftest (131, "t/c",  "S0RCE>DEST:}WB2OSZ-5>APDW12,DIGI1,DIGI2*,DIGI3,DIGI4:!4237.14NS07120.83W#PHG7140Chelmsford MA", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pftest (140, "r/42.6/-71.3/10", "WB2OSZ-5>APDW12,WIDE1-1,WIDE2-1:!4237.14NS07120.83W#PHG7140Chelmsford MA", 1);
 | 
						pftest (140, "r/42.6/-71.3/10", "WB2OSZ-5>APDW12,WIDE1-1,WIDE2-1:!4237.14NS07120.83W#PHG7140Chelmsford MA", 1);
 | 
				
			||||||
	pftest (141, "r/42.6/-71.3/10", "WA1PLE-5>APWW10,W1MHL,N8VIM,WIDE2*:@022301h4208.75N/07115.16WoAPRS-IS for Win32", 0);
 | 
						pftest (141, "r/42.6/-71.3/10", "WA1PLE-5>APWW10,W1MHL,N8VIM,WIDE2*:@022301h4208.75N/07115.16WoAPRS-IS for Win32", 0);
 | 
				
			||||||
| 
						 | 
					@ -1712,13 +1677,13 @@ int main ()
 | 
				
			||||||
	pftest (203, "t/w t/w", "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", -1);
 | 
						pftest (203, "t/w t/w", "CWAPID>APRS:;CWAttttz *DDHHMMzLATLONICONADVISETYPE{seq#", -1);
 | 
				
			||||||
	pftest (204, "r/42.6/-71.3", "WA1PLE-5>APWW10,W1MHL,N8VIM,WIDE2*:@022301h4208.75N/07115.16WoAPRS-IS for Win32", -1);
 | 
						pftest (204, "r/42.6/-71.3", "WA1PLE-5>APWW10,W1MHL,N8VIM,WIDE2*:@022301h4208.75N/07115.16WoAPRS-IS for Win32", -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pftest (220, "i/30/8/42.6/-71.3/50", "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
						pftest (210, "i/30/8/42.6/-71.3/50", "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
	pftest (222, "i/30/8/42.6/-71.3/",   "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
						pftest (212, "i/30/8/42.6/-71.3/",   "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
				
			||||||
	pftest (223, "i/30/8/42.6/-71.3",    "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
						pftest (213, "i/30/8/42.6/-71.3",    "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
				
			||||||
	pftest (224, "i/30/8/42.6/",         "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
						pftest (214, "i/30/8/42.6/",         "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
				
			||||||
	pftest (225, "i/30/8/42.6",          "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
						pftest (215, "i/30/8/42.6",          "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
				
			||||||
	pftest (226, "i/30/8/",              "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
						pftest (216, "i/30/8/",              "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
	pftest (227, "i/30/8",               "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
						pftest (217, "i/30/8",               "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// FIXME: behaves differently on Windows and Linux.  Why?
 | 
						// FIXME: behaves differently on Windows and Linux.  Why?
 | 
				
			||||||
	// On Windows we have our own version of strsep because it's not in the MS library.
 | 
						// On Windows we have our own version of strsep because it's not in the MS library.
 | 
				
			||||||
| 
						 | 
					@ -1726,7 +1691,12 @@ int main ()
 | 
				
			||||||
	//pftest (228, "i/30/",                "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
						//pftest (228, "i/30/",                "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pftest (229, "i/30",                 "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
						pftest (229, "i/30",                 "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
	pftest (230, "i/",                   "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
						pftest (230, "i/30",                 "X>X:}WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
 | 
						pftest (231, "i/",                   "WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Besure bulletins and telemetry metadata don't get included.
 | 
				
			||||||
 | 
						pftest (234, "i/30", "KJ4SNT>APMI04::KJ4SNT   :PARM.Vin,Rx1h,Dg1h,Eff1h,Rx10m,O1,O2,O3,O4,I1,I2,I3,I4", 0);
 | 
				
			||||||
 | 
						pftest (235, "i/30", "A>B::BLN      :test", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pftest (240, "s/", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
						pftest (240, "s/", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
				
			||||||
	pftest (241, "s/'/O/-/#/_", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
						pftest (241, "s/'/O/-/#/_", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
				
			||||||
| 
						 | 
					@ -1736,12 +1706,36 @@ int main ()
 | 
				
			||||||
	pftest (245, "s//", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
						pftest (245, "s//", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
				
			||||||
	pftest (246, "s///", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
						pftest (246, "s///", "WB2OSZ-5>APDW12:!4237.14N/07120.83WOPHG7140Chelmsford MA", -1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Third party header - done properly in 1.7.
 | 
				
			||||||
 | 
						// Packet filter t/h is no longer a mutually exclusive packet type.
 | 
				
			||||||
 | 
						// Now it is an independent attribute and the encapsulated part is evaluated.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// TODO: to be continued...
 | 
						pftest (250, "o/home", "A>B:}WB2OSZ>APDW12,WIDE1-1,WIDE2-1:;home     *111111z4237.14N/07120.83W-Chelmsford MA", 1);
 | 
				
			||||||
 | 
						pftest (251, "t/p",    "A>B:}W1WRA-7>TRSY3T,WIDE1-1,WIDE2-1:`c-:l!hK\\>\"4b}=<0x0d>", 1);
 | 
				
			||||||
 | 
						pftest (252, "i/180",  "A>B:}WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
 | 
						pftest (253, "t/m",  "A>B:}WB2OSZ-5>APDW14::W2UB     :Happy Birthday{001", 1);
 | 
				
			||||||
 | 
						pftest (254, "r/42.6/-71.3/10", "A>B:}WB2OSZ-5>APDW12,WIDE1-1,WIDE2-1:!4237.14NS07120.83W#PHG7140Chelmsford MA", 1);
 | 
				
			||||||
 | 
						pftest (254, "r/42.6/-71.3/10", "A>B:}WA1PLE-5>APWW10,W1MHL,N8VIM,WIDE2*:@022301h4208.75N/07115.16WoAPRS-IS for Win32", 0);
 | 
				
			||||||
 | 
						pftest (255, "t/h",  "KB1GKN-10>APRX27,UNCAN,WIDE1*:T#491,4.9,0.3,25.0,0.0,1.0,00000000", 0);
 | 
				
			||||||
 | 
						pftest (256, "t/h",  "A>B:}KB1GKN-10>APRX27,UNCAN,WIDE1*:T#491,4.9,0.3,25.0,0.0,1.0,00000000", 1);
 | 
				
			||||||
 | 
						pftest (258, "t/t",  "A>B:}KB1GKN-10>APRX27,UNCAN,WIDE1*:T#491,4.9,0.3,25.0,0.0,1.0,00000000", 1);
 | 
				
			||||||
 | 
						pftest (259, "t/t",  "A>B:}KJ4SNT>APMI04::KJ4SNT   :PARM.Vin,Rx1h,Dg1h,Eff1h,Rx10m,O1,O2,O3,O4,I1,I2,I3,I4", 1);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pftest (270, "g/BLN*", "WB2OSZ>APDW17::BLN1xxxxx:bulletin text", 1);
 | 
				
			||||||
 | 
						pftest (271, "g/BLN*", "A>B:}WB2OSZ>APDW17::BLN1xxxxx:bulletin text", 1);
 | 
				
			||||||
 | 
						pftest (272, "g/BLN*", "A>B:}WB2OSZ>APDW17::W1AW     :xxxx", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pftest (273, "g/NWS*", "WB2OSZ>APDW17::NWS-xxxxx:weather bulletin", 1);
 | 
				
			||||||
 | 
						pftest (274, "g/NWS*", "A>B:}WB2OSZ>APDW17::NWS-xxxxx:weather bulletin", 1);
 | 
				
			||||||
 | 
						pftest (275, "g/NWS*", "A>B:}WB2OSZ>APDW17::W1AW     :xxxx", 0);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: add b/ with 3rd party header.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// TODO: to be continued...  directed query ...
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (error_count > 0) {
 | 
						if (error_count > 0) {
 | 
				
			||||||
	  text_color_set (DW_COLOR_ERROR);
 | 
						  text_color_set (DW_COLOR_ERROR);
 | 
				
			||||||
	  dw_printf ("\nPacket Filtering Test - FAILED!\n");
 | 
						  dw_printf ("\nPacket Filtering Test - FAILED!     %d errors\n", error_count);
 | 
				
			||||||
	  exit (EXIT_FAILURE);
 | 
						  exit (EXIT_FAILURE);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	text_color_set (DW_COLOR_REC);
 | 
						text_color_set (DW_COLOR_REC);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue