Skip to content

Commit 9807d76

Browse files
committed
HSR/PRP: Add printing for PRP trailer
PRP is a redundancy protocol, like HSR, that duplicates packets and includes a sequence number. However, PRP uses a trailer on the packet, making the parsing a bit tricky. The trailer includes the packet size that can be used to help ascertain it is a valid PRP trailer, however it is still possible that this can appear naturally in a packet somewhere in a network that doesn't use PRP. Signed-off-by: Casper Andersson <[email protected]>
1 parent f643930 commit 9807d76

File tree

3 files changed

+51
-0
lines changed

3 files changed

+51
-0
lines changed

netdissect.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -655,6 +655,7 @@ extern void hex_print(netdissect_options *, const char *indent, const u_char *cp
655655
extern void hex_print_with_offset(netdissect_options *, const char *indent, const u_char *cp, u_int, u_int);
656656
extern void hncp_print(netdissect_options *, const u_char *, u_int);
657657
extern void hsr_print(netdissect_options *, const u_char *, u_int);
658+
extern void prp_print(netdissect_options *, const u_char *, u_int);
658659
extern void hsr_prp_supervision_print(netdissect_options *ndo, const u_char *bp, u_int length);
659660
extern void hsrp_print(netdissect_options *, const u_char *, u_int);
660661
extern void http_print(netdissect_options *, const u_char *, u_int);

print-ether.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ ether_common_print(netdissect_options *ndo, const u_char *p, u_int length,
151151
int printed_length;
152152
int llc_hdrlen;
153153
struct lladdr_info src, dst;
154+
int prp_suffix;
154155

155156
if (length < caplen) {
156157
ND_PRINT("[length %u < caplen %u]", length, caplen);
@@ -307,6 +308,13 @@ ether_common_print(netdissect_options *ndo, const u_char *p, u_int length,
307308
hdrlen += 6;
308309
}
309310

311+
if (caplen >= 6) {
312+
prp_suffix = GET_BE_U_2(p + caplen - 2);
313+
if (prp_suffix == 0x88fb) {
314+
prp_print(ndo, p, caplen);
315+
}
316+
}
317+
310318
/*
311319
* We now have the final length/type field.
312320
*/

print-hsr-prp.c

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,30 @@
4040
* header, tags before the HSR tag (e.g. VLAN), and the HSR ethertype field.
4141
* For PRP it includes the PRP suffix.
4242
*
43+
*
44+
* PRP trailer
45+
* 0 1 2 3
46+
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
47+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
48+
* | Sequence number | LanId | LSDUsize |
49+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
50+
* | PRP Suffix (0x88fb) |
51+
* +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
52+
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
53+
* 0 1 2 3
54+
*
55+
* PRP uses a trailer on the packets, making it harder to parse. The suffix
56+
* 0x88fb indicates that it is a PRP frame, but since this could occur
57+
* naturally in a packet there is also the LSDUsize that indicates the size of
58+
* the packet. If this size does not match then it is not a PRP trailer.
59+
* Unfortunately, this could still match on other packets if coincidentally
60+
* both the suffix and LSDUsize matches up. We could also verify that LanId is
61+
* valid (0xA or 0xB) to further reduce likelihood of bad matches.
62+
*
63+
* LanId in HSR header is 0 = LAN A and 1 = LAN B. In PRP frames it is
64+
* represented as 0xA and 0xB.
65+
*
66+
*
4367
* HSR/PRP Supervision frame
4468
* 0 1 2 3
4569
* 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
@@ -93,6 +117,24 @@ void hsr_print(netdissect_options *ndo, const u_char *bp, u_int length)
93117
nd_print_invalid(ndo);
94118
}
95119

120+
void prp_print(netdissect_options *ndo, const u_char *bp, u_int length)
121+
{
122+
u_int lsdu_size, lanid, seqnr;
123+
124+
lsdu_size = GET_BE_U_2(bp + length - 4) & 0xfff;
125+
lanid = GET_BE_U_2(bp + length - 4) >> 12;
126+
127+
/* If length does not match LSDUsize or LanId isn't valid it isn't a
128+
* valid PRP trailer. This length assumes VLAN tags have been stripped
129+
* away already.
130+
*/
131+
if (lsdu_size == length && (lanid == 0xA || lanid == 0xB)) {
132+
seqnr = GET_BE_U_2(bp + length - 6);
133+
ND_PRINT("PRP trailer (0x88fb), LSDUsize %d, SeqNr %d, LanId %s, ",
134+
lsdu_size, seqnr, lanid == 0xA ? "A" : "B");
135+
}
136+
}
137+
96138
void hsr_prp_supervision_print(netdissect_options *ndo, const u_char *bp, u_int length)
97139
{
98140
int tlvtype, tlvlength;

0 commit comments

Comments
 (0)