1*fcf3ce44SJohn Forte /*
2*fcf3ce44SJohn Forte * CDDL HEADER START
3*fcf3ce44SJohn Forte *
4*fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5*fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6*fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7*fcf3ce44SJohn Forte *
8*fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10*fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11*fcf3ce44SJohn Forte * and limitations under the License.
12*fcf3ce44SJohn Forte *
13*fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14*fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16*fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17*fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18*fcf3ce44SJohn Forte *
19*fcf3ce44SJohn Forte * CDDL HEADER END
20*fcf3ce44SJohn Forte */
21*fcf3ce44SJohn Forte
22*fcf3ce44SJohn Forte /*
23*fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24*fcf3ce44SJohn Forte * Use is subject to license terms.
25*fcf3ce44SJohn Forte */
26*fcf3ce44SJohn Forte
27*fcf3ce44SJohn Forte #include <stdlib.h>
28*fcf3ce44SJohn Forte #include <stdio.h>
29*fcf3ce44SJohn Forte #include <sys/types.h>
30*fcf3ce44SJohn Forte #include <sys/socket.h>
31*fcf3ce44SJohn Forte #include <netinet/in.h>
32*fcf3ce44SJohn Forte #include <arpa/inet.h>
33*fcf3ce44SJohn Forte #include <unistd.h>
34*fcf3ce44SJohn Forte #include <string.h>
35*fcf3ce44SJohn Forte #include <pthread.h>
36*fcf3ce44SJohn Forte #include <poll.h>
37*fcf3ce44SJohn Forte #ifdef DEBUG
38*fcf3ce44SJohn Forte #include <time.h>
39*fcf3ce44SJohn Forte #endif
40*fcf3ce44SJohn Forte
41*fcf3ce44SJohn Forte #include "isns_server.h"
42*fcf3ce44SJohn Forte #include "isns_cache.h"
43*fcf3ce44SJohn Forte #include "isns_pdu.h"
44*fcf3ce44SJohn Forte #include "isns_msgq.h"
45*fcf3ce44SJohn Forte #include "isns_func.h"
46*fcf3ce44SJohn Forte #include "isns_log.h"
47*fcf3ce44SJohn Forte #include "isns_provider.h"
48*fcf3ce44SJohn Forte
49*fcf3ce44SJohn Forte /* external functions */
50*fcf3ce44SJohn Forte #ifdef DEBUG
51*fcf3ce44SJohn Forte extern void dump_pdu1(isns_pdu_t *);
52*fcf3ce44SJohn Forte extern int verbose_tc;
53*fcf3ce44SJohn Forte #endif
54*fcf3ce44SJohn Forte
55*fcf3ce44SJohn Forte extern boolean_t time_to_exit;
56*fcf3ce44SJohn Forte
57*fcf3ce44SJohn Forte void *
isns_connection(void * arg)58*fcf3ce44SJohn Forte isns_connection(
59*fcf3ce44SJohn Forte void *arg
60*fcf3ce44SJohn Forte )
61*fcf3ce44SJohn Forte {
62*fcf3ce44SJohn Forte int status = 0;
63*fcf3ce44SJohn Forte
64*fcf3ce44SJohn Forte conn_arg_t *conn;
65*fcf3ce44SJohn Forte
66*fcf3ce44SJohn Forte isns_pdu_t *pdu, *combined_pdu, *new_combined_pdu;
67*fcf3ce44SJohn Forte uint8_t *payload_ptr;
68*fcf3ce44SJohn Forte size_t pdu_sz;
69*fcf3ce44SJohn Forte
70*fcf3ce44SJohn Forte conn = (conn_arg_t *)arg;
71*fcf3ce44SJohn Forte
72*fcf3ce44SJohn Forte conn->out_packet.pdu = NULL;
73*fcf3ce44SJohn Forte conn->out_packet.sz = 0;
74*fcf3ce44SJohn Forte combined_pdu = NULL;
75*fcf3ce44SJohn Forte pdu = NULL;
76*fcf3ce44SJohn Forte
77*fcf3ce44SJohn Forte while (status == 0 &&
78*fcf3ce44SJohn Forte time_to_exit == B_FALSE &&
79*fcf3ce44SJohn Forte isns_rcv_pdu(conn->so, &pdu, &pdu_sz, ISNS_RCV_TIMEOUT) > 0) {
80*fcf3ce44SJohn Forte uint16_t flags = pdu->flags;
81*fcf3ce44SJohn Forte if (ISNS_MSG_RECEIVED_ENABLED()) {
82*fcf3ce44SJohn Forte char buf[INET6_ADDRSTRLEN];
83*fcf3ce44SJohn Forte struct sockaddr_storage *ssp = &conn->ss;
84*fcf3ce44SJohn Forte struct sockaddr_in *sinp = (struct sockaddr_in *)ssp;
85*fcf3ce44SJohn Forte if (ssp->ss_family == AF_INET) {
86*fcf3ce44SJohn Forte (void) inet_ntop(AF_INET,
87*fcf3ce44SJohn Forte (void *)&(sinp->sin_addr),
88*fcf3ce44SJohn Forte buf, sizeof (buf));
89*fcf3ce44SJohn Forte } else {
90*fcf3ce44SJohn Forte (void) inet_ntop(AF_INET6,
91*fcf3ce44SJohn Forte (void *)&(sinp->sin_addr),
92*fcf3ce44SJohn Forte buf, sizeof (buf));
93*fcf3ce44SJohn Forte }
94*fcf3ce44SJohn Forte ISNS_MSG_RECEIVED((uintptr_t)buf);
95*fcf3ce44SJohn Forte }
96*fcf3ce44SJohn Forte
97*fcf3ce44SJohn Forte if ((flags & ISNS_FLAG_FIRST_PDU) == ISNS_FLAG_FIRST_PDU) {
98*fcf3ce44SJohn Forte if (combined_pdu != NULL || pdu->seq != 0) {
99*fcf3ce44SJohn Forte goto conn_done;
100*fcf3ce44SJohn Forte }
101*fcf3ce44SJohn Forte combined_pdu = pdu;
102*fcf3ce44SJohn Forte pdu = NULL;
103*fcf3ce44SJohn Forte } else {
104*fcf3ce44SJohn Forte if (combined_pdu == NULL ||
105*fcf3ce44SJohn Forte combined_pdu->func_id != pdu->func_id ||
106*fcf3ce44SJohn Forte combined_pdu->xid != pdu->xid ||
107*fcf3ce44SJohn Forte (combined_pdu->seq + 1) != pdu->seq) {
108*fcf3ce44SJohn Forte /* expect the first pdu, the same tranx id */
109*fcf3ce44SJohn Forte /* and the next sequence id */
110*fcf3ce44SJohn Forte goto conn_done;
111*fcf3ce44SJohn Forte }
112*fcf3ce44SJohn Forte new_combined_pdu = (isns_pdu_t *)malloc(
113*fcf3ce44SJohn Forte ISNSP_HEADER_SIZE +
114*fcf3ce44SJohn Forte combined_pdu->payload_len +
115*fcf3ce44SJohn Forte pdu->payload_len);
116*fcf3ce44SJohn Forte if (new_combined_pdu == NULL) {
117*fcf3ce44SJohn Forte goto conn_done;
118*fcf3ce44SJohn Forte }
119*fcf3ce44SJohn Forte (void) memcpy((void *)new_combined_pdu,
120*fcf3ce44SJohn Forte (void *)combined_pdu,
121*fcf3ce44SJohn Forte ISNSP_HEADER_SIZE + combined_pdu->payload_len);
122*fcf3ce44SJohn Forte payload_ptr = new_combined_pdu->payload +
123*fcf3ce44SJohn Forte combined_pdu->payload_len;
124*fcf3ce44SJohn Forte (void) memcpy((void *)payload_ptr,
125*fcf3ce44SJohn Forte (void *)pdu->payload,
126*fcf3ce44SJohn Forte pdu->payload_len);
127*fcf3ce44SJohn Forte new_combined_pdu->seq = pdu->seq;
128*fcf3ce44SJohn Forte free(combined_pdu);
129*fcf3ce44SJohn Forte combined_pdu = new_combined_pdu;
130*fcf3ce44SJohn Forte free(pdu);
131*fcf3ce44SJohn Forte pdu = NULL;
132*fcf3ce44SJohn Forte }
133*fcf3ce44SJohn Forte if ((flags & ISNS_FLAG_LAST_PDU) == ISNS_FLAG_LAST_PDU) {
134*fcf3ce44SJohn Forte #ifdef DEBUG
135*fcf3ce44SJohn Forte time_t t;
136*fcf3ce44SJohn Forte clock_t c;
137*fcf3ce44SJohn Forte
138*fcf3ce44SJohn Forte dump_pdu1(combined_pdu);
139*fcf3ce44SJohn Forte
140*fcf3ce44SJohn Forte if (verbose_tc != 0) {
141*fcf3ce44SJohn Forte t = time(NULL);
142*fcf3ce44SJohn Forte c = clock();
143*fcf3ce44SJohn Forte }
144*fcf3ce44SJohn Forte #endif
145*fcf3ce44SJohn Forte
146*fcf3ce44SJohn Forte conn->in_packet.pdu = combined_pdu;
147*fcf3ce44SJohn Forte conn->out_packet.pl = 0;
148*fcf3ce44SJohn Forte conn->ec = 0;
149*fcf3ce44SJohn Forte
150*fcf3ce44SJohn Forte if (packet_split_verify(conn) == 0) {
151*fcf3ce44SJohn Forte (void) cache_lock(conn->lock);
152*fcf3ce44SJohn Forte status = conn->handler(conn);
153*fcf3ce44SJohn Forte conn->ec = cache_unlock(conn->lock, conn->ec);
154*fcf3ce44SJohn Forte }
155*fcf3ce44SJohn Forte
156*fcf3ce44SJohn Forte switch (status) {
157*fcf3ce44SJohn Forte case -1:
158*fcf3ce44SJohn Forte /* error */
159*fcf3ce44SJohn Forte break;
160*fcf3ce44SJohn Forte case 0:
161*fcf3ce44SJohn Forte status = isns_response(conn);
162*fcf3ce44SJohn Forte
163*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_connection",
164*fcf3ce44SJohn Forte "Response status: %d.", status);
165*fcf3ce44SJohn Forte if (ISNS_MSG_RESPONDED_ENABLED()) {
166*fcf3ce44SJohn Forte char buf[INET6_ADDRSTRLEN];
167*fcf3ce44SJohn Forte struct sockaddr_storage *ssp =
168*fcf3ce44SJohn Forte &conn->ss;
169*fcf3ce44SJohn Forte struct sockaddr_in *sinp =
170*fcf3ce44SJohn Forte (struct sockaddr_in *)ssp;
171*fcf3ce44SJohn Forte if (ssp->ss_family == AF_INET) {
172*fcf3ce44SJohn Forte (void) inet_ntop(AF_INET,
173*fcf3ce44SJohn Forte (void *)&(sinp->sin_addr),
174*fcf3ce44SJohn Forte buf, sizeof (buf));
175*fcf3ce44SJohn Forte } else {
176*fcf3ce44SJohn Forte (void) inet_ntop(AF_INET6,
177*fcf3ce44SJohn Forte (void *)&(sinp->sin_addr),
178*fcf3ce44SJohn Forte buf, sizeof (buf));
179*fcf3ce44SJohn Forte }
180*fcf3ce44SJohn Forte ISNS_MSG_RESPONDED((uintptr_t)buf);
181*fcf3ce44SJohn Forte }
182*fcf3ce44SJohn Forte break;
183*fcf3ce44SJohn Forte default:
184*fcf3ce44SJohn Forte /* no need to send response message */
185*fcf3ce44SJohn Forte status = 0;
186*fcf3ce44SJohn Forte break;
187*fcf3ce44SJohn Forte }
188*fcf3ce44SJohn Forte
189*fcf3ce44SJohn Forte #ifdef DEBUG
190*fcf3ce44SJohn Forte if (verbose_tc != 0) {
191*fcf3ce44SJohn Forte t = time(NULL) - t;
192*fcf3ce44SJohn Forte c = clock() - c;
193*fcf3ce44SJohn Forte printf("time %d clock %.4lf -msg response\n",
194*fcf3ce44SJohn Forte t, c / (double)CLOCKS_PER_SEC);
195*fcf3ce44SJohn Forte }
196*fcf3ce44SJohn Forte #endif
197*fcf3ce44SJohn Forte free(combined_pdu);
198*fcf3ce44SJohn Forte combined_pdu = NULL;
199*fcf3ce44SJohn Forte }
200*fcf3ce44SJohn Forte }
201*fcf3ce44SJohn Forte
202*fcf3ce44SJohn Forte conn_done:
203*fcf3ce44SJohn Forte if (pdu != NULL) {
204*fcf3ce44SJohn Forte free(pdu);
205*fcf3ce44SJohn Forte }
206*fcf3ce44SJohn Forte if (combined_pdu != NULL) {
207*fcf3ce44SJohn Forte free(combined_pdu);
208*fcf3ce44SJohn Forte }
209*fcf3ce44SJohn Forte (void) close(conn->so);
210*fcf3ce44SJohn Forte (void) free(conn->out_packet.pdu);
211*fcf3ce44SJohn Forte (void) free(conn);
212*fcf3ce44SJohn Forte
213*fcf3ce44SJohn Forte /* decrease the thread ref count */
214*fcf3ce44SJohn Forte dec_thr_count();
215*fcf3ce44SJohn Forte
216*fcf3ce44SJohn Forte return (NULL);
217*fcf3ce44SJohn Forte }
218*fcf3ce44SJohn Forte
219*fcf3ce44SJohn Forte /* the iSNS server port watcher */
220*fcf3ce44SJohn Forte
221*fcf3ce44SJohn Forte void *
isns_port_watcher(void * arg)222*fcf3ce44SJohn Forte isns_port_watcher(
223*fcf3ce44SJohn Forte /* LINTED E_FUNC_ARG_UNUSED */
224*fcf3ce44SJohn Forte void *arg
225*fcf3ce44SJohn Forte )
226*fcf3ce44SJohn Forte {
227*fcf3ce44SJohn Forte int s, f;
228*fcf3ce44SJohn Forte int opt = 1;
229*fcf3ce44SJohn Forte struct sockaddr_in sin;
230*fcf3ce44SJohn Forte struct sockaddr_in *sinp;
231*fcf3ce44SJohn Forte struct sockaddr_storage *ssp;
232*fcf3ce44SJohn Forte socklen_t sslen;
233*fcf3ce44SJohn Forte char buf[INET6_ADDRSTRLEN];
234*fcf3ce44SJohn Forte pthread_t tid;
235*fcf3ce44SJohn Forte struct pollfd fds;
236*fcf3ce44SJohn Forte int poll_ret;
237*fcf3ce44SJohn Forte
238*fcf3ce44SJohn Forte conn_arg_t *conn;
239*fcf3ce44SJohn Forte
240*fcf3ce44SJohn Forte if ((s = socket(AF_INET, SOCK_STREAM, 0)) != -1) {
241*fcf3ce44SJohn Forte /* IPv4 */
242*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher", "IPv4 socket created.");
243*fcf3ce44SJohn Forte (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (void *)&opt,
244*fcf3ce44SJohn Forte sizeof (opt));
245*fcf3ce44SJohn Forte
246*fcf3ce44SJohn Forte sin.sin_family = AF_INET;
247*fcf3ce44SJohn Forte sin.sin_port = htons(ISNS_DEFAULT_SERVER_PORT);
248*fcf3ce44SJohn Forte sin.sin_addr.s_addr = htonl(INADDR_ANY);
249*fcf3ce44SJohn Forte
250*fcf3ce44SJohn Forte if (bind(s, (struct sockaddr *)&sin, sizeof (sin)) < 0) {
251*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
252*fcf3ce44SJohn Forte "binding on server port failed: %%m");
253*fcf3ce44SJohn Forte goto watch_failed;
254*fcf3ce44SJohn Forte }
255*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
256*fcf3ce44SJohn Forte "successful binding on server port.");
257*fcf3ce44SJohn Forte } else {
258*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
259*fcf3ce44SJohn Forte "cannot create socket: %%m.");
260*fcf3ce44SJohn Forte goto watch_failed;
261*fcf3ce44SJohn Forte }
262*fcf3ce44SJohn Forte
263*fcf3ce44SJohn Forte if (listen(s, 5) < 0) {
264*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
265*fcf3ce44SJohn Forte "listening on server port failed: %%m.");
266*fcf3ce44SJohn Forte goto watch_failed;
267*fcf3ce44SJohn Forte }
268*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher", "listening on server port ok.");
269*fcf3ce44SJohn Forte
270*fcf3ce44SJohn Forte fds.fd = s;
271*fcf3ce44SJohn Forte fds.events = (POLLIN | POLLRDNORM);
272*fcf3ce44SJohn Forte fds.revents = 0;
273*fcf3ce44SJohn Forte
274*fcf3ce44SJohn Forte /* waiting for connections */
275*fcf3ce44SJohn Forte for (;;) {
276*fcf3ce44SJohn Forte if (time_to_exit) {
277*fcf3ce44SJohn Forte return (NULL);
278*fcf3ce44SJohn Forte }
279*fcf3ce44SJohn Forte
280*fcf3ce44SJohn Forte poll_ret = poll(&fds, 1, 1000);
281*fcf3ce44SJohn Forte if (poll_ret <= 0) {
282*fcf3ce44SJohn Forte continue;
283*fcf3ce44SJohn Forte }
284*fcf3ce44SJohn Forte
285*fcf3ce44SJohn Forte /* allocate a connection argument */
286*fcf3ce44SJohn Forte conn = (conn_arg_t *)malloc(sizeof (conn_arg_t));
287*fcf3ce44SJohn Forte if (conn == NULL) {
288*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
289*fcf3ce44SJohn Forte "malloc() failed.");
290*fcf3ce44SJohn Forte goto watch_failed;
291*fcf3ce44SJohn Forte }
292*fcf3ce44SJohn Forte ssp = &conn->ss;
293*fcf3ce44SJohn Forte sslen = sizeof (conn->ss);
294*fcf3ce44SJohn Forte f = accept(s, (struct sockaddr *)ssp, &sslen);
295*fcf3ce44SJohn Forte if (f < 0) {
296*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
297*fcf3ce44SJohn Forte "accepting connection failed: %%m.");
298*fcf3ce44SJohn Forte goto watch_failed;
299*fcf3ce44SJohn Forte }
300*fcf3ce44SJohn Forte sinp = (struct sockaddr_in *)ssp;
301*fcf3ce44SJohn Forte if (ssp->ss_family == AF_INET) {
302*fcf3ce44SJohn Forte (void) inet_ntop(AF_INET, (void *)&(sinp->sin_addr),
303*fcf3ce44SJohn Forte buf, sizeof (buf));
304*fcf3ce44SJohn Forte } else {
305*fcf3ce44SJohn Forte (void) inet_ntop(AF_INET6, (void *)&(sinp->sin_addr),
306*fcf3ce44SJohn Forte buf, sizeof (buf));
307*fcf3ce44SJohn Forte }
308*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
309*fcf3ce44SJohn Forte "connection from %s:%d.", buf,
310*fcf3ce44SJohn Forte sinp->sin_port);
311*fcf3ce44SJohn Forte
312*fcf3ce44SJohn Forte if (ISNS_CONNECTION_ACCEPTED_ENABLED()) {
313*fcf3ce44SJohn Forte ISNS_CONNECTION_ACCEPTED((uintptr_t)buf);
314*fcf3ce44SJohn Forte }
315*fcf3ce44SJohn Forte
316*fcf3ce44SJohn Forte conn->so = f;
317*fcf3ce44SJohn Forte /* create an isns connection */
318*fcf3ce44SJohn Forte if (pthread_create(&tid, NULL,
319*fcf3ce44SJohn Forte isns_connection, (void *)conn) != 0) {
320*fcf3ce44SJohn Forte (void) close(f);
321*fcf3ce44SJohn Forte (void) free(conn);
322*fcf3ce44SJohn Forte isnslog(LOG_DEBUG, "isns_port_watcher",
323*fcf3ce44SJohn Forte "pthread_create() failed.");
324*fcf3ce44SJohn Forte } else {
325*fcf3ce44SJohn Forte /* increase the thread ref count */
326*fcf3ce44SJohn Forte inc_thr_count();
327*fcf3ce44SJohn Forte }
328*fcf3ce44SJohn Forte }
329*fcf3ce44SJohn Forte
330*fcf3ce44SJohn Forte watch_failed:
331*fcf3ce44SJohn Forte shutdown_server();
332*fcf3ce44SJohn Forte return (NULL);
333*fcf3ce44SJohn Forte }
334*fcf3ce44SJohn Forte
335*fcf3ce44SJohn Forte static uint16_t xid = 0;
336*fcf3ce44SJohn Forte static pthread_mutex_t xid_mtx = PTHREAD_MUTEX_INITIALIZER;
337*fcf3ce44SJohn Forte uint16_t
get_server_xid()338*fcf3ce44SJohn Forte get_server_xid(
339*fcf3ce44SJohn Forte )
340*fcf3ce44SJohn Forte {
341*fcf3ce44SJohn Forte uint16_t tmp;
342*fcf3ce44SJohn Forte
343*fcf3ce44SJohn Forte (void) pthread_mutex_lock(&xid_mtx);
344*fcf3ce44SJohn Forte tmp = ++ xid;
345*fcf3ce44SJohn Forte (void) pthread_mutex_unlock(&xid_mtx);
346*fcf3ce44SJohn Forte
347*fcf3ce44SJohn Forte return (tmp);
348*fcf3ce44SJohn Forte }
349