blob: 349caa4ccb548fb506f0595891cbe8226b49f292 [file] [log] [blame]
/*
* 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, and (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.
* 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.
*
* Original code by Hannes Gredler (hannes@juniper.net)
*/
#ifndef lint
static const char rcsid[] _U_ =
"@(#) $Header: /tcpdump/master/tcpdump/print-juniper.c,v 1.3 2004-10-28 09:36:16 hannes Exp $ (LBL)";
#endif
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <tcpdump-stdinc.h>
#include <pcap.h>
#include <stdio.h>
#include "interface.h"
#include "extract.h"
#include "ppp.h"
#define JUNIPER_BPF_OUT 0 /* Outgoing packet */
#define JUNIPER_BPF_IN 1 /* Incoming packet */
#define JUNIPER_BPF_PKT_IN 0x1 /* Incoming packet */
#define JUNIPER_BPF_NO_L2 0x2 /* L2 header stripped */
#define ATM2_PKT_TYPE_MASK 0x70
#define ATM2_GAP_COUNT_MASK 0x3F
int ip_heuristic_guess(register const u_char *, u_int);
int juniper_ppp_heuristic_guess(register const u_char *, u_int);
static int juniper_parse_header (const u_char *, u_int8_t *, u_int);
/*
* ATM1 PIC cookie format
*
* +-----+-------------------------+-------------------------------+
* |fmtid| vc index | channel ID |
* +-----+-------------------------+-------------------------------+
*/
u_int
juniper_atm1_print(const struct pcap_pkthdr *h, register const u_char *p)
{
register u_int length = h->len;
register u_int caplen = h->caplen;
u_int16_t extracted_ethertype;
u_int8_t direction;
u_int32_t cookie1;
if(juniper_parse_header(p, &direction,length) == 0)
return 0;
p+=4;
length-=4;
caplen-=4;
cookie1=EXTRACT_32BITS(p);
if (eflag) {
/* FIXME decode channel-id, vc-index, fmt-id
for once lets just hexdump the cookie */
printf("ATM1 cookie 0x%08x, ", EXTRACT_32BITS(p));
}
p+=4;
length-=4;
caplen-=4;
if (cookie1 & 0x80000000) { /* OAM cell ? */
oam_print(p,length);
}
if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
if (llc_print(p, length, caplen, NULL, NULL,
&extracted_ethertype) != 0)
return 8;
}
if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
isoclns_print(p + 1, length - 1, caplen - 1);
/* FIXME check if frame was recognized */
return 8;
}
if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
return 0;
return (8);
}
/*
* ATM2 PIC cookie format
*
* +-------------------------------+---------+---+-----+-----------+
* | channel ID | reserv |AAL| CCRQ| gap cnt |
* +-------------------------------+---------+---+-----+-----------+
*/
u_int
juniper_atm2_print(const struct pcap_pkthdr *h, register const u_char *p)
{
register u_int length = h->len;
register u_int caplen = h->caplen;
u_int16_t extracted_ethertype;
u_int8_t direction;
u_int32_t cookie1,cookie2;
if(juniper_parse_header(p, &direction,length) == 0)
return 0;
p+=4;
length-=4;
caplen-=4;
cookie1=EXTRACT_32BITS(p);
cookie2=EXTRACT_32BITS(p+4);
if (eflag) {
/* FIXME decode channel, fmt-id, ccrq, aal, gap cnt
for once lets just hexdump the cookie */
printf("ATM2 cookie 0x%08x%08x, ",
EXTRACT_32BITS(p),
EXTRACT_32BITS(p+4));
}
p+=8;
length-=8;
caplen-=8;
if (cookie2 & ATM2_PKT_TYPE_MASK) { /* OAM cell ? */
oam_print(p,length);
return 12;
}
if (EXTRACT_24BITS(p) == 0xfefe03 || /* NLPID encaps ? */
EXTRACT_24BITS(p) == 0xaaaa03) { /* SNAP encaps ? */
if (llc_print(p, length, caplen, NULL, NULL,
&extracted_ethertype) != 0)
return 12;
}
if (direction != JUNIPER_BPF_PKT_IN && /* ether-over-1483 encaps ? */
(cookie1 & ATM2_GAP_COUNT_MASK)) {
ether_print(p, length, caplen);
return 12;
}
if (p[0] == 0x03) { /* Cisco style NLPID encaps ? */
isoclns_print(p + 1, length - 1, caplen - 1);
/* FIXME check if frame was recognized */
return 12;
}
if(juniper_ppp_heuristic_guess(p, length) != 0) /* PPPoA vcmux encaps ? */
return 12;
if(ip_heuristic_guess(p, length) != 0) /* last try - vcmux encaps ? */
return 12;
return (12);
}
/* try to guess, based on all PPP protos that are supported in
* a juniper router if the payload data is encapsulated using PPP */
int
juniper_ppp_heuristic_guess(register const u_char *p, u_int length) {
switch(EXTRACT_16BITS(p)) {
case PPP_IP :
case PPP_OSI :
case PPP_MPLS_UCAST :
case PPP_MPLS_MCAST :
case PPP_IPCP :
case PPP_OSICP :
case PPP_MPLSCP :
case PPP_LCP :
case PPP_PAP :
case PPP_CHAP :
case PPP_ML :
#ifdef INET6
case PPP_IPV6 :
case PPP_IPV6CP :
#endif
ppp_print(p, length);
break;
default:
return 0; /* did not find a ppp header */
break;
}
return 1; /* we printed a ppp packet */
}
int
ip_heuristic_guess(register const u_char *p, u_int length) {
switch(p[0]) {
case 0x45:
case 0x46:
case 0x47:
case 0x48:
case 0x49:
case 0x4a:
case 0x4b:
case 0x4c:
case 0x4d:
case 0x4e:
case 0x4f:
ip_print(p, length);
break;
#ifdef INET6
case 0x60:
case 0x61:
case 0x62:
case 0x63:
case 0x64:
case 0x65:
case 0x66:
case 0x67:
case 0x68:
case 0x69:
case 0x6a:
case 0x6b:
case 0x6c:
case 0x6d:
case 0x6e:
case 0x6f:
ip6_print(p, length);
break;
#endif
default:
return 0; /* did not find a ip header */
break;
}
return 1; /* we printed an v4/v6 packet */
}
static int
juniper_parse_header (const u_char *p, u_int8_t *direction, u_int length) {
*direction = p[3]&JUNIPER_BPF_PKT_IN;
if (EXTRACT_24BITS(p) != 0x4d4743) /* magic number found ? */
return -1;
if (*direction == JUNIPER_BPF_PKT_IN) {
if (eflag)
printf("%3s ", "In");
}
else {
if (eflag)
printf("%3s ", "Out");
}
if ((p[3] & JUNIPER_BPF_NO_L2 ) == JUNIPER_BPF_NO_L2 ) {
if (eflag)
printf("no-L2-hdr, ");
/* there is no link-layer present -
* perform the v4/v6 heuristics
* to figure out what it is
*/
if(ip_heuristic_guess(p+8,length-8) == 0)
printf("no IP-hdr found!");
return 0; /* stop parsing the output further */
}
return 1; /* everything went ok so far. continue parsing */
}