17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 57c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 67c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 77c478bd9Sstevel@tonic-gate * with the License. 87c478bd9Sstevel@tonic-gate * 97c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 107c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 117c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 127c478bd9Sstevel@tonic-gate * and limitations under the License. 137c478bd9Sstevel@tonic-gate * 147c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 157c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 167c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 177c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 187c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 197c478bd9Sstevel@tonic-gate * 207c478bd9Sstevel@tonic-gate * CDDL HEADER END 217c478bd9Sstevel@tonic-gate */ 227c478bd9Sstevel@tonic-gate /* 237c478bd9Sstevel@tonic-gate * Copyright (c) 1998,2000 by Sun Microsystems, Inc. 247c478bd9Sstevel@tonic-gate * All rights reserved. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <stdio.h> 287c478bd9Sstevel@tonic-gate #include <arpa/inet.h> 297c478bd9Sstevel@tonic-gate #include <stdlib.h> 307c478bd9Sstevel@tonic-gate #include <string.h> 317c478bd9Sstevel@tonic-gate #include <sys/time.h> 327c478bd9Sstevel@tonic-gate #include <iconv.h> 337c478bd9Sstevel@tonic-gate #include "snoop.h" 347c478bd9Sstevel@tonic-gate #include "slp.h" 357c478bd9Sstevel@tonic-gate 367c478bd9Sstevel@tonic-gate #define MAXSUMLEN 30 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* define VERIFYSLP to enable full message checking in summary mode */ 397c478bd9Sstevel@tonic-gate #define VERIFYSLP 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate /* Globals -- ugly, yes, but fast and easy in macros */ 427c478bd9Sstevel@tonic-gate static int msglength; 437c478bd9Sstevel@tonic-gate static int retlength; 447c478bd9Sstevel@tonic-gate static char *msgend; /* the end of the summary message buffer */ 457c478bd9Sstevel@tonic-gate static char *p; /* current position in the packet */ 467c478bd9Sstevel@tonic-gate static char *msgbuf; /* message buffer for summary mode */ 477c478bd9Sstevel@tonic-gate static boolean_t url_auth = B_FALSE; 487c478bd9Sstevel@tonic-gate static boolean_t attr_auth = B_FALSE; 497c478bd9Sstevel@tonic-gate static boolean_t fresh = B_FALSE; 507c478bd9Sstevel@tonic-gate static boolean_t overflow = B_FALSE; 517c478bd9Sstevel@tonic-gate static int v1_charset = 0; /* character set; only in V1 */ 527c478bd9Sstevel@tonic-gate 537c478bd9Sstevel@tonic-gate /* Entry points for parsing the protocol */ 547c478bd9Sstevel@tonic-gate static int interpret_slp_v1(int, struct slpv1_hdr *, int); 557c478bd9Sstevel@tonic-gate static int interpret_slp_v2(int, struct slpv2_hdr *, int); 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate /* header parsing */ 587c478bd9Sstevel@tonic-gate static int v1_header(int, struct slpv1_hdr *, int); 597c478bd9Sstevel@tonic-gate static int v2_header(int, struct slpv2_hdr *, int *, int); 607c478bd9Sstevel@tonic-gate static int v2_finish(struct slpv2_hdr *, int); 617c478bd9Sstevel@tonic-gate 627c478bd9Sstevel@tonic-gate /* V2 auth blocks */ 637c478bd9Sstevel@tonic-gate static int slpv2_authblock(int); 647c478bd9Sstevel@tonic-gate 657c478bd9Sstevel@tonic-gate /* 667c478bd9Sstevel@tonic-gate * Functions for parsing each protocol message 677c478bd9Sstevel@tonic-gate * Each function takes the interpreter's flags argument as its input 687c478bd9Sstevel@tonic-gate * parameter, and returns 1 on success, or 0 on message corruption. 697c478bd9Sstevel@tonic-gate * retlength is set as a side-effect in summary mode. 707c478bd9Sstevel@tonic-gate */ 717c478bd9Sstevel@tonic-gate static int v2_srv_rqst(int); 727c478bd9Sstevel@tonic-gate static int v2_srv_rply(int); 737c478bd9Sstevel@tonic-gate static int v2_srv_reg(int); 747c478bd9Sstevel@tonic-gate static int v2_srv_dereg(int); 757c478bd9Sstevel@tonic-gate static int v2_srv_ack(int); 767c478bd9Sstevel@tonic-gate static int v2_attr_rqst(int); 777c478bd9Sstevel@tonic-gate static int v2_attr_rply(int); 787c478bd9Sstevel@tonic-gate static int v2_daadvert(int); 797c478bd9Sstevel@tonic-gate static int v2_srv_type_rqst(int); 807c478bd9Sstevel@tonic-gate static int v2_srv_type_rply(int); 817c478bd9Sstevel@tonic-gate static int v2_saadvert(int); 827c478bd9Sstevel@tonic-gate 837c478bd9Sstevel@tonic-gate static int v1_srv_rqst(int); 847c478bd9Sstevel@tonic-gate static int v1_srv_rply(int); 857c478bd9Sstevel@tonic-gate static int v1_srv_reg(int); 867c478bd9Sstevel@tonic-gate static int v1_srv_dereg(int); 877c478bd9Sstevel@tonic-gate static int v1_srv_ack(int); 887c478bd9Sstevel@tonic-gate static int v1_attr_rqst(int); 897c478bd9Sstevel@tonic-gate static int v1_attr_rply(int); 907c478bd9Sstevel@tonic-gate static int v1_daadvert(int); 917c478bd9Sstevel@tonic-gate static int v1_srv_type_rqst(int); 927c478bd9Sstevel@tonic-gate static int v1_srv_type_rply(int); 937c478bd9Sstevel@tonic-gate 947c478bd9Sstevel@tonic-gate /* 957c478bd9Sstevel@tonic-gate * The dispatch tables for handling individual messages, keyed by 967c478bd9Sstevel@tonic-gate * function number. 977c478bd9Sstevel@tonic-gate */ 987c478bd9Sstevel@tonic-gate typedef int function_handler(); 997c478bd9Sstevel@tonic-gate 1007c478bd9Sstevel@tonic-gate #define V2_MAX_FUNCTION 11 1017c478bd9Sstevel@tonic-gate 1027c478bd9Sstevel@tonic-gate static function_handler *v2_functions[V2_MAX_FUNCTION + 1] = { 1037c478bd9Sstevel@tonic-gate (function_handler *) NULL, 1047c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_rqst, 1057c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_rply, 1067c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_reg, 1077c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_dereg, 1087c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_ack, 1097c478bd9Sstevel@tonic-gate (function_handler *) v2_attr_rqst, 1107c478bd9Sstevel@tonic-gate (function_handler *) v2_attr_rply, 1117c478bd9Sstevel@tonic-gate (function_handler *) v2_daadvert, 1127c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_type_rqst, 1137c478bd9Sstevel@tonic-gate (function_handler *) v2_srv_type_rply, 1147c478bd9Sstevel@tonic-gate (function_handler *) v2_saadvert }; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate #define V1_MAX_FUNCTION 10 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate static function_handler *v1_functions[V1_MAX_FUNCTION + 1] = { 1197c478bd9Sstevel@tonic-gate (function_handler *) NULL, 1207c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_rqst, 1217c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_rply, 1227c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_reg, 1237c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_dereg, 1247c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_ack, 1257c478bd9Sstevel@tonic-gate (function_handler *) v1_attr_rqst, 1267c478bd9Sstevel@tonic-gate (function_handler *) v1_attr_rply, 1277c478bd9Sstevel@tonic-gate (function_handler *) v1_daadvert, 1287c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_type_rqst, 1297c478bd9Sstevel@tonic-gate (function_handler *) v1_srv_type_rply }; 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* TCP continuation handling */ 1327c478bd9Sstevel@tonic-gate static boolean_t tcp_continuation = B_FALSE; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate #define MAX_TCPCONT 16 1357c478bd9Sstevel@tonic-gate 1367c478bd9Sstevel@tonic-gate static struct tcp_cont { 1377c478bd9Sstevel@tonic-gate int dst_port; 1387c478bd9Sstevel@tonic-gate char *msg; 1397c478bd9Sstevel@tonic-gate int totallen; 1407c478bd9Sstevel@tonic-gate int curr_offset; 1417c478bd9Sstevel@tonic-gate } *tcp_cont[MAX_TCPCONT]; 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate static int current_tcp_cont; 1447c478bd9Sstevel@tonic-gate 1457c478bd9Sstevel@tonic-gate static void reg_tcp_cont(char *, int, int, int); 1467c478bd9Sstevel@tonic-gate static int add_tcp_cont(struct tcp_cont *, char *, int); 1477c478bd9Sstevel@tonic-gate static struct tcp_cont *find_tcp_cont(int); 1487c478bd9Sstevel@tonic-gate static void remove_tcp_cont(int); 1497c478bd9Sstevel@tonic-gate 1507c478bd9Sstevel@tonic-gate /* Conversions from numbers to strings */ 1517c478bd9Sstevel@tonic-gate static char *slpv2_func(int, boolean_t); 1527c478bd9Sstevel@tonic-gate static char *slpv2_error(unsigned short); 1537c478bd9Sstevel@tonic-gate static char *slpv1_func(int, boolean_t); 1547c478bd9Sstevel@tonic-gate static char *slpv1_error(unsigned short); 1557c478bd9Sstevel@tonic-gate static char *slpv1_charset(unsigned short); 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * The only external entry point to the SLP interpreter. This function 1597c478bd9Sstevel@tonic-gate * simply dispatches the packet based on the version. 1607c478bd9Sstevel@tonic-gate */ 161*d6913e07SToomas Soome int 162*d6913e07SToomas Soome interpret_slp(int flags, void *slp, int fraglen) 163*d6913e07SToomas Soome { 1647c478bd9Sstevel@tonic-gate extern int dst_port, curr_proto; 1657c478bd9Sstevel@tonic-gate struct tcp_cont *tce = NULL; 1665b8f338eSToomas Soome char *s; 1677c478bd9Sstevel@tonic-gate 1687c478bd9Sstevel@tonic-gate msglength = fraglen; 1697c478bd9Sstevel@tonic-gate retlength = 0; 1707c478bd9Sstevel@tonic-gate p = slp; 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate /* check if this is a TCP continuation */ 1737c478bd9Sstevel@tonic-gate if (flags & F_DTAIL && curr_proto == IPPROTO_TCP) { 174*d6913e07SToomas Soome tce = find_tcp_cont(dst_port); 175*d6913e07SToomas Soome if (tce) { 176*d6913e07SToomas Soome if (add_tcp_cont(tce, slp, fraglen)) { 177*d6913e07SToomas Soome slp = tce->msg; 178*d6913e07SToomas Soome fraglen = tce->curr_offset; 179*d6913e07SToomas Soome tcp_continuation = B_TRUE; 180*d6913e07SToomas Soome } 1817c478bd9Sstevel@tonic-gate } 1827c478bd9Sstevel@tonic-gate } 1835b8f338eSToomas Soome if (*(char *)slp == 2 || tce) 184*d6913e07SToomas Soome interpret_slp_v2(flags, slp, fraglen); 1857c478bd9Sstevel@tonic-gate else 186*d6913e07SToomas Soome interpret_slp_v1(flags, slp, fraglen); 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate tcp_continuation = B_FALSE; 189*d6913e07SToomas Soome return (0); 1907c478bd9Sstevel@tonic-gate } 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate /* 1937c478bd9Sstevel@tonic-gate * Primitives. These are implemented as much as possible as macros for 1947c478bd9Sstevel@tonic-gate * speed. 1957c478bd9Sstevel@tonic-gate */ 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate #define FIELD_DEFAULT 0 1987c478bd9Sstevel@tonic-gate #define FIELD_PREVRESP 1 1997c478bd9Sstevel@tonic-gate #define FIELD_TYPENA 2 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate static long long netval = 0; /* need signed 64 bit quantity */ 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* gets two bytes from p and leaves the result in netval */ 2047c478bd9Sstevel@tonic-gate #define nbtohs() \ 2057c478bd9Sstevel@tonic-gate netval = ((int)(p[0] & 0xff)) << 8; \ 2067c478bd9Sstevel@tonic-gate netval += ((int)(p[1] & 0xff)) 2077c478bd9Sstevel@tonic-gate 2087c478bd9Sstevel@tonic-gate /* gets four bytes from p and leaves the result in netval */ 2097c478bd9Sstevel@tonic-gate #define nbtohl() \ 2107c478bd9Sstevel@tonic-gate netval = ((int)(p[0] & 0xff)) << 24; \ 2117c478bd9Sstevel@tonic-gate netval += ((int)(p[1] & 0xff)) << 16; \ 2127c478bd9Sstevel@tonic-gate netval += ((int)(p[2] & 0xff)) << 8; \ 2137c478bd9Sstevel@tonic-gate netval += ((int)(p[3] & 0xff)) 2147c478bd9Sstevel@tonic-gate 2157c478bd9Sstevel@tonic-gate #define get_byte() \ 2167c478bd9Sstevel@tonic-gate if (msglength >= 1) { \ 2177c478bd9Sstevel@tonic-gate netval = *p; \ 2187c478bd9Sstevel@tonic-gate p++; \ 2197c478bd9Sstevel@tonic-gate msglength--; \ 2207c478bd9Sstevel@tonic-gate } else \ 2217c478bd9Sstevel@tonic-gate netval = -1 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate #define GETBYTE(x) \ 2247c478bd9Sstevel@tonic-gate get_byte(); \ 2257c478bd9Sstevel@tonic-gate if ((retlength = netval) < 0) \ 2267c478bd9Sstevel@tonic-gate return (0); \ 2277c478bd9Sstevel@tonic-gate x = netval 2287c478bd9Sstevel@tonic-gate 2297c478bd9Sstevel@tonic-gate #define SKIPBYTE \ 2307c478bd9Sstevel@tonic-gate get_byte(); \ 2317c478bd9Sstevel@tonic-gate if ((retlength = netval) < 0) \ 2327c478bd9Sstevel@tonic-gate return (0); \ 2337c478bd9Sstevel@tonic-gate 2347c478bd9Sstevel@tonic-gate /* 2357c478bd9Sstevel@tonic-gate * gets two bytes from p, leaves the result in netval, and updates 2367c478bd9Sstevel@tonic-gate * msglength and p. 2377c478bd9Sstevel@tonic-gate */ 2387c478bd9Sstevel@tonic-gate #define get_short() \ 2397c478bd9Sstevel@tonic-gate if (msglength >= sizeof (unsigned short)) { \ 2407c478bd9Sstevel@tonic-gate nbtohs(); \ 2417c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); \ 2427c478bd9Sstevel@tonic-gate msglength -= sizeof (unsigned short); \ 2437c478bd9Sstevel@tonic-gate } else \ 2447c478bd9Sstevel@tonic-gate netval = -1 2457c478bd9Sstevel@tonic-gate 2467c478bd9Sstevel@tonic-gate #define GETSHORT(x) \ 2477c478bd9Sstevel@tonic-gate get_short(); \ 2487c478bd9Sstevel@tonic-gate if ((retlength = netval) < 0) \ 2497c478bd9Sstevel@tonic-gate return (0); \ 2507c478bd9Sstevel@tonic-gate x = netval 2517c478bd9Sstevel@tonic-gate 2527c478bd9Sstevel@tonic-gate #define SKIPSHORT \ 2537c478bd9Sstevel@tonic-gate get_short(); \ 2547c478bd9Sstevel@tonic-gate if ((retlength = netval) < 0) \ 2557c478bd9Sstevel@tonic-gate return (0) 2567c478bd9Sstevel@tonic-gate 2577c478bd9Sstevel@tonic-gate #define get_int24(pp) \ 2587c478bd9Sstevel@tonic-gate netval = ((int)((pp)[0] & 0xff)) << 16; \ 2597c478bd9Sstevel@tonic-gate netval += ((int)((pp)[1] & 0xff)) << 8; \ 2607c478bd9Sstevel@tonic-gate netval += ((int)((pp)[2] & 0xff)) 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate static void slp_prevresp(char *p) { 2637c478bd9Sstevel@tonic-gate char *p2; 2647c478bd9Sstevel@tonic-gate 2657c478bd9Sstevel@tonic-gate /* cycle through all entries */ 2667c478bd9Sstevel@tonic-gate for (; p != NULL; p = p2) { 2677c478bd9Sstevel@tonic-gate p2 = strchr(p, ','); 2687c478bd9Sstevel@tonic-gate if (p2 != NULL) 2697c478bd9Sstevel@tonic-gate *p2++ = '\0'; 2707c478bd9Sstevel@tonic-gate 2717c478bd9Sstevel@tonic-gate /* print entry at p */ 2727c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " \"%s\"", p); 2737c478bd9Sstevel@tonic-gate } 2747c478bd9Sstevel@tonic-gate } 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate static int skip_field(int type) { 2777c478bd9Sstevel@tonic-gate unsigned short stringlen; 2787c478bd9Sstevel@tonic-gate 2797c478bd9Sstevel@tonic-gate get_short(); 2807c478bd9Sstevel@tonic-gate if (netval < 0) { 2817c478bd9Sstevel@tonic-gate return (-1); 2827c478bd9Sstevel@tonic-gate } 2837c478bd9Sstevel@tonic-gate stringlen = netval; 2847c478bd9Sstevel@tonic-gate 2857c478bd9Sstevel@tonic-gate /* special case for NA field in SrvTypeRqst */ 2867c478bd9Sstevel@tonic-gate if (type == FIELD_TYPENA && stringlen == 0xffff) { 2877c478bd9Sstevel@tonic-gate stringlen = 0; 2887c478bd9Sstevel@tonic-gate } 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate if (stringlen > msglength) { 2917c478bd9Sstevel@tonic-gate return (-1); 2927c478bd9Sstevel@tonic-gate } 2937c478bd9Sstevel@tonic-gate 2947c478bd9Sstevel@tonic-gate msglength -= stringlen; 2957c478bd9Sstevel@tonic-gate p += stringlen; 2967c478bd9Sstevel@tonic-gate 2977c478bd9Sstevel@tonic-gate return (stringlen); 2987c478bd9Sstevel@tonic-gate } 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate #define SKIPFIELD(type) \ 3017c478bd9Sstevel@tonic-gate if ((retlength = skip_field(type)) < 0) \ 3027c478bd9Sstevel@tonic-gate return (0) 3037c478bd9Sstevel@tonic-gate 3047c478bd9Sstevel@tonic-gate #define GETFIELD \ 3057c478bd9Sstevel@tonic-gate get_short(); \ 3067c478bd9Sstevel@tonic-gate if ((retlength = netval) < 0) \ 3077c478bd9Sstevel@tonic-gate return (0); \ 3087c478bd9Sstevel@tonic-gate strncat(msgbuf, p, (retlength > MAXSUMLEN ? MAXSUMLEN : retlength)); \ 3097c478bd9Sstevel@tonic-gate p += retlength; \ 3107c478bd9Sstevel@tonic-gate msglength -= retlength 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate /* 3137c478bd9Sstevel@tonic-gate * Determines from the first five bytes of a potential SLP header 3147c478bd9Sstevel@tonic-gate * if the following message is really an SLP message. Returns 1 if 3157c478bd9Sstevel@tonic-gate * it is a real SLP message, 0 if not. 3167c478bd9Sstevel@tonic-gate */ 3177c478bd9Sstevel@tonic-gate int valid_slp(unsigned char *slphdr, int len) { 3187c478bd9Sstevel@tonic-gate struct slpv1_hdr slp1; 3197c478bd9Sstevel@tonic-gate struct slpv2_hdr slp2; 3207c478bd9Sstevel@tonic-gate 3217c478bd9Sstevel@tonic-gate len -= (8 /* udp */ + 20 /* IP */ + 14 /* ether */); 3227c478bd9Sstevel@tonic-gate /* a valid version will be 1 or 2 */ 3237c478bd9Sstevel@tonic-gate switch (*slphdr) { 3247c478bd9Sstevel@tonic-gate case 1: 3257c478bd9Sstevel@tonic-gate memcpy(&slp1, slphdr, 5); 3267c478bd9Sstevel@tonic-gate /* valid function? */ 3277c478bd9Sstevel@tonic-gate if (slp1.function > V1_MAX_FUNCTION) { 3287c478bd9Sstevel@tonic-gate return (0); 3297c478bd9Sstevel@tonic-gate } 3307c478bd9Sstevel@tonic-gate /* valid length heuristic */ 3317c478bd9Sstevel@tonic-gate if (slp1.length > len) { 3327c478bd9Sstevel@tonic-gate return (0); 3337c478bd9Sstevel@tonic-gate } 3347c478bd9Sstevel@tonic-gate return (1); 3357c478bd9Sstevel@tonic-gate case 2: 3367c478bd9Sstevel@tonic-gate memcpy(&slp2, slphdr, 5); 3377c478bd9Sstevel@tonic-gate /* valid function? */ 3387c478bd9Sstevel@tonic-gate if (slp2.function > V2_MAX_FUNCTION) { 3397c478bd9Sstevel@tonic-gate return (0); 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate /* valid length heuristic */ 3427c478bd9Sstevel@tonic-gate get_int24(&(slp2.l1)); 3437c478bd9Sstevel@tonic-gate if (netval > len) { 3447c478bd9Sstevel@tonic-gate return (0); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate return (1); 3477c478bd9Sstevel@tonic-gate default: 3487c478bd9Sstevel@tonic-gate return (0); 3497c478bd9Sstevel@tonic-gate } 3507c478bd9Sstevel@tonic-gate } 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate /* 3537c478bd9Sstevel@tonic-gate * Converts a V1 char encoding to UTF8. If this fails, returns 0, 3547c478bd9Sstevel@tonic-gate * otherwise, 1. This function is the union of iconv UTF-8 3557c478bd9Sstevel@tonic-gate * modules and character sets registered with IANA. 3567c478bd9Sstevel@tonic-gate */ 3577c478bd9Sstevel@tonic-gate static int make_utf8(char *outbuf, size_t outlen, 3587c478bd9Sstevel@tonic-gate const char *inbuf, size_t inlen) { 3597c478bd9Sstevel@tonic-gate iconv_t cd; 3607c478bd9Sstevel@tonic-gate size_t converted; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate switch (v1_charset) { 3637c478bd9Sstevel@tonic-gate case 4: 3647c478bd9Sstevel@tonic-gate case 1004: 3657c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-1"); 3667c478bd9Sstevel@tonic-gate break; 3677c478bd9Sstevel@tonic-gate case 5: 3687c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-2"); 3697c478bd9Sstevel@tonic-gate break; 3707c478bd9Sstevel@tonic-gate case 6: 3717c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-3"); 3727c478bd9Sstevel@tonic-gate break; 3737c478bd9Sstevel@tonic-gate case 7: 3747c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-4"); 3757c478bd9Sstevel@tonic-gate break; 3767c478bd9Sstevel@tonic-gate case 8: 3777c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-5"); 3787c478bd9Sstevel@tonic-gate break; 3797c478bd9Sstevel@tonic-gate case 9: 3807c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-6"); 3817c478bd9Sstevel@tonic-gate break; 3827c478bd9Sstevel@tonic-gate case 10: 3837c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-7"); 3847c478bd9Sstevel@tonic-gate break; 3857c478bd9Sstevel@tonic-gate case 11: 3867c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-8"); 3877c478bd9Sstevel@tonic-gate break; 3887c478bd9Sstevel@tonic-gate case 12: 3897c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-9"); 3907c478bd9Sstevel@tonic-gate break; 3917c478bd9Sstevel@tonic-gate case 13: 3927c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "8859-10"); 3937c478bd9Sstevel@tonic-gate break; 3947c478bd9Sstevel@tonic-gate case 37: 3957c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "ko_KR-iso2022-7"); 3967c478bd9Sstevel@tonic-gate break; 3977c478bd9Sstevel@tonic-gate case 104: 3987c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "iso2022"); 3997c478bd9Sstevel@tonic-gate break; 4007c478bd9Sstevel@tonic-gate case 1000: 4017c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "UCS-2"); 4027c478bd9Sstevel@tonic-gate break; 4037c478bd9Sstevel@tonic-gate case 1001: 4047c478bd9Sstevel@tonic-gate cd = iconv_open("UTF-8", "UCS-4"); 4057c478bd9Sstevel@tonic-gate break; 4067c478bd9Sstevel@tonic-gate default: 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * charset not set, or reserved, or not supported, so 4097c478bd9Sstevel@tonic-gate * just copy it and hope for the best. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate converted = outlen < inlen ? outlen : inlen; 4127c478bd9Sstevel@tonic-gate memcpy(outbuf, inbuf, converted); 4137c478bd9Sstevel@tonic-gate outbuf[converted] = 0; 4147c478bd9Sstevel@tonic-gate return (1); 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate 4177c478bd9Sstevel@tonic-gate if (cd == (iconv_t)-1) { 4187c478bd9Sstevel@tonic-gate return (0); 4197c478bd9Sstevel@tonic-gate } 4207c478bd9Sstevel@tonic-gate 4217c478bd9Sstevel@tonic-gate if ((converted = iconv(cd, &inbuf, &inlen, &outbuf, &outlen)) 4227c478bd9Sstevel@tonic-gate == (size_t)-1) { 4237c478bd9Sstevel@tonic-gate return (0); 4247c478bd9Sstevel@tonic-gate } 4257c478bd9Sstevel@tonic-gate 4267c478bd9Sstevel@tonic-gate outbuf[converted] = 0; 4277c478bd9Sstevel@tonic-gate iconv_close(cd); 4287c478bd9Sstevel@tonic-gate 4297c478bd9Sstevel@tonic-gate return (1); 4307c478bd9Sstevel@tonic-gate } 4317c478bd9Sstevel@tonic-gate 4327c478bd9Sstevel@tonic-gate static int slp_field(char *tag, int type) { 4337c478bd9Sstevel@tonic-gate int length; 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate get_short(); 4367c478bd9Sstevel@tonic-gate if (netval < 0) { 4377c478bd9Sstevel@tonic-gate return (-1); 4387c478bd9Sstevel@tonic-gate } 4397c478bd9Sstevel@tonic-gate length = netval; 4407c478bd9Sstevel@tonic-gate 4417c478bd9Sstevel@tonic-gate /* special case for NA field in SrvTypeRqst */ 4427c478bd9Sstevel@tonic-gate if (type == FIELD_TYPENA && length == 0xffff) { 4437c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "%s: length = -1: Use all NAs", tag); 4447c478bd9Sstevel@tonic-gate return (0); 4457c478bd9Sstevel@tonic-gate } 4467c478bd9Sstevel@tonic-gate 4477c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "%s: length = %d", tag, length); 4487c478bd9Sstevel@tonic-gate if (length > msglength) { 4497c478bd9Sstevel@tonic-gate /* framing error: message is not long enough to contain data */ 4507c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 4517c478bd9Sstevel@tonic-gate " [Framing error: remaining pkt length = %u]", 4527c478bd9Sstevel@tonic-gate msglength); 4537c478bd9Sstevel@tonic-gate return (-1); 4547c478bd9Sstevel@tonic-gate } 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate if (length > 0) { 4577c478bd9Sstevel@tonic-gate char *buf = malloc(length + 1); 4587c478bd9Sstevel@tonic-gate if (buf != NULL) { 4597c478bd9Sstevel@tonic-gate if (v1_charset) { 4607c478bd9Sstevel@tonic-gate if (!make_utf8(buf, length, p, length)) { 4617c478bd9Sstevel@tonic-gate strcpy(buf, "[Invalid Character Encoding]"); 4627c478bd9Sstevel@tonic-gate } 4637c478bd9Sstevel@tonic-gate } else { 4647c478bd9Sstevel@tonic-gate memcpy(buf, p, length); 4657c478bd9Sstevel@tonic-gate buf[length] = '\0'; /* ensure null-terminated */ 4667c478bd9Sstevel@tonic-gate } 4677c478bd9Sstevel@tonic-gate 4687c478bd9Sstevel@tonic-gate switch (type) { 4697c478bd9Sstevel@tonic-gate case FIELD_PREVRESP: 4707c478bd9Sstevel@tonic-gate slp_prevresp(buf); 4717c478bd9Sstevel@tonic-gate break; 4727c478bd9Sstevel@tonic-gate 4737c478bd9Sstevel@tonic-gate default: 4747c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " \"%s\"", buf); 4757c478bd9Sstevel@tonic-gate break; 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate free(buf); 4787c478bd9Sstevel@tonic-gate } 4797c478bd9Sstevel@tonic-gate 4807c478bd9Sstevel@tonic-gate p += length; 4817c478bd9Sstevel@tonic-gate msglength -= length; 4827c478bd9Sstevel@tonic-gate } 4837c478bd9Sstevel@tonic-gate 4847c478bd9Sstevel@tonic-gate /* return ok */ 4857c478bd9Sstevel@tonic-gate return (0); 4867c478bd9Sstevel@tonic-gate } 4877c478bd9Sstevel@tonic-gate 4887c478bd9Sstevel@tonic-gate static int slpv2_url(int cnt) { 4897c478bd9Sstevel@tonic-gate time_t exp; 4907c478bd9Sstevel@tonic-gate int lifetime, length, n; 4917c478bd9Sstevel@tonic-gate 4927c478bd9Sstevel@tonic-gate /* reserved */ 4937c478bd9Sstevel@tonic-gate get_byte(); 4947c478bd9Sstevel@tonic-gate if (netval < 0) 4957c478bd9Sstevel@tonic-gate return (-1); 4967c478bd9Sstevel@tonic-gate 4977c478bd9Sstevel@tonic-gate /* lifetime */ 4987c478bd9Sstevel@tonic-gate get_short(); 4997c478bd9Sstevel@tonic-gate if ((lifetime = netval) < 0) 5007c478bd9Sstevel@tonic-gate return (-1); 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate /* length */ 5037c478bd9Sstevel@tonic-gate get_short(); 5047c478bd9Sstevel@tonic-gate if ((length = netval) < 0) 5057c478bd9Sstevel@tonic-gate return (-1); 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* time */ 5087c478bd9Sstevel@tonic-gate exp = time(0) + lifetime; 5097c478bd9Sstevel@tonic-gate if (cnt == -1) 5107c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 5117c478bd9Sstevel@tonic-gate "URL: length = %u, lifetime = %d (%24.24s)", 5127c478bd9Sstevel@tonic-gate length, lifetime, ctime(&exp)); 5137c478bd9Sstevel@tonic-gate else 5147c478bd9Sstevel@tonic-gate /* number the URLs to make it easier to parse them */ 5157c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 5167c478bd9Sstevel@tonic-gate "URL %d: length = %u, lifetime = %d (%24.24s)", 5177c478bd9Sstevel@tonic-gate cnt, length, lifetime, ctime(&exp)); 5187c478bd9Sstevel@tonic-gate 5197c478bd9Sstevel@tonic-gate if (length > msglength) { 5207c478bd9Sstevel@tonic-gate if (!tcp_continuation) 5217c478bd9Sstevel@tonic-gate /* framing error: message is not long enough to contain data */ 5227c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 5237c478bd9Sstevel@tonic-gate " [Framing error: remaining pkt length = %u]", 5247c478bd9Sstevel@tonic-gate msglength); 5257c478bd9Sstevel@tonic-gate return (-1); 5267c478bd9Sstevel@tonic-gate } 5277c478bd9Sstevel@tonic-gate 5287c478bd9Sstevel@tonic-gate if (length > 0) { 5297c478bd9Sstevel@tonic-gate char *buf = malloc(length + 1); 5307c478bd9Sstevel@tonic-gate if (buf != NULL) { 5317c478bd9Sstevel@tonic-gate memcpy(buf, p, length); 5327c478bd9Sstevel@tonic-gate buf[length] = '\0'; /* ensure null-terminated */ 5337c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " \"%s\"", buf); 5347c478bd9Sstevel@tonic-gate free(buf); 5357c478bd9Sstevel@tonic-gate } 5367c478bd9Sstevel@tonic-gate } 5377c478bd9Sstevel@tonic-gate msglength -= length; 5387c478bd9Sstevel@tonic-gate p += length; 5397c478bd9Sstevel@tonic-gate 5407c478bd9Sstevel@tonic-gate get_byte(); 5417c478bd9Sstevel@tonic-gate if ((n = netval) < 0) 5427c478bd9Sstevel@tonic-gate return (-1); 5437c478bd9Sstevel@tonic-gate 5447c478bd9Sstevel@tonic-gate if (n > 0) { 5457c478bd9Sstevel@tonic-gate int i; 5467c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "%d Authentication Blocks", n); 5477c478bd9Sstevel@tonic-gate for (i = 0; i < n; i++) 5487c478bd9Sstevel@tonic-gate if ((length = slpv2_authblock(i)) < 0) 5497c478bd9Sstevel@tonic-gate return (-1); 5507c478bd9Sstevel@tonic-gate } 5517c478bd9Sstevel@tonic-gate return (0); 5527c478bd9Sstevel@tonic-gate } 5537c478bd9Sstevel@tonic-gate 5547c478bd9Sstevel@tonic-gate #define DOFIELD(tag, type) \ 5557c478bd9Sstevel@tonic-gate if (slp_field(tag, type) < 0) \ 5567c478bd9Sstevel@tonic-gate return (0) 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate #define V2_DOURL(x) \ 5597c478bd9Sstevel@tonic-gate if (slpv2_url(x) < 0) \ 5607c478bd9Sstevel@tonic-gate return (0) 5617c478bd9Sstevel@tonic-gate 5627c478bd9Sstevel@tonic-gate #define V2_DOERRCODE \ 5637c478bd9Sstevel@tonic-gate if (msglength < sizeof (unsigned short)) \ 5647c478bd9Sstevel@tonic-gate return (0); \ 5657c478bd9Sstevel@tonic-gate nbtohs(); \ 5667c478bd9Sstevel@tonic-gate errcode = netval; \ 5677c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Error code = %d, %s", \ 5687c478bd9Sstevel@tonic-gate errcode, slpv2_error(errcode)); \ 5697c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); \ 5707c478bd9Sstevel@tonic-gate msglength -= sizeof (unsigned short); \ 5717c478bd9Sstevel@tonic-gate if (errcode != OK) \ 5727c478bd9Sstevel@tonic-gate msglength = 0; /* skip rest of message */ \ 5737c478bd9Sstevel@tonic-gate if (errcode != OK) \ 5747c478bd9Sstevel@tonic-gate return (0) 5757c478bd9Sstevel@tonic-gate 5767c478bd9Sstevel@tonic-gate #define V2_DOAUTH(cnt) \ 5777c478bd9Sstevel@tonic-gate if (slpv2_authblock(cnt) < 0) \ 5787c478bd9Sstevel@tonic-gate return (0) 5797c478bd9Sstevel@tonic-gate 5807c478bd9Sstevel@tonic-gate #define V2_DOTIMESTAMP \ 5817c478bd9Sstevel@tonic-gate if (msglength < 4) \ 5827c478bd9Sstevel@tonic-gate return (0); \ 5837c478bd9Sstevel@tonic-gate nbtohl(); \ 5847c478bd9Sstevel@tonic-gate timestamp = netval; \ 5857c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Timestamp = %u, %s", \ 5867c478bd9Sstevel@tonic-gate timestamp, (timestamp ? convert_ts(timestamp) : "0")); \ 5877c478bd9Sstevel@tonic-gate p += 4; \ 5887c478bd9Sstevel@tonic-gate msglength -= 4 5897c478bd9Sstevel@tonic-gate 5907c478bd9Sstevel@tonic-gate /* some V1 macros */ 5917c478bd9Sstevel@tonic-gate #define SKIPAUTH(auth) \ 5927c478bd9Sstevel@tonic-gate if (auth && ((retlength = skip_v1authblock()) < 0)) \ 5937c478bd9Sstevel@tonic-gate return (0) 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate #define DOERRCODE \ 5967c478bd9Sstevel@tonic-gate if (msglength < sizeof (unsigned short)) \ 5977c478bd9Sstevel@tonic-gate return (0); \ 5987c478bd9Sstevel@tonic-gate nbtohs(); \ 5997c478bd9Sstevel@tonic-gate errcode = netval; \ 6007c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Error code = %d, %s", errcode, \ 6017c478bd9Sstevel@tonic-gate slpv1_error(errcode)); \ 6027c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); \ 6037c478bd9Sstevel@tonic-gate msglength -= sizeof (unsigned short); \ 6047c478bd9Sstevel@tonic-gate if (errcode != OK) \ 6057c478bd9Sstevel@tonic-gate return (0) 6067c478bd9Sstevel@tonic-gate 6077c478bd9Sstevel@tonic-gate #define DOURL \ 6087c478bd9Sstevel@tonic-gate if (slpv1_url(url_auth) < 0) \ 6097c478bd9Sstevel@tonic-gate return (0) 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate #define DOAUTH(auth) \ 6127c478bd9Sstevel@tonic-gate if (auth && slpv1_authblock() < 0) \ 6137c478bd9Sstevel@tonic-gate return (0) 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate * TCP Continuation handling 6177c478bd9Sstevel@tonic-gate * We keep track of continuations in a fixed size cache, so as to prevent 6187c478bd9Sstevel@tonic-gate * memory leaks if some continuations are never finished. The continuations 6197c478bd9Sstevel@tonic-gate * are indexed by their destination ports. 6207c478bd9Sstevel@tonic-gate */ 6217c478bd9Sstevel@tonic-gate static void reg_tcp_cont(char *msg, int totallen, 6227c478bd9Sstevel@tonic-gate int fraglen, int dst_port) { 6237c478bd9Sstevel@tonic-gate struct tcp_cont *tce = malloc(sizeof (*tce)); 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate /* always overwrite the entry at current_tcp_cont */ 6267c478bd9Sstevel@tonic-gate if (tcp_cont[current_tcp_cont]) { 6277c478bd9Sstevel@tonic-gate free(tcp_cont[current_tcp_cont]->msg); 6287c478bd9Sstevel@tonic-gate free(tcp_cont[current_tcp_cont]); 6297c478bd9Sstevel@tonic-gate } 6307c478bd9Sstevel@tonic-gate 6317c478bd9Sstevel@tonic-gate tce->dst_port = dst_port; 6327c478bd9Sstevel@tonic-gate tce->msg = malloc(totallen); 6337c478bd9Sstevel@tonic-gate memcpy(tce->msg, msg, fraglen); 6347c478bd9Sstevel@tonic-gate tce->totallen = totallen; 6357c478bd9Sstevel@tonic-gate tce->curr_offset = fraglen; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate tcp_cont[current_tcp_cont++] = tce; 6387c478bd9Sstevel@tonic-gate if (current_tcp_cont == MAX_TCPCONT) 6397c478bd9Sstevel@tonic-gate current_tcp_cont = 0; 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* returns 0 if there is a mismatch error, 1 on success */ 6437c478bd9Sstevel@tonic-gate static int add_tcp_cont(struct tcp_cont *tce, char *msg, int fraglen) { 6447c478bd9Sstevel@tonic-gate if ((fraglen + tce->curr_offset) > tce->totallen) 6457c478bd9Sstevel@tonic-gate return (0); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate memcpy(tce->msg + tce->curr_offset, msg, fraglen); 6487c478bd9Sstevel@tonic-gate tce->curr_offset += fraglen; 6497c478bd9Sstevel@tonic-gate return (1); 6507c478bd9Sstevel@tonic-gate } 6517c478bd9Sstevel@tonic-gate 6527c478bd9Sstevel@tonic-gate static struct tcp_cont *find_tcp_cont(int dst_port) { 6537c478bd9Sstevel@tonic-gate int i; 6547c478bd9Sstevel@tonic-gate for (i = current_tcp_cont; i >= 0; i--) 6557c478bd9Sstevel@tonic-gate if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) 6567c478bd9Sstevel@tonic-gate return (tcp_cont[i]); 6577c478bd9Sstevel@tonic-gate 6587c478bd9Sstevel@tonic-gate for (i = MAX_TCPCONT -1; i > current_tcp_cont; i--) 6597c478bd9Sstevel@tonic-gate if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) 6607c478bd9Sstevel@tonic-gate return (tcp_cont[i]); 6617c478bd9Sstevel@tonic-gate 6627c478bd9Sstevel@tonic-gate return (NULL); 6637c478bd9Sstevel@tonic-gate } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate static void remove_tcp_cont(int dst_port) { 6667c478bd9Sstevel@tonic-gate int i; 6677c478bd9Sstevel@tonic-gate for (i = current_tcp_cont; i >= 0; i--) 6687c478bd9Sstevel@tonic-gate if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) { 6697c478bd9Sstevel@tonic-gate free(tcp_cont[i]->msg); 6707c478bd9Sstevel@tonic-gate free(tcp_cont[i]); 6717c478bd9Sstevel@tonic-gate tcp_cont[i] = NULL; 6727c478bd9Sstevel@tonic-gate return; 6737c478bd9Sstevel@tonic-gate } 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate for (i = MAX_TCPCONT -1; i > current_tcp_cont; i--) 6767c478bd9Sstevel@tonic-gate if (tcp_cont[i] && tcp_cont[i]->dst_port == dst_port) { 6777c478bd9Sstevel@tonic-gate free(tcp_cont[i]->msg); 6787c478bd9Sstevel@tonic-gate free(tcp_cont[i]); 6797c478bd9Sstevel@tonic-gate tcp_cont[i] = NULL; 6807c478bd9Sstevel@tonic-gate return; 6817c478bd9Sstevel@tonic-gate } 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * V2 interpreter 6867c478bd9Sstevel@tonic-gate */ 6877c478bd9Sstevel@tonic-gate 6887c478bd9Sstevel@tonic-gate static int interpret_slp_v2(int flags, struct slpv2_hdr *slp, int fraglen) { 6897c478bd9Sstevel@tonic-gate extern int src_port, dst_port, curr_proto; 6907c478bd9Sstevel@tonic-gate char msgbuf_real[256]; 6917c478bd9Sstevel@tonic-gate int totallen = 0; 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate msgbuf = msgbuf_real; 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate /* 6967c478bd9Sstevel@tonic-gate * Somewhat of a hack to decode traffic from a server that does 6977c478bd9Sstevel@tonic-gate * not send udp replies from its SLP src port. 6987c478bd9Sstevel@tonic-gate */ 6997c478bd9Sstevel@tonic-gate 7007c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_UDP && 7017c478bd9Sstevel@tonic-gate dst_port == 427 && 7027c478bd9Sstevel@tonic-gate src_port != 427) { 703*d6913e07SToomas Soome add_transient(src_port, interpret_slp); 7047c478bd9Sstevel@tonic-gate } 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate /* parse the header */ 7077c478bd9Sstevel@tonic-gate if (v2_header(flags, slp, &totallen, fraglen)) { 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate if (slp->function <= V2_MAX_FUNCTION && slp->function > 0) { 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate /* Parse the message body */ 7127c478bd9Sstevel@tonic-gate if ((v2_functions[slp->function])(flags)) { 7137c478bd9Sstevel@tonic-gate 7147c478bd9Sstevel@tonic-gate /* finish any remaining tasks */ 7157c478bd9Sstevel@tonic-gate v2_finish(slp, flags); 7167c478bd9Sstevel@tonic-gate 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate } 7207c478bd9Sstevel@tonic-gate 7217c478bd9Sstevel@tonic-gate } 7227c478bd9Sstevel@tonic-gate 7237c478bd9Sstevel@tonic-gate /* summary error check */ 7247c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 7257c478bd9Sstevel@tonic-gate if (retlength < 0) { 7267c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_TCP) 7277c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), 7287c478bd9Sstevel@tonic-gate "%s [partial TCP message]", msgbuf); 7297c478bd9Sstevel@tonic-gate else if (overflow) 7307c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s [OVERFLOW]", msgbuf); 7317c478bd9Sstevel@tonic-gate else 7327c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s [CORRUPTED MESSAGE]", msgbuf); 7337c478bd9Sstevel@tonic-gate } 7347c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 7357c478bd9Sstevel@tonic-gate else if (msglength > 0) 7367c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s +%d", msgbuf, msglength); 7377c478bd9Sstevel@tonic-gate #endif 7387c478bd9Sstevel@tonic-gate else 7397c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s", msgbuf); 7407c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 7417c478bd9Sstevel@tonic-gate /* detailed error check */ 7427c478bd9Sstevel@tonic-gate if (msglength > 0) { 7437c478bd9Sstevel@tonic-gate if (tcp_continuation) { 7447c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 7457c478bd9Sstevel@tonic-gate "[TCP Continuation, %d bytes remaining]", 7467c478bd9Sstevel@tonic-gate totallen - fraglen); 7477c478bd9Sstevel@tonic-gate } else 7487c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 7497c478bd9Sstevel@tonic-gate "[%d extra bytes at end of SLP message]", msglength); 7507c478bd9Sstevel@tonic-gate } 7517c478bd9Sstevel@tonic-gate 7527c478bd9Sstevel@tonic-gate show_trailer(); 7537c478bd9Sstevel@tonic-gate 7547c478bd9Sstevel@tonic-gate if (tcp_continuation && msglength == 0) 7557c478bd9Sstevel@tonic-gate remove_tcp_cont(dst_port); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate return (0); 7597c478bd9Sstevel@tonic-gate } 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate static int v2_header(int flags, 7627c478bd9Sstevel@tonic-gate struct slpv2_hdr *slp, 7637c478bd9Sstevel@tonic-gate int *totallen, 7647c478bd9Sstevel@tonic-gate int fraglen) { 7657c478bd9Sstevel@tonic-gate extern int curr_proto, dst_port; 7667c478bd9Sstevel@tonic-gate char *prototag = (curr_proto == IPPROTO_TCP ? "/tcp" : ""); 7677c478bd9Sstevel@tonic-gate 7687c478bd9Sstevel@tonic-gate if ((slp->flags & V2_OVERFLOW) == V2_OVERFLOW) 7697c478bd9Sstevel@tonic-gate overflow = B_TRUE; 7707c478bd9Sstevel@tonic-gate 7717c478bd9Sstevel@tonic-gate /* summary mode header parsing */ 7727c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate /* make sure we have at least a header */ 7757c478bd9Sstevel@tonic-gate if (msglength < sizeof (*slp)) { 7767c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "SLP V2 [Incomplete Header]"); 7777c478bd9Sstevel@tonic-gate return (0); 7787c478bd9Sstevel@tonic-gate } 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate sprintf(msgbuf, "SLP V2 %s [%d%s] ", 7817c478bd9Sstevel@tonic-gate slpv2_func(slp->function, B_TRUE), 7827c478bd9Sstevel@tonic-gate ntohs(slp->xid), prototag); 7837c478bd9Sstevel@tonic-gate 7847c478bd9Sstevel@tonic-gate /* skip to end of header */ 7857c478bd9Sstevel@tonic-gate msgend = msgbuf + strlen(msgbuf); 7867c478bd9Sstevel@tonic-gate msglength -= sizeof (*slp); 7877c478bd9Sstevel@tonic-gate p += sizeof (*slp); 7887c478bd9Sstevel@tonic-gate 7897c478bd9Sstevel@tonic-gate /* skip language tag */ 7907c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); 7917c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 7927c478bd9Sstevel@tonic-gate char *lang; 7937c478bd9Sstevel@tonic-gate int len; 7947c478bd9Sstevel@tonic-gate 7957c478bd9Sstevel@tonic-gate /* detailed mode header parsing */ 7967c478bd9Sstevel@tonic-gate show_header("SLP: ", "Service Location Protocol (v2)", fraglen); 7977c478bd9Sstevel@tonic-gate show_space(); 7987c478bd9Sstevel@tonic-gate 7997c478bd9Sstevel@tonic-gate if (msglength < sizeof (*slp)) { 8007c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "==> Incomplete SLP header"); 8017c478bd9Sstevel@tonic-gate return (0); 8027c478bd9Sstevel@tonic-gate } 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Version = %d", slp->vers); 8057c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Function = %d, %s", 8067c478bd9Sstevel@tonic-gate slp->function, slpv2_func(slp->function, B_FALSE)); 8077c478bd9Sstevel@tonic-gate get_int24(&(slp->l1)); 8087c478bd9Sstevel@tonic-gate *totallen = netval; 8097c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Message length = %u", *totallen); 8107c478bd9Sstevel@tonic-gate /* check for TCP continuation */ 8117c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_TCP && 8127c478bd9Sstevel@tonic-gate *totallen > msglength && 8137c478bd9Sstevel@tonic-gate !tcp_continuation) { 8147c478bd9Sstevel@tonic-gate tcp_continuation = B_TRUE; 8157c478bd9Sstevel@tonic-gate reg_tcp_cont((char *)slp, *totallen, msglength, dst_port); 8167c478bd9Sstevel@tonic-gate } 8177c478bd9Sstevel@tonic-gate 8187c478bd9Sstevel@tonic-gate if (!tcp_continuation && *totallen != msglength) { 8197c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 8207c478bd9Sstevel@tonic-gate " (Stated and on-the-wire lengths differ)"); 8217c478bd9Sstevel@tonic-gate } 8227c478bd9Sstevel@tonic-gate /* flags */ 8237c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags); 8247c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 8257c478bd9Sstevel@tonic-gate getflag(slp->flags, V2_OVERFLOW, 8267c478bd9Sstevel@tonic-gate "overflow", "no overflow")); 8277c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 8287c478bd9Sstevel@tonic-gate getflag(slp->flags, V2_FRESH, 8297c478bd9Sstevel@tonic-gate "fresh registration", "no fresh registration")); 8307c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 8317c478bd9Sstevel@tonic-gate getflag(slp->flags, V2_MCAST, 8327c478bd9Sstevel@tonic-gate "request multicast / broadcast", "unicast")); 8337c478bd9Sstevel@tonic-gate /* check reserved flags that must be zero */ 8347c478bd9Sstevel@tonic-gate if ((slp->flags & 7) != 0) { 8357c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 8367c478bd9Sstevel@tonic-gate " .... .xxx = %d (reserved flags nonzero)", 8377c478bd9Sstevel@tonic-gate slp->flags & 7); 8387c478bd9Sstevel@tonic-gate } 8397c478bd9Sstevel@tonic-gate /* end of flags */ 8407c478bd9Sstevel@tonic-gate 8417c478bd9Sstevel@tonic-gate /* language tag */ 8427c478bd9Sstevel@tonic-gate p = (char *)slp + sizeof (*slp); 8437c478bd9Sstevel@tonic-gate msglength -= sizeof (*slp); 8447c478bd9Sstevel@tonic-gate GETSHORT(len); 8457c478bd9Sstevel@tonic-gate if (len > msglength) { 8467c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 8477c478bd9Sstevel@tonic-gate "Language Tag Length = %u [CORRUPT MESSAGE]", 8487c478bd9Sstevel@tonic-gate len); 8497c478bd9Sstevel@tonic-gate return (0); 8507c478bd9Sstevel@tonic-gate } 8517c478bd9Sstevel@tonic-gate 8527c478bd9Sstevel@tonic-gate lang = get_line(0, 0); 8537c478bd9Sstevel@tonic-gate strcpy(lang, "Language Tag = "); 8547c478bd9Sstevel@tonic-gate strncat(lang, p, len); 8557c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid)); 8567c478bd9Sstevel@tonic-gate 8577c478bd9Sstevel@tonic-gate /* set msglength to remaining length of SLP message */ 8587c478bd9Sstevel@tonic-gate p += len; 8597c478bd9Sstevel@tonic-gate msglength -= len; 8607c478bd9Sstevel@tonic-gate } 8617c478bd9Sstevel@tonic-gate 8627c478bd9Sstevel@tonic-gate return (1); 8637c478bd9Sstevel@tonic-gate } 8647c478bd9Sstevel@tonic-gate 8657c478bd9Sstevel@tonic-gate static int v2_finish(struct slpv2_hdr *slp, int flags) { 8667c478bd9Sstevel@tonic-gate unsigned int firstop; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate if (!(flags & F_DTAIL)) 8697c478bd9Sstevel@tonic-gate return (1); 8707c478bd9Sstevel@tonic-gate 8717c478bd9Sstevel@tonic-gate /* check for options */ 8727c478bd9Sstevel@tonic-gate get_int24(&(slp->o1)); 8737c478bd9Sstevel@tonic-gate firstop = netval; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate if (firstop) { 8767c478bd9Sstevel@tonic-gate unsigned short op_id; 8777c478bd9Sstevel@tonic-gate unsigned short nextop; 8787c478bd9Sstevel@tonic-gate char *op_class; 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate for (;;) { 8817c478bd9Sstevel@tonic-gate unsigned short real_oplen; 8827c478bd9Sstevel@tonic-gate 8837c478bd9Sstevel@tonic-gate if (msglength < 4) { 8847c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 8857c478bd9Sstevel@tonic-gate "Option expected but not present"); 8867c478bd9Sstevel@tonic-gate return (0); 8877c478bd9Sstevel@tonic-gate } 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate nbtohs(); 8907c478bd9Sstevel@tonic-gate op_id = netval; 8917c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 8927c478bd9Sstevel@tonic-gate msglength -= sizeof (unsigned short); 8937c478bd9Sstevel@tonic-gate nbtohs(); 8947c478bd9Sstevel@tonic-gate nextop = netval; 8957c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 8967c478bd9Sstevel@tonic-gate msglength -= sizeof (unsigned short); 8977c478bd9Sstevel@tonic-gate 8987c478bd9Sstevel@tonic-gate real_oplen = nextop ? nextop : msglength; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* known options */ 9017c478bd9Sstevel@tonic-gate switch (op_id) { 9027c478bd9Sstevel@tonic-gate case 1: 9037c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 9047c478bd9Sstevel@tonic-gate "Option: Required Attribute Missing"); 9057c478bd9Sstevel@tonic-gate DOFIELD("Template IDVer", FIELD_DEFAULT); 9067c478bd9Sstevel@tonic-gate DOFIELD("Required Attrs", FIELD_DEFAULT); 9077c478bd9Sstevel@tonic-gate break; 9087c478bd9Sstevel@tonic-gate default: 9097c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Option: Unknown"); 9107c478bd9Sstevel@tonic-gate p += (real_oplen - 4); 9117c478bd9Sstevel@tonic-gate msglength -= (real_oplen - 4); 9127c478bd9Sstevel@tonic-gate break; 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate if (op_id < 0x3fff) 9167c478bd9Sstevel@tonic-gate op_class = "Standardized, optional"; 9177c478bd9Sstevel@tonic-gate else if (op_id < 0x7fff) 9187c478bd9Sstevel@tonic-gate op_class = "Standardized, mandatory"; 9197c478bd9Sstevel@tonic-gate else if (op_id < 0x8fff) 9207c478bd9Sstevel@tonic-gate op_class = "Not standardized, private"; 9217c478bd9Sstevel@tonic-gate else if (op_id < 0xffff) 9227c478bd9Sstevel@tonic-gate op_class = "Reserved"; 9237c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Option ID = 0x%04x, %s", 9247c478bd9Sstevel@tonic-gate op_id, op_class); 9257c478bd9Sstevel@tonic-gate if (nextop && 9267c478bd9Sstevel@tonic-gate ((nextop - 4) > msglength) && 9277c478bd9Sstevel@tonic-gate !tcp_continuation) { 9287c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 9297c478bd9Sstevel@tonic-gate "[Framing error: remaining pkt length = %u]", 9307c478bd9Sstevel@tonic-gate msglength); 9317c478bd9Sstevel@tonic-gate return (0); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 9347c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Option Length = %u", real_oplen); 9357c478bd9Sstevel@tonic-gate 9367c478bd9Sstevel@tonic-gate if (!nextop) 9377c478bd9Sstevel@tonic-gate break; 9387c478bd9Sstevel@tonic-gate } 9397c478bd9Sstevel@tonic-gate } 9407c478bd9Sstevel@tonic-gate 9417c478bd9Sstevel@tonic-gate return (1); 9427c478bd9Sstevel@tonic-gate } 9437c478bd9Sstevel@tonic-gate 9447c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 9457c478bd9Sstevel@tonic-gate static int skip_v2authblock() { 9467c478bd9Sstevel@tonic-gate unsigned short length, slen; 9477c478bd9Sstevel@tonic-gate 9487c478bd9Sstevel@tonic-gate /* auth header */ 9497c478bd9Sstevel@tonic-gate if (msglength < 10) 9507c478bd9Sstevel@tonic-gate return (-1); 9517c478bd9Sstevel@tonic-gate 9527c478bd9Sstevel@tonic-gate /* block descriptor: 2 bytes */ 9537c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 9547c478bd9Sstevel@tonic-gate /* length */ 9557c478bd9Sstevel@tonic-gate nbtohs(); 9567c478bd9Sstevel@tonic-gate length = netval; 9577c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 9587c478bd9Sstevel@tonic-gate /* timestamp */ 9597c478bd9Sstevel@tonic-gate p += 4; 9607c478bd9Sstevel@tonic-gate /* SPI String length */ 9617c478bd9Sstevel@tonic-gate nbtohs(); 9627c478bd9Sstevel@tonic-gate slen = netval; 9637c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 9647c478bd9Sstevel@tonic-gate 9657c478bd9Sstevel@tonic-gate msglength -= 10; 9667c478bd9Sstevel@tonic-gate if (slen > msglength || length > (msglength + 10)) 9677c478bd9Sstevel@tonic-gate return (-1); 9687c478bd9Sstevel@tonic-gate 9697c478bd9Sstevel@tonic-gate p += slen; 9707c478bd9Sstevel@tonic-gate msglength -= slen; 9717c478bd9Sstevel@tonic-gate 9727c478bd9Sstevel@tonic-gate /* structured auth block */ 9737c478bd9Sstevel@tonic-gate p += (length - 10 - slen); 9747c478bd9Sstevel@tonic-gate msglength -= (length - 10 - slen); 9757c478bd9Sstevel@tonic-gate return (0); 9767c478bd9Sstevel@tonic-gate } 9777c478bd9Sstevel@tonic-gate #endif 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate static char *display_bsd(unsigned short bsd) { 9807c478bd9Sstevel@tonic-gate switch (bsd) { 9817c478bd9Sstevel@tonic-gate case 1: return ("MD5 with RSA"); 9827c478bd9Sstevel@tonic-gate case 2: return ("DSA with SHA-1"); 9837c478bd9Sstevel@tonic-gate case 3: return ("Keyed HMAC with MD5"); 9847c478bd9Sstevel@tonic-gate default: return ("Unknown BSD"); 9857c478bd9Sstevel@tonic-gate } 9867c478bd9Sstevel@tonic-gate } 9877c478bd9Sstevel@tonic-gate 9887c478bd9Sstevel@tonic-gate static char *slpv2_func(int t, boolean_t s) { 9897c478bd9Sstevel@tonic-gate static char buf[128]; 9907c478bd9Sstevel@tonic-gate 9917c478bd9Sstevel@tonic-gate switch (t) { 9927c478bd9Sstevel@tonic-gate case V2_SRVRQST: return s? "SrvRqst" : "Service Request"; 9937c478bd9Sstevel@tonic-gate case V2_SRVRPLY: return s? "SrvRply" : "Service Reply"; 9947c478bd9Sstevel@tonic-gate case V2_SRVREG: return s? "SrvReg" : "Service Registration"; 9957c478bd9Sstevel@tonic-gate case V2_SRVDEREG: 9967c478bd9Sstevel@tonic-gate return (s ? "SrvDereg" : "Service Deregistration"); 9977c478bd9Sstevel@tonic-gate case V2_SRVACK: return s? "SrvAck" : "Service Acknowledge"; 9987c478bd9Sstevel@tonic-gate case V2_ATTRRQST: return s? "AttrRqst" : "Attribute Request"; 9997c478bd9Sstevel@tonic-gate case V2_ATTRRPLY: return s? "AttrRply" : "Attribute Reply"; 10007c478bd9Sstevel@tonic-gate case V2_DAADVERT: return s? "DAAdvert" : "DA advertisement"; 10017c478bd9Sstevel@tonic-gate case V2_SRVTYPERQST: 10027c478bd9Sstevel@tonic-gate return (s ? "SrvTypeRqst" : "Service Type Request"); 10037c478bd9Sstevel@tonic-gate case V2_SRVTYPERPLY: 10047c478bd9Sstevel@tonic-gate return (s ? "SrvTypeRply" : "Service Type Reply"); 10057c478bd9Sstevel@tonic-gate case V2_SAADVERT: return s? "SAAdvert" : "SA advertisement"; 10067c478bd9Sstevel@tonic-gate } 10077c478bd9Sstevel@tonic-gate sprintf(buf, "(func %d)", t); 10087c478bd9Sstevel@tonic-gate return (s ? buf : "unknown function"); 10097c478bd9Sstevel@tonic-gate } 10107c478bd9Sstevel@tonic-gate 10117c478bd9Sstevel@tonic-gate static char *slpv2_error(unsigned short code) { 10127c478bd9Sstevel@tonic-gate static char buf[128]; 10137c478bd9Sstevel@tonic-gate 10147c478bd9Sstevel@tonic-gate switch (code) { 10157c478bd9Sstevel@tonic-gate case OK: return "ok"; 10167c478bd9Sstevel@tonic-gate case LANG_NOT_SUPPORTED: return "language not supported"; 10177c478bd9Sstevel@tonic-gate case PROTOCOL_PARSE_ERR: return "protocol parse error"; 10187c478bd9Sstevel@tonic-gate case INVALID_REGISTRATION: return "invalid registration"; 10197c478bd9Sstevel@tonic-gate case SCOPE_NOT_SUPPORTED: return "scope not supported"; 10207c478bd9Sstevel@tonic-gate case AUTHENTICATION_UNKNOWN: return "authentication unknown"; 10217c478bd9Sstevel@tonic-gate case V2_AUTHENTICATION_ABSENT: return "authentication absent"; 10227c478bd9Sstevel@tonic-gate case V2_AUTHENTICATION_FAILED: return "authentication failed"; 10237c478bd9Sstevel@tonic-gate case V2_VER_NOT_SUPPORTED: return "version not supported"; 10247c478bd9Sstevel@tonic-gate case V2_INTERNAL_ERROR: return "internal error"; 10257c478bd9Sstevel@tonic-gate case V2_DA_BUSY_NOW: return "DA busy"; 10267c478bd9Sstevel@tonic-gate case V2_OPTION_NOT_UNDERSTOOD: return "option not understood"; 10277c478bd9Sstevel@tonic-gate case V2_INVALID_UPDATE: return "invalid update"; 10287c478bd9Sstevel@tonic-gate case V2_RQST_NOT_SUPPORTED: return "request not supported"; 10297c478bd9Sstevel@tonic-gate case INVALID_LIFETIME: return "invalid lifetime"; 10307c478bd9Sstevel@tonic-gate } 10317c478bd9Sstevel@tonic-gate sprintf(buf, "error %d", code); 10327c478bd9Sstevel@tonic-gate return (buf); 10337c478bd9Sstevel@tonic-gate } 10347c478bd9Sstevel@tonic-gate 10357c478bd9Sstevel@tonic-gate static char *convert_ts(unsigned int timestamp) { 10367c478bd9Sstevel@tonic-gate /* timestamp is in UNIX time */ 10377c478bd9Sstevel@tonic-gate static char buff[128]; 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate strcpy(buff, ctime((time_t *)×tamp)); 10407c478bd9Sstevel@tonic-gate buff[strlen(buff) - 1] = '\0'; 10417c478bd9Sstevel@tonic-gate return (buff); 10427c478bd9Sstevel@tonic-gate } 10437c478bd9Sstevel@tonic-gate 10447c478bd9Sstevel@tonic-gate static int slpv2_authblock(int cnt) { 10457c478bd9Sstevel@tonic-gate unsigned short bsd, length, slen; 10467c478bd9Sstevel@tonic-gate char *pp, *scopes; 10477c478bd9Sstevel@tonic-gate unsigned int timestamp; 10487c478bd9Sstevel@tonic-gate 10497c478bd9Sstevel@tonic-gate if (msglength < 10) { 10507c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 10517c478bd9Sstevel@tonic-gate " [no room for auth block header: remaining msg length = %u]", 10527c478bd9Sstevel@tonic-gate msglength); 10537c478bd9Sstevel@tonic-gate return (-1); 10547c478bd9Sstevel@tonic-gate } 10557c478bd9Sstevel@tonic-gate 10567c478bd9Sstevel@tonic-gate /* bsd */ 10577c478bd9Sstevel@tonic-gate nbtohs(); 10587c478bd9Sstevel@tonic-gate bsd = netval; 10597c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 10607c478bd9Sstevel@tonic-gate 10617c478bd9Sstevel@tonic-gate /* length */ 10627c478bd9Sstevel@tonic-gate nbtohs(); 10637c478bd9Sstevel@tonic-gate length = netval; 10647c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 10657c478bd9Sstevel@tonic-gate 10667c478bd9Sstevel@tonic-gate /* timestamp */ 10677c478bd9Sstevel@tonic-gate nbtohl(); 10687c478bd9Sstevel@tonic-gate timestamp = netval; 10697c478bd9Sstevel@tonic-gate p += 4; 10707c478bd9Sstevel@tonic-gate 10717c478bd9Sstevel@tonic-gate /* SPI String length */ 10727c478bd9Sstevel@tonic-gate nbtohs(); 10737c478bd9Sstevel@tonic-gate slen = netval; 10747c478bd9Sstevel@tonic-gate p += sizeof (unsigned short); 10757c478bd9Sstevel@tonic-gate 10767c478bd9Sstevel@tonic-gate msglength -= 10; 10777c478bd9Sstevel@tonic-gate if (slen > msglength) { 10787c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 10797c478bd9Sstevel@tonic-gate " [no room for auth block scopes: remaining msg length = %u]", 10807c478bd9Sstevel@tonic-gate msglength); 10817c478bd9Sstevel@tonic-gate return (-1); 10827c478bd9Sstevel@tonic-gate } 10837c478bd9Sstevel@tonic-gate 10847c478bd9Sstevel@tonic-gate if (length > (msglength + 10)) { 10857c478bd9Sstevel@tonic-gate if (!tcp_continuation) 10867c478bd9Sstevel@tonic-gate /* framing error: message is not long enough to contain data */ 10877c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 10887c478bd9Sstevel@tonic-gate " [Framing error: remaining pkt length = %u]", 10897c478bd9Sstevel@tonic-gate msglength); 10907c478bd9Sstevel@tonic-gate return (-1); 10917c478bd9Sstevel@tonic-gate } 10927c478bd9Sstevel@tonic-gate 10937c478bd9Sstevel@tonic-gate scopes = p; 10947c478bd9Sstevel@tonic-gate p += slen; 10957c478bd9Sstevel@tonic-gate msglength -= slen; 10967c478bd9Sstevel@tonic-gate 10977c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 10987c478bd9Sstevel@tonic-gate "Auth block %d: timestamp = %s", cnt, 10997c478bd9Sstevel@tonic-gate (timestamp) ? convert_ts(timestamp) : "0"); 11007c478bd9Sstevel@tonic-gate 11017c478bd9Sstevel@tonic-gate pp = get_line(0, 0); 11027c478bd9Sstevel@tonic-gate strcpy(pp, " SPI = "); 11037c478bd9Sstevel@tonic-gate strncat(pp, scopes, slen); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 11067c478bd9Sstevel@tonic-gate " block desc = 0x%04x: %s", bsd, display_bsd(bsd)); 11077c478bd9Sstevel@tonic-gate 11087c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " length = %u", length); 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate p += (length - 10 - slen); 11117c478bd9Sstevel@tonic-gate msglength -= (length - 10 - slen); 11127c478bd9Sstevel@tonic-gate return (0); 11137c478bd9Sstevel@tonic-gate } 11147c478bd9Sstevel@tonic-gate 11157c478bd9Sstevel@tonic-gate static int v2_srv_rqst(int flags) { 11167c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 11177c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* PR list */ 11187c478bd9Sstevel@tonic-gate GETFIELD; /* service type */ 11197c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scopes */ 11207c478bd9Sstevel@tonic-gate strcat(msgend, " ["); 11217c478bd9Sstevel@tonic-gate GETFIELD; /* predicate */ 11227c478bd9Sstevel@tonic-gate strcat(msgend, "]"); 11237c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* SPI */ 11247c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 11257c478bd9Sstevel@tonic-gate DOFIELD("Previous responders", FIELD_DEFAULT); 11267c478bd9Sstevel@tonic-gate DOFIELD("Service type", FIELD_DEFAULT); 11277c478bd9Sstevel@tonic-gate DOFIELD("Scopes", FIELD_DEFAULT); 11287c478bd9Sstevel@tonic-gate DOFIELD("Predicate string", FIELD_DEFAULT); 11297c478bd9Sstevel@tonic-gate DOFIELD("Requested SPI", FIELD_DEFAULT); 11307c478bd9Sstevel@tonic-gate } 11317c478bd9Sstevel@tonic-gate 11327c478bd9Sstevel@tonic-gate return (1); 11337c478bd9Sstevel@tonic-gate } 11347c478bd9Sstevel@tonic-gate 11357c478bd9Sstevel@tonic-gate static int v2_srv_rply(int flags) { 11367c478bd9Sstevel@tonic-gate unsigned short itemcnt, errcode; 11377c478bd9Sstevel@tonic-gate int n; 11387c478bd9Sstevel@tonic-gate 11397c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 11407c478bd9Sstevel@tonic-gate int i, auth_cnt; 11417c478bd9Sstevel@tonic-gate 11427c478bd9Sstevel@tonic-gate GETSHORT(errcode); 11437c478bd9Sstevel@tonic-gate if (errcode != OK) { 11447c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv2_error(errcode)); 11457c478bd9Sstevel@tonic-gate msglength = 0; /* skip rest of message */ 11467c478bd9Sstevel@tonic-gate return (0); 11477c478bd9Sstevel@tonic-gate } else { 11487c478bd9Sstevel@tonic-gate GETSHORT(itemcnt); 11497c478bd9Sstevel@tonic-gate sprintf(msgend, "%d URL entries", itemcnt); 11507c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 11517c478bd9Sstevel@tonic-gate for (n = 0; n < itemcnt; n++) { 11527c478bd9Sstevel@tonic-gate SKIPBYTE; /* reserved */ 11537c478bd9Sstevel@tonic-gate SKIPSHORT; /* lifetime */ 11547c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* URL */ 11557c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 11567c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; auth_cnt++) 11577c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 11587c478bd9Sstevel@tonic-gate return (0); 11597c478bd9Sstevel@tonic-gate } 11607c478bd9Sstevel@tonic-gate #endif 11617c478bd9Sstevel@tonic-gate } 11627c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 11637c478bd9Sstevel@tonic-gate V2_DOERRCODE; 11647c478bd9Sstevel@tonic-gate GETSHORT(itemcnt); 11657c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "URL entry count = %d", itemcnt); 11667c478bd9Sstevel@tonic-gate for (n = 0; n < itemcnt; n++) { 11677c478bd9Sstevel@tonic-gate V2_DOURL(n); 11687c478bd9Sstevel@tonic-gate } 11697c478bd9Sstevel@tonic-gate } 11707c478bd9Sstevel@tonic-gate 11717c478bd9Sstevel@tonic-gate return (1); 11727c478bd9Sstevel@tonic-gate } 11737c478bd9Sstevel@tonic-gate 11747c478bd9Sstevel@tonic-gate static int v2_srv_reg(int flags) { 11757c478bd9Sstevel@tonic-gate int i, auth_cnt; 11767c478bd9Sstevel@tonic-gate 11777c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 11787c478bd9Sstevel@tonic-gate SKIPBYTE; /* reserved */ 11797c478bd9Sstevel@tonic-gate SKIPSHORT; /* lifetime */ 11807c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 11817c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 11827c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 11837c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 11847c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 11857c478bd9Sstevel@tonic-gate return (0); 11867c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* type */ 11877c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scopes */ 11887c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* attrs */ 11897c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 11907c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 11917c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 11927c478bd9Sstevel@tonic-gate return (0); 11937c478bd9Sstevel@tonic-gate #endif 11947c478bd9Sstevel@tonic-gate } if (flags & F_DTAIL) { 11957c478bd9Sstevel@tonic-gate V2_DOURL(-1); 11967c478bd9Sstevel@tonic-gate DOFIELD("Service type", FIELD_DEFAULT); 11977c478bd9Sstevel@tonic-gate DOFIELD("Scopes", FIELD_DEFAULT); 11987c478bd9Sstevel@tonic-gate DOFIELD("Attribute list", FIELD_DEFAULT); 11997c478bd9Sstevel@tonic-gate /* auth */ 12007c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 12017c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 12027c478bd9Sstevel@tonic-gate V2_DOAUTH(i); 12037c478bd9Sstevel@tonic-gate } 12047c478bd9Sstevel@tonic-gate 12057c478bd9Sstevel@tonic-gate return (1); 12067c478bd9Sstevel@tonic-gate } 12077c478bd9Sstevel@tonic-gate 12087c478bd9Sstevel@tonic-gate static int v2_srv_dereg(int flags) { 12097c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 12107c478bd9Sstevel@tonic-gate int i, auth_cnt; 12117c478bd9Sstevel@tonic-gate 12127c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scopes */ 12137c478bd9Sstevel@tonic-gate SKIPBYTE; /* reserved */ 12147c478bd9Sstevel@tonic-gate SKIPSHORT; /* lifetime */ 12157c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 12167c478bd9Sstevel@tonic-gate 12177c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 12187c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 12197c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 12207c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 12217c478bd9Sstevel@tonic-gate return (0); 12227c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* attrs */ 12237c478bd9Sstevel@tonic-gate #endif 12247c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 12257c478bd9Sstevel@tonic-gate DOFIELD("Scopes", FIELD_DEFAULT); 12267c478bd9Sstevel@tonic-gate V2_DOURL(-1); 12277c478bd9Sstevel@tonic-gate DOFIELD("Tag list", FIELD_DEFAULT); 12287c478bd9Sstevel@tonic-gate } 12297c478bd9Sstevel@tonic-gate 12307c478bd9Sstevel@tonic-gate return (1); 12317c478bd9Sstevel@tonic-gate } 12327c478bd9Sstevel@tonic-gate 12337c478bd9Sstevel@tonic-gate static int v2_srv_ack(int flags) { 12347c478bd9Sstevel@tonic-gate unsigned short errcode; 12357c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 12367c478bd9Sstevel@tonic-gate GETSHORT(errcode); 12377c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv2_error(errcode)); 12387c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 12397c478bd9Sstevel@tonic-gate V2_DOERRCODE; 12407c478bd9Sstevel@tonic-gate } 12417c478bd9Sstevel@tonic-gate 12427c478bd9Sstevel@tonic-gate return (1); 12437c478bd9Sstevel@tonic-gate } 12447c478bd9Sstevel@tonic-gate 12457c478bd9Sstevel@tonic-gate static int v2_attr_rqst(int flags) { 12467c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 12477c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* PR list */ 12487c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 12497c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scopes */ 12507c478bd9Sstevel@tonic-gate strcat(msgend, " ["); 12517c478bd9Sstevel@tonic-gate GETFIELD; /* attrs */ 12527c478bd9Sstevel@tonic-gate strcat(msgend, "]"); 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 12557c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* SPI */ 12567c478bd9Sstevel@tonic-gate #endif 12577c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 12587c478bd9Sstevel@tonic-gate DOFIELD("Previous responders", FIELD_DEFAULT); 12597c478bd9Sstevel@tonic-gate DOFIELD("URL", FIELD_DEFAULT); 12607c478bd9Sstevel@tonic-gate DOFIELD("Scopes", FIELD_DEFAULT); 12617c478bd9Sstevel@tonic-gate DOFIELD("Tag list", FIELD_DEFAULT); 12627c478bd9Sstevel@tonic-gate DOFIELD("Requested SPI", FIELD_DEFAULT); 12637c478bd9Sstevel@tonic-gate } 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate return (1); 12667c478bd9Sstevel@tonic-gate } 12677c478bd9Sstevel@tonic-gate 12687c478bd9Sstevel@tonic-gate static int v2_attr_rply(int flags) { 12697c478bd9Sstevel@tonic-gate int auth_cnt, i; 12707c478bd9Sstevel@tonic-gate unsigned short errcode; 12717c478bd9Sstevel@tonic-gate 12727c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 12737c478bd9Sstevel@tonic-gate GETSHORT(errcode); 12747c478bd9Sstevel@tonic-gate if (errcode != OK) { 12757c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv2_error(errcode)); 12767c478bd9Sstevel@tonic-gate msglength = 0; /* skip rest of message */ 12777c478bd9Sstevel@tonic-gate return (0); 12787c478bd9Sstevel@tonic-gate } else { 12797c478bd9Sstevel@tonic-gate GETFIELD; /* attr list */ 12807c478bd9Sstevel@tonic-gate 12817c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 12827c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 12837c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 12847c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 12857c478bd9Sstevel@tonic-gate return (0); 12867c478bd9Sstevel@tonic-gate #endif 12877c478bd9Sstevel@tonic-gate } 12887c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 12897c478bd9Sstevel@tonic-gate V2_DOERRCODE; 12907c478bd9Sstevel@tonic-gate DOFIELD("Attribute list", FIELD_DEFAULT); 12917c478bd9Sstevel@tonic-gate /* auth */ 12927c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 12937c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 12947c478bd9Sstevel@tonic-gate V2_DOAUTH(i); 12957c478bd9Sstevel@tonic-gate } 12967c478bd9Sstevel@tonic-gate 12977c478bd9Sstevel@tonic-gate return (1); 12987c478bd9Sstevel@tonic-gate } 12997c478bd9Sstevel@tonic-gate 13007c478bd9Sstevel@tonic-gate static int v2_daadvert(int flags) { 13017c478bd9Sstevel@tonic-gate int auth_cnt, i; 13027c478bd9Sstevel@tonic-gate unsigned short errcode; 13037c478bd9Sstevel@tonic-gate unsigned int timestamp; 13047c478bd9Sstevel@tonic-gate 13057c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 13067c478bd9Sstevel@tonic-gate SKIPSHORT; /* error code */ 13077c478bd9Sstevel@tonic-gate SKIPSHORT; SKIPSHORT; /* timestamp */ 13087c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 13097c478bd9Sstevel@tonic-gate 13107c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 13117c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scopes */ 13127c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* attrs */ 13137c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* SPIs */ 13147c478bd9Sstevel@tonic-gate 13157c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 13167c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 13177c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 13187c478bd9Sstevel@tonic-gate return (0); 13197c478bd9Sstevel@tonic-gate #endif 13207c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 13217c478bd9Sstevel@tonic-gate V2_DOERRCODE; 13227c478bd9Sstevel@tonic-gate V2_DOTIMESTAMP; 13237c478bd9Sstevel@tonic-gate DOFIELD("URL", FIELD_DEFAULT); 13247c478bd9Sstevel@tonic-gate DOFIELD("Scope list", FIELD_DEFAULT); 13257c478bd9Sstevel@tonic-gate DOFIELD("Attribute list", FIELD_DEFAULT); 13267c478bd9Sstevel@tonic-gate DOFIELD("Configured SPIs", FIELD_DEFAULT); 13277c478bd9Sstevel@tonic-gate /* auth */ 13287c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 13297c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 13307c478bd9Sstevel@tonic-gate V2_DOAUTH(i); 13317c478bd9Sstevel@tonic-gate } 13327c478bd9Sstevel@tonic-gate 13337c478bd9Sstevel@tonic-gate return (1); 13347c478bd9Sstevel@tonic-gate } 13357c478bd9Sstevel@tonic-gate 13367c478bd9Sstevel@tonic-gate static int v2_srv_type_rqst(int flags) { 13377c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 13387c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* prev responders */ 13397c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_TYPENA); /* naming authority */ 13407c478bd9Sstevel@tonic-gate GETFIELD; /* scope */ 13417c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 13427c478bd9Sstevel@tonic-gate DOFIELD("Previous responders", FIELD_DEFAULT); 13437c478bd9Sstevel@tonic-gate DOFIELD("Naming authority", FIELD_TYPENA); 13447c478bd9Sstevel@tonic-gate DOFIELD("Scopes", FIELD_DEFAULT); 13457c478bd9Sstevel@tonic-gate } 13467c478bd9Sstevel@tonic-gate 13477c478bd9Sstevel@tonic-gate return (1); 13487c478bd9Sstevel@tonic-gate } 13497c478bd9Sstevel@tonic-gate 13507c478bd9Sstevel@tonic-gate static int v2_srv_type_rply(int flags) { 13517c478bd9Sstevel@tonic-gate unsigned short errcode; 13527c478bd9Sstevel@tonic-gate 13537c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 13547c478bd9Sstevel@tonic-gate GETSHORT(errcode); 13557c478bd9Sstevel@tonic-gate if (errcode != OK) 13567c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv2_error(errcode)); 13577c478bd9Sstevel@tonic-gate else 13587c478bd9Sstevel@tonic-gate GETFIELD; 13597c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 13607c478bd9Sstevel@tonic-gate V2_DOERRCODE; 13617c478bd9Sstevel@tonic-gate DOFIELD("Service types", FIELD_DEFAULT); 13627c478bd9Sstevel@tonic-gate } 13637c478bd9Sstevel@tonic-gate 13647c478bd9Sstevel@tonic-gate return (1); 13657c478bd9Sstevel@tonic-gate } 13667c478bd9Sstevel@tonic-gate 13677c478bd9Sstevel@tonic-gate static int v2_saadvert(int flags) { 13687c478bd9Sstevel@tonic-gate int auth_cnt, i; 13697c478bd9Sstevel@tonic-gate 13707c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 13717c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 13727c478bd9Sstevel@tonic-gate 13737c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 13747c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scopes */ 13757c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* attrs */ 13767c478bd9Sstevel@tonic-gate 13777c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 13787c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 13797c478bd9Sstevel@tonic-gate if (skip_v2authblock() < 0) 13807c478bd9Sstevel@tonic-gate return (0); 13817c478bd9Sstevel@tonic-gate #endif 13827c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 13837c478bd9Sstevel@tonic-gate DOFIELD("URL", FIELD_DEFAULT); 13847c478bd9Sstevel@tonic-gate DOFIELD("Scopes", FIELD_DEFAULT); 13857c478bd9Sstevel@tonic-gate DOFIELD("Attribute list", FIELD_DEFAULT); 13867c478bd9Sstevel@tonic-gate /* auth */ 13877c478bd9Sstevel@tonic-gate GETBYTE(auth_cnt); 13887c478bd9Sstevel@tonic-gate for (i = 0; i < auth_cnt; i++) 13897c478bd9Sstevel@tonic-gate V2_DOAUTH(i); 13907c478bd9Sstevel@tonic-gate } 13917c478bd9Sstevel@tonic-gate 13927c478bd9Sstevel@tonic-gate return (1); 13937c478bd9Sstevel@tonic-gate } 13947c478bd9Sstevel@tonic-gate 13957c478bd9Sstevel@tonic-gate /* 13967c478bd9Sstevel@tonic-gate * V1 Interpreter 13977c478bd9Sstevel@tonic-gate */ 13987c478bd9Sstevel@tonic-gate 13997c478bd9Sstevel@tonic-gate static int interpret_slp_v1(int flags, struct slpv1_hdr *slp, int fraglen) { 14007c478bd9Sstevel@tonic-gate char msgbuf_real[256]; 14017c478bd9Sstevel@tonic-gate extern int src_port, dst_port, curr_proto; 14027c478bd9Sstevel@tonic-gate boolean_t overflow = B_FALSE; 14037c478bd9Sstevel@tonic-gate 14047c478bd9Sstevel@tonic-gate msgbuf = msgbuf_real; 14057c478bd9Sstevel@tonic-gate 14067c478bd9Sstevel@tonic-gate if (msglength >= sizeof (*slp)) { 14077c478bd9Sstevel@tonic-gate if ((slp->flags & V1_URL_AUTH) == V1_URL_AUTH) 14087c478bd9Sstevel@tonic-gate url_auth = B_TRUE; 14097c478bd9Sstevel@tonic-gate if ((slp->flags & V1_ATTR_AUTH) == V1_ATTR_AUTH) 14107c478bd9Sstevel@tonic-gate attr_auth = B_TRUE; 14117c478bd9Sstevel@tonic-gate if ((slp->flags & V1_FRESH_REG) == V1_FRESH_REG) 14127c478bd9Sstevel@tonic-gate fresh = B_TRUE; 14137c478bd9Sstevel@tonic-gate if ((slp->flags & V1_OVERFLOW) == V1_OVERFLOW) 14147c478bd9Sstevel@tonic-gate overflow = B_TRUE; 14157c478bd9Sstevel@tonic-gate } 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate /* 14187c478bd9Sstevel@tonic-gate * Somewhat of a hack to decode traffic from a server that does 14197c478bd9Sstevel@tonic-gate * not send udp replies from its SLP src port. 14207c478bd9Sstevel@tonic-gate */ 14217c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_UDP && 14227c478bd9Sstevel@tonic-gate dst_port == 427 && 14237c478bd9Sstevel@tonic-gate src_port != 427) 1424*d6913e07SToomas Soome add_transient(src_port, interpret_slp); 14257c478bd9Sstevel@tonic-gate 14267c478bd9Sstevel@tonic-gate /* parse the header */ 14277c478bd9Sstevel@tonic-gate if (v1_header(flags, slp, fraglen)) { 14287c478bd9Sstevel@tonic-gate 14297c478bd9Sstevel@tonic-gate if (slp->function <= V1_MAX_FUNCTION && slp->function > 0) { 14307c478bd9Sstevel@tonic-gate 14317c478bd9Sstevel@tonic-gate /* Parse the message body */ 14327c478bd9Sstevel@tonic-gate (v1_functions[slp->function])(flags); 14337c478bd9Sstevel@tonic-gate 14347c478bd9Sstevel@tonic-gate } 14357c478bd9Sstevel@tonic-gate 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate /* summary error check */ 14397c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 14407c478bd9Sstevel@tonic-gate if (retlength < 0) { 14417c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_TCP) 14427c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), 14437c478bd9Sstevel@tonic-gate "%s [partial TCP message]", 14447c478bd9Sstevel@tonic-gate msgbuf); 14457c478bd9Sstevel@tonic-gate else if (overflow) 14467c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s [OVERFLOW]", msgbuf); 14477c478bd9Sstevel@tonic-gate else 14487c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s [CORRUPTED MESSAGE]", msgbuf); 14497c478bd9Sstevel@tonic-gate } 14507c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 14517c478bd9Sstevel@tonic-gate else if (msglength > 0) 14527c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s +%d", msgbuf, msglength); 14537c478bd9Sstevel@tonic-gate #endif 14547c478bd9Sstevel@tonic-gate else 14557c478bd9Sstevel@tonic-gate sprintf(get_sum_line(), "%s", msgbuf); 14567c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 14577c478bd9Sstevel@tonic-gate /* detail error check */ 14587c478bd9Sstevel@tonic-gate if (msglength > 0) { 14597c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 14607c478bd9Sstevel@tonic-gate "[%d extra bytes at end of SLP message]", msglength); 14617c478bd9Sstevel@tonic-gate } 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate show_trailer(); 14647c478bd9Sstevel@tonic-gate 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate v1_charset = 0; 14687c478bd9Sstevel@tonic-gate 14697c478bd9Sstevel@tonic-gate return (0); 14707c478bd9Sstevel@tonic-gate } 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate static int v1_header(int flags, 14737c478bd9Sstevel@tonic-gate struct slpv1_hdr *slp, 14747c478bd9Sstevel@tonic-gate int fraglen) { 14757c478bd9Sstevel@tonic-gate extern int src_port, dst_port, curr_proto; 14767c478bd9Sstevel@tonic-gate char *prototag = (curr_proto == IPPROTO_TCP? "/tcp" : ""); 14777c478bd9Sstevel@tonic-gate 14787c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 14797c478bd9Sstevel@tonic-gate char portflag = ' '; 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate if (msglength < sizeof (*slp)) { 14827c478bd9Sstevel@tonic-gate sprintf(msgbuf, "SLP V1 [incomplete header]"); 14837c478bd9Sstevel@tonic-gate return (0); 14847c478bd9Sstevel@tonic-gate } 14857c478bd9Sstevel@tonic-gate 14867c478bd9Sstevel@tonic-gate if (slp->vers != 1) { 14877c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_TCP) 14887c478bd9Sstevel@tonic-gate sprintf(msgbuf, "SLP [TCP Continuation]"); 14897c478bd9Sstevel@tonic-gate else 14907c478bd9Sstevel@tonic-gate sprintf(msgbuf, "SLP [unknown version %d]", slp->vers); 14917c478bd9Sstevel@tonic-gate return (0); 14927c478bd9Sstevel@tonic-gate } 14937c478bd9Sstevel@tonic-gate 14947c478bd9Sstevel@tonic-gate if (src_port != 427 && dst_port != 427) 14957c478bd9Sstevel@tonic-gate portflag = '-'; 14967c478bd9Sstevel@tonic-gate 14977c478bd9Sstevel@tonic-gate sprintf(msgbuf, "SLP V1%c%s [%d%s] ", portflag, 14987c478bd9Sstevel@tonic-gate slpv1_func(slp->function, B_TRUE), 14997c478bd9Sstevel@tonic-gate ntohs(slp->xid), prototag); 15007c478bd9Sstevel@tonic-gate msgend = msgbuf + strlen(msgbuf); 15017c478bd9Sstevel@tonic-gate msglength -= sizeof (*slp); 15027c478bd9Sstevel@tonic-gate p += sizeof (*slp); 15037c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 15047c478bd9Sstevel@tonic-gate show_header("SLP: ", "Service Location Protocol (v1)", fraglen); 15057c478bd9Sstevel@tonic-gate show_space(); 15067c478bd9Sstevel@tonic-gate 15077c478bd9Sstevel@tonic-gate if (msglength < sizeof (*slp)) { 15087c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "==> Incomplete SLP header"); 15097c478bd9Sstevel@tonic-gate return (0); 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Version = %d", slp->vers); 15137c478bd9Sstevel@tonic-gate if (slp->vers != 1) { 15147c478bd9Sstevel@tonic-gate if (curr_proto == IPPROTO_TCP) 15157c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "==> TCP continuation"); 15167c478bd9Sstevel@tonic-gate else 15177c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "==> Unexpected version number"); 15187c478bd9Sstevel@tonic-gate return (0); 15197c478bd9Sstevel@tonic-gate } 15207c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Function = %d, %s", 15217c478bd9Sstevel@tonic-gate slp->function, slpv1_func(slp->function, B_FALSE)); 15227c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Message length = %u", ntohs(slp->length)); 15237c478bd9Sstevel@tonic-gate 15247c478bd9Sstevel@tonic-gate /* flags */ 15257c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Flags = 0x%02x", slp->flags); 15267c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 15277c478bd9Sstevel@tonic-gate getflag(slp->flags, V1_OVERFLOW, 15287c478bd9Sstevel@tonic-gate "overflow", "no overflow")); 15297c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 15307c478bd9Sstevel@tonic-gate getflag(slp->flags, V1_MONOLINGUAL, 15317c478bd9Sstevel@tonic-gate "monolingual", "not monolingual")); 15327c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 15337c478bd9Sstevel@tonic-gate getflag(slp->flags, V1_URL_AUTH, 15347c478bd9Sstevel@tonic-gate "url authentication", "no url authentication")); 15357c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 15367c478bd9Sstevel@tonic-gate getflag(slp->flags, V1_ATTR_AUTH, 15377c478bd9Sstevel@tonic-gate "attribute authentication", "no attribute authentication")); 15387c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " %s", 15397c478bd9Sstevel@tonic-gate getflag(slp->flags, V1_FRESH_REG, 15407c478bd9Sstevel@tonic-gate "fresh registration", "no fresh registration")); 15417c478bd9Sstevel@tonic-gate /* check reserved flags that must be zero */ 15427c478bd9Sstevel@tonic-gate if ((slp->flags & 7) != 0) { 15437c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 15447c478bd9Sstevel@tonic-gate " .... .xxx = %d (reserved flags nonzero)", 15457c478bd9Sstevel@tonic-gate slp->flags & 7); 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate /* end of flags */ 15487c478bd9Sstevel@tonic-gate 15497c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Dialect = %u", slp->dialect); 15507c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Language = 0x%02x%02x, %c%c", 15517c478bd9Sstevel@tonic-gate slp->language[0], slp->language[1], 15527c478bd9Sstevel@tonic-gate slp->language[0], slp->language[1]); 15537c478bd9Sstevel@tonic-gate v1_charset = ntohs(slp->charset); 15547c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Character encoding = %u, %s", 15557c478bd9Sstevel@tonic-gate v1_charset, 15567c478bd9Sstevel@tonic-gate slpv1_charset(v1_charset)); 15577c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "XID = %u", ntohs(slp->xid)); 15587c478bd9Sstevel@tonic-gate 15597c478bd9Sstevel@tonic-gate /* set msglength to remaining length of SLP message */ 15607c478bd9Sstevel@tonic-gate msglength -= sizeof (*slp); 15617c478bd9Sstevel@tonic-gate p += sizeof (*slp); 15627c478bd9Sstevel@tonic-gate } 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate return (1); 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate static char *slpv1_func(int t, boolean_t s) { 15687c478bd9Sstevel@tonic-gate static char buf[128]; 15697c478bd9Sstevel@tonic-gate switch (t) { 15707c478bd9Sstevel@tonic-gate case V1_SRVREQ: return s? "SrvRqst" : "Service Request"; 15717c478bd9Sstevel@tonic-gate case V1_SRVRPLY: return s? "SrvRply" : "Service Reply"; 15727c478bd9Sstevel@tonic-gate case V1_SRVREG: return s? "SrvReg" : "Service Registration"; 15737c478bd9Sstevel@tonic-gate case V1_SRVDEREG: return s? 15747c478bd9Sstevel@tonic-gate "SrvDereg" : "Service Deregistration"; 15757c478bd9Sstevel@tonic-gate case V1_SRVACK: return s? "SrvAck" : "Service Acknowledge"; 15767c478bd9Sstevel@tonic-gate case V1_ATTRRQST: return s? "AttrRqst" : "Attribute Request"; 15777c478bd9Sstevel@tonic-gate case V1_ATTRRPLY: return s? "AttrRply" : "Attribute Reply"; 15787c478bd9Sstevel@tonic-gate case V1_DAADVERT: return s? "DAAdvert" : "DA advertisement"; 15797c478bd9Sstevel@tonic-gate case V1_SRVTYPERQST:return s? "SrvTypeRqst" : "Service Type Request"; 15807c478bd9Sstevel@tonic-gate case V1_SRVTYPERPLY:return s? "SrvTypeRply" : "Service Type Reply"; 15817c478bd9Sstevel@tonic-gate } 15827c478bd9Sstevel@tonic-gate sprintf(buf, "(func %d)", t); 15837c478bd9Sstevel@tonic-gate return (s ? buf : "unknown function"); 15847c478bd9Sstevel@tonic-gate } 15857c478bd9Sstevel@tonic-gate 15867c478bd9Sstevel@tonic-gate static char *slpv1_error(unsigned short code) { 15877c478bd9Sstevel@tonic-gate static char buf[128]; 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate switch (code) { 15907c478bd9Sstevel@tonic-gate case OK: return "ok"; 15917c478bd9Sstevel@tonic-gate case LANG_NOT_SUPPORTED: return "language not supported"; 15927c478bd9Sstevel@tonic-gate case PROTOCOL_PARSE_ERR: return "protocol parse error"; 15937c478bd9Sstevel@tonic-gate case INVALID_REGISTRATION: return "invalid registration"; 15947c478bd9Sstevel@tonic-gate case SCOPE_NOT_SUPPORTED: return "scope not supported"; 15957c478bd9Sstevel@tonic-gate case CHARSET_NOT_UNDERSTOOD:return "character set not understood"; 15967c478bd9Sstevel@tonic-gate case AUTHENTICATION_INVALID:return "invalid authentication"; 15977c478bd9Sstevel@tonic-gate case NOT_SUPPORTED_YET: return "not yet supported"; 15987c478bd9Sstevel@tonic-gate case REQUEST_TIMED_OUT: return "request timed out"; 15997c478bd9Sstevel@tonic-gate case COULD_NOT_INIT_NET_RESOURCES: 16007c478bd9Sstevel@tonic-gate return ("could not initialize net resources"); 16017c478bd9Sstevel@tonic-gate case COULD_NOT_ALLOCATE_MEMORY: 16027c478bd9Sstevel@tonic-gate return ("could not allocate memory"); 16037c478bd9Sstevel@tonic-gate case PARAMETER_BAD: return "bad parameter"; 16047c478bd9Sstevel@tonic-gate case INTERNAL_NET_ERROR: return "internal network error"; 16057c478bd9Sstevel@tonic-gate case INTERNAL_SYSTEM_ERROR: return "internal system error"; 16067c478bd9Sstevel@tonic-gate } 16077c478bd9Sstevel@tonic-gate sprintf(buf, "error %d", code); 16087c478bd9Sstevel@tonic-gate return (buf); 16097c478bd9Sstevel@tonic-gate } 16107c478bd9Sstevel@tonic-gate 16117c478bd9Sstevel@tonic-gate /* 16127c478bd9Sstevel@tonic-gate * Character set info from 16137c478bd9Sstevel@tonic-gate * www.isi.edu/in-notes/iana/assignments/character-sets 16147c478bd9Sstevel@tonic-gate * 16157c478bd9Sstevel@tonic-gate * Assigned MIB enum Numbers 16167c478bd9Sstevel@tonic-gate * ------------------------- 16177c478bd9Sstevel@tonic-gate * 0 Reserved 16187c478bd9Sstevel@tonic-gate * 1 Reserved 16197c478bd9Sstevel@tonic-gate * 3-106 Set By Standards Organizations 16207c478bd9Sstevel@tonic-gate * 1000-1010 Unicode / 10646 16217c478bd9Sstevel@tonic-gate * 2000-2087 Vendor 16227c478bd9Sstevel@tonic-gate * 2250-2258 Vendor 16237c478bd9Sstevel@tonic-gate * 16247c478bd9Sstevel@tonic-gate * MIBenum: 3 16257c478bd9Sstevel@tonic-gate * Alias: US-ASCII (preferred MIME name) 16267c478bd9Sstevel@tonic-gate * Source: ECMA registry [RFC1345] 16277c478bd9Sstevel@tonic-gate * 16287c478bd9Sstevel@tonic-gate * MIBenum: 106 16297c478bd9Sstevel@tonic-gate * Name: UTF-8 16307c478bd9Sstevel@tonic-gate * Source: RFC 2044 16317c478bd9Sstevel@tonic-gate */ 16327c478bd9Sstevel@tonic-gate 16337c478bd9Sstevel@tonic-gate static char *slpv1_charset(unsigned short code) { 16347c478bd9Sstevel@tonic-gate if (code <= 1) 16357c478bd9Sstevel@tonic-gate return ("Reserved"); 16367c478bd9Sstevel@tonic-gate if (code == 3) 16377c478bd9Sstevel@tonic-gate return ("US-ASCII"); 16387c478bd9Sstevel@tonic-gate if (code == 4) 16397c478bd9Sstevel@tonic-gate return ("latin1"); 16407c478bd9Sstevel@tonic-gate if (code == 106) 16417c478bd9Sstevel@tonic-gate return ("UTF-8"); 16427c478bd9Sstevel@tonic-gate if (code >= 3 && code <= 106) 16437c478bd9Sstevel@tonic-gate return ("set by standards organization"); 16447c478bd9Sstevel@tonic-gate if (code >= 1000 && code <= 1010) 16457c478bd9Sstevel@tonic-gate return ("Unicode variant"); 16467c478bd9Sstevel@tonic-gate if ((code >= 2000 && code <= 2087) || 16477c478bd9Sstevel@tonic-gate (code >= 2250 && code <= 2258)) 16487c478bd9Sstevel@tonic-gate return ("Vendor assigned"); 16497c478bd9Sstevel@tonic-gate 16507c478bd9Sstevel@tonic-gate return ("unknown"); 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 16547c478bd9Sstevel@tonic-gate static int skip_v1authblock() { 16557c478bd9Sstevel@tonic-gate unsigned short length; 16567c478bd9Sstevel@tonic-gate 16577c478bd9Sstevel@tonic-gate /* auth header: 12 bytes total */ 16587c478bd9Sstevel@tonic-gate if (msglength < 12) 16597c478bd9Sstevel@tonic-gate return (-1); 16607c478bd9Sstevel@tonic-gate 16617c478bd9Sstevel@tonic-gate /* timestamp: 8 bytes */ 16627c478bd9Sstevel@tonic-gate p += 8; /* timestamp: 8 bytes */ 16637c478bd9Sstevel@tonic-gate p += sizeof (short); /* block descriptor: 2 bytes */ 16647c478bd9Sstevel@tonic-gate nbtohs(); 16657c478bd9Sstevel@tonic-gate length = netval; 16667c478bd9Sstevel@tonic-gate p += sizeof (short); 16677c478bd9Sstevel@tonic-gate msglength -= 12; 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if (length > msglength) { 16707c478bd9Sstevel@tonic-gate /* framing error: message is not long enough to contain data */ 16717c478bd9Sstevel@tonic-gate return (-1); 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate p += length; 16757c478bd9Sstevel@tonic-gate msglength -= length; 16767c478bd9Sstevel@tonic-gate return (0); 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate #endif 16797c478bd9Sstevel@tonic-gate 16807c478bd9Sstevel@tonic-gate static int slpv1_authblock() { 16817c478bd9Sstevel@tonic-gate unsigned short bsd, length; 16827c478bd9Sstevel@tonic-gate char msgbuf[128]; 16837c478bd9Sstevel@tonic-gate int n; 16847c478bd9Sstevel@tonic-gate 16857c478bd9Sstevel@tonic-gate if (msglength < 12) { 16867c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 16877c478bd9Sstevel@tonic-gate " [no room for auth block: remaining msg length = %u]", 16887c478bd9Sstevel@tonic-gate msglength); 16897c478bd9Sstevel@tonic-gate return (-1); 16907c478bd9Sstevel@tonic-gate } 16917c478bd9Sstevel@tonic-gate 16927c478bd9Sstevel@tonic-gate /* timestamp: 8 bytes */ 16937c478bd9Sstevel@tonic-gate *msgbuf = '\0'; 16947c478bd9Sstevel@tonic-gate for (n = 0; n < 8; n++, p += 1) { 16957c478bd9Sstevel@tonic-gate char tmp[16]; 16967c478bd9Sstevel@tonic-gate sprintf(tmp, "%02x", (unsigned char)(*p)); 16977c478bd9Sstevel@tonic-gate strcat(msgbuf, tmp); 16987c478bd9Sstevel@tonic-gate } 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate nbtohs(); 17017c478bd9Sstevel@tonic-gate bsd = netval; 17027c478bd9Sstevel@tonic-gate p += sizeof (short); 17037c478bd9Sstevel@tonic-gate nbtohs(); 17047c478bd9Sstevel@tonic-gate length = netval; 17057c478bd9Sstevel@tonic-gate p += sizeof (short); 17067c478bd9Sstevel@tonic-gate msglength -= 12; 17077c478bd9Sstevel@tonic-gate 17087c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 17097c478bd9Sstevel@tonic-gate " Auth block: timestamp = %s", 17107c478bd9Sstevel@tonic-gate msgbuf); 17117c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 17127c478bd9Sstevel@tonic-gate " block desc = 0x%04x, length = %u", 17137c478bd9Sstevel@tonic-gate bsd, length); 17147c478bd9Sstevel@tonic-gate if (length > msglength) { 17157c478bd9Sstevel@tonic-gate /* framing error: message is not long enough to contain data */ 17167c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 17177c478bd9Sstevel@tonic-gate " [Framing error: remaining pkt length = %u]", msglength); 17187c478bd9Sstevel@tonic-gate return (-1); 17197c478bd9Sstevel@tonic-gate } 17207c478bd9Sstevel@tonic-gate 17217c478bd9Sstevel@tonic-gate p += length; 17227c478bd9Sstevel@tonic-gate msglength -= length; 17237c478bd9Sstevel@tonic-gate return (0); 17247c478bd9Sstevel@tonic-gate } 17257c478bd9Sstevel@tonic-gate 17267c478bd9Sstevel@tonic-gate static int slpv1_url(boolean_t auth_present) { 17277c478bd9Sstevel@tonic-gate time_t exp; 17287c478bd9Sstevel@tonic-gate int lifetime, length; 17297c478bd9Sstevel@tonic-gate 17307c478bd9Sstevel@tonic-gate get_short(); 17317c478bd9Sstevel@tonic-gate if ((lifetime = netval) < 0) 17327c478bd9Sstevel@tonic-gate return (-1); 17337c478bd9Sstevel@tonic-gate get_short(); 17347c478bd9Sstevel@tonic-gate if ((length = netval) < 0) 17357c478bd9Sstevel@tonic-gate return (-1); 17367c478bd9Sstevel@tonic-gate 17377c478bd9Sstevel@tonic-gate exp = time(0) + lifetime; 17387c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "URL: length = %u, lifetime = %d (%24.24s)", 17397c478bd9Sstevel@tonic-gate length, lifetime, ctime(&exp)); 17407c478bd9Sstevel@tonic-gate if (length > msglength) { 17417c478bd9Sstevel@tonic-gate /* framing error: message is not long enough to contain data */ 17427c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), 17437c478bd9Sstevel@tonic-gate " [Framing error: remaining pkt length = %u]", msglength); 17447c478bd9Sstevel@tonic-gate return (-1); 17457c478bd9Sstevel@tonic-gate } 17467c478bd9Sstevel@tonic-gate 17477c478bd9Sstevel@tonic-gate if (length > 0) { 17487c478bd9Sstevel@tonic-gate char *buf = malloc(length + 1); 17497c478bd9Sstevel@tonic-gate if (buf != NULL) { 17507c478bd9Sstevel@tonic-gate if (!make_utf8(buf, length, p, length)) { 17517c478bd9Sstevel@tonic-gate strcpy(buf, "[Invalid Character Encoding]"); 17527c478bd9Sstevel@tonic-gate } 17537c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), " \"%s\"", buf); 17547c478bd9Sstevel@tonic-gate free(buf); 17557c478bd9Sstevel@tonic-gate } 17567c478bd9Sstevel@tonic-gate } 17577c478bd9Sstevel@tonic-gate msglength -= length; 17587c478bd9Sstevel@tonic-gate p += length; 17597c478bd9Sstevel@tonic-gate 17607c478bd9Sstevel@tonic-gate if (auth_present) 17617c478bd9Sstevel@tonic-gate return (slpv1_authblock()); 17627c478bd9Sstevel@tonic-gate 17637c478bd9Sstevel@tonic-gate return (0); 17647c478bd9Sstevel@tonic-gate } 17657c478bd9Sstevel@tonic-gate 17667c478bd9Sstevel@tonic-gate static int v1_srv_rqst(int flags) { 17677c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 17687c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_PREVRESP); /* prev responders */ 17697c478bd9Sstevel@tonic-gate GETFIELD; /* predicate */ 17707c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 17717c478bd9Sstevel@tonic-gate DOFIELD("Previous responders", FIELD_PREVRESP); 17727c478bd9Sstevel@tonic-gate DOFIELD("predicate string", FIELD_DEFAULT); 17737c478bd9Sstevel@tonic-gate } 17747c478bd9Sstevel@tonic-gate 17757c478bd9Sstevel@tonic-gate return (1); 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate static int v1_srv_rply(int flags) { 17797c478bd9Sstevel@tonic-gate unsigned short errcode, itemcnt; 17807c478bd9Sstevel@tonic-gate int n; 17817c478bd9Sstevel@tonic-gate 17827c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 17837c478bd9Sstevel@tonic-gate GETSHORT(errcode); 17847c478bd9Sstevel@tonic-gate if (errcode != OK) { 17857c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv1_error(errcode)); 17867c478bd9Sstevel@tonic-gate } else { 17877c478bd9Sstevel@tonic-gate GETSHORT(itemcnt); 17887c478bd9Sstevel@tonic-gate sprintf(msgend, "%d URL entries", itemcnt); 17897c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 17907c478bd9Sstevel@tonic-gate for (n = 0; n < itemcnt; n++) { 17917c478bd9Sstevel@tonic-gate SKIPSHORT; /* lifetime */ 17927c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* URL */ 17937c478bd9Sstevel@tonic-gate SKIPAUTH(url_auth); /* URL auth */ 17947c478bd9Sstevel@tonic-gate } 17957c478bd9Sstevel@tonic-gate #endif 17967c478bd9Sstevel@tonic-gate } 17977c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 17987c478bd9Sstevel@tonic-gate DOERRCODE; 17997c478bd9Sstevel@tonic-gate GETSHORT(itemcnt); 18007c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "URL entry count = %d", itemcnt); 18017c478bd9Sstevel@tonic-gate for (n = 0; n < itemcnt; n++) { 18027c478bd9Sstevel@tonic-gate DOURL; 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate } 18057c478bd9Sstevel@tonic-gate 18067c478bd9Sstevel@tonic-gate return (1); 18077c478bd9Sstevel@tonic-gate } 18087c478bd9Sstevel@tonic-gate 18097c478bd9Sstevel@tonic-gate static int v1_srv_reg(int flags) { 18107c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 18117c478bd9Sstevel@tonic-gate SKIPSHORT; /* lifetime */ 18127c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 18137c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 18147c478bd9Sstevel@tonic-gate SKIPAUTH(url_auth); /* URL auth */ 18157c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* attribute list */ 18167c478bd9Sstevel@tonic-gate SKIPAUTH(attr_auth); /* attr auth */ 18177c478bd9Sstevel@tonic-gate #endif 18187c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 18197c478bd9Sstevel@tonic-gate DOURL; 18207c478bd9Sstevel@tonic-gate DOFIELD("Attribute list", FIELD_DEFAULT); 18217c478bd9Sstevel@tonic-gate DOAUTH(attr_auth); 18227c478bd9Sstevel@tonic-gate } 18237c478bd9Sstevel@tonic-gate 18247c478bd9Sstevel@tonic-gate return (1); 18257c478bd9Sstevel@tonic-gate } 18267c478bd9Sstevel@tonic-gate 18277c478bd9Sstevel@tonic-gate static int v1_srv_ack(int flags) { 18287c478bd9Sstevel@tonic-gate unsigned short errcode; 18297c478bd9Sstevel@tonic-gate 18307c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 18317c478bd9Sstevel@tonic-gate GETSHORT(errcode); 18327c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv1_error(errcode)); 18337c478bd9Sstevel@tonic-gate if (errcode == OK && fresh) { 18347c478bd9Sstevel@tonic-gate strcat(msgbuf, " [Fresh]"); 18357c478bd9Sstevel@tonic-gate } 18367c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 18377c478bd9Sstevel@tonic-gate DOERRCODE; 18387c478bd9Sstevel@tonic-gate } 18397c478bd9Sstevel@tonic-gate 18407c478bd9Sstevel@tonic-gate return (1); 18417c478bd9Sstevel@tonic-gate } 18427c478bd9Sstevel@tonic-gate 18437c478bd9Sstevel@tonic-gate static int v1_srv_dereg(int flags) { 18447c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 18457c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 18467c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 18477c478bd9Sstevel@tonic-gate SKIPAUTH(url_auth); 18487c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* tag spec */ 18497c478bd9Sstevel@tonic-gate #endif 18507c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 18517c478bd9Sstevel@tonic-gate DOFIELD("URL", FIELD_DEFAULT); 18527c478bd9Sstevel@tonic-gate DOAUTH(url_auth); 18537c478bd9Sstevel@tonic-gate DOFIELD("Tag spec", FIELD_DEFAULT); 18547c478bd9Sstevel@tonic-gate } 18557c478bd9Sstevel@tonic-gate 18567c478bd9Sstevel@tonic-gate return (1); 18577c478bd9Sstevel@tonic-gate } 18587c478bd9Sstevel@tonic-gate 18597c478bd9Sstevel@tonic-gate static int v1_attr_rqst(int flags) { 18607c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 18617c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_PREVRESP); /* prev responders */ 18627c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 18637c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 18647c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scope */ 18657c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* select list */ 18667c478bd9Sstevel@tonic-gate #endif 18677c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 18687c478bd9Sstevel@tonic-gate DOFIELD("Previous responders", FIELD_PREVRESP); 18697c478bd9Sstevel@tonic-gate DOFIELD("URL", FIELD_DEFAULT); 18707c478bd9Sstevel@tonic-gate DOFIELD("Scope", FIELD_DEFAULT); 18717c478bd9Sstevel@tonic-gate DOFIELD("Select list", FIELD_DEFAULT); 18727c478bd9Sstevel@tonic-gate } 18737c478bd9Sstevel@tonic-gate 18747c478bd9Sstevel@tonic-gate return (1); 18757c478bd9Sstevel@tonic-gate } 18767c478bd9Sstevel@tonic-gate 18777c478bd9Sstevel@tonic-gate static int v1_attr_rply(int flags) { 18787c478bd9Sstevel@tonic-gate unsigned short errcode; 18797c478bd9Sstevel@tonic-gate 18807c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 18817c478bd9Sstevel@tonic-gate GETSHORT(errcode); 18827c478bd9Sstevel@tonic-gate if (errcode != OK) { 18837c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv1_error(errcode)); 18847c478bd9Sstevel@tonic-gate } else { 18857c478bd9Sstevel@tonic-gate GETFIELD; /* attr list */ 18867c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 18877c478bd9Sstevel@tonic-gate SKIPAUTH(attr_auth); 18887c478bd9Sstevel@tonic-gate #endif 18897c478bd9Sstevel@tonic-gate } 18907c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 18917c478bd9Sstevel@tonic-gate DOERRCODE; 18927c478bd9Sstevel@tonic-gate DOFIELD("Attribute list", FIELD_DEFAULT); 18937c478bd9Sstevel@tonic-gate DOAUTH(attr_auth); 18947c478bd9Sstevel@tonic-gate } 18957c478bd9Sstevel@tonic-gate 18967c478bd9Sstevel@tonic-gate return (1); 18977c478bd9Sstevel@tonic-gate } 18987c478bd9Sstevel@tonic-gate 18997c478bd9Sstevel@tonic-gate static int v1_daadvert(int flags) { 19007c478bd9Sstevel@tonic-gate unsigned short errcode; 19017c478bd9Sstevel@tonic-gate 19027c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 19037c478bd9Sstevel@tonic-gate GETSHORT(errcode); 19047c478bd9Sstevel@tonic-gate if (errcode != OK) { 19057c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv1_error(errcode)); 19067c478bd9Sstevel@tonic-gate } else { 19077c478bd9Sstevel@tonic-gate GETFIELD; /* URL */ 19087c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 19097c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* scope list */ 19107c478bd9Sstevel@tonic-gate #endif 19117c478bd9Sstevel@tonic-gate } 19127c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 19137c478bd9Sstevel@tonic-gate DOERRCODE; 19147c478bd9Sstevel@tonic-gate DOFIELD("URL", FIELD_DEFAULT); 19157c478bd9Sstevel@tonic-gate DOFIELD("Scope list", FIELD_DEFAULT); 19167c478bd9Sstevel@tonic-gate } 19177c478bd9Sstevel@tonic-gate 19187c478bd9Sstevel@tonic-gate return (1); 19197c478bd9Sstevel@tonic-gate } 19207c478bd9Sstevel@tonic-gate 19217c478bd9Sstevel@tonic-gate static int v1_srv_type_rqst(int flags) { 19227c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 19237c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_PREVRESP); /* prev responders */ 19247c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_TYPENA); /* naming authority */ 19257c478bd9Sstevel@tonic-gate GETFIELD; /* scope */ 19267c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 19277c478bd9Sstevel@tonic-gate DOFIELD("Previous responders", FIELD_PREVRESP); 19287c478bd9Sstevel@tonic-gate DOFIELD("Naming authority", FIELD_TYPENA); 19297c478bd9Sstevel@tonic-gate DOFIELD("Scope string", FIELD_DEFAULT); 19307c478bd9Sstevel@tonic-gate } 19317c478bd9Sstevel@tonic-gate 19327c478bd9Sstevel@tonic-gate return (1); 19337c478bd9Sstevel@tonic-gate } 19347c478bd9Sstevel@tonic-gate 19357c478bd9Sstevel@tonic-gate static int v1_srv_type_rply(int flags) { 19367c478bd9Sstevel@tonic-gate unsigned short errcode, itemcnt; 19377c478bd9Sstevel@tonic-gate int n; 19387c478bd9Sstevel@tonic-gate 19397c478bd9Sstevel@tonic-gate if (flags & F_SUM) { 19407c478bd9Sstevel@tonic-gate GETSHORT(errcode); 19417c478bd9Sstevel@tonic-gate if (errcode != OK) { 19427c478bd9Sstevel@tonic-gate strcat(msgbuf, slpv1_error(errcode)); 19437c478bd9Sstevel@tonic-gate } else { 19447c478bd9Sstevel@tonic-gate GETSHORT(itemcnt); 19457c478bd9Sstevel@tonic-gate sprintf(msgend, "%d type entries", itemcnt); 19467c478bd9Sstevel@tonic-gate #ifdef VERIFYSLP 19477c478bd9Sstevel@tonic-gate for (n = 0; n < itemcnt; n++) { 19487c478bd9Sstevel@tonic-gate SKIPFIELD(FIELD_DEFAULT); /* Service type item */ 19497c478bd9Sstevel@tonic-gate } 19507c478bd9Sstevel@tonic-gate #endif 19517c478bd9Sstevel@tonic-gate } 19527c478bd9Sstevel@tonic-gate } else if (flags & F_DTAIL) { 19537c478bd9Sstevel@tonic-gate DOERRCODE; 19547c478bd9Sstevel@tonic-gate GETSHORT(itemcnt); 19557c478bd9Sstevel@tonic-gate sprintf(get_line(0, 0), "Service type count = %d", itemcnt); 19567c478bd9Sstevel@tonic-gate for (n = 0; n < itemcnt; n++) { 19577c478bd9Sstevel@tonic-gate DOFIELD(" Service type item", FIELD_DEFAULT); 19587c478bd9Sstevel@tonic-gate } 19597c478bd9Sstevel@tonic-gate } 19607c478bd9Sstevel@tonic-gate 19617c478bd9Sstevel@tonic-gate return (1); 19627c478bd9Sstevel@tonic-gate } 1963