1 /*
   2  * This file and its contents are supplied under the terms of the
   3  * Common Development and Distribution License ("CDDL"), version 1.0.
   4  * You may only use this file in accordance with the terms of version
   5  * 1.0 of the CDDL.
   6  *
   7  * A full copy of the text of the CDDL should have accompanied this
   8  * source.  A copy of the CDDL is also available via the Internet at
   9  * http://www.illumos.org/license/CDDL.
  10  */
  11 
  12 /*
  13  * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
  14  */
  15 
  16 #include <libintl.h>
  17 #include <sys/debug.h>
  18 #include <string.h>
  19 #include <stdarg.h>
  20 
  21 #include <sys/krrp.h>
  22 #include "krrp_error.h"
  23 #include "libkrrp.h"
  24 #include "libkrrp_impl.h"
  25 #include "libkrrp_error.h"
  26 
  27 /* Make lint happy */
  28 #pragma error_messages(off, E_UNDEFINED_SYMBOL, E_YACC_ERROR, \
  29     E_FUNC_VAR_UNUSED, E_BLOCK_DECL_UNUSED, E_RET_INT_IMPLICITLY, \
  30     E_NOP_ELSE_STMT)
  31 
  32 /* Taken from sys/zio.h */
  33 #define ECKSUM  EBADE
  34 
  35 static struct {
  36         krrp_errno_t krrp_errno;
  37         libkrrp_errno_t libkrrp_errno;
  38 } krrp_errs[] = {
  39         {KRRP_ERRNO_OK, LIBKRRP_ERRNO_OK},
  40         {KRRP_ERRNO_UNKNOWN, LIBKRRP_ERRNO_UNKNOWN},
  41 #define LIBKRRP_ERRNO_EXPAND(enum_name) \
  42         {KRRP_ERRNO_##enum_name, LIBKRRP_ERRNO_##enum_name},
  43         KRNKRRP_ERRNO_MAP(LIBKRRP_ERRNO_EXPAND)
  44 #undef  LIBKRRP_ERRNO_EXPAND
  45 };
  46 
  47 static size_t krrp_errs_sz = sizeof (krrp_errs) / sizeof (krrp_errs[0]);
  48 
  49 #define UNIX_ERRNO_EXPAND(enum_name) \
  50         {enum_name, "UNIX_ERRNO_"#enum_name},
  51 static struct {
  52         int errno_num;
  53         const char *errno_str;
  54 } unix_errnos[] = {
  55         {0, "UNIX_ERRNO_UNDEFINED"},
  56         UNIX_ERRNO_MAP(UNIX_ERRNO_EXPAND)
  57 };
  58 #undef UNIX_ERRNO_EXPAND
  59 
  60 static size_t unix_errnos_sz = sizeof (unix_errnos) / sizeof (unix_errnos[0]);
  61 
  62 #define KRRP_ERRDESCR_SVC_ENABLE_MAP(X) \
  63         X(BUSY, 0, LIBKRRP_EMSG_BUSY) \
  64 
  65 #define KRRP_ERRDESCR_SVC_DISABLE_MAP(X) \
  66         X(BUSY, 0, LIBKRRP_EMSG_BUSY) \
  67 
  68 #define KRRP_ERRDESCR_SVC_GET_CONFIG_MAP(X) \
  69         X(CFGTYPE, ENOENT, LIBKRRP_EMSG_CFGTYPE_NOENT) \
  70         X(CFGTYPE, EINVAL, LIBKRRP_EMSG_CFGTYPE_INVAL) \
  71         X(INVAL, 0, LIBKRRP_EMSG_SRVNOTRUN) \
  72 
  73 #define KRRP_ERRDESCR_SVC_SET_CONFIG_MAP(X) \
  74         X(CFGTYPE, ENOENT, LIBKRRP_EMSG_CFGTYPE_NOENT) \
  75         X(CFGTYPE, EINVAL, LIBKRRP_EMSG_CFGTYPE_INVAL) \
  76         X(ADDR, EINVAL, LIBKRRP_EMSG_ADDR_INVAL) \
  77         X(CREATEFAIL, 0, LIBKRRP_EMSG_CREATEFAIL, strerror(unix_errno)) \
  78         X(BINDFAIL, 0, LIBKRRP_EMSG_BINDFAIL, strerror(unix_errno)) \
  79         X(LISTENFAIL, 0, LIBKRRP_EMSG_LISTENFAIL, strerror(unix_errno)) \
  80         X(PORT, ENOENT, LIBKRRP_EMSG_LSTPORT_NOENT) \
  81         X(PORT, EINVAL, LIBKRRP_EMSG_LSTPORT_INVAL, \
  82             KRRP_MIN_PORT, KRRP_MAX_PORT) \
  83         X(BUSY, 0, LIBKRRP_EMSG_SRVRECONF) \
  84 
  85 #define KRRP_ERRDESCR_SESS_SET_PRIVATE_DATA_MAP(X) \
  86         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
  87         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
  88         X(SESS, ENODATA, LIBKRRP_EMSG_SESS_NODATA1) \
  89         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
  90 
  91 #define KRRP_ERRDESCR_SESS_GET_PRIVATE_DATA_MAP(X) \
  92         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
  93         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
  94         X(SESS, ENODATA, LIBKRRP_EMSG_SESS_NODATA2) \
  95         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
  96 
  97 #define KRRP_ERRDESCR_SESS_CREATE_MAP(X) \
  98         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
  99         X(SESSID, EINVAL, LIBKRRP_EMSG_SESSID_INVAL) \
 100         X(KSTATID, ENOENT, LIBKRRP_EMSG_KSTATID_NOENT) \
 101         X(KSTATID, EINVAL, LIBKRRP_EMSG_KSTATID_INVAL, \
 102             KRRP_KSTAT_ID_STRING_LENGTH - 1) \
 103         X(SESS, EALREADY, LIBKRRP_EMSG_SESS_ALREADY) \
 104         X(SESS, EINVAL, LIBKRRP_EMSG_SESS_CREATE_INVAL) \
 105         X(AUTH, EINVAL, LIBKRRP_EMSG_SESS_CREATE_AUTH_INVAL, \
 106             KRRP_AUTH_DIGEST_MAX_LEN - 1) \
 107 
 108 #define KRRP_ERRDESCR_SESS_CREATE_CONN_MAP(X) \
 109         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 110         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 111         X(SESS, EINVAL, LIBKRRP_EMSG_SESS_CREATE_CONN_INVAL) \
 112         X(SESS, EALREADY, LIBKRRP_EMSG_SESS_CONN_ALREADY) \
 113         X(ADDR, ENOENT, LIBKRRP_EMSG_HOST_NOENT) \
 114         X(ADDR, EINVAL, LIBKRRP_EMSG_HOST_INVAL) \
 115         X(PORT, ENOENT, LIBKRRP_EMSG_PORT_NOENT) \
 116         X(PORT, EINVAL, LIBKRRP_EMSG_PORT_INVAL, \
 117             KRRP_MIN_PORT, KRRP_MAX_PORT) \
 118         X(CREATEFAIL, 0, LIBKRRP_EMSG_CREATEFAIL, strerror(unix_errno)) \
 119         X(SETSOCKOPTFAIL, 0, LIBKRRP_EMSG_SETSOCKOPTFAIL, \
 120             strerror(unix_errno)) \
 121         X(CONNFAIL, 0, LIBKRRP_EMSG_CONNFAIL, strerror(unix_errno)) \
 122         X(SENDFAIL, 0, LIBKRRP_EMSG_SENDFAIL, strerror(unix_errno)) \
 123         X(RECVFAIL, 0, LIBKRRP_EMSG_RECVFAIL, strerror(unix_errno)) \
 124         X(UNEXPCLOSE, 0, LIBKRRP_EMSG_UNEXPCLOSE, strerror(unix_errno)) \
 125         X(UNEXPEND, 0, LIBKRRP_EMSG_UNEXPEND, strerror(unix_errno)) \
 126         X(AUTH, ENOENT, LIBKRRP_EMSG_AUTH_NOENT) \
 127         X(AUTH, EINVAL, LIBKRRP_EMSG_SESS_CREATE_CONN_AUTH_INVAL) \
 128         X(BADRESP, 0, LIBKRRP_EMSG_BADRESP) \
 129         X(NOMEM, 0, LIBKRRP_EMSG_NOMEM) \
 130         X(BIGPAYLOAD, 0, LIBKRRP_EMSG_BIGPAYLOAD) \
 131         X(CONNTIMEOUT, 0, LIBKRRP_EMSG_CONNTIMEOUT_INVAL, \
 132             KRRP_MIN_CONN_TIMEOUT, KRRP_MAX_CONN_TIMEOUT) \
 133         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 134 
 135 #define KRRP_ERRDESCR_SESS_CONN_THROTTLE_MAP(X) \
 136         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 137         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 138         X(CONN, ENOENT, LIBKRRP_EMSG_SESS_CONN_NOENT) \
 139         X(SESS, EINVAL, LIBKRRP_EMSG_SESS_THROTTLE_RECV) \
 140         X(THROTTLE, ENOENT, LIBKRRP_EMSG_THROTTLE_NOENT) \
 141         X(THROTTLE, EINVAL, LIBKRRP_EMSG_THROTTLE_INVAL, \
 142             KRRP_MIN_CONN_THROTTLE) \
 143         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 144 
 145 #define KRRP_ERRDESCR_SESS_CREATE_PDU_ENGINE_MAP(X) \
 146         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 147         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 148         X(SESS, EALREADY, LIBKRRP_EMSG_SESS_PDUENGINE_ALREADY) \
 149         X(DBLKSZ, EINVAL, LIBKRRP_EMSG_DBLKSZ_INVAL, \
 150             KRRP_MIN_SESS_PDU_DBLK_DATA_SZ, KRRP_MAX_SESS_PDU_DBLK_DATA_SZ) \
 151         X(DBLKSZ, ENOENT, LIBKRRP_EMSG_DBLKSZ_NOENT) \
 152         X(MAXMEMSZ, ENOENT, LIBKRRP_EMSG_MAXMEMSZ_NOENT) \
 153         X(MAXMEMSZ, EINVAL, LIBKRRP_EMSG_MAXMEMSZ_INVAL, KRRP_MIN_MAXMEM) \
 154         X(NOMEM, 0, LIBKRRP_EMSG_SESS_PDUENGINE_NOMEM) \
 155         X(CONN, ENOENT, LIBKRRP_EMSG_SESS_CONN_NOENT) \
 156         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 157 
 158 #define KRRP_ERRDESCR_SESS_CREATE_WRITE_STREAM_MAP(X) \
 159         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 160         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 161         X(SESS, EINVAL, LIBKRRP_EMSG_SESS_CREATE_WRITE_STREAM_FAIL) \
 162         X(SESS, EALREADY, LIBKRRP_EMSG_SESS_STREAM_ALREADY) \
 163         X(ZFSGCTXFAIL, 0, LIBKRRP_EMSG_ZFSGCTXFAIL) \
 164         X(CMNSNAP, EINVAL, LIBKRRP_EMSG_CMNSNAP_INVAL) \
 165         X(DSTDS, ENOENT, LIBKRRP_EMSG_DSTDS_NOENT) \
 166         X(DSTDS, EINVAL, LIBKRRP_EMSG_DSTDS_INVAL) \
 167         X(RESUMETOKEN, EINVAL, LIBKRRP_EMSG_RESUMETOKEN_INVAL) \
 168         X(RESUMETOKEN, ENOTSUP, LIBKRRP_EMSG_RESUMETOKEN_ENOTSUP) \
 169         X(RESUMETOKEN, EBADMSG, LIBKRRP_EMSG_RESUMETOKEN_EBADMSG) \
 170         X(RESUMETOKEN, ECKSUM, LIBKRRP_EMSG_RESUMETOKEN_ECKSUM) \
 171         X(RESUMETOKEN, ENOSR, LIBKRRP_EMSG_RESUMETOKEN_ENOSR) \
 172         X(RESUMETOKEN, ENODATA, LIBKRRP_EMSG_RESUMETOKEN_ENODATA) \
 173         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 174         X(KEEPSNAPS, 0, LIBKRRP_EMSG_KEEPSNAPS_INVAL, \
 175             KRRP_MIN_KEEP_SNAPS, KRRP_MAX_KEEP_SNAPS) \
 176 
 177 #define KRRP_ERRDESCR_SESS_CREATE_READ_STREAM_MAP(X) \
 178         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 179         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 180         X(SESS, EINVAL, LIBKRRP_EMSG_SESS_CREATE_READ_STREAM_FAIL) \
 181         X(SESS, EALREADY, LIBKRRP_EMSG_SESS_STREAM_ALREADY) \
 182         X(FAKEDSZ, ENOENT, LIBKRRP_EMSG_FAKEDSZ_NOENT) \
 183         X(FAKEDSZ, EINVAL, LIBKRRP_EMSG_FAKEDSZ_INVAL) \
 184         X(ZFSGCTXFAIL, 0, LIBKRRP_EMSG_ZFSGCTXFAIL) \
 185         X(SRCDS, ENOENT, LIBKRRP_EMSG_SRCDS_NOENT) \
 186         X(SRCDS, EINVAL, LIBKRRP_EMSG_SRCDS_INVAL) \
 187         X(SRCSNAP, EINVAL, LIBKRRP_EMSG_SRCSNAP_INVAL) \
 188         X(CMNSNAP, EINVAL, LIBKRRP_EMSG_CMNSNAP_INVAL) \
 189         X(STREAM, EINVAL, LIBKRRP_EMSG_SNAP_NAMES_EQUAL) \
 190         X(RESUMETOKEN, EINVAL, LIBKRRP_EMSG_RESUMETOKEN_INVAL) \
 191         X(RESUMETOKEN, ENOTSUP, LIBKRRP_EMSG_RESUMETOKEN_ENOTSUP) \
 192         X(RESUMETOKEN, EBADMSG, LIBKRRP_EMSG_RESUMETOKEN_EBADMSG) \
 193         X(RESUMETOKEN, ECKSUM, LIBKRRP_EMSG_RESUMETOKEN_ECKSUM) \
 194         X(RESUMETOKEN, ENOSR, LIBKRRP_EMSG_RESUMETOKEN_ENOSR) \
 195         X(RESUMETOKEN, ENODATA, LIBKRRP_EMSG_RESUMETOKEN_ENODATA) \
 196         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 197         X(KEEPSNAPS, 0, LIBKRRP_EMSG_KEEPSNAPS_INVAL, \
 198             KRRP_MIN_KEEP_SNAPS, KRRP_MAX_KEEP_SNAPS) \
 199         X(SKIP_SNAPS_MASK, EINVAL, \
 200             LIBKRRP_EMSG_SKIP_SNAPS_MASK_EINVAL) \
 201         X(SKIP_SNAPS_MASK, EMSGSIZE, \
 202             LIBKRRP_EMSG_SKIP_SNAPS_MASK_EMSGSIZE) \
 203         X(SKIP_SNAPS_MASK, ENAMETOOLONG, \
 204             LIBKRRP_EMSG_SKIP_SNAPS_MASK_ENAMETOOLONG) \
 205         X(SKIP_SNAPS_MASK, E2BIG, \
 206             LIBKRRP_EMSG_SKIP_SNAPS_MASK_E2BIG) \
 207 
 208 #define KRRP_ERRDESCR_SESS_COMMON_MAP(X) \
 209         X(AUTOSNAP, EINVAL, LIBKRRP_EMSG_AUTOSNAP_INVAL) \
 210         X(CMNSNAP, ENOENT, LIBKRRP_EMSG_CMNSNAP_NOTEXIST) \
 211         X(SRCDS, ENOENT, LIBKRRP_EMSG_SRCDS_NOTEXIST) \
 212         X(DSTDS, ENOENT, LIBKRRP_EMSG_DSTDS_NOTEXIST) \
 213         X(SRCSNAP, ENOENT, LIBKRRP_EMSG_SRCSNAP_NOTEXIST) \
 214         X(STREAM, ENXIO, LIBKRRP_EMSG_STREAM_POOL_FAULT) \
 215 
 216 #define KRRP_ERRDESCR_SESS_RUN_MAP(X) \
 217         KRRP_ERRDESCR_SESS_COMMON_MAP(X) \
 218         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 219         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 220         X(SESS, EALREADY, LIBKRRP_EMSG_SESS_STARTED) \
 221         X(SESS, EINVAL, LIBKRRP_EMSG_RUN_ONCE_RECV) \
 222         X(CONN, ENOENT, LIBKRRP_EMSG_SESS_CONN_NOENT) \
 223         X(PDUENGINE, ENOENT, LIBKRRP_EMSG_SESS_PDUENGINE_NOENT) \
 224         X(STREAM, EOPNOTSUPP, LIBKRRP_EMSG_STREAM_EOPNOTSUPP) \
 225         X(STREAM, ENOENT, LIBKRRP_EMSG_STREAM_NOENT) \
 226         X(STREAM, EINVAL, LIBKRRP_EMSG_SESS_RUN_ONCE_INCOMPAT) \
 227         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 228 
 229 #define KRRP_ERRDESCR_SESS_SEND_STOP_MAP(X) \
 230         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 231         X(STREAM, EALREADY, LIBKRRP_EMSG_SESS_SEND_STOP_ALREADY) \
 232         X(STREAM, EINVAL, LIBKRRP_EMSG_CANNOT_STOP_SESS) \
 233         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 234         X(SESS, ENOTACTIVE, LIBKRRP_EMSG_SESS_NOTACTIVE) \
 235         X(SESS, EINVAL, LIBKRRP_EMSG_SESS_SEND_STOP_RECV) \
 236         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 237 
 238 #define KRRP_ERRDESCR_SESS_DESTROY_MAP(X) \
 239         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 240         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 241         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 242 
 243 #define KRRP_ERRDESCR_SESS_STATUS_MAP(X) \
 244         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 245         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 246 
 247 #define KRRP_ERRDESCR_SESS_GET_CONN_INFO_MAP(X) \
 248         X(SESSID, ENOENT, LIBKRRP_EMSG_SESSID_NOENT) \
 249         X(SESS, ENOENT, LIBKRRP_EMSG_SESS_NOENT) \
 250         X(SESS, EBUSY, LIBKRRP_EMSG_SESS_BUSY) \
 251         X(SESS, ENOTSUP, LIBKRRP_EMSG_SESS_ENOTSUP) \
 252         X(CONN, ENOENT, LIBKRRP_EMSG_SESS_CONN_NOENT) \
 253 
 254 #define KRRP_ERRDESCR_SVC_STATE_MAP(X)
 255 #define KRRP_ERRDESCR_SESS_LIST_MAP(X)
 256 
 257 #define LIBKRRP_ERRDESCR_SESS_ERROR_MAP(X) \
 258         X(OK, 0, LIBKRRP_EMSG_OK) \
 259         X(PINGTIMEOUT, 0, LIBKRRP_EMSG_SESSPINGTIMEOUT) \
 260         X(WRITEFAIL, ENODEV, LIBKRRP_EMSG_SNAPMISMATCH) \
 261         X(WRITEFAIL, ETXTBSY, LIBKRRP_EMSG_DESTMODIFIED) \
 262         X(WRITEFAIL, EEXIST, LIBKRRP_EMSG_DESTEXISTS) \
 263         X(WRITEFAIL, EINVAL, LIBKRRP_EMSG_WRITEINVAL) \
 264         X(WRITEFAIL, ECKSUM, LIBKRRP_EMSG_CHKSUMMISMATCH) \
 265         X(WRITEFAIL, ENOTSUP, LIBKRRP_EMSG_OLDPOOL) \
 266         X(WRITEFAIL, EDQUOT, LIBKRRP_EMSG_DESTQUOTA) \
 267         X(WRITEFAIL, ENOSPC, LIBKRRP_EMSG_DESTNOSPACE) \
 268         X(WRITEFAIL, ENOLINK, LIBKRRP_EMSG_NOORIGIN) \
 269         X(WRITEFAIL, 0, LIBKRRP_EMSG_WRITEFAIL, \
 270             krrp_unix_errno_to_str(unix_errno)) \
 271         X(READFAIL, EXDEV, LIBKRRP_EMSG_NOTEARLIERSNAP) \
 272         X(READFAIL, EBUSY, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 273         X(READFAIL, EDQUOT, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 274         X(READFAIL, EFBIG, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 275         X(READFAIL, EIO, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 276         X(READFAIL, ENOLINK, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 277         X(READFAIL, ENOSPC, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 278         X(READFAIL, ENOSTR, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 279         X(READFAIL, ENXIO, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 280         X(READFAIL, EPIPE, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 281         X(READFAIL, ERANGE, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 282         X(READFAIL, EFAULT, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 283         X(READFAIL, EROFS, LIBKRRP_EMSG_READFAIL, strerror(unix_errno)) \
 284         X(READFAIL, 0, LIBKRRP_EMSG_READFAIL, \
 285             krrp_unix_errno_to_str(unix_errno)) \
 286         X(SENDFAIL, 0, LIBKRRP_EMSG_SENDFAIL, strerror(unix_errno)) \
 287         X(SENDMBLKFAIL, 0, LIBKRRP_EMSG_SENDMBLKFAIL, strerror(unix_errno)) \
 288         X(RECVFAIL, 0, LIBKRRP_EMSG_RECVFAIL, strerror(unix_errno)) \
 289         X(UNEXPEND, 0, LIBKRRP_EMSG_UNEXPEND) \
 290         X(BIGPAYLOAD, 0, LIBKRRP_EMSG_BIGPAYLOAD) \
 291         X(UNEXPCLOSE, 0, LIBKRRP_EMSG_UNEXPCLOSE) \
 292         X(SNAPFAIL, ENAMETOOLONG, LIBKRRP_EMSG_DSNAMETOOLONG) \
 293         X(SNAPFAIL, 0, LIBKRRP_EMSG_SNAPFAIL, \
 294             krrp_unix_errno_to_str(unix_errno)) \
 295 
 296 #define LIBKRRP_ERRDESCR_SESS_STATUS_ERROR_MAP(X) \
 297         LIBKRRP_ERRDESCR_SESS_ERROR_MAP(X) \
 298         KRRP_ERRDESCR_SESS_COMMON_MAP(X) \
 299 
 300 #define LIBKRRP_ERRDESCR_SERVER_ERROR_MAP(X) \
 301         X(CREATEFAIL, 0, LIBKRRP_EMSG_CREATEFAIL) \
 302         X(BINDFAIL, 0, LIBKRRP_EMSG_BINDFAIL) \
 303         X(LISTENFAIL, 0, LIBKRRP_EMSG_LISTENFAIL) \
 304         X(ADDR, EINVAL, LIBKRRP_EMSG_ADDR_INVAL) \
 305 
 306 
 307 static libkrrp_errno_t
 308 krrp_errno_to_libkrrp_errno(krrp_errno_t krrp_errno)
 309 {
 310         size_t i;
 311 
 312         for (i = 0; i < krrp_errs_sz; i++) {
 313                 if (krrp_errs[i].krrp_errno == krrp_errno)
 314                         return (krrp_errs[i].libkrrp_errno);
 315         }
 316 
 317         return (LIBKRRP_ERRNO_UNKNOWN);
 318 }
 319 
 320 void
 321 libkrrp_error_set(libkrrp_error_t *error, libkrrp_errno_t libkrrp_errno,
 322     int unix_errno, uint32_t flags)
 323 {
 324         VERIFY(error != NULL);
 325 
 326         error->libkrrp_errno = libkrrp_errno;
 327         error->unix_errno = unix_errno;
 328         error->flags = flags;
 329 }
 330 
 331 int
 332 libkrrp_error_from_nvl(nvlist_t *nvl, libkrrp_error_t *error)
 333 {
 334         krrp_errno_t krrp_errno;
 335         int unix_errno;
 336         uint32_t flags;
 337 
 338         ASSERT(error != NULL);
 339 
 340         if (krrp_param_get(KRRP_PARAM_ERROR_CODE, nvl, &krrp_errno) != 0)
 341                 return (-1);
 342 
 343         if (krrp_param_get(KRRP_PARAM_ERROR_EXCODE, nvl, &unix_errno) != 0)
 344                 return (-1);
 345 
 346         if (krrp_param_get(KRRP_PARAM_ERROR_FLAGS, nvl, &flags) != 0)
 347                 return (-1);
 348 
 349         libkrrp_error_set(error, krrp_errno_to_libkrrp_errno(krrp_errno),
 350             unix_errno, flags | LIBKRRP_ERRF_KERNEL);
 351 
 352         return (0);
 353 }
 354 
 355 boolean_t
 356 libkrrp_error_cmp(libkrrp_errno_t libkrrp_errno,
 357     libkrrp_errno_t m_libkrrp_errno, int unix_errno, int m_unix_errno,
 358     int flags, char *descr, char *m_descr, ...)
 359 {
 360         va_list ap;
 361 
 362         if ((libkrrp_errno == m_libkrrp_errno) &&
 363             (m_unix_errno == 0 || unix_errno == m_unix_errno)) {
 364                 va_start(ap, m_descr);
 365                 (void) vsnprintf(descr, sizeof (libkrrp_error_descr_t),
 366                     dgettext(TEXT_DOMAIN, m_descr), ap);
 367 
 368                 if (flags & LIBKRRP_ERRF_REMOTE) {
 369                         (void) strlcat(descr, " (",
 370                             sizeof (libkrrp_error_descr_t));
 371                         (void) strlcat(descr, dgettext(TEXT_DOMAIN,
 372                             LIBKRRP_EMSG_REMOTE_NODE_ERROR),
 373                             sizeof (libkrrp_error_descr_t));
 374                         (void) strlcat(descr, ")",
 375                             sizeof (libkrrp_error_descr_t));
 376                 }
 377 
 378                 va_end(ap);
 379                 return (B_TRUE);
 380         }
 381 
 382         return (B_FALSE);
 383 }
 384 
 385 const libkrrp_error_t *
 386 libkrrp_error(libkrrp_handle_t *hdl)
 387 {
 388         VERIFY(hdl != NULL);
 389         return (&hdl->libkrrp_error);
 390 }
 391 
 392 void
 393 libkrrp_set_error_description(libkrrp_handle_t *hdl, const char *descr)
 394 {
 395         VERIFY(hdl != NULL && hdl->libkrrp_error.libkrrp_errno != 0);
 396 
 397         (void) strlcpy(hdl->libkrrp_error_descr,
 398             descr, sizeof (libkrrp_error_descr_t));
 399 }
 400 
 401 const char *
 402 libkrrp_error_description(libkrrp_handle_t *hdl)
 403 {
 404         /* LINTED: E_FUNC_SET_NOT_USED */
 405         libkrrp_errno_t libkrrp_errno;
 406         /* LINTED: E_FUNC_SET_NOT_USED */
 407         int unix_errno;
 408         int flags;
 409         krrp_ioctl_cmd_t cmd;
 410         char *descr;
 411 
 412         VERIFY(hdl != NULL);
 413 
 414         descr = hdl->libkrrp_error_descr;
 415         if (descr[0] != '\0')
 416                 return (descr);
 417 
 418         libkrrp_errno = hdl->libkrrp_error.libkrrp_errno;
 419         unix_errno = hdl->libkrrp_error.unix_errno;
 420         flags = hdl->libkrrp_error.flags;
 421         cmd = hdl->libkrrp_last_cmd;
 422 
 423         if (flags & LIBKRRP_ERRF_KERNEL) {
 424                 switch (cmd) {
 425 #define         KRRP_IOCTL_EXPAND(cmd_m) \
 426                 case KRRP_IOCTL_##cmd_m: \
 427                         SET_ERROR_DESCR(KRRP_ERRDESCR_##cmd_m##_MAP); \
 428                         break;
 429 
 430                 KRRP_IOCTL_MAP(KRRP_IOCTL_EXPAND)
 431 #undef          KRRP_IOCTL_EXPAND
 432                 default:
 433                         break;
 434                 }
 435         } else {
 436                 SET_ERROR_DESCR(LIBKRRP_ERRDESCR_MAP);
 437         }
 438 
 439         if (descr[0] == '\0') {
 440                 (void) snprintf(descr, sizeof (libkrrp_error_descr_t) - 1,
 441                     dgettext(TEXT_DOMAIN, LIBKRRP_EMSG_UNKNOWN));
 442         }
 443 
 444         return (descr);
 445 }
 446 
 447 const char
 448 *krrp_unix_errno_to_str(int unix_errno)
 449 {
 450         size_t i;
 451         for (i = 0; i < unix_errnos_sz; i++) {
 452                 if (unix_errnos[i].errno_num == unix_errno)
 453                         return (unix_errnos[i].errno_str);
 454         }
 455 
 456         return ("UNIX_ERRNO_UNKNOWN");
 457 }
 458 
 459 void
 460 libkrrp_common_error_description(libkrrp_error_type_t error_type,
 461     libkrrp_error_t *error, libkrrp_error_descr_t descr)
 462 {
 463         /* LINTED: E_FUNC_SET_NOT_USED */
 464         libkrrp_errno_t libkrrp_errno;
 465         /* LINTED: E_FUNC_SET_NOT_USED */
 466         int unix_errno;
 467         /* LINTED: E_FUNC_SET_NOT_USED */
 468         int flags;
 469 
 470         VERIFY(error != NULL);
 471 
 472         descr[0] = '\0';
 473         libkrrp_errno = error->libkrrp_errno;
 474         unix_errno = error->unix_errno;
 475         flags = error->flags;
 476 
 477         switch (error_type) {
 478         case LIBKRRP_SRV_ERROR:
 479                 SET_ERROR_DESCR(LIBKRRP_ERRDESCR_SERVER_ERROR_MAP);
 480                 break;
 481         case LIBKRRP_SESS_ERROR:
 482                 SET_ERROR_DESCR(LIBKRRP_ERRDESCR_SESS_ERROR_MAP);
 483                 break;
 484         case LIBKRRP_SESS_STATUS_ERROR:
 485                 SET_ERROR_DESCR(LIBKRRP_ERRDESCR_SESS_STATUS_ERROR_MAP);
 486                 break;
 487         default:
 488                 break;
 489         }
 490 
 491         if (descr[0] == '\0') {
 492                 (void) snprintf(descr,
 493                     sizeof (libkrrp_error_descr_t) - 1,
 494                     dgettext(TEXT_DOMAIN, LIBKRRP_EMSG_UNKNOWN));
 495         }
 496 }
 497 
 498 void
 499 libkrrp_sess_error_description(libkrrp_error_t *error,
 500     libkrrp_error_descr_t descr)
 501 {
 502         libkrrp_common_error_description(LIBKRRP_SESS_STATUS_ERROR,
 503             error, descr);
 504 }