1 /* 2 * lib/netfilter/log.c Netfilter Log 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 /** 15 * @ingroup nfnl 16 * @defgroup log Log 17 * @brief 18 * @{ 19 */ 20 21 #include <sys/types.h> 22 #include <linux/netfilter/nfnetlink_log.h> 23 24 #include <netlink-local.h> 25 #include <netlink/attr.h> 26 #include <netlink/netfilter/nfnl.h> 27 #include <netlink/netfilter/log.h> 28 29 /** 30 * @name Log Commands 31 * @{ 32 */ 33 34 static int build_log_cmd_request(uint8_t family, uint16_t queuenum, 35 uint8_t command, struct nl_msg **result) 36 { 37 struct nl_msg *msg; 38 struct nfulnl_msg_config_cmd cmd; 39 40 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0, 41 family, queuenum); 42 if (msg == NULL) 43 return -NLE_NOMEM; 44 45 cmd.command = command; 46 if (nla_put(msg, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0) 47 goto nla_put_failure; 48 49 *result = msg; 50 return 0; 51 52 nla_put_failure: 53 nlmsg_free(msg); 54 return -NLE_MSGSIZE; 55 } 56 57 static int send_log_request(struct nl_sock *sk, struct nl_msg *msg) 58 { 59 int err; 60 61 err = nl_send_auto_complete(sk, msg); 62 nlmsg_free(msg); 63 if (err < 0) 64 return err; 65 66 return wait_for_ack(sk); 67 } 68 69 int nfnl_log_build_pf_bind(uint8_t pf, struct nl_msg **result) 70 { 71 return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_BIND, result); 72 } 73 74 int nfnl_log_pf_bind(struct nl_sock *nlh, uint8_t pf) 75 { 76 struct nl_msg *msg; 77 int err; 78 79 if ((err = nfnl_log_build_pf_bind(pf, &msg)) < 0) 80 return err; 81 82 return send_log_request(nlh, msg); 83 } 84 85 int nfnl_log_build_pf_unbind(uint8_t pf, struct nl_msg **result) 86 { 87 return build_log_cmd_request(pf, 0, NFULNL_CFG_CMD_PF_UNBIND, result); 88 } 89 90 int nfnl_log_pf_unbind(struct nl_sock *nlh, uint8_t pf) 91 { 92 struct nl_msg *msg; 93 int err; 94 95 if ((err = nfnl_log_build_pf_unbind(pf, &msg)) < 0) 96 return err; 97 98 return send_log_request(nlh, msg); 99 } 100 101 static int nfnl_log_build_request(const struct nfnl_log *log, 102 struct nl_msg **result) 103 { 104 struct nl_msg *msg; 105 106 if (!nfnl_log_test_group(log)) 107 return -NLE_MISSING_ATTR; 108 109 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_ULOG, NFULNL_MSG_CONFIG, 0, 110 0, nfnl_log_get_group(log)); 111 if (msg == NULL) 112 return -NLE_NOMEM; 113 114 /* This sucks. The nfnetlink_log interface always expects both 115 * parameters to be present. Needs to be done properly. 116 */ 117 if (nfnl_log_test_copy_mode(log)) { 118 struct nfulnl_msg_config_mode mode; 119 120 switch (nfnl_log_get_copy_mode(log)) { 121 case NFNL_LOG_COPY_NONE: 122 mode.copy_mode = NFULNL_COPY_NONE; 123 break; 124 case NFNL_LOG_COPY_META: 125 mode.copy_mode = NFULNL_COPY_META; 126 break; 127 case NFNL_LOG_COPY_PACKET: 128 mode.copy_mode = NFULNL_COPY_PACKET; 129 break; 130 } 131 mode.copy_range = htonl(nfnl_log_get_copy_range(log)); 132 mode._pad = 0; 133 134 if (nla_put(msg, NFULA_CFG_MODE, sizeof(mode), &mode) < 0) 135 goto nla_put_failure; 136 } 137 138 if (nfnl_log_test_flush_timeout(log) && 139 nla_put_u32(msg, NFULA_CFG_TIMEOUT, 140 htonl(nfnl_log_get_flush_timeout(log))) < 0) 141 goto nla_put_failure; 142 143 if (nfnl_log_test_alloc_size(log) && 144 nla_put_u32(msg, NFULA_CFG_NLBUFSIZ, 145 htonl(nfnl_log_get_alloc_size(log))) < 0) 146 goto nla_put_failure; 147 148 if (nfnl_log_test_queue_threshold(log) && 149 nla_put_u32(msg, NFULA_CFG_QTHRESH, 150 htonl(nfnl_log_get_queue_threshold(log))) < 0) 151 goto nla_put_failure; 152 153 *result = msg; 154 return 0; 155 156 nla_put_failure: 157 nlmsg_free(msg); 158 return -NLE_MSGSIZE; 159 } 160 161 int nfnl_log_build_create_request(const struct nfnl_log *log, 162 struct nl_msg **result) 163 { 164 struct nfulnl_msg_config_cmd cmd; 165 int err; 166 167 if ((err = nfnl_log_build_request(log, result)) < 0) 168 return err; 169 170 cmd.command = NFULNL_CFG_CMD_BIND; 171 172 if (nla_put(*result, NFULA_CFG_CMD, sizeof(cmd), &cmd) < 0) 173 goto nla_put_failure; 174 175 return 0; 176 177 nla_put_failure: 178 nlmsg_free(*result); 179 return -NLE_MSGSIZE; 180 } 181 182 int nfnl_log_create(struct nl_sock *nlh, const struct nfnl_log *log) 183 { 184 struct nl_msg *msg; 185 int err; 186 187 if ((err = nfnl_log_build_create_request(log, &msg)) < 0) 188 return err; 189 190 return send_log_request(nlh, msg); 191 } 192 193 int nfnl_log_build_change_request(const struct nfnl_log *log, 194 struct nl_msg **result) 195 { 196 return nfnl_log_build_request(log, result); 197 } 198 199 int nfnl_log_change(struct nl_sock *nlh, const struct nfnl_log *log) 200 { 201 struct nl_msg *msg; 202 int err; 203 204 if ((err = nfnl_log_build_change_request(log, &msg)) < 0) 205 return err; 206 207 return send_log_request(nlh, msg); 208 } 209 210 int nfnl_log_build_delete_request(const struct nfnl_log *log, 211 struct nl_msg **result) 212 { 213 if (!nfnl_log_test_group(log)) 214 return -NLE_MISSING_ATTR; 215 216 return build_log_cmd_request(0, nfnl_log_get_group(log), 217 NFULNL_CFG_CMD_UNBIND, result); 218 } 219 220 int nfnl_log_delete(struct nl_sock *nlh, const struct nfnl_log *log) 221 { 222 struct nl_msg *msg; 223 int err; 224 225 if ((err = nfnl_log_build_delete_request(log, &msg)) < 0) 226 return err; 227 228 return send_log_request(nlh, msg); 229 } 230 231 /** @} */ 232 233 static struct nl_cache_ops nfnl_log_ops = { 234 .co_name = "netfilter/log", 235 .co_obj_ops = &log_obj_ops, 236 .co_msgtypes = { 237 END_OF_MSGTYPES_LIST, 238 }, 239 }; 240 241 static void __init log_init(void) 242 { 243 nl_cache_mngt_register(&nfnl_log_ops); 244 } 245 246 static void __exit log_exit(void) 247 { 248 nl_cache_mngt_unregister(&nfnl_log_ops); 249 } 250 251 /** @} */ 252