/*
* Marko Kiiskila [email protected]
*
* Tampere University of Technology - Telecommunications Laboratory
*
* Permission to use, copy, modify and distribute this
* software and its documentation is hereby granted,
* provided that both the copyright notice and this
* permission notice appear in all copies of the software,
* derivative works or modified versions, and any portions
* thereof, that both notices appear in supporting
* documentation, and that the use of this software is
* acknowledged in any publications resulting from using
* the software.
*
* TUT ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
* CONDITION AND DISCLAIMS ANY LIABILITY OF ANY KIND FOR
* ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS
* SOFTWARE.
*
*/

#include <sys/cdefs.h>
#ifndef lint
__RCSID("$NetBSD: print-cip.c,v 1.8 2024/09/02 16:15:30 christos Exp $");
#endif

/* \summary: Linux Classical IP over ATM printer */

#include <config.h>

#include <string.h>

#include "netdissect-stdinc.h"

#define ND_LONGJMP_FROM_TCHECK
#include "netdissect.h"
#include "addrtoname.h"

static const unsigned char rfcllc[] = {
       0xaa,   /* DSAP: non-ISO */
       0xaa,   /* SSAP: non-ISO */
       0x03,   /* Ctrl: Unnumbered Information Command PDU */
       0x00,   /* OUI: EtherType */
       0x00,
       0x00 };

/*
* This is the top level routine of the printer.  'p' points
* to the LLC/SNAP or raw header of the packet, 'h->ts' is the timestamp,
* 'h->len' is the length of the packet off the wire, and 'h->caplen'
* is the number of bytes actually captured.
*/
void
cip_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
       u_int caplen = h->caplen;
       u_int length = h->len;
       int llc_hdrlen;

       ndo->ndo_protocol = "cip";

       if (ndo->ndo_eflag)
               /*
                * There is no MAC-layer header, so just print the length.
                */
               ND_PRINT("%u: ", length);

       ND_TCHECK_LEN(p, sizeof(rfcllc));
       if (memcmp(rfcllc, p, sizeof(rfcllc)) == 0) {
               /*
                * LLC header is present.  Try to print it & higher layers.
                */
               llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
               if (llc_hdrlen < 0) {
                       /* packet type not known, print raw packet */
                       if (!ndo->ndo_suppress_default_print)
                               ND_DEFAULTPRINT(p, caplen);
                       llc_hdrlen = -llc_hdrlen;
               }
       } else {
               /*
                * LLC header is absent; treat it as just IP.
                */
               llc_hdrlen = 0;
               ip_print(ndo, p, length);
       }

       ndo->ndo_ll_hdr_len += llc_hdrlen;
}