diff options
Diffstat (limited to 'plugins/vcgn-plugin/vcgn/cnat_pcp_server.h')
-rw-r--r-- | plugins/vcgn-plugin/vcgn/cnat_pcp_server.h | 398 |
1 files changed, 398 insertions, 0 deletions
diff --git a/plugins/vcgn-plugin/vcgn/cnat_pcp_server.h b/plugins/vcgn-plugin/vcgn/cnat_pcp_server.h new file mode 100644 index 00000000000..c77c6a875f8 --- /dev/null +++ b/plugins/vcgn-plugin/vcgn/cnat_pcp_server.h @@ -0,0 +1,398 @@ +/* + *------------------------------------------------------------------ + * cnat_pcp_server.h + * + * Copyright (c) 2009-2012 Cisco and/or its affiliates. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at: + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + *------------------------------------------------------------------ + */ + +#ifndef __CNAT_PCP_SERVER_H__ +#define __CNAT_PCP_SERVER_H__ + +#include "dslite_defs.h" + +/* Debug utils of PCP */ +#define PCP_DBG(debug, ...) \ + if(PREDICT_FALSE(cnat_pcp_debug_flag >= debug)) { \ + printf("%s:%s:%d - ", \ + __FILE__, __FUNCTION__, __LINE__);\ + printf(__VA_ARGS__);\ + printf("\n"); \ + } + +#define PCP_DUMP_PDATA \ + if(PREDICT_FALSE(cnat_pcp_debug_flag >= 100)) { \ + printf("%s:%s:%d - \n", \ + __FILE__, __FUNCTION__, __LINE__);\ + printf("src - ip = %X, proto = %d, port = %d i_vrf = %d, o_vrf = %d\n", \ + pcp_data.src_ip[3], pcp_data.proto, pcp_data.src_port, pcp_data.i_vrf, pcp_data.o_vrf); \ + printf(" third party ip = %X\n", pcp_data.third_party_ip[3]); \ + printf("map - ip = %X, port = %d \n", \ + pcp_data.ext_ip[3], pcp_data.ext_port);\ + printf("remote - ip = %X, port = %d \n", \ + pcp_data.peer_ip[3], pcp_data.peer_port); \ + printf("req life time = %d \n", pcp_data.req_lifetime); \ + printf("drop = %d \n", pcp_data.drop);\ + printf("udp_len = %d \n", pcp_data.udp_len); \ + printf("pm = %p \n", pcp_data.pm); \ + printf("cnat_proto = %X \n", pcp_data.cnat_proto); \ + printf("inst_id = %X \n", pcp_data.inst_id); \ + printf("======================================================\n"); \ + } + +#define PCP_DUMP_PACKET(ip, len) pcp_hex_dump(ip, len) + +#ifdef TOBE_PORTED +#define PCP_INCR(counter) pcp_counters.pcp_##counter++ ; +#else +#define PCP_INCR(counter) +#endif + +typedef struct pcp_debug_counters { + u64 pcp_input; + u64 pcp_output; + u64 pcp_service_nat44; + u64 pcp_service_dslite; + /* below all are drops */ + u64 pcp_drops; + u64 pcp_i2o_key_inuse; + u64 pcp_throttle_drops; + u64 pcp_udp_len; + u64 pcp_nrequest; + u64 pcp_min_udp_len; + u64 pcp_max_udp_len; + u64 pcp_mod4_len; + u64 pcp_invalid_3rd_len; + u64 pcp_invalid_option; + u64 pcp_version; + u64 pcp_invalid_opcode; + u64 pcp_invalid_client_ip; + u64 pcp_invalid_proto; + u64 pcp_invalid_port; + u64 pcp_invalid_vrfmap; + u64 pcp_invalid_ext_addr; + u64 pcp_out_addr_inuse; + u64 pcp_exact_match; + u64 pcp_exact_entry_created; + u64 pcp_exact_db_alloc_failed; + u64 pcp_udb_mismatch; + u64 pcp_noexact_db_allocated; + u64 pcp_static_entry_present; + u64 pcp_entry_deleted; + u64 pcp_3rd_party_option; + + /* map counters */ + u64 pcp_map_input; + u64 pcp_map_min_len; + u64 pcp_map_max_len; + u64 pcp_map_invalid_option; + u64 pcp_map_invalid_option_len; + u64 pcp_map_pref_fail_option; + u64 pcp_map_invalid_delete_req; + u64 pcp_map_delete_req; + u64 pcp_map_create_req; + u64 pcp_map_refresh; + + /* peer counters */ + u64 pcp_peer_input; + u64 pcp_peer_invalid_len; + u64 pcp_peer_delete_req; + u64 pcp_peer_create_req; + u64 pcp_peer_addr_mistmatch; + u64 pcp_peer_refresh; + +} pcp_debug_counters_t; + +typedef struct { + u16 msg_id; + u8 rc; + u8 pad[5]; + + /* better to have a group structures rather than individual + variables, any change in counters is will automatically + reflect here */ + pcp_debug_counters_t counters; +} pcp_show_counters_resp_t ; + + + +/* PCP opcodes */ +typedef enum pcp_opcode { + PCP_OPCODE_MAP = 1, + PCP_OPCODE_PEER = 2 +}pcp_opcode_t; + + +/* PCP opcodes */ +typedef enum pcp_options { + PCP_OPTION_3RD_PARTY = 1, + PCP_OPTION_PREF_FAIL = 2, + PCP_OPTION_FILTER = 3 +} pcp_options_t; + +/* PCP Result codes */ +typedef enum pcp_result_codes { + PCP_SUCCESS = 0, + PCP_ERR_UNSUPP_VERSION = 1, + PCP_ERR_NOT_AUTHORIZED = 2, + PCP_ERR_MALFORMED_REQUEST = 3, + PCP_ERR_UNSUPP_OPCODE = 4, + PCP_ERR_UNSUPP_OPTION = 5, + PCP_ERR_MALFORMED_OPTION = 6, + PCP_ERR_NETWORK_FAILURE = 7, + PCP_ERR_NO_RESOURCES = 8, + PCP_ERR_UNSUPP_PROTOCOL = 9, + PCP_ERR_USER_EX_QUOTA = 10, + PCP_ERR_CANNOT_PROVIDE_EXTERNAL = 11, + PCP_ERR_ADDRESS_MISMATCH = 12, + PCP_ERR_EXCESSIVE_REMOTE_PEERS = 13 +} pcp_result_codes_t; + +#define PCP_DISABLED 0 +#define PCP_ENABLED 1 + +#define PCP_DROP 1 + +#define PCP_STATIC_LIFETIME 0xFFFFFFFF +#define PCP_MAX_LIFETIME 0x00015180 /* 24 hours = 86400 seconds*/ + +#define PCP_VERSION_SUPPORTED 1 + +#define PCP_NO_PREF_FAIL_OPTION 0 +#define PCP_PREF_FAIL_OPTION 1 + +#define CNAT_DEF_PCP_PORT 5351 + +#define PCP_REQ_RESP_BIT 0x80 +#define PCP_RESPONSE(r_opcode) (r_opcode & PCP_REQ_RESP_BIT) +#define PCP_REQUEST(r_opcode) !(PCP_RESPONSE(r_opcode)) + +#define PCP_REQ_OPCODE(r_opcode) (r_opcode & 0x7F) + +/* 24 bytes */ +#define PCP_COMMON_HDR_LEN sizeof(pcp_request_t) + +/* 8 bytes */ +#define UDP_HDR_LEN sizeof(udp_hdr_type_t) + +#define PCP_PREF_FAIL_OPTION_SIZE \ + sizeof(pcp_prefer_fail_option_t) + +#define PCP_3RD_PARTY_OPTION_SIZE \ + sizeof(pcp_3rd_party_option_t) + +#define PCP_MIN_LEN PCP_COMMON_HDR_LEN + +/* 24+8=32 bytes */ +#define PCP_MIN_UDP_LEN (PCP_MIN_LEN + UDP_HDR_LEN) + +#define PCP_MAX_LEN 1024 + +/* 1024+8 = 1032 bytes */ +#define PCP_MAX_UDP_LEN (PCP_MAX_LEN + UDP_HDR_LEN) + +/* 24+ 24 = 48 bytes */ +#define PCP_MAP_OPCODE_MIN_LEN (PCP_COMMON_HDR_LEN + \ + sizeof( pcp_map_option_specific_data_t)) + +/* 24 + 44 = 68 bytes */ +#define PCP_PEER_OPCODE_MIN_LEN (PCP_COMMON_HDR_LEN + \ + sizeof( pcp_peer_option_specific_data_t)) + +/* 48 + 8 = 56 bytes */ +#define PCP_MAP_OPCODE_MIN_UDP_LEN (PCP_MAP_OPCODE_MIN_LEN + \ + UDP_HDR_LEN ) + +#define PCP_GET_MAP_OPTION_OFFSET(req) \ + ((u8*)req + PCP_MAP_OPCODE_MIN_LEN) + +#define PCP_GET_PEER_OPTION_OFFSET(req) \ + ((u8*)req + PCP_PEER_OPCODE_MIN_LEN) + + +#define PCP_REQ_TOTAL_LEN(udp) (udp->udp_length - \ + UDP_HDR_LEN) +/* 56 + 4 = 60 bytes */ +#define PCP_MAP_OPCODE_PREF_FAIL_OPTION_LEN \ + (PCP_MAP_OPCODE_MIN_UDP_LEN + \ + sizeof(pcp_prefer_fail_option_t)) + + +/* 68 + 8 = 76 bytes */ +#define PCP_PEER_OPCODE_MIN_UDP_LEN (PCP_PEER_OPCODE_MIN_LEN + \ + UDP_HDR_LEN) + +#define PCP_MUST_OPTION(option_code) (option_code & 0x80) + + + +/* 56 + 20 = 76*/ +#define PCP_DSLITE_MAP_OPCODE_MIN_UDP_LEN \ + ( PCP_MAP_OPCODE_MIN_UDP_LEN + \ + PCP_3RD_PARTY_OPTION_SIZE) + +/* 60 + 20 = 80 */ +#define PCP_DSLITE_MAP_OPCODE_MAX_UDP_LEN \ + ( PCP_MAP_OPCODE_PREF_FAIL_OPTION_LEN + \ + PCP_3RD_PARTY_OPTION_SIZE) + +/* 76 + 20 = 96 */ +#define PCP_DSLITE_PEER_OPCODE_MIN_UDP_LEN \ + ( PCP_PEER_OPCODE_MIN_UDP_LEN + \ + PCP_3RD_PARTY_OPTION_SIZE) + + +#define PCP_SET_CNAT_PROTO(proto) \ + pcp_data.cnat_proto = (proto == TCP_PROT) ? CNAT_TCP: \ + (proto == UDP_PROT)? CNAT_UDP : CNAT_ICMP; + +#define PCP_SET_REQ_LIFETIME() \ + if(pcp_data.db->flags & CNAT_DB_FLAG_STATIC_PORT) { \ + pcp_data.db->proto_data.seq_pcp.pcp_lifetime = \ + PCP_STATIC_LIFETIME; \ + pcp_data.req_lifetime = PCP_STATIC_LIFETIME; \ + } else { \ + pcp_data.db->proto_data.seq_pcp.pcp_lifetime = \ + pcp_data.req_lifetime + cnat_current_time ; \ + } + + +/* per second not more than PCP_THROTTLE_LIMIT + * delete requests will be handled. + * this excludes , specific entries, in which + * only one entry needs to be deleted + */ +#define PCP_THROTTLE_LIMIT 2 + +typedef struct pcp_request { + u8 ver; + u8 r_opcode; + u16 reserved; + u32 req_lifetime; + u32 ip[4]; /* ipv4 will be represented + by the ipv4 mapped ipv6 */ +} pcp_request_t; + +typedef struct pcp_response { + u8 ver; + u8 r_opcode; + u8 reserved; + u8 result_code; + u32 lifetime; + u32 epochtime; + u32 reserved1[3]; +} pcp_response_t; + + +typedef struct pcp_options_hdr { + u8 code; + u8 reserved; + u16 len; + u8 data[0]; +} pcp_options_hdr_t; + + +/* same for both request and response */ +typedef struct pcp_map_option_specific_data { + u8 protocol; + u8 reserved[3]; + u16 int_port; + u16 ext_port; + u32 ext_ip[4]; /* ipv4 will be represnted + by the ipv4 mapped ipv6 */ +} pcp_map_option_specific_data_t; + +/* same for both request and response */ +typedef struct pcp_peer_option_specific_data { + u8 protocol; + u8 reserved[3]; + u16 int_port; + u16 ext_port; + u32 ext_ip[4]; /* ipv4 will be represented + by the ipv4 mapped ipv6 */ + u16 peer_port; + u16 reserved1; + u32 peer_ip[4]; +} pcp_peer_option_specific_data_t; + +typedef struct pcp_prefer_fail_option { + u8 option; + u8 reserved; + u16 len; +} pcp_prefer_fail_option_t; + + +typedef struct pcp_3rd_party_option{ + u8 option; + u8 reserved; + u16 len; + u32 ip[4]; +} pcp_3rd_party_option_t; + +/* structure used as pipeline data */ + +typedef struct pcp_pipeline_data { + + union { + + u8 *p; + ipv4_header *ip ; + ipv6_header_t *ipv6 ; + + } l3addr; + + udp_hdr_type_t *udp; + pcp_request_t *req; + pcp_response_t *resp; + pcp_opcode_t opcode; + u32 src_ip[4]; + u16 src_port; + u8 proto; + u16 i_vrf; + u16 o_vrf; + u32 ext_ip[4]; + u16 ext_port; + u32 third_party_ip[4]; + + /* valid for peer opcode */ + u32 peer_ip[4]; + u32 peer_port; + u32 req_lifetime; + u32 udp_len; + pcp_options_t pref_fail; + pcp_options_t third_party; + u8 *option_spec; + pcp_result_codes_t ret_code; + cnat_portmap_v2_t *pm; + cnat_main_db_entry_t *db; + cnat_vrfmap_t *vrfmap; + dslite_table_entry_t *inst_ptr; + u16 inst_id; + u32 flags; + u16 cnat_proto; + + /* is packet needs to be dropped ? */ + u8 drop; + /* nat44, dslite, nat64 */ +#define PCP_SERVICE_NAT44 1 +#define PCP_SERVICE_DSLITE 2 +#define PCP_SERVICE_NAT64 3 + u8 service_type; + +#define PCP_REQ_ENTRY_PRESENT 1 +#define PCP_REQ_EXT_MAP_PRESENT 1 + u8 state; +} pcp_pipeline_data_t; + +#endif /* __CNAT_PCP_sERVER_H__ */ |