1 /*
2 * Copyright 2018 Google, Inc
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 #ifndef _LMKD_H_
18 #define _LMKD_H_
19
20 #include <arpa/inet.h>
21 #include <sys/cdefs.h>
22 #include <sys/types.h>
23
24 __BEGIN_DECLS
25
26 /*
27 * Supported LMKD commands
28 */
29 enum lmk_cmd {
30 LMK_TARGET = 0, /* Associate minfree with oom_adj_score */
31 LMK_PROCPRIO, /* Register a process and set its oom_adj_score */
32 LMK_PROCREMOVE, /* Unregister a process */
33 LMK_PROCPURGE, /* Purge all registered processes */
34 LMK_GETKILLCNT, /* Get number of kills */
35 LMK_SUBSCRIBE, /* Subscribe for asynchronous events */
36 LMK_PROCKILL, /* Unsolicited msg to subscribed clients on proc kills */
37 LMK_UPDATE_PROPS, /* Reinit properties */
38 LMK_STAT_KILL_OCCURRED, /* Unsolicited msg to subscribed clients on proc kills for statsd log */
39 LMK_STAT_STATE_CHANGED, /* Unsolicited msg to subscribed clients on state changed */
40 };
41
42 /*
43 * Max number of targets in LMK_TARGET command.
44 */
45 #define MAX_TARGETS 6
46
47 /*
48 * Max packet length in bytes.
49 * Longest packet is LMK_TARGET followed by MAX_TARGETS
50 * of minfree and oom_adj_score values
51 */
52 #define CTRL_PACKET_MAX_SIZE (sizeof(int) * (MAX_TARGETS * 2 + 1))
53
54 /* LMKD packet - first int is lmk_cmd followed by payload */
55 typedef int LMKD_CTRL_PACKET[CTRL_PACKET_MAX_SIZE / sizeof(int)];
56
57 /* Get LMKD packet command */
lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack)58 static inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) {
59 return (enum lmk_cmd)ntohl(pack[0]);
60 }
61
62 /* LMK_TARGET packet payload */
63 struct lmk_target {
64 int minfree;
65 int oom_adj_score;
66 };
67
68 /*
69 * For LMK_TARGET packet get target_idx-th payload.
70 * Warning: no checks performed, caller should ensure valid parameters.
71 */
lmkd_pack_get_target(LMKD_CTRL_PACKET packet,int target_idx,struct lmk_target * target)72 static inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet, int target_idx,
73 struct lmk_target* target) {
74 target->minfree = ntohl(packet[target_idx * 2 + 1]);
75 target->oom_adj_score = ntohl(packet[target_idx * 2 + 2]);
76 }
77
78 /*
79 * Prepare LMK_TARGET packet and return packet size in bytes.
80 * Warning: no checks performed, caller should ensure valid parameters.
81 */
lmkd_pack_set_target(LMKD_CTRL_PACKET packet,struct lmk_target * targets,size_t target_cnt)82 static inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet, struct lmk_target* targets,
83 size_t target_cnt) {
84 int idx = 0;
85 packet[idx++] = htonl(LMK_TARGET);
86 while (target_cnt) {
87 packet[idx++] = htonl(targets->minfree);
88 packet[idx++] = htonl(targets->oom_adj_score);
89 targets++;
90 target_cnt--;
91 }
92 return idx * sizeof(int);
93 }
94
95 /* Process types for lmk_procprio.ptype */
96 enum proc_type {
97 PROC_TYPE_FIRST,
98 PROC_TYPE_APP = PROC_TYPE_FIRST,
99 PROC_TYPE_SERVICE,
100 PROC_TYPE_COUNT,
101 };
102
103 /* LMK_PROCPRIO packet payload */
104 struct lmk_procprio {
105 pid_t pid;
106 uid_t uid;
107 int oomadj;
108 enum proc_type ptype;
109 };
110
111 /*
112 * For LMK_PROCPRIO packet get its payload.
113 * Warning: no checks performed, caller should ensure valid parameters.
114 */
lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet,int field_count,struct lmk_procprio * params)115 static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, int field_count,
116 struct lmk_procprio* params) {
117 params->pid = (pid_t)ntohl(packet[1]);
118 params->uid = (uid_t)ntohl(packet[2]);
119 params->oomadj = ntohl(packet[3]);
120 /* if field is missing assume PROC_TYPE_APP for backward compatibility */
121 params->ptype = field_count > 3 ? (enum proc_type)ntohl(packet[4]) : PROC_TYPE_APP;
122 }
123
124 /*
125 * Prepare LMK_PROCPRIO packet and return packet size in bytes.
126 * Warning: no checks performed, caller should ensure valid parameters.
127 */
lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet,struct lmk_procprio * params)128 static inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
129 packet[0] = htonl(LMK_PROCPRIO);
130 packet[1] = htonl(params->pid);
131 packet[2] = htonl(params->uid);
132 packet[3] = htonl(params->oomadj);
133 packet[4] = htonl((int)params->ptype);
134 return 5 * sizeof(int);
135 }
136
137 /* LMK_PROCREMOVE packet payload */
138 struct lmk_procremove {
139 pid_t pid;
140 };
141
142 /*
143 * For LMK_PROCREMOVE packet get its payload.
144 * Warning: no checks performed, caller should ensure valid parameters.
145 */
lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,struct lmk_procremove * params)146 static inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,
147 struct lmk_procremove* params) {
148 params->pid = (pid_t)ntohl(packet[1]);
149 }
150
151 /*
152 * Prepare LMK_PROCREMOVE packet and return packet size in bytes.
153 * Warning: no checks performed, caller should ensure valid parameters.
154 */
lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,struct lmk_procremove * params)155 static inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
156 struct lmk_procremove* params) {
157 packet[0] = htonl(LMK_PROCREMOVE);
158 packet[1] = htonl(params->pid);
159 return 2 * sizeof(int);
160 }
161
162 /*
163 * Prepare LMK_PROCPURGE packet and return packet size in bytes.
164 * Warning: no checks performed, caller should ensure valid parameters.
165 */
lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet)166 static inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
167 packet[0] = htonl(LMK_PROCPURGE);
168 return sizeof(int);
169 }
170
171 /* LMK_GETKILLCNT packet payload */
172 struct lmk_getkillcnt {
173 int min_oomadj;
174 int max_oomadj;
175 };
176
177 /*
178 * For LMK_GETKILLCNT packet get its payload.
179 * Warning: no checks performed, caller should ensure valid parameters.
180 */
lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,struct lmk_getkillcnt * params)181 static inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
182 struct lmk_getkillcnt* params) {
183 params->min_oomadj = ntohl(packet[1]);
184 params->max_oomadj = ntohl(packet[2]);
185 }
186
187 /*
188 * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
189 * Warning: no checks performed, caller should ensure valid parameters.
190 */
lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,struct lmk_getkillcnt * params)191 static inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
192 struct lmk_getkillcnt* params) {
193 packet[0] = htonl(LMK_GETKILLCNT);
194 packet[1] = htonl(params->min_oomadj);
195 packet[2] = htonl(params->max_oomadj);
196 return 3 * sizeof(int);
197 }
198
199 /*
200 * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
201 * Warning: no checks performed, caller should ensure valid parameters.
202 */
lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet,int kill_cnt)203 static inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
204 packet[0] = htonl(LMK_GETKILLCNT);
205 packet[1] = htonl(kill_cnt);
206 return 2 * sizeof(int);
207 }
208
209 /* Types of asynchronous events sent from lmkd to its clients */
210 enum async_event_type {
211 LMK_ASYNC_EVENT_FIRST,
212 LMK_ASYNC_EVENT_KILL = LMK_ASYNC_EVENT_FIRST,
213 LMK_ASYNC_EVENT_STAT,
214 LMK_ASYNC_EVENT_COUNT,
215 };
216
217 /* LMK_SUBSCRIBE packet payload */
218 struct lmk_subscribe {
219 enum async_event_type evt_type;
220 };
221
222 /*
223 * For LMK_SUBSCRIBE packet get its payload.
224 * Warning: no checks performed, caller should ensure valid parameters.
225 */
lmkd_pack_get_subscribe(LMKD_CTRL_PACKET packet,struct lmk_subscribe * params)226 static inline void lmkd_pack_get_subscribe(LMKD_CTRL_PACKET packet, struct lmk_subscribe* params) {
227 params->evt_type = (enum async_event_type)ntohl(packet[1]);
228 }
229
230 /**
231 * Prepare LMK_SUBSCRIBE packet and return packet size in bytes.
232 * Warning: no checks performed, caller should ensure valid parameters.
233 */
lmkd_pack_set_subscribe(LMKD_CTRL_PACKET packet,enum async_event_type evt_type)234 static inline size_t lmkd_pack_set_subscribe(LMKD_CTRL_PACKET packet, enum async_event_type evt_type) {
235 packet[0] = htonl(LMK_SUBSCRIBE);
236 packet[1] = htonl((int)evt_type);
237 return 2 * sizeof(int);
238 }
239
240 /**
241 * Prepare LMK_PROCKILL unsolicited packet and return packet size in bytes.
242 * Warning: no checks performed, caller should ensure valid parameters.
243 */
lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet,pid_t pid,uid_t uid)244 static inline size_t lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet, pid_t pid, uid_t uid) {
245 packet[0] = htonl(LMK_PROCKILL);
246 packet[1] = htonl(pid);
247 packet[2] = htonl(uid);
248 return 3 * sizeof(int);
249 }
250
251 /*
252 * Prepare LMK_UPDATE_PROPS packet and return packet size in bytes.
253 * Warning: no checks performed, caller should ensure valid parameters.
254 */
lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet)255 static inline size_t lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet) {
256 packet[0] = htonl(LMK_UPDATE_PROPS);
257 return sizeof(int);
258 }
259
260 /*
261 * Prepare LMK_UPDATE_PROPS reply packet and return packet size in bytes.
262 * Warning: no checks performed, caller should ensure valid parameters.
263 */
lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet,int result)264 static inline size_t lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet, int result) {
265 packet[0] = htonl(LMK_UPDATE_PROPS);
266 packet[1] = htonl(result);
267 return 2 * sizeof(int);
268 }
269
270 /* LMK_PROCPRIO reply payload */
271 struct lmk_update_props_reply {
272 int result;
273 };
274
275 /*
276 * For LMK_UPDATE_PROPS reply payload.
277 * Warning: no checks performed, caller should ensure valid parameters.
278 */
lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,struct lmk_update_props_reply * params)279 static inline void lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,
280 struct lmk_update_props_reply* params) {
281 params->result = ntohl(packet[1]);
282 }
283
284 __END_DECLS
285
286 #endif /* _LMKD_H_ */
287