2 * Routines for Amateur Packet Radio protocol dissection
3 * Copyright 2007,2008,2009,2010,2012 R.W. Stearn <richard@rns-stearn.demon.co.uk>
5 * Wireshark - Network traffic analyzer
6 * By Gerald Combs <gerald@wireshark.org>
7 * Copyright 1998 Gerald Combs
9 * SPDX-License-Identifier: GPL-2.0-or-later
13 * This dissector is for APRS (Automatic Packet Reporting System)
15 * Information was drawn from:
16 * http://www.aprs.org/
17 * Specification: http://www.aprs.org/doc/APRS101.PDF
19 * Inspiration on how to build the dissector drawn from
25 * with the base file built from README.developers.
32 #include <epan/packet.h>
33 #include <epan/prefs.h>
34 #include <epan/to_str.h>
38 void proto_register_aprs(void);
40 static int proto_aprs
;
42 /* aprs timestamp items */
43 static int hf_aprs_dhm
;
44 static int hf_aprs_hms
;
45 static int hf_aprs_mdhm
;
46 static int hf_aprs_tz
;
48 /* aprs position items */
49 /* static int hf_aprs_position; */
50 static int hf_aprs_lat
;
51 static int hf_aprs_long
;
54 static int hf_aprs_msg
;
55 static int hf_aprs_msg_rng
;
56 static int hf_aprs_msg_cse
;
57 static int hf_aprs_msg_spd
;
58 static int hf_aprs_msg_dir
;
59 static int hf_aprs_msg_brg
;
60 static int hf_aprs_msg_nrq
;
62 /* aprs compression type items */
63 static int hf_aprs_compression_type
;
64 static int hf_aprs_ct_gps_fix
;
65 static int hf_aprs_ct_nmea_src
;
66 static int hf_aprs_ct_origin
;
69 static int hf_aprs_msg_phg_p
;
70 static int hf_aprs_msg_phg_h
;
71 static int hf_aprs_msg_phg_g
;
72 static int hf_aprs_msg_phg_d
;
75 static int hf_aprs_msg_dfs_s
;
76 static int hf_aprs_msg_dfs_h
;
77 static int hf_aprs_msg_dfs_g
;
78 static int hf_aprs_msg_dfs_d
;
81 static int hf_aprs_weather_dir
;
82 static int hf_aprs_weather_spd
;
83 static int hf_aprs_weather_peak
;
84 static int hf_aprs_weather_temp
;
85 static int hf_aprs_weather_rain_1
;
86 static int hf_aprs_weather_rain_24
;
87 static int hf_aprs_weather_rain
;
88 static int hf_aprs_weather_humidty
;
89 static int hf_aprs_weather_press
;
90 static int hf_aprs_weather_luminosity
;
91 static int hf_aprs_weather_snow
;
92 static int hf_aprs_weather_raw_rain
;
93 static int hf_aprs_weather_software
;
94 static int hf_aprs_weather_unit
;
97 static int hf_aprs_msg_aod_t
;
98 static int hf_aprs_msg_aod_c
;
100 /* mic-e msg items */
101 static int hf_aprs_mic_e_dst
;
102 static int hf_aprs_mic_e_long_d
;
103 static int hf_aprs_mic_e_long_m
;
104 static int hf_aprs_mic_e_long_h
;
105 static int hf_aprs_mic_e_spd_sp
;
106 static int hf_aprs_mic_e_spd_dc
;
107 static int hf_aprs_mic_e_spd_se
;
108 static int hf_aprs_mic_e_telemetry
;
109 static int hf_aprs_mic_e_status
;
112 static int hf_aprs_storm_dir
;
113 static int hf_aprs_storm_spd
;
114 static int hf_aprs_storm_type
;
115 static int hf_aprs_storm_sws
;
116 static int hf_aprs_storm_pwg
;
117 static int hf_aprs_storm_cp
;
118 static int hf_aprs_storm_rhw
;
119 static int hf_aprs_storm_rtsw
;
120 static int hf_aprs_storm_rwg
;
122 /* aprs sundry items */
123 static int hf_aprs_dti
;
124 static int hf_aprs_sym_id
;
125 static int hf_aprs_sym_code
;
126 static int hf_aprs_comment
;
127 static int hf_aprs_storm
;
129 /* aprs main catagories items */
130 static int hf_ultimeter_2000
;
131 static int hf_aprs_status
;
132 static int hf_aprs_object
;
133 static int hf_aprs_item
;
134 static int hf_aprs_query
;
135 static int hf_aprs_telemetry
;
136 static int hf_aprs_raw
;
137 static int hf_aprs_station
;
138 static int hf_aprs_message
;
139 static int hf_aprs_agrelo
;
140 static int hf_aprs_maidenhead
;
141 static int hf_aprs_weather
;
142 static int hf_aprs_invalid_test
;
143 static int hf_aprs_user_defined
;
144 static int hf_aprs_third_party
;
145 static int hf_aprs_mic_e_0_current
;
146 static int hf_aprs_mic_e_0_old
;
147 static int hf_aprs_mic_e_old
;
148 static int hf_aprs_mic_e_current
;
149 static int hf_aprs_peet_1
;
150 static int hf_aprs_peet_2
;
151 static int hf_aprs_map_feature
;
152 static int hf_aprs_shelter_data
;
153 static int hf_aprs_space_weather
;
156 static bool gPREF_APRS_LAX
;
159 static int ett_aprs_msg
;
160 static int ett_aprs_ct
;
161 static int ett_aprs_weather
;
162 static int ett_aprs_storm
;
163 static int ett_aprs_mic_e
;
166 static const value_string ctype_vals
[] = {
169 { 2, "Software (DOS/Mac/Win/+SA)" },
173 { 6, "Other tracker [tbd]" },
174 { 7, "Digipeater conversion" },
178 static const value_string nmea_vals
[] = {
186 static const value_string gps_vals
[] = {
193 static const value_string aprs_description
[] = {
194 { 0x1c, "Current Mic-E Data (Rev 0 beta)" },
195 { 0x1d, "Old Mic-E Data (Rev 0 beta)" },
196 { '#', "Peet Bros U-II Weather Station" },
197 { '$', "Raw GPS data or Ultimeter 2000" },
198 { '%', "Agrelo DFJr / MicroFinder" },
199 { '&', "[Reserved - Map Feature]" },
200 { '\'', "Old Mic-E Data (current data for TM-D700)" },
202 { '*', "Peet Bros U-II Weather Station" },
203 { '+', "[Reserved - Shelter data with time]" },
204 { ',', "Invalid data or test data" },
205 { '.', "[Reserved - Space weather]" },
206 { '/', "Position + timestamp" },
209 { '<', "Station Capabilities" },
210 { '=', "Position + APRS data extension" },
213 { '@', "Position + timestamp + APRS data extension" },
214 { 'T', "Telemetry data" },
215 { '[', "Maidenhead grid locator beacon (obsolete)" },
216 { '_', "Weather Report (without position)" },
217 { '`', "Current Mic-E Data (not used in TM-D700)" },
218 { '{', "User-Defined APRS packet format" },
219 { '}', "Third-party traffic" },
222 static value_string_ext aprs_description_ext
= VALUE_STRING_EXT_INIT(aprs_description
);
224 /* MIC-E destination field code table */
233 } mic_e_dst_code_table_s
;
235 static const mic_e_dst_code_table_s dst_code
[] =
237 { '0' << 1, '0', 0, 'S', 0, 'E' },
238 { '1' << 1, '1', 0, 'S', 0, 'E' },
239 { '2' << 1, '2', 0, 'S', 0, 'E' },
240 { '3' << 1, '3', 0, 'S', 0, 'E' },
241 { '4' << 1, '4', 0, 'S', 0, 'E' },
242 { '5' << 1, '5', 0, 'S', 0, 'E' },
243 { '6' << 1, '6', 0, 'S', 0, 'E' },
244 { '7' << 1, '7', 0, 'S', 0, 'E' },
245 { '8' << 1, '8', 0, 'S', 0, 'E' },
246 { '9' << 1, '9', 0, 'S', 0, 'E' },
247 { 'A' << 1, '0', 1, '?', 0, '?' },
248 { 'B' << 1, '1', 1, '?', 0, '?' },
249 { 'C' << 1, '2', 1, '?', 0, '?' },
250 { 'D' << 1, '3', 1, '?', 0, '?' },
251 { 'E' << 1, '4', 1, '?', 0, '?' },
252 { 'F' << 1, '5', 1, '?', 0, '?' },
253 { 'G' << 1, '6', 1, '?', 0, '?' },
254 { 'H' << 1, '7', 1, '?', 0, '?' },
255 { 'I' << 1, '8', 1, '?', 0, '?' },
256 { 'J' << 1, '9', 1, '?', 0, '?' },
257 { 'K' << 1, ' ', 1, '?', 0, '?' },
258 { 'L' << 1, ' ', 0, 'S', 0, 'E' },
259 { 'P' << 1, '0', 1, 'N', 100, 'W' },
260 { 'Q' << 1, '1', 1, 'N', 100, 'W' },
261 { 'R' << 1, '2', 1, 'N', 100, 'W' },
262 { 'S' << 1, '3', 1, 'N', 100, 'W' },
263 { 'T' << 1, '4', 1, 'N', 100, 'W' },
264 { 'U' << 1, '5', 1, 'N', 100, 'W' },
265 { 'V' << 1, '6', 1, 'N', 100, 'W' },
266 { 'W' << 1, '7', 1, 'N', 100, 'W' },
267 { 'X' << 1, '8', 1, 'N', 100, 'W' },
268 { 'Y' << 1, '9', 1, 'N', 100, 'W' },
269 { 'Z' << 1, ' ', 1, 'N', 100, 'W' },
270 { 0, '_', 3, '?', 3, '?' },
274 /* MIC-E message table */
281 static const mic_e_msg_table_s mic_e_msg_table
[] =
283 { "Emergency", "Emergency" },
284 { "Priority", "Custom 6" },
285 { "Special", "Custom 5" },
286 { "Committed", "Custom 4" },
287 { "Returning", "Custom 3" },
288 { "In Service", "Custom 2" },
289 { "En Route", "Custom 1" },
290 { "Off Duty", "Custom 0" }
293 /* Code to actually dissect the packets */
296 dissect_aprs_compression_type( tvbuff_t
*tvb
,
298 proto_tree
*parent_tree
302 proto_tree
*compression_tree
;
305 uint8_t compression_type
;
309 new_offset
= offset
+ data_len
;
313 compression_type
= tvb_get_uint8( tvb
, offset
) - 33;
315 tc
= proto_tree_add_uint( parent_tree
, hf_aprs_compression_type
, tvb
, offset
, data_len
,
317 compression_tree
= proto_item_add_subtree( tc
, ett_aprs_ct
);
319 proto_tree_add_item( compression_tree
, hf_aprs_ct_gps_fix
, tvb
, offset
, data_len
, ENC_BIG_ENDIAN
);
320 proto_tree_add_item( compression_tree
, hf_aprs_ct_nmea_src
, tvb
, offset
, data_len
, ENC_BIG_ENDIAN
);
321 proto_tree_add_item( compression_tree
, hf_aprs_ct_origin
, tvb
, offset
, data_len
, ENC_BIG_ENDIAN
);
328 dissect_aprs_msg( tvbuff_t
*tvb
,
330 proto_tree
*parent_tree
,
335 proto_tree
*msg_tree
= NULL
;
342 tc
= proto_tree_add_item( parent_tree
, hf_aprs_msg
, tvb
, offset
, 7, ENC_ASCII
);
343 msg_tree
= proto_item_add_subtree( tc
, ett_aprs_msg
);
346 ch
= tvb_get_uint8( tvb
, offset
);
348 if ( g_ascii_isdigit( ch
) )
351 proto_tree_add_item( msg_tree
, hf_aprs_msg_dir
, tvb
, offset
, 3, ENC_ASCII
);
353 proto_tree_add_item( msg_tree
, hf_aprs_msg_cse
, tvb
, offset
, 3, ENC_ASCII
);
355 /* verify the separator */
357 proto_tree_add_item( msg_tree
, hf_aprs_msg_spd
, tvb
, offset
, 3, ENC_ASCII
);
366 proto_tree_add_item( msg_tree
, hf_aprs_msg_dfs_s
, tvb
, offset
, 1, ENC_ASCII
);
368 proto_tree_add_item( msg_tree
, hf_aprs_msg_dfs_h
, tvb
, offset
, 1, ENC_ASCII
);
370 proto_tree_add_item( msg_tree
, hf_aprs_msg_dfs_g
, tvb
, offset
, 1, ENC_ASCII
);
372 proto_tree_add_item( msg_tree
, hf_aprs_msg_dfs_d
, tvb
, offset
, 1, ENC_ASCII
);
374 case 'P' : /* phgd */
376 proto_tree_add_item( msg_tree
, hf_aprs_msg_phg_p
, tvb
, offset
, 1, ENC_ASCII
);
378 proto_tree_add_item( msg_tree
, hf_aprs_msg_phg_h
, tvb
, offset
, 1, ENC_ASCII
);
380 proto_tree_add_item( msg_tree
, hf_aprs_msg_phg_g
, tvb
, offset
, 1, ENC_ASCII
);
382 proto_tree_add_item( msg_tree
, hf_aprs_msg_phg_d
, tvb
, offset
, 1, ENC_ASCII
);
385 proto_tree_add_item( msg_tree
, hf_aprs_msg_rng
, tvb
, offset
, 7, ENC_ASCII
);
389 proto_tree_add_item( msg_tree
, hf_aprs_msg_aod_t
, tvb
, offset
, 2, ENC_ASCII
);
391 /* step over the /C */
393 proto_tree_add_item( msg_tree
, hf_aprs_msg_aod_c
, tvb
, offset
, 2, ENC_ASCII
);
401 proto_tree_add_item( msg_tree
, hf_aprs_msg_brg
, tvb
, offset
, 3, ENC_ASCII
);
403 /* verify the separator */
405 proto_tree_add_item( msg_tree
, hf_aprs_msg_nrq
, tvb
, offset
, 3, ENC_ASCII
);
413 dissect_aprs_compressed_msg( wmem_allocator_t
*scope
,
416 proto_tree
*parent_tree
420 proto_tree
*msg_tree
;
431 new_offset
= offset
+ data_len
;
435 tc
= proto_tree_add_item( parent_tree
, hf_aprs_msg
, tvb
, offset
, data_len
, ENC_ASCII
);
436 msg_tree
= proto_item_add_subtree( tc
, ett_aprs_msg
);
438 ch
= tvb_get_uint8( tvb
, offset
);
442 { /* Pre-Calculated Radio Range */
444 ch
= tvb_get_uint8( tvb
, offset
);
445 range
= exp( log( 1.08 ) * (ch
- 33) );
446 info_buffer
= wmem_strdup_printf( scope
, "%7.2f", range
);
447 proto_tree_add_string( msg_tree
, hf_aprs_msg_rng
, tvb
, offset
, 1, info_buffer
);
450 if ( ch
>= '!' && ch
<= 'z' )
452 course
= (ch
- 33) * 4;
453 info_buffer
= wmem_strdup_printf( scope
, "%d", course
);
454 proto_tree_add_string( msg_tree
, hf_aprs_msg_cse
,
455 tvb
, offset
, 1, info_buffer
);
457 ch
= tvb_get_uint8( tvb
, offset
);
458 speed
= exp( log( 1.08 ) * (ch
- 33) );
459 info_buffer
= wmem_strdup_printf( scope
, "%7.2f", speed
);
460 proto_tree_add_string( msg_tree
, hf_aprs_msg_spd
,
461 tvb
, offset
, 1, info_buffer
);
471 static const mic_e_dst_code_table_s
*
472 dst_code_lookup( uint8_t ch
)
477 while (indx
< array_length(dst_code
)
478 && dst_code
[ indx
].key
!= ch
479 && dst_code
[ indx
].key
> 0 )
481 return &( dst_code
[ indx
] );
485 d28_to_deg( uint8_t code
, int long_offset
)
489 value
= code
- 28 + long_offset
;
490 if ( value
>= 180 && value
<= 189 )
493 if ( value
>= 190 && value
<= 199 )
499 d28_to_min( uint8_t code
)
510 dissect_mic_e( tvbuff_t
*tvb
,
513 proto_tree
*parent_tree
,
518 proto_tree
*mic_e_tree
;
522 char latitude
[8] = { '?', '?', '?', '?', '.', '?', '?', 0x0 };
533 const mic_e_dst_code_table_s
*dst_code_entry
;
535 data_len
= tvb_reported_length_remaining( tvb
, offset
);
536 new_offset
= offset
+ data_len
;
538 info_buffer
= (char *)wmem_alloc( pinfo
->pool
, STRLEN
);
549 if ( pinfo
->dst
.type
== AT_AX25
&& pinfo
->dst
.len
== AX25_ADDR_LEN
)
551 /* decode the AX.25 destination address */
552 addr
= (const uint8_t *)pinfo
->dst
.data
;
554 dst_code_entry
= dst_code_lookup( addr
[ 0 ] );
555 latitude
[ 0 ] = dst_code_entry
->digit
;
556 msg_a
= dst_code_entry
->msg
& 0x1;
558 dst_code_entry
= dst_code_lookup( addr
[ 1 ] );
559 latitude
[ 1 ] = dst_code_entry
->digit
;
560 msg_b
= dst_code_entry
->msg
& 0x1;
562 dst_code_entry
= dst_code_lookup( addr
[ 2 ] );
563 latitude
[ 2 ] = dst_code_entry
->digit
;
564 msg_c
= dst_code_entry
->msg
& 0x1;
566 dst_code_entry
= dst_code_lookup( addr
[ 3 ] );
567 latitude
[ 3 ] = dst_code_entry
->digit
;
568 n_s
= dst_code_entry
->n_s
;
570 /* '.' already set */
572 dst_code_entry
= dst_code_lookup( addr
[ 4 ] );
573 latitude
[ 5 ] = dst_code_entry
->digit
;
574 long_offset
= dst_code_entry
->long_offset
;
576 dst_code_entry
= dst_code_lookup( addr
[ 5 ] );
577 latitude
[ 6 ] = dst_code_entry
->digit
;
578 w_e
= dst_code_entry
->w_e
;
580 ssid
= (addr
[ 6 ] >> 1) & 0x0f;
583 /* decode the mic-e info fields */
584 spd
= ((tvb_get_uint8( tvb
, offset
+ 3 ) - 28) * 10) + ((tvb_get_uint8( tvb
, offset
+ 4 ) - 28) / 10);
588 cse
= (((tvb_get_uint8( tvb
, offset
+ 4 ) - 28) % 10) * 100) + ((tvb_get_uint8( tvb
, offset
+ 5 ) - 28) * 10);
592 snprintf( info_buffer
, STRLEN
,
593 "Lat: %7.7s%c Long: %03d%02d.%02d%c, Cse: %d, Spd: %d, SSID: %d, Msg %s",
596 d28_to_deg( tvb_get_uint8( tvb
, offset
), long_offset
),
597 d28_to_min( tvb_get_uint8( tvb
, offset
+ 1 ) ),
598 tvb_get_uint8( tvb
, offset
+ 2 ) - 28,
603 mic_e_msg_table
[ (msg_a
<< 2) + (msg_b
<< 1) + msg_c
].std
606 col_set_str( pinfo
->cinfo
, COL_INFO
, "MIC-E " );
607 col_append_str( pinfo
->cinfo
, COL_INFO
, info_buffer
);
611 tc
= proto_tree_add_string( parent_tree
, hf_mic_e_idx
, tvb
, offset
, data_len
, info_buffer
);
612 mic_e_tree
= proto_item_add_subtree( tc
, ett_aprs_mic_e
);
614 snprintf( info_buffer
, STRLEN
,
615 "Lat %7.7s, Msg A %d, Msg B %d, Msg C %d, N/S %c, Long off %3d, W/E %c, SSID %d",
626 proto_tree_add_string( mic_e_tree
, hf_aprs_mic_e_dst
, tvb
, 0, 0, info_buffer
); /* ?? */
628 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_long_d
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
631 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_long_m
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
634 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_long_h
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
637 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_spd_sp
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
640 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_spd_dc
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
643 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_spd_se
, tvb
, offset
, 1, ENC_BIG_ENDIAN
);
646 proto_tree_add_item( mic_e_tree
, hf_aprs_sym_code
, tvb
, offset
, 1, ENC_ASCII
);
649 proto_tree_add_item( mic_e_tree
, hf_aprs_sym_id
, tvb
, offset
, 1, ENC_ASCII
);
652 if ( offset
< new_offset
)
654 uint8_t c
= tvb_get_uint8(tvb
, offset
);
655 if ( (c
== ',') || (c
== 0x1d) )
656 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_telemetry
,
657 tvb
, offset
, -1, ENC_NA
);
659 proto_tree_add_item( mic_e_tree
, hf_aprs_mic_e_status
,
660 tvb
, offset
, -1, ENC_ASCII
);
669 dissect_aprs_storm( tvbuff_t
*tvb
,
671 proto_tree
*parent_tree
674 proto_tree
*storm_tree
;
677 tc
= proto_tree_add_item( parent_tree
, hf_aprs_storm
, tvb
, offset
, -1, ENC_ASCII
);
678 storm_tree
= proto_item_add_subtree( tc
, ett_aprs_storm
);
680 proto_tree_add_item( storm_tree
, hf_aprs_storm_dir
, tvb
, offset
, 3, ENC_ASCII
);
683 proto_tree_add_item( storm_tree
, hf_aprs_storm_spd
, tvb
, offset
, 3, ENC_ASCII
);
685 proto_tree_add_item( storm_tree
, hf_aprs_storm_type
, tvb
, offset
, 3, ENC_ASCII
);
687 proto_tree_add_item( storm_tree
, hf_aprs_storm_sws
, tvb
, offset
, 4, ENC_ASCII
);
689 proto_tree_add_item( storm_tree
, hf_aprs_storm_pwg
, tvb
, offset
, 4, ENC_ASCII
);
691 proto_tree_add_item( storm_tree
, hf_aprs_storm_cp
, tvb
, offset
, 5, ENC_ASCII
);
693 proto_tree_add_item( storm_tree
, hf_aprs_storm_rhw
, tvb
, offset
, 4, ENC_ASCII
);
695 proto_tree_add_item( storm_tree
, hf_aprs_storm_rtsw
, tvb
, offset
, 4, ENC_ASCII
);
697 proto_tree_add_item( storm_tree
, hf_aprs_storm_rwg
, tvb
, offset
, 4, ENC_ASCII
);
704 dissect_aprs_weather( wmem_allocator_t
*scope _U_
,
707 proto_tree
*parent_tree
711 proto_tree
*weather_tree
;
717 data_len
= tvb_reported_length_remaining( tvb
, offset
);
718 new_offset
= offset
+ data_len
;
720 tc
= proto_tree_add_item( parent_tree
, hf_aprs_weather
, tvb
, offset
, data_len
, ENC_ASCII
);
721 weather_tree
= proto_item_add_subtree( tc
, ett_aprs_weather
);
723 ch
= tvb_get_uint8( tvb
, offset
);
724 if ( g_ascii_isdigit( ch
) )
726 proto_tree_add_item( weather_tree
, hf_aprs_weather_dir
, tvb
, offset
, 3, ENC_ASCII
);
728 /* verify the separator */
730 proto_tree_add_item( weather_tree
, hf_aprs_weather_spd
, tvb
, offset
, 3, ENC_ASCII
);
736 while ( offset
< new_offset
)
738 ch
= tvb_get_uint8( tvb
, offset
);
742 proto_tree_add_item( weather_tree
, hf_aprs_weather_dir
,
743 tvb
, offset
, 4, ENC_ASCII
);
747 proto_tree_add_item( weather_tree
, hf_aprs_weather_spd
,
748 tvb
, offset
, 4, ENC_ASCII
);
752 proto_tree_add_item( weather_tree
, hf_aprs_weather_peak
,
753 tvb
, offset
, 4, ENC_ASCII
);
757 proto_tree_add_item( weather_tree
, hf_aprs_weather_temp
,
758 tvb
, offset
, 4, ENC_ASCII
);
762 proto_tree_add_item( weather_tree
, hf_aprs_weather_rain_1
,
763 tvb
, offset
, 4, ENC_ASCII
);
767 proto_tree_add_item( weather_tree
, hf_aprs_weather_rain_24
,
768 tvb
, offset
, 4, ENC_ASCII
);
772 proto_tree_add_item( weather_tree
, hf_aprs_weather_rain
,
773 tvb
, offset
, 4, ENC_ASCII
);
777 proto_tree_add_item( weather_tree
, hf_aprs_weather_humidty
,
778 tvb
, offset
, 3, ENC_ASCII
);
782 proto_tree_add_item( weather_tree
, hf_aprs_weather_press
,
783 tvb
, offset
, 6, ENC_ASCII
);
788 proto_tree_add_item( weather_tree
, hf_aprs_weather_luminosity
,
789 tvb
, offset
, 4, ENC_ASCII
);
793 proto_tree_add_item( weather_tree
, hf_aprs_weather_snow
,
794 tvb
, offset
, 4, ENC_ASCII
);
798 proto_tree_add_item( weather_tree
, hf_aprs_weather_raw_rain
,
799 tvb
, offset
, 4, ENC_ASCII
);
804 /* optional: software type/unit: see if present */
805 lr
= new_offset
- offset
;
806 #if 0 /* fcn'al change: defer */
808 * XXX - ASCII or UTF-8?
809 * See http://www.aprs.org/aprs12/utf-8.txt
811 if ( ((lr
< 3) || (lr
> 5)) ||
812 ( lr
!= strspn( tvb_get_string_enc( scope
, tvb
, offset
, lr
, ENC_ASCII
|ENC_NA
), "a-zA-Z0-9-_" ) ) )
814 new_offset
= offset
; /* Assume rest is a comment: force exit from while */
815 break; /* from switch */
818 proto_tree_add_item( weather_tree
, hf_aprs_weather_software
,
819 tvb
, offset
, 1, ENC_ASCII
);
821 proto_tree_add_item( weather_tree
, hf_aprs_weather_unit
,
822 tvb
, offset
, lr
-1, ENC_ASCII
);
828 } /* if (parent_tree) */
833 aprs_timestamp( proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
)
842 ch
= tvb_get_uint8( tvb
, offset
+ 6 );
843 if ( g_ascii_isdigit( ch
) )
845 proto_tree_add_item( aprs_tree
, hf_aprs_mdhm
, tvb
, offset
, data_len
, ENC_ASCII
);
846 proto_tree_add_string( aprs_tree
, hf_aprs_tz
, tvb
, offset
, data_len
, tzone
);
853 proto_tree_add_item( aprs_tree
, hf_aprs_hms
, tvb
, offset
, data_len
, ENC_ASCII
);
854 proto_tree_add_string( aprs_tree
, hf_aprs_tz
, tvb
, offset
, data_len
, tzone
);
860 case 'z' : tzone
= "zulu"; break;
861 case '/' : tzone
= "local"; break;
862 default : tzone
= "unknown"; break;
864 proto_tree_add_item( aprs_tree
, hf_aprs_dhm
, tvb
, offset
, data_len
, ENC_ASCII
);
865 proto_tree_add_string( aprs_tree
, hf_aprs_tz
, tvb
, offset
+ 6, 1, tzone
);
869 return offset
+ data_len
;
873 aprs_latitude_compressed( wmem_allocator_t
*scope
, proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
)
880 info_buffer
= (char *)wmem_alloc( scope
, STRLEN
);
882 temp
= ( tvb_get_uint8( tvb
, offset
+ 0 ) - 33 );
883 temp
= ( tvb_get_uint8( tvb
, offset
+ 1 ) - 33 ) + ( temp
* 91 );
884 temp
= ( tvb_get_uint8( tvb
, offset
+ 2 ) - 33 ) + ( temp
* 91 );
885 temp
= ( tvb_get_uint8( tvb
, offset
+ 3 ) - 33 ) + ( temp
* 91 );
887 snprintf( info_buffer
, STRLEN
, "%6.2f", 90.0 - (temp
/ 380926.0) );
888 proto_tree_add_string( aprs_tree
, hf_aprs_lat
, tvb
, offset
, 4, info_buffer
);
894 aprs_longitude_compressed( wmem_allocator_t
*scope
, proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
)
901 info_buffer
= (char *)wmem_alloc( scope
, STRLEN
);
903 temp
= ( tvb_get_uint8( tvb
, offset
+ 0 ) - 33 );
904 temp
= ( tvb_get_uint8( tvb
, offset
+ 1 ) - 33 ) + ( temp
* 91 );
905 temp
= ( tvb_get_uint8( tvb
, offset
+ 2 ) - 33 ) + ( temp
* 91 );
906 temp
= ( tvb_get_uint8( tvb
, offset
+ 3 ) - 33 ) + ( temp
* 91 );
908 snprintf( info_buffer
, STRLEN
, "%7.2f", (temp
/ 190463.0) - 180.0 );
909 proto_tree_add_string( aprs_tree
, hf_aprs_long
, tvb
, offset
, 4, info_buffer
);
915 aprs_status( proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
)
919 data_len
= tvb_reported_length_remaining( tvb
, offset
);
921 if ( ( data_len
> 7 ) && ( tvb_get_uint8( tvb
, offset
+6 ) == 'z' ) )
923 proto_tree_add_item( aprs_tree
, hf_aprs_dhm
, tvb
, offset
, 6, ENC_ASCII
);
926 proto_tree_add_string( aprs_tree
, hf_aprs_tz
, tvb
, offset
, 1, "zulu" );
930 proto_tree_add_item( aprs_tree
, hf_aprs_status
, tvb
, offset
, data_len
, ENC_ASCII
);
932 return offset
+ data_len
;
936 aprs_item( wmem_allocator_t
*scope
, proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
)
945 * XXX - ASCII or UTF-8?
946 * See http://www.aprs.org/aprs12/utf-8.txt
948 info_buffer
= tvb_get_string_enc( scope
, tvb
, offset
, data_len
, ENC_ASCII
|ENC_NA
);
950 ch_ptr
= strchr( info_buffer
, '!' );
951 if ( ch_ptr
!= NULL
)
953 data_len
= (int)(ch_ptr
- info_buffer
+ 1);
958 ch_ptr
= strchr( info_buffer
, '!' );
959 if ( ch_ptr
!= NULL
)
961 data_len
= (int)(ch_ptr
- info_buffer
+ 1);
965 proto_tree_add_string( aprs_tree
, hf_aprs_item
, tvb
, offset
, data_len
, info_buffer
);
967 return offset
+ data_len
;
971 aprs_3rd_party( proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
, int data_len
)
973 /* If the type of the hf[] entry pointed to by hfindex is FT_BYTES or FT_STRING */
974 /* then data_len == -1 is allowed and means "remainder of the tvbuff" */
975 if ( data_len
== -1 )
977 data_len
= tvb_reported_length_remaining( tvb
, offset
);
978 #if 0 /* fcn'al change: defer */
980 return offset
; /* there's no data */
983 proto_tree_add_item( aprs_tree
, hf_aprs_third_party
, tvb
, offset
, data_len
, ENC_NA
);
986 return offset
+ data_len
;
990 aprs_default_string( proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
, int data_len
, int hfindex
)
992 /* Assumption: hfindex points to an hf[] entry with type FT_STRING; should be validated ? */
993 /* If the type of the hf[] entry pointed to by hfindex is FT_STRING */
994 /* then data_len == -1 is allowed and means "remainder of the tvbuff" */
995 if ( data_len
== -1 )
997 data_len
= tvb_reported_length_remaining( tvb
, offset
);
998 #if 0 /* fcn'al change: defer */
1000 return offset
; /* there's no data */
1003 proto_tree_add_item( aprs_tree
, hfindex
, tvb
, offset
, data_len
, ENC_ASCII
|ENC_NA
);
1004 return offset
+ data_len
;
1008 aprs_default_bytes( proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
, int data_len
, int hfindex
)
1010 /* Assumption: hfindex points to an hf[] entry with type FT_BYTES; should be validated ? */
1011 /* If the type of the hf[] entry pointed to by hfindex is FT_BYTES */
1012 /* then data_len == -1 is allowed and means "remainder of the tvbuff" */
1013 if ( data_len
== -1 )
1015 data_len
= tvb_reported_length_remaining( tvb
, offset
);
1016 #if 0 /* fcn'al change: defer */
1017 if ( data_len
<= 0 )
1018 return offset
; /* there's no data */
1021 proto_tree_add_item( aprs_tree
, hfindex
, tvb
, offset
, data_len
, ENC_NA
);
1022 return offset
+ data_len
;
1026 aprs_position( packet_info
*pinfo
, proto_tree
*aprs_tree
, tvbuff_t
*tvb
, int offset
, bool with_msg
)
1028 uint8_t symbol_table_id
= 0;
1029 uint8_t symbol_code
= 0;
1030 bool probably_a_msg
= false;
1031 bool probably_not_a_msg
= false;
1033 if ( g_ascii_isdigit( tvb_get_uint8( tvb
, offset
) ) )
1035 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 8, hf_aprs_lat
);
1036 symbol_table_id
= tvb_get_uint8( tvb
, offset
);
1037 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 1, hf_aprs_sym_id
);
1038 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 9, hf_aprs_long
);
1039 symbol_code
= tvb_get_uint8( tvb
, offset
);
1040 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 1, hf_aprs_sym_code
);
1041 if ( gPREF_APRS_LAX
)
1043 switch ( tvb_get_uint8( tvb
, offset
) )
1045 case 'D' : probably_a_msg
= true; break;
1046 case 'P' : probably_a_msg
= true; break;
1047 case 'R' : probably_a_msg
= true; break;
1048 case 'T' : probably_a_msg
= true; break;
1049 default : probably_not_a_msg
= true; break;
1052 if ( with_msg
|| probably_a_msg
|| ! probably_not_a_msg
)
1053 offset
= dissect_aprs_msg( tvb
,
1056 ( symbol_code
== '_' ),
1057 ( symbol_table_id
== '/' && symbol_code
== '\\' )
1062 symbol_table_id
= tvb_get_uint8( tvb
, offset
);
1063 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 1, hf_aprs_sym_id
);
1064 offset
= aprs_latitude_compressed( pinfo
->pool
, aprs_tree
, tvb
, offset
);
1065 offset
= aprs_longitude_compressed( pinfo
->pool
, aprs_tree
, tvb
, offset
);
1066 symbol_code
= tvb_get_uint8( tvb
, offset
);
1067 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 1, hf_aprs_sym_code
);
1068 offset
= dissect_aprs_compressed_msg( pinfo
->pool
,
1073 offset
= dissect_aprs_compression_type( tvb
,
1077 if ( symbol_table_id
== '/' && symbol_code
== '\\' )
1078 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 8, hf_aprs_msg_brg
);
1081 if ( symbol_code
== '_' )
1082 offset
= dissect_aprs_weather( pinfo
->pool
,
1087 if ( ( symbol_table_id
== '/' && symbol_code
== '@' ) || ( symbol_table_id
== '\\' && symbol_code
== '@' ) )
1088 offset
= dissect_aprs_storm( tvb
,
1097 dissect_aprs( tvbuff_t
*tvb
, packet_info
*pinfo
, proto_tree
*parent_tree
, void *data _U_
)
1100 proto_tree
*aprs_tree
;
1106 col_set_str( pinfo
->cinfo
, COL_PROTOCOL
, "APRS" );
1107 col_clear( pinfo
->cinfo
, COL_INFO
);
1111 dti
= tvb_get_uint8( tvb
, offset
);
1113 sb
= wmem_strbuf_create(pinfo
->pool
);
1116 wmem_strbuf_append(sb
, val_to_str_ext_const(dti
, &aprs_description_ext
, ""));
1121 /* Position or Ultimeter 2000 WX Station */
1122 if ( tvb_get_uint8( tvb
, offset
+ 1 ) == '!' )
1124 wmem_strbuf_append(sb
, "Ultimeter 2000 WX Station");
1128 /* Position "without APRS messaging" */
1129 wmem_strbuf_append(sb
, "Position (");
1130 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1, 8)); /* Lat */
1131 wmem_strbuf_append(sb
, " ");
1132 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 8 + 1, 9)); /* Long */
1133 wmem_strbuf_append(sb
, " ");
1134 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 8, 1)); /* Symbol table id */
1135 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 8 + 1 + 9, 1)); /* Symbol Code */
1140 /* Position "with APRS messaging" + Ext APRS message */
1141 wmem_strbuf_append(sb
, " (");
1142 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1, 8)); /* Lat */
1143 wmem_strbuf_append(sb
, " ");
1144 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 8 + 1, 9)); /* Long */
1145 wmem_strbuf_append(sb
, " ");
1146 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 8, 1)); /* Symbol table id */
1147 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 8 + 1 + 9, 1)); /* Symbol Code */
1151 /* Position + timestamp "without APRS messaging" */
1152 wmem_strbuf_append(sb
, " (");
1153 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1, 7)); /* Timestamp */
1154 wmem_strbuf_append(sb
, " ");
1155 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7 + 1, 8)); /*??*/ /* Lat */
1156 wmem_strbuf_append(sb
, " ");
1157 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7 + 8 + 1, 9)); /* Long */
1158 wmem_strbuf_append(sb
, " ");
1159 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7, 1)); /* Symbol table id */
1160 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7 + 1 + 9, 1)); /* Symbol Code */
1164 /* Position + timestamp "with APRS messaging" + Ext APRS message */
1165 wmem_strbuf_append(sb
, " (");
1166 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1, 7)); /* Timestamp */
1167 wmem_strbuf_append(sb
, " ");
1168 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7 + 1, 8)); /*??*/ /* Lat */
1169 wmem_strbuf_append(sb
, " ");
1170 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7 + 8 + 1, 9)); /* Long */
1171 wmem_strbuf_append(sb
, " ");
1172 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7, 1)); /* Symbol table id */
1173 wmem_strbuf_append(sb
, tvb_format_text(pinfo
->pool
, tvb
, offset
+ 1 + 7 + 1 + 9, 1)); /* Symbol Code */
1177 col_add_str( pinfo
->cinfo
, COL_INFO
, wmem_strbuf_get_str(sb
) );
1179 /* create display subtree for the protocol */
1180 ti
= proto_tree_add_protocol_format( parent_tree
, proto_aprs
, tvb
, 0, -1, "%s", wmem_strbuf_get_str(sb
) );
1181 aprs_tree
= proto_item_add_subtree( ti
, ett_aprs
);
1183 proto_tree_add_item( aprs_tree
, hf_aprs_dti
, tvb
, offset
, 1, ENC_ASCII
);
1188 case '<' : /* Station Capabilities */
1189 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_station
);
1191 case '>' : /* Status */
1192 offset
= aprs_status( aprs_tree
, tvb
, offset
);
1194 case '?' : /* Query */
1195 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_query
);
1197 case '$' : /* Raw GPS data or Ultimeter 2000 */
1198 if ( tvb_get_uint8( tvb
, offset
) == 'U' )
1199 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_ultimeter_2000
);
1201 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_raw
);
1203 case '%' : /* Agrelo DFJr / MicroFinder */
1204 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_agrelo
);
1206 case 'T' : /* Telemetry data */
1207 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_telemetry
);
1209 case '[' : /* Maidenhead grid locator beacon (obsolete) */
1210 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_maidenhead
);
1212 case '_' : /* Weather Report (without position) */
1213 offset
= aprs_timestamp( aprs_tree
, tvb
, offset
);
1214 offset
= dissect_aprs_weather( pinfo
->pool
,
1220 case ',' : /* Invalid data or test data */
1221 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_invalid_test
);
1223 case '{' : /* User-Defined APRS packet format */
1224 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_user_defined
);
1226 case '}' : /* Third-party traffic */
1227 offset
= aprs_3rd_party( aprs_tree
, tvb
, offset
, -1 );
1229 case ':' : /* Message */
1230 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_message
);
1232 case 0x1c : /* Current Mic-E Data (Rev 0 beta) */
1233 offset
= dissect_mic_e( tvb
,
1237 hf_aprs_mic_e_0_current
1240 case 0x1d : /* Old Mic-E Data (Rev 0 beta) */
1241 offset
= dissect_mic_e( tvb
,
1248 case '\'' : /* Old Mic-E Data (but Current data for TM-D700) */
1249 offset
= dissect_mic_e( tvb
,
1256 case '`' : /* Current Mic-E Data (not used in TM-D700) */
1257 offset
= dissect_mic_e( tvb
,
1261 hf_aprs_mic_e_current
1264 case '#' : /* Peet Bros U-II Weather Station */
1265 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_peet_1
);
1267 case '*' : /* Peet Bros U-II Weather Station */
1268 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_peet_2
);
1270 case '&' : /* [Reserved - Map Feature] */
1271 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_map_feature
);
1273 case '+' : /* [Reserved - Shelter data with time] */
1274 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_shelter_data
);
1276 case '.' : /* [Reserved - Space weather] */
1277 offset
= aprs_default_bytes( aprs_tree
, tvb
, offset
, -1, hf_aprs_space_weather
);
1279 case ')' : /* Item */
1280 offset
= aprs_item( pinfo
->pool
, aprs_tree
, tvb
, offset
);
1281 offset
= aprs_position( pinfo
, aprs_tree
, tvb
, offset
, true );
1282 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_comment
);
1284 case ';' : /* Object */
1285 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, 10, hf_aprs_object
);
1286 offset
= aprs_timestamp( aprs_tree
, tvb
, offset
);
1287 offset
= aprs_position( pinfo
, aprs_tree
, tvb
, offset
, true );
1288 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_comment
);
1290 case '!' : /* Position or Ultimeter 2000 WX Station */
1291 if ( tvb_get_uint8( tvb
, offset
) == '!' )
1292 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_ultimeter_2000
);
1295 offset
= aprs_position( pinfo
, aprs_tree
, tvb
, offset
, false );
1296 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_comment
);
1299 case '=' : /* Position + Ext APRS message */
1300 offset
= aprs_position( pinfo
, aprs_tree
, tvb
, offset
, true );
1301 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_comment
);
1303 case '/' : /* Position + timestamp */
1304 offset
= aprs_timestamp( aprs_tree
, tvb
, offset
);
1305 offset
= aprs_position( pinfo
, aprs_tree
, tvb
, offset
, false );
1306 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_comment
);
1308 case '@' : /* Position + timestamp + Ext APRS message */
1309 offset
= aprs_timestamp( aprs_tree
, tvb
, offset
);
1310 offset
= aprs_position( pinfo
, aprs_tree
, tvb
, offset
, true );
1311 offset
= aprs_default_string( aprs_tree
, tvb
, offset
, -1, hf_aprs_comment
);
1319 proto_register_aprs( void )
1321 module_t
*aprs_module
;
1323 static hf_register_info hf
[] = {
1325 { "Data Type Indicator", "aprs.dti",
1326 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1329 { &hf_aprs_sym_code
,
1330 { "Symbol code", "aprs.sym_code",
1331 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1335 { "Symbol table ID", "aprs.sym_id",
1336 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1342 { &hf_aprs_position
,
1343 { "Position", "aprs.position",
1344 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1349 { "Latitude", "aprs.position.lat",
1350 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1354 { "Longitude", "aprs.position.long",
1355 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1361 { "Comment", "aprs.comment",
1362 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1365 { &hf_ultimeter_2000
,
1366 { "Ultimeter 2000", "aprs.ultimeter_2000",
1367 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1371 { "Status", "aprs.status",
1372 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1376 { "Object", "aprs.object",
1377 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1381 { "Item", "aprs.item",
1382 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1386 { "Query", "aprs.query",
1387 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1390 { &hf_aprs_telemetry
,
1391 { "Telemetry", "aprs.telemetry",
1392 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1396 { "Raw", "aprs.raw",
1397 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1398 "Raw NMEA position report format", HFILL
}
1401 { "Station", "aprs.station",
1402 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1403 "Station capabilities", HFILL
}
1406 { "Message", "aprs.message",
1407 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1411 { "Agrelo", "aprs.agrelo",
1412 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1413 "Agrelo DFJr / MicroFinder", HFILL
}
1415 { &hf_aprs_maidenhead
,
1416 { "Maidenhead", "aprs.maidenhead",
1417 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1418 "Maidenhead grid locator beacon (obsolete)", HFILL
}
1420 { &hf_aprs_invalid_test
,
1421 { "Invalid or test", "aprs.invalid_test",
1422 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1423 "Invalid data or test data", HFILL
}
1425 { &hf_aprs_user_defined
,
1426 { "User-Defined", "aprs.user_defined",
1427 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1428 "User-Defined APRS packet format", HFILL
}
1430 { &hf_aprs_third_party
,
1431 { "Third-party", "aprs.third_party",
1432 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1433 "Third-party traffic", HFILL
}
1436 { "Peet U-II (1)", "aprs.peet_1",
1437 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1438 "Peet Bros U-II Weather Station", HFILL
}
1441 { "Peet U-II (2)", "aprs.peet_2",
1442 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1443 "Peet Bros U-II Weather Station", HFILL
}
1445 { &hf_aprs_map_feature
,
1446 { "Map Feature", "aprs.map_feature",
1447 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1448 "Reserved - Map Feature", HFILL
}
1450 { &hf_aprs_shelter_data
,
1451 { "Shelter data", "aprs.shelter_data",
1452 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1453 "[Reserved - Shelter data with time]", HFILL
}
1455 { &hf_aprs_space_weather
,
1456 { "Space weather", "aprs.space_weather",
1457 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1458 "[Reserved - Space weather]", HFILL
}
1461 { "Storm", "aprs.storm",
1462 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1468 { "Day/Hour/Minute", "aprs.dhm",
1469 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1473 { "Hour/Minute/Second", "aprs.hms",
1474 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1478 { "Month/Day/Hour/Minute", "aprs.mdhm",
1479 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1483 { "Time Zone", "aprs.tz",
1484 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1488 /* Compressed Msg */
1489 { &hf_aprs_compression_type
,
1490 { "Compression type", "aprs.ct",
1491 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1494 { &hf_aprs_ct_gps_fix
,
1495 { "GPS fix type", "aprs.ct.gps_fix",
1496 FT_UINT8
, BASE_HEX
, VALS(gps_vals
), 0x20,
1499 { &hf_aprs_ct_nmea_src
,
1500 { "NMEA source", "aprs.ct.nmea_src",
1501 FT_UINT8
, BASE_HEX
, VALS(nmea_vals
), 0x18,
1504 { &hf_aprs_ct_origin
,
1505 { "Compression origin", "aprs.ct.origin",
1506 FT_UINT8
, BASE_HEX
, VALS(ctype_vals
), 0x07,
1512 { "Extended message", "aprs.msg",
1513 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1517 { "Range", "aprs.msg.rng",
1518 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1519 "Pre-calculated radio range", HFILL
}
1522 { "Course", "aprs.msg.cse",
1523 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1527 { "Speed", "aprs.msg.spd",
1528 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1532 { "Wind direction", "aprs.msg.dir",
1533 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1537 { "Bearing", "aprs.msg.brg",
1538 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1542 { "Number/Range/Quality", "aprs.msg.nrq",
1543 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1548 { &hf_aprs_msg_phg_p
,
1549 { "Power", "aprs.msg.phg.p",
1550 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1553 { &hf_aprs_msg_phg_h
,
1554 { "Height", "aprs.msg.phg.h",
1555 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1558 { &hf_aprs_msg_phg_g
,
1559 { "Gain", "aprs.msg.phg.g",
1560 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1563 { &hf_aprs_msg_phg_d
,
1564 { "Directivity", "aprs.msg.phg.d",
1565 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1570 { &hf_aprs_msg_dfs_s
,
1571 { "Strength", "aprs.msg.dfs.s",
1572 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1575 { &hf_aprs_msg_dfs_h
,
1576 { "Height", "aprs.msg.dfs.h",
1577 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1580 { &hf_aprs_msg_dfs_g
,
1581 { "Gain", "aprs.msg.dfs.g",
1582 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1585 { &hf_aprs_msg_dfs_d
,
1586 { "Directivity", "aprs.msg.dfs.d",
1587 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1592 { &hf_aprs_msg_aod_t
,
1593 { "Type", "aprs.msg.aod.t",
1594 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1597 { &hf_aprs_msg_aod_c
,
1598 { "Colour", "aprs.msg.aod.c",
1599 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1605 { "Weather report", "aprs.weather",
1606 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1609 { &hf_aprs_weather_dir
,
1610 { "Wind direction", "aprs.weather.dir",
1611 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1614 { &hf_aprs_weather_spd
,
1615 { "Wind speed", "aprs.weather.speed",
1616 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1617 "Wind speed (1 minute)", HFILL
}
1619 { &hf_aprs_weather_peak
,
1620 { "Peak wind speed", "aprs.weather.peak",
1621 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1624 { &hf_aprs_weather_temp
,
1625 { "Temperature (F)", "aprs.weather.temp",
1626 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1629 { &hf_aprs_weather_rain_1
,
1630 { "Rain (last 1 hour)", "aprs.weather.1_hour",
1631 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1634 { &hf_aprs_weather_rain_24
,
1635 { "Rain (last 24 hours)", "aprs.weather.24_hour",
1636 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1639 { &hf_aprs_weather_rain
,
1640 { "Rain", "aprs.weather.rain",
1641 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1644 { &hf_aprs_weather_humidty
,
1645 { "Humidity", "aprs.weather.humidity",
1646 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1649 { &hf_aprs_weather_press
,
1650 { "Pressure", "aprs.weather.pressure",
1651 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1654 { &hf_aprs_weather_luminosity
,
1655 { "Luminosity", "aprs.weather.luminosity",
1656 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1659 { &hf_aprs_weather_snow
,
1660 { "Snow", "aprs.weather.snow",
1661 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1664 { &hf_aprs_weather_raw_rain
,
1665 { "Raw rain", "aprs.weather.raw_rain",
1666 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1669 { &hf_aprs_weather_software
,
1670 { "Software", "aprs.weather.software",
1671 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1674 { &hf_aprs_weather_unit
,
1675 { "Unit", "aprs.weather.unit",
1676 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1681 { &hf_aprs_mic_e_0_current
,
1682 { "Current Mic-E (Rev 0)", "aprs.mic_e_0_current",
1683 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1686 { &hf_aprs_mic_e_0_old
,
1687 { "Old Mic-E (Rev 0)", "aprs.mic_e_0_old",
1688 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1691 { &hf_aprs_mic_e_old
,
1692 { "Old Mic-E", "aprs.mic_e_old",
1693 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1694 "Old Mic-E Data (but Current data for TM-D700)", HFILL
}
1696 { &hf_aprs_mic_e_current
,
1697 { "Current Mic-E", "aprs.mic_e_current",
1698 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1699 "Current Mic-E Data (not used in TM-D700)", HFILL
}
1701 { &hf_aprs_mic_e_dst
,
1702 { "Destination Address", "aprs.mic_e.dst",
1703 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1706 { &hf_aprs_mic_e_long_d
,
1707 { "Longitude degrees", "aprs.mic_e.long_d",
1708 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1711 { &hf_aprs_mic_e_long_m
,
1712 { "Longitude minutes", "aprs.mic_e.long_m",
1713 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1716 { &hf_aprs_mic_e_long_h
,
1717 { "Longitude hundredths of minutes", "aprs.mic_e.long_h",
1718 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1721 { &hf_aprs_mic_e_spd_sp
,
1722 { "Speed (hundreds & tens)", "aprs.mic_e.speed_sp",
1723 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1726 { &hf_aprs_mic_e_spd_dc
,
1727 { "Speed (tens), Course (hundreds)", "aprs.mic_e.speed_dc",
1728 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1731 { &hf_aprs_mic_e_spd_se
,
1732 { "Course (tens & units)", "aprs.mic_e.speed_se",
1733 FT_UINT8
, BASE_HEX
, NULL
, 0x0,
1736 { &hf_aprs_mic_e_telemetry
,
1737 { "Telemetry", "aprs.mic_e.telemetry",
1738 FT_BYTES
, BASE_NONE
, NULL
, 0x0,
1741 { &hf_aprs_mic_e_status
,
1742 { "Status", "aprs.mic_e.status",
1743 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1746 { &hf_aprs_storm_dir
,
1747 { "Direction", "aprs.storm.direction",
1748 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1751 { &hf_aprs_storm_spd
,
1752 { "Speed (knots)", "aprs.storm.speed",
1753 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1756 { &hf_aprs_storm_type
,
1757 { "Type", "aprs.storm.type",
1758 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1761 { &hf_aprs_storm_sws
,
1762 { "Sustained wind speed (knots)", "aprs.storm.sws",
1763 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1766 { &hf_aprs_storm_pwg
,
1767 { "Peak wind gusts (knots)", "aprs.storm.pwg",
1768 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1771 { &hf_aprs_storm_cp
,
1772 { "Central pressure (millibars/hPascal)", "aprs.storm.central_pressure",
1773 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1776 { &hf_aprs_storm_rhw
,
1777 { "Radius Hurricane Winds (nautical miles)", "aprs.storm.radius_hurricane_winds",
1778 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1781 { &hf_aprs_storm_rtsw
,
1782 { "Radius Tropical Storm Winds (nautical miles)", "aprs.storm.radius_tropical_storms_winds",
1783 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1786 { &hf_aprs_storm_rwg
,
1787 { "Radius Whole Gale (nautical miles)", "aprs.storm.radius_whole_gale",
1788 FT_STRING
, BASE_NONE
, NULL
, 0x0,
1793 static int *ett
[] = {
1802 proto_aprs
= proto_register_protocol("Automatic Position Reporting System", "APRS", "aprs");
1804 register_dissector( "aprs", dissect_aprs
, proto_aprs
);
1806 proto_register_field_array( proto_aprs
, hf
, array_length(hf
) );
1807 proto_register_subtree_array( ett
, array_length( ett
) );
1809 aprs_module
= prefs_register_protocol( proto_aprs
, NULL
);
1811 prefs_register_bool_preference(aprs_module
, "showaprslax",
1812 "Allow APRS violations.",
1813 "Attempt to display common APRS protocol violations correctly",
1819 * Editor modelines - https://www.wireshark.org/tools/modelines.html
1824 * indent-tabs-mode: t
1827 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
1828 * :indentSize=8:tabSize=8:noTabs=false: