1 /* 2 * src/nf-log.c Monitor netfilter log events 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation version 2.1 7 * of the License. 8 * 9 * Copyright (c) 2003-2008 Thomas Graf <tgraf (at) suug.ch> 10 * Copyright (c) 2007 Philip Craig <philipc (at) snapgear.com> 11 * Copyright (c) 2007 Secure Computing Corporation 12 */ 13 14 #include <netlink/cli/utils.h> 15 #include <netlink/cli/link.h> 16 #include <linux/netfilter/nfnetlink_log.h> 17 #include <netlink/netfilter/nfnl.h> 18 #include <netlink/netfilter/log.h> 19 20 static struct nfnl_log *alloc_log(void) 21 { 22 struct nfnl_log *log; 23 24 log = nfnl_log_alloc(); 25 if (!log) 26 nl_cli_fatal(ENOMEM, "Unable to allocate log object"); 27 28 return log; 29 } 30 31 static void obj_input(struct nl_object *obj, void *arg) 32 { 33 struct nl_dump_params dp = { 34 .dp_type = NL_DUMP_STATS, 35 .dp_fd = stdout, 36 .dp_dump_msgtype = 1, 37 }; 38 39 nl_object_dump(obj, &dp); 40 } 41 42 static int event_input(struct nl_msg *msg, void *arg) 43 { 44 if (nl_msg_parse(msg, &obj_input, NULL) < 0) 45 fprintf(stderr, "<<EVENT>> Unknown message type\n"); 46 47 /* Exit nl_recvmsgs_def() and return to the main select() */ 48 return NL_STOP; 49 } 50 51 int main(int argc, char *argv[]) 52 { 53 struct nl_sock *nf_sock; 54 struct nl_sock *rt_sock; 55 struct nl_cache *link_cache; 56 struct nfnl_log *log; 57 enum nfnl_log_copy_mode copy_mode; 58 uint32_t copy_range; 59 int err; 60 int family; 61 62 nf_sock = nl_cli_alloc_socket(); 63 nl_socket_disable_seq_check(nf_sock); 64 nl_socket_modify_cb(nf_sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL); 65 66 if ((argc > 1 && !strcasecmp(argv[1], "-h")) || argc < 3) { 67 printf("Usage: nf-log family group [ copy_mode ] " 68 "[copy_range] \n"); 69 return 2; 70 } 71 72 nl_cli_connect(nf_sock, NETLINK_NETFILTER); 73 74 family = nl_str2af(argv[1]); 75 if (family == AF_UNSPEC) 76 nl_cli_fatal(NLE_INVAL, "Unknown family \"%s\": %s", 77 argv[1], nl_geterror(family)); 78 79 nfnl_log_pf_unbind(nf_sock, family); 80 if ((err = nfnl_log_pf_bind(nf_sock, family)) < 0) 81 nl_cli_fatal(err, "Unable to bind logger: %s", 82 nl_geterror(err)); 83 84 log = alloc_log(); 85 nfnl_log_set_group(log, atoi(argv[2])); 86 87 copy_mode = NFNL_LOG_COPY_META; 88 if (argc > 3) { 89 copy_mode = nfnl_log_str2copy_mode(argv[3]); 90 if (copy_mode < 0) 91 nl_cli_fatal(copy_mode, 92 "Unable to parse copy mode \"%s\": %s", 93 argv[3], nl_geterror(copy_mode)); 94 } 95 nfnl_log_set_copy_mode(log, copy_mode); 96 97 copy_range = 0xFFFF; 98 if (argc > 4) 99 copy_mode = atoi(argv[4]); 100 nfnl_log_set_copy_range(log, copy_range); 101 102 if ((err = nfnl_log_create(nf_sock, log)) < 0) 103 nl_cli_fatal(err, "Unable to bind instance: %s", 104 nl_geterror(err)); 105 106 { 107 struct nl_dump_params dp = { 108 .dp_type = NL_DUMP_STATS, 109 .dp_fd = stdout, 110 .dp_dump_msgtype = 1, 111 }; 112 113 printf("log params: "); 114 nl_object_dump((struct nl_object *) log, &dp); 115 } 116 117 rt_sock = nl_cli_alloc_socket(); 118 nl_cli_connect(rt_sock, NETLINK_ROUTE); 119 link_cache = nl_cli_link_alloc_cache(rt_sock); 120 121 while (1) { 122 fd_set rfds; 123 int nffd, rtfd, maxfd, retval; 124 125 FD_ZERO(&rfds); 126 127 maxfd = nffd = nl_socket_get_fd(nf_sock); 128 FD_SET(nffd, &rfds); 129 130 rtfd = nl_socket_get_fd(rt_sock); 131 FD_SET(rtfd, &rfds); 132 if (maxfd < rtfd) 133 maxfd = rtfd; 134 135 /* wait for an incoming message on the netlink nf_socket */ 136 retval = select(maxfd+1, &rfds, NULL, NULL, NULL); 137 138 if (retval) { 139 if (FD_ISSET(nffd, &rfds)) 140 nl_recvmsgs_default(nf_sock); 141 if (FD_ISSET(rtfd, &rfds)) 142 nl_recvmsgs_default(rt_sock); 143 } 144 } 145 146 return 0; 147 } 148