1 /*
2 * Shared library add-on to iptables to add early socket matching support.
3 *
4 * Copyright (C) 2007 BalaBit IT Ltd.
5 */
6 #include <stdio.h>
7 #include <xtables.h>
8 #include <linux/netfilter/xt_socket.h>
9
10 enum {
11 O_TRANSPARENT = 0,
12 O_NOWILDCARD = 1,
13 O_RESTORESKMARK = 2,
14 };
15
16 static const struct xt_option_entry socket_mt_opts[] = {
17 {.name = "transparent", .id = O_TRANSPARENT, .type = XTTYPE_NONE},
18 XTOPT_TABLEEND,
19 };
20
21 static const struct xt_option_entry socket_mt_opts_v2[] = {
22 {.name = "transparent", .id = O_TRANSPARENT, .type = XTTYPE_NONE},
23 {.name = "nowildcard", .id = O_NOWILDCARD, .type = XTTYPE_NONE},
24 XTOPT_TABLEEND,
25 };
26
27 static const struct xt_option_entry socket_mt_opts_v3[] = {
28 {.name = "transparent", .id = O_TRANSPARENT, .type = XTTYPE_NONE},
29 {.name = "nowildcard", .id = O_NOWILDCARD, .type = XTTYPE_NONE},
30 {.name = "restore-skmark", .id = O_RESTORESKMARK, .type = XTTYPE_NONE},
31 XTOPT_TABLEEND,
32 };
33
socket_mt_help(void)34 static void socket_mt_help(void)
35 {
36 printf(
37 "socket match options:\n"
38 " --transparent Ignore non-transparent sockets\n\n");
39 }
40
socket_mt_help_v2(void)41 static void socket_mt_help_v2(void)
42 {
43 printf(
44 "socket match options:\n"
45 " --nowildcard Do not ignore LISTEN sockets bound on INADDR_ANY\n"
46 " --transparent Ignore non-transparent sockets\n\n");
47 }
48
socket_mt_help_v3(void)49 static void socket_mt_help_v3(void)
50 {
51 printf(
52 "socket match options:\n"
53 " --nowildcard Do not ignore LISTEN sockets bound on INADDR_ANY\n"
54 " --transparent Ignore non-transparent sockets\n"
55 " --restore-skmark Set the packet mark to the socket mark if\n"
56 " the socket matches and transparent / \n"
57 " nowildcard conditions are satisfied\n\n");
58 }
59
socket_mt_parse(struct xt_option_call * cb)60 static void socket_mt_parse(struct xt_option_call *cb)
61 {
62 struct xt_socket_mtinfo1 *info = cb->data;
63
64 xtables_option_parse(cb);
65 switch (cb->entry->id) {
66 case O_TRANSPARENT:
67 info->flags |= XT_SOCKET_TRANSPARENT;
68 break;
69 }
70 }
71
socket_mt_parse_v2(struct xt_option_call * cb)72 static void socket_mt_parse_v2(struct xt_option_call *cb)
73 {
74 struct xt_socket_mtinfo2 *info = cb->data;
75
76 xtables_option_parse(cb);
77 switch (cb->entry->id) {
78 case O_TRANSPARENT:
79 info->flags |= XT_SOCKET_TRANSPARENT;
80 break;
81 case O_NOWILDCARD:
82 info->flags |= XT_SOCKET_NOWILDCARD;
83 break;
84 }
85 }
86
socket_mt_parse_v3(struct xt_option_call * cb)87 static void socket_mt_parse_v3(struct xt_option_call *cb)
88 {
89 struct xt_socket_mtinfo2 *info = cb->data;
90
91 xtables_option_parse(cb);
92 switch (cb->entry->id) {
93 case O_TRANSPARENT:
94 info->flags |= XT_SOCKET_TRANSPARENT;
95 break;
96 case O_NOWILDCARD:
97 info->flags |= XT_SOCKET_NOWILDCARD;
98 break;
99 case O_RESTORESKMARK:
100 info->flags |= XT_SOCKET_RESTORESKMARK;
101 break;
102 }
103 }
104
105 static void
socket_mt_save(const void * ip,const struct xt_entry_match * match)106 socket_mt_save(const void *ip, const struct xt_entry_match *match)
107 {
108 const struct xt_socket_mtinfo1 *info = (const void *)match->data;
109
110 if (info->flags & XT_SOCKET_TRANSPARENT)
111 printf(" --transparent");
112 }
113
114 static void
socket_mt_print(const void * ip,const struct xt_entry_match * match,int numeric)115 socket_mt_print(const void *ip, const struct xt_entry_match *match,
116 int numeric)
117 {
118 printf(" socket");
119 socket_mt_save(ip, match);
120 }
121
122 static void
socket_mt_save_v2(const void * ip,const struct xt_entry_match * match)123 socket_mt_save_v2(const void *ip, const struct xt_entry_match *match)
124 {
125 const struct xt_socket_mtinfo2 *info = (const void *)match->data;
126
127 if (info->flags & XT_SOCKET_TRANSPARENT)
128 printf(" --transparent");
129 if (info->flags & XT_SOCKET_NOWILDCARD)
130 printf(" --nowildcard");
131 }
132
133 static void
socket_mt_print_v2(const void * ip,const struct xt_entry_match * match,int numeric)134 socket_mt_print_v2(const void *ip, const struct xt_entry_match *match,
135 int numeric)
136 {
137 printf(" socket");
138 socket_mt_save_v2(ip, match);
139 }
140
141 static void
socket_mt_save_v3(const void * ip,const struct xt_entry_match * match)142 socket_mt_save_v3(const void *ip, const struct xt_entry_match *match)
143 {
144 const struct xt_socket_mtinfo3 *info = (const void *)match->data;
145
146 if (info->flags & XT_SOCKET_TRANSPARENT)
147 printf(" --transparent");
148 if (info->flags & XT_SOCKET_NOWILDCARD)
149 printf(" --nowildcard");
150 if (info->flags & XT_SOCKET_RESTORESKMARK)
151 printf(" --restore-skmark");
152 }
153
154 static void
socket_mt_print_v3(const void * ip,const struct xt_entry_match * match,int numeric)155 socket_mt_print_v3(const void *ip, const struct xt_entry_match *match,
156 int numeric)
157 {
158 printf(" socket");
159 socket_mt_save_v3(ip, match);
160 }
161
162 static struct xtables_match socket_mt_reg[] = {
163 {
164 .name = "socket",
165 .revision = 0,
166 .family = NFPROTO_IPV4,
167 .version = XTABLES_VERSION,
168 .size = XT_ALIGN(0),
169 .userspacesize = XT_ALIGN(0),
170 },
171 {
172 .name = "socket",
173 .revision = 1,
174 .family = NFPROTO_UNSPEC,
175 .version = XTABLES_VERSION,
176 .size = XT_ALIGN(sizeof(struct xt_socket_mtinfo1)),
177 .userspacesize = XT_ALIGN(sizeof(struct xt_socket_mtinfo1)),
178 .help = socket_mt_help,
179 .print = socket_mt_print,
180 .save = socket_mt_save,
181 .x6_parse = socket_mt_parse,
182 .x6_options = socket_mt_opts,
183 },
184 {
185 .name = "socket",
186 .revision = 2,
187 .family = NFPROTO_UNSPEC,
188 .version = XTABLES_VERSION,
189 .size = XT_ALIGN(sizeof(struct xt_socket_mtinfo2)),
190 .userspacesize = XT_ALIGN(sizeof(struct xt_socket_mtinfo2)),
191 .help = socket_mt_help_v2,
192 .print = socket_mt_print_v2,
193 .save = socket_mt_save_v2,
194 .x6_parse = socket_mt_parse_v2,
195 .x6_options = socket_mt_opts_v2,
196 },
197 {
198 .name = "socket",
199 .revision = 3,
200 .family = NFPROTO_UNSPEC,
201 .version = XTABLES_VERSION,
202 .size = XT_ALIGN(sizeof(struct xt_socket_mtinfo2)),
203 .userspacesize = XT_ALIGN(sizeof(struct xt_socket_mtinfo2)),
204 .help = socket_mt_help_v3,
205 .print = socket_mt_print_v3,
206 .save = socket_mt_save_v3,
207 .x6_parse = socket_mt_parse_v3,
208 .x6_options = socket_mt_opts_v3,
209 },
210 };
211
_init(void)212 void _init(void)
213 {
214 xtables_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
215 }
216