]>
Commit | Line | Data |
---|---|---|
0ad19a3f | 1 | /* |
2 | * lxc: linux Container library | |
3 | * | |
4 | * (C) Copyright IBM Corp. 2007, 2008 | |
5 | * | |
6 | * Authors: | |
7 | * Daniel Lezcano <dlezcano at fr.ibm.com> | |
8 | * | |
9 | * This library is free software; you can redistribute it and/or | |
10 | * modify it under the terms of the GNU Lesser General Public | |
11 | * License as published by the Free Software Foundation; either | |
12 | * version 2.1 of the License, or (at your option) any later version. | |
13 | * | |
14 | * This library is distributed in the hope that it will be useful, | |
15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 | * Lesser General Public License for more details. | |
18 | * | |
19 | * You should have received a copy of the GNU Lesser General Public | |
20 | * License along with this library; if not, write to the Free Software | |
21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | |
22 | */ | |
23 | #include <stdio.h> | |
24 | #include <errno.h> | |
25 | #include <unistd.h> | |
26 | #include <string.h> | |
27 | #include <stdlib.h> | |
28 | #include <fcntl.h> | |
29 | #include <sys/types.h> | |
30 | #include <sys/stat.h> | |
31 | #include <sys/param.h> | |
32 | #include <sys/inotify.h> | |
33 | #include <sys/socket.h> | |
0ad19a3f | 34 | #include <netinet/in.h> |
35 | #include <net/if.h> | |
80f41298 | 36 | #include <linux/netlink.h> |
37 | #include <linux/rtnetlink.h> | |
b113348e | 38 | |
e2bcd7db | 39 | #include "error.h" |
b113348e | 40 | #include <lxc/lxc.h> |
0ad19a3f | 41 | |
42 | #ifndef UNIX_PATH_MAX | |
43 | #define UNIX_PATH_MAX 108 | |
44 | #endif | |
45 | ||
80f41298 | 46 | #ifndef SOL_NETLINK |
47 | #define SOL_NETLINK 270 | |
48 | #endif | |
49 | ||
50 | /* assuming this multicast group is not used by anyone else :/ | |
51 | * otherwise a new genetlink family should be defined to own | |
52 | * its multicast groups */ | |
53 | #define MONITOR_MCGROUP RTNLGRP_MAX | |
54 | ||
0ad19a3f | 55 | int lxc_monitor(const char *name, int output_fd) |
56 | { | |
57 | char path[MAXPATHLEN]; | |
58 | int err = -1, nfd, wfd, state; | |
59 | ||
60 | nfd = inotify_init(); | |
61 | if (nfd < 0) { | |
62 | lxc_log_syserror("failed to initialize inotify"); | |
63 | return -1; | |
64 | } | |
65 | ||
66 | snprintf(path, MAXPATHLEN, LXCPATH "/%s/state", name); | |
67 | ||
68 | wfd = inotify_add_watch(nfd, path, IN_DELETE_SELF|IN_CLOSE_WRITE); | |
69 | if (wfd < 0) { | |
70 | lxc_log_syserror("failed to add a watch on %s", path); | |
71 | goto out; | |
72 | } | |
73 | ||
74 | for(;;) { | |
75 | struct inotify_event evt; | |
76 | ||
77 | if (read(nfd, &evt, sizeof(evt)) < 0) { | |
78 | lxc_log_syserror("failed to read inotify event"); | |
79 | goto out; | |
80 | } | |
81 | ||
82 | if (evt.mask & IN_CLOSE_WRITE) { | |
83 | ||
84 | state = lxc_getstate(name); | |
85 | if (state < 0) { | |
86 | lxc_log_error("failed to get the state for %s", | |
87 | name); | |
88 | goto out; | |
89 | } | |
90 | ||
91 | if (write(output_fd, &state, sizeof(state)) < 0) { | |
92 | lxc_log_syserror("failed to send state to %d", | |
93 | output_fd); | |
94 | goto out; | |
95 | } | |
96 | continue; | |
97 | } | |
98 | ||
99 | if (evt.mask & IN_DELETE_SELF) { | |
100 | close(output_fd); | |
101 | err = 0; | |
102 | goto out; | |
103 | } | |
104 | ||
105 | lxc_log_error("unknown evt for inotity (%d)", evt.mask); | |
106 | goto out; | |
107 | } | |
108 | ||
109 | out: | |
110 | inotify_rm_watch(nfd, wfd); | |
111 | close(nfd); | |
112 | return err; | |
113 | } | |
114 | ||
80f41298 | 115 | static void lxc_monitor_send(struct lxc_msg *msg) |
0ad19a3f | 116 | { |
117 | int fd; | |
80f41298 | 118 | struct sockaddr_nl addr; |
0ad19a3f | 119 | |
80f41298 | 120 | fd = socket(PF_NETLINK, SOCK_RAW, 0); |
eae6543d | 121 | if (fd < 0) { |
0ad19a3f | 122 | lxc_log_syserror("failed to create notification socket"); |
eae6543d | 123 | return; |
124 | } | |
0ad19a3f | 125 | |
126 | memset(&addr, 0, sizeof(addr)); | |
80f41298 | 127 | |
128 | addr.nl_family = AF_NETLINK; | |
129 | addr.nl_pid = 0; | |
130 | addr.nl_groups = MONITOR_MCGROUP; | |
0ad19a3f | 131 | |
eae6543d | 132 | sendto(fd, msg, sizeof(*msg), 0, |
0ad19a3f | 133 | (const struct sockaddr *)&addr, sizeof(addr)); |
134 | ||
135 | close(fd); | |
136 | } | |
137 | ||
eae6543d | 138 | void lxc_monitor_send_state(const char *name, lxc_state_t state) |
139 | { | |
140 | struct lxc_msg msg = { .type = lxc_msg_state, | |
141 | .value = state }; | |
80f41298 | 142 | strncpy(msg.name, name, sizeof(msg.name)); |
eae6543d | 143 | |
80f41298 | 144 | lxc_monitor_send(&msg); |
0ad19a3f | 145 | } |
146 | ||
80f41298 | 147 | int lxc_monitor_open(void) |
0ad19a3f | 148 | { |
149 | int fd; | |
80f41298 | 150 | struct sockaddr_nl addr; |
0ad19a3f | 151 | |
80f41298 | 152 | fd = socket(PF_NETLINK, SOCK_RAW, 0); |
0ad19a3f | 153 | if (fd < 0) { |
154 | lxc_log_syserror("failed to create notification socket"); | |
e2bcd7db | 155 | return -LXC_ERROR_INTERNAL; |
0ad19a3f | 156 | } |
157 | ||
158 | memset(&addr, 0, sizeof(addr)); | |
159 | ||
80f41298 | 160 | addr.nl_family = AF_NETLINK; |
161 | addr.nl_pid = 0; | |
162 | addr.nl_groups = MONITOR_MCGROUP; | |
0ad19a3f | 163 | |
164 | if (bind(fd, (const struct sockaddr *)&addr, sizeof(addr))) { | |
80f41298 | 165 | lxc_log_syserror("failed to bind to multicast group '%d'", |
166 | addr.nl_groups); | |
0ad19a3f | 167 | close(fd); |
168 | return -1; | |
169 | } | |
170 | ||
171 | return fd; | |
172 | } | |
173 | ||
eae6543d | 174 | int lxc_monitor_read(int fd, struct lxc_msg *msg) |
0ad19a3f | 175 | { |
80f41298 | 176 | struct sockaddr_nl from; |
177 | socklen_t len = sizeof(from); | |
0ad19a3f | 178 | int ret; |
179 | ||
80f41298 | 180 | ret = recvfrom(fd, msg, sizeof(*msg), 0, |
181 | (struct sockaddr *)&from, &len); | |
0ad19a3f | 182 | if (ret < 0) { |
183 | lxc_log_syserror("failed to received state"); | |
e2bcd7db | 184 | return -LXC_ERROR_INTERNAL; |
0ad19a3f | 185 | } |
186 | ||
187 | return ret; | |
188 | } | |
189 | ||
190 | int lxc_monitor_close(int fd) | |
191 | { | |
192 | return close(fd); | |
193 | } |