xref: /freebsd/contrib/tcpdump/print-esp.c (revision 9afd0c2902649a0007676d044c6ae7fa099e8cf3)
1b0453382SBill Fenner /*	$NetBSD: print-ah.c,v 1.4 1996/05/20 00:41:16 fvdl Exp $	*/
2b0453382SBill Fenner 
3b0453382SBill Fenner /*
4b0453382SBill Fenner  * Copyright (c) 1988, 1989, 1990, 1991, 1992, 1993, 1994
5b0453382SBill Fenner  *	The Regents of the University of California.  All rights reserved.
6b0453382SBill Fenner  *
7b0453382SBill Fenner  * Redistribution and use in source and binary forms, with or without
8b0453382SBill Fenner  * modification, are permitted provided that: (1) source code distributions
9b0453382SBill Fenner  * retain the above copyright notice and this paragraph in its entirety, (2)
10b0453382SBill Fenner  * distributions including binary code include the above copyright notice and
11b0453382SBill Fenner  * this paragraph in its entirety in the documentation or other materials
12b0453382SBill Fenner  * provided with the distribution, and (3) all advertising materials mentioning
13b0453382SBill Fenner  * features or use of this software display the following acknowledgement:
14b0453382SBill Fenner  * ``This product includes software developed by the University of California,
15b0453382SBill Fenner  * Lawrence Berkeley Laboratory and its contributors.'' Neither the name of
16b0453382SBill Fenner  * the University nor the names of its contributors may be used to endorse
17b0453382SBill Fenner  * or promote products derived from this software without specific prior
18b0453382SBill Fenner  * written permission.
19b0453382SBill Fenner  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
20b0453382SBill Fenner  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
21b0453382SBill Fenner  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22b0453382SBill Fenner  */
23b0453382SBill Fenner 
24b0453382SBill Fenner #ifndef lint
25b0453382SBill Fenner static const char rcsid[] =
269afd0c29SBill Fenner     "@(#) $Header: /tcpdump/master/tcpdump/print-esp.c,v 1.20.4.2 2002/02/22 09:26:27 guy Exp $ (LBL)";
27b0453382SBill Fenner #endif
28b0453382SBill Fenner 
29b0453382SBill Fenner #ifdef HAVE_CONFIG_H
30b0453382SBill Fenner #include "config.h"
31b0453382SBill Fenner #endif
32b0453382SBill Fenner 
33b0453382SBill Fenner #include <string.h>
34b0453382SBill Fenner #include <sys/param.h>
35b0453382SBill Fenner #include <sys/time.h>
36b0453382SBill Fenner #include <sys/types.h>
37b0453382SBill Fenner #include <sys/socket.h>
389afd0c29SBill Fenner #include <stdlib.h>
39b0453382SBill Fenner 
40b0453382SBill Fenner #include <netinet/in.h>
41b0453382SBill Fenner 
42685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO
43a90e161bSBill Fenner #include <openssl/des.h>
44a90e161bSBill Fenner #include <openssl/blowfish.h>
45b0453382SBill Fenner #ifdef HAVE_RC5_H
46a90e161bSBill Fenner #include <openssl/rc5.h>
47b0453382SBill Fenner #endif
48b0453382SBill Fenner #ifdef HAVE_CAST_H
49a90e161bSBill Fenner #include <openssl/cast.h>
50b0453382SBill Fenner #endif
51b0453382SBill Fenner #endif
52b0453382SBill Fenner 
53b0453382SBill Fenner #include <stdio.h>
54b0453382SBill Fenner 
55685295f4SBill Fenner #include "ip.h"
56685295f4SBill Fenner #include "esp.h"
57b0453382SBill Fenner #ifdef INET6
58685295f4SBill Fenner #include "ip6.h"
59b0453382SBill Fenner #endif
60b0453382SBill Fenner 
61a90e161bSBill Fenner #define AVOID_CHURN 1
62b0453382SBill Fenner #include "interface.h"
63b0453382SBill Fenner #include "addrtoname.h"
64b0453382SBill Fenner 
65a90e161bSBill Fenner static struct esp_algorithm *espsecret_xform=NULL;  /* cache of decoded alg. */
66a90e161bSBill Fenner static char                 *espsecret_key=NULL;
67a90e161bSBill Fenner 
68a90e161bSBill Fenner 
69a90e161bSBill Fenner enum cipher { NONE,
70a90e161bSBill Fenner 	      DESCBC,
71a90e161bSBill Fenner 	      BLOWFISH,
72a90e161bSBill Fenner 	      RC5,
73a90e161bSBill Fenner 	      CAST128,
74a90e161bSBill Fenner 	      DES3CBC};
75a90e161bSBill Fenner 
76a90e161bSBill Fenner 
77a90e161bSBill Fenner 
78a90e161bSBill Fenner struct esp_algorithm {
79a90e161bSBill Fenner 	char        *name;
80a90e161bSBill Fenner 	enum  cipher algo;
81a90e161bSBill Fenner 	int          ivlen;
82a90e161bSBill Fenner 	int          authlen;
83a90e161bSBill Fenner 	int          replaysize;
84a90e161bSBill Fenner };
85a90e161bSBill Fenner 
86a90e161bSBill Fenner struct esp_algorithm esp_xforms[]={
87a90e161bSBill Fenner 	{"none",                  NONE,    0,  0, 0},
88a90e161bSBill Fenner 	{"des-cbc",               DESCBC,  8,  0, 0},
89a90e161bSBill Fenner 	{"des-cbc-hmac96",        DESCBC,  8, 12, 4},
90a90e161bSBill Fenner 	{"blowfish-cbc",          BLOWFISH,8,  0, 0},
91a90e161bSBill Fenner 	{"blowfish-cbc-hmac96",   BLOWFISH,8, 12, 4},
92a90e161bSBill Fenner 	{"rc5-cbc",               RC5,     8,  0, 0},
93a90e161bSBill Fenner 	{"rc5-cbc-hmac96",        RC5,     8, 12, 4},
94a90e161bSBill Fenner 	{"cast128-cbc",           CAST128, 8,  0, 0},
95a90e161bSBill Fenner 	{"cast128-cbc-hmac96",    CAST128, 8, 12, 4},
96a90e161bSBill Fenner 	{"3des-cbc-hmac96",       DES3CBC, 8, 12, 4},
97a90e161bSBill Fenner };
98a90e161bSBill Fenner 
99a90e161bSBill Fenner static int hexdigit(char hex)
100a90e161bSBill Fenner {
101a90e161bSBill Fenner 	if(hex >= '0' && hex <= '9') {
102a90e161bSBill Fenner 		return (hex - '0');
103a90e161bSBill Fenner 	} else if(hex >= 'A' && hex <= 'F') {
104a90e161bSBill Fenner 		return (hex - 'A' + 10);
105a90e161bSBill Fenner 	} else if(hex >= 'a' && hex <= 'f') {
106a90e161bSBill Fenner 		return (hex - 'a' + 10);
107a90e161bSBill Fenner 	} else {
108a90e161bSBill Fenner 		printf("invalid hex digit %c in espsecret\n", hex);
109a90e161bSBill Fenner 		return 0;
110a90e161bSBill Fenner 	}
111a90e161bSBill Fenner }
112a90e161bSBill Fenner 
113a90e161bSBill Fenner static int hex2byte(char *hexstring)
114a90e161bSBill Fenner {
115a90e161bSBill Fenner 	int byte;
116a90e161bSBill Fenner 
117a90e161bSBill Fenner 	byte = (hexdigit(hexstring[0]) << 4) +
118a90e161bSBill Fenner 		hexdigit(hexstring[1]);
119a90e161bSBill Fenner 	return byte;
120a90e161bSBill Fenner }
121a90e161bSBill Fenner 
122a90e161bSBill Fenner 
1239afd0c29SBill Fenner static void esp_print_decodesecret(void)
124a90e161bSBill Fenner {
125a90e161bSBill Fenner 	char *colon;
126a90e161bSBill Fenner 	int   len, i;
127a90e161bSBill Fenner 	struct esp_algorithm *xf;
128a90e161bSBill Fenner 
129a90e161bSBill Fenner 	if(espsecret == NULL) {
130a90e161bSBill Fenner 		/* set to NONE transform */
131a90e161bSBill Fenner 		espsecret_xform = esp_xforms;
132a90e161bSBill Fenner 		return;
133a90e161bSBill Fenner 	}
134a90e161bSBill Fenner 
135a90e161bSBill Fenner 	if(espsecret_key != NULL) {
136a90e161bSBill Fenner 		return;
137a90e161bSBill Fenner 	}
138a90e161bSBill Fenner 
139a90e161bSBill Fenner 	colon = strchr(espsecret, ':');
140a90e161bSBill Fenner 	if(colon == NULL) {
141a90e161bSBill Fenner 		printf("failed to decode espsecret: %s\n",
142a90e161bSBill Fenner 		       espsecret);
143a90e161bSBill Fenner 		/* set to NONE transform */
144a90e161bSBill Fenner 		espsecret_xform = esp_xforms;
145a90e161bSBill Fenner 	}
146a90e161bSBill Fenner 
147a90e161bSBill Fenner 	len   = colon - espsecret;
148a90e161bSBill Fenner 	xf = esp_xforms;
149a90e161bSBill Fenner 	while(xf->name && strncasecmp(espsecret, xf->name, len)!=0) {
150a90e161bSBill Fenner 		xf++;
151a90e161bSBill Fenner 	}
152a90e161bSBill Fenner 	if(xf->name == NULL) {
153a90e161bSBill Fenner 		printf("failed to find cipher algo %s\n",
154a90e161bSBill Fenner 		       espsecret);
155a90e161bSBill Fenner 		espsecret_xform = esp_xforms;
156a90e161bSBill Fenner 		return;
157a90e161bSBill Fenner 	}
158a90e161bSBill Fenner 	espsecret_xform = xf;
159a90e161bSBill Fenner 
160a90e161bSBill Fenner 	colon++;
161a90e161bSBill Fenner 	if(colon[0]=='0' && colon[1]=='x') {
162a90e161bSBill Fenner 		/* decode some hex! */
163a90e161bSBill Fenner 		colon+=2;
164a90e161bSBill Fenner 		len = strlen(colon) / 2;
165a90e161bSBill Fenner 		espsecret_key = (char *)malloc(len);
166a90e161bSBill Fenner 		if(espsecret_key == NULL) {
167a90e161bSBill Fenner 		  fprintf(stderr, "%s: ran out of memory (%d) to allocate secret key\n",
168a90e161bSBill Fenner 			  program_name, len);
169a90e161bSBill Fenner 		  exit(2);
170a90e161bSBill Fenner 		}
171a90e161bSBill Fenner 		i = 0;
172a90e161bSBill Fenner 		while(colon[0] != '\0' && colon[1]!='\0') {
173a90e161bSBill Fenner 			espsecret_key[i]=hex2byte(colon);
174a90e161bSBill Fenner 			colon+=2;
175a90e161bSBill Fenner 			i++;
176a90e161bSBill Fenner 		}
177a90e161bSBill Fenner 	} else {
178a90e161bSBill Fenner 		espsecret_key = colon;
179a90e161bSBill Fenner 	}
180a90e161bSBill Fenner }
181a90e161bSBill Fenner 
182b0453382SBill Fenner int
183a90e161bSBill Fenner esp_print(register const u_char *bp, register const u_char *bp2,
184a90e161bSBill Fenner 	  int *nhdr, int *padlen)
185b0453382SBill Fenner {
186b0453382SBill Fenner 	register const struct esp *esp;
187b0453382SBill Fenner 	register const u_char *ep;
188b0453382SBill Fenner 	u_int32_t spi;
189b0453382SBill Fenner 	struct ip *ip = NULL;
190b0453382SBill Fenner #ifdef INET6
191b0453382SBill Fenner 	struct ip6_hdr *ip6 = NULL;
192b0453382SBill Fenner #endif
193b0453382SBill Fenner 	int advance;
194b0453382SBill Fenner 	int len;
195a90e161bSBill Fenner 	char *secret;
196b0453382SBill Fenner 	int ivlen = 0;
197b0453382SBill Fenner 	u_char *ivoff;
198a90e161bSBill Fenner 	u_char *p;
199b0453382SBill Fenner 
200b0453382SBill Fenner 	esp = (struct esp *)bp;
201b0453382SBill Fenner 	spi = (u_int32_t)ntohl(esp->esp_spi);
202a90e161bSBill Fenner 	secret = NULL;
203a90e161bSBill Fenner 
204a90e161bSBill Fenner #if 0
205a90e161bSBill Fenner 	/* keep secret out of a register */
206a90e161bSBill Fenner 	p = (u_char *)&secret;
207a90e161bSBill Fenner #endif
208b0453382SBill Fenner 
209685295f4SBill Fenner 	/* 'ep' points to the end of available data. */
210b0453382SBill Fenner 	ep = snapend;
211b0453382SBill Fenner 
212b0453382SBill Fenner 	if ((u_char *)(esp + 1) >= ep - sizeof(struct esp)) {
213b0453382SBill Fenner 		fputs("[|ESP]", stdout);
214b0453382SBill Fenner 		goto fail;
215b0453382SBill Fenner 	}
216685295f4SBill Fenner 	printf("ESP(spi=0x%08x", spi);
217b0453382SBill Fenner 	printf(",seq=0x%x", (u_int32_t)ntohl(*(u_int32_t *)(esp + 1)));
218b0453382SBill Fenner 	printf(")");
219b0453382SBill Fenner 
220b0453382SBill Fenner 	/* if we don't have decryption key, we can't decrypt this packet. */
221b0453382SBill Fenner 	if (!espsecret)
222b0453382SBill Fenner 		goto fail;
223b0453382SBill Fenner 
224a90e161bSBill Fenner 	if(!espsecret_xform) {
225a90e161bSBill Fenner 		esp_print_decodesecret();
226a90e161bSBill Fenner 	}
227a90e161bSBill Fenner 	if(espsecret_xform->algo == NONE) {
228a90e161bSBill Fenner 		goto fail;
229b0453382SBill Fenner 	}
230b0453382SBill Fenner 
231b0453382SBill Fenner 	ip = (struct ip *)bp2;
232685295f4SBill Fenner 	switch (IP_V(ip)) {
233b0453382SBill Fenner #ifdef INET6
234b0453382SBill Fenner 	case 6:
235b0453382SBill Fenner 		ip6 = (struct ip6_hdr *)bp2;
236b0453382SBill Fenner 		ip = NULL;
237b0453382SBill Fenner 		/* we do not attempt to decrypt jumbograms */
238b0453382SBill Fenner 		if (!ntohs(ip6->ip6_plen))
239b0453382SBill Fenner 			goto fail;
240b0453382SBill Fenner 		/* if we can't get nexthdr, we do not need to decrypt it */
241b0453382SBill Fenner 		len = sizeof(struct ip6_hdr) + ntohs(ip6->ip6_plen);
242b0453382SBill Fenner 		break;
243b0453382SBill Fenner #endif /*INET6*/
244b0453382SBill Fenner 	case 4:
245a90e161bSBill Fenner 		/* nexthdr & padding are in the last fragment */
246a90e161bSBill Fenner 		if (ntohs(ip->ip_off) & IP_MF)
247a90e161bSBill Fenner 			goto fail;
248b0453382SBill Fenner #ifdef INET6
249b0453382SBill Fenner 		ip6 = NULL;
250b0453382SBill Fenner #endif
251b0453382SBill Fenner 		len = ntohs(ip->ip_len);
252b0453382SBill Fenner 		break;
253b0453382SBill Fenner 	default:
254b0453382SBill Fenner 		goto fail;
255b0453382SBill Fenner 	}
256b0453382SBill Fenner 
257b0453382SBill Fenner 	/* if we can't get nexthdr, we do not need to decrypt it */
258b0453382SBill Fenner 	if (ep - bp2 < len)
259b0453382SBill Fenner 		goto fail;
260b0453382SBill Fenner 
261a90e161bSBill Fenner 	ivoff = (u_char *)(esp + 1) + espsecret_xform->replaysize;
262a90e161bSBill Fenner 	ivlen = espsecret_xform->ivlen;
263a90e161bSBill Fenner 	secret = espsecret_key;
264b0453382SBill Fenner 
265a90e161bSBill Fenner 	switch (espsecret_xform->algo) {
266b0453382SBill Fenner 	case DESCBC:
267685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO
268b0453382SBill Fenner 	    {
269b0453382SBill Fenner 		u_char iv[8];
270b0453382SBill Fenner 		des_key_schedule schedule;
271b0453382SBill Fenner 
272b0453382SBill Fenner 		switch (ivlen) {
273b0453382SBill Fenner 		case 4:
274b0453382SBill Fenner 			memcpy(iv, ivoff, 4);
275b0453382SBill Fenner 			memcpy(&iv[4], ivoff, 4);
276b0453382SBill Fenner 			p = &iv[4];
277b0453382SBill Fenner 			*p++ ^= 0xff;
278b0453382SBill Fenner 			*p++ ^= 0xff;
279b0453382SBill Fenner 			*p++ ^= 0xff;
280b0453382SBill Fenner 			*p++ ^= 0xff;
281b0453382SBill Fenner 			break;
282b0453382SBill Fenner 		case 8:
283b0453382SBill Fenner 			memcpy(iv, ivoff, 8);
284b0453382SBill Fenner 			break;
285b0453382SBill Fenner 		default:
286b0453382SBill Fenner 			goto fail;
287b0453382SBill Fenner 		}
288b0453382SBill Fenner 
289b0453382SBill Fenner 		des_check_key = 0;
290b0453382SBill Fenner 		des_set_key((void *)secret, schedule);
291b0453382SBill Fenner 
292b0453382SBill Fenner 		p = ivoff + ivlen;
293b0453382SBill Fenner 		des_cbc_encrypt((void *)p, (void *)p,
294b0453382SBill Fenner 			(long)(ep - p), schedule, (void *)iv,
295b0453382SBill Fenner 			DES_DECRYPT);
296b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
297b0453382SBill Fenner 		break;
298b0453382SBill Fenner 	    }
299b0453382SBill Fenner #else
300b0453382SBill Fenner 		goto fail;
301685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/
302b0453382SBill Fenner 
303b0453382SBill Fenner 	case BLOWFISH:
304685295f4SBill Fenner #ifdef HAVE_LIBCRYPTO
305b0453382SBill Fenner 	    {
306b0453382SBill Fenner 		BF_KEY schedule;
307b0453382SBill Fenner 
308b0453382SBill Fenner 		BF_set_key(&schedule, strlen(secret), secret);
309b0453382SBill Fenner 
310b0453382SBill Fenner 		p = ivoff + ivlen;
311b0453382SBill Fenner 		BF_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
312b0453382SBill Fenner 			BF_DECRYPT);
313b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
314b0453382SBill Fenner 		break;
315b0453382SBill Fenner 	    }
316b0453382SBill Fenner #else
317b0453382SBill Fenner 		goto fail;
318685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/
319b0453382SBill Fenner 
320b0453382SBill Fenner 	case RC5:
321685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) && defined(HAVE_RC5_H)
322b0453382SBill Fenner 	    {
323b0453382SBill Fenner 		RC5_32_KEY schedule;
324b0453382SBill Fenner 
325b0453382SBill Fenner 		RC5_32_set_key(&schedule, strlen(secret), secret,
326b0453382SBill Fenner 			RC5_16_ROUNDS);
327b0453382SBill Fenner 
328b0453382SBill Fenner 		p = ivoff + ivlen;
329b0453382SBill Fenner 		RC5_32_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
330b0453382SBill Fenner 			RC5_DECRYPT);
331b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
332b0453382SBill Fenner 		break;
333b0453382SBill Fenner 	    }
334b0453382SBill Fenner #else
335b0453382SBill Fenner 		goto fail;
336685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/
337b0453382SBill Fenner 
338b0453382SBill Fenner 	case CAST128:
339685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO) && defined(HAVE_CAST_H) && !defined(HAVE_BUGGY_CAST128)
340b0453382SBill Fenner 	    {
341b0453382SBill Fenner 		CAST_KEY schedule;
342b0453382SBill Fenner 
343b0453382SBill Fenner 		CAST_set_key(&schedule, strlen(secret), secret);
344b0453382SBill Fenner 
345b0453382SBill Fenner 		p = ivoff + ivlen;
346b0453382SBill Fenner 		CAST_cbc_encrypt(p, p, (long)(ep - p), &schedule, ivoff,
347b0453382SBill Fenner 			CAST_DECRYPT);
348b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
349b0453382SBill Fenner 		break;
350b0453382SBill Fenner 	    }
351b0453382SBill Fenner #else
352b0453382SBill Fenner 		goto fail;
353685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/
354b0453382SBill Fenner 
355b0453382SBill Fenner 	case DES3CBC:
356685295f4SBill Fenner #if defined(HAVE_LIBCRYPTO)
357b0453382SBill Fenner 	    {
358b0453382SBill Fenner 		des_key_schedule s1, s2, s3;
359b0453382SBill Fenner 
360a90e161bSBill Fenner 		des_check_key = 1;
361a90e161bSBill Fenner 		des_set_odd_parity((void *)secret);
3629afd0c29SBill Fenner 		des_set_odd_parity((void *)(secret + 8));
3639afd0c29SBill Fenner 		des_set_odd_parity((void *)(secret + 16));
364a90e161bSBill Fenner 		if(des_set_key((void *)secret, s1) != 0) {
365a90e161bSBill Fenner 		  printf("failed to schedule key 1\n");
366a90e161bSBill Fenner 		}
367a90e161bSBill Fenner 		if(des_set_key((void *)(secret + 8), s2)!=0) {
368a90e161bSBill Fenner 		  printf("failed to schedule key 2\n");
369a90e161bSBill Fenner 		}
370a90e161bSBill Fenner 		if(des_set_key((void *)(secret + 16), s3)!=0) {
371a90e161bSBill Fenner 		  printf("failed to schedule key 3\n");
372a90e161bSBill Fenner 		}
373b0453382SBill Fenner 
374b0453382SBill Fenner 		p = ivoff + ivlen;
375b0453382SBill Fenner 		des_ede3_cbc_encrypt((void *)p, (void *)p,
376a90e161bSBill Fenner 				     (long)(ep - p),
377a90e161bSBill Fenner 				     s1, s2, s3,
378a90e161bSBill Fenner 				     (void *)ivoff, DES_DECRYPT);
379b0453382SBill Fenner 		advance = ivoff - (u_char *)esp + ivlen;
380b0453382SBill Fenner 		break;
381b0453382SBill Fenner 	    }
382b0453382SBill Fenner #else
383b0453382SBill Fenner 		goto fail;
384685295f4SBill Fenner #endif /*HAVE_LIBCRYPTO*/
385b0453382SBill Fenner 
386b0453382SBill Fenner 	case NONE:
387b0453382SBill Fenner 	default:
388a90e161bSBill Fenner 		advance = sizeof(struct esp) + espsecret_xform->replaysize;
389b0453382SBill Fenner 		break;
390b0453382SBill Fenner 	}
391b0453382SBill Fenner 
392a90e161bSBill Fenner 	ep = ep - espsecret_xform->authlen;
393b0453382SBill Fenner 	/* sanity check for pad length */
394b0453382SBill Fenner 	if (ep - bp < *(ep - 2))
395b0453382SBill Fenner 		goto fail;
396b0453382SBill Fenner 
397a90e161bSBill Fenner 	if (padlen)
398a90e161bSBill Fenner 		*padlen = *(ep - 2) + 2;
399a90e161bSBill Fenner 
400b0453382SBill Fenner 	if (nhdr)
401b0453382SBill Fenner 		*nhdr = *(ep - 1);
402b0453382SBill Fenner 
403b0453382SBill Fenner 	printf(": ");
404b0453382SBill Fenner 	return advance;
405b0453382SBill Fenner 
406b0453382SBill Fenner fail:
407b0453382SBill Fenner 	if (nhdr)
408b0453382SBill Fenner 		*nhdr = -1;
409b0453382SBill Fenner 	return 65536;
410b0453382SBill Fenner }
411