libnl
3.2.3
|
00001 /* 00002 * lib/netfilter/queue.c Netfilter Queue 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation version 2.1 00007 * of the License. 00008 * 00009 * Copyright (c) 2007, 2008 Patrick McHardy <kaber@trash.net> 00010 */ 00011 00012 /** 00013 * @ingroup nfnl 00014 * @defgroup queue Queue 00015 * @brief 00016 * @{ 00017 */ 00018 00019 #include <sys/types.h> 00020 #include <linux/netfilter/nfnetlink_queue.h> 00021 00022 #include <netlink-local.h> 00023 #include <netlink/attr.h> 00024 #include <netlink/netfilter/nfnl.h> 00025 #include <netlink/netfilter/queue.h> 00026 00027 struct nl_sock *nfnl_queue_socket_alloc(void) 00028 { 00029 struct nl_sock *nlsk; 00030 00031 nlsk = nl_socket_alloc(); 00032 if (nlsk) 00033 nl_socket_disable_auto_ack(nlsk); 00034 return nlsk; 00035 } 00036 00037 static int send_queue_request(struct nl_sock *sk, struct nl_msg *msg) 00038 { 00039 int err; 00040 00041 err = nl_send_auto_complete(sk, msg); 00042 nlmsg_free(msg); 00043 if (err < 0) 00044 return err; 00045 00046 return wait_for_ack(sk); 00047 } 00048 00049 /** 00050 * @name Queue Commands 00051 * @{ 00052 */ 00053 00054 static int build_queue_cmd_request(uint8_t family, uint16_t queuenum, 00055 uint8_t command, struct nl_msg **result) 00056 { 00057 struct nl_msg *msg; 00058 struct nfqnl_msg_config_cmd cmd; 00059 00060 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0, 00061 family, queuenum); 00062 if (msg == NULL) 00063 return -NLE_NOMEM; 00064 00065 cmd.pf = htons(family); 00066 cmd._pad = 0; 00067 cmd.command = command; 00068 if (nla_put(msg, NFQA_CFG_CMD, sizeof(cmd), &cmd) < 0) 00069 goto nla_put_failure; 00070 00071 *result = msg; 00072 return 0; 00073 00074 nla_put_failure: 00075 nlmsg_free(msg); 00076 return -NLE_MSGSIZE; 00077 } 00078 00079 int nfnl_queue_build_pf_bind(uint8_t pf, struct nl_msg **result) 00080 { 00081 return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_BIND, result); 00082 } 00083 00084 int nfnl_queue_pf_bind(struct nl_sock *nlh, uint8_t pf) 00085 { 00086 struct nl_msg *msg; 00087 int err; 00088 00089 if ((err = nfnl_queue_build_pf_bind(pf, &msg)) < 0) 00090 return err; 00091 00092 return send_queue_request(nlh, msg); 00093 } 00094 00095 int nfnl_queue_build_pf_unbind(uint8_t pf, struct nl_msg **result) 00096 { 00097 return build_queue_cmd_request(pf, 0, NFQNL_CFG_CMD_PF_UNBIND, result); 00098 } 00099 00100 int nfnl_queue_pf_unbind(struct nl_sock *nlh, uint8_t pf) 00101 { 00102 struct nl_msg *msg; 00103 int err; 00104 00105 if ((err = nfnl_queue_build_pf_unbind(pf, &msg)) < 0) 00106 return err; 00107 00108 return send_queue_request(nlh, msg); 00109 } 00110 00111 static int nfnl_queue_build_request(const struct nfnl_queue *queue, 00112 struct nl_msg **result) 00113 { 00114 struct nl_msg *msg; 00115 00116 if (!nfnl_queue_test_group(queue)) 00117 return -NLE_MISSING_ATTR; 00118 00119 msg = nfnlmsg_alloc_simple(NFNL_SUBSYS_QUEUE, NFQNL_MSG_CONFIG, 0, 00120 0, nfnl_queue_get_group(queue)); 00121 if (msg == NULL) 00122 return -NLE_NOMEM; 00123 00124 if (nfnl_queue_test_maxlen(queue) && 00125 nla_put_u32(msg, NFQA_CFG_QUEUE_MAXLEN, 00126 htonl(nfnl_queue_get_maxlen(queue))) < 0) 00127 goto nla_put_failure; 00128 00129 /* This sucks, the nfnetlink_queue interface always expects both 00130 * parameters to be present. Needs to be done properly. 00131 */ 00132 if (nfnl_queue_test_copy_mode(queue)) { 00133 struct nfqnl_msg_config_params params; 00134 00135 switch (nfnl_queue_get_copy_mode(queue)) { 00136 case NFNL_QUEUE_COPY_NONE: 00137 params.copy_mode = NFQNL_COPY_NONE; 00138 break; 00139 case NFNL_QUEUE_COPY_META: 00140 params.copy_mode = NFQNL_COPY_META; 00141 break; 00142 case NFNL_QUEUE_COPY_PACKET: 00143 params.copy_mode = NFQNL_COPY_PACKET; 00144 break; 00145 } 00146 params.copy_range = htonl(nfnl_queue_get_copy_range(queue)); 00147 00148 if (nla_put(msg, NFQA_CFG_PARAMS, sizeof(params), ¶ms) < 0) 00149 goto nla_put_failure; 00150 } 00151 00152 *result = msg; 00153 return 0; 00154 00155 nla_put_failure: 00156 nlmsg_free(msg); 00157 return -NLE_MSGSIZE; 00158 } 00159 00160 int nfnl_queue_build_create_request(const struct nfnl_queue *queue, 00161 struct nl_msg **result) 00162 { 00163 struct nfqnl_msg_config_cmd cmd; 00164 int err; 00165 00166 if ((err = nfnl_queue_build_request(queue, result)) < 0) 00167 return err; 00168 00169 cmd.pf = 0; 00170 cmd._pad = 0; 00171 cmd.command = NFQNL_CFG_CMD_BIND; 00172 00173 NLA_PUT(*result, NFQA_CFG_CMD, sizeof(cmd), &cmd); 00174 00175 return 0; 00176 00177 nla_put_failure: 00178 nlmsg_free(*result); 00179 return -NLE_MSGSIZE; 00180 } 00181 00182 int nfnl_queue_create(struct nl_sock *nlh, const struct nfnl_queue *queue) 00183 { 00184 struct nl_msg *msg; 00185 int err; 00186 00187 if ((err = nfnl_queue_build_create_request(queue, &msg)) < 0) 00188 return err; 00189 00190 return send_queue_request(nlh, msg); 00191 } 00192 00193 int nfnl_queue_build_change_request(const struct nfnl_queue *queue, 00194 struct nl_msg **result) 00195 { 00196 return nfnl_queue_build_request(queue, result); 00197 } 00198 00199 int nfnl_queue_change(struct nl_sock *nlh, const struct nfnl_queue *queue) 00200 { 00201 struct nl_msg *msg; 00202 int err; 00203 00204 if ((err = nfnl_queue_build_change_request(queue, &msg)) < 0) 00205 return err; 00206 00207 return send_queue_request(nlh, msg); 00208 } 00209 00210 int nfnl_queue_build_delete_request(const struct nfnl_queue *queue, 00211 struct nl_msg **result) 00212 { 00213 if (!nfnl_queue_test_group(queue)) 00214 return -NLE_MISSING_ATTR; 00215 00216 return build_queue_cmd_request(0, nfnl_queue_get_group(queue), 00217 NFQNL_CFG_CMD_UNBIND, result); 00218 } 00219 00220 int nfnl_queue_delete(struct nl_sock *nlh, const struct nfnl_queue *queue) 00221 { 00222 struct nl_msg *msg; 00223 int err; 00224 00225 if ((err = nfnl_queue_build_delete_request(queue, &msg)) < 0) 00226 return err; 00227 00228 return send_queue_request(nlh, msg); 00229 } 00230 00231 /** @} */ 00232 00233 static struct nl_cache_ops nfnl_queue_ops = { 00234 .co_name = "netfilter/queue", 00235 .co_obj_ops = &queue_obj_ops, 00236 .co_msgtypes = { 00237 END_OF_MSGTYPES_LIST, 00238 }, 00239 }; 00240 00241 static void __init nfnl_queue_init(void) 00242 { 00243 nl_cache_mngt_register(&nfnl_queue_ops); 00244 } 00245 00246 static void __exit nfnl_queue_exit(void) 00247 { 00248 nl_cache_mngt_unregister(&nfnl_queue_ops); 00249 } 00250 00251 /** @} */