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