1*7836SJohn.Forte@Sun.COM /*
2*7836SJohn.Forte@Sun.COM * CDDL HEADER START
3*7836SJohn.Forte@Sun.COM *
4*7836SJohn.Forte@Sun.COM * The contents of this file are subject to the terms of the
5*7836SJohn.Forte@Sun.COM * Common Development and Distribution License (the "License").
6*7836SJohn.Forte@Sun.COM * You may not use this file except in compliance with the License.
7*7836SJohn.Forte@Sun.COM *
8*7836SJohn.Forte@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*7836SJohn.Forte@Sun.COM * or http://www.opensolaris.org/os/licensing.
10*7836SJohn.Forte@Sun.COM * See the License for the specific language governing permissions
11*7836SJohn.Forte@Sun.COM * and limitations under the License.
12*7836SJohn.Forte@Sun.COM *
13*7836SJohn.Forte@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each
14*7836SJohn.Forte@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*7836SJohn.Forte@Sun.COM * If applicable, add the following below this CDDL HEADER, with the
16*7836SJohn.Forte@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying
17*7836SJohn.Forte@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner]
18*7836SJohn.Forte@Sun.COM *
19*7836SJohn.Forte@Sun.COM * CDDL HEADER END
20*7836SJohn.Forte@Sun.COM */
21*7836SJohn.Forte@Sun.COM
22*7836SJohn.Forte@Sun.COM /*
23*7836SJohn.Forte@Sun.COM * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24*7836SJohn.Forte@Sun.COM * Use is subject to license terms.
25*7836SJohn.Forte@Sun.COM */
26*7836SJohn.Forte@Sun.COM
27*7836SJohn.Forte@Sun.COM #include <stdio.h>
28*7836SJohn.Forte@Sun.COM #include <stdlib.h>
29*7836SJohn.Forte@Sun.COM #include <string.h>
30*7836SJohn.Forte@Sun.COM #include <strings.h>
31*7836SJohn.Forte@Sun.COM #include <sys/types.h>
32*7836SJohn.Forte@Sun.COM #include <sys/socket.h>
33*7836SJohn.Forte@Sun.COM #include <netinet/in.h>
34*7836SJohn.Forte@Sun.COM #include <arpa/inet.h>
35*7836SJohn.Forte@Sun.COM #include <unistd.h>
36*7836SJohn.Forte@Sun.COM #include <poll.h>
37*7836SJohn.Forte@Sun.COM #include <errno.h>
38*7836SJohn.Forte@Sun.COM
39*7836SJohn.Forte@Sun.COM #include "isns_server.h"
40*7836SJohn.Forte@Sun.COM #include "isns_log.h"
41*7836SJohn.Forte@Sun.COM #include "isns_pdu.h"
42*7836SJohn.Forte@Sun.COM
43*7836SJohn.Forte@Sun.COM #define ISNS_MAX_IOVEC 5
44*7836SJohn.Forte@Sun.COM #define MAX_XID (2^16)
45*7836SJohn.Forte@Sun.COM #define MAX_RCV_RSP_COUNT 10 /* Maximum number of unmatched xid */
46*7836SJohn.Forte@Sun.COM #define ISNS_RCV_RETRY_MAX 2
47*7836SJohn.Forte@Sun.COM #define IPV4_RSVD_BYTES 10
48*7836SJohn.Forte@Sun.COM
49*7836SJohn.Forte@Sun.COM /* externs */
50*7836SJohn.Forte@Sun.COM #ifdef DEBUG
51*7836SJohn.Forte@Sun.COM extern void dump_pdu2(isns_pdu_t *);
52*7836SJohn.Forte@Sun.COM #endif
53*7836SJohn.Forte@Sun.COM
54*7836SJohn.Forte@Sun.COM /*
55*7836SJohn.Forte@Sun.COM * local functions.
56*7836SJohn.Forte@Sun.COM */
57*7836SJohn.Forte@Sun.COM
58*7836SJohn.Forte@Sun.COM size_t
isns_rcv_pdu(int fd,isns_pdu_t ** pdu,size_t * pdu_size,int rcv_timeout)59*7836SJohn.Forte@Sun.COM isns_rcv_pdu(
60*7836SJohn.Forte@Sun.COM int fd,
61*7836SJohn.Forte@Sun.COM isns_pdu_t **pdu,
62*7836SJohn.Forte@Sun.COM size_t *pdu_size,
63*7836SJohn.Forte@Sun.COM int rcv_timeout
64*7836SJohn.Forte@Sun.COM )
65*7836SJohn.Forte@Sun.COM {
66*7836SJohn.Forte@Sun.COM int poll_cnt;
67*7836SJohn.Forte@Sun.COM struct pollfd fds;
68*7836SJohn.Forte@Sun.COM iovec_t iovec[ISNS_MAX_IOVEC];
69*7836SJohn.Forte@Sun.COM isns_pdu_t *tmp_pdu_hdr;
70*7836SJohn.Forte@Sun.COM ssize_t bytes_received, total_bytes_received = 0;
71*7836SJohn.Forte@Sun.COM struct msghdr msg;
72*7836SJohn.Forte@Sun.COM uint8_t *tmp_pdu_data;
73*7836SJohn.Forte@Sun.COM
74*7836SJohn.Forte@Sun.COM uint16_t payload_len = 0;
75*7836SJohn.Forte@Sun.COM
76*7836SJohn.Forte@Sun.COM /* initialize to zero */
77*7836SJohn.Forte@Sun.COM *pdu = NULL;
78*7836SJohn.Forte@Sun.COM *pdu_size = 0;
79*7836SJohn.Forte@Sun.COM
80*7836SJohn.Forte@Sun.COM fds.fd = fd;
81*7836SJohn.Forte@Sun.COM fds.events = (POLLIN | POLLRDNORM);
82*7836SJohn.Forte@Sun.COM fds.revents = 0;
83*7836SJohn.Forte@Sun.COM
84*7836SJohn.Forte@Sun.COM /* Receive the header first */
85*7836SJohn.Forte@Sun.COM tmp_pdu_hdr = (isns_pdu_t *)malloc(ISNSP_HEADER_SIZE);
86*7836SJohn.Forte@Sun.COM if (tmp_pdu_hdr == NULL) {
87*7836SJohn.Forte@Sun.COM return (0);
88*7836SJohn.Forte@Sun.COM }
89*7836SJohn.Forte@Sun.COM (void) memset((void *)&tmp_pdu_hdr[0], 0, ISNSP_HEADER_SIZE);
90*7836SJohn.Forte@Sun.COM (void) memset((void *)&iovec[0], 0, sizeof (iovec_t));
91*7836SJohn.Forte@Sun.COM iovec[0].iov_base = (void *)tmp_pdu_hdr;
92*7836SJohn.Forte@Sun.COM iovec[0].iov_len = ISNSP_HEADER_SIZE;
93*7836SJohn.Forte@Sun.COM
94*7836SJohn.Forte@Sun.COM /* Initialization of the message header. */
95*7836SJohn.Forte@Sun.COM bzero(&msg, sizeof (msg));
96*7836SJohn.Forte@Sun.COM msg.msg_iov = &iovec[0];
97*7836SJohn.Forte@Sun.COM /* msg.msg_flags = MSG_WAITALL, */
98*7836SJohn.Forte@Sun.COM msg.msg_iovlen = 1;
99*7836SJohn.Forte@Sun.COM
100*7836SJohn.Forte@Sun.COM /* Poll and receive the pdu header */
101*7836SJohn.Forte@Sun.COM poll_cnt = 0;
102*7836SJohn.Forte@Sun.COM do {
103*7836SJohn.Forte@Sun.COM int err = poll(&fds, 1, rcv_timeout * 1000);
104*7836SJohn.Forte@Sun.COM if (err <= 0) {
105*7836SJohn.Forte@Sun.COM poll_cnt ++;
106*7836SJohn.Forte@Sun.COM } else {
107*7836SJohn.Forte@Sun.COM bytes_received = recvmsg(fd, &msg, MSG_WAITALL);
108*7836SJohn.Forte@Sun.COM break;
109*7836SJohn.Forte@Sun.COM }
110*7836SJohn.Forte@Sun.COM } while (poll_cnt < ISNS_RCV_RETRY_MAX);
111*7836SJohn.Forte@Sun.COM
112*7836SJohn.Forte@Sun.COM if (poll_cnt >= ISNS_RCV_RETRY_MAX) {
113*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
114*7836SJohn.Forte@Sun.COM return (0);
115*7836SJohn.Forte@Sun.COM }
116*7836SJohn.Forte@Sun.COM
117*7836SJohn.Forte@Sun.COM if (bytes_received <= 0) {
118*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
119*7836SJohn.Forte@Sun.COM return (0);
120*7836SJohn.Forte@Sun.COM }
121*7836SJohn.Forte@Sun.COM
122*7836SJohn.Forte@Sun.COM total_bytes_received += bytes_received;
123*7836SJohn.Forte@Sun.COM
124*7836SJohn.Forte@Sun.COM payload_len = ntohs(tmp_pdu_hdr->payload_len);
125*7836SJohn.Forte@Sun.COM /* Verify the received payload len is within limit */
126*7836SJohn.Forte@Sun.COM if (payload_len > ISNSP_MAX_PAYLOAD_SIZE) {
127*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
128*7836SJohn.Forte@Sun.COM return (0);
129*7836SJohn.Forte@Sun.COM }
130*7836SJohn.Forte@Sun.COM
131*7836SJohn.Forte@Sun.COM /* Proceed to receive additional data. */
132*7836SJohn.Forte@Sun.COM tmp_pdu_data = malloc(payload_len);
133*7836SJohn.Forte@Sun.COM if (tmp_pdu_data == NULL) {
134*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
135*7836SJohn.Forte@Sun.COM return (0);
136*7836SJohn.Forte@Sun.COM }
137*7836SJohn.Forte@Sun.COM (void) memset((void *)&iovec[0], 0, sizeof (iovec_t));
138*7836SJohn.Forte@Sun.COM iovec[0].iov_base = (void *)tmp_pdu_data;
139*7836SJohn.Forte@Sun.COM iovec[0].iov_len = payload_len;
140*7836SJohn.Forte@Sun.COM
141*7836SJohn.Forte@Sun.COM /* Initialization of the message header. */
142*7836SJohn.Forte@Sun.COM bzero(&msg, sizeof (msg));
143*7836SJohn.Forte@Sun.COM msg.msg_iov = &iovec[0];
144*7836SJohn.Forte@Sun.COM /* msg.msg_flags = MSG_WAITALL, */
145*7836SJohn.Forte@Sun.COM msg.msg_iovlen = 1;
146*7836SJohn.Forte@Sun.COM
147*7836SJohn.Forte@Sun.COM /* poll and receive the pdu payload */
148*7836SJohn.Forte@Sun.COM poll_cnt = 0;
149*7836SJohn.Forte@Sun.COM do {
150*7836SJohn.Forte@Sun.COM int err = poll(&fds, 1, rcv_timeout * 1000);
151*7836SJohn.Forte@Sun.COM if (err <= 0) {
152*7836SJohn.Forte@Sun.COM poll_cnt ++;
153*7836SJohn.Forte@Sun.COM } else {
154*7836SJohn.Forte@Sun.COM bytes_received = recvmsg(fd, &msg, MSG_WAITALL);
155*7836SJohn.Forte@Sun.COM break;
156*7836SJohn.Forte@Sun.COM }
157*7836SJohn.Forte@Sun.COM } while (poll_cnt < ISNS_RCV_RETRY_MAX);
158*7836SJohn.Forte@Sun.COM
159*7836SJohn.Forte@Sun.COM if (poll_cnt >= ISNS_RCV_RETRY_MAX) {
160*7836SJohn.Forte@Sun.COM free(tmp_pdu_data);
161*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
162*7836SJohn.Forte@Sun.COM return (0);
163*7836SJohn.Forte@Sun.COM }
164*7836SJohn.Forte@Sun.COM
165*7836SJohn.Forte@Sun.COM if (bytes_received <= 0) {
166*7836SJohn.Forte@Sun.COM free(tmp_pdu_data);
167*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
168*7836SJohn.Forte@Sun.COM return (0);
169*7836SJohn.Forte@Sun.COM }
170*7836SJohn.Forte@Sun.COM
171*7836SJohn.Forte@Sun.COM total_bytes_received += bytes_received;
172*7836SJohn.Forte@Sun.COM
173*7836SJohn.Forte@Sun.COM *pdu_size = ISNSP_HEADER_SIZE + payload_len;
174*7836SJohn.Forte@Sun.COM (*pdu) = (isns_pdu_t *)malloc(*pdu_size);
175*7836SJohn.Forte@Sun.COM if (*pdu == NULL) {
176*7836SJohn.Forte@Sun.COM *pdu_size = 0;
177*7836SJohn.Forte@Sun.COM free(tmp_pdu_data);
178*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
179*7836SJohn.Forte@Sun.COM return (0);
180*7836SJohn.Forte@Sun.COM }
181*7836SJohn.Forte@Sun.COM (*pdu)->version = ntohs(tmp_pdu_hdr->version);
182*7836SJohn.Forte@Sun.COM (*pdu)->func_id = ntohs(tmp_pdu_hdr->func_id);
183*7836SJohn.Forte@Sun.COM (*pdu)->payload_len = payload_len;
184*7836SJohn.Forte@Sun.COM (*pdu)->flags = ntohs(tmp_pdu_hdr->flags);
185*7836SJohn.Forte@Sun.COM (*pdu)->xid = ntohs(tmp_pdu_hdr->xid);
186*7836SJohn.Forte@Sun.COM (*pdu)->seq = ntohs(tmp_pdu_hdr->seq);
187*7836SJohn.Forte@Sun.COM (void) memcpy(&((*pdu)->payload), tmp_pdu_data, payload_len);
188*7836SJohn.Forte@Sun.COM
189*7836SJohn.Forte@Sun.COM free(tmp_pdu_data);
190*7836SJohn.Forte@Sun.COM tmp_pdu_data = NULL;
191*7836SJohn.Forte@Sun.COM free(tmp_pdu_hdr);
192*7836SJohn.Forte@Sun.COM tmp_pdu_hdr = NULL;
193*7836SJohn.Forte@Sun.COM
194*7836SJohn.Forte@Sun.COM return (total_bytes_received);
195*7836SJohn.Forte@Sun.COM }
196*7836SJohn.Forte@Sun.COM
197*7836SJohn.Forte@Sun.COM int
isns_send_pdu(int fd,isns_pdu_t * pdu,size_t pl)198*7836SJohn.Forte@Sun.COM isns_send_pdu(
199*7836SJohn.Forte@Sun.COM int fd,
200*7836SJohn.Forte@Sun.COM isns_pdu_t *pdu,
201*7836SJohn.Forte@Sun.COM size_t pl
202*7836SJohn.Forte@Sun.COM )
203*7836SJohn.Forte@Sun.COM {
204*7836SJohn.Forte@Sun.COM uint8_t *payload;
205*7836SJohn.Forte@Sun.COM uint16_t flags;
206*7836SJohn.Forte@Sun.COM uint16_t seq;
207*7836SJohn.Forte@Sun.COM iovec_t iovec[ISNS_MAX_IOVEC];
208*7836SJohn.Forte@Sun.COM struct msghdr msg = { 0 };
209*7836SJohn.Forte@Sun.COM
210*7836SJohn.Forte@Sun.COM size_t send_len;
211*7836SJohn.Forte@Sun.COM ssize_t bytes_sent;
212*7836SJohn.Forte@Sun.COM
213*7836SJohn.Forte@Sun.COM
214*7836SJohn.Forte@Sun.COM /* Initialization of the message header. */
215*7836SJohn.Forte@Sun.COM msg.msg_iov = &iovec[0];
216*7836SJohn.Forte@Sun.COM /* msg.msg_flags = MSG_WAITALL, */
217*7836SJohn.Forte@Sun.COM msg.msg_iovlen = 2;
218*7836SJohn.Forte@Sun.COM
219*7836SJohn.Forte@Sun.COM /*
220*7836SJohn.Forte@Sun.COM * Initialize the pdu flags.
221*7836SJohn.Forte@Sun.COM */
222*7836SJohn.Forte@Sun.COM flags = ISNS_FLAG_SERVER;
223*7836SJohn.Forte@Sun.COM flags |= ISNS_FLAG_FIRST_PDU;
224*7836SJohn.Forte@Sun.COM
225*7836SJohn.Forte@Sun.COM /*
226*7836SJohn.Forte@Sun.COM * Initialize the pdu sequence id.
227*7836SJohn.Forte@Sun.COM */
228*7836SJohn.Forte@Sun.COM seq = 0;
229*7836SJohn.Forte@Sun.COM
230*7836SJohn.Forte@Sun.COM iovec[0].iov_base = (void *)pdu;
231*7836SJohn.Forte@Sun.COM iovec[0].iov_len = (ISNSP_HEADER_SIZE);
232*7836SJohn.Forte@Sun.COM
233*7836SJohn.Forte@Sun.COM payload = pdu->payload;
234*7836SJohn.Forte@Sun.COM
235*7836SJohn.Forte@Sun.COM #ifdef DEBUG
236*7836SJohn.Forte@Sun.COM pdu->flags = htons(flags);
237*7836SJohn.Forte@Sun.COM pdu->seq = htons(0);
238*7836SJohn.Forte@Sun.COM pdu->payload_len = htons(pl);
239*7836SJohn.Forte@Sun.COM dump_pdu2(pdu);
240*7836SJohn.Forte@Sun.COM #endif
241*7836SJohn.Forte@Sun.COM
242*7836SJohn.Forte@Sun.COM do {
243*7836SJohn.Forte@Sun.COM /* set the payload for sending */
244*7836SJohn.Forte@Sun.COM iovec[1].iov_base = (void *)payload;
245*7836SJohn.Forte@Sun.COM
246*7836SJohn.Forte@Sun.COM if (pl > ISNSP_MAX_PAYLOAD_SIZE) {
247*7836SJohn.Forte@Sun.COM send_len = ISNSP_MAX_PAYLOAD_SIZE;
248*7836SJohn.Forte@Sun.COM } else {
249*7836SJohn.Forte@Sun.COM send_len = pl;
250*7836SJohn.Forte@Sun.COM /* set the last pdu flag */
251*7836SJohn.Forte@Sun.COM flags |= ISNS_FLAG_LAST_PDU;
252*7836SJohn.Forte@Sun.COM }
253*7836SJohn.Forte@Sun.COM iovec[1].iov_len = send_len;
254*7836SJohn.Forte@Sun.COM pdu->payload_len = htons(send_len);
255*7836SJohn.Forte@Sun.COM
256*7836SJohn.Forte@Sun.COM /* set the pdu flags */
257*7836SJohn.Forte@Sun.COM pdu->flags = htons(flags);
258*7836SJohn.Forte@Sun.COM /* set the pdu sequence id */
259*7836SJohn.Forte@Sun.COM pdu->seq = htons(seq);
260*7836SJohn.Forte@Sun.COM
261*7836SJohn.Forte@Sun.COM /* send the packet */
262*7836SJohn.Forte@Sun.COM bytes_sent = sendmsg(fd, &msg, 0);
263*7836SJohn.Forte@Sun.COM
264*7836SJohn.Forte@Sun.COM /* get rid of the first pdu flag */
265*7836SJohn.Forte@Sun.COM flags &= ~(ISNS_FLAG_FIRST_PDU);
266*7836SJohn.Forte@Sun.COM
267*7836SJohn.Forte@Sun.COM /* next part of payload */
268*7836SJohn.Forte@Sun.COM payload += send_len;
269*7836SJohn.Forte@Sun.COM pl -= send_len;
270*7836SJohn.Forte@Sun.COM
271*7836SJohn.Forte@Sun.COM /* add the length of header for verification */
272*7836SJohn.Forte@Sun.COM send_len += ISNSP_HEADER_SIZE;
273*7836SJohn.Forte@Sun.COM
274*7836SJohn.Forte@Sun.COM /* increase the sequence id by one */
275*7836SJohn.Forte@Sun.COM seq ++;
276*7836SJohn.Forte@Sun.COM } while (bytes_sent == send_len && pl > 0);
277*7836SJohn.Forte@Sun.COM
278*7836SJohn.Forte@Sun.COM if (bytes_sent == send_len) {
279*7836SJohn.Forte@Sun.COM return (0);
280*7836SJohn.Forte@Sun.COM } else {
281*7836SJohn.Forte@Sun.COM isnslog(LOG_DEBUG, "isns_send_pdu", "sending pdu failed.");
282*7836SJohn.Forte@Sun.COM return (-1);
283*7836SJohn.Forte@Sun.COM }
284*7836SJohn.Forte@Sun.COM }
285*7836SJohn.Forte@Sun.COM
286*7836SJohn.Forte@Sun.COM #define RSP_PDU_FRAG_SZ (ISNSP_MAX_PDU_SIZE / 10)
287*7836SJohn.Forte@Sun.COM static int
pdu_reset(isns_pdu_t ** rsp,size_t * sz)288*7836SJohn.Forte@Sun.COM pdu_reset(
289*7836SJohn.Forte@Sun.COM isns_pdu_t **rsp,
290*7836SJohn.Forte@Sun.COM size_t *sz
291*7836SJohn.Forte@Sun.COM )
292*7836SJohn.Forte@Sun.COM {
293*7836SJohn.Forte@Sun.COM int ec = 0;
294*7836SJohn.Forte@Sun.COM
295*7836SJohn.Forte@Sun.COM if (*rsp == NULL) {
296*7836SJohn.Forte@Sun.COM *rsp = (isns_pdu_t *)malloc(RSP_PDU_FRAG_SZ);
297*7836SJohn.Forte@Sun.COM if (*rsp != NULL) {
298*7836SJohn.Forte@Sun.COM *sz = RSP_PDU_FRAG_SZ;
299*7836SJohn.Forte@Sun.COM } else {
300*7836SJohn.Forte@Sun.COM ec = ISNS_RSP_INTERNAL_ERROR;
301*7836SJohn.Forte@Sun.COM }
302*7836SJohn.Forte@Sun.COM }
303*7836SJohn.Forte@Sun.COM
304*7836SJohn.Forte@Sun.COM return (ec);
305*7836SJohn.Forte@Sun.COM }
306*7836SJohn.Forte@Sun.COM
307*7836SJohn.Forte@Sun.COM int
pdu_reset_rsp(isns_pdu_t ** rsp,size_t * pl,size_t * sz)308*7836SJohn.Forte@Sun.COM pdu_reset_rsp(
309*7836SJohn.Forte@Sun.COM isns_pdu_t **rsp,
310*7836SJohn.Forte@Sun.COM size_t *pl,
311*7836SJohn.Forte@Sun.COM size_t *sz
312*7836SJohn.Forte@Sun.COM )
313*7836SJohn.Forte@Sun.COM {
314*7836SJohn.Forte@Sun.COM int ec = pdu_reset(rsp, sz);
315*7836SJohn.Forte@Sun.COM
316*7836SJohn.Forte@Sun.COM if (ec == 0) {
317*7836SJohn.Forte@Sun.COM /* leave space for status code */
318*7836SJohn.Forte@Sun.COM *pl = 4;
319*7836SJohn.Forte@Sun.COM }
320*7836SJohn.Forte@Sun.COM
321*7836SJohn.Forte@Sun.COM return (ec);
322*7836SJohn.Forte@Sun.COM }
323*7836SJohn.Forte@Sun.COM
324*7836SJohn.Forte@Sun.COM int
pdu_reset_scn(isns_pdu_t ** pdu,size_t * pl,size_t * sz)325*7836SJohn.Forte@Sun.COM pdu_reset_scn(
326*7836SJohn.Forte@Sun.COM isns_pdu_t **pdu,
327*7836SJohn.Forte@Sun.COM size_t *pl,
328*7836SJohn.Forte@Sun.COM size_t *sz
329*7836SJohn.Forte@Sun.COM )
330*7836SJohn.Forte@Sun.COM {
331*7836SJohn.Forte@Sun.COM int ec = pdu_reset(pdu, sz);
332*7836SJohn.Forte@Sun.COM
333*7836SJohn.Forte@Sun.COM if (ec == 0) {
334*7836SJohn.Forte@Sun.COM *pl = 0;
335*7836SJohn.Forte@Sun.COM }
336*7836SJohn.Forte@Sun.COM
337*7836SJohn.Forte@Sun.COM return (ec);
338*7836SJohn.Forte@Sun.COM }
339*7836SJohn.Forte@Sun.COM
340*7836SJohn.Forte@Sun.COM int
pdu_reset_esi(isns_pdu_t ** pdu,size_t * pl,size_t * sz)341*7836SJohn.Forte@Sun.COM pdu_reset_esi(
342*7836SJohn.Forte@Sun.COM isns_pdu_t **pdu,
343*7836SJohn.Forte@Sun.COM size_t *pl,
344*7836SJohn.Forte@Sun.COM size_t *sz
345*7836SJohn.Forte@Sun.COM )
346*7836SJohn.Forte@Sun.COM {
347*7836SJohn.Forte@Sun.COM return (pdu_reset_scn(pdu, pl, sz));
348*7836SJohn.Forte@Sun.COM }
349*7836SJohn.Forte@Sun.COM
350*7836SJohn.Forte@Sun.COM int
pdu_update_code(isns_pdu_t * pdu,size_t * pl,int code)351*7836SJohn.Forte@Sun.COM pdu_update_code(
352*7836SJohn.Forte@Sun.COM isns_pdu_t *pdu,
353*7836SJohn.Forte@Sun.COM size_t *pl,
354*7836SJohn.Forte@Sun.COM int code
355*7836SJohn.Forte@Sun.COM )
356*7836SJohn.Forte@Sun.COM {
357*7836SJohn.Forte@Sun.COM isns_resp_t *resp;
358*7836SJohn.Forte@Sun.COM
359*7836SJohn.Forte@Sun.COM resp = (isns_resp_t *)pdu->payload;
360*7836SJohn.Forte@Sun.COM
361*7836SJohn.Forte@Sun.COM /* reset the payload length */
362*7836SJohn.Forte@Sun.COM if (code != ISNS_RSP_SUCCESSFUL || *pl == 0) {
363*7836SJohn.Forte@Sun.COM *pl = 4;
364*7836SJohn.Forte@Sun.COM }
365*7836SJohn.Forte@Sun.COM
366*7836SJohn.Forte@Sun.COM resp->status = htonl(code);
367*7836SJohn.Forte@Sun.COM
368*7836SJohn.Forte@Sun.COM return (0);
369*7836SJohn.Forte@Sun.COM }
370*7836SJohn.Forte@Sun.COM
371*7836SJohn.Forte@Sun.COM int
pdu_add_tlv(isns_pdu_t ** pdu,size_t * pl,size_t * sz,uint32_t attr_id,uint32_t attr_len,void * attr_data,int pflag)372*7836SJohn.Forte@Sun.COM pdu_add_tlv(
373*7836SJohn.Forte@Sun.COM isns_pdu_t **pdu,
374*7836SJohn.Forte@Sun.COM size_t *pl,
375*7836SJohn.Forte@Sun.COM size_t *sz,
376*7836SJohn.Forte@Sun.COM uint32_t attr_id,
377*7836SJohn.Forte@Sun.COM uint32_t attr_len,
378*7836SJohn.Forte@Sun.COM void *attr_data,
379*7836SJohn.Forte@Sun.COM int pflag
380*7836SJohn.Forte@Sun.COM )
381*7836SJohn.Forte@Sun.COM {
382*7836SJohn.Forte@Sun.COM int ec = 0;
383*7836SJohn.Forte@Sun.COM
384*7836SJohn.Forte@Sun.COM isns_pdu_t *new_pdu;
385*7836SJohn.Forte@Sun.COM size_t new_sz;
386*7836SJohn.Forte@Sun.COM
387*7836SJohn.Forte@Sun.COM isns_tlv_t *attr_tlv;
388*7836SJohn.Forte@Sun.COM uint8_t *payload_ptr;
389*7836SJohn.Forte@Sun.COM uint32_t normalized_attr_len;
390*7836SJohn.Forte@Sun.COM uint64_t attr_tlv_len;
391*7836SJohn.Forte@Sun.COM
392*7836SJohn.Forte@Sun.COM /* The attribute length must be 4-byte aligned. Section 5.1.3. */
393*7836SJohn.Forte@Sun.COM normalized_attr_len = (attr_len % 4) == 0 ? (attr_len) :
394*7836SJohn.Forte@Sun.COM (attr_len + (4 - (attr_len % 4)));
395*7836SJohn.Forte@Sun.COM attr_tlv_len = ISNS_TLV_ATTR_ID_LEN
396*7836SJohn.Forte@Sun.COM + ISNS_TLV_ATTR_LEN_LEN
397*7836SJohn.Forte@Sun.COM + normalized_attr_len;
398*7836SJohn.Forte@Sun.COM /* Check if we are going to exceed the maximum PDU length. */
399*7836SJohn.Forte@Sun.COM if ((ISNSP_HEADER_SIZE + *pl + attr_tlv_len) > *sz) {
400*7836SJohn.Forte@Sun.COM new_sz = *sz + RSP_PDU_FRAG_SZ;
401*7836SJohn.Forte@Sun.COM new_pdu = (isns_pdu_t *)realloc(*pdu, new_sz);
402*7836SJohn.Forte@Sun.COM if (new_pdu != NULL) {
403*7836SJohn.Forte@Sun.COM *sz = new_sz;
404*7836SJohn.Forte@Sun.COM *pdu = new_pdu;
405*7836SJohn.Forte@Sun.COM } else {
406*7836SJohn.Forte@Sun.COM ec = ISNS_RSP_INTERNAL_ERROR;
407*7836SJohn.Forte@Sun.COM return (ec);
408*7836SJohn.Forte@Sun.COM }
409*7836SJohn.Forte@Sun.COM }
410*7836SJohn.Forte@Sun.COM
411*7836SJohn.Forte@Sun.COM attr_tlv = (isns_tlv_t *)malloc(attr_tlv_len);
412*7836SJohn.Forte@Sun.COM (void) memset((void *)attr_tlv, 0, attr_tlv_len);
413*7836SJohn.Forte@Sun.COM
414*7836SJohn.Forte@Sun.COM attr_tlv->attr_id = htonl(attr_id);
415*7836SJohn.Forte@Sun.COM
416*7836SJohn.Forte@Sun.COM switch (attr_id) {
417*7836SJohn.Forte@Sun.COM case ISNS_DELIMITER_ATTR_ID:
418*7836SJohn.Forte@Sun.COM break;
419*7836SJohn.Forte@Sun.COM
420*7836SJohn.Forte@Sun.COM case ISNS_PORTAL_IP_ADDR_ATTR_ID:
421*7836SJohn.Forte@Sun.COM case ISNS_PG_PORTAL_IP_ADDR_ATTR_ID:
422*7836SJohn.Forte@Sun.COM /* IPv6 */
423*7836SJohn.Forte@Sun.COM ASSERT(attr_len == sizeof (in6_addr_t));
424*7836SJohn.Forte@Sun.COM (void) memcpy(attr_tlv->attr_value, attr_data,
425*7836SJohn.Forte@Sun.COM sizeof (in6_addr_t));
426*7836SJohn.Forte@Sun.COM break;
427*7836SJohn.Forte@Sun.COM
428*7836SJohn.Forte@Sun.COM case ISNS_EID_ATTR_ID:
429*7836SJohn.Forte@Sun.COM case ISNS_ISCSI_NAME_ATTR_ID:
430*7836SJohn.Forte@Sun.COM case ISNS_ISCSI_ALIAS_ATTR_ID:
431*7836SJohn.Forte@Sun.COM case ISNS_PG_ISCSI_NAME_ATTR_ID:
432*7836SJohn.Forte@Sun.COM (void) memcpy(attr_tlv->attr_value, (char *)attr_data,
433*7836SJohn.Forte@Sun.COM attr_len);
434*7836SJohn.Forte@Sun.COM break;
435*7836SJohn.Forte@Sun.COM
436*7836SJohn.Forte@Sun.COM default:
437*7836SJohn.Forte@Sun.COM if (attr_len == 8) {
438*7836SJohn.Forte@Sun.COM if (pflag == 0) {
439*7836SJohn.Forte@Sun.COM /*
440*7836SJohn.Forte@Sun.COM * In the iSNS protocol, there is only one
441*7836SJohn.Forte@Sun.COM * attribute ISNS_TIMESTAMP_ATTR_ID which has
442*7836SJohn.Forte@Sun.COM * 8 bytes length integer value and when the
443*7836SJohn.Forte@Sun.COM * function "pdu_add_tlv" is called for adding
444*7836SJohn.Forte@Sun.COM * the timestamp attribute, the value of
445*7836SJohn.Forte@Sun.COM * the attribute is always passed in as its
446*7836SJohn.Forte@Sun.COM * address, i.e. the pflag sets to 1.
447*7836SJohn.Forte@Sun.COM * So it is an error when we get to this code
448*7836SJohn.Forte@Sun.COM * path.
449*7836SJohn.Forte@Sun.COM */
450*7836SJohn.Forte@Sun.COM ec = ISNS_RSP_INTERNAL_ERROR;
451*7836SJohn.Forte@Sun.COM return (ec);
452*7836SJohn.Forte@Sun.COM } else {
453*7836SJohn.Forte@Sun.COM *(uint64_t *)attr_tlv->attr_value =
454*7836SJohn.Forte@Sun.COM *(uint64_t *)attr_data;
455*7836SJohn.Forte@Sun.COM }
456*7836SJohn.Forte@Sun.COM } else if (attr_len == 4) {
457*7836SJohn.Forte@Sun.COM if (pflag == 0) {
458*7836SJohn.Forte@Sun.COM *(uint32_t *)attr_tlv->attr_value =
459*7836SJohn.Forte@Sun.COM htonl((uint32_t)attr_data);
460*7836SJohn.Forte@Sun.COM } else {
461*7836SJohn.Forte@Sun.COM *(uint32_t *)attr_tlv->attr_value =
462*7836SJohn.Forte@Sun.COM *(uint32_t *)attr_data;
463*7836SJohn.Forte@Sun.COM }
464*7836SJohn.Forte@Sun.COM }
465*7836SJohn.Forte@Sun.COM break;
466*7836SJohn.Forte@Sun.COM }
467*7836SJohn.Forte@Sun.COM
468*7836SJohn.Forte@Sun.COM attr_tlv->attr_len = htonl(normalized_attr_len);
469*7836SJohn.Forte@Sun.COM /*
470*7836SJohn.Forte@Sun.COM * Convert the network byte ordered payload length to host byte
471*7836SJohn.Forte@Sun.COM * ordered for local address calculation.
472*7836SJohn.Forte@Sun.COM */
473*7836SJohn.Forte@Sun.COM payload_ptr = (*pdu)->payload + *pl;
474*7836SJohn.Forte@Sun.COM (void) memcpy(payload_ptr, attr_tlv, attr_tlv_len);
475*7836SJohn.Forte@Sun.COM *pl += attr_tlv_len;
476*7836SJohn.Forte@Sun.COM
477*7836SJohn.Forte@Sun.COM /*
478*7836SJohn.Forte@Sun.COM * The payload length might exceed the maximum length of a
479*7836SJohn.Forte@Sun.COM * payload that isnsp allows, we will split the payload and
480*7836SJohn.Forte@Sun.COM * set the size of each payload before they are sent.
481*7836SJohn.Forte@Sun.COM */
482*7836SJohn.Forte@Sun.COM
483*7836SJohn.Forte@Sun.COM free(attr_tlv);
484*7836SJohn.Forte@Sun.COM attr_tlv = NULL;
485*7836SJohn.Forte@Sun.COM
486*7836SJohn.Forte@Sun.COM return (ec);
487*7836SJohn.Forte@Sun.COM }
488*7836SJohn.Forte@Sun.COM
489*7836SJohn.Forte@Sun.COM isns_tlv_t *
pdu_get_source(isns_pdu_t * pdu)490*7836SJohn.Forte@Sun.COM pdu_get_source(
491*7836SJohn.Forte@Sun.COM isns_pdu_t *pdu
492*7836SJohn.Forte@Sun.COM )
493*7836SJohn.Forte@Sun.COM {
494*7836SJohn.Forte@Sun.COM uint8_t *payload = &pdu->payload[0];
495*7836SJohn.Forte@Sun.COM uint16_t payload_len = pdu->payload_len;
496*7836SJohn.Forte@Sun.COM isns_tlv_t *tlv = NULL;
497*7836SJohn.Forte@Sun.COM
498*7836SJohn.Forte@Sun.COM /* response code */
499*7836SJohn.Forte@Sun.COM if (pdu->func_id & ISNS_RSP_MASK) {
500*7836SJohn.Forte@Sun.COM if (payload_len < 4) {
501*7836SJohn.Forte@Sun.COM return (NULL);
502*7836SJohn.Forte@Sun.COM }
503*7836SJohn.Forte@Sun.COM payload += 4;
504*7836SJohn.Forte@Sun.COM payload_len -= 4;
505*7836SJohn.Forte@Sun.COM }
506*7836SJohn.Forte@Sun.COM
507*7836SJohn.Forte@Sun.COM if (payload_len > 8) {
508*7836SJohn.Forte@Sun.COM tlv = (isns_tlv_t *)payload;
509*7836SJohn.Forte@Sun.COM tlv->attr_id = ntohl(tlv->attr_id);
510*7836SJohn.Forte@Sun.COM tlv->attr_len = ntohl(tlv->attr_len);
511*7836SJohn.Forte@Sun.COM }
512*7836SJohn.Forte@Sun.COM
513*7836SJohn.Forte@Sun.COM return (tlv);
514*7836SJohn.Forte@Sun.COM }
515*7836SJohn.Forte@Sun.COM
516*7836SJohn.Forte@Sun.COM isns_tlv_t *
pdu_get_key(isns_pdu_t * pdu,size_t * key_len)517*7836SJohn.Forte@Sun.COM pdu_get_key(
518*7836SJohn.Forte@Sun.COM isns_pdu_t *pdu,
519*7836SJohn.Forte@Sun.COM size_t *key_len
520*7836SJohn.Forte@Sun.COM )
521*7836SJohn.Forte@Sun.COM {
522*7836SJohn.Forte@Sun.COM uint8_t *payload = &pdu->payload[0];
523*7836SJohn.Forte@Sun.COM uint16_t payload_len = pdu->payload_len;
524*7836SJohn.Forte@Sun.COM isns_tlv_t *tlv, *key;
525*7836SJohn.Forte@Sun.COM
526*7836SJohn.Forte@Sun.COM /* reset */
527*7836SJohn.Forte@Sun.COM *key_len = 0;
528*7836SJohn.Forte@Sun.COM
529*7836SJohn.Forte@Sun.COM /* response code */
530*7836SJohn.Forte@Sun.COM if (pdu->func_id & ISNS_RSP_MASK) {
531*7836SJohn.Forte@Sun.COM if (payload_len <= 4) {
532*7836SJohn.Forte@Sun.COM return (NULL);
533*7836SJohn.Forte@Sun.COM }
534*7836SJohn.Forte@Sun.COM payload += 4;
535*7836SJohn.Forte@Sun.COM payload_len -= 4;
536*7836SJohn.Forte@Sun.COM }
537*7836SJohn.Forte@Sun.COM
538*7836SJohn.Forte@Sun.COM /* skip the soure */
539*7836SJohn.Forte@Sun.COM if (payload_len >= 8) {
540*7836SJohn.Forte@Sun.COM tlv = (isns_tlv_t *)payload;
541*7836SJohn.Forte@Sun.COM payload += (8 + tlv->attr_len);
542*7836SJohn.Forte@Sun.COM payload_len -= (8 + tlv->attr_len);
543*7836SJohn.Forte@Sun.COM key = (isns_tlv_t *)payload;
544*7836SJohn.Forte@Sun.COM while (payload_len >= 8) {
545*7836SJohn.Forte@Sun.COM tlv = (isns_tlv_t *)payload;
546*7836SJohn.Forte@Sun.COM tlv->attr_id = ntohl(tlv->attr_id);
547*7836SJohn.Forte@Sun.COM tlv->attr_len = ntohl(tlv->attr_len);
548*7836SJohn.Forte@Sun.COM if (tlv->attr_id == ISNS_DELIMITER_ATTR_ID) {
549*7836SJohn.Forte@Sun.COM break;
550*7836SJohn.Forte@Sun.COM }
551*7836SJohn.Forte@Sun.COM *key_len += (8 + tlv->attr_len);
552*7836SJohn.Forte@Sun.COM payload += (8 + tlv->attr_len);
553*7836SJohn.Forte@Sun.COM payload_len -= (8 + tlv->attr_len);
554*7836SJohn.Forte@Sun.COM }
555*7836SJohn.Forte@Sun.COM }
556*7836SJohn.Forte@Sun.COM
557*7836SJohn.Forte@Sun.COM if (*key_len >= 8) {
558*7836SJohn.Forte@Sun.COM return (key);
559*7836SJohn.Forte@Sun.COM }
560*7836SJohn.Forte@Sun.COM
561*7836SJohn.Forte@Sun.COM return (NULL);
562*7836SJohn.Forte@Sun.COM }
563*7836SJohn.Forte@Sun.COM
564*7836SJohn.Forte@Sun.COM isns_tlv_t *
pdu_get_operand(isns_pdu_t * pdu,size_t * op_len)565*7836SJohn.Forte@Sun.COM pdu_get_operand(
566*7836SJohn.Forte@Sun.COM isns_pdu_t *pdu,
567*7836SJohn.Forte@Sun.COM size_t *op_len
568*7836SJohn.Forte@Sun.COM )
569*7836SJohn.Forte@Sun.COM {
570*7836SJohn.Forte@Sun.COM uint8_t *payload = &pdu->payload[0];
571*7836SJohn.Forte@Sun.COM uint16_t payload_len = pdu->payload_len;
572*7836SJohn.Forte@Sun.COM isns_tlv_t *tlv, *op = NULL;
573*7836SJohn.Forte@Sun.COM int found_op = 0;
574*7836SJohn.Forte@Sun.COM
575*7836SJohn.Forte@Sun.COM /* reset */
576*7836SJohn.Forte@Sun.COM *op_len = 0;
577*7836SJohn.Forte@Sun.COM
578*7836SJohn.Forte@Sun.COM /* response code */
579*7836SJohn.Forte@Sun.COM if (pdu->func_id & ISNS_RSP_MASK) {
580*7836SJohn.Forte@Sun.COM if (payload_len < 4) {
581*7836SJohn.Forte@Sun.COM return (NULL);
582*7836SJohn.Forte@Sun.COM }
583*7836SJohn.Forte@Sun.COM payload += 4;
584*7836SJohn.Forte@Sun.COM payload_len -= 4;
585*7836SJohn.Forte@Sun.COM }
586*7836SJohn.Forte@Sun.COM
587*7836SJohn.Forte@Sun.COM /* tlvs */
588*7836SJohn.Forte@Sun.COM while (payload_len >= 8) {
589*7836SJohn.Forte@Sun.COM tlv = (isns_tlv_t *)payload;
590*7836SJohn.Forte@Sun.COM if (found_op != 0) {
591*7836SJohn.Forte@Sun.COM tlv->attr_id = ntohl(tlv->attr_id);
592*7836SJohn.Forte@Sun.COM tlv->attr_len = ntohl(tlv->attr_len);
593*7836SJohn.Forte@Sun.COM payload += (8 + tlv->attr_len);
594*7836SJohn.Forte@Sun.COM payload_len -= (8 + tlv->attr_len);
595*7836SJohn.Forte@Sun.COM } else {
596*7836SJohn.Forte@Sun.COM payload += (8 + tlv->attr_len);
597*7836SJohn.Forte@Sun.COM payload_len -= (8 + tlv->attr_len);
598*7836SJohn.Forte@Sun.COM if (tlv->attr_id == ISNS_DELIMITER_ATTR_ID) {
599*7836SJohn.Forte@Sun.COM /* found it */
600*7836SJohn.Forte@Sun.COM op = (isns_tlv_t *)payload;
601*7836SJohn.Forte@Sun.COM *op_len = payload_len;
602*7836SJohn.Forte@Sun.COM found_op = 1;
603*7836SJohn.Forte@Sun.COM }
604*7836SJohn.Forte@Sun.COM }
605*7836SJohn.Forte@Sun.COM }
606*7836SJohn.Forte@Sun.COM
607*7836SJohn.Forte@Sun.COM if (*op_len >= 8) {
608*7836SJohn.Forte@Sun.COM return (op);
609*7836SJohn.Forte@Sun.COM }
610*7836SJohn.Forte@Sun.COM
611*7836SJohn.Forte@Sun.COM return (NULL);
612*7836SJohn.Forte@Sun.COM }
613