1/* 2 * (C) 2005-2011 by Pablo Neira Ayuso <pablo@netfilter.org> 3 * 4 * This program is free software; you can redistribute it and/or modify it 5 * under the terms of the GNU General Public License as published by 6 * the Free Software Foundation; either version 2 of the License, or 7 * (at your option) any later version. 8 */ 9 10#include "internal/internal.h" 11 12static int __parse_message(const struct nlmsghdr *nlh) 13{ 14 uint16_t type = NFNL_MSG_TYPE(nlh->nlmsg_type); 15 uint16_t flags = nlh->nlmsg_flags; 16 int ret = NFCT_T_UNKNOWN; 17 18 switch(type) { 19 case IPCTNL_MSG_CT_NEW: /* same value for IPCTNL_MSG_EXP_NEW. */ 20 if (flags & (NLM_F_CREATE|NLM_F_EXCL)) 21 ret = NFCT_T_NEW; 22 else 23 ret = NFCT_T_UPDATE; 24 break; 25 case IPCTNL_MSG_CT_DELETE: /* same value for IPCTNL_MSG_EXP_DELETE. */ 26 ret = NFCT_T_DESTROY; 27 break; 28 } 29 return ret; 30} 31 32int __callback(struct nlmsghdr *nlh, struct nfattr *nfa[], void *data) 33{ 34 int ret = NFNL_CB_STOP; 35 unsigned int type; 36 struct nf_conntrack *ct = NULL; 37 struct nf_expect *exp = NULL; 38 struct __data_container *container = data; 39 uint8_t subsys = NFNL_SUBSYS_ID(nlh->nlmsg_type); 40 41 if (nlh->nlmsg_len < NLMSG_LENGTH(sizeof(struct nfgenmsg))) { 42 errno = EINVAL; 43 return NFNL_CB_FAILURE; 44 } 45 type = __parse_message(nlh); 46 if (!(type & container->type)) 47 return NFNL_CB_CONTINUE; 48 49 switch(subsys) { 50 case NFNL_SUBSYS_CTNETLINK: 51 ct = nfct_new(); 52 if (ct == NULL) 53 return NFNL_CB_FAILURE; 54 55 __parse_conntrack(nlh, nfa, ct); 56 57 if (container->h->cb) { 58 ret = container->h->cb(type, ct, container->data); 59 } else if (container->h->cb2) { 60 ret = container->h->cb2(nlh, type, ct, 61 container->data); 62 } 63 break; 64 case NFNL_SUBSYS_CTNETLINK_EXP: 65 exp = nfexp_new(); 66 if (exp == NULL) 67 return NFNL_CB_FAILURE; 68 69 __parse_expect(nlh, nfa, exp); 70 71 if (container->h->expect_cb) { 72 ret = container->h->expect_cb(type, exp, 73 container->data); 74 } else if (container->h->expect_cb2) { 75 ret = container->h->expect_cb2(nlh, type, exp, 76 container->data); 77 } 78 break; 79 default: 80 errno = ENOTSUP; 81 ret = NFNL_CB_FAILURE; 82 break; 83 } 84 85 if (ret == NFCT_CB_STOLEN) 86 return NFNL_CB_CONTINUE; 87 88 if (ct) 89 nfct_destroy(ct); 90 if (exp) 91 nfexp_destroy(exp); 92 93 return ret; 94} 95