1 /*
2  * Copyright (c) 1998,1999,2000
3  *	Traakan, Inc., Los Altos, CA
4  *	All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36 
37 
38 #include "ndmlib.h"
39 
40 
41 
42 xdrproc_t
ndmnmb_find_xdrproc(struct ndmp_msg_buf * nmb)43 ndmnmb_find_xdrproc (struct ndmp_msg_buf *nmb)
44 {
45 	struct ndmp_xdr_message_table *	xmte;
46 
47 	xmte = ndmp_xmt_lookup (nmb->protocol_version, nmb->header.message);
48 
49 	if (!xmte) {
50 		return 0;
51 	}
52 
53 	if (nmb->header.message_type == NDMP0_MESSAGE_REQUEST) {
54 		return (xdrproc_t) xmte->xdr_request;
55 	}
56 
57 	if (nmb->header.message_type == NDMP0_MESSAGE_REPLY) {
58 		return (xdrproc_t) xmte->xdr_reply;
59 	}
60 
61 	return 0;
62 }
63 
64 void
ndmnmb_free(struct ndmp_msg_buf * nmb)65 ndmnmb_free (struct ndmp_msg_buf *nmb)
66 {
67 	xdrproc_t xdr_body = ndmnmb_find_xdrproc (nmb);
68 
69 	if (nmb->flags & NDMNMB_FLAG_NO_FREE)
70 		return;
71 
72 	if (xdr_body) {
73 		xdr_free (xdr_body, (void*) &nmb->body);
74 	}
75 }
76 
77 void
ndmnmb_snoop(struct ndmlog * log,char * tag,int level,struct ndmp_msg_buf * nmb,char * whence)78 ndmnmb_snoop (
79   struct ndmlog *log,
80   char *tag,
81   int level,
82   struct ndmp_msg_buf *nmb,
83   char *whence)
84 {
85 	int		rc, nl, i;
86 	char		buf[2048];
87 	int		(*ndmpp)();
88 	int		level5 = 5;
89 	int		level6 = 6;
90 
91 	 if (level < 6 && nmb->protocol_version == 4) {
92 		ndmp4_header *header = (ndmp4_header *)&nmb->header;
93 		if ((header->message_code == NDMP4_NOTIFY_DATA_HALTED &&
94 		     header->error_code == NDMP4_DATA_HALT_SUCCESSFUL) ||
95 		    (header->message_code == NDMP4_NOTIFY_MOVER_HALTED &&
96 		     header->error_code == NDMP4_MOVER_HALT_CONNECT_CLOSED)) {
97 			level = 6;
98 			level5 = 0;
99 			level6 = 0;
100 		}
101 	}
102 
103 	if (!log || level < 5) {
104 		return;
105 	}
106 
107 	rc = ndmp_pp_header (nmb->protocol_version, &nmb->header, buf);
108 #if 0
109 	ndmlogf (log, tag, level5, "%s %s", buf, whence);
110 #else
111 	{
112 		char combo[3];
113 
114 		if (*whence == 'R') {
115 			combo[0] = '>';
116 			combo[1] = buf[0];
117 		} else {
118 			combo[0] = buf[0];
119 			combo[1] = '>';
120 		}
121 		combo[2] = 0;
122 
123 		ndmlogf (log, tag, level5, "%s %s", combo, buf+2);
124 	}
125 #endif
126 
127 	if (level < 6) {
128 		return;
129 	}
130 	if (rc <= 0) {		/* no body */
131 		return;
132 	}
133 
134 	if (nmb->header.message_type == NDMP0_MESSAGE_REQUEST) {
135 		ndmpp = ndmp_pp_request;
136 	} else if (nmb->header.message_type == NDMP0_MESSAGE_REPLY) {
137 		ndmpp = ndmp_pp_reply;
138 	} else {
139 		return;		/* should not happen */
140 	}
141 
142 	nl = 1;
143 	for (i = 0; i < nl; i++) {
144 		nl = (*ndmpp)(nmb->protocol_version,
145 			nmb->header.message, &nmb->body, i, buf);
146 		if (nl == 0)
147 			break;		/* no printable body (void) */
148 
149 		ndmlogf (log, tag, level6, "   %s", buf);
150 	}
151 }
152 
153 unsigned
ndmnmb_get_reply_error_raw(struct ndmp_msg_buf * nmb)154 ndmnmb_get_reply_error_raw (struct ndmp_msg_buf *nmb)
155 {
156 	unsigned	protocol_version = nmb->protocol_version;
157 	unsigned	msg = nmb->header.message;
158 	unsigned	raw_error;
159 
160 	if (NDMNMB_IS_UNFORTUNATE_REPLY_TYPE(protocol_version, msg)) {
161 		raw_error = nmb->body.unf3_error.error;
162 	} else {
163 		raw_error = nmb->body.error;
164 	}
165 
166 	return raw_error;
167 }
168 
169 ndmp9_error
ndmnmb_get_reply_error(struct ndmp_msg_buf * nmb)170 ndmnmb_get_reply_error (struct ndmp_msg_buf *nmb)
171 {
172 	unsigned	protocol_version = nmb->protocol_version;
173 	unsigned	raw_error = ndmnmb_get_reply_error_raw (nmb);
174 	ndmp9_error	error;
175 
176 	switch (protocol_version) {
177 	default:
178 		/* best effort */
179 		error = (ndmp9_error) raw_error;
180 		break;
181 
182 #ifndef NDMOS_OPTION_NO_NDMP2
183 	case NDMP2VER:
184 		{
185 			ndmp2_error	error2 = raw_error;
186 
187 			ndmp_2to9_error (&error2, &error);
188 		}
189 		break;
190 #endif /* !NDMOS_OPTION_NO_NDMP2 */
191 
192 #ifndef NDMOS_OPTION_NO_NDMP3
193 	case NDMP3VER:
194 		{
195 			ndmp3_error	error3 = raw_error;
196 
197 			ndmp_3to9_error (&error3, &error);
198 		}
199 		break;
200 #endif /* !NDMOS_OPTION_NO_NDMP3 */
201 
202 #ifndef NDMOS_OPTION_NO_NDMP4
203 	case NDMP4VER:
204 		{
205 			ndmp4_error	error4 = raw_error;
206 
207 			ndmp_4to9_error (&error4, &error);
208 		}
209 		break;
210 #endif /* !NDMOS_OPTION_NO_NDMP4 */
211 	}
212 
213 	return error;
214 }
215 
216 int
ndmnmb_set_reply_error_raw(struct ndmp_msg_buf * nmb,unsigned raw_error)217 ndmnmb_set_reply_error_raw (struct ndmp_msg_buf *nmb, unsigned raw_error)
218 {
219 	unsigned	protocol_version = nmb->protocol_version;
220 	unsigned	msg = nmb->header.message;
221 
222 	if (NDMNMB_IS_UNFORTUNATE_REPLY_TYPE(protocol_version, msg)) {
223 		nmb->body.unf3_error.error = raw_error;
224 	} else {
225 		nmb->body.error = raw_error;
226 	}
227 
228 	return 0;
229 }
230 
231 int
ndmnmb_set_reply_error(struct ndmp_msg_buf * nmb,ndmp9_error error)232 ndmnmb_set_reply_error (struct ndmp_msg_buf *nmb, ndmp9_error error)
233 {
234 	unsigned	protocol_version = nmb->protocol_version;
235 	unsigned	raw_error;
236 
237 	switch (protocol_version) {
238 	default:
239 		/* best effort */
240 		raw_error = (unsigned) error;
241 		break;
242 
243 #ifndef NDMOS_OPTION_NO_NDMP2
244 	case NDMP2VER:
245 		{
246 			ndmp2_error	error2;
247 
248 			ndmp_9to2_error (&error, &error2);
249 			raw_error = (unsigned) error2;
250 		}
251 		break;
252 #endif /* !NDMOS_OPTION_NO_NDMP2 */
253 
254 #ifndef NDMOS_OPTION_NO_NDMP3
255 	case NDMP3VER:
256 		{
257 			ndmp3_error	error3;
258 
259 			ndmp_9to3_error (&error, &error3);
260 			raw_error = (unsigned) error3;
261 		}
262 		break;
263 #endif /* !NDMOS_OPTION_NO_NDMP3 */
264 
265 #ifndef NDMOS_OPTION_NO_NDMP4
266 	case NDMP4VER:
267 		{
268 			ndmp4_error	error4;
269 
270 			ndmp_9to4_error (&error, &error4);
271 			raw_error = (unsigned) error4;
272 		}
273 		break;
274 #endif /* !NDMOS_OPTION_NO_NDMP4 */
275 	}
276 
277 	return ndmnmb_set_reply_error_raw (nmb, raw_error);
278 }
279