2 * Copyright (c) 1998,2001
3 * Traakan, Inc., Los Altos, CA
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice unmodified, this list of conditions, and the following
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.
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
34 * This contains code fragments common between the
35 * O/S (Operating System) portions of NDMJOBLIB.
37 * This file is #include'd by the O/S specific ndmos_*.c
38 * file, and fragments are selected by #ifdef's.
40 * There are four major portions:
41 * 1) Misc support routines: password check, local info, etc
42 * 2) Non-blocking I/O support routines
43 * 3) Tape interfacs ndmos_tape_xxx()
44 * 4) OS Specific NDMP request dispatcher which intercepts
45 * requests implemented here, such as SCSI operations
46 * and system configuration queries.
54 ****************************************************************
57 #ifdef NDMOS_COMMON_SYNC_CONFIG_INFO
59 * Get local info. Supports NDMPx_CONFIG_GET_HOST_INFO,
60 * NDMP3_CONFIG_GET_SERVER_INFO, and NDMPx_CONFIG_GET_SCSI_INFO.
63 ndmos_sync_config_info (struct ndm_session *sess)
65 static struct utsname unam;
66 static char osbuf[100];
67 static char idbuf[30];
68 static char revbuf[50];
71 if (sess->config_info.hostname) {
76 obuf[0] = (char)(NDMOS_ID >> 24);
77 obuf[1] = (char)(NDMOS_ID >> 16);
78 obuf[2] = (char)(NDMOS_ID >> 8);
79 obuf[3] = (char)(NDMOS_ID >> 0);
83 sprintf (idbuf, "%lu", gethostid());
85 * give CONTROL via NDMPv2 a chance to recognize this
86 * implementation (no ndmp2_config_get_server).
88 sprintf (osbuf, "%s (running %s from %s)",
90 NDMOS_CONST_PRODUCT_NAME,
91 NDMOS_CONST_VENDOR_NAME);
93 sess->config_info.hostname = unam.nodename;
94 sess->config_info.os_type = osbuf;
95 sess->config_info.os_vers = unam.release;
96 sess->config_info.hostid = idbuf;
98 sess->config_info.vendor_name = NDMOS_CONST_VENDOR_NAME;
99 sess->config_info.product_name = NDMOS_CONST_PRODUCT_NAME;
101 sprintf (revbuf, "%s LIB:%d.%d/%s OS:%s (%s)",
102 NDMOS_CONST_PRODUCT_REVISION,
103 NDMJOBLIB_VERSION, NDMJOBLIB_RELEASE,
104 NDMOS_CONST_NDMJOBLIB_REVISION,
105 NDMOS_CONST_NDMOS_REVISION,
108 sess->config_info.revision_number = revbuf;
110 /* best effort; note that this loads scsi and tape config */
111 ndmcfg_load (sess->param.config_file_name, &sess->config_info);
113 #endif /* NDMOS_COMMON_SYNC_CONFIG_INFO */
119 * AUTHENTICATION SUPPORT
120 ****************************************************************
123 #ifdef NDMOS_COMMON_OK_NAME_PASSWORD
125 * Determine whether the clear-text account name and password
126 * are valid. Supports NDMPx_CONNECT_CLIENT_AUTH requests.
129 ndmos_ok_name_password (struct ndm_session *sess, char *name, char *pass)
131 if (strcmp (name, "ndmp") != 0)
134 if (strcmp (pass, "ndmp") != 0)
139 #endif /* NDMOS_COMMON_OK_NAME_PASSWORD */
144 #ifdef NDMOS_COMMON_MD5
146 * MD5 authentication support
152 ndmos_get_md5_challenge (struct ndm_session *sess)
154 ndmmd5_generate_challenge (sess->md5_challenge);
155 sess->md5_challenge_valid = 1;
160 ndmos_ok_name_md5_digest (struct ndm_session *sess,
161 char *name, char digest[16])
163 if (strcmp (name, "ndmp") != 0)
166 if (!ndmmd5_ok_digest (sess->md5_challenge, "ndmp", digest))
171 #endif /* NDMOS_COMMON_MD5 */
175 #ifdef NDMOS_COMMON_NONBLOCKING_IO_SUPPORT
177 * NON-BLOCKING I/O SUPPORT
178 ****************************************************************
179 * As support non-blocking I/O for NDMCHAN, condition different
180 * types of file descriptors to not block.
184 ndmos_condition_listen_socket (struct ndm_session *sess, int sock)
189 setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, (void*)&flag, sizeof flag);
193 ndmos_condition_control_socket (struct ndm_session *sess, int sock)
199 ndmos_condition_image_stream_socket (struct ndm_session *sess, int sock)
201 fcntl (sock, F_SETFL, O_NONBLOCK);
202 signal (SIGPIPE, SIG_IGN);
206 ndmos_condition_pipe_fd (struct ndm_session *sess, int fd)
208 fcntl (fd, F_SETFL, O_NONBLOCK);
209 signal (SIGPIPE, SIG_IGN);
211 #endif /* NDMOS_COMMON_NONBLOCKING_IO_SUPPORT */
216 #ifdef NDMOS_COMMON_TAPE_INTERFACE
217 #ifndef NDMOS_OPTION_NO_TAPE_AGENT
218 #ifndef NDMOS_OPTION_TAPE_SIMULATOR
221 ****************************************************************
222 * These interface to the O/S specific tape drivers and subsystem.
223 * They must result in functionality equivalent to the reference
224 * tape simulator. The NDMP TAPE model is demanding, and it is
225 * often necessary to workaround the native device driver(s)
226 * to achieve NDMP TAPE model conformance.
228 * It's easy to test this ndmos_tape_xxx() implementation
229 * using the ndmjob(1) command in test-tape conformance mode.
230 * The tape simulator passes this test. To test this implementation,
231 * rebuild ndmjob, then use this command:
233 * ndmjob -o test-tape -T. -f /dev/whatever
235 * These ndmos_tape_xxx() interfaces must maintain the tape state
236 * (sess->tape_agent.tape_state). In particular, the position
237 * information (file_num and blockno) must be accurate at all
238 * times. A typical workaround is to maintain these here rather
239 * than relying on the native device drivers. Another workaround
240 * is to implement NDMP MTIO operations using repeated native MTIO
241 * operations with count=1, then interpret the results and errors
242 * to maintain accurate position and residual information.
244 * Workarounds in this implementation (please keep this updated):
249 ndmos_tape_initialize (struct ndm_session *sess)
255 ndmos_tape_sync_state (struct ndm_session *sess)
257 the_tape_state.error = NDMP9_DEV_NOT_OPEN_ERR;
261 ndmos_tape_open (struct ndm_session *sess, char *name, int will_write)
263 return NDMP9_NOT_SUPPORTED_ERR;
267 ndmos_tape_close (struct ndm_session *sess)
269 return NDMP9_NOT_SUPPORTED_ERR;
273 ndmos_tape_write (struct ndm_session *sess, char *data,
274 unsigned long count, unsigned long * done_count)
276 return NDMP9_NOT_SUPPORTED_ERR;
280 ndmos_tape_read (struct ndm_session *sess, char *data,
281 unsigned long count, unsigned long * done_count)
283 return NDMP9_NOT_SUPPORTED_ERR;
287 ndmos_tape_mtio (struct ndm_session *sess, ndmp9_tape_mtio_op op,
288 unsigned long count, unsigned long * done_count)
290 return NDMP9_NOT_SUPPORTED_ERR;
294 ndmos_tape_execute_cdb (struct ndm_session *sess,
295 ndmp9_execute_cdb_request *request,
296 ndmp9_execute_cdb_reply *reply)
298 return NDMP9_NOT_SUPPORTED_ERR;
301 #endif /* !NDMOS_OPTION_TAPE_SIMULATOR */
302 #else /* !NDMOS_OPTION_NO_TAPE_AGENT */
303 /* tape interfaces implemented in ndma_tape_simulator.c */
304 #endif /* !NDMOS_OPTION_NO_TAPE_AGENT */
305 #endif /* NDMOS_COMMON_TAPE_INTERFACE */
308 #ifdef NDMOS_COMMON_ROBOT_INTERFACE
309 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT
310 #ifndef NDMOS_OPTION_ROBOT_SIMULATOR
312 /* ndmos_robot_* functions here */
314 #endif /* !NDMOS_OPTION_ROBOT_SIMULATOR */
315 #else /* !NDMOS_OPTION_NO_ROBOT_AGENT */
316 /* robot interfaces implemented in ndma_robot_simulator.c */
317 #endif /* !NDMOS_OPTION_NO_ROBOT_AGENT */
318 #endif /* NDMOS_COMMON_ROBOT_INTERFACE */
321 #ifdef NDMOS_COMMON_SCSI_INTERFACE
322 #ifndef NDMOS_OPTION_NO_ROBOT_AGENT /* Surrounds all SCSI intfs */
323 #ifndef NDMOS_OPTION_ROBOT_SIMULATOR
326 ****************************************************************
330 ndmos_scsi_initialize (struct ndm_session *sess)
336 ndmos_scsi_sync_state (struct ndm_session *sess)
338 sess->robot_acb.scsi_state.error = NDMP9_DEV_NOT_OPEN_ERR;
342 ndmos_scsi_open (struct ndm_session *sess, char *name)
344 return NDMP9_NOT_SUPPORTED_ERR;
348 ndmos_scsi_close (struct ndm_session *sess)
350 return NDMP9_NOT_SUPPORTED_ERR;
355 ndmos_scsi_set_target (struct ndm_session *sess)
357 return NDMP9_NOT_SUPPORTED_ERR;
362 ndmos_scsi_reset_device (struct ndm_session *sess)
364 return NDMP9_NOT_SUPPORTED_ERR;
369 ndmos_scsi_reset_bus (struct ndm_session *sess)
371 return NDMP9_NOT_SUPPORTED_ERR;
375 ndmos_scsi_execute_cdb (struct ndm_session *sess,
376 ndmp9_execute_cdb_request *request,
377 ndmp9_execute_cdb_reply *reply)
379 return NDMP9_NOT_SUPPORTED_ERR;
382 #endif /* NDMOS_OPTION_ROBOT_SIMULATOR */
383 #endif /* NDMOS_OPTION_NO_ROBOT_AGENT Surrounds all SCSI intfs */
384 #endif /* NDMOS_COMMON_SCSI_INTERFACE */
389 #ifdef NDMOS_COMMON_DISPATCH_REQUEST
391 * ndmos_dispatch_request() -- O/S Specific Agent Dispatch Request (ADR)
392 ****************************************************************
393 * Some NDMP requests can only be handled as O/S specific portions,
394 * and are implemented here.
396 * The more generic NDMP requests may be re-implemented here rather
397 * than modifying the main body of code. Extensions to the NDMP protocol
398 * may also be implemented here. Neither is ever a good idea beyond
399 * experimentation. The structures in ndmagents.h provide for O/S
400 * specific extensions. Such extensions are #define'd in the ndmos_xxx.h.
402 * The return value from ndmos_dispatch_request() tells the main
403 * dispatcher, ndma_dispatch_request(), whether or not the request
404 * was intercepted. ndmos_dispatch_request() is called after basic
405 * reply setup is done (message headers and buffers), but before
406 * the request is interpretted.
409 #ifndef I_HAVE_DISPATCH_REQUEST
412 * If we're not intercepting, keep it simple
415 ndmos_dispatch_request (struct ndm_session *sess,
416 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
418 return -1; /* not intercepted */
421 #else /* !I_HAVE_DISPATCH_REQUEST */
424 * The following fragment is here for reference.
425 * If the O/S module intercepts requests, copy
426 * all this into the module source file and
427 * #undef NDMOS_COMMON_DISPATCH_REQUEST.
430 extern struct ndm_dispatch_version_table ndmos_dispatch_version_table[];
433 ndmos_dispatch_request (struct ndm_session *sess,
434 struct ndmp_xa_buf *xa, struct ndmconn *ref_conn)
436 struct ndm_dispatch_request_table *drt;
437 unsigned protocol_version = ref_conn->protocol_version;
438 unsigned msg = xa->request.header.message;
441 drt = ndma_drt_lookup (ndmos_dispatch_version_table,
442 protocol_version, msg);
445 return -1; /* not intercepted */
449 * Replicate the ndma_dispatch_request() permission checks
452 && !(drt->flags & NDM_DRT_FLAG_OK_NOT_CONNECTED)) {
453 xa->reply.header.error = NDMP0_PERMISSION_ERR;
457 if (!sess->conn_authorized
458 && !(drt->flags & NDM_DRT_FLAG_OK_NOT_AUTHORIZED)) {
459 xa->reply.header.error = NDMP9_NOT_AUTHORIZED_ERR;
463 rc = (*drt->dispatch_request)(sess, xa, ref_conn);
466 xa->reply.header.error = NDMP0_NOT_SUPPORTED_ERR;
476 * Dispatch Version Table and Dispatch Request Tables (DVT/DRT)
477 ****************************************************************
480 struct ndm_dispatch_request_table ndmos_dispatch_request_table_v0[] = {
484 #ifndef NDMOS_OPTION_NO_NDMP2
485 struct ndm_dispatch_request_table ndmos_dispatch_request_table_v2[] = {
488 #endif /* !NDMOS_OPTION_NO_NDMP2 */
490 #ifndef NDMOS_OPTION_NO_NDMP3
491 struct ndm_dispatch_request_table ndmos_dispatch_request_table_v3[] = {
494 #endif /* !NDMOS_OPTION_NO_NDMP3 */
496 #ifndef NDMOS_OPTION_NO_NDMP4
497 struct ndm_dispatch_request_table ndmos_dispatch_request_table_v4[] = {
500 #endif /* !NDMOS_OPTION_NO_NDMP4 */
503 struct ndm_dispatch_version_table ndmos_dispatch_version_table[] = {
504 { 0, ndmos_dispatch_request_table_v0 },
505 #ifndef NDMOS_OPTION_NO_NDMP2
506 { NDMP2VER, ndmos_dispatch_request_table_v2 },
507 #endif /* !NDMOS_OPTION_NO_NDMP2 */
508 #ifndef NDMOS_OPTION_NO_NDMP3
509 { NDMP3VER, ndmos_dispatch_request_table_v3 },
510 #endif /* !NDMOS_OPTION_NO_NDMP2 */
511 #ifndef NDMOS_OPTION_NO_NDMP4
512 { NDMP4VER, ndmos_dispatch_request_table_v4 },
513 #endif /* !NDMOS_OPTION_NO_NDMP4 */
516 #endif /* !I_HAVE_DISPATCH_REQUEST */
517 #endif /* NDMOS_COMMON_DISPATCH_REQUEST */