1 /*
   2  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
   3  * Use is subject to license terms.
   4  */
   5 
   6 /*
   7  * BSD 3 Clause License
   8  *
   9  * Redistribution and use in source and binary forms, with or without
  10  * modification, are permitted provided that the following conditions are met:
  11  *      - Redistributions of source code must retain the above copyright
  12  *      notice, this list of conditions and the following disclaimer.
  13  *
  14  *      - Redistributions in binary form must reproduce the above copyright
  15  *      notice, this list of conditions and the following disclaimer in the
  16  *      documentation and/or other materials provided with the distribution.
  17  *
  18  *      - Neither the name of Sun Microsystems, Inc. nor the
  19  *      names of its contributors may be used to endorse or promote products
  20  *      derived from this software without specific prior written permission.
  21  *
  22  * THIS SOFTWARE IS PROVIDED BY SUN MICROSYSTEMS, INC. ''AS IS'' AND ANY
  23  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  24  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  25  * DISCLAIMED. IN NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY
  26  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
  27  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  28  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  29  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  30  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
  31  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  32  */
  33 
  34 /*
  35  * Copyright 2015 Nexenta Systems, Inc.  All rights reserved.
  36  */
  37 
  38 #include <ndmp.h>
  39 #include <ndmp_connect.h>
  40 #include <log.h>
  41 #include <stdlib.h>
  42 
  43 handletable * getmessage_handle(handletable *, ndmp_message, FILE *);
  44 int initialize_handletable(handletable *);
  45 conn_table * get_connection(conn_table *, conn_handle *, FILE *);
  46 int create_conntable(conn_table *, xdr_info *, conn_handle *, FILE *);
  47 int getrandom_num();
  48 int insert_connection(conn_table *, xdr_info *, conn_handle *, FILE *);
  49 void print_conntable(conn_table *);
  50 conn_table * delete_connection(conn_table *, conn_handle *, FILE *);
  51 
  52 /*
  53  * getmessage_handle() method gets the handletable entry for the messagecode
  54  * Args are     :
  55  * tbl          : Handle table
  56  * messagecode  : NDMP messagecode to be searched
  57  * loghandle    : Log handle
  58  * Return Value : returns the pointer to the handletable structure
  59  */
  60 
  61 handletable * getmessage_handle(handletable *tbl, ndmp_message messagecode,
  62     FILE *log)
  63 {
  64 
  65         while (tbl) {
  66 
  67                 if (tbl->messagecode == messagecode) {
  68                         ndmp_dprintf(log,
  69                             "Message code %x found & returning struct\n",
  70                             tbl->messagecode);
  71                         return (tbl);
  72                 }
  73                 tbl++;
  74         }
  75         return (NULL);
  76 }
  77 
  78 /*
  79  * initialize_handletable() method initializes the handletable entries with the
  80  * messagecode, reply structure size and xdr encode/decode function pointers.
  81  * This table is populated here and will remain constant.
  82  * Args are     :
  83  * tbl          : Handle table
  84  * Return Value : returns SUCCESS(0): Success ERROR(1):Failure
  85  */
  86 
  87 int
  88 initialize_handletable(handletable *tbl)
  89 {
  90         /* Initialize the handletable with all the ndmp interface xdr methods */
  91 
  92         tbl[0].messagecode = NDMP_CONNECT_OPEN;
  93         tbl[0].replysize = sizeof (ndmp_connect_open_reply);
  94 
  95         tbl[1].messagecode = NDMP_CONFIG_GET_SERVER_INFO;
  96         tbl[1].replysize = sizeof (ndmp_config_get_server_info_reply);
  97 
  98         tbl[2].messagecode = NDMP_NOTIFY_CONNECTION_STATUS;
  99         tbl[2].replysize = sizeof (ndmp_notify_connection_status_post);
 100 
 101         tbl[3].messagecode = NDMP_CONFIG_GET_SERVER_INFO;
 102         tbl[3].replysize = sizeof (ndmp_config_get_server_info_reply);
 103 
 104         tbl[4].messagecode = NDMP_CONNECT_CLIENT_AUTH;
 105         tbl[4].replysize = sizeof (ndmp_connect_client_auth_reply);
 106 
 107         tbl[5].messagecode = NDMP_CONNECT_CLOSE;
 108         tbl[5].replysize = 0;
 109 
 110         tbl[6].messagecode = NDMP_CONFIG_GET_HOST_INFO;
 111         tbl[6].replysize = sizeof (ndmp_config_get_host_info_reply);
 112 
 113         tbl[7].messagecode = NDMP_CONFIG_GET_CONNECTION_TYPE;
 114         tbl[7].replysize = sizeof (ndmp_config_get_connection_type_reply);
 115 
 116         tbl[8].messagecode = NDMP_CONFIG_GET_AUTH_ATTR;
 117         tbl[8].replysize = sizeof (ndmp_config_get_auth_attr_reply);
 118 
 119         tbl[9].messagecode = NDMP_CONFIG_GET_BUTYPE_INFO;
 120         tbl[9].replysize = sizeof (ndmp_config_get_butype_attr_reply);
 121 
 122         tbl[10].messagecode = NDMP_CONFIG_GET_FS_INFO;
 123         tbl[10].replysize = sizeof (ndmp_config_get_fs_info_reply);
 124 
 125         tbl[11].messagecode = NDMP_CONFIG_GET_TAPE_INFO;
 126         tbl[11].replysize = sizeof (ndmp_config_get_tape_info_reply);
 127 
 128         tbl[12].messagecode = NDMP_CONFIG_GET_SCSI_INFO;
 129         tbl[12].replysize = sizeof (ndmp_config_get_scsi_info_reply);
 130 
 131         tbl[13].messagecode = NDMP_CONFIG_GET_EXT_LIST;
 132         tbl[13].replysize = sizeof (ndmp_config_get_ext_list_reply);
 133 
 134         tbl[14].messagecode = NDMP_SCSI_OPEN;
 135         tbl[14].replysize = sizeof (ndmp_scsi_open_reply);
 136 
 137         tbl[15].messagecode = NDMP_SCSI_CLOSE;
 138         tbl[15].replysize = sizeof (ndmp_scsi_close_reply);
 139 
 140         tbl[16].messagecode = NDMP_SCSI_GET_STATE;
 141         tbl[16].replysize = sizeof (ndmp_scsi_get_state_reply);
 142 
 143         tbl[17].messagecode = NDMP_SCSI_RESET_DEVICE;
 144         tbl[17].replysize = sizeof (ndmp_scsi_reset_device_reply);
 145 
 146         tbl[18].messagecode = NDMP_SCSI_EXECUTE_CDB;
 147         tbl[18].replysize = sizeof (ndmp_execute_cdb_reply);
 148 
 149         tbl[19].messagecode = NDMP_TAPE_OPEN;
 150         tbl[19].replysize = sizeof (ndmp_tape_open_reply);
 151 
 152         tbl[20].messagecode = NDMP_TAPE_CLOSE;
 153         tbl[20].replysize = sizeof (ndmp_tape_close_reply);
 154 
 155         tbl[21].messagecode = NDMP_TAPE_GET_STATE;
 156         tbl[21].replysize = sizeof (ndmp_tape_get_state_reply);
 157 
 158         tbl[22].messagecode = NDMP_TAPE_MTIO;
 159         tbl[22].replysize = sizeof (ndmp_tape_mtio_reply);
 160 
 161         tbl[23].messagecode = NDMP_TAPE_WRITE;
 162         tbl[23].replysize = sizeof (ndmp_tape_write_reply);
 163 
 164         tbl[24].messagecode = NDMP_TAPE_READ;
 165         tbl[24].replysize = sizeof (ndmp_tape_read_reply);
 166 
 167         tbl[25].messagecode = NDMP_TAPE_EXECUTE_CDB;
 168         tbl[25].replysize = sizeof (ndmp_tape_execute_cdb_reply);
 169 
 170         tbl[26].messagecode = NDMP_DATA_GET_STATE;
 171         tbl[26].replysize = sizeof (ndmp_data_get_state_reply);
 172 
 173         tbl[27].messagecode = NDMP_DATA_START_BACKUP;
 174         tbl[27].replysize = sizeof (ndmp_data_start_backup_reply);
 175 
 176         tbl[28].messagecode = NDMP_DATA_START_RECOVER;
 177         tbl[28].replysize = sizeof (ndmp_data_start_recover_reply);
 178 
 179         tbl[29].messagecode = NDMP_DATA_GET_ENV;
 180         tbl[29].replysize = sizeof (ndmp_data_get_env_reply);
 181 
 182         tbl[30].messagecode = NDMP_DATA_STOP;
 183         tbl[30].replysize = sizeof (ndmp_data_stop_reply);
 184 
 185         tbl[31].messagecode = NDMP_DATA_LISTEN;
 186         tbl[31].replysize = sizeof (ndmp_data_listen_reply);
 187 
 188         tbl[32].messagecode = NDMP_DATA_CONNECT;
 189         tbl[32].replysize = sizeof (ndmp_data_connect_reply);
 190 
 191         tbl[33].messagecode = NDMP_DATA_START_RECOVER_FILEHIST;
 192         tbl[33].replysize = sizeof (ndmp_data_start_recover_reply);
 193 
 194         tbl[34].messagecode = NDMP_NOTIFY_DATA_HALTED;
 195         tbl[34].replysize = sizeof (ndmp_notify_data_halted_post);
 196 
 197         tbl[35].messagecode = NDMP_NOTIFY_MOVER_HALTED;
 198         tbl[35].replysize = sizeof (ndmp_notify_mover_halted_post);
 199 
 200         tbl[36].messagecode = NDMP_NOTIFY_MOVER_PAUSED;
 201         tbl[36].replysize = sizeof (ndmp_notify_mover_paused_post);
 202 
 203         tbl[37].messagecode = NDMP_NOTIFY_DATA_READ;
 204         tbl[37].replysize = sizeof (ndmp_notify_data_read_post);
 205 
 206         tbl[38].messagecode = NDMP_LOG_FILE;
 207         tbl[38].replysize = sizeof (ndmp_log_file_post);
 208 
 209         tbl[39].messagecode = NDMP_LOG_MESSAGE;
 210         tbl[39].replysize = sizeof (ndmp_log_message_post);
 211 
 212         tbl[40].messagecode = NDMP_FH_ADD_FILE;
 213         tbl[40].replysize = sizeof (ndmp_fh_add_file_post);
 214 
 215         tbl[41].messagecode = NDMP_FH_ADD_DIR;
 216         tbl[41].replysize = sizeof (ndmp_fh_add_dir_post);
 217 
 218         tbl[42].messagecode = NDMP_FH_ADD_NODE;
 219         tbl[42].replysize = sizeof (ndmp_fh_add_node_post);
 220 
 221         tbl[43].messagecode = NDMP_MOVER_GET_STATE;
 222         tbl[43].replysize = sizeof (ndmp_mover_get_state_reply);
 223 
 224         tbl[44].messagecode = NDMP_MOVER_LISTEN;
 225         tbl[44].replysize = sizeof (ndmp_mover_listen_reply);
 226 
 227         tbl[45].messagecode = NDMP_MOVER_CONTINUE;
 228         tbl[45].replysize = sizeof (ndmp_mover_continue_reply);
 229 
 230         tbl[46].messagecode = NDMP_MOVER_ABORT;
 231         tbl[46].replysize = sizeof (ndmp_mover_abort_reply);
 232 
 233         tbl[47].messagecode = NDMP_MOVER_STOP;
 234         tbl[47].replysize = sizeof (ndmp_mover_stop_reply);
 235 
 236         tbl[48].messagecode = NDMP_MOVER_SET_WINDOW;
 237         tbl[48].replysize = sizeof (ndmp_mover_set_window_reply);
 238 
 239         tbl[49].messagecode = NDMP_MOVER_READ;
 240         tbl[49].replysize = sizeof (ndmp_mover_read_reply);
 241 
 242         tbl[50].messagecode = NDMP_MOVER_CLOSE;
 243         tbl[50].replysize = sizeof (ndmp_mover_close_reply);
 244 
 245         tbl[51].messagecode = NDMP_MOVER_SET_RECORD_SIZE;
 246         tbl[51].replysize = sizeof (ndmp_mover_set_record_size_reply);
 247 
 248         tbl[52].messagecode = NDMP_MOVER_CONNECT;
 249         tbl[52].replysize = sizeof (ndmp_mover_connect_reply);
 250 
 251         tbl[53].messagecode = NDMP_DATA_ABORT;
 252         tbl[53].replysize = sizeof (ndmp_data_abort_reply);
 253 
 254         tbl[54].messagecode = NDMP_CONFIG_SET_EXT_LIST;
 255         tbl[54].replysize = sizeof (ndmp_config_set_ext_list_reply);
 256 
 257         tbl[55].messagecode = NDMP_CONNECT_SERVER_AUTH;
 258         tbl[55].replysize = sizeof (ndmp_connect_server_auth_reply);
 259 
 260         return (SUCCESS);
 261 }
 262 
 263 /*
 264  * get_connection() method gets a pointer to the connection object from the
 265  * connection table
 266  * Args are     :
 267  * tbl          : Connection table
 268  * conn         : Connection handle to be searched
 269  * log          : Log file handle
 270  * Return Value : returns pointer to the connection table entry found
 271  */
 272 
 273 conn_table *
 274     get_connection(conn_table *tbl, conn_handle *conn, FILE *log)
 275 {
 276 
 277         ndmp_dprintf(log, "In getconnection method \n");
 278 
 279         if (tbl == NULL) {
 280                 ndmp_dprintf(log, "getconnection(): connection tbl is null \n");
 281                 return (NULL);
 282         }
 283 
 284         while (tbl) {
 285                 if (tbl->conn->connhandle == conn->connhandle) {
 286                         ndmp_dprintf(log, "getconnection(): "
 287                             "connection found \n");
 288                         return (tbl);
 289                 }
 290                 tbl = tbl->next;
 291         }
 292         ndmp_dprintf(log, "getconnection (): connection not found in table \n");
 293         return (NULL);
 294 }
 295 
 296 /*
 297  * create_conntable() method creates the connection table to hold the connection
 298  * objects and inserts the first element in the connection table
 299  * Args are     :
 300  * conntbl2     : Connection table
 301  * xinfo        : Pointer to the xdr_info containing sd and xdr pointer
 302  * conn         : Connection object to be inserted in connection table
 303  * log          : Log file handle
 304  * Return Value : returns SUCCESS(0): Success ERROR(1):Failure
 305  */
 306 
 307 
 308 int create_conntable(conn_table *conntbl2, xdr_info *xinfo, conn_handle *conn,
 309     FILE *log)
 310 {
 311         /* Get the random number for the connection handle */
 312 
 313         conn->connhandle = getrandom_num();
 314 
 315         ndmp_dprintf(log, "Inside create_conntable connection handle is %d\n",
 316             conn->connhandle);
 317 
 318 
 319         ndmp_dprintf(log, "conntable is null and creating conn_table \n");
 320 
 321 
 322         conntbl2->conn->connhandle = conn->connhandle;
 323         ndmp_dprintf(log, "connection handle is %d and conn id %d \n",
 324             conntbl2->conn->connhandle, conn->connhandle);
 325 
 326         conntbl2->xdrinfo->xdrs = xinfo->xdrs;
 327 
 328         conntbl2->xdrinfo->sd = xinfo->sd;
 329 
 330         ndmp_dprintf(log, "socket desc is %d and xdr sock id  %d \n",
 331             conntbl2->xdrinfo->sd, xinfo->sd);
 332 
 333         conntbl2->next = NULL;
 334 
 335         return (SUCCESS);
 336 
 337 }
 338 
 339 /*
 340  * getrandom_num() method generates random number each time when its called
 341  * This method is used to generate unique connection handle.
 342  * Return Value : returns random number generated
 343  */
 344 
 345 int
 346 getrandom_num()
 347 {
 348         const int HIGH = 100;
 349         srand(time(NULL));
 350         return (random() % HIGH);
 351 }
 352 
 353 /*
 354  * insert_connection() method inserts connetion object into an exisiting
 355  * connection table
 356  * Args are     :
 357  * conntbl2     : Connection table
 358  * xinfo        : Pointer to the xdr_info containing sd and xdr pointer
 359  * conn         : Connection object to be inserted in connection table
 360  * log          : Log file handle
 361  * Return Value : returns SUCCESS(0): Success ERROR(1):Failure
 362  */
 363 
 364 int
 365 insert_connection(conn_table *conntbl, xdr_info *xinfo, conn_handle *conn,
 366     FILE *log)
 367 {
 368         conn_table *temp = conntbl;
 369 
 370         conn->connhandle = getrandom_num();
 371 
 372         ndmp_dprintf(log, "Inside insert_connection : conn handle %d \n",
 373             conn->connhandle);
 374 
 375         while (temp) {
 376                 if (temp->next == NULL) {
 377                         conn_table *new = (conn_table *)
 378                             malloc(sizeof (conn_table));
 379 
 380                         new->conn = (conn_handle *)
 381                             malloc(sizeof (conn_handle));
 382 
 383                         new->xdrinfo = (xdr_info *) malloc(sizeof (xdr_info));
 384 
 385                         new->xdrinfo->xdrs = (XDR *) malloc(sizeof (XDR));
 386 
 387                         new->conn->connhandle = conn->connhandle;
 388 
 389                         new->xdrinfo->xdrs = xinfo->xdrs;
 390 
 391                         new->xdrinfo->sd = xinfo->sd;
 392 
 393                         new->next = NULL;
 394 
 395                         temp->next = new;
 396                         return (SUCCESS);
 397 
 398                 }
 399                 temp = temp->next;
 400         }
 401 
 402         return (ERROR);
 403 }
 404 
 405 /*
 406  * print_conntable() method prints the connection table entries
 407  * This method is used for debugging pursposes
 408  * Args are     :
 409  * conntbl      : Connection table
 410  * Return Value : returns void
 411  */
 412 
 413 void
 414 print_conntable(conn_table *conntbl)
 415 {
 416         printf("Table contents are \n");
 417 
 418         while (conntbl) {
 419 
 420                 printf("Connection handle is %d \n", conntbl->conn->connhandle);
 421                 printf("Socket id is         %d \n", conntbl->xdrinfo->sd);
 422                 conntbl = conntbl->next;
 423         }
 424 }
 425 
 426 /*
 427  * delete_connection() method frees up memory allocated for conn_table entries
 428  * and deletes the connection object from connection table
 429  * Args are     :
 430  * tbl          : Connection table
 431  * conn         : Connection object to be deleted
 432  * log          : Log file handle
 433  * Return Value : returns pointer to the connection table after deletion
 434  */
 435 
 436 conn_table *
 437     delete_connection(conn_table *tbl, conn_handle *conn, FILE *log)
 438 {
 439         conn_table *temp = tbl;
 440         conn_table *temp1 = temp;
 441 
 442         if (temp->next == NULL) {
 443                 tbl = temp->next;
 444 
 445                 /* close the socket */
 446                 shutdown(temp->xdrinfo->sd, 2);
 447                 free(temp->xdrinfo->xdrs);
 448                 free(temp->xdrinfo);
 449                 free(temp);
 450                 ndmp_dprintf(log, "delete_connection():Deletion successful \n");
 451                 return (tbl);
 452         }
 453 
 454         while (temp) {
 455                 if ((temp->conn->connhandle == conn->connhandle)) {
 456                         temp1->next = temp->next;
 457                         /* Close the socket */
 458                         shutdown(temp->xdrinfo->sd, 2);
 459                         free(temp->xdrinfo->xdrs);
 460                         free(temp->xdrinfo);
 461                         free(temp);
 462 
 463                         return (tbl);
 464                 }
 465                 temp1 = temp;
 466                 temp = temp->next;
 467         }
 468 
 469         return (tbl);
 470 }