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