4 * Copyright (c) 2003 Evgeniy Polyakov <johnpol@2ka.mipt.ru>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 * iptables interface for OS fingerprint matching module.
34 #include <linux/netfilter_ipv4/ipt_osf.h>
36 static void help(void)
38 printf("OS fingerprint match options:\n"
39 "--genre [!] string Match a OS genre by passive fingerprinting.\n"
40 "--smart Use some smart extensions to determine OS (do not use TTL).\n"
41 "--log level Log all(or only first) determined genres even if "
42 "they do not match desired one. "
43 "Level may be 0(all) or 1(only first entry).\n"
44 "--netlink Log through netlink(NETLINK_NFLOG).\n",
45 "--connector Log through kernel connector [in 2.6.12-mm+].\n"
50 static struct option opts
[] = {
51 { .name
= "genre", .has_arg
= 1, .flag
= 0, .val
= '1' },
52 { .name
= "smart", .has_arg
= 0, .flag
= 0, .val
= '2' },
53 { .name
= "log", .has_arg
= 1, .flag
= 0, .val
= '3' },
54 { .name
= "netlink", .has_arg
= 0, .flag
= 0, .val
= '4' },
55 { .name
= "connector", .has_arg
= 0, .flag
= 0, .val
= '5' },
59 static void parse_string(const unsigned char *s
, struct ipt_osf_info
*info
)
61 if (strlen(s
) < MAXGENRELEN
)
62 strcpy(info
->genre
, s
);
64 exit_error(PARAMETER_PROBLEM
, "Genre string too long `%s' [%d], max=%d",
65 s
, strlen(s
), MAXGENRELEN
);
68 static int parse(int c
, char **argv
, int invert
, unsigned int *flags
,
69 const struct ipt_entry
*entry
,
70 unsigned int *nfcache
,
71 struct ipt_entry_match
**match
)
73 struct ipt_osf_info
*info
= (struct ipt_osf_info
*)(*match
)->data
;
77 case '1': /* --genre */
78 if (*flags
& IPT_OSF_GENRE
)
79 exit_error(PARAMETER_PROBLEM
, "Can't specify multiple genre parameter");
80 check_inverse(optarg
, &invert
, &optind
, 0);
81 parse_string(argv
[optind
-1], info
);
84 info
->len
=strlen((char *)info
->genre
);
85 *flags
|= IPT_OSF_GENRE
;
87 case '2': /* --smart */
88 if (*flags
& IPT_OSF_SMART
)
89 exit_error(PARAMETER_PROBLEM
, "Can't specify multiple smart parameter");
90 *flags
|= IPT_OSF_SMART
;
91 info
->flags
|= IPT_OSF_SMART
;
94 if (*flags
& IPT_OSF_LOG
)
95 exit_error(PARAMETER_PROBLEM
, "Can't specify multiple log parameter");
96 *flags
|= IPT_OSF_LOG
;
97 info
->loglevel
= atoi(argv
[optind
-1]);
98 info
->flags
|= IPT_OSF_LOG
;
100 case '4': /* --netlink */
101 if (*flags
& IPT_OSF_NETLINK
)
102 exit_error(PARAMETER_PROBLEM
, "Can't specify multiple netlink parameter");
103 *flags
|= IPT_OSF_NETLINK
;
104 info
->flags
|= IPT_OSF_NETLINK
;
106 case '5': /* --connector */
107 if (*flags
& IPT_OSF_CONNECTOR
)
108 exit_error(PARAMETER_PROBLEM
, "Can't specify multiple connector parameter");
109 *flags
|= IPT_OSF_CONNECTOR
;
110 info
->flags
|= IPT_OSF_CONNECTOR
;
119 static void final_check(unsigned int flags
)
122 exit_error(PARAMETER_PROBLEM
, "OS fingerprint match: You must specify `--genre'");
125 static void print(const struct ipt_ip
*ip
, const struct ipt_entry_match
*match
, int numeric
)
127 const struct ipt_osf_info
*info
= (const struct ipt_osf_info
*) match
->data
;
129 printf("OS fingerprint match %s%s ", (info
->invert
) ? "!" : "", info
->genre
);
132 static void save(const struct ipt_ip
*ip
, const struct ipt_entry_match
*match
)
134 const struct ipt_osf_info
*info
= (const struct ipt_osf_info
*) match
->data
;
136 printf("--genre %s%s ", (info
->invert
) ? "! ": "", info
->genre
);
137 if (info
->flags
& IPT_OSF_SMART
)
139 if (info
->flags
& IPT_OSF_LOG
)
140 printf("--log %d ", info
->loglevel
);
141 if (info
->flags
& IPT_OSF_NETLINK
)
142 printf("--netlink ");
143 if (info
->flags
& IPT_OSF_CONNECTOR
)
144 printf("--connector ");
148 static struct iptables_match osf_match
= {
150 .version
= IPTABLES_VERSION
,
151 .size
= IPT_ALIGN(sizeof(struct ipt_osf_info
)),
152 .userspacesize
= IPT_ALIGN(sizeof(struct ipt_osf_info
)),
155 .final_check
= &final_check
,
164 register_match(&osf_match
);