1 /* The program allows the user to send a trespass command to change the
2 * LUN ownership from one Service-Processor to this one on an EMC
3 * CLARiiON and potentially other devices.
4 *
5 * Copyright (C) 2004-2018 Lars Marowsky-Bree <[email protected]>
6 *
7 * Based on sg_start.c; credits from there also apply.
8 * Minor modifications for sg_lib, D. Gilbert 2004/10/19
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2, or (at your option)
13 * any later version.
14 *
15 * SPDX-License-Identifier: GPL-2.0-or-later
16 */
17
18 #include <stdio.h>
19 #include <stdlib.h>
20 #include <unistd.h>
21 #include <stdlib.h>
22 #include <stdarg.h>
23 #include <stdbool.h>
24 #include <string.h>
25 #include <sys/types.h>
26 #include <sys/stat.h>
27 #include <fcntl.h>
28
29 #ifdef HAVE_CONFIG_H
30 #include "config.h"
31 #endif
32 #include "sg_lib.h"
33 #include "sg_cmds_basic.h"
34 #include "sg_pr2serr.h"
35
36
37 static const char * version_str = "0.23 20180219";
38
39 static int debug = 0;
40
41 #define TRESPASS_PAGE 0x22
42
43 static int
do_trespass(int fd,bool hr,bool short_cmd)44 do_trespass(int fd, bool hr, bool short_cmd)
45 {
46 uint8_t long_trespass_pg[] =
47 { 0, 0, 0, 0, 0, 0, 0, 0x00,
48 TRESPASS_PAGE, /* Page code */
49 0x09, /* Page length - 2 */
50 0x81, /* Trespass code + Honor reservation
51 * bit */
52 0xff, 0xff, /* Trespass target */
53 0, 0, 0, 0, 0, 0 /* Reserved bytes / unknown */
54 };
55 uint8_t short_trespass_pg[] =
56 { 0, 0, 0, 0,
57 TRESPASS_PAGE, /* Page code */
58 0x02, /* Page length - 2 */
59 0x81, /* Trespass code + Honor reservation
60 * bit */
61 0xff, /* Trespass target */
62 };
63 int res;
64 char b[80];
65
66 if (hr) { /* override Trespass code + Honor reservation bit */
67 short_trespass_pg[6] = 0x01;
68 long_trespass_pg[10] = 0x01;
69 }
70 if (short_cmd)
71 res = sg_ll_mode_select6(fd, true /* pf */, false /* sp */,
72 short_trespass_pg, sizeof(short_trespass_pg),
73 true, (debug ? 2 : 0));
74 else
75 res = sg_ll_mode_select10(fd, true /* pf */, false /* sp */,
76 long_trespass_pg, sizeof(long_trespass_pg),
77 true, (debug ? 2 : 0));
78
79 switch (res) {
80 case 0:
81 if (debug)
82 pr2serr("%s trespass successful\n",
83 short_cmd ? "short" : "long");
84 break;
85 case SG_LIB_CAT_INVALID_OP:
86 case SG_LIB_CAT_ILLEGAL_REQ:
87 pr2serr("%s form trepass page failed, try again %s '-s' "
88 "option\n", short_cmd ? "short" : "long",
89 short_cmd ? "without" : "with");
90 break;
91 case SG_LIB_CAT_NOT_READY:
92 pr2serr("device not ready\n");
93 break;
94 case SG_LIB_CAT_UNIT_ATTENTION:
95 pr2serr("unit attention\n");
96 break;
97 default:
98 sg_get_category_sense_str(res, sizeof(b), b, debug);
99 pr2serr("%s trespass failed: %s\n",
100 (short_cmd ? "short" : "long"), b);
101 break;
102 }
103 return res;
104 }
105
usage()106 void usage ()
107 {
108 pr2serr("Usage: sg_emc_trespass [-d] [-hr] [-s] [-V] DEVICE\n"
109 " Change ownership of a LUN from another SP to this one.\n"
110 " EMC CLARiiON CX-/AX-family + FC5300/FC4500/FC4700.\n"
111 " -d : output debug\n"
112 " -hr: Set Honor Reservation bit\n"
113 " -s : Send Short Trespass Command page (default: long)\n"
114 " (for FC series)\n"
115 " -V: print version string then exit\n"
116 " DEVICE sg or block device (latter in lk 2.6 or lk 3 "
117 "series)\n"
118 " Example: sg_emc_trespass /dev/sda\n");
119 exit (1);
120 }
121
main(int argc,char * argv[])122 int main(int argc, char * argv[])
123 {
124 char **argptr;
125 char * file_name = 0;
126 int k, fd;
127 bool hr = false;
128 bool short_cmd = false;
129 int ret = 0;
130
131 if (argc < 2)
132 usage ();
133
134 for (k = 1; k < argc; ++k) {
135 argptr = argv + k;
136 if (!strcmp (*argptr, "-d"))
137 ++debug;
138 else if (!strcmp (*argptr, "-s"))
139 short_cmd = true;
140 else if (!strcmp (*argptr, "-hr"))
141 hr = true;
142 else if (!strcmp (*argptr, "-V")) {
143 printf("Version string: %s\n", version_str);
144 exit(0);
145 }
146 else if (*argv[k] == '-') {
147 pr2serr("Unrecognized switch: %s\n", argv[k]);
148 file_name = NULL;
149 break;
150 }
151 else if (NULL == file_name)
152 file_name = argv[k];
153 else {
154 pr2serr("too many arguments\n");
155 file_name = NULL;
156 break;
157 }
158 }
159 if (NULL == file_name) {
160 usage();
161 return SG_LIB_SYNTAX_ERROR;
162 }
163
164 fd = open(file_name, O_RDWR | O_NONBLOCK);
165 if (fd < 0) {
166 pr2serr("Error trying to open %s\n", file_name);
167 perror("");
168 usage();
169 return SG_LIB_FILE_ERROR;
170 }
171
172 ret = do_trespass(fd, hr, short_cmd);
173
174 close (fd);
175 return (ret >= 0) ? ret : SG_LIB_CAT_OTHER;
176 }
177