ctdb-protocol: Fix marshalling for ctdb_event
[vlendec/samba-autobuild/.git] / ctdb / protocol / protocol_util.c
1 /*
2    CTDB protocol marshalling
3
4    Copyright (C) Amitay Isaacs  2015
5
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
10
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, see <http://www.gnu.org/licenses/>.
18 */
19
20 #include "replace.h"
21 #include "system/network.h"
22
23 #include <talloc.h>
24 #include <tdb.h>
25
26 #include "protocol.h"
27 #include "protocol_private.h"
28 #include "protocol_api.h"
29
30 static struct {
31         enum ctdb_runstate runstate;
32         const char * label;
33 } runstate_map[] = {
34         { CTDB_RUNSTATE_UNKNOWN, "UNKNOWN" },
35         { CTDB_RUNSTATE_INIT, "INIT" },
36         { CTDB_RUNSTATE_SETUP, "SETUP" },
37         { CTDB_RUNSTATE_FIRST_RECOVERY, "FIRST_RECOVERY" },
38         { CTDB_RUNSTATE_STARTUP, "STARTUP" },
39         { CTDB_RUNSTATE_RUNNING, "RUNNING" },
40         { CTDB_RUNSTATE_SHUTDOWN, "SHUTDOWN" },
41         { -1, NULL },
42 };
43
44 const char *ctdb_runstate_to_string(enum ctdb_runstate runstate)
45 {
46         int i;
47
48         for (i=0; runstate_map[i].label != NULL; i++) {
49                 if (runstate_map[i].runstate == runstate) {
50                         return runstate_map[i].label;
51                 }
52         }
53
54         return runstate_map[0].label;
55 }
56
57 enum ctdb_runstate ctdb_runstate_from_string(const char *runstate_str)
58 {
59         int i;
60
61         for (i=0; runstate_map[i].label != NULL; i++) {
62                 if (strcasecmp(runstate_map[i].label,
63                                runstate_str) == 0) {
64                         return runstate_map[i].runstate;
65                 }
66         }
67
68         return CTDB_RUNSTATE_UNKNOWN;
69 }
70
71 static struct {
72         enum ctdb_event event;
73         const char *label;
74 } event_map[] = {
75         { CTDB_EVENT_INIT, "init" },
76         { CTDB_EVENT_SETUP, "setup" },
77         { CTDB_EVENT_STARTUP, "startup" },
78         { CTDB_EVENT_START_RECOVERY, "startrecovery" },
79         { CTDB_EVENT_RECOVERED, "recovered" },
80         { CTDB_EVENT_TAKE_IP, "takeip" },
81         { CTDB_EVENT_RELEASE_IP, "releaseip" },
82         { CTDB_EVENT_MONITOR, "monitor" },
83         { CTDB_EVENT_SHUTDOWN, "shutdown" },
84         { CTDB_EVENT_UPDATE_IP, "updateip" },
85         { CTDB_EVENT_IPREALLOCATED, "ipreallocated" },
86         { CTDB_EVENT_MAX, "all" },
87         { -1, NULL },
88 };
89
90 const char *ctdb_event_to_string(enum ctdb_event event)
91 {
92         int i;
93
94         for (i=0; event_map[i].label != NULL; i++) {
95                 if (event_map[i].event == event) {
96                         return event_map[i].label;
97                 }
98         }
99
100         return "unknown";
101 }
102
103 enum ctdb_event ctdb_event_from_string(const char *event_str)
104 {
105         int i;
106
107         for (i=0; event_map[i].label != NULL; i++) {
108                 if (strcmp(event_map[i].label, event_str) == 0) {
109                         return event_map[i].event;
110                 }
111         }
112
113         return CTDB_EVENT_MAX;
114 }
115
116 const char *ctdb_sock_addr_to_string(TALLOC_CTX *mem_ctx, ctdb_sock_addr *addr)
117 {
118         char *cip;
119
120         cip = talloc_size(mem_ctx, 128);
121         if (cip == NULL) {
122                 return "Memory Error";
123         }
124
125         switch (addr->sa.sa_family) {
126         case AF_INET:
127                 inet_ntop(addr->ip.sin_family, &addr->ip.sin_addr,
128                           cip, 128);
129                 break;
130
131         case AF_INET6:
132                 inet_ntop(addr->ip6.sin6_family, &addr->ip6.sin6_addr,
133                           cip, 128);
134                 break;
135
136         default:
137                 sprintf(cip, "Unknown family %u", addr->sa.sa_family);
138                 break;
139         }
140
141         return cip;
142 }
143
144 int ctdb_sock_addr_cmp_ip(const ctdb_sock_addr *addr1,
145                           const ctdb_sock_addr *addr2)
146 {
147         int ret = 0;
148
149         /* This is somewhat arbitrary.  However, when used for sorting
150          * it just needs to be consistent.
151          */
152         if (addr1->sa.sa_family < addr2->sa.sa_family) {
153                 return -1;
154         }
155         if (addr1->sa.sa_family > addr2->sa.sa_family) {
156                 return 1;
157         }
158
159         switch (addr1->sa.sa_family) {
160         case AF_INET:
161                 ret = memcmp(&addr1->ip.sin_addr.s_addr,
162                              &addr2->ip.sin_addr.s_addr, 4);
163                 break;
164
165         case AF_INET6:
166                 ret = memcmp(addr1->ip6.sin6_addr.s6_addr,
167                              addr2->ip6.sin6_addr.s6_addr, 16);
168                 break;
169
170         default:
171                 ret = -1;
172         }
173
174         return ret;
175 }
176
177 int ctdb_sock_addr_cmp(const ctdb_sock_addr *addr1,
178                        const ctdb_sock_addr *addr2)
179 {
180         int ret = 0;
181
182         ret = ctdb_sock_addr_cmp_ip(addr1, addr2);
183         if (ret != 0) {
184                 return ret;
185         }
186
187         switch (addr1->sa.sa_family) {
188         case AF_INET:
189                 if (addr1->ip.sin_port < addr2->ip.sin_port) {
190                         ret = -1;
191                 } else if (addr1->ip.sin_port > addr2->ip.sin_port) {
192                         ret = 1;
193                 }
194                 break;
195
196         case AF_INET6:
197                 if (addr1->ip6.sin6_port < addr2->ip6.sin6_port) {
198                         ret = -1;
199                 } else if (addr1->ip6.sin6_port > addr2->ip6.sin6_port) {
200                         ret = 1;
201                 }
202                 break;
203
204         default:
205                 ret = -1;
206         }
207
208         return ret;
209 }
210
211 bool ctdb_sock_addr_same_ip(const ctdb_sock_addr *addr1,
212                             const ctdb_sock_addr *addr2)
213 {
214         return (ctdb_sock_addr_cmp_ip(addr1, addr2) == 0);
215 }
216
217 bool ctdb_sock_addr_same(const ctdb_sock_addr *addr1,
218                          const ctdb_sock_addr *addr2)
219 {
220         return (ctdb_sock_addr_cmp(addr1, addr2) == 0);
221 }