#ifndef lint
static const char rcsid[] _U_ =
- "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.72.2.3 2004-01-16 10:07:20 hannes Exp $";
+ "@(#) $Header: /tcpdump/master/tcpdump/print-bgp.c,v 1.72.2.4 2004-03-24 00:04:04 guy Exp $";
#endif
#include <tcpdump-stdinc.h>
struct in_addr addr;
u_int plen;
+ TCHECK(pptr[0]);
plen = pptr[0];
if (32 < plen)
return -1;
memset(&addr, 0, sizeof(addr));
+ TCHECK2(pptr[1], (plen + 7) / 8);
memcpy(&addr, &pptr[1], (plen + 7) / 8);
if (plen % 8) {
((u_char *)&addr)[(plen + 7) / 8 - 1] &=
}
snprintf(buf, buflen, "%s/%d", getname((u_char *)&addr), plen);
return 1 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
static int
struct in_addr addr;
u_int plen;
+ TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
/* this is one of the weirdnesses of rfc3107
return -1;
memset(&addr, 0, sizeof(addr));
+ TCHECK2(pptr[4], (plen + 7) / 8);
memcpy(&addr, &pptr[4], (plen + 7) / 8);
if (plen % 8) {
((u_char *)&addr)[(plen + 7) / 8 - 1] &=
((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 4 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
/* RDs and RTs share the same semantics
u_int8_t route_target[8];
u_int plen;
+ TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
plen-=32; /* adjust prefix length */
return -1;
memset(&route_target, 0, sizeof(route_target));
+ TCHECK2(pptr[1], (plen + 7) / 8);
memcpy(&route_target, &pptr[1], (plen + 7) / 8);
if (plen % 8) {
((u_char *)&route_target)[(plen + 7) / 8 - 1] &=
bgp_vpn_rd_print((u_char *)&route_target));
return 5 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
static int
struct in_addr addr;
u_int plen;
+ TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
return -1;
memset(&addr, 0, sizeof(addr));
+ TCHECK2(pptr[12], (plen + 7) / 8);
memcpy(&addr, &pptr[12], (plen + 7) / 8);
if (plen % 8) {
((u_char *)&addr)[(plen + 7) / 8 - 1] &=
((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 12 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
static int
decode_labeled_vpn_l2(const u_char *pptr, char *buf, u_int buflen)
{
int plen,tlen,strlen,tlv_type,tlv_len,ttlv_len;
+
+ TCHECK2(pptr[0], 2);
plen=EXTRACT_16BITS(pptr);
tlen=plen;
pptr+=2;
+ TCHECK2(pptr[0],15);
strlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
bgp_vpn_rd_print(pptr),
EXTRACT_16BITS(pptr+8),
/* ok now the variable part - lets read out TLVs*/
while (tlen>0) {
+ if (tlen < 3)
+ return -1;
+ TCHECK2(pptr[0], 3);
tlv_type=*pptr++;
tlv_len=EXTRACT_16BITS(pptr);
ttlv_len=tlv_len;
tlv_len);
ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
while (ttlv_len>0) {
+ TCHECK(pptr[0]);
strlen+=snprintf(buf+strlen,buflen-strlen, "%02x",*pptr++);
ttlv_len--;
}
tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it tright */
}
return plen+2;
+
+trunc:
+ return -2;
}
#ifdef INET6
struct in6_addr addr;
u_int plen;
+ TCHECK(pd[0]);
plen = pd[0];
if (128 < plen)
return -1;
memset(&addr, 0, sizeof(addr));
+ TCHECK2(pd[1], (plen + 7) / 8);
memcpy(&addr, &pd[1], (plen + 7) / 8);
if (plen % 8) {
addr.s6_addr[(plen + 7) / 8 - 1] &=
}
snprintf(buf, buflen, "%s/%d", getname6((u_char *)&addr), plen);
return 1 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
static int
struct in6_addr addr;
u_int plen;
+ TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
plen-=24; /* adjust prefixlen - labellength */
return -1;
memset(&addr, 0, sizeof(addr));
+ TCHECK2(pptr[4], (plen + 7) / 8);
memcpy(&addr, &pptr[4], (plen + 7) / 8);
if (plen % 8) {
addr.s6_addr[(plen + 7) / 8 - 1] &=
((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 4 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
static int
struct in6_addr addr;
u_int plen;
+ TCHECK(pptr[0]);
plen = pptr[0]; /* get prefix length */
plen-=(24+64); /* adjust prefixlen - labellength - RD len*/
return -1;
memset(&addr, 0, sizeof(addr));
+ TCHECK2(pptr[12], (plen + 7) / 8);
memcpy(&addr, &pptr[12], (plen + 7) / 8);
if (plen % 8) {
addr.s6_addr[(plen + 7) / 8 - 1] &=
((pptr[3]&1)==0) ? "(BOGUS: Bottom of Stack NOT set!)" : "(bottom)" );
return 12 + (plen + 7) / 8;
+
+trunc:
+ return -2;
}
#endif
-static void
+static int
bgp_attr_print(const struct bgp_attr *attr, const u_char *pptr, int len)
{
int i;
case BGPTYPE_ORIGIN:
if (len != 1)
printf("invalid len");
- else
+ else {
+ TCHECK(*tptr);
printf("%s", tok2str(bgp_origin_values, "Unknown Origin Typecode", tptr[0]));
+ }
break;
case BGPTYPE_AS_PATH:
if (len % 2) {
}
while (tptr < pptr + len) {
+ TCHECK(tptr[0]);
printf("%s", tok2str(bgp_as_path_segment_open_values, "?", tptr[0]));
for (i = 0; i < tptr[1] * 2; i += 2) {
+ TCHECK2(tptr[2 + i], 2);
printf("%u ", EXTRACT_16BITS(&tptr[2 + i]));
}
+ TCHECK(tptr[0]);
printf("%s", tok2str(bgp_as_path_segment_close_values, "?", tptr[0]));
+ TCHECK(tptr[1]);
tptr += 2 + tptr[1] * 2;
}
break;
case BGPTYPE_NEXT_HOP:
if (len != 4)
printf("invalid len");
- else
+ else {
+ TCHECK2(tptr[0], 4);
printf("%s", getname(tptr));
+ }
break;
case BGPTYPE_MULTI_EXIT_DISC:
case BGPTYPE_LOCAL_PREF:
if (len != 4)
printf("invalid len");
- else
+ else {
+ TCHECK2(tptr[0], 4);
printf("%u", EXTRACT_32BITS(tptr));
+ }
break;
case BGPTYPE_ATOMIC_AGGREGATE:
if (len != 0)
printf("invalid len");
break;
}
+ TCHECK2(tptr[0], 6);
printf(" AS #%u, origin %s", EXTRACT_16BITS(tptr),
getname(tptr + 2));
break;
}
while (tlen>0) {
u_int32_t comm;
+ TCHECK2(tptr[0], 4);
comm = EXTRACT_32BITS(tptr);
switch (comm) {
case BGP_COMMUNITY_NO_EXPORT:
printf("invalid len");
break;
}
+ TCHECK2(tptr[0], 4);
printf("%s",getname(tptr));
break;
case BGPTYPE_CLUSTER_LIST:
+ if (len % 4) {
+ printf("invalid len");
+ break;
+ }
while (tlen>0) {
+ TCHECK2(tptr[0], 4);
printf("%s%s",
getname(tptr),
(tlen>4) ? ", " : "");
}
break;
case BGPTYPE_MP_REACH_NLRI:
+ TCHECK2(tptr[0], 3);
af = EXTRACT_16BITS(tptr);
safi = tptr[2];
tptr +=3;
+ TCHECK(tptr[0]);
tlen = tptr[0];
tptr++;
case SAFNUM_UNIMULTICAST:
case SAFNUM_LABUNICAST:
case SAFNUM_RT_ROUTING_INFO:
- printf("%s",getname(tptr));
- tlen -= sizeof(struct in_addr);
- tptr += sizeof(struct in_addr);
+ if (tlen < (int)sizeof(struct in_addr)) {
+ printf("invalid len");
+ tlen = 0;
+ } else {
+ TCHECK2(tptr[0], sizeof(struct in_addr));
+ printf("%s",getname(tptr));
+ tlen -= sizeof(struct in_addr);
+ tptr += sizeof(struct in_addr);
+ }
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
- printf("RD: %s, %s",
+ if (tlen < (int)(sizeof(struct in_addr)+BGP_VPN_RD_LEN)) {
+ printf("invalid len");
+ tlen = 0;
+ } else {
+ TCHECK2(tptr[0], sizeof(struct in_addr)+BGP_VPN_RD_LEN);
+ printf("RD: %s, %s",
bgp_vpn_rd_print(tptr),
getname(tptr+BGP_VPN_RD_LEN));
- tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
- tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
+ tlen -= (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
+ tptr += (sizeof(struct in_addr)+BGP_VPN_RD_LEN);
+ }
break;
default:
- printf("no SAFI %u decoder",safi);
+ TCHECK2(tptr[0], tlen);
+ printf("no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr,"\n\t ",tlen);
+ tptr += tlen;
+ tlen = 0;
break;
}
break;
case SAFNUM_UNIMULTICAST:
case SAFNUM_LABUNICAST:
case SAFNUM_RT_ROUTING_INFO:
- printf("%s", getname6(tptr));
- tlen -= sizeof(struct in6_addr);
- tptr += sizeof(struct in6_addr);
+ if (tlen < (int)sizeof(struct in6_addr)) {
+ printf("invalid len");
+ tlen = 0;
+ } else {
+ TCHECK2(tptr[0], sizeof(struct in6_addr));
+ printf("%s", getname6(tptr));
+ tlen -= sizeof(struct in6_addr);
+ tptr += sizeof(struct in6_addr);
+ }
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
- printf("RD: %s, %s",
+ if (tlen < (int)(sizeof(struct in6_addr)+BGP_VPN_RD_LEN)) {
+ printf("invalid len");
+ tlen = 0;
+ } else {
+ TCHECK2(tptr[0], sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
+ printf("RD: %s, %s",
bgp_vpn_rd_print(tptr),
getname6(tptr+BGP_VPN_RD_LEN));
- tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
- tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
+ tlen -= (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
+ tptr += (sizeof(struct in6_addr)+BGP_VPN_RD_LEN);
+ }
break;
default:
+ TCHECK2(tptr[0], tlen);
printf("no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr,"\n\t ",tlen);
+ tptr += tlen;
+ tlen = 0;
break;
}
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
- printf("%s", getname(tptr));
- tlen -= (sizeof(struct in_addr));
- tptr += (sizeof(struct in_addr));
- break;
+ if (tlen < (int)sizeof(struct in_addr)) {
+ printf("invalid len");
+ tlen = 0;
+ } else {
+ TCHECK2(tptr[0], sizeof(struct in_addr));
+ printf("%s", getname(tptr));
+ tlen -= (sizeof(struct in_addr));
+ tptr += (sizeof(struct in_addr));
+ }
+ break;
default:
+ TCHECK2(tptr[0], tlen);
printf("no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr,"\n\t ",tlen);
+ tptr += tlen;
+ tlen = 0;
break;
}
break;
default:
+ TCHECK2(tptr[0], tlen);
printf("no AFI %u decoder",af);
if (vflag <= 1)
print_unknown_data(tptr,"\n\t ",tlen);
+ tptr += tlen;
+ tlen = 0;
break;
}
}
}
tptr += tlen;
+ TCHECK(tptr[0]);
snpa = tptr[0];
tptr++;
if (snpa) {
printf("\n\t %u SNPA", snpa);
for (/*nothing*/; snpa > 0; snpa--) {
+ TCHECK(tptr[0]);
printf("\n\t %d bytes", tptr[0]);
tptr += tptr[0] + 1;
}
} else {
- printf(", no SNPA");
+ printf(", no SNPA");
}
while (len - (tptr - pptr) > 0) {
case SAFNUM_MULTICAST:
case SAFNUM_UNIMULTICAST:
advance = decode_prefix4(tptr, buf, sizeof(buf));
- if (advance >= 0)
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
printf("\n\t %s", buf);
- else
- printf("\n\t (illegal prefix length)");
break;
case SAFNUM_LABUNICAST:
advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_RT_ROUTING_INFO:
advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("\n\t no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
case SAFNUM_MULTICAST:
case SAFNUM_UNIMULTICAST:
advance = decode_prefix6(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_LABUNICAST:
advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_RT_ROUTING_INFO:
advance = decode_rt_routing_info(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("\n\t no SAFI %u decoder ",safi);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
default:
+ TCHECK2(*tptr,tlen);
printf("no SAFI %u decoder",safi);
if (vflag <= 1)
- print_unknown_data(tptr,"\n\t ",tlen);
+ print_unknown_data(tptr,"\n\t ",tlen);
advance = 0;
tptr = pptr + len;
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("\n\t no AFI %u decoder ",af);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
break;
case BGPTYPE_MP_UNREACH_NLRI:
+ TCHECK2(tptr[0], 3);
af = EXTRACT_16BITS(tptr);
safi = tptr[2];
case SAFNUM_MULTICAST:
case SAFNUM_UNIMULTICAST:
advance = decode_prefix4(tptr, buf, sizeof(buf));
- if (advance >= 0)
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
printf("\n\t %s", buf);
- else
- printf("\n\t (illegal prefix length)");
break;
case SAFNUM_LABUNICAST:
advance = decode_labeled_prefix4(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
advance = decode_labeled_vpn_prefix4(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("\n\t no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
case SAFNUM_MULTICAST:
case SAFNUM_UNIMULTICAST:
advance = decode_prefix6(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_LABUNICAST:
advance = decode_labeled_prefix6(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
case SAFNUM_VPNUNICAST:
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
advance = decode_labeled_vpn_prefix6(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("\n\t no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
case SAFNUM_VPNMULTICAST:
case SAFNUM_VPNUNIMULTICAST:
advance = decode_labeled_vpn_l2(tptr, buf, sizeof(buf));
- printf("\n\t %s", buf);
+ if (advance == -1)
+ printf("\n\t (illegal length)");
+ else if (advance == -2)
+ goto trunc;
+ else
+ printf("\n\t %s", buf);
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("no SAFI %u decoder",safi);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
break;
default:
+ TCHECK2(*(tptr-3),tlen);
printf("\n\t no AFI %u decoder",af);
if (vflag <= 1)
print_unknown_data(tptr-3,"\n\t ",tlen);
}
while (tlen>0) {
u_int16_t extd_comm;
+
+ TCHECK2(tptr[0], 2);
extd_comm=EXTRACT_16BITS(tptr);
printf("\n\t %s (0x%04x), Flags [%s]",
extd_comm,
bittok2str(bgp_extd_comm_flag_values, "none", extd_comm));
+ TCHECK2(*(tptr+2), 6);
switch(extd_comm) {
case BGP_EXT_COM_RT_0:
case BGP_EXT_COM_RO_0:
break;
default:
+ TCHECK2(*pptr,len);
printf("\n\t no Attribute %u decoder",attr->bgpa_type); /* we have no decoder for the attribute */
if (vflag <= 1)
print_unknown_data(pptr,"\n\t ",len);
}
if (vflag > 1 && len) /* omit zero length attributes*/
print_unknown_data(pptr,"\n\t ",len);
+ return 1;
+
+trunc:
+ return 0;
}
static void
while(i < 2 + len) {
wpfx = decode_prefix4(&p[i], buf, sizeof(buf));
- if (wpfx >= 0) {
- i += wpfx;
- printf("\n\t %s", buf);
- } else {
+ if (wpfx == -1) {
printf("\n\t (illegal prefix length)");
break;
+ } else if (wpfx == -2)
+ goto trunc;
+ else {
+ i += wpfx;
+ printf("\n\t %s", buf);
}
}
#endif
printf("+%x", bgpa.bgpa_flags & 0xf);
printf("]: ");
}
- bgp_attr_print(&bgpa, &p[i + aoff], alen);
+ if (!bgp_attr_print(&bgpa, &p[i + aoff], alen))
+ goto trunc;
i += aoff + alen;
}
}
while (dat + length > p) {
char buf[MAXHOSTNAMELEN + 100];
i = decode_prefix4(p, buf, sizeof(buf));
- if (i >= 0) {
+ if (i == -1)
+ printf("\n\t (illegal prefix length)");
+ else if (i == -2)
+ goto trunc;
+ else {
printf("\n\t %s", buf);
p += i;
- } else {
- printf("\n\t (illegal prefix length)");
- break;
}
}
}
return;
}
-static void
+static int
bgp_header_print(const u_char *dat, int length)
{
struct bgp bgp;
print_unknown_data(dat,"\n\t ",length);
break;
}
- return;
+ return 1;
trunc:
printf("[|BGP]");
+ return 0;
}
void
}
if (TTEST2(p[0], hlen)) {
- bgp_header_print(p, hlen);
+ if (!bgp_header_print(p, hlen))
+ return;
p += hlen;
start = p;
} else {