xref: /onnv-gate/usr/src/uts/common/fs/sockfs/nl7c.c (revision 8348:4137e18bfaf0)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
51974Sbrutus  * Common Development and Distribution License (the "License").
61974Sbrutus  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*8348SEric.Yu@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate /*
270Sstevel@tonic-gate  * NL7C (Network Layer 7 Cache) as part of SOCKFS provides an in-kernel
280Sstevel@tonic-gate  * gateway cache for the request/response message based L7 protocol HTTP
290Sstevel@tonic-gate  * (Hypertext Transfer Protocol, see HTTP/1.1 RFC2616) in a semantically
300Sstevel@tonic-gate  * transparent manner.
310Sstevel@tonic-gate  *
325331Samw  * Neither the requesting user agent (client, e.g. web browser) nor the
330Sstevel@tonic-gate  * origin server (e.g. webserver) that provided the response cached by
340Sstevel@tonic-gate  * NL7C are impacted in any way.
350Sstevel@tonic-gate  *
360Sstevel@tonic-gate  * Note, currently NL7C only processes HTTP messages via the embedded
370Sstevel@tonic-gate  * URI of scheme http (not https nor any other), additional scheme are
385331Samw  * intended to be supported as is practical such that much of the NL7C
395331Samw  * framework may appear more general purpose then would be needed just
400Sstevel@tonic-gate  * for an HTTP gateway cache.
410Sstevel@tonic-gate  *
420Sstevel@tonic-gate  * NL7C replaces NCA (Network Cache and Accelerator) and in the future
430Sstevel@tonic-gate  * NCAS (NCA/SSL).
440Sstevel@tonic-gate  *
450Sstevel@tonic-gate  * Further, NL7C uses all NCA configuration files, see "/etc/nca/", the
465331Samw  * NCA socket API, "AF_NCA", and "ndd /dev/nca" for backwards compatibility.
470Sstevel@tonic-gate  */
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #include <sys/systm.h>
500Sstevel@tonic-gate #include <sys/strsun.h>
510Sstevel@tonic-gate #include <sys/strsubr.h>
520Sstevel@tonic-gate #include <inet/common.h>
530Sstevel@tonic-gate #include <inet/led.h>
540Sstevel@tonic-gate #include <inet/mi.h>
550Sstevel@tonic-gate #include <netinet/in.h>
560Sstevel@tonic-gate #include <fs/sockfs/nl7c.h>
570Sstevel@tonic-gate #include <fs/sockfs/nl7curi.h>
58*8348SEric.Yu@Sun.COM #include <fs/sockfs/socktpi.h>
590Sstevel@tonic-gate 
600Sstevel@tonic-gate #include <inet/nca/ncadoorhdr.h>
610Sstevel@tonic-gate #include <inet/nca/ncalogd.h>
621974Sbrutus #include <inet/nca/ncandd.h>
631974Sbrutus 
641974Sbrutus #include <sys/promif.h>
650Sstevel@tonic-gate 
660Sstevel@tonic-gate /*
670Sstevel@tonic-gate  * NL7C, NCA, NL7C logger enabled:
680Sstevel@tonic-gate  */
690Sstevel@tonic-gate 
700Sstevel@tonic-gate boolean_t	nl7c_enabled = B_FALSE;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate boolean_t	nl7c_logd_enabled = B_FALSE;
730Sstevel@tonic-gate boolean_t	nl7c_logd_started = B_FALSE;
740Sstevel@tonic-gate boolean_t	nl7c_logd_cycle = B_TRUE;
750Sstevel@tonic-gate 
760Sstevel@tonic-gate /*
770Sstevel@tonic-gate  * Some externs:
780Sstevel@tonic-gate  */
790Sstevel@tonic-gate 
800Sstevel@tonic-gate extern int	inet_pton(int, char *, void *);
810Sstevel@tonic-gate 
820Sstevel@tonic-gate extern void	nl7c_uri_init(void);
830Sstevel@tonic-gate extern boolean_t nl7c_logd_init(int, caddr_t *);
840Sstevel@tonic-gate extern void	nl7c_nca_init(void);
850Sstevel@tonic-gate 
860Sstevel@tonic-gate /*
870Sstevel@tonic-gate  * nl7c_addr_t - a singly linked grounded list, pointed to by *nl7caddrs,
880Sstevel@tonic-gate  * constructed at init time by parsing "/etc/nca/ncaport.conf".
890Sstevel@tonic-gate  *
900Sstevel@tonic-gate  * This list is searched at bind(3SOCKET) time when an application doesn't
910Sstevel@tonic-gate  * explicitly set AF_NCA but instead uses AF_INET, if a match is found then
92*8348SEric.Yu@Sun.COM  * the underlying socket is marked sti_nl7c_flags NL7C_ENABLED.
930Sstevel@tonic-gate  */
940Sstevel@tonic-gate 
950Sstevel@tonic-gate typedef struct nl7c_addr_s {
960Sstevel@tonic-gate 	struct nl7c_addr_s *next;	/* next entry */
970Sstevel@tonic-gate 	sa_family_t	family;		/* addr type, only INET and INET6 */
980Sstevel@tonic-gate 	uint16_t	port;		/* port */
990Sstevel@tonic-gate 	union {
1000Sstevel@tonic-gate 		ipaddr_t	v4;	/* IPv4 address */
1010Sstevel@tonic-gate 		in6_addr_t	v6;	/* IPv6 address */
1020Sstevel@tonic-gate 		void		*align;	/* foce alignment */
1030Sstevel@tonic-gate 	}		addr;		/* address */
1040Sstevel@tonic-gate 
1051974Sbrutus 	struct sonode	*listener;	/* listen()er's sonode */
1060Sstevel@tonic-gate 	boolean_t	temp;		/* temporary addr via add_addr() ? */
1070Sstevel@tonic-gate } nl7c_addr_t;
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate nl7c_addr_t	*nl7caddrs = NULL;
1100Sstevel@tonic-gate 
1111974Sbrutus /*
1121974Sbrutus  * Called for an NL7C_ENABLED listen()er socket for the nl7c_addr_t
1131974Sbrutus  * previously returned by nl7c_lookup_addr().
1141974Sbrutus  */
1151974Sbrutus 
1160Sstevel@tonic-gate void
nl7c_listener_addr(void * arg,struct sonode * so)1171974Sbrutus nl7c_listener_addr(void *arg, struct sonode *so)
1180Sstevel@tonic-gate {
1191974Sbrutus 	nl7c_addr_t		*p = (nl7c_addr_t *)arg;
1201974Sbrutus 
1211974Sbrutus 	if (p->listener == NULL)
1221974Sbrutus 		p->listener = so;
123*8348SEric.Yu@Sun.COM 	SOTOTPI(so)->sti_nl7c_addr = arg;
1241974Sbrutus }
1250Sstevel@tonic-gate 
1261974Sbrutus struct sonode *
nl7c_addr2portso(void * arg)1271974Sbrutus nl7c_addr2portso(void *arg)
1281974Sbrutus {
1291974Sbrutus 	nl7c_addr_t		*p = (nl7c_addr_t *)arg;
1301974Sbrutus 
1311974Sbrutus 	return (p->listener);
1320Sstevel@tonic-gate }
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate void *
nl7c_lookup_addr(void * addr,t_uscalar_t addrlen)1350Sstevel@tonic-gate nl7c_lookup_addr(void *addr, t_uscalar_t addrlen)
1360Sstevel@tonic-gate {
1370Sstevel@tonic-gate 	struct sockaddr		*sap = addr;
1380Sstevel@tonic-gate 	struct sockaddr_in	*v4p = addr;
1390Sstevel@tonic-gate 	nl7c_addr_t		*p = nl7caddrs;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	if (sap->sa_family != AF_INET || addrlen != sizeof (*v4p)) {
1420Sstevel@tonic-gate 		/* Only support IPv4 */
1430Sstevel@tonic-gate 		return (B_FALSE);
1440Sstevel@tonic-gate 	}
1450Sstevel@tonic-gate 	while (p) {
1460Sstevel@tonic-gate 		if (sap->sa_family == p->family &&
1470Sstevel@tonic-gate 		    v4p->sin_port == p->port &&
1480Sstevel@tonic-gate 		    (v4p->sin_addr.s_addr == p->addr.v4 ||
1490Sstevel@tonic-gate 		    p->addr.v4 == INADDR_ANY)) {
1500Sstevel@tonic-gate 			/* Match */
1510Sstevel@tonic-gate 			return (p);
1520Sstevel@tonic-gate 		}
1530Sstevel@tonic-gate 		p = p->next;
1540Sstevel@tonic-gate 	}
1550Sstevel@tonic-gate 	return (NULL);
1560Sstevel@tonic-gate }
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate void *
nl7c_add_addr(void * addr,t_uscalar_t addrlen)1590Sstevel@tonic-gate nl7c_add_addr(void *addr, t_uscalar_t addrlen)
1600Sstevel@tonic-gate {
1610Sstevel@tonic-gate 	struct sockaddr		*sap = addr;
1620Sstevel@tonic-gate 	struct sockaddr_in	*v4p = addr;
1630Sstevel@tonic-gate 	nl7c_addr_t		*new = NULL;
1640Sstevel@tonic-gate 	nl7c_addr_t		*old;
1650Sstevel@tonic-gate 	nl7c_addr_t		*p;
1660Sstevel@tonic-gate 	boolean_t		alloced;
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 	if (sap->sa_family != AF_INET || addrlen != sizeof (*v4p)) {
1690Sstevel@tonic-gate 		/* Only support IPv4 */
1700Sstevel@tonic-gate 		return (NULL);
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate again:
1730Sstevel@tonic-gate 	p = nl7caddrs;
1740Sstevel@tonic-gate 	while (p) {
1750Sstevel@tonic-gate 		if (new == NULL && p->port == 0)
1760Sstevel@tonic-gate 			new = p;
1770Sstevel@tonic-gate 		if (sap->sa_family == p->family &&
1780Sstevel@tonic-gate 		    v4p->sin_port == p->port &&
1790Sstevel@tonic-gate 		    (v4p->sin_addr.s_addr == p->addr.v4 ||
1800Sstevel@tonic-gate 		    p->addr.v4 == INADDR_ANY)) {
1810Sstevel@tonic-gate 			/* Match */
1820Sstevel@tonic-gate 			return (p);
1830Sstevel@tonic-gate 		}
1840Sstevel@tonic-gate 		p = p->next;
1850Sstevel@tonic-gate 	}
1860Sstevel@tonic-gate 	if (new == NULL) {
1870Sstevel@tonic-gate 		new = kmem_zalloc(sizeof (*new), KM_SLEEP);
1880Sstevel@tonic-gate 		alloced = B_TRUE;
1890Sstevel@tonic-gate 	} else
1900Sstevel@tonic-gate 		alloced = B_FALSE;
1910Sstevel@tonic-gate 
1920Sstevel@tonic-gate 	new->family = sap->sa_family;
1930Sstevel@tonic-gate 	new->port = v4p->sin_port;
1940Sstevel@tonic-gate 	new->addr.v4 = v4p->sin_addr.s_addr;
1950Sstevel@tonic-gate 	new->temp = B_TRUE;
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	if (alloced) {
1981974Sbrutus 		old = nl7caddrs;
1990Sstevel@tonic-gate 		new->next = old;
2000Sstevel@tonic-gate 		if (atomic_cas_ptr(&nl7caddrs, old, new) != old) {
2010Sstevel@tonic-gate 			kmem_free(new, sizeof (*new));
2020Sstevel@tonic-gate 			goto again;
2030Sstevel@tonic-gate 		}
2040Sstevel@tonic-gate 	}
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	return (new);
2070Sstevel@tonic-gate }
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate boolean_t
nl7c_close_addr(struct sonode * so)2100Sstevel@tonic-gate nl7c_close_addr(struct sonode *so)
2110Sstevel@tonic-gate {
2120Sstevel@tonic-gate 	nl7c_addr_t	*p = nl7caddrs;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 	while (p) {
2151974Sbrutus 		if (p->listener == so) {
2160Sstevel@tonic-gate 			if (p->temp)
2170Sstevel@tonic-gate 				p->port = (uint16_t)-1;
2181974Sbrutus 			p->listener = NULL;
2190Sstevel@tonic-gate 			return (B_TRUE);
2200Sstevel@tonic-gate 		}
2210Sstevel@tonic-gate 		p = p->next;
2220Sstevel@tonic-gate 	}
2230Sstevel@tonic-gate 	return (B_FALSE);
2240Sstevel@tonic-gate }
2250Sstevel@tonic-gate 
2260Sstevel@tonic-gate static void
nl7c_addr_add(nl7c_addr_t * p)2270Sstevel@tonic-gate nl7c_addr_add(nl7c_addr_t *p)
2280Sstevel@tonic-gate {
2290Sstevel@tonic-gate 	p->next = nl7caddrs;
2300Sstevel@tonic-gate 	nl7caddrs = p;
2310Sstevel@tonic-gate }
2320Sstevel@tonic-gate 
2330Sstevel@tonic-gate void
nl7c_mi_report_addr(mblk_t * mp)2340Sstevel@tonic-gate nl7c_mi_report_addr(mblk_t *mp)
2350Sstevel@tonic-gate {
2360Sstevel@tonic-gate 	ipaddr_t	ip;
2370Sstevel@tonic-gate 	uint16_t	port;
2380Sstevel@tonic-gate 	nl7c_addr_t	*p = nl7caddrs;
2391974Sbrutus 	struct sonode	*so;
2400Sstevel@tonic-gate 	char		addr[32];
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	(void) mi_mpprintf(mp, "Door  Up-Call-Queue IPaddr:TCPport Listenning");
2430Sstevel@tonic-gate 	while (p) {
2441974Sbrutus 		if (p->port != (uint16_t)-1) {
2451974Sbrutus 			/* Don't report freed slots */
2460Sstevel@tonic-gate 			ip = ntohl(p->addr.v4);
2470Sstevel@tonic-gate 			port = ntohs(p->port);
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 			if (ip == INADDR_ANY) {
2500Sstevel@tonic-gate 				(void) strcpy(addr, "*");
2510Sstevel@tonic-gate 			} else {
2520Sstevel@tonic-gate 				int a1 = (ip >> 24) & 0xFF;
2530Sstevel@tonic-gate 				int a2 = (ip >> 16) & 0xFF;
2540Sstevel@tonic-gate 				int a3 = (ip >> 8) & 0xFF;
2550Sstevel@tonic-gate 				int a4 = ip & 0xFF;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 				(void) mi_sprintf(addr, "%d.%d.%d.%d",
258*8348SEric.Yu@Sun.COM 				    a1, a2, a3, a4);
2590Sstevel@tonic-gate 			}
2601974Sbrutus 			so = p->listener;
2611974Sbrutus 			(void) mi_mpprintf(mp, "%p  %s:%d  %d",
2621974Sbrutus 			    so ? (void *)strvp2wq(SOTOV(so)) : NULL,
2631974Sbrutus 			    addr, port, p->listener ? 1 : 0);
2640Sstevel@tonic-gate 		}
2650Sstevel@tonic-gate 		p = p->next;
2660Sstevel@tonic-gate 	}
2670Sstevel@tonic-gate }
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate /*
2700Sstevel@tonic-gate  * ASCII to unsigned.
2710Sstevel@tonic-gate  *
2720Sstevel@tonic-gate  * Note, it's assumed that *p is a valid zero byte terminated string.
2730Sstevel@tonic-gate  */
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate static unsigned
atou(const char * p)2760Sstevel@tonic-gate atou(const char *p)
2770Sstevel@tonic-gate {
2780Sstevel@tonic-gate 	int c;
2790Sstevel@tonic-gate 	int v = 0;
2800Sstevel@tonic-gate 
2810Sstevel@tonic-gate 	/* Shift and add digit by digit */
2820Sstevel@tonic-gate 	while ((c = *p++) != NULL && isdigit(c)) {
2830Sstevel@tonic-gate 		v *= 10;
2840Sstevel@tonic-gate 		v += c - '0';
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 	return (v);
2870Sstevel@tonic-gate }
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate /*
2900Sstevel@tonic-gate  * strdup(), yet another strdup() in the kernel.
2910Sstevel@tonic-gate  */
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate static char *
strdup(char * s)2940Sstevel@tonic-gate strdup(char *s)
2950Sstevel@tonic-gate {
2960Sstevel@tonic-gate 	int	len = strlen(s) + 1;
2970Sstevel@tonic-gate 	char	*ret = kmem_alloc(len, KM_SLEEP);
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 	bcopy(s, ret, len);
3000Sstevel@tonic-gate 
3010Sstevel@tonic-gate 	return (ret);
3020Sstevel@tonic-gate }
3030Sstevel@tonic-gate 
3040Sstevel@tonic-gate /*
3050Sstevel@tonic-gate  * Inet ASCII to binary.
3060Sstevel@tonic-gate  *
3070Sstevel@tonic-gate  * Note, it's assumed that *s is a valid zero byte terminated string, and
3080Sstevel@tonic-gate  * that *p is a zero initialized struct (this is important as the value of
3090Sstevel@tonic-gate  * INADDR_ANY and IN6ADDR_ANY is zero).
3100Sstevel@tonic-gate  */
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate static int
inet_atob(char * s,nl7c_addr_t * p)3130Sstevel@tonic-gate inet_atob(char *s, nl7c_addr_t *p)
3140Sstevel@tonic-gate {
3150Sstevel@tonic-gate 	if (strcmp(s, "*") == 0) {
3160Sstevel@tonic-gate 		/* INADDR_ANY */
3170Sstevel@tonic-gate 		p->family = AF_INET;
3180Sstevel@tonic-gate 		return (0);
3190Sstevel@tonic-gate 	}
3200Sstevel@tonic-gate 	if (strcmp(s, "::") == 0) {
3210Sstevel@tonic-gate 		/* IN6ADDR_ANY */
3220Sstevel@tonic-gate 		p->family = AF_INET6;
3230Sstevel@tonic-gate 		return (0);
3240Sstevel@tonic-gate 	}
3250Sstevel@tonic-gate 	/* IPv4 address ? */
3260Sstevel@tonic-gate 	if (inet_pton(AF_INET, s, &p->addr.v4) != 1) {
3270Sstevel@tonic-gate 		/* Nop, IPv6 address ? */
3280Sstevel@tonic-gate 		if (inet_pton(AF_INET6, s, &p->addr.v6) != 1) {
3290Sstevel@tonic-gate 			/* Nop, return error */
3300Sstevel@tonic-gate 			return (1);
3310Sstevel@tonic-gate 		}
3320Sstevel@tonic-gate 		p->family = AF_INET6;
3330Sstevel@tonic-gate 	} else {
3340Sstevel@tonic-gate 		p->family = AF_INET;
3351974Sbrutus 		p->addr.v4 = ntohl(p->addr.v4);
3360Sstevel@tonic-gate 	}
3370Sstevel@tonic-gate 	return (0);
3380Sstevel@tonic-gate }
3390Sstevel@tonic-gate 
3400Sstevel@tonic-gate /*
3410Sstevel@tonic-gate  * Open and read each line from "/etc/nca/ncaport.conf", the syntax of a
3421974Sbrutus  * ncaport.conf file line is:
3431974Sbrutus  *
3441974Sbrutus  *	ncaport=IPaddr/Port[/Proxy]
3451974Sbrutus  *
3461974Sbrutus  * Where:
3470Sstevel@tonic-gate  *
3480Sstevel@tonic-gate  * ncaport - the only token recognized.
3490Sstevel@tonic-gate  *
3500Sstevel@tonic-gate  *  IPaddr - an IPv4 numeric dot address (e.g. 192.168.84.71) or '*' for
3510Sstevel@tonic-gate  *           INADDR_ANY, or an IPv6 numeric address or "::" for IN6ADDR_ANY.
3520Sstevel@tonic-gate  *
3535331Samw  *       / - IPaddr/Port separator.
3540Sstevel@tonic-gate  *
3550Sstevel@tonic-gate  *    Port - a TCP decimal port number.
3561974Sbrutus  *
3571974Sbrutus  * Note, all other lines will be ignored.
3580Sstevel@tonic-gate  */
3590Sstevel@tonic-gate 
3600Sstevel@tonic-gate static void
ncaportconf_read(void)3610Sstevel@tonic-gate ncaportconf_read(void)
3620Sstevel@tonic-gate {
3630Sstevel@tonic-gate 	int	ret;
3640Sstevel@tonic-gate 	struct vnode *vp;
3650Sstevel@tonic-gate 	char	c;
3660Sstevel@tonic-gate 	ssize_t resid;
3670Sstevel@tonic-gate 	char	buf[1024];
3680Sstevel@tonic-gate 	char	*ebp = &buf[sizeof (buf)];
3690Sstevel@tonic-gate 	char	*bp = ebp;
3700Sstevel@tonic-gate 	offset_t off = 0;
3710Sstevel@tonic-gate 	enum parse_e {START, TOK, ADDR, PORT, EOL} parse = START;
3720Sstevel@tonic-gate 	nl7c_addr_t *addrp = NULL;
3730Sstevel@tonic-gate 	char	*ncaport = "ncaport";
3740Sstevel@tonic-gate 	char	string[] = "XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX:XXXX";
3750Sstevel@tonic-gate 	char	*stringp;
3760Sstevel@tonic-gate 	char	*tok;
3770Sstevel@tonic-gate 	char	*portconf = "/etc/nca/ncaport.conf";
3780Sstevel@tonic-gate 
3790Sstevel@tonic-gate 	ret = vn_open(portconf, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0);
3800Sstevel@tonic-gate 	if (ret == ENOENT) {
3810Sstevel@tonic-gate 		/* No portconf file, nothing to do */
3820Sstevel@tonic-gate 		return;
3830Sstevel@tonic-gate 	}
3840Sstevel@tonic-gate 	if (ret != 0) {
3850Sstevel@tonic-gate 		/* Error of some sort, tell'm about it */
3860Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s: open error %d", portconf, ret);
3870Sstevel@tonic-gate 		return;
3880Sstevel@tonic-gate 	}
3890Sstevel@tonic-gate 	/*
3900Sstevel@tonic-gate 	 * Read portconf one buf[] at a time, parse one char at a time.
3910Sstevel@tonic-gate 	 */
3920Sstevel@tonic-gate 	for (;;) {
3930Sstevel@tonic-gate 		if (bp == ebp) {
3940Sstevel@tonic-gate 			/* Nothing left in buf[], read another */
3950Sstevel@tonic-gate 			ret = vn_rdwr(UIO_READ, vp, buf, sizeof (buf), off,
3960Sstevel@tonic-gate 			    UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid);
3970Sstevel@tonic-gate 			if (ret != 0) {
3980Sstevel@tonic-gate 				/* Error of some sort, tell'm about it */
3990Sstevel@tonic-gate 				cmn_err(CE_WARN, "%s: read error %d",
400*8348SEric.Yu@Sun.COM 				    portconf, ret);
4010Sstevel@tonic-gate 				break;
4020Sstevel@tonic-gate 			}
4030Sstevel@tonic-gate 			if (resid == sizeof (buf)) {
4040Sstevel@tonic-gate 				/* EOF, done */
4050Sstevel@tonic-gate 				break;
4060Sstevel@tonic-gate 			}
4070Sstevel@tonic-gate 			/* Initilize per buf[] state */
4080Sstevel@tonic-gate 			bp = buf;
4090Sstevel@tonic-gate 			ebp = &buf[sizeof (buf) - resid];
4100Sstevel@tonic-gate 			off += sizeof (buf) - resid;
4110Sstevel@tonic-gate 		}
4120Sstevel@tonic-gate 		c = *bp++;
4130Sstevel@tonic-gate 		switch (parse) {
4140Sstevel@tonic-gate 		case START:
4150Sstevel@tonic-gate 			/* Initilize all per file line state */
4160Sstevel@tonic-gate 			if (addrp == NULL) {
4170Sstevel@tonic-gate 				addrp = kmem_zalloc(sizeof (*addrp),
4180Sstevel@tonic-gate 				    KM_NOSLEEP);
4190Sstevel@tonic-gate 			}
4200Sstevel@tonic-gate 			tok = ncaport;
4210Sstevel@tonic-gate 			stringp = string;
4220Sstevel@tonic-gate 			parse = TOK;
4230Sstevel@tonic-gate 			/*FALLTHROUGH*/
4240Sstevel@tonic-gate 		case TOK:
4250Sstevel@tonic-gate 			if (c == '#') {
4260Sstevel@tonic-gate 				/* Comment through end of line */
4270Sstevel@tonic-gate 				parse = EOL;
4280Sstevel@tonic-gate 				break;
4290Sstevel@tonic-gate 			}
4300Sstevel@tonic-gate 			if (isalpha(c)) {
4310Sstevel@tonic-gate 				if (c != *tok++) {
4320Sstevel@tonic-gate 					/* Only know one token, skip */
4330Sstevel@tonic-gate 					parse = EOL;
4340Sstevel@tonic-gate 				}
4350Sstevel@tonic-gate 			} else if (c == '=') {
4360Sstevel@tonic-gate 				if (*tok != NULL) {
4370Sstevel@tonic-gate 					/* Only know one token, skip */
4380Sstevel@tonic-gate 					parse = EOL;
4390Sstevel@tonic-gate 					break;
4400Sstevel@tonic-gate 				}
4410Sstevel@tonic-gate 				parse = ADDR;
4420Sstevel@tonic-gate 			} else if (c == '\n') {
4430Sstevel@tonic-gate 				/* Found EOL, empty line, next line */
4440Sstevel@tonic-gate 				parse = START;
4450Sstevel@tonic-gate 			} else {
4460Sstevel@tonic-gate 				/* Unexpected char, skip */
4470Sstevel@tonic-gate 				parse = EOL;
4480Sstevel@tonic-gate 			}
4490Sstevel@tonic-gate 			break;
4500Sstevel@tonic-gate 
4510Sstevel@tonic-gate 		case ADDR:
4520Sstevel@tonic-gate 			if (c == '/') {
4530Sstevel@tonic-gate 				/* addr/port separator, end of addr */
4540Sstevel@tonic-gate 				*stringp = NULL;
4550Sstevel@tonic-gate 				if (inet_atob(string, addrp)) {
4560Sstevel@tonic-gate 					/* Bad addr, skip */
4570Sstevel@tonic-gate 					parse = EOL;
4580Sstevel@tonic-gate 				} else {
4590Sstevel@tonic-gate 					stringp = string;
4600Sstevel@tonic-gate 					parse = PORT;
4610Sstevel@tonic-gate 				}
4620Sstevel@tonic-gate 			} else {
4630Sstevel@tonic-gate 				/* Save char to string */
4640Sstevel@tonic-gate 				if (stringp ==
4650Sstevel@tonic-gate 				    &string[sizeof (string) - 1]) {
4660Sstevel@tonic-gate 					/* Would overflow, skip */
4670Sstevel@tonic-gate 					parse = EOL;
4680Sstevel@tonic-gate 				} else {
4690Sstevel@tonic-gate 					/* Copy IP addr char */
4700Sstevel@tonic-gate 					*stringp++ = c;
4710Sstevel@tonic-gate 				}
4720Sstevel@tonic-gate 			}
4730Sstevel@tonic-gate 			break;
4740Sstevel@tonic-gate 
4750Sstevel@tonic-gate 		case PORT:
4760Sstevel@tonic-gate 			if (isdigit(c)) {
4770Sstevel@tonic-gate 				/* Save char to string */
4780Sstevel@tonic-gate 				if (stringp ==
4790Sstevel@tonic-gate 				    &string[sizeof (string) - 1]) {
4800Sstevel@tonic-gate 					/* Would overflow, skip */
4810Sstevel@tonic-gate 					parse = EOL;
4820Sstevel@tonic-gate 				} else {
4830Sstevel@tonic-gate 					/* Copy port digit char */
4840Sstevel@tonic-gate 					*stringp++ = c;
4850Sstevel@tonic-gate 				}
4860Sstevel@tonic-gate 				break;
4870Sstevel@tonic-gate 			} else if (c == '#' || isspace(c)) {
4880Sstevel@tonic-gate 				/* End of port number, convert */
4890Sstevel@tonic-gate 				*stringp = NULL;
4901974Sbrutus 				addrp->port = ntohs(atou(string));
4910Sstevel@tonic-gate 
4920Sstevel@tonic-gate 				/* End of parse, add entry */
4930Sstevel@tonic-gate 				nl7c_addr_add(addrp);
4940Sstevel@tonic-gate 				addrp = NULL;
4950Sstevel@tonic-gate 				parse = EOL;
4960Sstevel@tonic-gate 			} else {
4970Sstevel@tonic-gate 				/* Unrecognized char, skip */
4980Sstevel@tonic-gate 				parse = EOL;
4990Sstevel@tonic-gate 				break;
5000Sstevel@tonic-gate 			}
5011974Sbrutus 			if (c == '\n') {
5021974Sbrutus 				/* Found EOL, start on next line */
5031974Sbrutus 				parse = START;
5041974Sbrutus 			}
5051974Sbrutus 			break;
5061974Sbrutus 
5070Sstevel@tonic-gate 		case EOL:
5080Sstevel@tonic-gate 			if (c == '\n') {
5090Sstevel@tonic-gate 				/* Found EOL, start on next line */
5100Sstevel@tonic-gate 				parse = START;
5110Sstevel@tonic-gate 			}
5120Sstevel@tonic-gate 			break;
5130Sstevel@tonic-gate 		}
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 	if (addrp != NULL) {
5170Sstevel@tonic-gate 		kmem_free(addrp, sizeof (*addrp));
5180Sstevel@tonic-gate 	}
5195331Samw 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
5200Sstevel@tonic-gate 	VN_RELE(vp);
5210Sstevel@tonic-gate }
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate /*
5240Sstevel@tonic-gate  * Open and read each line from "/etc/nca/ncakmod.conf" and parse looking
5250Sstevel@tonic-gate  * for the NCA enabled, the syntax is: status=enabled, all other lines will
5260Sstevel@tonic-gate  * be ignored.
5270Sstevel@tonic-gate  */
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate static void
ncakmodconf_read(void)5300Sstevel@tonic-gate ncakmodconf_read(void)
5310Sstevel@tonic-gate {
5320Sstevel@tonic-gate 	int	ret;
5330Sstevel@tonic-gate 	struct vnode *vp;
5340Sstevel@tonic-gate 	char	c;
5350Sstevel@tonic-gate 	ssize_t resid;
5360Sstevel@tonic-gate 	char	buf[1024];
5370Sstevel@tonic-gate 	char	*ebp = &buf[sizeof (buf)];
5380Sstevel@tonic-gate 	char	*bp = ebp;
5390Sstevel@tonic-gate 	offset_t off = 0;
5400Sstevel@tonic-gate 	enum parse_e {START, TOK, EOL} parse = START;
5410Sstevel@tonic-gate 	char	*status = "status=enabled";
5420Sstevel@tonic-gate 	char	*tok;
5430Sstevel@tonic-gate 	char	*ncakmod = "/etc/nca/ncakmod.conf";
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate 	ret = vn_open(ncakmod, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0);
5460Sstevel@tonic-gate 	if (ret == ENOENT) {
5470Sstevel@tonic-gate 		/* No ncakmod file, nothing to do */
5480Sstevel@tonic-gate 		return;
5490Sstevel@tonic-gate 	}
5500Sstevel@tonic-gate 	if (ret != 0) {
5510Sstevel@tonic-gate 		/* Error of some sort, tell'm about it */
5520Sstevel@tonic-gate 		cmn_err(CE_WARN, "%s: open error %d", status, ret);
5530Sstevel@tonic-gate 		return;
5540Sstevel@tonic-gate 	}
5550Sstevel@tonic-gate 	/*
5560Sstevel@tonic-gate 	 * Read ncakmod one buf[] at a time, parse one char at a time.
5570Sstevel@tonic-gate 	 */
5580Sstevel@tonic-gate 	for (;;) {
5590Sstevel@tonic-gate 		if (bp == ebp) {
5600Sstevel@tonic-gate 			/* Nothing left in buf[], read another */
5610Sstevel@tonic-gate 			ret = vn_rdwr(UIO_READ, vp, buf, sizeof (buf), off,
5620Sstevel@tonic-gate 			    UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid);
5630Sstevel@tonic-gate 			if (ret != 0) {
5640Sstevel@tonic-gate 				/* Error of some sort, tell'm about it */
5650Sstevel@tonic-gate 				cmn_err(CE_WARN, "%s: read error %d",
566*8348SEric.Yu@Sun.COM 				    status, ret);
5670Sstevel@tonic-gate 				break;
5680Sstevel@tonic-gate 			}
5690Sstevel@tonic-gate 			if (resid == sizeof (buf)) {
5700Sstevel@tonic-gate 				/* EOF, done */
5710Sstevel@tonic-gate 				break;
5720Sstevel@tonic-gate 			}
5730Sstevel@tonic-gate 			/* Initilize per buf[] state */
5740Sstevel@tonic-gate 			bp = buf;
5750Sstevel@tonic-gate 			ebp = &buf[sizeof (buf) - resid];
5760Sstevel@tonic-gate 			off += sizeof (buf) - resid;
5770Sstevel@tonic-gate 		}
5780Sstevel@tonic-gate 		c = *bp++;
5790Sstevel@tonic-gate 		switch (parse) {
5800Sstevel@tonic-gate 		case START:
5810Sstevel@tonic-gate 			/* Initilize all per file line state */
5820Sstevel@tonic-gate 			tok = status;
5830Sstevel@tonic-gate 			parse = TOK;
5840Sstevel@tonic-gate 			/*FALLTHROUGH*/
5850Sstevel@tonic-gate 		case TOK:
5860Sstevel@tonic-gate 			if (c == '#') {
5870Sstevel@tonic-gate 				/* Comment through end of line */
5880Sstevel@tonic-gate 				parse = EOL;
5890Sstevel@tonic-gate 				break;
5900Sstevel@tonic-gate 			}
5910Sstevel@tonic-gate 			if (isalpha(c) || c == '=') {
5920Sstevel@tonic-gate 				if (c != *tok++) {
5930Sstevel@tonic-gate 					/* Only know one token, skip */
5940Sstevel@tonic-gate 					parse = EOL;
5950Sstevel@tonic-gate 				}
5960Sstevel@tonic-gate 			} else if (c == '\n') {
5970Sstevel@tonic-gate 				/*
5980Sstevel@tonic-gate 				 * Found EOL, if tok found done,
5990Sstevel@tonic-gate 				 * else start on next-line.
6000Sstevel@tonic-gate 				 */
6010Sstevel@tonic-gate 				if (*tok == NULL) {
6020Sstevel@tonic-gate 					nl7c_enabled = B_TRUE;
6030Sstevel@tonic-gate 					goto done;
6040Sstevel@tonic-gate 				}
6050Sstevel@tonic-gate 				parse = START;
6060Sstevel@tonic-gate 			} else {
6070Sstevel@tonic-gate 				/* Unexpected char, skip */
6080Sstevel@tonic-gate 				parse = EOL;
6090Sstevel@tonic-gate 			}
6100Sstevel@tonic-gate 			break;
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 		case EOL:
6130Sstevel@tonic-gate 			if (c == '\n') {
6140Sstevel@tonic-gate 				/* Found EOL, start on next line */
6150Sstevel@tonic-gate 				parse = START;
6160Sstevel@tonic-gate 			}
6170Sstevel@tonic-gate 			break;
6180Sstevel@tonic-gate 		}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	}
6210Sstevel@tonic-gate done:
6225331Samw 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
6230Sstevel@tonic-gate 	VN_RELE(vp);
6240Sstevel@tonic-gate }
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate /*
6270Sstevel@tonic-gate  * Open and read each line from "/etc/nca/ncalogd.conf" and parse for
6280Sstevel@tonic-gate  * the tokens and token text (i.e. key and value ncalogd.conf(4)):
6290Sstevel@tonic-gate  *
6300Sstevel@tonic-gate  *	status=enabled
6310Sstevel@tonic-gate  *
6320Sstevel@tonic-gate  *	logd_file_size=[0-9]+
6330Sstevel@tonic-gate  *
6340Sstevel@tonic-gate  *	logd_file_name=["]filename( filename)*["]
6350Sstevel@tonic-gate  */
6360Sstevel@tonic-gate 
6370Sstevel@tonic-gate static int	file_size = 1000000;
6380Sstevel@tonic-gate static caddr_t	fnv[NCA_FIOV_SZ];
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate static void
ncalogdconf_read(void)6410Sstevel@tonic-gate ncalogdconf_read(void)
6420Sstevel@tonic-gate {
6430Sstevel@tonic-gate 	int	ret;
6440Sstevel@tonic-gate 	struct vnode *vp;
6450Sstevel@tonic-gate 	char	c;
6460Sstevel@tonic-gate 	int	sz;
6470Sstevel@tonic-gate 	ssize_t resid;
6480Sstevel@tonic-gate 	char	buf[1024];
6490Sstevel@tonic-gate 	char	*ebp = &buf[sizeof (buf)];
6500Sstevel@tonic-gate 	char	*bp = ebp;
6510Sstevel@tonic-gate 	offset_t off = 0;
6520Sstevel@tonic-gate 	enum parse_e {START, TOK, TEXT, EOL} parse = START;
6530Sstevel@tonic-gate 	char	*tokstatus = "status\0enabled";
6540Sstevel@tonic-gate 	char	*toksize = "logd_file_size";
6550Sstevel@tonic-gate 	char	*tokfile = "logd_path_name";
6560Sstevel@tonic-gate 	char	*tokstatusp;
6570Sstevel@tonic-gate 	char	*toksizep;
6580Sstevel@tonic-gate 	char	*tokfilep;
6590Sstevel@tonic-gate 	char	*tok;
6600Sstevel@tonic-gate 	int	tokdelim = 0;
6610Sstevel@tonic-gate 	char	*ncalogd = "/etc/nca/ncalogd.conf";
6620Sstevel@tonic-gate 	char	*ncadeflog = "/var/nca/log";
6630Sstevel@tonic-gate 	char	file[TYPICALMAXPATHLEN] = {0};
6640Sstevel@tonic-gate 	char	*fp = file;
6650Sstevel@tonic-gate 	caddr_t	*fnvp = fnv;
6660Sstevel@tonic-gate 
6670Sstevel@tonic-gate 	ret = vn_open(ncalogd, UIO_SYSSPACE, FREAD, 0, &vp, 0, 0);
6680Sstevel@tonic-gate 	if (ret == ENOENT) {
6690Sstevel@tonic-gate 		/* No ncalogd file, nothing to do */
6700Sstevel@tonic-gate 		return;
6710Sstevel@tonic-gate 	}
6720Sstevel@tonic-gate 	if (ret != 0) {
6730Sstevel@tonic-gate 		/* Error of some sort, tell'm about it */
6740Sstevel@tonic-gate 		cmn_err(CE_WARN, "ncalogdconf_read: %s: open error(%d).",
6750Sstevel@tonic-gate 		    ncalogd, ret);
6760Sstevel@tonic-gate 		return;
6770Sstevel@tonic-gate 	}
6780Sstevel@tonic-gate 	/*
6790Sstevel@tonic-gate 	 * Read ncalogd.conf one buf[] at a time, parse one char at a time.
6800Sstevel@tonic-gate 	 */
6810Sstevel@tonic-gate 	for (;;) {
6820Sstevel@tonic-gate 		if (bp == ebp) {
6830Sstevel@tonic-gate 			/* Nothing left in buf[], read another */
6840Sstevel@tonic-gate 			ret = vn_rdwr(UIO_READ, vp, buf, sizeof (buf), off,
6850Sstevel@tonic-gate 			    UIO_SYSSPACE, 0, (rlim64_t)0, CRED(), &resid);
6860Sstevel@tonic-gate 			if (ret != 0) {
6870Sstevel@tonic-gate 				/* Error of some sort, tell'm about it */
6880Sstevel@tonic-gate 				cmn_err(CE_WARN, "%s: read error %d",
689*8348SEric.Yu@Sun.COM 				    ncalogd, ret);
6900Sstevel@tonic-gate 				break;
6910Sstevel@tonic-gate 			}
6920Sstevel@tonic-gate 			if (resid == sizeof (buf)) {
6930Sstevel@tonic-gate 				/* EOF, done */
6940Sstevel@tonic-gate 				break;
6950Sstevel@tonic-gate 			}
6960Sstevel@tonic-gate 			/* Initilize per buf[] state */
6970Sstevel@tonic-gate 			bp = buf;
6980Sstevel@tonic-gate 			ebp = &buf[sizeof (buf) - resid];
6990Sstevel@tonic-gate 			off += sizeof (buf) - resid;
7000Sstevel@tonic-gate 		}
7010Sstevel@tonic-gate 		c = *bp++;
7020Sstevel@tonic-gate 		switch (parse) {
7030Sstevel@tonic-gate 		case START:
7040Sstevel@tonic-gate 			/* Initilize all per file line state */
7050Sstevel@tonic-gate 			tokstatusp = tokstatus;
7060Sstevel@tonic-gate 			toksizep = toksize;
7070Sstevel@tonic-gate 			tokfilep = tokfile;
7080Sstevel@tonic-gate 			tok = NULL;
7090Sstevel@tonic-gate 			parse = TOK;
7100Sstevel@tonic-gate 			sz = 0;
7110Sstevel@tonic-gate 			/*FALLTHROUGH*/
7120Sstevel@tonic-gate 		case TOK:
7130Sstevel@tonic-gate 			if (isalpha(c) || c == '_') {
7140Sstevel@tonic-gate 				/*
7150Sstevel@tonic-gate 				 * Found a valid tok char, if matches
7160Sstevel@tonic-gate 				 * any of the tokens continue else NULL
7170Sstevel@tonic-gate 				 * then string pointer.
7180Sstevel@tonic-gate 				 */
7190Sstevel@tonic-gate 				if (tokstatusp != NULL && c != *tokstatusp++)
7200Sstevel@tonic-gate 					tokstatusp = NULL;
7210Sstevel@tonic-gate 				if (toksizep != NULL && c != *toksizep++)
7220Sstevel@tonic-gate 					toksizep = NULL;
7230Sstevel@tonic-gate 				if (tokfilep != NULL && c != *tokfilep++)
7240Sstevel@tonic-gate 					tokfilep = NULL;
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 				if (tokstatusp == NULL &&
7270Sstevel@tonic-gate 				    toksizep == NULL &&
7280Sstevel@tonic-gate 				    tokfilep == NULL) {
7290Sstevel@tonic-gate 					/*
7300Sstevel@tonic-gate 					 * All tok string pointers are NULL
7310Sstevel@tonic-gate 					 * so skip rest of line.
7320Sstevel@tonic-gate 					 */
7330Sstevel@tonic-gate 					parse = EOL;
7340Sstevel@tonic-gate 				}
7350Sstevel@tonic-gate 			} else if (c == '=') {
7360Sstevel@tonic-gate 				/*
7370Sstevel@tonic-gate 				 * Found tok separator, if tok found get
7380Sstevel@tonic-gate 				 * tok text, else skip rest of line.
7390Sstevel@tonic-gate 				 */
7400Sstevel@tonic-gate 				if (tokstatusp != NULL && *tokstatusp == NULL)
7410Sstevel@tonic-gate 					tok = tokstatus;
7420Sstevel@tonic-gate 				else if (toksizep != NULL && *toksizep == NULL)
7430Sstevel@tonic-gate 					tok = toksize;
7440Sstevel@tonic-gate 				else if (tokfilep != NULL && *tokfilep == NULL)
7450Sstevel@tonic-gate 					tok = tokfile;
7460Sstevel@tonic-gate 				if (tok != NULL)
7470Sstevel@tonic-gate 					parse = TEXT;
7480Sstevel@tonic-gate 				else
7490Sstevel@tonic-gate 					parse = EOL;
7500Sstevel@tonic-gate 			} else if (c == '\n') {
7510Sstevel@tonic-gate 				/* Found EOL, start on next line */
7520Sstevel@tonic-gate 				parse = START;
7530Sstevel@tonic-gate 			} else {
7540Sstevel@tonic-gate 				/* Comment or unknown char, skip rest of line */
7550Sstevel@tonic-gate 				parse = EOL;
7560Sstevel@tonic-gate 			}
7570Sstevel@tonic-gate 			break;
7580Sstevel@tonic-gate 		case TEXT:
7590Sstevel@tonic-gate 			if (c == '\n') {
7600Sstevel@tonic-gate 				/*
7610Sstevel@tonic-gate 				 * Found EOL, finish up tok text processing
7620Sstevel@tonic-gate 				 * (if any) and start on next line.
7630Sstevel@tonic-gate 				 */
7640Sstevel@tonic-gate 				if (tok == tokstatus) {
7650Sstevel@tonic-gate 					if (*++tokstatusp == NULL)
7660Sstevel@tonic-gate 						nl7c_logd_enabled = B_TRUE;
7670Sstevel@tonic-gate 				} else if (tok == toksize) {
7680Sstevel@tonic-gate 					file_size = sz;
7690Sstevel@tonic-gate 				} else if (tok == tokfile) {
7700Sstevel@tonic-gate 					if (tokdelim == 0) {
7710Sstevel@tonic-gate 						/* Non delimited path name */
7720Sstevel@tonic-gate 						*fnvp++ = strdup(file);
7730Sstevel@tonic-gate 					} else if (fp != file) {
7740Sstevel@tonic-gate 						/* No closing delimiter */
7750Sstevel@tonic-gate 						/*EMPTY*/;
7760Sstevel@tonic-gate 					}
7770Sstevel@tonic-gate 				}
7780Sstevel@tonic-gate 				parse = START;
7790Sstevel@tonic-gate 			} else if (tok == tokstatus) {
7800Sstevel@tonic-gate 				if (! isalpha(c) || *++tokstatusp == NULL ||
7810Sstevel@tonic-gate 				    c != *tokstatusp) {
7820Sstevel@tonic-gate 					/* Not enabled, skip line */
7830Sstevel@tonic-gate 					parse = EOL;
7840Sstevel@tonic-gate 				}
7850Sstevel@tonic-gate 			} else if (tok == toksize) {
7860Sstevel@tonic-gate 				if (isdigit(c)) {
7870Sstevel@tonic-gate 					sz *= 10;
7880Sstevel@tonic-gate 					sz += c - '0';
7890Sstevel@tonic-gate 				} else {
7900Sstevel@tonic-gate 					/* Not a decimal digit, skip line */
7910Sstevel@tonic-gate 					parse = EOL;
7920Sstevel@tonic-gate 				}
7930Sstevel@tonic-gate 			} else {
7940Sstevel@tonic-gate 				/* File name */
7950Sstevel@tonic-gate 				if (c == '"' && tokdelim++ == 0) {
7960Sstevel@tonic-gate 					/* Opening delimiter, skip */
7970Sstevel@tonic-gate 					/*EMPTY*/;
7980Sstevel@tonic-gate 				} else if (c == '"' || c == ' ') {
7995331Samw 					/* List delim or filename separator */
8000Sstevel@tonic-gate 					*fnvp++ = strdup(file);
8010Sstevel@tonic-gate 					fp = file;
8020Sstevel@tonic-gate 				} else if (fp < &file[sizeof (file) - 1]) {
8030Sstevel@tonic-gate 					/* Filename char */
8040Sstevel@tonic-gate 					*fp++ = c;
8050Sstevel@tonic-gate 				} else {
8060Sstevel@tonic-gate 					/* Filename to long, skip line */
8070Sstevel@tonic-gate 					parse = EOL;
8080Sstevel@tonic-gate 				}
8090Sstevel@tonic-gate 			}
8100Sstevel@tonic-gate 			break;
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 		case EOL:
8130Sstevel@tonic-gate 			if (c == '\n') {
8140Sstevel@tonic-gate 				/* Found EOL, start on next line */
8150Sstevel@tonic-gate 				parse = START;
8160Sstevel@tonic-gate 			}
8170Sstevel@tonic-gate 			break;
8180Sstevel@tonic-gate 		}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	}
8210Sstevel@tonic-gate done:
8225331Samw 	(void) VOP_CLOSE(vp, FREAD, 1, (offset_t)0, CRED(), NULL);
8230Sstevel@tonic-gate 	VN_RELE(vp);
8240Sstevel@tonic-gate 
8250Sstevel@tonic-gate 	if (nl7c_logd_enabled) {
8260Sstevel@tonic-gate 		if (fnvp == fnv) {
8270Sstevel@tonic-gate 			/*
8280Sstevel@tonic-gate 			 * No logfile was specified and found so
8290Sstevel@tonic-gate 			 * so use defualt NCA log file path.
8300Sstevel@tonic-gate 			 */
8310Sstevel@tonic-gate 			*fnvp++ = strdup(ncadeflog);
8320Sstevel@tonic-gate 		}
8330Sstevel@tonic-gate 		if (fnvp < &fnv[NCA_FIOV_SZ]) {
8340Sstevel@tonic-gate 			/* NULL terminate list */
8350Sstevel@tonic-gate 			*fnvp = NULL;
8360Sstevel@tonic-gate 		}
8370Sstevel@tonic-gate 	}
8380Sstevel@tonic-gate }
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate void
nl7clogd_startup(void)8410Sstevel@tonic-gate nl7clogd_startup(void)
8420Sstevel@tonic-gate {
8430Sstevel@tonic-gate 	static kmutex_t startup;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 	/*
8460Sstevel@tonic-gate 	 * Called on the first log() attempt, have to wait until then to
8470Sstevel@tonic-gate 	 * initialize logd as at logdconf_read() the root fs is read-only.
8480Sstevel@tonic-gate 	 */
8490Sstevel@tonic-gate 	mutex_enter(&startup);
8500Sstevel@tonic-gate 	if (nl7c_logd_started) {
8510Sstevel@tonic-gate 		/* Lost the race, nothing todo */
8520Sstevel@tonic-gate 		mutex_exit(&startup);
8530Sstevel@tonic-gate 		return;
8540Sstevel@tonic-gate 	}
8550Sstevel@tonic-gate 	nl7c_logd_started = B_TRUE;
8560Sstevel@tonic-gate 	if (! nl7c_logd_init(file_size, fnv)) {
8570Sstevel@tonic-gate 		/* Failure, disable logging */
8580Sstevel@tonic-gate 		nl7c_logd_enabled = B_FALSE;
8590Sstevel@tonic-gate 		cmn_err(CE_WARN, "nl7clogd_startup: failed, disabling loggin");
8600Sstevel@tonic-gate 		mutex_exit(&startup);
8610Sstevel@tonic-gate 		return;
8620Sstevel@tonic-gate 	}
8630Sstevel@tonic-gate 	mutex_exit(&startup);
8640Sstevel@tonic-gate }
8650Sstevel@tonic-gate 
8660Sstevel@tonic-gate 
8670Sstevel@tonic-gate void
nl7c_startup()8680Sstevel@tonic-gate nl7c_startup()
8690Sstevel@tonic-gate {
8701974Sbrutus 	/*
8711974Sbrutus 	 * Open, read, and parse the NCA logd configuration file,
8721974Sbrutus 	 * then initialize URI processing and NCA compat.
8731974Sbrutus 	 */
8740Sstevel@tonic-gate 	ncalogdconf_read();
8750Sstevel@tonic-gate 	nl7c_uri_init();
8760Sstevel@tonic-gate 	nl7c_nca_init();
8770Sstevel@tonic-gate }
8780Sstevel@tonic-gate 
8790Sstevel@tonic-gate void
nl7c_init()8800Sstevel@tonic-gate nl7c_init()
8810Sstevel@tonic-gate {
8820Sstevel@tonic-gate 	/* Open, read, and parse the NCA kmod configuration file */
8830Sstevel@tonic-gate 	ncakmodconf_read();
8840Sstevel@tonic-gate 
8850Sstevel@tonic-gate 	if (nl7c_enabled) {
8860Sstevel@tonic-gate 		/*
8870Sstevel@tonic-gate 		 * NL7C is enabled so open, read, and parse
8880Sstevel@tonic-gate 		 * the NCA address/port configuration file
8890Sstevel@tonic-gate 		 * and call startup() to finish config/init.
8900Sstevel@tonic-gate 		 */
8910Sstevel@tonic-gate 		ncaportconf_read();
8920Sstevel@tonic-gate 		nl7c_startup();
8930Sstevel@tonic-gate 	}
8940Sstevel@tonic-gate }
8950Sstevel@tonic-gate 
8960Sstevel@tonic-gate /*
8970Sstevel@tonic-gate  * The main processing function called by accept() on a newly created
8980Sstevel@tonic-gate  * socket prior to returning it to the caller of accept().
8990Sstevel@tonic-gate  *
9000Sstevel@tonic-gate  * Here data is read from the socket until a completed L7 request parse
9010Sstevel@tonic-gate  * is completed. Data will be read in the context of the user thread
9020Sstevel@tonic-gate  * which called accept(), when parse has been completed either B_TRUE
9030Sstevel@tonic-gate  * or B_FALSE will be returned.
9040Sstevel@tonic-gate  *
9050Sstevel@tonic-gate  * If NL7C successfully process the L7 protocol request, i.e. generates
9060Sstevel@tonic-gate  * a response, B_TRUE will be returned.
9070Sstevel@tonic-gate  *
9080Sstevel@tonic-gate  * Else, B_FALSE will be returned if NL7C can't process the request:
9090Sstevel@tonic-gate  *
9100Sstevel@tonic-gate  * 1) Couldn't locate a URI within the request.
9110Sstevel@tonic-gate  *
9120Sstevel@tonic-gate  * 2) URI scheme not reqcognized.
9130Sstevel@tonic-gate  *
9145331Samw  * 3) A request which can't be processed.
9150Sstevel@tonic-gate  *
9160Sstevel@tonic-gate  * 4) A request which could be processed but NL7C dosen't currently have
9170Sstevel@tonic-gate  *    the response data. In which case NL7C will parse the returned response
9180Sstevel@tonic-gate  *    from the application for possible caching for subsequent request(s).
9190Sstevel@tonic-gate  */
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate volatile uint64_t nl7c_proc_cnt = 0;
9220Sstevel@tonic-gate volatile uint64_t nl7c_proc_error = 0;
9230Sstevel@tonic-gate volatile uint64_t nl7c_proc_ETIME = 0;
9240Sstevel@tonic-gate volatile uint64_t nl7c_proc_again = 0;
9250Sstevel@tonic-gate volatile uint64_t nl7c_proc_next = 0;
9260Sstevel@tonic-gate volatile uint64_t nl7c_proc_rcv = 0;
9270Sstevel@tonic-gate volatile uint64_t nl7c_proc_noLRI = 0;
9281974Sbrutus volatile uint64_t nl7c_proc_nodata = 0;
9291974Sbrutus volatile uint64_t nl7c_proc_parse = 0;
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate boolean_t
nl7c_process(struct sonode * so,boolean_t nonblocking)9321974Sbrutus nl7c_process(struct sonode *so, boolean_t nonblocking)
9330Sstevel@tonic-gate {
9340Sstevel@tonic-gate 	vnode_t	*vp = SOTOV(so);
935*8348SEric.Yu@Sun.COM 	sotpi_info_t *sti = SOTOTPI(so);
936*8348SEric.Yu@Sun.COM 	mblk_t	*rmp = sti->sti_nl7c_rcv_mp;
9370Sstevel@tonic-gate 	clock_t	timout;
9381974Sbrutus 	rval_t	rval;
9390Sstevel@tonic-gate 	uchar_t pri;
9400Sstevel@tonic-gate 	int 	pflag;
9410Sstevel@tonic-gate 	int	error;
9420Sstevel@tonic-gate 	boolean_t more;
9431974Sbrutus 	boolean_t ret = B_FALSE;
9441974Sbrutus 	boolean_t first = B_TRUE;
945*8348SEric.Yu@Sun.COM 	boolean_t pollin = (sti->sti_nl7c_flags & NL7C_POLLIN);
9460Sstevel@tonic-gate 
9470Sstevel@tonic-gate 	nl7c_proc_cnt++;
9480Sstevel@tonic-gate 
9491974Sbrutus 	/* Caller has so_lock enter()ed */
9500Sstevel@tonic-gate 	error = so_lock_read_intr(so, nonblocking ? FNDELAY|FNONBLOCK : 0);
9510Sstevel@tonic-gate 	if (error) {
9520Sstevel@tonic-gate 		/* Couldn't read lock, pass on this socket */
953*8348SEric.Yu@Sun.COM 		sti->sti_nl7c_flags = 0;
9540Sstevel@tonic-gate 		nl7c_proc_noLRI++;
9551974Sbrutus 		return (B_FALSE);
9560Sstevel@tonic-gate 	}
9571974Sbrutus 	/* Exit so_lock for now, will be reenter()ed prior to return */
9580Sstevel@tonic-gate 	mutex_exit(&so->so_lock);
9590Sstevel@tonic-gate 
9601974Sbrutus 	if (pollin)
961*8348SEric.Yu@Sun.COM 		sti->sti_nl7c_flags &= ~NL7C_POLLIN;
9620Sstevel@tonic-gate 
9630Sstevel@tonic-gate 	/* Initialize some kstrgetmsg() constants */
9641974Sbrutus 	pflag = MSG_ANY | MSG_DELAYERROR;
9650Sstevel@tonic-gate 	pri = 0;
9661974Sbrutus 	if (nonblocking) {
9671974Sbrutus 		/* Non blocking so don't block */
9680Sstevel@tonic-gate 		timout = 0;
969*8348SEric.Yu@Sun.COM 	} else if (sti->sti_nl7c_flags & NL7C_SOPERSIST) {
9701974Sbrutus 		/* 2nd or more time(s) here so use keep-alive value */
9711974Sbrutus 		timout = nca_http_keep_alive_timeout;
9721974Sbrutus 	} else {
9731974Sbrutus 		/* 1st time here so use connection value */
9741974Sbrutus 		timout = nca_http_timeout;
9751974Sbrutus 	}
9760Sstevel@tonic-gate 
9771974Sbrutus 	rval.r_vals = 0;
9780Sstevel@tonic-gate 	do {
9791974Sbrutus 		/*
9801974Sbrutus 		 * First time through, if no data left over from a previous
9811974Sbrutus 		 * kstrgetmsg() then try to get some, else just process it.
9821974Sbrutus 		 *
9835331Samw 		 * Thereafter, rmp = NULL after the successful kstrgetmsg()
9841974Sbrutus 		 * so try to get some new data and append to list (i.e. until
9855331Samw 		 * enough fragments are collected for a successful parse).
9861974Sbrutus 		 */
9870Sstevel@tonic-gate 		if (rmp == NULL) {
9881974Sbrutus 
9890Sstevel@tonic-gate 			error = kstrgetmsg(vp, &rmp, NULL, &pri, &pflag,
9901974Sbrutus 			    timout, &rval);
9910Sstevel@tonic-gate 			if (error) {
9920Sstevel@tonic-gate 				if (error == ETIME) {
9930Sstevel@tonic-gate 					/* Timeout */
9940Sstevel@tonic-gate 					nl7c_proc_ETIME++;
9951974Sbrutus 				} else if (error != EWOULDBLOCK) {
9960Sstevel@tonic-gate 					/* Error of some sort */
9970Sstevel@tonic-gate 					nl7c_proc_error++;
9981974Sbrutus 					rval.r_v.r_v2 = error;
999*8348SEric.Yu@Sun.COM 					sti->sti_nl7c_flags = 0;
10001974Sbrutus 					break;
10010Sstevel@tonic-gate 				}
10021974Sbrutus 				error = 0;
10031974Sbrutus 			}
10041974Sbrutus 			if (rmp != NULL) {
1005*8348SEric.Yu@Sun.COM 				mblk_t	*mp = sti->sti_nl7c_rcv_mp;
10061974Sbrutus 
10071974Sbrutus 
10081974Sbrutus 				if (mp == NULL) {
10091974Sbrutus 					/* Just new data, common case */
1010*8348SEric.Yu@Sun.COM 					sti->sti_nl7c_rcv_mp = rmp;
10111974Sbrutus 				} else {
10121974Sbrutus 					/* Add new data to tail */
10131974Sbrutus 					while (mp->b_cont != NULL)
10141974Sbrutus 						mp = mp->b_cont;
10151974Sbrutus 					mp->b_cont = rmp;
10161974Sbrutus 				}
10171974Sbrutus 			}
1018*8348SEric.Yu@Sun.COM 			if (sti->sti_nl7c_rcv_mp == NULL) {
10191974Sbrutus 				/* No data */
10201974Sbrutus 				nl7c_proc_nodata++;
10211974Sbrutus 				if (timout > 0 || (first && pollin)) {
10221974Sbrutus 					/* Expected data so EOF */
10231974Sbrutus 					ret = B_TRUE;
1024*8348SEric.Yu@Sun.COM 				} else if (sti->sti_nl7c_flags &
1025*8348SEric.Yu@Sun.COM 				    NL7C_SOPERSIST) {
10261974Sbrutus 					/* Persistent so just checking */
10271974Sbrutus 					ret = B_FALSE;
10281974Sbrutus 				}
10290Sstevel@tonic-gate 				break;
10300Sstevel@tonic-gate 			}
10311974Sbrutus 			rmp = NULL;
10321974Sbrutus 		}
10331974Sbrutus 		first = B_FALSE;
10341974Sbrutus 	again:
10351974Sbrutus 		nl7c_proc_parse++;
10360Sstevel@tonic-gate 
10371974Sbrutus 		more = nl7c_parse(so, nonblocking, &ret);
10381974Sbrutus 
1039*8348SEric.Yu@Sun.COM 		if (ret == B_TRUE && (sti->sti_nl7c_flags & NL7C_SOPERSIST)) {
10401974Sbrutus 			/*
10411974Sbrutus 			 * Parse complete, cache hit, response on its way,
10421974Sbrutus 			 * socket is persistent so try to process the next
10431974Sbrutus 			 * request.
10441974Sbrutus 			 */
10451974Sbrutus 			if (nonblocking) {
10460Sstevel@tonic-gate 				ret = B_FALSE;
10470Sstevel@tonic-gate 				break;
10480Sstevel@tonic-gate 			}
1049*8348SEric.Yu@Sun.COM 			if (sti->sti_nl7c_rcv_mp) {
10501974Sbrutus 				/* More recv-side data, pipelined */
10510Sstevel@tonic-gate 				nl7c_proc_again++;
10520Sstevel@tonic-gate 				goto again;
10530Sstevel@tonic-gate 			}
10540Sstevel@tonic-gate 			nl7c_proc_next++;
10550Sstevel@tonic-gate 			if (nonblocking)
10560Sstevel@tonic-gate 				timout = 0;
10570Sstevel@tonic-gate 			else
10581974Sbrutus 				timout = nca_http_keep_alive_timeout;
10591974Sbrutus 
10600Sstevel@tonic-gate 			more = B_TRUE;
10610Sstevel@tonic-gate 		}
10620Sstevel@tonic-gate 
10630Sstevel@tonic-gate 	} while (more);
10640Sstevel@tonic-gate 
1065*8348SEric.Yu@Sun.COM 	if (sti->sti_nl7c_rcv_mp) {
10660Sstevel@tonic-gate 		nl7c_proc_rcv++;
10670Sstevel@tonic-gate 	}
1068*8348SEric.Yu@Sun.COM 	sti->sti_nl7c_rcv_rval = rval.r_vals;
10691974Sbrutus 	/* Renter so_lock, caller called with it enter()ed */
10700Sstevel@tonic-gate 	mutex_enter(&so->so_lock);
10710Sstevel@tonic-gate 	so_unlock_read(so);
10721974Sbrutus 
10730Sstevel@tonic-gate 	return (ret);
10740Sstevel@tonic-gate }
1075