Mercurial > illumos > onarm
view usr/src/cmd/iscsi/iscsitgtd/mgmt.c @ 4:1a15d5aaf794
synchronized with onnv_86 (6202) in onnv-gate
author | Koji Uno <koji.uno@sun.com> |
---|---|
date | Mon, 31 Aug 2009 14:38:03 +0900 |
parents | c9caec207d52 |
children |
line wrap: on
line source
/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2006 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" #include <stdio.h> #include <unistd.h> #include <strings.h> #include <stdlib.h> #include <poll.h> #include <sys/types.h> #include <sys/socket.h> #include <sys/select.h> #include <netinet/in.h> #include <sys/filio.h> #include <utility.h> #include <synch.h> #include <sys/stropts.h> #include <libxml/xmlreader.h> #include <iscsitgt_impl.h> #include "queue.h" #include "port.h" #include "utility.h" static void mgmt_monitor_queue(port_args_t *p) { target_queue_t *in = p->port_dataq; msg_t *m; int process = True; char *data, *output; do { m = queue_message_get(in); switch (m->msg_type) { case msg_conn_lost: process = False; break; case msg_log: data = (char *)m->msg_data; output = NULL; tgt_buf_add(&output, "log", data); (void) write(p->port_socket, output, strlen(output)); free(output); break; case msg_mgmt_rply: data = (char *)m->msg_data; output = NULL; tgt_buf_add(&output, "mgmt", data); (void) write(p->port_socket, output, strlen(output)); free(output); free(data); m->msg_data = NULL; break; default: break; } if (m->msg_data) free(m->msg_data); queue_message_free(m); } while (process == True); } static void * mgmt_process(void *v) { port_args_t *p = (port_args_t *)v; int nbytes, nmsgs, pval, ret; char *buf; nfds_t nfds = 1; struct pollfd fds[1]; xmlTextReaderPtr r; tgt_node_t *node = NULL; mgmt_request_t m; fds[0].fd = p->port_socket; fds[0].events = POLLIN; m.m_q = p->port_dataq; m.m_request = mgmt_parse_xml; m.m_time = time(NULL); m.m_targ_name = NULL; while ((pval = poll(fds, nfds, -1)) != -1) { if ((nmsgs = ioctl(p->port_socket, FIONREAD, &nbytes)) == -1) { queue_message_set(p->port_dataq, 0, msg_conn_lost, 0); break; } else if ((nmsgs == 0) && (nbytes == 0)) { queue_message_set(p->port_dataq, 0, msg_conn_lost, 0); break; } else if ((buf = malloc(nbytes)) == NULL) { queue_message_set(p->port_dataq, 0, msg_conn_lost, 0); break; } else if (read(p->port_socket, buf, nbytes) != nbytes) { queue_message_set(p->port_dataq, 0, msg_conn_lost, 0); break; } buf[nbytes] = '\0'; r = (xmlTextReaderPtr)xmlReaderForMemory(buf, nbytes, NULL, NULL, 0); if (r != NULL) { ret = xmlTextReaderRead(r); while (ret == 1) { if (tgt_node_process(r, &node) == False) break; ret = xmlTextReaderRead(r); } if (node != NULL) { m.m_u.m_node = node; queue_message_set(p->port_mgmtq, 0, msg_mgmt_rqst, &m); } xmlFreeTextReader(r); tgt_node_free(node); node = NULL; } } if (pval == -1) queue_message_set(p->port_dataq, 0, msg_conn_lost, 0); (void) close(p->port_socket); p->port_socket = -1; return (NULL); } void * port_management(void *v) { int s, fd, on = 1; struct sockaddr_in sin_ip; struct sockaddr_in6 sin6_ip; socklen_t fromlen; struct sockaddr_storage from; port_args_t *p = (port_args_t *)v; target_queue_t *q = p->port_mgmtq; int l; pthread_t junk; char debug[80]; if ((s = socket(PF_INET6, SOCK_STREAM, 0)) == -1) { if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) { queue_str(q, Q_GEN_ERRS, msg_status, "Can't open socket"); return (NULL); } else { bzero(&sin_ip, sizeof (sin_ip)); sin_ip.sin_family = AF_INET; sin_ip.sin_port = htons(p->port_num); sin_ip.sin_addr.s_addr = INADDR_ANY; (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)); if ((bind(s, (struct sockaddr *)&sin_ip, sizeof (sin_ip))) < 0) { (void) snprintf(debug, sizeof (debug), "bind on port %d failed\n", p->port_num); queue_str(q, Q_GEN_ERRS, msg_status, debug); return (NULL); } } } else { bzero(&sin6_ip, sizeof (sin6_ip)); sin6_ip.sin6_family = AF_INET6; sin6_ip.sin6_port = htons(p->port_num); sin6_ip.sin6_addr = in6addr_any; (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof (on)); if ((bind(s, (struct sockaddr *)&sin6_ip, sizeof (sin6_ip))) < 0) { (void) snprintf(debug, sizeof (debug), "bind on port %d failed\n", p->port_num); queue_str(q, Q_GEN_ERRS, msg_status, debug); return (NULL); } } if (listen(s, 5) < 0) { queue_str(q, Q_GEN_ERRS, msg_status, "listen failed"); return (NULL); } /*CONSTANTCONDITION*/ while (1) { fromlen = sizeof (from); if ((fd = accept(s, (struct sockaddr *)&from, &fromlen)) < 0) { queue_str(q, Q_GEN_ERRS, msg_status, "accept failed"); return (NULL); } l = 128 * 1024; if (setsockopt(fd, SOL_SOCKET, SO_RCVBUF, (char *)&l, sizeof (l)) < 0) queue_str(q, Q_GEN_ERRS, msg_status, "setsockopt failed"); if (setsockopt(fd, SOL_SOCKET, SO_SNDBUF, (char *)&l, sizeof (l)) < 0) queue_str(q, Q_GEN_ERRS, msg_status, "setsockopt failed"); p->port_socket = fd; (void) pthread_create(&junk, NULL, mgmt_process, p); mgmt_monitor_queue(p); } return (NULL); }