libipt_ULOG.c revision 03d99486d8283552705b58dc55b6085dffc38792
1015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte/* Shared library add-on to iptables to add ULOG support. 2015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte * 3d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * (C) 2000 by Harald Welte <laforge@gnumonks.org> 4d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * 5d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * multipart netlink support based on ideas by Sebastian Zander 6d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * <zander@fokus.gmd.de> 7015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte * 8015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte * This software is released under the terms of GNU GPL 9015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte * 10d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte * libipt_ULOG.c,v 1.7 2001/01/30 11:55:02 laforge Exp 11015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte */ 12c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <stdio.h> 13c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <netdb.h> 14c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <string.h> 15c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <stdlib.h> 16c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <syslog.h> 17c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <getopt.h> 18c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <iptables.h> 19c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#include <linux/netfilter_ipv4/ip_tables.h> 201eb0081027ee567e822b24377ea614e66c408ff2Martin Josefsson/* For 64bit kernel / 32bit userspace */ 21a2a7f2b531cc582ab6cc3c2b73715ed1d58b9eabJan Engelhardt#include <linux/netfilter_ipv4/ipt_ULOG.h> 22c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 23c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 2433690a1aec0b6309ff90066ca56285b6e43013f2Jan Engelhardtstatic void print_groups(unsigned int gmask) 25c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 26c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte int b; 27c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte unsigned int test; 28c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 29015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte for (b = 31; b >= 0; b--) { 30c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte test = (1 << b); 31c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte if (gmask & test) 32c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte printf("%d ", b + 1); 33c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte } 34c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 35c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 361d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_help(void) 37c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 388b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt printf("ULOG target options:\n" 3944540942fbd1f2a0f0dcd7247275a702bcf45a02Marc Boucher " --ulog-nlgroup nlgroup NETLINK group used for logging\n" 40015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte " --ulog-cprange size Bytes of each packet to be passed\n" 41d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte " --ulog-qthreshold Threshold of in-kernel queue\n" 428b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt " --ulog-prefix prefix Prefix log messages with this prefix.\n"); 43c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 44c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 451d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic const struct option ULOG_opts[] = { 46500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy {"ulog-nlgroup", 1, NULL, '!'}, 47500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy {"ulog-prefix", 1, NULL, '#'}, 48500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy {"ulog-cprange", 1, NULL, 'A'}, 49500f483fff529dcd88ec96b9d5054be6cd6363a0Patrick McHardy {"ulog-qthreshold", 1, NULL, 'B'}, 509ee386a1b6d7704b259460152c959ab0e79e02aaMax Kellermann { .name = NULL } 51c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}; 52c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 531d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_init(struct xt_entry_target *t) 54c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 55015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte struct ipt_ulog_info *loginfo = (struct ipt_ulog_info *) t->data; 56c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 57c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte loginfo->nl_group = ULOG_DEFAULT_NLGROUP; 58d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte loginfo->qthreshold = ULOG_DEFAULT_QTHRESHOLD; 59c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 60c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 61c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 62c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define IPT_LOG_OPT_NLGROUP 0x01 63c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte#define IPT_LOG_OPT_PREFIX 0x02 64015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte#define IPT_LOG_OPT_CPRANGE 0x04 65d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte#define IPT_LOG_OPT_QTHRESHOLD 0x08 66c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 671d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic int ULOG_parse(int c, char **argv, int invert, unsigned int *flags, 681d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt const void *entry, struct xt_entry_target **target) 69c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 70015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte struct ipt_ulog_info *loginfo = 71015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte (struct ipt_ulog_info *) (*target)->data; 72c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte int group_d; 73c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 74c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte switch (c) { 75c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte case '!': 76c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte if (*flags & IPT_LOG_OPT_NLGROUP) 77c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte exit_error(PARAMETER_PROBLEM, 78c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte "Can't specify --ulog-nlgroup twice"); 79c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 80b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte if (check_inverse(optarg, &invert, NULL, 0)) 81c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte exit_error(PARAMETER_PROBLEM, 82c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte "Unexpected `!' after --ulog-nlgroup"); 83c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte group_d = atoi(optarg); 84c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte if (group_d > 32 || group_d < 1) 85c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte exit_error(PARAMETER_PROBLEM, 86015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte "--ulog-nlgroup has to be between 1 and 32"); 87c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 88015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte loginfo->nl_group = (1 << (group_d - 1)); 89c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 90c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte *flags |= IPT_LOG_OPT_NLGROUP; 91c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte break; 92c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 93c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte case '#': 94c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte if (*flags & IPT_LOG_OPT_PREFIX) 95c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte exit_error(PARAMETER_PROBLEM, 96c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte "Can't specify --ulog-prefix twice"); 97c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 98b77f1dafb9f35752bb9685323bcacb32a0e6ddc5Harald Welte if (check_inverse(optarg, &invert, NULL, 0)) 99c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte exit_error(PARAMETER_PROBLEM, 100c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte "Unexpected `!' after --ulog-prefix"); 101c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 102c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte if (strlen(optarg) > sizeof(loginfo->prefix) - 1) 103c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte exit_error(PARAMETER_PROBLEM, 104c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte "Maximum prefix length %u for --ulog-prefix", 105a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson (unsigned int)sizeof(loginfo->prefix) - 1); 106c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 107ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger if (strlen(optarg) == 0) 108ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger exit_error(PARAMETER_PROBLEM, 109ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger "No prefix specified for --ulog-prefix"); 110ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger 111ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger if (strlen(optarg) != strlen(strtok(optarg, "\n"))) 112ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger exit_error(PARAMETER_PROBLEM, 113ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger "Newlines not allowed in --ulog-prefix"); 114ed26b7b0cedcdb9621ae7d4e225048614f52dc0fMike Frysinger 115c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte strcpy(loginfo->prefix, optarg); 116c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte *flags |= IPT_LOG_OPT_PREFIX; 117c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte break; 118015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte case 'A': 119015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte if (*flags & IPT_LOG_OPT_CPRANGE) 120015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte exit_error(PARAMETER_PROBLEM, 121015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte "Can't specify --ulog-cprange twice"); 122015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte if (atoi(optarg) < 0) 123015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte exit_error(PARAMETER_PROBLEM, 124015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte "Negative copy range?"); 125015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte loginfo->copy_range = atoi(optarg); 126015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte *flags |= IPT_LOG_OPT_CPRANGE; 127015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte break; 128d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte case 'B': 129d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte if (*flags & IPT_LOG_OPT_QTHRESHOLD) 130d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte exit_error(PARAMETER_PROBLEM, 131d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte "Can't specify --ulog-qthreshold twice"); 132d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte if (atoi(optarg) < 1) 133d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte exit_error(PARAMETER_PROBLEM, 134d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte "Negative or zero queue threshold ?"); 135d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte if (atoi(optarg) > ULOG_MAX_QLEN) 136d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte exit_error(PARAMETER_PROBLEM, 137d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte "Maximum queue length exceeded"); 138d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte loginfo->qthreshold = atoi(optarg); 139d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte *flags |= IPT_LOG_OPT_QTHRESHOLD; 140d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte break; 141e556800cf137e49a47cf1ac889c613f5d33cfe3bPatrick McHardy default: 142e556800cf137e49a47cf1ac889c613f5d33cfe3bPatrick McHardy return 0; 143c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte } 144c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte return 1; 145c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 146c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 1471d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_save(const void *ip, const struct xt_entry_target *target) 148c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 149015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte const struct ipt_ulog_info *loginfo 150015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte = (const struct ipt_ulog_info *) target->data; 151c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 152a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann if (strcmp(loginfo->prefix, "") != 0) { 153a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann fputs("--ulog-prefix ", stdout); 154a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann save_string(loginfo->prefix); 155a5d099400fd6f9ad3880dda10f85d2aa36b5ec65Max Kellermann } 156c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 157015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte if (loginfo->nl_group != ULOG_DEFAULT_NLGROUP) { 158015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte printf("--ulog-nlgroup "); 159c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte print_groups(loginfo->nl_group); 160c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte } 161015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte if (loginfo->copy_range) 162a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson printf("--ulog-cprange %u ", (unsigned int)loginfo->copy_range); 163d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte 164d3beea368e0f293d8822153366e38e0d62fcea6aHarald Welte if (loginfo->qthreshold != ULOG_DEFAULT_QTHRESHOLD) 165a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson printf("--ulog-qthreshold %u ", (unsigned int)loginfo->qthreshold); 166c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 167c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 1681d5b63d12984d12c8d87242179855e17657be16dJan Engelhardtstatic void ULOG_print(const void *ip, const struct xt_entry_target *target, 1691d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt int numeric) 170c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 171c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte const struct ipt_ulog_info *loginfo 172015dffbad370115ef15d9064a807acbe9ef7c60cHarald Welte = (const struct ipt_ulog_info *) target->data; 173c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 174c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte printf("ULOG "); 175a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson printf("copy_range %u nlgroup ", (unsigned int)loginfo->copy_range); 176c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte print_groups(loginfo->nl_group); 177c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte if (strcmp(loginfo->prefix, "") != 0) 178c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte printf("prefix `%s' ", loginfo->prefix); 179a28d495285ad7dd9f286d63958cf20d74eec6bcbMartin Josefsson printf("queue_threshold %u ", (unsigned int)loginfo->qthreshold); 180c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 181c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 1828b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardtstatic struct xtables_target ulog_tg_reg = { 1838caee8b9e34fed4562fcff553197c161fc9d9979Pablo Neira .name = "ULOG", 1848b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .version = XTABLES_VERSION, 18503d99486d8283552705b58dc55b6085dffc38792Jan Engelhardt .family = NFPROTO_IPV4, 1868b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .size = XT_ALIGN(sizeof(struct ipt_ulog_info)), 1878b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt .userspacesize = XT_ALIGN(sizeof(struct ipt_ulog_info)), 1881d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .help = ULOG_help, 1891d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .init = ULOG_init, 1901d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .parse = ULOG_parse, 1911d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .print = ULOG_print, 1921d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .save = ULOG_save, 1931d5b63d12984d12c8d87242179855e17657be16dJan Engelhardt .extra_opts = ULOG_opts, 194c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte}; 195c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte 196c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Weltevoid _init(void) 197c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte{ 1988b7c64d6ba156a99008fcd810cba874c73294333Jan Engelhardt xtables_register_target(&ulog_tg_reg); 199c5bdb40e2d78999e3bfed6256d0fd2df4bba784fHarald Welte} 200