From 6bd375efc4024c3cee42d43d4dd3de730a1976e6 Mon Sep 17 00:00:00 2001 From: Luca Deri Date: Tue, 10 Nov 2020 17:58:35 +0100 Subject: [PATCH] Compilation fixes Network filtering code has been temporarely commented out as it is broken --- include/n2n.h | 50 +- src/edge.c | 152 ++--- src/edge_utils.c | 103 +-- src/network_traffic_filter.c | 1171 +++++++++++++++++----------------- 4 files changed, 781 insertions(+), 695 deletions(-) diff --git a/include/n2n.h b/include/n2n.h index 30a4aa0..3a9ee53 100644 --- a/include/n2n.h +++ b/include/n2n.h @@ -109,6 +109,51 @@ struct ether_hdr typedef struct ether_hdr ether_hdr_t; +struct n2n_iphdr { +#if defined(__LITTLE_ENDIAN__) + u_int8_t ihl:4, version:4; +#elif defined(__BIG_ENDIAN__) + u_int8_t version:4, ihl:4; +#else +# error "Byte order must be defined" +#endif + u_int8_t tos; + u_int16_t tot_len; + u_int16_t id; + u_int16_t frag_off; + u_int8_t ttl; + u_int8_t protocol; + u_int16_t check; + u_int32_t saddr; + u_int32_t daddr; +} __attribute__ ((__packed__)); + +struct n2n_tcphdr +{ + u_int16_t source; + u_int16_t dest; + u_int32_t seq; + u_int32_t ack_seq; +#if defined(__LITTLE_ENDIAN__) + u_int16_t res1:4, doff:4, fin:1, syn:1, rst:1, psh:1, ack:1, urg:1, ece:1, cwr:1; +#elif defined(__BIG_ENDIAN__) + u_int16_t doff:4, res1:4, cwr:1, ece:1, urg:1, ack:1, psh:1, rst:1, syn:1, fin:1; +#else +# error "Byte order must be defined" +#endif + u_int16_t window; + u_int16_t check; + u_int16_t urg_ptr; +} __attribute__ ((__packed__)); + +struct n2n_udphdr +{ + u_int16_t source; + u_int16_t dest; + u_int16_t len; + u_int16_t check; +} __attribute__ ((__packed__)); + #ifdef HAVE_LIBZSTD #include #endif @@ -310,7 +355,8 @@ typedef struct network_traffic_filter /* A packet has been received from a peer. N2N_DROP can be returned to * drop the packet. The packet payload can be modified. This only allows * the packet size to be reduced */ - n2n_verdict (*filter_packet_from_peer)(struct network_traffic_filter* filter, n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size); + n2n_verdict (*filter_packet_from_peer)(struct network_traffic_filter* filter, n2n_edge_t *eee, + const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size); /* A packet has been received from the TAP interface. N2N_DROP can be * returned to drop the packet. The packet payload can be modified. @@ -361,7 +407,9 @@ typedef struct n2n_edge_conf { int register_ttl; /**< TTL for registration packet when UDP NAT hole punching through supernode. */ int local_port; int mgmt_port; +#ifdef FILTER_TRAFFIC filter_rule_t *network_traffic_filter_rules; +#endif } n2n_edge_conf_t; diff --git a/src/edge.c b/src/edge.c index cc9b15b..99f8e8c 100644 --- a/src/edge.c +++ b/src/edge.c @@ -35,8 +35,8 @@ #include "network_traffic_filter.h" static cap_value_t cap_values[] = { - //CAP_NET_RAW, /* Use RAW and PACKET sockets */ - CAP_NET_ADMIN /* Needed to performs routes cleanup at exit */ + //CAP_NET_RAW, /* Use RAW and PACKET sockets */ + CAP_NET_ADMIN /* Needed to performs routes cleanup at exit */ }; int num_cap = sizeof(cap_values)/sizeof(cap_value_t); @@ -144,7 +144,11 @@ static void help() { #ifndef __APPLE__ "[-D] " #endif - "[-r] [-E] [-v] [-i ] [-L ] [-t ] [-A[]] [-H] [-z[]] [-R ] [-h]\n\n"); + "[-r] [-E] [-v] [-i ] [-L ] [-t ] [-A[]] [-H] [-z[]] " +#ifdef FILTER_TRAFFIC + "[-R ] " +#endif + "[-h]\n\n"); #if defined(N2N_CAN_NAME_IFACE) printf("-d | tap device name\n"); @@ -176,14 +180,14 @@ static void help() { printf("-A1 | Disable payload encryption. Do not use with key (defaulting to Twofish then).\n"); printf("-A2 ... -A5 or -A | Choose a cipher for payload encryption, requires a key: -A2 = Twofish (default),\n"); printf(" | -A3 or -A (deprecated) = AES, " - "-A4 = ChaCha20, " - "-A5 = Speck-CTR.\n"); + "-A4 = ChaCha20, " + "-A5 = Speck-CTR.\n"); printf("-H | Enable full header encryption. Requires supernode with fixed community.\n"); printf("-z1 ... -z2 or -z | Enable compression for outgoing data packets: -z1 or -z = lzo1x" #ifdef N2N_HAVE_ZSTD - ", -z2 = zstd" + ", -z2 = zstd" #endif - " (default=disabled).\n"); + " (default=disabled).\n"); printf("-E | Accept multicast MAC addresses (default=drop).\n"); printf("-S | Do not connect P2P. Always use the supernode.\n"); #ifdef __linux__ @@ -383,10 +387,10 @@ static int setOption(int optkey, char *optargument, n2n_tuntap_priv_config_t *ec case 'H': /* indicate header encryption */ { - /* we cannot be sure if this gets parsed before the community name is set. - * so, only an indicator is set, action is taken later*/ - conf->header_encryption = HEADER_ENCRYPTION_ENABLED; - break; + /* we cannot be sure if this gets parsed before the community name is set. + * so, only an indicator is set, action is taken later*/ + conf->header_encryption = HEADER_ENCRYPTION_ENABLED; + break; } case 'z': @@ -440,10 +444,10 @@ static int setOption(int optkey, char *optargument, n2n_tuntap_priv_config_t *ec { conf->local_port = atoi(optargument); - if(conf->local_port == 0){ - traceEvent(TRACE_WARNING, "Bad local port format"); - break; - } + if(conf->local_port == 0){ + traceEvent(TRACE_WARNING, "Bad local port format"); + break; + } break; } @@ -519,21 +523,23 @@ static int setOption(int optkey, char *optargument, n2n_tuntap_priv_config_t *ec setTraceLevel(getTraceLevel() + 1); break; +#ifdef FILTER_TRAFFIC case 'R': /* network traffic filter */ - { - filter_rule_t *new_rule = malloc(sizeof(filter_rule_t)); - memset(new_rule, 0, sizeof(filter_rule_t)); - if(process_traffic_filter_rule_str(optargument, new_rule) ) { - HASH_ADD(hh, conf->network_traffic_filter_rules, key, sizeof(filter_rule_key_t), new_rule); - }else{ + filter_rule_t *new_rule = malloc(sizeof(filter_rule_t)); + memset(new_rule, 0, sizeof(filter_rule_t)); + if(process_traffic_filter_rule_str(optargument, new_rule) ) + { + HASH_ADD(hh, conf->network_traffic_filter_rules, key, sizeof(filter_rule_key_t), new_rule); + }else{ free(new_rule); traceEvent(TRACE_WARNING, "Invalid filter rule: %s", optargument); return(-1); + } + break; } - break; - } - +#endif + default: { traceEvent(TRACE_WARNING, "Unknown option -%c: Ignored", (char)optkey); @@ -548,15 +554,15 @@ static int setOption(int optkey, char *optargument, n2n_tuntap_priv_config_t *ec static const struct option long_options[] = { - { "community", required_argument, NULL, 'c' }, - { "supernode-list", required_argument, NULL, 'l' }, - { "tap-device", required_argument, NULL, 'd' }, - { "euid", required_argument, NULL, 'u' }, - { "egid", required_argument, NULL, 'g' }, - { "help" , no_argument, NULL, 'h' }, - { "verbose", no_argument, NULL, 'v' }, - { NULL, 0, NULL, 0 } -}; + { "community", required_argument, NULL, 'c' }, + { "supernode-list", required_argument, NULL, 'l' }, + { "tap-device", required_argument, NULL, 'd' }, + { "euid", required_argument, NULL, 'u' }, + { "egid", required_argument, NULL, 'g' }, + { "help" , no_argument, NULL, 'h' }, + { "verbose", no_argument, NULL, 'v' }, + { NULL, 0, NULL, 0 } + }; /* *************************************************** */ @@ -842,48 +848,48 @@ int main(int argc, char* argv[]) { if(conf.encrypt_key && !strcmp((char*)conf.community_name, conf.encrypt_key)) traceEvent(TRACE_WARNING, "Community and encryption key must differ, otherwise security will be compromised"); - if((eee = edge_init(&conf, &rc)) == NULL) { - traceEvent(TRACE_ERROR, "Failed in edge_init"); - exit(1); - } - memcpy(&(eee->tuntap_priv_conf), &ec, sizeof(ec)); - - if ((0 == strcmp("static", eee->tuntap_priv_conf.ip_mode)) || - ((eee->tuntap_priv_conf.ip_mode[0] == '\0') && (eee->tuntap_priv_conf.ip_addr[0] != '\0'))) { - traceEvent(TRACE_NORMAL, "Use manually set IP address."); - eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_STATIC; - } else if (0 == strcmp("dhcp", eee->tuntap_priv_conf.ip_mode)) { - traceEvent(TRACE_NORMAL, "Obtain IP from other edge DHCP services."); - eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_DHCP; - } else { - traceEvent(TRACE_NORMAL, "Automatically assign IP address by supernode."); - eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN; - do { - fd_set socket_mask; - struct timeval wait_time; - - update_supernode_reg(eee, time(NULL)); - FD_ZERO(&socket_mask); - FD_SET(eee->udp_sock, &socket_mask); - wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; - wait_time.tv_usec = 0; - - if (select(eee->udp_sock + 1, &socket_mask, NULL, NULL, &wait_time) > 0) { - if (FD_ISSET(eee->udp_sock, &socket_mask)) { - readFromIPSocket(eee, eee->udp_sock); - } - } - } while (eee->sn_wait); - eee->last_register_req = 0; + if((eee = edge_init(&conf, &rc)) == NULL) { + traceEvent(TRACE_ERROR, "Failed in edge_init"); + exit(1); + } + memcpy(&(eee->tuntap_priv_conf), &ec, sizeof(ec)); + + if ((0 == strcmp("static", eee->tuntap_priv_conf.ip_mode)) || + ((eee->tuntap_priv_conf.ip_mode[0] == '\0') && (eee->tuntap_priv_conf.ip_addr[0] != '\0'))) { + traceEvent(TRACE_NORMAL, "Use manually set IP address."); + eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_STATIC; + } else if (0 == strcmp("dhcp", eee->tuntap_priv_conf.ip_mode)) { + traceEvent(TRACE_NORMAL, "Obtain IP from other edge DHCP services."); + eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_DHCP; + } else { + traceEvent(TRACE_NORMAL, "Automatically assign IP address by supernode."); + eee->conf.tuntap_ip_mode = TUNTAP_IP_MODE_SN_ASSIGN; + do { + fd_set socket_mask; + struct timeval wait_time; + + update_supernode_reg(eee, time(NULL)); + FD_ZERO(&socket_mask); + FD_SET(eee->udp_sock, &socket_mask); + wait_time.tv_sec = SOCKET_TIMEOUT_INTERVAL_SECS; + wait_time.tv_usec = 0; + + if (select(eee->udp_sock + 1, &socket_mask, NULL, NULL, &wait_time) > 0) { + if (FD_ISSET(eee->udp_sock, &socket_mask)) { + readFromIPSocket(eee, eee->udp_sock); } + } + } while (eee->sn_wait); + eee->last_register_req = 0; + } - if (tuntap_open(&tuntap, eee->tuntap_priv_conf.tuntap_dev_name, eee->tuntap_priv_conf.ip_mode, - eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask, - eee->tuntap_priv_conf.device_mac, eee->tuntap_priv_conf.mtu) < 0) exit(1); - traceEvent(TRACE_NORMAL, "Local tap IP: %s, Mask: %s", - eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask); - memcpy(&eee->device, &tuntap, sizeof(tuntap)); -// hexdump((unsigned char*)&tuntap,sizeof(tuntap_dev)); + if (tuntap_open(&tuntap, eee->tuntap_priv_conf.tuntap_dev_name, eee->tuntap_priv_conf.ip_mode, + eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask, + eee->tuntap_priv_conf.device_mac, eee->tuntap_priv_conf.mtu) < 0) exit(1); + traceEvent(TRACE_NORMAL, "Local tap IP: %s, Mask: %s", + eee->tuntap_priv_conf.ip_addr, eee->tuntap_priv_conf.netmask); + memcpy(&eee->device, &tuntap, sizeof(tuntap)); + // hexdump((unsigned char*)&tuntap,sizeof(tuntap_dev)); #ifndef WIN32 if(eee->tuntap_priv_conf.daemon) { diff --git a/src/edge_utils.c b/src/edge_utils.c index 8d4c8a5..8b926ee 100644 --- a/src/edge_utils.c +++ b/src/edge_utils.c @@ -271,9 +271,11 @@ n2n_edge_t* edge_init(const n2n_edge_conf_t *conf, int *rv) { goto edge_init_error; } - eee->network_traffic_filter = create_network_traffic_filter(); +#ifdef FILTER_TRAFFIC + eee->network_traffic_filter = create_network_traffic_filter(); network_traffic_filter_add_rule(eee->network_traffic_filter, eee->conf.network_traffic_filter_rules); - +#endif + //edge_init_success: *rv = 0; return(eee); @@ -726,8 +728,8 @@ static void send_query_peer( n2n_edge_t * eee, if(eee->conf.header_encryption == HEADER_ENCRYPTION_ENABLED){ packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, - eee->conf.header_iv_ctx, - time_stamp (), pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, + time_stamp (), pearson_hash_16 (pktbuf, idx)); } sendto_sock( eee->udp_sock, pktbuf, idx, &(eee->supernode) ); @@ -742,8 +744,8 @@ static void send_query_peer( n2n_edge_t * eee, /* Re-encrypt the orginal message again for non-repeating IV. */ memcpy(pktbuf, tmp_pkt, idx); packet_header_encrypt (pktbuf, idx, eee->conf.header_encryption_ctx, - eee->conf.header_iv_ctx, - time_stamp (), pearson_hash_16 (pktbuf, idx)); + eee->conf.header_iv_ctx, + time_stamp (), pearson_hash_16 (pktbuf, idx)); } sendto_sock( eee->udp_sock, pktbuf, idx, &(peer->sock)); } @@ -806,23 +808,23 @@ static void send_register_super(n2n_edge_t *eee) { static int sort_supernodes(n2n_edge_t *eee, time_t now){ struct peer_info *scan, *tmp; - if(eee->curr_sn != eee->conf.supernodes){ - eee->curr_sn = eee->conf.supernodes; - memcpy(&eee->supernode, &(eee->curr_sn->sock), sizeof(n2n_sock_t)); - eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; + if(eee->curr_sn != eee->conf.supernodes){ + eee->curr_sn = eee->conf.supernodes; + memcpy(&eee->supernode, &(eee->curr_sn->sock), sizeof(n2n_sock_t)); + eee->sup_attempts = N2N_EDGE_SUP_ATTEMPTS; - traceEvent(TRACE_INFO, "Registering with supernode [%s][number of supernodes %d][attempts left %u]", - supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts); + traceEvent(TRACE_INFO, "Registering with supernode [%s][number of supernodes %d][attempts left %u]", + supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts); - send_register_super(eee); - eee->sn_wait = 1; - } + send_register_super(eee); + eee->sn_wait = 1; + } - if(now - eee->last_sweep > SWEEP_TIME){ + if(now - eee->last_sweep > SWEEP_TIME){ if(eee->sn_wait == 0){ // this routine gets periodically called // it sorts supernodes in ascending order of their ping_time-fields - HASH_SORT(eee->conf.supernodes, ping_time_sort); + HASH_SORT(eee->conf.supernodes, ping_time_sort); } HASH_ITER(hh, eee->conf.supernodes, scan, tmp){ @@ -1020,7 +1022,7 @@ void update_supernode_reg(n2n_edge_t * eee, time_t nowTime) { if(supernode2sock(&(eee->supernode), eee->curr_sn->ip_addr) == 0) { traceEvent(TRACE_INFO, "Registering with supernode [%s][number of supernodes %d][attempts left %u]", - supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts); + supernode_ip(eee), HASH_COUNT(eee->conf.supernodes), (unsigned int)eee->sup_attempts); send_register_super(eee); } @@ -1157,6 +1159,7 @@ static int handle_PACKET(n2n_edge_t * eee, return(-1); } else if((!eee->conf.allow_routing) && (!is_multicast)) { /* Check if it is a routed packet */ + if((ntohs(eh->type) == 0x0800) && (eth_size >= ETH_FRAMESIZE + IP4_MIN_SIZE)) { uint32_t *dst = (uint32_t*)ð_payload[ETH_FRAMESIZE + IP4_DSTOFFSET]; uint8_t *dst_mac = (uint8_t*)eth_payload; @@ -1178,7 +1181,7 @@ static int handle_PACKET(n2n_edge_t * eee, } if( eee->network_traffic_filter->filter_packet_from_peer( eee->network_traffic_filter, eee, orig_sender, - eth_payload, eth_size ) == N2N_DROP){ + eth_payload, eth_size ) == N2N_DROP){ traceEvent(TRACE_DEBUG, "Filtered packet %u", (unsigned int)eth_size); return(0); } @@ -1347,9 +1350,9 @@ static void readFromMgmtSocket(n2n_edge_t *eee, int *keep_running) { "community: %s\n", eee->conf.community_name); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - " id tun_tap MAC edge hint last_seen\n"); + " id tun_tap MAC edge hint last_seen\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "-----------------------------------------------------------------------------------------------\n"); + "-----------------------------------------------------------------------------------------------\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "supernode_forward:\n"); @@ -1362,9 +1365,9 @@ static void readFromMgmtSocket(n2n_edge_t *eee, int *keep_running) { " %-4u %-15s %-17s %-21s %-15s %lu\n", ++num, inet_ntoa(*(struct in_addr *) &net), macaddr_str(mac_buf, peer->mac_addr), - sock_to_cstr(sockbuf, &(peer->sock)), - peer->dev_desc, - now - peer->last_seen); + sock_to_cstr(sockbuf, &(peer->sock)), + peer->dev_desc, + now - peer->last_seen); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); @@ -1382,9 +1385,9 @@ static void readFromMgmtSocket(n2n_edge_t *eee, int *keep_running) { " %-4u %-15s %-17s %-21s %-15s %lu\n", ++num, inet_ntoa(*(struct in_addr *) &net), macaddr_str(mac_buf, peer->mac_addr), - sock_to_cstr(sockbuf, &(peer->sock)), - peer->dev_desc, - now - peer->last_seen); + sock_to_cstr(sockbuf, &(peer->sock)), + peer->dev_desc, + now - peer->last_seen); sendto(eee->udp_mgmt_sock, udp_buf, msg_len, 0/*flags*/, (struct sockaddr *) &sender_sock, sizeof(struct sockaddr_in)); @@ -1392,7 +1395,7 @@ static void readFromMgmtSocket(n2n_edge_t *eee, int *keep_running) { } msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), - "-----------------------------------------------------------------------------------------------\n"); + "-----------------------------------------------------------------------------------------------\n"); msg_len += snprintf((char *) (udp_buf + msg_len), (N2N_PKT_BUF_SIZE - msg_len), "uptime %lu | ", @@ -1733,11 +1736,14 @@ void edge_read_from_tap(n2n_edge_t * eee) { } else { - if( eee->network_traffic_filter->filter_packet_from_tap( eee->network_traffic_filter, eee, eth_pkt, - len) == N2N_DROP){ + if(eee->network_traffic_filter) { + if( eee->network_traffic_filter->filter_packet_from_tap( eee->network_traffic_filter, eee, eth_pkt, + len) == N2N_DROP){ traceEvent(TRACE_DEBUG, "Filtered packet %u", (unsigned int)len); return; - } + } + } + if(eee->cb.packet_from_tap) { uint16_t tmp_len = len; if(eee->cb.packet_from_tap(eee, eth_pkt, &tmp_len) == N2N_DROP) { @@ -1799,7 +1805,7 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) { * IP transport version the packet arrived on. May need to UDP sockets. */ /* REVISIT: do not endprse use with several supernodes - memset(&sender, 0, sizeof(n2n_sock_t)); */ + memset(&sender, 0, sizeof(n2n_sock_t)); */ sender.family = AF_INET; /* UDP socket was opened PF_INET v4 */ sender.port = ntohs(sender_sock.sin_port); @@ -1970,12 +1976,12 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) { in_addr_t net; char * ip_str = NULL; n2n_REGISTER_SUPER_ACK_t ra; - uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; - n2n_sock_t *tmp_sock; - n2n_mac_t *tmp_mac; - int i; - int skip_add; - struct peer_info *sn; + uint8_t tmpbuf[REG_SUPER_ACK_PAYLOAD_SPACE]; + n2n_sock_t *tmp_sock; + n2n_mac_t *tmp_mac; + int i; + int skip_add; + struct peer_info *sn; memset(&ra, 0, sizeof(n2n_REGISTER_SUPER_ACK_t)); @@ -2037,7 +2043,7 @@ void readFromIPSocket(n2n_edge_t * eee, int in_sock) { /* REVISIT: find a more elegant expression to increase following pointers. */ tmp_sock = (void*)tmp_sock + REG_SUPER_ACK_PAYLOAD_ENTRY_SIZE; tmp_mac = (void*)tmp_sock + sizeof(n2n_sock_t); - } + } eee->last_sup = now; eee->sn_wait=0; @@ -2309,8 +2315,10 @@ void edge_term(n2n_edge_t * eee) { edge_cleanup_routes(eee); +#ifdef FILTER_TRAFFIC destroy_network_traffic_filter(eee->network_traffic_filter); - +#endif + closeTraceFile(); free(eee); @@ -2810,16 +2818,17 @@ void edge_term_conf(n2n_edge_conf_t *conf) { if (conf->routes) free(conf->routes); if (conf->encrypt_key) free(conf->encrypt_key); +#ifdef FILTER_TRAFFIC if(conf->network_traffic_filter_rules) - { - filter_rule_t *el = 0, *tmp = 0; - HASH_ITER(hh, conf->network_traffic_filter_rules, el, tmp) { - HASH_DEL(conf->network_traffic_filter_rules, el); - free(el); + filter_rule_t *el = 0, *tmp = 0; + HASH_ITER(hh, conf->network_traffic_filter_rules, el, tmp) + { + HASH_DEL(conf->network_traffic_filter_rules, el); + free(el); + } } - } - +#endif } /* ************************************** */ diff --git a/src/network_traffic_filter.c b/src/network_traffic_filter.c index e49d958..a3ce3e8 100644 --- a/src/network_traffic_filter.c +++ b/src/network_traffic_filter.c @@ -16,6 +16,7 @@ * */ +#ifdef FILTER_TRAFFIC #include "network_traffic_filter.h" #include "uthash.h" @@ -27,427 +28,444 @@ #define CLAER_CACHE_ACTIVE_COUNT 10 typedef enum { - FPP_UNKNOWN=0, - FPP_ARP = 1, - FPP_TCP=2, - FPP_UDP=3, - FPP_ICMP=4, - FPP_IGMP=5 + FPP_UNKNOWN=0, + FPP_ARP = 1, + FPP_TCP=2, + FPP_UDP=3, + FPP_ICMP=4, + FPP_IGMP=5 } filter_packet_proto; const char* get_filter_packet_proto_name(filter_packet_proto proto) { - switch (proto) + switch (proto) { - case FPP_ARP: - return "ARP"; - case FPP_TCP: - return "TCP"; - case FPP_UDP: - return "UDP"; - case FPP_ICMP: - return "ICMP"; - case FPP_IGMP: - return "IGMP"; - default: - return "UNKNOWN_PROTO"; + case FPP_ARP: + return "ARP"; + case FPP_TCP: + return "TCP"; + case FPP_UDP: + return "UDP"; + case FPP_ICMP: + return "ICMP"; + case FPP_IGMP: + return "IGMP"; + default: + return "UNKNOWN_PROTO"; } } typedef struct packet_address_proto_info{ - in_addr_t src_ip; - uint16_t src_port; - in_addr_t dst_ip; - uint16_t dst_port; - filter_packet_proto proto; + in_addr_t src_ip; + uint16_t src_port; + in_addr_t dst_ip; + uint16_t dst_port; + filter_packet_proto proto; }packet_address_proto_info_t; const char* get_filter_packet_info_log_string(packet_address_proto_info_t* info) { - static char buf[1024] = {0}; - switch (info->proto) + static char buf[1024] = {0}; + switch (info->proto) { - case FPP_ARP: - case FPP_ICMP: - case FPP_IGMP: - return get_filter_packet_proto_name(info->proto); - case FPP_TCP: - case FPP_UDP: - { - struct in_addr src, dst; - src.s_addr = info->src_ip; - dst.s_addr = info->dst_ip; - const char* proto = get_filter_packet_proto_name(info->proto); - char src_ip[64] = {0}; char dst_ip[64] = {0}; - strcpy( src_ip, inet_ntoa(src)); strcpy(dst_ip, inet_ntoa(dst)); - sprintf(buf, "%s\t%s:%d->%s:%d", proto, src_ip, info->src_port, dst_ip, info->dst_port); - return buf; - } - default: - return "UNKNOWN_PROTO"; + case FPP_ARP: + case FPP_ICMP: + case FPP_IGMP: + return get_filter_packet_proto_name(info->proto); + case FPP_TCP: + case FPP_UDP: + { + struct in_addr src, dst; + src.s_addr = info->src_ip; + dst.s_addr = info->dst_ip; + const char* proto = get_filter_packet_proto_name(info->proto); + char src_ip[64] = {0}; char dst_ip[64] = {0}; + strcpy( src_ip, inet_ntoa(src)); strcpy(dst_ip, inet_ntoa(dst)); + sprintf(buf, "%s\t%s:%d->%s:%d", proto, src_ip, info->src_port, dst_ip, info->dst_port); + return buf; + } + default: + return "UNKNOWN_PROTO"; } } void collect_packet_info(packet_address_proto_info_t* out_info, unsigned char *buffer, int size) { - struct ethhdr *hdr_ether = (struct ethhdr*)buffer; - memset(out_info, 0, sizeof(packet_address_proto_info_t)); - uint16_t ether_type = ntohs(hdr_ether->h_proto); - switch (ether_type) { - case 0x0800: - { - buffer += ETH_HLEN; size -= ETH_HLEN; if(size <= 0) return; - struct iphdr *hdr_ip = (struct iphdr*)buffer; - switch (hdr_ip->version) - { - case 4: - { - out_info->src_ip = hdr_ip->saddr; - out_info->dst_ip = hdr_ip->daddr; - switch (hdr_ip->protocol) { - case 0x01: - out_info->proto = FPP_ICMP; - break; - case 0x02: - out_info->proto = FPP_IGMP; - break; - case 0x06: - { - out_info->proto = FPP_TCP; - buffer += hdr_ip->ihl * 4; size -= hdr_ip->ihl * 4; if(size <= 0) return; - struct tcphdr *hdr_tcp = (struct tcphdr*)buffer; - out_info->src_port = ntohs(hdr_tcp->th_sport); - out_info->dst_port = ntohs(hdr_tcp->th_dport); - break; - } - case 0x11: - { - out_info->proto = FPP_UDP; - buffer += hdr_ip->ihl * 4; size -= hdr_ip->ihl * 4; if(size <= 0) return; - struct udphdr *udp_hdr = (struct tcphdr*)buffer; - out_info->src_port = ntohs(udp_hdr->uh_sport); - out_info->dst_port = ntohs(udp_hdr->uh_dport); - break; - } - default: - out_info->proto = FPP_UNKNOWN; - }; - break; - } - case 6: - { - // TODO: IPV6 Not Support - out_info->proto = FPP_UNKNOWN; - break; - } - default: - out_info->proto = FPP_UNKNOWN; - } - break; - } - case 0x0806: - out_info->proto = FPP_ARP; - break; - case 0x86DD: - out_info->proto = FPP_UNKNOWN; - break; - default: - printf("EtherType 0x%04X", ether_type); - }; + ether_hdr_t *hdr_ether = (ether_hdr_t*)buffer; + uint16_t ether_type = ntohs(hdr_ether->type); + + memset(out_info, 0, sizeof(packet_address_proto_info_t)); + + switch (ether_type) { + case 0x0800: + { + buffer += sizeof(ether_hdr_t); size -= sizeof(ether_hdr_t); if(size <= 0) return; + struct n2n_iphdr *hdr_ip = (struct n2n_iphdr*)buffer; + + switch (hdr_ip->version) + { + case 4: + { + out_info->src_ip = hdr_ip->saddr; + out_info->dst_ip = hdr_ip->daddr; + switch (hdr_ip->protocol) { + case 0x01: + out_info->proto = FPP_ICMP; + break; + case 0x02: + out_info->proto = FPP_IGMP; + break; + case 0x06: + { + out_info->proto = FPP_TCP; + buffer += hdr_ip->ihl * 4; size -= hdr_ip->ihl * 4; if(size <= 0) return; + struct n2n_tcphdr *hdr_tcp = (struct n2n_tcphdr*)buffer; + out_info->src_port = ntohs(hdr_tcp->source); + out_info->dst_port = ntohs(hdr_tcp->dest); + break; + } + case 0x11: + { + out_info->proto = FPP_UDP; + buffer += hdr_ip->ihl * 4; size -= hdr_ip->ihl * 4; if(size <= 0) return; + struct n2n_udphdr *udp_hdr = (struct n2n_udphdr*)buffer; + out_info->src_port = ntohs(udp_hdr->source); + out_info->dst_port = ntohs(udp_hdr->dest); + break; + } + default: + out_info->proto = FPP_UNKNOWN; + }; + break; + } + case 6: + { + // TODO: IPV6 Not Support + out_info->proto = FPP_UNKNOWN; + break; + } + default: + out_info->proto = FPP_UNKNOWN; + } + break; + } + case 0x0806: + out_info->proto = FPP_ARP; + break; + case 0x86DD: + out_info->proto = FPP_UNKNOWN; + break; + default: + printf("EtherType 0x%04X", ether_type); + }; } const char* get_filter_rule_info_log_string(filter_rule_t* rule) { - static char buf[1024] = {0}; - char* print_start = buf; - char src_net[64] = {0}; char dst_net[64] = {0}; - struct in_addr src, dst; - src.s_addr = rule->key.src_net_cidr; - dst.s_addr = rule->key.dst_net_cidr; - strcpy(src_net, inet_ntoa(src)); strcpy(dst_net, inet_ntoa(dst)); - print_start += sprintf(print_start, "%s/%d:[%d,%d],%s/%d:[%d,%d]", - src_net, rule->key.src_net_bit_len, rule->key.src_port_range.start_port, rule->key.src_port_range.end_port, - dst_net, rule->key.dst_net_bit_len, rule->key.dst_port_range.start_port, rule->key.dst_port_range.end_port, - rule->bool_accept_tcp ? '+' : '-', rule->bool_accept_udp ? '+' : '-', rule->bool_accept_icmp ? '+' : '-'); - if(rule->key.bool_tcp_configured) - print_start += sprintf(print_start, ",TCP%c", rule->bool_accept_tcp ? '+' : '-'); - if(rule->key.bool_udp_configured) - print_start += sprintf(print_start, ",UDP%c", rule->bool_accept_udp ? '+' : '-'); - if(rule->key.bool_icmp_configured) - print_start += sprintf(print_start, ",ICMP%c", rule->bool_accept_icmp ? '+' : '-'); - return buf; + static char buf[1024] = {0}; + char* print_start = buf; + char src_net[64] = {0}; char dst_net[64] = {0}; + struct in_addr src, dst; + + src.s_addr = rule->key.src_net_cidr; + dst.s_addr = rule->key.dst_net_cidr; + strcpy(src_net, inet_ntoa(src)); strcpy(dst_net, inet_ntoa(dst)); + print_start += sprintf(print_start, "%s/%d:[%d,%d],%s/%d:[%d,%d]", + src_net, rule->key.src_net_bit_len, + rule->key.src_port_range.start_port, rule->key.src_port_range.end_port, + dst_net, rule->key.dst_net_bit_len, + rule->key.dst_port_range.start_port, rule->key.dst_port_range.end_port +#if 0 + , + rule->bool_accept_tcp ? '+' : '-', rule->bool_accept_udp ? '+' : '-', rule->bool_accept_icmp ? '+' : '-' +#endif + ); + if(rule->key.bool_tcp_configured) + print_start += sprintf(print_start, ",TCP%c", rule->bool_accept_tcp ? '+' : '-'); + if(rule->key.bool_udp_configured) + print_start += sprintf(print_start, ",UDP%c", rule->bool_accept_udp ? '+' : '-'); + if(rule->key.bool_icmp_configured) + print_start += sprintf(print_start, ",ICMP%c", rule->bool_accept_icmp ? '+' : '-'); + return buf; } typedef struct filter_rule_pair_cache { - packet_address_proto_info_t key; + packet_address_proto_info_t key; - uint8_t bool_allow_traffic; + uint8_t bool_allow_traffic; - uint32_t active_count; + uint32_t active_count; - UT_hash_handle hh; /* makes this structure hashable */ + UT_hash_handle hh; /* makes this structure hashable */ } filter_rule_pair_cache_t; uint8_t march_cidr_and_address(in_addr_t network, uint8_t net_bitlen, in_addr_t ip_addr) { - in_addr_t mask = 0, ip_addr_network = 0; - network = ntohl(network), ip_addr = ntohl(ip_addr); - uint32_t mask1 = net_bitlen != 0 ? ((~mask) << (32u-net_bitlen)) : 0; - ip_addr_network = ip_addr & mask1; - if( network == ip_addr_network ) - return net_bitlen + 1; // march 0.0.0.0/0 still march success, that case return 1 - else - return 0; + in_addr_t mask = 0, ip_addr_network = 0; + network = ntohl(network), ip_addr = ntohl(ip_addr); + uint32_t mask1 = net_bitlen != 0 ? ((~mask) << (32u-net_bitlen)) : 0; + ip_addr_network = ip_addr & mask1; + if( network == ip_addr_network ) + return net_bitlen + 1; // march 0.0.0.0/0 still march success, that case return 1 + else + return 0; } // if ports march, compare cidr. if cidr ok, return sum of src&dst cidr net_bitlen. means always select larger net_bitlen record when multi record is marched. uint8_t march_rule_and_cache_key(filter_rule_key_t *rule_key, packet_address_proto_info_t *pkt_addr_info) { - // march failed if proto is not configured at the rule. - switch (pkt_addr_info->proto) + // march failed if proto is not configured at the rule. + switch (pkt_addr_info->proto) { - case FPP_ICMP: - if(!rule_key->bool_icmp_configured) return 0; - break; - case FPP_UDP: - if(!rule_key->bool_udp_configured) return 0; - break; - case FPP_TCP: - if(!rule_key->bool_tcp_configured) return 0; - break; - default: - return 0; + case FPP_ICMP: + if(!rule_key->bool_icmp_configured) return 0; + break; + case FPP_UDP: + if(!rule_key->bool_udp_configured) return 0; + break; + case FPP_TCP: + if(!rule_key->bool_tcp_configured) return 0; + break; + default: + return 0; } - // ignore ports for ICMP proto. - if( pkt_addr_info->proto == FPP_ICMP || (rule_key->src_port_range.start_port <= pkt_addr_info->src_port - && pkt_addr_info->src_port <= rule_key->src_port_range.end_port - && rule_key->dst_port_range.start_port <= pkt_addr_info->dst_port - && pkt_addr_info->dst_port <= rule_key->dst_port_range.end_port) ) + // ignore ports for ICMP proto. + if( pkt_addr_info->proto == FPP_ICMP || (rule_key->src_port_range.start_port <= pkt_addr_info->src_port + && pkt_addr_info->src_port <= rule_key->src_port_range.end_port + && rule_key->dst_port_range.start_port <= pkt_addr_info->dst_port + && pkt_addr_info->dst_port <= rule_key->dst_port_range.end_port) ) { - uint8_t march_src_score = march_cidr_and_address(rule_key->src_net_cidr, rule_key->src_net_bit_len, pkt_addr_info->src_ip); - uint8_t march_dst_score = march_cidr_and_address(rule_key->dst_net_cidr, rule_key->dst_net_bit_len, pkt_addr_info->dst_ip); - if( march_src_score > 0 && march_dst_score > 0 ) - return march_src_score + march_dst_score; - }else{ - return 0; + uint8_t march_src_score = march_cidr_and_address(rule_key->src_net_cidr, rule_key->src_net_bit_len, pkt_addr_info->src_ip); + uint8_t march_dst_score = march_cidr_and_address(rule_key->dst_net_cidr, rule_key->dst_net_bit_len, pkt_addr_info->dst_ip); + if( march_src_score > 0 && march_dst_score > 0 ) + return march_src_score + march_dst_score; } + + return(0); } filter_rule_t* get_filter_rule(filter_rule_t **rules, packet_address_proto_info_t *pkt_addr_info) { - filter_rule_t *item = 0, *tmp = 0, *marched_rule = 0; - int march_score = 0; - - HASH_ITER(hh, *rules, item, tmp) { - /* ... it is safe to delete and free s here */ - uint8_t cur_march_score = march_rule_and_cache_key(&(item->key), pkt_addr_info); - if( cur_march_score > march_score ) - { - marched_rule = item; - march_score = cur_march_score; - } - } - return marched_rule; + filter_rule_t *item = 0, *tmp = 0, *marched_rule = 0; + int march_score = 0; + + HASH_ITER(hh, *rules, item, tmp) { + /* ... it is safe to delete and free s here */ + uint8_t cur_march_score = march_rule_and_cache_key(&(item->key), pkt_addr_info); + if( cur_march_score > march_score ) + { + marched_rule = item; + march_score = cur_march_score; + } + } + return marched_rule; } typedef struct network_traffic_filter_impl { - n2n_verdict (*filter_packet_from_peer)(struct network_traffic_filter* filter, n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size); + n2n_verdict (*filter_packet_from_peer)(struct network_traffic_filter* filter, n2n_edge_t *eee, + const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size); - n2n_verdict (*filter_packet_from_tap)(struct network_traffic_filter* filter, n2n_edge_t *eee, uint8_t *payload, uint16_t payload_size); + n2n_verdict (*filter_packet_from_tap)(struct network_traffic_filter* filter, n2n_edge_t *eee, + uint8_t *payload, uint16_t payload_size); - filter_rule_t *rules; + filter_rule_t *rules; - filter_rule_pair_cache_t *connections_rule_cache; + filter_rule_pair_cache_t *connections_rule_cache; - uint32_t work_count_scene_last_clear; + uint32_t work_count_scene_last_clear; }network_traffic_filter_impl_t; void update_and_clear_cache_if_need(network_traffic_filter_impl_t *filter) { - if( ++(filter->work_count_scene_last_clear) > CLEAR_CACHE_EVERY_X_COUNT) + if( ++(filter->work_count_scene_last_clear) > CLEAR_CACHE_EVERY_X_COUNT) { - filter_rule_pair_cache_t *item = NULL, *tmp = NULL; - HASH_ITER(hh, filter->connections_rule_cache, item, tmp) { - /* ... it is safe to delete and free s here */ - if( item->active_count < CLAER_CACHE_ACTIVE_COUNT ) - { - traceEvent(TRACE_DEBUG, "### DELETE filter cache %s", get_filter_packet_info_log_string(&item->key)); - HASH_DEL(filter->connections_rule_cache, item); - free(item); - }else{ - item->active_count = 0; - } - } - filter->work_count_scene_last_clear = 0; + filter_rule_pair_cache_t *item = NULL, *tmp = NULL; + HASH_ITER(hh, filter->connections_rule_cache, item, tmp) { + /* ... it is safe to delete and free s here */ + if( item->active_count < CLAER_CACHE_ACTIVE_COUNT ) + { + traceEvent(TRACE_DEBUG, "### DELETE filter cache %s", get_filter_packet_info_log_string(&item->key)); + HASH_DEL(filter->connections_rule_cache, item); + free(item); + }else{ + item->active_count = 0; + } + } + filter->work_count_scene_last_clear = 0; } } filter_rule_pair_cache_t* get_or_create_filter_rule_cache(network_traffic_filter_impl_t *filter, packet_address_proto_info_t *pkt_addr_info) { - filter_rule_pair_cache_t* rule_cache_find_result = 0; - HASH_FIND(hh, filter->connections_rule_cache, pkt_addr_info, sizeof(packet_address_proto_info_t), rule_cache_find_result); - if( !rule_cache_find_result ) + filter_rule_pair_cache_t* rule_cache_find_result = 0; + HASH_FIND(hh, filter->connections_rule_cache, pkt_addr_info, sizeof(packet_address_proto_info_t), rule_cache_find_result); + if( !rule_cache_find_result ) { - filter_rule_t* rule = get_filter_rule(&filter->rules, pkt_addr_info); - if( !rule ) - return NULL; - - rule_cache_find_result = malloc(sizeof(filter_rule_pair_cache_t)); - memset(rule_cache_find_result, 0, sizeof(filter_rule_pair_cache_t)); - rule_cache_find_result->key = *pkt_addr_info; - switch(rule_cache_find_result->key.proto) + filter_rule_t* rule = get_filter_rule(&filter->rules, pkt_addr_info); + if( !rule ) + return NULL; + + rule_cache_find_result = malloc(sizeof(filter_rule_pair_cache_t)); + memset(rule_cache_find_result, 0, sizeof(filter_rule_pair_cache_t)); + rule_cache_find_result->key = *pkt_addr_info; + switch(rule_cache_find_result->key.proto) { - case FPP_ICMP: - rule_cache_find_result->bool_allow_traffic = rule->bool_accept_icmp; - break; - case FPP_UDP: - rule_cache_find_result->bool_allow_traffic = rule->bool_accept_udp; - break; - case FPP_TCP: - rule_cache_find_result->bool_allow_traffic = rule->bool_accept_tcp; - break; - default: - traceEvent(TRACE_WARNING, "### Generate filter rule cache failed!"); - return NULL; + case FPP_ICMP: + rule_cache_find_result->bool_allow_traffic = rule->bool_accept_icmp; + break; + case FPP_UDP: + rule_cache_find_result->bool_allow_traffic = rule->bool_accept_udp; + break; + case FPP_TCP: + rule_cache_find_result->bool_allow_traffic = rule->bool_accept_tcp; + break; + default: + traceEvent(TRACE_WARNING, "### Generate filter rule cache failed!"); + return NULL; } - traceEvent(TRACE_DEBUG, "### ADD filter cache %s", get_filter_packet_info_log_string(&rule_cache_find_result->key)); - HASH_ADD(hh, filter->connections_rule_cache, key, sizeof(packet_address_proto_info_t), rule_cache_find_result); + traceEvent(TRACE_DEBUG, "### ADD filter cache %s", get_filter_packet_info_log_string(&rule_cache_find_result->key)); + HASH_ADD(hh, filter->connections_rule_cache, key, sizeof(packet_address_proto_info_t), rule_cache_find_result); } - ++(rule_cache_find_result->active_count); - update_and_clear_cache_if_need(filter); - return rule_cache_find_result; + ++(rule_cache_find_result->active_count); + update_and_clear_cache_if_need(filter); + return rule_cache_find_result; } n2n_verdict filter_packet_from_peer(network_traffic_filter_impl_t *filter, n2n_edge_t *eee, const n2n_sock_t *peer, uint8_t *payload, uint16_t payload_size) { - filter_rule_pair_cache_t *cur_pkt_rule = 0; - packet_address_proto_info_t pkt_info; - collect_packet_info(&pkt_info, payload, payload_size); - cur_pkt_rule = get_or_create_filter_rule_cache(filter, &pkt_info); - if( cur_pkt_rule && !cur_pkt_rule->bool_allow_traffic) + filter_rule_pair_cache_t *cur_pkt_rule = 0; + packet_address_proto_info_t pkt_info; + + collect_packet_info(&pkt_info, payload, payload_size); + cur_pkt_rule = get_or_create_filter_rule_cache(filter, &pkt_info); + if( cur_pkt_rule && !cur_pkt_rule->bool_allow_traffic) { - traceEvent(TRACE_DEBUG, "### DROP %s", get_filter_packet_info_log_string(&pkt_info)); - return N2N_DROP; + traceEvent(TRACE_DEBUG, "### DROP %s", get_filter_packet_info_log_string(&pkt_info)); + return N2N_DROP; } - return N2N_ACCEPT; + return N2N_ACCEPT; } n2n_verdict filter_packet_from_tap(network_traffic_filter_impl_t *filter, n2n_edge_t *eee, uint8_t *payload, uint16_t payload_size) { - filter_rule_pair_cache_t *cur_pkt_rule = 0; - packet_address_proto_info_t pkt_info; - collect_packet_info(&pkt_info, payload, payload_size); - cur_pkt_rule = get_or_create_filter_rule_cache(filter, &pkt_info); - if( cur_pkt_rule && !cur_pkt_rule->bool_allow_traffic) + filter_rule_pair_cache_t *cur_pkt_rule = 0; + packet_address_proto_info_t pkt_info; + + collect_packet_info(&pkt_info, payload, payload_size); + cur_pkt_rule = get_or_create_filter_rule_cache(filter, &pkt_info); + if( cur_pkt_rule && !cur_pkt_rule->bool_allow_traffic) { - traceEvent(TRACE_DEBUG, "### DROP %s", get_filter_packet_info_log_string(&pkt_info)); - return N2N_DROP; + traceEvent(TRACE_DEBUG, "### DROP %s", get_filter_packet_info_log_string(&pkt_info)); + return N2N_DROP; } - return N2N_ACCEPT; + return N2N_ACCEPT; } network_traffic_filter_t *create_network_traffic_filter() { - network_traffic_filter_impl_t *filter = malloc(sizeof(network_traffic_filter_impl_t)); - memset(filter, 0, sizeof(network_traffic_filter_impl_t)); - filter->filter_packet_from_peer = filter_packet_from_peer; - filter->filter_packet_from_tap = filter_packet_from_tap; - return filter; + network_traffic_filter_impl_t *filter = malloc(sizeof(network_traffic_filter_impl_t)); + + memset(filter, 0, sizeof(network_traffic_filter_impl_t)); + filter->filter_packet_from_peer = filter_packet_from_peer; + filter->filter_packet_from_tap = filter_packet_from_tap; + return filter; } void destroy_network_traffic_filter(network_traffic_filter_t *filter) { - network_traffic_filter_impl_t *_filter = filter; - + network_traffic_filter_impl_t *_filter = filter; + filter_rule_t *el = 0, *tmp = 0; + filter_rule_pair_cache_t *el = 0, *tmp = 0; + + HASH_ITER(hh, _filter->rules, el, tmp) { - filter_rule_t *el = 0, *tmp = 0; - HASH_ITER(hh, _filter->rules, el, tmp) - { - HASH_DEL(_filter->rules, el); - free(el); - } + HASH_DEL(_filter->rules, el); + free(el); } + HASH_ITER(hh, _filter->connections_rule_cache, el, tmp) { - filter_rule_pair_cache_t *el = 0, *tmp = 0; - HASH_ITER(hh, _filter->connections_rule_cache, el, tmp) - { - HASH_DEL(_filter->connections_rule_cache, el); - free(el); - } + HASH_DEL(_filter->connections_rule_cache, el); + free(el); } - free(filter); + free(filter); } void network_traffic_filter_add_rule(network_traffic_filter_t* filter, filter_rule_t* rules) { - filter_rule_t *item=NULL, *tmp=NULL; - HASH_ITER(hh, rules, item, tmp) { - network_traffic_filter_impl_t *_filter = filter; - filter_rule_t *new_rule = malloc(sizeof(filter_rule_t)); - memcpy(new_rule, item, sizeof(filter_rule_t)); - HASH_ADD(hh, _filter->rules, key, sizeof(filter_rule_key_t), new_rule); - traceEvent(TRACE_NORMAL, "### ADD network traffic filter %s", get_filter_rule_info_log_string(new_rule)); - } + filter_rule_t *item=NULL, *tmp=NULL; + + HASH_ITER(hh, rules, item, tmp) { + network_traffic_filter_impl_t *_filter = filter; + filter_rule_t *new_rule = malloc(sizeof(filter_rule_t)); + memcpy(new_rule, item, sizeof(filter_rule_t)); + HASH_ADD(hh, _filter->rules, key, sizeof(filter_rule_key_t), new_rule); + traceEvent(TRACE_NORMAL, "### ADD network traffic filter %s", get_filter_rule_info_log_string(new_rule)); + } } in_addr_t get_int32_addr_from_ip_string(const char* begin, const char* next_pos_of_last_char) { - char buf[16] = {0}; - if( next_pos_of_last_char - begin > 15 ) { - traceEvent(TRACE_WARNING, "Internal Error"); - return -1; - } - memcpy(buf, begin, next_pos_of_last_char - begin); - struct in_addr addr; - if(1 == inet_aton(buf, &addr) ) - return addr.s_addr; - else - return -1; + char buf[16] = {0}; + struct in_addr addr; + + if( next_pos_of_last_char - begin > 15 ) { + traceEvent(TRACE_WARNING, "Internal Error"); + return -1; + } + + memcpy(buf, begin, next_pos_of_last_char - begin); + + if(1 == inet_aton(buf, &addr) ) + return addr.s_addr; + else + return -1; } int get_int32_from_number_string(const char* begin, const char* next_pos_of_last_char) { - char buf[6] = {0}; - if( next_pos_of_last_char - begin > 5 ) // max is 65535, 5 char + char buf[6] = {0}; + + if( next_pos_of_last_char - begin > 5 ) // max is 65535, 5 char { - traceEvent(TRACE_WARNING, "Internal Error"); - return 0; + traceEvent(TRACE_WARNING, "Internal Error"); + return 0; } - memcpy(buf, begin, next_pos_of_last_char - begin); - return atoi(buf); + memcpy(buf, begin, next_pos_of_last_char - begin); + return atoi(buf); } void process_traffic_filter_proto(const char* begin, const char* next_pos_of_last_char, filter_rule_t *rule_struct) { - char buf[6] = {0}; - if( next_pos_of_last_char - begin > 5 ) // max length str is "ICMP+", 5 char - { - traceEvent(TRACE_WARNING, "Internal Error"); - } - memcpy(buf, begin, next_pos_of_last_char - begin); + char buf[6] = {0}; - if(strstr(buf, "TCP")){ - rule_struct->key.bool_tcp_configured = 1; - rule_struct->bool_accept_tcp = buf[3] == '+'; - } - else if(strstr(buf, "UDP")){ - rule_struct->key.bool_udp_configured = 1; - rule_struct->bool_accept_udp = buf[3] == '+'; + if( next_pos_of_last_char - begin > 5 ) // max length str is "ICMP+", 5 char + { + traceEvent(TRACE_WARNING, "Internal Error"); } - else if(strstr(buf, "ICMP")) + memcpy(buf, begin, next_pos_of_last_char - begin); + + if(strstr(buf, "TCP")){ + rule_struct->key.bool_tcp_configured = 1; + rule_struct->bool_accept_tcp = buf[3] == '+'; + } + else if(strstr(buf, "UDP")){ + rule_struct->key.bool_udp_configured = 1; + rule_struct->bool_accept_udp = buf[3] == '+'; + } + else if(strstr(buf, "ICMP")) { - rule_struct->key.bool_icmp_configured = 1; - rule_struct->bool_accept_icmp = buf[4] == '+'; + rule_struct->key.bool_icmp_configured = 1; + rule_struct->bool_accept_icmp = buf[4] == '+'; } - else - traceEvent(TRACE_WARNING, "Invalid Proto : %s", buf); + else + traceEvent(TRACE_WARNING, "Invalid Proto : %s", buf); } typedef enum -{ + { FPS_SRC_NET = 1, FPS_SRC_NET_BIT_LEN, FPS_SRC_PORT_SINGLE, @@ -461,283 +479,288 @@ typedef enum FPS_DST_PORT_START, FPS_DST_PORT_END, FPS_PROTO -} filter_process_stage; + } filter_process_stage; uint8_t process_traffic_filter_rule_str(const char *rule_str, filter_rule_t *rule_struct) { - const char *cur_pos = rule_str, *stage_begin_pos = rule_str; - filter_process_stage stage = FPS_SRC_NET; - while(1) + const char *cur_pos = rule_str, *stage_begin_pos = rule_str; + filter_process_stage stage = FPS_SRC_NET; + while(1) { - switch(stage) + switch(stage) { - case FPS_SRC_NET: - { - if( (*cur_pos >= '0' && *cur_pos <= '9') || *cur_pos == '.') - ; // Normal FPS_SRC_NET, next char - else if( *cur_pos == '/' ) { - // FPS_SRC_NET finish, next is FPS_SRC_NET_BIT_LEN - rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 1; - stage = FPS_SRC_NET_BIT_LEN; - }else if( *cur_pos == ':') { - // FPS_SRC_NET finish, ignore FPS_SRC_NET_BIT_LEN(default 32), next is one of FPS_SRC_PORT_RANGE/FPS_SRC_PORT_SINGLE - rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); - rule_struct->key.src_net_bit_len = 32; - stage_begin_pos = cur_pos + 1; - if( *(cur_pos+1) == '[' ) - stage = FPS_SRC_PORT_RANGE; - else - stage = FPS_SRC_PORT_SINGLE; - }else if( *cur_pos == ','){ - // FPS_SRC_NET finish, ignore FPS_SRC_NET_BIT_LEN(default 32), ignore FPS_SRC_PORT(default all), - // next is FPS_DST_NET - rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); - rule_struct->key.src_net_bit_len = 32; - rule_struct->key.src_port_range.start_port = 0; - rule_struct->key.src_port_range.end_port = 65535; - stage_begin_pos = cur_pos + 1; - stage = FPS_DST_NET; - } else { - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_SRC_NET_BIT_LEN: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_SRC_NET_BIT_LEN, next char - else if( *cur_pos == ':') { - // FPS_SRC_NET_BIT_LEN finish, next is one of FPS_SRC_PORT_RANGE/FPS_SRC_PORT_SINGLE - rule_struct->key.src_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 1; - if( *(cur_pos+1) == '[' ) - stage = FPS_SRC_PORT_RANGE; - else - stage = FPS_SRC_PORT_SINGLE; - }else if( *cur_pos == ','){ - // FPS_SRC_NET_BIT_LEN finish, ignore FPS_SRC_PORT(default all), next is FPS_DST_NET - rule_struct->key.src_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos);; - rule_struct->key.src_port_range.start_port = 0; - rule_struct->key.src_port_range.end_port = 65535; - stage_begin_pos = cur_pos + 1; - stage = FPS_DST_NET; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_SRC_PORT_SINGLE: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_SRC_PORT_SINGLE, next char - else if(*cur_pos == ','){ - // FPS_SRC_PORT_SINGLE finish, next is FPS_DST_NET - rule_struct->key.src_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); - rule_struct->key.src_port_range.end_port = rule_struct->key.src_port_range.start_port; - stage_begin_pos = cur_pos + 1; - stage = FPS_DST_NET; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_SRC_PORT_RANGE: - { - if(*cur_pos == '[') - { - stage_begin_pos = cur_pos + 1; - stage = FPS_SRC_PORT_START; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_SRC_PORT_START: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_SRC_PORT_START, next char - else if(*cur_pos == ',') - { - // FPS_SRC_PORT_START finish, next is FPS_SRC_PORT_END - rule_struct->key.src_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 1; - stage = FPS_SRC_PORT_END; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_SRC_PORT_END: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_SRC_PORT_END, next char - else if(*cur_pos == ']' && *(cur_pos + 1) == ',') - { - // FPS_SRC_PORT_END finish, next is FPS_DST_NET - rule_struct->key.src_port_range.end_port = get_int32_from_number_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 2; - stage = FPS_DST_NET; - ++cur_pos; //skip next char ',' - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_DST_NET: - { - if( (*cur_pos >= '0' && *cur_pos <= '9') || *cur_pos == '.') - ; // Normal FPS_DST_NET, next char - else if( *cur_pos == '/' ) { - // FPS_DST_NET finish, next is FPS_DST_NET_BIT_LEN - rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 1; - stage = FPS_DST_NET_BIT_LEN; - }else if( *cur_pos == ':') { - // FPS_DST_NET finish, ignore FPS_DST_NET_BIT_LEN(default 32), next is one of FPS_DST_PORT_RANGE/FPS_DST_PORT_SINGLE - rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); - rule_struct->key.dst_net_bit_len = 32; - stage_begin_pos = cur_pos + 1; - if( *(cur_pos+1) == '[' ) - stage = FPS_DST_PORT_RANGE; - else - stage = FPS_DST_PORT_SINGLE; - }else if( *cur_pos == ',' || *cur_pos == 0){ - // FPS_DST_NET finish, ignore FPS_DST_NET_BIT_LEN(default 32), ignore FPS_DST_PORT(default all), - // next is FPS_PROTO - rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); - rule_struct->key.dst_net_bit_len = 32; - rule_struct->key.dst_port_range.start_port = 0; - rule_struct->key.dst_port_range.end_port = 65535; - stage_begin_pos = cur_pos + 1; - stage = FPS_PROTO; - } else { - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_DST_NET_BIT_LEN: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_DST_NET_BIT_LEN, next char - else if( *cur_pos == ':') { - // FPS_DST_NET_BIT_LEN finish, next is one of FPS_DST_PORT_RANGE/FPS_DST_PORT_SINGLE - rule_struct->key.dst_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 1; - if( *(cur_pos+1) == '[' ) - stage = FPS_DST_PORT_RANGE; - else - stage = FPS_DST_PORT_SINGLE; - }else if( *cur_pos == ',' || *cur_pos == 0){ - // FPS_DST_NET_BIT_LEN finish, ignore FPS_DST_PORT(default all), next is FPS_PROTO - rule_struct->key.dst_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos);; - rule_struct->key.dst_port_range.start_port = 0; - rule_struct->key.dst_port_range.end_port = 65535; - stage_begin_pos = cur_pos + 1; - stage = FPS_PROTO; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_DST_PORT_SINGLE: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_DST_PORT_SINGLE, next char - else if(*cur_pos == ',' || *cur_pos == 0){ - // FPS_DST_PORT_SINGLE finish, next is FPS_PROTO - rule_struct->key.dst_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); - rule_struct->key.dst_port_range.end_port = rule_struct->key.dst_port_range.start_port; - stage_begin_pos = cur_pos + 1; - stage = FPS_PROTO; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_DST_PORT_RANGE: - { - if(*cur_pos == '[') - { - stage_begin_pos = cur_pos + 1; - stage = FPS_DST_PORT_START; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_DST_PORT_START: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_DST_PORT_START, next char - else if(*cur_pos == ',') - { - // FPS_DST_PORT_START finish, next is FPS_DST_PORT_END - rule_struct->key.dst_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); - stage_begin_pos = cur_pos + 1; - stage = FPS_DST_PORT_END; - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_DST_PORT_END: - { - if( *cur_pos >= '0' && *cur_pos <= '9') - ; // Normal FPS_DST_PORT_END, next char - else if(*cur_pos == ']') - { - // FPS_DST_PORT_END finish, next is FPS_PROTO - rule_struct->key.dst_port_range.end_port = get_int32_from_number_string(stage_begin_pos, cur_pos); - stage = FPS_PROTO; - if(*(cur_pos + 1) == ',') { - stage_begin_pos = cur_pos + 2; - ++cur_pos; //skip next char ',' - }else if(*(cur_pos + 1) != 0){ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - }else{ - traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } - case FPS_PROTO: - { - if(*cur_pos != '-' && *cur_pos != '+' && *cur_pos != ',') - ; // Normal FPS_PROTO. next char - else if( *cur_pos != ',' ) - { - process_traffic_filter_proto(stage_begin_pos, cur_pos + 1, rule_struct); - if( *(cur_pos+1) == 0 ) // end of whole rule string - break; - else{ // new proto info, and skip next char ',' - stage_begin_pos = cur_pos + 2; - ++cur_pos; - } - } - else { - traceEvent(TRACE_WARNING, "Internal Error: ',' should skiped", *cur_pos, cur_pos - rule_str); - return 0; - } - break; - } + case FPS_SRC_NET: + { + if( (*cur_pos >= '0' && *cur_pos <= '9') || *cur_pos == '.') + ; // Normal FPS_SRC_NET, next char + else if( *cur_pos == '/' ) { + // FPS_SRC_NET finish, next is FPS_SRC_NET_BIT_LEN + rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 1; + stage = FPS_SRC_NET_BIT_LEN; + } else if( *cur_pos == ':') { + // FPS_SRC_NET finish, ignore FPS_SRC_NET_BIT_LEN(default 32), next is one of FPS_SRC_PORT_RANGE/FPS_SRC_PORT_SINGLE + rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); + rule_struct->key.src_net_bit_len = 32; + stage_begin_pos = cur_pos + 1; + if( *(cur_pos+1) == '[' ) + stage = FPS_SRC_PORT_RANGE; + else + stage = FPS_SRC_PORT_SINGLE; + } else if( *cur_pos == ','){ + // FPS_SRC_NET finish, ignore FPS_SRC_NET_BIT_LEN(default 32), ignore FPS_SRC_PORT(default all), + // next is FPS_DST_NET + rule_struct->key.src_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); + rule_struct->key.src_net_bit_len = 32; + rule_struct->key.src_port_range.start_port = 0; + rule_struct->key.src_port_range.end_port = 65535; + stage_begin_pos = cur_pos + 1; + stage = FPS_DST_NET; + } else { + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + + case FPS_SRC_NET_BIT_LEN: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_SRC_NET_BIT_LEN, next char + else if( *cur_pos == ':') { + // FPS_SRC_NET_BIT_LEN finish, next is one of FPS_SRC_PORT_RANGE/FPS_SRC_PORT_SINGLE + rule_struct->key.src_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 1; + if( *(cur_pos+1) == '[' ) + stage = FPS_SRC_PORT_RANGE; + else + stage = FPS_SRC_PORT_SINGLE; + }else if( *cur_pos == ','){ + // FPS_SRC_NET_BIT_LEN finish, ignore FPS_SRC_PORT(default all), next is FPS_DST_NET + rule_struct->key.src_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos);; + rule_struct->key.src_port_range.start_port = 0; + rule_struct->key.src_port_range.end_port = 65535; + stage_begin_pos = cur_pos + 1; + stage = FPS_DST_NET; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + + case FPS_SRC_PORT_SINGLE: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_SRC_PORT_SINGLE, next char + else if(*cur_pos == ','){ + // FPS_SRC_PORT_SINGLE finish, next is FPS_DST_NET + rule_struct->key.src_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); + rule_struct->key.src_port_range.end_port = rule_struct->key.src_port_range.start_port; + stage_begin_pos = cur_pos + 1; + stage = FPS_DST_NET; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + + case FPS_SRC_PORT_RANGE: + { + if(*cur_pos == '[') + { + stage_begin_pos = cur_pos + 1; + stage = FPS_SRC_PORT_START; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_SRC_PORT_START: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_SRC_PORT_START, next char + else if(*cur_pos == ',') + { + // FPS_SRC_PORT_START finish, next is FPS_SRC_PORT_END + rule_struct->key.src_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 1; + stage = FPS_SRC_PORT_END; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_SRC_PORT_END: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_SRC_PORT_END, next char + else if(*cur_pos == ']' && *(cur_pos + 1) == ',') + { + // FPS_SRC_PORT_END finish, next is FPS_DST_NET + rule_struct->key.src_port_range.end_port = get_int32_from_number_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 2; + stage = FPS_DST_NET; + ++cur_pos; //skip next char ',' + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_DST_NET: + { + if( (*cur_pos >= '0' && *cur_pos <= '9') || *cur_pos == '.') + ; // Normal FPS_DST_NET, next char + else if( *cur_pos == '/' ) { + // FPS_DST_NET finish, next is FPS_DST_NET_BIT_LEN + rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 1; + stage = FPS_DST_NET_BIT_LEN; + }else if( *cur_pos == ':') { + // FPS_DST_NET finish, ignore FPS_DST_NET_BIT_LEN(default 32), next is one of FPS_DST_PORT_RANGE/FPS_DST_PORT_SINGLE + rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); + rule_struct->key.dst_net_bit_len = 32; + stage_begin_pos = cur_pos + 1; + if( *(cur_pos+1) == '[' ) + stage = FPS_DST_PORT_RANGE; + else + stage = FPS_DST_PORT_SINGLE; + }else if( *cur_pos == ',' || *cur_pos == 0){ + // FPS_DST_NET finish, ignore FPS_DST_NET_BIT_LEN(default 32), ignore FPS_DST_PORT(default all), + // next is FPS_PROTO + rule_struct->key.dst_net_cidr = get_int32_addr_from_ip_string(stage_begin_pos, cur_pos); + rule_struct->key.dst_net_bit_len = 32; + rule_struct->key.dst_port_range.start_port = 0; + rule_struct->key.dst_port_range.end_port = 65535; + stage_begin_pos = cur_pos + 1; + stage = FPS_PROTO; + } else { + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_DST_NET_BIT_LEN: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_DST_NET_BIT_LEN, next char + else if( *cur_pos == ':') { + // FPS_DST_NET_BIT_LEN finish, next is one of FPS_DST_PORT_RANGE/FPS_DST_PORT_SINGLE + rule_struct->key.dst_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 1; + if( *(cur_pos+1) == '[' ) + stage = FPS_DST_PORT_RANGE; + else + stage = FPS_DST_PORT_SINGLE; + }else if( *cur_pos == ',' || *cur_pos == 0){ + // FPS_DST_NET_BIT_LEN finish, ignore FPS_DST_PORT(default all), next is FPS_PROTO + rule_struct->key.dst_net_bit_len = get_int32_from_number_string(stage_begin_pos, cur_pos);; + rule_struct->key.dst_port_range.start_port = 0; + rule_struct->key.dst_port_range.end_port = 65535; + stage_begin_pos = cur_pos + 1; + stage = FPS_PROTO; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_DST_PORT_SINGLE: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_DST_PORT_SINGLE, next char + else if(*cur_pos == ',' || *cur_pos == 0){ + // FPS_DST_PORT_SINGLE finish, next is FPS_PROTO + rule_struct->key.dst_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); + rule_struct->key.dst_port_range.end_port = rule_struct->key.dst_port_range.start_port; + stage_begin_pos = cur_pos + 1; + stage = FPS_PROTO; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_DST_PORT_RANGE: + { + if(*cur_pos == '[') + { + stage_begin_pos = cur_pos + 1; + stage = FPS_DST_PORT_START; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_DST_PORT_START: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_DST_PORT_START, next char + else if(*cur_pos == ',') + { + // FPS_DST_PORT_START finish, next is FPS_DST_PORT_END + rule_struct->key.dst_port_range.start_port = get_int32_from_number_string(stage_begin_pos, cur_pos); + stage_begin_pos = cur_pos + 1; + stage = FPS_DST_PORT_END; + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_DST_PORT_END: + { + if( *cur_pos >= '0' && *cur_pos <= '9') + ; // Normal FPS_DST_PORT_END, next char + else if(*cur_pos == ']') + { + // FPS_DST_PORT_END finish, next is FPS_PROTO + rule_struct->key.dst_port_range.end_port = get_int32_from_number_string(stage_begin_pos, cur_pos); + stage = FPS_PROTO; + if(*(cur_pos + 1) == ',') { + stage_begin_pos = cur_pos + 2; + ++cur_pos; //skip next char ',' + }else if(*(cur_pos + 1) != 0){ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + }else{ + traceEvent(TRACE_WARNING, "process filter rule with error char %c at pos %d", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } + case FPS_PROTO: + { + if(*cur_pos != '-' && *cur_pos != '+' && *cur_pos != ',') + ; // Normal FPS_PROTO. next char + else if( *cur_pos != ',' ) + { + process_traffic_filter_proto(stage_begin_pos, cur_pos + 1, rule_struct); + if( *(cur_pos+1) == 0 ) // end of whole rule string + break; + else{ // new proto info, and skip next char ',' + stage_begin_pos = cur_pos + 2; + ++cur_pos; + } + } + else { + traceEvent(TRACE_WARNING, "Internal Error: ',' should skiped", *cur_pos, cur_pos - rule_str); + return 0; + } + break; + } } - if(0 == *cur_pos) - break; - ++cur_pos; + if(0 == *cur_pos) + break; + ++cur_pos; } - return 1; + return 1; } + +#endif