1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
8fcf3ce44SJohn Forte * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9fcf3ce44SJohn Forte * or http://www.opensolaris.org/os/licensing.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte /*
22fcf3ce44SJohn Forte * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23fcf3ce44SJohn Forte * Use is subject to license terms.
24fcf3ce44SJohn Forte */
25fcf3ce44SJohn Forte
26fcf3ce44SJohn Forte #include <sys/types.h>
27fcf3ce44SJohn Forte #include <sys/socket.h>
28fcf3ce44SJohn Forte
29fcf3ce44SJohn Forte
30fcf3ce44SJohn Forte #ifdef _KERNEL
31fcf3ce44SJohn Forte #include <sys/sunddi.h>
32fcf3ce44SJohn Forte #else
33fcf3ce44SJohn Forte #include <stdio.h>
34fcf3ce44SJohn Forte #include <stdlib.h>
35fcf3ce44SJohn Forte #include <strings.h>
36fcf3ce44SJohn Forte #include <ctype.h>
37fcf3ce44SJohn Forte #include <netinet/in.h>
38fcf3ce44SJohn Forte #include <sys/utsname.h>
39fcf3ce44SJohn Forte
40fcf3ce44SJohn Forte /*
41fcf3ce44SJohn Forte * NOTE: This routine is found in libnsl. There's apparently no prototype to
42fcf3ce44SJohn Forte * be found in any of the header files in /usr/include so defining a prototype
43fcf3ce44SJohn Forte * here to keep the compiler happy.
44fcf3ce44SJohn Forte */
45fcf3ce44SJohn Forte int getdomainname(char *, int);
46fcf3ce44SJohn Forte
47fcf3ce44SJohn Forte static const char *iqn_template = "iqn.2004-02.%s";
48fcf3ce44SJohn Forte #endif
49fcf3ce44SJohn Forte
50fcf3ce44SJohn Forte #include <sys/scsi/adapters/iscsi_if.h>
51fcf3ce44SJohn Forte
52fcf3ce44SJohn Forte typedef struct utils_val_name {
53fcf3ce44SJohn Forte int u_val;
54fcf3ce44SJohn Forte char *u_name;
55fcf3ce44SJohn Forte } utils_val_name_t;
56fcf3ce44SJohn Forte
57fcf3ce44SJohn Forte utils_val_name_t param_names[] = {
58fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER, "Sequence In Order"},
59fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_IMMEDIATE_DATA, "Immediate Data"},
60fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_INITIAL_R2T, "Inital R2T"},
61fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER, "Data PDU In Order"},
62fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_HEADER_DIGEST, "Header Digest"},
63fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_DATA_DIGEST, "Data Digest"},
64fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN, "Default Time To Retain"},
65fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT, "Default Time To Wait"},
66fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH,
67fcf3ce44SJohn Forte "Max Recv Data Segment Length"},
68fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH, "First Burst Length"},
69fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH, "Max Burst Length"},
70fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_MAX_CONNECTIONS, "Max Connections"},
71fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_OUTSTANDING_R2T, "Outstanding R2T"},
72fcf3ce44SJohn Forte { ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL, "Error Recovery Level"},
73fcf3ce44SJohn Forte { 0, NULL }
74fcf3ce44SJohn Forte };
75fcf3ce44SJohn Forte
76fcf3ce44SJohn Forte /*
77fcf3ce44SJohn Forte * utils_map_param -- Given a parameter return it's ascii name
78fcf3ce44SJohn Forte *
79fcf3ce44SJohn Forte * This routine was created because previously an array contained in order
80fcf3ce44SJohn Forte * the parameter names. Once or twice the parameters value changed which
81fcf3ce44SJohn Forte * changed the order, but not the array. To avoid further confusion we'll
82fcf3ce44SJohn Forte * do a simple lookup. This code is rarely called so it shouldn't be an
83fcf3ce44SJohn Forte * issue.
84fcf3ce44SJohn Forte */
85fcf3ce44SJohn Forte char *
utils_map_param(int p)86fcf3ce44SJohn Forte utils_map_param(int p)
87fcf3ce44SJohn Forte {
88fcf3ce44SJohn Forte utils_val_name_t *pn;
89fcf3ce44SJohn Forte
90fcf3ce44SJohn Forte for (pn = param_names; pn->u_name != NULL; pn++)
91fcf3ce44SJohn Forte if (pn->u_val == p)
92fcf3ce44SJohn Forte return (pn->u_name);
93fcf3ce44SJohn Forte return (NULL);
94fcf3ce44SJohn Forte }
95fcf3ce44SJohn Forte
96fcf3ce44SJohn Forte /*
97fcf3ce44SJohn Forte * prt_bitmap -- print out ascii strings associated with bit numbers.
98fcf3ce44SJohn Forte */
99fcf3ce44SJohn Forte char *
prt_bitmap(int bitmap,char * str,char * buf,int size)100fcf3ce44SJohn Forte prt_bitmap(int bitmap, char *str, char *buf, int size)
101fcf3ce44SJohn Forte {
102fcf3ce44SJohn Forte char *p = NULL;
103fcf3ce44SJohn Forte char *start = buf;
104fcf3ce44SJohn Forte int do_put = 0;
105fcf3ce44SJohn Forte
106fcf3ce44SJohn Forte /*
107fcf3ce44SJohn Forte * The maximum space required will if the bitmap was all 1's which
108fcf3ce44SJohn Forte * would cause the octal characters to be replaced by '|'. So make
109fcf3ce44SJohn Forte * sure the buffer has enough space.
110fcf3ce44SJohn Forte */
111fcf3ce44SJohn Forte if (size < strlen(str))
112fcf3ce44SJohn Forte return ("No room");
113fcf3ce44SJohn Forte
114fcf3ce44SJohn Forte for (p = str; size--; p++) {
115fcf3ce44SJohn Forte if (*p < 0x20) {
116fcf3ce44SJohn Forte
117fcf3ce44SJohn Forte /*
118fcf3ce44SJohn Forte * if we have been putting out stuff add separator
119fcf3ce44SJohn Forte */
120fcf3ce44SJohn Forte if (do_put)
121fcf3ce44SJohn Forte *buf++ = '|';
122fcf3ce44SJohn Forte
123fcf3ce44SJohn Forte do_put = ((1 << *p) & bitmap);
124fcf3ce44SJohn Forte bitmap &= ~(1 << *p);
125fcf3ce44SJohn Forte
126fcf3ce44SJohn Forte } else if (do_put)
127fcf3ce44SJohn Forte *buf++ = *p;
128fcf3ce44SJohn Forte }
129fcf3ce44SJohn Forte
130fcf3ce44SJohn Forte /* ---- remove the last separator if it was added ---- */
131fcf3ce44SJohn Forte if ((buf > start) && (*(buf - 1) == '|'))
132fcf3ce44SJohn Forte buf--;
133fcf3ce44SJohn Forte *buf = '\0';
134fcf3ce44SJohn Forte return (start);
135fcf3ce44SJohn Forte }
136fcf3ce44SJohn Forte
137fcf3ce44SJohn Forte /*
138fcf3ce44SJohn Forte * parse_addr_port_tpgt - Used to parse addr, port and tpgt from string
139fcf3ce44SJohn Forte *
140fcf3ce44SJohn Forte * This function is used to parse addr, port and tpgt from a string. Callers
141fcf3ce44SJohn Forte * of this function are the sendtargets and login redirection code. The
142fcf3ce44SJohn Forte * caller must be aware that this function will modify the callers string
143fcf3ce44SJohn Forte * to insert NULL terminators if required. Port and TPGT are optional.
144fcf3ce44SJohn Forte */
145fcf3ce44SJohn Forte boolean_t
parse_addr_port_tpgt(char * in,char ** addr,int * type,char ** port,char ** tpgt)146fcf3ce44SJohn Forte parse_addr_port_tpgt(char *in, char **addr, int *type, char **port, char **tpgt)
147fcf3ce44SJohn Forte {
148fcf3ce44SJohn Forte char *t_port, *t_tpgt;
149fcf3ce44SJohn Forte
150fcf3ce44SJohn Forte /* default return values if requested */
151fcf3ce44SJohn Forte if (addr == NULL) {
152fcf3ce44SJohn Forte return (B_FALSE);
153fcf3ce44SJohn Forte } else {
154fcf3ce44SJohn Forte *addr = NULL;
155fcf3ce44SJohn Forte }
156fcf3ce44SJohn Forte if (port != NULL) {
157fcf3ce44SJohn Forte *port = NULL;
158fcf3ce44SJohn Forte }
159fcf3ce44SJohn Forte if (tpgt != NULL) {
160fcf3ce44SJohn Forte *tpgt = NULL;
161fcf3ce44SJohn Forte }
162fcf3ce44SJohn Forte
163fcf3ce44SJohn Forte /* extract ip or domain name */
164fcf3ce44SJohn Forte if (*in == '[') {
165fcf3ce44SJohn Forte /* IPV6 */
166fcf3ce44SJohn Forte *type = AF_INET6;
167fcf3ce44SJohn Forte *addr = ++in;
168fcf3ce44SJohn Forte in = strchr(*addr, ']');
169fcf3ce44SJohn Forte if (in == NULL)
170fcf3ce44SJohn Forte return (B_FALSE);
171*71531557SToomas Soome *in++ = '\0';
172fcf3ce44SJohn Forte } else {
173fcf3ce44SJohn Forte /* IPV4 or domainname */
174fcf3ce44SJohn Forte *type = AF_INET;
175fcf3ce44SJohn Forte *addr = in;
176fcf3ce44SJohn Forte }
177fcf3ce44SJohn Forte
178fcf3ce44SJohn Forte /* extract port */
179fcf3ce44SJohn Forte if (port != NULL) {
180fcf3ce44SJohn Forte t_port = strchr(in, ':');
181fcf3ce44SJohn Forte if (t_port != NULL) {
182fcf3ce44SJohn Forte *t_port++ = '\0';
183fcf3ce44SJohn Forte *port = in = t_port;
184fcf3ce44SJohn Forte }
185fcf3ce44SJohn Forte }
186fcf3ce44SJohn Forte
187fcf3ce44SJohn Forte /* exact tpgt */
188fcf3ce44SJohn Forte if (tpgt != NULL) {
189fcf3ce44SJohn Forte t_tpgt = strchr(in, ',');
190fcf3ce44SJohn Forte if (t_tpgt != NULL) {
191fcf3ce44SJohn Forte *t_tpgt++ = '\0';
192fcf3ce44SJohn Forte *tpgt = in = t_tpgt;
193fcf3ce44SJohn Forte }
194fcf3ce44SJohn Forte }
195fcf3ce44SJohn Forte
196fcf3ce44SJohn Forte return (B_TRUE);
197fcf3ce44SJohn Forte }
198fcf3ce44SJohn Forte
199fcf3ce44SJohn Forte #ifndef _KERNEL
200fcf3ce44SJohn Forte /*
201fcf3ce44SJohn Forte * []--------------------------------------------------------------[]
202fcf3ce44SJohn Forte * | reverse_fqdn -- given a fully qualified domain name reverse it |
203fcf3ce44SJohn Forte * | |
204fcf3ce44SJohn Forte * | The routine has the obvious problem that it can only handle a |
205fcf3ce44SJohn Forte * | name with 5 or less dots. This needs to be fixed by counting |
206fcf3ce44SJohn Forte * | the number of dots in the incoming name, calloc'ing an array |
207fcf3ce44SJohn Forte * | of the appropriate size and then handling the pointers. |
208fcf3ce44SJohn Forte * []--------------------------------------------------------------[]
209fcf3ce44SJohn Forte */
210fcf3ce44SJohn Forte static boolean_t
211fcf3ce44SJohn Forte /* LINTED E_FUNC_ARG_UNUSED for 3rd arg size */
reverse_fqdn(const char * domain,char * buf,int size)212fcf3ce44SJohn Forte reverse_fqdn(const char *domain, char *buf, int size)
213fcf3ce44SJohn Forte {
214fcf3ce44SJohn Forte char *ptrs[5];
215fcf3ce44SJohn Forte char *dp;
216fcf3ce44SJohn Forte char *dp1;
217fcf3ce44SJohn Forte char *p;
218fcf3ce44SJohn Forte int v = 4;
219fcf3ce44SJohn Forte
220fcf3ce44SJohn Forte if ((dp = dp1 = malloc(strlen(domain) + 1)) == NULL)
221fcf3ce44SJohn Forte return (B_FALSE);
222fcf3ce44SJohn Forte (void) strcpy(dp, domain);
223fcf3ce44SJohn Forte while ((p = (char *)strchr(dp, '.')) != NULL) {
224fcf3ce44SJohn Forte *p = '\0';
225fcf3ce44SJohn Forte if (v < 0) {
226fcf3ce44SJohn Forte free(dp1);
227fcf3ce44SJohn Forte return (B_FALSE);
228fcf3ce44SJohn Forte }
229fcf3ce44SJohn Forte ptrs[v--] = dp;
230fcf3ce44SJohn Forte dp = p + 1;
231fcf3ce44SJohn Forte }
232fcf3ce44SJohn Forte (void) strcpy(buf, dp);
233fcf3ce44SJohn Forte for (v++; v < 5; v++) {
234fcf3ce44SJohn Forte (void) strcat(buf, ".");
235fcf3ce44SJohn Forte (void) strcat(buf, ptrs[v]);
236fcf3ce44SJohn Forte }
237fcf3ce44SJohn Forte free(dp1);
238fcf3ce44SJohn Forte return (B_TRUE);
239fcf3ce44SJohn Forte }
240fcf3ce44SJohn Forte
241fcf3ce44SJohn Forte /*
242fcf3ce44SJohn Forte * []------------------------------------------------------------------[]
243fcf3ce44SJohn Forte * | utils_iqn_create -- returns an iqn name for the machine |
244fcf3ce44SJohn Forte * | |
245fcf3ce44SJohn Forte * | The information found in the iqn is not correct. The year and |
246fcf3ce44SJohn Forte * | date should be flexible. Currently this is hardwired to the |
247fcf3ce44SJohn Forte * | current year and month of this project. |
248fcf3ce44SJohn Forte * []------------------------------------------------------------------[]
249fcf3ce44SJohn Forte */
250fcf3ce44SJohn Forte boolean_t
utils_iqn_create(char * iqn_buf,int size)251fcf3ce44SJohn Forte utils_iqn_create(char *iqn_buf, int size)
252fcf3ce44SJohn Forte {
253fcf3ce44SJohn Forte struct utsname uts_info;
254fcf3ce44SJohn Forte char domainname[256];
255fcf3ce44SJohn Forte char *temp = NULL;
256fcf3ce44SJohn Forte char *p;
257fcf3ce44SJohn Forte char *pmet = NULL; /* temp reversed .. get it */
258fcf3ce44SJohn Forte int len;
259fcf3ce44SJohn Forte boolean_t rval = B_FALSE; /* Default */
260fcf3ce44SJohn Forte
261fcf3ce44SJohn Forte if (uname(&uts_info) == -1) {
262fcf3ce44SJohn Forte goto out;
263fcf3ce44SJohn Forte }
264fcf3ce44SJohn Forte
265fcf3ce44SJohn Forte if (getdomainname(domainname, sizeof (domainname))) {
266fcf3ce44SJohn Forte goto out;
267fcf3ce44SJohn Forte }
268fcf3ce44SJohn Forte
269fcf3ce44SJohn Forte if ((temp = malloc(strlen(uts_info.nodename) +
270fcf3ce44SJohn Forte strlen(domainname) + 2)) == NULL) {
271fcf3ce44SJohn Forte goto out;
272fcf3ce44SJohn Forte }
273fcf3ce44SJohn Forte
274fcf3ce44SJohn Forte /*
275fcf3ce44SJohn Forte * getdomainname always returns something in the order of
276fcf3ce44SJohn Forte * host.domainname so we need to skip over that portion of the
277fcf3ce44SJohn Forte * host name because we don't care about it.
278fcf3ce44SJohn Forte */
279fcf3ce44SJohn Forte if ((p = strchr(domainname, '.')) == NULL)
280fcf3ce44SJohn Forte p = domainname;
281fcf3ce44SJohn Forte else
282fcf3ce44SJohn Forte p++;
283fcf3ce44SJohn Forte
284fcf3ce44SJohn Forte /* ---- Create Fully Qualified Domain Name ---- */
285fcf3ce44SJohn Forte (void) snprintf(temp, strlen(p), "%s.%s", uts_info.nodename, p);
286fcf3ce44SJohn Forte
287fcf3ce44SJohn Forte /* ---- According to the spec, names must be lower case ---- */
288fcf3ce44SJohn Forte for (p = temp; *p; p++)
289fcf3ce44SJohn Forte if (isupper(*p))
290fcf3ce44SJohn Forte *p = tolower(*p);
291fcf3ce44SJohn Forte
292fcf3ce44SJohn Forte len = strlen(temp) + 1;
293fcf3ce44SJohn Forte if ((pmet = malloc(len)) == NULL) {
294fcf3ce44SJohn Forte goto out;
295fcf3ce44SJohn Forte }
296fcf3ce44SJohn Forte
297fcf3ce44SJohn Forte if (reverse_fqdn(temp, pmet, len) == B_FALSE) {
298fcf3ce44SJohn Forte goto out;
299fcf3ce44SJohn Forte }
300fcf3ce44SJohn Forte
301fcf3ce44SJohn Forte /*
302fcf3ce44SJohn Forte * Now use the template with the reversed domainname to create
303fcf3ce44SJohn Forte * an iSCSI name using the IQN format. Only count it a success
304fcf3ce44SJohn Forte * if the number of characters formated is less than the buffer
305fcf3ce44SJohn Forte * size.
306fcf3ce44SJohn Forte */
307fcf3ce44SJohn Forte if (snprintf(iqn_buf, size, iqn_template, pmet) <= size)
308fcf3ce44SJohn Forte rval = B_TRUE;
309fcf3ce44SJohn Forte out:
310fcf3ce44SJohn Forte if (temp)
311fcf3ce44SJohn Forte free(temp);
312fcf3ce44SJohn Forte if (pmet)
313fcf3ce44SJohn Forte free(pmet);
314fcf3ce44SJohn Forte
315fcf3ce44SJohn Forte return (rval);
316fcf3ce44SJohn Forte }
317fcf3ce44SJohn Forte #endif /* !_KERNEL */
318