diff --git a/ndpi-netfilter/FLOW_INFO.txt b/ndpi-netfilter/FLOW_INFO.txt index 46cb6e89f..961aaa06e 100644 --- a/ndpi-netfilter/FLOW_INFO.txt +++ b/ndpi-netfilter/FLOW_INFO.txt @@ -46,7 +46,7 @@ line when reading the beginning of the data. "LOST_TRAFFIC x x x x" - summary information on lost traffic (see below). -Each line of connection information has 14 required fields and 4 additional fields: +Each line of connection information has 14 required fields and 5 additional fields: 1. Connection start time. 2. The time of the last connection packet. @@ -61,11 +61,12 @@ Each line of connection information has 14 required fields and 4 additional fiel 11. Bytes from destination to sourse 12. Packets from destination to sourse 13. Interface indexes. Format: "I=," -14. Source NAT. Optional, only for IPv4. Format: "SN=ipv4_address:port" -15. Destination NAT. Optional, only for IPv4. Format: "DN=ipv4_address:port" -16. NDPI protocol. Format: "P=xxx" -17. NDPI hostname info. Optional. Only for DNS,HTTP. Format: "H=hostname" -18. NDPI SSL info. Optional. Only for SSL. Format: "C=cert_name" +14. Connection mark. Optional. Format: "CM=" +15. Source NAT. Optional, only for IPv4. Format: "SN=ipv4_address:port" +16. Destination NAT. Optional, only for IPv4. Format: "DN=ipv4_address:port" +17. NDPI protocol. Format: "P=xxx" +18. NDPI hostname info. Optional. Only for DNS,HTTP. Format: "H=hostname" +19. NDPI SSL info. Optional. Only for SSL. Format: "C=cert_name" We must read the file until we get an EOF. In the process of reading data, the memory occupied by closed connections is released. If the number of records of diff --git a/ndpi-netfilter/src/main.c b/ndpi-netfilter/src/main.c index f7d1f612e..976f5905d 100644 --- a/ndpi-netfilter/src/main.c +++ b/ndpi-netfilter/src/main.c @@ -1228,6 +1228,10 @@ ndpi_mt(const struct sk_buff *skb, struct xt_action_param *par) !ct_ndpi->nat_done && !ct_proto_get_flow_nat(c_proto)) { ct_proto_set_flow_nat(c_proto,1); } +#if defined(CONFIG_NF_CONNTRACK_MARK) + if(ct->mark && ct->mark != ct_ndpi->connmark) + ct_ndpi->connmark = ct->mark; +#endif #ifdef USE_HACK_USERID if(!ct_ndpi->userid && diff --git a/ndpi-netfilter/src/ndpi_main_netfilter.h b/ndpi-netfilter/src/ndpi_main_netfilter.h index 8885c37ef..8df5ead40 100644 --- a/ndpi-netfilter/src/ndpi_main_netfilter.h +++ b/ndpi-netfilter/src/ndpi_main_netfilter.h @@ -15,6 +15,7 @@ typedef enum write_buf_id { W_BUF_IP=0, W_BUF_HOST, W_BUF_PROTO, + W_BUF_FLOW, W_BUF_LAST } write_buf_id_t; @@ -109,6 +110,7 @@ struct nf_ct_ext_ndpi { char *ssl; // 4/8 bytes struct flow_info flinfo; // 108 bytes ndpi_protocol proto; // 4 bytes + uint32_t connmark; // 4 bytes spinlock_t lock; // 2/4 bytes uint8_t l4_proto, // 1 flow_info, // 1 @@ -124,7 +126,7 @@ struct nf_ct_ext_ndpi { uint8_t pad[2]; #endif /* - * 32bit - 144 bytes, 64bit - 172 bytes; + * 32bit - 148 bytes, 64bit - 176 bytes; */ } __attribute ((packed)); diff --git a/ndpi-netfilter/src/ndpi_proc_flow.c b/ndpi-netfilter/src/ndpi_proc_flow.c index fd796e8cc..2d34cb7a9 100644 --- a/ndpi-netfilter/src/ndpi_proc_flow.c +++ b/ndpi-netfilter/src/ndpi_proc_flow.c @@ -16,6 +16,7 @@ #include "ndpi_strcol.h" #include "ndpi_main_netfilter.h" #include "ndpi_proc_flow.h" +#include "ndpi_proc_generic.h" void nflow_proc_read_start(struct ndpi_net *n) { @@ -25,29 +26,6 @@ void nflow_proc_read_start(struct ndpi_net *n) { } -int nflow_proc_open(struct inode *inode, struct file *file) { - struct ndpi_net *n = PDE_DATA(file_inode(file)); - - if(!ndpi_enable_flow) return -EINVAL; - - if(atomic_xchg(&n->acc_open,1)) { - return -EBUSY; - } - n->acc_read_mode = 0; - if(!n->acc_wait) n->acc_wait = 60; - nflow_proc_read_start(n); - return 0; -} - -int nflow_proc_close(struct inode *inode, struct file *file) -{ - struct ndpi_net *n = PDE_DATA(file_inode(file)); - if(!ndpi_enable_flow) return -EINVAL; - n->acc_gc = jiffies + n->acc_wait*HZ; - atomic_set(&n->acc_open,0); - return 0; -} - static ssize_t acct_info_len = 256; ssize_t ndpi_dump_acct_info(struct ndpi_net *n,char *buf, size_t buflen, struct nf_ct_ext_ndpi *ct) { @@ -78,7 +56,10 @@ ssize_t ndpi_dump_acct_info(struct ndpi_net *n,char *buf, size_t buflen, } l += snprintf(&buf[l],buflen-l," I=%d,%d",ct->flinfo.ifidx,ct->flinfo.ofidx); - +#if defined(CONFIG_NF_CONNTRACK_MARK) + if(ct->connmark) + l += snprintf(&buf[l],buflen-l," CM=%x",ct->connmark); +#endif if(!ct->ipv6) { if(ct->snat) { l += snprintf(&buf[l],buflen-l," SN=%pI4n:%d", @@ -124,48 +105,74 @@ ssize_t nflow_proc_read(struct file *file, char __user *buf, return nflow_read(n, buf, count, ppos); } -ssize_t nflow_proc_write(struct file *file, const char __user *buffer, - size_t length, loff_t *loff) +static int parse_ndpi_flow(struct ndpi_net *n,char *buf) { - struct ndpi_net *n = PDE_DATA(file_inode(file)); - char buf[32]; int idx; if(!ndpi_enable_flow) return -EINVAL; - if (length > 0) { - memset(buf,0,sizeof(buf)); - if (!(ACCESS_OK(VERIFY_READ, buffer, length) && - !__copy_from_user(&buf[0], buffer, min(length,sizeof(buf)-1)))) - return -EFAULT; - if(sscanf(buf,"timeout=%d",&idx) == 1) { - if(idx < 1 || idx > 600) return -EINVAL; - n->acc_wait = idx; - printk("%s: set timeout=%d\n",__func__,n->acc_wait); - } else if(sscanf(buf,"limit=%d",&idx) == 1) { - if(idx < atomic_read(&n->acc_work) || idx > ndpi_flow_limit) - return -EINVAL; - n->acc_limit = idx; - printk("%s: set limit=%d\n",__func__,n->acc_limit); - } else if(!strcmp(buf,"read_closed")) { - if(n->acc_end || !n->flow_l) { - n->acc_read_mode = 1; - } else return -EINVAL; - printk("%s: set read_mode=%d\n",__func__,n->acc_read_mode); - } else if(!strcmp(buf,"read_flows")) { - if(n->acc_end || !n->flow_l) { - n->acc_read_mode = 2; - } else return -EINVAL; - printk("%s: set read_mode=%d\n",__func__,n->acc_read_mode); - } else if(!strcmp(buf,"read_all")) { - if(n->acc_end || !n->flow_l) { - n->acc_read_mode = 0; - } else return -EINVAL; - printk("%s: set read_mode=%d\n",__func__,n->acc_read_mode); - } else + if(!buf[0]) return 0; + + if(sscanf(buf,"timeout=%d",&idx) == 1) { + if(idx < 1 || idx > 600) return -EINVAL; + n->acc_wait = idx; + printk("%s: set timeout=%d\n",__func__,n->acc_wait); + } else if(sscanf(buf,"limit=%d",&idx) == 1) { + if(idx < atomic_read(&n->acc_work) || idx > ndpi_flow_limit) return -EINVAL; - } - return length; + n->acc_limit = idx; + printk("%s: set limit=%d\n",__func__,n->acc_limit); + } else if(!strcmp(buf,"read_closed")) { + if(n->acc_end || !n->flow_l) { + n->acc_read_mode = 1; + } else return -EINVAL; + printk("%s: set read_mode=%d\n",__func__,n->acc_read_mode); + } else if(!strcmp(buf,"read_flows")) { + if(n->acc_end || !n->flow_l) { + n->acc_read_mode = 2; + } else return -EINVAL; + printk("%s: set read_mode=%d\n",__func__,n->acc_read_mode); + } else if(!strcmp(buf,"read_all")) { + if(n->acc_end || !n->flow_l) { + n->acc_read_mode = 0; + } else return -EINVAL; + printk("%s: set read_mode=%d\n",__func__,n->acc_read_mode); + } else + return -EINVAL; + return 0; +} + +int nflow_proc_open(struct inode *inode, struct file *file) { + struct ndpi_net *n = PDE_DATA(file_inode(file)); + + if(!ndpi_enable_flow) return -EINVAL; + + if(atomic_xchg(&n->acc_open,1)) { + return -EBUSY; + } + n->acc_read_mode = 0; + if(!n->acc_wait) n->acc_wait = 60; + nflow_proc_read_start(n); + return 0; +} + +int nflow_proc_close(struct inode *inode, struct file *file) +{ + struct ndpi_net *n = PDE_DATA(file_inode(file)); + if(!ndpi_enable_flow) return -EINVAL; + generic_proc_close(n,parse_ndpi_flow,W_BUF_FLOW); + n->acc_gc = jiffies + n->acc_wait*HZ; + atomic_set(&n->acc_open,0); + return 0; +} + +ssize_t +nflow_proc_write(struct file *file, const char __user *buffer, + size_t length, loff_t *loff) +{ + if(!ndpi_enable_flow) return -EINVAL; + return generic_proc_write(PDE_DATA(file_inode(file)), buffer, length, loff, + parse_ndpi_flow, 4060 , W_BUF_FLOW); } loff_t nflow_proc_llseek(struct file *file, loff_t offset, int whence) {