4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 #include <sys/types.h>
27 #include <sys/socket.h>
31 #include <sys/sunddi.h>
37 #include <netinet/in.h>
38 #include <sys/utsname.h>
41 * NOTE: This routine is found in libnsl. There's apparently no prototype to
42 * be found in any of the header files in /usr/include so defining a prototype
43 * here to keep the compiler happy.
45 int getdomainname(char *, int);
47 static const char *iqn_template
= "iqn.2004-02.%s";
50 #include <sys/scsi/adapters/iscsi_if.h>
52 typedef struct utils_val_name
{
57 utils_val_name_t param_names
[] = {
58 { ISCSI_LOGIN_PARAM_DATA_SEQUENCE_IN_ORDER
, "Sequence In Order"},
59 { ISCSI_LOGIN_PARAM_IMMEDIATE_DATA
, "Immediate Data"},
60 { ISCSI_LOGIN_PARAM_INITIAL_R2T
, "Inital R2T"},
61 { ISCSI_LOGIN_PARAM_DATA_PDU_IN_ORDER
, "Data PDU In Order"},
62 { ISCSI_LOGIN_PARAM_HEADER_DIGEST
, "Header Digest"},
63 { ISCSI_LOGIN_PARAM_DATA_DIGEST
, "Data Digest"},
64 { ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_RETAIN
, "Default Time To Retain"},
65 { ISCSI_LOGIN_PARAM_DEFAULT_TIME_2_WAIT
, "Default Time To Wait"},
66 { ISCSI_LOGIN_PARAM_MAX_RECV_DATA_SEGMENT_LENGTH
,
67 "Max Recv Data Segment Length"},
68 { ISCSI_LOGIN_PARAM_FIRST_BURST_LENGTH
, "First Burst Length"},
69 { ISCSI_LOGIN_PARAM_MAX_BURST_LENGTH
, "Max Burst Length"},
70 { ISCSI_LOGIN_PARAM_MAX_CONNECTIONS
, "Max Connections"},
71 { ISCSI_LOGIN_PARAM_OUTSTANDING_R2T
, "Outstanding R2T"},
72 { ISCSI_LOGIN_PARAM_ERROR_RECOVERY_LEVEL
, "Error Recovery Level"},
77 * utils_map_param -- Given a parameter return it's ascii name
79 * This routine was created because previously an array contained in order
80 * the parameter names. Once or twice the parameters value changed which
81 * changed the order, but not the array. To avoid further confusion we'll
82 * do a simple lookup. This code is rarely called so it shouldn't be an
86 utils_map_param(int p
)
90 for (pn
= param_names
; pn
->u_name
!= NULL
; pn
++)
97 * prt_bitmap -- print out ascii strings associated with bit numbers.
100 prt_bitmap(int bitmap
, char *str
, char *buf
, int size
)
107 * The maximum space required will if the bitmap was all 1's which
108 * would cause the octal characters to be replaced by '|'. So make
109 * sure the buffer has enough space.
111 if (size
< strlen(str
))
114 for (p
= str
; size
--; p
++) {
118 * if we have been putting out stuff add separator
123 do_put
= ((1 << *p
) & bitmap
);
124 bitmap
&= ~(1 << *p
);
130 /* ---- remove the last separator if it was added ---- */
131 if ((buf
> start
) && (*(buf
- 1) == '|'))
138 * parse_addr_port_tpgt - Used to parse addr, port and tpgt from string
140 * This function is used to parse addr, port and tpgt from a string. Callers
141 * of this function are the sendtargets and login redirection code. The
142 * caller must be aware that this function will modify the callers string
143 * to insert NULL terminators if required. Port and TPGT are optional.
146 parse_addr_port_tpgt(char *in
, char **addr
, int *type
, char **port
, char **tpgt
)
148 char *t_port
, *t_tpgt
;
150 /* default return values if requested */
163 /* extract ip or domain name */
168 in
= strchr(*addr
, ']');
173 /* IPV4 or domainname */
180 t_port
= strchr(in
, ':');
181 if (t_port
!= NULL
) {
189 t_tpgt
= strchr(in
, ',');
190 if (t_tpgt
!= NULL
) {
201 * []--------------------------------------------------------------[]
202 * | reverse_fqdn -- given a fully qualified domain name reverse it |
204 * | The routine has the obvious problem that it can only handle a |
205 * | name with 5 or less dots. This needs to be fixed by counting |
206 * | the number of dots in the incoming name, calloc'ing an array |
207 * | of the appropriate size and then handling the pointers. |
208 * []--------------------------------------------------------------[]
211 /* LINTED E_FUNC_ARG_UNUSED for 3rd arg size */
212 reverse_fqdn(const char *domain
, char *buf
, int size
)
220 if ((dp
= dp1
= malloc(strlen(domain
) + 1)) == NULL
)
222 (void) strcpy(dp
, domain
);
223 while ((p
= (char *)strchr(dp
, '.')) != NULL
) {
232 (void) strcpy(buf
, dp
);
233 for (v
++; v
< 5; v
++) {
234 (void) strcat(buf
, ".");
235 (void) strcat(buf
, ptrs
[v
]);
242 * []------------------------------------------------------------------[]
243 * | utils_iqn_create -- returns an iqn name for the machine |
245 * | The information found in the iqn is not correct. The year and |
246 * | date should be flexible. Currently this is hardwired to the |
247 * | current year and month of this project. |
248 * []------------------------------------------------------------------[]
251 utils_iqn_create(char *iqn_buf
, int size
)
253 struct utsname uts_info
;
254 char domainname
[256];
257 char *pmet
= NULL
; /* temp reversed .. get it */
259 boolean_t rval
= B_FALSE
; /* Default */
261 if (uname(&uts_info
) == -1) {
265 if (getdomainname(domainname
, sizeof (domainname
))) {
269 if ((temp
= malloc(strlen(uts_info
.nodename
) +
270 strlen(domainname
) + 2)) == NULL
) {
275 * getdomainname always returns something in the order of
276 * host.domainname so we need to skip over that portion of the
277 * host name because we don't care about it.
279 if ((p
= strchr(domainname
, '.')) == NULL
)
284 /* ---- Create Fully Qualified Domain Name ---- */
285 (void) snprintf(temp
, strlen(p
), "%s.%s", uts_info
.nodename
, p
);
287 /* ---- According to the spec, names must be lower case ---- */
288 for (p
= temp
; *p
; p
++)
292 len
= strlen(temp
) + 1;
293 if ((pmet
= malloc(len
)) == NULL
) {
297 if (reverse_fqdn(temp
, pmet
, len
) == B_FALSE
) {
302 * Now use the template with the reversed domainname to create
303 * an iSCSI name using the IQN format. Only count it a success
304 * if the number of characters formated is less than the buffer
307 if (snprintf(iqn_buf
, size
, iqn_template
, pmet
) <= size
)
317 #endif /* !_KERNEL */