xref: /titanic_50/usr/src/uts/common/fs/sockfs/nl7c.c (revision b819cea2f73f98c5662230cc9affc8cc84f77fcf)
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
52c9e429eSbrutus  * Common Development and Distribution License (the "License").
62c9e429eSbrutus  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
21*59927d31SYuri Pankov 
227c478bd9Sstevel@tonic-gate /*
230f1702c5SYu Xiangning  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*59927d31SYuri Pankov  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
267c478bd9Sstevel@tonic-gate  */
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate /*
297c478bd9Sstevel@tonic-gate  * NL7C (Network Layer 7 Cache) as part of SOCKFS provides an in-kernel
307c478bd9Sstevel@tonic-gate  * gateway cache for the request/response message based L7 protocol HTTP
317c478bd9Sstevel@tonic-gate  * (Hypertext Transfer Protocol, see HTTP/1.1 RFC2616) in a semantically
327c478bd9Sstevel@tonic-gate  * transparent manner.
337c478bd9Sstevel@tonic-gate  *
34da6c28aaSamw  * Neither the requesting user agent (client, e.g. web browser) nor the
357c478bd9Sstevel@tonic-gate  * origin server (e.g. webserver) that provided the response cached by
367c478bd9Sstevel@tonic-gate  * NL7C are impacted in any way.
377c478bd9Sstevel@tonic-gate  *
387c478bd9Sstevel@tonic-gate  * Note, currently NL7C only processes HTTP messages via the embedded
397c478bd9Sstevel@tonic-gate  * URI of scheme http (not https nor any other), additional scheme are
40da6c28aaSamw  * intended to be supported as is practical such that much of the NL7C
41da6c28aaSamw  * framework may appear more general purpose then would be needed just
427c478bd9Sstevel@tonic-gate  * for an HTTP gateway cache.
437c478bd9Sstevel@tonic-gate  *
447c478bd9Sstevel@tonic-gate  * NL7C replaces NCA (Network Cache and Accelerator) and in the future
457c478bd9Sstevel@tonic-gate  * NCAS (NCA/SSL).
467c478bd9Sstevel@tonic-gate  *
477c478bd9Sstevel@tonic-gate  * Further, NL7C uses all NCA configuration files, see "/etc/nca/", the
48da6c28aaSamw  * NCA socket API, "AF_NCA", and "ndd /dev/nca" for backwards compatibility.
497c478bd9Sstevel@tonic-gate  */
507c478bd9Sstevel@tonic-gate 
517c478bd9Sstevel@tonic-gate #include <sys/systm.h>
527c478bd9Sstevel@tonic-gate #include <sys/strsun.h>
537c478bd9Sstevel@tonic-gate #include <sys/strsubr.h>
547c478bd9Sstevel@tonic-gate #include <inet/common.h>
55*59927d31SYuri Pankov #include <inet/ip.h>
567c478bd9Sstevel@tonic-gate #include <inet/led.h>
577c478bd9Sstevel@tonic-gate #include <inet/mi.h>
587c478bd9Sstevel@tonic-gate #include <netinet/in.h>
597c478bd9Sstevel@tonic-gate #include <fs/sockfs/nl7c.h>
607c478bd9Sstevel@tonic-gate #include <fs/sockfs/nl7curi.h>
610f1702c5SYu Xiangning #include <fs/sockfs/socktpi.h>
627c478bd9Sstevel@tonic-gate 
637c478bd9Sstevel@tonic-gate #include <inet/nca/ncadoorhdr.h>
647c478bd9Sstevel@tonic-gate #include <inet/nca/ncalogd.h>
652c9e429eSbrutus #include <inet/nca/ncandd.h>
662c9e429eSbrutus 
672c9e429eSbrutus #include <sys/promif.h>
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * NL7C, NCA, NL7C logger enabled:
717c478bd9Sstevel@tonic-gate  */
727c478bd9Sstevel@tonic-gate 
737c478bd9Sstevel@tonic-gate boolean_t	nl7c_enabled = B_FALSE;
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate boolean_t	nl7c_logd_enabled = B_FALSE;
767c478bd9Sstevel@tonic-gate boolean_t	nl7c_logd_started = B_FALSE;
777c478bd9Sstevel@tonic-gate boolean_t	nl7c_logd_cycle = B_TRUE;
787c478bd9Sstevel@tonic-gate 
797c478bd9Sstevel@tonic-gate /*
807c478bd9Sstevel@tonic-gate  * Some externs:
817c478bd9Sstevel@tonic-gate  */
827c478bd9Sstevel@tonic-gate extern void	nl7c_uri_init(void);
837c478bd9Sstevel@tonic-gate extern boolean_t nl7c_logd_init(int, caddr_t *);
847c478bd9Sstevel@tonic-gate extern void	nl7c_nca_init(void);
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate /*
877c478bd9Sstevel@tonic-gate  * nl7c_addr_t - a singly linked grounded list, pointed to by *nl7caddrs,
887c478bd9Sstevel@tonic-gate  * constructed at init time by parsing "/etc/nca/ncaport.conf".
897c478bd9Sstevel@tonic-gate  *
907c478bd9Sstevel@tonic-gate  * This list is searched at bind(3SOCKET) time when an application doesn't
917c478bd9Sstevel@tonic-gate  * explicitly set AF_NCA but instead uses AF_INET, if a match is found then
920f1702c5SYu Xiangning  * the underlying socket is marked sti_nl7c_flags NL7C_ENABLED.
937c478bd9Sstevel@tonic-gate  */
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate typedef struct nl7c_addr_s {
967c478bd9Sstevel@tonic-gate 	struct nl7c_addr_s *next;	/* next entry */
977c478bd9Sstevel@tonic-gate 	sa_family_t	family;		/* addr type, only INET and INET6 */
987c478bd9Sstevel@tonic-gate 	uint16_t	port;		/* port */
997c478bd9Sstevel@tonic-gate 	union {
1007c478bd9Sstevel@tonic-gate 		ipaddr_t	v4;	/* IPv4 address */
1017c478bd9Sstevel@tonic-gate 		in6_addr_t	v6;	/* IPv6 address */
1027c478bd9Sstevel@tonic-gate 		void		*align;	/* foce alignment */
1037c478bd9Sstevel@tonic-gate 	}		addr;		/* address */
1047c478bd9Sstevel@tonic-gate 
1052c9e429eSbrutus 	struct sonode	*listener;	/* listen()er's sonode */
1067c478bd9Sstevel@tonic-gate 	boolean_t	temp;		/* temporary addr via add_addr() ? */
1077c478bd9Sstevel@tonic-gate } nl7c_addr_t;
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate nl7c_addr_t	*nl7caddrs = NULL;
1107c478bd9Sstevel@tonic-gate 
1112c9e429eSbrutus /*
1122c9e429eSbrutus  * Called for an NL7C_ENABLED listen()er socket for the nl7c_addr_t
1132c9e429eSbrutus  * previously returned by nl7c_lookup_addr().
1142c9e429eSbrutus  */
1152c9e429eSbrutus 
1167c478bd9Sstevel@tonic-gate void
nl7c_listener_addr(void * arg,struct sonode * so)1172c9e429eSbrutus nl7c_listener_addr(void *arg, struct sonode *so)
1187c478bd9Sstevel@tonic-gate {
1197c478bd9Sstevel@tonic-gate 	nl7c_addr_t		*p = (nl7c_addr_t *)arg;
1207c478bd9Sstevel@tonic-gate 
1212c9e429eSbrutus 	if (p->listener == NULL)
1222c9e429eSbrutus 		p->listener = so;
1230f1702c5SYu Xiangning 	SOTOTPI(so)->sti_nl7c_addr = arg;
1242c9e429eSbrutus }
1252c9e429eSbrutus 
1262c9e429eSbrutus struct sonode *
nl7c_addr2portso(void * arg)1272c9e429eSbrutus nl7c_addr2portso(void *arg)
1282c9e429eSbrutus {
1292c9e429eSbrutus 	nl7c_addr_t		*p = (nl7c_addr_t *)arg;
1302c9e429eSbrutus 
1312c9e429eSbrutus 	return (p->listener);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate void *
nl7c_lookup_addr(void * addr,t_uscalar_t addrlen)1357c478bd9Sstevel@tonic-gate nl7c_lookup_addr(void *addr, t_uscalar_t addrlen)
1367c478bd9Sstevel@tonic-gate {
1377c478bd9Sstevel@tonic-gate 	struct sockaddr		*sap = addr;
1387c478bd9Sstevel@tonic-gate 	struct sockaddr_in	*v4p = addr;
1397c478bd9Sstevel@tonic-gate 	nl7c_addr_t		*p = nl7caddrs;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	if (sap->sa_family != AF_INET || addrlen != sizeof (*v4p)) {
1427c478bd9Sstevel@tonic-gate 		/* Only support IPv4 */
1437c478bd9Sstevel@tonic-gate 		return (B_FALSE);
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 	while (p) {
1467c478bd9Sstevel@tonic-gate 		if (sap->sa_family == p->family &&
1477c478bd9Sstevel@tonic-gate 		    v4p->sin_port == p->port &&
1487c478bd9Sstevel@tonic-gate 		    (v4p->sin_addr.s_addr == p->addr.v4 ||
1497c478bd9Sstevel@tonic-gate 		    p->addr.v4 == INADDR_ANY)) {
1507c478bd9Sstevel@tonic-gate 			/* Match */
1517c478bd9Sstevel@tonic-gate 			return (p);
1527c478bd9Sstevel@tonic-gate 		}
1537c478bd9Sstevel@tonic-gate 		p = p->next;
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 	return (NULL);
1567c478bd9Sstevel@tonic-gate }
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate void *
nl7c_add_addr(void * addr,t_uscalar_t addrlen)1597c478bd9Sstevel@tonic-gate nl7c_add_addr(void *addr, t_uscalar_t addrlen)
1607c478bd9Sstevel@tonic-gate {
1617c478bd9Sstevel@tonic-gate 	struct sockaddr		*sap = addr;
1627c478bd9Sstevel@tonic-gate 	struct sockaddr_in	*v4p = addr;
1637c478bd9Sstevel@tonic-gate 	nl7c_addr_t		*new = NULL;
1647c478bd9Sstevel@tonic-gate 	nl7c_addr_t		*old;
1657c478bd9Sstevel@tonic-gate 	nl7c_addr_t		*p;
1667c478bd9Sstevel@tonic-gate 	boolean_t		alloced;
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	if (sap->sa_family != AF_INET || addrlen != sizeof (*v4p)) {
1697c478bd9Sstevel@tonic-gate 		/* Only support IPv4 */
1707c478bd9Sstevel@tonic-gate 		return (NULL);
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate again:
1737c478bd9Sstevel@tonic-gate 	p = nl7caddrs;
1747c478bd9Sstevel@tonic-gate 	while (p) {
1757c478bd9Sstevel@tonic-gate 		if (new == NULL && p->port == 0)
1767c478bd9Sstevel@tonic-gate 			new = p;
1777c478bd9Sstevel@tonic-gate 		if (sap->sa_family == p->family &&
1787c478bd9Sstevel@tonic-gate 		    v4p->sin_port == p->port &&
1797c478bd9Sstevel@tonic-gate 		    (v4p->sin_addr.s_addr == p->addr.v4 ||
1807c478bd9Sstevel@tonic-gate 		    p->addr.v4 == INADDR_ANY)) {
1817c478bd9Sstevel@tonic-gate 			/* Match */
1827c478bd9Sstevel@tonic-gate 			return (p);
1837c478bd9Sstevel@tonic-gate 		}
1847c478bd9Sstevel@tonic-gate 		p = p->next;
1857c478bd9Sstevel@tonic-gate 	}
1867c478bd9Sstevel@tonic-gate 	if (new == NULL) {
1877c478bd9Sstevel@tonic-gate 		new = kmem_zalloc(sizeof (*new), KM_SLEEP);
1887c478bd9Sstevel@tonic-gate 		alloced = B_TRUE;
1897c478bd9Sstevel@tonic-gate 	} else
1907c478bd9Sstevel@tonic-gate 		alloced = B_FALSE;
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 	new->family = sap->sa_family;
1937c478bd9Sstevel@tonic-gate 	new->port = v4p->sin_port;
1947c478bd9Sstevel@tonic-gate 	new->addr.v4 = v4p->sin_addr.s_addr;
1957c478bd9Sstevel@tonic-gate 	new->temp = B_TRUE;
1967c478bd9Sstevel@tonic-gate 
1977c478bd9Sstevel@tonic-gate 	if (alloced) {
1982c9e429eSbrutus 		old = nl7caddrs;
1997c478bd9Sstevel@tonic-gate 		new->next = old;
2007c478bd9Sstevel@tonic-gate 		if (atomic_cas_ptr(&nl7caddrs, old, new) != old) {
2017c478bd9Sstevel@tonic-gate 			kmem_free(new, sizeof (*new));
2027c478bd9Sstevel@tonic-gate 			goto again;
2037c478bd9Sstevel@tonic-gate 		}
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 	return (new);
2077c478bd9Sstevel@tonic-gate }
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate boolean_t
nl7c_close_addr(struct sonode * so)2107c478bd9Sstevel@tonic-gate nl7c_close_addr(struct sonode *so)
2117c478bd9Sstevel@tonic-gate {
2127c478bd9Sstevel@tonic-gate 	nl7c_addr_t	*p = nl7caddrs;
2137c478bd9Sstevel@tonic-gate 
2147c478bd9Sstevel@tonic-gate 	while (p) {
2152c9e429eSbrutus 		if (p->listener == so) {
2167c478bd9Sstevel@tonic-gate 			if (p->temp)
2177c478bd9Sstevel@tonic-gate 				p->port = (uint16_t)-1;
2182c9e429eSbrutus 			p->listener = NULL;
2197c478bd9Sstevel@tonic-gate 			return (B_TRUE);
2207c478bd9Sstevel@tonic-gate 		}
2217c478bd9Sstevel@tonic-gate 		p = p->next;
2227c478bd9Sstevel@tonic-gate 	}
2237c478bd9Sstevel@tonic-gate 	return (B_FALSE);
2247c478bd9Sstevel@tonic-gate }
2257c478bd9Sstevel@tonic-gate 
2267c478bd9Sstevel@tonic-gate static void
nl7c_addr_add(nl7c_addr_t * p)2277c478bd9Sstevel@tonic-gate nl7c_addr_add(nl7c_addr_t *p)
2287c478bd9Sstevel@tonic-gate {
2297c478bd9Sstevel@tonic-gate 	p->next = nl7caddrs;
2307c478bd9Sstevel@tonic-gate 	nl7caddrs = p;
2317c478bd9Sstevel@tonic-gate }
2327c478bd9Sstevel@tonic-gate 
2337c478bd9Sstevel@tonic-gate void
nl7c_mi_report_addr(mblk_t * mp)2347c478bd9Sstevel@tonic-gate nl7c_mi_report_addr(mblk_t *mp)
2357c478bd9Sstevel@tonic-gate {
2367c478bd9Sstevel@tonic-gate 	ipaddr_t	ip;
2377c478bd9Sstevel@tonic-gate 	uint16_t	port;
2387c478bd9Sstevel@tonic-gate 	nl7c_addr_t	*p = nl7caddrs;
2392c9e429eSbrutus 	struct sonode	*so;
2407c478bd9Sstevel@tonic-gate 	char		addr[32];
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "Door  Up-Call-Queue IPaddr:TCPport Listenning");
2437c478bd9Sstevel@tonic-gate 	while (p) {
2442c9e429eSbrutus 		if (p->port != (uint16_t)-1) {
2452c9e429eSbrutus 			/* Don't report freed slots */
2467c478bd9Sstevel@tonic-gate 			ip = ntohl(p->addr.v4);
2477c478bd9Sstevel@tonic-gate 			port = ntohs(p->port);
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 			if (ip == INADDR_ANY) {
2507c478bd9Sstevel@tonic-gate 				(void) strcpy(addr, "*");
2517c478bd9Sstevel@tonic-gate 			} else {
2527c478bd9Sstevel@tonic-gate 				int a1 = (ip >> 24) & 0xFF;
2537c478bd9Sstevel@tonic-gate 				int a2 = (ip >> 16) & 0xFF;
2547c478bd9Sstevel@tonic-gate 				int a3 = (ip >> 8) & 0xFF;
2557c478bd9Sstevel@tonic-gate 				int a4 = ip & 0xFF;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 				(void) mi_sprintf(addr, "%d.%d.%d.%d",
2587c478bd9Sstevel@tonic-gate 				    a1, a2, a3, a4);
2597c478bd9Sstevel@tonic-gate 			}
2602c9e429eSbrutus 			so = p->listener;
2612c9e429eSbrutus 			(void) mi_mpprintf(mp, "%p  %s:%d  %d",
2622c9e429eSbrutus 			    so ? (void *)strvp2wq(SOTOV(so)) : NULL,
2632c9e429eSbrutus 			    addr, port, p->listener ? 1 : 0);
2647c478bd9Sstevel@tonic-gate 		}
2657c478bd9Sstevel@tonic-gate 		p = p->next;
2667c478bd9Sstevel@tonic-gate 	}
2677c478bd9Sstevel@tonic-gate }
2687c478bd9Sstevel@tonic-gate 
2697c478bd9Sstevel@tonic-gate /*
2707c478bd9Sstevel@tonic-gate  * ASCII to unsigned.
2717c478bd9Sstevel@tonic-gate  *
2727c478bd9Sstevel@tonic-gate  * Note, it's assumed that *p is a valid zero byte terminated string.
2737c478bd9Sstevel@tonic-gate  */
2747c478bd9Sstevel@tonic-gate 
2757c478bd9Sstevel@tonic-gate static unsigned
atou(const char * p)2767c478bd9Sstevel@tonic-gate atou(const char *p)
2777c478bd9Sstevel@tonic-gate {
2787c478bd9Sstevel@tonic-gate 	int c;
2797c478bd9Sstevel@tonic-gate 	int v = 0;
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 	/* Shift and add digit by digit */
2827c478bd9Sstevel@tonic-gate 	while ((c = *p++) != NULL && isdigit(c)) {
2837c478bd9Sstevel@tonic-gate 		v *= 10;
2847c478bd9Sstevel@tonic-gate 		v += c - '0';
2857c478bd9Sstevel@tonic-gate 	}
2867c478bd9Sstevel@tonic-gate 	return (v);
2877c478bd9Sstevel@tonic-gate }
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate /*
2907c478bd9Sstevel@tonic-gate  * Inet ASCII to binary.
2917c478bd9Sstevel@tonic-gate  *
2927c478bd9Sstevel@tonic-gate  * Note, it's assumed that *s is a valid zero byte terminated string, and
2937c478bd9Sstevel@tonic-gate  * that *p is a zero initialized struct (this is important as the value of
2947c478bd9Sstevel@tonic-gate  * INADDR_ANY and IN6ADDR_ANY is zero).
2957c478bd9Sstevel@tonic-gate  */
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate static int
inet_atob(char * s,nl7c_addr_t * p)2987c478bd9Sstevel@tonic-gate inet_atob(char *s, nl7c_addr_t *p)
2997c478bd9Sstevel@tonic-gate {
3007c478bd9Sstevel@tonic-gate 	if (strcmp(s, "*") == 0) {
3017c478bd9Sstevel@tonic-gate 		/* INADDR_ANY */
3027c478bd9Sstevel@tonic-gate 		p->family = AF_INET;
3037c478bd9Sstevel@tonic-gate 		return (0);
3047c478bd9Sstevel@tonic-gate 	}
3057c478bd9Sstevel@tonic-gate 	if (strcmp(s, "::") == 0) {
3067c478bd9Sstevel@tonic-gate 		/* IN6ADDR_ANY */
3077c478bd9Sstevel@tonic-gate 		p->family = AF_INET6;
3087c478bd9Sstevel@tonic-gate 		return (0);
3097c478bd9Sstevel@tonic-gate 	}
3107c478bd9Sstevel@tonic-gate 	/* IPv4 address ? */
3117c478bd9Sstevel@tonic-gate 	if (inet_pton(AF_INET, s, &p->addr.v4) != 1) {
3127c478bd9Sstevel@tonic-gate 		/* Nop, IPv6 address ? */
3137c478bd9Sstevel@tonic-gate 		if (inet_pton(AF_INET6, s, &p->addr.v6) != 1) {
3147c478bd9Sstevel@tonic-gate 			/* Nop, return error */
3157c478bd9Sstevel@tonic-gate 			return (1);
3167c478bd9Sstevel@tonic-gate 		}
3177c478bd9Sstevel@tonic-gate 		p->family = AF_INET6;
3187c478bd9Sstevel@tonic-gate 	} else {
3197c478bd9Sstevel@tonic-gate 		p->family = AF_INET;
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 	return (0);
3227c478bd9Sstevel@tonic-gate }
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate  * Open and read each line from "/etc/nca/ncaport.conf", the syntax of a
3262c9e429eSbrutus  * ncaport.conf file line is:
3272c9e429eSbrutus  *
3282c9e429eSbrutus  *	ncaport=IPaddr/Port[/Proxy]
3292c9e429eSbrutus  *
3302c9e429eSbrutus  * Where:
3317c478bd9Sstevel@tonic-gate  *
3327c478bd9Sstevel@tonic-gate  * ncaport - the only token recognized.
3337c478bd9Sstevel@tonic-gate  *
3347c478bd9Sstevel@tonic-gate  *  IPaddr - an IPv4 numeric dot address (e.g. 192.168.84.71) or '*' for
3357c478bd9Sstevel@tonic-gate  *           INADDR_ANY, or an IPv6 numeric address or "::" for IN6ADDR_ANY.
3367c478bd9Sstevel@tonic-gate  *
337da6c28aaSamw  *       / - IPaddr/Port separator.
3387c478bd9Sstevel@tonic-gate  *
3397c478bd9Sstevel@tonic-gate  *    Port - a TCP decimal port number.
3402c9e429eSbrutus  *
3412c9e429eSbrutus  * Note, all other lines will be ignored.
3427c478bd9Sstevel@tonic-gate  */
3437c478bd9Sstevel@tonic-gate 
3447c478bd9Sstevel@tonic-gate static void
ncaportconf_read(void)3457c478bd9Sstevel@tonic-gate ncaportconf_read(void)
3467c478bd9Sstevel@tonic-gate {
3477c478bd9Sstevel@tonic-gate 	int	ret;
3487c478bd9Sstevel@tonic-gate 	struct vnode *vp;
3497c478bd9Sstevel@tonic-gate 	char	c;
3507c478bd9Sstevel@tonic-gate 	ssize_t resid;
3517c478bd9Sstevel@tonic-gate 	char	buf[1024];
3527c478bd9Sstevel@tonic-gate 	char	*ebp = &buf[sizeof (buf)];
3537c478bd9Sstevel@tonic-gate 	char	*bp = ebp;
3547c478bd9Sstevel@tonic-gate 	offset_t off = 0;
3557c478bd9Sstevel@tonic-gate 	enum parse_e {START, TOK, ADDR, PORT, EOL} parse = START;
3567c478bd9Sstevel@tonic-gate 	nl7c_addr_t *addrp = NULL;
3577c478bd9Sstevel@tonic-gate 	char	*ncaport = "ncaport";
3587c478bd9Sstevel@tonic-gate 	char	string[] = "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX";
3597c478bd9Sstevel@tonic-gate 	char	*stringp;
3607c478bd9Sstevel@tonic-gate 	char	*tok;
3617c478bd9Sstevel@tonic-gate 	char	*portconf = "/etc/nca/ncaport.conf";
3627c478bd9Sstevel@tonic-gate 
3637c478bd9Sstevel@tonic-gate 	ret = vn_open(portconf, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0);
3647c478bd9Sstevel@tonic-gate 	if (ret == ENOENT) {
3657c478bd9Sstevel@tonic-gate 		/* No portconf file, nothing to do */
3667c478bd9Sstevel@tonic-gate 		return;
3677c478bd9Sstevel@tonic-gate 	}
3687c478bd9Sstevel@tonic-gate 	if (ret != 0) {
3697c478bd9Sstevel@tonic-gate 		/* Error of some sort, tell'm about it */
3707c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s: open error %d", portconf, ret);
3717c478bd9Sstevel@tonic-gate 		return;
3727c478bd9Sstevel@tonic-gate 	}
3737c478bd9Sstevel@tonic-gate 	/*
3747c478bd9Sstevel@tonic-gate 	 * Read portconf one buf[] at a time, parse one char at a time.
3757c478bd9Sstevel@tonic-gate 	 */
3767c478bd9Sstevel@tonic-gate 	for (;;) {
3777c478bd9Sstevel@tonic-gate 		if (bp == ebp) {
3787c478bd9Sstevel@tonic-gate 			/* Nothing left in buf[], read another */
3797c478bd9Sstevel@tonic-gate 			ret = vn_rdwr(UIO_READ, vp, buf, sizeof (buf), off,
3807c478bd9Sstevel@tonic-gate 			    UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid);
3817c478bd9Sstevel@tonic-gate 			if (ret != 0) {
3827c478bd9Sstevel@tonic-gate 				/* Error of some sort, tell'm about it */
3837c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "%s: read error %d",
3847c478bd9Sstevel@tonic-gate 				    portconf, ret);
3857c478bd9Sstevel@tonic-gate 				break;
3867c478bd9Sstevel@tonic-gate 			}
3877c478bd9Sstevel@tonic-gate 			if (resid == sizeof (buf)) {
3887c478bd9Sstevel@tonic-gate 				/* EOF, done */
3897c478bd9Sstevel@tonic-gate 				break;
3907c478bd9Sstevel@tonic-gate 			}
3917c478bd9Sstevel@tonic-gate 			/* Initilize per buf[] state */
3927c478bd9Sstevel@tonic-gate 			bp = buf;
3937c478bd9Sstevel@tonic-gate 			ebp = &buf[sizeof (buf) - resid];
3947c478bd9Sstevel@tonic-gate 			off += sizeof (buf) - resid;
3957c478bd9Sstevel@tonic-gate 		}
3967c478bd9Sstevel@tonic-gate 		c = *bp++;
3977c478bd9Sstevel@tonic-gate 		switch (parse) {
3987c478bd9Sstevel@tonic-gate 		case START:
3997c478bd9Sstevel@tonic-gate 			/* Initilize all per file line state */
4007c478bd9Sstevel@tonic-gate 			if (addrp == NULL) {
4017c478bd9Sstevel@tonic-gate 				addrp = kmem_zalloc(sizeof (*addrp),
4027c478bd9Sstevel@tonic-gate 				    KM_NOSLEEP);
4037c478bd9Sstevel@tonic-gate 			}
4047c478bd9Sstevel@tonic-gate 			tok = ncaport;
4057c478bd9Sstevel@tonic-gate 			stringp = string;
4067c478bd9Sstevel@tonic-gate 			parse = TOK;
4077c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
4087c478bd9Sstevel@tonic-gate 		case TOK:
4097c478bd9Sstevel@tonic-gate 			if (c == '#') {
4107c478bd9Sstevel@tonic-gate 				/* Comment through end of line */
4117c478bd9Sstevel@tonic-gate 				parse = EOL;
4127c478bd9Sstevel@tonic-gate 				break;
4137c478bd9Sstevel@tonic-gate 			}
4147c478bd9Sstevel@tonic-gate 			if (isalpha(c)) {
4157c478bd9Sstevel@tonic-gate 				if (c != *tok++) {
4167c478bd9Sstevel@tonic-gate 					/* Only know one token, skip */
4177c478bd9Sstevel@tonic-gate 					parse = EOL;
4187c478bd9Sstevel@tonic-gate 				}
4197c478bd9Sstevel@tonic-gate 			} else if (c == '=') {
4207c478bd9Sstevel@tonic-gate 				if (*tok != NULL) {
4217c478bd9Sstevel@tonic-gate 					/* Only know one token, skip */
4227c478bd9Sstevel@tonic-gate 					parse = EOL;
4237c478bd9Sstevel@tonic-gate 					break;
4247c478bd9Sstevel@tonic-gate 				}
4257c478bd9Sstevel@tonic-gate 				parse = ADDR;
4267c478bd9Sstevel@tonic-gate 			} else if (c == '\n') {
4277c478bd9Sstevel@tonic-gate 				/* Found EOL, empty line, next line */
4287c478bd9Sstevel@tonic-gate 				parse = START;
4297c478bd9Sstevel@tonic-gate 			} else {
4307c478bd9Sstevel@tonic-gate 				/* Unexpected char, skip */
4317c478bd9Sstevel@tonic-gate 				parse = EOL;
4327c478bd9Sstevel@tonic-gate 			}
4337c478bd9Sstevel@tonic-gate 			break;
4347c478bd9Sstevel@tonic-gate 
4357c478bd9Sstevel@tonic-gate 		case ADDR:
4367c478bd9Sstevel@tonic-gate 			if (c == '/') {
4377c478bd9Sstevel@tonic-gate 				/* addr/port separator, end of addr */
4387c478bd9Sstevel@tonic-gate 				*stringp = NULL;
4397c478bd9Sstevel@tonic-gate 				if (inet_atob(string, addrp)) {
4407c478bd9Sstevel@tonic-gate 					/* Bad addr, skip */
4417c478bd9Sstevel@tonic-gate 					parse = EOL;
4427c478bd9Sstevel@tonic-gate 				} else {
4437c478bd9Sstevel@tonic-gate 					stringp = string;
4447c478bd9Sstevel@tonic-gate 					parse = PORT;
4457c478bd9Sstevel@tonic-gate 				}
4467c478bd9Sstevel@tonic-gate 			} else {
4477c478bd9Sstevel@tonic-gate 				/* Save char to string */
4487c478bd9Sstevel@tonic-gate 				if (stringp ==
4497c478bd9Sstevel@tonic-gate 				    &string[sizeof (string) - 1]) {
4507c478bd9Sstevel@tonic-gate 					/* Would overflow, skip */
4517c478bd9Sstevel@tonic-gate 					parse = EOL;
4527c478bd9Sstevel@tonic-gate 				} else {
4537c478bd9Sstevel@tonic-gate 					/* Copy IP addr char */
4547c478bd9Sstevel@tonic-gate 					*stringp++ = c;
4557c478bd9Sstevel@tonic-gate 				}
4567c478bd9Sstevel@tonic-gate 			}
4577c478bd9Sstevel@tonic-gate 			break;
4587c478bd9Sstevel@tonic-gate 
4597c478bd9Sstevel@tonic-gate 		case PORT:
4607c478bd9Sstevel@tonic-gate 			if (isdigit(c)) {
4617c478bd9Sstevel@tonic-gate 				/* Save char to string */
4627c478bd9Sstevel@tonic-gate 				if (stringp ==
4637c478bd9Sstevel@tonic-gate 				    &string[sizeof (string) - 1]) {
4647c478bd9Sstevel@tonic-gate 					/* Would overflow, skip */
4657c478bd9Sstevel@tonic-gate 					parse = EOL;
4667c478bd9Sstevel@tonic-gate 				} else {
4677c478bd9Sstevel@tonic-gate 					/* Copy port digit char */
4687c478bd9Sstevel@tonic-gate 					*stringp++ = c;
4697c478bd9Sstevel@tonic-gate 				}
4707c478bd9Sstevel@tonic-gate 				break;
4717c478bd9Sstevel@tonic-gate 			} else if (c == '#' || isspace(c)) {
4727c478bd9Sstevel@tonic-gate 				/* End of port number, convert */
4737c478bd9Sstevel@tonic-gate 				*stringp = NULL;
4742c9e429eSbrutus 				addrp->port = ntohs(atou(string));
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 				/* End of parse, add entry */
4777c478bd9Sstevel@tonic-gate 				nl7c_addr_add(addrp);
4787c478bd9Sstevel@tonic-gate 				addrp = NULL;
4797c478bd9Sstevel@tonic-gate 				parse = EOL;
4807c478bd9Sstevel@tonic-gate 			} else {
4817c478bd9Sstevel@tonic-gate 				/* Unrecognized char, skip */
4827c478bd9Sstevel@tonic-gate 				parse = EOL;
4837c478bd9Sstevel@tonic-gate 				break;
4847c478bd9Sstevel@tonic-gate 			}
4852c9e429eSbrutus 			if (c == '\n') {
4862c9e429eSbrutus 				/* Found EOL, start on next line */
4872c9e429eSbrutus 				parse = START;
4882c9e429eSbrutus 			}
4892c9e429eSbrutus 			break;
4902c9e429eSbrutus 
4917c478bd9Sstevel@tonic-gate 		case EOL:
4927c478bd9Sstevel@tonic-gate 			if (c == '\n') {
4937c478bd9Sstevel@tonic-gate 				/* Found EOL, start on next line */
4947c478bd9Sstevel@tonic-gate 				parse = START;
4957c478bd9Sstevel@tonic-gate 			}
4967c478bd9Sstevel@tonic-gate 			break;
4977c478bd9Sstevel@tonic-gate 		}
4987c478bd9Sstevel@tonic-gate 
4997c478bd9Sstevel@tonic-gate 	}
5007c478bd9Sstevel@tonic-gate 	if (addrp != NULL) {
5017c478bd9Sstevel@tonic-gate 		kmem_free(addrp, sizeof (*addrp));
5027c478bd9Sstevel@tonic-gate 	}
503da6c28aaSamw 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5047c478bd9Sstevel@tonic-gate 	VN_RELE(vp);
5057c478bd9Sstevel@tonic-gate }
5067c478bd9Sstevel@tonic-gate 
5077c478bd9Sstevel@tonic-gate /*
5087c478bd9Sstevel@tonic-gate  * Open and read each line from "/etc/nca/ncakmod.conf" and parse looking
5097c478bd9Sstevel@tonic-gate  * for the NCA enabled, the syntax is: status=enabled, all other lines will
5107c478bd9Sstevel@tonic-gate  * be ignored.
5117c478bd9Sstevel@tonic-gate  */
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate static void
ncakmodconf_read(void)5147c478bd9Sstevel@tonic-gate ncakmodconf_read(void)
5157c478bd9Sstevel@tonic-gate {
5167c478bd9Sstevel@tonic-gate 	int	ret;
5177c478bd9Sstevel@tonic-gate 	struct vnode *vp;
5187c478bd9Sstevel@tonic-gate 	char	c;
5197c478bd9Sstevel@tonic-gate 	ssize_t resid;
5207c478bd9Sstevel@tonic-gate 	char	buf[1024];
5217c478bd9Sstevel@tonic-gate 	char	*ebp = &buf[sizeof (buf)];
5227c478bd9Sstevel@tonic-gate 	char	*bp = ebp;
5237c478bd9Sstevel@tonic-gate 	offset_t off = 0;
5247c478bd9Sstevel@tonic-gate 	enum parse_e {START, TOK, EOL} parse = START;
5257c478bd9Sstevel@tonic-gate 	char	*status = "status=enabled";
5267c478bd9Sstevel@tonic-gate 	char	*tok;
5277c478bd9Sstevel@tonic-gate 	char	*ncakmod = "/etc/nca/ncakmod.conf";
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	ret = vn_open(ncakmod, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0);
5307c478bd9Sstevel@tonic-gate 	if (ret == ENOENT) {
5317c478bd9Sstevel@tonic-gate 		/* No ncakmod file, nothing to do */
5327c478bd9Sstevel@tonic-gate 		return;
5337c478bd9Sstevel@tonic-gate 	}
5347c478bd9Sstevel@tonic-gate 	if (ret != 0) {
5357c478bd9Sstevel@tonic-gate 		/* Error of some sort, tell'm about it */
5367c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s: open error %d", status, ret);
5377c478bd9Sstevel@tonic-gate 		return;
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 	/*
5407c478bd9Sstevel@tonic-gate 	 * Read ncakmod one buf[] at a time, parse one char at a time.
5417c478bd9Sstevel@tonic-gate 	 */
5427c478bd9Sstevel@tonic-gate 	for (;;) {
5437c478bd9Sstevel@tonic-gate 		if (bp == ebp) {
5447c478bd9Sstevel@tonic-gate 			/* Nothing left in buf[], read another */
5457c478bd9Sstevel@tonic-gate 			ret = vn_rdwr(UIO_READ, vp, buf, sizeof (buf), off,
5467c478bd9Sstevel@tonic-gate 			    UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid);
5477c478bd9Sstevel@tonic-gate 			if (ret != 0) {
5487c478bd9Sstevel@tonic-gate 				/* Error of some sort, tell'm about it */
5497c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "%s: read error %d",
5507c478bd9Sstevel@tonic-gate 				    status, ret);
5517c478bd9Sstevel@tonic-gate 				break;
5527c478bd9Sstevel@tonic-gate 			}
5537c478bd9Sstevel@tonic-gate 			if (resid == sizeof (buf)) {
5547c478bd9Sstevel@tonic-gate 				/* EOF, done */
5557c478bd9Sstevel@tonic-gate 				break;
5567c478bd9Sstevel@tonic-gate 			}
5577c478bd9Sstevel@tonic-gate 			/* Initilize per buf[] state */
5587c478bd9Sstevel@tonic-gate 			bp = buf;
5597c478bd9Sstevel@tonic-gate 			ebp = &buf[sizeof (buf) - resid];
5607c478bd9Sstevel@tonic-gate 			off += sizeof (buf) - resid;
5617c478bd9Sstevel@tonic-gate 		}
5627c478bd9Sstevel@tonic-gate 		c = *bp++;
5637c478bd9Sstevel@tonic-gate 		switch (parse) {
5647c478bd9Sstevel@tonic-gate 		case START:
5657c478bd9Sstevel@tonic-gate 			/* Initilize all per file line state */
5667c478bd9Sstevel@tonic-gate 			tok = status;
5677c478bd9Sstevel@tonic-gate 			parse = TOK;
5687c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
5697c478bd9Sstevel@tonic-gate 		case TOK:
5707c478bd9Sstevel@tonic-gate 			if (c == '#') {
5717c478bd9Sstevel@tonic-gate 				/* Comment through end of line */
5727c478bd9Sstevel@tonic-gate 				parse = EOL;
5737c478bd9Sstevel@tonic-gate 				break;
5747c478bd9Sstevel@tonic-gate 			}
5757c478bd9Sstevel@tonic-gate 			if (isalpha(c) || c == '=') {
5767c478bd9Sstevel@tonic-gate 				if (c != *tok++) {
5777c478bd9Sstevel@tonic-gate 					/* Only know one token, skip */
5787c478bd9Sstevel@tonic-gate 					parse = EOL;
5797c478bd9Sstevel@tonic-gate 				}
5807c478bd9Sstevel@tonic-gate 			} else if (c == '\n') {
5817c478bd9Sstevel@tonic-gate 				/*
5827c478bd9Sstevel@tonic-gate 				 * Found EOL, if tok found done,
5837c478bd9Sstevel@tonic-gate 				 * else start on next-line.
5847c478bd9Sstevel@tonic-gate 				 */
5857c478bd9Sstevel@tonic-gate 				if (*tok == NULL) {
5867c478bd9Sstevel@tonic-gate 					nl7c_enabled = B_TRUE;
5877c478bd9Sstevel@tonic-gate 					goto done;
5887c478bd9Sstevel@tonic-gate 				}
5897c478bd9Sstevel@tonic-gate 				parse = START;
5907c478bd9Sstevel@tonic-gate 			} else {
5917c478bd9Sstevel@tonic-gate 				/* Unexpected char, skip */
5927c478bd9Sstevel@tonic-gate 				parse = EOL;
5937c478bd9Sstevel@tonic-gate 			}
5947c478bd9Sstevel@tonic-gate 			break;
5957c478bd9Sstevel@tonic-gate 
5967c478bd9Sstevel@tonic-gate 		case EOL:
5977c478bd9Sstevel@tonic-gate 			if (c == '\n') {
5987c478bd9Sstevel@tonic-gate 				/* Found EOL, start on next line */
5997c478bd9Sstevel@tonic-gate 				parse = START;
6007c478bd9Sstevel@tonic-gate 			}
6017c478bd9Sstevel@tonic-gate 			break;
6027c478bd9Sstevel@tonic-gate 		}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	}
6057c478bd9Sstevel@tonic-gate done:
606da6c28aaSamw 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
6077c478bd9Sstevel@tonic-gate 	VN_RELE(vp);
6087c478bd9Sstevel@tonic-gate }
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate /*
6117c478bd9Sstevel@tonic-gate  * Open and read each line from "/etc/nca/ncalogd.conf" and parse for
6127c478bd9Sstevel@tonic-gate  * the tokens and token text (i.e. key and value ncalogd.conf(4)):
6137c478bd9Sstevel@tonic-gate  *
6147c478bd9Sstevel@tonic-gate  *	status=enabled
6157c478bd9Sstevel@tonic-gate  *
6167c478bd9Sstevel@tonic-gate  *	logd_file_size=[0-9]+
6177c478bd9Sstevel@tonic-gate  *
6187c478bd9Sstevel@tonic-gate  *	logd_file_name=["]filename( filename)*["]
6197c478bd9Sstevel@tonic-gate  */
6207c478bd9Sstevel@tonic-gate 
6217c478bd9Sstevel@tonic-gate static int	file_size = 1000000;
6227c478bd9Sstevel@tonic-gate static caddr_t	fnv[NCA_FIOV_SZ];
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate static void
ncalogdconf_read(void)6257c478bd9Sstevel@tonic-gate ncalogdconf_read(void)
6267c478bd9Sstevel@tonic-gate {
6277c478bd9Sstevel@tonic-gate 	int	ret;
6287c478bd9Sstevel@tonic-gate 	struct vnode *vp;
6297c478bd9Sstevel@tonic-gate 	char	c;
6307c478bd9Sstevel@tonic-gate 	int	sz;
6317c478bd9Sstevel@tonic-gate 	ssize_t resid;
6327c478bd9Sstevel@tonic-gate 	char	buf[1024];
6337c478bd9Sstevel@tonic-gate 	char	*ebp = &buf[sizeof (buf)];
6347c478bd9Sstevel@tonic-gate 	char	*bp = ebp;
6357c478bd9Sstevel@tonic-gate 	offset_t off = 0;
6367c478bd9Sstevel@tonic-gate 	enum parse_e {START, TOK, TEXT, EOL} parse = START;
6377c478bd9Sstevel@tonic-gate 	char	*tokstatus = "status\0enabled";
6387c478bd9Sstevel@tonic-gate 	char	*toksize = "logd_file_size";
6397c478bd9Sstevel@tonic-gate 	char	*tokfile = "logd_path_name";
6407c478bd9Sstevel@tonic-gate 	char	*tokstatusp;
6417c478bd9Sstevel@tonic-gate 	char	*toksizep;
6427c478bd9Sstevel@tonic-gate 	char	*tokfilep;
6437c478bd9Sstevel@tonic-gate 	char	*tok;
6447c478bd9Sstevel@tonic-gate 	int	tokdelim = 0;
6457c478bd9Sstevel@tonic-gate 	char	*ncalogd = "/etc/nca/ncalogd.conf";
6467c478bd9Sstevel@tonic-gate 	char	*ncadeflog = "/var/nca/log";
6477c478bd9Sstevel@tonic-gate 	char	file[TYPICALMAXPATHLEN] = {0};
6487c478bd9Sstevel@tonic-gate 	char	*fp = file;
6497c478bd9Sstevel@tonic-gate 	caddr_t	*fnvp = fnv;
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate 	ret = vn_open(ncalogd, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0);
6527c478bd9Sstevel@tonic-gate 	if (ret == ENOENT) {
6537c478bd9Sstevel@tonic-gate 		/* No ncalogd file, nothing to do */
6547c478bd9Sstevel@tonic-gate 		return;
6557c478bd9Sstevel@tonic-gate 	}
6567c478bd9Sstevel@tonic-gate 	if (ret != 0) {
6577c478bd9Sstevel@tonic-gate 		/* Error of some sort, tell'm about it */
6587c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "ncalogdconf_read: %s: open error(%d).",
6597c478bd9Sstevel@tonic-gate 		    ncalogd, ret);
6607c478bd9Sstevel@tonic-gate 		return;
6617c478bd9Sstevel@tonic-gate 	}
6627c478bd9Sstevel@tonic-gate 	/*
6637c478bd9Sstevel@tonic-gate 	 * Read ncalogd.conf one buf[] at a time, parse one char at a time.
6647c478bd9Sstevel@tonic-gate 	 */
6657c478bd9Sstevel@tonic-gate 	for (;;) {
6667c478bd9Sstevel@tonic-gate 		if (bp == ebp) {
6677c478bd9Sstevel@tonic-gate 			/* Nothing left in buf[], read another */
6687c478bd9Sstevel@tonic-gate 			ret = vn_rdwr(UIO_READ, vp, buf, sizeof (buf), off,
6697c478bd9Sstevel@tonic-gate 			    UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid);
6707c478bd9Sstevel@tonic-gate 			if (ret != 0) {
6717c478bd9Sstevel@tonic-gate 				/* Error of some sort, tell'm about it */
6727c478bd9Sstevel@tonic-gate 				cmn_err(CE_WARN, "%s: read error %d",
6737c478bd9Sstevel@tonic-gate 				    ncalogd, ret);
6747c478bd9Sstevel@tonic-gate 				break;
6757c478bd9Sstevel@tonic-gate 			}
6767c478bd9Sstevel@tonic-gate 			if (resid == sizeof (buf)) {
6777c478bd9Sstevel@tonic-gate 				/* EOF, done */
6787c478bd9Sstevel@tonic-gate 				break;
6797c478bd9Sstevel@tonic-gate 			}
6807c478bd9Sstevel@tonic-gate 			/* Initilize per buf[] state */
6817c478bd9Sstevel@tonic-gate 			bp = buf;
6827c478bd9Sstevel@tonic-gate 			ebp = &buf[sizeof (buf) - resid];
6837c478bd9Sstevel@tonic-gate 			off += sizeof (buf) - resid;
6847c478bd9Sstevel@tonic-gate 		}
6857c478bd9Sstevel@tonic-gate 		c = *bp++;
6867c478bd9Sstevel@tonic-gate 		switch (parse) {
6877c478bd9Sstevel@tonic-gate 		case START:
6887c478bd9Sstevel@tonic-gate 			/* Initilize all per file line state */
6897c478bd9Sstevel@tonic-gate 			tokstatusp = tokstatus;
6907c478bd9Sstevel@tonic-gate 			toksizep = toksize;
6917c478bd9Sstevel@tonic-gate 			tokfilep = tokfile;
6927c478bd9Sstevel@tonic-gate 			tok = NULL;
6937c478bd9Sstevel@tonic-gate 			parse = TOK;
6947c478bd9Sstevel@tonic-gate 			sz = 0;
6957c478bd9Sstevel@tonic-gate 			/*FALLTHROUGH*/
6967c478bd9Sstevel@tonic-gate 		case TOK:
6977c478bd9Sstevel@tonic-gate 			if (isalpha(c) || c == '_') {
6987c478bd9Sstevel@tonic-gate 				/*
6997c478bd9Sstevel@tonic-gate 				 * Found a valid tok char, if matches
7007c478bd9Sstevel@tonic-gate 				 * any of the tokens continue else NULL
7017c478bd9Sstevel@tonic-gate 				 * then string pointer.
7027c478bd9Sstevel@tonic-gate 				 */
7037c478bd9Sstevel@tonic-gate 				if (tokstatusp != NULL && c != *tokstatusp++)
7047c478bd9Sstevel@tonic-gate 					tokstatusp = NULL;
7057c478bd9Sstevel@tonic-gate 				if (toksizep != NULL && c != *toksizep++)
7067c478bd9Sstevel@tonic-gate 					toksizep = NULL;
7077c478bd9Sstevel@tonic-gate 				if (tokfilep != NULL && c != *tokfilep++)
7087c478bd9Sstevel@tonic-gate 					tokfilep = NULL;
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate 				if (tokstatusp == NULL &&
7117c478bd9Sstevel@tonic-gate 				    toksizep == NULL &&
7127c478bd9Sstevel@tonic-gate 				    tokfilep == NULL) {
7137c478bd9Sstevel@tonic-gate 					/*
7147c478bd9Sstevel@tonic-gate 					 * All tok string pointers are NULL
7157c478bd9Sstevel@tonic-gate 					 * so skip rest of line.
7167c478bd9Sstevel@tonic-gate 					 */
7177c478bd9Sstevel@tonic-gate 					parse = EOL;
7187c478bd9Sstevel@tonic-gate 				}
7197c478bd9Sstevel@tonic-gate 			} else if (c == '=') {
7207c478bd9Sstevel@tonic-gate 				/*
7217c478bd9Sstevel@tonic-gate 				 * Found tok separator, if tok found get
7227c478bd9Sstevel@tonic-gate 				 * tok text, else skip rest of line.
7237c478bd9Sstevel@tonic-gate 				 */
7247c478bd9Sstevel@tonic-gate 				if (tokstatusp != NULL && *tokstatusp == NULL)
7257c478bd9Sstevel@tonic-gate 					tok = tokstatus;
7267c478bd9Sstevel@tonic-gate 				else if (toksizep != NULL && *toksizep == NULL)
7277c478bd9Sstevel@tonic-gate 					tok = toksize;
7287c478bd9Sstevel@tonic-gate 				else if (tokfilep != NULL && *tokfilep == NULL)
7297c478bd9Sstevel@tonic-gate 					tok = tokfile;
7307c478bd9Sstevel@tonic-gate 				if (tok != NULL)
7317c478bd9Sstevel@tonic-gate 					parse = TEXT;
7327c478bd9Sstevel@tonic-gate 				else
7337c478bd9Sstevel@tonic-gate 					parse = EOL;
7347c478bd9Sstevel@tonic-gate 			} else if (c == '\n') {
7357c478bd9Sstevel@tonic-gate 				/* Found EOL, start on next line */
7367c478bd9Sstevel@tonic-gate 				parse = START;
7377c478bd9Sstevel@tonic-gate 			} else {
7387c478bd9Sstevel@tonic-gate 				/* Comment or unknown char, skip rest of line */
7397c478bd9Sstevel@tonic-gate 				parse = EOL;
7407c478bd9Sstevel@tonic-gate 			}
7417c478bd9Sstevel@tonic-gate 			break;
7427c478bd9Sstevel@tonic-gate 		case TEXT:
7437c478bd9Sstevel@tonic-gate 			if (c == '\n') {
7447c478bd9Sstevel@tonic-gate 				/*
7457c478bd9Sstevel@tonic-gate 				 * Found EOL, finish up tok text processing
7467c478bd9Sstevel@tonic-gate 				 * (if any) and start on next line.
7477c478bd9Sstevel@tonic-gate 				 */
7487c478bd9Sstevel@tonic-gate 				if (tok == tokstatus) {
7497c478bd9Sstevel@tonic-gate 					if (*++tokstatusp == NULL)
7507c478bd9Sstevel@tonic-gate 						nl7c_logd_enabled = B_TRUE;
7517c478bd9Sstevel@tonic-gate 				} else if (tok == toksize) {
7527c478bd9Sstevel@tonic-gate 					file_size = sz;
7537c478bd9Sstevel@tonic-gate 				} else if (tok == tokfile) {
7547c478bd9Sstevel@tonic-gate 					if (tokdelim == 0) {
7557c478bd9Sstevel@tonic-gate 						/* Non delimited path name */
7567c478bd9Sstevel@tonic-gate 						*fnvp++ = strdup(file);
7577c478bd9Sstevel@tonic-gate 					} else if (fp != file) {
7587c478bd9Sstevel@tonic-gate 						/* No closing delimiter */
7597c478bd9Sstevel@tonic-gate 						/*EMPTY*/;
7607c478bd9Sstevel@tonic-gate 					}
7617c478bd9Sstevel@tonic-gate 				}
7627c478bd9Sstevel@tonic-gate 				parse = START;
7637c478bd9Sstevel@tonic-gate 			} else if (tok == tokstatus) {
7647c478bd9Sstevel@tonic-gate 				if (! isalpha(c) || *++tokstatusp == NULL ||
7657c478bd9Sstevel@tonic-gate 				    c != *tokstatusp) {
7667c478bd9Sstevel@tonic-gate 					/* Not enabled, skip line */
7677c478bd9Sstevel@tonic-gate 					parse = EOL;
7687c478bd9Sstevel@tonic-gate 				}
7697c478bd9Sstevel@tonic-gate 			} else if (tok == toksize) {
7707c478bd9Sstevel@tonic-gate 				if (isdigit(c)) {
7717c478bd9Sstevel@tonic-gate 					sz *= 10;
7727c478bd9Sstevel@tonic-gate 					sz += c - '0';
7737c478bd9Sstevel@tonic-gate 				} else {
7747c478bd9Sstevel@tonic-gate 					/* Not a decimal digit, skip line */
7757c478bd9Sstevel@tonic-gate 					parse = EOL;
7767c478bd9Sstevel@tonic-gate 				}
7777c478bd9Sstevel@tonic-gate 			} else {
7787c478bd9Sstevel@tonic-gate 				/* File name */
7797c478bd9Sstevel@tonic-gate 				if (c == '"' && tokdelim++ == 0) {
7807c478bd9Sstevel@tonic-gate 					/* Opening delimiter, skip */
7817c478bd9Sstevel@tonic-gate 					/*EMPTY*/;
7827c478bd9Sstevel@tonic-gate 				} else if (c == '"' || c == ' ') {
783da6c28aaSamw 					/* List delim or filename separator */
7847c478bd9Sstevel@tonic-gate 					*fnvp++ = strdup(file);
7857c478bd9Sstevel@tonic-gate 					fp = file;
7867c478bd9Sstevel@tonic-gate 				} else if (fp < &file[sizeof (file) - 1]) {
7877c478bd9Sstevel@tonic-gate 					/* Filename char */
7887c478bd9Sstevel@tonic-gate 					*fp++ = c;
7897c478bd9Sstevel@tonic-gate 				} else {
7907c478bd9Sstevel@tonic-gate 					/* Filename to long, skip line */
7917c478bd9Sstevel@tonic-gate 					parse = EOL;
7927c478bd9Sstevel@tonic-gate 				}
7937c478bd9Sstevel@tonic-gate 			}
7947c478bd9Sstevel@tonic-gate 			break;
7957c478bd9Sstevel@tonic-gate 
7967c478bd9Sstevel@tonic-gate 		case EOL:
7977c478bd9Sstevel@tonic-gate 			if (c == '\n') {
7987c478bd9Sstevel@tonic-gate 				/* Found EOL, start on next line */
7997c478bd9Sstevel@tonic-gate 				parse = START;
8007c478bd9Sstevel@tonic-gate 			}
8017c478bd9Sstevel@tonic-gate 			break;
8027c478bd9Sstevel@tonic-gate 		}
8037c478bd9Sstevel@tonic-gate 
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate done:
806da6c28aaSamw 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
8077c478bd9Sstevel@tonic-gate 	VN_RELE(vp);
8087c478bd9Sstevel@tonic-gate 
8097c478bd9Sstevel@tonic-gate 	if (nl7c_logd_enabled) {
8107c478bd9Sstevel@tonic-gate 		if (fnvp == fnv) {
8117c478bd9Sstevel@tonic-gate 			/*
8127c478bd9Sstevel@tonic-gate 			 * No logfile was specified and found so
8137c478bd9Sstevel@tonic-gate 			 * so use defualt NCA log file path.
8147c478bd9Sstevel@tonic-gate 			 */
8157c478bd9Sstevel@tonic-gate 			*fnvp++ = strdup(ncadeflog);
8167c478bd9Sstevel@tonic-gate 		}
8177c478bd9Sstevel@tonic-gate 		if (fnvp < &fnv[NCA_FIOV_SZ]) {
8187c478bd9Sstevel@tonic-gate 			/* NULL terminate list */
8197c478bd9Sstevel@tonic-gate 			*fnvp = NULL;
8207c478bd9Sstevel@tonic-gate 		}
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate }
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate void
nl7clogd_startup(void)8257c478bd9Sstevel@tonic-gate nl7clogd_startup(void)
8267c478bd9Sstevel@tonic-gate {
8277c478bd9Sstevel@tonic-gate 	static kmutex_t startup;
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	/*
8307c478bd9Sstevel@tonic-gate 	 * Called on the first log() attempt, have to wait until then to
8317c478bd9Sstevel@tonic-gate 	 * initialize logd as at logdconf_read() the root fs is read-only.
8327c478bd9Sstevel@tonic-gate 	 */
8337c478bd9Sstevel@tonic-gate 	mutex_enter(&startup);
8347c478bd9Sstevel@tonic-gate 	if (nl7c_logd_started) {
8357c478bd9Sstevel@tonic-gate 		/* Lost the race, nothing todo */
8367c478bd9Sstevel@tonic-gate 		mutex_exit(&startup);
8377c478bd9Sstevel@tonic-gate 		return;
8387c478bd9Sstevel@tonic-gate 	}
8397c478bd9Sstevel@tonic-gate 	nl7c_logd_started = B_TRUE;
8407c478bd9Sstevel@tonic-gate 	if (! nl7c_logd_init(file_size, fnv)) {
8417c478bd9Sstevel@tonic-gate 		/* Failure, disable logging */
8427c478bd9Sstevel@tonic-gate 		nl7c_logd_enabled = B_FALSE;
8437c478bd9Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7clogd_startup: failed, disabling loggin");
8447c478bd9Sstevel@tonic-gate 		mutex_exit(&startup);
8457c478bd9Sstevel@tonic-gate 		return;
8467c478bd9Sstevel@tonic-gate 	}
8477c478bd9Sstevel@tonic-gate 	mutex_exit(&startup);
8487c478bd9Sstevel@tonic-gate }
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 
8517c478bd9Sstevel@tonic-gate void
nl7c_startup()8527c478bd9Sstevel@tonic-gate nl7c_startup()
8537c478bd9Sstevel@tonic-gate {
8542c9e429eSbrutus 	/*
8552c9e429eSbrutus 	 * Open, read, and parse the NCA logd configuration file,
8562c9e429eSbrutus 	 * then initialize URI processing and NCA compat.
8572c9e429eSbrutus 	 */
8587c478bd9Sstevel@tonic-gate 	ncalogdconf_read();
8597c478bd9Sstevel@tonic-gate 	nl7c_uri_init();
8607c478bd9Sstevel@tonic-gate 	nl7c_nca_init();
8617c478bd9Sstevel@tonic-gate }
8627c478bd9Sstevel@tonic-gate 
8637c478bd9Sstevel@tonic-gate void
nl7c_init()8647c478bd9Sstevel@tonic-gate nl7c_init()
8657c478bd9Sstevel@tonic-gate {
8667c478bd9Sstevel@tonic-gate 	/* Open, read, and parse the NCA kmod configuration file */
8677c478bd9Sstevel@tonic-gate 	ncakmodconf_read();
8687c478bd9Sstevel@tonic-gate 
8697c478bd9Sstevel@tonic-gate 	if (nl7c_enabled) {
8707c478bd9Sstevel@tonic-gate 		/*
8717c478bd9Sstevel@tonic-gate 		 * NL7C is enabled so open, read, and parse
8727c478bd9Sstevel@tonic-gate 		 * the NCA address/port configuration file
8737c478bd9Sstevel@tonic-gate 		 * and call startup() to finish config/init.
8747c478bd9Sstevel@tonic-gate 		 */
8757c478bd9Sstevel@tonic-gate 		ncaportconf_read();
8767c478bd9Sstevel@tonic-gate 		nl7c_startup();
8777c478bd9Sstevel@tonic-gate 	}
8787c478bd9Sstevel@tonic-gate }
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate /*
8817c478bd9Sstevel@tonic-gate  * The main processing function called by accept() on a newly created
8827c478bd9Sstevel@tonic-gate  * socket prior to returning it to the caller of accept().
8837c478bd9Sstevel@tonic-gate  *
8847c478bd9Sstevel@tonic-gate  * Here data is read from the socket until a completed L7 request parse
8857c478bd9Sstevel@tonic-gate  * is completed. Data will be read in the context of the user thread
8867c478bd9Sstevel@tonic-gate  * which called accept(), when parse has been completed either B_TRUE
8877c478bd9Sstevel@tonic-gate  * or B_FALSE will be returned.
8887c478bd9Sstevel@tonic-gate  *
8897c478bd9Sstevel@tonic-gate  * If NL7C successfully process the L7 protocol request, i.e. generates
8907c478bd9Sstevel@tonic-gate  * a response, B_TRUE will be returned.
8917c478bd9Sstevel@tonic-gate  *
8927c478bd9Sstevel@tonic-gate  * Else, B_FALSE will be returned if NL7C can't process the request:
8937c478bd9Sstevel@tonic-gate  *
8947c478bd9Sstevel@tonic-gate  * 1) Couldn't locate a URI within the request.
8957c478bd9Sstevel@tonic-gate  *
8967c478bd9Sstevel@tonic-gate  * 2) URI scheme not reqcognized.
8977c478bd9Sstevel@tonic-gate  *
898da6c28aaSamw  * 3) A request which can't be processed.
8997c478bd9Sstevel@tonic-gate  *
9007c478bd9Sstevel@tonic-gate  * 4) A request which could be processed but NL7C dosen't currently have
9017c478bd9Sstevel@tonic-gate  *    the response data. In which case NL7C will parse the returned response
9027c478bd9Sstevel@tonic-gate  *    from the application for possible caching for subsequent request(s).
9037c478bd9Sstevel@tonic-gate  */
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_cnt = 0;
9067c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_error = 0;
9077c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_ETIME = 0;
9087c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_again = 0;
9097c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_next = 0;
9107c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_rcv = 0;
9117c478bd9Sstevel@tonic-gate volatile uint64_t nl7c_proc_noLRI = 0;
9122c9e429eSbrutus volatile uint64_t nl7c_proc_nodata = 0;
9132c9e429eSbrutus volatile uint64_t nl7c_proc_parse = 0;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate boolean_t
nl7c_process(struct sonode * so,boolean_t nonblocking)9162c9e429eSbrutus nl7c_process(struct sonode *so, boolean_t nonblocking)
9177c478bd9Sstevel@tonic-gate {
9187c478bd9Sstevel@tonic-gate 	vnode_t	*vp = SOTOV(so);
9190f1702c5SYu Xiangning 	sotpi_info_t *sti = SOTOTPI(so);
9200f1702c5SYu Xiangning 	mblk_t	*rmp = sti->sti_nl7c_rcv_mp;
9217c478bd9Sstevel@tonic-gate 	clock_t	timout;
9222c9e429eSbrutus 	rval_t	rval;
9237c478bd9Sstevel@tonic-gate 	uchar_t pri;
9247c478bd9Sstevel@tonic-gate 	int 	pflag;
9257c478bd9Sstevel@tonic-gate 	int	error;
9267c478bd9Sstevel@tonic-gate 	boolean_t more;
9272c9e429eSbrutus 	boolean_t ret = B_FALSE;
9282c9e429eSbrutus 	boolean_t first = B_TRUE;
9290f1702c5SYu Xiangning 	boolean_t pollin = (sti->sti_nl7c_flags & NL7C_POLLIN);
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	nl7c_proc_cnt++;
9327c478bd9Sstevel@tonic-gate 
9332c9e429eSbrutus 	/* Caller has so_lock enter()ed */
9347c478bd9Sstevel@tonic-gate 	error = so_lock_read_intr(so, nonblocking ? FNDELAY|FNONBLOCK : 0);
9357c478bd9Sstevel@tonic-gate 	if (error) {
9367c478bd9Sstevel@tonic-gate 		/* Couldn't read lock, pass on this socket */
9370f1702c5SYu Xiangning 		sti->sti_nl7c_flags = 0;
9387c478bd9Sstevel@tonic-gate 		nl7c_proc_noLRI++;
9392c9e429eSbrutus 		return (B_FALSE);
9407c478bd9Sstevel@tonic-gate 	}
9412c9e429eSbrutus 	/* Exit so_lock for now, will be reenter()ed prior to return */
9427c478bd9Sstevel@tonic-gate 	mutex_exit(&so->so_lock);
9437c478bd9Sstevel@tonic-gate 
9442c9e429eSbrutus 	if (pollin)
9450f1702c5SYu Xiangning 		sti->sti_nl7c_flags &= ~NL7C_POLLIN;
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	/* Initialize some kstrgetmsg() constants */
9482c9e429eSbrutus 	pflag = MSG_ANY | MSG_DELAYERROR;
9497c478bd9Sstevel@tonic-gate 	pri = 0;
9502c9e429eSbrutus 	if (nonblocking) {
9512c9e429eSbrutus 		/* Non blocking so don't block */
9527c478bd9Sstevel@tonic-gate 		timout = 0;
9530f1702c5SYu Xiangning 	} else if (sti->sti_nl7c_flags & NL7C_SOPERSIST) {
9542c9e429eSbrutus 		/* 2nd or more time(s) here so use keep-alive value */
9552c9e429eSbrutus 		timout = nca_http_keep_alive_timeout;
9562c9e429eSbrutus 	} else {
9572c9e429eSbrutus 		/* 1st time here so use connection value */
9582c9e429eSbrutus 		timout = nca_http_timeout;
9592c9e429eSbrutus 	}
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	rval.r_vals = 0;
9622c9e429eSbrutus 	do {
9632c9e429eSbrutus 		/*
9642c9e429eSbrutus 		 * First time through, if no data left over from a previous
9652c9e429eSbrutus 		 * kstrgetmsg() then try to get some, else just process it.
9662c9e429eSbrutus 		 *
967da6c28aaSamw 		 * Thereafter, rmp = NULL after the successful kstrgetmsg()
9682c9e429eSbrutus 		 * so try to get some new data and append to list (i.e. until
969da6c28aaSamw 		 * enough fragments are collected for a successful parse).
9702c9e429eSbrutus 		 */
9712c9e429eSbrutus 		if (rmp == NULL) {
9722c9e429eSbrutus 
9737c478bd9Sstevel@tonic-gate 			error = kstrgetmsg(vp, &rmp, NULL, &pri, &pflag,
9747c478bd9Sstevel@tonic-gate 			    timout, &rval);
9757c478bd9Sstevel@tonic-gate 			if (error) {
9767c478bd9Sstevel@tonic-gate 				if (error == ETIME) {
9777c478bd9Sstevel@tonic-gate 					/* Timeout */
9787c478bd9Sstevel@tonic-gate 					nl7c_proc_ETIME++;
9792c9e429eSbrutus 				} else if (error != EWOULDBLOCK) {
9807c478bd9Sstevel@tonic-gate 					/* Error of some sort */
9817c478bd9Sstevel@tonic-gate 					nl7c_proc_error++;
9822c9e429eSbrutus 					rval.r_v.r_v2 = error;
9830f1702c5SYu Xiangning 					sti->sti_nl7c_flags = 0;
9847c478bd9Sstevel@tonic-gate 					break;
9857c478bd9Sstevel@tonic-gate 				}
9862c9e429eSbrutus 				error = 0;
9872c9e429eSbrutus 			}
9882c9e429eSbrutus 			if (rmp != NULL) {
9890f1702c5SYu Xiangning 				mblk_t	*mp = sti->sti_nl7c_rcv_mp;
9907c478bd9Sstevel@tonic-gate 
9912c9e429eSbrutus 
9927c478bd9Sstevel@tonic-gate 				if (mp == NULL) {
9932c9e429eSbrutus 					/* Just new data, common case */
9940f1702c5SYu Xiangning 					sti->sti_nl7c_rcv_mp = rmp;
9957c478bd9Sstevel@tonic-gate 				} else {
9962c9e429eSbrutus 					/* Add new data to tail */
9972c9e429eSbrutus 					while (mp->b_cont != NULL)
9982c9e429eSbrutus 						mp = mp->b_cont;
9992c9e429eSbrutus 					mp->b_cont = rmp;
10007c478bd9Sstevel@tonic-gate 				}
10012c9e429eSbrutus 			}
10020f1702c5SYu Xiangning 			if (sti->sti_nl7c_rcv_mp == NULL) {
10032c9e429eSbrutus 				/* No data */
10042c9e429eSbrutus 				nl7c_proc_nodata++;
10052c9e429eSbrutus 				if (timout > 0 || (first && pollin)) {
10062c9e429eSbrutus 					/* Expected data so EOF */
10072c9e429eSbrutus 					ret = B_TRUE;
10080f1702c5SYu Xiangning 				} else if (sti->sti_nl7c_flags &
10090f1702c5SYu Xiangning 				    NL7C_SOPERSIST) {
10102c9e429eSbrutus 					/* Persistent so just checking */
10112c9e429eSbrutus 					ret = B_FALSE;
10122c9e429eSbrutus 				}
10132c9e429eSbrutus 				break;
10142c9e429eSbrutus 			}
10157c478bd9Sstevel@tonic-gate 			rmp = NULL;
10162c9e429eSbrutus 		}
10172c9e429eSbrutus 		first = B_FALSE;
10187c478bd9Sstevel@tonic-gate 	again:
10192c9e429eSbrutus 		nl7c_proc_parse++;
10207c478bd9Sstevel@tonic-gate 
10212c9e429eSbrutus 		more = nl7c_parse(so, nonblocking, &ret);
10222c9e429eSbrutus 
10230f1702c5SYu Xiangning 		if (ret == B_TRUE && (sti->sti_nl7c_flags & NL7C_SOPERSIST)) {
10247c478bd9Sstevel@tonic-gate 			/*
10252c9e429eSbrutus 			 * Parse complete, cache hit, response on its way,
10262c9e429eSbrutus 			 * socket is persistent so try to process the next
10272c9e429eSbrutus 			 * request.
10287c478bd9Sstevel@tonic-gate 			 */
10292c9e429eSbrutus 			if (nonblocking) {
10302c9e429eSbrutus 				ret = B_FALSE;
10312c9e429eSbrutus 				break;
10322c9e429eSbrutus 			}
10330f1702c5SYu Xiangning 			if (sti->sti_nl7c_rcv_mp) {
10342c9e429eSbrutus 				/* More recv-side data, pipelined */
10357c478bd9Sstevel@tonic-gate 				nl7c_proc_again++;
10367c478bd9Sstevel@tonic-gate 				goto again;
10377c478bd9Sstevel@tonic-gate 			}
10387c478bd9Sstevel@tonic-gate 			nl7c_proc_next++;
10397c478bd9Sstevel@tonic-gate 			if (nonblocking)
10407c478bd9Sstevel@tonic-gate 				timout = 0;
10417c478bd9Sstevel@tonic-gate 			else
10422c9e429eSbrutus 				timout = nca_http_keep_alive_timeout;
10432c9e429eSbrutus 
10447c478bd9Sstevel@tonic-gate 			more = B_TRUE;
10457c478bd9Sstevel@tonic-gate 		}
10467c478bd9Sstevel@tonic-gate 
10477c478bd9Sstevel@tonic-gate 	} while (more);
10487c478bd9Sstevel@tonic-gate 
10490f1702c5SYu Xiangning 	if (sti->sti_nl7c_rcv_mp) {
10507c478bd9Sstevel@tonic-gate 		nl7c_proc_rcv++;
10517c478bd9Sstevel@tonic-gate 	}
10520f1702c5SYu Xiangning 	sti->sti_nl7c_rcv_rval = rval.r_vals;
10532c9e429eSbrutus 	/* Renter so_lock, caller called with it enter()ed */
10547c478bd9Sstevel@tonic-gate 	mutex_enter(&so->so_lock);
10557c478bd9Sstevel@tonic-gate 	so_unlock_read(so);
10562c9e429eSbrutus 
10577c478bd9Sstevel@tonic-gate 	return (ret);
10587c478bd9Sstevel@tonic-gate }
1059