xref: /illumos-gate/usr/src/cmd/cmd-inet/usr.sbin/snoop/snoop_slp.c (revision 7c478bd95313f5f23a4c958a745db2134aa0324)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright (c) 1998,2000 by Sun Microsystems, Inc.
24*7c478bd9Sstevel@tonic-gate  * All rights reserved.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdio.h>
30*7c478bd9Sstevel@tonic-gate #include <arpa/inet.h>
31*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
32*7c478bd9Sstevel@tonic-gate #include <string.h>
33*7c478bd9Sstevel@tonic-gate #include <sys/time.h>
34*7c478bd9Sstevel@tonic-gate #include <iconv.h>
35*7c478bd9Sstevel@tonic-gate #include "snoop.h"
36*7c478bd9Sstevel@tonic-gate #include "slp.h"
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate #define	MAXSUMLEN 30
39*7c478bd9Sstevel@tonic-gate 
40*7c478bd9Sstevel@tonic-gate /* define VERIFYSLP to enable full message checking in summary mode */
41*7c478bd9Sstevel@tonic-gate #define	VERIFYSLP
42*7c478bd9Sstevel@tonic-gate 
43*7c478bd9Sstevel@tonic-gate /* Globals -- ugly, yes, but fast and easy in macros */
44*7c478bd9Sstevel@tonic-gate static int msglength;
45*7c478bd9Sstevel@tonic-gate static int retlength;
46*7c478bd9Sstevel@tonic-gate static char *msgend;	/* the end of the summary message buffer */
47*7c478bd9Sstevel@tonic-gate static char *p;		/* current position in the packet */
48*7c478bd9Sstevel@tonic-gate static char *msgbuf;	/* message buffer for summary mode */
49*7c478bd9Sstevel@tonic-gate static boolean_t url_auth	= B_FALSE;
50*7c478bd9Sstevel@tonic-gate static boolean_t attr_auth	= B_FALSE;
51*7c478bd9Sstevel@tonic-gate static boolean_t fresh		= B_FALSE;
52*7c478bd9Sstevel@tonic-gate static boolean_t overflow	= B_FALSE;
53*7c478bd9Sstevel@tonic-gate static int v1_charset		= 0;	/* character set; only in V1 */
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate /* Entry points for parsing the protocol */
56*7c478bd9Sstevel@tonic-gate static int interpret_slp_v1(int, struct slpv1_hdr *, int);
57*7c478bd9Sstevel@tonic-gate static int interpret_slp_v2(int, struct slpv2_hdr *, int);
58*7c478bd9Sstevel@tonic-gate 
59*7c478bd9Sstevel@tonic-gate /* header parsing */
60*7c478bd9Sstevel@tonic-gate static int v1_header(int, struct slpv1_hdr *, int);
61*7c478bd9Sstevel@tonic-gate static int v2_header(int, struct slpv2_hdr *, int *, int);
62*7c478bd9Sstevel@tonic-gate static int v2_finish(struct slpv2_hdr *, int);
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate /* V2 auth blocks */
65*7c478bd9Sstevel@tonic-gate static int slpv2_authblock(int);
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate /* From snoop_rport: */
68*7c478bd9Sstevel@tonic-gate extern int add_transient(int, int (*)());
69*7c478bd9Sstevel@tonic-gate 
70*7c478bd9Sstevel@tonic-gate /*
71*7c478bd9Sstevel@tonic-gate  * Functions for parsing each protocol message
72*7c478bd9Sstevel@tonic-gate  * Each function takes the interpreter's flags argument as its input
73*7c478bd9Sstevel@tonic-gate  * parameter, and returns 1 on success, or 0 on message corruption.
74*7c478bd9Sstevel@tonic-gate  * retlength is set as a side-effect in summary mode.
75*7c478bd9Sstevel@tonic-gate  */
76*7c478bd9Sstevel@tonic-gate static int v2_srv_rqst(int);
77*7c478bd9Sstevel@tonic-gate static int v2_srv_rply(int);
78*7c478bd9Sstevel@tonic-gate static int v2_srv_reg(int);
79*7c478bd9Sstevel@tonic-gate static int v2_srv_dereg(int);
80*7c478bd9Sstevel@tonic-gate static int v2_srv_ack(int);
81*7c478bd9Sstevel@tonic-gate static int v2_attr_rqst(int);
82*7c478bd9Sstevel@tonic-gate static int v2_attr_rply(int);
83*7c478bd9Sstevel@tonic-gate static int v2_daadvert(int);
84*7c478bd9Sstevel@tonic-gate static int v2_srv_type_rqst(int);
85*7c478bd9Sstevel@tonic-gate static int v2_srv_type_rply(int);
86*7c478bd9Sstevel@tonic-gate static int v2_saadvert(int);
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static int v1_srv_rqst(int);
89*7c478bd9Sstevel@tonic-gate static int v1_srv_rply(int);
90*7c478bd9Sstevel@tonic-gate static int v1_srv_reg(int);
91*7c478bd9Sstevel@tonic-gate static int v1_srv_dereg(int);
92*7c478bd9Sstevel@tonic-gate static int v1_srv_ack(int);
93*7c478bd9Sstevel@tonic-gate static int v1_attr_rqst(int);
94*7c478bd9Sstevel@tonic-gate static int v1_attr_rply(int);
95*7c478bd9Sstevel@tonic-gate static int v1_daadvert(int);
96*7c478bd9Sstevel@tonic-gate static int v1_srv_type_rqst(int);
97*7c478bd9Sstevel@tonic-gate static int v1_srv_type_rply(int);
98*7c478bd9Sstevel@tonic-gate 
99*7c478bd9Sstevel@tonic-gate /*
100*7c478bd9Sstevel@tonic-gate  * The dispatch tables for handling individual messages, keyed by
101*7c478bd9Sstevel@tonic-gate  * function number.
102*7c478bd9Sstevel@tonic-gate  */
103*7c478bd9Sstevel@tonic-gate typedef int function_handler();
104*7c478bd9Sstevel@tonic-gate 
105*7c478bd9Sstevel@tonic-gate #define	V2_MAX_FUNCTION	11
106*7c478bd9Sstevel@tonic-gate 
107*7c478bd9Sstevel@tonic-gate static function_handler *v2_functions[V2_MAX_FUNCTION + 1] = {
108*7c478bd9Sstevel@tonic-gate 	(function_handler *) NULL,
109*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_rqst,
110*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_rply,
111*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_reg,
112*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_dereg,
113*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_ack,
114*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_attr_rqst,
115*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_attr_rply,
116*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_daadvert,
117*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_type_rqst,
118*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_srv_type_rply,
119*7c478bd9Sstevel@tonic-gate 	(function_handler *) v2_saadvert };
120*7c478bd9Sstevel@tonic-gate 
121*7c478bd9Sstevel@tonic-gate #define	V1_MAX_FUNCTION	10
122*7c478bd9Sstevel@tonic-gate 
123*7c478bd9Sstevel@tonic-gate static function_handler *v1_functions[V1_MAX_FUNCTION + 1] = {
124*7c478bd9Sstevel@tonic-gate 	(function_handler *) NULL,
125*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_rqst,
126*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_rply,
127*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_reg,
128*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_dereg,
129*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_ack,
130*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_attr_rqst,
131*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_attr_rply,
132*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_daadvert,
133*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_type_rqst,
134*7c478bd9Sstevel@tonic-gate 	(function_handler *) v1_srv_type_rply };
135*7c478bd9Sstevel@tonic-gate 
136*7c478bd9Sstevel@tonic-gate /* TCP continuation handling */
137*7c478bd9Sstevel@tonic-gate static boolean_t tcp_continuation = B_FALSE;
138*7c478bd9Sstevel@tonic-gate 
139*7c478bd9Sstevel@tonic-gate #define	MAX_TCPCONT	16
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate static struct tcp_cont {
142*7c478bd9Sstevel@tonic-gate 	int dst_port;
143*7c478bd9Sstevel@tonic-gate 	char *msg;
144*7c478bd9Sstevel@tonic-gate 	int totallen;
145*7c478bd9Sstevel@tonic-gate 	int curr_offset;
146*7c478bd9Sstevel@tonic-gate } *tcp_cont[MAX_TCPCONT];
147*7c478bd9Sstevel@tonic-gate 
148*7c478bd9Sstevel@tonic-gate static int current_tcp_cont;
149*7c478bd9Sstevel@tonic-gate 
150*7c478bd9Sstevel@tonic-gate static void reg_tcp_cont(char *, int, int, int);
151*7c478bd9Sstevel@tonic-gate static int add_tcp_cont(struct tcp_cont *, char *, int);
152*7c478bd9Sstevel@tonic-gate static struct tcp_cont *find_tcp_cont(int);
153*7c478bd9Sstevel@tonic-gate static void remove_tcp_cont(int);
154*7c478bd9Sstevel@tonic-gate 
155*7c478bd9Sstevel@tonic-gate /* Conversions from numbers to strings */
156*7c478bd9Sstevel@tonic-gate static char *slpv2_func(int, boolean_t);
157*7c478bd9Sstevel@tonic-gate static char *slpv2_error(unsigned short);
158*7c478bd9Sstevel@tonic-gate static char *slpv1_func(int, boolean_t);
159*7c478bd9Sstevel@tonic-gate static char *slpv1_error(unsigned short);
160*7c478bd9Sstevel@tonic-gate static char *slpv1_charset(unsigned short);
161*7c478bd9Sstevel@tonic-gate 
162*7c478bd9Sstevel@tonic-gate /*
163*7c478bd9Sstevel@tonic-gate  * The only external entry point to the SLP interpreter. This function
164*7c478bd9Sstevel@tonic-gate  * simply dispatches the packet based on the version.
165*7c478bd9Sstevel@tonic-gate  */
166*7c478bd9Sstevel@tonic-gate void interpret_slp(int flags, char *slp, int fraglen) {
167*7c478bd9Sstevel@tonic-gate 	extern int dst_port, curr_proto;
168*7c478bd9Sstevel@tonic-gate 	struct tcp_cont *tce = NULL;
169*7c478bd9Sstevel@tonic-gate 
170*7c478bd9Sstevel@tonic-gate 	msglength = fraglen;
171*7c478bd9Sstevel@tonic-gate 	retlength = 0;
172*7c478bd9Sstevel@tonic-gate 	p = slp;
173*7c478bd9Sstevel@tonic-gate 
174*7c478bd9Sstevel@tonic-gate 	/* check if this is a TCP continuation */
175*7c478bd9Sstevel@tonic-gate 	if (flags & F_DTAIL && curr_proto == IPPROTO_TCP) {
176*7c478bd9Sstevel@tonic-gate 	    tce = find_tcp_cont(dst_port);
177*7c478bd9Sstevel@tonic-gate 	    if (tce) {
178*7c478bd9Sstevel@tonic-gate 		if (add_tcp_cont(tce, slp, fraglen)) {
179*7c478bd9Sstevel@tonic-gate 		    slp = tce->msg;
180*7c478bd9Sstevel@tonic-gate 		    fraglen = tce->curr_offset;
181*7c478bd9Sstevel@tonic-gate 		    tcp_continuation = B_TRUE;
182*7c478bd9Sstevel@tonic-gate 		}
183*7c478bd9Sstevel@tonic-gate 	    }
184*7c478bd9Sstevel@tonic-gate 	}
185*7c478bd9Sstevel@tonic-gate 	if (*slp == 2 || tce)
186*7c478bd9Sstevel@tonic-gate 	    interpret_slp_v2(flags, (void *)slp, fraglen);
187*7c478bd9Sstevel@tonic-gate 	else
188*7c478bd9Sstevel@tonic-gate 	    interpret_slp_v1(flags, (void *)slp, fraglen);
189*7c478bd9Sstevel@tonic-gate 
190*7c478bd9Sstevel@tonic-gate 	tcp_continuation = B_FALSE;
191*7c478bd9Sstevel@tonic-gate }
192*7c478bd9Sstevel@tonic-gate 
193*7c478bd9Sstevel@tonic-gate /*
194*7c478bd9Sstevel@tonic-gate  * Primitives. These are implemented as much as possible as macros for
195*7c478bd9Sstevel@tonic-gate  * speed.
196*7c478bd9Sstevel@tonic-gate  */
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate #define	FIELD_DEFAULT	0
199*7c478bd9Sstevel@tonic-gate #define	FIELD_PREVRESP	1
200*7c478bd9Sstevel@tonic-gate #define	FIELD_TYPENA	2
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate static long long netval = 0;	/* need signed 64 bit quantity */
203*7c478bd9Sstevel@tonic-gate 
204*7c478bd9Sstevel@tonic-gate /* gets two bytes from p and leaves the result in netval */
205*7c478bd9Sstevel@tonic-gate #define	nbtohs() \
206*7c478bd9Sstevel@tonic-gate 	netval = ((int)(p[0] & 0xff)) << 8; \
207*7c478bd9Sstevel@tonic-gate 	netval += ((int)(p[1] & 0xff))
208*7c478bd9Sstevel@tonic-gate 
209*7c478bd9Sstevel@tonic-gate /* gets four bytes from p and leaves the result in netval */
210*7c478bd9Sstevel@tonic-gate #define	nbtohl() \
211*7c478bd9Sstevel@tonic-gate 	netval = ((int)(p[0] & 0xff)) << 24; \
212*7c478bd9Sstevel@tonic-gate 	netval += ((int)(p[1] & 0xff)) << 16; \
213*7c478bd9Sstevel@tonic-gate 	netval += ((int)(p[2] & 0xff)) << 8; \
214*7c478bd9Sstevel@tonic-gate 	netval += ((int)(p[3] & 0xff))
215*7c478bd9Sstevel@tonic-gate 
216*7c478bd9Sstevel@tonic-gate #define	get_byte() \
217*7c478bd9Sstevel@tonic-gate 	if (msglength >= 1) { \
218*7c478bd9Sstevel@tonic-gate 		netval = *p; \
219*7c478bd9Sstevel@tonic-gate 		p++; \
220*7c478bd9Sstevel@tonic-gate 		msglength--; \
221*7c478bd9Sstevel@tonic-gate 	} else \
222*7c478bd9Sstevel@tonic-gate 		netval = -1
223*7c478bd9Sstevel@tonic-gate 
224*7c478bd9Sstevel@tonic-gate #define	GETBYTE(x) \
225*7c478bd9Sstevel@tonic-gate 	get_byte(); \
226*7c478bd9Sstevel@tonic-gate 	if ((retlength = netval) < 0) \
227*7c478bd9Sstevel@tonic-gate 		return (0); \
228*7c478bd9Sstevel@tonic-gate 	x = netval
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate #define	SKIPBYTE \
231*7c478bd9Sstevel@tonic-gate 	get_byte(); \
232*7c478bd9Sstevel@tonic-gate 	if ((retlength = netval) < 0) \
233*7c478bd9Sstevel@tonic-gate 		return (0); \
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate /*
236*7c478bd9Sstevel@tonic-gate  * gets two bytes from p, leaves the result in netval, and updates
237*7c478bd9Sstevel@tonic-gate  * msglength and p.
238*7c478bd9Sstevel@tonic-gate  */
239*7c478bd9Sstevel@tonic-gate #define	get_short() \
240*7c478bd9Sstevel@tonic-gate 	if (msglength >= sizeof (unsigned short)) { \
241*7c478bd9Sstevel@tonic-gate 		nbtohs(); \
242*7c478bd9Sstevel@tonic-gate 		p += sizeof (unsigned short); \
243*7c478bd9Sstevel@tonic-gate 		msglength -= sizeof (unsigned short); \
244*7c478bd9Sstevel@tonic-gate 	} else \
245*7c478bd9Sstevel@tonic-gate 		netval = -1
246*7c478bd9Sstevel@tonic-gate 
247*7c478bd9Sstevel@tonic-gate #define	GETSHORT(x) \
248*7c478bd9Sstevel@tonic-gate 	get_short(); \
249*7c478bd9Sstevel@tonic-gate 	if ((retlength = netval) < 0) \
250*7c478bd9Sstevel@tonic-gate 		return (0); \
251*7c478bd9Sstevel@tonic-gate 	x = netval
252*7c478bd9Sstevel@tonic-gate 
253*7c478bd9Sstevel@tonic-gate #define	SKIPSHORT \
254*7c478bd9Sstevel@tonic-gate 	get_short(); \
255*7c478bd9Sstevel@tonic-gate 	if ((retlength = netval) < 0) \
256*7c478bd9Sstevel@tonic-gate 		return (0)
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate #define	get_int24(pp) \
259*7c478bd9Sstevel@tonic-gate 	netval = ((int)((pp)[0] & 0xff)) << 16; \
260*7c478bd9Sstevel@tonic-gate 	netval += ((int)((pp)[1] & 0xff)) << 8; \
261*7c478bd9Sstevel@tonic-gate 	netval += ((int)((pp)[2] & 0xff))
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate static void slp_prevresp(char *p) {
264*7c478bd9Sstevel@tonic-gate 	char *p2;
265*7c478bd9Sstevel@tonic-gate 
266*7c478bd9Sstevel@tonic-gate 	/* cycle through all entries */
267*7c478bd9Sstevel@tonic-gate 	for (; p != NULL; p = p2) {
268*7c478bd9Sstevel@tonic-gate 	    p2 = strchr(p, ',');
269*7c478bd9Sstevel@tonic-gate 	    if (p2 != NULL)
270*7c478bd9Sstevel@tonic-gate 		*p2++ = '\0';
271*7c478bd9Sstevel@tonic-gate 
272*7c478bd9Sstevel@tonic-gate 	    /* print entry at p */
273*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "  \"%s\"", p);
274*7c478bd9Sstevel@tonic-gate 	}
275*7c478bd9Sstevel@tonic-gate }
276*7c478bd9Sstevel@tonic-gate 
277*7c478bd9Sstevel@tonic-gate static int skip_field(int type) {
278*7c478bd9Sstevel@tonic-gate 	unsigned short stringlen;
279*7c478bd9Sstevel@tonic-gate 
280*7c478bd9Sstevel@tonic-gate 	get_short();
281*7c478bd9Sstevel@tonic-gate 	if (netval < 0) {
282*7c478bd9Sstevel@tonic-gate 	    return (-1);
283*7c478bd9Sstevel@tonic-gate 	}
284*7c478bd9Sstevel@tonic-gate 	stringlen = netval;
285*7c478bd9Sstevel@tonic-gate 
286*7c478bd9Sstevel@tonic-gate 	/* special case for NA field in SrvTypeRqst */
287*7c478bd9Sstevel@tonic-gate 	if (type == FIELD_TYPENA && stringlen == 0xffff) {
288*7c478bd9Sstevel@tonic-gate 	    stringlen = 0;
289*7c478bd9Sstevel@tonic-gate 	}
290*7c478bd9Sstevel@tonic-gate 
291*7c478bd9Sstevel@tonic-gate 	if (stringlen > msglength) {
292*7c478bd9Sstevel@tonic-gate 	    return (-1);
293*7c478bd9Sstevel@tonic-gate 	}
294*7c478bd9Sstevel@tonic-gate 
295*7c478bd9Sstevel@tonic-gate 	msglength -= stringlen;
296*7c478bd9Sstevel@tonic-gate 	p += stringlen;
297*7c478bd9Sstevel@tonic-gate 
298*7c478bd9Sstevel@tonic-gate 	return (stringlen);
299*7c478bd9Sstevel@tonic-gate }
300*7c478bd9Sstevel@tonic-gate 
301*7c478bd9Sstevel@tonic-gate #define	SKIPFIELD(type) \
302*7c478bd9Sstevel@tonic-gate 	if ((retlength = skip_field(type)) < 0) \
303*7c478bd9Sstevel@tonic-gate 		return (0)
304*7c478bd9Sstevel@tonic-gate 
305*7c478bd9Sstevel@tonic-gate #define	GETFIELD \
306*7c478bd9Sstevel@tonic-gate 	get_short(); \
307*7c478bd9Sstevel@tonic-gate 	if ((retlength = netval) < 0) \
308*7c478bd9Sstevel@tonic-gate 		return (0); \
309*7c478bd9Sstevel@tonic-gate 	strncat(msgbuf, p, (retlength > MAXSUMLEN ? MAXSUMLEN : retlength)); \
310*7c478bd9Sstevel@tonic-gate 	p += retlength; \
311*7c478bd9Sstevel@tonic-gate 	msglength -= retlength
312*7c478bd9Sstevel@tonic-gate 
313*7c478bd9Sstevel@tonic-gate /*
314*7c478bd9Sstevel@tonic-gate  * Determines from the first five bytes of a potential SLP header
315*7c478bd9Sstevel@tonic-gate  * if the following message is really an SLP message. Returns 1 if
316*7c478bd9Sstevel@tonic-gate  * it is a real SLP message, 0 if not.
317*7c478bd9Sstevel@tonic-gate  */
318*7c478bd9Sstevel@tonic-gate int valid_slp(unsigned char *slphdr, int len) {
319*7c478bd9Sstevel@tonic-gate 	struct slpv1_hdr slp1;
320*7c478bd9Sstevel@tonic-gate 	struct slpv2_hdr slp2;
321*7c478bd9Sstevel@tonic-gate 
322*7c478bd9Sstevel@tonic-gate 	len -= (8 /* udp */ + 20 /* IP */ + 14 /* ether */);
323*7c478bd9Sstevel@tonic-gate 	/* a valid version will be 1 or 2 */
324*7c478bd9Sstevel@tonic-gate 	switch (*slphdr) {
325*7c478bd9Sstevel@tonic-gate 	case 1:
326*7c478bd9Sstevel@tonic-gate 	    memcpy(&slp1, slphdr, 5);
327*7c478bd9Sstevel@tonic-gate 	    /* valid function? */
328*7c478bd9Sstevel@tonic-gate 	    if (slp1.function > V1_MAX_FUNCTION) {
329*7c478bd9Sstevel@tonic-gate 		return (0);
330*7c478bd9Sstevel@tonic-gate 	    }
331*7c478bd9Sstevel@tonic-gate 	    /* valid length heuristic */
332*7c478bd9Sstevel@tonic-gate 	    if (slp1.length > len) {
333*7c478bd9Sstevel@tonic-gate 		return (0);
334*7c478bd9Sstevel@tonic-gate 	    }
335*7c478bd9Sstevel@tonic-gate 	    return (1);
336*7c478bd9Sstevel@tonic-gate 	case 2:
337*7c478bd9Sstevel@tonic-gate 	    memcpy(&slp2, slphdr, 5);
338*7c478bd9Sstevel@tonic-gate 	    /* valid function? */
339*7c478bd9Sstevel@tonic-gate 	    if (slp2.function > V2_MAX_FUNCTION) {
340*7c478bd9Sstevel@tonic-gate 		return (0);
341*7c478bd9Sstevel@tonic-gate 	    }
342*7c478bd9Sstevel@tonic-gate 	    /* valid length heuristic */
343*7c478bd9Sstevel@tonic-gate 	    get_int24(&(slp2.l1));
344*7c478bd9Sstevel@tonic-gate 	    if (netval > len) {
345*7c478bd9Sstevel@tonic-gate 		return (0);
346*7c478bd9Sstevel@tonic-gate 	    }
347*7c478bd9Sstevel@tonic-gate 	    return (1);
348*7c478bd9Sstevel@tonic-gate 	default:
349*7c478bd9Sstevel@tonic-gate 	    return (0);
350*7c478bd9Sstevel@tonic-gate 	}
351*7c478bd9Sstevel@tonic-gate }
352*7c478bd9Sstevel@tonic-gate 
353*7c478bd9Sstevel@tonic-gate /*
354*7c478bd9Sstevel@tonic-gate  * Converts a V1 char encoding to UTF8. If this fails, returns 0,
355*7c478bd9Sstevel@tonic-gate  * otherwise, 1. This function is the union of iconv UTF-8
356*7c478bd9Sstevel@tonic-gate  * modules and character sets registered with IANA.
357*7c478bd9Sstevel@tonic-gate  */
358*7c478bd9Sstevel@tonic-gate static int make_utf8(char *outbuf, size_t outlen,
359*7c478bd9Sstevel@tonic-gate 			const char *inbuf, size_t inlen) {
360*7c478bd9Sstevel@tonic-gate 	iconv_t cd;
361*7c478bd9Sstevel@tonic-gate 	size_t converted;
362*7c478bd9Sstevel@tonic-gate 
363*7c478bd9Sstevel@tonic-gate 	switch (v1_charset) {
364*7c478bd9Sstevel@tonic-gate 	case 4:
365*7c478bd9Sstevel@tonic-gate 	case 1004:
366*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-1");
367*7c478bd9Sstevel@tonic-gate 	    break;
368*7c478bd9Sstevel@tonic-gate 	case 5:
369*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-2");
370*7c478bd9Sstevel@tonic-gate 	    break;
371*7c478bd9Sstevel@tonic-gate 	case 6:
372*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-3");
373*7c478bd9Sstevel@tonic-gate 	    break;
374*7c478bd9Sstevel@tonic-gate 	case 7:
375*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-4");
376*7c478bd9Sstevel@tonic-gate 	    break;
377*7c478bd9Sstevel@tonic-gate 	case 8:
378*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-5");
379*7c478bd9Sstevel@tonic-gate 	    break;
380*7c478bd9Sstevel@tonic-gate 	case 9:
381*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-6");
382*7c478bd9Sstevel@tonic-gate 	    break;
383*7c478bd9Sstevel@tonic-gate 	case 10:
384*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-7");
385*7c478bd9Sstevel@tonic-gate 	    break;
386*7c478bd9Sstevel@tonic-gate 	case 11:
387*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-8");
388*7c478bd9Sstevel@tonic-gate 	    break;
389*7c478bd9Sstevel@tonic-gate 	case 12:
390*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-9");
391*7c478bd9Sstevel@tonic-gate 	    break;
392*7c478bd9Sstevel@tonic-gate 	case 13:
393*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "8859-10");
394*7c478bd9Sstevel@tonic-gate 	    break;
395*7c478bd9Sstevel@tonic-gate 	case 37:
396*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "ko_KR-iso2022-7");
397*7c478bd9Sstevel@tonic-gate 	    break;
398*7c478bd9Sstevel@tonic-gate 	case 104:
399*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "iso2022");
400*7c478bd9Sstevel@tonic-gate 	    break;
401*7c478bd9Sstevel@tonic-gate 	case 1000:
402*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "UCS-2");
403*7c478bd9Sstevel@tonic-gate 	    break;
404*7c478bd9Sstevel@tonic-gate 	case 1001:
405*7c478bd9Sstevel@tonic-gate 	    cd = iconv_open("UTF-8", "UCS-4");
406*7c478bd9Sstevel@tonic-gate 	    break;
407*7c478bd9Sstevel@tonic-gate 	default:
408*7c478bd9Sstevel@tonic-gate 		/*
409*7c478bd9Sstevel@tonic-gate 		 * charset not set, or reserved, or not supported, so
410*7c478bd9Sstevel@tonic-gate 		 * just copy it and hope for the best.
411*7c478bd9Sstevel@tonic-gate 		 */
412*7c478bd9Sstevel@tonic-gate 	    converted = outlen < inlen ? outlen : inlen;
413*7c478bd9Sstevel@tonic-gate 	    memcpy(outbuf, inbuf, converted);
414*7c478bd9Sstevel@tonic-gate 	    outbuf[converted] = 0;
415*7c478bd9Sstevel@tonic-gate 	    return (1);
416*7c478bd9Sstevel@tonic-gate 	}
417*7c478bd9Sstevel@tonic-gate 
418*7c478bd9Sstevel@tonic-gate 	if (cd == (iconv_t)-1) {
419*7c478bd9Sstevel@tonic-gate 	    return (0);
420*7c478bd9Sstevel@tonic-gate 	}
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	if ((converted = iconv(cd, &inbuf, &inlen, &outbuf, &outlen))
423*7c478bd9Sstevel@tonic-gate 	    == (size_t)-1) {
424*7c478bd9Sstevel@tonic-gate 	    return (0);
425*7c478bd9Sstevel@tonic-gate 	}
426*7c478bd9Sstevel@tonic-gate 
427*7c478bd9Sstevel@tonic-gate 	outbuf[converted] = 0;
428*7c478bd9Sstevel@tonic-gate 	iconv_close(cd);
429*7c478bd9Sstevel@tonic-gate 
430*7c478bd9Sstevel@tonic-gate 	return (1);
431*7c478bd9Sstevel@tonic-gate }
432*7c478bd9Sstevel@tonic-gate 
433*7c478bd9Sstevel@tonic-gate static int slp_field(char *tag, int type) {
434*7c478bd9Sstevel@tonic-gate 	int length;
435*7c478bd9Sstevel@tonic-gate 
436*7c478bd9Sstevel@tonic-gate 	get_short();
437*7c478bd9Sstevel@tonic-gate 	if (netval < 0) {
438*7c478bd9Sstevel@tonic-gate 	    return (-1);
439*7c478bd9Sstevel@tonic-gate 	}
440*7c478bd9Sstevel@tonic-gate 	length = netval;
441*7c478bd9Sstevel@tonic-gate 
442*7c478bd9Sstevel@tonic-gate 	/* special case for NA field in SrvTypeRqst */
443*7c478bd9Sstevel@tonic-gate 	if (type == FIELD_TYPENA && length == 0xffff) {
444*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "%s: length = -1: Use all NAs", tag);
445*7c478bd9Sstevel@tonic-gate 	    return (0);
446*7c478bd9Sstevel@tonic-gate 	}
447*7c478bd9Sstevel@tonic-gate 
448*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0), "%s: length = %d", tag, length);
449*7c478bd9Sstevel@tonic-gate 	if (length > msglength) {
450*7c478bd9Sstevel@tonic-gate 	    /* framing error: message is not long enough to contain data */
451*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
452*7c478bd9Sstevel@tonic-gate 		    "  [Framing error: remaining pkt length = %u]",
453*7c478bd9Sstevel@tonic-gate 		    msglength);
454*7c478bd9Sstevel@tonic-gate 	    return (-1);
455*7c478bd9Sstevel@tonic-gate 	}
456*7c478bd9Sstevel@tonic-gate 
457*7c478bd9Sstevel@tonic-gate 	if (length > 0) {
458*7c478bd9Sstevel@tonic-gate 	    char *buf = malloc(length + 1);
459*7c478bd9Sstevel@tonic-gate 	    if (buf != NULL) {
460*7c478bd9Sstevel@tonic-gate 		if (v1_charset) {
461*7c478bd9Sstevel@tonic-gate 		    if (!make_utf8(buf, length, p, length)) {
462*7c478bd9Sstevel@tonic-gate 			strcpy(buf, "[Invalid Character Encoding]");
463*7c478bd9Sstevel@tonic-gate 		    }
464*7c478bd9Sstevel@tonic-gate 		} else {
465*7c478bd9Sstevel@tonic-gate 		    memcpy(buf, p, length);
466*7c478bd9Sstevel@tonic-gate 		    buf[length] = '\0';		/* ensure null-terminated */
467*7c478bd9Sstevel@tonic-gate 		}
468*7c478bd9Sstevel@tonic-gate 
469*7c478bd9Sstevel@tonic-gate 		switch (type) {
470*7c478bd9Sstevel@tonic-gate 		    case FIELD_PREVRESP:
471*7c478bd9Sstevel@tonic-gate 			slp_prevresp(buf);
472*7c478bd9Sstevel@tonic-gate 			break;
473*7c478bd9Sstevel@tonic-gate 
474*7c478bd9Sstevel@tonic-gate 		    default:
475*7c478bd9Sstevel@tonic-gate 			sprintf(get_line(0, 0), "  \"%s\"", buf);
476*7c478bd9Sstevel@tonic-gate 			break;
477*7c478bd9Sstevel@tonic-gate 		}
478*7c478bd9Sstevel@tonic-gate 		free(buf);
479*7c478bd9Sstevel@tonic-gate 	    }
480*7c478bd9Sstevel@tonic-gate 
481*7c478bd9Sstevel@tonic-gate 	    p += length;
482*7c478bd9Sstevel@tonic-gate 	    msglength -= length;
483*7c478bd9Sstevel@tonic-gate 	}
484*7c478bd9Sstevel@tonic-gate 
485*7c478bd9Sstevel@tonic-gate 	/* return ok */
486*7c478bd9Sstevel@tonic-gate 	return (0);
487*7c478bd9Sstevel@tonic-gate }
488*7c478bd9Sstevel@tonic-gate 
489*7c478bd9Sstevel@tonic-gate static int slpv2_url(int cnt) {
490*7c478bd9Sstevel@tonic-gate 	time_t exp;
491*7c478bd9Sstevel@tonic-gate 	int lifetime, length, n;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 	/* reserved */
494*7c478bd9Sstevel@tonic-gate 	get_byte();
495*7c478bd9Sstevel@tonic-gate 	if (netval < 0)
496*7c478bd9Sstevel@tonic-gate 	    return (-1);
497*7c478bd9Sstevel@tonic-gate 
498*7c478bd9Sstevel@tonic-gate 	/* lifetime */
499*7c478bd9Sstevel@tonic-gate 	get_short();
500*7c478bd9Sstevel@tonic-gate 	if ((lifetime = netval) < 0)
501*7c478bd9Sstevel@tonic-gate 	    return (-1);
502*7c478bd9Sstevel@tonic-gate 
503*7c478bd9Sstevel@tonic-gate 	/* length */
504*7c478bd9Sstevel@tonic-gate 	get_short();
505*7c478bd9Sstevel@tonic-gate 	if ((length = netval) < 0)
506*7c478bd9Sstevel@tonic-gate 	    return (-1);
507*7c478bd9Sstevel@tonic-gate 
508*7c478bd9Sstevel@tonic-gate 	/* time */
509*7c478bd9Sstevel@tonic-gate 	exp = time(0) + lifetime;
510*7c478bd9Sstevel@tonic-gate 	if (cnt == -1)
511*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
512*7c478bd9Sstevel@tonic-gate 		    "URL: length = %u, lifetime = %d (%24.24s)",
513*7c478bd9Sstevel@tonic-gate 		    length, lifetime, ctime(&exp));
514*7c478bd9Sstevel@tonic-gate 	else
515*7c478bd9Sstevel@tonic-gate 	    /* number the URLs to make it easier to parse them */
516*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
517*7c478bd9Sstevel@tonic-gate 		    "URL %d: length = %u, lifetime = %d (%24.24s)",
518*7c478bd9Sstevel@tonic-gate 		    cnt, length, lifetime, ctime(&exp));
519*7c478bd9Sstevel@tonic-gate 
520*7c478bd9Sstevel@tonic-gate 	if (length > msglength) {
521*7c478bd9Sstevel@tonic-gate 	    if (!tcp_continuation)
522*7c478bd9Sstevel@tonic-gate 		/* framing error: message is not long enough to contain data */
523*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
524*7c478bd9Sstevel@tonic-gate 			"  [Framing error: remaining pkt length = %u]",
525*7c478bd9Sstevel@tonic-gate 			msglength);
526*7c478bd9Sstevel@tonic-gate 	    return (-1);
527*7c478bd9Sstevel@tonic-gate 	}
528*7c478bd9Sstevel@tonic-gate 
529*7c478bd9Sstevel@tonic-gate 	if (length > 0) {
530*7c478bd9Sstevel@tonic-gate 	    char *buf = malloc(length + 1);
531*7c478bd9Sstevel@tonic-gate 	    if (buf != NULL) {
532*7c478bd9Sstevel@tonic-gate 		memcpy(buf, p, length);
533*7c478bd9Sstevel@tonic-gate 		buf[length] = '\0';		/* ensure null-terminated */
534*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0), "  \"%s\"", buf);
535*7c478bd9Sstevel@tonic-gate 		free(buf);
536*7c478bd9Sstevel@tonic-gate 	    }
537*7c478bd9Sstevel@tonic-gate 	}
538*7c478bd9Sstevel@tonic-gate 	msglength -= length;
539*7c478bd9Sstevel@tonic-gate 	p += length;
540*7c478bd9Sstevel@tonic-gate 
541*7c478bd9Sstevel@tonic-gate 	get_byte();
542*7c478bd9Sstevel@tonic-gate 	if ((n = netval) < 0)
543*7c478bd9Sstevel@tonic-gate 	    return (-1);
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate 	if (n > 0) {
546*7c478bd9Sstevel@tonic-gate 	    int i;
547*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "%d Authentication Blocks", n);
548*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < n; i++)
549*7c478bd9Sstevel@tonic-gate 		if ((length = slpv2_authblock(i)) < 0)
550*7c478bd9Sstevel@tonic-gate 		    return (-1);
551*7c478bd9Sstevel@tonic-gate 	}
552*7c478bd9Sstevel@tonic-gate 	return (0);
553*7c478bd9Sstevel@tonic-gate }
554*7c478bd9Sstevel@tonic-gate 
555*7c478bd9Sstevel@tonic-gate #define	DOFIELD(tag, type) \
556*7c478bd9Sstevel@tonic-gate 	if (slp_field(tag, type) < 0) \
557*7c478bd9Sstevel@tonic-gate 		return (0)
558*7c478bd9Sstevel@tonic-gate 
559*7c478bd9Sstevel@tonic-gate #define	V2_DOURL(x) \
560*7c478bd9Sstevel@tonic-gate 	if (slpv2_url(x) < 0) \
561*7c478bd9Sstevel@tonic-gate 		return (0)
562*7c478bd9Sstevel@tonic-gate 
563*7c478bd9Sstevel@tonic-gate #define	V2_DOERRCODE \
564*7c478bd9Sstevel@tonic-gate 	if (msglength < sizeof (unsigned short)) \
565*7c478bd9Sstevel@tonic-gate 		return (0); \
566*7c478bd9Sstevel@tonic-gate 	nbtohs(); \
567*7c478bd9Sstevel@tonic-gate 	errcode = netval; \
568*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0), "Error code = %d, %s", \
569*7c478bd9Sstevel@tonic-gate 				errcode, slpv2_error(errcode)); \
570*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short); \
571*7c478bd9Sstevel@tonic-gate 	msglength -= sizeof (unsigned short); \
572*7c478bd9Sstevel@tonic-gate 	if (errcode != OK) \
573*7c478bd9Sstevel@tonic-gate 		msglength = 0;	/* skip rest of message */ \
574*7c478bd9Sstevel@tonic-gate 	if (errcode != OK) \
575*7c478bd9Sstevel@tonic-gate 		return (0)
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate #define	V2_DOAUTH(cnt) \
578*7c478bd9Sstevel@tonic-gate 	if (slpv2_authblock(cnt) < 0) \
579*7c478bd9Sstevel@tonic-gate 		return (0)
580*7c478bd9Sstevel@tonic-gate 
581*7c478bd9Sstevel@tonic-gate #define	V2_DOTIMESTAMP \
582*7c478bd9Sstevel@tonic-gate 	if (msglength < 4) \
583*7c478bd9Sstevel@tonic-gate 		return (0); \
584*7c478bd9Sstevel@tonic-gate 	nbtohl(); \
585*7c478bd9Sstevel@tonic-gate 	timestamp = netval; \
586*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0), "Timestamp = %u, %s", \
587*7c478bd9Sstevel@tonic-gate 		timestamp, (timestamp ? convert_ts(timestamp) : "0")); \
588*7c478bd9Sstevel@tonic-gate 	p += 4; \
589*7c478bd9Sstevel@tonic-gate 	msglength -= 4
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate /* some V1 macros */
592*7c478bd9Sstevel@tonic-gate #define	SKIPAUTH(auth) \
593*7c478bd9Sstevel@tonic-gate 	if (auth && ((retlength = skip_v1authblock()) < 0)) \
594*7c478bd9Sstevel@tonic-gate 		return (0)
595*7c478bd9Sstevel@tonic-gate 
596*7c478bd9Sstevel@tonic-gate #define	DOERRCODE \
597*7c478bd9Sstevel@tonic-gate 	if (msglength < sizeof (unsigned short)) \
598*7c478bd9Sstevel@tonic-gate 		return (0); \
599*7c478bd9Sstevel@tonic-gate 	nbtohs(); \
600*7c478bd9Sstevel@tonic-gate 	errcode = netval; \
601*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0), "Error code = %d, %s", errcode, \
602*7c478bd9Sstevel@tonic-gate 				slpv1_error(errcode)); \
603*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short); \
604*7c478bd9Sstevel@tonic-gate 	msglength -= sizeof (unsigned short); \
605*7c478bd9Sstevel@tonic-gate 	if (errcode != OK) \
606*7c478bd9Sstevel@tonic-gate 		return (0)
607*7c478bd9Sstevel@tonic-gate 
608*7c478bd9Sstevel@tonic-gate #define	DOURL \
609*7c478bd9Sstevel@tonic-gate 	if (slpv1_url(url_auth) < 0) \
610*7c478bd9Sstevel@tonic-gate 		return (0)
611*7c478bd9Sstevel@tonic-gate 
612*7c478bd9Sstevel@tonic-gate #define	DOAUTH(auth) \
613*7c478bd9Sstevel@tonic-gate 	if (auth && slpv1_authblock() < 0) \
614*7c478bd9Sstevel@tonic-gate 		return (0)
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate /*
617*7c478bd9Sstevel@tonic-gate  * TCP Continuation handling
618*7c478bd9Sstevel@tonic-gate  * We keep track of continuations in a fixed size cache, so as to prevent
619*7c478bd9Sstevel@tonic-gate  * memory leaks if some continuations are never finished. The continuations
620*7c478bd9Sstevel@tonic-gate  * are indexed by their destination ports.
621*7c478bd9Sstevel@tonic-gate  */
622*7c478bd9Sstevel@tonic-gate static void reg_tcp_cont(char *msg, int totallen,
623*7c478bd9Sstevel@tonic-gate 			    int fraglen, int dst_port) {
624*7c478bd9Sstevel@tonic-gate 	struct tcp_cont *tce = malloc(sizeof (*tce));
625*7c478bd9Sstevel@tonic-gate 
626*7c478bd9Sstevel@tonic-gate 	/* always overwrite the entry at current_tcp_cont */
627*7c478bd9Sstevel@tonic-gate 	if (tcp_cont[current_tcp_cont]) {
628*7c478bd9Sstevel@tonic-gate 	    free(tcp_cont[current_tcp_cont]->msg);
629*7c478bd9Sstevel@tonic-gate 	    free(tcp_cont[current_tcp_cont]);
630*7c478bd9Sstevel@tonic-gate 	}
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 	tce->dst_port = dst_port;
633*7c478bd9Sstevel@tonic-gate 	tce->msg = malloc(totallen);
634*7c478bd9Sstevel@tonic-gate 	memcpy(tce->msg, msg, fraglen);
635*7c478bd9Sstevel@tonic-gate 	tce->totallen = totallen;
636*7c478bd9Sstevel@tonic-gate 	tce->curr_offset = fraglen;
637*7c478bd9Sstevel@tonic-gate 
638*7c478bd9Sstevel@tonic-gate 	tcp_cont[current_tcp_cont++] = tce;
639*7c478bd9Sstevel@tonic-gate 	if (current_tcp_cont == MAX_TCPCONT)
640*7c478bd9Sstevel@tonic-gate 	    current_tcp_cont = 0;
641*7c478bd9Sstevel@tonic-gate }
642*7c478bd9Sstevel@tonic-gate 
643*7c478bd9Sstevel@tonic-gate /* returns 0 if there is a mismatch error, 1 on success */
644*7c478bd9Sstevel@tonic-gate static int add_tcp_cont(struct tcp_cont *tce, char *msg, int fraglen) {
645*7c478bd9Sstevel@tonic-gate 	if ((fraglen + tce->curr_offset) > tce->totallen)
646*7c478bd9Sstevel@tonic-gate 	    return (0);
647*7c478bd9Sstevel@tonic-gate 
648*7c478bd9Sstevel@tonic-gate 	memcpy(tce->msg + tce->curr_offset, msg, fraglen);
649*7c478bd9Sstevel@tonic-gate 	tce->curr_offset += fraglen;
650*7c478bd9Sstevel@tonic-gate 	return (1);
651*7c478bd9Sstevel@tonic-gate }
652*7c478bd9Sstevel@tonic-gate 
653*7c478bd9Sstevel@tonic-gate static struct tcp_cont *find_tcp_cont(int dst_port) {
654*7c478bd9Sstevel@tonic-gate 	int i;
655*7c478bd9Sstevel@tonic-gate 	for (i = current_tcp_cont; i >= 0; i--)
656*7c478bd9Sstevel@tonic-gate 	    if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port)
657*7c478bd9Sstevel@tonic-gate 		return (tcp_cont[i]);
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	for (i = MAX_TCPCONT -1; i > current_tcp_cont; i--)
660*7c478bd9Sstevel@tonic-gate 	    if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port)
661*7c478bd9Sstevel@tonic-gate 		return (tcp_cont[i]);
662*7c478bd9Sstevel@tonic-gate 
663*7c478bd9Sstevel@tonic-gate 	return (NULL);
664*7c478bd9Sstevel@tonic-gate }
665*7c478bd9Sstevel@tonic-gate 
666*7c478bd9Sstevel@tonic-gate static void remove_tcp_cont(int dst_port) {
667*7c478bd9Sstevel@tonic-gate 	int i;
668*7c478bd9Sstevel@tonic-gate 	for (i = current_tcp_cont; i >= 0; i--)
669*7c478bd9Sstevel@tonic-gate 	    if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) {
670*7c478bd9Sstevel@tonic-gate 		free(tcp_cont[i]->msg);
671*7c478bd9Sstevel@tonic-gate 		free(tcp_cont[i]);
672*7c478bd9Sstevel@tonic-gate 		tcp_cont[i] = NULL;
673*7c478bd9Sstevel@tonic-gate 		return;
674*7c478bd9Sstevel@tonic-gate 	    }
675*7c478bd9Sstevel@tonic-gate 
676*7c478bd9Sstevel@tonic-gate 	for (i = MAX_TCPCONT -1; i > current_tcp_cont; i--)
677*7c478bd9Sstevel@tonic-gate 	    if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) {
678*7c478bd9Sstevel@tonic-gate 		free(tcp_cont[i]->msg);
679*7c478bd9Sstevel@tonic-gate 		free(tcp_cont[i]);
680*7c478bd9Sstevel@tonic-gate 		tcp_cont[i] = NULL;
681*7c478bd9Sstevel@tonic-gate 		return;
682*7c478bd9Sstevel@tonic-gate 	    }
683*7c478bd9Sstevel@tonic-gate }
684*7c478bd9Sstevel@tonic-gate 
685*7c478bd9Sstevel@tonic-gate /*
686*7c478bd9Sstevel@tonic-gate  * V2 interpreter
687*7c478bd9Sstevel@tonic-gate  */
688*7c478bd9Sstevel@tonic-gate 
689*7c478bd9Sstevel@tonic-gate static int interpret_slp_v2(int flags, struct slpv2_hdr *slp, int fraglen) {
690*7c478bd9Sstevel@tonic-gate 	extern int src_port, dst_port, curr_proto;
691*7c478bd9Sstevel@tonic-gate 	char msgbuf_real[256];
692*7c478bd9Sstevel@tonic-gate 	int totallen = 0;
693*7c478bd9Sstevel@tonic-gate 
694*7c478bd9Sstevel@tonic-gate 	msgbuf = msgbuf_real;
695*7c478bd9Sstevel@tonic-gate 
696*7c478bd9Sstevel@tonic-gate 	/*
697*7c478bd9Sstevel@tonic-gate 	 * Somewhat of a hack to decode traffic from a server that does
698*7c478bd9Sstevel@tonic-gate 	 * not send udp replies from its SLP src port.
699*7c478bd9Sstevel@tonic-gate 	 */
700*7c478bd9Sstevel@tonic-gate 
701*7c478bd9Sstevel@tonic-gate 	if (curr_proto == IPPROTO_UDP &&
702*7c478bd9Sstevel@tonic-gate 	    dst_port == 427 &&
703*7c478bd9Sstevel@tonic-gate 	    src_port != 427) {
704*7c478bd9Sstevel@tonic-gate 	    add_transient(src_port, (int (*)())interpret_slp);
705*7c478bd9Sstevel@tonic-gate 	}
706*7c478bd9Sstevel@tonic-gate 
707*7c478bd9Sstevel@tonic-gate 	/* parse the header */
708*7c478bd9Sstevel@tonic-gate 	if (v2_header(flags, slp, &totallen, fraglen)) {
709*7c478bd9Sstevel@tonic-gate 
710*7c478bd9Sstevel@tonic-gate 	    if (slp->function <= V2_MAX_FUNCTION && slp->function > 0) {
711*7c478bd9Sstevel@tonic-gate 
712*7c478bd9Sstevel@tonic-gate 		/* Parse the message body */
713*7c478bd9Sstevel@tonic-gate 		if ((v2_functions[slp->function])(flags)) {
714*7c478bd9Sstevel@tonic-gate 
715*7c478bd9Sstevel@tonic-gate 		    /* finish any remaining tasks */
716*7c478bd9Sstevel@tonic-gate 		    v2_finish(slp, flags);
717*7c478bd9Sstevel@tonic-gate 
718*7c478bd9Sstevel@tonic-gate 		}
719*7c478bd9Sstevel@tonic-gate 
720*7c478bd9Sstevel@tonic-gate 	    }
721*7c478bd9Sstevel@tonic-gate 
722*7c478bd9Sstevel@tonic-gate 	}
723*7c478bd9Sstevel@tonic-gate 
724*7c478bd9Sstevel@tonic-gate 	/* summary error check */
725*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
726*7c478bd9Sstevel@tonic-gate 	    if (retlength < 0) {
727*7c478bd9Sstevel@tonic-gate 		if (curr_proto == IPPROTO_TCP)
728*7c478bd9Sstevel@tonic-gate 		    sprintf(get_sum_line(),
729*7c478bd9Sstevel@tonic-gate 			    "%s [partial TCP message]", msgbuf);
730*7c478bd9Sstevel@tonic-gate 		else if (overflow)
731*7c478bd9Sstevel@tonic-gate 		    sprintf(get_sum_line(), "%s [OVERFLOW]", msgbuf);
732*7c478bd9Sstevel@tonic-gate 		else
733*7c478bd9Sstevel@tonic-gate 		    sprintf(get_sum_line(), "%s [CORRUPTED MESSAGE]", msgbuf);
734*7c478bd9Sstevel@tonic-gate 	    }
735*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
736*7c478bd9Sstevel@tonic-gate 	    else if (msglength > 0)
737*7c478bd9Sstevel@tonic-gate 		sprintf(get_sum_line(), "%s +%d", msgbuf, msglength);
738*7c478bd9Sstevel@tonic-gate #endif
739*7c478bd9Sstevel@tonic-gate 	    else
740*7c478bd9Sstevel@tonic-gate 		sprintf(get_sum_line(), "%s", msgbuf);
741*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
742*7c478bd9Sstevel@tonic-gate 	    /* detailed error check */
743*7c478bd9Sstevel@tonic-gate 	    if (msglength > 0) {
744*7c478bd9Sstevel@tonic-gate 		if (tcp_continuation) {
745*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
746*7c478bd9Sstevel@tonic-gate 			    "[TCP Continuation, %d bytes remaining]",
747*7c478bd9Sstevel@tonic-gate 			    totallen - fraglen);
748*7c478bd9Sstevel@tonic-gate 		} else
749*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
750*7c478bd9Sstevel@tonic-gate 			"[%d extra bytes at end of SLP message]", msglength);
751*7c478bd9Sstevel@tonic-gate 	    }
752*7c478bd9Sstevel@tonic-gate 
753*7c478bd9Sstevel@tonic-gate 	    show_trailer();
754*7c478bd9Sstevel@tonic-gate 
755*7c478bd9Sstevel@tonic-gate 	    if (tcp_continuation && msglength == 0)
756*7c478bd9Sstevel@tonic-gate 		remove_tcp_cont(dst_port);
757*7c478bd9Sstevel@tonic-gate 	}
758*7c478bd9Sstevel@tonic-gate 
759*7c478bd9Sstevel@tonic-gate 	return (0);
760*7c478bd9Sstevel@tonic-gate }
761*7c478bd9Sstevel@tonic-gate 
762*7c478bd9Sstevel@tonic-gate static int v2_header(int flags,
763*7c478bd9Sstevel@tonic-gate 			struct slpv2_hdr *slp,
764*7c478bd9Sstevel@tonic-gate 			int *totallen,
765*7c478bd9Sstevel@tonic-gate 			int fraglen) {
766*7c478bd9Sstevel@tonic-gate 	extern int curr_proto, dst_port;
767*7c478bd9Sstevel@tonic-gate 	char *prototag = (curr_proto == IPPROTO_TCP ? "/tcp" : "");
768*7c478bd9Sstevel@tonic-gate 
769*7c478bd9Sstevel@tonic-gate 	if ((slp->flags & V2_OVERFLOW) == V2_OVERFLOW)
770*7c478bd9Sstevel@tonic-gate 	    overflow = B_TRUE;
771*7c478bd9Sstevel@tonic-gate 
772*7c478bd9Sstevel@tonic-gate 	/* summary mode header parsing */
773*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
774*7c478bd9Sstevel@tonic-gate 
775*7c478bd9Sstevel@tonic-gate 	    /* make sure we have at least a header */
776*7c478bd9Sstevel@tonic-gate 	    if (msglength < sizeof (*slp)) {
777*7c478bd9Sstevel@tonic-gate 		sprintf(get_sum_line(), "SLP V2 [Incomplete Header]");
778*7c478bd9Sstevel@tonic-gate 		return (0);
779*7c478bd9Sstevel@tonic-gate 	    }
780*7c478bd9Sstevel@tonic-gate 
781*7c478bd9Sstevel@tonic-gate 	    sprintf(msgbuf, "SLP V2 %s [%d%s] ",
782*7c478bd9Sstevel@tonic-gate 		    slpv2_func(slp->function, B_TRUE),
783*7c478bd9Sstevel@tonic-gate 		    ntohs(slp->xid), prototag);
784*7c478bd9Sstevel@tonic-gate 
785*7c478bd9Sstevel@tonic-gate 	    /* skip to end of header */
786*7c478bd9Sstevel@tonic-gate 	    msgend = msgbuf + strlen(msgbuf);
787*7c478bd9Sstevel@tonic-gate 	    msglength -= sizeof (*slp);
788*7c478bd9Sstevel@tonic-gate 	    p += sizeof (*slp);
789*7c478bd9Sstevel@tonic-gate 
790*7c478bd9Sstevel@tonic-gate 	    /* skip language tag */
791*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);
792*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
793*7c478bd9Sstevel@tonic-gate 	    char *lang;
794*7c478bd9Sstevel@tonic-gate 	    int len;
795*7c478bd9Sstevel@tonic-gate 
796*7c478bd9Sstevel@tonic-gate 	    /* detailed mode header parsing */
797*7c478bd9Sstevel@tonic-gate 	    show_header("SLP:  ", "Service Location Protocol (v2)", fraglen);
798*7c478bd9Sstevel@tonic-gate 	    show_space();
799*7c478bd9Sstevel@tonic-gate 
800*7c478bd9Sstevel@tonic-gate 	    if (msglength < sizeof (*slp)) {
801*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0), "==> Incomplete SLP header");
802*7c478bd9Sstevel@tonic-gate 		return (0);
803*7c478bd9Sstevel@tonic-gate 	    }
804*7c478bd9Sstevel@tonic-gate 
805*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Version = %d", slp->vers);
806*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Function = %d, %s",
807*7c478bd9Sstevel@tonic-gate 		    slp->function, slpv2_func(slp->function, B_FALSE));
808*7c478bd9Sstevel@tonic-gate 	    get_int24(&(slp->l1));
809*7c478bd9Sstevel@tonic-gate 	    *totallen = netval;
810*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Message length = %u", *totallen);
811*7c478bd9Sstevel@tonic-gate 	    /* check for TCP continuation */
812*7c478bd9Sstevel@tonic-gate 	    if (curr_proto == IPPROTO_TCP &&
813*7c478bd9Sstevel@tonic-gate 		*totallen > msglength &&
814*7c478bd9Sstevel@tonic-gate 		!tcp_continuation) {
815*7c478bd9Sstevel@tonic-gate 		tcp_continuation = B_TRUE;
816*7c478bd9Sstevel@tonic-gate 		reg_tcp_cont((char *)slp, *totallen, msglength, dst_port);
817*7c478bd9Sstevel@tonic-gate 	    }
818*7c478bd9Sstevel@tonic-gate 
819*7c478bd9Sstevel@tonic-gate 	    if (!tcp_continuation && *totallen != msglength) {
820*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
821*7c478bd9Sstevel@tonic-gate 			"  (Stated and on-the-wire lengths differ)");
822*7c478bd9Sstevel@tonic-gate 	    }
823*7c478bd9Sstevel@tonic-gate 	    /* flags */
824*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags);
825*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
826*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V2_OVERFLOW,
827*7c478bd9Sstevel@tonic-gate 			    "overflow", "no overflow"));
828*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
829*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V2_FRESH,
830*7c478bd9Sstevel@tonic-gate 			    "fresh registration", "no fresh registration"));
831*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
832*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V2_MCAST,
833*7c478bd9Sstevel@tonic-gate 			    "request multicast / broadcast", "unicast"));
834*7c478bd9Sstevel@tonic-gate 	    /* check reserved flags that must be zero */
835*7c478bd9Sstevel@tonic-gate 	    if ((slp->flags & 7) != 0) {
836*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
837*7c478bd9Sstevel@tonic-gate 			"      .... .xxx = %d (reserved flags nonzero)",
838*7c478bd9Sstevel@tonic-gate 			slp->flags & 7);
839*7c478bd9Sstevel@tonic-gate 	    }
840*7c478bd9Sstevel@tonic-gate 	    /* end of flags */
841*7c478bd9Sstevel@tonic-gate 
842*7c478bd9Sstevel@tonic-gate 	    /* language tag */
843*7c478bd9Sstevel@tonic-gate 	    p = (char *)slp + sizeof (*slp);
844*7c478bd9Sstevel@tonic-gate 	    msglength -= sizeof (*slp);
845*7c478bd9Sstevel@tonic-gate 	    GETSHORT(len);
846*7c478bd9Sstevel@tonic-gate 	    if (len > msglength) {
847*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
848*7c478bd9Sstevel@tonic-gate 			"Language Tag Length = %u [CORRUPT MESSAGE]",
849*7c478bd9Sstevel@tonic-gate 			len);
850*7c478bd9Sstevel@tonic-gate 		return (0);
851*7c478bd9Sstevel@tonic-gate 	    }
852*7c478bd9Sstevel@tonic-gate 
853*7c478bd9Sstevel@tonic-gate 	    lang = get_line(0, 0);
854*7c478bd9Sstevel@tonic-gate 	    strcpy(lang, "Language Tag = ");
855*7c478bd9Sstevel@tonic-gate 	    strncat(lang,  p, len);
856*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid));
857*7c478bd9Sstevel@tonic-gate 
858*7c478bd9Sstevel@tonic-gate 	    /* set msglength to remaining length of SLP message */
859*7c478bd9Sstevel@tonic-gate 	    p += len;
860*7c478bd9Sstevel@tonic-gate 	    msglength -= len;
861*7c478bd9Sstevel@tonic-gate 	}
862*7c478bd9Sstevel@tonic-gate 
863*7c478bd9Sstevel@tonic-gate 	return (1);
864*7c478bd9Sstevel@tonic-gate }
865*7c478bd9Sstevel@tonic-gate 
866*7c478bd9Sstevel@tonic-gate static int v2_finish(struct slpv2_hdr *slp, int flags) {
867*7c478bd9Sstevel@tonic-gate 	unsigned int firstop;
868*7c478bd9Sstevel@tonic-gate 
869*7c478bd9Sstevel@tonic-gate 	if (!(flags & F_DTAIL))
870*7c478bd9Sstevel@tonic-gate 	    return (1);
871*7c478bd9Sstevel@tonic-gate 
872*7c478bd9Sstevel@tonic-gate 	/* check for options */
873*7c478bd9Sstevel@tonic-gate 	get_int24(&(slp->o1));
874*7c478bd9Sstevel@tonic-gate 	firstop = netval;
875*7c478bd9Sstevel@tonic-gate 
876*7c478bd9Sstevel@tonic-gate 	if (firstop) {
877*7c478bd9Sstevel@tonic-gate 	    unsigned short op_id;
878*7c478bd9Sstevel@tonic-gate 	    unsigned short nextop;
879*7c478bd9Sstevel@tonic-gate 	    char *op_class;
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 	    for (;;) {
882*7c478bd9Sstevel@tonic-gate 		unsigned short real_oplen;
883*7c478bd9Sstevel@tonic-gate 
884*7c478bd9Sstevel@tonic-gate 		if (msglength < 4) {
885*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
886*7c478bd9Sstevel@tonic-gate 			    "Option expected but not present");
887*7c478bd9Sstevel@tonic-gate 		    return (0);
888*7c478bd9Sstevel@tonic-gate 		}
889*7c478bd9Sstevel@tonic-gate 
890*7c478bd9Sstevel@tonic-gate 		nbtohs();
891*7c478bd9Sstevel@tonic-gate 		op_id = netval;
892*7c478bd9Sstevel@tonic-gate 		p += sizeof (unsigned short);
893*7c478bd9Sstevel@tonic-gate 		msglength -= sizeof (unsigned short);
894*7c478bd9Sstevel@tonic-gate 		nbtohs();
895*7c478bd9Sstevel@tonic-gate 		nextop = netval;
896*7c478bd9Sstevel@tonic-gate 		p += sizeof (unsigned short);
897*7c478bd9Sstevel@tonic-gate 		msglength -= sizeof (unsigned short);
898*7c478bd9Sstevel@tonic-gate 
899*7c478bd9Sstevel@tonic-gate 		real_oplen = nextop ? nextop : msglength;
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate 		/* known options */
902*7c478bd9Sstevel@tonic-gate 		switch (op_id) {
903*7c478bd9Sstevel@tonic-gate 		case 1:
904*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
905*7c478bd9Sstevel@tonic-gate 			    "Option: Required Attribute Missing");
906*7c478bd9Sstevel@tonic-gate 		    DOFIELD("Template IDVer", FIELD_DEFAULT);
907*7c478bd9Sstevel@tonic-gate 		    DOFIELD("Required Attrs", FIELD_DEFAULT);
908*7c478bd9Sstevel@tonic-gate 		    break;
909*7c478bd9Sstevel@tonic-gate 		default:
910*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0), "Option: Unknown");
911*7c478bd9Sstevel@tonic-gate 		    p += (real_oplen - 4);
912*7c478bd9Sstevel@tonic-gate 		    msglength -= (real_oplen - 4);
913*7c478bd9Sstevel@tonic-gate 		    break;
914*7c478bd9Sstevel@tonic-gate 		}
915*7c478bd9Sstevel@tonic-gate 
916*7c478bd9Sstevel@tonic-gate 		if (op_id < 0x3fff)
917*7c478bd9Sstevel@tonic-gate 		    op_class = "Standardized, optional";
918*7c478bd9Sstevel@tonic-gate 		else if (op_id < 0x7fff)
919*7c478bd9Sstevel@tonic-gate 		    op_class = "Standardized, mandatory";
920*7c478bd9Sstevel@tonic-gate 		else if (op_id < 0x8fff)
921*7c478bd9Sstevel@tonic-gate 		    op_class = "Not standardized, private";
922*7c478bd9Sstevel@tonic-gate 		else if (op_id < 0xffff)
923*7c478bd9Sstevel@tonic-gate 		    op_class = "Reserved";
924*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0), "Option ID = 0x%04x, %s",
925*7c478bd9Sstevel@tonic-gate 			op_id, op_class);
926*7c478bd9Sstevel@tonic-gate 		if (nextop &&
927*7c478bd9Sstevel@tonic-gate 		    ((nextop - 4) > msglength) &&
928*7c478bd9Sstevel@tonic-gate 		    !tcp_continuation) {
929*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0),
930*7c478bd9Sstevel@tonic-gate 			    "[Framing error: remaining pkt length = %u]",
931*7c478bd9Sstevel@tonic-gate 			    msglength);
932*7c478bd9Sstevel@tonic-gate 		    return (0);
933*7c478bd9Sstevel@tonic-gate 		}
934*7c478bd9Sstevel@tonic-gate 
935*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0), "Option Length = %u", real_oplen);
936*7c478bd9Sstevel@tonic-gate 
937*7c478bd9Sstevel@tonic-gate 		if (!nextop)
938*7c478bd9Sstevel@tonic-gate 		    break;
939*7c478bd9Sstevel@tonic-gate 	    }
940*7c478bd9Sstevel@tonic-gate 	}
941*7c478bd9Sstevel@tonic-gate 
942*7c478bd9Sstevel@tonic-gate 	return (1);
943*7c478bd9Sstevel@tonic-gate }
944*7c478bd9Sstevel@tonic-gate 
945*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
946*7c478bd9Sstevel@tonic-gate static int skip_v2authblock() {
947*7c478bd9Sstevel@tonic-gate 	unsigned short length, slen;
948*7c478bd9Sstevel@tonic-gate 
949*7c478bd9Sstevel@tonic-gate 	/* auth header */
950*7c478bd9Sstevel@tonic-gate 	if (msglength < 10)
951*7c478bd9Sstevel@tonic-gate 	    return (-1);
952*7c478bd9Sstevel@tonic-gate 
953*7c478bd9Sstevel@tonic-gate 	/* block descriptor: 2 bytes */
954*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short);
955*7c478bd9Sstevel@tonic-gate 	/* length */
956*7c478bd9Sstevel@tonic-gate 	nbtohs();
957*7c478bd9Sstevel@tonic-gate 	length = netval;
958*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short);
959*7c478bd9Sstevel@tonic-gate 	/* timestamp */
960*7c478bd9Sstevel@tonic-gate 	p += 4;
961*7c478bd9Sstevel@tonic-gate 	/* SPI String length */
962*7c478bd9Sstevel@tonic-gate 	nbtohs();
963*7c478bd9Sstevel@tonic-gate 	slen = netval;
964*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short);
965*7c478bd9Sstevel@tonic-gate 
966*7c478bd9Sstevel@tonic-gate 	msglength -= 10;
967*7c478bd9Sstevel@tonic-gate 	if (slen > msglength || length > (msglength + 10))
968*7c478bd9Sstevel@tonic-gate 	    return (-1);
969*7c478bd9Sstevel@tonic-gate 
970*7c478bd9Sstevel@tonic-gate 	p += slen;
971*7c478bd9Sstevel@tonic-gate 	msglength -= slen;
972*7c478bd9Sstevel@tonic-gate 
973*7c478bd9Sstevel@tonic-gate 	/* structured auth block */
974*7c478bd9Sstevel@tonic-gate 	p += (length - 10 - slen);
975*7c478bd9Sstevel@tonic-gate 	msglength -= (length - 10 - slen);
976*7c478bd9Sstevel@tonic-gate 	return (0);
977*7c478bd9Sstevel@tonic-gate }
978*7c478bd9Sstevel@tonic-gate #endif
979*7c478bd9Sstevel@tonic-gate 
980*7c478bd9Sstevel@tonic-gate static char *display_bsd(unsigned short bsd) {
981*7c478bd9Sstevel@tonic-gate 	switch (bsd) {
982*7c478bd9Sstevel@tonic-gate 	case 1: return ("MD5 with RSA");
983*7c478bd9Sstevel@tonic-gate 	case 2: return ("DSA with SHA-1");
984*7c478bd9Sstevel@tonic-gate 	case 3: return ("Keyed HMAC with MD5");
985*7c478bd9Sstevel@tonic-gate 	default: return ("Unknown BSD");
986*7c478bd9Sstevel@tonic-gate 	}
987*7c478bd9Sstevel@tonic-gate }
988*7c478bd9Sstevel@tonic-gate 
989*7c478bd9Sstevel@tonic-gate static char *slpv2_func(int t, boolean_t s) {
990*7c478bd9Sstevel@tonic-gate 	static char buf[128];
991*7c478bd9Sstevel@tonic-gate 
992*7c478bd9Sstevel@tonic-gate 	switch (t) {
993*7c478bd9Sstevel@tonic-gate 	case V2_SRVRQST:	return s? "SrvRqst"  : "Service Request";
994*7c478bd9Sstevel@tonic-gate 	case V2_SRVRPLY:	return s? "SrvRply"  : "Service Reply";
995*7c478bd9Sstevel@tonic-gate 	case V2_SRVREG:		return s? "SrvReg"   : "Service Registration";
996*7c478bd9Sstevel@tonic-gate 	case V2_SRVDEREG:
997*7c478bd9Sstevel@tonic-gate 	    return (s ? "SrvDereg" : "Service Deregistration");
998*7c478bd9Sstevel@tonic-gate 	case V2_SRVACK:		return s? "SrvAck"   : "Service Acknowledge";
999*7c478bd9Sstevel@tonic-gate 	case V2_ATTRRQST:	return s? "AttrRqst" : "Attribute Request";
1000*7c478bd9Sstevel@tonic-gate 	case V2_ATTRRPLY:	return s? "AttrRply" : "Attribute Reply";
1001*7c478bd9Sstevel@tonic-gate 	case V2_DAADVERT:	return s? "DAAdvert" : "DA advertisement";
1002*7c478bd9Sstevel@tonic-gate 	case V2_SRVTYPERQST:
1003*7c478bd9Sstevel@tonic-gate 	    return (s ? "SrvTypeRqst" : "Service Type Request");
1004*7c478bd9Sstevel@tonic-gate 	case V2_SRVTYPERPLY:
1005*7c478bd9Sstevel@tonic-gate 	    return (s ? "SrvTypeRply" : "Service Type Reply");
1006*7c478bd9Sstevel@tonic-gate 	case V2_SAADVERT:	return s? "SAAdvert" : "SA advertisement";
1007*7c478bd9Sstevel@tonic-gate 	}
1008*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "(func %d)", t);
1009*7c478bd9Sstevel@tonic-gate 	return (s ? buf : "unknown function");
1010*7c478bd9Sstevel@tonic-gate }
1011*7c478bd9Sstevel@tonic-gate 
1012*7c478bd9Sstevel@tonic-gate static char *slpv2_error(unsigned short code) {
1013*7c478bd9Sstevel@tonic-gate 	static char buf[128];
1014*7c478bd9Sstevel@tonic-gate 
1015*7c478bd9Sstevel@tonic-gate 	switch (code) {
1016*7c478bd9Sstevel@tonic-gate 	case OK:			return "ok";
1017*7c478bd9Sstevel@tonic-gate 	case LANG_NOT_SUPPORTED:	return "language not supported";
1018*7c478bd9Sstevel@tonic-gate 	case PROTOCOL_PARSE_ERR:	return "protocol parse error";
1019*7c478bd9Sstevel@tonic-gate 	case INVALID_REGISTRATION:	return "invalid registration";
1020*7c478bd9Sstevel@tonic-gate 	case SCOPE_NOT_SUPPORTED:	return "scope not supported";
1021*7c478bd9Sstevel@tonic-gate 	case AUTHENTICATION_UNKNOWN:	return "authentication unknown";
1022*7c478bd9Sstevel@tonic-gate 	case V2_AUTHENTICATION_ABSENT:	return "authentication absent";
1023*7c478bd9Sstevel@tonic-gate 	case V2_AUTHENTICATION_FAILED:	return "authentication failed";
1024*7c478bd9Sstevel@tonic-gate 	case V2_VER_NOT_SUPPORTED:	return "version not supported";
1025*7c478bd9Sstevel@tonic-gate 	case V2_INTERNAL_ERROR:		return "internal error";
1026*7c478bd9Sstevel@tonic-gate 	case V2_DA_BUSY_NOW:		return "DA busy";
1027*7c478bd9Sstevel@tonic-gate 	case V2_OPTION_NOT_UNDERSTOOD:	return "option not understood";
1028*7c478bd9Sstevel@tonic-gate 	case V2_INVALID_UPDATE:		return "invalid update";
1029*7c478bd9Sstevel@tonic-gate 	case V2_RQST_NOT_SUPPORTED:	return "request not supported";
1030*7c478bd9Sstevel@tonic-gate 	case INVALID_LIFETIME:		return "invalid lifetime";
1031*7c478bd9Sstevel@tonic-gate 	}
1032*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "error %d", code);
1033*7c478bd9Sstevel@tonic-gate 	return (buf);
1034*7c478bd9Sstevel@tonic-gate }
1035*7c478bd9Sstevel@tonic-gate 
1036*7c478bd9Sstevel@tonic-gate static char *convert_ts(unsigned int timestamp) {
1037*7c478bd9Sstevel@tonic-gate 	/* timestamp is in UNIX time */
1038*7c478bd9Sstevel@tonic-gate 	static char buff[128];
1039*7c478bd9Sstevel@tonic-gate 
1040*7c478bd9Sstevel@tonic-gate 	strcpy(buff, ctime((time_t *)&timestamp));
1041*7c478bd9Sstevel@tonic-gate 	buff[strlen(buff) - 1] = '\0';
1042*7c478bd9Sstevel@tonic-gate 	return (buff);
1043*7c478bd9Sstevel@tonic-gate }
1044*7c478bd9Sstevel@tonic-gate 
1045*7c478bd9Sstevel@tonic-gate static int slpv2_authblock(int cnt) {
1046*7c478bd9Sstevel@tonic-gate 	unsigned short bsd, length, slen;
1047*7c478bd9Sstevel@tonic-gate 	char *pp, *scopes;
1048*7c478bd9Sstevel@tonic-gate 	unsigned int timestamp;
1049*7c478bd9Sstevel@tonic-gate 
1050*7c478bd9Sstevel@tonic-gate 	if (msglength < 10) {
1051*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
1052*7c478bd9Sstevel@tonic-gate 		"  [no room for auth block header: remaining msg length = %u]",
1053*7c478bd9Sstevel@tonic-gate 		    msglength);
1054*7c478bd9Sstevel@tonic-gate 	    return (-1);
1055*7c478bd9Sstevel@tonic-gate 	}
1056*7c478bd9Sstevel@tonic-gate 
1057*7c478bd9Sstevel@tonic-gate 	/* bsd */
1058*7c478bd9Sstevel@tonic-gate 	nbtohs();
1059*7c478bd9Sstevel@tonic-gate 	bsd = netval;
1060*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short);
1061*7c478bd9Sstevel@tonic-gate 
1062*7c478bd9Sstevel@tonic-gate 	/* length */
1063*7c478bd9Sstevel@tonic-gate 	nbtohs();
1064*7c478bd9Sstevel@tonic-gate 	length = netval;
1065*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short);
1066*7c478bd9Sstevel@tonic-gate 
1067*7c478bd9Sstevel@tonic-gate 	/* timestamp */
1068*7c478bd9Sstevel@tonic-gate 	nbtohl();
1069*7c478bd9Sstevel@tonic-gate 	timestamp = netval;
1070*7c478bd9Sstevel@tonic-gate 	p += 4;
1071*7c478bd9Sstevel@tonic-gate 
1072*7c478bd9Sstevel@tonic-gate 	/* SPI String length */
1073*7c478bd9Sstevel@tonic-gate 	nbtohs();
1074*7c478bd9Sstevel@tonic-gate 	slen = netval;
1075*7c478bd9Sstevel@tonic-gate 	p += sizeof (unsigned short);
1076*7c478bd9Sstevel@tonic-gate 
1077*7c478bd9Sstevel@tonic-gate 	msglength -= 10;
1078*7c478bd9Sstevel@tonic-gate 	if (slen > msglength) {
1079*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
1080*7c478bd9Sstevel@tonic-gate 		"  [no room for auth block scopes: remaining msg length = %u]",
1081*7c478bd9Sstevel@tonic-gate 		    msglength);
1082*7c478bd9Sstevel@tonic-gate 	    return (-1);
1083*7c478bd9Sstevel@tonic-gate 	}
1084*7c478bd9Sstevel@tonic-gate 
1085*7c478bd9Sstevel@tonic-gate 	if (length > (msglength + 10)) {
1086*7c478bd9Sstevel@tonic-gate 	    if (!tcp_continuation)
1087*7c478bd9Sstevel@tonic-gate 		/* framing error: message is not long enough to contain data */
1088*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
1089*7c478bd9Sstevel@tonic-gate 			"  [Framing error: remaining pkt length = %u]",
1090*7c478bd9Sstevel@tonic-gate 			msglength);
1091*7c478bd9Sstevel@tonic-gate 	    return (-1);
1092*7c478bd9Sstevel@tonic-gate 	}
1093*7c478bd9Sstevel@tonic-gate 
1094*7c478bd9Sstevel@tonic-gate 	scopes = p;
1095*7c478bd9Sstevel@tonic-gate 	p += slen;
1096*7c478bd9Sstevel@tonic-gate 	msglength -= slen;
1097*7c478bd9Sstevel@tonic-gate 
1098*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0),
1099*7c478bd9Sstevel@tonic-gate 	    "Auth block %d: timestamp = %s", cnt,
1100*7c478bd9Sstevel@tonic-gate 	    (timestamp) ? convert_ts(timestamp) : "0");
1101*7c478bd9Sstevel@tonic-gate 
1102*7c478bd9Sstevel@tonic-gate 	pp = get_line(0, 0);
1103*7c478bd9Sstevel@tonic-gate 	strcpy(pp, "              SPI = ");
1104*7c478bd9Sstevel@tonic-gate 	strncat(pp, scopes, slen);
1105*7c478bd9Sstevel@tonic-gate 
1106*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0),
1107*7c478bd9Sstevel@tonic-gate 	    "              block desc = 0x%04x: %s", bsd, display_bsd(bsd));
1108*7c478bd9Sstevel@tonic-gate 
1109*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0), "              length = %u", length);
1110*7c478bd9Sstevel@tonic-gate 
1111*7c478bd9Sstevel@tonic-gate 	p += (length - 10 - slen);
1112*7c478bd9Sstevel@tonic-gate 	msglength -= (length - 10 - slen);
1113*7c478bd9Sstevel@tonic-gate 	return (0);
1114*7c478bd9Sstevel@tonic-gate }
1115*7c478bd9Sstevel@tonic-gate 
1116*7c478bd9Sstevel@tonic-gate static int v2_srv_rqst(int flags) {
1117*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1118*7c478bd9Sstevel@tonic-gate 		SKIPFIELD(FIELD_DEFAULT);	/* PR list */
1119*7c478bd9Sstevel@tonic-gate 		GETFIELD;			/* service type */
1120*7c478bd9Sstevel@tonic-gate 		SKIPFIELD(FIELD_DEFAULT);	/* scopes */
1121*7c478bd9Sstevel@tonic-gate 		strcat(msgend, " [");
1122*7c478bd9Sstevel@tonic-gate 		GETFIELD;			/* predicate */
1123*7c478bd9Sstevel@tonic-gate 		strcat(msgend, "]");
1124*7c478bd9Sstevel@tonic-gate 		SKIPFIELD(FIELD_DEFAULT);	/* SPI */
1125*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1126*7c478bd9Sstevel@tonic-gate 		DOFIELD("Previous responders", FIELD_DEFAULT);
1127*7c478bd9Sstevel@tonic-gate 		DOFIELD("Service type",  FIELD_DEFAULT);
1128*7c478bd9Sstevel@tonic-gate 		DOFIELD("Scopes",  FIELD_DEFAULT);
1129*7c478bd9Sstevel@tonic-gate 		DOFIELD("Predicate string",  FIELD_DEFAULT);
1130*7c478bd9Sstevel@tonic-gate 		DOFIELD("Requested SPI", FIELD_DEFAULT);
1131*7c478bd9Sstevel@tonic-gate 	}
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate 	return (1);
1134*7c478bd9Sstevel@tonic-gate }
1135*7c478bd9Sstevel@tonic-gate 
1136*7c478bd9Sstevel@tonic-gate static int v2_srv_rply(int flags) {
1137*7c478bd9Sstevel@tonic-gate 	unsigned short itemcnt, errcode;
1138*7c478bd9Sstevel@tonic-gate 	int n;
1139*7c478bd9Sstevel@tonic-gate 
1140*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1141*7c478bd9Sstevel@tonic-gate 	    int i, auth_cnt;
1142*7c478bd9Sstevel@tonic-gate 
1143*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1144*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK) {
1145*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv2_error(errcode));
1146*7c478bd9Sstevel@tonic-gate 		msglength = 0;	/* skip rest of message */
1147*7c478bd9Sstevel@tonic-gate 		return (0);
1148*7c478bd9Sstevel@tonic-gate 	    } else {
1149*7c478bd9Sstevel@tonic-gate 		GETSHORT(itemcnt);
1150*7c478bd9Sstevel@tonic-gate 		sprintf(msgend, "%d URL entries", itemcnt);
1151*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1152*7c478bd9Sstevel@tonic-gate 		for (n = 0; n < itemcnt; n++) {
1153*7c478bd9Sstevel@tonic-gate 		    SKIPBYTE;			/* reserved */
1154*7c478bd9Sstevel@tonic-gate 		    SKIPSHORT;			/* lifetime */
1155*7c478bd9Sstevel@tonic-gate 		    SKIPFIELD(FIELD_DEFAULT);	/* URL */
1156*7c478bd9Sstevel@tonic-gate 		    GETBYTE(auth_cnt);
1157*7c478bd9Sstevel@tonic-gate 		    for (i = 0; i < auth_cnt; auth_cnt++)
1158*7c478bd9Sstevel@tonic-gate 			if (skip_v2authblock() < 0)
1159*7c478bd9Sstevel@tonic-gate 			    return (0);
1160*7c478bd9Sstevel@tonic-gate 		}
1161*7c478bd9Sstevel@tonic-gate #endif
1162*7c478bd9Sstevel@tonic-gate 	    }
1163*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1164*7c478bd9Sstevel@tonic-gate 	    V2_DOERRCODE;
1165*7c478bd9Sstevel@tonic-gate 	    GETSHORT(itemcnt);
1166*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "URL entry count = %d", itemcnt);
1167*7c478bd9Sstevel@tonic-gate 	    for (n = 0; n < itemcnt; n++) {
1168*7c478bd9Sstevel@tonic-gate 		V2_DOURL(n);
1169*7c478bd9Sstevel@tonic-gate 	    }
1170*7c478bd9Sstevel@tonic-gate 	}
1171*7c478bd9Sstevel@tonic-gate 
1172*7c478bd9Sstevel@tonic-gate 	return (1);
1173*7c478bd9Sstevel@tonic-gate }
1174*7c478bd9Sstevel@tonic-gate 
1175*7c478bd9Sstevel@tonic-gate static int v2_srv_reg(int flags) {
1176*7c478bd9Sstevel@tonic-gate 	int i, auth_cnt;
1177*7c478bd9Sstevel@tonic-gate 
1178*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1179*7c478bd9Sstevel@tonic-gate 	    SKIPBYTE;			/* reserved */
1180*7c478bd9Sstevel@tonic-gate 	    SKIPSHORT;			/* lifetime */
1181*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1182*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1183*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1184*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1185*7c478bd9Sstevel@tonic-gate 		if (skip_v2authblock() < 0)
1186*7c478bd9Sstevel@tonic-gate 		    return (0);
1187*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* type */
1188*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* scopes */
1189*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* attrs */
1190*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1191*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1192*7c478bd9Sstevel@tonic-gate 		if (skip_v2authblock() < 0)
1193*7c478bd9Sstevel@tonic-gate 		    return (0);
1194*7c478bd9Sstevel@tonic-gate #endif
1195*7c478bd9Sstevel@tonic-gate 	} if (flags & F_DTAIL) {
1196*7c478bd9Sstevel@tonic-gate 	    V2_DOURL(-1);
1197*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Service type", FIELD_DEFAULT);
1198*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scopes", FIELD_DEFAULT);
1199*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Attribute list", FIELD_DEFAULT);
1200*7c478bd9Sstevel@tonic-gate 	    /* auth */
1201*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1202*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1203*7c478bd9Sstevel@tonic-gate 		V2_DOAUTH(i);
1204*7c478bd9Sstevel@tonic-gate 	}
1205*7c478bd9Sstevel@tonic-gate 
1206*7c478bd9Sstevel@tonic-gate 	return (1);
1207*7c478bd9Sstevel@tonic-gate }
1208*7c478bd9Sstevel@tonic-gate 
1209*7c478bd9Sstevel@tonic-gate static int v2_srv_dereg(int flags) {
1210*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1211*7c478bd9Sstevel@tonic-gate 	    int i, auth_cnt;
1212*7c478bd9Sstevel@tonic-gate 
1213*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* scopes */
1214*7c478bd9Sstevel@tonic-gate 	    SKIPBYTE;			/* reserved */
1215*7c478bd9Sstevel@tonic-gate 	    SKIPSHORT;			/* lifetime */
1216*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1219*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1220*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1221*7c478bd9Sstevel@tonic-gate 		if (skip_v2authblock() < 0)
1222*7c478bd9Sstevel@tonic-gate 		    return (0);
1223*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* attrs */
1224*7c478bd9Sstevel@tonic-gate #endif
1225*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1226*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scopes", FIELD_DEFAULT);
1227*7c478bd9Sstevel@tonic-gate 	    V2_DOURL(-1);
1228*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Tag list",  FIELD_DEFAULT);
1229*7c478bd9Sstevel@tonic-gate 	}
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate 	return (1);
1232*7c478bd9Sstevel@tonic-gate }
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate static int v2_srv_ack(int flags) {
1235*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1236*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1237*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1238*7c478bd9Sstevel@tonic-gate 	    strcat(msgbuf, slpv2_error(errcode));
1239*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1240*7c478bd9Sstevel@tonic-gate 	    V2_DOERRCODE;
1241*7c478bd9Sstevel@tonic-gate 	}
1242*7c478bd9Sstevel@tonic-gate 
1243*7c478bd9Sstevel@tonic-gate 	return (1);
1244*7c478bd9Sstevel@tonic-gate }
1245*7c478bd9Sstevel@tonic-gate 
1246*7c478bd9Sstevel@tonic-gate static int v2_attr_rqst(int flags) {
1247*7c478bd9Sstevel@tonic-gate 	if (flags  & F_SUM) {
1248*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* PR list */
1249*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1250*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* scopes */
1251*7c478bd9Sstevel@tonic-gate 	    strcat(msgend, " [");
1252*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* attrs */
1253*7c478bd9Sstevel@tonic-gate 	    strcat(msgend, "]");
1254*7c478bd9Sstevel@tonic-gate 
1255*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1256*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* SPI */
1257*7c478bd9Sstevel@tonic-gate #endif
1258*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1259*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Previous responders", FIELD_DEFAULT);
1260*7c478bd9Sstevel@tonic-gate 	    DOFIELD("URL",  FIELD_DEFAULT);
1261*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scopes",  FIELD_DEFAULT);
1262*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Tag list",  FIELD_DEFAULT);
1263*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Requested SPI", FIELD_DEFAULT);
1264*7c478bd9Sstevel@tonic-gate 	}
1265*7c478bd9Sstevel@tonic-gate 
1266*7c478bd9Sstevel@tonic-gate 	return (1);
1267*7c478bd9Sstevel@tonic-gate }
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate static int v2_attr_rply(int flags) {
1270*7c478bd9Sstevel@tonic-gate 	int auth_cnt, i;
1271*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1272*7c478bd9Sstevel@tonic-gate 
1273*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1274*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1275*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK) {
1276*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv2_error(errcode));
1277*7c478bd9Sstevel@tonic-gate 		msglength = 0;	/* skip rest of message */
1278*7c478bd9Sstevel@tonic-gate 		return (0);
1279*7c478bd9Sstevel@tonic-gate 	    } else {
1280*7c478bd9Sstevel@tonic-gate 		GETFIELD;			/* attr list */
1281*7c478bd9Sstevel@tonic-gate 
1282*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1283*7c478bd9Sstevel@tonic-gate 		GETBYTE(auth_cnt);
1284*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < auth_cnt; i++)
1285*7c478bd9Sstevel@tonic-gate 		    if (skip_v2authblock() < 0)
1286*7c478bd9Sstevel@tonic-gate 			return (0);
1287*7c478bd9Sstevel@tonic-gate #endif
1288*7c478bd9Sstevel@tonic-gate 	    }
1289*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1290*7c478bd9Sstevel@tonic-gate 	    V2_DOERRCODE;
1291*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Attribute list", FIELD_DEFAULT);
1292*7c478bd9Sstevel@tonic-gate 	    /* auth */
1293*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1294*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1295*7c478bd9Sstevel@tonic-gate 		V2_DOAUTH(i);
1296*7c478bd9Sstevel@tonic-gate 	}
1297*7c478bd9Sstevel@tonic-gate 
1298*7c478bd9Sstevel@tonic-gate 	return (1);
1299*7c478bd9Sstevel@tonic-gate }
1300*7c478bd9Sstevel@tonic-gate 
1301*7c478bd9Sstevel@tonic-gate static int v2_daadvert(int flags) {
1302*7c478bd9Sstevel@tonic-gate 	int auth_cnt, i;
1303*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1304*7c478bd9Sstevel@tonic-gate 	unsigned int timestamp;
1305*7c478bd9Sstevel@tonic-gate 
1306*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1307*7c478bd9Sstevel@tonic-gate 	    SKIPSHORT;			/* error code */
1308*7c478bd9Sstevel@tonic-gate 	    SKIPSHORT; SKIPSHORT;	/* timestamp */
1309*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1310*7c478bd9Sstevel@tonic-gate 
1311*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1312*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* scopes */
1313*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* attrs */
1314*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* SPIs */
1315*7c478bd9Sstevel@tonic-gate 
1316*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1317*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1318*7c478bd9Sstevel@tonic-gate 		if (skip_v2authblock() < 0)
1319*7c478bd9Sstevel@tonic-gate 		    return (0);
1320*7c478bd9Sstevel@tonic-gate #endif
1321*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1322*7c478bd9Sstevel@tonic-gate 	    V2_DOERRCODE;
1323*7c478bd9Sstevel@tonic-gate 	    V2_DOTIMESTAMP;
1324*7c478bd9Sstevel@tonic-gate 	    DOFIELD("URL", FIELD_DEFAULT);
1325*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scope list", FIELD_DEFAULT);
1326*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Attribute list", FIELD_DEFAULT);
1327*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Configured SPIs", FIELD_DEFAULT);
1328*7c478bd9Sstevel@tonic-gate 	    /* auth */
1329*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1330*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1331*7c478bd9Sstevel@tonic-gate 		V2_DOAUTH(i);
1332*7c478bd9Sstevel@tonic-gate 	}
1333*7c478bd9Sstevel@tonic-gate 
1334*7c478bd9Sstevel@tonic-gate 	return (1);
1335*7c478bd9Sstevel@tonic-gate }
1336*7c478bd9Sstevel@tonic-gate 
1337*7c478bd9Sstevel@tonic-gate static int v2_srv_type_rqst(int flags) {
1338*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1339*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* prev responders */
1340*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_TYPENA);	/* naming authority */
1341*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* scope */
1342*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1343*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Previous responders", FIELD_DEFAULT);
1344*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Naming authority", FIELD_TYPENA);
1345*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scopes",  FIELD_DEFAULT);
1346*7c478bd9Sstevel@tonic-gate 	}
1347*7c478bd9Sstevel@tonic-gate 
1348*7c478bd9Sstevel@tonic-gate 	return (1);
1349*7c478bd9Sstevel@tonic-gate }
1350*7c478bd9Sstevel@tonic-gate 
1351*7c478bd9Sstevel@tonic-gate static int v2_srv_type_rply(int flags) {
1352*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1355*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1356*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK)
1357*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv2_error(errcode));
1358*7c478bd9Sstevel@tonic-gate 	    else
1359*7c478bd9Sstevel@tonic-gate 		GETFIELD;
1360*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1361*7c478bd9Sstevel@tonic-gate 		V2_DOERRCODE;
1362*7c478bd9Sstevel@tonic-gate 		DOFIELD("Service types", FIELD_DEFAULT);
1363*7c478bd9Sstevel@tonic-gate 	}
1364*7c478bd9Sstevel@tonic-gate 
1365*7c478bd9Sstevel@tonic-gate 	return (1);
1366*7c478bd9Sstevel@tonic-gate }
1367*7c478bd9Sstevel@tonic-gate 
1368*7c478bd9Sstevel@tonic-gate static int v2_saadvert(int flags) {
1369*7c478bd9Sstevel@tonic-gate 	int auth_cnt, i;
1370*7c478bd9Sstevel@tonic-gate 
1371*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1372*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1373*7c478bd9Sstevel@tonic-gate 
1374*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1375*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* scopes */
1376*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* attrs */
1377*7c478bd9Sstevel@tonic-gate 
1378*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1379*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1380*7c478bd9Sstevel@tonic-gate 		if (skip_v2authblock() < 0)
1381*7c478bd9Sstevel@tonic-gate 		    return (0);
1382*7c478bd9Sstevel@tonic-gate #endif
1383*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1384*7c478bd9Sstevel@tonic-gate 	    DOFIELD("URL", FIELD_DEFAULT);
1385*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scopes",  FIELD_DEFAULT);
1386*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Attribute list", FIELD_DEFAULT);
1387*7c478bd9Sstevel@tonic-gate 	    /* auth */
1388*7c478bd9Sstevel@tonic-gate 	    GETBYTE(auth_cnt);
1389*7c478bd9Sstevel@tonic-gate 	    for (i = 0; i < auth_cnt; i++)
1390*7c478bd9Sstevel@tonic-gate 		V2_DOAUTH(i);
1391*7c478bd9Sstevel@tonic-gate 	}
1392*7c478bd9Sstevel@tonic-gate 
1393*7c478bd9Sstevel@tonic-gate 	return (1);
1394*7c478bd9Sstevel@tonic-gate }
1395*7c478bd9Sstevel@tonic-gate 
1396*7c478bd9Sstevel@tonic-gate /*
1397*7c478bd9Sstevel@tonic-gate  * V1 Interpreter
1398*7c478bd9Sstevel@tonic-gate  */
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate static int interpret_slp_v1(int flags, struct slpv1_hdr *slp, int fraglen) {
1401*7c478bd9Sstevel@tonic-gate 	char msgbuf_real[256];
1402*7c478bd9Sstevel@tonic-gate 	extern int src_port, dst_port, curr_proto;
1403*7c478bd9Sstevel@tonic-gate 	boolean_t overflow	= B_FALSE;
1404*7c478bd9Sstevel@tonic-gate 
1405*7c478bd9Sstevel@tonic-gate 	msgbuf = msgbuf_real;
1406*7c478bd9Sstevel@tonic-gate 
1407*7c478bd9Sstevel@tonic-gate 	if (msglength >= sizeof (*slp)) {
1408*7c478bd9Sstevel@tonic-gate 	    if ((slp->flags & V1_URL_AUTH) == V1_URL_AUTH)
1409*7c478bd9Sstevel@tonic-gate 		url_auth = B_TRUE;
1410*7c478bd9Sstevel@tonic-gate 	    if ((slp->flags & V1_ATTR_AUTH) == V1_ATTR_AUTH)
1411*7c478bd9Sstevel@tonic-gate 		attr_auth = B_TRUE;
1412*7c478bd9Sstevel@tonic-gate 	    if ((slp->flags & V1_FRESH_REG) == V1_FRESH_REG)
1413*7c478bd9Sstevel@tonic-gate 		fresh = B_TRUE;
1414*7c478bd9Sstevel@tonic-gate 	    if ((slp->flags & V1_OVERFLOW) == V1_OVERFLOW)
1415*7c478bd9Sstevel@tonic-gate 		overflow = B_TRUE;
1416*7c478bd9Sstevel@tonic-gate 	}
1417*7c478bd9Sstevel@tonic-gate 
1418*7c478bd9Sstevel@tonic-gate 	/*
1419*7c478bd9Sstevel@tonic-gate 	 * Somewhat of a hack to decode traffic from a server that does
1420*7c478bd9Sstevel@tonic-gate 	 * not send udp replies from its SLP src port.
1421*7c478bd9Sstevel@tonic-gate 	 */
1422*7c478bd9Sstevel@tonic-gate 	if (curr_proto == IPPROTO_UDP &&
1423*7c478bd9Sstevel@tonic-gate 	    dst_port == 427 &&
1424*7c478bd9Sstevel@tonic-gate 	    src_port != 427)
1425*7c478bd9Sstevel@tonic-gate 		add_transient(src_port, (int (*)())interpret_slp);
1426*7c478bd9Sstevel@tonic-gate 
1427*7c478bd9Sstevel@tonic-gate 	/* parse the header */
1428*7c478bd9Sstevel@tonic-gate 	if (v1_header(flags, slp, fraglen)) {
1429*7c478bd9Sstevel@tonic-gate 
1430*7c478bd9Sstevel@tonic-gate 	    if (slp->function <= V1_MAX_FUNCTION && slp->function > 0) {
1431*7c478bd9Sstevel@tonic-gate 
1432*7c478bd9Sstevel@tonic-gate 		/* Parse the message body */
1433*7c478bd9Sstevel@tonic-gate 		(v1_functions[slp->function])(flags);
1434*7c478bd9Sstevel@tonic-gate 
1435*7c478bd9Sstevel@tonic-gate 	    }
1436*7c478bd9Sstevel@tonic-gate 
1437*7c478bd9Sstevel@tonic-gate 	}
1438*7c478bd9Sstevel@tonic-gate 
1439*7c478bd9Sstevel@tonic-gate 	/* summary error check */
1440*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1441*7c478bd9Sstevel@tonic-gate 	    if (retlength < 0) {
1442*7c478bd9Sstevel@tonic-gate 		if (curr_proto == IPPROTO_TCP)
1443*7c478bd9Sstevel@tonic-gate 		    sprintf(get_sum_line(),
1444*7c478bd9Sstevel@tonic-gate 			    "%s [partial TCP message]",
1445*7c478bd9Sstevel@tonic-gate 			    msgbuf);
1446*7c478bd9Sstevel@tonic-gate 		else if (overflow)
1447*7c478bd9Sstevel@tonic-gate 		    sprintf(get_sum_line(), "%s [OVERFLOW]", msgbuf);
1448*7c478bd9Sstevel@tonic-gate 		else
1449*7c478bd9Sstevel@tonic-gate 		    sprintf(get_sum_line(), "%s [CORRUPTED MESSAGE]", msgbuf);
1450*7c478bd9Sstevel@tonic-gate 	    }
1451*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1452*7c478bd9Sstevel@tonic-gate 	    else if (msglength > 0)
1453*7c478bd9Sstevel@tonic-gate 		sprintf(get_sum_line(), "%s +%d", msgbuf, msglength);
1454*7c478bd9Sstevel@tonic-gate #endif
1455*7c478bd9Sstevel@tonic-gate 	    else
1456*7c478bd9Sstevel@tonic-gate 		sprintf(get_sum_line(), "%s", msgbuf);
1457*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1458*7c478bd9Sstevel@tonic-gate 	    /* detail error check */
1459*7c478bd9Sstevel@tonic-gate 	    if (msglength > 0) {
1460*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
1461*7c478bd9Sstevel@tonic-gate 			"[%d extra bytes at end of SLP message]", msglength);
1462*7c478bd9Sstevel@tonic-gate 	    }
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	    show_trailer();
1465*7c478bd9Sstevel@tonic-gate 
1466*7c478bd9Sstevel@tonic-gate 	}
1467*7c478bd9Sstevel@tonic-gate 
1468*7c478bd9Sstevel@tonic-gate 	v1_charset = 0;
1469*7c478bd9Sstevel@tonic-gate 
1470*7c478bd9Sstevel@tonic-gate 	return (0);
1471*7c478bd9Sstevel@tonic-gate }
1472*7c478bd9Sstevel@tonic-gate 
1473*7c478bd9Sstevel@tonic-gate static int v1_header(int flags,
1474*7c478bd9Sstevel@tonic-gate 			struct slpv1_hdr *slp,
1475*7c478bd9Sstevel@tonic-gate 			int fraglen) {
1476*7c478bd9Sstevel@tonic-gate 	extern int src_port, dst_port, curr_proto;
1477*7c478bd9Sstevel@tonic-gate 	char *prototag = (curr_proto == IPPROTO_TCP? "/tcp" : "");
1478*7c478bd9Sstevel@tonic-gate 
1479*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1480*7c478bd9Sstevel@tonic-gate 	    char portflag = ' ';
1481*7c478bd9Sstevel@tonic-gate 
1482*7c478bd9Sstevel@tonic-gate 	    if (msglength < sizeof (*slp)) {
1483*7c478bd9Sstevel@tonic-gate 		sprintf(msgbuf, "SLP V1 [incomplete header]");
1484*7c478bd9Sstevel@tonic-gate 		return (0);
1485*7c478bd9Sstevel@tonic-gate 	    }
1486*7c478bd9Sstevel@tonic-gate 
1487*7c478bd9Sstevel@tonic-gate 	    if (slp->vers != 1) {
1488*7c478bd9Sstevel@tonic-gate 		if (curr_proto == IPPROTO_TCP)
1489*7c478bd9Sstevel@tonic-gate 		    sprintf(msgbuf, "SLP [TCP Continuation]");
1490*7c478bd9Sstevel@tonic-gate 		else
1491*7c478bd9Sstevel@tonic-gate 		    sprintf(msgbuf, "SLP [unknown version %d]", slp->vers);
1492*7c478bd9Sstevel@tonic-gate 		return (0);
1493*7c478bd9Sstevel@tonic-gate 	    }
1494*7c478bd9Sstevel@tonic-gate 
1495*7c478bd9Sstevel@tonic-gate 	    if (src_port != 427 && dst_port != 427)
1496*7c478bd9Sstevel@tonic-gate 		portflag = '-';
1497*7c478bd9Sstevel@tonic-gate 
1498*7c478bd9Sstevel@tonic-gate 	    sprintf(msgbuf, "SLP V1%c%s [%d%s] ", portflag,
1499*7c478bd9Sstevel@tonic-gate 		    slpv1_func(slp->function, B_TRUE),
1500*7c478bd9Sstevel@tonic-gate 		    ntohs(slp->xid), prototag);
1501*7c478bd9Sstevel@tonic-gate 	    msgend = msgbuf + strlen(msgbuf);
1502*7c478bd9Sstevel@tonic-gate 	    msglength -= sizeof (*slp);
1503*7c478bd9Sstevel@tonic-gate 	    p += sizeof (*slp);
1504*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1505*7c478bd9Sstevel@tonic-gate 	    show_header("SLP:  ", "Service Location Protocol (v1)", fraglen);
1506*7c478bd9Sstevel@tonic-gate 	    show_space();
1507*7c478bd9Sstevel@tonic-gate 
1508*7c478bd9Sstevel@tonic-gate 	    if (msglength < sizeof (*slp)) {
1509*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0), "==> Incomplete SLP header");
1510*7c478bd9Sstevel@tonic-gate 		return (0);
1511*7c478bd9Sstevel@tonic-gate 	    }
1512*7c478bd9Sstevel@tonic-gate 
1513*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Version = %d", slp->vers);
1514*7c478bd9Sstevel@tonic-gate 	    if (slp->vers != 1) {
1515*7c478bd9Sstevel@tonic-gate 		if (curr_proto == IPPROTO_TCP)
1516*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0), "==> TCP continuation");
1517*7c478bd9Sstevel@tonic-gate 		else
1518*7c478bd9Sstevel@tonic-gate 		    sprintf(get_line(0, 0), "==> Unexpected version number");
1519*7c478bd9Sstevel@tonic-gate 		return (0);
1520*7c478bd9Sstevel@tonic-gate 	    }
1521*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Function = %d, %s",
1522*7c478bd9Sstevel@tonic-gate 		slp->function, slpv1_func(slp->function, B_FALSE));
1523*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Message length = %u", ntohs(slp->length));
1524*7c478bd9Sstevel@tonic-gate 
1525*7c478bd9Sstevel@tonic-gate 	    /* flags */
1526*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags);
1527*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
1528*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V1_OVERFLOW,
1529*7c478bd9Sstevel@tonic-gate 			    "overflow", "no overflow"));
1530*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
1531*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V1_MONOLINGUAL,
1532*7c478bd9Sstevel@tonic-gate 			    "monolingual", "not monolingual"));
1533*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
1534*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V1_URL_AUTH,
1535*7c478bd9Sstevel@tonic-gate 			    "url authentication", "no url authentication"));
1536*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
1537*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V1_ATTR_AUTH,
1538*7c478bd9Sstevel@tonic-gate 		"attribute authentication", "no attribute authentication"));
1539*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "      %s",
1540*7c478bd9Sstevel@tonic-gate 		    getflag(slp->flags, V1_FRESH_REG,
1541*7c478bd9Sstevel@tonic-gate 			    "fresh registration", "no fresh registration"));
1542*7c478bd9Sstevel@tonic-gate 	    /* check reserved flags that must be zero */
1543*7c478bd9Sstevel@tonic-gate 	    if ((slp->flags & 7) != 0) {
1544*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0),
1545*7c478bd9Sstevel@tonic-gate 			"      .... .xxx = %d (reserved flags nonzero)",
1546*7c478bd9Sstevel@tonic-gate 			slp->flags & 7);
1547*7c478bd9Sstevel@tonic-gate 	    }
1548*7c478bd9Sstevel@tonic-gate 	    /* end of flags */
1549*7c478bd9Sstevel@tonic-gate 
1550*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Dialect = %u", slp->dialect);
1551*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Language = 0x%02x%02x, %c%c",
1552*7c478bd9Sstevel@tonic-gate 		    slp->language[0], slp->language[1],
1553*7c478bd9Sstevel@tonic-gate 		    slp->language[0], slp->language[1]);
1554*7c478bd9Sstevel@tonic-gate 	    v1_charset = ntohs(slp->charset);
1555*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Character encoding = %u, %s",
1556*7c478bd9Sstevel@tonic-gate 		    v1_charset,
1557*7c478bd9Sstevel@tonic-gate 		    slpv1_charset(v1_charset));
1558*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid));
1559*7c478bd9Sstevel@tonic-gate 
1560*7c478bd9Sstevel@tonic-gate 	    /* set msglength to remaining length of SLP message */
1561*7c478bd9Sstevel@tonic-gate 	    msglength -= sizeof (*slp);
1562*7c478bd9Sstevel@tonic-gate 	    p += sizeof (*slp);
1563*7c478bd9Sstevel@tonic-gate 	}
1564*7c478bd9Sstevel@tonic-gate 
1565*7c478bd9Sstevel@tonic-gate 	return (1);
1566*7c478bd9Sstevel@tonic-gate }
1567*7c478bd9Sstevel@tonic-gate 
1568*7c478bd9Sstevel@tonic-gate static char *slpv1_func(int t, boolean_t s) {
1569*7c478bd9Sstevel@tonic-gate 	static char buf[128];
1570*7c478bd9Sstevel@tonic-gate 	switch (t) {
1571*7c478bd9Sstevel@tonic-gate 	case V1_SRVREQ:	return s? "SrvRqst"  : "Service Request";
1572*7c478bd9Sstevel@tonic-gate 	case V1_SRVRPLY:	return s? "SrvRply"  : "Service Reply";
1573*7c478bd9Sstevel@tonic-gate 	case V1_SRVREG:	return s? "SrvReg"   : "Service Registration";
1574*7c478bd9Sstevel@tonic-gate 	case V1_SRVDEREG:	return s?
1575*7c478bd9Sstevel@tonic-gate 					"SrvDereg" : "Service Deregistration";
1576*7c478bd9Sstevel@tonic-gate 	case V1_SRVACK:	return s? "SrvAck"   : "Service Acknowledge";
1577*7c478bd9Sstevel@tonic-gate 	case V1_ATTRRQST:	return s? "AttrRqst" : "Attribute Request";
1578*7c478bd9Sstevel@tonic-gate 	case V1_ATTRRPLY:	return s? "AttrRply" : "Attribute Reply";
1579*7c478bd9Sstevel@tonic-gate 	case V1_DAADVERT:	return s? "DAAdvert" : "DA advertisement";
1580*7c478bd9Sstevel@tonic-gate 	case V1_SRVTYPERQST:return s? "SrvTypeRqst" : "Service Type Request";
1581*7c478bd9Sstevel@tonic-gate 	case V1_SRVTYPERPLY:return s? "SrvTypeRply" : "Service Type Reply";
1582*7c478bd9Sstevel@tonic-gate 	}
1583*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "(func %d)", t);
1584*7c478bd9Sstevel@tonic-gate 	return (s ? buf : "unknown function");
1585*7c478bd9Sstevel@tonic-gate }
1586*7c478bd9Sstevel@tonic-gate 
1587*7c478bd9Sstevel@tonic-gate static char *slpv1_error(unsigned short code) {
1588*7c478bd9Sstevel@tonic-gate 	static char buf[128];
1589*7c478bd9Sstevel@tonic-gate 
1590*7c478bd9Sstevel@tonic-gate 	switch (code) {
1591*7c478bd9Sstevel@tonic-gate 	    case OK:			return "ok";
1592*7c478bd9Sstevel@tonic-gate 	    case LANG_NOT_SUPPORTED:	return "language not supported";
1593*7c478bd9Sstevel@tonic-gate 	    case PROTOCOL_PARSE_ERR:	return "protocol parse error";
1594*7c478bd9Sstevel@tonic-gate 	    case INVALID_REGISTRATION:	return "invalid registration";
1595*7c478bd9Sstevel@tonic-gate 	    case SCOPE_NOT_SUPPORTED:	return "scope not supported";
1596*7c478bd9Sstevel@tonic-gate 	    case CHARSET_NOT_UNDERSTOOD:return "character set not understood";
1597*7c478bd9Sstevel@tonic-gate 	    case AUTHENTICATION_INVALID:return "invalid authentication";
1598*7c478bd9Sstevel@tonic-gate 	    case NOT_SUPPORTED_YET:	return "not yet supported";
1599*7c478bd9Sstevel@tonic-gate 	    case REQUEST_TIMED_OUT:	return "request timed out";
1600*7c478bd9Sstevel@tonic-gate 	    case COULD_NOT_INIT_NET_RESOURCES:
1601*7c478bd9Sstevel@tonic-gate 				return ("could not initialize net resources");
1602*7c478bd9Sstevel@tonic-gate 	    case COULD_NOT_ALLOCATE_MEMORY:
1603*7c478bd9Sstevel@tonic-gate 					return ("could not allocate memory");
1604*7c478bd9Sstevel@tonic-gate 	    case PARAMETER_BAD:		return "bad parameter";
1605*7c478bd9Sstevel@tonic-gate 	    case INTERNAL_NET_ERROR:	return "internal network error";
1606*7c478bd9Sstevel@tonic-gate 	    case INTERNAL_SYSTEM_ERROR:	return "internal system error";
1607*7c478bd9Sstevel@tonic-gate 	}
1608*7c478bd9Sstevel@tonic-gate 	sprintf(buf, "error %d", code);
1609*7c478bd9Sstevel@tonic-gate 	return (buf);
1610*7c478bd9Sstevel@tonic-gate }
1611*7c478bd9Sstevel@tonic-gate 
1612*7c478bd9Sstevel@tonic-gate /*
1613*7c478bd9Sstevel@tonic-gate  *  Character set info from
1614*7c478bd9Sstevel@tonic-gate  *    www.isi.edu/in-notes/iana/assignments/character-sets
1615*7c478bd9Sstevel@tonic-gate  *
1616*7c478bd9Sstevel@tonic-gate  *	Assigned MIB enum Numbers
1617*7c478bd9Sstevel@tonic-gate  *	-------------------------
1618*7c478bd9Sstevel@tonic-gate  *	0               Reserved
1619*7c478bd9Sstevel@tonic-gate  *	1               Reserved
1620*7c478bd9Sstevel@tonic-gate  *	3-106           Set By Standards Organizations
1621*7c478bd9Sstevel@tonic-gate  *	1000-1010       Unicode / 10646
1622*7c478bd9Sstevel@tonic-gate  *	2000-2087       Vendor
1623*7c478bd9Sstevel@tonic-gate  *	2250-2258       Vendor
1624*7c478bd9Sstevel@tonic-gate  *
1625*7c478bd9Sstevel@tonic-gate  *	MIBenum: 3
1626*7c478bd9Sstevel@tonic-gate  *	Alias: US-ASCII (preferred MIME name)
1627*7c478bd9Sstevel@tonic-gate  *	Source: ECMA registry [RFC1345]
1628*7c478bd9Sstevel@tonic-gate  *
1629*7c478bd9Sstevel@tonic-gate  *	MIBenum: 106
1630*7c478bd9Sstevel@tonic-gate  *	Name: UTF-8
1631*7c478bd9Sstevel@tonic-gate  *	Source: RFC 2044
1632*7c478bd9Sstevel@tonic-gate  */
1633*7c478bd9Sstevel@tonic-gate 
1634*7c478bd9Sstevel@tonic-gate static char *slpv1_charset(unsigned short code) {
1635*7c478bd9Sstevel@tonic-gate 	if (code <= 1)
1636*7c478bd9Sstevel@tonic-gate 	    return ("Reserved");
1637*7c478bd9Sstevel@tonic-gate 	if (code == 3)
1638*7c478bd9Sstevel@tonic-gate 	    return ("US-ASCII");
1639*7c478bd9Sstevel@tonic-gate 	if (code == 4)
1640*7c478bd9Sstevel@tonic-gate 	    return ("latin1");
1641*7c478bd9Sstevel@tonic-gate 	if (code == 106)
1642*7c478bd9Sstevel@tonic-gate 	    return ("UTF-8");
1643*7c478bd9Sstevel@tonic-gate 	if (code >= 3 && code <= 106)
1644*7c478bd9Sstevel@tonic-gate 	    return ("set by standards organization");
1645*7c478bd9Sstevel@tonic-gate 	if (code >= 1000 && code <= 1010)
1646*7c478bd9Sstevel@tonic-gate 	    return ("Unicode variant");
1647*7c478bd9Sstevel@tonic-gate 	if ((code >= 2000 && code <= 2087) ||
1648*7c478bd9Sstevel@tonic-gate 	    (code >= 2250 && code <= 2258))
1649*7c478bd9Sstevel@tonic-gate 	    return ("Vendor assigned");
1650*7c478bd9Sstevel@tonic-gate 
1651*7c478bd9Sstevel@tonic-gate 	return ("unknown");
1652*7c478bd9Sstevel@tonic-gate }
1653*7c478bd9Sstevel@tonic-gate 
1654*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1655*7c478bd9Sstevel@tonic-gate static int skip_v1authblock() {
1656*7c478bd9Sstevel@tonic-gate 	unsigned short length;
1657*7c478bd9Sstevel@tonic-gate 
1658*7c478bd9Sstevel@tonic-gate 	/* auth header: 12 bytes total */
1659*7c478bd9Sstevel@tonic-gate 	if (msglength < 12)
1660*7c478bd9Sstevel@tonic-gate 	    return (-1);
1661*7c478bd9Sstevel@tonic-gate 
1662*7c478bd9Sstevel@tonic-gate 	/* timestamp: 8 bytes */
1663*7c478bd9Sstevel@tonic-gate 	p += 8;			/* timestamp: 8 bytes */
1664*7c478bd9Sstevel@tonic-gate 	p += sizeof (short);		/* block descriptor: 2 bytes */
1665*7c478bd9Sstevel@tonic-gate 	nbtohs();
1666*7c478bd9Sstevel@tonic-gate 	length = netval;
1667*7c478bd9Sstevel@tonic-gate 	p += sizeof (short);
1668*7c478bd9Sstevel@tonic-gate 	msglength -= 12;
1669*7c478bd9Sstevel@tonic-gate 
1670*7c478bd9Sstevel@tonic-gate 	if (length > msglength) {
1671*7c478bd9Sstevel@tonic-gate 	    /* framing error: message is not long enough to contain data */
1672*7c478bd9Sstevel@tonic-gate 	    return (-1);
1673*7c478bd9Sstevel@tonic-gate 	}
1674*7c478bd9Sstevel@tonic-gate 
1675*7c478bd9Sstevel@tonic-gate 	p += length;
1676*7c478bd9Sstevel@tonic-gate 	msglength -= length;
1677*7c478bd9Sstevel@tonic-gate 	return (0);
1678*7c478bd9Sstevel@tonic-gate }
1679*7c478bd9Sstevel@tonic-gate #endif
1680*7c478bd9Sstevel@tonic-gate 
1681*7c478bd9Sstevel@tonic-gate static int slpv1_authblock() {
1682*7c478bd9Sstevel@tonic-gate 	unsigned short bsd, length;
1683*7c478bd9Sstevel@tonic-gate 	char msgbuf[128];
1684*7c478bd9Sstevel@tonic-gate 	int n;
1685*7c478bd9Sstevel@tonic-gate 
1686*7c478bd9Sstevel@tonic-gate 	if (msglength < 12) {
1687*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
1688*7c478bd9Sstevel@tonic-gate 		    "  [no room for auth block: remaining msg length = %u]",
1689*7c478bd9Sstevel@tonic-gate 		    msglength);
1690*7c478bd9Sstevel@tonic-gate 	    return (-1);
1691*7c478bd9Sstevel@tonic-gate 	}
1692*7c478bd9Sstevel@tonic-gate 
1693*7c478bd9Sstevel@tonic-gate 	/* timestamp: 8 bytes */
1694*7c478bd9Sstevel@tonic-gate 	*msgbuf = '\0';
1695*7c478bd9Sstevel@tonic-gate 	for (n = 0; n < 8; n++, p += 1) {
1696*7c478bd9Sstevel@tonic-gate 	    char tmp[16];
1697*7c478bd9Sstevel@tonic-gate 	    sprintf(tmp, "%02x", (unsigned char)(*p));
1698*7c478bd9Sstevel@tonic-gate 	    strcat(msgbuf, tmp);
1699*7c478bd9Sstevel@tonic-gate 	}
1700*7c478bd9Sstevel@tonic-gate 
1701*7c478bd9Sstevel@tonic-gate 	nbtohs();
1702*7c478bd9Sstevel@tonic-gate 	bsd = netval;
1703*7c478bd9Sstevel@tonic-gate 	p += sizeof (short);
1704*7c478bd9Sstevel@tonic-gate 	nbtohs();
1705*7c478bd9Sstevel@tonic-gate 	length = netval;
1706*7c478bd9Sstevel@tonic-gate 	p += sizeof (short);
1707*7c478bd9Sstevel@tonic-gate 	msglength -= 12;
1708*7c478bd9Sstevel@tonic-gate 
1709*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0),
1710*7c478bd9Sstevel@tonic-gate 		"  Auth block: timestamp = %s",
1711*7c478bd9Sstevel@tonic-gate 		msgbuf);
1712*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0),
1713*7c478bd9Sstevel@tonic-gate 		"              block desc = 0x%04x, length = %u",
1714*7c478bd9Sstevel@tonic-gate 		bsd, length);
1715*7c478bd9Sstevel@tonic-gate 	if (length > msglength) {
1716*7c478bd9Sstevel@tonic-gate 	    /* framing error: message is not long enough to contain data */
1717*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
1718*7c478bd9Sstevel@tonic-gate 		"  [Framing error: remaining pkt length = %u]",  msglength);
1719*7c478bd9Sstevel@tonic-gate 	    return (-1);
1720*7c478bd9Sstevel@tonic-gate 	}
1721*7c478bd9Sstevel@tonic-gate 
1722*7c478bd9Sstevel@tonic-gate 	p += length;
1723*7c478bd9Sstevel@tonic-gate 	msglength -= length;
1724*7c478bd9Sstevel@tonic-gate 	return (0);
1725*7c478bd9Sstevel@tonic-gate }
1726*7c478bd9Sstevel@tonic-gate 
1727*7c478bd9Sstevel@tonic-gate static int slpv1_url(boolean_t auth_present) {
1728*7c478bd9Sstevel@tonic-gate 	time_t exp;
1729*7c478bd9Sstevel@tonic-gate 	int lifetime, length;
1730*7c478bd9Sstevel@tonic-gate 
1731*7c478bd9Sstevel@tonic-gate 	get_short();
1732*7c478bd9Sstevel@tonic-gate 	if ((lifetime = netval) < 0)
1733*7c478bd9Sstevel@tonic-gate 	    return (-1);
1734*7c478bd9Sstevel@tonic-gate 	get_short();
1735*7c478bd9Sstevel@tonic-gate 	if ((length = netval) < 0)
1736*7c478bd9Sstevel@tonic-gate 	    return (-1);
1737*7c478bd9Sstevel@tonic-gate 
1738*7c478bd9Sstevel@tonic-gate 	exp = time(0) + lifetime;
1739*7c478bd9Sstevel@tonic-gate 	sprintf(get_line(0, 0), "URL: length = %u, lifetime = %d (%24.24s)",
1740*7c478bd9Sstevel@tonic-gate 		length, lifetime, ctime(&exp));
1741*7c478bd9Sstevel@tonic-gate 	if (length > msglength) {
1742*7c478bd9Sstevel@tonic-gate 	    /* framing error: message is not long enough to contain data */
1743*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0),
1744*7c478bd9Sstevel@tonic-gate 		"  [Framing error: remaining pkt length = %u]",  msglength);
1745*7c478bd9Sstevel@tonic-gate 	    return (-1);
1746*7c478bd9Sstevel@tonic-gate 	}
1747*7c478bd9Sstevel@tonic-gate 
1748*7c478bd9Sstevel@tonic-gate 	if (length > 0) {
1749*7c478bd9Sstevel@tonic-gate 	    char *buf = malloc(length + 1);
1750*7c478bd9Sstevel@tonic-gate 	    if (buf != NULL) {
1751*7c478bd9Sstevel@tonic-gate 		if (!make_utf8(buf, length, p, length)) {
1752*7c478bd9Sstevel@tonic-gate 			strcpy(buf, "[Invalid Character Encoding]");
1753*7c478bd9Sstevel@tonic-gate 		}
1754*7c478bd9Sstevel@tonic-gate 		sprintf(get_line(0, 0), "  \"%s\"", buf);
1755*7c478bd9Sstevel@tonic-gate 		free(buf);
1756*7c478bd9Sstevel@tonic-gate 	    }
1757*7c478bd9Sstevel@tonic-gate 	}
1758*7c478bd9Sstevel@tonic-gate 	msglength -= length;
1759*7c478bd9Sstevel@tonic-gate 	p += length;
1760*7c478bd9Sstevel@tonic-gate 
1761*7c478bd9Sstevel@tonic-gate 	if (auth_present)
1762*7c478bd9Sstevel@tonic-gate 	    return (slpv1_authblock());
1763*7c478bd9Sstevel@tonic-gate 
1764*7c478bd9Sstevel@tonic-gate 	return (0);
1765*7c478bd9Sstevel@tonic-gate }
1766*7c478bd9Sstevel@tonic-gate 
1767*7c478bd9Sstevel@tonic-gate static int v1_srv_rqst(int flags) {
1768*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1769*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_PREVRESP);	/* prev responders */
1770*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* predicate */
1771*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1772*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Previous responders", FIELD_PREVRESP);
1773*7c478bd9Sstevel@tonic-gate 	    DOFIELD("predicate string", FIELD_DEFAULT);
1774*7c478bd9Sstevel@tonic-gate 	}
1775*7c478bd9Sstevel@tonic-gate 
1776*7c478bd9Sstevel@tonic-gate 	return (1);
1777*7c478bd9Sstevel@tonic-gate }
1778*7c478bd9Sstevel@tonic-gate 
1779*7c478bd9Sstevel@tonic-gate static int v1_srv_rply(int flags) {
1780*7c478bd9Sstevel@tonic-gate 	unsigned short errcode, itemcnt;
1781*7c478bd9Sstevel@tonic-gate 	int n;
1782*7c478bd9Sstevel@tonic-gate 
1783*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1784*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1785*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK) {
1786*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv1_error(errcode));
1787*7c478bd9Sstevel@tonic-gate 	    } else {
1788*7c478bd9Sstevel@tonic-gate 		GETSHORT(itemcnt);
1789*7c478bd9Sstevel@tonic-gate 		sprintf(msgend, "%d URL entries", itemcnt);
1790*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1791*7c478bd9Sstevel@tonic-gate 		for (n = 0; n < itemcnt; n++) {
1792*7c478bd9Sstevel@tonic-gate 		    SKIPSHORT;		/* lifetime */
1793*7c478bd9Sstevel@tonic-gate 		    SKIPFIELD(FIELD_DEFAULT);	/* URL */
1794*7c478bd9Sstevel@tonic-gate 		    SKIPAUTH(url_auth);		/* URL auth */
1795*7c478bd9Sstevel@tonic-gate 		}
1796*7c478bd9Sstevel@tonic-gate #endif
1797*7c478bd9Sstevel@tonic-gate 	    }
1798*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1799*7c478bd9Sstevel@tonic-gate 	    DOERRCODE;
1800*7c478bd9Sstevel@tonic-gate 	    GETSHORT(itemcnt);
1801*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "URL entry count = %d", itemcnt);
1802*7c478bd9Sstevel@tonic-gate 	    for (n = 0; n < itemcnt; n++) {
1803*7c478bd9Sstevel@tonic-gate 		DOURL;
1804*7c478bd9Sstevel@tonic-gate 	    }
1805*7c478bd9Sstevel@tonic-gate 	}
1806*7c478bd9Sstevel@tonic-gate 
1807*7c478bd9Sstevel@tonic-gate 	return (1);
1808*7c478bd9Sstevel@tonic-gate }
1809*7c478bd9Sstevel@tonic-gate 
1810*7c478bd9Sstevel@tonic-gate static int v1_srv_reg(int flags) {
1811*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1812*7c478bd9Sstevel@tonic-gate 	    SKIPSHORT;			/* lifetime */
1813*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1814*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1815*7c478bd9Sstevel@tonic-gate 	    SKIPAUTH(url_auth);		/* URL auth */
1816*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* attribute list */
1817*7c478bd9Sstevel@tonic-gate 	    SKIPAUTH(attr_auth);		/* attr auth */
1818*7c478bd9Sstevel@tonic-gate #endif
1819*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1820*7c478bd9Sstevel@tonic-gate 	    DOURL;
1821*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Attribute list", FIELD_DEFAULT);
1822*7c478bd9Sstevel@tonic-gate 	    DOAUTH(attr_auth);
1823*7c478bd9Sstevel@tonic-gate 	}
1824*7c478bd9Sstevel@tonic-gate 
1825*7c478bd9Sstevel@tonic-gate 	return (1);
1826*7c478bd9Sstevel@tonic-gate }
1827*7c478bd9Sstevel@tonic-gate 
1828*7c478bd9Sstevel@tonic-gate static int v1_srv_ack(int flags) {
1829*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1830*7c478bd9Sstevel@tonic-gate 
1831*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1832*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1833*7c478bd9Sstevel@tonic-gate 	    strcat(msgbuf, slpv1_error(errcode));
1834*7c478bd9Sstevel@tonic-gate 	    if (errcode == OK && fresh) {
1835*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, " [Fresh]");
1836*7c478bd9Sstevel@tonic-gate 	    }
1837*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1838*7c478bd9Sstevel@tonic-gate 	    DOERRCODE;
1839*7c478bd9Sstevel@tonic-gate 	}
1840*7c478bd9Sstevel@tonic-gate 
1841*7c478bd9Sstevel@tonic-gate 	return (1);
1842*7c478bd9Sstevel@tonic-gate }
1843*7c478bd9Sstevel@tonic-gate 
1844*7c478bd9Sstevel@tonic-gate static int v1_srv_dereg(int flags) {
1845*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1846*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1847*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1848*7c478bd9Sstevel@tonic-gate 	    SKIPAUTH(url_auth);
1849*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* tag spec */
1850*7c478bd9Sstevel@tonic-gate #endif
1851*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1852*7c478bd9Sstevel@tonic-gate 	    DOFIELD("URL", FIELD_DEFAULT);
1853*7c478bd9Sstevel@tonic-gate 	    DOAUTH(url_auth);
1854*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Tag spec", FIELD_DEFAULT);
1855*7c478bd9Sstevel@tonic-gate 	}
1856*7c478bd9Sstevel@tonic-gate 
1857*7c478bd9Sstevel@tonic-gate 	return (1);
1858*7c478bd9Sstevel@tonic-gate }
1859*7c478bd9Sstevel@tonic-gate 
1860*7c478bd9Sstevel@tonic-gate static int v1_attr_rqst(int flags) {
1861*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1862*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_PREVRESP);	/* prev responders */
1863*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* URL */
1864*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1865*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* scope */
1866*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_DEFAULT);	/* select list */
1867*7c478bd9Sstevel@tonic-gate #endif
1868*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1869*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Previous responders", FIELD_PREVRESP);
1870*7c478bd9Sstevel@tonic-gate 	    DOFIELD("URL", FIELD_DEFAULT);
1871*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scope", FIELD_DEFAULT);
1872*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Select list", FIELD_DEFAULT);
1873*7c478bd9Sstevel@tonic-gate 	}
1874*7c478bd9Sstevel@tonic-gate 
1875*7c478bd9Sstevel@tonic-gate 	return (1);
1876*7c478bd9Sstevel@tonic-gate }
1877*7c478bd9Sstevel@tonic-gate 
1878*7c478bd9Sstevel@tonic-gate static int v1_attr_rply(int flags) {
1879*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1880*7c478bd9Sstevel@tonic-gate 
1881*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1882*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1883*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK) {
1884*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv1_error(errcode));
1885*7c478bd9Sstevel@tonic-gate 	    } else {
1886*7c478bd9Sstevel@tonic-gate 		GETFIELD;			/* attr list */
1887*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1888*7c478bd9Sstevel@tonic-gate 		SKIPAUTH(attr_auth);
1889*7c478bd9Sstevel@tonic-gate #endif
1890*7c478bd9Sstevel@tonic-gate 	    }
1891*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1892*7c478bd9Sstevel@tonic-gate 	    DOERRCODE;
1893*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Attribute list", FIELD_DEFAULT);
1894*7c478bd9Sstevel@tonic-gate 	    DOAUTH(attr_auth);
1895*7c478bd9Sstevel@tonic-gate 	}
1896*7c478bd9Sstevel@tonic-gate 
1897*7c478bd9Sstevel@tonic-gate 	return (1);
1898*7c478bd9Sstevel@tonic-gate }
1899*7c478bd9Sstevel@tonic-gate 
1900*7c478bd9Sstevel@tonic-gate static int v1_daadvert(int flags) {
1901*7c478bd9Sstevel@tonic-gate 	unsigned short errcode;
1902*7c478bd9Sstevel@tonic-gate 
1903*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1904*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1905*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK) {
1906*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv1_error(errcode));
1907*7c478bd9Sstevel@tonic-gate 	    } else {
1908*7c478bd9Sstevel@tonic-gate 		    GETFIELD;			/* URL */
1909*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1910*7c478bd9Sstevel@tonic-gate 		    SKIPFIELD(FIELD_DEFAULT);	/* scope list */
1911*7c478bd9Sstevel@tonic-gate #endif
1912*7c478bd9Sstevel@tonic-gate 	    }
1913*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1914*7c478bd9Sstevel@tonic-gate 	    DOERRCODE;
1915*7c478bd9Sstevel@tonic-gate 	    DOFIELD("URL", FIELD_DEFAULT);
1916*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scope list", FIELD_DEFAULT);
1917*7c478bd9Sstevel@tonic-gate 	}
1918*7c478bd9Sstevel@tonic-gate 
1919*7c478bd9Sstevel@tonic-gate 	return (1);
1920*7c478bd9Sstevel@tonic-gate }
1921*7c478bd9Sstevel@tonic-gate 
1922*7c478bd9Sstevel@tonic-gate static int v1_srv_type_rqst(int flags) {
1923*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1924*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_PREVRESP);	/* prev responders */
1925*7c478bd9Sstevel@tonic-gate 	    SKIPFIELD(FIELD_TYPENA);	/* naming authority */
1926*7c478bd9Sstevel@tonic-gate 	    GETFIELD;			/* scope */
1927*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1928*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Previous responders", FIELD_PREVRESP);
1929*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Naming authority", FIELD_TYPENA);
1930*7c478bd9Sstevel@tonic-gate 	    DOFIELD("Scope string", FIELD_DEFAULT);
1931*7c478bd9Sstevel@tonic-gate 	}
1932*7c478bd9Sstevel@tonic-gate 
1933*7c478bd9Sstevel@tonic-gate 	return (1);
1934*7c478bd9Sstevel@tonic-gate }
1935*7c478bd9Sstevel@tonic-gate 
1936*7c478bd9Sstevel@tonic-gate static int v1_srv_type_rply(int flags) {
1937*7c478bd9Sstevel@tonic-gate 	unsigned short errcode, itemcnt;
1938*7c478bd9Sstevel@tonic-gate 	int n;
1939*7c478bd9Sstevel@tonic-gate 
1940*7c478bd9Sstevel@tonic-gate 	if (flags & F_SUM) {
1941*7c478bd9Sstevel@tonic-gate 	    GETSHORT(errcode);
1942*7c478bd9Sstevel@tonic-gate 	    if (errcode != OK) {
1943*7c478bd9Sstevel@tonic-gate 		strcat(msgbuf, slpv1_error(errcode));
1944*7c478bd9Sstevel@tonic-gate 	    } else {
1945*7c478bd9Sstevel@tonic-gate 		GETSHORT(itemcnt);
1946*7c478bd9Sstevel@tonic-gate 		sprintf(msgend, "%d type entries", itemcnt);
1947*7c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP
1948*7c478bd9Sstevel@tonic-gate 		for (n = 0; n < itemcnt; n++) {
1949*7c478bd9Sstevel@tonic-gate 		    SKIPFIELD(FIELD_DEFAULT);  /* Service type item */
1950*7c478bd9Sstevel@tonic-gate 		}
1951*7c478bd9Sstevel@tonic-gate #endif
1952*7c478bd9Sstevel@tonic-gate 	    }
1953*7c478bd9Sstevel@tonic-gate 	} else if (flags & F_DTAIL) {
1954*7c478bd9Sstevel@tonic-gate 	    DOERRCODE;
1955*7c478bd9Sstevel@tonic-gate 	    GETSHORT(itemcnt);
1956*7c478bd9Sstevel@tonic-gate 	    sprintf(get_line(0, 0), "Service type count = %d", itemcnt);
1957*7c478bd9Sstevel@tonic-gate 	    for (n = 0; n < itemcnt; n++) {
1958*7c478bd9Sstevel@tonic-gate 		DOFIELD("  Service type item", FIELD_DEFAULT);
1959*7c478bd9Sstevel@tonic-gate 	    }
1960*7c478bd9Sstevel@tonic-gate 	}
1961*7c478bd9Sstevel@tonic-gate 
1962*7c478bd9Sstevel@tonic-gate 	return (1);
1963*7c478bd9Sstevel@tonic-gate }
1964