/*
 * Copyright (c) 1998,1999,2000
 *      Traakan, Inc., Los Altos, CA
 *      All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice unmodified, this list of conditions, and the following
 *    disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 * SUCH DAMAGE.
 */

/*
 * Project:  NDMJOB
 * Ident:    $Id: $
 *
 * Description:
 *      This is the key #include file for the NDMP protocol
 *      layer of NDMJOBLIB.
 *
 *      There are multiple version of NDMP. This gathers them together.
 *      Under control of #ifdef NDMOS_OPTION_NO_NDMPx specific versions
 *      may be omitted. At this time, NDMPv2 and NDMPv3 are deployed.
 *      NDMPv1 was defined but not widely deployed, and deemed irrelevant.
 *      NDMPv4 is under consideration.
 *
 *      NDMP is defined using RPC protocol specification
 *      files (.x files). NDMP does not really use the RPC
 *      layer, but it does use the RPC XDR (External Data
 *      Representation) layer.
 *
 *      The original NDMP .x files are cosmetically transformed for
 *      NDMJOBLIB. The original NDMPv2 and NDMPv3 .x files use names
 *      like ndmp_name and ndmp_config_get_host_info_reply. These
 *      changed between versions even though they have the same name.
 *      Data structures which didn't change, like ndmp_pval, caused
 *      compile-time agony. For example, xdr_ndmp_pval() would be
 *      multiply defined at ld(1)-time. The first approach considered
 *      and rejected to resolve this was to make a unified, all
 *      versions .x file. It was rejected because it becomes difficult,
 *      even impractical, to integrate new versions and to omit old ones.
 *      The approach taken was to transform the names to reflect protocol
 *      version. This same approach was adopted by NFS for NFSv3 and
 *      NFSv4. Now there is an ndmp2_pval and an ndmp3_pval, and the
 *      compiler is happy. When it's defined, there will be an ndmp4_pval.
 *
 *      There are two pseudo-versions of the protocol here: NDMPv0
 *      and NDMPv9. These are used for internal convenience. These
 *      are also defined using .x files because it's easy to
 *      cut-n-paste from the official .x files. Neither NDMPv0
 *      nor NDMPv9 may be omitted.
 *
 *      NDMPv0 is the NDMP protocol subset used before the protocol
 *      version negotiation is complete. This subset of the protocol
 *      must necessarily remain immutable and constant for all time.
 *      NDMPv0 is the over-the-wire protocol until the version is
 *      negotiated.
 *
 *      NDMPv9 is an internal representation of the protocol and
 *      isolates higher layers of NDMJOB from most variations between
 *      protocol version. NDMPv9 makes it a little easier to add
 *      new versions and omit older ones. NDMPv9 is never used
 *      over-the-wire, and therefore there are no XDR routines.
 *
 *      There are three primary elements of this layer:
 *
 *      1) Header files which define each version of the protocol.
 *         These are generated from files (.x files) by rpcgen(1).
 *
 *      2) XDR routines which convert to/from the over-the-wire
 *         protocol and internal data structures. These are
 *         also generated by rpcgen(1). There are also
 *         tables of XDR routines.
 *
 *      3) Support for pretty-printing the protocol data structures.
 *         Maybe someday rpcgen(1) will generate these, too.
 */


/*
 * PROTOCOL VERSIONS
 ****************************************************************
 *
 */

#include "ndmp0.h"

#ifndef NDMOS_OPTION_NO_NDMP2
#include "ndmp2.h"
#endif /* !NDMOS_OPTION_NO_NDMP2 */

#ifndef NDMOS_OPTION_NO_NDMP3
#include "ndmp3.h"
#endif /* !NDMOS_OPTION_NO_NDMP3 */

#ifndef NDMOS_OPTION_NO_NDMP4
#include "ndmp4.h"
#endif /* !NDMOS_OPTION_NO_NDMP4 */

#include "ndmp9.h"


/*
 * Protocol amendments. These are important constants
 * omitted from the spec and .x files.
 */
#include "ndmp_ammend.h"

#ifdef __cplusplus
extern "C" {
#endif


/*
 * XDR MESSAGE TABLES
 ****************************************************************
 *
 * Table for binding a ndmp_message to appropriate XDR routines.
 */

struct ndmp_xdr_message_table {
  int msg;
  int (*xdr_request)();
  int (*xdr_reply)();
};

extern struct ndmp_xdr_message_table ndmp0_xdr_message_table[];

#ifndef NDMOS_OPTION_NO_NDMP2
extern struct ndmp_xdr_message_table ndmp2_xdr_message_table[];
#endif /* !NDMOS_OPTION_NO_NDMP2 */

#ifndef NDMOS_OPTION_NO_NDMP3
extern struct ndmp_xdr_message_table ndmp3_xdr_message_table[];
#endif /* !NDMOS_OPTION_NO_NDMP3 */

#ifndef NDMOS_OPTION_NO_NDMP4
extern struct ndmp_xdr_message_table ndmp4_xdr_message_table[];
#endif /* !NDMOS_OPTION_NO_NDMP4 */

/* Note: no ndmp9 XDRs */

extern struct ndmp_xdr_message_table* ndmp_xmt_lookup(int protocol_version,
                                                      int msg);


/*
 * ENUM STRING TABLES
 ****************************************************************
 */

struct ndmp_enum_str_table {
  char* name;
  int value;
};

extern char* ndmp_enum_to_str(int val, struct ndmp_enum_str_table* table);
extern int ndmp_enum_from_str(int* valp,
                              char* str,
                              struct ndmp_enum_str_table* table);


#include "ndmp0_enum_strs.h"

#ifndef NDMOS_OPTION_NO_NDMP2
#include "ndmp2_enum_strs.h"
#endif /* !NDMOS_OPTION_NO_NDMP2 */

#ifndef NDMOS_OPTION_NO_NDMP3
#include "ndmp3_enum_strs.h"
#endif /* !NDMOS_OPTION_NO_NDMP3 */

#ifndef NDMOS_OPTION_NO_NDMP4
#include "ndmp4_enum_strs.h"
#endif /* !NDMOS_OPTION_NO_NDMP4 */

#include "ndmp9_enum_strs.h"


/*
 * MULTI-VERSION ENUM TO STRING CONVERTERS
 ****************************************************************
 */

extern char* ndmp_message_to_str(int protocol_version, int msg);
extern char* ndmp_error_to_str(int protocol_version, int msg);


/*
 * PRETTY PRINTERS
 ****************************************************************
 *
 * The ndmp[v]_pp_... (pretty printer) routines are debugging aids.
 * They pretty much implement an NDMP snooping package.
 *
 * All routines return -1 for an error. Otherwise, they
 * return the number of lines required to print the entire
 * data structure.  A return of 0 indicates a void data
 * structure. lineno parameter begins at 0.
 *
 * Line number 0 is usually usable as a summary.
 * Three levels of increasing detail are easy:
 *      1) Just ndmp_pp_header()
 *      2) ndmp_pp_header() and ndmp_pp_{request|reply} w/ lineno=0
 *      3) ndmp_pp_header() and ndmp_pp_{request|reply} all lines
 */


extern int ndmp_pp_header(int vers, void* data, char* buf);
extern int ndmp_pp_request(int vers,
                           int msg,
                           void* data,
                           int lineno,
                           char* buf);
extern int ndmp_pp_reply(int vers, int msg, void* data, int lineno, char* buf);

extern int ndmp0_pp_header(void* data, char* buf);
extern int ndmp0_pp_request(ndmp0_message msg,
                            void* data,
                            int lineno,
                            char* buf);
extern int ndmp0_pp_reply(ndmp0_message msg, void* data, int lineno, char* buf);

#ifndef NDMOS_OPTION_NO_NDMP2
extern int ndmp2_pp_header(void* data, char* buf);
extern int ndmp2_pp_request(ndmp2_message msg,
                            void* data,
                            int lineno,
                            char* buf);
extern int ndmp2_pp_reply(ndmp2_message msg, void* data, int lineno, char* buf);
#endif /* !NDMOS_OPTION_NO_NDMP2 */

#ifndef NDMOS_OPTION_NO_NDMP3
extern int ndmp3_pp_header(void* data, char* buf);
extern int ndmp3_pp_request(ndmp3_message msg,
                            void* data,
                            int lineno,
                            char* buf);
extern int ndmp3_pp_reply(ndmp3_message msg, void* data, int lineno, char* buf);
#endif /* !NDMOS_OPTION_NO_NDMP3 */

#ifndef NDMOS_OPTION_NO_NDMP4
extern int ndmp4_pp_header(void* data, char* buf);
extern int ndmp4_pp_request(ndmp4_message msg,
                            void* data,
                            int lineno,
                            char* buf);
extern int ndmp4_pp_reply(ndmp4_message msg, void* data, int lineno, char* buf);
#endif /* !NDMOS_OPTION_NO_NDMP4 */


#define NDMP_PP_AS(T) ((T*)data)

#define NDMP_PP_WITH(T) \
  {                     \
    T* p = ((T*)data);
#define NDMP_PP_ENDWITH }

#ifdef __cplusplus
}
#endif
