Beispiel #1
0
static int
arcnet_encap_print(netdissect_options *ndo, u_char arctype, const u_char *p,
    u_int length, u_int caplen)
{
	switch (arctype) {

	case ARCTYPE_IP_OLD:
	case ARCTYPE_IP:
	        ip_print(ndo, p, length);
		return (1);

	case ARCTYPE_INET6:
		ip6_print(ndo, p, length);
		return (1);

	case ARCTYPE_ARP_OLD:
	case ARCTYPE_ARP:
	case ARCTYPE_REVARP:
		arp_print(ndo, p, length, caplen);
		return (1);

	case ARCTYPE_ATALK:	/* XXX was this ever used? */
		if (ndo->ndo_vflag)
			ND_PRINT("et1 ");
		atalk_print(ndo, p, length);
		return (1);

	case ARCTYPE_IPX:
		ipx_print(ndo, p, length);
		return (1);

	default:
		return (0);
	}
}
Beispiel #2
0
/* PPP */
static void
handle_ppp(netdissect_options *ndo,
           u_int proto, const u_char *p, int length)
{
	if ((proto & 0xff00) == 0x7e00) { /* is this an escape code ? */
		ppp_hdlc(ndo, p - 1, length);
		return;
	}

	switch (proto) {
	case PPP_LCP: /* fall through */
	case PPP_IPCP:
	case PPP_OSICP:
	case PPP_MPLSCP:
	case PPP_IPV6CP:
	case PPP_CCP:
	case PPP_BACP:
		handle_ctrl_proto(ndo, proto, p, length);
		break;
	case PPP_ML:
		handle_mlppp(ndo, p, length);
		break;
	case PPP_CHAP:
		handle_chap(ndo, p, length);
		break;
	case PPP_PAP:
		handle_pap(ndo, p, length);
		break;
	case PPP_BAP:		/* XXX: not yet completed */
		handle_bap(ndo, p, length);
		break;
	case ETHERTYPE_IP:	/*XXX*/
        case PPP_VJNC:
	case PPP_IP:
		ip_print(ndo, p, length);
		break;
	case ETHERTYPE_IPV6:	/*XXX*/
	case PPP_IPV6:
		ip6_print(ndo, p, length);
		break;
	case ETHERTYPE_IPX:	/*XXX*/
	case PPP_IPX:
		ipx_print(ndo, p, length);
		break;
	case PPP_OSI:
		isoclns_print(ndo, p, length, length);
		break;
	case PPP_MPLS_UCAST:
	case PPP_MPLS_MCAST:
		mpls_print(ndo, p, length);
		break;
	case PPP_COMP:
		ND_PRINT((ndo, "compressed PPP data"));
		break;
	default:
		ND_PRINT((ndo, "%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto)));
		print_unknown_data(ndo, p, "\n\t", length);
		break;
	}
}
Beispiel #3
0
static
char *ipx_prpr(struct ipx_addr *x)
{
	struct sockaddr_ipx *sipx = &ssipx;

	sipx->sipx_addr = *x;
	return(ipx_print((struct sockaddr *)sipx));
}
Beispiel #4
0
static int
arcnet_encap_print(u_char arctype, const u_char *p,
    u_int length, u_int caplen)
{
	switch (arctype) {

	case ARCTYPE_IP_OLD:
	case ARCTYPE_IP:
	        ip_print(gndo, p, length);
		return (1);

#ifdef INET6
	case ARCTYPE_INET6:
		ip6_print(gndo, p, length);
		return (1);
#endif /*INET6*/

	case ARCTYPE_ARP_OLD:
	case ARCTYPE_ARP:
	case ARCTYPE_REVARP:
		arp_print(gndo, p, length, caplen);
		return (1);

	case ARCTYPE_ATALK:	/* XXX was this ever used? */
		if (vflag)
			fputs("et1 ", stdout);
		atalk_print(p, length);
		return (1);

	case ARCTYPE_IPX:
		ipx_print(p, length);
		return (1);

	default:
		return (0);
	}
}
Beispiel #5
0
/*
 * This is the top level routine of the printer.  'p' points to the
 * Linux "cooked capture" 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.
 */
u_int
sll_if_print(const struct pcap_pkthdr *h, const u_char *p)
{
	u_int caplen = h->caplen;
	u_int length = h->len;
	register const struct sll_header *sllp;
	u_short ether_type;
	u_short extracted_ethertype;

	if (caplen < SLL_HDR_LEN) {
		/*
		 * XXX - this "can't happen" because "pcap-linux.c" always
		 * adds this many bytes of header to every packet in a
		 * cooked socket capture.
		 */
		printf("[|sll]");
		return (caplen);
	}

	sllp = (const struct sll_header *)p;

	if (eflag)
		sll_print(sllp, length);

	/*
	 * Go past the cooked-mode header.
	 */
	length -= SLL_HDR_LEN;
	caplen -= SLL_HDR_LEN;
	p += SLL_HDR_LEN;

	ether_type = EXTRACT_16BITS(&sllp->sll_protocol);

recurse:
	/*
	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
	 * packet type?
	 */
	if (ether_type <= ETHERMTU) {
		/*
		 * Yes - what type is it?
		 */
		switch (ether_type) {

		case LINUX_SLL_P_802_3:
			/*
			 * Ethernet_802.3 IPX frame.
			 */
			ipx_print(p, length);
			break;

		case LINUX_SLL_P_802_2:
			/*
			 * 802.2.
			 * Try to print the LLC-layer header & higher layers.
			 */
			if (llc_print(p, length, caplen, NULL, NULL,
			    &extracted_ethertype) == 0)
				goto unknown;	/* unknown LLC type */
			break;

		default:
			extracted_ethertype = 0;
			/*FALLTHROUGH*/

		unknown:
			/* ether_type not known, print raw packet */
			if (!eflag)
				sll_print(sllp, length + SLL_HDR_LEN);
			if (extracted_ethertype) {
				printf("(LLC %s) ",
			       etherproto_string(htons(extracted_ethertype)));
			}
			if (!suppress_default_print)
				default_print(p, caplen);
			break;
		}
	} else if (ether_type == ETHERTYPE_8021Q) {
		/*
		 * Print VLAN information, and then go back and process
		 * the enclosed type field.
		 */
		if (caplen < 4 || length < 4) {
			printf("[|vlan]");
			return (SLL_HDR_LEN);
		}
	        if (eflag) {
	        	u_int16_t tag = EXTRACT_16BITS(p);

			printf("vlan %u, p %u%s, ",
			    tag & 0xfff,
			    tag >> 13,
			    (tag & 0x1000) ? ", CFI" : "");
		}

		ether_type = EXTRACT_16BITS(p + 2);
		if (ether_type <= ETHERMTU)
			ether_type = LINUX_SLL_P_802_2;
		if (!qflag) {
			(void)printf("ethertype %s, ",
			    tok2str(ethertype_values, "Unknown", ether_type));
		}
		p += 4;
		length -= 4;
		caplen -= 4;
		goto recurse;
	} else {
		if (ethertype_print(gndo, ether_type, p, length, caplen) == 0) {
Beispiel #6
0
static const char *
fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
{
	static char workbuf[128];
	const char *cp;

	if (sa == NULL)
		return ("null");

	switch(sa->sa_family) {
	case AF_INET:
	    {
		struct sockaddr_in *sockin = (struct sockaddr_in *)sa;

		if ((sockin->sin_addr.s_addr == INADDR_ANY) &&
			mask &&
			ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr)
				==0L)
				cp = "default" ;
		else if (flags & RTF_HOST)
			cp = routename(sockin->sin_addr.s_addr);
		else if (mask)
			cp = netname(sockin->sin_addr.s_addr,
				     ntohl(((struct sockaddr_in *)mask)
					   ->sin_addr.s_addr));
		else
			cp = netname(sockin->sin_addr.s_addr, 0L);
		break;
	    }

#ifdef INET6
	case AF_INET6:
	    {
		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;

		in6_fillscopeid(sa6);

		if (flags & RTF_HOST)
		    cp = routename6(sa6);
		else if (mask)
		    cp = netname6(sa6,
				  &((struct sockaddr_in6 *)mask)->sin6_addr);
		else {
		    cp = netname6(sa6, NULL);
		}
		break;
	    }
#endif /*INET6*/

	case AF_IPX:
	    {
		struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
		if (ipx_nullnet(satoipx_addr(work)))
			cp = "default";
		else
			cp = ipx_print(sa);
		break;
	    }
	case AF_APPLETALK:
	    {
		if (!(flags & RTF_HOST) && mask)
			cp = atalk_print2(sa,mask,9);
		else
			cp = atalk_print(sa,11);
		break;
	    }
	case AF_NETGRAPH:
	    {
		strlcpy(workbuf, ((struct sockaddr_ng *)sa)->sg_data,
		        sizeof(workbuf));
		cp = workbuf;
		break;
	    }

	case AF_LINK:
	    {
		struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;

		if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
		    sdl->sdl_slen == 0) {
			(void) sprintf(workbuf, "link#%d", sdl->sdl_index);
			cp = workbuf;
		} else
			switch (sdl->sdl_type) {

			case IFT_ETHER:
			case IFT_L2VLAN:
			case IFT_BRIDGE:
				if (sdl->sdl_alen == ETHER_ADDR_LEN) {
					cp = ether_ntoa((struct ether_addr *)
					    (sdl->sdl_data + sdl->sdl_nlen));
					break;
				}
				/* FALLTHROUGH */
			default:
				cp = link_ntoa(sdl);
				break;
			}
		break;
	    }

	default:
	    {
		u_char *s = (u_char *)sa->sa_data, *slim;
		char *cq, *cqlim;

		cq = workbuf;
		slim =  sa->sa_len + (u_char *) sa;
		cqlim = cq + sizeof(workbuf) - 6;
		cq += sprintf(cq, "(%d)", sa->sa_family);
		while (s < slim && cq < cqlim) {
			cq += sprintf(cq, " %02x", *s++);
			if (s < slim)
			    cq += sprintf(cq, "%02x", *s++);
		}
		cp = workbuf;
	    }
	}

	return (cp);
}
Beispiel #7
0
/*
 * This is the top level routine of the printer.  'p' points
 * to the ether 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.
 */
u_int
null_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
	u_int length = h->len;
	u_int caplen = h->caplen;
	u_int family;

	if (caplen < NULL_HDRLEN) {
		ND_PRINT((ndo, "[|null]"));
		return (NULL_HDRLEN);
	}

	memcpy((char *)&family, (char *)p, sizeof(family));

	/*
	 * This isn't necessarily in our host byte order; if this is
	 * a DLT_LOOP capture, it's in network byte order, and if
	 * this is a DLT_NULL capture from a machine with the opposite
	 * byte-order, it's in the opposite byte order from ours.
	 *
	 * If the upper 16 bits aren't all zero, assume it's byte-swapped.
	 */
	if ((family & 0xFFFF0000) != 0)
		family = SWAPLONG(family);

	if (ndo->ndo_eflag)
		null_hdr_print(ndo, family, length);

	length -= NULL_HDRLEN;
	caplen -= NULL_HDRLEN;
	p += NULL_HDRLEN;

	switch (family) {

	case BSD_AFNUM_INET:
		ip_print(ndo, p, length);
		break;

	case BSD_AFNUM_INET6_BSD:
	case BSD_AFNUM_INET6_FREEBSD:
	case BSD_AFNUM_INET6_DARWIN:
		ip6_print(ndo, p, length);
		break;

	case BSD_AFNUM_ISO:
		isoclns_print(ndo, p, length, caplen);
		break;

	case BSD_AFNUM_APPLETALK:
		atalk_print(ndo, p, length);
		break;

	case BSD_AFNUM_IPX:
		ipx_print(ndo, p, length);
		break;

	default:
		/* unknown AF_ value */
		if (!ndo->ndo_eflag)
			null_hdr_print(ndo, family, length + NULL_HDRLEN);
		if (!ndo->ndo_suppress_default_print)
			ND_DEFAULTPRINT(p, caplen);
	}

	return (NULL_HDRLEN);
}
Beispiel #8
0
int
llc_print(const u_char *p, u_int length, u_int caplen,
          const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
{
    u_int8_t dsap_field, dsap, ssap_field, ssap;
    u_int16_t control;
    int is_u;
    register int ret;

    *extracted_ethertype = 0;

    if (caplen < 3) {
        (void)printf("[|llc]");
        default_print((u_char *)p, caplen);
        return(0);
    }

    dsap_field = *p;
    ssap_field = *(p + 1);

    /*
     * OK, what type of LLC frame is this?  The length
     * of the control field depends on that - I frames
     * have a two-byte control field, and U frames have
     * a one-byte control field.
     */
    control = *(p + 2);
    if ((control & LLC_U_FMT) == LLC_U_FMT) {
        /*
         * U frame.
         */
        is_u = 1;
    } else {
        /*
         * The control field in I and S frames is
         * 2 bytes...
         */
        if (caplen < 4) {
            (void)printf("[|llc]");
            default_print((u_char *)p, caplen);
            return(0);
        }

        /*
         * ...and is little-endian.
         */
        control = EXTRACT_LE_16BITS(p + 2);
        is_u = 0;
    }

    if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) {
        /*
         * This is an Ethernet_802.3 IPX frame; it has an
         * 802.3 header (i.e., an Ethernet header where the
         * type/length field is <= ETHERMTU, i.e. it's a length
         * field, not a type field), but has no 802.2 header -
         * the IPX packet starts right after the Ethernet header,
         * with a signature of two bytes of 0xFF (which is
         * LLCSAP_GLOBAL).
         *
         * (It might also have been an Ethernet_802.3 IPX at
         * one time, but got bridged onto another network,
         * such as an 802.11 network; this has appeared in at
         * least one capture file.)
         */

        if (eflag)
            printf("IPX 802.3: ");

        ipx_print(p, length);
        return (1);
    }

    dsap = dsap_field & ~LLC_IG;
    ssap = ssap_field & ~LLC_GSAP;

    if (eflag) {
        printf("LLC, dsap %s (0x%02x) %s, ssap %s (0x%02x) %s",
               tok2str(llc_values, "Unknown", dsap),
               dsap,
               tok2str(llc_ig_flag_values, "Unknown", dsap_field & LLC_IG),
               tok2str(llc_values, "Unknown", ssap),
               ssap,
               tok2str(llc_flag_values, "Unknown", ssap_field & LLC_GSAP));

        if (is_u) {
            printf(", ctrl 0x%02x: ", control);
        } else {
            printf(", ctrl 0x%04x: ", control);
        }
    }

    if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
            control == LLC_UI) {
        stp_print(p+3, length-3);
        return (1);
    }

    if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
            control == LLC_UI) {
        ip_print(gndo, p+4, length-4);
        return (1);
    }

    if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
            control == LLC_UI) {
        /*
         * This is an Ethernet_802.2 IPX frame, with an 802.3
         * header and an 802.2 LLC header with the source and
         * destination SAPs being the IPX SAP.
         *
         * Skip DSAP, LSAP, and control field.
         */
        if (eflag)
            printf("IPX 802.2: ");

        ipx_print(p+3, length-3);
        return (1);
    }

#ifdef TCPDUMP_DO_SMB
    if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
            && (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
        /*
         * we don't actually have a full netbeui parser yet, but the
         * smb parser can handle many smb-in-netbeui packets, which
         * is very useful, so we call that
         *
         * We don't call it for S frames, however, just I frames
         * (which are frames that don't have the low-order bit,
         * LLC_S_FMT, set in the first byte of the control field)
         * and UI frames (whose control field is just 3, LLC_U_FMT).
         */

        /*
         * Skip the LLC header.
         */
        if (is_u) {
            p += 3;
            length -= 3;
            caplen -= 3;
        } else {
            p += 4;
            length -= 4;
            caplen -= 4;
        }
        netbeui_print(control, p, length);
        return (1);
    }
#endif
    if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
            && control == LLC_UI) {
        isoclns_print(p + 3, length - 3, caplen - 3);
        return (1);
    }

    if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
            && control == LLC_UI) {
        /*
         * XXX - what *is* the right bridge pad value here?
         * Does anybody ever bridge one form of LAN traffic
         * over a networking type that uses 802.2 LLC?
         */
        ret = snap_print(p+3, length-3, caplen-3, extracted_ethertype,
                         2);
        if (ret)
            return (ret);
    }

    if (!eflag) {
        if (ssap == dsap) {
            if (esrc == NULL || edst == NULL)
                (void)printf("%s ", tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
            else
                (void)printf("%s > %s %s ",
                             etheraddr_string(esrc),
                             etheraddr_string(edst),
                             tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
        } else {
            if (esrc == NULL || edst == NULL)
                (void)printf("%s > %s ",
                             tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
                             tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
            else
                (void)printf("%s %s > %s %s ",
                             etheraddr_string(esrc),
                             tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
                             etheraddr_string(edst),
                             tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
        }
    }

    if (is_u) {
        printf("Unnumbered, %s, Flags [%s], length %u",
               tok2str(llc_cmd_values, "%02x", LLC_U_CMD(control)),
               tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_U_POLL)),
               length);

        p += 3;
        length -= 3;
        caplen -= 3;

        if ((control & ~LLC_U_POLL) == LLC_XID) {
            if (*p == LLC_XID_FI) {
                printf(": %02x %02x", p[1], p[2]);
                p += 3;
                length -= 3;
                caplen -= 3;
            }
        }
    } else {
        if ((control & LLC_S_FMT) == LLC_S_FMT) {
            (void)printf("Supervisory, %s, rcv seq %u, Flags [%s], length %u",
                         tok2str(llc_supervisory_values,"?",LLC_S_CMD(control)),
                         LLC_IS_NR(control),
                         tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
                         length);
        } else {
            (void)printf("Information, send seq %u, rcv seq %u, Flags [%s], length %u",
                         LLC_I_NS(control),
                         LLC_IS_NR(control),
                         tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
                         length);
        }
        p += 4;
        length -= 4;
        caplen -= 4;
    }
    return(1);
}
Beispiel #9
0
int
ethertype_print(netdissect_options *ndo,
                u_short ether_type, const u_char *p,
                u_int length, u_int caplen)
{
	switch (ether_type) {

	case ETHERTYPE_IP:
	        ip_print(ndo, p, length);
		return (1);

	case ETHERTYPE_IPV6:
		ip6_print(ndo, p, length);
		return (1);

	case ETHERTYPE_ARP:
	case ETHERTYPE_REVARP:
  	        arp_print(ndo, p, length, caplen);
		return (1);

	case ETHERTYPE_DN:
		decnet_print(ndo, p, length, caplen);
		return (1);

	case ETHERTYPE_ATALK:
		if (ndo->ndo_vflag)
			ND_PRINT((ndo, "et1 "));
		atalk_print(ndo, p, length);
		return (1);

	case ETHERTYPE_AARP:
		aarp_print(ndo, p, length);
		return (1);

	case ETHERTYPE_IPX:
		ND_PRINT((ndo, "(NOV-ETHII) "));
		ipx_print(ndo, p, length);
		return (1);

	case ETHERTYPE_ISO:
		isoclns_print(ndo, p + 1, length - 1, length - 1);
		return(1);

	case ETHERTYPE_PPPOED:
	case ETHERTYPE_PPPOES:
	case ETHERTYPE_PPPOED2:
	case ETHERTYPE_PPPOES2:
		pppoe_print(ndo, p, length);
		return (1);

	case ETHERTYPE_EAPOL:
	        eap_print(ndo, p, length);
		return (1);

	case ETHERTYPE_RRCP:
	        rrcp_print(ndo, p - 14 , length + 14);
		return (1);

	case ETHERTYPE_PPP:
		if (length) {
			ND_PRINT((ndo, ": "));
			ppp_print(ndo, p, length);
		}
		return (1);

	case ETHERTYPE_MPCP:
	        mpcp_print(ndo, p, length);
		return (1);

	case ETHERTYPE_SLOW:
	        slow_print(ndo, p, length);
		return (1);

	case ETHERTYPE_CFM:
	case ETHERTYPE_CFM_OLD:
		cfm_print(ndo, p, length);
		return (1);

	case ETHERTYPE_LLDP:
		lldp_print(ndo, p, length);
		return (1);

        case ETHERTYPE_LOOPBACK:
		loopback_print(ndo, p, length);
                return (1);

	case ETHERTYPE_MPLS:
	case ETHERTYPE_MPLS_MULTI:
		mpls_print(ndo, p, length);
		return (1);

	case ETHERTYPE_TIPC:
		tipc_print(ndo, p, length, caplen);
		return (1);

	case ETHERTYPE_MS_NLB_HB:
		msnlb_print(ndo, p);
		return (1);

        case ETHERTYPE_GEONET_OLD:
        case ETHERTYPE_GEONET:
                geonet_print(ndo, p-14, p, length);
                return (1);

        case ETHERTYPE_CALM_FAST:
                calm_fast_print(ndo, p-14, p, length);
                return (1);

	case ETHERTYPE_AOE:
		aoe_print(ndo, p, length);
		return (1);

	case ETHERTYPE_LAT:
	case ETHERTYPE_SCA:
	case ETHERTYPE_MOPRC:
	case ETHERTYPE_MOPDL:
	case ETHERTYPE_IEEE1905_1:
		/* default_print for now */
	default:
		return (0);
	}
}
Beispiel #10
0
/*
 * If we printed information about the payload, returns the length of the LLC
 * header, plus the length of any SNAP header following it.
 *
 * Otherwise (for example, if the packet has unknown SAPs or has a SNAP
 * header with an unknown OUI/PID combination), returns the *negative*
 * of that value.
 */
int
llc_print(netdissect_options *ndo, const u_char *p, u_int length, u_int caplen,
	  const struct lladdr_info *src, const struct lladdr_info *dst)
{
	uint8_t dsap_field, dsap, ssap_field, ssap;
	uint16_t control;
	int hdrlen;
	int is_u;

	if (caplen < 3) {
		ND_PRINT("[|llc]");
		ND_DEFAULTPRINT((const u_char *)p, caplen);
		return (caplen);
	}
	if (length < 3) {
		ND_PRINT("[|llc]");
		ND_DEFAULTPRINT((const u_char *)p, caplen);
		return (length);
	}

	dsap_field = EXTRACT_U_1(p);
	ssap_field = EXTRACT_U_1(p + 1);

	/*
	 * OK, what type of LLC frame is this?  The length
	 * of the control field depends on that - I frames
	 * have a two-byte control field, and U frames have
	 * a one-byte control field.
	 */
	control = EXTRACT_U_1(p + 2);
	if ((control & LLC_U_FMT) == LLC_U_FMT) {
		/*
		 * U frame.
		 */
		is_u = 1;
		hdrlen = 3;	/* DSAP, SSAP, 1-byte control field */
	} else {
		/*
		 * The control field in I and S frames is
		 * 2 bytes...
		 */
		if (caplen < 4) {
			ND_PRINT("[|llc]");
			ND_DEFAULTPRINT((const u_char *)p, caplen);
			return (caplen);
		}
		if (length < 4) {
			ND_PRINT("[|llc]");
			ND_DEFAULTPRINT((const u_char *)p, caplen);
			return (length);
		}

		/*
		 * ...and is little-endian.
		 */
		control = EXTRACT_LE_U_2(p + 2);
		is_u = 0;
		hdrlen = 4;	/* DSAP, SSAP, 2-byte control field */
	}

	if (ssap_field == LLCSAP_GLOBAL && dsap_field == LLCSAP_GLOBAL) {
		/*
		 * This is an Ethernet_802.3 IPX frame; it has an
		 * 802.3 header (i.e., an Ethernet header where the
		 * type/length field is <= MAX_ETHERNET_LENGTH_VAL,
		 * i.e. it's a length field, not a type field), but
		 * has no 802.2 header - the IPX packet starts right
		 * after the Ethernet header, with a signature of two
		 * bytes of 0xFF (which is LLCSAP_GLOBAL).
		 *
		 * (It might also have been an Ethernet_802.3 IPX at
		 * one time, but got bridged onto another network,
		 * such as an 802.11 network; this has appeared in at
		 * least one capture file.)
		 */

            if (ndo->ndo_eflag)
		ND_PRINT("IPX 802.3: ");

            ipx_print(ndo, p, length);
            return (0);		/* no LLC header */
	}

	dsap = dsap_field & ~LLC_IG;
	ssap = ssap_field & ~LLC_GSAP;

	if (ndo->ndo_eflag) {
                ND_PRINT("LLC, dsap %s (0x%02x) %s, ssap %s (0x%02x) %s",
                       tok2str(llc_values, "Unknown", dsap),
                       dsap,
                       tok2str(llc_ig_flag_values, "Unknown", dsap_field & LLC_IG),
                       tok2str(llc_values, "Unknown", ssap),
                       ssap,
                       tok2str(llc_flag_values, "Unknown", ssap_field & LLC_GSAP));

		if (is_u) {
			ND_PRINT(", ctrl 0x%02x: ", control);
		} else {
			ND_PRINT(", ctrl 0x%04x: ", control);
		}
	}

	/*
	 * Skip LLC header.
	 */
	p += hdrlen;
	length -= hdrlen;
	caplen -= hdrlen;

	if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
	    && control == LLC_UI) {
		/*
		 * XXX - what *is* the right bridge pad value here?
		 * Does anybody ever bridge one form of LAN traffic
		 * over a networking type that uses 802.2 LLC?
		 */
		if (!snap_print(ndo, p, length, caplen, src, dst, 2)) {
			/*
			 * Unknown packet type; tell our caller, by
			 * returning a negative value, so they
			 * can print the raw packet.
			 */
			return (-(hdrlen + 5));	/* include LLC and SNAP header */
		} else
			return (hdrlen + 5);	/* include LLC and SNAP header */
	}

	if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
	    control == LLC_UI) {
		stp_print(ndo, p, length);
		return (hdrlen);
	}

	if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
	    control == LLC_UI) {
		/*
		 * This is an RFC 948-style IP packet, with
		 * an 802.3 header and an 802.2 LLC header
		 * with the source and destination SAPs being
		 * the IP SAP.
		 */
		ip_print(ndo, p, length);
		return (hdrlen);
	}

	if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
	    control == LLC_UI) {
		/*
		 * This is an Ethernet_802.2 IPX frame, with an 802.3
		 * header and an 802.2 LLC header with the source and
		 * destination SAPs being the IPX SAP.
		 */
                if (ndo->ndo_eflag)
                        ND_PRINT("IPX 802.2: ");

		ipx_print(ndo, p, length);
		return (hdrlen);
	}

#ifdef ENABLE_SMB
	if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
	    && (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
		/*
		 * we don't actually have a full netbeui parser yet, but the
		 * smb parser can handle many smb-in-netbeui packets, which
		 * is very useful, so we call that
		 *
		 * We don't call it for S frames, however, just I frames
		 * (which are frames that don't have the low-order bit,
		 * LLC_S_FMT, set in the first byte of the control field)
		 * and UI frames (whose control field is just 3, LLC_U_FMT).
		 */
		netbeui_print(ndo, control, p, length);
		return (hdrlen);
	}
#endif
	if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
	    && control == LLC_UI) {
		isoclns_print(ndo, p, length);
		return (hdrlen);
	}

	if (!ndo->ndo_eflag) {
		if (ssap == dsap) {
			if (src == NULL || dst == NULL)
				ND_PRINT("%s ", tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
			else
				ND_PRINT("%s > %s %s ",
						(src->addr_string)(ndo, src->addr),
						(dst->addr_string)(ndo, dst->addr),
						tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
		} else {
			if (src == NULL || dst == NULL)
				ND_PRINT("%s > %s ",
                                        tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
					tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
			else
				ND_PRINT("%s %s > %s %s ",
					(src->addr_string)(ndo, src->addr),
                                        tok2str(llc_values, "Unknown SSAP 0x%02x", ssap),
					(dst->addr_string)(ndo, dst->addr),
					tok2str(llc_values, "Unknown DSAP 0x%02x", dsap));
		}
	}

	if (is_u) {
		ND_PRINT("Unnumbered, %s, Flags [%s], length %u",
                       tok2str(llc_cmd_values, "%02x", LLC_U_CMD(control)),
                       tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_U_POLL)),
                       length + hdrlen);

		if ((control & ~LLC_U_POLL) == LLC_XID) {
			if (length == 0) {
				/*
				 * XID with no payload.
				 * This could, for example, be an SNA
				 * "short form" XID.
                                 */
				return (hdrlen);
			}
			if (caplen < 1) {
				ND_PRINT("[|llc]");
				if (caplen > 0)
					ND_DEFAULTPRINT((const u_char *)p, caplen);
				return (hdrlen);
			}
			if (EXTRACT_U_1(p) == LLC_XID_FI) {
				if (caplen < 3 || length < 3) {
					ND_PRINT("[|llc]");
					if (caplen > 0)
						ND_DEFAULTPRINT((const u_char *)p, caplen);
				} else
					ND_PRINT(": %02x %02x",
						  EXTRACT_U_1(p + 1),
						  EXTRACT_U_1(p + 2));
				return (hdrlen);
			}
		}
	} else {
		if ((control & LLC_S_FMT) == LLC_S_FMT) {
			ND_PRINT("Supervisory, %s, rcv seq %u, Flags [%s], length %u",
				tok2str(llc_supervisory_values,"?",LLC_S_CMD(control)),
				LLC_IS_NR(control),
				tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
                                length + hdrlen);
			return (hdrlen);	/* no payload to print */
		} else {
			ND_PRINT("Information, send seq %u, rcv seq %u, Flags [%s], length %u",
				LLC_I_NS(control),
				LLC_IS_NR(control),
				tok2str(llc_flag_values,"?",(ssap_field & LLC_GSAP) | (control & LLC_IS_POLL)),
                                length + hdrlen);
		}
	}
	return (-hdrlen);
}
Beispiel #11
0
static const char *
fmt_sockaddr(struct sockaddr *sa, struct sockaddr *mask, int flags)
{
	static char workbuf[128];
	const char *cp;

	switch(sa->sa_family) {
	case AF_INET:
	    {
		struct sockaddr_in *sockin = (struct sockaddr_in *)sa;

		if ((sockin->sin_addr.s_addr == INADDR_ANY) &&
			mask &&
			ntohl(((struct sockaddr_in *)mask)->sin_addr.s_addr)
				==0L)
				cp = "default" ;
		else if (flags & RTF_HOST)
			cp = routename(sockin->sin_addr.s_addr);
		else if (mask)
			cp = netname(sockin->sin_addr.s_addr,
				     ntohl(((struct sockaddr_in *)mask)
					   ->sin_addr.s_addr));
		else
			cp = netname(sockin->sin_addr.s_addr, 0L);
		break;
	    }

#ifdef INET6
	case AF_INET6:
	    {
		struct sockaddr_in6 *sa6 = (struct sockaddr_in6 *)sa;
		struct in6_addr *in6 = &sa6->sin6_addr;

		/*
		 * XXX: This is a special workaround for KAME kernels.
		 * sin6_scope_id field of SA should be set in the future.
		 */
		if (IN6_IS_ADDR_LINKLOCAL(in6) ||
		    IN6_IS_ADDR_MC_LINKLOCAL(in6) ||
		    IN6_IS_ADDR_MC_NODELOCAL(in6)) {
		    /* XXX: override is ok? */
		    sa6->sin6_scope_id = (u_int32_t)ntohs(*(u_short *)&in6->s6_addr[2]);
		    *(u_short *)&in6->s6_addr[2] = 0;
		}

		if (flags & RTF_HOST)
		    cp = routename6(sa6);
		else if (mask)
		    cp = netname6(sa6,
				  &((struct sockaddr_in6 *)mask)->sin6_addr);
		else {
		    cp = netname6(sa6, NULL);
		}
		break;
	    }
#endif /*INET6*/

	case AF_IPX:
	    {
		struct ipx_addr work = ((struct sockaddr_ipx *)sa)->sipx_addr;
		if (ipx_nullnet(satoipx_addr(work)))
			cp = "default";
		else
			cp = ipx_print(sa);
		break;
	    }
	case AF_APPLETALK:
	    {
		if (!(flags & RTF_HOST) && mask)
			cp = atalk_print2(sa,mask,9);
		else
			cp = atalk_print(sa,11);
		break;
	    }
	case AF_NETGRAPH:
	    {
		printf("%s", ((struct sockaddr_ng *)sa)->sg_data);
		break;
	    }

	case AF_LINK:
	    {
		struct sockaddr_dl *sdl = (struct sockaddr_dl *)sa;

		if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 &&
		    sdl->sdl_slen == 0) {
			(void) sprintf(workbuf, "link#%d", sdl->sdl_index);
			cp = workbuf;
		} else
			switch (sdl->sdl_type) {

			case IFT_ETHER:
			case IFT_L2VLAN:
				if (sdl->sdl_alen == ETHER_ADDR_LEN) {
					cp = ether_ntoa((struct ether_addr *)
					    (sdl->sdl_data + sdl->sdl_nlen));
					break;
				}
				/* FALLTHROUGH */
			default:
				cp = link_ntoa(sdl);
				break;
			}
		break;
	    }

	default:
	    {
		u_char *s = (u_char *)sa->sa_data, *slim;
		char *cq, *cqlim;

		cq = workbuf;
		slim =  sa->sa_len + (u_char *) sa;
		cqlim = cq + sizeof(workbuf) - 6;
		cq += sprintf(cq, "(%d)", sa->sa_family);
		while (s < slim && cq < cqlim) {
			cq += sprintf(cq, " %02x", *s++);
			if (s < slim)
			    cq += sprintf(cq, "%02x", *s++);
		}
		cp = workbuf;
	    }
	}

	return (cp);
}
Beispiel #12
0
void
gre_print_0(const u_char *bp, u_int length)
{
	u_int len = length;
	u_int16_t flags, prot;

	flags = EXTRACT_16BITS(bp);
        if (vflag)
            printf(", Flags [%s]",
                   bittok2str(gre_flag_values,"none",flags));

	len -= 2;
	bp += 2;

	if (len < 2)
		goto trunc;
	prot = EXTRACT_16BITS(bp);
	len -= 2;
	bp += 2;

	if ((flags & GRE_CP) | (flags & GRE_RP)) {
		if (len < 2)
			goto trunc;
		if (vflag)
			printf(", sum 0x%x", EXTRACT_16BITS(bp));
		bp += 2;
		len -= 2;

		if (len < 2)
			goto trunc;
		printf(", off 0x%x", EXTRACT_16BITS(bp));
		bp += 2;
		len -= 2;
	}

	if (flags & GRE_KP) {
		if (len < 4)
			goto trunc;
		printf(", key=0x%x", EXTRACT_32BITS(bp));
		bp += 4;
		len -= 4;
	}

	if (flags & GRE_SP) {
		if (len < 4)
			goto trunc;
		printf(", seq %u", EXTRACT_32BITS(bp));
		bp += 4;
		len -= 4;
	}

	if (flags & GRE_RP) {
		for (;;) {
			u_int16_t af;
			u_int8_t sreoff;
			u_int8_t srelen;

			if (len < 4)
				goto trunc;
			af = EXTRACT_16BITS(bp);
			sreoff = *(bp + 2);
			srelen = *(bp + 3);
			bp += 4;
			len -= 4;

			if (af == 0 && srelen == 0)
				break;

			gre_sre_print(af, sreoff, srelen, bp, len);

			if (len < srelen)
				goto trunc;
			bp += srelen;
			len -= srelen;
		}
	}

        if (eflag)
            printf(", proto %s (0x%04x)",
                   tok2str(ethertype_values,"unknown",prot),
                   prot);

        printf(", length %u",length);

        if (vflag < 1)
            printf(": "); /* put in a colon as protocol demarc */
        else
            printf("\n\t"); /* if verbose go multiline */

	switch (prot) {
	case ETHERTYPE_IP:
	        ip_print(gndo, bp, len);
		break;
#ifdef INET6
	case ETHERTYPE_IPV6:
		ip6_print(gndo, bp, len);
		break;
#endif
	case ETHERTYPE_MPLS:
		mpls_print(bp, len);
		break;
	case ETHERTYPE_IPX:
		ipx_print(bp, len);
		break;
	case ETHERTYPE_ATALK:
		atalk_print(bp, len);
		break;
	case ETHERTYPE_GRE_ISO:
		isoclns_print(bp, len, len);
		break;
	case ETHERTYPE_TEB:
		ether_print(gndo, bp, len, len, NULL, NULL);
		break;
	default:
		printf("gre-proto-0x%x", prot);
	}
	return;

trunc:
	printf("[|gre]");
}
Beispiel #13
0
static void
gre_print_0(netdissect_options *ndo, const u_char *bp, u_int length)
{
	u_int len = length;
	uint16_t flags, prot;

	/* 16 bits ND_TCHECKed in gre_print() */
	flags = EXTRACT_BE_U_2(bp);
        if (ndo->ndo_vflag)
            ND_PRINT(", Flags [%s]",
                   bittok2str(gre_flag_values,"none",flags));

	len -= 2;
	bp += 2;

	ND_TCHECK_2(bp);
	if (len < 2)
		goto trunc;
	prot = EXTRACT_BE_U_2(bp);
	len -= 2;
	bp += 2;

	if ((flags & GRE_CP) | (flags & GRE_RP)) {
		ND_TCHECK_2(bp);
		if (len < 2)
			goto trunc;
		if (ndo->ndo_vflag)
			ND_PRINT(", sum 0x%x", EXTRACT_BE_U_2(bp));
		bp += 2;
		len -= 2;

		ND_TCHECK_2(bp);
		if (len < 2)
			goto trunc;
		ND_PRINT(", off 0x%x", EXTRACT_BE_U_2(bp));
		bp += 2;
		len -= 2;
	}

	if (flags & GRE_KP) {
		ND_TCHECK_4(bp);
		if (len < 4)
			goto trunc;
		ND_PRINT(", key=0x%x", EXTRACT_BE_U_4(bp));
		bp += 4;
		len -= 4;
	}

	if (flags & GRE_SP) {
		ND_TCHECK_4(bp);
		if (len < 4)
			goto trunc;
		ND_PRINT(", seq %u", EXTRACT_BE_U_4(bp));
		bp += 4;
		len -= 4;
	}

	if (flags & GRE_RP) {
		for (;;) {
			uint16_t af;
			uint8_t sreoff;
			uint8_t srelen;

			ND_TCHECK_4(bp);
			if (len < 4)
				goto trunc;
			af = EXTRACT_BE_U_2(bp);
			sreoff = EXTRACT_U_1(bp + 2);
			srelen = EXTRACT_U_1(bp + 3);
			bp += 4;
			len -= 4;

			if (af == 0 && srelen == 0)
				break;

			if (!gre_sre_print(ndo, af, sreoff, srelen, bp, len))
				goto trunc;

			if (len < srelen)
				goto trunc;
			bp += srelen;
			len -= srelen;
		}
	}

        if (ndo->ndo_eflag)
            ND_PRINT(", proto %s (0x%04x)",
                   tok2str(ethertype_values,"unknown",prot),
                   prot);

        ND_PRINT(", length %u",length);

        if (ndo->ndo_vflag < 1)
            ND_PRINT(": "); /* put in a colon as protocol demarc */
        else
            ND_PRINT("\n\t"); /* if verbose go multiline */

	switch (prot) {
	case ETHERTYPE_IP:
	        ip_print(ndo, bp, len);
		break;
	case ETHERTYPE_IPV6:
		ip6_print(ndo, bp, len);
		break;
	case ETHERTYPE_MPLS:
		mpls_print(ndo, bp, len);
		break;
	case ETHERTYPE_IPX:
		ipx_print(ndo, bp, len);
		break;
	case ETHERTYPE_ATALK:
		atalk_print(ndo, bp, len);
		break;
	case ETHERTYPE_GRE_ISO:
		isoclns_print(ndo, bp, len);
		break;
	case ETHERTYPE_TEB:
		ether_print(ndo, bp, len, ndo->ndo_snapend - bp, NULL, NULL);
		break;
	default:
		ND_PRINT("gre-proto-0x%x", prot);
	}
	return;

trunc:
	ND_PRINT("%s", tstr);
}
Beispiel #14
0
/*
 * Returns non-zero IFF it succeeds in printing the header
 */
int
llc_print(const u_char *p, u_int length, u_int caplen,
	  const u_char *esrc, const u_char *edst, u_short *extracted_ethertype)
{
	u_int8_t dsap, ssap;
	u_int16_t control;
	int is_u;
	register int ret;

	if (caplen < 3) {
		(void)printf("[|llc]");
		default_print((u_char *)p, caplen);
		return(0);
	}

	dsap = *p;
	ssap = *(p + 1);

	/*
	 * OK, what type of LLC frame is this?  The length
	 * of the control field depends on that - I frames
	 * have a two-byte control field, and U frames have
	 * a one-byte control field.
	 */
	control = *(p + 2);
	if ((control & LLC_U_FMT) == LLC_U_FMT) {
		/*
		 * U frame.
		 */
		is_u = 1;
	} else {
		/*
		 * The control field in I and S frames is
		 * 2 bytes...
		 */
		if (caplen < 4) {
			(void)printf("[|llc]");
			default_print((u_char *)p, caplen);
			return(0);
		}

		/*
		 * ...and is little-endian.
		 */
		control = EXTRACT_LE_16BITS(p + 2);
		is_u = 0;
	}

#if !defined(EMBED) || defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
	if (ssap == LLCSAP_GLOBAL && dsap == LLCSAP_GLOBAL) {
		/*
		 * This is an Ethernet_802.3 IPX frame; it has an
		 * 802.3 header (i.e., an Ethernet header where the
		 * type/length field is <= ETHERMTU, i.e. it's a length
		 * field, not a type field), but has no 802.2 header -
		 * the IPX packet starts right after the Ethernet header,
		 * with a signature of two bytes of 0xFF (which is
		 * LLCSAP_GLOBAL).
		 *
		 * (It might also have been an Ethernet_802.3 IPX at
		 * one time, but got bridged onto another network,
		 * such as an 802.11 network; this has appeared in at
		 * least one capture file.)
		 */

            if (eflag)
		printf("IPX-802.3: ");

            ipx_print(p, length);
            return (1);
	}
#endif

	if (eflag) {
		if (is_u) {
			printf("LLC, dsap %s (0x%02x), ssap %s (0x%02x), cmd 0x%02x: ",
			    tok2str(llc_values, "Unknown", dsap),
			    dsap,
			    tok2str(llc_values, "Unknown", ssap),
			    ssap,
			    control);
		} else {
			printf("LLC, dsap %s (0x%02x), ssap %s (0x%02x), cmd 0x%04x: ",
			    tok2str(llc_values, "Unknown", dsap),
			    dsap,
			    tok2str(llc_values, "Unknown", ssap),
			    ssap,
			    control);
		}
	}

#if !defined(EMBED) || defined(CONFIG_BRIDGE) || defined(CONFIG_BRIDGE_MODULE)
	if (ssap == LLCSAP_8021D && dsap == LLCSAP_8021D &&
	    control == LLC_UI) {
		stp_print(p+3, length-3);
		return (1);
	}
#endif

	if (ssap == LLCSAP_IP && dsap == LLCSAP_IP &&
	    control == LLC_UI) {
		ip_print(gndo, p+4, length-4);
		return (1);
	}

#if !defined(EMBED) || defined(CONFIG_IPX) || defined(CONFIG_IPX_MODULE)
	if (ssap == LLCSAP_IPX && dsap == LLCSAP_IPX &&
	    control == LLC_UI) {
		/*
		 * This is an Ethernet_802.2 IPX frame, with an 802.3
		 * header and an 802.2 LLC header with the source and
		 * destination SAPs being the IPX SAP.
		 *
		 * Skip DSAP, LSAP, and control field.
		 */
		printf("(NOV-802.2) ");
		ipx_print(p+3, length-3);
		return (1);
	}
#endif

#ifdef TCPDUMP_DO_SMB
	if (ssap == LLCSAP_NETBEUI && dsap == LLCSAP_NETBEUI
	    && (!(control & LLC_S_FMT) || control == LLC_U_FMT)) {
		/*
		 * we don't actually have a full netbeui parser yet, but the
		 * smb parser can handle many smb-in-netbeui packets, which
		 * is very useful, so we call that
		 *
		 * We don't call it for S frames, however, just I frames
		 * (which are frames that don't have the low-order bit,
		 * LLC_S_FMT, set in the first byte of the control field)
		 * and UI frames (whose control field is just 3, LLC_U_FMT).
		 */

		/*
		 * Skip the LLC header.
		 */
		if (is_u) {
			p += 3;
			length -= 3;
			caplen -= 3;
		} else {
			p += 4;
			length -= 4;
			caplen -= 4;
		}
		netbeui_print(control, p, length);
		return (1);
	}
#endif
#if !defined(EMBED)
	if (ssap == LLCSAP_ISONS && dsap == LLCSAP_ISONS
	    && control == LLC_UI) {
		isoclns_print(p + 3, length - 3, caplen - 3);
		return (1);
	}
#endif

	if (ssap == LLCSAP_SNAP && dsap == LLCSAP_SNAP
	    && control == LLC_UI) {
		/*
		 * XXX - what *is* the right bridge pad value here?
		 * Does anybody ever bridge one form of LAN traffic
		 * over a networking type that uses 802.2 LLC?
		 */
		ret = snap_print(p+3, length-3, caplen-3, extracted_ethertype,
		    2);
		if (ret)
			return (ret);
	}

	if (!eflag) {
		if ((ssap & ~LLC_GSAP) == dsap) {
			if (esrc == NULL || edst == NULL)
				(void)printf("%s ", llcsap_string(dsap));
			else
				(void)printf("%s > %s %s ",
						etheraddr_string(esrc),
						etheraddr_string(edst),
						llcsap_string(dsap));
		} else {
			if (esrc == NULL || edst == NULL)
				(void)printf("%s > %s ",
					llcsap_string(ssap & ~LLC_GSAP),
					llcsap_string(dsap));
			else
				(void)printf("%s %s > %s %s ",
					etheraddr_string(esrc),
					llcsap_string(ssap & ~LLC_GSAP),
					etheraddr_string(edst),
					llcsap_string(dsap));
		}
	}

	if (is_u) {
		const char *m;
		char f;

		m = tok2str(cmd2str, "%02x", LLC_U_CMD(control));
		switch ((ssap & LLC_GSAP) | (control & LLC_U_POLL)) {
			case 0:			f = 'C'; break;
			case LLC_GSAP:		f = 'R'; break;
			case LLC_U_POLL:	f = 'P'; break;
			case LLC_GSAP|LLC_U_POLL: f = 'F'; break;
			default:		f = '?'; break;
		}

		printf("%s/%c", m, f);

		p += 3;
		length -= 3;
		caplen -= 3;

		if ((control & ~LLC_U_POLL) == LLC_XID) {
			if (*p == LLC_XID_FI) {
				printf(": %02x %02x", p[1], p[2]);
				p += 3;
				length -= 3;
				caplen -= 3;
			}
		}
	} else {
		char f;

		switch ((ssap & LLC_GSAP) | (control & LLC_IS_POLL)) {
			case 0:			f = 'C'; break;
			case LLC_GSAP:		f = 'R'; break;
			case LLC_IS_POLL:	f = 'P'; break;
			case LLC_GSAP|LLC_IS_POLL: f = 'F'; break;
			default:		f = '?'; break;
		}

		if ((control & LLC_S_FMT) == LLC_S_FMT) {
			static const char *llc_s[] = { "rr", "rej", "rnr", "03" };
			(void)printf("%s (r=%d,%c)",
				llc_s[LLC_S_CMD(control)],
				LLC_IS_NR(control),
				f);
		} else {
			(void)printf("I (s=%d,r=%d,%c)",
				LLC_I_NS(control),
				LLC_IS_NR(control),
				f);
		}
		p += 4;
		length -= 4;
		caplen -= 4;
	}
	return(1);
}
Beispiel #15
0
/*
 * This is the top level routine of the printer.  'p' points to the
 * Linux "cooked capture" 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.
 */
u_int
sll_if_print(netdissect_options *ndo, const struct pcap_pkthdr *h, const u_char *p)
{
	u_int caplen = h->caplen;
	u_int length = h->len;
	register const struct sll_header *sllp;
	u_short ether_type;
	int llc_hdrlen;
	u_int hdrlen;

	if (caplen < SLL_HDR_LEN) {
		/*
		 * XXX - this "can't happen" because "pcap-linux.c" always
		 * adds this many bytes of header to every packet in a
		 * cooked socket capture.
		 */
		ND_PRINT((ndo, "[|sll]"));
		return (caplen);
	}

	sllp = (const struct sll_header *)p;

	if (ndo->ndo_eflag)
		sll_print(ndo, sllp, length);

	/*
	 * Go past the cooked-mode header.
	 */
	length -= SLL_HDR_LEN;
	caplen -= SLL_HDR_LEN;
	p += SLL_HDR_LEN;
	hdrlen = SLL_HDR_LEN;

	ether_type = EXTRACT_16BITS(&sllp->sll_protocol);

recurse:
	/*
	 * Is it (gag) an 802.3 encapsulation, or some non-Ethernet
	 * packet type?
	 */
	if (ether_type <= ETHERMTU) {
		/*
		 * Yes - what type is it?
		 */
		switch (ether_type) {

		case LINUX_SLL_P_802_3:
			/*
			 * Ethernet_802.3 IPX frame.
			 */
			ipx_print(ndo, p, length);
			break;

		case LINUX_SLL_P_802_2:
			/*
			 * 802.2.
			 * Try to print the LLC-layer header & higher layers.
			 */
			llc_hdrlen = llc_print(ndo, p, length, caplen, NULL, NULL);
			if (llc_hdrlen < 0)
				goto unknown;	/* unknown LLC type */
			hdrlen += llc_hdrlen;
			break;

		default:
			/*FALLTHROUGH*/

		unknown:
			/* packet type not known, print raw packet */
			if (!ndo->ndo_suppress_default_print)
				ND_DEFAULTPRINT(p, caplen);
			break;
		}
	} else if (ether_type == ETHERTYPE_8021Q) {
		/*
		 * Print VLAN information, and then go back and process
		 * the enclosed type field.
		 */
		if (caplen < 4) {
			ND_PRINT((ndo, "[|vlan]"));
			return (hdrlen + caplen);
		}
		if (length < 4) {
			ND_PRINT((ndo, "[|vlan]"));
			return (hdrlen + length);
		}
	        if (ndo->ndo_eflag) {
	        	uint16_t tag = EXTRACT_16BITS(p);

			ND_PRINT((ndo, "%s, ", ieee8021q_tci_string(tag)));
		}

		ether_type = EXTRACT_16BITS(p + 2);
		if (ether_type <= ETHERMTU)
			ether_type = LINUX_SLL_P_802_2;
		if (!ndo->ndo_qflag) {
			ND_PRINT((ndo, "ethertype %s, ",
			    tok2str(ethertype_values, "Unknown", ether_type)));
		}
		p += 4;
		length -= 4;
		caplen -= 4;
		hdrlen += 4;
		goto recurse;
	} else {
		if (ethertype_print(ndo, ether_type, p, length, caplen) == 0) {
			/* ether_type not known, print raw packet */
			if (!ndo->ndo_eflag)
				sll_print(ndo, sllp, length + SLL_HDR_LEN);
			if (!ndo->ndo_suppress_default_print)
				ND_DEFAULTPRINT(p, caplen);
		}
	}

	return (hdrlen);
}
Beispiel #16
0
/*
 * Returns non-zero IFF it succeeds in printing the header
 */
int
llc_print(const u_char *p, u_int length, u_int caplen,
	  const u_char *esrc, const u_char *edst)
{
	struct llc llc;
	register u_short et;
	register int ret;

	if (caplen < 3) {
		(void)printf("[|llc]");
		default_print((u_char *)p, caplen);
		return(0);
	}

	/* Watch out for possible alignment problems */
	memcpy((char *)&llc, (char *)p, min(caplen, sizeof(llc)));

	if (llc.ssap == LLCSAP_GLOBAL && llc.dsap == LLCSAP_GLOBAL) {
		ipx_print(p, length);
		return (1);
	}
#ifdef notyet
	else if (p[0] == 0xf0 && p[1] == 0xf0)
		netbios_print(p, length);
#endif
	if (llc.ssap == LLCSAP_ISONS && llc.dsap == LLCSAP_ISONS
	    && llc.llcui == LLC_UI) {
		isoclns_print(p + 3, length - 3, caplen - 3, esrc, edst);
		return (1);
	}

	if (llc.ssap == LLCSAP_SNAP && llc.dsap == LLCSAP_SNAP
	    && llc.llcui == LLC_UI) {
		if (caplen < sizeof(llc)) {
		    (void)printf("[|llc-snap]");
		    default_print((u_char *)p, caplen);
		    return (0);
		}
		if (vflag)
			(void)printf("snap %s ", protoid_string(llc.llcpi));

		caplen -= sizeof(llc);
		length -= sizeof(llc);
		p += sizeof(llc);

		/* This is an encapsulated Ethernet packet */
		et = EXTRACT_16BITS(&llc.ethertype[0]);
		ret = ether_encap_print(et, p, length, caplen);
		if (ret)
			return (ret);
	}

	if ((llc.ssap & ~LLC_GSAP) == llc.dsap) {
		if (eflag)
			(void)printf("%s ", llcsap_string(llc.dsap));
		else
			(void)printf("%s > %s %s ",
					etheraddr_string(esrc),
					etheraddr_string(edst),
					llcsap_string(llc.dsap));
	} else {
		if (eflag)
			(void)printf("%s > %s ",
				llcsap_string(llc.ssap & ~LLC_GSAP),
				llcsap_string(llc.dsap));
		else
			(void)printf("%s %s > %s %s ",
				etheraddr_string(esrc),
				llcsap_string(llc.ssap & ~LLC_GSAP),
				etheraddr_string(edst),
				llcsap_string(llc.dsap));
	}

	if ((llc.llcu & LLC_U_FMT) == LLC_U_FMT) {
		const char *m;
		char f;
		m = tok2str(cmd2str, "%02x", LLC_U_CMD(llc.llcu));
		switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
		    case 0:			f = 'C'; break;
		    case LLC_GSAP:		f = 'R'; break;
		    case LLC_U_POLL:		f = 'P'; break;
		    case LLC_GSAP|LLC_U_POLL:	f = 'F'; break;
		    default:			f = '?'; break;
		}

		printf("%s/%c", m, f);

		p += 3;
		length -= 3;
		caplen -= 3;

		if ((llc.llcu & ~LLC_U_POLL) == LLC_XID) {
		    if (*p == LLC_XID_FI) {
			printf(": %02x %02x", p[1], p[2]);
			p += 3;
			length -= 3;
			caplen -= 3;
		    }
		}
	} else {
		char f;
		llc.llcis = ntohs(llc.llcis);
		switch ((llc.ssap & LLC_GSAP) | (llc.llcu & LLC_U_POLL)) {
		    case 0:			f = 'C'; break;
		    case LLC_GSAP:		f = 'R'; break;
		    case LLC_U_POLL:		f = 'P'; break;
		    case LLC_GSAP|LLC_U_POLL:	f = 'F'; break;
		    default:			f = '?'; break;
		}

		if ((llc.llcu & LLC_S_FMT) == LLC_S_FMT) {
			static char *llc_s[] = { "rr", "rej", "rnr", "03" };
			(void)printf("%s (r=%d,%c)",
				llc_s[LLC_S_CMD(llc.llcis)],
				LLC_IS_NR(llc.llcis),
				f);
		} else {
			(void)printf("I (s=%d,r=%d,%c)",
				LLC_I_NS(llc.llcis),
				LLC_IS_NR(llc.llcis),
				f);
		}
		p += 4;
		length -= 4;
		caplen -= 4;
	}
	(void)printf(" len=%d", length);
	if (caplen > 0) {
		default_print_unaligned(p, caplen);
	}
	return(1);
}