1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3 *
4 * Copyright (c) 2010 Pawel Jakub Dawidek <pjd@FreeBSD.org>
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
27 */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD: stable/12/sbin/hastd/event.c 326276 2017-11-27 15:37:16Z pfg $");
31
32 #include <errno.h>
33
34 #include "hast.h"
35 #include "hast_proto.h"
36 #include "hooks.h"
37 #include "nv.h"
38 #include "pjdlog.h"
39 #include "proto.h"
40 #include "subr.h"
41
42 #include "event.h"
43
44 void
event_send(const struct hast_resource * res,int event)45 event_send(const struct hast_resource *res, int event)
46 {
47 struct nv *nvin, *nvout;
48 int error;
49
50 PJDLOG_ASSERT(res != NULL);
51 PJDLOG_ASSERT(event >= EVENT_MIN && event <= EVENT_MAX);
52
53 nvin = nvout = NULL;
54
55 /*
56 * Prepare and send event to parent process.
57 */
58 nvout = nv_alloc();
59 nv_add_uint8(nvout, (uint8_t)event, "event");
60 error = nv_error(nvout);
61 if (error != 0) {
62 pjdlog_common(LOG_ERR, 0, error,
63 "Unable to prepare event header");
64 goto done;
65 }
66 if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) == -1) {
67 pjdlog_errno(LOG_ERR, "Unable to send event header");
68 goto done;
69 }
70 if (hast_proto_recv_hdr(res->hr_event, &nvin) == -1) {
71 pjdlog_errno(LOG_ERR, "Unable to receive event header");
72 goto done;
73 }
74 /*
75 * Do nothing with the answer. We only wait for it to be sure not
76 * to exit too quickly after sending an event and exiting immediately.
77 */
78 done:
79 if (nvin != NULL)
80 nv_free(nvin);
81 if (nvout != NULL)
82 nv_free(nvout);
83 }
84
85 int
event_recv(const struct hast_resource * res)86 event_recv(const struct hast_resource *res)
87 {
88 struct nv *nvin, *nvout;
89 const char *evstr;
90 uint8_t event;
91 int error;
92
93 PJDLOG_ASSERT(res != NULL);
94
95 nvin = nvout = NULL;
96
97 if (hast_proto_recv_hdr(res->hr_event, &nvin) == -1) {
98 /*
99 * First error log as debug. This is because worker process
100 * most likely exited.
101 */
102 pjdlog_common(LOG_DEBUG, 1, errno,
103 "Unable to receive event header");
104 goto fail;
105 }
106
107 event = nv_get_uint8(nvin, "event");
108 if (event == EVENT_NONE) {
109 pjdlog_error("Event header is missing 'event' field.");
110 goto fail;
111 }
112
113 switch (event) {
114 case EVENT_CONNECT:
115 evstr = "connect";
116 break;
117 case EVENT_DISCONNECT:
118 evstr = "disconnect";
119 break;
120 case EVENT_SYNCSTART:
121 evstr = "syncstart";
122 break;
123 case EVENT_SYNCDONE:
124 evstr = "syncdone";
125 break;
126 case EVENT_SYNCINTR:
127 evstr = "syncintr";
128 break;
129 case EVENT_SPLITBRAIN:
130 evstr = "split-brain";
131 break;
132 default:
133 pjdlog_error("Event header contain invalid event number (%hhu).",
134 event);
135 goto fail;
136 }
137
138 pjdlog_prefix_set("[%s] (%s) ", res->hr_name, role2str(res->hr_role));
139 hook_exec(res->hr_exec, evstr, res->hr_name, NULL);
140 pjdlog_prefix_set("%s", "");
141
142 nvout = nv_alloc();
143 nv_add_int16(nvout, 0, "error");
144 error = nv_error(nvout);
145 if (error != 0) {
146 pjdlog_common(LOG_ERR, 0, error,
147 "Unable to prepare event header");
148 goto fail;
149 }
150 if (hast_proto_send(res, res->hr_event, nvout, NULL, 0) == -1) {
151 pjdlog_errno(LOG_ERR, "Unable to send event header");
152 goto fail;
153 }
154 nv_free(nvin);
155 nv_free(nvout);
156 return (0);
157 fail:
158 if (nvin != NULL)
159 nv_free(nvin);
160 if (nvout != NULL)
161 nv_free(nvout);
162 return (-1);
163 }
164