Skip to content

Commit f11e0f8

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 c3fe165 commit f11e0f8

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
@@ -599,6 +599,7 @@ extern void hex_print(netdissect_options *, const char *ident, const u_char *cp,
599599
extern void hex_print_with_offset(netdissect_options *, const char *ident, const u_char *cp, u_int, u_int);
600600
extern void hncp_print(netdissect_options *, const u_char *, u_int);
601601
extern void hsr_print(netdissect_options *, const u_char *, u_int);
602+
extern void prp_print(netdissect_options *, const u_char *, u_int);
602603
extern void hsr_prp_supervision_print(netdissect_options *ndo, const u_char *bp, u_int length);
603604
extern void hsrp_print(netdissect_options *, const u_char *, u_int);
604605
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 (caplen < ETHER_HDRLEN + switch_tag_len) {
156157
nd_print_trunc(ndo);
@@ -305,6 +306,13 @@ ether_common_print(netdissect_options *ndo, const u_char *p, u_int length,
305306
hdrlen += 6;
306307
}
307308

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

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
@@ -95,6 +119,24 @@ void hsr_print(netdissect_options *ndo, const u_char *bp, u_int length)
95119
nd_print_invalid(ndo);
96120
}
97121

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

0 commit comments

Comments
 (0)