/
events.c
95 lines (75 loc) · 2.4 KB
/
events.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
/*
* Copyright (c) 2014 Daniel Malon <daniel.malon@me.com>
* See LICENSE file for copyright and license details.
*/
#include <sys/zone.h>
#include <libsysevent.h>
#include <libzonecfg.h>
#include <strings.h>
#include <unistd.h>
#include "gate.h"
// XXX: maybe use zonecfg_notify_bind()
// https://github.com/joyent/illumos-joyent/blob/master/usr/src/lib/libzdoor/common/zdoor.c
static int
sysev_evc_handler(sysevent_t *ev, void *cookie)
{
char *name, *zonename, *oldstate, *newstate;
nvlist_t *nvlist;
nvpair_t *curr, *next;
cookie = cookie; // SILENCE!
if (sysevent_get_attr_list(ev, &nvlist) != 0) {
// XXX Error
return (1);
}
// loop through event nvpairs to get our interesting values
curr = nvlist_next_nvpair(nvlist, NULL);
while (curr != NULL) {
// all fields we're interested in are strings
if (nvpair_type(curr) == DATA_TYPE_STRING) {
name = nvpair_name(curr);
if (strcmp(name, ZONE_CB_NAME) == 0) {
nvpair_value_string(curr, &zonename);
} else if (strcmp(name, ZONE_CB_NEWSTATE) == 0) {
nvpair_value_string(curr, &newstate);
} else if (strcmp(name, ZONE_CB_OLDSTATE) == 0) {
nvpair_value_string(curr, &oldstate);
}
}
next = nvlist_next_nvpair(nvlist, curr);
curr = next;
}
// if it is a boot into running we need to enable the gate
if (strcmp(oldstate, ZONE_EVENT_READY) == 0 &&
strcmp(newstate, ZONE_EVENT_RUNNING) == 0) {
gate_attach(zonename);
}
// ignore multiple shutting_down -> shutting_down transitions
if (strcmp(oldstate, newstate) != 0) {
char zonebrand[MAXNAMELEN];
// get brand for zone
if (zone_get_brand(zonename, zonebrand, sizeof (zonebrand)) == Z_OK) {
request_send_state_event(zonename, zonebrand, oldstate, newstate);
} else {
request_send_state_event(zonename, NULL, oldstate, newstate);
}
}
return (0);
}
int
zone_events_init()
{
int res;
evchan_t *ch;
char subid[16];
if ((res = sysevent_evc_bind(ZONE_EVENT_CHANNEL, &ch, 0)) != 0) {
fprintf(stderr, "failed to bind to sysevent channel: %d\n", res);
return (-1);
}
snprintf(subid, sizeof (subid), "gate-%ld", (long int)getpid());
if ((res = sysevent_evc_subscribe(ch, subid, ZONE_EVENT_STATUS_CLASS,
sysev_evc_handler, (void *)ZONE_EVENT_CHANNEL, 0)) != 0) {
fprintf(stderr, "failed to subscribe to channel: %d\n", res);
return (-1);
}
return (0);
}