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