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 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 * 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 * 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 * 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 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 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 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 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 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 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 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 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 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 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 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 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