1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright (c) 1996-1998,2001 by Sun Microsystems, Inc.
24  * All rights reserved.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 /*
30  * Protocol interpreter for the Hypertext Transfer Protocol (HTTP)
31  *
32  * Relevant standards:
33  *	Berners-Lee, T., et al: Hypertext Transfer Protocol -- HTTP/1.0.
34  *	    RFC 1945, May 1996
35  *	Fielding, R., et al: Hypertext Transfer Protocol -- HTTP/1.1.
36  *	    RFC 2068, June 1999
37  */
38 
39 #include <netinet/in.h>
40 #include <stdio.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include "snoop.h"
44 
45 #define	CR	13			/* "carriage return" character */
46 #define	LF	10			/* "line feed" character */
47 
48 /*
49  * Summary lines: packet contents starting with less than MINCHARS
50  * printable characters will not be printed. MAXCHARS is the maximum
51  * number of characters printed.
52  * Detail lines: NLINES is the maximum number of content lines to print
53  */
54 #define	MINCHARS	10
55 #define	MAXCHARS	80
56 #define	NLINES		5
57 
58 #define	MIN(a, b) (((a) < (b)) ? (a) : (b))
59 
60 static int printable(const char *line, const char *endp);
61 
62 int
63 interpret_http(int flags, char *line, int fraglen)
64 {
65 	char *p, *q, *endp;
66 	int c;
67 	int lineno;
68 
69 	endp = line + fraglen;
70 
71 	if (flags & F_SUM) {
72 		c = printable(line, endp - 1);
73 		if (c < MINCHARS) {
74 			(void) snprintf(get_sum_line(), MAXLINE,
75 				"HTTP (body)");
76 		} else {
77 			(void) snprintf(get_sum_line(), MAXLINE,
78 			    "HTTP %.*s", MIN(c, MAXCHARS), line);
79 		}
80 	}
81 
82 	if (flags & F_DTAIL) {
83 		show_header("HTTP: ", "HyperText Transfer Protocol", fraglen);
84 		show_space();
85 
86 		lineno = 0;
87 		for (p = line; p < endp && lineno < NLINES; p = q + 1) {
88 			c = printable(p, endp - 1);
89 
90 			/* stop if no printables, except if at line end */
91 			if (c == 0 && *p != CR && *p != LF)
92 				break;
93 
94 			/*
95 			 * A line may be terminated either by an CR LF sequence
96 			 * (DOS, Mac), or by LF alone
97 			 */
98 
99 			q = memchr(p, CR, (endp - p));
100 			if (q != NULL) {
101 			    if (q < endp - 1 && q[1] == LF)
102 				++q;	/* ignore subsequent LF character */
103 			} else {
104 			    q = memchr(p, LF, (endp - p));
105 			    /* no CR/LF: use end of buffer */
106 			    if (q == NULL)
107 				q = endp - 1;
108 			}
109 
110 			/* truncate lines containing non-printable characters */
111 			(void) snprintf(get_line(0, c), get_line_remain(),
112 			    "%.*s", c, p);
113 			++lineno;
114 		}
115 
116 		if (p < endp)	/* there was more data to be printed */
117 			(void) snprintf(get_line(0, 5), get_line_remain(),
118 			    "[...]");
119 
120 		show_space();
121 	}
122 
123 	return (fraglen);
124 }
125 
126 /*
127  * Return the length of the initial string starting with "startp" and
128  * ending with "endp" (inclusively) consisting only of printable
129  * characters.
130  */
131 
132 static int
133 printable(const char *startp, const char *endp)
134 {
135 	const char *p = startp;
136 
137 	while (p <= endp && (isprint(*p) || *p == '\t'))
138 		p++;
139 
140 	return (p - startp);
141 }
142