1 /* 2 * Copyright (c) 2003+ Evgeniy Polyakov <zbr (at) ioremap.net> 3 * 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 2 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 */ 19 20 /* 21 * xtables interface for OS fingerprint matching module. 22 */ 23 #include <stdio.h> 24 #include <string.h> 25 #include <xtables.h> 26 #include <netinet/ip.h> 27 #include <netinet/tcp.h> 28 #include <linux/netfilter/xt_osf.h> 29 30 enum { 31 O_GENRE = 0, 32 O_TTL, 33 O_LOGLEVEL, 34 }; 35 36 static void osf_help(void) 37 { 38 printf("OS fingerprint match options:\n" 39 "[!] --genre string Match a OS genre by passive fingerprinting.\n" 40 "--ttl level Use some TTL check extensions to determine OS:\n" 41 " 0 true ip and fingerprint TTL comparison. Works for LAN.\n" 42 " 1 check if ip TTL is less than fingerprint one. Works for global addresses.\n" 43 " 2 do not compare TTL at all. Allows to detect NMAP, but can produce false results.\n" 44 "--log level Log determined genres into dmesg even if they do not match desired one:\n" 45 " 0 log all matched or unknown signatures.\n" 46 " 1 log only first one.\n" 47 " 2 log all known matched signatures.\n" 48 ); 49 } 50 51 #define s struct xt_osf_info 52 static const struct xt_option_entry osf_opts[] = { 53 {.name = "genre", .id = O_GENRE, .type = XTTYPE_STRING, 54 .flags = XTOPT_MAND | XTOPT_INVERT | XTOPT_PUT, 55 XTOPT_POINTER(s, genre)}, 56 {.name = "ttl", .id = O_TTL, .type = XTTYPE_UINT32, 57 .flags = XTOPT_PUT, XTOPT_POINTER(s, ttl), .min = 0, .max = 2}, 58 {.name = "log", .id = O_LOGLEVEL, .type = XTTYPE_UINT32, 59 .flags = XTOPT_PUT, XTOPT_POINTER(s, loglevel), .min = 0, .max = 2}, 60 XTOPT_TABLEEND, 61 }; 62 #undef s 63 64 static void osf_parse(struct xt_option_call *cb) 65 { 66 struct xt_osf_info *info = cb->data; 67 68 xtables_option_parse(cb); 69 switch (cb->entry->id) { 70 case O_GENRE: 71 if (cb->invert) 72 info->flags |= XT_OSF_INVERT; 73 info->len = strlen(info->genre); 74 break; 75 case O_TTL: 76 info->flags |= XT_OSF_TTL; 77 break; 78 case O_LOGLEVEL: 79 info->flags |= XT_OSF_LOG; 80 break; 81 } 82 } 83 84 static void osf_print(const void *ip, const struct xt_entry_match *match, int numeric) 85 { 86 const struct xt_osf_info *info = (const struct xt_osf_info*) match->data; 87 88 printf(" OS fingerprint match %s%s", (info->flags & XT_OSF_INVERT) ? "! " : "", info->genre); 89 } 90 91 static void osf_save(const void *ip, const struct xt_entry_match *match) 92 { 93 const struct xt_osf_info *info = (const struct xt_osf_info*) match->data; 94 95 if (info->flags & XT_OSF_INVERT) 96 printf(" !"); 97 98 printf(" --genre %s", info->genre); 99 if (info->flags & XT_OSF_TTL) 100 printf(" --ttl %u", info->ttl); 101 if (info->flags & XT_OSF_LOG) 102 printf(" --log %u", info->loglevel); 103 } 104 105 static struct xtables_match osf_match = { 106 .name = "osf", 107 .version = XTABLES_VERSION, 108 .size = XT_ALIGN(sizeof(struct xt_osf_info)), 109 .userspacesize = XT_ALIGN(sizeof(struct xt_osf_info)), 110 .help = osf_help, 111 .x6_parse = osf_parse, 112 .print = osf_print, 113 .save = osf_save, 114 .x6_options = osf_opts, 115 .family = NFPROTO_IPV4, 116 }; 117 118 void _init(void) 119 { 120 xtables_register_match(&osf_match); 121 } 122