Bug Summary

File:builds/wireshark/wireshark/epan/dissectors/packet-ax25.c
Warning:line 2674, column 5
Value stored to 'off' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name packet-ax25.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -fno-delete-null-pointer-checks -mframe-pointer=all -relaxed-aliasing -fmath-errno -ffp-contract=on -fno-rounding-math -ffloat16-excess-precision=fast -fbfloat16-excess-precision=fast -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/builds/wireshark/wireshark/build -fcoverage-compilation-dir=/builds/wireshark/wireshark/build -resource-dir /usr/lib/llvm-22/lib/clang/22 -isystem /usr/include/glib-2.0 -isystem /usr/lib/x86_64-linux-gnu/glib-2.0/include -isystem /builds/wireshark/wireshark/epan/dissectors -isystem /builds/wireshark/wireshark/build/epan/dissectors -isystem /usr/include/mit-krb5 -isystem /usr/include/libxml2 -isystem /builds/wireshark/wireshark/epan -D CARES_NO_DEPRECATED -D G_DISABLE_DEPRECATED -D G_DISABLE_SINGLE_INCLUDES -D WS_BUILD_DLL -D WS_DEBUG -D WS_DEBUG_UTF_8 -I /builds/wireshark/wireshark/build -I /builds/wireshark/wireshark -I /builds/wireshark/wireshark/include -D _GLIBCXX_ASSERTIONS -internal-isystem /usr/lib/llvm-22/lib/clang/22/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -fmacro-prefix-map=/builds/wireshark/wireshark/= -fmacro-prefix-map=/builds/wireshark/wireshark/build/= -fmacro-prefix-map=../= -Wno-format-nonliteral -std=gnu17 -ferror-limit 19 -fvisibility=hidden -fwrapv -fwrapv-pointer -fstrict-flex-arrays=3 -stack-protector 2 -fstack-clash-protection -fcf-protection=full -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fexceptions -fcolor-diagnostics -analyzer-output=html -faddrsig -fdwarf2-cfi-asm -o /builds/wireshark/wireshark/sbout/2026-11-04-100346-3662-1 -x c /builds/wireshark/wireshark/epan/dissectors/packet-ax25.c
1/* packet-ax25.c
2 *
3 * Routines for Amateur Packet Radio protocol dissection
4 * AX.25 frames
5 * Copyright 2005,2006,2007,2008,2009,2010,2012 R.W. Stearn <richard@rns-stearn.demon.co.uk>
6 *
7 * Wireshark - Network traffic analyzer
8 * By Gerald Combs <gerald@wireshark.org>
9 * Copyright 1998 Gerald Combs
10 *
11 * SPDX-License-Identifier: GPL-2.0-or-later
12 */
13
14/*
15 * This dissector is for:
16 * AX.25 Amateur Packet-Radio Link-Layer Protocol, Version 2.0, October 1984
17 *
18 * At the time of writing the specification could be found here:
19 * http://www.tapr.org/pub_ax25.html
20 *
21 * A newer version, Version 2.2, July 1998, can be found at
22 * http://www.ax25.net/AX25.2.2-Jul%2098-2.pdf
23 *
24 * The link tracking follows the Version 2.2 revision of September 2017
25 * (referred to as "the spec" below; section numbers are from it).
26 *
27 * Inspiration on how to build the dissector drawn from
28 * packet-sdlc.c
29 * packet-x25.c
30 * packet-lapb.c
31 * packet-gprs-llc.c
32 * xdlc.c
33 * with the base file built from README.developers.
34 */
35
36/*
37 * Link tracking
38 * -------------
39 * Every frame belongs to a link, identified by the two station addresses,
40 * the KISS port and the capture interface (see ax25_link_key()). A link is
41 * a conversation; a new conversation starts at each connection attempt.
42 * UI frames are connectionless (section 6.3.7): they are tracked with the
43 * link (digipeated copies, segments), but they don't count as traffic of
44 * the connection and get no ax25.stream index. A stream index is only
45 * allocated when the first other frame shows up.
46 *
47 * State is only updated on the first pass, in frame order. Everything a
48 * later pass needs is copied into a per-packet ax25_pkt_t, so the output
49 * doesn't depend on -2 or on the order frames are dissected in later.
50 * That also means nothing is decided retroactively: a frame is decoded
51 * with what was known when it was first seen.
52 *
53 * The modulo (8 or 128) of I and S frames comes from the link: SABME
54 * followed by a UA in the other direction sets 128, SABM followed by UA
55 * sets 8, from the UA on. If the capture starts mid-session it is
56 * inferred from the first decisive S frame, and assumed to be 8 until
57 * then.
58 */
59
60#include "config.h"
61
62#include <epan/packet.h>
63#include <epan/capture_dissectors.h>
64#include <epan/to_str.h>
65#include <epan/prefs.h>
66#include <epan/tfs.h>
67#include <epan/conversation.h>
68#include <epan/proto_data.h>
69#include <epan/expert.h>
70#include <epan/uat.h>
71#include <epan/unit_strings.h>
72#include <wsutil/strtoi.h>
73#include "packet-ax25.h"
74#include "packet-xdlc.h"
75#include <epan/iana-info.h>
76
77#define STRLEN80 80
78
79#define AX25_HEADER_SIZE15 15 /* length of src_addr + dst_addr + cntl */
80#define AX25_MAX_DIGIS8 8
81
82/* SSID octet: CRRSSSSx (destination/source), HRRSSSSx (repeater) */
83#define AX25_SSID_CR0x80 0x80 /* C bit (dst/src) or H bit (repeater) */
84#define AX25_SSID_SSID0x1E 0x1E /* the SSID itself */
85#define AX25_SSID_EXT0x01 0x01 /* HDLC address extension bit */
86
87/*
88 * Link key values used when the information isn't available. A frame
89 * without a KISS port shares the value with KISS port 0; they can't be
90 * confused, as KISS and other AX.25 encapsulations don't share a capture
91 * interface, and the interface is part of the key.
92 */
93#define AX25_NO_PORT0 0
94#define AX25_NO_INTERFACE0xFFFFFFFFU 0xFFFFFFFFU
95
96/*
97 * Direction of a frame on a link, relative to the canonical order of the
98 * two masked addresses (see ax25_mask_address()).
99 */
100#define AX25_DIR_LO_HI0 0 /* source is the lower address */
101#define AX25_DIR_HI_LO1 1 /* source is the higher address */
102
103/* Bits 4-7 of the first octet of a modulo 128 S frame are always 0 (Figure 4.1b) */
104#define AX25_S128_ZERO_BITS0xF0 0xF0
105
106void proto_register_ax25(void);
107void proto_reg_handoff_ax25(void);
108
109/* Dissector table */
110static dissector_table_t ax25_dissector_table;
111
112static capture_dissector_handle_t ax25_cap_handle;
113
114/* Initialize the protocol and registered fields */
115static int proto_ax25;
116static int hf_ax25_dst;
117static int hf_ax25_src;
118static int hf_ax25_via[ AX25_MAX_DIGIS8 ];
119
120static int hf_ax25_ctl;
121static int hf_ax25_ctl_ext;
122
123static int hf_ax25_n_r;
124static int hf_ax25_n_r_ext;
125static int hf_ax25_n_s;
126static int hf_ax25_n_s_ext;
127
128static int hf_ax25_p;
129static int hf_ax25_f;
130static int hf_ax25_p_ext;
131static int hf_ax25_f_ext;
132static int hf_ax25_pf;
133static int hf_ax25_pf_ext;
134
135static int hf_ax25_ftype_s;
136static int hf_ax25_ftype_s_ext;
137static int hf_ax25_ftype_i;
138static int hf_ax25_ftype_i_ext;
139static int hf_ax25_ftype_su;
140static int hf_ax25_ftype_su_ext;
141
142static int hf_ax25_u_cmd;
143static int hf_ax25_u_resp;
144
145static int hf_ax25_pid;
146
147static int hf_ax25_stream;
148static int hf_ax25_version;
149static int hf_ax25_cr;
150static int hf_ax25_modulo;
151static int hf_ax25_modulo_source;
152static int hf_ax25_modulo_frame;
153static int hf_ax25_link_state;
154static int hf_ax25_link_state_frame;
155static int hf_ax25_link_refused;
156static int hf_ax25_link_fallback;
157static int hf_ax25_link_frmr_xid;
158static int hf_ax25_link_idle;
159static int hf_ax25_dup_of;
160static int hf_ax25_param_version;
161static int hf_ax25_param_version_source;
162static int hf_ax25_param_version_frame;
163static int hf_ax25_param_t1;
164static int hf_ax25_param_t1_source;
165static int hf_ax25_param_t3;
166static int hf_ax25_param_t3_source;
167static int hf_ax25_param_n2;
168static int hf_ax25_param_n2_source;
169static int hf_ax25_param_n1;
170static int hf_ax25_param_n1_source;
171static int hf_ax25_param_k;
172static int hf_ax25_param_k_source;
173static int hf_ax25_param_xid_frame;
174static int hf_ax25_xid;
175static int hf_ax25_xidn_command_frame;
176static int hf_ax25_xidn_duplex;
177static int hf_ax25_xidn_reject;
178static int hf_ax25_xidn_modulo;
179static int hf_ax25_xidn_segmenter;
180static int hf_ax25_xidn_t1;
181static int hf_ax25_xidn_n2;
182static int hf_ax25_xidn_n1;
183static int hf_ax25_xidn_k;
184static int hf_ax25_xidn_kept;
185static int hf_ax25_xidn_v22;
186static int hf_ax25_seg;
187static int hf_ax25_seg_first;
188static int hf_ax25_seg_remaining;
189static int hf_ax25_seg_pid;
190static int hf_ax25_seg_first_frame;
191static int hf_ax25_seg_gap;
192static int hf_ax25_xid_fi;
193static int hf_ax25_xid_gi;
194static int hf_ax25_xid_gl;
195static int hf_ax25_xid_pi;
196static int hf_ax25_xid_pl;
197static int hf_ax25_xid_pv;
198static int hf_ax25_xid_trailing;
199static int hf_ax25_xid_cop;
200static int hf_ax25_xid_hdlc;
201static int hf_ax25_xid_n1_tx;
202static int hf_ax25_xid_n1_rx;
203static int hf_ax25_xid_k_tx;
204static int hf_ax25_xid_k_rx;
205static int hf_ax25_xid_t1;
206static int hf_ax25_xid_n2;
207static int hf_ax25_xid_cop_abm;
208static int hf_ax25_xid_cop_nrm_pri;
209static int hf_ax25_xid_cop_nrm_sec;
210static int hf_ax25_xid_cop_arm_pri;
211static int hf_ax25_xid_cop_arm_sec;
212static int hf_ax25_xid_cop_half;
213static int hf_ax25_xid_cop_full;
214static int hf_ax25_xid_cop_reserved;
215static int hf_ax25_xid_hdlc_reserved0;
216static int hf_ax25_xid_hdlc_rej;
217static int hf_ax25_xid_hdlc_srej;
218static int hf_ax25_xid_hdlc_ui;
219static int hf_ax25_xid_hdlc_sim_rim;
220static int hf_ax25_xid_hdlc_up;
221static int hf_ax25_xid_hdlc_basic_addr;
222static int hf_ax25_xid_hdlc_ext_addr;
223static int hf_ax25_xid_hdlc_del_i_resp;
224static int hf_ax25_xid_hdlc_del_i_cmd;
225static int hf_ax25_xid_hdlc_mod8;
226static int hf_ax25_xid_hdlc_mod128;
227static int hf_ax25_xid_hdlc_rset;
228static int hf_ax25_xid_hdlc_test;
229static int hf_ax25_xid_hdlc_rd;
230static int hf_ax25_xid_hdlc_fcs16;
231static int hf_ax25_xid_hdlc_fcs32;
232static int hf_ax25_xid_hdlc_sync_tx;
233static int hf_ax25_xid_hdlc_ss_tx;
234static int hf_ax25_xid_hdlc_ss_flow;
235static int hf_ax25_xid_hdlc_ss_octet;
236static int hf_ax25_xid_hdlc_srej_multi;
237static int hf_ax25_xid_hdlc_segmenter;
238static int hf_ax25_xid_hdlc_reserved23;
239
240static expert_field ei_ax25_modulo_assumed;
241static expert_field ei_ax25_modulo_inferred;
242static expert_field ei_ax25_modulo_no_ua;
243static expert_field ei_ax25_s128_bits;
244static expert_field ei_ax25_pre20_v22_feature;
245static expert_field ei_ax25_cr_mixed;
246static expert_field ei_ax25_after_disc;
247static expert_field ei_ax25_after_dm;
248static expert_field ei_ax25_after_frmr;
249static expert_field ei_ax25_disconnecting;
250static expert_field ei_ax25_after_idle;
251static expert_field ei_ax25_capture_gap;
252static expert_field ei_ax25_refused;
253static expert_field ei_ax25_fallback;
254static expert_field ei_ax25_frmr_xid;
255static expert_field ei_ax25_dup;
256static expert_field ei_ax25_n1_exceeded;
257static expert_field ei_ax25_xid_rule;
258static expert_field ei_ax25_sabm_xid;
259static expert_field ei_ax25_xid_modulo;
260static expert_field ei_ax25_xid_length;
261static expert_field ei_ax25_seg_not_negotiated;
262static expert_field ei_ax25_seg_neg_not_captured;
263static expert_field ei_ax25_seg_missing_first;
264static expert_field ei_ax25_seg_remaining;
265static expert_field ei_ax25_seg_interleaved;
266static expert_field ei_ax25_seg_too_long;
267static expert_field ei_ax25_seg_tr210;
268
269static const xdlc_cf_items ax25_cf_items = {
270 &hf_ax25_n_r,
271 &hf_ax25_n_s,
272 &hf_ax25_p,
273 &hf_ax25_f,
274 &hf_ax25_ftype_s,
275 &hf_ax25_u_cmd,
276 &hf_ax25_u_resp,
277 &hf_ax25_ftype_i,
278 &hf_ax25_ftype_su
279};
280
281static const xdlc_cf_items ax25_cf_items_ext = {
282 &hf_ax25_n_r_ext,
283 &hf_ax25_n_s_ext,
284 &hf_ax25_p_ext,
285 &hf_ax25_f_ext,
286 &hf_ax25_ftype_s_ext,
287 &hf_ax25_u_cmd,
288 &hf_ax25_u_resp,
289 &hf_ax25_ftype_i_ext,
290 &hf_ax25_ftype_su_ext
291};
292
293static const value_string pid_vals[] = {
294 { AX25_P_ROSE0x01, "Rose" },
295 { AX25_P_RFC1144C0x06, "RFC1144 (compressed)" },
296 { AX25_P_RFC11440x07, "RFC1144 (uncompressed)" },
297 { AX25_P_SEGMENT0x08, "Segment" },
298 { AX25_P_TEXNET0xC3, "Texnet" },
299 { AX25_P_LCP0xC4, "Link Quality protocol" },
300 { AX25_P_ATALK0xCA, "AppleTalk" },
301 { AX25_P_ATALKARP0xCB, "AppleTalk ARP" },
302 { AX25_P_IP0xCC, "IP" },
303 { AX25_P_ARP0xCD, "ARP" },
304 { AX25_P_FLEXNET0xCE, "FlexNet" },
305 { AX25_P_NETROM0xCF, "NetRom" },
306 { AX25_P_NO_L30xF0, "No L3" },
307 { AX25_P_L3_ESC0xFF, "L3 esc" },
308 { 0, NULL((void*)0) }
309};
310
311/* C/R bit interpretation (section 6.1.2, Figure 6.1) */
312typedef enum {
313 AX25_CR_COMMAND,
314 AX25_CR_RESPONSE,
315 AX25_CR_UNKNOWN
316} ax25_cr_e;
317
318static const value_string ax25_cr_vals[] = {
319 { AX25_CR_COMMAND, "Command" },
320 { AX25_CR_RESPONSE, "Response" },
321 { AX25_CR_UNKNOWN, "Unknown" },
322 { 0, NULL((void*)0) }
323};
324
325/* Protocol version, as far as the C/R bits of a single frame tell */
326typedef enum {
327 AX25_VERSION_PRE20, /* both C bits equal */
328 AX25_VERSION_2X /* exactly one C bit set */
329} ax25_version_e;
330
331static const value_string ax25_version_vals[] = {
332 { AX25_VERSION_PRE20, "pre-2.0" },
333 { AX25_VERSION_2X, "2.x" },
334 { 0, NULL((void*)0) }
335};
336
337/* Where the modulo in effect came from */
338typedef enum {
339 AX25_MODSRC_ASSUMED, /* nothing known; using 8 */
340 AX25_MODSRC_INFERRED, /* from an S frame (mid-session start) */
341 AX25_MODSRC_NO_UA, /* from a SABM(E) whose UA wasn't captured */
342 AX25_MODSRC_SABM_UA, /* from a SABM(E) and its UA */
343 AX25_MODSRC_XID /* from an XID response after the UA */
344} ax25_modsrc_e;
345
346static const value_string ax25_modsrc_vals[] = {
347 { AX25_MODSRC_ASSUMED, "Assumed (no SABM(E)/UA or decisive S frame seen yet)" },
348 { AX25_MODSRC_INFERRED, "Inferred from an S frame" },
349 { AX25_MODSRC_NO_UA, "SABM(E), UA not captured" },
350 { AX25_MODSRC_SABM_UA, "SABM(E) and UA" },
351 { AX25_MODSRC_XID, "XID" },
352 { 0, NULL((void*)0) }
353};
354
355/* Short U frame names, for frames whose C/R is unknown */
356static const value_string ax25_u_short_vals[] = {
357 { XDLC_UI0x00, "UI" },
358 { XDLC_SABM0x2C, "SABM" },
359 { XDLC_SABME0x6C, "SABME" },
360 { XDLC_DISC0x40, "DISC" },
361 { XDLC_UA0x60, "UA" },
362 { XDLC_DM0x0C, "DM" },
363 { XDLC_FRMR0x84, "FRMR" },
364 { XDLC_XID0xAC, "XID" },
365 { XDLC_TEST0xE0, "TEST" },
366 { 0, NULL((void*)0) }
367};
368
369static int ett_ax25;
370static int ett_ax25_ctl;
371static int ett_ax25_link;
372static int ett_ax25_params;
373static int ett_ax25_xid;
374static int ett_ax25_xid_param;
375static int ett_ax25_xid_bits;
376static int ett_ax25_seg;
377static int ett_ax25_xidn;
378
379static int * const ax25_xid_cop_fields[] = {
380 &hf_ax25_xid_cop_abm,
381 &hf_ax25_xid_cop_nrm_pri,
382 &hf_ax25_xid_cop_nrm_sec,
383 &hf_ax25_xid_cop_arm_pri,
384 &hf_ax25_xid_cop_arm_sec,
385 &hf_ax25_xid_cop_half,
386 &hf_ax25_xid_cop_full,
387 &hf_ax25_xid_cop_reserved,
388 NULL((void*)0)
389};
390
391static int * const ax25_xid_hdlc_fields[] = {
392 &hf_ax25_xid_hdlc_reserved0,
393 &hf_ax25_xid_hdlc_rej,
394 &hf_ax25_xid_hdlc_srej,
395 &hf_ax25_xid_hdlc_ui,
396 &hf_ax25_xid_hdlc_sim_rim,
397 &hf_ax25_xid_hdlc_up,
398 &hf_ax25_xid_hdlc_basic_addr,
399 &hf_ax25_xid_hdlc_ext_addr,
400 &hf_ax25_xid_hdlc_del_i_resp,
401 &hf_ax25_xid_hdlc_del_i_cmd,
402 &hf_ax25_xid_hdlc_mod8,
403 &hf_ax25_xid_hdlc_mod128,
404 &hf_ax25_xid_hdlc_rset,
405 &hf_ax25_xid_hdlc_test,
406 &hf_ax25_xid_hdlc_rd,
407 &hf_ax25_xid_hdlc_fcs16,
408 &hf_ax25_xid_hdlc_fcs32,
409 &hf_ax25_xid_hdlc_sync_tx,
410 &hf_ax25_xid_hdlc_ss_tx,
411 &hf_ax25_xid_hdlc_ss_flow,
412 &hf_ax25_xid_hdlc_ss_octet,
413 &hf_ax25_xid_hdlc_srej_multi,
414 &hf_ax25_xid_hdlc_segmenter,
415 &hf_ax25_xid_hdlc_reserved23,
416 NULL((void*)0)
417};
418
419
420static dissector_handle_t ax25_handle;
421
422/* Preferences; 0 means "not set" except where noted */
423static unsigned ax25_pref_t3_s = 300; /* T3; the spec gives no default, this is Linux's AX25_DEF_T3 */
424static unsigned ax25_pref_t1_ms;
425static unsigned ax25_pref_n2;
426static unsigned ax25_pref_n1;
427static unsigned ax25_pref_k;
428/*
429 * Spec default for k in modulo 8. The spec disagrees with itself: 7 in
430 * section 6.3.2 (v2.0 defaults) and section 6.7.2.3, 4 in section
431 * 4.3.3.7 (PI 8, which Direwolf follows). 7 until that is settled.
432 */
433static unsigned ax25_pref_k_mod8_default = 7;
434/* TR210, next segment timer; the spec gives no value. 0: N2 x T1 of the sender */
435static unsigned ax25_pref_tr210_s;
436
437/* pinfo->pool key: the AX.25 snapshot, for the segment dissector */
438#define AX25_PROTO_DATA_SEG_PKT0x80000002U 0x80000002U
439
440/* Segment header (section 6.6, Figure 6.2) */
441#define AX25_SEG_FIRST0x80 0x80
442#define AX25_SEG_REMAINING0x7F 0x7F
443
444/* Segment expert infos */
445#define AX25_SEGF_NOT_NEGOTIATED0x0001 0x0001
446#define AX25_SEGF_NEG_NOT_CAPTURED0x0002 0x0002
447#define AX25_SEGF_MISSING_FIRST0x0004 0x0004
448#define AX25_SEGF_BAD_REMAINING0x0008 0x0008
449#define AX25_SEGF_ABANDONED0x0010 0x0010 /* new first segment, previous one incomplete */
450#define AX25_SEGF_INTERLEAVED0x0020 0x0020 /* another frame in the middle of a sequence */
451#define AX25_SEGF_TR2100x0040 0x0040
452#define AX25_SEGF_RETRANSMISSION0x0080 0x0080
453
454/* Spec defaults (section 6.3.2; the same for v2.0 and v2.2 except k) */
455#define AX25_SPEC_T1_MS3000 3000
456#define AX25_SPEC_N210 10
457#define AX25_SPEC_N1256 256
458#define AX25_SPEC_K_MOD12832 32
459
460/*
461 * Per-station overrides (UAT), for parameters the capture doesn't show.
462 */
463#define AX25_UAT_VERSION_NONE0 0
464#define AX25_UAT_VERSION_2020 20
465#define AX25_UAT_VERSION_2222 22
466
467typedef struct _ax25_station_uat {
468 char *callsign; /* CALL or CALL-SSID */
469 uint32_t t1_ms;
470 uint32_t t3_s;
471 uint32_t n2;
472 uint32_t n1;
473 uint32_t k;
474 unsigned version; /* AX25_UAT_VERSION_xxx */
475 uint8_t masked[AX25_ADDR_LEN7]; /* callsign, as ax25_mask_address() makes it */
476} ax25_station_uat_t;
477
478static ax25_station_uat_t *ax25_stations;
479static unsigned ax25_num_stations;
480
481static const value_string ax25_uat_version_vals[] = {
482 { AX25_UAT_VERSION_NONE0, "Unknown" },
483 { AX25_UAT_VERSION_2020, "2.0" },
484 { AX25_UAT_VERSION_2222, "2.2" },
485 { 0, NULL((void*)0) }
486};
487
488/* Where a link parameter value came from, in order of precedence */
489typedef enum {
490 AX25_PSRC_SPEC, /* spec default for the version in effect */
491 AX25_PSRC_PREF, /* global preference */
492 AX25_PSRC_UAT, /* per-station override */
493 AX25_PSRC_XID /* negotiated (or notified) by XID */
494} ax25_psrc_e;
495
496static const value_string ax25_psrc_vals[] = {
497 { AX25_PSRC_SPEC, "spec default" },
498 { AX25_PSRC_PREF, "preference" },
499 { AX25_PSRC_UAT, "station table" },
500 { AX25_PSRC_XID, "XID" },
501 { 0, NULL((void*)0) }
502};
503
504typedef struct _ax25_param {
505 uint32_t value;
506 ax25_psrc_e src;
507 uint32_t frame; /* the XID frame, for AX25_PSRC_XID */
508} ax25_param_t;
509
510/* Version whose defaults apply */
511typedef enum {
512 AX25_VEFF_20,
513 AX25_VEFF_22
514} ax25_veff_e;
515
516typedef enum {
517 AX25_VSRC_DEFAULT, /* no evidence; v2.0 */
518 AX25_VSRC_UAT, /* station table hint */
519 AX25_VSRC_EVIDENCE /* seen in the capture */
520} ax25_vsrc_e;
521
522static const value_string ax25_veff_vals[] = {
523 { AX25_VEFF_20, "2.0" },
524 { AX25_VEFF_22, "2.2" },
525 { 0, NULL((void*)0) }
526};
527
528static const value_string ax25_vsrc_vals[] = {
529 { AX25_VSRC_DEFAULT, "default (nothing seen)" },
530 { AX25_VSRC_UAT, "station table" },
531 { AX25_VSRC_EVIDENCE, "seen" },
532 { 0, NULL((void*)0) }
533};
534
535/* Parameters in effect for a frame, in the direction it was sent */
536typedef struct _ax25_params {
537 ax25_param_t t1_ms; /* acknowledgement timer */
538 ax25_param_t t3_s; /* inactive link timer, of the sender */
539 ax25_param_t n2; /* retries */
540 ax25_param_t n1; /* longest I field the receiver accepts */
541 ax25_param_t k; /* window the receiver accepts */
542 ax25_veff_e version;
543 ax25_vsrc_e version_src;
544 uint32_t version_frame;
545} ax25_params_t;
546
547/*
548 * Contents of an XID information field (ISO 8885 general purpose XID,
549 * parameter negotiation group), as far as AX.25 uses it.
550 */
551#define AX25_XID_FI0x82 0x82
552#define AX25_XID_GI0x80 0x80
553
554#define AX25_XID_PI_COP2 2 /* Classes of Procedures */
555#define AX25_XID_PI_HDLC3 3 /* HDLC Optional Functions */
556#define AX25_XID_PI_N1_TX5 5 /* I field length Tx, bits */
557#define AX25_XID_PI_N1_RX6 6 /* I field length Rx, bits */
558#define AX25_XID_PI_K_TX7 7 /* window size Tx */
559#define AX25_XID_PI_K_RX8 8 /* window size Rx */
560#define AX25_XID_PI_T19 9 /* acknowledge timer, ms */
561#define AX25_XID_PI_N210 10 /* retries (labelled N1 in the spec) */
562
563static const value_string ax25_xid_pi_vals[] = {
564 { AX25_XID_PI_COP2, "Classes of Procedures" },
565 { AX25_XID_PI_HDLC3, "HDLC Optional Functions" },
566 { AX25_XID_PI_N1_TX5, "I Field Length Tx" },
567 { AX25_XID_PI_N1_RX6, "I Field Length Rx" },
568 { AX25_XID_PI_K_TX7, "Window Size Tx" },
569 { AX25_XID_PI_K_RX8, "Window Size Rx" },
570 { AX25_XID_PI_T19, "Acknowledge Timer" },
571 { AX25_XID_PI_N210, "Retries" },
572 { 0, NULL((void*)0) }
573};
574
575/*
576 * Bit fields (PI 2 and 3) are sent least significant octet first, so bit
577 * n of Figure 4.5 is bit n%8 of octet n/8. Numeric fields are big-endian.
578 * The text doesn't say; this is what Figure 4.6 shows for the numeric
579 * fields and what Direwolf (xid.c) does for both. Figure 4.6 itself has
580 * errata in the bit fields: its Classes of Procedures 0x22 0x00 sets bit
581 * 1 (Unbalanced NRM primary) instead of bit 0 (Balanced ABM), and its
582 * HDLC Optional Functions 0x82 0xA8 0x22 sets REJ and SREJ multiframe
583 * (bit 21) while the text says SREJ/REJ; Direwolf's self-test corrects
584 * them to 0x21 0x00 and 0x86 0xA8 0x02. Linux net/ax25 doesn't do XID.
585 */
586#define AX25_COP_ABM0x0001 0x0001
587#define AX25_COP_NRM_PRI0x0002 0x0002
588#define AX25_COP_NRM_SEC0x0004 0x0004
589#define AX25_COP_ARM_PRI0x0008 0x0008
590#define AX25_COP_ARM_SEC0x0010 0x0010
591#define AX25_COP_HALF_DUPLEX0x0020 0x0020
592#define AX25_COP_FULL_DUPLEX0x0040 0x0040
593#define AX25_COP_RESERVED0xFF80 0xFF80
594
595#define AX25_HDLC_BIT(n)(1U << (n)) (1U << (n))
596#define AX25_HDLC_REJ(1U << (1)) AX25_HDLC_BIT(1)(1U << (1))
597#define AX25_HDLC_SREJ(1U << (2)) AX25_HDLC_BIT(2)(1U << (2))
598#define AX25_HDLC_MOD8(1U << (10)) AX25_HDLC_BIT(10)(1U << (10))
599#define AX25_HDLC_MOD128(1U << (11)) AX25_HDLC_BIT(11)(1U << (11))
600#define AX25_HDLC_SREJ_MULTI(1U << (21)) AX25_HDLC_BIT(21)(1U << (21))
601#define AX25_HDLC_SEGMENTER(1U << (22)) AX25_HDLC_BIT(22)(1U << (22))
602
603/* Selective reject levels, lowest first (section 6.3.2 ordering) */
604#define AX25_REJ_NONE0 0
605#define AX25_REJ_REJ1 1
606#define AX25_REJ_SREJ2 2
607
608#define AX25_XID_HAS_DUPLEX0x0001 0x0001
609#define AX25_XID_HAS_REJ0x0002 0x0002
610#define AX25_XID_HAS_MODULO0x0004 0x0004
611#define AX25_XID_HAS_SEGMENTER0x0008 0x0008
612#define AX25_XID_HAS_N1_RX0x0010 0x0010
613#define AX25_XID_HAS_K_RX0x0020 0x0020
614#define AX25_XID_HAS_T10x0040 0x0040
615#define AX25_XID_HAS_N20x0080 0x0080
616/* the parameter was present with PL=0 (or GL=0): its default applies */
617#define AX25_XID_DEF_SHIFT8 8
618
619typedef struct _ax25_xid {
620 bool_Bool valid; /* FI/GI recognized */
621 bool_Bool gl_zero; /* all defaults */
622 unsigned has; /* AX25_XID_HAS_xxx, and << AX25_XID_DEF_SHIFT for defaults */
623 bool_Bool full_duplex; /* highest offered */
624 uint8_t rej; /* highest offered, AX25_REJ_xxx */
625 uint8_t modulo; /* highest offered */
626 bool_Bool segmenter;
627 uint32_t n1_rx; /* octets */
628 uint32_t k_rx;
629 uint32_t t1_ms;
630 uint32_t n2;
631 uint32_t cop; /* PI 2 as received, for showing what was offered */
632 uint32_t hdlc; /* PI 3 as received */
633} ax25_xid_t;
634
635/*
636 * Negotiation as seen in one XID frame, for the tree: what a command
637 * offers, or what a response selects and what results from it. Only
638 * looks back, so a command can't point at the response that answers it:
639 * that would need a second pass and break the output without -2.
640 */
641typedef struct _ax25_xid_neg {
642 bool_Bool response;
643 ax25_xid_t self; /* this frame */
644 uint32_t cmd_frame; /* response: the command it answers (0: not captured) */
645 ax25_xid_t cmd; /* that command */
646 uint8_t modulo_before; /* response: modulo in effect before it */
647 bool_Bool connected; /* the link was connected */
648 ax25_params_t params[2]; /* parameters after this frame, per direction */
649} ax25_xid_neg_t;
650
651/* Things an XID response breaks in the section 6.3.2 negotiation rules */
652#define AX25_XIDCHK_DUPLEX0x01 0x01
653#define AX25_XIDCHK_REJ0x02 0x02
654#define AX25_XIDCHK_MODULO0x04 0x04
655#define AX25_XIDCHK_T10x08 0x08
656#define AX25_XIDCHK_N20x10 0x10
657
658typedef struct _ax25_xid_check {
659 uint32_t cmd_frame;
660 unsigned flags;
661 ax25_xid_t cmd;
662 ax25_xid_t resp;
663} ax25_xid_check_t;
664
665/*
666 * Frame types, classified from the first control octet only. The low two
667 * bits tell I, S and U frames apart in both modulo 8 and modulo 128, the
668 * S frame function is in bits 2-3 in both, and U frames are always one
669 * octet, so this works before the modulo is known.
670 */
671typedef enum {
672 AX25_FT_I,
673 AX25_FT_RR,
674 AX25_FT_RNR,
675 AX25_FT_REJ,
676 AX25_FT_SREJ,
677 AX25_FT_SABM,
678 AX25_FT_SABME,
679 AX25_FT_DISC,
680 AX25_FT_UA,
681 AX25_FT_DM,
682 AX25_FT_FRMR,
683 AX25_FT_UI,
684 AX25_FT_XID,
685 AX25_FT_TEST,
686 AX25_FT_U_OTHER,
687 AX25_FT_NONE /* no frame / nothing recorded */
688} ax25_ftype_e;
689
690static const value_string ax25_ftype_names[] = {
691 { AX25_FT_I, "I" },
692 { AX25_FT_RR, "RR" },
693 { AX25_FT_RNR, "RNR" },
694 { AX25_FT_REJ, "REJ" },
695 { AX25_FT_SREJ, "SREJ" },
696 { AX25_FT_SABM, "SABM" },
697 { AX25_FT_SABME, "SABME" },
698 { AX25_FT_DISC, "DISC" },
699 { AX25_FT_UA, "UA" },
700 { AX25_FT_DM, "DM" },
701 { AX25_FT_FRMR, "FRMR" },
702 { AX25_FT_UI, "UI" },
703 { AX25_FT_XID, "XID" },
704 { AX25_FT_TEST, "TEST" },
705 { AX25_FT_U_OTHER, "U" },
706 { AX25_FT_NONE, "none" },
707 { 0, NULL((void*)0) }
708};
709
710/* Link state (data-link state machine as seen from the channel) */
711typedef enum {
712 AX25_LINK_UNKNOWN,
713 AX25_LINK_CONNECTING, /* SABM(E) sent, not answered */
714 AX25_LINK_CONNECTED,
715 AX25_LINK_DISCONNECTING, /* DISC sent, not answered */
716 AX25_LINK_DISCONNECTED_DISC, /* DISC answered by UA */
717 AX25_LINK_DISCONNECTED_DM, /* DM: refused, or link down */
718 AX25_LINK_FRMR, /* frame reject (pre-2.2 peer) */
719 AX25_LINK_PRESUMED_DOWN /* idle longer than T3 + N2 * T1 */
720} ax25_link_state_e;
721
722static const value_string ax25_link_state_vals[] = {
723 { AX25_LINK_UNKNOWN, "Unknown" },
724 { AX25_LINK_CONNECTING, "Connecting" },
725 { AX25_LINK_CONNECTED, "Connected" },
726 { AX25_LINK_DISCONNECTING, "Disconnecting" },
727 { AX25_LINK_DISCONNECTED_DISC, "Disconnected (DISC/UA)" },
728 { AX25_LINK_DISCONNECTED_DM, "Disconnected (DM)" },
729 { AX25_LINK_FRMR, "Frame rejected (FRMR)" },
730 { AX25_LINK_PRESUMED_DOWN, "Presumed down (idle timeout)" },
731 { 0, NULL((void*)0) }
732};
733
734/* Sequence expert infos, one per frame at most */
735typedef enum {
736 AX25_SEQ_NONE,
737 AX25_SEQ_AFTER_DISC,
738 AX25_SEQ_AFTER_DM,
739 AX25_SEQ_AFTER_FRMR,
740 AX25_SEQ_DISCONNECTING,
741 AX25_SEQ_AFTER_IDLE,
742 AX25_SEQ_CAPTURE_GAP
743} ax25_seq_expert_e;
744
745/* C/R encodings seen in one direction */
746#define AX25_ENC_NONE0 0
747#define AX25_ENC_PRE201 1
748#define AX25_ENC_2X2 2
749
750/*
751 * Per-packet snapshot, computed on the first pass and attached to the
752 * frame (file scope, keyed by layer number). Later passes, and frames
753 * dissected out of order, only read it.
754 */
755typedef struct _ax25_pkt {
756 bool_Bool has_stream; /* false for UI frames */
757 uint32_t stream;
758 uint8_t dir;
759
760 uint8_t modulo;
761 ax25_modsrc_e modulo_src;
762 uint32_t modulo_frame;
763
764 uint32_t pre20_frame; /* a pre-2.0 frame was seen on the link before (or at) this one */
765 uint32_t cr_mixed_frame; /* previous frame in this direction used the other C/R encoding */
766
767 ax25_link_state_e state; /* link state after this frame */
768 ax25_seq_expert_e seq_expert;
769 uint32_t seq_frame; /* frame that caused the state seq_expert is about */
770 ax25_ftype_e seq_ftype; /* its type */
771 nstime_t idle_gap; /* for AX25_SEQ_AFTER_IDLE / AX25_SEQ_CAPTURE_GAP */
772 double idle_limit_s;
773
774 uint32_t refused_frame; /* this DM/FRMR refuses the SABM(E) in that frame */
775 uint32_t frmr_xid_frame; /* this FRMR answers the XID command in that frame */
776 uint32_t fallback_frame; /* this SABM retries after the DM/FRMR to SABME in that frame */
777 uint32_t dup_of; /* this is a digipeated copy of that frame */
778
779 ax25_params_t params; /* in effect for this frame's direction */
780 ax25_xid_check_t *xid_check; /* XID response breaking the negotiation rules */
781 uint32_t sabm_xid_frame; /* SABM(E) disagrees with the modulo the XID in that frame negotiated */
782 uint8_t sabm_xid_modulo;
783 uint8_t xid_modulo_prev; /* this XID changed the modulo from that (0 = no change) */
784 ax25_xid_neg_t *xid_neg; /* XID frames: negotiation details for the tree */
785
786 /* Segmenter analysis */
787 unsigned seg_flags; /* AX25_SEGF_xxx */
788 uint32_t seg_first_frame; /* first segment of the sequence this frame is in (or breaks) */
789 uint8_t seg_expected; /* remaining count expected, for AX25_SEGF_BAD_REMAINING */
790 uint32_t seg_xid_frame; /* XID response that didn't negotiate the segmenter */
791 nstime_t seg_gap; /* for AX25_SEGF_TR210 */
792 double seg_tr210_s;
793} ax25_pkt_t;
794
795/* Recent frames on a link, to recognize digipeated copies */
796#define AX25_DUP_HISTORY8 8
797
798typedef struct _ax25_hist {
799 uint32_t frame;
800 nstime_t ts;
801 unsigned reported_len;
802 unsigned len; /* captured octets in data */
803 uint8_t hbits; /* H bit of each digipeater, bit n = digipeater n+1 */
804 uint8_t *data; /* the frame with the H bits cleared */
805 ax25_pkt_t *pkt;
806} ax25_hist_t;
807
808/*
809 * Per-link state, kept in the conversation and only touched on the first
810 * pass. Everything a later pass needs is copied into ax25_pkt_t.
811 */
812typedef struct _ax25_conv {
813 bool_Bool has_stream; /* stream allocated (a frame other than UI was seen) */
814 uint32_t stream; /* ax25.stream */
815 uint32_t nframes; /* frames other than UI seen so far on this stream */
816
817 ax25_link_state_e state;
818 uint32_t state_frame; /* frame that caused the state */
819 ax25_ftype_e state_ftype; /* its type */
820
821 /* AX25_LINK_CONNECTING */
822 uint8_t connect_dir;
823 ax25_ftype_e connect_type; /* SABM or SABME */
824 uint32_t connect_frame;
825 /* AX25_LINK_DISCONNECTING */
826 uint8_t disc_dir;
827 /* A DM or FRMR answered a SABME: a SABM from the same side may follow
828 * (v2.2 -> v2.0 fallback, section 4.3.3.2) */
829 bool_Bool fallback_pending;
830 uint8_t fallback_dir;
831 uint32_t fallback_frame;
832
833 /* Last command each side sent, to pair responses with */
834 ax25_ftype_e last_cmd[2];
835 uint32_t last_cmd_frame[2];
836
837 /* Sequence numbers last seen from each side */
838 uint8_t last_ns[2];
839 uint8_t last_nr[2];
840 bool_Bool ns_valid[2];
841 bool_Bool nr_valid[2];
842
843 /* Last frame on the link, either direction */
844 uint32_t last_frame;
845 nstime_t last_ts;
846 /* AX25_LINK_PRESUMED_DOWN: the silence that caused it */
847 nstime_t idle_gap;
848 double idle_limit_s;
849
850 /* Modulo in effect for I and S frames */
851 uint8_t modulo; /* 8 or 128 */
852 ax25_modsrc_e modulo_src;
853 uint32_t modulo_frame; /* frame that set it, 0 if assumed */
854
855 /* Version evidence */
856 uint32_t pre20_frame; /* first pre-2.0 frame on the link, 0 if none */
857 uint8_t last_enc[2]; /* AX25_ENC_xxx of the last frame, per direction */
858 uint32_t last_enc_frame[2];
859
860 ax25_hist_t hist[AX25_DUP_HISTORY8];
861 unsigned hist_next;
862
863 /* The station sending in each direction, and its station table entry */
864 uint8_t addr[2][AX25_ADDR_LEN7];
865 bool_Bool has_uat[2];
866 ax25_station_uat_t uat[2]; /* copy; callsign not kept */
867
868 /* Version evidence: latest frame pointing at each version */
869 uint32_t v20_frame;
870 uint32_t v22_frame;
871 /* Last frame that was about the connection itself (not XID/UI/TEST) */
872 uint32_t conn_activity_frame;
873
874 /* XID: last command from each side, for checking the response */
875 bool_Bool xid_cmd_valid[2];
876 uint32_t xid_cmd_frame[2];
877 ax25_xid_t xid_cmd[2];
878 /* XID: negotiated (from the response) for the whole link... */
879 uint32_t xid_neg_frame; /* 0 = no XID response seen */
880 uint32_t xid_t1_frame; /* PI 9 */
881 bool_Bool xid_t1_default;
882 uint32_t xid_t1_ms;
883 uint32_t xid_n2_frame; /* PI 10 */
884 bool_Bool xid_n2_default;
885 uint32_t xid_n2;
886 uint8_t xid_modulo; /* 0 = not negotiated */
887 bool_Bool xid_segmenter_known;
888 bool_Bool xid_segmenter;
889 /* ...and notified by each station about what it can receive */
890 uint32_t xid_n1_frame[2]; /* PI 6 */
891 bool_Bool xid_n1_default[2];
892 uint32_t xid_n1[2]; /* octets */
893 uint32_t xid_k_frame[2]; /* PI 8 */
894 bool_Bool xid_k_default[2];
895 uint32_t xid_k[2];
896
897 /* Segmenter: sequence in progress from each side */
898 bool_Bool seg_active[2];
899 bool_Bool seg_over_ui[2];
900 uint8_t seg_remaining[2];
901 uint32_t seg_first_frame[2];
902 nstime_t seg_last_ts[2];
903 bool_Bool seg_last_ns_valid[2];
904 uint8_t seg_last_ns[2];
905 /*
906 * TODO: these sequences are what reassembly of segmented data
907 * units (section 6.6) would work from.
908 */
909
910 /*
911 * TODO: the N(S)/N(R) tracking here would also support
912 * retransmission and window analysis (k), and the conversation
913 * could feed conversation/endpoint tables and Follow Stream.
914 */
915} ax25_conv_t;
916
917/* What the first pass needs to know about the frame being dissected */
918typedef struct _ax25_frame {
919 tvbuff_t *tvb;
920 int ctl_offset;
921 uint8_t dir;
922 ax25_ftype_e ftype;
923 ax25_cr_e cr;
924 ax25_version_e version;
925 uint8_t c0; /* first control octet */
926 int ctl_remaining; /* octets from the control field to the end */
927 unsigned ndigis;
928 int digi_ssid_offset[AX25_MAX_DIGIS8];
929 uint8_t hbits;
930} ax25_frame_t;
931
932static uint32_t ax25_stream_count;
933
934static void ax25_set_modulo(ax25_conv_t *conv, uint8_t modulo, ax25_modsrc_e src, uint32_t frame);
935
936static ax25_ftype_e
937ax25_classify_control(uint8_t c0)
938{
939 if ((c0 & XDLC_I_MASK0x01) == XDLC_I0x00)
940 return AX25_FT_I;
941
942 if ((c0 & XDLC_S_U_MASK0x03) == XDLC_S0x01) {
943 switch (c0 & XDLC_S_FTYPE_MASK0x0C) {
944 case XDLC_RR0x00: return AX25_FT_RR;
945 case XDLC_RNR0x04: return AX25_FT_RNR;
946 case XDLC_REJ0x08: return AX25_FT_REJ;
947 default: return AX25_FT_SREJ;
948 }
949 }
950
951 switch (c0 & XDLC_U_MODIFIER_MASK0xEC) {
952 case XDLC_SABM0x2C: return AX25_FT_SABM;
953 case XDLC_SABME0x6C: return AX25_FT_SABME;
954 case XDLC_DISC0x40: return AX25_FT_DISC;
955 case XDLC_UA0x60: return AX25_FT_UA;
956 case XDLC_DM0x0C: return AX25_FT_DM;
957 case XDLC_FRMR0x84: return AX25_FT_FRMR;
958 case XDLC_UI0x00: return AX25_FT_UI;
959 case XDLC_XID0xAC: return AX25_FT_XID;
960 case XDLC_TEST0xE0: return AX25_FT_TEST;
961 default: return AX25_FT_U_OTHER;
962 }
963}
964
965static bool_Bool
966ax25_ftype_is_sabm(ax25_ftype_e ft)
967{
968 return ft == AX25_FT_SABM || ft == AX25_FT_SABME;
969}
970
971static bool_Bool
972ax25_ftype_is_s(ax25_ftype_e ft)
973{
974 return ft == AX25_FT_RR || ft == AX25_FT_RNR || ft == AX25_FT_REJ || ft == AX25_FT_SREJ;
975}
976
977/* I and S frames are the ones whose control field depends on the modulo */
978static bool_Bool
979ax25_ftype_is_numbered(ax25_ftype_e ft)
980{
981 return ft == AX25_FT_I || ax25_ftype_is_s(ft);
982}
983
984/*
985 * Pre-2.0 stations set both C bits the same way, so the bits say nothing
986 * about command or response. Use what the frame type implies (Figure 4.4
987 * for U frames; I frames are always commands). S frames, XID and TEST can
988 * be either.
989 */
990static ax25_cr_e
991ax25_pre20_cr(ax25_ftype_e ft)
992{
993 switch (ft) {
994 case AX25_FT_I:
995 case AX25_FT_UI:
996 case AX25_FT_SABM:
997 case AX25_FT_SABME:
998 case AX25_FT_DISC:
999 return AX25_CR_COMMAND;
1000 case AX25_FT_UA:
1001 case AX25_FT_DM:
1002 case AX25_FT_FRMR:
1003 return AX25_CR_RESPONSE;
1004 default:
1005 return AX25_CR_UNKNOWN;
1006 }
1007}
1008
1009/*
1010 * Reduce an address subfield to what identifies a station: the six
1011 * callsign octets and the SSID. The C/R (or H) bit, the two reserved
1012 * bits and the extension bit are dropped.
1013 */
1014static void
1015ax25_mask_address(tvbuff_t *tvb, int offset, uint8_t *masked)
1016{
1017 int i;
1018
1019 for (i = 0; i < AX25_ADDR_LEN7 - 1; i++)
1020 masked[i] = tvb_get_uint8(tvb, offset + i) & 0xFE;
1021 masked[AX25_ADDR_LEN7 - 1] = tvb_get_uint8(tvb, offset + AX25_ADDR_LEN7 - 1) & AX25_SSID_SSID0x1E;
1022}
1023
1024/*
1025 * Build the link key in pinfo->pool: the two masked addresses in canonical
1026 * order (lower first), each followed by the KISS port, then the capture
1027 * interface. That is the address/port/address/port layout other code
1028 * expects (e.g. conversation_key_addr2(), used by Lua's tostring() of a
1029 * conversation). Absent values use AX25_NO_PORT / AX25_NO_INTERFACE so
1030 * every key has the same shape. The digipeater path is deliberately not
1031 * part of the key: a link keeps its identity if the path changes, and
1032 * frames heard both before and after a digipeater belong to the same link.
1033 */
1034#define AX25_KEY_ADDR_LO0 0
1035#define AX25_KEY_ADDR_HI2 2
1036
1037static conversation_element_t *
1038ax25_link_key(packet_info *pinfo, const uint8_t *lo, const uint8_t *hi,
1039 uint32_t port, uint32_t iface)
1040{
1041 conversation_element_t *key = wmem_alloc0_array(pinfo->pool, conversation_element_t, 6)((conversation_element_t*)wmem_alloc0((pinfo->pool), (((((
6)) <= 0) || ((size_t)sizeof(conversation_element_t) > (
9223372036854775807L / (size_t)((6))))) ? 0 : (sizeof(conversation_element_t
) * ((6))))))
;
1042
1043 key[AX25_KEY_ADDR_LO0].type = CE_ADDRESS;
1044 set_address(&key[AX25_KEY_ADDR_LO0].addr_val, AT_AX25, AX25_ADDR_LEN7, lo);
1045 key[1].type = CE_PORT;
1046 key[1].port_val = port;
1047 key[AX25_KEY_ADDR_HI2].type = CE_ADDRESS;
1048 set_address(&key[AX25_KEY_ADDR_HI2].addr_val, AT_AX25, AX25_ADDR_LEN7, hi);
1049 key[3].type = CE_PORT;
1050 key[3].port_val = port;
1051 key[4].type = CE_UINT;
1052 key[4].uint_val = iface;
1053 key[5].type = CE_CONVERSATION_TYPE;
1054 key[5].conversation_type_val = CONVERSATION_AX25;
1055
1056 return key;
1057}
1058
1059/*
1060 * Version whose defaults apply: what the capture showed last (SABME/UA
1061 * or an XID response for 2.2; a pre-2.0 frame, SABM/UA, FRMR to XID or
1062 * a fallback to SABM for 2.0), else the station table's hint (the lower
1063 * of the two), else 2.0.
1064 */
1065static void
1066ax25_version_in_effect(const ax25_conv_t *conv, ax25_params_t *p)
1067{
1068 uint8_t d;
1069 unsigned hint = AX25_UAT_VERSION_NONE0;
1070
1071 if (conv->v20_frame || conv->v22_frame) {
1072 p->version_src = AX25_VSRC_EVIDENCE;
1073 if (conv->v22_frame > conv->v20_frame) {
1074 p->version = AX25_VEFF_22;
1075 p->version_frame = conv->v22_frame;
1076 } else {
1077 p->version = AX25_VEFF_20;
1078 p->version_frame = conv->v20_frame;
1079 }
1080 return;
1081 }
1082 for (d = 0; d < 2; d++) {
1083 if (conv->has_uat[d] && conv->uat[d].version != AX25_UAT_VERSION_NONE0 &&
1084 (hint == AX25_UAT_VERSION_NONE0 || conv->uat[d].version < hint))
1085 hint = conv->uat[d].version;
1086 }
1087 p->version_frame = 0;
1088 if (hint != AX25_UAT_VERSION_NONE0) {
1089 p->version_src = AX25_VSRC_UAT;
1090 p->version = (hint == AX25_UAT_VERSION_2222) ? AX25_VEFF_22 : AX25_VEFF_20;
1091 } else {
1092 p->version_src = AX25_VSRC_DEFAULT;
1093 p->version = AX25_VEFF_20;
1094 }
1095}
1096
1097/*
1098 * One parameter, in order of precedence: XID, station table, preference,
1099 * spec default. 0 means "not set" in the station table and preferences.
1100 */
1101static void
1102ax25_resolve_param(ax25_param_t *out, uint32_t xid_frame, bool_Bool xid_default, uint32_t xid_value,
1103 bool_Bool has_uat, uint32_t uat_value, unsigned pref_value, uint32_t spec_value)
1104{
1105 out->frame = 0;
1106 if (xid_frame) {
1107 out->src = AX25_PSRC_XID;
1108 out->frame = xid_frame;
1109 out->value = xid_default ? spec_value : xid_value;
1110 } else if (has_uat && uat_value) {
1111 out->src = AX25_PSRC_UAT;
1112 out->value = uat_value;
1113 } else if (pref_value) {
1114 out->src = AX25_PSRC_PREF;
1115 out->value = pref_value;
1116 } else {
1117 out->src = AX25_PSRC_SPEC;
1118 out->value = spec_value;
1119 }
1120}
1121
1122/*
1123 * Parameters for frames sent in direction dir. T1, N2 and T3 are the
1124 * sender's (T1 and N2 are negotiated for the whole link); N1 and k are
1125 * what the receiver notified it can take (section 6.3.2). The k default
1126 * follows the modulo in effect rather than the version: a v2.2 station
1127 * connected with SABM runs modulo 8.
1128 */
1129static void
1130ax25_resolve_params(const ax25_conv_t *conv, uint8_t dir, ax25_params_t *p)
1131{
1132 uint8_t rx = !dir;
1133
1134 ax25_version_in_effect(conv, p);
1135 ax25_resolve_param(&p->t1_ms, conv->xid_t1_frame, conv->xid_t1_default, conv->xid_t1_ms,
1136 conv->has_uat[dir], conv->uat[dir].t1_ms, ax25_pref_t1_ms, AX25_SPEC_T1_MS3000);
1137 ax25_resolve_param(&p->n2, conv->xid_n2_frame, conv->xid_n2_default, conv->xid_n2,
1138 conv->has_uat[dir], conv->uat[dir].n2, ax25_pref_n2, AX25_SPEC_N210);
1139 /* T3 isn't negotiated and has no spec default; the preference always applies */
1140 ax25_resolve_param(&p->t3_s, 0, false0, 0,
1141 conv->has_uat[dir], conv->uat[dir].t3_s, ax25_pref_t3_s, 0);
1142 ax25_resolve_param(&p->n1, conv->xid_n1_frame[rx], conv->xid_n1_default[rx], conv->xid_n1[rx],
1143 conv->has_uat[rx], conv->uat[rx].n1, ax25_pref_n1, AX25_SPEC_N1256);
1144 ax25_resolve_param(&p->k, conv->xid_k_frame[rx], conv->xid_k_default[rx], conv->xid_k[rx],
1145 conv->has_uat[rx], conv->uat[rx].k, ax25_pref_k,
1146 conv->modulo == 128 ? AX25_SPEC_K_MOD12832 : ax25_pref_k_mod8_default);
1147}
1148
1149static double
1150ax25_param_t1_s(const ax25_conv_t *conv, uint8_t dir)
1151{
1152 ax25_params_t p;
1153
1154 ax25_resolve_params(conv, dir, &p);
1155 return p.t1_ms.value / 1000.0;
1156}
1157
1158static unsigned
1159ax25_param_n2(const ax25_conv_t *conv, uint8_t dir)
1160{
1161 ax25_params_t p;
1162
1163 ax25_resolve_params(conv, dir, &p);
1164 return p.n2.value;
1165}
1166
1167/* 0 disables the idle timeout */
1168static double
1169ax25_param_t3_s(const ax25_conv_t *conv, uint8_t dir)
1170{
1171 ax25_params_t p;
1172
1173 ax25_resolve_params(conv, dir, &p);
1174 return (double)p.t3_s.value;
1175}
1176
1177/* Station table lookup by masked address */
1178static const ax25_station_uat_t *
1179ax25_find_station(const uint8_t *masked)
1180{
1181 unsigned i;
1182
1183 for (i = 0; i < ax25_num_stations; i++) {
1184 if (memcmp(ax25_stations[i].masked, masked, AX25_ADDR_LEN7) == 0)
1185 return &ax25_stations[i];
1186 }
1187 return NULL((void*)0);
1188}
1189
1190/* XID integers: bit fields least significant octet first, numbers big-endian */
1191static uint32_t
1192ax25_xid_le(const uint8_t *pv, unsigned pl)
1193{
1194 uint32_t v = 0;
1195 unsigned i;
1196
1197 for (i = 0; i < pl && i < 4; i++)
1198 v |= (uint32_t)pv[i] << (8 * i);
1199 return v;
1200}
1201
1202static uint32_t
1203ax25_xid_be(const uint8_t *pv, unsigned pl)
1204{
1205 uint32_t v = 0;
1206 unsigned i;
1207
1208 for (i = 0; i < pl && i < 4; i++)
1209 v = (v << 8) | pv[i];
1210 return v;
1211}
1212
1213static uint8_t
1214ax25_xid_rej_level(uint32_t hdlc, bool_Bool highest)
1215{
1216 bool_Bool srej = (hdlc & (AX25_HDLC_SREJ(1U << (2)) | AX25_HDLC_SREJ_MULTI(1U << (21)))) != 0;
1217 bool_Bool rej = (hdlc & AX25_HDLC_REJ(1U << (1))) != 0;
1218
1219 if (highest)
1220 return srej ? AX25_REJ_SREJ2 : (rej ? AX25_REJ_REJ1 : AX25_REJ_NONE0);
1221 return rej ? AX25_REJ_REJ1 : (srej ? AX25_REJ_SREJ2 : AX25_REJ_NONE0);
1222}
1223
1224/*
1225 * Parse an XID information field (first pass; never throws). A command
1226 * offers a menu, so "highest" picks the best it offers; a response should
1227 * select one, and if it doesn't the lesser is taken.
1228 */
1229static void
1230ax25_parse_xid(tvbuff_t *tvb, int offset, bool_Bool highest, ax25_xid_t *x)
1231{
1232 const uint8_t *data;
1233 unsigned len, end, off, pl;
1234 uint8_t pi;
1235 uint32_t v;
1236
1237 memset(x, 0, sizeof *x);
1238 len = tvb_captured_length_remaining(tvb, offset);
1239 if (len < 4)
1240 return;
1241 data = tvb_get_ptr(tvb, offset, len);
1242 if (data[0] != AX25_XID_FI0x82 || data[1] != AX25_XID_GI0x80)
1243 return;
1244 x->valid = true1;
1245 v = ((unsigned)data[2] << 8) | data[3];
1246 if (v == 0) {
1247 /* "all parameters assume their default values" */
1248 x->gl_zero = true1;
1249 x->has = (AX25_XID_HAS_DUPLEX0x0001 | AX25_XID_HAS_REJ0x0002 | AX25_XID_HAS_MODULO0x0004 |
1250 AX25_XID_HAS_SEGMENTER0x0008 | AX25_XID_HAS_N1_RX0x0010 | AX25_XID_HAS_K_RX0x0020 |
1251 AX25_XID_HAS_T10x0040 | AX25_XID_HAS_N20x0080) << AX25_XID_DEF_SHIFT8;
1252 return;
1253 }
1254 end = MIN(len, 4 + v)(((len) < (4 + v)) ? (len) : (4 + v));
1255 off = 4;
1256 while (off + 2 <= end) {
1257 pi = data[off];
1258 pl = data[off + 1];
1259 off += 2;
1260 if (off + pl > end)
1261 break;
1262 switch (pi) {
1263 case AX25_XID_PI_COP2:
1264 if (pl == 0) {
1265 x->has |= AX25_XID_HAS_DUPLEX0x0001 << AX25_XID_DEF_SHIFT8;
1266 break;
1267 }
1268 v = ax25_xid_le(&data[off], pl);
1269 x->cop = v;
1270 x->has |= AX25_XID_HAS_DUPLEX0x0001;
1271 x->full_duplex = (v & AX25_COP_FULL_DUPLEX0x0040) &&
1272 (highest || !(v & AX25_COP_HALF_DUPLEX0x0020));
1273 break;
1274 case AX25_XID_PI_HDLC3:
1275 if (pl == 0) {
1276 x->has |= (AX25_XID_HAS_REJ0x0002 | AX25_XID_HAS_MODULO0x0004 | AX25_XID_HAS_SEGMENTER0x0008)
1277 << AX25_XID_DEF_SHIFT8;
1278 break;
1279 }
1280 v = ax25_xid_le(&data[off], pl);
1281 x->hdlc = v;
1282 x->rej = ax25_xid_rej_level(v, highest);
1283 if (x->rej != AX25_REJ_NONE0)
1284 x->has |= AX25_XID_HAS_REJ0x0002;
1285 if (v & (AX25_HDLC_MOD8(1U << (10)) | AX25_HDLC_MOD128(1U << (11)))) {
1286 x->has |= AX25_XID_HAS_MODULO0x0004;
1287 if ((v & AX25_HDLC_MOD128(1U << (11))) && (highest || !(v & AX25_HDLC_MOD8(1U << (10)))))
1288 x->modulo = 128;
1289 else
1290 x->modulo = 8;
1291 }
1292 x->has |= AX25_XID_HAS_SEGMENTER0x0008;
1293 x->segmenter = (v & AX25_HDLC_SEGMENTER(1U << (22))) != 0;
1294 break;
1295 case AX25_XID_PI_N1_RX6:
1296 if (pl == 0) {
1297 x->has |= AX25_XID_HAS_N1_RX0x0010 << AX25_XID_DEF_SHIFT8;
1298 break;
1299 }
1300 x->has |= AX25_XID_HAS_N1_RX0x0010;
1301 x->n1_rx = ax25_xid_be(&data[off], pl) / 8;
1302 break;
1303 case AX25_XID_PI_K_RX8:
1304 if (pl == 0) {
1305 x->has |= AX25_XID_HAS_K_RX0x0020 << AX25_XID_DEF_SHIFT8;
1306 break;
1307 }
1308 x->has |= AX25_XID_HAS_K_RX0x0020;
1309 x->k_rx = ax25_xid_be(&data[off], pl);
1310 break;
1311 case AX25_XID_PI_T19:
1312 if (pl == 0) {
1313 x->has |= AX25_XID_HAS_T10x0040 << AX25_XID_DEF_SHIFT8;
1314 break;
1315 }
1316 x->has |= AX25_XID_HAS_T10x0040;
1317 x->t1_ms = ax25_xid_be(&data[off], pl);
1318 break;
1319 case AX25_XID_PI_N210:
1320 if (pl == 0) {
1321 x->has |= AX25_XID_HAS_N20x0080 << AX25_XID_DEF_SHIFT8;
1322 break;
1323 }
1324 x->has |= AX25_XID_HAS_N20x0080;
1325 x->n2 = ax25_xid_be(&data[off], pl);
1326 break;
1327 default:
1328 /* "A parameter field containing an unrecognized PI is ignored" */
1329 break;
1330 }
1331 off += pl;
1332 }
1333}
1334
1335/* Has the XID got the parameter, or a default for it? */
1336static bool_Bool
1337ax25_xid_has(const ax25_xid_t *x, unsigned flag, bool_Bool *is_default)
1338{
1339 *is_default = (x->has & (flag << AX25_XID_DEF_SHIFT8)) != 0;
1340 return (x->has & flag) || *is_default;
1341}
1342
1343/*
1344 * What an XID command or response from direction d tells us. Each side
1345 * notifies what it can receive (N1 Rx, k Rx) in both; the response sets
1346 * the negotiated values for the link (section 6.3.2). An omitted PI keeps
1347 * the current value.
1348 */
1349static void
1350ax25_apply_xid_notifications(ax25_conv_t *conv, uint8_t d, const ax25_xid_t *x, uint32_t frame)
1351{
1352 bool_Bool def;
1353
1354 if (ax25_xid_has(x, AX25_XID_HAS_N1_RX0x0010, &def)) {
1355 conv->xid_n1_frame[d] = frame;
1356 conv->xid_n1_default[d] = def;
1357 conv->xid_n1[d] = x->n1_rx;
1358 }
1359 if (ax25_xid_has(x, AX25_XID_HAS_K_RX0x0020, &def)) {
1360 conv->xid_k_frame[d] = frame;
1361 conv->xid_k_default[d] = def;
1362 conv->xid_k[d] = x->k_rx;
1363 }
1364}
1365
1366static void
1367ax25_check_xid_response(ax25_pkt_t *pkt, const ax25_xid_t *cmd, uint32_t cmd_frame,
1368 const ax25_xid_t *resp)
1369{
1370 unsigned flags = 0;
1371
1372 /* The lesser of what was offered and what was answered... */
1373 if ((cmd->has & resp->has & AX25_XID_HAS_DUPLEX0x0001) && resp->full_duplex && !cmd->full_duplex)
1374 flags |= AX25_XIDCHK_DUPLEX0x01;
1375 if ((cmd->has & resp->has & AX25_XID_HAS_REJ0x0002) && resp->rej > cmd->rej)
1376 flags |= AX25_XIDCHK_REJ0x02;
1377 if ((cmd->has & resp->has & AX25_XID_HAS_MODULO0x0004) && resp->modulo > cmd->modulo)
1378 flags |= AX25_XIDCHK_MODULO0x04;
1379 /* ...but the greater for the timer and retries */
1380 if ((cmd->has & resp->has & AX25_XID_HAS_T10x0040) && resp->t1_ms < cmd->t1_ms)
1381 flags |= AX25_XIDCHK_T10x08;
1382 if ((cmd->has & resp->has & AX25_XID_HAS_N20x0080) && resp->n2 < cmd->n2)
1383 flags |= AX25_XIDCHK_N20x10;
1384
1385 if (!flags)
1386 return;
1387 pkt->xid_check = wmem_new(wmem_file_scope(), ax25_xid_check_t)((ax25_xid_check_t*)wmem_alloc((wmem_file_scope()), sizeof(ax25_xid_check_t
)))
;
1388 pkt->xid_check->cmd_frame = cmd_frame;
1389 pkt->xid_check->flags = flags;
1390 pkt->xid_check->cmd = *cmd;
1391 pkt->xid_check->resp = *resp;
1392}
1393
1394/*
1395 * XID frames (first pass). Accepted before the SABM(E) (sections 4.3.3.7
1396 * and 6.3.2) as well as after the UA (Appendix C5.3; what Direwolf does).
1397 */
1398static void
1399ax25_handle_xid(ax25_conv_t *conv, ax25_pkt_t *pkt, packet_info *pinfo, const ax25_frame_t *f)
1400{
1401 ax25_xid_t x;
1402 bool_Bool def;
1403 uint8_t d = f->dir;
1404
1405 ax25_xid_neg_t *neg;
1406
1407 ax25_parse_xid(f->tvb, f->ctl_offset + 1, f->cr != AX25_CR_RESPONSE, &x);
1408 if (!x.valid)
1409 return;
1410
1411 ax25_apply_xid_notifications(conv, d, &x, pinfo->num);
1412
1413 if (f->cr != AX25_CR_UNKNOWN) {
1414 neg = wmem_new0(wmem_file_scope(), ax25_xid_neg_t)((ax25_xid_neg_t*)wmem_alloc0((wmem_file_scope()), sizeof(ax25_xid_neg_t
)))
;
1415 neg->response = (f->cr == AX25_CR_RESPONSE);
1416 neg->self = x;
1417 neg->modulo_before = conv->modulo;
1418 neg->connected = (conv->state == AX25_LINK_CONNECTED);
1419 if (neg->response && conv->xid_cmd_valid[!d]) {
1420 neg->cmd_frame = conv->xid_cmd_frame[!d];
1421 neg->cmd = conv->xid_cmd[!d];
1422 }
1423 pkt->xid_neg = neg;
1424 }
1425
1426 if (f->cr == AX25_CR_COMMAND) {
1427 conv->xid_cmd_valid[d] = true1;
1428 conv->xid_cmd_frame[d] = pinfo->num;
1429 conv->xid_cmd[d] = x;
1430 return;
1431 }
1432 if (f->cr != AX25_CR_RESPONSE)
1433 return;
1434
1435 /* A response: both stations do v2.2 (section 6.3.2) */
1436 conv->v22_frame = pinfo->num;
1437 conv->xid_neg_frame = pinfo->num;
1438 if (conv->xid_cmd_valid[!d])
1439 ax25_check_xid_response(pkt, &conv->xid_cmd[!d], conv->xid_cmd_frame[!d], &x);
1440 conv->xid_cmd_valid[!d] = false0;
1441
1442 if (ax25_xid_has(&x, AX25_XID_HAS_T10x0040, &def)) {
1443 conv->xid_t1_frame = pinfo->num;
1444 conv->xid_t1_default = def;
1445 conv->xid_t1_ms = x.t1_ms;
1446 }
1447 if (ax25_xid_has(&x, AX25_XID_HAS_N20x0080, &def)) {
1448 conv->xid_n2_frame = pinfo->num;
1449 conv->xid_n2_default = def;
1450 conv->xid_n2 = x.n2;
1451 }
1452 if (x.has & AX25_XID_HAS_SEGMENTER0x0008) {
1453 conv->xid_segmenter_known = true1;
1454 conv->xid_segmenter = x.segmenter;
1455 }
1456 /*
1457 * The modulo only changes on an explicit selection, not on PL=0 or
1458 * GL=0: switching a running link to a default it wasn't set up
1459 * with would wreck the decoding.
1460 */
1461 if (x.has & AX25_XID_HAS_MODULO0x0004) {
1462 conv->xid_modulo = x.modulo;
1463 if (conv->state == AX25_LINK_CONNECTED && x.modulo != conv->modulo) {
1464 pkt->xid_modulo_prev = conv->modulo;
1465 ax25_set_modulo(conv, x.modulo, AX25_MODSRC_XID, pinfo->num);
1466 }
1467 }
1468}
1469
1470/*
1471 * How long a connected link can stay silent before it must be down: each
1472 * side polls after T3 and gives up after N2 tries of T1 (section 6.7.1.3).
1473 * Use the more patient side.
1474 */
1475static double
1476ax25_idle_limit_s(const ax25_conv_t *conv)
1477{
1478 double lim = 0, t3;
1479 uint8_t d;
1480
1481 for (d = 0; d < 2; d++) {
1482 t3 = ax25_param_t3_s(conv, d);
1483 if (t3 <= 0)
1484 continue; /* that side doesn't poll */
1485 lim = MAX(lim, t3 + ax25_param_n2(conv, d) * ax25_param_t1_s(conv, d))(((lim) > (t3 + ax25_param_n2(conv, d) * ax25_param_t1_s(conv
, d))) ? (lim) : (t3 + ax25_param_n2(conv, d) * ax25_param_t1_s
(conv, d)))
;
1486 }
1487 return lim; /* 0: disabled */
1488}
1489
1490/* How long after a frame a digipeated copy of it may still be heard */
1491static double
1492ax25_dup_window_s(const ax25_conv_t *conv)
1493{
1494 return MAX(ax25_param_t1_s(conv, AX25_DIR_LO_HI), ax25_param_t1_s(conv, AX25_DIR_HI_LO))(((ax25_param_t1_s(conv, 0)) > (ax25_param_t1_s(conv, 1)))
? (ax25_param_t1_s(conv, 0)) : (ax25_param_t1_s(conv, 1)))
;
1495}
1496
1497/*
1498 * Does a SABM(E) start a new stream on this link (TCP-style reuse)?
1499 * Yes if anything at all has been seen on the current stream, except:
1500 * - while a connection attempt is unanswered, retries of the same
1501 * SABM(E) from the same side, and the other side sending the same
1502 * SABM(E) at the same time (a collision, section 6.3.6.2);
1503 * - a SABM from the side whose SABME was just answered by DM or FRMR:
1504 * that is the same connection attempt falling back to v2.0
1505 * (section 4.3.3.2).
1506 */
1507static bool_Bool
1508ax25_sabm_starts_stream(const ax25_conv_t *conv, const ax25_frame_t *f)
1509{
1510 if (conv->nframes == 0)
1511 return false0;
1512 if (conv->state == AX25_LINK_CONNECTING && conv->connect_type == f->ftype)
1513 return false0;
1514 if (conv->fallback_pending && f->ftype == AX25_FT_SABM && f->dir == conv->fallback_dir)
1515 return false0;
1516 return true1;
1517}
1518
1519/*
1520 * Hearing only the responder: a UA nobody asked for while the link is
1521 * known to be down can only answer a SABM(E) we didn't hear (a DISC
1522 * while disconnected gets a DM, section 6.3.5), so it starts a stream.
1523 * Not on PRESUMED_DOWN, which is only inferred.
1524 */
1525static bool_Bool
1526ax25_ua_starts_stream(const ax25_conv_t *conv, const ax25_frame_t *f)
1527{
1528 if (f->ftype != AX25_FT_UA || conv->nframes == 0)
1529 return false0;
1530 if (conv->last_cmd[!f->dir] != AX25_FT_NONE &&
1531 conv->last_cmd_frame[!f->dir] > conv->state_frame)
1532 return false0; /* it answers something we heard */
1533 return conv->state == AX25_LINK_DISCONNECTED_DISC ||
1534 conv->state == AX25_LINK_DISCONNECTED_DM ||
1535 conv->state == AX25_LINK_FRMR;
1536}
1537
1538/*
1539 * Start the state of a new stream. What we know about the stations
1540 * carries over from the previous stream on the same link: the modulo
1541 * stays in effect until the UA of the new connection, and version
1542 * evidence is about the stations, not the connection.
1543 */
1544static ax25_conv_t *
1545ax25_new_conv(conversation_t *conversation, const ax25_conv_t *prev,
1546 const conversation_element_t *key)
1547{
1548 ax25_conv_t *conv = wmem_new0(wmem_file_scope(), ax25_conv_t)((ax25_conv_t*)wmem_alloc0((wmem_file_scope()), sizeof(ax25_conv_t
)))
;
1549 const ax25_station_uat_t *st;
1550 uint8_t d;
1551
1552 conv->state = AX25_LINK_UNKNOWN;
1553 conv->state_ftype = AX25_FT_NONE;
1554 conv->last_cmd[0] = conv->last_cmd[1] = AX25_FT_NONE;
1555 for (d = 0; d < 2; d++) {
1556 /* The lower address sends in AX25_DIR_LO_HI */
1557 memcpy(conv->addr[d],
1558 key[d == AX25_DIR_LO_HI0 ? AX25_KEY_ADDR_LO0 : AX25_KEY_ADDR_HI2].addr_val.data,
1559 AX25_ADDR_LEN7);
1560 st = ax25_find_station(conv->addr[d]);
1561 if (st) {
1562 conv->has_uat[d] = true1;
1563 conv->uat[d] = *st;
1564 conv->uat[d].callsign = NULL((void*)0);
1565 }
1566 }
1567 if (prev) {
1568 conv->v20_frame = prev->v20_frame;
1569 conv->v22_frame = prev->v22_frame;
1570 /*
1571 * An XID exchange since the last connection activity is the
1572 * parameter negotiation for this new connection (XID before
1573 * SABM(E), section 6.3.2); keep it.
1574 */
1575 if (prev->xid_neg_frame > prev->conn_activity_frame ||
1576 prev->xid_n1_frame[0] > prev->conn_activity_frame ||
1577 prev->xid_n1_frame[1] > prev->conn_activity_frame ||
1578 prev->xid_k_frame[0] > prev->conn_activity_frame ||
1579 prev->xid_k_frame[1] > prev->conn_activity_frame) {
1580 memcpy(conv->xid_cmd_valid, prev->xid_cmd_valid, sizeof conv->xid_cmd_valid);
1581 memcpy(conv->xid_cmd_frame, prev->xid_cmd_frame, sizeof conv->xid_cmd_frame);
1582 memcpy(conv->xid_cmd, prev->xid_cmd, sizeof conv->xid_cmd);
1583 conv->xid_neg_frame = prev->xid_neg_frame;
1584 conv->xid_t1_frame = prev->xid_t1_frame;
1585 conv->xid_t1_default = prev->xid_t1_default;
1586 conv->xid_t1_ms = prev->xid_t1_ms;
1587 conv->xid_n2_frame = prev->xid_n2_frame;
1588 conv->xid_n2_default = prev->xid_n2_default;
1589 conv->xid_n2 = prev->xid_n2;
1590 conv->xid_modulo = prev->xid_modulo;
1591 conv->xid_segmenter_known = prev->xid_segmenter_known;
1592 conv->xid_segmenter = prev->xid_segmenter;
1593 memcpy(conv->xid_n1_frame, prev->xid_n1_frame, sizeof conv->xid_n1_frame);
1594 memcpy(conv->xid_n1_default, prev->xid_n1_default, sizeof conv->xid_n1_default);
1595 memcpy(conv->xid_n1, prev->xid_n1, sizeof conv->xid_n1);
1596 memcpy(conv->xid_k_frame, prev->xid_k_frame, sizeof conv->xid_k_frame);
1597 memcpy(conv->xid_k_default, prev->xid_k_default, sizeof conv->xid_k_default);
1598 memcpy(conv->xid_k, prev->xid_k, sizeof conv->xid_k);
1599 }
1600 conv->modulo = prev->modulo;
1601 conv->modulo_src = prev->modulo_src;
1602 conv->modulo_frame = prev->modulo_frame;
1603 conv->pre20_frame = prev->pre20_frame;
1604 conv->last_enc[0] = prev->last_enc[0];
1605 conv->last_enc[1] = prev->last_enc[1];
1606 conv->last_enc_frame[0] = prev->last_enc_frame[0];
1607 conv->last_enc_frame[1] = prev->last_enc_frame[1];
1608 conv->fallback_pending = prev->fallback_pending;
1609 conv->fallback_dir = prev->fallback_dir;
1610 conv->fallback_frame = prev->fallback_frame;
1611 } else {
1612 conv->modulo = 8;
1613 conv->modulo_src = AX25_MODSRC_ASSUMED;
1614 }
1615 conversation_add_proto_data(conversation, proto_ax25, conv);
1616 return conv;
1617}
1618
1619static void
1620ax25_set_modulo(ax25_conv_t *conv, uint8_t modulo, ax25_modsrc_e src, uint32_t frame)
1621{
1622 conv->modulo = modulo;
1623 conv->modulo_src = src;
1624 conv->modulo_frame = frame;
1625}
1626
1627static void
1628ax25_set_state(ax25_conv_t *conv, ax25_link_state_e state, uint32_t frame, ax25_ftype_e ft)
1629{
1630 conv->state = state;
1631 conv->state_frame = frame;
1632 conv->state_ftype = ft;
1633}
1634
1635/*
1636 * Mid-session start: try to tell the modulo from an S frame.
1637 *
1638 * - In modulo 128 bits 4-7 of the first octet are always 0 (Figure 4.1b),
1639 * so any of them set proves modulo 8.
1640 * - Without anything after the control field, a modulo 8 S frame is one
1641 * octet long and a modulo 128 one two octets. AX.25 has no information
1642 * field in S frames, so a frame that ends right after one or two control
1643 * octets is decisive. A trailing FCS doesn't fool this: it would make
1644 * the frame at least three octets long, which isn't decisive.
1645 *
1646 * Returns 0 if the frame doesn't tell.
1647 */
1648static uint8_t
1649ax25_infer_modulo(const ax25_frame_t *f)
1650{
1651 if (!ax25_ftype_is_s(f->ftype))
1652 return 0;
1653 if (f->c0 & AX25_S128_ZERO_BITS0xF0)
1654 return 8;
1655 if (f->ctl_remaining == 1)
1656 return 8;
1657 if (f->ctl_remaining == 2)
1658 return 128;
1659 return 0;
1660}
1661
1662/*
1663 * The modulo the control field of this frame is decoded with. Called on
1664 * the first pass before the frame is decoded.
1665 */
1666static void
1667ax25_update_modulo_before(ax25_conv_t *conv, packet_info *pinfo, const ax25_frame_t *f)
1668{
1669 uint8_t inferred;
1670
1671 if (!ax25_ftype_is_numbered(f->ftype))
1672 return;
1673
1674 /*
1675 * I or S frames from the side that sent an unanswered SABM(E): that
1676 * station only sends them once it has the UA (section 6.3.1), so
1677 * the UA was missed (we may hear only one side). Use what the
1678 * SABM(E) asked for. Frames from the other side between the SABM(E)
1679 * and the UA keep the previous modulo.
1680 */
1681 if (conv->state == AX25_LINK_CONNECTING) {
1682 if (f->dir == conv->connect_dir)
1683 ax25_set_modulo(conv, conv->connect_type == AX25_FT_SABME ? 128 : 8,
1684 AX25_MODSRC_NO_UA, conv->connect_frame);
1685 return;
1686 }
1687
1688 if (conv->modulo_src == AX25_MODSRC_ASSUMED) {
1689 inferred = ax25_infer_modulo(f);
1690 if (inferred)
1691 ax25_set_modulo(conv, inferred, AX25_MODSRC_INFERRED, pinfo->num);
1692 }
1693}
1694
1695/* N(S) and N(R) of an I or S frame, without throwing */
1696static bool_Bool
1697ax25_get_seq(const ax25_frame_t *f, uint8_t modulo, uint8_t *ns, uint8_t *nr)
1698{
1699 unsigned c;
1700
1701 if (!ax25_ftype_is_numbered(f->ftype))
1702 return false0;
1703 if (modulo == 128) {
1704 if (tvb_captured_length_remaining(f->tvb, f->ctl_offset) < 2)
1705 return false0;
1706 c = tvb_get_letohs(f->tvb, f->ctl_offset);
1707 *nr = (uint8_t)((c & XDLC_N_R_EXT_MASK0xFE00) >> XDLC_N_R_EXT_SHIFT9);
1708 *ns = (uint8_t)((c & XDLC_N_S_EXT_MASK0x00FE) >> XDLC_N_S_EXT_SHIFT1);
1709 } else {
1710 c = f->c0;
1711 *nr = (uint8_t)((c & XDLC_N_R_MASK0xE0) >> XDLC_N_R_SHIFT5);
1712 *ns = (uint8_t)((c & XDLC_N_S_MASK0x0E) >> XDLC_N_S_SHIFT1);
1713 }
1714 return true1;
1715}
1716
1717/*
1718 * After an idle gap, does this frame carry on where the link left off?
1719 * An I frame continues if its N(S) follows (or repeats) the last N(S)
1720 * from the same side, or is what the other side last asked for in N(R).
1721 * An S frame continues if its N(R) repeats the last one from the same
1722 * side, or acknowledges the last I frame from the other side.
1723 */
1724static bool_Bool
1725ax25_seq_continues(const ax25_conv_t *conv, const ax25_frame_t *f, uint8_t modulo,
1726 uint8_t ns, uint8_t nr)
1727{
1728 uint8_t d = f->dir;
1729
1730 if (f->ftype == AX25_FT_I) {
1731 if (conv->ns_valid[d] &&
1732 (ns == conv->last_ns[d] || ns == (conv->last_ns[d] + 1) % modulo))
1733 return true1;
1734 if (conv->nr_valid[!d] && ns == conv->last_nr[!d])
1735 return true1;
1736 return false0;
1737 }
1738 if (conv->nr_valid[d] && nr == conv->last_nr[d])
1739 return true1;
1740 if (conv->ns_valid[!d] && nr == (conv->last_ns[!d] + 1) % modulo)
1741 return true1;
1742 return false0;
1743}
1744
1745/*
1746 * Copy of the frame with the H bits of the digipeater path cleared, so
1747 * a digipeated copy compares equal to what it was copied from.
1748 */
1749static uint8_t *
1750ax25_dup_signature(const ax25_frame_t *f, unsigned *len)
1751{
1752 uint8_t *data;
1753 unsigned i;
1754
1755 *len = tvb_captured_length(f->tvb);
1756 data = (uint8_t *)tvb_memdup(wmem_file_scope(), f->tvb, 0, *len);
1757 for (i = 0; i < f->ndigis; i++)
1758 data[f->digi_ssid_offset[i]] &= ~AX25_SSID_CR0x80;
1759 return data;
1760}
1761
1762/*
1763 * A digipeated copy matches a recent frame on the link except for the H
1764 * bits, and has the same H bits set plus at least one more. A frame
1765 * repeated with the same H bits is a retransmission, not a copy.
1766 */
1767static const ax25_hist_t *
1768ax25_find_dup(const ax25_conv_t *conv, packet_info *pinfo, const ax25_frame_t *f,
1769 const uint8_t *sig, unsigned len)
1770{
1771 const ax25_hist_t *h;
1772 nstime_t age;
1773 unsigned i, n;
1774
1775 if (f->ndigis == 0)
1776 return NULL((void*)0);
1777
1778 for (n = 1; n <= AX25_DUP_HISTORY8; n++) {
1779 i = (conv->hist_next + AX25_DUP_HISTORY8 - n) % AX25_DUP_HISTORY8;
1780 h = &conv->hist[i];
1781 if (!h->data)
1782 break;
1783 if (h->reported_len != tvb_reported_length(f->tvb) || h->len != len ||
1784 memcmp(h->data, sig, len) != 0)
1785 continue;
1786 /* The most recent frame with the same content decides */
1787 nstime_delta(&age, &pinfo->abs_ts, &h->ts);
1788 if (nstime_to_sec(&age) > ax25_dup_window_s(conv))
1789 return NULL((void*)0);
1790 if (f->hbits != h->hbits && (f->hbits & h->hbits) == h->hbits)
1791 return h;
1792 return NULL((void*)0);
1793 }
1794 return NULL((void*)0);
1795}
1796
1797static void
1798ax25_remember_frame(ax25_conv_t *conv, packet_info *pinfo, const ax25_frame_t *f,
1799 uint8_t *sig, unsigned len, ax25_pkt_t *pkt)
1800{
1801 ax25_hist_t *h;
1802
1803 if (!sig)
1804 return;
1805 h = &conv->hist[conv->hist_next];
1806 if (h->data)
1807 wmem_free(wmem_file_scope(), h->data);
1808 h->frame = pinfo->num;
1809 h->ts = pinfo->abs_ts;
1810 h->reported_len = tvb_reported_length(f->tvb);
1811 h->len = len;
1812 h->hbits = f->hbits;
1813 h->data = sig;
1814 h->pkt = pkt;
1815 conv->hist_next = (conv->hist_next + 1) % AX25_DUP_HISTORY8;
1816}
1817
1818static void
1819ax25_seq_flag(ax25_pkt_t *pkt, const ax25_conv_t *conv, ax25_seq_expert_e e)
1820{
1821 pkt->seq_expert = e;
1822 pkt->seq_frame = conv->state_frame;
1823 pkt->seq_ftype = conv->state_ftype;
1824}
1825
1826/*
1827 * The link state machine. Responses are paired with the last command
1828 * from the other side. It has to cope with hearing only one side of the
1829 * link, so missing frames are inferred where the protocol allows it.
1830 */
1831static void
1832ax25_update_state(ax25_conv_t *conv, ax25_pkt_t *pkt, packet_info *pinfo,
1833 const ax25_frame_t *f, uint8_t modulo)
1834{
1835 uint8_t d = f->dir;
1836 uint8_t ns = 0, nr = 0;
1837 bool_Bool have_seq;
1838 nstime_t gap;
1839 double limit;
1840
1841 have_seq = ax25_get_seq(f, modulo, &ns, &nr);
1842
1843 /* A connected link silent for longer than it can be is down */
1844 if (conv->state == AX25_LINK_CONNECTED && conv->nframes > 0) {
1845 nstime_delta(&gap, &pinfo->abs_ts, &conv->last_ts);
1846 limit = ax25_idle_limit_s(conv);
1847 if (limit > 0 && nstime_to_sec(&gap) > limit) {
1848 ax25_set_state(conv, AX25_LINK_PRESUMED_DOWN, conv->last_frame, AX25_FT_NONE);
1849 conv->idle_gap = gap;
1850 conv->idle_limit_s = limit;
1851 }
1852 }
1853
1854 switch (f->ftype) {
1855 case AX25_FT_SABM:
1856 case AX25_FT_SABME:
1857 if (conv->fallback_pending && f->ftype == AX25_FT_SABM && d == conv->fallback_dir) {
1858 pkt->fallback_frame = conv->fallback_frame;
1859 conv->v20_frame = pinfo->num;
1860 }
1861 conv->fallback_pending = false0;
1862 /* Connecting in a modulo other than the one just negotiated */
1863 if (conv->xid_neg_frame && conv->xid_modulo &&
1864 conv->xid_modulo != (f->ftype == AX25_FT_SABME ? 128 : 8)) {
1865 pkt->sabm_xid_frame = conv->xid_neg_frame;
1866 pkt->sabm_xid_modulo = conv->xid_modulo;
1867 }
1868 if (conv->state != AX25_LINK_CONNECTING) {
1869 ax25_set_state(conv, AX25_LINK_CONNECTING, pinfo->num, f->ftype);
1870 conv->connect_dir = d;
1871 conv->connect_type = f->ftype;
1872 conv->connect_frame = pinfo->num;
1873 }
1874 break;
1875
1876 case AX25_FT_DISC:
1877 ax25_set_state(conv, AX25_LINK_DISCONNECTING, pinfo->num, f->ftype);
1878 conv->disc_dir = d;
1879 break;
1880
1881 case AX25_FT_UA:
1882 if (conv->state == AX25_LINK_CONNECTING && d != conv->connect_dir) {
1883 ax25_set_state(conv, AX25_LINK_CONNECTED, pinfo->num, f->ftype);
1884 ax25_set_modulo(conv, conv->connect_type == AX25_FT_SABME ? 128 : 8,
1885 AX25_MODSRC_SABM_UA, pinfo->num);
1886 /* SABME exists from v2.2 on; a SABM link is a v2.0 one */
1887 if (conv->connect_type == AX25_FT_SABME)
1888 conv->v22_frame = pinfo->num;
1889 else
1890 conv->v20_frame = pinfo->num;
1891 conv->ns_valid[0] = conv->ns_valid[1] = false0;
1892 conv->nr_valid[0] = conv->nr_valid[1] = false0;
1893 } else if (conv->state == AX25_LINK_DISCONNECTING && d != conv->disc_dir) {
1894 ax25_set_state(conv, AX25_LINK_DISCONNECTED_DISC, pinfo->num, f->ftype);
1895 }
1896 /* Otherwise we can't tell what it answers: a UA as the first
1897 * frame stays UNKNOWN (see ax25_first_pass() for a UA that
1898 * starts a stream). */
1899 break;
1900
1901 case AX25_FT_DM:
1902 if (conv->state == AX25_LINK_CONNECTING && d != conv->connect_dir) {
1903 /* DM answering SABM(E): refused (section 6.3.1) */
1904 pkt->refused_frame = conv->connect_frame;
1905 if (conv->connect_type == AX25_FT_SABME) {
1906 conv->fallback_pending = true1;
1907 conv->fallback_dir = conv->connect_dir;
1908 conv->fallback_frame = pinfo->num;
1909 }
1910 }
1911 /* Otherwise, answering I/S frames, a DISC, or unsolicited: down */
1912 ax25_set_state(conv, AX25_LINK_DISCONNECTED_DM, pinfo->num, f->ftype);
1913 break;
1914
1915 case AX25_FT_FRMR:
1916 if (conv->last_cmd[!d] == AX25_FT_XID) {
1917 /* A pre-2.2 station rejecting XID (section 6.3.2): it
1918 * uses v2.0 defaults. Not a link error. */
1919 pkt->frmr_xid_frame = conv->last_cmd_frame[!d];
1920 conv->v20_frame = pinfo->num;
1921 conv->xid_cmd_valid[!d] = false0;
1922 } else if (conv->state == AX25_LINK_CONNECTING && d != conv->connect_dir &&
1923 conv->connect_type == AX25_FT_SABME) {
1924 /* A pre-2.2 station rejecting SABME (section 4.3.3.2);
1925 * expect a SABM. */
1926 pkt->refused_frame = conv->connect_frame;
1927 conv->fallback_pending = true1;
1928 conv->fallback_dir = conv->connect_dir;
1929 conv->fallback_frame = pinfo->num;
1930 ax25_set_state(conv, AX25_LINK_DISCONNECTED_DM, pinfo->num, f->ftype);
1931 } else {
1932 ax25_set_state(conv, AX25_LINK_FRMR, pinfo->num, f->ftype);
1933 }
1934 break;
1935
1936 case AX25_FT_I:
1937 case AX25_FT_RR:
1938 case AX25_FT_RNR:
1939 case AX25_FT_REJ:
1940 case AX25_FT_SREJ:
1941 /* Checked: I frames, and S frames sent as commands */
1942 if (f->ftype == AX25_FT_I || f->cr == AX25_CR_COMMAND) {
1943 switch (conv->state) {
1944 case AX25_LINK_DISCONNECTED_DISC:
1945 ax25_seq_flag(pkt, conv, AX25_SEQ_AFTER_DISC);
1946 break;
1947 case AX25_LINK_DISCONNECTED_DM:
1948 ax25_seq_flag(pkt, conv, AX25_SEQ_AFTER_DM);
1949 break;
1950 case AX25_LINK_FRMR:
1951 ax25_seq_flag(pkt, conv, AX25_SEQ_AFTER_FRMR);
1952 break;
1953 case AX25_LINK_DISCONNECTING:
1954 ax25_seq_flag(pkt, conv, AX25_SEQ_DISCONNECTING);
1955 break;
1956 default:
1957 break;
1958 }
1959 }
1960 switch (conv->state) {
1961 case AX25_LINK_UNKNOWN:
1962 /* Mid-session start: traffic means the link is up */
1963 ax25_set_state(conv, AX25_LINK_CONNECTED, pinfo->num, f->ftype);
1964 break;
1965 case AX25_LINK_CONNECTING:
1966 /* From the initiator, the UA was missed (see
1967 * ax25_update_modulo_before()). From the other side
1968 * these are left over from before the SABM(E). */
1969 if (d == conv->connect_dir)
1970 ax25_set_state(conv, AX25_LINK_CONNECTED, pinfo->num, f->ftype);
1971 break;
1972 case AX25_LINK_PRESUMED_DOWN:
1973 /* Traffic resumed after the gap. Only an inferred state,
1974 * so it never splits the stream or changes the modulo. */
1975 if (f->ftype == AX25_FT_I || f->cr == AX25_CR_COMMAND) {
1976 ax25_seq_flag(pkt, conv,
1977 have_seq && ax25_seq_continues(conv, f, modulo, ns, nr) ?
1978 AX25_SEQ_CAPTURE_GAP : AX25_SEQ_AFTER_IDLE);
1979 pkt->idle_gap = conv->idle_gap;
1980 pkt->idle_limit_s = conv->idle_limit_s;
1981 }
1982 ax25_set_state(conv, AX25_LINK_CONNECTED, pinfo->num, f->ftype);
1983 break;
1984 default:
1985 break;
1986 }
1987 if (have_seq) {
1988 if (f->ftype == AX25_FT_I) {
1989 conv->last_ns[d] = ns;
1990 conv->ns_valid[d] = true1;
1991 }
1992 conv->last_nr[d] = nr;
1993 conv->nr_valid[d] = true1;
1994 }
1995 break;
1996
1997 case AX25_FT_XID:
1998 /* Doesn't change the link state, but the parameters */
1999 ax25_handle_xid(conv, pkt, pinfo, f);
2000 break;
2001
2002 default:
2003 /* UI and TEST don't change the link state */
2004 break;
2005 }
2006
2007 switch (f->ftype) {
2008 case AX25_FT_UI:
2009 case AX25_FT_XID:
2010 case AX25_FT_TEST:
2011 case AX25_FT_U_OTHER:
2012 break;
2013 case AX25_FT_FRMR:
2014 if (pkt->frmr_xid_frame)
2015 break;
2016 /* FALLTHROUGH */
2017 default:
2018 conv->conn_activity_frame = pinfo->num;
2019 break;
2020 }
2021
2022 if (f->cr == AX25_CR_COMMAND) {
2023 conv->last_cmd[d] = f->ftype;
2024 conv->last_cmd_frame[d] = pinfo->num;
2025 }
2026}
2027
2028/* PID of an I or UI frame, without throwing */
2029static bool_Bool
2030ax25_get_pid(const ax25_frame_t *f, uint8_t modulo, int *pid_offset, uint8_t *pid)
2031{
2032 int off;
2033
2034 if (f->ftype != AX25_FT_I && f->ftype != AX25_FT_UI)
2035 return false0;
2036 off = f->ctl_offset + ((f->ftype == AX25_FT_I && modulo == 128) ? 2 : 1);
2037 if (tvb_captured_length_remaining(f->tvb, off) < 1)
2038 return false0;
2039 *pid_offset = off;
2040 *pid = tvb_get_uint8(f->tvb, off);
2041 return true1;
2042}
2043
2044/* TR210: the preference, or how long the sender keeps trying (N2 x T1) */
2045static double
2046ax25_tr210_s(const ax25_pkt_t *pkt)
2047{
2048 if (ax25_pref_tr210_s)
2049 return (double)ax25_pref_tr210_s;
2050 return pkt->params.n2.value * (pkt->params.t1_ms.value / 1000.0);
2051}
2052
2053/*
2054 * Segmenter analysis (section 6.6, Appendix C6), per direction, over I
2055 * and UI frames alike. No reassembly: just check that each sequence
2056 * starts with a first segment, that the remaining count goes down by one
2057 * each time, and that nothing else is sent in the middle of a sequence
2058 * (C6.3.2).
2059 */
2060static void
2061ax25_track_segments(ax25_conv_t *conv, ax25_pkt_t *pkt, packet_info *pinfo,
2062 const ax25_frame_t *f, uint8_t modulo)
2063{
2064 uint8_t d = f->dir;
2065 uint8_t pid, hdr, remaining, ns = 0, nr = 0;
2066 int pid_offset;
2067 bool_Bool first, have_ns, over_ui;
2068 nstime_t gap;
2069
2070 if (!ax25_get_pid(f, modulo, &pid_offset, &pid))
2071 return;
2072 over_ui = (f->ftype == AX25_FT_UI);
2073
2074 if (pid != AX25_P_SEGMENT0x08) {
2075 /* Any other data from the same side breaks a sequence */
2076 if (conv->seg_active[d]) {
2077 pkt->seg_flags |= AX25_SEGF_INTERLEAVED0x0020;
2078 pkt->seg_first_frame = conv->seg_first_frame[d];
2079 conv->seg_active[d] = false0;
2080 }
2081 return;
2082 }
2083 if (tvb_captured_length_remaining(f->tvb, pid_offset + 1) < 1)
2084 return;
2085 hdr = tvb_get_uint8(f->tvb, pid_offset + 1);
2086 first = (hdr & AX25_SEG_FIRST0x80) != 0;
2087 remaining = hdr & AX25_SEG_REMAINING0x7F;
2088 have_ns = (f->ftype == AX25_FT_I) && ax25_get_seq(f, modulo, &ns, &nr);
2089
2090 /* An I frame sent again (same N(S), same segment) isn't a new segment */
2091 if (have_ns && conv->seg_last_ns_valid[d] && ns == conv->seg_last_ns[d] &&
2092 !conv->seg_over_ui[d] &&
2093 (conv->seg_active[d] ? remaining == conv->seg_remaining[d] : remaining == 0)) {
2094 pkt->seg_flags |= AX25_SEGF_RETRANSMISSION0x0080;
2095 pkt->seg_first_frame = conv->seg_first_frame[d];
2096 return;
2097 }
2098
2099 /* Did the stations agree to use the segmenter? */
2100 if (first || !conv->seg_active[d]) {
2101 if (!conv->xid_neg_frame) {
2102 pkt->seg_flags |= AX25_SEGF_NEG_NOT_CAPTURED0x0002;
2103 } else if (conv->xid_segmenter_known && !conv->xid_segmenter) {
2104 pkt->seg_flags |= AX25_SEGF_NOT_NEGOTIATED0x0001;
2105 pkt->seg_xid_frame = conv->xid_neg_frame;
2106 }
2107 }
2108
2109 if (conv->seg_active[d]) {
2110 nstime_delta(&gap, &pinfo->abs_ts, &conv->seg_last_ts[d]);
2111 pkt->seg_tr210_s = ax25_tr210_s(pkt);
2112 if (pkt->seg_tr210_s > 0 && nstime_to_sec(&gap) > pkt->seg_tr210_s) {
2113 pkt->seg_flags |= AX25_SEGF_TR2100x0040;
2114 pkt->seg_gap = gap;
2115 }
2116 if (conv->seg_over_ui[d] != over_ui) {
2117 /* I and UI segments don't make one sequence */
2118 pkt->seg_flags |= AX25_SEGF_INTERLEAVED0x0020;
2119 pkt->seg_first_frame = conv->seg_first_frame[d];
2120 conv->seg_active[d] = false0;
2121 }
2122 }
2123
2124 if (first) {
2125 if (conv->seg_active[d]) {
2126 pkt->seg_flags |= AX25_SEGF_ABANDONED0x0010;
2127 pkt->seg_expected = conv->seg_remaining[d] - 1;
2128 pkt->seg_first_frame = conv->seg_first_frame[d];
2129 }
2130 conv->seg_first_frame[d] = pinfo->num;
2131 conv->seg_active[d] = (remaining > 0);
2132 } else if (!conv->seg_active[d]) {
2133 pkt->seg_flags |= AX25_SEGF_MISSING_FIRST0x0004;
2134 /* Follow what's left of the sequence anyway */
2135 conv->seg_first_frame[d] = 0;
2136 conv->seg_active[d] = (remaining > 0);
2137 } else {
2138 if (remaining != conv->seg_remaining[d] - 1) {
2139 pkt->seg_flags |= AX25_SEGF_BAD_REMAINING0x0008;
2140 pkt->seg_expected = conv->seg_remaining[d] - 1;
2141 }
2142 conv->seg_active[d] = (remaining > 0);
2143 }
2144 if (!pkt->seg_first_frame)
2145 pkt->seg_first_frame = conv->seg_first_frame[d];
2146 conv->seg_remaining[d] = remaining;
2147 conv->seg_over_ui[d] = over_ui;
2148 conv->seg_last_ts[d] = pinfo->abs_ts;
2149 conv->seg_last_ns_valid[d] = have_ns;
2150 conv->seg_last_ns[d] = ns;
2151}
2152
2153/*
2154 * First pass: find (or start) the link this frame belongs to, update its
2155 * state and return the snapshot later passes will use.
2156 */
2157static ax25_pkt_t *
2158ax25_first_pass(packet_info *pinfo, conversation_element_t *key, const ax25_frame_t *f)
2159{
2160 conversation_t *conversation;
2161 ax25_conv_t *conv = NULL((void*)0);
2162 ax25_pkt_t *pkt;
2163 const ax25_hist_t *orig;
2164 uint8_t *sig;
2165 unsigned sig_len = 0;
2166 uint8_t enc;
2167
2168 conversation = find_conversation_full(pinfo->num, key);
2169 if (conversation)
2170 conv = (ax25_conv_t *)conversation_get_proto_data(conversation, proto_ax25);
2171
2172 sig = f->ndigis ? ax25_dup_signature(f, &sig_len) : NULL((void*)0);
2173
2174 /* A digipeated copy is decoded like the original and changes nothing */
2175 if (conv && sig && (orig = ax25_find_dup(conv, pinfo, f, sig, sig_len)) != NULL((void*)0)) {
2176 pkt = wmem_new(wmem_file_scope(), ax25_pkt_t)((ax25_pkt_t*)wmem_alloc((wmem_file_scope()), sizeof(ax25_pkt_t
)))
;
2177 *pkt = *orig->pkt;
2178 pkt->seq_expert = AX25_SEQ_NONE;
2179 pkt->cr_mixed_frame = 0;
2180 pkt->refused_frame = 0;
2181 pkt->frmr_xid_frame = 0;
2182 pkt->fallback_frame = 0;
2183 pkt->xid_check = NULL((void*)0);
2184 pkt->sabm_xid_frame = 0;
2185 pkt->xid_modulo_prev = 0;
2186 pkt->xid_neg = NULL((void*)0);
2187 pkt->seg_flags = 0;
2188 pkt->dup_of = orig->frame;
2189 wmem_free(wmem_file_scope(), sig);
2190 return pkt;
2191 }
2192
2193 if (conv && ((ax25_ftype_is_sabm(f->ftype) && ax25_sabm_starts_stream(conv, f)) ||
2194 ax25_ua_starts_stream(conv, f))) {
2195 conversation = conversation_new_full(pinfo->num, key);
2196 conv = ax25_new_conv(conversation, conv, key);
2197 if (f->ftype == AX25_FT_UA) {
2198 /* Hearing only the responder: it accepted a SABM(E)
2199 * we didn't hear. Can't tell which, so the modulo is
2200 * open again. */
2201 ax25_set_state(conv, AX25_LINK_CONNECTED, pinfo->num, f->ftype);
2202 conv->modulo_src = AX25_MODSRC_ASSUMED;
2203 conv->modulo_frame = 0;
2204 }
2205 }
2206 if (!conversation)
2207 conversation = conversation_new_full(pinfo->num, key);
2208 if (!conv)
2209 conv = ax25_new_conv(conversation, NULL((void*)0), key);
2210
2211 pkt = wmem_new0(wmem_file_scope(), ax25_pkt_t)((ax25_pkt_t*)wmem_alloc0((wmem_file_scope()), sizeof(ax25_pkt_t
)))
;
2212
2213 /* Version evidence */
2214 enc = (f->version == AX25_VERSION_PRE20) ? AX25_ENC_PRE201 : AX25_ENC_2X2;
2215 if (enc == AX25_ENC_PRE201) {
2216 if (conv->pre20_frame == 0)
2217 conv->pre20_frame = pinfo->num;
2218 /* "implies v2.0 defaults" */
2219 conv->v20_frame = pinfo->num;
2220 }
2221 if (conv->last_enc[f->dir] != AX25_ENC_NONE0 && conv->last_enc[f->dir] != enc)
2222 pkt->cr_mixed_frame = conv->last_enc_frame[f->dir];
2223 conv->last_enc[f->dir] = enc;
2224 conv->last_enc_frame[f->dir] = pinfo->num;
2225
2226 /* Modulo this frame is decoded with */
2227 ax25_update_modulo_before(conv, pinfo, f);
2228 pkt->modulo = conv->modulo;
2229 pkt->modulo_src = conv->modulo_src;
2230 pkt->modulo_frame = conv->modulo_frame;
2231
2232 ax25_update_state(conv, pkt, pinfo, f, pkt->modulo);
2233 if (f->ftype == AX25_FT_UA) {
2234 /* The UA is the frame the new modulo takes effect at */
2235 pkt->modulo = conv->modulo;
2236 pkt->modulo_src = conv->modulo_src;
2237 pkt->modulo_frame = conv->modulo_frame;
2238 }
2239
2240 /* UI frames aren't part of the connection: no stream, and they
2241 * neither count as traffic nor keep the link from being idle */
2242 if (f->ftype != AX25_FT_UI) {
2243 if (!conv->has_stream) {
2244 conv->has_stream = true1;
2245 conv->stream = ax25_stream_count++;
2246 }
2247 pkt->has_stream = true1;
2248 pkt->stream = conv->stream;
2249 }
2250 pkt->dir = f->dir;
2251 pkt->pre20_frame = conv->pre20_frame;
2252 pkt->state = conv->state;
2253 ax25_resolve_params(conv, f->dir, &pkt->params);
2254 if (pkt->xid_neg) {
2255 ax25_resolve_params(conv, AX25_DIR_LO_HI0, &pkt->xid_neg->params[AX25_DIR_LO_HI0]);
2256 ax25_resolve_params(conv, AX25_DIR_HI_LO1, &pkt->xid_neg->params[AX25_DIR_HI_LO1]);
2257 }
2258 ax25_track_segments(conv, pkt, pinfo, f, pkt->modulo);
2259
2260 if (f->ftype != AX25_FT_UI) {
2261 conv->nframes++;
2262 conv->last_frame = pinfo->num;
2263 conv->last_ts = pinfo->abs_ts;
2264 }
2265 ax25_remember_frame(conv, pinfo, f, sig, sig_len, pkt);
2266
2267 return pkt;
2268}
2269
2270/*
2271 * Control field of an S or U frame whose C/R is unknown (pre-2.0 C/R
2272 * encoding). Same layout as dissect_xdlc_control(), but the P/F bit is
2273 * shown as "P/F" instead of being forced to Poll.
2274 */
2275static int
2276ax25_dissect_control_unknown_cr(tvbuff_t *tvb, int offset, packet_info *pinfo,
2277 proto_tree *tree, bool_Bool is_extended)
2278{
2279 proto_item *tc;
2280 proto_tree *control_tree;
2281 int control;
2282 int control_len;
2283 bool_Bool poll_final;
2284 char *info;
2285 const char *frame_type;
2286
2287 if ((tvb_get_uint8(tvb, offset) & XDLC_S_U_MASK0x03) == XDLC_S0x01) {
2288 if (is_extended) {
2289 control = tvb_get_letohs(tvb, offset);
2290 control_len = 2;
2291 poll_final = (control & XDLC_P_F_EXT0x0100) != 0;
2292 } else {
2293 control = tvb_get_uint8(tvb, offset);
2294 control_len = 1;
2295 poll_final = (control & XDLC_P_F0x10) != 0;
2296 }
2297 switch (control & XDLC_S_FTYPE_MASK0x0C) {
2298 case XDLC_RR0x00: frame_type = "RR"; break;
2299 case XDLC_RNR0x04: frame_type = "RNR"; break;
2300 case XDLC_REJ0x08: frame_type = "REJ"; break;
2301 default: frame_type = "SREJ"; break;
2302 }
2303 info = wmem_strdup_printf(pinfo->pool, "S%s, func=%s, N(R)=%u",
2304 poll_final ? " P/F" : "", frame_type,
2305 is_extended ?
2306 (unsigned)((control & XDLC_N_R_EXT_MASK0xFE00) >> XDLC_N_R_EXT_SHIFT9) :
2307 (unsigned)((control & XDLC_N_R_MASK0xE0) >> XDLC_N_R_SHIFT5));
2308 col_add_str(pinfo->cinfo, COL_INFO, info);
2309 tc = proto_tree_add_uint_format(tree, is_extended ? hf_ax25_ctl_ext : hf_ax25_ctl,
2310 tvb, offset, control_len, control,
2311 is_extended ? "Control field: %s (0x%04X)" : "Control field: %s (0x%02X)",
2312 info, control);
2313 control_tree = proto_item_add_subtree(tc, ett_ax25_ctl);
2314 proto_tree_add_uint(control_tree, is_extended ? hf_ax25_n_r_ext : hf_ax25_n_r,
2315 tvb, offset, control_len, control);
2316 if (poll_final)
2317 proto_tree_add_boolean(control_tree, is_extended ? hf_ax25_pf_ext : hf_ax25_pf,
2318 tvb, offset, control_len, control);
2319 proto_tree_add_uint(control_tree, is_extended ? hf_ax25_ftype_s_ext : hf_ax25_ftype_s,
2320 tvb, offset, control_len, control);
2321 proto_tree_add_uint(control_tree, is_extended ? hf_ax25_ftype_su_ext : hf_ax25_ftype_su,
2322 tvb, offset, control_len, control);
2323 return control;
2324 }
2325
2326 /* U frame: always one octet */
2327 control = tvb_get_uint8(tvb, offset);
2328 poll_final = (control & XDLC_P_F0x10) != 0;
2329 info = wmem_strdup_printf(pinfo->pool, "U%s, func=%s",
2330 poll_final ? " P/F" : "",
2331 val_to_str(pinfo->pool, control & XDLC_U_MODIFIER_MASK0xEC, ax25_u_short_vals, "Unknown"));
2332 col_add_str(pinfo->cinfo, COL_INFO, info);
2333 tc = proto_tree_add_uint_format(tree, hf_ax25_ctl, tvb, offset, 1, control,
2334 "Control field: %s (0x%02X)", info, control);
2335 control_tree = proto_item_add_subtree(tc, ett_ax25_ctl);
2336 if (poll_final)
2337 proto_tree_add_boolean(control_tree, hf_ax25_pf, tvb, offset, 1, control);
2338 proto_tree_add_uint(control_tree, hf_ax25_u_cmd, tvb, offset, 1, control);
2339 proto_tree_add_uint(control_tree, hf_ax25_ftype_su, tvb, offset, 1, control);
2340 return control;
2341}
2342
2343/* Generated decode items (stream, modulo) and their expert infos */
2344static void
2345ax25_add_decode_items(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
2346 const ax25_pkt_t *pkt, const ax25_frame_t *f)
2347{
2348 proto_item *ti;
2349
2350 if (pkt->has_stream) {
2351 ti = proto_tree_add_uint(tree, hf_ax25_stream, tvb, 0, 0, pkt->stream);
2352 proto_item_set_generated(ti);
2353 }
2354
2355 if (!ax25_ftype_is_numbered(f->ftype))
2356 return;
2357
2358 ti = proto_tree_add_uint(tree, hf_ax25_modulo, tvb, 0, 0, pkt->modulo);
2359 proto_item_set_generated(ti);
2360 ti = proto_tree_add_uint(tree, hf_ax25_modulo_source, tvb, 0, 0, pkt->modulo_src);
2361 proto_item_set_generated(ti);
2362 if (pkt->modulo_frame) {
2363 ti = proto_tree_add_uint(tree, hf_ax25_modulo_frame, tvb, 0, 0, pkt->modulo_frame);
2364 proto_item_set_generated(ti);
2365 }
2366
2367 switch (pkt->modulo_src) {
2368 case AX25_MODSRC_ASSUMED:
2369 proto_tree_add_expert(tree, pinfo, &ei_ax25_modulo_assumed, tvb, 0, 0);
2370 break;
2371 case AX25_MODSRC_INFERRED:
2372 proto_tree_add_expert_format(tree, pinfo, &ei_ax25_modulo_inferred, tvb, 0, 0,
2373 "Modulo %u inferred from the S frame in frame %u",
2374 pkt->modulo, pkt->modulo_frame);
2375 break;
2376 case AX25_MODSRC_NO_UA:
2377 proto_tree_add_expert_format(tree, pinfo, &ei_ax25_modulo_no_ua, tvb, 0, 0,
2378 "Modulo %u taken from the SABM%s in frame %u; its UA was not captured",
2379 pkt->modulo, pkt->modulo == 128 ? "E" : "", pkt->modulo_frame);
2380 break;
2381 case AX25_MODSRC_SABM_UA:
2382 case AX25_MODSRC_XID:
2383 break;
2384 }
2385}
2386
2387static void
2388ax25_add_param(proto_tree *tree, tvbuff_t *tvb, int hf, int hf_src, const ax25_param_t *p)
2389{
2390 proto_item *ti;
2391 proto_tree *pt;
2392
2393 ti = proto_tree_add_uint(tree, hf, tvb, 0, 0, p->value);
2394 proto_item_set_generated(ti);
2395 if (p->src == AX25_PSRC_XID)
2396 proto_item_append_text(ti, " (XID, frame %u)", p->frame);
2397 else
2398 proto_item_append_text(ti, " (%s)", val_to_str_const(p->src, ax25_psrc_vals, "?"));
2399 pt = proto_item_add_subtree(ti, ett_ax25_params);
2400 ti = proto_tree_add_uint(pt, hf_src, tvb, 0, 0, p->src);
2401 proto_item_set_generated(ti);
2402 if (p->frame) {
2403 ti = proto_tree_add_uint(pt, hf_ax25_param_xid_frame, tvb, 0, 0, p->frame);
2404 proto_item_set_generated(ti);
2405 }
2406}
2407
2408/* Parameters in effect for the direction of this frame, and their sources */
2409static void
2410ax25_add_params(proto_tree *tree, tvbuff_t *tvb, const ax25_params_t *p)
2411{
2412 proto_item *ti, *pi;
2413 proto_tree *pt;
2414
2415 pt = proto_tree_add_subtree(tree, tvb, 0, 0, ett_ax25_params, &pi, "Parameters for this direction");
2416 proto_item_set_generated(pi);
2417
2418 ti = proto_tree_add_uint(pt, hf_ax25_param_version, tvb, 0, 0, p->version);
2419 proto_item_set_generated(ti);
2420 proto_item_append_text(ti, " (%s)", val_to_str_const(p->version_src, ax25_vsrc_vals, "?"));
2421 ti = proto_tree_add_uint(pt, hf_ax25_param_version_source, tvb, 0, 0, p->version_src);
2422 proto_item_set_generated(ti);
2423 if (p->version_frame) {
2424 ti = proto_tree_add_uint(pt, hf_ax25_param_version_frame, tvb, 0, 0, p->version_frame);
2425 proto_item_set_generated(ti);
2426 }
2427 ax25_add_param(pt, tvb, hf_ax25_param_t1, hf_ax25_param_t1_source, &p->t1_ms);
2428 ax25_add_param(pt, tvb, hf_ax25_param_t3, hf_ax25_param_t3_source, &p->t3_s);
2429 ax25_add_param(pt, tvb, hf_ax25_param_n2, hf_ax25_param_n2_source, &p->n2);
2430 ax25_add_param(pt, tvb, hf_ax25_param_n1, hf_ax25_param_n1_source, &p->n1);
2431 ax25_add_param(pt, tvb, hf_ax25_param_k, hf_ax25_param_k_source, &p->k);
2432}
2433
2434/* What an XID response did wrong (section 6.3.2) */
2435static void
2436ax25_add_xid_check(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo, const ax25_xid_check_t *c)
2437{
2438 wmem_strbuf_t *why = wmem_strbuf_new(pinfo->pool, "");
2439
2440 /* Kept short: expert messages are cut at ITEM_LABEL_LENGTH */
2441 if (c->flags & AX25_XIDCHK_DUPLEX0x01)
2442 wmem_strbuf_append(why, "; full duplex, half offered");
2443 if (c->flags & AX25_XIDCHK_REJ0x02)
2444 wmem_strbuf_append(why, "; SREJ, REJ offered");
2445 if (c->flags & AX25_XIDCHK_MODULO0x04)
2446 wmem_strbuf_append(why, "; modulo 128, 8 offered");
2447 if (c->flags & AX25_XIDCHK_T10x08)
2448 wmem_strbuf_append_printf(why, "; T1 %u ms < %u ms offered",
2449 c->resp.t1_ms, c->cmd.t1_ms);
2450 if (c->flags & AX25_XIDCHK_N20x10)
2451 wmem_strbuf_append_printf(why, "; N2 %u < %u offered",
2452 c->resp.n2, c->cmd.n2);
2453 proto_tree_add_expert_format(tree, pinfo, &ei_ax25_xid_rule, tvb, 0, 0,
2454 "XID response to frame %u breaks section 6.3.2%s",
2455 c->cmd_frame, wmem_strbuf_get_str(why));
2456}
2457
2458/* Link analysis subtree: state, sequence expert infos, digipeated copies */
2459static void
2460ax25_add_link_items(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
2461 const ax25_pkt_t *pkt, const ax25_frame_t *f)
2462{
2463 proto_item *ti, *li;
2464 proto_tree *link_tree;
2465 const char *what;
2466 expert_field *ei = NULL((void*)0);
2467
2468 /* Nothing to say about connectionless traffic (APRS and the like) */
2469 if (pkt->state == AX25_LINK_UNKNOWN && !pkt->dup_of &&
2470 !(pkt->seg_flags & AX25_SEGF_INTERLEAVED0x0020) &&
2471 (f->ftype == AX25_FT_UI || f->ftype == AX25_FT_TEST || f->ftype == AX25_FT_U_OTHER))
2472 return;
2473
2474 link_tree = proto_tree_add_subtree(tree, tvb, 0, 0, ett_ax25_link, &li, "Link analysis");
2475 proto_item_set_generated(li);
2476
2477 if (pkt->dup_of) {
2478 ti = proto_tree_add_uint(link_tree, hf_ax25_dup_of, tvb, 0, 0, pkt->dup_of);
2479 proto_item_set_generated(ti);
2480 expert_add_info_format(pinfo, ti, &ei_ax25_dup,
2481 "Digipeated copy of frame %u (differs only in the H bits)", pkt->dup_of);
2482 proto_item_append_text(li, ": digipeated copy of frame %u", pkt->dup_of);
2483 return;
2484 }
2485
2486 ti = proto_tree_add_uint(link_tree, hf_ax25_link_state, tvb, 0, 0, pkt->state);
2487 proto_item_set_generated(ti);
2488 proto_item_append_text(li, ": %s", val_to_str_const(pkt->state, ax25_link_state_vals, "Unknown"));
2489
2490 if (pkt->refused_frame) {
2491 ti = proto_tree_add_uint(link_tree, hf_ax25_link_refused, tvb, 0, 0, pkt->refused_frame);
2492 proto_item_set_generated(ti);
2493 expert_add_info_format(pinfo, ti, &ei_ax25_refused,
2494 "Connection refused: %s answering the SABM(E) in frame %u",
2495 val_to_str_const(f->ftype, ax25_ftype_names, "?"), pkt->refused_frame);
2496 }
2497 if (pkt->fallback_frame) {
2498 ti = proto_tree_add_uint(link_tree, hf_ax25_link_fallback, tvb, 0, 0, pkt->fallback_frame);
2499 proto_item_set_generated(ti);
2500 expert_add_info_format(pinfo, ti, &ei_ax25_fallback,
2501 "SABM after the SABME was rejected in frame %u: falling back to v2.0",
2502 pkt->fallback_frame);
2503 }
2504 if (pkt->frmr_xid_frame) {
2505 ti = proto_tree_add_uint(link_tree, hf_ax25_link_frmr_xid, tvb, 0, 0, pkt->frmr_xid_frame);
2506 proto_item_set_generated(ti);
2507 expert_add_info_format(pinfo, ti, &ei_ax25_frmr_xid,
2508 "FRMR answering the XID in frame %u: the peer uses AX.25 v2.0 (not a link error)",
2509 pkt->frmr_xid_frame);
2510 }
2511 if (pkt->xid_check)
2512 ax25_add_xid_check(link_tree, tvb, pinfo, pkt->xid_check);
2513 if (pkt->sabm_xid_frame)
2514 proto_tree_add_expert_format(link_tree, pinfo, &ei_ax25_sabm_xid, tvb, 0, 0,
2515 "%s, but the XID in frame %u negotiated modulo %u",
2516 f->ftype == AX25_FT_SABME ? "SABME (modulo 128)" : "SABM (modulo 8)",
2517 pkt->sabm_xid_frame, pkt->sabm_xid_modulo);
2518 if (pkt->xid_modulo_prev)
2519 proto_tree_add_expert_format(link_tree, pinfo, &ei_ax25_xid_modulo, tvb, 0, 0,
2520 "XID after the UA changes the modulo from %u to %u from here on",
2521 pkt->xid_modulo_prev, pkt->xid_modulo_prev == 8 ? 128 : 8);
2522
2523 if (pkt->seg_flags & AX25_SEGF_INTERLEAVED0x0020) {
2524 if (pkt->seg_first_frame) {
2525 ti = proto_tree_add_uint(link_tree, hf_ax25_seg_first_frame, tvb, 0, 0, pkt->seg_first_frame);
2526 proto_item_set_generated(ti);
2527 expert_add_info_format(pinfo, ti, &ei_ax25_seg_interleaved,
2528 "Frame sent in the middle of the segmented data unit that started in frame %u"
2529 " (Appendix C6.3.2 forbids it)", pkt->seg_first_frame);
2530 } else {
2531 proto_tree_add_expert_format(link_tree, pinfo, &ei_ax25_seg_interleaved, tvb, 0, 0,
2532 "Frame sent in the middle of a segmented data unit whose first segment wasn't seen"
2533 " (Appendix C6.3.2 forbids it)");
2534 }
2535 }
2536
2537 ax25_add_params(link_tree, tvb, &pkt->params);
2538
2539 if (pkt->seq_expert == AX25_SEQ_NONE)
2540 return;
2541
2542 what = (f->ftype == AX25_FT_I) ? "I frame" :
2543 wmem_strdup_printf(pinfo->pool, "%s command",
2544 val_to_str_const(f->ftype, ax25_ftype_names, "?"));
2545 ti = proto_tree_add_uint(link_tree, hf_ax25_link_state_frame, tvb, 0, 0, pkt->seq_frame);
2546 proto_item_set_generated(ti);
2547
2548 switch (pkt->seq_expert) {
2549 case AX25_SEQ_AFTER_DISC:
2550 expert_add_info_format(pinfo, ti, &ei_ax25_after_disc,
2551 "%s after the link was disconnected by DISC/UA (UA in frame %u)",
2552 what, pkt->seq_frame);
2553 break;
2554 case AX25_SEQ_AFTER_DM:
2555 expert_add_info_format(pinfo, ti, &ei_ax25_after_dm,
2556 "%s after %s in frame %u", what,
2557 val_to_str_const(pkt->seq_ftype, ax25_ftype_names, "DM"), pkt->seq_frame);
2558 break;
2559 case AX25_SEQ_AFTER_FRMR:
2560 expert_add_info_format(pinfo, ti, &ei_ax25_after_frmr,
2561 "%s after FRMR in frame %u", what, pkt->seq_frame);
2562 break;
2563 case AX25_SEQ_DISCONNECTING:
2564 expert_add_info_format(pinfo, ti, &ei_ax25_disconnecting,
2565 "%s while disconnecting (DISC in frame %u)", what, pkt->seq_frame);
2566 break;
2567 case AX25_SEQ_AFTER_IDLE:
2568 ei = &ei_ax25_after_idle;
2569 /* FALLTHROUGH */
2570 case AX25_SEQ_CAPTURE_GAP:
2571 if (!ei)
2572 ei = &ei_ax25_capture_gap;
2573 ti = proto_tree_add_time(link_tree, hf_ax25_link_idle, tvb, 0, 0, &pkt->idle_gap);
2574 proto_item_set_generated(ti);
2575 if (pkt->seq_expert == AX25_SEQ_AFTER_IDLE)
2576 expert_add_info_format(pinfo, ti, ei,
2577 "%s after %.1f s of silence since frame %u (more than T3 + N2 x T1 = %.1f s): the link was presumed down",
2578 what, nstime_to_sec(&pkt->idle_gap), pkt->seq_frame, pkt->idle_limit_s);
2579 else
2580 expert_add_info_format(pinfo, ti, ei,
2581 "%s continues the sequence numbers after %.1f s of silence since frame %u (more than T3 + N2 x T1 = %.1f s): possible capture gap",
2582 what, nstime_to_sec(&pkt->idle_gap), pkt->seq_frame, pkt->idle_limit_s);
2583 break;
2584 case AX25_SEQ_NONE:
2585 break;
2586 }
2587}
2588
2589/* A numeric XID parameter (big-endian, up to four octets) */
2590static void
2591ax25_xid_number(proto_tree *tree, proto_item *pi, tvbuff_t *tvb, int offset, unsigned pl,
2592 int hf, const char *unit, unsigned divisor)
2593{
2594 proto_item *ti;
2595 uint32_t v;
2596
2597 if (pl > 4) {
2598 proto_tree_add_item(tree, hf_ax25_xid_pv, tvb, offset, pl, ENC_NA0x00000000);
2599 return;
2600 }
2601 v = (uint32_t)tvb_get_bits64(tvb, offset * 8, pl * 8, ENC_BIG_ENDIAN0x00000000);
2602 ti = proto_tree_add_uint(tree, hf, tvb, offset, pl, v);
2603 if (divisor > 1) {
2604 proto_item_append_text(ti, " (%u %s)", v / divisor, unit);
2605 proto_item_append_text(pi, ": %u %s", v / divisor, unit);
2606 } else {
2607 proto_item_append_text(pi, ": %u%s%s", v, unit[0] ? " " : "", unit);
2608 }
2609}
2610
2611/*
2612 * XID information field (section 4.3.3.7, ISO 8885): zero or more
2613 * information elements, each FI, GI, a two-octet big-endian GL and then
2614 * PI/PL/PV parameters. See the comment at AX25_COP_ABM for the encoding.
2615 */
2616static void
2617ax25_dissect_xid(tvbuff_t *tvb, int offset, packet_info *pinfo, proto_tree *tree)
2618{
2619 proto_item *xi, *gi, *pi, *ti;
2620 proto_tree *xt, *pt;
2621 uint8_t fi, gid, pid, pl;
2622 uint16_t gl;
2623 int end, off;
2624
2625 unsigned avail, glen, plen;
2626
2627 if (tvb_reported_length_remaining(tvb, offset) <= 0)
2628 return;
2629
2630 xi = proto_tree_add_item(tree, hf_ax25_xid, tvb, offset, -1, ENC_NA0x00000000);
2631 xt = proto_item_add_subtree(xi, ett_ax25_xid);
2632
2633 /*
2634 * Lengths that run past their group or the frame are flagged and
2635 * clamped, so the rest of the field is still shown.
2636 */
2637 while (tvb_reported_length_remaining(tvb, offset) > 0) {
2638 if (tvb_reported_length_remaining(tvb, offset) < 4) {
2639 pi = proto_tree_add_item(xt, hf_ax25_xid_trailing, tvb, offset, -1, ENC_NA0x00000000);
2640 expert_add_info_format(pinfo, pi, &ei_ax25_xid_length,
2641 "Octets after the last information element, too short for another one");
2642 break;
2643 }
2644 proto_tree_add_item_ret_uint8(xt, hf_ax25_xid_fi, tvb, offset, 1, ENC_NA0x00000000, &fi);
2645 proto_tree_add_item_ret_uint8(xt, hf_ax25_xid_gi, tvb, offset + 1, 1, ENC_NA0x00000000, &gid);
2646 gi = proto_tree_add_item_ret_uint16(xt, hf_ax25_xid_gl, tvb, offset + 2, 2, ENC_BIG_ENDIAN0x00000000, &gl);
2647 offset += 4;
2648 avail = tvb_reported_length_remaining(tvb, offset);
2649 glen = gl;
2650 if (glen > avail) {
2651 expert_add_info_format(pinfo, gi, &ei_ax25_xid_length,
2652 "Group length %u runs past the end of the frame (%u octets left)", gl, avail);
2653 glen = avail;
2654 }
2655 if (fi != AX25_XID_FI0x82 || gid != AX25_XID_GI0x80) {
2656 /* Not the general purpose / parameter negotiation group */
2657 if (glen)
2658 proto_tree_add_item(xt, hf_ax25_xid_pv, tvb, offset, glen, ENC_NA0x00000000);
2659 offset += glen;
2660 continue;
2661 }
2662 if (gl == 0) {
2663 proto_item_append_text(gi, " (all parameters take their default values)");
2664 continue;
2665 }
2666 end = offset + glen;
2667 off = offset;
2668 while (off < end) {
2669 pid = tvb_get_uint8(tvb, off);
2670 if (end - off < 2) {
2671 pi = proto_tree_add_uint(xt, hf_ax25_xid_pi, tvb, off, 1, pid);
2672 expert_add_info_format(pinfo, pi, &ei_ax25_xid_length,
2673 "Parameter identifier at the end of the group, without a length");
2674 off = end;
Value stored to 'off' is never read
2675 break;
2676 }
2677 pl = tvb_get_uint8(tvb, off + 1);
2678 plen = MIN((unsigned)pl, (unsigned)(end - off - 2))((((unsigned)pl) < ((unsigned)(end - off - 2))) ? ((unsigned
)pl) : ((unsigned)(end - off - 2)))
;
2679 pt = proto_tree_add_subtree(xt, tvb, off, 2 + plen, ett_ax25_xid_param, &pi,
2680 val_to_str(pinfo->pool, pid, ax25_xid_pi_vals, "Parameter %u"));
2681 proto_tree_add_uint(pt, hf_ax25_xid_pi, tvb, off, 1, pid);
2682 ti = proto_tree_add_uint(pt, hf_ax25_xid_pl, tvb, off + 1, 1, pl);
2683 off += 2;
2684 if (plen < pl) {
2685 expert_add_info_format(pinfo, ti, &ei_ax25_xid_length,
2686 "Parameter length %u runs past the group (%u octets left)", pl, plen);
2687 /* Don't decode a value that isn't all there */
2688 if (plen)
2689 proto_tree_add_item(pt, hf_ax25_xid_pv, tvb, off, plen, ENC_NA0x00000000);
2690 off += plen;
2691 continue;
2692 }
2693 if (pl == 0) {
2694 proto_item_append_text(pi, ": default");
2695 continue;
2696 }
2697 switch (pid) {
2698 case AX25_XID_PI_COP2:
2699 if (pl == 2)
2700 proto_tree_add_bitmask_with_flags(pt, tvb, off, hf_ax25_xid_cop,
2701 ett_ax25_xid_bits, ax25_xid_cop_fields, ENC_LITTLE_ENDIAN0x80000000,
2702 BMT_NO_FALSE0x04 | BMT_NO_INT0x02);
2703 else
2704 proto_tree_add_item(pt, hf_ax25_xid_pv, tvb, off, pl, ENC_NA0x00000000);
2705 break;
2706 case AX25_XID_PI_HDLC3:
2707 if (pl == 3)
2708 proto_tree_add_bitmask_with_flags(pt, tvb, off, hf_ax25_xid_hdlc,
2709 ett_ax25_xid_bits, ax25_xid_hdlc_fields, ENC_LITTLE_ENDIAN0x80000000,
2710 BMT_NO_FALSE0x04 | BMT_NO_INT0x02);
2711 else
2712 proto_tree_add_item(pt, hf_ax25_xid_pv, tvb, off, pl, ENC_NA0x00000000);
2713 break;
2714 case AX25_XID_PI_N1_TX5:
2715 ax25_xid_number(pt, pi, tvb, off, pl, hf_ax25_xid_n1_tx, "octets", 8);
2716 break;
2717 case AX25_XID_PI_N1_RX6:
2718 ax25_xid_number(pt, pi, tvb, off, pl, hf_ax25_xid_n1_rx, "octets", 8);
2719 break;
2720 case AX25_XID_PI_K_TX7:
2721 ax25_xid_number(pt, pi, tvb, off, pl, hf_ax25_xid_k_tx, "frames", 1);
2722 break;
2723 case AX25_XID_PI_K_RX8:
2724 ax25_xid_number(pt, pi, tvb, off, pl, hf_ax25_xid_k_rx, "frames", 1);
2725 break;
2726 case AX25_XID_PI_T19:
2727 ax25_xid_number(pt, pi, tvb, off, pl, hf_ax25_xid_t1, "ms", 1);
2728 break;
2729 case AX25_XID_PI_N210:
2730 /* Figure 4.5 doesn't list PI 10 */
2731 ax25_xid_number(pt, pi, tvb, off, pl, hf_ax25_xid_n2, "", 1);
2732 break;
2733 default:
2734 proto_tree_add_item(pt, hf_ax25_xid_pv, tvb, off, pl, ENC_NA0x00000000);
2735 break;
2736 }
2737 off += pl;
2738 }
2739 offset = end;
2740 }
2741}
2742
2743/*
2744 * Segment (PID 0x08, section 6.6): a one-octet header (first flag,
2745 * number of segments remaining) and a piece of the data unit. Linux
2746 * (ax25_output()) and Direwolf both send the original PID as the first
2747 * octet of the first segment, so it is decoded as such.
2748 *
2749 * TODO: reassemble the data unit and hand it to the ax25.pid dissector
2750 * of the original PID.
2751 */
2752static int
2753dissect_ax25_segment( tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data _U___attribute__((unused)) )
2754{
2755 proto_item *si, *ti;
2756 proto_tree *st;
2757 const ax25_pkt_t *pkt;
2758 uint8_t hdr;
2759 bool_Bool first;
2760 int offset = 0;
2761
2762 pkt = (const ax25_pkt_t *)p_get_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_SEG_PKT0x80000002U );
2763
2764 hdr = tvb_get_uint8( tvb, 0 );
2765 first = ( hdr & AX25_SEG_FIRST0x80 ) != 0;
2766 si = proto_tree_add_item( tree, hf_ax25_seg, tvb, 0, first ? 2 : 1, ENC_NA0x00000000 );
2767 st = proto_item_add_subtree( si, ett_ax25_seg );
2768 proto_tree_add_boolean( st, hf_ax25_seg_first, tvb, 0, 1, hdr );
2769 proto_tree_add_uint( st, hf_ax25_seg_remaining, tvb, 0, 1, hdr );
2770 proto_item_append_text( si, ": %s%u remaining", first ? "first, " : "", hdr & AX25_SEG_REMAINING0x7F );
2771 col_append_fstr( pinfo->cinfo, COL_INFO, " (%s%u remaining)", first ? "first, " : "",
2772 hdr & AX25_SEG_REMAINING0x7F );
2773 offset = 1;
2774 if ( first )
2775 {
2776 proto_tree_add_item( st, hf_ax25_seg_pid, tvb, 1, 1, ENC_NA0x00000000 );
2777 offset = 2;
2778 }
2779
2780 if ( pkt )
2781 {
2782 if ( pkt->seg_first_frame && pkt->seg_first_frame != pinfo->num )
2783 {
2784 ti = proto_tree_add_uint( st, hf_ax25_seg_first_frame, tvb, 0, 0, pkt->seg_first_frame );
2785 proto_item_set_generated( ti );
2786 }
2787 if ( pkt->seg_flags & AX25_SEGF_RETRANSMISSION0x0080 )
2788 proto_item_append_text( si, " [retransmission]" );
2789 if ( pkt->seg_flags & AX25_SEGF_NOT_NEGOTIATED0x0001 )
2790 proto_tree_add_expert_format( st, pinfo, &ei_ax25_seg_not_negotiated, tvb, 0, 1,
2791 "Segment, but the XID response in frame %u didn't enable the segmenter",
2792 pkt->seg_xid_frame );
2793 if ( pkt->seg_flags & AX25_SEGF_NEG_NOT_CAPTURED0x0002 )
2794 proto_tree_add_expert( st, pinfo, &ei_ax25_seg_neg_not_captured, tvb, 0, 1 );
2795 if ( pkt->seg_flags & AX25_SEGF_MISSING_FIRST0x0004 )
2796 proto_tree_add_expert( st, pinfo, &ei_ax25_seg_missing_first, tvb, 0, 1 );
2797 if ( pkt->seg_flags & AX25_SEGF_BAD_REMAINING0x0008 )
2798 proto_tree_add_expert_format( st, pinfo, &ei_ax25_seg_remaining, tvb, 0, 1,
2799 "%u segments remaining, expected %u (the count goes down by one per segment)",
2800 hdr & AX25_SEG_REMAINING0x7F, pkt->seg_expected );
2801 if ( pkt->seg_flags & AX25_SEGF_ABANDONED0x0010 )
2802 {
2803 if ( pkt->seg_first_frame )
2804 proto_tree_add_expert_format( st, pinfo, &ei_ax25_seg_remaining, tvb, 0, 1,
2805 "First segment while the sequence from frame %u still had segments to come"
2806 " (expected %u remaining)", pkt->seg_first_frame, pkt->seg_expected );
2807 else
2808 proto_tree_add_expert_format( st, pinfo, &ei_ax25_seg_remaining, tvb, 0, 1,
2809 "First segment while the previous sequence still had segments to come"
2810 " (expected %u remaining)", pkt->seg_expected );
2811 }
2812 if ( pkt->seg_flags & AX25_SEGF_INTERLEAVED0x0020 )
2813 proto_tree_add_expert( st, pinfo, &ei_ax25_seg_interleaved, tvb, 0, 1 );
2814 if ( pkt->seg_flags & AX25_SEGF_TR2100x0040 )
2815 {
2816 ti = proto_tree_add_time( st, hf_ax25_seg_gap, tvb, 0, 0, &pkt->seg_gap );
2817 proto_item_set_generated( ti );
2818 expert_add_info_format( pinfo, ti, &ei_ax25_seg_tr210,
2819 "%.1f s since the previous segment, more than TR210 (%.1f s)",
2820 nstime_to_sec( &pkt->seg_gap ), pkt->seg_tr210_s );
2821 }
2822 /* The I field (header included) of each segment is limited by N1 */
2823 if ( tvb_reported_length( tvb ) > pkt->params.n1.value )
2824 proto_tree_add_expert_format( st, pinfo, &ei_ax25_seg_too_long, tvb, 0, 1,
2825 "Segment of %u octets is longer than the receiver's N1 of %u",
2826 tvb_reported_length( tvb ), pkt->params.n1.value );
2827 }
2828
2829 call_data_dissector( tvb_new_subset_remaining( tvb, offset ), pinfo, tree );
2830 return tvb_captured_length( tvb );
2831}
2832
2833/* Negotiated values (section 6.3.2) */
2834#define AX25_XIDN_HALF0 0
2835#define AX25_XIDN_FULL1 1
2836
2837static const value_string ax25_xidn_duplex_vals[] = {
2838 { AX25_XIDN_HALF0, "Half duplex" },
2839 { AX25_XIDN_FULL1, "Full duplex" },
2840 { 0, NULL((void*)0) }
2841};
2842
2843static const value_string ax25_xidn_reject_vals[] = {
2844 { AX25_REJ_NONE0, "None" },
2845 { AX25_REJ_REJ1, "Implicit reject (REJ)" },
2846 { AX25_REJ_SREJ2, "Selective reject (SREJ)" },
2847 { 0, NULL((void*)0) }
2848};
2849
2850/* What a PI 2 offers, in words */
2851static const char *
2852ax25_xidn_duplex_set(const ax25_xid_t *x)
2853{
2854 bool_Bool half = (x->cop & AX25_COP_HALF_DUPLEX0x0020) != 0;
2855 bool_Bool full = (x->cop & AX25_COP_FULL_DUPLEX0x0040) != 0;
2856
2857 if (half && full)
2858 return "half or full duplex";
2859 if (full)
2860 return "full duplex";
2861 if (half)
2862 return "half duplex";
2863 return "neither half nor full duplex";
2864}
2865
2866/* What a PI 3 offers for reject, in words */
2867static const char *
2868ax25_xidn_reject_set(wmem_allocator_t *scope, const ax25_xid_t *x)
2869{
2870 wmem_strbuf_t *b = wmem_strbuf_new(scope, "");
2871
2872 if (x->hdlc & AX25_HDLC_REJ(1U << (1)))
2873 wmem_strbuf_append(b, "REJ");
2874 if (x->hdlc & AX25_HDLC_SREJ(1U << (2)))
2875 wmem_strbuf_append_printf(b, "%sSREJ", wmem_strbuf_get_len(b) ? ", " : "");
2876 if (x->hdlc & AX25_HDLC_SREJ_MULTI(1U << (21)))
2877 wmem_strbuf_append_printf(b, "%sSREJ multiframe", wmem_strbuf_get_len(b) ? ", " : "");
2878 if (!wmem_strbuf_get_len(b))
2879 wmem_strbuf_append(b, "neither REJ nor SREJ");
2880 return wmem_strbuf_get_str(b);
2881}
2882
2883/* What a PI 3 offers for the modulo, in words */
2884static const char *
2885ax25_xidn_modulo_set(const ax25_xid_t *x)
2886{
2887 bool_Bool m8 = (x->hdlc & AX25_HDLC_MOD8(1U << (10))) != 0;
2888 bool_Bool m128 = (x->hdlc & AX25_HDLC_MOD128(1U << (11))) != 0;
2889
2890 if (m8 && m128)
2891 return "modulo 8 or 128";
2892 if (m128)
2893 return "modulo 128";
2894 if (m8)
2895 return "modulo 8";
2896 return "no modulo";
2897}
2898
2899#define AX25_XIDN_BREACH" [breaks section 6.3.2]" " [breaks section 6.3.2]"
2900
2901/* A response should select one option; several means it took the lesser */
2902static void
2903ax25_xidn_several(proto_item *ti, bool_Bool several)
2904{
2905 if (several)
2906 proto_item_append_text(ti, " [the response selects several; taking the lesser]");
2907}
2908
2909/* Does the XID carry the parameter (PL=0 or GL=0 count, as defaults)? */
2910static bool_Bool
2911ax25_xidn_has(const ax25_xid_t *x, unsigned flag)
2912{
2913 bool_Bool def;
2914
2915 return ax25_xid_has(x, flag, &def);
2916}
2917
2918static bool_Bool
2919ax25_xidn_default(const ax25_xid_t *x, unsigned flag)
2920{
2921 return (x->has & (flag << AX25_XID_DEF_SHIFT8)) != 0;
2922}
2923
2924/*
2925 * One negotiated parameter on a response. If the response leaves it out
2926 * but the command offered it, the current value is kept (section 4.3.3.7).
2927 */
2928static proto_item *
2929ax25_xidn_kept(proto_tree *tree, tvbuff_t *tvb, const char *what)
2930{
2931 proto_item *ti;
2932
2933 ti = proto_tree_add_none_format(tree, hf_ax25_xidn_kept, tvb, 0, 0,
2934 "%s: not in the response, the current value is kept", what);
2935 proto_item_set_generated(ti);
2936 return ti;
2937}
2938
2939/*
2940 * "XID negotiation" subtree on XID frames: what a command offers, or what
2941 * a response selects, how that compares with the command, and the values
2942 * that result (section 6.3.2). The raw fields are in "XID information".
2943 */
2944static void
2945ax25_add_xid_negotiation(proto_tree *tree, tvbuff_t *tvb, packet_info *pinfo,
2946 const ax25_pkt_t *pkt, const ax25_frame_t *f)
2947{
2948 const ax25_xid_neg_t *neg = pkt->xid_neg;
2949 const ax25_xid_t *x, *c;
2950 const ax25_params_t *to_sender;
2951 proto_tree *nt;
2952 proto_item *ni, *ti;
2953 const char *src;
2954 bool_Bool have_cmd;
2955
2956 if (!neg)
2957 return;
2958 x = &neg->self;
2959 c = &neg->cmd;
2960 have_cmd = neg->cmd_frame != 0;
2961 src = address_to_str(pinfo->pool, &pinfo->src);
2962 /* N1 and k of the station that sent this XID: they limit frames sent to it */
2963 to_sender = &neg->params[!f->dir];
2964
2965 nt = proto_tree_add_subtree(tree, tvb, 0, 0, ett_ax25_xidn, &ni,
2966 neg->response ? "XID negotiation: result" : "XID negotiation: offer");
2967 proto_item_set_generated(ni);
2968
2969 if (neg->response) {
2970 if (have_cmd) {
2971 ti = proto_tree_add_uint(nt, hf_ax25_xidn_command_frame, tvb, 0, 0, neg->cmd_frame);
2972 proto_item_set_generated(ti);
2973 } else {
2974 proto_item_append_text(ni, " (the XID command wasn't captured)");
2975 }
2976 /* "The receipt of an XID response ... establishes that both
2977 * stations are using AX.25 version 2.2 or higher" */
2978 ti = proto_tree_add_item(nt, hf_ax25_xidn_v22, tvb, 0, 0, ENC_NA0x00000000);
2979 proto_item_set_generated(ti);
2980 }
2981 if (x->gl_zero)
2982 proto_item_append_text(ni, ", all parameters take their default values (GL=0)");
2983
2984 /* Classes of Procedures: half or full duplex, the lesser of the two */
2985 if (ax25_xidn_has(x, AX25_XID_HAS_DUPLEX0x0001)) {
2986 ti = proto_tree_add_uint(nt, hf_ax25_xidn_duplex, tvb, 0, 0,
2987 x->full_duplex ? AX25_XIDN_FULL1 : AX25_XIDN_HALF0);
2988 proto_item_set_generated(ti);
2989 if (ax25_xidn_default(x, AX25_XID_HAS_DUPLEX0x0001))
2990 proto_item_append_text(ti, " (default)");
2991 else if (!neg->response)
2992 proto_item_append_text(ti, " (offers %s)", ax25_xidn_duplex_set(x));
2993 else {
2994 ax25_xidn_several(ti, (x->cop & AX25_COP_HALF_DUPLEX0x0020) && (x->cop & AX25_COP_FULL_DUPLEX0x0040));
2995 if (have_cmd && ax25_xidn_has(c, AX25_XID_HAS_DUPLEX0x0001))
2996 proto_item_append_text(ti, " (command offered %s; the lesser of the two applies)%s",
2997 ax25_xidn_duplex_set(c),
2998 (c->has & AX25_XID_HAS_DUPLEX0x0001) && x->full_duplex && !c->full_duplex ?
2999 AX25_XIDN_BREACH" [breaks section 6.3.2]" : "");
3000 }
3001 } else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_DUPLEX0x0001)) {
3002 ax25_xidn_kept(nt, tvb, "Duplex");
3003 }
3004
3005 /* HDLC Optional Functions: reject, the lesser of the two */
3006 if (ax25_xidn_has(x, AX25_XID_HAS_REJ0x0002)) {
3007 ti = proto_tree_add_uint(nt, hf_ax25_xidn_reject, tvb, 0, 0,
3008 ax25_xidn_default(x, AX25_XID_HAS_REJ0x0002) ? AX25_REJ_SREJ2 : x->rej);
3009 proto_item_set_generated(ti);
3010 if (ax25_xidn_default(x, AX25_XID_HAS_REJ0x0002))
3011 proto_item_append_text(ti, " (default)");
3012 else if (!neg->response)
3013 proto_item_append_text(ti, " (offers %s)", ax25_xidn_reject_set(pinfo->pool, x));
3014 else {
3015 ax25_xidn_several(ti, (x->hdlc & AX25_HDLC_REJ(1U << (1))) &&
3016 (x->hdlc & (AX25_HDLC_SREJ(1U << (2)) | AX25_HDLC_SREJ_MULTI(1U << (21)))));
3017 if (have_cmd && ax25_xidn_has(c, AX25_XID_HAS_REJ0x0002))
3018 proto_item_append_text(ti, " (command offered %s; the lesser of the two applies)%s",
3019 ax25_xidn_reject_set(pinfo->pool, c),
3020 (c->has & AX25_XID_HAS_REJ0x0002) && x->rej > c->rej ? AX25_XIDN_BREACH" [breaks section 6.3.2]" : "");
3021 }
3022 } else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_REJ0x0002)) {
3023 ax25_xidn_kept(nt, tvb, "Reject");
3024 }
3025
3026 /*
3027 * Modulo, the lesser of the two. A default (PL=0, GL=0) is shown but
3028 * doesn't change a running link (see ax25_handle_xid()).
3029 */
3030 if (ax25_xidn_has(x, AX25_XID_HAS_MODULO0x0004)) {
3031 ti = proto_tree_add_uint(nt, hf_ax25_xidn_modulo, tvb, 0, 0,
3032 ax25_xidn_default(x, AX25_XID_HAS_MODULO0x0004) ? 128 : x->modulo);
3033 proto_item_set_generated(ti);
3034 if (ax25_xidn_default(x, AX25_XID_HAS_MODULO0x0004) && neg->connected)
3035 proto_item_append_text(ti, " (default; the running link keeps modulo %u)",
3036 neg->modulo_before);
3037 else if (ax25_xidn_default(x, AX25_XID_HAS_MODULO0x0004))
3038 proto_item_append_text(ti, " (default)");
3039 else if (!neg->response)
3040 proto_item_append_text(ti, " (offers %s)", ax25_xidn_modulo_set(x));
3041 else {
3042 ax25_xidn_several(ti, (x->hdlc & AX25_HDLC_MOD8(1U << (10))) && (x->hdlc & AX25_HDLC_MOD128(1U << (11))));
3043 if (have_cmd && ax25_xidn_has(c, AX25_XID_HAS_MODULO0x0004))
3044 proto_item_append_text(ti, " (command offered %s; the lesser of the two applies)%s",
3045 ax25_xidn_modulo_set(c),
3046 (c->has & AX25_XID_HAS_MODULO0x0004) && x->modulo > c->modulo ?
3047 AX25_XIDN_BREACH" [breaks section 6.3.2]" : "");
3048 }
3049 } else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_MODULO0x0004)) {
3050 ti = ax25_xidn_kept(nt, tvb, "Modulo");
3051 if (neg->connected)
3052 proto_item_append_text(ti, " (%u)", neg->modulo_before);
3053 }
3054
3055 /* Segmenter/reassembler (section 6.6) */
3056 if (ax25_xidn_has(x, AX25_XID_HAS_SEGMENTER0x0008)) {
3057 ti = proto_tree_add_boolean(nt, hf_ax25_xidn_segmenter, tvb, 0, 0,
3058 !ax25_xidn_default(x, AX25_XID_HAS_SEGMENTER0x0008) && x->segmenter);
3059 proto_item_set_generated(ti);
3060 if (ax25_xidn_default(x, AX25_XID_HAS_SEGMENTER0x0008))
3061 proto_item_append_text(ti, " (default)");
3062 else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_SEGMENTER0x0008))
3063 proto_item_append_text(ti, " (command %s)", c->segmenter ? "offered it" : "didn't offer it");
3064 } else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_SEGMENTER0x0008)) {
3065 ax25_xidn_kept(nt, tvb, "Segmenter");
3066 }
3067
3068 /* T1 and N2: the greater of the two, for the whole link */
3069 if (ax25_xidn_has(x, AX25_XID_HAS_T10x0040)) {
3070 ti = proto_tree_add_uint(nt, hf_ax25_xidn_t1, tvb, 0, 0,
3071 ax25_xidn_default(x, AX25_XID_HAS_T10x0040) ? AX25_SPEC_T1_MS3000 : x->t1_ms);
3072 proto_item_set_generated(ti);
3073 if (ax25_xidn_default(x, AX25_XID_HAS_T10x0040))
3074 proto_item_append_text(ti, " (default)");
3075 else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_T10x0040))
3076 proto_item_append_text(ti, " (command offered %u ms; the greater of the two applies)%s",
3077 ax25_xidn_default(c, AX25_XID_HAS_T10x0040) ? AX25_SPEC_T1_MS3000 : c->t1_ms,
3078 (c->has & AX25_XID_HAS_T10x0040) && x->t1_ms < c->t1_ms ? AX25_XIDN_BREACH" [breaks section 6.3.2]" : "");
3079 } else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_T10x0040)) {
3080 ti = ax25_xidn_kept(nt, tvb, "T1");
3081 proto_item_append_text(ti, " (%u ms, %s)", neg->params[f->dir].t1_ms.value,
3082 val_to_str_const(neg->params[f->dir].t1_ms.src, ax25_psrc_vals, "?"));
3083 }
3084 if (ax25_xidn_has(x, AX25_XID_HAS_N20x0080)) {
3085 ti = proto_tree_add_uint(nt, hf_ax25_xidn_n2, tvb, 0, 0,
3086 ax25_xidn_default(x, AX25_XID_HAS_N20x0080) ? AX25_SPEC_N210 : x->n2);
3087 proto_item_set_generated(ti);
3088 if (ax25_xidn_default(x, AX25_XID_HAS_N20x0080))
3089 proto_item_append_text(ti, " (default)");
3090 else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_N20x0080))
3091 proto_item_append_text(ti, " (command offered %u; the greater of the two applies)%s",
3092 ax25_xidn_default(c, AX25_XID_HAS_N20x0080) ? AX25_SPEC_N210 : c->n2,
3093 (c->has & AX25_XID_HAS_N20x0080) && x->n2 < c->n2 ? AX25_XIDN_BREACH" [breaks section 6.3.2]" : "");
3094 } else if (neg->response && have_cmd && ax25_xidn_has(c, AX25_XID_HAS_N20x0080)) {
3095 ti = ax25_xidn_kept(nt, tvb, "N2");
3096 proto_item_append_text(ti, " (%u, %s)", neg->params[f->dir].n2.value,
3097 val_to_str_const(neg->params[f->dir].n2.src, ax25_psrc_vals, "?"));
3098 }
3099
3100 /*
3101 * N1 and k are notifications, not negotiated: the sender of this XID
3102 * says what it can receive, in a command as well as in a response.
3103 */
3104 if (ax25_xidn_has(x, AX25_XID_HAS_N1_RX0x0010)) {
3105 ti = proto_tree_add_uint(nt, hf_ax25_xidn_n1, tvb, 0, 0, to_sender->n1.value);
3106 proto_item_set_generated(ti);
3107 proto_item_append_text(ti, " (%snotified by %s: frames sent to it must not exceed this)",
3108 ax25_xidn_default(x, AX25_XID_HAS_N1_RX0x0010) ? "default, " : "", src);
3109 }
3110 if (ax25_xidn_has(x, AX25_XID_HAS_K_RX0x0020)) {
3111 ti = proto_tree_add_uint(nt, hf_ax25_xidn_k, tvb, 0, 0, to_sender->k.value);
3112 proto_item_set_generated(ti);
3113 proto_item_append_text(ti, " (%snotified by %s: no more frames outstanding towards it)",
3114 ax25_xidn_default(x, AX25_XID_HAS_K_RX0x0020) ? "default, " : "", src);
3115 }
3116}
3117
3118static int
3119dissect_ax25( tvbuff_t *tvb, packet_info *pinfo, proto_tree *parent_tree, void* data _U___attribute__((unused)) )
3120{
3121 proto_item *ti;
3122 proto_item *gi;
3123 proto_tree *ax25_tree;
3124 int offset;
3125 int ctl_offset;
3126 int via_index;
3127 char *info_buffer;
3128 const char *ax25_version;
3129 int control;
3130 uint8_t pid = AX25_P_NO_L30xF0;
3131 uint8_t src_ssid;
3132 uint8_t dst_ssid;
3133 tvbuff_t *next_tvb = NULL((void*)0);
3134 uint8_t *dst_masked, *src_masked;
3135 const uint8_t *addr_lo, *addr_hi;
3136 uint32_t port = AX25_NO_PORT0;
3137 uint32_t iface = AX25_NO_INTERFACE0xFFFFFFFFU;
3138 void *port_data;
3139 unsigned trailer = 0;
3140 conversation_element_t *link_key;
3141 ax25_frame_t frame;
3142 ax25_pkt_t *pkt;
3143 bool_Bool is_extended;
3144
3145
3146 info_buffer = (char *)wmem_alloc( pinfo->pool, STRLEN80 );
3147 info_buffer[0] = '\0';
3148
3149 col_set_str( pinfo->cinfo, COL_PROTOCOL, "AX.25" );
3150 col_clear( pinfo->cinfo, COL_INFO );
3151
3152 /* The KISS port, if we came through KISS. Consume it so it doesn't
3153 * leak into an AX.25 frame tunnelled further down. */
3154 port_data = p_get_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_PORT0x80000001U );
3155 if ( port_data )
3156 {
3157 port = GPOINTER_TO_UINT( port_data )((guint) (gulong) (port_data)) - 1;
3158 p_remove_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_PORT0x80000001U );
3159 }
3160 /* Octets at the end that aren't AX.25 (a KISS checksum) */
3161 port_data = p_get_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_TRAILER0x80000003U );
3162 if ( port_data )
3163 {
3164 trailer = GPOINTER_TO_UINT( port_data )((guint) (gulong) (port_data));
3165 p_remove_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_TRAILER0x80000003U );
3166 }
3167 if ( pinfo->rec->presence_flags & WTAP_HAS_INTERFACE_ID0x00000004 )
3168 iface = pinfo->rec->rec_header.packet_header.interface_id;
3169
3170 memset( &frame, 0, sizeof frame );
3171 frame.tvb = tvb;
3172
3173 /* start at the dst addr */
3174 offset = 0;
3175 /* create display subtree for the protocol */
3176 ti = proto_tree_add_protocol_format( parent_tree, proto_ax25, tvb, offset, -1, "AX.25");
3177 ax25_tree = proto_item_add_subtree( ti, ett_ax25 );
3178
3179 proto_tree_add_item( ax25_tree, hf_ax25_dst, tvb, offset, AX25_ADDR_LEN7, ENC_NA0x00000000);
3180 set_address_tvb(&pinfo->dl_dst, AT_AX25, AX25_ADDR_LEN7, tvb, offset);
3181 copy_address_shallow(&pinfo->dst, &pinfo->dl_dst);
3182 dst_ssid = tvb_get_uint8(tvb, offset+6);
3183 dst_masked = (uint8_t *)wmem_alloc( pinfo->pool, AX25_ADDR_LEN7 );
3184 ax25_mask_address( tvb, offset, dst_masked );
3185
3186 /* step over dst addr point at src addr */
3187 offset += AX25_ADDR_LEN7;
3188
3189 proto_tree_add_item( ax25_tree, hf_ax25_src, tvb, offset, AX25_ADDR_LEN7, ENC_NA0x00000000);
3190 set_address_tvb(&pinfo->dl_src, AT_AX25, AX25_ADDR_LEN7, tvb, offset);
3191 copy_address_shallow(&pinfo->src, &pinfo->dl_src);
3192 src_ssid = tvb_get_uint8(tvb, offset+6);
3193 src_masked = (uint8_t *)wmem_alloc( pinfo->pool, AX25_ADDR_LEN7 );
3194 ax25_mask_address( tvb, offset, src_masked );
3195
3196 /* step over src addr point at either 1st via addr or control byte */
3197 offset += AX25_ADDR_LEN7;
3198
3199 proto_item_append_text( ti, ", Src: %s, Dst: %s",
3200 address_to_str(pinfo->pool, &pinfo->src),
3201 address_to_str(pinfo->pool, &pinfo->dst));
3202
3203 /* handle the vias, if any */
3204 via_index = 0;
3205 while ( ( tvb_get_uint8( tvb, offset - 1 ) & 0x01 ) == 0 )
3206 {
3207 if ( via_index < AX25_MAX_DIGIS8 )
3208 {
3209 proto_tree_add_item( ax25_tree, hf_ax25_via[ via_index ], tvb, offset, AX25_ADDR_LEN7, ENC_NA0x00000000);
3210 /* H bits, for recognizing digipeated copies */
3211 frame.digi_ssid_offset[ via_index ] = offset + AX25_ADDR_LEN7 - 1;
3212 if ( tvb_get_uint8( tvb, offset + AX25_ADDR_LEN7 - 1 ) & AX25_SSID_CR0x80 )
3213 frame.hbits |= 1U << via_index;
3214 via_index++;
3215 }
3216 /* step over a via addr */
3217 offset += AX25_ADDR_LEN7;
3218 }
3219 frame.ndigis = via_index;
3220 ctl_offset = offset;
3221
3222 /* What the frame is, before decoding the control field */
3223 frame.ctl_offset = ctl_offset;
3224 frame.c0 = tvb_get_uint8( tvb, ctl_offset );
3225 frame.ftype = ax25_classify_control( frame.c0 );
3226 frame.ctl_remaining = tvb_reported_length_remaining( tvb, ctl_offset ) - (int)trailer;
3227
3228 /* decode the cmd/resp field (section 6.1.2, Figure 6.1) */
3229 switch ( ( (dst_ssid >> 6) & 0x02) | ( (src_ssid >> 7) & 0x01 ) )
3230 {
3231 case 1 : /* V2.0 Response */
3232 frame.version = AX25_VERSION_2X;
3233 frame.cr = AX25_CR_RESPONSE;
3234 ax25_version = "V2.0+";
3235 break;
3236 case 2 : /* V2.0 Command */
3237 frame.version = AX25_VERSION_2X;
3238 frame.cr = AX25_CR_COMMAND;
3239 ax25_version = "V2.0+";
3240 break;
3241 default : /* 00 or 11: a station older than 2.0 */
3242 frame.version = AX25_VERSION_PRE20;
3243 frame.cr = ax25_pre20_cr( frame.ftype );
3244 ax25_version = "pre-2.0";
3245 break;
3246 }
3247 proto_item_append_text( ti, ", Ver: %s", ax25_version );
3248
3249 /* Link tracking. */
3250 if ( memcmp( src_masked, dst_masked, AX25_ADDR_LEN7 ) <= 0 )
3251 {
3252 addr_lo = src_masked;
3253 addr_hi = dst_masked;
3254 frame.dir = AX25_DIR_LO_HI0;
3255 }
3256 else
3257 {
3258 addr_lo = dst_masked;
3259 addr_hi = src_masked;
3260 frame.dir = AX25_DIR_HI_LO1;
3261 }
3262 link_key = ax25_link_key( pinfo, addr_lo, addr_hi, port, iface );
3263
3264 if ( !PINFO_FD_VISITED( pinfo )((pinfo)->fd->visited) )
3265 {
3266 pkt = ax25_first_pass( pinfo, link_key, &frame );
3267 p_add_proto_data( wmem_file_scope(), pinfo, proto_ax25, pinfo->curr_layer_num, pkt );
3268 }
3269 else
3270 pkt = (ax25_pkt_t *)p_get_proto_data( wmem_file_scope(), pinfo, proto_ax25, pinfo->curr_layer_num );
3271
3272 /* Let L3 dissectors find this link with find_conversation_pinfo() */
3273 pinfo->conv_elements = link_key;
3274
3275 gi = proto_tree_add_uint( ax25_tree, hf_ax25_version, tvb, 0, 0, frame.version );
3276 proto_item_set_generated( gi );
3277 gi = proto_tree_add_uint( ax25_tree, hf_ax25_cr, tvb, 0, 0, frame.cr );
3278 proto_item_set_generated( gi );
3279 if ( pkt )
3280 {
3281 ax25_add_decode_items( ax25_tree, tvb, pinfo, pkt, &frame );
3282 if ( pkt->cr_mixed_frame )
3283 proto_tree_add_expert_format( ax25_tree, pinfo, &ei_ax25_cr_mixed, tvb, 0, 0,
3284 "C/R encoding is %s here but was %s in frame %u, in the same direction",
3285 frame.version == AX25_VERSION_PRE20 ? "pre-2.0" : "2.x",
3286 frame.version == AX25_VERSION_PRE20 ? "2.x" : "pre-2.0",
3287 pkt->cr_mixed_frame );
3288 if ( pkt->pre20_frame && ( frame.ftype == AX25_FT_SABME || frame.ftype == AX25_FT_XID ) )
3289 proto_tree_add_expert_format( ax25_tree, pinfo, &ei_ax25_pre20_v22_feature, tvb, ctl_offset, 1,
3290 "%s on a link where frame %u used pre-2.0 C/R encoding",
3291 frame.ftype == AX25_FT_SABME ? "SABME" : "XID", pkt->pre20_frame );
3292 ax25_add_link_items( ax25_tree, tvb, pinfo, pkt, &frame );
3293 }
3294 is_extended = pkt && pkt->modulo == 128 && ax25_ftype_is_numbered( frame.ftype );
3295
3296 if ( frame.cr == AX25_CR_UNKNOWN )
3297 control = ax25_dissect_control_unknown_cr( tvb, ctl_offset, pinfo, ax25_tree, is_extended );
3298 else
3299 control = dissect_xdlc_control( tvb,
3300 ctl_offset,
3301 pinfo,
3302 ax25_tree,
3303 is_extended ? hf_ax25_ctl_ext : hf_ax25_ctl,
3304 ett_ax25_ctl,
3305 &ax25_cf_items,
3306 &ax25_cf_items_ext,
3307 NULL((void*)0),
3308 NULL((void*)0),
3309 frame.cr == AX25_CR_RESPONSE,
3310 is_extended,
3311 false0 );
3312 offset = ctl_offset + XDLC_CONTROL_LEN(control, is_extended)((((control) & 0x03) == 0x03 || !(is_extended)) ? 1 : 2); /* step over control field */
3313
3314 if ( is_extended && ax25_ftype_is_s( frame.ftype ) && ( frame.c0 & AX25_S128_ZERO_BITS0xF0 ) )
3315 proto_tree_add_expert( ax25_tree, pinfo, &ei_ax25_s128_bits, tvb, ctl_offset, 1 );
3316
3317 if ( frame.ftype == AX25_FT_XID )
3318 {
3319 ax25_dissect_xid( tvb, offset, pinfo, ax25_tree );
3320 if ( pkt )
3321 ax25_add_xid_negotiation( ax25_tree, tvb, pinfo, pkt, &frame );
3322 }
3323
3324 /* I and UI frames carry a PID; UI may have P/F set (Figure 4.4) */
3325 if ( frame.ftype == AX25_FT_I || frame.ftype == AX25_FT_UI )
3326 {
3327
3328 pid = tvb_get_uint8( tvb, offset );
3329 col_append_fstr( pinfo->cinfo, COL_INFO, ", %s", val_to_str(pinfo->pool, pid, pid_vals, "Unknown (0x%02x)") );
3330 gi = proto_tree_add_uint( ax25_tree, hf_ax25_pid, tvb, offset, 1, pid );
3331 if ( pkt && pkt->pre20_frame && pid == AX25_P_SEGMENT0x08 )
3332 expert_add_info_format( pinfo, gi, &ei_ax25_pre20_v22_feature,
3333 "Segment on a link where frame %u used pre-2.0 C/R encoding", pkt->pre20_frame );
3334
3335 /* Call sub-dissectors here */
3336
3337 offset += 1; /* step over pid to the 1st byte of the payload */
3338
3339 /* The PID isn't part of the I field (section 3.4) */
3340 if ( pkt && frame.ftype == AX25_FT_I && pid != AX25_P_SEGMENT0x08 &&
3341 (unsigned)tvb_reported_length_remaining( tvb, offset ) > pkt->params.n1.value )
3342 proto_tree_add_expert_format( ax25_tree, pinfo, &ei_ax25_n1_exceeded, tvb, offset,
3343 tvb_captured_length_remaining( tvb, offset ),
3344 "I field of %u octets is longer than the receiver's N1 of %u (%s)",
3345 tvb_reported_length_remaining( tvb, offset ), pkt->params.n1.value,
3346 pkt->params.n1.src == AX25_PSRC_XID ?
3347 wmem_strdup_printf( pinfo->pool, "XID, frame %u", pkt->params.n1.frame ) :
3348 val_to_str_const( pkt->params.n1.src, ax25_psrc_vals, "?" ) );
3349
3350 proto_item_set_end(ti, tvb, offset);
3351
3352 next_tvb = tvb_new_subset_remaining(tvb, offset);
3353
3354 /* The data pointer is the whole control field: one octet, or two
3355 * (low octet first, as on the wire) for modulo 128 I frames. */
3356 if ( pkt )
3357 p_add_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_SEG_PKT0x80000002U, pkt );
3358 if (!dissector_try_uint_with_data(ax25_dissector_table, pid, next_tvb, pinfo, parent_tree, true1, GINT_TO_POINTER(control)((gpointer) (glong) (control))))
3359 {
3360 call_data_dissector(next_tvb, pinfo, parent_tree);
3361 }
3362 p_remove_proto_data( pinfo->pool, pinfo, proto_ax25, AX25_PROTO_DATA_SEG_PKT0x80000002U );
3363 }
3364 else
3365 proto_item_set_end(ti, tvb, offset);
3366
3367 return tvb_captured_length(tvb);
3368}
3369
3370/*
3371 * Capture dissectors are stateless, so this can't know the modulo of the
3372 * link.
3373 * XXX - in modulo 128 the control field of I frames is two octets, so the
3374 * PID offset computed here is one octet short and the PID read is the
3375 * second control octet. UI frames (one control octet in both modes) are
3376 * right.
3377 */
3378static bool_Bool
3379capture_ax25( const unsigned char *pd, int offset, int len, capture_packet_info_t *cpinfo, const union wtap_pseudo_header *pseudo_header)
3380{
3381 uint8_t control;
3382 uint8_t pid;
3383 int l_offset;
3384
3385 if ( ! BYTES_ARE_IN_FRAME( offset, len, AX25_HEADER_SIZE )((unsigned)(offset) + (unsigned)(15) > (unsigned)(offset) &&
(unsigned)(offset) + (unsigned)(15) <= (unsigned)(len))
)
3386 return false0;
3387
3388 l_offset = offset;
3389 l_offset += AX25_ADDR_LEN7; /* step over dst addr point at src addr */
3390 l_offset += AX25_ADDR_LEN7; /* step over src addr point at either 1st via addr or control byte */
3391 while ( ( pd[ l_offset - 1 ] & 0x01 ) == 0 )
3392 {
3393 /* the via addr and the control byte after it must be in the frame */
3394 if ( ! BYTES_ARE_IN_FRAME( l_offset, len, AX25_ADDR_LEN + 1 )((unsigned)(l_offset) + (unsigned)(7 + 1) > (unsigned)(l_offset
) && (unsigned)(l_offset) + (unsigned)(7 + 1) <= (
unsigned)(len))
)
3395 return false0;
3396 l_offset += AX25_ADDR_LEN7; /* step over a via addr */
3397 }
3398
3399 control = pd[ l_offset ];
3400
3401 /* decode the pid field (if appropriate) */
3402 if ( XDLC_IS_INFORMATION( control )(((control) & 0x01) == 0x00 || (control) == (0x00|0x03)) )
3403 {
3404 if ( ! BYTES_ARE_IN_FRAME( l_offset, len, 2 )((unsigned)(l_offset) + (unsigned)(2) > (unsigned)(l_offset
) && (unsigned)(l_offset) + (unsigned)(2) <= (unsigned
)(len))
)
3405 return false0;
3406 l_offset += 1; /* step over control byte point at pid */
3407 pid = pd[ l_offset ];
3408
3409 l_offset += 1; /* step over the pid and point to the first byte of the payload */
3410 return try_capture_dissector("ax25.pid", pid & 0x0ff, pd, l_offset, len, cpinfo, pseudo_header);
3411 }
3412 return false0;
3413}
3414
3415/* Station table */
3416UAT_CSTRING_CB_DEF(ax25_stations, callsign, ax25_station_uat_t)static void ax25_stations_callsign_set_cb(void* rec, const char
* buf, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* new_buf = g_strndup
(buf,len); (__builtin_object_size (((((ax25_station_uat_t*)rec
)->callsign)), 0) != ((size_t) - 1)) ? g_free_sized ((((ax25_station_uat_t
*)rec)->callsign), __builtin_object_size (((((ax25_station_uat_t
*)rec)->callsign)), 0)) : (g_free) ((((ax25_station_uat_t*
)rec)->callsign)); (((ax25_station_uat_t*)rec)->callsign
) = new_buf; } static void ax25_stations_callsign_tostr_cb(void
* rec, char** out_ptr, unsigned* out_len, const void* u1 __attribute__
((unused)), const void* u2 __attribute__((unused))) { if (((ax25_station_uat_t
*)rec)->callsign ) { *out_ptr = g_strdup_inline ((((ax25_station_uat_t
*)rec)->callsign)); *out_len = (unsigned)strlen((((ax25_station_uat_t
*)rec)->callsign)); } else { *out_ptr = g_strdup_inline (""
); *out_len = 0; } }
3417UAT_DEC_CB_DEF(ax25_stations, t1_ms, ax25_station_uat_t)static void ax25_stations_t1_ms_set_cb(void* rec, const char*
buf, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* tmp_str = g_strndup
(buf,len); ws_strtou32(tmp_str, ((void*)0), &((ax25_station_uat_t
*)rec)->t1_ms); (__builtin_object_size ((tmp_str), 0) != (
(size_t) - 1)) ? g_free_sized (tmp_str, __builtin_object_size
((tmp_str), 0)) : (g_free) (tmp_str); } static void ax25_stations_t1_ms_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* u1
__attribute__((unused)), const void* u2 __attribute__((unused
))) { *out_ptr = wmem_strdup_printf(((void*)0), "%u",((ax25_station_uat_t
*)rec)->t1_ms); *out_len = (unsigned)strlen(*out_ptr); }
3418UAT_DEC_CB_DEF(ax25_stations, t3_s, ax25_station_uat_t)static void ax25_stations_t3_s_set_cb(void* rec, const char* buf
, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* tmp_str = g_strndup
(buf,len); ws_strtou32(tmp_str, ((void*)0), &((ax25_station_uat_t
*)rec)->t3_s); (__builtin_object_size ((tmp_str), 0) != ((
size_t) - 1)) ? g_free_sized (tmp_str, __builtin_object_size (
(tmp_str), 0)) : (g_free) (tmp_str); } static void ax25_stations_t3_s_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* u1
__attribute__((unused)), const void* u2 __attribute__((unused
))) { *out_ptr = wmem_strdup_printf(((void*)0), "%u",((ax25_station_uat_t
*)rec)->t3_s); *out_len = (unsigned)strlen(*out_ptr); }
3419UAT_DEC_CB_DEF(ax25_stations, n2, ax25_station_uat_t)static void ax25_stations_n2_set_cb(void* rec, const char* buf
, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* tmp_str = g_strndup
(buf,len); ws_strtou32(tmp_str, ((void*)0), &((ax25_station_uat_t
*)rec)->n2); (__builtin_object_size ((tmp_str), 0) != ((size_t
) - 1)) ? g_free_sized (tmp_str, __builtin_object_size ((tmp_str
), 0)) : (g_free) (tmp_str); } static void ax25_stations_n2_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* u1
__attribute__((unused)), const void* u2 __attribute__((unused
))) { *out_ptr = wmem_strdup_printf(((void*)0), "%u",((ax25_station_uat_t
*)rec)->n2); *out_len = (unsigned)strlen(*out_ptr); }
3420UAT_DEC_CB_DEF(ax25_stations, n1, ax25_station_uat_t)static void ax25_stations_n1_set_cb(void* rec, const char* buf
, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* tmp_str = g_strndup
(buf,len); ws_strtou32(tmp_str, ((void*)0), &((ax25_station_uat_t
*)rec)->n1); (__builtin_object_size ((tmp_str), 0) != ((size_t
) - 1)) ? g_free_sized (tmp_str, __builtin_object_size ((tmp_str
), 0)) : (g_free) (tmp_str); } static void ax25_stations_n1_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* u1
__attribute__((unused)), const void* u2 __attribute__((unused
))) { *out_ptr = wmem_strdup_printf(((void*)0), "%u",((ax25_station_uat_t
*)rec)->n1); *out_len = (unsigned)strlen(*out_ptr); }
3421UAT_DEC_CB_DEF(ax25_stations, k, ax25_station_uat_t)static void ax25_stations_k_set_cb(void* rec, const char* buf
, unsigned len, const void* u1 __attribute__((unused)), const
void* u2 __attribute__((unused))) { char* tmp_str = g_strndup
(buf,len); ws_strtou32(tmp_str, ((void*)0), &((ax25_station_uat_t
*)rec)->k); (__builtin_object_size ((tmp_str), 0) != ((size_t
) - 1)) ? g_free_sized (tmp_str, __builtin_object_size ((tmp_str
), 0)) : (g_free) (tmp_str); } static void ax25_stations_k_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* u1
__attribute__((unused)), const void* u2 __attribute__((unused
))) { *out_ptr = wmem_strdup_printf(((void*)0), "%u",((ax25_station_uat_t
*)rec)->k); *out_len = (unsigned)strlen(*out_ptr); }
3422UAT_VS_DEF(ax25_stations, version, ax25_station_uat_t, unsigned, AX25_UAT_VERSION_NONE, "Unknown")static void ax25_stations_version_set_cb(void* rec, const char
* buf, unsigned len, const void* vs, const void* u2 __attribute__
((unused))) { unsigned i; char* str = g_strndup(buf,len); const
char* cstr; ((ax25_station_uat_t*)rec)->version = 0; for(
i=0; ( cstr = ((const value_string*)vs)[i].strptr ) ;i++) { if
((strcmp ((const char *) (cstr), (const char *) (str)) == 0)
) { ((ax25_station_uat_t*)rec)->version = (unsigned)((const
value_string*)vs)[i].value; (__builtin_object_size ((str), 0
) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size
((str), 0)) : (g_free) (str); return; } } (__builtin_object_size
((str), 0) != ((size_t) - 1)) ? g_free_sized (str, __builtin_object_size
((str), 0)) : (g_free) (str); } static void ax25_stations_version_tostr_cb
(void* rec, char** out_ptr, unsigned* out_len, const void* vs
, const void* u2 __attribute__((unused))) { unsigned i; for(i
=0;((const value_string*)vs)[i].strptr;i++) { if ( ((const value_string
*)vs)[i].value == ((ax25_station_uat_t*)rec)->version ) { *
out_ptr = g_strdup_inline (((const value_string*)vs)[i].strptr
); *out_len = (unsigned)strlen(*out_ptr); return; } } *out_ptr
= g_strdup_inline ("Unknown"); *out_len = (unsigned)strlen("Unknown"
); }
3423
3424/*
3425 * "CALL" or "CALL-SSID" to the address octets ax25_mask_address() makes:
3426 * up to six letters or digits shifted left one bit, padded with spaces,
3427 * then the SSID (0 if not given) in bits 1-4.
3428 */
3429static bool_Bool
3430ax25_callsign_to_masked(const char *str, uint8_t *masked, char **err)
3431{
3432 const char *p;
3433 unsigned i = 0;
3434 unsigned ssid = 0;
3435 char c;
3436
3437 if (!str || !*str) {
3438 *err = g_strdup("A callsign is required")g_strdup_inline ("A callsign is required");
3439 return false0;
3440 }
3441 for (p = str; *p && *p != '-'; p++) {
3442 c = g_ascii_toupper(*p);
3443 if (i == AX25_ADDR_LEN7 - 1 || !(g_ascii_isupper(c)((g_ascii_table[(guchar) (c)] & G_ASCII_UPPER) != 0) || g_ascii_isdigit(c)((g_ascii_table[(guchar) (c)] & G_ASCII_DIGIT) != 0))) {
3444 *err = ws_strdup_printf("\"%s\" isn't a callsign: up to six letters or digits", str)wmem_strdup_printf(((void*)0), "\"%s\" isn't a callsign: up to six letters or digits"
, str)
;
3445 return false0;
3446 }
3447 masked[i++] = (uint8_t)(c << 1);
3448 }
3449 if (i == 0) {
3450 *err = ws_strdup_printf("\"%s\" has no callsign before the SSID", str)wmem_strdup_printf(((void*)0), "\"%s\" has no callsign before the SSID"
, str)
;
3451 return false0;
3452 }
3453 for (; i < AX25_ADDR_LEN7 - 1; i++)
3454 masked[i] = ' ' << 1;
3455 if (*p == '-') {
3456 if (!ws_strtou32(p + 1, NULL((void*)0), &ssid) || ssid > 15) {
3457 *err = ws_strdup_printf("\"%s\": the SSID must be 0 to 15", str)wmem_strdup_printf(((void*)0), "\"%s\": the SSID must be 0 to 15"
, str)
;
3458 return false0;
3459 }
3460 }
3461 masked[AX25_ADDR_LEN7 - 1] = (uint8_t)((ssid << 1) & AX25_SSID_SSID0x1E);
3462 return true1;
3463}
3464
3465static void *
3466ax25_stations_copy_cb(void *dest, const void *src, size_t len _U___attribute__((unused)))
3467{
3468 const ax25_station_uat_t *o = (const ax25_station_uat_t *)src;
3469 ax25_station_uat_t *d = (ax25_station_uat_t *)dest;
3470
3471 *d = *o;
3472 d->callsign = g_strdup(o->callsign)g_strdup_inline (o->callsign);
3473 return d;
3474}
3475
3476static bool_Bool
3477ax25_stations_update_cb(void *r, char **err)
3478{
3479 ax25_station_uat_t *rec = (ax25_station_uat_t *)r;
3480
3481 return ax25_callsign_to_masked(rec->callsign, rec->masked, err);
3482}
3483
3484static void
3485ax25_stations_free_cb(void *r)
3486{
3487 ax25_station_uat_t *rec = (ax25_station_uat_t *)r;
3488
3489 g_free(rec->callsign)(__builtin_object_size ((rec->callsign), 0) != ((size_t) -
1)) ? g_free_sized (rec->callsign, __builtin_object_size (
(rec->callsign), 0)) : (g_free) (rec->callsign)
;
3490}
3491
3492static void
3493ax25_init(void)
3494{
3495 ax25_stream_count = 0;
3496}
3497
3498void
3499proto_register_ax25(void)
3500{
3501 /* Setup list of header fields */
3502 static hf_register_info hf[] = {
3503 { &hf_ax25_dst,
3504 { "Destination", "ax25.dst",
3505 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3506 "Destination callsign", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3507 },
3508 { &hf_ax25_src,
3509 { "Source", "ax25.src",
3510 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3511 "Source callsign", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3512 },
3513 { &hf_ax25_via[ 0 ],
3514 { "Via 1", "ax25.via1",
3515 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3516 "Via callsign 1", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3517 },
3518 { &hf_ax25_via[ 1 ],
3519 { "Via 2", "ax25.via2",
3520 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3521 "Via callsign 2", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3522 },
3523 { &hf_ax25_via[ 2 ],
3524 { "Via 3", "ax25.via3",
3525 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3526 "Via callsign 3", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3527 },
3528 { &hf_ax25_via[ 3 ],
3529 { "Via 4", "ax25.via4",
3530 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3531 "Via callsign 4", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3532 },
3533 { &hf_ax25_via[ 4 ],
3534 { "Via 5", "ax25.via5",
3535 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3536 "Via callsign 5", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3537 },
3538 { &hf_ax25_via[ 5 ],
3539 { "Via 6", "ax25.via6",
3540 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3541 "Via callsign 6", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3542 },
3543 { &hf_ax25_via[ 6 ],
3544 { "Via 7", "ax25.via7",
3545 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3546 "Via callsign 7", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3547 },
3548 { &hf_ax25_via[ 7 ],
3549 { "Via 8", "ax25.via8",
3550 FT_AX25, BASE_NONE, NULL((void*)0), 0x0,
3551 "Via callsign 8", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3552 },
3553 { &hf_ax25_ctl,
3554 { "Control", "ax25.ctl",
3555 FT_UINT8, BASE_HEX, NULL((void*)0), 0x0,
3556 "Control field", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3557 },
3558 { &hf_ax25_ctl_ext,
3559 { "Control", "ax25.ctl_ext",
3560 FT_UINT16, BASE_HEX, NULL((void*)0), 0x0,
3561 "Control field", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3562 },
3563 { &hf_ax25_n_r,
3564 { "n(r)", "ax25.ctl.n_r",
3565 FT_UINT8, BASE_DEC, NULL((void*)0), XDLC_N_R_MASK0xE0,
3566 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3567 },
3568 { &hf_ax25_n_r_ext,
3569 { "n(r) ext", "ax25.ctl.n_r_ext",
3570 FT_UINT16, BASE_DEC, NULL((void*)0), XDLC_N_R_EXT_MASK0xFE00,
3571 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3572 },
3573 { &hf_ax25_n_s,
3574 { "n(s)", "ax25.ctl.n_s",
3575 FT_UINT8, BASE_DEC, NULL((void*)0), XDLC_N_S_MASK0x0E,
3576 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3577 },
3578 { &hf_ax25_n_s_ext,
3579 { "n(s) ext", "ax25.ctl.n_s_ext",
3580 FT_UINT16, BASE_DEC, NULL((void*)0), XDLC_N_S_EXT_MASK0x00FE,
3581 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3582 },
3583 { &hf_ax25_p,
3584 { "Poll", "ax25.ctl.p",
3585 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, XDLC_P_F0x10,
3586 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3587 },
3588 { &hf_ax25_f_ext,
3589 { "Final", "ax25.ctl.f_ext",
3590 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, XDLC_P_F_EXT0x0100,
3591 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3592 },
3593 { &hf_ax25_p_ext,
3594 { "Poll", "ax25.ctl.p_ext",
3595 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, XDLC_P_F_EXT0x0100,
3596 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3597 },
3598 { &hf_ax25_f,
3599 { "Final", "ax25.ctl.f",
3600 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, XDLC_P_F0x10,
3601 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3602 },
3603 { &hf_ax25_pf,
3604 { "Poll/Final", "ax25.ctl.pf",
3605 FT_BOOLEAN, 8, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, XDLC_P_F0x10,
3606 "P/F bit of a frame whose C/R is unknown (pre-2.0 encoding)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3607 },
3608 { &hf_ax25_pf_ext,
3609 { "Poll/Final", "ax25.ctl.pf_ext",
3610 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, XDLC_P_F_EXT0x0100,
3611 "P/F bit of a frame whose C/R is unknown (pre-2.0 encoding)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3612 },
3613 { &hf_ax25_ftype_s,
3614 { "Frame type", "ax25.ctl.ftype_s",
3615 FT_UINT8, BASE_HEX, VALS(stype_vals)((0 ? (const struct _value_string*)0 : ((stype_vals)))), XDLC_S_FTYPE_MASK0x0C,
3616 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3617 },
3618 { &hf_ax25_ftype_s_ext,
3619 { "Frame type", "ax25.ctl.ftype_s_ext",
3620 FT_UINT16, BASE_HEX, VALS(stype_vals)((0 ? (const struct _value_string*)0 : ((stype_vals)))), XDLC_S_FTYPE_MASK0x0C,
3621 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3622 },
3623 { &hf_ax25_ftype_i,
3624 { "Frame type", "ax25.ctl.ftype_i",
3625 FT_UINT8, BASE_HEX, VALS(ftype_vals)((0 ? (const struct _value_string*)0 : ((ftype_vals)))), XDLC_I_MASK0x01,
3626 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3627 },
3628 { &hf_ax25_ftype_i_ext,
3629 { "Frame type", "ax25.ctl.ftype_i_ext",
3630 FT_UINT16, BASE_HEX, VALS(ftype_vals)((0 ? (const struct _value_string*)0 : ((ftype_vals)))), XDLC_I_MASK0x01,
3631 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3632 },
3633 { &hf_ax25_ftype_su,
3634 { "Frame type", "ax25.ctl.ftype_su",
3635 FT_UINT8, BASE_HEX, VALS(ftype_vals)((0 ? (const struct _value_string*)0 : ((ftype_vals)))), XDLC_S_U_MASK0x03,
3636 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3637 },
3638 { &hf_ax25_ftype_su_ext,
3639 { "Frame type", "ax25.ctl.ftype_su_ext",
3640 FT_UINT16, BASE_HEX, VALS(ftype_vals)((0 ? (const struct _value_string*)0 : ((ftype_vals)))), XDLC_S_U_MASK0x03,
3641 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3642 },
3643 { &hf_ax25_u_cmd,
3644 { "Frame type", "ax25.ctl.u_cmd",
3645 FT_UINT8, BASE_HEX, VALS(modifier_vals_cmd)((0 ? (const struct _value_string*)0 : ((modifier_vals_cmd)))
)
, XDLC_U_MODIFIER_MASK0xEC,
3646 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3647 },
3648 { &hf_ax25_u_resp,
3649 { "Frame type", "ax25.ctl.u_resp",
3650 FT_UINT8, BASE_HEX, VALS(modifier_vals_resp)((0 ? (const struct _value_string*)0 : ((modifier_vals_resp))
))
, XDLC_U_MODIFIER_MASK0xEC,
3651 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3652 },
3653 { &hf_ax25_pid,
3654 { "Protocol ID", "ax25.pid",
3655 FT_UINT8, BASE_HEX, VALS(pid_vals)((0 ? (const struct _value_string*)0 : ((pid_vals)))), 0x0,
3656 "Protocol identifier", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3657 },
3658 { &hf_ax25_stream,
3659 { "Stream index", "ax25.stream",
3660 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3661 "Index of the AX.25 connection; a new stream starts at each connection attempt. UI frames have none", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3662 },
3663 { &hf_ax25_version,
3664 { "Version", "ax25.version",
3665 FT_UINT8, BASE_DEC, VALS(ax25_version_vals)((0 ? (const struct _value_string*)0 : ((ax25_version_vals)))
)
, 0x0,
3666 "Protocol version implied by the C/R bits (section 6.1.2)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3667 },
3668 { &hf_ax25_cr,
3669 { "Command/Response", "ax25.cr",
3670 FT_UINT8, BASE_DEC, VALS(ax25_cr_vals)((0 ? (const struct _value_string*)0 : ((ax25_cr_vals)))), 0x0,
3671 "From the C/R bits, or from the frame type for pre-2.0 frames", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3672 },
3673 { &hf_ax25_modulo,
3674 { "Modulo", "ax25.modulo",
3675 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
3676 "Sequence number modulo the control field was decoded with", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3677 },
3678 { &hf_ax25_modulo_source,
3679 { "Modulo source", "ax25.modulo.source",
3680 FT_UINT8, BASE_DEC, VALS(ax25_modsrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_modsrc_vals)))), 0x0,
3681 "How the modulo in effect was determined", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3682 },
3683 { &hf_ax25_modulo_frame,
3684 { "Modulo set in frame", "ax25.modulo.frame",
3685 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
3686 "The frame the modulo in effect was determined from", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3687 },
3688 { &hf_ax25_link_state,
3689 { "Link state", "ax25.link.state",
3690 FT_UINT8, BASE_DEC, VALS(ax25_link_state_vals)((0 ? (const struct _value_string*)0 : ((ax25_link_state_vals
))))
, 0x0,
3691 "State of the link after this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3692 },
3693 { &hf_ax25_link_state_frame,
3694 { "Link state set in frame", "ax25.link.state_frame",
3695 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
3696 "The frame that caused the link state this frame is out of place in", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3697 },
3698 { &hf_ax25_link_refused,
3699 { "Refused SABM(E) in frame", "ax25.link.refused",
3700 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0x0,
3701 "The connection request this DM or FRMR refuses", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3702 },
3703 { &hf_ax25_link_fallback,
3704 { "SABME rejected in frame", "ax25.link.fallback",
3705 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
3706 "This SABM falls back to v2.0 after that frame rejected a SABME", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3707 },
3708 { &hf_ax25_link_frmr_xid,
3709 { "Rejected XID in frame", "ax25.link.frmr_xid",
3710 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_RESPONSE)((gpointer) (glong) (FT_FRAMENUM_RESPONSE)), 0x0,
3711 "The XID command this FRMR answers", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3712 },
3713 { &hf_ax25_link_idle,
3714 { "Idle time", "ax25.link.idle",
3715 FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,
3716 "Silence on the link before this frame", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3717 },
3718 { &hf_ax25_dup_of,
3719 { "Digipeated copy of frame", "ax25.link.dup_of",
3720 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_DUP_ACK)((gpointer) (glong) (FT_FRAMENUM_DUP_ACK)), 0x0,
3721 "This frame is a digipeated copy of that frame (only the H bits differ)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3722 },
3723 { &hf_ax25_param_version,
3724 { "Version in effect", "ax25.param.version",
3725 FT_UINT8, BASE_DEC, VALS(ax25_veff_vals)((0 ? (const struct _value_string*)0 : ((ax25_veff_vals)))), 0x0,
3726 "AX.25 version whose defaults apply to this link (section 6.3.2)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3727 },
3728 { &hf_ax25_param_version_source,
3729 { "Version source", "ax25.param.version.source",
3730 FT_UINT8, BASE_DEC, VALS(ax25_vsrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_vsrc_vals)))), 0x0,
3731 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3732 },
3733 { &hf_ax25_param_version_frame,
3734 { "Version seen in frame", "ax25.param.version.frame",
3735 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
3736 "The latest frame that showed the version", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3737 },
3738 { &hf_ax25_param_t1,
3739 { "T1", "ax25.param.t1",
3740 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_milliseconds)((0 ? (const struct unit_name_string*)0 : ((&units_milliseconds
))))
, 0x0,
3741 "Acknowledgement timer of the sender", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3742 },
3743 { &hf_ax25_param_t1_source,
3744 { "T1 source", "ax25.param.t1.source",
3745 FT_UINT8, BASE_DEC, VALS(ax25_psrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_psrc_vals)))), 0x0,
3746 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3747 },
3748 { &hf_ax25_param_t3,
3749 { "T3", "ax25.param.t3",
3750 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_seconds)((0 ? (const struct unit_name_string*)0 : ((&units_seconds
))))
, 0x0,
3751 "Inactive link timer of the sender (0: idle timeout off)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3752 },
3753 { &hf_ax25_param_t3_source,
3754 { "T3 source", "ax25.param.t3.source",
3755 FT_UINT8, BASE_DEC, VALS(ax25_psrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_psrc_vals)))), 0x0,
3756 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3757 },
3758 { &hf_ax25_param_n2,
3759 { "N2", "ax25.param.n2",
3760 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3761 "Maximum number of retries of the sender", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3762 },
3763 { &hf_ax25_param_n2_source,
3764 { "N2 source", "ax25.param.n2.source",
3765 FT_UINT8, BASE_DEC, VALS(ax25_psrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_psrc_vals)))), 0x0,
3766 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3767 },
3768 { &hf_ax25_param_n1,
3769 { "N1", "ax25.param.n1",
3770 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_octet_octets)((0 ? (const struct unit_name_string*)0 : ((&units_octet_octets
))))
, 0x0,
3771 "Longest I field the receiver accepts", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3772 },
3773 { &hf_ax25_param_n1_source,
3774 { "N1 source", "ax25.param.n1.source",
3775 FT_UINT8, BASE_DEC, VALS(ax25_psrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_psrc_vals)))), 0x0,
3776 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3777 },
3778 { &hf_ax25_param_k,
3779 { "k", "ax25.param.k",
3780 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3781 "Largest window the receiver accepts", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3782 },
3783 { &hf_ax25_param_k_source,
3784 { "k source", "ax25.param.k.source",
3785 FT_UINT8, BASE_DEC, VALS(ax25_psrc_vals)((0 ? (const struct _value_string*)0 : ((ax25_psrc_vals)))), 0x0,
3786 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3787 },
3788 { &hf_ax25_param_xid_frame,
3789 { "Set by XID in frame", "ax25.param.xid_frame",
3790 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
3791 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3792 },
3793 { &hf_ax25_xidn_command_frame,
3794 { "Answers the XID command in frame", "ax25.xid.neg.command_frame",
3795 FT_FRAMENUM, BASE_NONE, FRAMENUM_TYPE(FT_FRAMENUM_REQUEST)((gpointer) (glong) (FT_FRAMENUM_REQUEST)), 0x0,
3796 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3797 },
3798 { &hf_ax25_xidn_duplex,
3799 { "Duplex", "ax25.xid.neg.duplex",
3800 FT_UINT8, BASE_DEC, VALS(ax25_xidn_duplex_vals)((0 ? (const struct _value_string*)0 : ((ax25_xidn_duplex_vals
))))
, 0x0,
3801 "Offered (command) or selected (response) by Classes of Procedures", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3802 },
3803 { &hf_ax25_xidn_reject,
3804 { "Reject", "ax25.xid.neg.reject",
3805 FT_UINT8, BASE_DEC, VALS(ax25_xidn_reject_vals)((0 ? (const struct _value_string*)0 : ((ax25_xidn_reject_vals
))))
, 0x0,
3806 "Highest offered (command) or selected (response) by HDLC Optional Functions", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3807 },
3808 { &hf_ax25_xidn_modulo,
3809 { "Modulo", "ax25.xid.neg.modulo",
3810 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
3811 "Highest offered (command) or selected (response) by HDLC Optional Functions", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3812 },
3813 { &hf_ax25_xidn_segmenter,
3814 { "Segmenter/reassembler", "ax25.xid.neg.segmenter",
3815 FT_BOOLEAN, BASE_NONE, TFS(&tfs_enabled_disabled)((0 ? (const struct true_false_string*)0 : ((&tfs_enabled_disabled
))))
, 0x0,
3816 "Offered (command) or selected (response) by HDLC Optional Functions", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3817 },
3818 { &hf_ax25_xidn_t1,
3819 { "T1", "ax25.xid.neg.t1",
3820 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_milliseconds)((0 ? (const struct unit_name_string*)0 : ((&units_milliseconds
))))
, 0x0,
3821 "Acknowledge timer offered (command) or selected (response)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3822 },
3823 { &hf_ax25_xidn_n2,
3824 { "N2", "ax25.xid.neg.n2",
3825 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3826 "Retries offered (command) or selected (response)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3827 },
3828 { &hf_ax25_xidn_n1,
3829 { "N1", "ax25.xid.neg.n1",
3830 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_octet_octets)((0 ? (const struct unit_name_string*)0 : ((&units_octet_octets
))))
, 0x0,
3831 "Longest I field the sender of this XID accepts (notification)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3832 },
3833 { &hf_ax25_xidn_k,
3834 { "k", "ax25.xid.neg.k",
3835 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3836 "Largest window the sender of this XID accepts (notification)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3837 },
3838 { &hf_ax25_xidn_kept,
3839 { "Kept", "ax25.xid.neg.kept",
3840 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3841 "The command offered a parameter the response leaves out: its current value is kept", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3842 },
3843 { &hf_ax25_xidn_v22,
3844 { "Both stations use AX.25 v2.2 or later", "ax25.xid.neg.v22",
3845 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3846 "An XID response establishes v2.2, with segmenter and selective reject (section 6.3.2)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3847 },
3848 { &hf_ax25_seg,
3849 { "Segment header", "ax25.seg",
3850 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3851 "Segmenter/reassembler header (section 6.6)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3852 },
3853 { &hf_ax25_seg_first,
3854 { "First segment", "ax25.seg.first",
3855 FT_BOOLEAN, 8, TFS(&tfs_yes_no)((0 ? (const struct true_false_string*)0 : ((&tfs_yes_no)
)))
, AX25_SEG_FIRST0x80,
3856 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3857 },
3858 { &hf_ax25_seg_remaining,
3859 { "Segments remaining", "ax25.seg.remaining",
3860 FT_UINT8, BASE_DEC, NULL((void*)0), AX25_SEG_REMAINING0x7F,
3861 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3862 },
3863 { &hf_ax25_seg_pid,
3864 { "Protocol ID", "ax25.seg.pid",
3865 FT_UINT8, BASE_HEX, VALS(pid_vals)((0 ? (const struct _value_string*)0 : ((pid_vals)))), 0x0,
3866 "PID of the segmented data unit, in the first segment", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3867 },
3868 { &hf_ax25_seg_first_frame,
3869 { "First segment in frame", "ax25.seg.first_frame",
3870 FT_FRAMENUM, BASE_NONE, NULL((void*)0), 0x0,
3871 "First segment of the sequence", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3872 },
3873 { &hf_ax25_seg_gap,
3874 { "Time since previous segment", "ax25.seg.gap",
3875 FT_RELATIVE_TIME, BASE_NONE, NULL((void*)0), 0x0,
3876 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3877 },
3878 { &hf_ax25_xid,
3879 { "XID information", "ax25.xid",
3880 FT_NONE, BASE_NONE, NULL((void*)0), 0x0,
3881 "ISO 8885 general purpose XID information field (section 4.3.3.7)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3882 },
3883 { &hf_ax25_xid_fi,
3884 { "Format identifier", "ax25.xid.fi",
3885 FT_UINT8, BASE_HEX, NULL((void*)0), 0x0,
3886 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3887 },
3888 { &hf_ax25_xid_gi,
3889 { "Group identifier", "ax25.xid.gi",
3890 FT_UINT8, BASE_HEX, NULL((void*)0), 0x0,
3891 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3892 },
3893 { &hf_ax25_xid_gl,
3894 { "Group length", "ax25.xid.gl",
3895 FT_UINT16, BASE_DEC, NULL((void*)0), 0x0,
3896 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3897 },
3898 { &hf_ax25_xid_pi,
3899 { "Parameter identifier", "ax25.xid.pi",
3900 FT_UINT8, BASE_DEC, VALS(ax25_xid_pi_vals)((0 ? (const struct _value_string*)0 : ((ax25_xid_pi_vals)))), 0x0,
3901 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3902 },
3903 { &hf_ax25_xid_pl,
3904 { "Parameter length", "ax25.xid.pl",
3905 FT_UINT8, BASE_DEC, NULL((void*)0), 0x0,
3906 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3907 },
3908 { &hf_ax25_xid_pv,
3909 { "Parameter value", "ax25.xid.pv",
3910 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
3911 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3912 },
3913 { &hf_ax25_xid_trailing,
3914 { "Trailing octets", "ax25.xid.trailing",
3915 FT_BYTES, BASE_NONE, NULL((void*)0), 0x0,
3916 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3917 },
3918 { &hf_ax25_xid_cop,
3919 { "Classes of Procedures", "ax25.xid.cop",
3920 FT_UINT16, BASE_HEX, NULL((void*)0), 0x0,
3921 "Bit field, least significant octet first", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3922 },
3923 { &hf_ax25_xid_hdlc,
3924 { "HDLC Optional Functions", "ax25.xid.hdlc",
3925 FT_UINT24, BASE_HEX, NULL((void*)0), 0x0,
3926 "Bit field, least significant octet first", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3927 },
3928 { &hf_ax25_xid_n1_tx,
3929 { "I field length Tx", "ax25.xid.n1_tx",
3930 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_bit_bits)((0 ? (const struct unit_name_string*)0 : ((&units_bit_bits
))))
, 0x0,
3931 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3932 },
3933 { &hf_ax25_xid_n1_rx,
3934 { "I field length Rx", "ax25.xid.n1_rx",
3935 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_bit_bits)((0 ? (const struct unit_name_string*)0 : ((&units_bit_bits
))))
, 0x0,
3936 "Longest I field the sender of this XID accepts (N1 x 8)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3937 },
3938 { &hf_ax25_xid_k_tx,
3939 { "Window size Tx", "ax25.xid.k_tx",
3940 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3941 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3942 },
3943 { &hf_ax25_xid_k_rx,
3944 { "Window size Rx", "ax25.xid.k_rx",
3945 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3946 "Largest window the sender of this XID accepts", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3947 },
3948 { &hf_ax25_xid_t1,
3949 { "Acknowledge timer", "ax25.xid.t1",
3950 FT_UINT32, BASE_DEC|BASE_UNIT_STRING0x00001000, UNS(&units_milliseconds)((0 ? (const struct unit_name_string*)0 : ((&units_milliseconds
))))
, 0x0,
3951 "T1", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3952 },
3953 { &hf_ax25_xid_n2,
3954 { "Retries", "ax25.xid.n2",
3955 FT_UINT32, BASE_DEC, NULL((void*)0), 0x0,
3956 "N2 (the spec calls it N1 in sections 4.3.3.7 and 6.3.2)", HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3957 },
3958 { &hf_ax25_xid_cop_abm,
3959 { "Balanced ABM", "ax25.xid.cop.abm",
3960 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_ABM0x0001,
3961 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3962 },
3963 { &hf_ax25_xid_cop_nrm_pri,
3964 { "Unbalanced NRM primary", "ax25.xid.cop.nrm_pri",
3965 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_NRM_PRI0x0002,
3966 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3967 },
3968 { &hf_ax25_xid_cop_nrm_sec,
3969 { "Unbalanced NRM secondary", "ax25.xid.cop.nrm_sec",
3970 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_NRM_SEC0x0004,
3971 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3972 },
3973 { &hf_ax25_xid_cop_arm_pri,
3974 { "Unbalanced ARM primary", "ax25.xid.cop.arm_pri",
3975 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_ARM_PRI0x0008,
3976 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3977 },
3978 { &hf_ax25_xid_cop_arm_sec,
3979 { "Unbalanced ARM secondary", "ax25.xid.cop.arm_sec",
3980 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_ARM_SEC0x0010,
3981 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3982 },
3983 { &hf_ax25_xid_cop_half,
3984 { "Half duplex", "ax25.xid.cop.half",
3985 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_HALF_DUPLEX0x0020,
3986 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3987 },
3988 { &hf_ax25_xid_cop_full,
3989 { "Full duplex", "ax25.xid.cop.full",
3990 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_FULL_DUPLEX0x0040,
3991 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3992 },
3993 { &hf_ax25_xid_cop_reserved,
3994 { "Reserved", "ax25.xid.cop.reserved",
3995 FT_BOOLEAN, 16, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_COP_RESERVED0xFF80,
3996 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
3997 },
3998 { &hf_ax25_xid_hdlc_reserved0,
3999 { "Reserved (bit 0)", "ax25.xid.hdlc.reserved0",
4000 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(0)(1U << (0)),
4001 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4002 },
4003 { &hf_ax25_xid_hdlc_rej,
4004 { "REJ command/response", "ax25.xid.hdlc.rej",
4005 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(1)(1U << (1)),
4006 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4007 },
4008 { &hf_ax25_xid_hdlc_srej,
4009 { "SREJ command/response", "ax25.xid.hdlc.srej",
4010 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(2)(1U << (2)),
4011 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4012 },
4013 { &hf_ax25_xid_hdlc_ui,
4014 { "UI command/response", "ax25.xid.hdlc.ui",
4015 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(3)(1U << (3)),
4016 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4017 },
4018 { &hf_ax25_xid_hdlc_sim_rim,
4019 { "SIM command/RIM response", "ax25.xid.hdlc.sim_rim",
4020 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(4)(1U << (4)),
4021 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4022 },
4023 { &hf_ax25_xid_hdlc_up,
4024 { "UP command", "ax25.xid.hdlc.up",
4025 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(5)(1U << (5)),
4026 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4027 },
4028 { &hf_ax25_xid_hdlc_basic_addr,
4029 { "Basic address", "ax25.xid.hdlc.basic_addr",
4030 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(6)(1U << (6)),
4031 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4032 },
4033 { &hf_ax25_xid_hdlc_ext_addr,
4034 { "Extended address", "ax25.xid.hdlc.ext_addr",
4035 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(7)(1U << (7)),
4036 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4037 },
4038 { &hf_ax25_xid_hdlc_del_i_resp,
4039 { "Delete I response", "ax25.xid.hdlc.del_i_resp",
4040 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(8)(1U << (8)),
4041 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4042 },
4043 { &hf_ax25_xid_hdlc_del_i_cmd,
4044 { "Delete I command", "ax25.xid.hdlc.del_i_cmd",
4045 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(9)(1U << (9)),
4046 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4047 },
4048 { &hf_ax25_xid_hdlc_mod8,
4049 { "Modulo 8", "ax25.xid.hdlc.mod8",
4050 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(10)(1U << (10)),
4051 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4052 },
4053 { &hf_ax25_xid_hdlc_mod128,
4054 { "Modulo 128", "ax25.xid.hdlc.mod128",
4055 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(11)(1U << (11)),
4056 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4057 },
4058 { &hf_ax25_xid_hdlc_rset,
4059 { "RSET command", "ax25.xid.hdlc.rset",
4060 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(12)(1U << (12)),
4061 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4062 },
4063 { &hf_ax25_xid_hdlc_test,
4064 { "TEST command/response", "ax25.xid.hdlc.test",
4065 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(13)(1U << (13)),
4066 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4067 },
4068 { &hf_ax25_xid_hdlc_rd,
4069 { "RD response", "ax25.xid.hdlc.rd",
4070 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(14)(1U << (14)),
4071 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4072 },
4073 { &hf_ax25_xid_hdlc_fcs16,
4074 { "16-bit FCS", "ax25.xid.hdlc.fcs16",
4075 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(15)(1U << (15)),
4076 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4077 },
4078 { &hf_ax25_xid_hdlc_fcs32,
4079 { "32-bit FCS", "ax25.xid.hdlc.fcs32",
4080 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(16)(1U << (16)),
4081 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4082 },
4083 { &hf_ax25_xid_hdlc_sync_tx,
4084 { "Synchronous transmit", "ax25.xid.hdlc.sync_tx",
4085 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(17)(1U << (17)),
4086 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4087 },
4088 { &hf_ax25_xid_hdlc_ss_tx,
4089 { "Start/stop transmission", "ax25.xid.hdlc.ss_tx",
4090 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(18)(1U << (18)),
4091 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4092 },
4093 { &hf_ax25_xid_hdlc_ss_flow,
4094 { "Start/stop basic flow control", "ax25.xid.hdlc.ss_flow",
4095 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(19)(1U << (19)),
4096 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4097 },
4098 { &hf_ax25_xid_hdlc_ss_octet,
4099 { "Start/stop octet transparency", "ax25.xid.hdlc.ss_octet",
4100 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(20)(1U << (20)),
4101 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4102 },
4103 { &hf_ax25_xid_hdlc_srej_multi,
4104 { "SREJ multiframe", "ax25.xid.hdlc.srej_multi",
4105 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(21)(1U << (21)),
4106 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4107 },
4108 { &hf_ax25_xid_hdlc_segmenter,
4109 { "Segmenter/reassembler", "ax25.xid.hdlc.segmenter",
4110 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(22)(1U << (22)),
4111 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4112 },
4113 { &hf_ax25_xid_hdlc_reserved23,
4114 { "Reserved (bit 23)", "ax25.xid.hdlc.reserved23",
4115 FT_BOOLEAN, 24, TFS(&tfs_set_notset)((0 ? (const struct true_false_string*)0 : ((&tfs_set_notset
))))
, AX25_HDLC_BIT(23)(1U << (23)),
4116 NULL((void*)0), HFILL-1, 0, HF_REF_TYPE_NONE, -1, ((void*)0) }
4117 },
4118 };
4119
4120 /* Setup protocol subtree array */
4121 static int *ett[] = {
4122 &ett_ax25,
4123 &ett_ax25_ctl,
4124 &ett_ax25_link,
4125 &ett_ax25_params,
4126 &ett_ax25_xid,
4127 &ett_ax25_xid_param,
4128 &ett_ax25_xid_bits,
4129 &ett_ax25_seg,
4130 &ett_ax25_xidn,
4131 };
4132
4133 static ei_register_info ei[] = {
4134 { &ei_ax25_modulo_assumed,
4135 { "ax25.modulo.assumed", PI_ASSUMPTION0x0d000000, PI_NOTE0x00400000,
4136 "Modulo not known yet (no SABM(E)/UA or decisive S frame seen); assuming 8", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4137 },
4138 { &ei_ax25_modulo_inferred,
4139 { "ax25.modulo.inferred", PI_ASSUMPTION0x0d000000, PI_CHAT0x00200000,
4140 "Modulo inferred from an S frame", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4141 },
4142 { &ei_ax25_modulo_no_ua,
4143 { "ax25.modulo.no_ua", PI_ASSUMPTION0x0d000000, PI_NOTE0x00400000,
4144 "Modulo taken from a SABM(E) whose UA was not captured", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4145 },
4146 { &ei_ax25_s128_bits,
4147 { "ax25.ctl.s128_bits", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4148 "Bits 4-7 of a modulo 128 S frame must be zero (Figure 4.1b)", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4149 },
4150 { &ei_ax25_pre20_v22_feature,
4151 { "ax25.pre20.v22_feature", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4152 "Version 2.2 feature on a link with a pre-2.0 station", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4153 },
4154 { &ei_ax25_cr_mixed,
4155 { "ax25.cr.mixed", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4156 "Pre-2.0 and 2.x C/R encoding mixed in one direction", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4157 },
4158 { &ei_ax25_after_disc,
4159 { "ax25.link.after_disc", PI_SEQUENCE0x02000000, PI_WARN0x00600000,
4160 "Frame after the link was disconnected by DISC/UA", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4161 },
4162 { &ei_ax25_after_dm,
4163 { "ax25.link.after_dm", PI_SEQUENCE0x02000000, PI_WARN0x00600000,
4164 "Frame after DM", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4165 },
4166 { &ei_ax25_after_frmr,
4167 { "ax25.link.after_frmr", PI_SEQUENCE0x02000000, PI_WARN0x00600000,
4168 "Frame after FRMR", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4169 },
4170 { &ei_ax25_disconnecting,
4171 { "ax25.link.disconnecting", PI_SEQUENCE0x02000000, PI_NOTE0x00400000,
4172 "Frame while disconnecting", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4173 },
4174 { &ei_ax25_after_idle,
4175 { "ax25.link.after_idle", PI_SEQUENCE0x02000000, PI_NOTE0x00400000,
4176 "Frame after the link was presumed down (idle timeout)", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4177 },
4178 { &ei_ax25_capture_gap,
4179 { "ax25.link.capture_gap", PI_SEQUENCE0x02000000, PI_CHAT0x00200000,
4180 "Sequence numbers continue after an idle timeout: possible capture gap", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4181 },
4182 { &ei_ax25_refused,
4183 { "ax25.link.refused.expert", PI_SEQUENCE0x02000000, PI_NOTE0x00400000,
4184 "Connection refused", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4185 },
4186 { &ei_ax25_fallback,
4187 { "ax25.link.fallback.expert", PI_PROTOCOL0x09000000, PI_NOTE0x00400000,
4188 "SABM after a rejected SABME: falling back to v2.0", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4189 },
4190 { &ei_ax25_frmr_xid,
4191 { "ax25.link.frmr_xid.expert", PI_PROTOCOL0x09000000, PI_NOTE0x00400000,
4192 "FRMR answering XID: the peer uses AX.25 v2.0", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4193 },
4194 { &ei_ax25_dup,
4195 { "ax25.link.dup", PI_SEQUENCE0x02000000, PI_NOTE0x00400000,
4196 "Digipeated copy of an earlier frame", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4197 },
4198 { &ei_ax25_n1_exceeded,
4199 { "ax25.param.n1.exceeded", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4200 "I field longer than the receiver's N1", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4201 },
4202 { &ei_ax25_xid_rule,
4203 { "ax25.xid.negotiation", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4204 "XID response breaks section 6.3.2: the lesser of the two for duplex, reject and modulo, the greater for T1 and N2", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4205 },
4206 { &ei_ax25_sabm_xid,
4207 { "ax25.xid.sabm_modulo", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4208 "SABM(E) asks for a modulo other than the one negotiated by XID", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4209 },
4210 { &ei_ax25_xid_modulo,
4211 { "ax25.xid.modulo_change", PI_PROTOCOL0x09000000, PI_NOTE0x00400000,
4212 "XID after the UA changes the modulo", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4213 },
4214 { &ei_ax25_seg_not_negotiated,
4215 { "ax25.seg.not_negotiated", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4216 "Segment on a link that didn't negotiate the segmenter", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4217 },
4218 { &ei_ax25_seg_neg_not_captured,
4219 { "ax25.seg.negotiation_not_captured", PI_PROTOCOL0x09000000, PI_NOTE0x00400000,
4220 "Segment; the XID negotiation (if any) wasn't captured", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4221 },
4222 { &ei_ax25_seg_missing_first,
4223 { "ax25.seg.missing_first", PI_SEQUENCE0x02000000, PI_WARN0x00600000,
4224 "Segment without a first segment before it", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4225 },
4226 { &ei_ax25_seg_remaining,
4227 { "ax25.seg.remaining.bad", PI_SEQUENCE0x02000000, PI_WARN0x00600000,
4228 "Segments remaining doesn't go down by one", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4229 },
4230 { &ei_ax25_seg_interleaved,
4231 { "ax25.seg.interleaved", PI_SEQUENCE0x02000000, PI_WARN0x00600000,
4232 "Frame in the middle of a segmented data unit", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4233 },
4234 { &ei_ax25_seg_too_long,
4235 { "ax25.seg.too_long", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4236 "Segment longer than the receiver's N1", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4237 },
4238 { &ei_ax25_seg_tr210,
4239 { "ax25.seg.tr210", PI_SEQUENCE0x02000000, PI_NOTE0x00400000,
4240 "Gap between segments longer than TR210", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4241 },
4242 { &ei_ax25_xid_length,
4243 { "ax25.xid.length", PI_PROTOCOL0x09000000, PI_WARN0x00600000,
4244 "XID length runs past its group or the frame", EXPFILL0, ((void*)0), 0, ((void*)0), {0, {((void*)0), ((void*)0), FT_NONE
, BASE_NONE, ((void*)0), 0, ((void*)0), -1, 0, HF_REF_TYPE_NONE
, -1, ((void*)0)}}
}
4245 },
4246 };
4247
4248 module_t *ax25_module;
4249 expert_module_t *expert_ax25;
4250 uat_t *stations_uat;
4251
4252 static uat_field_t ax25_stations_fields[] = {
4253 UAT_FLD_CSTRING(ax25_stations, callsign, "Callsign",{"callsign", "Callsign", PT_TXTMOD_STRING,{uat_fld_chk_str,ax25_stations_callsign_set_cb
,ax25_stations_callsign_tostr_cb},{0,0,0},0,"CALL or CALL-SSID (without an SSID, SSID 0)"
,((void*)0)}
4254 "CALL or CALL-SSID (without an SSID, SSID 0)"){"callsign", "Callsign", PT_TXTMOD_STRING,{uat_fld_chk_str,ax25_stations_callsign_set_cb
,ax25_stations_callsign_tostr_cb},{0,0,0},0,"CALL or CALL-SSID (without an SSID, SSID 0)"
,((void*)0)}
,
4255 UAT_FLD_DEC(ax25_stations, t1_ms, "T1 (ms)",{"t1_ms", "T1 (ms)", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_t1_ms_set_cb
,ax25_stations_t1_ms_tostr_cb},{0,0,0},0,"Acknowledgement timer of the station; 0: not set"
,((void*)0)}
4256 "Acknowledgement timer of the station; 0: not set"){"t1_ms", "T1 (ms)", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_t1_ms_set_cb
,ax25_stations_t1_ms_tostr_cb},{0,0,0},0,"Acknowledgement timer of the station; 0: not set"
,((void*)0)}
,
4257 UAT_FLD_DEC(ax25_stations, t3_s, "T3 (s)",{"t3_s", "T3 (s)", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_t3_s_set_cb
,ax25_stations_t3_s_tostr_cb},{0,0,0},0,"Inactive link timer of the station; 0: not set"
,((void*)0)}
4258 "Inactive link timer of the station; 0: not set"){"t3_s", "T3 (s)", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_t3_s_set_cb
,ax25_stations_t3_s_tostr_cb},{0,0,0},0,"Inactive link timer of the station; 0: not set"
,((void*)0)}
,
4259 UAT_FLD_DEC(ax25_stations, n2, "N2",{"n2", "N2", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_n2_set_cb
,ax25_stations_n2_tostr_cb},{0,0,0},0,"Maximum number of retries of the station; 0: not set"
,((void*)0)}
4260 "Maximum number of retries of the station; 0: not set"){"n2", "N2", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_n2_set_cb
,ax25_stations_n2_tostr_cb},{0,0,0},0,"Maximum number of retries of the station; 0: not set"
,((void*)0)}
,
4261 UAT_FLD_DEC(ax25_stations, n1, "N1 (octets)",{"n1", "N1 (octets)", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_n1_set_cb
,ax25_stations_n1_tostr_cb},{0,0,0},0,"Longest I field the station accepts; 0: not set"
,((void*)0)}
4262 "Longest I field the station accepts; 0: not set"){"n1", "N1 (octets)", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_n1_set_cb
,ax25_stations_n1_tostr_cb},{0,0,0},0,"Longest I field the station accepts; 0: not set"
,((void*)0)}
,
4263 UAT_FLD_DEC(ax25_stations, k, "k",{"k", "k", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_k_set_cb
,ax25_stations_k_tostr_cb},{0,0,0},0,"Largest window the station accepts; 0: not set"
,((void*)0)}
4264 "Largest window the station accepts; 0: not set"){"k", "k", PT_TXTMOD_STRING,{uat_fld_chk_num_dec,ax25_stations_k_set_cb
,ax25_stations_k_tostr_cb},{0,0,0},0,"Largest window the station accepts; 0: not set"
,((void*)0)}
,
4265 UAT_FLD_VS(ax25_stations, version, "Version", ax25_uat_version_vals,{"version", "Version", PT_TXTMOD_ENUM,{uat_fld_chk_enum,ax25_stations_version_set_cb
,ax25_stations_version_tostr_cb},{&(ax25_uat_version_vals
),&(ax25_uat_version_vals),&(ax25_uat_version_vals)},
&(ax25_uat_version_vals),"AX.25 version the station runs, for links where the capture doesn't show it"
,((void*)0)}
4266 "AX.25 version the station runs, for links where the capture doesn't show it"){"version", "Version", PT_TXTMOD_ENUM,{uat_fld_chk_enum,ax25_stations_version_set_cb
,ax25_stations_version_tostr_cb},{&(ax25_uat_version_vals
),&(ax25_uat_version_vals),&(ax25_uat_version_vals)},
&(ax25_uat_version_vals),"AX.25 version the station runs, for links where the capture doesn't show it"
,((void*)0)}
,
4267 UAT_END_FIELDS{((void*)0),((void*)0),PT_TXTMOD_NONE,{0,0,0},{0,0,0},0,0,((void
*)0)}
4268 };
4269
4270 /* Register the protocol name and description */
4271 proto_ax25 = proto_register_protocol("Amateur Radio AX.25", "AX.25", "ax25");
4272 ax25_module = prefs_register_protocol(proto_ax25, NULL((void*)0));
4273 /* The modulo now comes from the link (SABM/SABME/UA, or inferred) */
4274 prefs_register_obsolete_preference(ax25_module, "extended");
4275 prefs_register_uint_preference(ax25_module, "t3",
4276 "Inactive link timer T3 (s)",
4277 "T3, used with T1 and N2 to decide when a silent link must be down"
4278 " (T3 + N2 x T1). The spec gives no default; 300 s is the Linux default.",
4279 10, &ax25_pref_t3_s);
4280 prefs_register_uint_preference(ax25_module, "t1",
4281 "Acknowledgement timer T1 (ms)",
4282 "T1 for links that didn't negotiate it with XID; 0: the spec default (3000 ms)",
4283 10, &ax25_pref_t1_ms);
4284 prefs_register_uint_preference(ax25_module, "n2",
4285 "Maximum number of retries N2",
4286 "N2 for links that didn't negotiate it with XID; 0: the spec default (10)",
4287 10, &ax25_pref_n2);
4288 prefs_register_uint_preference(ax25_module, "n1",
4289 "Maximum I field length N1 (octets)",
4290 "N1 for stations that didn't notify it with XID; 0: the spec default (256)",
4291 10, &ax25_pref_n1);
4292 prefs_register_uint_preference(ax25_module, "k",
4293 "Maximum window size k",
4294 "k for stations that didn't notify it with XID; 0: the spec default"
4295 " (see below for modulo 8, 32 for modulo 128)",
4296 10, &ax25_pref_k);
4297 prefs_register_uint_preference(ax25_module, "k_mod8_default",
4298 "Spec default window size k (modulo 8)",
4299 "The spec gives 7 in sections 6.3.2 and 6.7.2.3 but 4 in section 4.3.3.7",
4300 10, &ax25_pref_k_mod8_default);
4301 prefs_register_uint_preference(ax25_module, "tr210",
4302 "Next segment timer TR210 (s)",
4303 "Longest expected gap between two segments. The spec gives no value;"
4304 " 0: N2 x T1 of the sender",
4305 10, &ax25_pref_tr210_s);
4306
4307 /*
4308 * Per-station parameters, in between XID and the preferences above.
4309 * Precedence: XID, this table, preferences, spec defaults.
4310 */
4311 stations_uat = uat_new("AX.25 stations",
4312 sizeof(ax25_station_uat_t),
4313 "ax25_stations",
4314 true1,
4315 &ax25_stations,
4316 &ax25_num_stations,
4317 UAT_AFFECTS_DISSECTION0x00000001,
4318 NULL((void*)0),
4319 ax25_stations_copy_cb,
4320 ax25_stations_update_cb,
4321 ax25_stations_free_cb,
4322 NULL((void*)0),
4323 NULL((void*)0),
4324 ax25_stations_fields);
4325 prefs_register_uat_preference(ax25_module, "stations",
4326 "Station parameters",
4327 "Link parameters of known stations, used when the capture doesn't show them",
4328 stations_uat);
4329
4330 /* Register the dissector */
4331 ax25_handle = register_dissector( "ax25", dissect_ax25, proto_ax25 );
4332
4333 /* Required function calls to register the header fields and subtrees used */
4334 proto_register_field_array( proto_ax25, hf, array_length(hf )(sizeof (hf) / sizeof (hf)[0]) );
4335 proto_register_subtree_array(ett, array_length(ett )(sizeof (ett) / sizeof (ett)[0]) );
4336 expert_ax25 = expert_register_protocol( proto_ax25 );
4337 expert_register_field_array( expert_ax25, ei, array_length( ei )(sizeof (ei) / sizeof (ei)[0]) );
4338
4339 /* Register dissector table for protocol IDs */
4340 ax25_dissector_table = register_dissector_table("ax25.pid", "AX.25 protocol ID", proto_ax25, FT_UINT8, BASE_HEX);
4341 register_capture_dissector_table("ax25.pid", "AX.25");
4342
4343 ax25_cap_handle = register_capture_dissector("ax25", capture_ax25, proto_ax25);
4344
4345 register_init_routine( ax25_init );
4346}
4347
4348void
4349proto_reg_handoff_ax25(void)
4350{
4351 dissector_add_uint("ax25.pid", AX25_P_SEGMENT0x08,
4352 create_dissector_handle(dissect_ax25_segment, proto_ax25));
4353 dissector_add_uint("wtap_encap", WTAP_ENCAP_AX25148, ax25_handle);
4354 dissector_add_uint("ip.proto", IP_PROTO_AX2593, ax25_handle);
4355
4356 capture_dissector_add_uint("wtap_encap", WTAP_ENCAP_AX25148, ax25_cap_handle);
4357}
4358
4359/*
4360 * Editor modelines - https://www.wireshark.org/tools/modelines.html
4361 *
4362 * Local variables:
4363 * c-basic-offset: 8
4364 * tab-width: 8
4365 * indent-tabs-mode: t
4366 * End:
4367 *
4368 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
4369 * :indentSize=8:tabSize=8:noTabs=false:
4370 */