summaryrefslogtreecommitdiffstats
path: root/print-sl.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 17:13:01 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-15 17:13:01 +0000
commit7adcb5b605cc1328a3084c334f4697ec9771936c (patch)
tree03e681bfda053978ba896745828e09cb056ad156 /print-sl.c
parentInitial commit. (diff)
downloadtcpdump-7adcb5b605cc1328a3084c334f4697ec9771936c.tar.xz
tcpdump-7adcb5b605cc1328a3084c334f4697ec9771936c.zip
Adding upstream version 4.99.4.upstream/4.99.4upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'print-sl.c')
-rw-r--r--print-sl.c259
1 files changed, 259 insertions, 0 deletions
diff --git a/print-sl.c b/print-sl.c
new file mode 100644
index 0000000..85b7624
--- /dev/null
+++ b/print-sl.c
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that: (1) source code distributions
+ * retain the above copyright notice and this paragraph in its entirety, (2)
+ * distributions including binary code include the above copyright notice and
+ * this paragraph in its entirety in the documentation or other materials
+ * provided with the distribution, and (3) all advertising materials mentioning
+ * features or use of this software display the following acknowledgement:
+ * ``This product includes software developed by the University of California,
+ * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
+ * the University nor the names of its contributors may be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/* \summary: Compressed Serial Line Internet Protocol printer */
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "netdissect-stdinc.h"
+
+#define ND_LONGJMP_FROM_TCHECK
+#include "netdissect.h"
+#include "extract.h"
+
+#include "ip.h"
+#include "tcp.h"
+#include "slcompress.h"
+
+/*
+ * definitions of the pseudo- link-level header attached to slip
+ * packets grabbed by the packet filter (bpf) traffic monitor.
+ */
+#define SLIP_HDRLEN 16
+
+#define SLX_DIR 0
+#define SLX_CHDR 1
+
+#define SLIPDIR_IN 0
+#define SLIPDIR_OUT 1
+
+
+static u_int lastlen[2][256];
+static u_int lastconn = 255;
+
+static void sliplink_print(netdissect_options *, const u_char *, const struct ip *, u_int);
+static void compressed_sl_print(netdissect_options *, const u_char *, const struct ip *, u_int, int);
+
+void
+sl_if_print(netdissect_options *ndo,
+ const struct pcap_pkthdr *h, const u_char *p)
+{
+ u_int length = h->len;
+ const struct ip *ip;
+
+ ndo->ndo_protocol = "slip";
+ ND_TCHECK_LEN(p, SLIP_HDRLEN);
+ ndo->ndo_ll_hdr_len += SLIP_HDRLEN;
+
+ length -= SLIP_HDRLEN;
+
+ ip = (const struct ip *)(p + SLIP_HDRLEN);
+
+ if (ndo->ndo_eflag)
+ sliplink_print(ndo, p, ip, length);
+
+ switch (IP_V(ip)) {
+ case 4:
+ ip_print(ndo, (const u_char *)ip, length);
+ break;
+ case 6:
+ ip6_print(ndo, (const u_char *)ip, length);
+ break;
+ default:
+ ND_PRINT("ip v%u", IP_V(ip));
+ }
+}
+
+void
+sl_bsdos_if_print(netdissect_options *ndo,
+ const struct pcap_pkthdr *h, const u_char *p)
+{
+ u_int length = h->len;
+ const struct ip *ip;
+
+ ndo->ndo_protocol = "slip_bsdos";
+ ND_TCHECK_LEN(p, SLIP_HDRLEN);
+ ndo->ndo_ll_hdr_len += SLIP_HDRLEN;
+
+ length -= SLIP_HDRLEN;
+
+ ip = (const struct ip *)(p + SLIP_HDRLEN);
+
+#ifdef notdef
+ if (ndo->ndo_eflag)
+ sliplink_print(ndo, p, ip, length);
+#endif
+
+ ip_print(ndo, (const u_char *)ip, length);
+}
+
+static void
+sliplink_print(netdissect_options *ndo,
+ const u_char *p, const struct ip *ip,
+ u_int length)
+{
+ int dir;
+ u_int hlen;
+
+ dir = GET_U_1(p + SLX_DIR);
+ switch (dir) {
+
+ case SLIPDIR_IN:
+ ND_PRINT("I ");
+ break;
+
+ case SLIPDIR_OUT:
+ ND_PRINT("O ");
+ break;
+
+ default:
+ ND_PRINT("Invalid direction %d ", dir);
+ dir = -1;
+ break;
+ }
+ switch (GET_U_1(p + SLX_CHDR) & 0xf0) {
+
+ case TYPE_IP:
+ ND_PRINT("ip %u: ", length + SLIP_HDRLEN);
+ break;
+
+ case TYPE_UNCOMPRESSED_TCP:
+ /*
+ * The connection id is stored in the IP protocol field.
+ * Get it from the link layer since sl_uncompress_tcp()
+ * has restored the IP header copy to IPPROTO_TCP.
+ */
+ lastconn = GET_U_1(((const struct ip *)(p + SLX_CHDR))->ip_p);
+ ND_PRINT("utcp %u: ", lastconn);
+ if (dir == -1) {
+ /* Direction is bogus, don't use it */
+ return;
+ }
+ ND_TCHECK_SIZE(ip);
+ hlen = IP_HL(ip);
+ ND_TCHECK_SIZE((const struct tcphdr *)&((const int *)ip)[hlen]);
+ hlen += TH_OFF((const struct tcphdr *)&((const int *)ip)[hlen]);
+ lastlen[dir][lastconn] = length - (hlen << 2);
+ break;
+
+ default:
+ if (dir == -1) {
+ /* Direction is bogus, don't use it */
+ return;
+ }
+ if (GET_U_1(p + SLX_CHDR) & TYPE_COMPRESSED_TCP) {
+ compressed_sl_print(ndo, p + SLX_CHDR, ip, length, dir);
+ ND_PRINT(": ");
+ } else
+ ND_PRINT("slip-%u!: ", GET_U_1(p + SLX_CHDR));
+ }
+}
+
+static const u_char *
+print_sl_change(netdissect_options *ndo,
+ const char *str, const u_char *cp)
+{
+ u_int i;
+
+ if ((i = GET_U_1(cp)) == 0) {
+ cp++;
+ i = GET_BE_U_2(cp);
+ cp += 2;
+ }
+ ND_PRINT(" %s%u", str, i);
+ return (cp);
+}
+
+static const u_char *
+print_sl_winchange(netdissect_options *ndo,
+ const u_char *cp)
+{
+ int16_t i;
+
+ if ((i = GET_U_1(cp)) == 0) {
+ cp++;
+ i = GET_BE_S_2(cp);
+ cp += 2;
+ }
+ if (i >= 0)
+ ND_PRINT(" W+%d", i);
+ else
+ ND_PRINT(" W%d", i);
+ return (cp);
+}
+
+static void
+compressed_sl_print(netdissect_options *ndo,
+ const u_char *chdr, const struct ip *ip,
+ u_int length, int dir)
+{
+ const u_char *cp = chdr;
+ u_int flags, hlen;
+
+ flags = GET_U_1(cp);
+ cp++;
+ if (flags & NEW_C) {
+ lastconn = GET_U_1(cp);
+ cp++;
+ ND_PRINT("ctcp %u", lastconn);
+ } else
+ ND_PRINT("ctcp *");
+
+ /* skip tcp checksum */
+ cp += 2;
+
+ switch (flags & SPECIALS_MASK) {
+ case SPECIAL_I:
+ ND_PRINT(" *SA+%u", lastlen[dir][lastconn]);
+ break;
+
+ case SPECIAL_D:
+ ND_PRINT(" *S+%u", lastlen[dir][lastconn]);
+ break;
+
+ default:
+ if (flags & NEW_U)
+ cp = print_sl_change(ndo, "U=", cp);
+ if (flags & NEW_W)
+ cp = print_sl_winchange(ndo, cp);
+ if (flags & NEW_A)
+ cp = print_sl_change(ndo, "A+", cp);
+ if (flags & NEW_S)
+ cp = print_sl_change(ndo, "S+", cp);
+ break;
+ }
+ if (flags & NEW_I)
+ cp = print_sl_change(ndo, "I+", cp);
+
+ /*
+ * 'hlen' is the length of the uncompressed TCP/IP header (in words).
+ * 'cp - chdr' is the length of the compressed header.
+ * 'length - hlen' is the amount of data in the packet.
+ */
+ ND_TCHECK_SIZE(ip);
+ hlen = IP_HL(ip);
+ ND_TCHECK_SIZE((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
+ hlen += TH_OFF((const struct tcphdr *)&((const int32_t *)ip)[hlen]);
+ lastlen[dir][lastconn] = length - (hlen << 2);
+ ND_PRINT(" %u (%ld)", lastlen[dir][lastconn], (long)(cp - chdr));
+}