1
2#include <sys/cdefs.h>
3#ifndef lint
4__RCSID("$NetBSD: print-ipnet.c,v 1.5 2023/08/17 20:19:40 christos Exp $");
5#endif
6
7/* \summary: Solaris DLT_IPNET printer */
8
9#ifdef HAVE_CONFIG_H
10#include <config.h>
11#endif
12
13#include "netdissect-stdinc.h"
14
15#define ND_LONGJMP_FROM_TCHECK
16#include "netdissect.h"
17#include "extract.h"
18
19
20typedef struct ipnet_hdr {
21	nd_uint8_t	iph_version;
22	nd_uint8_t	iph_family;
23	nd_uint16_t	iph_htype;
24	nd_uint32_t	iph_pktlen;
25	nd_uint32_t	iph_ifindex;
26	nd_uint32_t	iph_grifindex;
27	nd_uint32_t	iph_zsrc;
28	nd_uint32_t	iph_zdst;
29} ipnet_hdr_t;
30
31#define	IPH_AF_INET	2		/* Matches Solaris's AF_INET */
32#define	IPH_AF_INET6	26		/* Matches Solaris's AF_INET6 */
33
34#ifdef DLT_IPNET
35
36static const struct tok ipnet_values[] = {
37	{ IPH_AF_INET,		"IPv4" },
38	{ IPH_AF_INET6,		"IPv6" },
39	{ 0,			NULL }
40};
41
42static void
43ipnet_hdr_print(netdissect_options *ndo, const u_char *bp, u_int length)
44{
45	const ipnet_hdr_t *hdr;
46	hdr = (const ipnet_hdr_t *)bp;
47
48	ND_PRINT("%u > %u", GET_BE_U_4(hdr->iph_zsrc),
49		  GET_BE_U_4(hdr->iph_zdst));
50
51	if (!ndo->ndo_qflag) {
52		ND_PRINT(", family %s (%u)",
53                          tok2str(ipnet_values, "Unknown",
54                                  GET_U_1(hdr->iph_family)),
55                          GET_U_1(hdr->iph_family));
56        } else {
57		ND_PRINT(", %s",
58                          tok2str(ipnet_values,
59                                  "Unknown Ethertype (0x%04x)",
60				  GET_U_1(hdr->iph_family)));
61        }
62
63	ND_PRINT(", length %u: ", length);
64}
65
66static void
67ipnet_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen)
68{
69	const ipnet_hdr_t *hdr;
70
71	ND_TCHECK_LEN(p, sizeof(ipnet_hdr_t));
72	ndo->ndo_ll_hdr_len += sizeof(ipnet_hdr_t);
73
74	if (ndo->ndo_eflag)
75		ipnet_hdr_print(ndo, p, length);
76
77	length -= sizeof(ipnet_hdr_t);
78	caplen -= sizeof(ipnet_hdr_t);
79	hdr = (const ipnet_hdr_t *)p;
80	p += sizeof(ipnet_hdr_t);
81
82	switch (GET_U_1(hdr->iph_family)) {
83
84	case IPH_AF_INET:
85	        ip_print(ndo, p, length);
86		break;
87
88	case IPH_AF_INET6:
89		ip6_print(ndo, p, length);
90		break;
91
92	default:
93		if (!ndo->ndo_eflag)
94			ipnet_hdr_print(ndo, (const u_char *)hdr,
95					length + sizeof(ipnet_hdr_t));
96
97		if (!ndo->ndo_suppress_default_print)
98			ND_DEFAULTPRINT(p, caplen);
99		break;
100	}
101}
102
103/*
104 * This is the top level routine of the printer.  'p' points
105 * to the ether header of the packet, 'h->ts' is the timestamp,
106 * 'h->len' is the length of the packet off the wire, and 'h->caplen'
107 * is the number of bytes actually captured.
108 */
109void
110ipnet_if_print(netdissect_options *ndo,
111               const struct pcap_pkthdr *h, const u_char *p)
112{
113	ndo->ndo_protocol = "ipnet";
114	ipnet_print(ndo, p, h->len, h->caplen);
115}
116#endif /* DLT_IPNET */
117