00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
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
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
00130
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