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 10enum { 11 O_TRANSPARENT = 0, 12 O_NOWILDCARD = 1, 13 O_RESTORESKMARK = 2, 14}; 15 16static const struct xt_option_entry socket_mt_opts[] = { 17 {.name = "transparent", .id = O_TRANSPARENT, .type = XTTYPE_NONE}, 18 XTOPT_TABLEEND, 19}; 20 21static 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 27static 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 34static void socket_mt_help(void) 35{ 36 printf( 37 "socket match options:\n" 38 " --transparent Ignore non-transparent sockets\n\n"); 39} 40 41static 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 49static 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 60static 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 72static 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 87static 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 105static void 106socket_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 114static void 115socket_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 122static void 123socket_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 133static void 134socket_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 141static void 142socket_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 154static void 155socket_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 162static 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 212void _init(void) 213{ 214 xtables_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); 215} 216