156893Sfenner/*
256893Sfenner * Copyright (c) 1990, 1991, 1993, 1994, 1995, 1996, 1997
356893Sfenner *	The Regents of the University of California.  All rights reserved.
456893Sfenner *
556893Sfenner * Redistribution and use in source and binary forms, with or without
656893Sfenner * modification, are permitted provided that: (1) source code distributions
756893Sfenner * retain the above copyright notice and this paragraph in its entirety, (2)
856893Sfenner * distributions including binary code include the above copyright notice and
956893Sfenner * this paragraph in its entirety in the documentation or other materials
1056893Sfenner * provided with the distribution, and (3) all advertising materials mentioning
1156893Sfenner * features or use of this software display the following acknowledgement:
1256893Sfenner * ``This product includes software developed by the University of California,
1356893Sfenner * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
1456893Sfenner * the University nor the names of its contributors may be used to endorse
1556893Sfenner * or promote products derived from this software without specific prior
1656893Sfenner * written permission.
1756893Sfenner * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
1856893Sfenner * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
1956893Sfenner * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
2056893Sfenner */
2156893Sfenner
2256893Sfenner#ifndef lint
23127668Sbmsstatic const char rcsid[] _U_ =
24190207Srpaulo    "@(#) $Header: /tcpdump/master/tcpdump/print-chdlc.c,v 1.43 2005-11-29 08:56:19 hannes Exp $ (LBL)";
2556893Sfenner#endif
2656893Sfenner
2756893Sfenner#ifdef HAVE_CONFIG_H
2856893Sfenner#include "config.h"
2956893Sfenner#endif
3056893Sfenner
31127668Sbms#include <tcpdump-stdinc.h>
3256893Sfenner
3356893Sfenner#include <pcap.h>
3456893Sfenner#include <stdio.h>
3556893Sfenner
3656893Sfenner#include "interface.h"
3756893Sfenner#include "addrtoname.h"
3875115Sfenner#include "ethertype.h"
3998524Sfenner#include "extract.h"
4056893Sfenner#include "ppp.h"
4175115Sfenner#include "chdlc.h"
4256893Sfenner
4356893Sfennerstatic void chdlc_slarp_print(const u_char *, u_int);
4456893Sfenner
45172683Smlaierconst struct tok chdlc_cast_values[] = {
46172683Smlaier    { CHDLC_UNICAST, "unicast" },
47172683Smlaier    { CHDLC_BCAST, "bcast" },
48172683Smlaier    { 0, NULL}
49172683Smlaier};
50172683Smlaier
51172683Smlaier
5256893Sfenner/* Standard CHDLC printer */
53127668Sbmsu_int
54127668Sbmschdlc_if_print(const struct pcap_pkthdr *h, register const u_char *p)
5556893Sfenner{
5656893Sfenner	register u_int length = h->len;
5756893Sfenner	register u_int caplen = h->caplen;
5898524Sfenner
5998524Sfenner	if (caplen < CHDLC_HDRLEN) {
6098524Sfenner		printf("[|chdlc]");
61127668Sbms		return (caplen);
6298524Sfenner	}
63162017Ssam        return (chdlc_print(p,length));
64162017Ssam}
6598524Sfenner
66162017Ssamu_int
67162017Ssamchdlc_print(register const u_char *p, u_int length) {
68162017Ssam	u_int proto;
69162017Ssam
7098524Sfenner	proto = EXTRACT_16BITS(&p[2]);
7156893Sfenner	if (eflag) {
72172683Smlaier                printf("%s, ethertype %s (0x%04x), length %u: ",
73172683Smlaier                       tok2str(chdlc_cast_values, "0x%02x", p[0]),
74172683Smlaier                       tok2str(ethertype_values, "Unknown", proto),
75172683Smlaier                       proto,
76172683Smlaier                       length);
7756893Sfenner	}
7856893Sfenner
7956893Sfenner	length -= CHDLC_HDRLEN;
80172683Smlaier	p += CHDLC_HDRLEN;
81172683Smlaier
8275115Sfenner	switch (proto) {
8356893Sfenner	case ETHERTYPE_IP:
84172683Smlaier		ip_print(gndo, p, length);
8556893Sfenner		break;
8656893Sfenner#ifdef INET6
8756893Sfenner	case ETHERTYPE_IPV6:
88236192Sdelphij		ip6_print(gndo, p, length);
8956893Sfenner		break;
9056893Sfenner#endif
9156893Sfenner	case CHDLC_TYPE_SLARP:
92172683Smlaier		chdlc_slarp_print(p, length);
9356893Sfenner		break;
9456893Sfenner#if 0
9556893Sfenner	case CHDLC_TYPE_CDP:
96172683Smlaier		chdlc_cdp_print(p, length);
9756893Sfenner		break;
9856893Sfenner#endif
99127668Sbms        case ETHERTYPE_MPLS:
100127668Sbms        case ETHERTYPE_MPLS_MULTI:
101172683Smlaier                mpls_print(p, length);
102127668Sbms		break;
103127668Sbms        case ETHERTYPE_ISO:
104127668Sbms                /* is the fudge byte set ? lets verify by spotting ISO headers */
105172683Smlaier                if (*(p+1) == 0x81 ||
106172683Smlaier                    *(p+1) == 0x82 ||
107172683Smlaier                    *(p+1) == 0x83)
108172683Smlaier                    isoclns_print(p+1, length-1, length-1);
109127668Sbms                else
110172683Smlaier                    isoclns_print(p, length, length);
111127668Sbms                break;
112127668Sbms	default:
113172683Smlaier                if (!eflag)
114172683Smlaier                        printf("unknown CHDLC protocol (0x%04x)", proto);
115127668Sbms                break;
11656893Sfenner	}
117127668Sbms
118127668Sbms	return (CHDLC_HDRLEN);
11956893Sfenner}
12056893Sfenner
121147899Ssam/*
122147899Ssam * The fixed-length portion of a SLARP packet.
123147899Ssam */
12456893Sfennerstruct cisco_slarp {
125147899Ssam	u_int8_t code[4];
12656893Sfenner#define SLARP_REQUEST	0
12756893Sfenner#define SLARP_REPLY	1
12856893Sfenner#define SLARP_KEEPALIVE	2
12956893Sfenner	union {
13056893Sfenner		struct {
131147899Ssam			u_int8_t addr[4];
132147899Ssam			u_int8_t mask[4];
13356893Sfenner		} addr;
13456893Sfenner		struct {
135147899Ssam			u_int8_t myseq[4];
136147899Ssam			u_int8_t yourseq[4];
137147899Ssam			u_int8_t rel[2];
13856893Sfenner		} keep;
13956893Sfenner	} un;
14056893Sfenner};
14156893Sfenner
142147899Ssam#define SLARP_MIN_LEN	14
143147899Ssam#define SLARP_MAX_LEN	18
14456893Sfenner
14556893Sfennerstatic void
14656893Sfennerchdlc_slarp_print(const u_char *cp, u_int length)
14756893Sfenner{
14898524Sfenner	const struct cisco_slarp *slarp;
149147899Ssam        u_int sec,min,hrs,days;
15056893Sfenner
151147899Ssam        printf("SLARP (length: %u), ",length);
152147899Ssam	if (length < SLARP_MIN_LEN)
153127668Sbms		goto trunc;
15456893Sfenner
15598524Sfenner	slarp = (const struct cisco_slarp *)cp;
156147899Ssam	TCHECK2(*slarp, SLARP_MIN_LEN);
157127668Sbms	switch (EXTRACT_32BITS(&slarp->code)) {
15856893Sfenner	case SLARP_REQUEST:
159127668Sbms		printf("request");
160147899Ssam		/*
161147899Ssam		 * At least according to William "Chops" Westfield's
162147899Ssam		 * message in
163147899Ssam		 *
164147899Ssam		 *	http://www.nethelp.no/net/cisco-hdlc.txt
165147899Ssam		 *
166147899Ssam		 * the address and mask aren't used in requests -
167147899Ssam		 * they're just zero.
168147899Ssam		 */
16956893Sfenner		break;
17056893Sfenner	case SLARP_REPLY:
171127668Sbms		printf("reply %s/%s",
17256893Sfenner			ipaddr_string(&slarp->un.addr.addr),
17356893Sfenner			ipaddr_string(&slarp->un.addr.mask));
17456893Sfenner		break;
17556893Sfenner	case SLARP_KEEPALIVE:
176147899Ssam		printf("keepalive: mineseen=0x%08x, yourseen=0x%08x, reliability=0x%04x",
177147899Ssam                       EXTRACT_32BITS(&slarp->un.keep.myseq),
178147899Ssam                       EXTRACT_32BITS(&slarp->un.keep.yourseq),
179147899Ssam                       EXTRACT_16BITS(&slarp->un.keep.rel));
180147899Ssam
181147899Ssam                if (length >= SLARP_MAX_LEN) { /* uptime-stamp is optional */
182147899Ssam                        cp += SLARP_MIN_LEN;
183147899Ssam                        if (!TTEST2(*cp, 4))
184147899Ssam                                goto trunc;
185147899Ssam                        sec = EXTRACT_32BITS(cp) / 1000;
186147899Ssam                        min = sec / 60; sec -= min * 60;
187147899Ssam                        hrs = min / 60; min -= hrs * 60;
188147899Ssam                        days = hrs / 24; hrs -= days * 24;
189147899Ssam                        printf(", link uptime=%ud%uh%um%us",days,hrs,min,sec);
190147899Ssam                }
19156893Sfenner		break;
19256893Sfenner	default:
193127668Sbms		printf("0x%02x unknown", EXTRACT_32BITS(&slarp->code));
194127668Sbms                if (vflag <= 1)
195127668Sbms                    print_unknown_data(cp+4,"\n\t",length-4);
19656893Sfenner		break;
19756893Sfenner	}
19856893Sfenner
199147899Ssam	if (SLARP_MAX_LEN < length && vflag)
200147899Ssam		printf(", (trailing junk: %d bytes)", length - SLARP_MAX_LEN);
201127668Sbms        if (vflag > 1)
202127668Sbms            print_unknown_data(cp+4,"\n\t",length-4);
203127668Sbms	return;
204127668Sbms
205127668Sbmstrunc:
206127668Sbms	printf("[|slarp]");
20756893Sfenner}
208146773Ssam
209146773Ssam
210146773Ssam/*
211146773Ssam * Local Variables:
212146773Ssam * c-style: whitesmith
213146773Ssam * c-basic-offset: 8
214146773Ssam * End:
215146773Ssam */
216