1*a71a9546SAutomerger Merge Worker /*
2*a71a9546SAutomerger Merge Worker * libxt_owner - iptables addon for xt_owner
3*a71a9546SAutomerger Merge Worker *
4*a71a9546SAutomerger Merge Worker * Copyright © CC Computer Consultants GmbH, 2007 - 2008
5*a71a9546SAutomerger Merge Worker * Jan Engelhardt <[email protected]>
6*a71a9546SAutomerger Merge Worker */
7*a71a9546SAutomerger Merge Worker #include <grp.h>
8*a71a9546SAutomerger Merge Worker #include <pwd.h>
9*a71a9546SAutomerger Merge Worker #include <stdbool.h>
10*a71a9546SAutomerger Merge Worker #include <stdio.h>
11*a71a9546SAutomerger Merge Worker #include <limits.h>
12*a71a9546SAutomerger Merge Worker #include <xtables.h>
13*a71a9546SAutomerger Merge Worker #include <linux/netfilter/xt_owner.h>
14*a71a9546SAutomerger Merge Worker
15*a71a9546SAutomerger Merge Worker /* match and invert flags */
16*a71a9546SAutomerger Merge Worker enum {
17*a71a9546SAutomerger Merge Worker IPT_OWNER_UID = 0x01,
18*a71a9546SAutomerger Merge Worker IPT_OWNER_GID = 0x02,
19*a71a9546SAutomerger Merge Worker IPT_OWNER_PID = 0x04,
20*a71a9546SAutomerger Merge Worker IPT_OWNER_SID = 0x08,
21*a71a9546SAutomerger Merge Worker IPT_OWNER_COMM = 0x10,
22*a71a9546SAutomerger Merge Worker IP6T_OWNER_UID = IPT_OWNER_UID,
23*a71a9546SAutomerger Merge Worker IP6T_OWNER_GID = IPT_OWNER_GID,
24*a71a9546SAutomerger Merge Worker IP6T_OWNER_PID = IPT_OWNER_PID,
25*a71a9546SAutomerger Merge Worker IP6T_OWNER_SID = IPT_OWNER_SID,
26*a71a9546SAutomerger Merge Worker IP6T_OWNER_COMM = IPT_OWNER_COMM,
27*a71a9546SAutomerger Merge Worker };
28*a71a9546SAutomerger Merge Worker
29*a71a9546SAutomerger Merge Worker struct ipt_owner_info {
30*a71a9546SAutomerger Merge Worker uid_t uid;
31*a71a9546SAutomerger Merge Worker gid_t gid;
32*a71a9546SAutomerger Merge Worker pid_t pid;
33*a71a9546SAutomerger Merge Worker pid_t sid;
34*a71a9546SAutomerger Merge Worker char comm[16];
35*a71a9546SAutomerger Merge Worker uint8_t match, invert; /* flags */
36*a71a9546SAutomerger Merge Worker };
37*a71a9546SAutomerger Merge Worker
38*a71a9546SAutomerger Merge Worker struct ip6t_owner_info {
39*a71a9546SAutomerger Merge Worker uid_t uid;
40*a71a9546SAutomerger Merge Worker gid_t gid;
41*a71a9546SAutomerger Merge Worker pid_t pid;
42*a71a9546SAutomerger Merge Worker pid_t sid;
43*a71a9546SAutomerger Merge Worker char comm[16];
44*a71a9546SAutomerger Merge Worker uint8_t match, invert; /* flags */
45*a71a9546SAutomerger Merge Worker };
46*a71a9546SAutomerger Merge Worker
47*a71a9546SAutomerger Merge Worker /*
48*a71a9546SAutomerger Merge Worker * Note: "UINT32_MAX - 1" is used in the code because -1 is a reserved
49*a71a9546SAutomerger Merge Worker * UID/GID value anyway.
50*a71a9546SAutomerger Merge Worker */
51*a71a9546SAutomerger Merge Worker
52*a71a9546SAutomerger Merge Worker enum {
53*a71a9546SAutomerger Merge Worker O_USER = 0,
54*a71a9546SAutomerger Merge Worker O_GROUP,
55*a71a9546SAutomerger Merge Worker O_SOCK_EXISTS,
56*a71a9546SAutomerger Merge Worker O_PROCESS,
57*a71a9546SAutomerger Merge Worker O_SESSION,
58*a71a9546SAutomerger Merge Worker O_COMM,
59*a71a9546SAutomerger Merge Worker O_SUPPL_GROUPS,
60*a71a9546SAutomerger Merge Worker };
61*a71a9546SAutomerger Merge Worker
owner_mt_help_v0(void)62*a71a9546SAutomerger Merge Worker static void owner_mt_help_v0(void)
63*a71a9546SAutomerger Merge Worker {
64*a71a9546SAutomerger Merge Worker printf(
65*a71a9546SAutomerger Merge Worker "owner match options:\n"
66*a71a9546SAutomerger Merge Worker "[!] --uid-owner userid Match local UID\n"
67*a71a9546SAutomerger Merge Worker "[!] --gid-owner groupid Match local GID\n"
68*a71a9546SAutomerger Merge Worker "[!] --pid-owner processid Match local PID\n"
69*a71a9546SAutomerger Merge Worker "[!] --sid-owner sessionid Match local SID\n"
70*a71a9546SAutomerger Merge Worker "[!] --cmd-owner name Match local command name\n"
71*a71a9546SAutomerger Merge Worker "NOTE: PID, SID and command matching are broken on SMP\n");
72*a71a9546SAutomerger Merge Worker }
73*a71a9546SAutomerger Merge Worker
owner_mt6_help_v0(void)74*a71a9546SAutomerger Merge Worker static void owner_mt6_help_v0(void)
75*a71a9546SAutomerger Merge Worker {
76*a71a9546SAutomerger Merge Worker printf(
77*a71a9546SAutomerger Merge Worker "owner match options:\n"
78*a71a9546SAutomerger Merge Worker "[!] --uid-owner userid Match local UID\n"
79*a71a9546SAutomerger Merge Worker "[!] --gid-owner groupid Match local GID\n"
80*a71a9546SAutomerger Merge Worker "[!] --pid-owner processid Match local PID\n"
81*a71a9546SAutomerger Merge Worker "[!] --sid-owner sessionid Match local SID\n"
82*a71a9546SAutomerger Merge Worker "NOTE: PID and SID matching are broken on SMP\n");
83*a71a9546SAutomerger Merge Worker }
84*a71a9546SAutomerger Merge Worker
owner_mt_help(void)85*a71a9546SAutomerger Merge Worker static void owner_mt_help(void)
86*a71a9546SAutomerger Merge Worker {
87*a71a9546SAutomerger Merge Worker printf(
88*a71a9546SAutomerger Merge Worker "owner match options:\n"
89*a71a9546SAutomerger Merge Worker "[!] --uid-owner userid[-userid] Match local UID\n"
90*a71a9546SAutomerger Merge Worker "[!] --gid-owner groupid[-groupid] Match local GID\n"
91*a71a9546SAutomerger Merge Worker "[!] --socket-exists Match if socket exists\n"
92*a71a9546SAutomerger Merge Worker " --suppl-groups Also match supplementary groups set with --gid-owner\n");
93*a71a9546SAutomerger Merge Worker }
94*a71a9546SAutomerger Merge Worker
95*a71a9546SAutomerger Merge Worker #define s struct ipt_owner_info
96*a71a9546SAutomerger Merge Worker static const struct xt_option_entry owner_mt_opts_v0[] = {
97*a71a9546SAutomerger Merge Worker {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
98*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
99*a71a9546SAutomerger Merge Worker {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
100*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
101*a71a9546SAutomerger Merge Worker {.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32,
102*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid),
103*a71a9546SAutomerger Merge Worker .max = INT_MAX},
104*a71a9546SAutomerger Merge Worker {.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32,
105*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid),
106*a71a9546SAutomerger Merge Worker .max = INT_MAX},
107*a71a9546SAutomerger Merge Worker {.name = "cmd-owner", .id = O_COMM, .type = XTTYPE_STRING,
108*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, comm)},
109*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
110*a71a9546SAutomerger Merge Worker };
111*a71a9546SAutomerger Merge Worker #undef s
112*a71a9546SAutomerger Merge Worker
113*a71a9546SAutomerger Merge Worker #define s struct ip6t_owner_info
114*a71a9546SAutomerger Merge Worker static const struct xt_option_entry owner_mt6_opts_v0[] = {
115*a71a9546SAutomerger Merge Worker {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
116*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
117*a71a9546SAutomerger Merge Worker {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
118*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
119*a71a9546SAutomerger Merge Worker {.name = "pid-owner", .id = O_PROCESS, .type = XTTYPE_UINT32,
120*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, pid),
121*a71a9546SAutomerger Merge Worker .max = INT_MAX},
122*a71a9546SAutomerger Merge Worker {.name = "sid-owner", .id = O_SESSION, .type = XTTYPE_UINT32,
123*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT | XTOPT_PUT, XTOPT_POINTER(s, sid),
124*a71a9546SAutomerger Merge Worker .max = INT_MAX},
125*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
126*a71a9546SAutomerger Merge Worker };
127*a71a9546SAutomerger Merge Worker #undef s
128*a71a9546SAutomerger Merge Worker
129*a71a9546SAutomerger Merge Worker static const struct xt_option_entry owner_mt_opts[] = {
130*a71a9546SAutomerger Merge Worker {.name = "uid-owner", .id = O_USER, .type = XTTYPE_STRING,
131*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
132*a71a9546SAutomerger Merge Worker {.name = "gid-owner", .id = O_GROUP, .type = XTTYPE_STRING,
133*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
134*a71a9546SAutomerger Merge Worker {.name = "socket-exists", .id = O_SOCK_EXISTS, .type = XTTYPE_NONE,
135*a71a9546SAutomerger Merge Worker .flags = XTOPT_INVERT},
136*a71a9546SAutomerger Merge Worker {.name = "suppl-groups", .id = O_SUPPL_GROUPS, .type = XTTYPE_NONE},
137*a71a9546SAutomerger Merge Worker XTOPT_TABLEEND,
138*a71a9546SAutomerger Merge Worker };
139*a71a9546SAutomerger Merge Worker
owner_mt_parse_v0(struct xt_option_call * cb)140*a71a9546SAutomerger Merge Worker static void owner_mt_parse_v0(struct xt_option_call *cb)
141*a71a9546SAutomerger Merge Worker {
142*a71a9546SAutomerger Merge Worker struct ipt_owner_info *info = cb->data;
143*a71a9546SAutomerger Merge Worker struct passwd *pwd;
144*a71a9546SAutomerger Merge Worker struct group *grp;
145*a71a9546SAutomerger Merge Worker unsigned int id;
146*a71a9546SAutomerger Merge Worker
147*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
148*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
149*a71a9546SAutomerger Merge Worker case O_USER:
150*a71a9546SAutomerger Merge Worker if ((pwd = getpwnam(cb->arg)) != NULL)
151*a71a9546SAutomerger Merge Worker id = pwd->pw_uid;
152*a71a9546SAutomerger Merge Worker else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
153*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg);
154*a71a9546SAutomerger Merge Worker if (cb->invert)
155*a71a9546SAutomerger Merge Worker info->invert |= IPT_OWNER_UID;
156*a71a9546SAutomerger Merge Worker info->match |= IPT_OWNER_UID;
157*a71a9546SAutomerger Merge Worker info->uid = id;
158*a71a9546SAutomerger Merge Worker break;
159*a71a9546SAutomerger Merge Worker case O_GROUP:
160*a71a9546SAutomerger Merge Worker if ((grp = getgrnam(cb->arg)) != NULL)
161*a71a9546SAutomerger Merge Worker id = grp->gr_gid;
162*a71a9546SAutomerger Merge Worker else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
163*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg);
164*a71a9546SAutomerger Merge Worker if (cb->invert)
165*a71a9546SAutomerger Merge Worker info->invert |= IPT_OWNER_GID;
166*a71a9546SAutomerger Merge Worker info->match |= IPT_OWNER_GID;
167*a71a9546SAutomerger Merge Worker info->gid = id;
168*a71a9546SAutomerger Merge Worker break;
169*a71a9546SAutomerger Merge Worker case O_PROCESS:
170*a71a9546SAutomerger Merge Worker if (cb->invert)
171*a71a9546SAutomerger Merge Worker info->invert |= IPT_OWNER_PID;
172*a71a9546SAutomerger Merge Worker info->match |= IPT_OWNER_PID;
173*a71a9546SAutomerger Merge Worker break;
174*a71a9546SAutomerger Merge Worker case O_SESSION:
175*a71a9546SAutomerger Merge Worker if (cb->invert)
176*a71a9546SAutomerger Merge Worker info->invert |= IPT_OWNER_SID;
177*a71a9546SAutomerger Merge Worker info->match |= IPT_OWNER_SID;
178*a71a9546SAutomerger Merge Worker break;
179*a71a9546SAutomerger Merge Worker case O_COMM:
180*a71a9546SAutomerger Merge Worker if (cb->invert)
181*a71a9546SAutomerger Merge Worker info->invert |= IPT_OWNER_COMM;
182*a71a9546SAutomerger Merge Worker info->match |= IPT_OWNER_COMM;
183*a71a9546SAutomerger Merge Worker break;
184*a71a9546SAutomerger Merge Worker }
185*a71a9546SAutomerger Merge Worker }
186*a71a9546SAutomerger Merge Worker
owner_mt6_parse_v0(struct xt_option_call * cb)187*a71a9546SAutomerger Merge Worker static void owner_mt6_parse_v0(struct xt_option_call *cb)
188*a71a9546SAutomerger Merge Worker {
189*a71a9546SAutomerger Merge Worker struct ip6t_owner_info *info = cb->data;
190*a71a9546SAutomerger Merge Worker struct passwd *pwd;
191*a71a9546SAutomerger Merge Worker struct group *grp;
192*a71a9546SAutomerger Merge Worker unsigned int id;
193*a71a9546SAutomerger Merge Worker
194*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
195*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
196*a71a9546SAutomerger Merge Worker case O_USER:
197*a71a9546SAutomerger Merge Worker if ((pwd = getpwnam(cb->arg)) != NULL)
198*a71a9546SAutomerger Merge Worker id = pwd->pw_uid;
199*a71a9546SAutomerger Merge Worker else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
200*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", "--uid-owner", cb->arg);
201*a71a9546SAutomerger Merge Worker if (cb->invert)
202*a71a9546SAutomerger Merge Worker info->invert |= IP6T_OWNER_UID;
203*a71a9546SAutomerger Merge Worker info->match |= IP6T_OWNER_UID;
204*a71a9546SAutomerger Merge Worker info->uid = id;
205*a71a9546SAutomerger Merge Worker break;
206*a71a9546SAutomerger Merge Worker case O_GROUP:
207*a71a9546SAutomerger Merge Worker if ((grp = getgrnam(cb->arg)) != NULL)
208*a71a9546SAutomerger Merge Worker id = grp->gr_gid;
209*a71a9546SAutomerger Merge Worker else if (!xtables_strtoui(cb->arg, NULL, &id, 0, UINT32_MAX - 1))
210*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", "--gid-owner", cb->arg);
211*a71a9546SAutomerger Merge Worker if (cb->invert)
212*a71a9546SAutomerger Merge Worker info->invert |= IP6T_OWNER_GID;
213*a71a9546SAutomerger Merge Worker info->match |= IP6T_OWNER_GID;
214*a71a9546SAutomerger Merge Worker info->gid = id;
215*a71a9546SAutomerger Merge Worker break;
216*a71a9546SAutomerger Merge Worker case O_PROCESS:
217*a71a9546SAutomerger Merge Worker if (cb->invert)
218*a71a9546SAutomerger Merge Worker info->invert |= IP6T_OWNER_PID;
219*a71a9546SAutomerger Merge Worker info->match |= IP6T_OWNER_PID;
220*a71a9546SAutomerger Merge Worker break;
221*a71a9546SAutomerger Merge Worker case O_SESSION:
222*a71a9546SAutomerger Merge Worker if (cb->invert)
223*a71a9546SAutomerger Merge Worker info->invert |= IP6T_OWNER_SID;
224*a71a9546SAutomerger Merge Worker info->match |= IP6T_OWNER_SID;
225*a71a9546SAutomerger Merge Worker break;
226*a71a9546SAutomerger Merge Worker }
227*a71a9546SAutomerger Merge Worker }
228*a71a9546SAutomerger Merge Worker
owner_parse_range(const char * s,unsigned int * from,unsigned int * to,const char * opt)229*a71a9546SAutomerger Merge Worker static void owner_parse_range(const char *s, unsigned int *from,
230*a71a9546SAutomerger Merge Worker unsigned int *to, const char *opt)
231*a71a9546SAutomerger Merge Worker {
232*a71a9546SAutomerger Merge Worker char *end;
233*a71a9546SAutomerger Merge Worker
234*a71a9546SAutomerger Merge Worker /* -1 is reversed, so the max is one less than that. */
235*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(s, &end, from, 0, UINT32_MAX - 1))
236*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
237*a71a9546SAutomerger Merge Worker *to = *from;
238*a71a9546SAutomerger Merge Worker if (*end == '-' || *end == ':')
239*a71a9546SAutomerger Merge Worker if (!xtables_strtoui(end + 1, &end, to, 0, UINT32_MAX - 1))
240*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
241*a71a9546SAutomerger Merge Worker if (*end != '\0')
242*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", opt, s);
243*a71a9546SAutomerger Merge Worker }
244*a71a9546SAutomerger Merge Worker
owner_mt_parse(struct xt_option_call * cb)245*a71a9546SAutomerger Merge Worker static void owner_mt_parse(struct xt_option_call *cb)
246*a71a9546SAutomerger Merge Worker {
247*a71a9546SAutomerger Merge Worker struct xt_owner_match_info *info = cb->data;
248*a71a9546SAutomerger Merge Worker struct passwd *pwd;
249*a71a9546SAutomerger Merge Worker struct group *grp;
250*a71a9546SAutomerger Merge Worker unsigned int from, to;
251*a71a9546SAutomerger Merge Worker
252*a71a9546SAutomerger Merge Worker xtables_option_parse(cb);
253*a71a9546SAutomerger Merge Worker switch (cb->entry->id) {
254*a71a9546SAutomerger Merge Worker case O_USER:
255*a71a9546SAutomerger Merge Worker if ((pwd = getpwnam(cb->arg)) != NULL)
256*a71a9546SAutomerger Merge Worker from = to = pwd->pw_uid;
257*a71a9546SAutomerger Merge Worker else
258*a71a9546SAutomerger Merge Worker owner_parse_range(cb->arg, &from, &to, "--uid-owner");
259*a71a9546SAutomerger Merge Worker if (cb->invert)
260*a71a9546SAutomerger Merge Worker info->invert |= XT_OWNER_UID;
261*a71a9546SAutomerger Merge Worker info->match |= XT_OWNER_UID;
262*a71a9546SAutomerger Merge Worker info->uid_min = from;
263*a71a9546SAutomerger Merge Worker info->uid_max = to;
264*a71a9546SAutomerger Merge Worker break;
265*a71a9546SAutomerger Merge Worker case O_GROUP:
266*a71a9546SAutomerger Merge Worker if ((grp = getgrnam(cb->arg)) != NULL)
267*a71a9546SAutomerger Merge Worker from = to = grp->gr_gid;
268*a71a9546SAutomerger Merge Worker else
269*a71a9546SAutomerger Merge Worker owner_parse_range(cb->arg, &from, &to, "--gid-owner");
270*a71a9546SAutomerger Merge Worker if (cb->invert)
271*a71a9546SAutomerger Merge Worker info->invert |= XT_OWNER_GID;
272*a71a9546SAutomerger Merge Worker info->match |= XT_OWNER_GID;
273*a71a9546SAutomerger Merge Worker info->gid_min = from;
274*a71a9546SAutomerger Merge Worker info->gid_max = to;
275*a71a9546SAutomerger Merge Worker break;
276*a71a9546SAutomerger Merge Worker case O_SOCK_EXISTS:
277*a71a9546SAutomerger Merge Worker if (cb->invert)
278*a71a9546SAutomerger Merge Worker info->invert |= XT_OWNER_SOCKET;
279*a71a9546SAutomerger Merge Worker info->match |= XT_OWNER_SOCKET;
280*a71a9546SAutomerger Merge Worker break;
281*a71a9546SAutomerger Merge Worker case O_SUPPL_GROUPS:
282*a71a9546SAutomerger Merge Worker if (!(info->match & XT_OWNER_GID))
283*a71a9546SAutomerger Merge Worker xtables_param_act(XTF_BAD_VALUE, "owner", "--suppl-groups", "you need to use --gid-owner first");
284*a71a9546SAutomerger Merge Worker info->match |= XT_OWNER_SUPPL_GROUPS;
285*a71a9546SAutomerger Merge Worker break;
286*a71a9546SAutomerger Merge Worker }
287*a71a9546SAutomerger Merge Worker }
288*a71a9546SAutomerger Merge Worker
owner_mt_check(struct xt_fcheck_call * cb)289*a71a9546SAutomerger Merge Worker static void owner_mt_check(struct xt_fcheck_call *cb)
290*a71a9546SAutomerger Merge Worker {
291*a71a9546SAutomerger Merge Worker if (cb->xflags == 0)
292*a71a9546SAutomerger Merge Worker xtables_error(PARAMETER_PROBLEM, "owner: At least one of "
293*a71a9546SAutomerger Merge Worker "--uid-owner, --gid-owner or --socket-exists "
294*a71a9546SAutomerger Merge Worker "is required");
295*a71a9546SAutomerger Merge Worker }
296*a71a9546SAutomerger Merge Worker
297*a71a9546SAutomerger Merge Worker static void
owner_mt_print_item_v0(const struct ipt_owner_info * info,const char * label,uint8_t flag,bool numeric)298*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(const struct ipt_owner_info *info, const char *label,
299*a71a9546SAutomerger Merge Worker uint8_t flag, bool numeric)
300*a71a9546SAutomerger Merge Worker {
301*a71a9546SAutomerger Merge Worker if (!(info->match & flag))
302*a71a9546SAutomerger Merge Worker return;
303*a71a9546SAutomerger Merge Worker if (info->invert & flag)
304*a71a9546SAutomerger Merge Worker printf(" !");
305*a71a9546SAutomerger Merge Worker printf(" %s", label);
306*a71a9546SAutomerger Merge Worker
307*a71a9546SAutomerger Merge Worker switch (info->match & flag) {
308*a71a9546SAutomerger Merge Worker case IPT_OWNER_UID:
309*a71a9546SAutomerger Merge Worker if (!numeric) {
310*a71a9546SAutomerger Merge Worker struct passwd *pwd = getpwuid(info->uid);
311*a71a9546SAutomerger Merge Worker
312*a71a9546SAutomerger Merge Worker if (pwd != NULL && pwd->pw_name != NULL) {
313*a71a9546SAutomerger Merge Worker printf(" %s", pwd->pw_name);
314*a71a9546SAutomerger Merge Worker break;
315*a71a9546SAutomerger Merge Worker }
316*a71a9546SAutomerger Merge Worker }
317*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->uid);
318*a71a9546SAutomerger Merge Worker break;
319*a71a9546SAutomerger Merge Worker
320*a71a9546SAutomerger Merge Worker case IPT_OWNER_GID:
321*a71a9546SAutomerger Merge Worker if (!numeric) {
322*a71a9546SAutomerger Merge Worker struct group *grp = getgrgid(info->gid);
323*a71a9546SAutomerger Merge Worker
324*a71a9546SAutomerger Merge Worker if (grp != NULL && grp->gr_name != NULL) {
325*a71a9546SAutomerger Merge Worker printf(" %s", grp->gr_name);
326*a71a9546SAutomerger Merge Worker break;
327*a71a9546SAutomerger Merge Worker }
328*a71a9546SAutomerger Merge Worker }
329*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->gid);
330*a71a9546SAutomerger Merge Worker break;
331*a71a9546SAutomerger Merge Worker
332*a71a9546SAutomerger Merge Worker case IPT_OWNER_PID:
333*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->pid);
334*a71a9546SAutomerger Merge Worker break;
335*a71a9546SAutomerger Merge Worker
336*a71a9546SAutomerger Merge Worker case IPT_OWNER_SID:
337*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->sid);
338*a71a9546SAutomerger Merge Worker break;
339*a71a9546SAutomerger Merge Worker
340*a71a9546SAutomerger Merge Worker case IPT_OWNER_COMM:
341*a71a9546SAutomerger Merge Worker printf(" %.*s", (int)sizeof(info->comm), info->comm);
342*a71a9546SAutomerger Merge Worker break;
343*a71a9546SAutomerger Merge Worker }
344*a71a9546SAutomerger Merge Worker }
345*a71a9546SAutomerger Merge Worker
346*a71a9546SAutomerger Merge Worker static void
owner_mt6_print_item_v0(const struct ip6t_owner_info * info,const char * label,uint8_t flag,bool numeric)347*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(const struct ip6t_owner_info *info, const char *label,
348*a71a9546SAutomerger Merge Worker uint8_t flag, bool numeric)
349*a71a9546SAutomerger Merge Worker {
350*a71a9546SAutomerger Merge Worker if (!(info->match & flag))
351*a71a9546SAutomerger Merge Worker return;
352*a71a9546SAutomerger Merge Worker if (info->invert & flag)
353*a71a9546SAutomerger Merge Worker printf(" !");
354*a71a9546SAutomerger Merge Worker printf(" %s", label);
355*a71a9546SAutomerger Merge Worker
356*a71a9546SAutomerger Merge Worker switch (info->match & flag) {
357*a71a9546SAutomerger Merge Worker case IP6T_OWNER_UID:
358*a71a9546SAutomerger Merge Worker if (!numeric) {
359*a71a9546SAutomerger Merge Worker struct passwd *pwd = getpwuid(info->uid);
360*a71a9546SAutomerger Merge Worker
361*a71a9546SAutomerger Merge Worker if (pwd != NULL && pwd->pw_name != NULL) {
362*a71a9546SAutomerger Merge Worker printf(" %s", pwd->pw_name);
363*a71a9546SAutomerger Merge Worker break;
364*a71a9546SAutomerger Merge Worker }
365*a71a9546SAutomerger Merge Worker }
366*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->uid);
367*a71a9546SAutomerger Merge Worker break;
368*a71a9546SAutomerger Merge Worker
369*a71a9546SAutomerger Merge Worker case IP6T_OWNER_GID:
370*a71a9546SAutomerger Merge Worker if (!numeric) {
371*a71a9546SAutomerger Merge Worker struct group *grp = getgrgid(info->gid);
372*a71a9546SAutomerger Merge Worker
373*a71a9546SAutomerger Merge Worker if (grp != NULL && grp->gr_name != NULL) {
374*a71a9546SAutomerger Merge Worker printf(" %s", grp->gr_name);
375*a71a9546SAutomerger Merge Worker break;
376*a71a9546SAutomerger Merge Worker }
377*a71a9546SAutomerger Merge Worker }
378*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->gid);
379*a71a9546SAutomerger Merge Worker break;
380*a71a9546SAutomerger Merge Worker
381*a71a9546SAutomerger Merge Worker case IP6T_OWNER_PID:
382*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->pid);
383*a71a9546SAutomerger Merge Worker break;
384*a71a9546SAutomerger Merge Worker
385*a71a9546SAutomerger Merge Worker case IP6T_OWNER_SID:
386*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->sid);
387*a71a9546SAutomerger Merge Worker break;
388*a71a9546SAutomerger Merge Worker }
389*a71a9546SAutomerger Merge Worker }
390*a71a9546SAutomerger Merge Worker
391*a71a9546SAutomerger Merge Worker static void
owner_mt_print_item(const struct xt_owner_match_info * info,const char * label,uint8_t flag,bool numeric)392*a71a9546SAutomerger Merge Worker owner_mt_print_item(const struct xt_owner_match_info *info, const char *label,
393*a71a9546SAutomerger Merge Worker uint8_t flag, bool numeric)
394*a71a9546SAutomerger Merge Worker {
395*a71a9546SAutomerger Merge Worker if (!(info->match & flag))
396*a71a9546SAutomerger Merge Worker return;
397*a71a9546SAutomerger Merge Worker if (info->invert & flag)
398*a71a9546SAutomerger Merge Worker printf(" !");
399*a71a9546SAutomerger Merge Worker printf(" %s", label);
400*a71a9546SAutomerger Merge Worker
401*a71a9546SAutomerger Merge Worker switch (info->match & flag) {
402*a71a9546SAutomerger Merge Worker case XT_OWNER_UID:
403*a71a9546SAutomerger Merge Worker if (info->uid_min != info->uid_max) {
404*a71a9546SAutomerger Merge Worker printf(" %u-%u", (unsigned int)info->uid_min,
405*a71a9546SAutomerger Merge Worker (unsigned int)info->uid_max);
406*a71a9546SAutomerger Merge Worker break;
407*a71a9546SAutomerger Merge Worker } else if (!numeric) {
408*a71a9546SAutomerger Merge Worker const struct passwd *pwd = getpwuid(info->uid_min);
409*a71a9546SAutomerger Merge Worker
410*a71a9546SAutomerger Merge Worker if (pwd != NULL && pwd->pw_name != NULL) {
411*a71a9546SAutomerger Merge Worker printf(" %s", pwd->pw_name);
412*a71a9546SAutomerger Merge Worker break;
413*a71a9546SAutomerger Merge Worker }
414*a71a9546SAutomerger Merge Worker }
415*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->uid_min);
416*a71a9546SAutomerger Merge Worker break;
417*a71a9546SAutomerger Merge Worker
418*a71a9546SAutomerger Merge Worker case XT_OWNER_GID:
419*a71a9546SAutomerger Merge Worker if (info->gid_min != info->gid_max) {
420*a71a9546SAutomerger Merge Worker printf(" %u-%u", (unsigned int)info->gid_min,
421*a71a9546SAutomerger Merge Worker (unsigned int)info->gid_max);
422*a71a9546SAutomerger Merge Worker break;
423*a71a9546SAutomerger Merge Worker } else if (!numeric) {
424*a71a9546SAutomerger Merge Worker const struct group *grp = getgrgid(info->gid_min);
425*a71a9546SAutomerger Merge Worker
426*a71a9546SAutomerger Merge Worker if (grp != NULL && grp->gr_name != NULL) {
427*a71a9546SAutomerger Merge Worker printf(" %s", grp->gr_name);
428*a71a9546SAutomerger Merge Worker break;
429*a71a9546SAutomerger Merge Worker }
430*a71a9546SAutomerger Merge Worker }
431*a71a9546SAutomerger Merge Worker printf(" %u", (unsigned int)info->gid_min);
432*a71a9546SAutomerger Merge Worker break;
433*a71a9546SAutomerger Merge Worker }
434*a71a9546SAutomerger Merge Worker }
435*a71a9546SAutomerger Merge Worker
436*a71a9546SAutomerger Merge Worker static void
owner_mt_print_v0(const void * ip,const struct xt_entry_match * match,int numeric)437*a71a9546SAutomerger Merge Worker owner_mt_print_v0(const void *ip, const struct xt_entry_match *match,
438*a71a9546SAutomerger Merge Worker int numeric)
439*a71a9546SAutomerger Merge Worker {
440*a71a9546SAutomerger Merge Worker const struct ipt_owner_info *info = (void *)match->data;
441*a71a9546SAutomerger Merge Worker
442*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "owner UID match", IPT_OWNER_UID, numeric);
443*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "owner GID match", IPT_OWNER_GID, numeric);
444*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "owner PID match", IPT_OWNER_PID, numeric);
445*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "owner SID match", IPT_OWNER_SID, numeric);
446*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "owner CMD match", IPT_OWNER_COMM, numeric);
447*a71a9546SAutomerger Merge Worker }
448*a71a9546SAutomerger Merge Worker
449*a71a9546SAutomerger Merge Worker static void
owner_mt6_print_v0(const void * ip,const struct xt_entry_match * match,int numeric)450*a71a9546SAutomerger Merge Worker owner_mt6_print_v0(const void *ip, const struct xt_entry_match *match,
451*a71a9546SAutomerger Merge Worker int numeric)
452*a71a9546SAutomerger Merge Worker {
453*a71a9546SAutomerger Merge Worker const struct ip6t_owner_info *info = (void *)match->data;
454*a71a9546SAutomerger Merge Worker
455*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "owner UID match", IPT_OWNER_UID, numeric);
456*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "owner GID match", IPT_OWNER_GID, numeric);
457*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "owner PID match", IPT_OWNER_PID, numeric);
458*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "owner SID match", IPT_OWNER_SID, numeric);
459*a71a9546SAutomerger Merge Worker }
460*a71a9546SAutomerger Merge Worker
owner_mt_print(const void * ip,const struct xt_entry_match * match,int numeric)461*a71a9546SAutomerger Merge Worker static void owner_mt_print(const void *ip, const struct xt_entry_match *match,
462*a71a9546SAutomerger Merge Worker int numeric)
463*a71a9546SAutomerger Merge Worker {
464*a71a9546SAutomerger Merge Worker const struct xt_owner_match_info *info = (void *)match->data;
465*a71a9546SAutomerger Merge Worker
466*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "owner socket exists", XT_OWNER_SOCKET, numeric);
467*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "owner UID match", XT_OWNER_UID, numeric);
468*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "owner GID match", XT_OWNER_GID, numeric);
469*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "incl. suppl. groups", XT_OWNER_SUPPL_GROUPS, numeric);
470*a71a9546SAutomerger Merge Worker }
471*a71a9546SAutomerger Merge Worker
472*a71a9546SAutomerger Merge Worker static void
owner_mt_save_v0(const void * ip,const struct xt_entry_match * match)473*a71a9546SAutomerger Merge Worker owner_mt_save_v0(const void *ip, const struct xt_entry_match *match)
474*a71a9546SAutomerger Merge Worker {
475*a71a9546SAutomerger Merge Worker const struct ipt_owner_info *info = (void *)match->data;
476*a71a9546SAutomerger Merge Worker
477*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "--uid-owner", IPT_OWNER_UID, true);
478*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "--gid-owner", IPT_OWNER_GID, true);
479*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "--pid-owner", IPT_OWNER_PID, true);
480*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "--sid-owner", IPT_OWNER_SID, true);
481*a71a9546SAutomerger Merge Worker owner_mt_print_item_v0(info, "--cmd-owner", IPT_OWNER_COMM, true);
482*a71a9546SAutomerger Merge Worker }
483*a71a9546SAutomerger Merge Worker
484*a71a9546SAutomerger Merge Worker static void
owner_mt6_save_v0(const void * ip,const struct xt_entry_match * match)485*a71a9546SAutomerger Merge Worker owner_mt6_save_v0(const void *ip, const struct xt_entry_match *match)
486*a71a9546SAutomerger Merge Worker {
487*a71a9546SAutomerger Merge Worker const struct ip6t_owner_info *info = (void *)match->data;
488*a71a9546SAutomerger Merge Worker
489*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "--uid-owner", IPT_OWNER_UID, true);
490*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "--gid-owner", IPT_OWNER_GID, true);
491*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "--pid-owner", IPT_OWNER_PID, true);
492*a71a9546SAutomerger Merge Worker owner_mt6_print_item_v0(info, "--sid-owner", IPT_OWNER_SID, true);
493*a71a9546SAutomerger Merge Worker }
494*a71a9546SAutomerger Merge Worker
owner_mt_save(const void * ip,const struct xt_entry_match * match)495*a71a9546SAutomerger Merge Worker static void owner_mt_save(const void *ip, const struct xt_entry_match *match)
496*a71a9546SAutomerger Merge Worker {
497*a71a9546SAutomerger Merge Worker const struct xt_owner_match_info *info = (void *)match->data;
498*a71a9546SAutomerger Merge Worker
499*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "--socket-exists", XT_OWNER_SOCKET, true);
500*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "--uid-owner", XT_OWNER_UID, true);
501*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "--gid-owner", XT_OWNER_GID, true);
502*a71a9546SAutomerger Merge Worker owner_mt_print_item(info, "--suppl-groups", XT_OWNER_SUPPL_GROUPS, true);
503*a71a9546SAutomerger Merge Worker }
504*a71a9546SAutomerger Merge Worker
505*a71a9546SAutomerger Merge Worker static int
owner_mt_print_uid_xlate(const struct xt_owner_match_info * info,struct xt_xlate * xl)506*a71a9546SAutomerger Merge Worker owner_mt_print_uid_xlate(const struct xt_owner_match_info *info,
507*a71a9546SAutomerger Merge Worker struct xt_xlate *xl)
508*a71a9546SAutomerger Merge Worker {
509*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "skuid%s ", info->invert ? " !=" : "");
510*a71a9546SAutomerger Merge Worker
511*a71a9546SAutomerger Merge Worker if (info->uid_min != info->uid_max)
512*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%u-%u", (unsigned int)info->uid_min,
513*a71a9546SAutomerger Merge Worker (unsigned int)info->uid_max);
514*a71a9546SAutomerger Merge Worker else
515*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%u", (unsigned int)info->uid_min);
516*a71a9546SAutomerger Merge Worker
517*a71a9546SAutomerger Merge Worker return 1;
518*a71a9546SAutomerger Merge Worker }
519*a71a9546SAutomerger Merge Worker
520*a71a9546SAutomerger Merge Worker static int
owner_mt_print_gid_xlate(const struct xt_owner_match_info * info,struct xt_xlate * xl)521*a71a9546SAutomerger Merge Worker owner_mt_print_gid_xlate(const struct xt_owner_match_info *info,
522*a71a9546SAutomerger Merge Worker struct xt_xlate *xl)
523*a71a9546SAutomerger Merge Worker {
524*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "skgid%s ", info->invert ? " !=" : "");
525*a71a9546SAutomerger Merge Worker
526*a71a9546SAutomerger Merge Worker if (info->gid_min != info->gid_max)
527*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%u-%u", (unsigned int)info->gid_min,
528*a71a9546SAutomerger Merge Worker (unsigned int)info->gid_max);
529*a71a9546SAutomerger Merge Worker else
530*a71a9546SAutomerger Merge Worker xt_xlate_add(xl, "%u", (unsigned int)info->gid_min);
531*a71a9546SAutomerger Merge Worker
532*a71a9546SAutomerger Merge Worker return 1;
533*a71a9546SAutomerger Merge Worker }
534*a71a9546SAutomerger Merge Worker
owner_mt_xlate(struct xt_xlate * xl,const struct xt_xlate_mt_params * params)535*a71a9546SAutomerger Merge Worker static int owner_mt_xlate(struct xt_xlate *xl,
536*a71a9546SAutomerger Merge Worker const struct xt_xlate_mt_params *params)
537*a71a9546SAutomerger Merge Worker {
538*a71a9546SAutomerger Merge Worker const struct xt_owner_match_info *info = (void *)params->match->data;
539*a71a9546SAutomerger Merge Worker int ret;
540*a71a9546SAutomerger Merge Worker
541*a71a9546SAutomerger Merge Worker switch (info->match) {
542*a71a9546SAutomerger Merge Worker case XT_OWNER_UID:
543*a71a9546SAutomerger Merge Worker ret = owner_mt_print_uid_xlate(info, xl);
544*a71a9546SAutomerger Merge Worker break;
545*a71a9546SAutomerger Merge Worker case XT_OWNER_GID:
546*a71a9546SAutomerger Merge Worker ret = owner_mt_print_gid_xlate(info, xl);
547*a71a9546SAutomerger Merge Worker break;
548*a71a9546SAutomerger Merge Worker default:
549*a71a9546SAutomerger Merge Worker ret = 0;
550*a71a9546SAutomerger Merge Worker }
551*a71a9546SAutomerger Merge Worker
552*a71a9546SAutomerger Merge Worker return ret;
553*a71a9546SAutomerger Merge Worker }
554*a71a9546SAutomerger Merge Worker
555*a71a9546SAutomerger Merge Worker static struct xtables_match owner_mt_reg[] = {
556*a71a9546SAutomerger Merge Worker {
557*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
558*a71a9546SAutomerger Merge Worker .name = "owner",
559*a71a9546SAutomerger Merge Worker .revision = 0,
560*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV4,
561*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct ipt_owner_info)),
562*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct ipt_owner_info)),
563*a71a9546SAutomerger Merge Worker .help = owner_mt_help_v0,
564*a71a9546SAutomerger Merge Worker .x6_parse = owner_mt_parse_v0,
565*a71a9546SAutomerger Merge Worker .x6_fcheck = owner_mt_check,
566*a71a9546SAutomerger Merge Worker .print = owner_mt_print_v0,
567*a71a9546SAutomerger Merge Worker .save = owner_mt_save_v0,
568*a71a9546SAutomerger Merge Worker .x6_options = owner_mt_opts_v0,
569*a71a9546SAutomerger Merge Worker },
570*a71a9546SAutomerger Merge Worker {
571*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
572*a71a9546SAutomerger Merge Worker .name = "owner",
573*a71a9546SAutomerger Merge Worker .revision = 0,
574*a71a9546SAutomerger Merge Worker .family = NFPROTO_IPV6,
575*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct ip6t_owner_info)),
576*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct ip6t_owner_info)),
577*a71a9546SAutomerger Merge Worker .help = owner_mt6_help_v0,
578*a71a9546SAutomerger Merge Worker .x6_parse = owner_mt6_parse_v0,
579*a71a9546SAutomerger Merge Worker .x6_fcheck = owner_mt_check,
580*a71a9546SAutomerger Merge Worker .print = owner_mt6_print_v0,
581*a71a9546SAutomerger Merge Worker .save = owner_mt6_save_v0,
582*a71a9546SAutomerger Merge Worker .x6_options = owner_mt6_opts_v0,
583*a71a9546SAutomerger Merge Worker },
584*a71a9546SAutomerger Merge Worker {
585*a71a9546SAutomerger Merge Worker .version = XTABLES_VERSION,
586*a71a9546SAutomerger Merge Worker .name = "owner",
587*a71a9546SAutomerger Merge Worker .revision = 1,
588*a71a9546SAutomerger Merge Worker .family = NFPROTO_UNSPEC,
589*a71a9546SAutomerger Merge Worker .size = XT_ALIGN(sizeof(struct xt_owner_match_info)),
590*a71a9546SAutomerger Merge Worker .userspacesize = XT_ALIGN(sizeof(struct xt_owner_match_info)),
591*a71a9546SAutomerger Merge Worker .help = owner_mt_help,
592*a71a9546SAutomerger Merge Worker .x6_parse = owner_mt_parse,
593*a71a9546SAutomerger Merge Worker .x6_fcheck = owner_mt_check,
594*a71a9546SAutomerger Merge Worker .print = owner_mt_print,
595*a71a9546SAutomerger Merge Worker .save = owner_mt_save,
596*a71a9546SAutomerger Merge Worker .x6_options = owner_mt_opts,
597*a71a9546SAutomerger Merge Worker .xlate = owner_mt_xlate,
598*a71a9546SAutomerger Merge Worker },
599*a71a9546SAutomerger Merge Worker };
600*a71a9546SAutomerger Merge Worker
_init(void)601*a71a9546SAutomerger Merge Worker void _init(void)
602*a71a9546SAutomerger Merge Worker {
603*a71a9546SAutomerger Merge Worker xtables_register_matches(owner_mt_reg, ARRAY_SIZE(owner_mt_reg));
604*a71a9546SAutomerger Merge Worker }
605