/* * (C) 2012 by Pablo Neira Ayuso <pablo@netfilter.org> * * 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 code has been sponsored by Vyatta Inc. <http://www.vyatta.com> */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <sys/types.h> #include <dirent.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <time.h> #include <netinet/in.h> #include <errno.h> #include <libmnl/libmnl.h> #include "linux_list.h" #include "nfct.h" static int nfct_cmd_version(int argc, char *argv[]); static int nfct_cmd_help(int argc, char *argv[]); static void usage(char *argv[]) { fprintf(stderr, "Usage: %s subsystem command [parameters]...\n", argv[0]); } void nfct_perror(const char *msg) { if (errno == 0) { fprintf(stderr, "nfct v%s: %s\n", VERSION, msg); } else { fprintf(stderr, "nfct v%s: %s: %s\n", VERSION, msg, strerror(errno)); } } static LIST_HEAD(nfct_extension_list); void nfct_extension_register(struct nfct_extension *ext) { list_add(&ext->head, &nfct_extension_list); } static struct nfct_extension *nfct_extension_lookup(int type) { struct nfct_extension *ext; list_for_each_entry(ext, &nfct_extension_list, head) { if (ext->type == type) return ext; } return NULL; } int main(int argc, char *argv[]) { int subsys = NFCT_SUBSYS_NONE, ret = 0; struct nfct_extension *ext; struct mnl_socket *nl; if (argc < 2) { usage(argv); exit(EXIT_FAILURE); } if (strncmp(argv[1], "timeout", strlen(argv[1])) == 0) { subsys = NFCT_SUBSYS_TIMEOUT; } else if (strncmp(argv[1], "helper", strlen(argv[1])) == 0) { subsys = NFCT_SUBSYS_HELPER; } else if (strncmp(argv[1], "version", strlen(argv[1])) == 0) subsys = NFCT_SUBSYS_VERSION; else if (strncmp(argv[1], "help", strlen(argv[1])) == 0) subsys = NFCT_SUBSYS_HELP; else { fprintf(stderr, "nfct v%s: Unknown subsystem: %s\n", VERSION, argv[1]); usage(argv); exit(EXIT_FAILURE); } switch(subsys) { case NFCT_SUBSYS_VERSION: ret = nfct_cmd_version(argc, argv); break; case NFCT_SUBSYS_HELP: ret = nfct_cmd_help(argc, argv); break; default: ext = nfct_extension_lookup(subsys); if (ext == NULL) { fprintf(stderr, "nfct v%s: subsystem %s not supported\n", VERSION, argv[1]); return EXIT_FAILURE; } nl = nfct_mnl_open(); if (nl == NULL) { nfct_perror("cannot open netlink"); return -1; } ret = ext->parse_params(nl, argc, argv); mnl_socket_close(nl); break; } return ret < 0 ? EXIT_FAILURE : EXIT_SUCCESS; } static const char version_msg[] = "nfct v%s: utility for the Netfilter's Connection Tracking System\n" "Copyright (C) 2012 Pablo Neira Ayuso <pablo@netfilter.org>\n" "This program comes with ABSOLUTELY NO WARRANTY.\n" "This is free software, and you are welcome to redistribute it under " "certain \nconditions; see LICENSE file distributed in this package " "for details.\n"; static int nfct_cmd_version(int argc, char *argv[]) { printf(version_msg, VERSION); return 0; } static const char help_msg[] = "nfct v%s: utility for the Netfilter's Connection Tracking System\n" "Usage: %s command [parameters]...\n\n" "Subsystem:\n" " helper\t\tAllows to configure user-space helper\n" " timeout\t\tAllows definition of fine-grain timeout policies\n" " version\t\tDisplay version and disclaimer\n" " help\t\t\tDisplay this help message\n" "Commands:\n" " list [reset]\t\tList the accounting object table (and reset)\n" " add object-name\tAdd new accounting object to table\n" " delete object-name\tDelete existing accounting object\n" " get object-name\tGet existing accounting object\n" " flush\t\t\tFlush accounting object table\n"; static int nfct_cmd_help(int argc, char *argv[]) { printf(help_msg, VERSION, argv[0]); return 0; } int nfct_mnl_talk(struct mnl_socket *nl, struct nlmsghdr *nlh, uint32_t seq, uint32_t portid, int (*cb)(const struct nlmsghdr *nlh, void *data), void *data) { int ret; char buf[MNL_SOCKET_BUFFER_SIZE]; if (mnl_socket_sendto(nl, nlh, nlh->nlmsg_len) < 0) return -1; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); while (ret > 0) { ret = mnl_cb_run(buf, ret, seq, portid, cb, data); if (ret <= 0) break; ret = mnl_socket_recvfrom(nl, buf, sizeof(buf)); } if (ret == -1) return -1; return 0; } struct mnl_socket *nfct_mnl_open(void) { struct mnl_socket *nl; nl = mnl_socket_open(NETLINK_NETFILTER); if (nl == NULL) return NULL; if (mnl_socket_bind(nl, 0, MNL_SOCKET_AUTOPID) < 0) return NULL; return nl; }