1 /*
2  * Copyright (c) 1998,1999,2000,2002
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 #ifndef _NDMLIB_H_
39 #define _NDMLIB_H_
40 
41 #include "ndmos.h"
42 
43 #include "ndmprotocol.h"
44 #include "ndmp_msg_buf.h"
45 #include "ndmp_translate.h"
46 
47 /* Probably unnecessary, yet prudent. Compilers/debuggers sometimes goof. */
48 #ifndef NDM_FLAG_DECL
49 #define NDM_FLAG_DECL(XXX) unsigned XXX : 1;
50 #endif /* !NDM_FLAG_DECL */
51 
52 #ifdef  __cplusplus
53 extern "C" {
54 #endif
55 
56 /* boring forward reference stuff */
57 struct ndmagent;
58 
59 
60 
61 
62 /*
63  * NDMLOG
64  ****************************************************************
65  *
66  * ndmlog is a simple abstraction for log messages.
67  * Each log entry has:
68  *   - a tag, which is a short string indicating origin or purpose
69  *   - a level between 0-9, the higher the value the greater the detail
70  *   - a message
71  * The application will typically direct log messages to a file.
72  * Yet, logging directly to a FILE tends to be restrictive. Hence
73  * this abstraction.
74  *
75  * The time stamp is relative to the start time, and has millisecond
76  * granularity.
77  */
78 
79 struct ndmlog {
80 	void	(*deliver)(struct ndmlog *log, char *tag, int lev, char *msg);
81 	void *	ctx;
82 	struct ndm_fhdb_callbacks *nfc;
83 };
84 extern char *	ndmlog_time_stamp (void);
85 extern void	ndmlogf (struct ndmlog *log, char *tag,
86 					int level, char *fmt, ...);
87 extern void	ndmlogfv (struct ndmlog *log, char *tag,
88 					int level, char *fmt, va_list ap);
89 
90 
91 
92 
93 /*
94  * NDMNMB -- NDMP Message Buffer
95  ****************************************************************
96  *
97  * The ndmnmb routines are trivial aids for handling
98  * NMB (NDMP Messsage Buffer). ndmp_msg_buf is defined in
99  * ndmp_msg_buf.h, and pretty much amounts to a huge
100  * union of all NDMP request and reply types.
101  */
102 
103 extern xdrproc_t	ndmnmb_find_xdrproc (struct ndmp_msg_buf *nmb);
104 extern void		ndmnmb_free (struct ndmp_msg_buf *nmb);
105 extern void		ndmnmb_snoop (struct ndmlog *log, char *tag, int level,
106 				struct ndmp_msg_buf *nmb, char *whence);
107 extern unsigned		ndmnmb_get_reply_error_raw (struct ndmp_msg_buf *nmb);
108 extern ndmp9_error	ndmnmb_get_reply_error (struct ndmp_msg_buf *nmb);
109 extern int		ndmnmb_set_reply_error_raw (struct ndmp_msg_buf *nmb,
110 				unsigned raw_error);
111 extern int		ndmnmb_set_reply_error (struct ndmp_msg_buf *nmb,
112 				ndmp9_error error);
113 
114 
115 
116 
117 
118 
119 
120 /*
121  * NDMCHAN -- Async I/O channel
122  ****************************************************************
123  *
124  * ndmchan is a wrapper around I/O channels, and is used
125  * to juggle (manage) multiple I/O activities at one time.
126  * The data buffer is used linearly. beg_ix and end_ix
127  * bracket the valid data. When the end of the buffer is reached,
128  * the remaining valid data is moved to the begining.
129  */
130 struct ndmchan {
131 	char *		name;		/* short name, helps debugging */
132 
133 	char		mode;		/* NDMCHAN_MODE_... (see below) */
134 
135 	NDM_FLAG_DECL(check)		/* Want select()/poll() to check */
136 	NDM_FLAG_DECL(ready)		/* select()/poll() indicates ready */
137 	NDM_FLAG_DECL(eof)		/* eof pending upon n_ready()==0 */
138 	NDM_FLAG_DECL(error)		/* error (channel shutdown) */
139 
140 	int		fd;		/* der eff dee */
141 	int		saved_errno;	/* errno captured if ->error occurs */
142 
143 	unsigned	beg_ix;		/* relative to ->data */
144 	unsigned	end_ix;		/* relative to ->data */
145 	char *		data;		/* data buffer (READ/WRITE/RESIDENT) */
146 	unsigned	data_size;	/* size of data buffer */
147 };
148 #define NDMCHAN_MODE_IDLE	0	/* not doing anything */
149 #define NDMCHAN_MODE_RESIDENT	1	/* resident, within this process */
150 #define NDMCHAN_MODE_READ	2	/* read from ->fd into ->data */
151 #define NDMCHAN_MODE_WRITE	3	/* write to ->fd from ->data */
152 #define NDMCHAN_MODE_READCHK	4	/* check ->fd readable, no ->data */
153 #define NDMCHAN_MODE_LISTEN	5	/* ->fd listen()ing */
154 #define NDMCHAN_MODE_PENDING	6	/* ->fd and ->data ready */
155 #define NDMCHAN_MODE_CLOSED	7	/* ->fd closed */
156 
157 enum ndmchan_read_interpretation {
158 	NDMCHAN_RI_EMPTY = 10,	/* no data, might be more coming */
159 	NDMCHAN_RI_READY,	/* data ready */
160 	NDMCHAN_RI_READY_FULL,	/* data ready, no more until consumed */
161 	NDMCHAN_RI_DRAIN_EOF,	/* data ready, DONE_EOF after consumed */
162 	NDMCHAN_RI_DRAIN_ERROR,	/* data ready, DONE_ERROR after consumed */
163 	NDMCHAN_RI_DONE_EOF,	/* no data, no more coming, normal EOF */
164 	NDMCHAN_RI_DONE_ERROR,	/* no data, no more coming, something wrong */
165 	NDMCHAN_RI_FAULT 	/* crazy request */
166 };
167 
168 enum ndmchan_write_interpretation {
169 	NDMCHAN_WI_FULL = 30,	/* no buffer, no more until some sent */
170 	NDMCHAN_WI_AVAIL,	/* buffer ready, sending in progress */
171 	NDMCHAN_WI_AVAIL_EMPTY,	/* buffer ready, done sending */
172 	NDMCHAN_WI_DRAIN_EOF,	/* no more buffer, DONE_EOF after sent */
173 	NDMCHAN_WI_DRAIN_ERROR,	/* no more buffer, DONE_ERROR after sent */
174 	NDMCHAN_WI_DONE_EOF,	/* no more buffer, done sending, normal EOF */
175 	NDMCHAN_WI_DONE_ERROR,	/* no more buffer, done sending, went wrong */
176 	NDMCHAN_WI_FAULT 	/* crazy request */
177 };
178 
179 extern void	ndmchan_initialize (struct ndmchan *ch, char *name);
180 extern int	ndmchan_setbuf (struct ndmchan *ch, char *data,
181 			unsigned data_size);
182 extern int	ndmchan_start_mode (struct ndmchan *ch, int fd, int chan_mode);
183 extern int	ndmchan_start_read (struct ndmchan *ch, int fd);
184 extern int	ndmchan_start_write (struct ndmchan *ch, int fd);
185 extern int	ndmchan_start_readchk (struct ndmchan *ch, int fd);
186 extern int	ndmchan_start_listen (struct ndmchan *ch, int fd);
187 extern int	ndmchan_start_resident (struct ndmchan *ch);
188 extern int	ndmchan_start_pending (struct ndmchan *ch, int fd);
189 extern int	ndmchan_pending_to_mode (struct ndmchan *ch, int chan_mode);
190 extern int	ndmchan_pending_to_read (struct ndmchan *ch);
191 extern int	ndmchan_pending_to_write (struct ndmchan *ch);
192 extern void	ndmchan_set_eof (struct ndmchan *ch);
193 extern void	ndmchan_close_set_errno (struct ndmchan *ch, int err_no);
194 extern void	ndmchan_close (struct ndmchan *ch);
195 extern void	ndmchan_abort (struct ndmchan *ch);
196 extern void	ndmchan_close_as_is (struct ndmchan *ch);
197 extern void	ndmchan_cleanup (struct ndmchan *ch);
198 extern int	ndmchan_quantum (struct ndmchan *chtab[],
199 			unsigned n_chtab, int milli_timo);
200 extern int	ndmchan_pre_poll (struct ndmchan *chtab[], unsigned n_chtab);
201 extern int	ndmchan_post_poll (struct ndmchan *chtab[], unsigned n_chtab);
202 extern void	ndmchan_compress (struct ndmchan *ch);
203 extern int	ndmchan_n_avail (struct ndmchan *ch);
204 extern int	ndmchan_n_avail_record (struct ndmchan *ch, uint32_t size);
205 extern int	ndmchan_n_avail_total (struct ndmchan *ch);
206 extern int	ndmchan_n_ready (struct ndmchan *ch);
207 extern enum ndmchan_read_interpretation
208 		ndmchan_read_interpret (struct ndmchan *ch, char **data_p,
209 			unsigned *n_ready_p);
210 extern enum ndmchan_write_interpretation
211 		ndmchan_write_interpret (struct ndmchan *ch, char **data_p,
212 			unsigned *n_avail_p);
213 
214 extern void	ndmchan_pp (struct ndmchan *ch, char *buf);
215 
216 extern int	ndmos_chan_poll (struct ndmchan *chtab[],
217 			unsigned n_chtab, int milli_timo);
218 
219 
220 
221 
222 /*
223  * NDMCONN -- Bidirectional control connections
224  ****************************************************************
225  */
226 
227 #define NDMCONN_TYPE_NONE		0
228 #define NDMCONN_TYPE_RESIDENT		1
229 #define NDMCONN_TYPE_REMOTE		2
230 
231 
232 #define NDMCONN_CALL_STATUS_HDR_ERROR	(-2)
233 #define NDMCONN_CALL_STATUS_BOTCH	(-1)
234 #define NDMCONN_CALL_STATUS_OK		0
235 #define NDMCONN_CALL_STATUS_REPLY_ERROR	1
236 #define NDMCONN_CALL_STATUS_REPLY_LATE	2
237 
238 
239 struct ndmconn {
240 	struct sockaddr	sa;
241 
242 	struct ndmchan	chan;
243 
244 	char		conn_type;
245 	char		protocol_version;
246 	char		was_allocated;
247 
248 	void *		context;
249 
250 	XDR		xdrs;
251 	unsigned char	frag_hdr_buf[4];	/* see ndmconn_readit() */
252 	unsigned	fhb_off;
253 	uint32_t	frag_resid;
254 
255 	uint32_t	next_sequence;
256 
257 	void		(*unexpected)(struct ndmconn *conn,
258 					struct ndmp_msg_buf *nmb);
259 
260 	int		snoop_level;
261 	struct ndmlog *	snoop_log;
262 
263 	char *		last_err_msg;
264 
265 	int		(*call) (struct ndmconn *conn, struct ndmp_xa_buf *xa);
266 
267 	struct ndmp_xa_buf call_xa_buf;
268 
269 	int		last_message;
270 	int		last_call_status;
271 	ndmp9_error	last_header_error;
272 	ndmp9_error	last_reply_error;
273 
274 	long   		sent_time;
275 	long		received_time;
276 	long            time_limit;
277 };
278 
279 extern struct ndmconn *	ndmconn_initialize (struct ndmconn *aconn, char *name);
280 extern void		ndmconn_destruct (struct ndmconn *conn);
281 extern int		ndmconn_connect_agent (struct ndmconn *conn,
282 				struct ndmagent *agent);
283 extern int		ndmconn_connect_host_port (struct ndmconn *conn,
284 				char * hostname, int port,
285 				unsigned want_protocol_version);
286 extern int		ndmconn_connect_sockaddr_in (struct ndmconn *conn,
287 				struct sockaddr_in *sin,
288 				unsigned want_protocol_version);
289 extern int		ndmconn_try_open (struct ndmconn *conn,
290 				unsigned protocol_version);
291 extern int		ndmconn_accept (struct ndmconn *conn, int sock);
292 extern int		ndmconn_abort (struct ndmconn *conn);
293 extern int		ndmconn_close (struct ndmconn *conn);
294 extern int		ndmconn_fileno (struct ndmconn *conn);
295 extern int		ndmconn_auth_agent (struct ndmconn *conn,
296 				struct ndmagent *agent);
297 extern int		ndmconn_auth_none (struct ndmconn *conn);
298 extern int		ndmconn_auth_text (struct ndmconn *conn,
299 				char *id, char *pw);
300 extern int		ndmconn_auth_md5 (struct ndmconn *conn,
301 				char *id, char *pw);
302 extern int		ndmconn_call (struct ndmconn *conn,
303 				struct ndmp_xa_buf *xa);
304 extern int		ndmconn_exchange_nmb (struct ndmconn *conn,
305 				struct ndmp_msg_buf *request_nmb,
306 				struct ndmp_msg_buf *reply_nmb);
307 extern int		ndmconn_send_nmb (struct ndmconn *conn,
308 				struct ndmp_msg_buf *nmb);
309 extern int		ndmconn_recv_nmb (struct ndmconn *conn,
310 				struct ndmp_msg_buf *nmb);
311 extern void		ndmconn_free_nmb (struct ndmconn *conn,
312 				struct ndmp_msg_buf *nmb);
313 extern int		ndmconn_xdr_nmb (struct ndmconn *conn,
314 				struct ndmp_msg_buf *nmb,
315 				enum xdr_op x_op);
316 extern int		ndmconn_readit (void *a_conn, char *buf, int len);
317 extern int		ndmconn_writeit (void *a_conn, char *buf, int len);
318 extern int		ndmconn_sys_read (struct ndmconn *conn,
319 				char *buf, unsigned len);
320 extern int		ndmconn_sys_write (struct ndmconn *conn,
321 				char *buf, unsigned len);
322 extern void		ndmconn_unexpected (struct ndmconn *conn,
323 				struct ndmp_msg_buf *nmb);
324 extern int		ndmconn_set_snoop (struct ndmconn *conn,
325 				struct ndmlog *log, int level);
326 extern void		ndmconn_clear_snoop (struct ndmconn *conn);
327 extern void		ndmconn_snoop_nmb (struct ndmconn *conn,
328 				struct ndmp_msg_buf *nmb,
329 				char *whence);
330 extern void		ndmconn_snoop (struct ndmconn *conn,
331 				int level, char *fmt, ...);
332 extern void		ndmconn_hex_dump (struct ndmconn *conn,
333 				char *buf, unsigned len);
334 extern int		ndmconn_set_err_msg (struct ndmconn *conn,
335 				char *err_msg);
336 extern char *		ndmconn_get_err_msg (struct ndmconn *conn);
337 
338 
339 
340 
341 /*
342  * NDMC_WITH() AND FRIENDS
343  ****************************************************************
344  *
345  * Macro NDMC_WITH() and friends. These are patterned after
346  * the Pascal "with" construct. These macros take care of
347  * the tedious, error prone, mind-numbing, and distracting
348  * code required to perform NDMP RPCs. These greatly
349  * facilitate the clarity of the main body of code.
350  * Code sequences look something like:
351  *
352  *	NDMC_WITH(ndmp_config_get_butype_attr)
353  *		request->xxx = yyy;
354  *		...
355  *		rc = NDMC_CALL(ndmconn);
356  *		if (rc == 0) {
357  *			reply->xxx ...
358  *			....
359  *		}
360  *		NDMC_FREE_REPLY()
361  *	NDMC_ENDWITH
362  *
363  * The NDMC macros are for client-side (caller) sequences.
364  * The NDMS macros are for server-side (callee) sequences.
365  *
366  * These macros are very dependent on ndmp_msg_buf.h and ndmp_ammend.h
367  *
368  * Implementation note: initialization of *request and *reply
369  * are separate from their declarations. They used to be
370  * initialized declarators. The separation made gcc -Wall happy.
371  */
372 
373 #define NDMC_WITH(TYPE,VERS) \
374   { \
375 	struct ndmp_xa_buf *	xa = &conn->call_xa_buf; \
376 	TYPE##_request * request; \
377 	TYPE##_reply   * reply; \
378 	request = &xa->request.body.TYPE##_request_body; \
379 	reply = &xa->reply.body.TYPE##_reply_body; \
380 	NDMOS_MACRO_ZEROFILL (xa); \
381 	xa->request.protocol_version = VERS; \
382 	xa->request.header.message = (ndmp0_message) MT_##TYPE; \
383      {
384 
385 
386 #define NDMC_WITH_VOID_REQUEST(TYPE,VERS) \
387   { \
388 	struct ndmp_xa_buf *	xa = &conn->call_xa_buf; \
389 	TYPE##_reply   * reply; \
390 	reply = &xa->reply.body.TYPE##_reply_body; \
391 	NDMOS_MACRO_ZEROFILL (xa); \
392 	xa->request.protocol_version = VERS; \
393 	xa->request.header.message = (ndmp0_message) MT_##TYPE; \
394      {
395 
396 #define NDMC_WITH_NO_REPLY(TYPE,VERS) \
397   { \
398 	struct ndmp_xa_buf *	xa = &conn->call_xa_buf; \
399 	TYPE##_request * request; \
400 	request = &xa->request.body.TYPE##_request_body; \
401 	NDMOS_MACRO_ZEROFILL (xa); \
402 	xa->request.protocol_version = VERS; \
403 	xa->request.header.message = (ndmp0_message) MT_##TYPE; \
404      {
405 
406 #ifndef NDMOS_OPTION_NO_NDMP4
407 #define NDMC_WITH_POST(TYPE,VERS) \
408   { \
409 	struct ndmp_xa_buf *	xa = &conn->call_xa_buf; \
410 	TYPE##_post * request; \
411 	request = &xa->request.body.TYPE##_post_body; \
412 	NDMOS_MACRO_ZEROFILL (xa); \
413 	xa->request.protocol_version = VERS; \
414 	xa->request.header.message = (ndmp0_message) MT_##TYPE; \
415      {
416 #endif /* !NDMOS_OPTION_NO_NDMP4 */
417 
418 
419 #define NDMC_ENDWITH \
420   } }
421 
422 #define NDMC_CALL(CONN) (*(CONN)->call)(CONN, xa);
423 #define NDMC_SEND(CONN) (*(CONN)->call)(CONN, xa);
424 #define NDMC_FREE_REPLY() ndmconn_free_nmb ((void*)0, &xa->reply)
425 
426 
427 
428 #define NDMS_WITH(TYPE) \
429   { \
430 	TYPE##_request * request; \
431 	TYPE##_reply   * reply; \
432 	request = &xa->request.body.TYPE##_request_body; \
433 	reply = &xa->reply.body.TYPE##_reply_body; \
434      {
435 
436 #define NDMS_WITH_VOID_REQUEST(TYPE) \
437   { \
438 	TYPE##_reply   * reply; \
439 	reply = &xa->reply.body.TYPE##_reply_body; \
440      {
441 
442 #define NDMS_WITH_NO_REPLY(TYPE) \
443   { \
444 	TYPE##_request * request; \
445 	request = &xa->request.body.TYPE##_request_body; \
446      {
447 
448 #ifndef NDMOS_OPTION_NO_NDMP4
449 #define NDMS_WITH_POST(TYPE) \
450   { \
451 	TYPE##_post * request; \
452 	request = &xa->request.body.TYPE##_post_body; \
453      {
454 #endif /* !NDMOS_OPTION_NO_NDMP4 */
455 
456 #define NDMS_ENDWITH \
457   } }
458 
459 
460 
461 
462 
463 
464 /*
465  * NDMAGENT -- "Address" of agent
466  ****************************************************************
467  *
468  * A struct ndmagent contains the information necessary
469  * to establish a connection with an NDMP agent (server).
470  * An agent can be remote (NDMCONN_TYPE_REMOTE) or resident
471  * (...._RESIDENT).
472  * TODO: MD5
473  */
474 #define NDMAGENT_HOST_MAX	63
475 #define NDMAGENT_ACCOUNT_MAX	15
476 #define NDMAGENT_PASSWORD_MAX	32
477 
478 struct ndmagent {
479 	char		conn_type;	/* NDMCONN_TYPE_... (see above) */
480 	char		protocol_version; /* 0->best, 2->v2 3->v3 */
481 	char		host[NDMAGENT_HOST_MAX+1];	/* name */
482 	int		port;		/* 0->default (NDMPPORT) */
483 	char		account[NDMAGENT_ACCOUNT_MAX+1]; /* clear text */
484 	char		password[NDMAGENT_PASSWORD_MAX+1]; /* clear text */
485 #if 0
486 	ndmp_auth_type	auth_type;
487 #else
488 	int		auth_type;
489 #endif
490 };
491 extern int	ndmagent_from_str (struct ndmagent *agent, char *str);
492 extern int	ndmhost_lookup (char *hostname, struct sockaddr_in *sin);
493 extern int	ndmagent_to_sockaddr_in (struct ndmagent *agent,
494 			struct sockaddr_in *sin);
495 
496 
497 
498 
499 /*
500  * NDMSCSI -- "Address" of SCSI device
501  ****************************************************************
502  */
503 
504 struct ndmscsi_target {
505 	char		dev_name[NDMOS_CONST_PATH_MAX];
506 	int		controller;
507 	int		sid;
508 	int		lun;
509 };
510 
511 #define NDMSCSI_MAX_SENSE_DATA	127
512 struct ndmscsi_request {
513 	unsigned char	completion_status;
514 	unsigned char	status_byte;
515 	unsigned char	data_dir;
516 	unsigned char	n_cmd;
517 
518 	unsigned char	cmd[12];
519 
520 	unsigned char *	data;
521 	unsigned	n_data_avail;
522 	unsigned	n_data_done;
523 	uint32_t	_pad;
524 
525 	unsigned char	n_sense_data;
526 	unsigned char	sense_data[NDMSCSI_MAX_SENSE_DATA];
527 };
528 
529 #define NDMSCSI_CS_GOOD	0
530 #define NDMSCSI_CS_FAIL	1
531 /* more? */
532 
533 #define NDMSCSI_DD_NONE	0
534 #define NDMSCSI_DD_IN	1	/* adapter->app */
535 #define NDMSCSI_DD_OUT	2	/* app->adapter */
536 
537 
538 extern int		ndmscsi_target_from_str (struct ndmscsi_target *targ,
539 				char *str);
540 extern int		ndmscsi_open (struct ndmconn *conn, char *dev_name);
541 extern int		ndmscsi_close (struct ndmconn *conn);
542 extern int		ndmscsi_get_state (struct ndmconn *conn,
543 				struct ndmscsi_target *targ);
544 extern int		ndmscsi_set_target (struct ndmconn *conn,
545 				struct ndmscsi_target *targ);
546 extern int		ndmscsi_use (struct ndmconn *conn,
547 				struct ndmscsi_target *targ);
548 extern int		ndmscsi_execute (struct ndmconn *conn,
549 				struct ndmscsi_request *req,
550 				struct ndmscsi_target *targ);
551 
552 
553 
554 
555 /*
556  * NDMMEDIA -- media (tape) labels, position, and status
557  ****************************************************************
558  */
559 
560 #define NDMMEDIA_LABEL_MAX	31
561 
562 struct ndmmedia {
563 	NDM_FLAG_DECL(valid_label)	/* ->label[] valid */
564 	NDM_FLAG_DECL(valid_filemark)	/* ->file_mark_skip valid */
565 	NDM_FLAG_DECL(valid_n_bytes)	/* ->n_bytes valid */
566 	NDM_FLAG_DECL(valid_slot)	/* ->slot_addr valid */
567 
568 	/* results flags */
569 	NDM_FLAG_DECL(media_used)	/* was used (loaded) */
570 	NDM_FLAG_DECL(media_written)	/* media was written */
571 	NDM_FLAG_DECL(media_eof)	/* reached EOF of tape file */
572 	NDM_FLAG_DECL(media_eom)	/* reached EOM (tape full) */
573 	NDM_FLAG_DECL(media_open_error)	/* open-time error (write-protect?) */
574 	NDM_FLAG_DECL(media_io_error)	/* media error */
575 
576 	NDM_FLAG_DECL(label_read)	/* ->label[] read fm media */
577 	NDM_FLAG_DECL(label_written)	/* ->label[] written to media */
578 	NDM_FLAG_DECL(label_io_error)	/* error label read/write */
579 	NDM_FLAG_DECL(label_mismatch)	/* label wasn't as expected */
580 
581 	NDM_FLAG_DECL(fmark_error)	/* error skipping file marks */
582 
583 	NDM_FLAG_DECL(nb_determined)	/* true ->n_bytes determined */
584 	NDM_FLAG_DECL(nb_aligned)	/* ->n_bytes aligned per rec_size */
585 
586 	NDM_FLAG_DECL(slot_empty)	/* slot empty per robot */
587 	NDM_FLAG_DECL(slot_bad)		/* ->slot_addr invalid */
588 	NDM_FLAG_DECL(slot_missing)	/* !->valid_slot */
589 
590 	/* all fields are specified/actual depending on context */
591 	char		label[NDMMEDIA_LABEL_MAX+1];
592 	unsigned	file_mark_offset;
593 	uint64_t	n_bytes;
594 	unsigned	slot_addr;
595 
596 	/* scratch pad */
597 	uint64_t	begin_offset, end_offset;
598 
599 	int		index;
600 	struct ndmmedia *next;
601 };
602 
603 extern int	ndmmedia_from_str (struct ndmmedia *me, char *str);
604 extern int	ndmmedia_to_str (struct ndmmedia *me, char *str);
605 extern int	ndmmedia_pp (struct ndmmedia *me, int lineno, char *buf);
606 extern int64_t	ndmmedia_strtoll (char *str, char **tailp, int defbase);
607 
608 
609 
610 
611 /*
612  * NDMFHH -- file history (FH) heap
613  ****************************************************************
614  *
615  * As DATA accumulates individual File History (FH) entries they
616  * are saved into a heap buffer. When the heap is full it is flushed
617  * from DATA to CONTROL using NDMP?_FH_ADD_.... requests/posts.
618  */
619 
620 struct ndmfhheap {
621 	int		fhtype;
622 	int		entry_size;
623 
624 	void *		table;
625 	void *		allo_entry;
626 
627 	void *		allo_item;
628 
629 	void *		heap_base;
630 	void *		heap_end;
631 	unsigned	heap_size;
632 
633 	void *		heap_top;
634 	void *		heap_bot;
635 };
636 
637 struct ndmfhh_generic_table {
638 	u_int	table_len;
639 	void *	table_val;
640 };
641 
642 #define NDMFHH_RET_OK		(0)
643 #define NDMFHH_RET_OVERFLOW	(-1)
644 #define NDMFHH_RET_TYPE_CHANGE	(-2)
645 #define NDMFHH_RET_NO_HEAP	(-3)
646 #define NDMFHH_RET_ENTRY_SIZE_MISMATCH (-4)
647 
648 
649 extern int	ndmfhh_initialize (struct ndmfhheap *fhh);
650 extern int	ndmfhh_commission (struct ndmfhheap *fhh,
651 					void *heap, unsigned size);
652 extern int	ndmfhh_prepare (struct ndmfhheap *fhh,
653 					int fhtype, int entry_size,
654 					unsigned n_item,
655 					unsigned total_size_of_items);
656 extern void *	ndmfhh_add_entry (struct ndmfhheap *fhh);
657 extern void *	ndmfhh_add_item (struct ndmfhheap *fhh, unsigned size);
658 extern void *	ndmfhh_save_item (struct ndmfhheap *fhh,
659 					void *item, unsigned size);
660 extern int	ndmfhh_reset (struct ndmfhheap *fhh);
661 extern int	ndmfhh_get_table (struct ndmfhheap *fhh,
662 					int *fhtype_p, void **table_p,
663 					unsigned *n_entry_p);
664 
665 
666 
667 
668 /*
669  * NDMCSTR -- canonical strings
670  ****************************************************************
671  * Convert strings to/from HTTP-like canonical strings (%xx).
672  * Example "a b%c" --> "a%20b%25c"
673  */
674 
675 #define NDMCSTR_WARN	'%'
676 extern int	ndmcstr_from_str (char *src, char *dst, unsigned dst_max);
677 extern int	ndmcstr_to_str (char *src, char *dst, unsigned dst_max);
678 extern int	ndmcstr_from_hex (int c);
679 
680 
681 
682 
683 /*
684  * NDMMD5 -- MD5 helpers
685  ****************************************************************
686  * This is a wrapper around the MD5 functions. ndml_md5.c
687  * is the only thing that needs to #include md5.h.
688  * The NDMP rules for converting a clear-text password
689  * into an MD5 digest are implemented here.
690  */
691 
692 #define NDMP_MD5_CHALLENGE_LENGTH	64
693 #define NDMP_MD5_DIGEST_LENGTH		16
694 #define NDMP_MD5_MESSAGE_LENGTH		128
695 #define NDMP_MD5_MAX_PASSWORD_LENGTH	32
696 
697 
698 extern int	ndmmd5_digest (char challenge[NDMP_MD5_CHALLENGE_LENGTH],
699 				char *clear_text_password,
700 				char digest[NDMP_MD5_DIGEST_LENGTH]);
701 extern int	ndmmd5_generate_challenge (
702 				char challenge[NDMP_MD5_CHALLENGE_LENGTH]);
703 
704 extern int	ndmmd5_ok_digest (char challenge[NDMP_MD5_CHALLENGE_LENGTH],
705 				char *clear_text_password,
706 				char digest[NDMP_MD5_DIGEST_LENGTH]);
707 
708 
709 
710 
711 /*
712  * NDMBSTF -- Binary Search Text File
713  ****************************************************************
714  * Use conventional binary search method on a sorted text
715  * file. The file MUST be sorted in ascending, lexicographic
716  * order. This is the default order of sort(1).
717  */
718 
719 extern int ndmbstf_first (FILE *fp, char *key, char *buf, unsigned max_buf);
720 extern int ndmbstf_next (FILE *fp, char *key, char *buf, unsigned max_buf);
721 extern int ndmbstf_first_with_bounds (FILE *fp, char *key,
722 	    char *buf, unsigned max_buf, off_t lower_bound, off_t upper_bound);
723 extern int ndmbstf_getline (FILE *fp, char *buf, unsigned max_buf);
724 extern int ndmbstf_seek_and_align (FILE *fp, off_t *off);
725 extern int ndmbstf_match (char *key, char *buf);
726 extern int ndmbstf_compare (char *key, char *buf);
727 
728 
729 
730 
731 /*
732  * NDMSTZF -- Stanza File
733  ****************************************************************
734  *
735  * Stanza files look about like this:
736  *	[stanza name line]
737  *	stanza body lines
738  *
739  * These are used for config files.
740  */
741 extern int ndmstz_getline (FILE *fp, char *buf, int n_buf);
742 extern int ndmstz_getstanza (FILE *fp, char *buf, int n_buf);
743 extern int ndmstz_parse (char *buf, char *argv[], int max_argv);
744 
745 
746 
747 
748 /*
749  * NDMCFG -- Config File
750  ****************************************************************
751  *
752  * Config files are stanza files (see above) which describe
753  * backup types, tape and scsi devices, etc.
754  * See ndml_config.c for details and stanza formats.
755  */
756 extern int	ndmcfg_load (char *filename, ndmp9_config_info *config_info);
757 extern int	ndmcfg_loadfp (FILE *fp, ndmp9_config_info *config_info);
758 
759 
760 
761 
762 /*
763  * NDMFHDB -- File History Database
764  *
765  * The File History is generated by the DATA and sent to the CONTROL
766  * using NDMP?_FH_ADD_... requests/posts. During backup the CONTROL
767  * writes the File History info to a text file as it arrives. Upon
768  * completion of the backup the text file should be sorted (UNIX
769  * sort(1) command). For recovery the file history index is searched
770  * using binary search (see NDMBSTF above). The fh_info, a 64-bit
771  * cookie used by DATA to identify the region of the backup image
772  * containing the corresponding object, is retreived from the index.
773  */
774 
775 struct ndmfhdb {
776 	FILE *			fp;
777 	int			use_dir_node;
778 	uint64_t		root_node;
779 };
780 
781 struct ndm_fhdb_callbacks {
782 	int (*add_file) (struct ndmlog *ixlog, int tagc,
783 		char *raw_name, ndmp9_file_stat *fstat);
784 	int (*add_dir) (struct ndmlog *ixlog, int tagc,
785 		char *raw_name, ndmp9_u_quad dir_node, ndmp9_u_quad node);
786 	int (*add_node) (struct ndmlog *ixlog, int tagc,
787 		ndmp9_u_quad node, ndmp9_file_stat *fstat);
788 	int (*add_dirnode_root) (struct ndmlog *ixlog, int tagc,
789 		ndmp9_u_quad root_node);
790 };
791 
792 extern void	ndmfhdb_register_callbacks (struct ndmlog *ixlog,
793 			struct ndm_fhdb_callbacks *callbacks);
794 extern void	ndmfhdb_unregister_callbacks (struct ndmlog *ixlog);
795 extern int	ndmfhdb_add_file (struct ndmlog *ixlog, int tagc,
796 			char *raw_name, ndmp9_file_stat *fstat);
797 extern int	ndmfhdb_add_dir (struct ndmlog *ixlog, int tagc,
798 			char *raw_name, ndmp9_u_quad dir_node,
799 			ndmp9_u_quad node);
800 extern int	ndmfhdb_add_node (struct ndmlog *ixlog, int tagc,
801 			ndmp9_u_quad node, ndmp9_file_stat *fstat);
802 extern int	ndmfhdb_add_dirnode_root (struct ndmlog *ixlog, int tagc,
803 			ndmp9_u_quad root_node);
804 
805 extern int	ndmfhdb_add_fh_info_to_nlist (FILE *fp,
806 			ndmp9_name *nlist, int n_nlist);
807 extern int	ndmfhdb_open (FILE *fp, struct ndmfhdb *fhcb);
808 extern int	ndmfhdb_lookup (struct ndmfhdb *fhcb, char *path,
809 			ndmp9_file_stat *fstat);
810 extern int	ndmfhdb_dirnode_root (struct ndmfhdb *fhcb);
811 extern int	ndmfhdb_dirnode_lookup (struct ndmfhdb *fhcb, char *path,
812 			ndmp9_file_stat *fstat);
813 extern int	ndmfhdb_dir_lookup (struct ndmfhdb *fhcb,
814 			uint64_t dir_node, char *name, uint64_t *node_p);
815 extern int	ndmfhdb_node_lookup (struct ndmfhdb *fhcb,
816 			uint64_t node, ndmp9_file_stat *fstat);
817 extern int	ndmfhdb_file_root (struct ndmfhdb *fhcb);
818 extern int	ndmfhdb_file_lookup (struct ndmfhdb *fhcb, char *path,
819 			ndmp9_file_stat *fstat);
820 extern char *	ndm_fstat_to_str (ndmp9_file_stat *fstat, char *buf);
821 extern int	ndm_fstat_from_str (ndmp9_file_stat *fstat, char *buf);
822 
823 #ifdef  __cplusplus
824 }
825 #endif
826 
827 #endif /* _NDMLIB_H_ */
828