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