diff options
author | Roman Yeryomin <roman@advem.lv> | 2012-09-13 00:40:35 +0300 |
---|---|---|
committer | Roman Yeryomin <roman@advem.lv> | 2013-05-26 00:28:21 +0300 |
commit | 3dd631678a9d5f512d7055b5550455005908047c (patch) | |
tree | 2355929a4b8cf1888cd0797cfabdb42e0077c524 /target/linux/realtek/files/net/bridge | |
parent | 36b130ad5bf5fd6b33721e6d3d137ce0bfb7d7d5 (diff) |
Add realtek target files
Signed-off-by: Roman Yeryomin <roman@advem.lv>
Diffstat (limited to 'target/linux/realtek/files/net/bridge')
-rw-r--r-- | target/linux/realtek/files/net/bridge/lan_restrict.c | 442 | ||||
-rw-r--r-- | target/linux/realtek/files/net/bridge/lan_restrict.h | 10 | ||||
-rw-r--r-- | target/linux/realtek/files/net/bridge/pocket_filter.c | 505 |
3 files changed, 957 insertions, 0 deletions
diff --git a/target/linux/realtek/files/net/bridge/lan_restrict.c b/target/linux/realtek/files/net/bridge/lan_restrict.c new file mode 100644 index 000000000..8f09a9409 --- /dev/null +++ b/target/linux/realtek/files/net/bridge/lan_restrict.c @@ -0,0 +1,442 @@ +#include <linux/module.h> +#include <linux/proc_fs.h> +#include <linux/types.h> +#include <linux/errno.h> +#include <linux/sched.h> +#include <linux/kernel.h> +#include <linux/kernel_stat.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/slab.h> +#include <asm/uaccess.h> +//#include <linux/brlock.h> +#include <linux/net.h> +#include <linux/socket.h> + +#include <linux/netdevice.h> +#include <linux/etherdevice.h> +#include <linux/string.h> +#include <net/ip.h> +#include <net/protocol.h> +#include <net/route.h> +#include <net/sock.h> +#include <net/arp.h> +#include <net/raw.h> +#include <net/checksum.h> +#include <linux/netfilter.h> +#include <linux/netfilter_ipv4.h> +#include <linux/netlink.h> +#include <linux/inetdevice.h> +#include "lan_restrict.h" + +static char lan_restrict_flag[1024]; +int8 enable_lanrestrict = FALSE; +static struct proc_dir_entry *res=NULL; + +static inline int _strncasecmp(const char *s1, const char *s2, unsigned int n) +{ + if (n == 0) + return 0; + + while ((n-- != 0) + && (tolower(*(unsigned char *) s1) == + tolower(*(unsigned char *) s2))) { + if (n == 0 || *s1 == '\0' || *s2 == '\0') + return 0; + s1++; + s2++; + } + + return tolower(*(unsigned char *) s1) - tolower(*(unsigned char *) s2); +} + +int lan_restrict_rcv(struct sk_buff *skb, struct net_device *dev) +{ + int32 found = FAILED; + ether_addr_t *macAddr; +// int8 port_num; + int32 column; + int32 SrcBlk; + + if ((memcmp(skb->dev->name, RTL_PS_BR0_DEV_NAME, 3) ==0) || (memcmp(skb->dev->name, RTL_PS_LAN_P0_DEV_NAME, 4) ==0) ) + { + macAddr = (ether_addr_t *)(eth_hdr(skb)->h_source); + found = rtl_check_fdb_entry_check_exist(RTL_LAN_FID, macAddr, FDB_DYNAMIC); +/* printk("\nrecv packet from dev:%s\n", skb->dev->name);*/ + /*can found in asic , do noting here , in linux fdb module , it can be authed*/ + if (found == SUCCESS ) + { +#if 0 + port_num = rtl865x_ConvertPortMasktoPortNum(fdbEntry.memberPortMask); + + if (lan_restrict_tbl[port_num].enable == TRUE) + { + if ((lan_restrict_tbl[port_num].curr_num < lan_restrict_tbl[port_num].max_num)) + { +/* printk("\nPASS:lan_restrict_tbl[%d] current number is %d\n", port_num, lan_restrict_tbl[port_num].curr_num);*/ + return NET_RX_SUCCESS; + } + else + { + if (fdbEntry.auth == TRUE) + { +/* printk("\nPASS1:lan_restrict_tbl[%d] current number is %d\n", port_num, lan_restrict_tbl[port_num].curr_num);*/ + return NET_RX_SUCCESS; + } + else + { +/* printk("\nDROP:lan_restrict_tbl[%d] current number is %d\n", port_num, lan_restrict_tbl[port_num].curr_num);*/ + l2temp_entry.l2type = (fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII; + l2temp_entry.process = FDB_TYPE_FWD; + l2temp_entry.memberPortMask = fdbEntry.memberPortMask; + l2temp_entry.auth = FALSE; + l2temp_entry.SrcBlk = TRUE; + memcpy(&(l2temp_entry.macAddr), macAddr, sizeof(ether_addr_t)); + rtl865x_addAuthFilterDatabaseEntryExtension(fdbEntry.fid, &l2temp_entry); + return NET_RX_AUTH_BLOCK; + } + } + } + else + { + return NET_RX_SUCCESS; + } +#endif + return NET_RX_SUCCESS; + } + else + { +/* printk(" \nnot found in hw table, src port is %d\n", skb->srcPort);*/ + if (lan_restrict_tbl[skb->srcPort].enable == TRUE) + { + /*found in sw l2 table*/ + if(rtl_check_fdb_entry_check_srcBlock(0, macAddr, &SrcBlk) == SUCCESS) + { + if (SrcBlk == TRUE)/*sw block*/ + { + return NET_RX_AUTH_BLOCK; + } + else + { + return NET_RX_SUCCESS; + } + } + else /*not found in sw l2 table*/ + { +/* printk(" \nnot found ind hw and sw table\n");*/ + if ((lan_restrict_tbl[skb->srcPort].curr_num < lan_restrict_tbl[skb->srcPort].max_num)) + { + /*try to add into sw l2 table*/ +/* printk("\ntry to add into sw l2 table\n");*/ + rtl865x_addAuthFDBEntry((unsigned char *)macAddr, TRUE, skb->srcPort); + return NET_RX_SUCCESS; + } + else + { + return NET_RX_AUTH_BLOCK; + } + } + + } + else + { +/* printk("dev name is %s\n", skb->dev->name);*/ + return NET_RX_SUCCESS; + } + } + } + else + { + return NET_RX_SUCCESS; + } +} +#if 0 +static struct packet_type lan_restrict_packet_type = { + .type = __constant_htons(ETH_P_ALL), + .func = lan_restrict_rcv, +}; +#endif +static int lan_restrict_tbl_int(void) +{ + uint8 i; + + for (i=0; i < LAN_RESTRICT_PORT_NUMBER; i++ ) + { + lan_restrict_tbl[i].port_num = 0; + lan_restrict_tbl[i].enable = FALSE; + lan_restrict_tbl[i].max_num = 0; + lan_restrict_tbl[i].curr_num = 0; + } + return TRUE; +} + +static int lan_restrict_tbl_reset(void) +{ + uint8 i; + + for (i=0; i < LAN_RESTRICT_PORT_NUMBER; i++ ) + { + lan_restrict_tbl[i].port_num = 0; + lan_restrict_tbl[i].enable = FALSE; + lan_restrict_tbl[i].max_num = 0; + lan_restrict_tbl[i].curr_num = 0; + } + return TRUE; +} + + +static int lan_restrict_set_singleport(uint8 portnum , int8 enable, int32 max_num) +{ + int32 ret; + if (enable == TRUE) + { + lan_restrict_tbl[portnum].max_num = max_num; + } + else + { + lan_restrict_tbl[portnum].max_num = 0; + } + + ret =rtl865x_setRestrictPortNum(portnum, enable, max_num); + return ret; +} + +static int lan_restrict_perport_setting(void) +{ + int i; + for (i=0; i < LAN_RESTRICT_PORT_NUMBER; i++ ) + { + lan_restrict_set_singleport(lan_restrict_tbl[i].port_num, lan_restrict_tbl[i].enable, lan_restrict_tbl[i].max_num); + } + return TRUE; +} + +static int lan_restrict_enable(void) +{ + /* + enable + */ + rtl865x_enableLanPortNumRestrict(TRUE); + lan_restrict_perport_setting(); + return TRUE; +} + +static int lan_restrict_disable(void) +{ + /* + disable + */ + rtl865x_enableLanPortNumRestrict(FALSE); + lan_restrict_tbl_reset(); + lan_restrict_perport_setting(); + return TRUE; +} +/* +int32 lanrestrict_addfdbentry(const unsigned char *addr) +{ + int32 found = FAILED; + ether_addr_t *macAddr; + int32 ret=FAILED; + int8 port_num; + int32 column; + rtl865x_tblAsicDrv_l2Param_t fdbEntry; + rtl865x_filterDbTableEntry_t l2temp_entry; + + macAddr = (ether_addr_t *)(addr); + found = rtl865x_Lookup_fdb_entry(0, macAddr, FDB_DYNAMIC, &column, &fdbEntry); + if (found == SUCCESS ) + { + port_num = rtl865x_ConvertPortMasktoPortNum(fdbEntry.memberPortMask); + + if (rtl865x_lookup_FilterDatabaseEntry(fdbEntry.fid, macAddr) != SUCCESS) + { + l2temp_entry.l2type = (fdbEntry.nhFlag==0)?RTL865x_L2_TYPEI: RTL865x_L2_TYPEII; + l2temp_entry.process = FDB_TYPE_FWD; + l2temp_entry.memberPortMask = fdbEntry.memberPortMask; + l2temp_entry.auth = TRUE; + l2temp_entry.SrcBlk = FALSE; + memcpy(&(l2temp_entry.macAddr), macAddr, sizeof(ether_addr_t)); + ret =rtl865x_addAuthFilterDatabaseEntryExtension(fdbEntry.fid, &l2temp_entry); + } + } + return ret; +} +*/ + +int32 lan_restrict_getBlockAddr(int32 port , const unsigned char *swap_addr) +{ + int32 ret = FAILED; + + if (lan_restrict_tbl[port].enable == TRUE) + { + ret = rtl865x_check_authfdbentry_Byport(port , swap_addr); + } + + return ret; +} + +int32 lan_restrict_CheckStatusByport(int32 port) +{ + if (lan_restrict_tbl[port].enable == TRUE) + { + if (lan_restrict_tbl[port].curr_num < lan_restrict_tbl[port].max_num) + { + return TRUE; + } + else + { + return FALSE; + } + } + else + { + return FAILED; + } +} +static int lan_restrict_read_proc(char *page, char **start, off_t off, + int count, int *eof, void *data) +{ + int len, i ; + len = sprintf(page, "%s\n", "lan restrict table:"); + if (len <= off+count) + *eof = 1; + + for (i = 0; i < LAN_RESTRICT_PORT_NUMBER; i++) + { + len += sprintf(page + len, " PORT[%d] ", i); + len += sprintf(page + len,"%6s %6d %6d ",lan_restrict_tbl[i].enable?"ON":"OFF", lan_restrict_tbl[i].max_num, lan_restrict_tbl[i].curr_num); + len += sprintf(page + len,"\n"); + } + + return len; +} + +static int lan_restrict_write_proc(struct file *file, const char *buffer, + unsigned long count, void *data) +{ + char tmpbuf[1024]; + char *entryPtr, *portnumPtr, *enablePtr, *maxnumPtr, *strptr=tmpbuf; + int8 port, port_enable, maxnum; + + if (count < 2) + return -EFAULT; + /* + format: entry1;entry2;entry3 + entry format: port_num enable max_num curr_num; + port_num: 0,1,2... + enable: on/off + max_num: 0,1,2... + curr_num: 0,1,2..., can not write, can only read from proc file and write again, just for display + */ + + memset(lan_restrict_flag,0,strlen(lan_restrict_flag)); + if (buffer && !copy_from_user(tmpbuf, buffer, count)) + { + if(memcmp(strptr,"enable", strlen("enable")) == 0) + { + lan_restrict_enable(); + enable_lanrestrict = TRUE; +/* printk("Fun[%s][%d]\n", __FUNCTION__, __LINE__);*/ + printk("enable lan restrict FUNC.....\n"); + } + else if(memcmp(strptr,"disable", strlen("enable")) == 0) + { + lan_restrict_disable(); + enable_lanrestrict = FALSE; +/* printk("Fun[%s][%d]\n", __FUNCTION__, __LINE__);*/ + printk("disable lan restrict FUNC.....\n"); + } + else + { + if (lan_restrict_enable == FALSE) + return count; + + /* + format: entry1;entry2;entry3 + entry format: port_num enable max_num curr_num; + port_num: 0,1,2... + enable: on/off + max_num: 0,1,2... + curr_num: 0,1,2..., can not write, can only read from proc file and write again, just for display + */ + entryPtr = strsep(&strptr,";"); + while (entryPtr != NULL) + { + /*1. port_num*/ + portnumPtr = strsep(&entryPtr," "); + if(portnumPtr == NULL) + { + printk("lan restrict setting format error1\n"); + break; + } + port = simple_strtol(portnumPtr,NULL,0); + printk("set port num is %d\n", port); + + /*2. enable or not*/ + enablePtr = strsep(&entryPtr," "); + if(enablePtr == NULL) + { + printk("lan restrict setting format error2\n"); + break; + } + if(_strncasecmp(enablePtr,"OFF",3) == 0) + { + port_enable = FALSE; + } + else if (_strncasecmp(enablePtr,"ON",3) == 0) + { + port_enable = TRUE; + } + else + { + printk("lan restrict setting format error3\n"); + break; + } + printk("port_enable is %d\n", port_enable); + + /*3max num*/ + maxnumPtr = strsep(&entryPtr," "); + if(maxnumPtr == NULL) + { + printk("lan restrict setting format error4\n"); + break; + } + maxnum = simple_strtol(maxnumPtr,NULL,0); + printk("set max num is %d\n", maxnum); + + lan_restrict_tbl[port].enable = port_enable; + lan_restrict_tbl[port].max_num = maxnum; + /* + set Asic + */ + lan_restrict_set_singleport(port, port_enable, maxnum); + } + } + } + + return count; +} + +static int lan_restrict_proc_init(void) +{ + res = create_proc_entry("lan_restrict_info",0,NULL); + if(res) + { + res->read_proc = lan_restrict_read_proc; + res->write_proc = lan_restrict_write_proc; + lanrestrict_unRegister_event(); + lanrestrict_register_event(); + return TRUE; + } + return FALSE; +} + +int __init lan_restrict_init(void) +{ + lan_restrict_tbl_int(); +// dev_add_pack(&lan_restrict_packet_type); + lan_restrict_proc_init(); + return 0; +} + + diff --git a/target/linux/realtek/files/net/bridge/lan_restrict.h b/target/linux/realtek/files/net/bridge/lan_restrict.h new file mode 100644 index 000000000..0ad313b47 --- /dev/null +++ b/target/linux/realtek/files/net/bridge/lan_restrict.h @@ -0,0 +1,10 @@ +//#include <common/rtl865x_common.h>
+#include <net/rtl/rtl_types.h>
+#include <net/rtl/rtl_queue.h>
+#include <net/rtl/rtl_nic.h>
+#include <net/rtl/rtl865x_fdb_api.h>
+
+int32 lan_restrict_getBlockAddr(int32 port , const unsigned char *swap_addr);
+extern int __init lan_restrict_init(void);
+extern int lan_restrict_rcv(struct sk_buff *skb, struct net_device *dev);
+extern int32 lan_restrict_CheckStatusByport(int32 port);
diff --git a/target/linux/realtek/files/net/bridge/pocket_filter.c b/target/linux/realtek/files/net/bridge/pocket_filter.c new file mode 100644 index 000000000..05c2d809a --- /dev/null +++ b/target/linux/realtek/files/net/bridge/pocket_filter.c @@ -0,0 +1,505 @@ +#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/proc_fs.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/kernel_stat.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <asm/uaccess.h>
+//#include <linux/brlock.h>
+#include <linux/net.h>
+#include <linux/socket.h>
+
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/string.h>
+#include <net/ip.h>
+#include <net/protocol.h>
+#include <net/route.h>
+#include <net/sock.h>
+#include <net/arp.h>
+#include <net/raw.h>
+#include <net/checksum.h>
+#include <linux/netfilter.h>
+#include <linux/netfilter_ipv4.h>
+#include <linux/netlink.h>
+#include <net/udp.h>
+#include <net/rtl/rtl865x_netif.h>
+#include <net/rtl/rtl_nic.h>
+#if defined(CONFIG_HTTP_FILE_SERVER_SUPPORT)
+extern void get_lan_ip_mask(void);
+#endif
+#define OPT_CODE 0
+#define OPT_LEN 1
+#define OPT_DATA 2
+#define OPTION_FIELD 0
+#define FILE_FIELD 1
+#define SNAME_FIELD 2
+/* DHCP option codes (partial list) */
+#define DHCP_PADDING 0x00
+#define DHCP_SUBNET 0x01
+#define DHCP_TIME_OFFSET 0x02
+#define DHCP_ROUTER 0x03
+#define DHCP_TIME_SERVER 0x04
+#define DHCP_NAME_SERVER 0x05
+#define DHCP_DNS_SERVER 0x06
+#define DHCP_LOG_SERVER 0x07
+#define DHCP_COOKIE_SERVER 0x08
+#define DHCP_LPR_SERVER 0x09
+#define DHCP_HOST_NAME 0x0c
+#define DHCP_BOOT_SIZE 0x0d
+#define DHCP_DOMAIN_NAME 0x0f
+#define DHCP_SWAP_SERVER 0x10
+#define DHCP_ROOT_PATH 0x11
+#define DHCP_IP_TTL 0x17
+#define DHCP_MTU 0x1a
+#define DHCP_BROADCAST 0x1c
+#define DHCP_STATIC_ROUTE 0x21
+#define DHCP_NTP_SERVER 0x2a
+#define DHCP_WINS_SERVER 0x2c
+#define DHCP_REQUESTED_IP 0x32
+#define DHCP_LEASE_TIME 0x33
+#define DHCP_OPTION_OVER 0x34
+#define DHCP_MESSAGE_TYPE 0x35
+#define DHCP_SERVER_ID 0x36
+#define DHCP_PARAM_REQ 0x37
+#define DHCP_MESSAGE 0x38
+#define DHCP_MAX_SIZE 0x39
+#define DHCP_T1 0x3a
+#define DHCP_T2 0x3b
+#define DHCP_VENDOR 0x3c
+#define DHCP_CLIENT_ID 0x3d
+#define DHCP_NETBIOS_NODETYPE 0x2e
+#define DHCP_NETBIOS_SCOPE 0x2F
+#define DHCP_END 0xFF
+int br_filter_mangle_udp_packet(struct sk_buff **skb, unsigned int match_offset,unsigned int match_len,unsigned char *rep_buffer, unsigned int rep_len);
+struct proc_dir_entry *filter_root=NULL;
+static struct proc_dir_entry *res1=NULL;
+static struct proc_dir_entry *res2=NULL;
+int enable_filter=0;
+static unsigned char filter_config[256];
+int dut_br0_ip=0;
+unsigned char dut_br0_mac[6]={0};
+unsigned char Filter_State=0;
+struct dhcpMessage {
+ unsigned char op;
+ unsigned char htype;
+ unsigned char hlen;
+ unsigned char hops;
+ unsigned int xid;
+ unsigned short secs;
+ unsigned short flags;
+ unsigned int ciaddr;
+ unsigned int yiaddr;
+ unsigned int siaddr;
+ unsigned int giaddr;
+ unsigned char chaddr[16];
+ unsigned char sname[64];
+ unsigned char file[128];
+ unsigned int cookie;
+ unsigned char options[308]; /* 312 - cookie */
+};
+
+struct udp_dhcp_packet {
+ struct iphdr ip;
+ struct udphdr udp;
+ struct dhcpMessage data;
+};
+
+static int br_filter_resize_packet(struct sk_buff **skb, int new_size)
+{
+ struct iphdr *iph;
+
+
+
+ if (new_size > (*skb)->len + skb_tailroom(*skb)) {
+ struct sk_buff *newskb;
+ newskb = skb_copy_expand(*skb, skb_headroom(*skb), new_size - (*skb)->len,GFP_ATOMIC);
+
+ if (!newskb) {
+ return 0;
+ } else {
+ kfree_skb(*skb);
+ *skb = newskb;
+ }
+ }
+
+ return 1;
+}
+
+int br_filter_mangle_udp_packet(struct sk_buff **skb, unsigned int match_offset,unsigned int match_len,unsigned char *rep_buffer, unsigned int rep_len)
+{
+ //struct iphdr *iph = (*skb)->nh.iph;
+ struct iphdr *iph = (struct iphdr *)skb_network_header(*skb);
+ struct udphdr *udph = (void *)iph + iph->ihl * 4;
+ unsigned char *data;
+ u_int32_t udplen, newlen, newudplen;
+
+ udplen = (*skb)->len - iph->ihl*4;
+ newudplen = udplen - match_len + rep_len;
+ newlen = iph->ihl*4 + newudplen;
+
+ /* UDP helpers might accidentally mangle the wrong packet */
+ if (udplen < sizeof(*udph) + match_offset + match_len) {
+ return 0;
+ }
+
+ if (newlen > 65535) {
+ return 0;
+ }
+
+ if ((*skb)->len != newlen) {
+ if (!br_filter_resize_packet(skb, newlen)) {
+ return 0;
+ }
+ }
+
+ /* skb may be copied !! */
+ //iph = (*skb)->nh.iph;
+ iph = (struct iphdr *)skb_network_header(*skb);
+ udph = (void *)iph + iph->ihl*4;
+ data = (void *)udph + sizeof(struct udphdr);
+
+ if (rep_len != match_len)
+ /* move post-replacement */
+ memmove(data + match_offset + rep_len,
+ data + match_offset + match_len,
+ (*skb)->tail - (data + match_offset + match_len));
+
+ /* insert data from buffer */
+ memcpy(data + match_offset, rep_buffer, rep_len);
+
+ /* update skb info */
+ if (newlen > (*skb)->len) {
+
+ skb_put(*skb, newlen - (*skb)->len);
+ } else {
+
+ skb_trim(*skb, newlen);
+ }
+
+ /* update the length of the UDP and IP packets to the new values*/
+ udph->len = htons((*skb)->len - iph->ihl*4);
+ iph->tot_len = htons(newlen);
+
+ /* fix udp checksum if udp checksum was previously calculated */
+ if (udph->check != 0) {
+ udph->check = 0;
+ udph->check = csum_tcpudp_magic(iph->saddr, iph->daddr,
+ newudplen, IPPROTO_UDP,
+ csum_partial((char *)udph,
+ newudplen, 0));
+ }
+ ip_send_check(iph);
+
+ return 1;
+}
+unsigned char *br_filter_get_dhcp_option(struct dhcpMessage *packet, int code)
+{
+ int i, length;
+ unsigned char *optionptr=NULL;
+ int over = 0, done = 0, curr = OPTION_FIELD;
+
+ optionptr = packet->options;
+ i = 0;
+ length = 308;
+ while (!done) {
+ if (i >= length) {
+ return NULL;
+ }
+ if (optionptr[i + OPT_CODE] == code) {
+ if (i + 1 + optionptr[i + OPT_LEN] >= length) {
+ return NULL;
+ }
+ return optionptr + i + 2;
+ }
+ switch (optionptr[i + OPT_CODE]) {
+ case DHCP_PADDING:
+ i++;
+ break;
+ case DHCP_OPTION_OVER:
+ if (i + 1 + optionptr[i + OPT_LEN] >= length) {
+ return NULL;
+ }
+ over = optionptr[i + 3];
+ i += optionptr[OPT_LEN] + 2;
+ break;
+ case DHCP_END:
+ if (curr == OPTION_FIELD && over & FILE_FIELD) {
+ optionptr = packet->file;
+ i = 0;
+ length = 128;
+ curr = FILE_FIELD;
+ } else if (curr == FILE_FIELD && over & SNAME_FIELD) {
+ optionptr = packet->sname;
+ i = 0;
+ length = 64;
+ curr = SNAME_FIELD;
+ } else done = 1;
+ break;
+ default:
+ i += optionptr[OPT_LEN + i] + 2;
+ }
+ }
+ return NULL;
+}
+int br_filter_enter(struct sk_buff *skb)
+{
+ struct iphdr *iph;
+ struct udphdr *udph;
+ unsigned char *data_start;
+ struct udp_dhcp_packet *dhcp_packet=NULL;
+ //iph = skb->nh.iph;
+ iph = (struct iphdr *)skb_network_header(skb);
+ int i;
+ unsigned int match_offset=0;
+ unsigned int match_len=0;
+ unsigned char replace_buffer[6]={0};
+ unsigned char option_len=0,*temp;
+ if(enable_filter==0)
+ return 0;
+ else{
+
+ udph=(void *) iph + iph->ihl*4;
+ //panic_printk("start to trace dhcp packet, dst port=%d\n",udph->dest);
+ if(iph->protocol==IPPROTO_UDP &&(udph->dest ==67 || udph->dest ==68)){
+ if(udph->dest ==67){//from Client host in dhcp
+ //panic_printk("start to trace dhcp packet:client packet from :%s\n",skb->dev->name);
+ if(!strcmp(skb->dev->name, RTL_PS_LAN_P0_DEV_NAME)){
+ if(Filter_State==0){
+ //panic_printk("in this state, we drop client packet:Filter_State=%d\n",Filter_State);
+ return 1;
+ }
+ }
+
+ }
+
+ if(udph->dest ==68){//from server host in dhcp
+ if(Filter_State==1 || Filter_State==0){ //our dut has got ip address
+ dhcp_packet =(struct udp_dhcp_packet *)skb->data;
+ if ((temp = br_filter_get_dhcp_option(&(dhcp_packet->data), DHCP_DNS_SERVER)))
+ {
+ int roop=0;
+ unsigned char *router_temp, *subnet_temp;
+
+ router_temp = br_filter_get_dhcp_option(&(dhcp_packet->data), DHCP_ROUTER);
+
+ subnet_temp = br_filter_get_dhcp_option(&(dhcp_packet->data), DHCP_SUBNET);
+
+#if 0 //debug for domain name query
+printk("\r\n DHCP_ROUTER=[%x.%x.%x.%x]__[%s-%u]\r\n",(unsigned char *)router_temp[0],
+(unsigned char *)router_temp[1], (unsigned char *)router_temp[2], (unsigned char *)router_temp[3], __FILE__,__LINE__);
+
+printk("\r\n DHCP_SUBNET=[%x.%x.%x.%x]__[%s-%u]\r\n",(unsigned char *)subnet_temp[0],
+(unsigned char *)subnet_temp[1], (unsigned char *)subnet_temp[2], (unsigned char *)subnet_temp[3], __FILE__,__LINE__);
+
+
+printk("\r\n dut_br0_ip=[%x.%x.%x.%x]__[%s-%u]\r\n",((unsigned char *)&dut_br0_ip)[0],
+((unsigned char *)&dut_br0_ip)[1], ((unsigned char *)&dut_br0_ip)[2], ((unsigned char *)&dut_br0_ip)[3], __FILE__,__LINE__);
+
+printk("\r\n router_temp & subnet_temp=[%x],__[%s-%u]\r\n",((*(unsigned int*)router_temp) & (*(unsigned int*)subnet_temp)),__FILE__,__LINE__);
+printk("\r\n dut_br0_ip & subnet_temp=[%x],__[%s-%u]\r\n",(dut_br0_ip & (*(unsigned int*)subnet_temp)),__FILE__,__LINE__);
+#endif //#if 0 //debug for domain name query
+
+ if(((*(unsigned int*)router_temp) & (*(unsigned int*)subnet_temp)) != (dut_br0_ip & (*(unsigned int*)subnet_temp)))
+ {
+ //printk("\r\n dut ip does not in the client's subnet. __[%s-%u]\r\n",__FILE__,__LINE__);
+ return 0;
+ }
+
+ option_len = (temp-1)[0];
+ match_offset=(temp-2)-(unsigned char *)&(dhcp_packet->data);
+ match_len = option_len+2;
+
+ replace_buffer[0]= DHCP_DNS_SERVER;
+ replace_buffer[1]=4;
+ replace_buffer[2]=((unsigned char *)&dut_br0_ip)[0];
+ replace_buffer[3]=((unsigned char *)&dut_br0_ip)[1];
+ replace_buffer[4]=((unsigned char *)&dut_br0_ip)[2];
+ replace_buffer[5]=((unsigned char *)&dut_br0_ip)[3];
+ if(replace_buffer[2] != 0 || replace_buffer[3] != 0 || replace_buffer[4] != 0 || replace_buffer[5] != 0){
+ //panic_printk("in this state, we mangle dhcp server packet, dns ip =%02X%02X%02X%02X\n",replace_buffer[2],replace_buffer[3],replace_buffer[4],replace_buffer[5]);
+ br_filter_mangle_udp_packet(&skb, match_offset, match_len, replace_buffer, 6);
+ }
+ }
+ }
+
+
+ }
+ }
+ return 0;
+ }
+}
+
+
+static int en_filter_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+
+ int len=0;
+
+ len = sprintf(page, "%d\n", enable_filter);
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+
+ return len;
+
+}
+
+static int filter_conf_proc_read(char *page, char **start, off_t off,
+ int count, int *eof, void *data)
+{
+
+ int len=0;
+
+ len = sprintf(page, "%s\n", filter_config);
+
+
+ if (len <= off+count) *eof = 1;
+ *start = page + off;
+ len -= off;
+ if (len>count) len = count;
+ if (len<0) len = 0;
+ return len;
+
+}
+
+static int _is_hex_br_filter(char c)
+{
+ if(((c >= '0') && (c <= '9')) ||((c >= 'A') && (c <= 'F')) ||((c >= 'a') && (c <= 'f')))
+ return 1;
+ else
+ return 0;
+}
+static int en_filter_proc_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char tmpbuf[80];
+
+
+ if (count < 2)
+ return -EFAULT;
+
+ if (buffer && !copy_from_user(tmpbuf, buffer, 80)) {
+ if (tmpbuf[0] == '0'){
+ enable_filter = 0;
+ }else if (tmpbuf[0] == '1'){
+ enable_filter = 1;
+ }
+ return count;
+ }
+ return -EFAULT;
+}
+int br_filter_string_to_hex(char *string, unsigned char *key, int len)
+{
+ char tmpBuf[4];
+ int idx, ii=0;
+ for (idx=0; idx<len; idx+=2) {
+ tmpBuf[0] = string[idx];
+ tmpBuf[1] = string[idx+1];
+ tmpBuf[2] = 0;
+ if ( !_is_hex_br_filter(tmpBuf[0]) || !_is_hex_br_filter(tmpBuf[1]))
+ return 0;
+
+ key[ii++] = (unsigned char) simple_strtol(tmpBuf, (char**)NULL, 16);
+ }
+ return 1;
+}
+static int filter_conf_proc_write(struct file *file, const char *buffer,
+ unsigned long count, void *data)
+{
+ char tmpbuf[1024];
+ char *tokptr, *strptr=tmpbuf;
+ u_int8_t idx=1;
+ u_int32_t val;
+
+ if (count < 2)
+ return -EFAULT;
+ memset(filter_config, 0x00, 256);
+ if (buffer && !copy_from_user(&filter_config, buffer, count)) {
+ strncpy(tmpbuf,filter_config,count);
+ while ((tokptr = strtok(strptr," ")) !=NULL)
+ {
+ strptr=NULL;
+ val=simple_strtol(tokptr,NULL,0);
+ switch(idx)
+ {
+ case 1:
+ val=simple_strtol(tokptr,NULL,16);
+ dut_br0_ip=val;
+ break;
+ case 2:
+ br_filter_string_to_hex(tokptr, dut_br0_mac, 12);
+ //panic_printk("dut mac=%02X:%02X:%02X:%02X:%02X:%02X\n",dut_br0_mac[0], dut_br0_mac[1], dut_br0_mac[2], dut_br0_mac[3],dut_br0_mac[4],dut_br0_mac[5]);
+ break;
+ case 3:
+ val=simple_strtol(tokptr,NULL,10);
+ Filter_State=val;
+ //panic_printk("Filter_State=%d\n",Filter_State);
+ break;
+ default:
+ break;
+ }
+ idx++;
+
+ }
+#if defined(CONFIG_HTTP_FILE_SERVER_SUPPORT)
+ get_lan_ip_mask();
+#endif
+ return count;
+ }
+ return -EFAULT;
+}
+
+
+int __init br_filter_init(void)
+{
+#if defined(CONFIG_PROC_FS)
+
+ struct proc_dir_entry *devices = NULL,*pvc = NULL,*svc = NULL;
+ filter_root = proc_mkdir("pocket",NULL);
+ if (!filter_root){
+ printk("create folder fail\n");
+ return -ENOMEM;
+ }
+ res1 = create_proc_entry("en_filter", 0, filter_root);
+ if (res1) {
+ res1->read_proc = en_filter_proc_read;
+ res1->write_proc = en_filter_proc_write;
+ }
+
+ res2 = create_proc_entry("filter_conf", 0, filter_root);
+ if (res2) {
+ res2->read_proc = filter_conf_proc_read;
+ res2->write_proc = filter_conf_proc_write;
+ }
+
+#endif // CONFIG_PROC_FS
+ return 0;
+}
+
+void __exit br_filter_exit(void)
+{
+#if defined(CONFIG_PROC_FS)
+ if (res1) {
+ remove_proc_entry("en_filter", filter_root);
+ res2 = NULL;
+ }
+ if (res2) {
+ remove_proc_entry("filter_conf", filter_root);
+ res2 = NULL;
+ }
+
+ remove_proc_entry("pocket",NULL);
+#endif // CONFIG_PROC_FS
+}
+
+
|