| /* |
| * |
| * Copyright (C) 2007 Mindspeed Technologies, Inc. |
| * |
| * This program is free software; you can redistribute it and/or modify |
| * it under the terms of the GNU General Public License as published by |
| * the Free Software Foundation; either version 2 of the License, or |
| * (at your option) any later version. |
| * |
| * This program is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| * GNU General Public License for more details. |
| * |
| * You should have received a copy of the GNU General Public License |
| * along with this program; if not, write to the Free Software |
| * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <net/if.h> |
| #include "cmm.h" |
| |
| int * cmm_third_part_init(void) |
| { |
| #ifndef CMM_THIRD_PART |
| return NULL; |
| #endif |
| |
| cmm_print(DEBUG_INFO, "%s\n", __func__); |
| |
| /* perform all required initialization */ |
| |
| /* define and return private data */ |
| |
| return NULL; |
| } |
| |
| |
| static void cmm_third_part_cb (void *priv, unsigned short type, void *data, unsigned short *resp_length, unsigned short *resp_payload) |
| { |
| struct cmm_ct_to_queue_t *msg; |
| char saddr_buf[INET6_ADDRSTRLEN]; |
| char daddr_buf[INET6_ADDRSTRLEN]; |
| char ifname[IFNAMSIZ]; |
| |
| cmm_print(DEBUG_INFO, "%s\n", __func__); |
| |
| /* For now the only supported event type has mandatory data. Should be moved to switch-case below if new event are added */ |
| if(data == NULL) |
| return; |
| |
| /* Handling of the private data should be done here if needed */ |
| |
| |
| /* Event type handling */ |
| switch(type) |
| { |
| case CMM_CB_CT_TO_QUEUE: |
| /* Retrieve connection information */ |
| msg = (struct cmm_ct_to_queue_t *)data; |
| |
| cmm_print(DEBUG_INFO, "CMM_CB_CT_TO_QUEUE\nstate %d ipfamily %d proto %d mark 0x%08x\n", msg->state, msg->ip_family, msg->proto, msg->mark); |
| |
| if(msg->state & ORIGINATOR) |
| cmm_print(DEBUG_INFO, "originate output_itf %s saddr %s daddr %s sport %d dport %d gw mac %02x:%02x:%02x:%02x:%02x:%02x\n", if_indextoname(msg->orig_output, ifname), inet_ntop(msg->ip_family, msg->orig_saddr, saddr_buf, INET6_ADDRSTRLEN), inet_ntop(msg->ip_family, msg->orig_daddr, daddr_buf, INET6_ADDRSTRLEN), ntohs(msg->orig_sport), ntohs(msg->orig_dport), msg->orig_gw_mac[0],msg->orig_gw_mac[1],msg->orig_gw_mac[2],msg->orig_gw_mac[3],msg->orig_gw_mac[4],msg->orig_gw_mac[5]); |
| |
| if(msg->state & REPLIER) |
| cmm_print(DEBUG_INFO, "replier output_itf %s saddr %s daddr %s sport %d dport %d gw mac %02x:%02x:%02x:%02x:%02x:%02x\n", if_indextoname(msg->repl_output, ifname), inet_ntop(msg->ip_family, msg->repl_saddr, saddr_buf, INET6_ADDRSTRLEN), inet_ntop(msg->ip_family, msg->repl_daddr, daddr_buf, INET6_ADDRSTRLEN), ntohs(msg->repl_sport), ntohs(msg->repl_dport), msg->repl_gw_mac[0],msg->repl_gw_mac[1],msg->repl_gw_mac[2],msg->repl_gw_mac[3],msg->repl_gw_mac[4],msg->repl_gw_mac[5]); |
| |
| /* Define new mark */ |
| |
| /* Following lines are for test purpose only (mark change for a given port 1024) */ |
| #if 0 |
| if(ntohs(msg->orig_sport) == 1024) |
| msg->mark = 0x1; |
| #endif |
| break; |
| |
| default: |
| break; |
| } |
| } |
| |
| void cmm_third_part_exit(void *priv_data) |
| { |
| #ifndef CMM_THIRD_PART |
| return; |
| #endif |
| |
| cmm_print(DEBUG_INFO, "%s\n", __func__); |
| |
| /* free allocated resources */ |
| } |
| |
| |
| static void cmm_third_part_dump_ct(struct cmm_ct_to_queue_t * msg) |
| { |
| char saddr_buf[INET6_ADDRSTRLEN], daddr_buf[INET6_ADDRSTRLEN]; |
| |
| cmm_print(DEBUG_INFO, "orig_saddr %s orig_daddr %s orig_sport %d orig_dport %d\n", |
| inet_ntop(msg->ip_family, msg->orig_saddr, saddr_buf, INET6_ADDRSTRLEN), |
| inet_ntop(msg->ip_family, msg->orig_daddr, daddr_buf, INET6_ADDRSTRLEN), |
| ntohs(msg->orig_sport), |
| ntohs(msg->orig_dport)); |
| |
| cmm_print(DEBUG_INFO, "repl_saddr %s repl_daddr %s repl_sport %d repl_dport %d\n", |
| inet_ntop(msg->ip_family, msg->repl_saddr, saddr_buf, INET6_ADDRSTRLEN), |
| inet_ntop(msg->ip_family, msg->repl_daddr, daddr_buf, INET6_ADDRSTRLEN), |
| ntohs(msg->repl_sport), |
| ntohs(msg->repl_dport)); |
| |
| cmm_print(DEBUG_INFO, "mark 0x%08x\n", msg->mark); |
| } |
| |
| |
| void cmm_third_part_update(struct ctTable *ctEntry, int dir) |
| { |
| #ifndef CMM_THIRD_PART |
| return; |
| #endif |
| |
| /* Fill a buffer with the information required for CMM_CB_CT_TO_QUEUE event */ |
| struct cmm_ct_to_queue_t msg; |
| const unsigned int *dAddrOrig, *dAddrRepl, *sAddrOrig, *sAddrRepl; |
| unsigned short dPortOrig, dPortRepl, sPortOrig, sPortRepl; |
| unsigned char proto; |
| struct nf_conntrack *ct = ctEntry->ct; |
| |
| proto = nfct_get_attr_u8(ct, ATTR_ORIG_L4PROTO); |
| |
| if (ctEntry->family == AF_INET) |
| { |
| sAddrOrig = nfct_get_attr(ct, ATTR_ORIG_IPV4_SRC); |
| sAddrRepl = nfct_get_attr(ct, ATTR_REPL_IPV4_SRC); |
| dAddrOrig = nfct_get_attr(ct, ATTR_ORIG_IPV4_DST); |
| dAddrRepl = nfct_get_attr(ct, ATTR_REPL_IPV4_DST); |
| } |
| else |
| { |
| sAddrOrig = nfct_get_attr(ct, ATTR_ORIG_IPV6_SRC); |
| sAddrRepl = nfct_get_attr(ct, ATTR_REPL_IPV6_SRC); |
| dAddrOrig = nfct_get_attr(ct, ATTR_ORIG_IPV6_DST); |
| dAddrRepl = nfct_get_attr(ct, ATTR_REPL_IPV6_DST); |
| } |
| |
| sPortOrig = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_SRC); |
| sPortRepl = nfct_get_attr_u16(ct, ATTR_REPL_PORT_SRC); |
| dPortOrig = nfct_get_attr_u16(ct, ATTR_ORIG_PORT_DST); |
| dPortRepl = nfct_get_attr_u16(ct, ATTR_REPL_PORT_DST); |
| |
| memset(&msg, 0, sizeof(struct cmm_ct_to_queue_t )); |
| |
| msg.ip_family = ctEntry->family; |
| msg.proto = proto; |
| msg.mark = nfct_get_attr_u32(ct, ATTR_MARK); |
| |
| if(dir & ORIGINATOR) |
| { |
| if (ctEntry->family == AF_INET) |
| { |
| msg.orig_saddr[0] = sAddrOrig[0]; |
| msg.orig_daddr[0] = dAddrOrig[0]; |
| } |
| else |
| { |
| memcpy(msg.orig_saddr, sAddrOrig, 16); |
| memcpy(msg.orig_daddr, dAddrOrig, 16); |
| } |
| |
| msg.orig_sport = sPortOrig; |
| msg.orig_dport = dPortOrig; |
| if(ctEntry->orig.route->neighEntry) |
| memcpy(msg.orig_gw_mac, ctEntry->orig.route->neighEntry->macAddr, 6); |
| msg.orig_output = ctEntry->orig.route->oifindex; |
| } |
| |
| if(dir & REPLIER) |
| { |
| if (ctEntry->family == AF_INET) |
| { |
| msg.repl_saddr[0] = sAddrRepl[0]; |
| msg.repl_daddr[0] = dAddrRepl[0]; |
| } |
| else |
| { |
| memcpy(msg.repl_saddr, sAddrRepl, 16); |
| memcpy(msg.repl_daddr, dAddrRepl, 16); |
| } |
| |
| msg.repl_sport = sPortRepl; |
| msg.repl_dport = dPortRepl; |
| if(ctEntry->rep.route->neighEntry) |
| memcpy(msg.repl_gw_mac, ctEntry->rep.route->neighEntry->macAddr, 6); |
| msg.repl_output = ctEntry->rep.route->oifindex; |
| } |
| |
| /* Call 3rd Party callback */ |
| if((dir & (ORIGINATOR | REPLIER)) && (ctEntry->flags & FPP_NEEDS_UPDATE)) |
| { |
| cmm_print(DEBUG_INFO, "%s: Old connection entry\n", __func__); |
| cmm_third_part_dump_ct(&msg); |
| |
| msg.state = dir; |
| cmm_third_part_cb(globalConf.third_part_data, CMM_CB_CT_TO_QUEUE, (void*)&msg, NULL, NULL); |
| |
| cmm_print(DEBUG_INFO, "%s: New connection entry\n", __func__); |
| cmm_third_part_dump_ct(&msg); |
| |
| /* Retrieve modified parameter and apply to the connection */ |
| nfct_set_attr_u32(ct, ATTR_MARK, msg.mark); |
| } |
| |
| } |
| |
| |