print-ppp.c

来自「TCPDUMP的C语言源代码,是在数据链路层的应用」· C语言 代码 · 共 1,758 行 · 第 1/3 页

C
1,758
字号
		return 0;	if (len < 2) {	        printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",        	       tok2str(ccpconfopts_values, "Unknown", opt),	               opt,        	       len);        	return 0;        }        printf("\n\t  %s Option (0x%02x), length %u:",               tok2str(ccpconfopts_values, "Unknown", opt),               opt,               len);	switch (opt) {                /* fall through --> default: nothing supported yet */	case CCPOPT_OUI:	case CCPOPT_PRED1:	case CCPOPT_PRED2:	case CCPOPT_PJUMP:	case CCPOPT_HPPPC:	case CCPOPT_STACLZS:	case CCPOPT_MPPC:	case CCPOPT_GFZA:	case CCPOPT_V42BIS:	case CCPOPT_BSDCOMP:	case CCPOPT_LZSDCP:	case CCPOPT_MVRCA:	case CCPOPT_DEC:	case CCPOPT_DEFLATE:	case CCPOPT_RESV:	default:                if(vflag<2)                        print_unknown_data(&p[2],"\n\t    ",len-2);		break;	}        if (vflag>1)                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */	return len;trunc:	printf("[|ccp]");	return 0;}/* BACP config options */static intprint_bacp_config_options(const u_char *p, int length){	int len, opt;	if (length < 2)		return 0;	TCHECK2(*p, 2);	len = p[1];	opt = p[0];	if (length < len)		return 0;	if (len < 2) {	        printf("\n\t  %s Option (0x%02x), length %u (bogus, should be >= 2)",        	       tok2str(bacconfopts_values, "Unknown", opt),	               opt,        	       len);        	return 0;        }        printf("\n\t  %s Option (0x%02x), length %u:",               tok2str(bacconfopts_values, "Unknown", opt),               opt,               len);	switch (opt) {	case BACPOPT_FPEER:		TCHECK2(*(p + 2), 4);		printf(", Magic-Num 0x%08x", EXTRACT_32BITS(p + 2));                break;	default:                if(vflag<2)                        print_unknown_data(&p[2],"\n\t    ",len-2);		break;	}        if (vflag>1)                print_unknown_data(&p[2],"\n\t    ",len-2); /* exclude TLV header */	return len;trunc:	printf("[|bacp]");	return 0;}static voidppp_hdlc(const u_char *p, int length){	u_char *b, *s, *t, c;	int i, proto;	const void *se;	b = (u_int8_t *)malloc(length);	if (b == NULL)		return;	/*	 * Unescape all the data into a temporary, private, buffer.	 * Do this so that we dont overwrite the original packet	 * contents.	 */	for (s = (u_char *)p, t = b, i = length; i > 0; i--) {		c = *s++;		if (c == 0x7d) {			if (i > 1) {				i--;				c = *s++ ^ 0x20;			} else				continue;		}		*t++ = c;	}	se = snapend;	snapend = t;        /* now lets guess about the payload codepoint format */        proto = *b; /* start with a one-octet codepoint guess */                switch (proto) {        case PPP_IP:		ip_print(gndo, b+1, t - b - 1);		goto cleanup;#ifdef INET6        case PPP_IPV6:            ip6_print(b+1, t - b - 1);            goto cleanup;#endif        default: /* no luck - try next guess */            break;        }        proto = EXTRACT_16BITS(b); /* next guess - load two octets */        switch (proto) {        case (PPP_ADDRESS << 8 | PPP_CONTROL): /* looks like a PPP frame */            proto = EXTRACT_16BITS(b+2); /* load the PPP proto-id */            handle_ppp(proto, b+4, t - b - 4);            break;        default: /* last guess - proto must be a PPP proto-id */            handle_ppp(proto, b+2, t - b - 2);            break;        }cleanup:        snapend = se;	free(b);        return;}/* PPP */static voidhandle_ppp(u_int proto, const u_char *p, int length){        if ((proto & 0xff00) == 0x7e00) {/* is this an escape code ? */            ppp_hdlc(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(proto, p, length);		break;        case PPP_ML:                handle_mlppp(p, length);                break;	case PPP_CHAP:		handle_chap(p, length);		break;	case PPP_PAP:		handle_pap(p, length);		break;	case PPP_BAP:		/* XXX: not yet completed */		handle_bap(p, length);		break;	case ETHERTYPE_IP:	/*XXX*/        case PPP_VJNC:	case PPP_IP:		ip_print(gndo, p, length);		break;#ifdef INET6	case ETHERTYPE_IPV6:	/*XXX*/	case PPP_IPV6:		ip6_print(p, length);		break;#endif	case ETHERTYPE_IPX:	/*XXX*/	case PPP_IPX:		ipx_print(p, length);		break;	case PPP_OSI:	        isoclns_print(p, length, length);	        break;	case PPP_MPLS_UCAST:	case PPP_MPLS_MCAST:		mpls_print(p, length);		break;	case PPP_COMP:		printf("compressed PPP data");		break;	default:		printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));		print_unknown_data(p,"\n\t",length);		break;	}}/* Standard PPP printer */u_intppp_print(register const u_char *p, u_int length){	u_int proto,ppp_header;        u_int olen = length; /* _o_riginal length */	u_int hdr_len = 0;	/*	 * Here, we assume that p points to the Address and Control	 * field (if they present).	 */	if (length < 2)		goto trunc;	TCHECK2(*p, 2);        ppp_header = EXTRACT_16BITS(p);        switch(ppp_header) {        case (PPP_WITHDIRECTION_IN  << 8 | PPP_CONTROL):            if (eflag) printf("In  ");            p += 2;            length -= 2;            hdr_len += 2;            break;        case (PPP_WITHDIRECTION_OUT << 8 | PPP_CONTROL):            if (eflag) printf("Out ");            p += 2;            length -= 2;            hdr_len += 2;            break;        case (PPP_ADDRESS << 8 | PPP_CONTROL):            p += 2;			/* ACFC not used */            length -= 2;            hdr_len += 2;            break;        default:            break;        }	if (length < 2)		goto trunc;	TCHECK(*p);	if (*p % 2) {		proto = *p;		/* PFC is used */		p++;		length--;		hdr_len++;	} else {		TCHECK2(*p, 2);		proto = EXTRACT_16BITS(p);		p += 2;		length -= 2;		hdr_len += 2;	}        if (eflag)            printf("%s (0x%04x), length %u: ",                   tok2str(ppptype2str, "unknown", proto),                   proto,                   olen);	handle_ppp(proto, p, length);	return (hdr_len);trunc:	printf("[|ppp]");	return (0);}/* PPP I/F printer */u_intppp_if_print(const struct pcap_pkthdr *h, register const u_char *p){	register u_int length = h->len;	register u_int caplen = h->caplen;	if (caplen < PPP_HDRLEN) {		printf("[|ppp]");		return (caplen);	}#if 0	/*	 * XXX: seems to assume that there are 2 octets prepended to an	 * actual PPP frame. The 1st octet looks like Input/Output flag	 * while 2nd octet is unknown, at least to me	 * (mshindo@mshindo.net).	 *	 * That was what the original tcpdump code did.	 *	 * FreeBSD's "if_ppp.c" *does* set the first octet to 1 for outbound	 * packets and 0 for inbound packets - but only if the	 * protocol field has the 0x8000 bit set (i.e., it's a network	 * control protocol); it does so before running the packet through	 * "bpf_filter" to see if it should be discarded, and to see	 * if we should update the time we sent the most recent packet...	 *	 * ...but it puts the original address field back after doing	 * so.	 *	 * NetBSD's "if_ppp.c" doesn't set the first octet in that fashion.	 *	 * I don't know if any PPP implementation handed up to a BPF	 * device packets with the first octet being 1 for outbound and	 * 0 for inbound packets, so I (guy@alum.mit.edu) don't know	 * whether that ever needs to be checked or not.	 *	 * Note that NetBSD has a DLT_PPP_SERIAL, which it uses for PPP,	 * and its tcpdump appears to assume that the frame always	 * begins with an address field and a control field, and that	 * the address field might be 0x0f or 0x8f, for Cisco	 * point-to-point with HDLC framing as per section 4.3.1 of RFC	 * 1547, as well as 0xff, for PPP in HDLC-like framing as per	 * RFC 1662.	 *	 * (Is the Cisco framing in question what DLT_C_HDLC, in	 * BSD/OS, is?)	 */	if (eflag)		printf("%c %4d %02x ", p[0] ? 'O' : 'I', length, p[1]);#endif	ppp_print(p, length);	return (0);}/* * PPP I/F printer to use if we know that RFC 1662-style PPP in HDLC-like * framing, or Cisco PPP with HDLC framing as per section 4.3.1 of RFC 1547, * is being used (i.e., we don't check for PPP_ADDRESS and PPP_CONTROL, * discard them *if* those are the first two octets, and parse the remaining * packet as a PPP packet, as "ppp_print()" does). * * This handles, for example, DLT_PPP_SERIAL in NetBSD. */u_intppp_hdlc_if_print(const struct pcap_pkthdr *h, register const u_char *p){	register u_int length = h->len;	register u_int caplen = h->caplen;	u_int proto;	u_int hdrlen = 0;	if (caplen < 2) {		printf("[|ppp]");		return (caplen);	}	switch (p[0]) {	case PPP_ADDRESS:		if (caplen < 4) {			printf("[|ppp]");			return (caplen);		}		if (eflag)			printf("%02x %02x %d ", p[0], p[1], length);		p += 2;		length -= 2;		hdrlen += 2;		proto = EXTRACT_16BITS(p);		p += 2;		length -= 2;		hdrlen += 2;		printf("%s: ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", proto));		handle_ppp(proto, p, length);		break;	case CHDLC_UNICAST:	case CHDLC_BCAST:		return (chdlc_if_print(h, p));	default:		if (eflag)			printf("%02x %02x %d ", p[0], p[1], length);		p += 2;		length -= 2;		hdrlen += 2;		/*		 * XXX - NetBSD's "ppp_netbsd_serial_if_print()" treats		 * the next two octets as an Ethernet type; does that		 * ever happen?		 */		printf("unknown addr %02x; ctrl %02x", p[0], p[1]);		break;	}	return (hdrlen);}#define PPP_BSDI_HDRLEN 24/* BSD/OS specific PPP printer */u_intppp_bsdos_if_print(const struct pcap_pkthdr *h _U_, register const u_char *p _U_){	register int hdrlength;#ifdef __bsdi__	register u_int length = h->len;	register u_int caplen = h->caplen;	u_int16_t ptype;	const u_char *q;	int i;	if (caplen < PPP_BSDI_HDRLEN) {		printf("[|ppp]");		return (caplen)	}	hdrlength = 0;#if 0	if (p[0] == PPP_ADDRESS && p[1] == PPP_CONTROL) {		if (eflag)			printf("%02x %02x ", p[0], p[1]);		p += 2;		hdrlength = 2;	}	if (eflag)		printf("%d ", length);	/* Retrieve the protocol type */	if (*p & 01) {		/* Compressed protocol field */		ptype = *p;		if (eflag)			printf("%02x ", ptype);		p++;		hdrlength += 1;	} else {		/* Un-compressed protocol field */		ptype = ntohs(*(u_int16_t *)p);		if (eflag)			printf("%04x ", ptype);		p += 2;		hdrlength += 2;	}#else	ptype = 0;	/*XXX*/	if (eflag)		printf("%c ", p[SLC_DIR] ? 'O' : 'I');	if (p[SLC_LLHL]) {		/* link level header */		struct ppp_header *ph;		q = p + SLC_BPFHDRLEN;		ph = (struct ppp_header *)q;		if (ph->phdr_addr == PPP_ADDRESS		 && ph->phdr_ctl == PPP_CONTROL) {			if (eflag)				printf("%02x %02x ", q[0], q[1]);			ptype = ntohs(ph->phdr_type);			if (eflag && (ptype == PPP_VJC || ptype == PPP_VJNC)) {				printf("%s ", tok2str(ppptype2str,						"proto-#%d", ptype));			}		} else {			if (eflag) {				printf("LLH=[");				for (i = 0; i < p[SLC_LLHL]; i++)					printf("%02x", q[i]);				printf("] ");			}		}	}	if (eflag)		printf("%d ", length);	if (p[SLC_CHL]) {		q = p + SLC_BPFHDRLEN + p[SLC_LLHL];		switch (ptype) {		case PPP_VJC:			ptype = vjc_print(q, ptype);			hdrlength = PPP_BSDI_HDRLEN;			p += hdrlength;			switch (ptype) {			case PPP_IP:				ip_print(p, length);				break;#ifdef INET6			case PPP_IPV6:				ip6_print(p, length);				break;#endif			case PPP_MPLS_UCAST:			case PPP_MPLS_MCAST:				mpls_print(p, length);				break;			}			goto printx;		case PPP_VJNC:			ptype = vjc_print(q, ptype);			hdrlength = PPP_BSDI_HDRLEN;			p += hdrlength;			switch (ptype) {			case PPP_IP:				ip_print(p, length);				break;#ifdef INET6			case PPP_IPV6:				ip6_print(p, length);				break;#endif			case PPP_MPLS_UCAST:			case PPP_MPLS_MCAST:				mpls_print(p, length);				break;			}			goto printx;		default:			if (eflag) {				printf("CH=[");				for (i = 0; i < p[SLC_LLHL]; i++)					printf("%02x", q[i]);				printf("] ");			}			break;		}	}	hdrlength = PPP_BSDI_HDRLEN;#endif	length -= hdrlength;	p += hdrlength;	switch (ptype) {	case PPP_IP:		ip_print(p, length);		break;#ifdef INET6	case PPP_IPV6:		ip6_print(p, length);		break;#endif        case PPP_MPLS_UCAST:        case PPP_MPLS_MCAST:                mpls_print(p, length);                break;	default:		printf("%s ", tok2str(ppptype2str, "unknown PPP protocol (0x%04x)", ptype));	}printx:#else /* __bsdi */	hdrlength = 0;#endif /* __bsdi__ */	return (hdrlength);}/* * Local Variables: * c-style: whitesmith * c-basic-offset: 8 * End: */

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?