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 };
39
40 /*
41 * Max number of targets in LMK_TARGET command.
42 */
43 #define MAX_TARGETS 6
44
45 /*
46 * Max packet length in bytes.
47 * Longest packet is LMK_TARGET followed by MAX_TARGETS
48 * of minfree and oom_adj_score values
49 */
50 #define CTRL_PACKET_MAX_SIZE (sizeof(int) * (MAX_TARGETS * 2 + 1))
51
52 /* LMKD packet - first int is lmk_cmd followed by payload */
53 typedef int LMKD_CTRL_PACKET[CTRL_PACKET_MAX_SIZE / sizeof(int)];
54
55 /* Get LMKD packet command */
lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack)56 static inline enum lmk_cmd lmkd_pack_get_cmd(LMKD_CTRL_PACKET pack) {
57 return (enum lmk_cmd)ntohl(pack[0]);
58 }
59
60 /* LMK_TARGET packet payload */
61 struct lmk_target {
62 int minfree;
63 int oom_adj_score;
64 };
65
66 /*
67 * For LMK_TARGET packet get target_idx-th payload.
68 * Warning: no checks performed, caller should ensure valid parameters.
69 */
lmkd_pack_get_target(LMKD_CTRL_PACKET packet,int target_idx,struct lmk_target * target)70 static inline void lmkd_pack_get_target(LMKD_CTRL_PACKET packet, int target_idx,
71 struct lmk_target* target) {
72 target->minfree = ntohl(packet[target_idx * 2 + 1]);
73 target->oom_adj_score = ntohl(packet[target_idx * 2 + 2]);
74 }
75
76 /*
77 * Prepare LMK_TARGET packet and return packet size in bytes.
78 * Warning: no checks performed, caller should ensure valid parameters.
79 */
lmkd_pack_set_target(LMKD_CTRL_PACKET packet,struct lmk_target * targets,size_t target_cnt)80 static inline size_t lmkd_pack_set_target(LMKD_CTRL_PACKET packet, struct lmk_target* targets,
81 size_t target_cnt) {
82 int idx = 0;
83 packet[idx++] = htonl(LMK_TARGET);
84 while (target_cnt) {
85 packet[idx++] = htonl(targets->minfree);
86 packet[idx++] = htonl(targets->oom_adj_score);
87 targets++;
88 target_cnt--;
89 }
90 return idx * sizeof(int);
91 }
92
93 /* Process types for lmk_procprio.ptype */
94 enum proc_type {
95 PROC_TYPE_FIRST,
96 PROC_TYPE_APP = PROC_TYPE_FIRST,
97 PROC_TYPE_SERVICE,
98 PROC_TYPE_COUNT,
99 };
100
101 /* LMK_PROCPRIO packet payload */
102 struct lmk_procprio {
103 pid_t pid;
104 uid_t uid;
105 int oomadj;
106 enum proc_type ptype;
107 };
108
109 /*
110 * For LMK_PROCPRIO packet get its payload.
111 * Warning: no checks performed, caller should ensure valid parameters.
112 */
lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet,int field_count,struct lmk_procprio * params)113 static inline void lmkd_pack_get_procprio(LMKD_CTRL_PACKET packet, int field_count,
114 struct lmk_procprio* params) {
115 params->pid = (pid_t)ntohl(packet[1]);
116 params->uid = (uid_t)ntohl(packet[2]);
117 params->oomadj = ntohl(packet[3]);
118 /* if field is missing assume PROC_TYPE_APP for backward compatibility */
119 params->ptype = field_count > 3 ? (enum proc_type)ntohl(packet[4]) : PROC_TYPE_APP;
120 }
121
122 /*
123 * Prepare LMK_PROCPRIO packet and return packet size in bytes.
124 * Warning: no checks performed, caller should ensure valid parameters.
125 */
lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet,struct lmk_procprio * params)126 static inline size_t lmkd_pack_set_procprio(LMKD_CTRL_PACKET packet, struct lmk_procprio* params) {
127 packet[0] = htonl(LMK_PROCPRIO);
128 packet[1] = htonl(params->pid);
129 packet[2] = htonl(params->uid);
130 packet[3] = htonl(params->oomadj);
131 packet[4] = htonl((int)params->ptype);
132 return 5 * sizeof(int);
133 }
134
135 /* LMK_PROCREMOVE packet payload */
136 struct lmk_procremove {
137 pid_t pid;
138 };
139
140 /*
141 * For LMK_PROCREMOVE packet get its payload.
142 * Warning: no checks performed, caller should ensure valid parameters.
143 */
lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,struct lmk_procremove * params)144 static inline void lmkd_pack_get_procremove(LMKD_CTRL_PACKET packet,
145 struct lmk_procremove* params) {
146 params->pid = (pid_t)ntohl(packet[1]);
147 }
148
149 /*
150 * Prepare LMK_PROCREMOVE packet and return packet size in bytes.
151 * Warning: no checks performed, caller should ensure valid parameters.
152 */
lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,struct lmk_procremove * params)153 static inline size_t lmkd_pack_set_procremove(LMKD_CTRL_PACKET packet,
154 struct lmk_procremove* params) {
155 packet[0] = htonl(LMK_PROCREMOVE);
156 packet[1] = htonl(params->pid);
157 return 2 * sizeof(int);
158 }
159
160 /*
161 * Prepare LMK_PROCPURGE packet and return packet size in bytes.
162 * Warning: no checks performed, caller should ensure valid parameters.
163 */
lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet)164 static inline size_t lmkd_pack_set_procpurge(LMKD_CTRL_PACKET packet) {
165 packet[0] = htonl(LMK_PROCPURGE);
166 return sizeof(int);
167 }
168
169 /* LMK_GETKILLCNT packet payload */
170 struct lmk_getkillcnt {
171 int min_oomadj;
172 int max_oomadj;
173 };
174
175 /*
176 * For LMK_GETKILLCNT packet get its payload.
177 * Warning: no checks performed, caller should ensure valid parameters.
178 */
lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,struct lmk_getkillcnt * params)179 static inline void lmkd_pack_get_getkillcnt(LMKD_CTRL_PACKET packet,
180 struct lmk_getkillcnt* params) {
181 params->min_oomadj = ntohl(packet[1]);
182 params->max_oomadj = ntohl(packet[2]);
183 }
184
185 /*
186 * Prepare LMK_GETKILLCNT packet and return packet size in bytes.
187 * Warning: no checks performed, caller should ensure valid parameters.
188 */
lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,struct lmk_getkillcnt * params)189 static inline size_t lmkd_pack_set_getkillcnt(LMKD_CTRL_PACKET packet,
190 struct lmk_getkillcnt* params) {
191 packet[0] = htonl(LMK_GETKILLCNT);
192 packet[1] = htonl(params->min_oomadj);
193 packet[2] = htonl(params->max_oomadj);
194 return 3 * sizeof(int);
195 }
196
197 /*
198 * Prepare LMK_GETKILLCNT reply packet and return packet size in bytes.
199 * Warning: no checks performed, caller should ensure valid parameters.
200 */
lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet,int kill_cnt)201 static inline size_t lmkd_pack_set_getkillcnt_repl(LMKD_CTRL_PACKET packet, int kill_cnt) {
202 packet[0] = htonl(LMK_GETKILLCNT);
203 packet[1] = htonl(kill_cnt);
204 return 2 * sizeof(int);
205 }
206
207 /* Types of asyncronous events sent from lmkd to its clients */
208 enum async_event_type {
209 LMK_ASYNC_EVENT_FIRST,
210 LMK_ASYNC_EVENT_KILL = LMK_ASYNC_EVENT_FIRST,
211 LMK_ASYNC_EVENT_COUNT,
212 };
213
214 /* LMK_SUBSCRIBE packet payload */
215 struct lmk_subscribe {
216 enum async_event_type evt_type;
217 };
218
219 /*
220 * For LMK_SUBSCRIBE packet get its payload.
221 * Warning: no checks performed, caller should ensure valid parameters.
222 */
lmkd_pack_get_subscribe(LMKD_CTRL_PACKET packet,struct lmk_subscribe * params)223 static inline void lmkd_pack_get_subscribe(LMKD_CTRL_PACKET packet, struct lmk_subscribe* params) {
224 params->evt_type = (enum async_event_type)ntohl(packet[1]);
225 }
226
227 /**
228 * Prepare LMK_SUBSCRIBE packet and return packet size in bytes.
229 * Warning: no checks performed, caller should ensure valid parameters.
230 */
lmkd_pack_set_subscribe(LMKD_CTRL_PACKET packet,enum async_event_type evt_type)231 static inline size_t lmkd_pack_set_subscribe(LMKD_CTRL_PACKET packet, enum async_event_type evt_type) {
232 packet[0] = htonl(LMK_SUBSCRIBE);
233 packet[1] = htonl((int)evt_type);
234 return 2 * sizeof(int);
235 }
236
237 /**
238 * Prepare LMK_PROCKILL unsolicited packet and return packet size in bytes.
239 * Warning: no checks performed, caller should ensure valid parameters.
240 */
lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet,pid_t pid,uid_t uid)241 static inline size_t lmkd_pack_set_prockills(LMKD_CTRL_PACKET packet, pid_t pid, uid_t uid) {
242 packet[0] = htonl(LMK_PROCKILL);
243 packet[1] = htonl(pid);
244 packet[2] = htonl(uid);
245 return 3 * sizeof(int);
246 }
247
248 /*
249 * Prepare LMK_UPDATE_PROPS packet and return packet size in bytes.
250 * Warning: no checks performed, caller should ensure valid parameters.
251 */
lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet)252 static inline size_t lmkd_pack_set_update_props(LMKD_CTRL_PACKET packet) {
253 packet[0] = htonl(LMK_UPDATE_PROPS);
254 return sizeof(int);
255 }
256
257 /*
258 * Prepare LMK_UPDATE_PROPS reply packet and return packet size in bytes.
259 * Warning: no checks performed, caller should ensure valid parameters.
260 */
lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet,int result)261 static inline size_t lmkd_pack_set_update_props_repl(LMKD_CTRL_PACKET packet, int result) {
262 packet[0] = htonl(LMK_UPDATE_PROPS);
263 packet[1] = htonl(result);
264 return 2 * sizeof(int);
265 }
266
267 /* LMK_PROCPRIO reply payload */
268 struct lmk_update_props_reply {
269 int result;
270 };
271
272 /*
273 * For LMK_UPDATE_PROPS reply payload.
274 * Warning: no checks performed, caller should ensure valid parameters.
275 */
lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,struct lmk_update_props_reply * params)276 static inline void lmkd_pack_get_update_props_repl(LMKD_CTRL_PACKET packet,
277 struct lmk_update_props_reply* params) {
278 params->result = ntohl(packet[1]);
279 }
280
281 __END_DECLS
282
283 #endif /* _LMKD_H_ */
284