File: | src/usr.sbin/iscsid/iscsid.c |
Warning: | line 100, column 2 Value stored to 'argv' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | /* $OpenBSD: iscsid.c,v 1.22 2021/04/16 14:37:06 claudio Exp $ */ |
2 | |
3 | /* |
4 | * Copyright (c) 2009 Claudio Jeker <claudio@openbsd.org> |
5 | * |
6 | * Permission to use, copy, modify, and distribute this software for any |
7 | * purpose with or without fee is hereby granted, provided that the above |
8 | * copyright notice and this permission notice appear in all copies. |
9 | * |
10 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
11 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
12 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
13 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
14 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
15 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
16 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
17 | */ |
18 | |
19 | #include <sys/queue.h> |
20 | #include <sys/socket.h> |
21 | #include <sys/sysctl.h> |
22 | #include <sys/time.h> |
23 | #include <sys/uio.h> |
24 | |
25 | #include <err.h> |
26 | #include <event.h> |
27 | #include <pwd.h> |
28 | #include <signal.h> |
29 | #include <stdio.h> |
30 | #include <stdlib.h> |
31 | #include <string.h> |
32 | #include <unistd.h> |
33 | |
34 | #include "iscsid.h" |
35 | #include "log.h" |
36 | |
37 | void main_sig_handler(int, short, void *); |
38 | __dead__attribute__((__noreturn__)) void usage(void); |
39 | void shutdown_cb(int, short, void *); |
40 | |
41 | extern struct initiator *initiator; |
42 | struct event exit_ev; |
43 | int exit_rounds; |
44 | #define ISCSI_EXIT_WAIT5 5 |
45 | |
46 | const struct session_params iscsi_sess_defaults = { |
47 | .MaxBurstLength = 262144, |
48 | .FirstBurstLength = 65536, |
49 | .DefaultTime2Wait = 2, |
50 | .DefaultTime2Retain = 20, |
51 | .MaxOutstandingR2T = 1, |
52 | .MaxConnections = 1, |
53 | .InitialR2T = 1, |
54 | .ImmediateData = 1, |
55 | .DataPDUInOrder = 1, |
56 | .DataSequenceInOrder = 1, |
57 | .ErrorRecoveryLevel = 0 |
58 | }; |
59 | |
60 | const struct connection_params iscsi_conn_defaults = { |
61 | .MaxRecvDataSegmentLength = 8192 |
62 | }; |
63 | |
64 | int |
65 | main(int argc, char *argv[]) |
66 | { |
67 | struct event ev_sigint, ev_sigterm, ev_sighup; |
68 | struct passwd *pw; |
69 | char *ctrlsock = ISCSID_CONTROL"/var/run/iscsid.sock"; |
70 | char *vscsidev = ISCSID_DEVICE"/dev/vscsi0"; |
71 | int name[] = { CTL_KERN1, KERN_PROC_NOBROADCASTKILL79, 0 }; |
72 | int ch, debug = 0, verbose = 0, nobkill = 1; |
73 | |
74 | log_procname = getprogname(); |
75 | |
76 | log_init(1); /* log to stderr until daemonized */ |
77 | log_verbose(1); |
78 | |
79 | while ((ch = getopt(argc, argv, "dn:s:v")) != -1) { |
80 | switch (ch) { |
81 | case 'd': |
82 | debug = 1; |
83 | break; |
84 | case 'n': |
85 | vscsidev = optarg; |
86 | break; |
87 | case 's': |
88 | ctrlsock = optarg; |
89 | break; |
90 | case 'v': |
91 | verbose = 1; |
92 | break; |
93 | default: |
94 | usage(); |
95 | /* NOTREACHED */ |
96 | } |
97 | } |
98 | |
99 | argc -= optind; |
100 | argv += optind; |
Value stored to 'argv' is never read | |
101 | |
102 | if (argc > 0) |
103 | usage(); |
104 | |
105 | /* check for root privileges */ |
106 | if (geteuid()) |
107 | errx(1, "need root privileges"); |
108 | |
109 | log_init(debug); |
110 | log_verbose(verbose); |
111 | |
112 | if (control_init(ctrlsock) == -1) |
113 | fatalx("control socket setup failed"); |
114 | |
115 | if (!debug) |
116 | daemon(1, 0); |
117 | log_info("startup"); |
118 | |
119 | name[2] = getpid(); |
120 | if (sysctl(name, 3, NULL((void *)0), 0, &nobkill, sizeof(nobkill)) != 0) |
121 | fatal("sysctl"); |
122 | |
123 | event_init(); |
124 | vscsi_open(vscsidev); |
125 | |
126 | /* chroot and drop to iscsid user */ |
127 | if ((pw = getpwnam(ISCSID_USER"_iscsid")) == NULL((void *)0)) |
128 | errx(1, "unknown user %s", ISCSID_USER"_iscsid"); |
129 | |
130 | if (chroot(pw->pw_dir) == -1) |
131 | fatal("chroot"); |
132 | if (chdir("/") == -1) |
133 | fatal("chdir(\"/\")"); |
134 | if (setgroups(1, &pw->pw_gid) || |
135 | setresgid(pw->pw_gid, pw->pw_gid, pw->pw_gid) || |
136 | setresuid(pw->pw_uid, pw->pw_uid, pw->pw_uid)) |
137 | fatal("can't drop privileges"); |
138 | |
139 | /* setup signal handler */ |
140 | signal_set(&ev_sigint, SIGINT, main_sig_handler, NULL)event_set(&ev_sigint, 2, 0x08|0x10, main_sig_handler, ((void *)0)); |
141 | signal_set(&ev_sigterm, SIGTERM, main_sig_handler, NULL)event_set(&ev_sigterm, 15, 0x08|0x10, main_sig_handler, ( (void *)0)); |
142 | signal_set(&ev_sighup, SIGHUP, main_sig_handler, NULL)event_set(&ev_sighup, 1, 0x08|0x10, main_sig_handler, ((void *)0)); |
143 | signal_add(&ev_sigint, NULL)event_add(&ev_sigint, ((void *)0)); |
144 | signal_add(&ev_sigterm, NULL)event_add(&ev_sigterm, ((void *)0)); |
145 | signal_add(&ev_sighup, NULL)event_add(&ev_sighup, ((void *)0)); |
146 | signal(SIGPIPE13, SIG_IGN(void (*)(int))1); |
147 | |
148 | control_event_init(); |
149 | initiator = initiator_init(); |
150 | |
151 | event_dispatch(); |
152 | |
153 | /* do some cleanup on the way out */ |
154 | control_cleanup(ctrlsock); |
155 | initiator_cleanup(initiator); |
156 | log_info("exiting."); |
157 | return 0; |
158 | } |
159 | |
160 | void |
161 | shutdown_cb(int fd, short event, void *arg) |
162 | { |
163 | struct timeval tv; |
164 | |
165 | if (exit_rounds++ >= ISCSI_EXIT_WAIT5 || initiator_isdown(initiator)) |
166 | event_loopexit(NULL((void *)0)); |
167 | |
168 | timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0; |
169 | tv.tv_sec = 1; |
170 | |
171 | if (evtimer_add(&exit_ev, &tv)event_add(&exit_ev, &tv) == -1) |
172 | fatal("shutdown_cb"); |
173 | } |
174 | |
175 | void |
176 | main_sig_handler(int sig, short event, void *arg) |
177 | { |
178 | struct timeval tv; |
179 | |
180 | /* signal handler rules don't apply, libevent decouples for us */ |
181 | switch (sig) { |
182 | case SIGTERM15: |
183 | case SIGINT2: |
184 | case SIGHUP1: |
185 | initiator_shutdown(initiator); |
186 | evtimer_set(&exit_ev, shutdown_cb, NULL)event_set(&exit_ev, -1, 0, shutdown_cb, ((void *)0)); |
187 | timerclear(&tv)(&tv)->tv_sec = (&tv)->tv_usec = 0; |
188 | if (evtimer_add(&exit_ev, &tv)event_add(&exit_ev, &tv) == -1) |
189 | fatal("main_sig_handler"); |
190 | break; |
191 | default: |
192 | fatalx("unexpected signal"); |
193 | /* NOTREACHED */ |
194 | } |
195 | } |
196 | |
197 | __dead__attribute__((__noreturn__)) void |
198 | usage(void) |
199 | { |
200 | extern char *__progname; |
201 | |
202 | fprintf(stderr(&__sF[2]), "usage: %s [-dv] [-n device] [-s socket]\n", |
203 | __progname); |
204 | exit(1); |
205 | } |
206 | |
207 | void |
208 | iscsid_ctrl_dispatch(void *ch, struct pdu *pdu) |
209 | { |
210 | struct ctrlmsghdr *cmh; |
211 | struct initiator_config *ic; |
212 | struct session_config *sc; |
213 | struct session *s; |
214 | struct session_poll p = { 0 }; |
215 | int *valp; |
216 | |
217 | cmh = pdu_getbuf(pdu, NULL((void *)0), 0); |
218 | if (cmh == NULL((void *)0)) |
219 | goto done; |
220 | |
221 | switch (cmh->type) { |
222 | case CTRL_INITIATOR_CONFIG4: |
223 | if (cmh->len[0] != sizeof(*ic)) { |
224 | log_warnx("CTRL_INITIATOR_CONFIG bad size"); |
225 | control_compose(ch, CTRL_FAILURE2, NULL((void *)0), 0); |
226 | break; |
227 | } |
228 | ic = pdu_getbuf(pdu, NULL((void *)0), 1); |
229 | memcpy(&initiator->config, ic, sizeof(initiator->config)); |
230 | control_compose(ch, CTRL_SUCCESS1, NULL((void *)0), 0); |
231 | break; |
232 | case CTRL_SESSION_CONFIG5: |
233 | if (cmh->len[0] != sizeof(*sc)) { |
234 | log_warnx("CTRL_SESSION_CONFIG bad size"); |
235 | control_compose(ch, CTRL_FAILURE2, NULL((void *)0), 0); |
236 | break; |
237 | } |
238 | sc = pdu_getbuf(pdu, NULL((void *)0), 1); |
239 | if (cmh->len[1]) |
240 | sc->TargetName = pdu_getbuf(pdu, NULL((void *)0), 2); |
241 | else if (sc->SessionType != SESSION_TYPE_DISCOVERY1) { |
242 | control_compose(ch, CTRL_FAILURE2, NULL((void *)0), 0); |
243 | goto done; |
244 | } else |
245 | sc->TargetName = NULL((void *)0); |
246 | if (cmh->len[2]) |
247 | sc->InitiatorName = pdu_getbuf(pdu, NULL((void *)0), 3); |
248 | else |
249 | sc->InitiatorName = NULL((void *)0); |
250 | |
251 | s = session_find(initiator, sc->SessionName); |
252 | if (s == NULL((void *)0)) { |
253 | s = session_new(initiator, sc->SessionType); |
254 | if (s == NULL((void *)0)) { |
255 | control_compose(ch, CTRL_FAILURE2, NULL((void *)0), 0); |
256 | goto done; |
257 | } |
258 | } |
259 | |
260 | session_config(s, sc); |
261 | if (s->state == SESS_INIT0x0001) |
262 | session_fsm(s, SESS_EV_START, NULL((void *)0), 0); |
263 | |
264 | control_compose(ch, CTRL_SUCCESS1, NULL((void *)0), 0); |
265 | break; |
266 | case CTRL_LOG_VERBOSE6: |
267 | if (cmh->len[0] != sizeof(int)) { |
268 | log_warnx("CTRL_LOG_VERBOSE bad size"); |
269 | control_compose(ch, CTRL_FAILURE2, NULL((void *)0), 0); |
270 | break; |
271 | } |
272 | valp = pdu_getbuf(pdu, NULL((void *)0), 1); |
273 | log_verbose(*valp); |
274 | control_compose(ch, CTRL_SUCCESS1, NULL((void *)0), 0); |
275 | break; |
276 | case CTRL_VSCSI_STATS7: |
277 | control_compose(ch, CTRL_VSCSI_STATS7, vscsi_stats(), |
278 | sizeof(struct vscsi_stats)); |
279 | break; |
280 | case CTRL_SHOW_SUM8: |
281 | control_compose(ch, CTRL_INITIATOR_CONFIG4, &initiator->config, |
282 | sizeof(initiator->config)); |
283 | |
284 | TAILQ_FOREACH(s, &initiator->sessions, entry)for((s) = ((&initiator->sessions)->tqh_first); (s) != ((void *)0); (s) = ((s)->entry.tqe_next)) { |
285 | struct ctrldata cdv[3]; |
286 | bzero(cdv, sizeof(cdv)); |
287 | |
288 | cdv[0].buf = &s->config; |
289 | cdv[0].len = sizeof(s->config); |
290 | |
291 | if (s->config.TargetName) { |
292 | cdv[1].buf = s->config.TargetName; |
293 | cdv[1].len = |
294 | strlen(s->config.TargetName) + 1; |
295 | } |
296 | if (s->config.InitiatorName) { |
297 | cdv[2].buf = s->config.InitiatorName; |
298 | cdv[2].len = |
299 | strlen(s->config.InitiatorName) + 1; |
300 | } |
301 | |
302 | control_build(ch, CTRL_SESSION_CONFIG5, |
303 | nitems(cdv)(sizeof((cdv)) / sizeof((cdv)[0])), cdv); |
304 | } |
305 | |
306 | control_compose(ch, CTRL_SUCCESS1, NULL((void *)0), 0); |
307 | break; |
308 | case CTRL_SESS_POLL9: |
309 | TAILQ_FOREACH(s, &initiator->sessions, entry)for((s) = ((&initiator->sessions)->tqh_first); (s) != ((void *)0); (s) = ((s)->entry.tqe_next)) |
310 | poll_session(&p, s); |
311 | poll_finalize(&p); |
312 | control_compose(ch, CTRL_SESS_POLL9, &p, sizeof(p)); |
313 | break; |
314 | default: |
315 | log_warnx("unknown control message type %d", cmh->type); |
316 | control_compose(ch, CTRL_FAILURE2, NULL((void *)0), 0); |
317 | break; |
318 | } |
319 | |
320 | done: |
321 | pdu_free(pdu); |
322 | } |
323 | |
324 | #define MERGE_MIN(r, a, b, v) \ |
325 | r->v = (a->v < b->v ? a->v : b->v) |
326 | #define MERGE_MAX(r, a, b, v) \ |
327 | r->v = (a->v > b->v ? a->v : b->v) |
328 | #define MERGE_OR(r, a, b, v) \ |
329 | r->v = (a->v || b->v) |
330 | #define MERGE_AND(r, a, b, v) \ |
331 | r->v = (a->v && b->v) |
332 | |
333 | void |
334 | iscsi_merge_sess_params(struct session_params *res, |
335 | struct session_params *mine, struct session_params *his) |
336 | { |
337 | MERGE_MIN(res, mine, his, MaxBurstLength); |
338 | MERGE_MIN(res, mine, his, FirstBurstLength); |
339 | MERGE_MAX(res, mine, his, DefaultTime2Wait); |
340 | MERGE_MIN(res, mine, his, DefaultTime2Retain); |
341 | MERGE_MIN(res, mine, his, MaxOutstandingR2T); |
342 | res->TargetPortalGroupTag = his->TargetPortalGroupTag; |
343 | MERGE_MIN(res, mine, his, MaxConnections); |
344 | MERGE_OR(res, mine, his, InitialR2T); |
345 | MERGE_AND(res, mine, his, ImmediateData); |
346 | MERGE_OR(res, mine, his, DataPDUInOrder); |
347 | MERGE_OR(res, mine, his, DataSequenceInOrder); |
348 | MERGE_MIN(res, mine, his, ErrorRecoveryLevel); |
349 | |
350 | } |
351 | |
352 | void |
353 | iscsi_merge_conn_params(struct connection_params *res, |
354 | struct connection_params *mine, struct connection_params *his) |
355 | { |
356 | res->MaxRecvDataSegmentLength = his->MaxRecvDataSegmentLength; |
357 | /* XXX HeaderDigest and DataDigest */ |
358 | } |
359 | |
360 | #undef MERGE_MIN |
361 | #undef MERGE_MAX |
362 | #undef MERGE_OR |
363 | #undef MERGE_AND |