switch (code) {
	case EAP_REQUEST:
		if (len < 1) {
			printer(arg, " <missing type>");
			break;
		}
		GETCHAR(rtype, inp);
		len--;
		if (rtype >= 1 &&
		    rtype <= sizeof (eap_typenames) / sizeof (char *))
			printer(arg, " %s", eap_typenames[rtype-1]);
		else
			printer(arg, " type=0x%x", rtype);
		switch (rtype) {
		case EAPT_IDENTITY:
		case EAPT_NOTIFICATION:
			if (len > 0) {
				printer(arg, " <Message ");
				print_string((char *)inp, len, printer, arg);
				printer(arg, ">");
				INCPTR(len, inp);
				len = 0;
			} else {
				printer(arg, " <No message>");
			}
			break;

		case EAPT_MD5CHAP:
			if (len <= 0)
				break;
			GETCHAR(vallen, inp);
			len--;
			if (vallen > len)
				goto truncated;
			printer(arg, " <Value%.*B>", vallen, inp);
			INCPTR(vallen, inp);
			len -= vallen;
			if (len > 0) {
				printer(arg, " <Name ");
				print_string((char *)inp, len, printer, arg);
				printer(arg, ">");
				INCPTR(len, inp);
				len = 0;
			} else {
				printer(arg, " <No name>");
			}
			break;

		case EAPT_SRP:
			if (len < 3)
				goto truncated;
			GETCHAR(vallen, inp);
			len--;
			printer(arg, "-%d", vallen);
			switch (vallen) {
			case EAPSRP_CHALLENGE:
				GETCHAR(vallen, inp);
				len--;
				if (vallen >= len)
					goto truncated;
				if (vallen > 0) {
					printer(arg, " <Name ");
					print_string((char *)inp, vallen, printer,
					    arg);
					printer(arg, ">");
				} else {
					printer(arg, " <No name>");
				}
				INCPTR(vallen, inp);
				len -= vallen;
				GETCHAR(vallen, inp);
				len--;
				if (vallen >= len)
					goto truncated;
				printer(arg, " <s%.*B>", vallen, inp);
				INCPTR(vallen, inp);
				len -= vallen;
				GETCHAR(vallen, inp);
				len--;
				if (vallen > len)
					goto truncated;
				if (vallen == 0) {
					printer(arg, " <Default g=2>");
				} else {
					printer(arg, " <g%.*B>", vallen, inp);
				}
				INCPTR(vallen, inp);
				len -= vallen;
				if (len == 0) {
					printer(arg, " <Default N>");
				} else {
					printer(arg, " <N%.*B>", len, inp);
					INCPTR(len, inp);
					len = 0;
				}
				break;

			case EAPSRP_SKEY:
				printer(arg, " <B%.*B>", len, inp);
				INCPTR(len, inp);
				len = 0;
				break;

			case EAPSRP_SVALIDATOR:
				if (len < sizeof (u_int32_t))
					break;
				GETLONG(uval, inp);
				len -= sizeof (u_int32_t);
				if (uval & SRPVAL_EBIT) {
					printer(arg, " E");
					uval &= ~SRPVAL_EBIT;
				}
				if (uval != 0) {
					printer(arg, " f<%X>", uval);
				}
				if ((vallen = len) > SHA_DIGESTSIZE)
					vallen = SHA_DIGESTSIZE;
				printer(arg, " <M2%.*B%s>", len, inp,
				    len < SHA_DIGESTSIZE ? "?" : "");
				INCPTR(vallen, inp);
				len -= vallen;
				if (len > 0) {
					printer(arg, " <PN%.*B>", len, inp);
					INCPTR(len, inp);
					len = 0;
				}
				break;

			case EAPSRP_LWRECHALLENGE:
				printer(arg, " <Challenge%.*B>", len, inp);
				INCPTR(len, inp);
				len = 0;
				break;
			}
			break;
		}
		break;

	case EAP_RESPONSE:
		if (len < 1)
			break;
		GETCHAR(rtype, inp);
		len--;
		if (rtype >= 1 &&
		    rtype <= sizeof (eap_typenames) / sizeof (char *))
			printer(arg, " %s", eap_typenames[rtype-1]);
		else
			printer(arg, " type=0x%x", rtype);
		switch (rtype) {
		case EAPT_IDENTITY:
			if (len > 0) {
				printer(arg, " <Name ");
				print_string((char *)inp, len, printer, arg);
				printer(arg, ">");
				INCPTR(len, inp);
				len = 0;
			}
			break;

		case EAPT_NAK:
			if (len <= 0) {
				printer(arg, " <missing hint>");
				break;
			}
			GETCHAR(rtype, inp);
			len--;
			printer(arg, " <Suggested-type %02X", rtype);
			if (rtype >= 1 &&
			    rtype < sizeof (eap_typenames) / sizeof (char *))
				printer(arg, " (%s)", eap_typenames[rtype-1]);
			printer(arg, ">");
			break;

		case EAPT_MD5CHAP:
			if (len <= 0) {
				printer(arg, " <missing length>");
				break;
			}
			GETCHAR(vallen, inp);
			len--;
			if (vallen > len)
				goto truncated;
			printer(arg, " <Value%.*B>", vallen, inp);
			INCPTR(vallen, inp);
			len -= vallen;
			if (len > 0) {
				printer(arg, " <Name ");
				print_string((char *)inp, len, printer, arg);
				printer(arg, ">");
				INCPTR(len, inp);
				len = 0;
			} else {
				printer(arg, " <No name>");
			}
			break;

		case EAPT_SRP:
			if (len < 1)
				goto truncated;
			GETCHAR(vallen, inp);
			len--;
			printer(arg, "-%d", vallen);
			switch (vallen) {
			case EAPSRP_CKEY:
				printer(arg, " <A%.*B>", len, inp);
				INCPTR(len, inp);
				len = 0;
				break;

			case EAPSRP_CVALIDATOR:
				if (len < sizeof (u_int32_t))
					break;
				GETLONG(uval, inp);
				len -= sizeof (u_int32_t);
				if (uval & SRPVAL_EBIT) {
					printer(arg, " E");
					uval &= ~SRPVAL_EBIT;
				}
				if (uval != 0) {
					printer(arg, " f<%X>", uval);
				}
				printer(arg, " <M1%.*B%s>", len, inp,
				    len == SHA_DIGESTSIZE ? "" : "?");
				INCPTR(len, inp);
				len = 0;
				break;

			case EAPSRP_ACK:
				break;

			case EAPSRP_LWRECHALLENGE:
				printer(arg, " <Response%.*B%s>", len, inp,
				    len == SHA_DIGESTSIZE ? "" : "?");
				if ((vallen = len) > SHA_DIGESTSIZE)
					vallen = SHA_DIGESTSIZE;
				INCPTR(vallen, inp);
				len -= vallen;
				break;
			}
			break;
		}
		break;

	case EAP_SUCCESS:	/* No payload expected for these! */
	case EAP_FAILURE:
		break;

	truncated:
		printer(arg, " <truncated>");
		break;
	}