/* * libipt_osf.c * * Copyright (c) 2003-2006 Evgeniy Polyakov * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ /* * iptables interface for OS fingerprint matching module. */ #include #include #include #include #include #include #include typedef unsigned int __u32; typedef unsigned short __u16; typedef unsigned char __u8; #include "ipt_osf.h" static void osf_help(void) { printf("OS fingerprint match options:\n" "--genre [!] string Match a OS genre by passive fingerprinting.\n" "--ttl Use some TTL check extensions to determine OS:\n" " 0 true ip and fingerprint TTL comparison. Works for LAN.\n" " 1 check if ip TTL is less than fingerprint one. Works for global addresses.\n" " 2 do not compare TTL at all. Allows to detect NMAP, but can produce false results.\n" "--log level Log determined genres into dmesg even if they do not match desired one:\n" " 0 log all matched or unknown signatures.\n" " 1 log only first one.\n" " 2 log all known matched signatures.\n" "--connector Log through kernel connector [2.6.14+].\n\n" ); } static const struct option osf_opts[] = { { .name = "genre", .has_arg = 1, .flag = 0, .val = '1' }, { .name = "ttl", .has_arg = 1, .flag = 0, .val = '2' }, { .name = "log", .has_arg = 1, .flag = 0, .val = '3' }, { .name = "connector", .has_arg = 0, .flag = 0, .val = '5' }, { .name = NULL } }; static void osf_init(struct xt_entry_match *m) { } static void osf_parse_string(const unsigned char *s, struct ipt_osf_info *info) { if (strlen(s) < MAXGENRELEN) strcpy(info->genre, s); else exit_error(PARAMETER_PROBLEM, "Genre string too long `%s' [%d], max=%d", s, strlen(s), MAXGENRELEN); } static int osf_parse(int c, char **argv, int invert, unsigned int *flags, const void *entry, struct xt_entry_match **match) { struct ipt_osf_info *info = (struct ipt_osf_info *)(*match)->data; switch(c) { case '1': /* --genre */ if (*flags & IPT_OSF_GENRE) exit_error(PARAMETER_PROBLEM, "Can't specify multiple genre parameter"); check_inverse(optarg, &invert, &optind, 0); osf_parse_string(argv[optind-1], info); if (invert) info->flags |= IPT_OSF_INVERT; info->len=strlen((char *)info->genre); *flags |= IPT_OSF_GENRE; break; case '2': /* --ttl */ if (*flags & IPT_OSF_TTL) exit_error(PARAMETER_PROBLEM, "Can't specify multiple ttl parameter"); *flags |= IPT_OSF_TTL; info->flags |= IPT_OSF_TTL; info->ttl = atoi(argv[optind-1]); break; case '3': /* --log */ if (*flags & IPT_OSF_LOG) exit_error(PARAMETER_PROBLEM, "Can't specify multiple log parameter"); *flags |= IPT_OSF_LOG; info->loglevel = atoi(argv[optind-1]); info->flags |= IPT_OSF_LOG; break; case '5': /* --connector */ if (*flags & IPT_OSF_CONNECTOR) exit_error(PARAMETER_PROBLEM, "Can't specify multiple connector parameter"); *flags |= IPT_OSF_CONNECTOR; info->flags |= IPT_OSF_CONNECTOR; break; default: return 0; } return 1; } static void osf_final_check(unsigned int flags) { if (!flags) exit_error(PARAMETER_PROBLEM, "OS fingerprint match: You must specify `--genre'"); } static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric) { const struct ipt_osf_info *info = (const struct ipt_osf_info*) match->data; printf("OS fingerprint match %s%s ", (info->flags & IPT_OSF_INVERT) ? "!" : "", info->genre); } static void osf_save(const void *ip, const struct xt_entry_match *match) { const struct ipt_osf_info *info = (const struct ipt_osf_info*) match->data; printf("--genre %s%s ", (info->flags & IPT_OSF_INVERT) ? "! ": "", info->genre); } static struct xtables_match osf_match = { .name = "osf", .version = XTABLES_VERSION, .size = XT_ALIGN(sizeof(struct ipt_osf_info)), .userspacesize = XT_ALIGN(sizeof(struct ipt_osf_info)), .help = &osf_help, .init = &osf_init, .parse = &osf_parse, .print = &osf_print, .final_check = &osf_final_check, .save = &osf_save, .extra_opts = osf_opts }; void _init(void) { xtables_register_match(&osf_match); }