static int lcp_printpkt()

in net/ip/lwip_base/src/netif/ppp/lcp.c [2384:2632]


static int lcp_printpkt(const u_char *p, int plen,
		void (*printer) (void *, const char *, ...), void *arg) {
    int code, id, len, olen, i;
    const u_char *pstart, *optend;
    u_short cishort;
    u32_t cilong;

    if (plen < HEADERLEN)
	return 0;
    pstart = p;
    GETCHAR(code, p);
    GETCHAR(id, p);
    GETSHORT(len, p);
    if (len < HEADERLEN || len > plen)
	return 0;

   if (code >= 1 && code <= (int)LWIP_ARRAYSIZE(lcp_codenames))
	printer(arg, " %s", lcp_codenames[code-1]);
    else
	printer(arg, " code=0x%x", code);
    printer(arg, " id=0x%x", id);
    len -= HEADERLEN;
    switch (code) {
    case CONFREQ:
    case CONFACK:
    case CONFNAK:
    case CONFREJ:
	/* print option list */
	while (len >= 2) {
	    GETCHAR(code, p);
	    GETCHAR(olen, p);
	    p -= 2;
	    if (olen < 2 || olen > len) {
		break;
	    }
	    printer(arg, " <");
	    len -= olen;
	    optend = p + olen;
	    switch (code) {
	    case CI_MRU:
		if (olen == CILEN_SHORT) {
		    p += 2;
		    GETSHORT(cishort, p);
		    printer(arg, "mru %d", cishort);
		}
		break;
	    case CI_ASYNCMAP:
		if (olen == CILEN_LONG) {
		    p += 2;
		    GETLONG(cilong, p);
		    printer(arg, "asyncmap 0x%x", cilong);
		}
		break;
	    case CI_AUTHTYPE:
		if (olen >= CILEN_SHORT) {
		    p += 2;
		    printer(arg, "auth ");
		    GETSHORT(cishort, p);
		    switch (cishort) {
#if PAP_SUPPORT
		    case PPP_PAP:
			printer(arg, "pap");
			break;
#endif /* PAP_SUPPORT */
#if CHAP_SUPPORT
		    case PPP_CHAP:
			printer(arg, "chap");
			if (p < optend) {
			    switch (*p) {
			    case CHAP_MD5:
				printer(arg, " MD5");
				++p;
				break;
#if MSCHAP_SUPPORT
			    case CHAP_MICROSOFT:
				printer(arg, " MS");
				++p;
				break;

			    case CHAP_MICROSOFT_V2:
				printer(arg, " MS-v2");
				++p;
				break;
#endif /* MSCHAP_SUPPORT */
			    default:
				break;
			    }
			}
			break;
#endif /* CHAP_SUPPORT */
#if EAP_SUPPORT
		    case PPP_EAP:
			printer(arg, "eap");
			break;
#endif /* EAP_SUPPORT */
		    default:
			printer(arg, "0x%x", cishort);
		    }
		}
		break;
#if LQR_SUPPORT
	    case CI_QUALITY:
		if (olen >= CILEN_SHORT) {
		    p += 2;
		    printer(arg, "quality ");
		    GETSHORT(cishort, p);
		    switch (cishort) {
		    case PPP_LQR:
			printer(arg, "lqr");
			break;
		    default:
			printer(arg, "0x%x", cishort);
		    }
		}
		break;
#endif /* LQR_SUPPORT */
	    case CI_CALLBACK:
		if (olen >= CILEN_CHAR) {
		    p += 2;
		    printer(arg, "callback ");
		    GETCHAR(cishort, p);
		    switch (cishort) {
		    case CBCP_OPT:
			printer(arg, "CBCP");
			break;
		    default:
			printer(arg, "0x%x", cishort);
		    }
		}
		break;
	    case CI_MAGICNUMBER:
		if (olen == CILEN_LONG) {
		    p += 2;
		    GETLONG(cilong, p);
		    printer(arg, "magic 0x%x", cilong);
		}
		break;
	    case CI_PCOMPRESSION:
		if (olen == CILEN_VOID) {
		    p += 2;
		    printer(arg, "pcomp");
		}
		break;
	    case CI_ACCOMPRESSION:
		if (olen == CILEN_VOID) {
		    p += 2;
		    printer(arg, "accomp");
		}
		break;
	    case CI_MRRU:
		if (olen == CILEN_SHORT) {
		    p += 2;
		    GETSHORT(cishort, p);
		    printer(arg, "mrru %d", cishort);
		}
		break;
	    case CI_SSNHF:
		if (olen == CILEN_VOID) {
		    p += 2;
		    printer(arg, "ssnhf");
		}
		break;
	    case CI_EPDISC:
#ifdef HAVE_MULTILINK
		if (olen >= CILEN_CHAR) {
		    struct epdisc epd;
		    p += 2;
		    GETCHAR(epd.class, p);
		    epd.length = olen - CILEN_CHAR;
		    if (epd.length > MAX_ENDP_LEN)
			epd.length = MAX_ENDP_LEN;
		    if (epd.length > 0) {
			MEMCPY(epd.value, p, epd.length);
			p += epd.length;
		    }
		    printer(arg, "endpoint [%s]", epdisc_to_str(&epd));
		}
#else
		printer(arg, "endpoint");
#endif
		break;
	    default:
		break;
	    }
	    while (p < optend) {
		GETCHAR(code, p);
		printer(arg, " %.2x", code);
	    }
	    printer(arg, ">");
	}
	break;

    case TERMACK:
    case TERMREQ:
	if (len > 0 && *p >= ' ' && *p < 0x7f) {
	    printer(arg, " ");
	    ppp_print_string(p, len, printer, arg);
	    p += len;
	    len = 0;
	}
	break;

    case ECHOREQ:
    case ECHOREP:
    case DISCREQ:
	if (len >= 4) {
	    GETLONG(cilong, p);
	    printer(arg, " magic=0x%x", cilong);
	    len -= 4;
	}
	break;

    case IDENTIF:
    case TIMEREM:
	if (len >= 4) {
	    GETLONG(cilong, p);
	    printer(arg, " magic=0x%x", cilong);
	    len -= 4;
	}
	if (code == TIMEREM) {
	    if (len < 4)
		break;
	    GETLONG(cilong, p);
	    printer(arg, " seconds=%u", cilong);
	    len -= 4;
	}
	if (len > 0) {
	    printer(arg, " ");
	    ppp_print_string(p, len, printer, arg);
	    p += len;
	    len = 0;
	}
	break;
    default:
	break;
    }

    /* print the rest of the bytes in the packet */
    for (i = 0; i < len && i < 32; ++i) {
	GETCHAR(code, p);
	printer(arg, " %.2x", code);
    }
    if (i < len) {
	printer(arg, " ...");
	p += len - i;
    }

    return p - pstart;
}