1 /******************************************************************************
3 * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * You should have received a copy of the GNU General Public License along with
15 * this program; if not, write to the Free Software Foundation, Inc.,
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
19 ******************************************************************************/
20 #define _RTW_BR_EXT_C_
23 #include <linux/if_arp.h>
26 #include <linux/atalk.h>
27 #include <linux/udp.h>
28 #include <linux/if_pppox.h>
31 #if 1 // rtw_wifi_driver
33 #include <drv_types.h>
34 #include "rtw_br_ext.h"
35 #else // rtw_wifi_driver
36 #include "./8192cd_cfg.h"
39 #include "./sys-support.h"
43 #include "./8192cd_headers.h"
44 #include "./8192cd_br_ext.h"
45 #include "./8192cd_debug.h"
46 #endif // rtw_wifi_driver
50 #include <linux/ipv6.h>
51 #include <linux/icmpv6.h>
52 #include <net/ndisc.h>
53 #include <net/checksum.h>
54 #include <net/ip6_checksum.h>
60 //#define BR_EXT_DEBUG
65 #define NAT25_APPLE 04
66 #define NAT25_PPPOE 05
68 #define RTL_RELAY_TAG_LEN (ETH_ALEN)
71 #define MAGIC_CODE 0x8186
72 #define MAGIC_CODE_LEN 2
73 #define WAIT_TIME_PPPOE 5 // waiting time for pppoe server in sec
75 /*-----------------------------------------------------------------
76 How database records network address:
77 0 1 2 3 4 5 6 7 8 9 10
78 |----|----|----|----|----|----|----|----|----|----|----|
79 IPv4 |type| | IP addr |
80 IPX |type| Net addr | Node addr |
81 IPX |type| Net addr |Sckt addr|
82 Apple |type| Network |node|
83 PPPoE |type| SID | AC MAC |
84 -----------------------------------------------------------------*/
87 //Find a tag in pppoe frame and return the pointer
88 static __inline__
unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr
*ph
, unsigned short type
)
90 unsigned char *cur_ptr
, *start_ptr
;
91 unsigned short tagLen
, tagType
;
93 start_ptr
= cur_ptr
= (unsigned char *)ph
->tag
;
94 while((cur_ptr
- start_ptr
) < ntohs(ph
->length
)) {
95 // prevent un-alignment access
96 tagType
= (unsigned short)((cur_ptr
[0] << 8) + cur_ptr
[1]);
97 tagLen
= (unsigned short)((cur_ptr
[2] << 8) + cur_ptr
[3]);
100 cur_ptr
= cur_ptr
+ TAG_HDR_LEN
+ tagLen
;
106 static __inline__
int __nat25_add_pppoe_tag(struct sk_buff
*skb
, struct pppoe_tag
*tag
)
108 struct pppoe_hdr
*ph
= (struct pppoe_hdr
*)(skb
->data
+ ETH_HLEN
);
111 data_len
= tag
->tag_len
+ TAG_HDR_LEN
;
112 if (skb_tailroom(skb
) < data_len
) {
113 _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
117 skb_put(skb
, data_len
);
118 // have a room for new tag
119 memmove(((unsigned char *)ph
->tag
+ data_len
), (unsigned char *)ph
->tag
, ntohs(ph
->length
));
120 ph
->length
= htons(ntohs(ph
->length
) + data_len
);
121 memcpy((unsigned char *)ph
->tag
, tag
, data_len
);
125 static int skb_pull_and_merge(struct sk_buff
*skb
, unsigned char *src
, int len
)
128 unsigned long end
, tail
;
130 if ((src
+len
) > skb_tail_pointer(skb
) || skb
->len
< len
)
133 tail
= (unsigned long)skb_tail_pointer(skb
);
134 end
= (unsigned long)src
+len
;
138 tail_len
= (int)(tail
-end
);
140 memmove(src
, src
+len
, tail_len
);
142 skb_trim(skb
, skb
->len
-len
);
146 static __inline__
unsigned long __nat25_timeout(_adapter
*priv
)
148 unsigned long timeout
;
150 timeout
= jiffies
- NAT25_AGEING_TIME
*HZ
;
156 static __inline__
int __nat25_has_expired(_adapter
*priv
,
157 struct nat25_network_db_entry
*fdb
)
159 if(time_before_eq(fdb
->ageing_timer
, __nat25_timeout(priv
)))
166 static __inline__
void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr
,
167 unsigned int *ipAddr
)
169 memset(networkAddr
, 0, MAX_NETWORK_ADDR_LEN
);
171 networkAddr
[0] = NAT25_IPV4
;
172 memcpy(networkAddr
+7, (unsigned char *)ipAddr
, 4);
176 static __inline__
void __nat25_generate_ipx_network_addr_with_node(unsigned char *networkAddr
,
177 unsigned int *ipxNetAddr
, unsigned char *ipxNodeAddr
)
179 memset(networkAddr
, 0, MAX_NETWORK_ADDR_LEN
);
181 networkAddr
[0] = NAT25_IPX
;
182 memcpy(networkAddr
+1, (unsigned char *)ipxNetAddr
, 4);
183 memcpy(networkAddr
+5, ipxNodeAddr
, 6);
187 static __inline__
void __nat25_generate_ipx_network_addr_with_socket(unsigned char *networkAddr
,
188 unsigned int *ipxNetAddr
, unsigned short *ipxSocketAddr
)
190 memset(networkAddr
, 0, MAX_NETWORK_ADDR_LEN
);
192 networkAddr
[0] = NAT25_IPX
;
193 memcpy(networkAddr
+1, (unsigned char *)ipxNetAddr
, 4);
194 memcpy(networkAddr
+5, (unsigned char *)ipxSocketAddr
, 2);
198 static __inline__
void __nat25_generate_apple_network_addr(unsigned char *networkAddr
,
199 unsigned short *network
, unsigned char *node
)
201 memset(networkAddr
, 0, MAX_NETWORK_ADDR_LEN
);
203 networkAddr
[0] = NAT25_APPLE
;
204 memcpy(networkAddr
+1, (unsigned char *)network
, 2);
205 networkAddr
[3] = *node
;
209 static __inline__
void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr
,
210 unsigned char *ac_mac
, unsigned short *sid
)
212 memset(networkAddr
, 0, MAX_NETWORK_ADDR_LEN
);
214 networkAddr
[0] = NAT25_PPPOE
;
215 memcpy(networkAddr
+1, (unsigned char *)sid
, 2);
216 memcpy(networkAddr
+3, (unsigned char *)ac_mac
, 6);
221 static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr
,
222 unsigned int *ipAddr
)
224 memset(networkAddr
, 0, MAX_NETWORK_ADDR_LEN
);
226 networkAddr
[0] = NAT25_IPV6
;
227 memcpy(networkAddr
+1, (unsigned char *)ipAddr
, 16);
231 static unsigned char *scan_tlv(unsigned char *data
, int len
, unsigned char tag
, unsigned char len8b
)
234 if (*data
== tag
&& *(data
+1) == len8b
&& len
>= len8b
*8)
237 len
-= (*(data
+1))*8;
238 data
+= (*(data
+1))*8;
244 static int update_nd_link_layer_addr(unsigned char *data
, int len
, unsigned char *replace_mac
)
246 struct icmp6hdr
*icmphdr
= (struct icmp6hdr
*)data
;
249 if (icmphdr
->icmp6_type
== NDISC_ROUTER_SOLICITATION
) {
251 mac
= scan_tlv(&data
[8], len
-8, 1, 1);
253 _DEBUG_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
254 mac
[0],mac
[1],mac
[2],mac
[3],mac
[4],mac
[5],
255 replace_mac
[0],replace_mac
[1],replace_mac
[2],replace_mac
[3],replace_mac
[4],replace_mac
[5]);
256 memcpy(mac
, replace_mac
, 6);
261 else if (icmphdr
->icmp6_type
== NDISC_ROUTER_ADVERTISEMENT
) {
263 mac
= scan_tlv(&data
[16], len
-16, 1, 1);
265 _DEBUG_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
266 mac
[0],mac
[1],mac
[2],mac
[3],mac
[4],mac
[5],
267 replace_mac
[0],replace_mac
[1],replace_mac
[2],replace_mac
[3],replace_mac
[4],replace_mac
[5]);
268 memcpy(mac
, replace_mac
, 6);
273 else if (icmphdr
->icmp6_type
== NDISC_NEIGHBOUR_SOLICITATION
) {
275 mac
= scan_tlv(&data
[24], len
-24, 1, 1);
277 _DEBUG_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
278 mac
[0],mac
[1],mac
[2],mac
[3],mac
[4],mac
[5],
279 replace_mac
[0],replace_mac
[1],replace_mac
[2],replace_mac
[3],replace_mac
[4],replace_mac
[5]);
280 memcpy(mac
, replace_mac
, 6);
285 else if (icmphdr
->icmp6_type
== NDISC_NEIGHBOUR_ADVERTISEMENT
) {
287 mac
= scan_tlv(&data
[24], len
-24, 2, 1);
289 _DEBUG_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
290 mac
[0],mac
[1],mac
[2],mac
[3],mac
[4],mac
[5],
291 replace_mac
[0],replace_mac
[1],replace_mac
[2],replace_mac
[3],replace_mac
[4],replace_mac
[5]);
292 memcpy(mac
, replace_mac
, 6);
297 else if (icmphdr
->icmp6_type
== NDISC_REDIRECT
) {
299 mac
= scan_tlv(&data
[40], len
-40, 2, 1);
301 _DEBUG_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
302 mac
[0],mac
[1],mac
[2],mac
[3],mac
[4],mac
[5],
303 replace_mac
[0],replace_mac
[1],replace_mac
[2],replace_mac
[3],replace_mac
[4],replace_mac
[5]);
304 memcpy(mac
, replace_mac
, 6);
313 static void convert_ipv6_mac_to_mc(struct sk_buff
*skb
)
315 struct ipv6hdr
*iph
= (struct ipv6hdr
*)(skb
->data
+ ETH_HLEN
);
316 unsigned char *dst_mac
= skb
->data
;
320 /*modified by qinjunjie,ipv6 multicast address ix 0x33-33-xx-xx-xx-xx*/
323 memcpy(&dst_mac
[2], &iph
->daddr
.s6_addr32
[3], 4);
324 #if defined(__LINUX_2_6__)
325 /*modified by qinjunjie,warning:should not remove next line*/
326 skb
->pkt_type
= PACKET_MULTICAST
;
329 #endif /* CL_IPV6_PASS */
332 static __inline__
int __nat25_network_hash(unsigned char *networkAddr
)
334 if(networkAddr
[0] == NAT25_IPV4
)
338 x
= networkAddr
[7] ^ networkAddr
[8] ^ networkAddr
[9] ^ networkAddr
[10];
340 return x
& (NAT25_HASH_SIZE
- 1);
342 else if(networkAddr
[0] == NAT25_IPX
)
346 x
= networkAddr
[1] ^ networkAddr
[2] ^ networkAddr
[3] ^ networkAddr
[4] ^ networkAddr
[5] ^
347 networkAddr
[6] ^ networkAddr
[7] ^ networkAddr
[8] ^ networkAddr
[9] ^ networkAddr
[10];
349 return x
& (NAT25_HASH_SIZE
- 1);
351 else if(networkAddr
[0] == NAT25_APPLE
)
355 x
= networkAddr
[1] ^ networkAddr
[2] ^ networkAddr
[3];
357 return x
& (NAT25_HASH_SIZE
- 1);
359 else if(networkAddr
[0] == NAT25_PPPOE
)
363 x
= networkAddr
[0] ^ networkAddr
[1] ^ networkAddr
[2] ^ networkAddr
[3] ^ networkAddr
[4] ^ networkAddr
[5] ^ networkAddr
[6] ^ networkAddr
[7] ^ networkAddr
[8];
365 return x
& (NAT25_HASH_SIZE
- 1);
368 else if(networkAddr
[0] == NAT25_IPV6
)
372 x
= networkAddr
[1] ^ networkAddr
[2] ^ networkAddr
[3] ^ networkAddr
[4] ^ networkAddr
[5] ^
373 networkAddr
[6] ^ networkAddr
[7] ^ networkAddr
[8] ^ networkAddr
[9] ^ networkAddr
[10] ^
374 networkAddr
[11] ^ networkAddr
[12] ^ networkAddr
[13] ^ networkAddr
[14] ^ networkAddr
[15] ^
377 return x
& (NAT25_HASH_SIZE
- 1);
385 for (i
=0; i
<MAX_NETWORK_ADDR_LEN
; i
++)
388 return x
& (NAT25_HASH_SIZE
- 1);
393 static __inline__
void __network_hash_link(_adapter
*priv
,
394 struct nat25_network_db_entry
*ent
, int hash
)
396 // Caller must _enter_critical_bh already!
398 //_enter_critical_bh(&priv->br_ext_lock, &irqL);
400 ent
->next_hash
= priv
->nethash
[hash
];
401 if(ent
->next_hash
!= NULL
)
402 ent
->next_hash
->pprev_hash
= &ent
->next_hash
;
403 priv
->nethash
[hash
] = ent
;
404 ent
->pprev_hash
= &priv
->nethash
[hash
];
406 //_exit_critical_bh(&priv->br_ext_lock, &irqL);
410 static __inline__
void __network_hash_unlink(struct nat25_network_db_entry
*ent
)
412 // Caller must _enter_critical_bh already!
414 //_enter_critical_bh(&priv->br_ext_lock, &irqL);
416 *(ent
->pprev_hash
) = ent
->next_hash
;
417 if(ent
->next_hash
!= NULL
)
418 ent
->next_hash
->pprev_hash
= ent
->pprev_hash
;
419 ent
->next_hash
= NULL
;
420 ent
->pprev_hash
= NULL
;
422 //_exit_critical_bh(&priv->br_ext_lock, &irqL);
426 static int __nat25_db_network_lookup_and_replace(_adapter
*priv
,
427 struct sk_buff
*skb
, unsigned char *networkAddr
)
429 struct nat25_network_db_entry
*db
;
431 _enter_critical_bh(&priv
->br_ext_lock
, &irqL
);
433 db
= priv
->nethash
[__nat25_network_hash(networkAddr
)];
436 if(!memcmp(db
->networkAddr
, networkAddr
, MAX_NETWORK_ADDR_LEN
))
438 if(!__nat25_has_expired(priv
, db
))
440 // replace the destination mac address
441 memcpy(skb
->data
, db
->macAddr
, ETH_ALEN
);
442 atomic_inc(&db
->use_count
);
445 DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
446 "%02x%02x%02x%02x%02x%02x\n",
469 db
->networkAddr
[16]);
471 DEBUG_INFO("NAT25: Lookup M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
488 db
->networkAddr
[10]);
491 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
498 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
503 static void __nat25_db_network_insert(_adapter
*priv
,
504 unsigned char *macAddr
, unsigned char *networkAddr
)
506 struct nat25_network_db_entry
*db
;
509 _enter_critical_bh(&priv
->br_ext_lock
, &irqL
);
511 hash
= __nat25_network_hash(networkAddr
);
512 db
= priv
->nethash
[hash
];
515 if(!memcmp(db
->networkAddr
, networkAddr
, MAX_NETWORK_ADDR_LEN
))
517 memcpy(db
->macAddr
, macAddr
, ETH_ALEN
);
518 db
->ageing_timer
= jiffies
;
519 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
526 db
= (struct nat25_network_db_entry
*) rtw_malloc(sizeof(*db
));
528 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
532 memcpy(db
->networkAddr
, networkAddr
, MAX_NETWORK_ADDR_LEN
);
533 memcpy(db
->macAddr
, macAddr
, ETH_ALEN
);
534 atomic_set(&db
->use_count
, 1);
535 db
->ageing_timer
= jiffies
;
537 __network_hash_link(priv
, db
, hash
);
539 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
543 static void __nat25_db_print(_adapter
*priv
)
546 _enter_critical_bh(&priv
->br_ext_lock
, &irqL
);
549 static int counter
= 0;
551 struct nat25_network_db_entry
*db
;
554 if((counter
% 16) != 0)
557 for(i
=0, j
=0; i
<NAT25_HASH_SIZE
; i
++)
559 db
= priv
->nethash
[i
];
564 panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
565 "%02x%02x%02x%02x%02x%02x\n",
568 atomic_read(&db
->use_count
),
591 db
->networkAddr
[16]);
593 panic_printk("NAT25: DB(%d) H(%02d) C(%d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
596 atomic_read(&db
->use_count
),
613 db
->networkAddr
[10]);
622 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
632 void nat25_db_cleanup(_adapter
*priv
)
636 _enter_critical_bh(&priv
->br_ext_lock
, &irqL
);
638 for(i
=0; i
<NAT25_HASH_SIZE
; i
++)
640 struct nat25_network_db_entry
*f
;
641 f
= priv
->nethash
[i
];
643 struct nat25_network_db_entry
*g
;
646 if(priv
->scdb_entry
== f
)
648 memset(priv
->scdb_mac
, 0, ETH_ALEN
);
649 memset(priv
->scdb_ip
, 0, 4);
650 priv
->scdb_entry
= NULL
;
652 __network_hash_unlink(f
);
653 rtw_mfree((u8
*) f
, sizeof(struct nat25_network_db_entry
));
659 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
663 void nat25_db_expire(_adapter
*priv
)
667 _enter_critical_bh(&priv
->br_ext_lock
, &irqL
);
669 //if(!priv->ethBrExtInfo.nat25_disable)
671 for (i
=0; i
<NAT25_HASH_SIZE
; i
++)
673 struct nat25_network_db_entry
*f
;
674 f
= priv
->nethash
[i
];
678 struct nat25_network_db_entry
*g
;
681 if(__nat25_has_expired(priv
, f
))
683 if(atomic_dec_and_test(&f
->use_count
))
687 panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x"
688 "%02x%02x%02x%02x%02x%02x\n",
715 panic_printk("NAT25 Expire H(%02d) M:%02x%02x%02x%02x%02x%02x N:%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n",
736 if(priv
->scdb_entry
== f
)
738 memset(priv
->scdb_mac
, 0, ETH_ALEN
);
739 memset(priv
->scdb_ip
, 0, 4);
740 priv
->scdb_entry
= NULL
;
742 __network_hash_unlink(f
);
743 rtw_mfree((u8
*) f
, sizeof(struct nat25_network_db_entry
));
752 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
756 #ifdef SUPPORT_TX_MCAST2UNI
757 static int checkIPMcAndReplace(_adapter
*priv
, struct sk_buff
*skb
, unsigned int *dst_ip
)
759 struct stat_info
*pstat
;
760 struct list_head
*phead
, *plist
;
763 phead
= &priv
->asoc_list
;
766 while (plist
!= phead
) {
767 pstat
= list_entry(plist
, struct stat_info
, asoc_list
);
770 if (pstat
->ipmc_num
== 0)
773 for (i
=0; i
<MAX_IP_MC_ENTRY
; i
++) {
774 if (pstat
->ipmc
[i
].used
&& !memcmp(&pstat
->ipmc
[i
].mcmac
[3], ((unsigned char *)dst_ip
)+1, 3)) {
775 memcpy(skb
->data
, pstat
->ipmc
[i
].mcmac
, ETH_ALEN
);
784 int nat25_db_handle(_adapter
*priv
, struct sk_buff
*skb
, int method
)
786 unsigned short protocol
;
787 unsigned char networkAddr
[MAX_NETWORK_ADDR_LEN
];
792 if((method
<= NAT25_MIN
) || (method
>= NAT25_MAX
))
795 protocol
= *((unsigned short *)(skb
->data
+ 2 * ETH_ALEN
));
797 /*---------------------------------------------------*/
798 /* Handle IP frame */
799 /*---------------------------------------------------*/
800 if(protocol
== __constant_htons(ETH_P_IP
))
802 struct iphdr
* iph
= (struct iphdr
*)(skb
->data
+ ETH_HLEN
);
804 if(((unsigned char*)(iph
) + (iph
->ihl
<<2)) >= (skb
->data
+ ETH_HLEN
+ skb
->len
))
806 DEBUG_WARN("NAT25: malformed IP packet !\n");
817 //some muticast with source IP is all zero, maybe other case is illegal
818 //in class A, B, C, host address is all zero or all one is illegal
821 DEBUG_INFO("NAT25: Insert IP, SA=%08x, DA=%08x\n", iph
->saddr
, iph
->daddr
);
822 __nat25_generate_ipv4_network_addr(networkAddr
, &iph
->saddr
);
823 //record source IP address and , source mac address into db
824 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
826 __nat25_db_print(priv
);
832 DEBUG_INFO("NAT25: Lookup IP, SA=%08x, DA=%08x\n", iph
->saddr
, iph
->daddr
);
833 #ifdef SUPPORT_TX_MCAST2UNI
834 if (priv
->pshare
->rf_ft_var
.mc2u_disable
||
835 ((((OPMODE
& (WIFI_STATION_STATE
|WIFI_ASOC_STATE
))
836 == (WIFI_STATION_STATE
|WIFI_ASOC_STATE
)) &&
837 !checkIPMcAndReplace(priv
, skb
, &iph
->daddr
)) ||
838 (OPMODE
& WIFI_ADHOC_STATE
)))
841 __nat25_generate_ipv4_network_addr(networkAddr
, &iph
->daddr
);
843 if (!__nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
)) {
844 if (*((unsigned char *)&iph
->daddr
+ 3) == 0xff) {
845 // L2 is unicast but L3 is broadcast, make L2 bacome broadcast
846 DEBUG_INFO("NAT25: Set DA as boardcast\n");
847 memset(skb
->data
, 0xff, ETH_ALEN
);
850 // forward unknow IP packet to upper TCP/IP
851 DEBUG_INFO("NAT25: Replace DA with BR's MAC\n");
852 if ( (*(u32
*)priv
->br_mac
) == 0 && (*(u16
*)(priv
->br_mac
+4)) == 0 ) {
853 void netdev_br_init(struct net_device
*netdev
);
854 printk("Re-init netdev_br_init() due to br_mac==0!\n");
855 netdev_br_init(priv
->pnetdev
);
857 memcpy(skb
->data
, priv
->br_mac
, ETH_ALEN
);
869 /*---------------------------------------------------*/
870 /* Handle ARP frame */
871 /*---------------------------------------------------*/
872 else if(protocol
== __constant_htons(ETH_P_ARP
))
874 struct arphdr
*arp
= (struct arphdr
*)(skb
->data
+ ETH_HLEN
);
875 unsigned char *arp_ptr
= (unsigned char *)(arp
+ 1);
876 unsigned int *sender
, *target
;
878 if(arp
->ar_pro
!= __constant_htons(ETH_P_IP
))
880 DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", htons(arp
->ar_pro
));
887 return 0; // skb_copy for all ARP frame
891 DEBUG_INFO("NAT25: Insert ARP, MAC=%02x%02x%02x%02x%02x%02x\n", arp_ptr
[0],
892 arp_ptr
[1], arp_ptr
[2], arp_ptr
[3], arp_ptr
[4], arp_ptr
[5]);
894 // change to ARP sender mac address to wlan STA address
895 memcpy(arp_ptr
, GET_MY_HWADDR(priv
), ETH_ALEN
);
897 arp_ptr
+= arp
->ar_hln
;
898 sender
= (unsigned int *)arp_ptr
;
900 __nat25_generate_ipv4_network_addr(networkAddr
, sender
);
902 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
904 __nat25_db_print(priv
);
910 DEBUG_INFO("NAT25: Lookup ARP\n");
912 arp_ptr
+= arp
->ar_hln
;
913 sender
= (unsigned int *)arp_ptr
;
914 arp_ptr
+= (arp
->ar_hln
+ arp
->ar_pln
);
915 target
= (unsigned int *)arp_ptr
;
917 __nat25_generate_ipv4_network_addr(networkAddr
, target
);
919 __nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
);
921 // change to ARP target mac address to Lookup result
922 arp_ptr
= (unsigned char *)(arp
+ 1);
923 arp_ptr
+= (arp
->ar_hln
+ arp
->ar_pln
);
924 memcpy(arp_ptr
, skb
->data
, ETH_ALEN
);
933 /*---------------------------------------------------*/
934 /* Handle IPX and Apple Talk frame */
935 /*---------------------------------------------------*/
936 else if((protocol
== __constant_htons(ETH_P_IPX
)) ||
937 (protocol
<= __constant_htons(ETH_FRAME_LEN
)))
939 unsigned char ipx_header
[2] = {0xFF, 0xFF};
940 struct ipxhdr
*ipx
= NULL
;
941 struct elapaarp
*ea
= NULL
;
942 struct ddpehdr
*ddp
= NULL
;
943 unsigned char *framePtr
= skb
->data
+ ETH_HLEN
;
945 if(protocol
== __constant_htons(ETH_P_IPX
))
947 DEBUG_INFO("NAT25: Protocol=IPX (Ethernet II)\n");
948 ipx
= (struct ipxhdr
*)framePtr
;
950 else if(protocol
<= __constant_htons(ETH_FRAME_LEN
))
952 if(!memcmp(ipx_header
, framePtr
, 2))
954 DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.3)\n");
955 ipx
= (struct ipxhdr
*)framePtr
;
959 unsigned char ipx_8022_type
= 0xE0;
960 unsigned char snap_8022_type
= 0xAA;
962 if(*framePtr
== snap_8022_type
)
964 unsigned char ipx_snap_id
[5] = {0x0, 0x0, 0x0, 0x81, 0x37}; // IPX SNAP ID
965 unsigned char aarp_snap_id
[5] = {0x00, 0x00, 0x00, 0x80, 0xF3}; // Apple Talk AARP SNAP ID
966 unsigned char ddp_snap_id
[5] = {0x08, 0x00, 0x07, 0x80, 0x9B}; // Apple Talk DDP SNAP ID
968 framePtr
+= 3; // eliminate the 802.2 header
970 if(!memcmp(ipx_snap_id
, framePtr
, 5))
972 framePtr
+= 5; // eliminate the SNAP header
974 DEBUG_INFO("NAT25: Protocol=IPX (Ethernet SNAP)\n");
975 ipx
= (struct ipxhdr
*)framePtr
;
977 else if(!memcmp(aarp_snap_id
, framePtr
, 5))
979 framePtr
+= 5; // eliminate the SNAP header
981 ea
= (struct elapaarp
*)framePtr
;
983 else if(!memcmp(ddp_snap_id
, framePtr
, 5))
985 framePtr
+= 5; // eliminate the SNAP header
987 ddp
= (struct ddpehdr
*)framePtr
;
991 DEBUG_WARN("NAT25: Protocol=Ethernet SNAP %02x%02x%02x%02x%02x\n", framePtr
[0],
992 framePtr
[1], framePtr
[2], framePtr
[3], framePtr
[4]);
996 else if(*framePtr
== ipx_8022_type
)
998 framePtr
+= 3; // eliminate the 802.2 header
1000 if(!memcmp(ipx_header
, framePtr
, 2))
1002 DEBUG_INFO("NAT25: Protocol=IPX (Ethernet 802.2)\n");
1003 ipx
= (struct ipxhdr
*)framePtr
;
1021 if(!memcmp(skb
->data
+ETH_ALEN
, ipx
->ipx_source
.node
, ETH_ALEN
))
1023 DEBUG_INFO("NAT25: Check IPX skb_copy\n");
1030 DEBUG_INFO("NAT25: Insert IPX, Dest=%08x,%02x%02x%02x%02x%02x%02x,%04x Source=%08x,%02x%02x%02x%02x%02x%02x,%04x\n",
1032 ipx
->ipx_dest
.node
[0],
1033 ipx
->ipx_dest
.node
[1],
1034 ipx
->ipx_dest
.node
[2],
1035 ipx
->ipx_dest
.node
[3],
1036 ipx
->ipx_dest
.node
[4],
1037 ipx
->ipx_dest
.node
[5],
1039 ipx
->ipx_source
.net
,
1040 ipx
->ipx_source
.node
[0],
1041 ipx
->ipx_source
.node
[1],
1042 ipx
->ipx_source
.node
[2],
1043 ipx
->ipx_source
.node
[3],
1044 ipx
->ipx_source
.node
[4],
1045 ipx
->ipx_source
.node
[5],
1046 ipx
->ipx_source
.sock
);
1048 if(!memcmp(skb
->data
+ETH_ALEN
, ipx
->ipx_source
.node
, ETH_ALEN
))
1050 DEBUG_INFO("NAT25: Use IPX Net, and Socket as network addr\n");
1052 __nat25_generate_ipx_network_addr_with_socket(networkAddr
, &ipx
->ipx_source
.net
, &ipx
->ipx_source
.sock
);
1054 // change IPX source node addr to wlan STA address
1055 memcpy(ipx
->ipx_source
.node
, GET_MY_HWADDR(priv
), ETH_ALEN
);
1059 __nat25_generate_ipx_network_addr_with_node(networkAddr
, &ipx
->ipx_source
.net
, ipx
->ipx_source
.node
);
1062 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
1064 __nat25_db_print(priv
);
1070 if(!memcmp(GET_MY_HWADDR(priv
), ipx
->ipx_dest
.node
, ETH_ALEN
))
1072 DEBUG_INFO("NAT25: Lookup IPX, Modify Destination IPX Node addr\n");
1074 __nat25_generate_ipx_network_addr_with_socket(networkAddr
, &ipx
->ipx_dest
.net
, &ipx
->ipx_dest
.sock
);
1076 __nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
);
1078 // replace IPX destination node addr with Lookup destination MAC addr
1079 memcpy(ipx
->ipx_dest
.node
, skb
->data
, ETH_ALEN
);
1083 __nat25_generate_ipx_network_addr_with_node(networkAddr
, &ipx
->ipx_dest
.net
, ipx
->ipx_dest
.node
);
1085 __nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
);
1098 /* Sanity check fields. */
1099 if(ea
->hw_len
!= ETH_ALEN
|| ea
->pa_len
!= AARP_PA_ALEN
)
1101 DEBUG_WARN("NAT25: Appletalk AARP Sanity check fail!\n");
1112 // change to AARP source mac address to wlan STA address
1113 memcpy(ea
->hw_src
, GET_MY_HWADDR(priv
), ETH_ALEN
);
1115 DEBUG_INFO("NAT25: Insert AARP, Source=%d,%d Destination=%d,%d\n",
1121 __nat25_generate_apple_network_addr(networkAddr
, &ea
->pa_src_net
, &ea
->pa_src_node
);
1123 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
1125 __nat25_db_print(priv
);
1131 DEBUG_INFO("NAT25: Lookup AARP, Source=%d,%d Destination=%d,%d\n",
1137 __nat25_generate_apple_network_addr(networkAddr
, &ea
->pa_dst_net
, &ea
->pa_dst_node
);
1139 __nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
);
1141 // change to AARP destination mac address to Lookup result
1142 memcpy(ea
->hw_dst
, skb
->data
, ETH_ALEN
);
1152 else if(ddp
!= NULL
)
1161 DEBUG_INFO("NAT25: Insert DDP, Source=%d,%d Destination=%d,%d\n",
1167 __nat25_generate_apple_network_addr(networkAddr
, &ddp
->deh_snet
, &ddp
->deh_snode
);
1169 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
1171 __nat25_db_print(priv
);
1177 DEBUG_INFO("NAT25: Lookup DDP, Source=%d,%d Destination=%d,%d\n",
1183 __nat25_generate_apple_network_addr(networkAddr
, &ddp
->deh_dnet
, &ddp
->deh_dnode
);
1185 __nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
);
1197 /*---------------------------------------------------*/
1198 /* Handle PPPoE frame */
1199 /*---------------------------------------------------*/
1200 else if((protocol
== __constant_htons(ETH_P_PPP_DISC
)) ||
1201 (protocol
== __constant_htons(ETH_P_PPP_SES
)))
1203 struct pppoe_hdr
*ph
= (struct pppoe_hdr
*)(skb
->data
+ ETH_HLEN
);
1204 unsigned short *pMagic
;
1214 if(ph
->sid
== 0) // Discovery phase according to tag
1216 if(ph
->code
== PADI_CODE
|| ph
->code
== PADR_CODE
)
1218 if (priv
->ethBrExtInfo
.addPPPoETag
) {
1219 struct pppoe_tag
*tag
, *pOldTag
;
1220 unsigned char tag_buf
[40];
1223 tag
= (struct pppoe_tag
*)tag_buf
;
1224 pOldTag
= (struct pppoe_tag
*)__nat25_find_pppoe_tag(ph
, ntohs(PTT_RELAY_SID
));
1225 if (pOldTag
) { // if SID existed, copy old value and delete it
1226 old_tag_len
= ntohs(pOldTag
->tag_len
);
1227 if (old_tag_len
+TAG_HDR_LEN
+MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
> sizeof(tag_buf
)) {
1228 DEBUG_ERR("SID tag length too long!\n");
1232 memcpy(tag
->tag_data
+MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
,
1233 pOldTag
->tag_data
, old_tag_len
);
1235 if (skb_pull_and_merge(skb
, (unsigned char *)pOldTag
, TAG_HDR_LEN
+old_tag_len
) < 0) {
1236 DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
1239 ph
->length
= htons(ntohs(ph
->length
)-TAG_HDR_LEN
-old_tag_len
);
1242 tag
->tag_type
= PTT_RELAY_SID
;
1243 tag
->tag_len
= htons(MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
+old_tag_len
);
1245 // insert the magic_code+client mac in relay tag
1246 pMagic
= (unsigned short *)tag
->tag_data
;
1247 *pMagic
= htons(MAGIC_CODE
);
1248 memcpy(tag
->tag_data
+MAGIC_CODE_LEN
, skb
->data
+ETH_ALEN
, ETH_ALEN
);
1251 if(__nat25_add_pppoe_tag(skb
, tag
) < 0)
1254 DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n",
1255 (ph
->code
== PADI_CODE
? "PADI" : "PADR"));
1257 else { // not add relay tag
1258 if (priv
->pppoe_connection_in_progress
&&
1259 memcmp(skb
->data
+ETH_ALEN
, priv
->pppoe_addr
, ETH_ALEN
)) {
1260 DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
1264 if (priv
->pppoe_connection_in_progress
== 0)
1265 memcpy(priv
->pppoe_addr
, skb
->data
+ETH_ALEN
, ETH_ALEN
);
1267 priv
->pppoe_connection_in_progress
= WAIT_TIME_PPPOE
;
1273 else // session phase
1275 DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb
->dev
->name
);
1277 __nat25_generate_pppoe_network_addr(networkAddr
, skb
->data
, &(ph
->sid
));
1279 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
1281 __nat25_db_print(priv
);
1283 if (!priv
->ethBrExtInfo
.addPPPoETag
&&
1284 priv
->pppoe_connection_in_progress
&&
1285 !memcmp(skb
->data
+ETH_ALEN
, priv
->pppoe_addr
, ETH_ALEN
))
1286 priv
->pppoe_connection_in_progress
= 0;
1291 if(ph
->code
== PADO_CODE
|| ph
->code
== PADS_CODE
)
1293 if (priv
->ethBrExtInfo
.addPPPoETag
) {
1294 struct pppoe_tag
*tag
;
1296 unsigned short tagType
, tagLen
;
1299 if((ptr
= __nat25_find_pppoe_tag(ph
, ntohs(PTT_RELAY_SID
))) == 0) {
1300 DEBUG_ERR("Fail to find PTT_RELAY_SID in FADO!\n");
1304 tag
= (struct pppoe_tag
*)ptr
;
1305 tagType
= (unsigned short)((ptr
[0] << 8) + ptr
[1]);
1306 tagLen
= (unsigned short)((ptr
[2] << 8) + ptr
[3]);
1308 if((tagType
!= ntohs(PTT_RELAY_SID
)) || (tagLen
< (MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
))) {
1309 DEBUG_ERR("Invalid PTT_RELAY_SID tag length [%d]!\n", tagLen
);
1313 pMagic
= (unsigned short *)tag
->tag_data
;
1314 if (ntohs(*pMagic
) != MAGIC_CODE
) {
1315 DEBUG_ERR("Can't find MAGIC_CODE in %s packet!\n",
1316 (ph
->code
== PADO_CODE
? "PADO" : "PADS"));
1320 memcpy(skb
->data
, tag
->tag_data
+MAGIC_CODE_LEN
, ETH_ALEN
);
1322 if (tagLen
> MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
)
1323 offset
= TAG_HDR_LEN
;
1325 if (skb_pull_and_merge(skb
, ptr
+offset
, TAG_HDR_LEN
+MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
-offset
) < 0) {
1326 DEBUG_ERR("call skb_pull_and_merge() failed in PADO packet!\n");
1329 ph
->length
= htons(ntohs(ph
->length
)-(TAG_HDR_LEN
+MAGIC_CODE_LEN
+RTL_RELAY_TAG_LEN
-offset
));
1331 tag
->tag_len
= htons(tagLen
-MAGIC_CODE_LEN
-RTL_RELAY_TAG_LEN
);
1333 DEBUG_INFO("NAT25: Lookup PPPoE, forward %s Packet from %s\n",
1334 (ph
->code
== PADO_CODE
? "PADO" : "PADS"), skb
->dev
->name
);
1336 else { // not add relay tag
1337 if (!priv
->pppoe_connection_in_progress
) {
1338 DEBUG_ERR("Discard PPPoE packet due to no connection in progresss!\n");
1341 memcpy(skb
->data
, priv
->pppoe_addr
, ETH_ALEN
);
1342 priv
->pppoe_connection_in_progress
= WAIT_TIME_PPPOE
;
1348 DEBUG_INFO("NAT25: Lookup PPPoE, lookup session packet from %s\n", skb
->dev
->name
);
1349 __nat25_generate_pppoe_network_addr(networkAddr
, skb
->data
+ETH_ALEN
, &(ph
->sid
));
1351 __nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
);
1353 __nat25_db_print(priv
);
1366 /*---------------------------------------------------*/
1367 /* Handle EAP frame */
1368 /*---------------------------------------------------*/
1369 else if(protocol
== __constant_htons(0x888e))
1387 /*---------------------------------------------------*/
1388 /* Handle C-Media proprietary frame */
1389 /*---------------------------------------------------*/
1390 else if((protocol
== __constant_htons(0xe2ae)) ||
1391 (protocol
== __constant_htons(0xe2af)))
1409 /*---------------------------------------------------*/
1410 /* Handle IPV6 frame */
1411 /*---------------------------------------------------*/
1413 else if(protocol
== __constant_htons(ETH_P_IPV6
))
1415 struct ipv6hdr
*iph
= (struct ipv6hdr
*)(skb
->data
+ ETH_HLEN
);
1417 if (sizeof(*iph
) >= (skb
->len
- ETH_HLEN
))
1419 DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
1426 if (skb
->data
[0] & 1)
1432 DEBUG_INFO("NAT25: Insert IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
1433 " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
1434 iph
->saddr
.s6_addr16
[0],iph
->saddr
.s6_addr16
[1],iph
->saddr
.s6_addr16
[2],iph
->saddr
.s6_addr16
[3],
1435 iph
->saddr
.s6_addr16
[4],iph
->saddr
.s6_addr16
[5],iph
->saddr
.s6_addr16
[6],iph
->saddr
.s6_addr16
[7],
1436 iph
->daddr
.s6_addr16
[0],iph
->daddr
.s6_addr16
[1],iph
->daddr
.s6_addr16
[2],iph
->daddr
.s6_addr16
[3],
1437 iph
->daddr
.s6_addr16
[4],iph
->daddr
.s6_addr16
[5],iph
->daddr
.s6_addr16
[6],iph
->daddr
.s6_addr16
[7]);
1439 if (memcmp(&iph
->saddr
, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
1440 __nat25_generate_ipv6_network_addr(networkAddr
, (unsigned int *)&iph
->saddr
);
1441 __nat25_db_network_insert(priv
, skb
->data
+ETH_ALEN
, networkAddr
);
1442 __nat25_db_print(priv
);
1444 if (iph
->nexthdr
== IPPROTO_ICMPV6
&&
1445 skb
->len
> (ETH_HLEN
+ sizeof(*iph
) + 4)) {
1446 if (update_nd_link_layer_addr(skb
->data
+ ETH_HLEN
+ sizeof(*iph
),
1447 skb
->len
- ETH_HLEN
- sizeof(*iph
), GET_MY_HWADDR(priv
))) {
1448 struct icmp6hdr
*hdr
= (struct icmp6hdr
*)(skb
->data
+ ETH_HLEN
+ sizeof(*iph
));
1449 hdr
->icmp6_cksum
= 0;
1450 hdr
->icmp6_cksum
= csum_ipv6_magic(&iph
->saddr
, &iph
->daddr
,
1453 csum_partial((__u8
*)hdr
, iph
->payload_len
, 0));
1461 DEBUG_INFO("NAT25: Lookup IP, SA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
1462 " DA=%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
1463 iph
->saddr
.s6_addr16
[0],iph
->saddr
.s6_addr16
[1],iph
->saddr
.s6_addr16
[2],iph
->saddr
.s6_addr16
[3],
1464 iph
->saddr
.s6_addr16
[4],iph
->saddr
.s6_addr16
[5],iph
->saddr
.s6_addr16
[6],iph
->saddr
.s6_addr16
[7],
1465 iph
->daddr
.s6_addr16
[0],iph
->daddr
.s6_addr16
[1],iph
->daddr
.s6_addr16
[2],iph
->daddr
.s6_addr16
[3],
1466 iph
->daddr
.s6_addr16
[4],iph
->daddr
.s6_addr16
[5],iph
->daddr
.s6_addr16
[6],iph
->daddr
.s6_addr16
[7]);
1469 __nat25_generate_ipv6_network_addr(networkAddr
, (unsigned int *)&iph
->daddr
);
1470 if (!__nat25_db_network_lookup_and_replace(priv
, skb
, networkAddr
)) {
1471 #ifdef SUPPORT_RX_UNI2MCAST
1472 if (iph
->daddr
.s6_addr
[0] == 0xff)
1473 convert_ipv6_mac_to_mc(skb
);
1482 #endif // CL_IPV6_PASS
1488 int nat25_handle_frame(_adapter
*priv
, struct sk_buff
*skb
)
1491 if((!priv
->ethBrExtInfo
.nat25_disable
) && (!(skb
->data
[0] & 1)))
1493 panic_printk("NAT25: Input Frame: DA=%02x%02x%02x%02x%02x%02x SA=%02x%02x%02x%02x%02x%02x\n",
1509 if(!(skb
->data
[0] & 1))
1511 int is_vlan_tag
=0, i
, retval
=0;
1512 unsigned short vlan_hdr
=0;
1514 if (*((unsigned short *)(skb
->data
+ETH_ALEN
*2)) == __constant_htons(ETH_P_8021Q
)) {
1516 vlan_hdr
= *((unsigned short *)(skb
->data
+ETH_ALEN
*2+2));
1518 *((unsigned short *)(skb
->data
+ETH_ALEN
*2+2-i
*2)) = *((unsigned short *)(skb
->data
+ETH_ALEN
*2-2-i
*2));
1522 if (!priv
->ethBrExtInfo
.nat25_disable
)
1525 _enter_critical_bh(&priv
->br_ext_lock
, &irqL
);
1527 * This function look up the destination network address from
1528 * the NAT2.5 database. Return value = -1 means that the
1529 * corresponding network protocol is NOT support.
1531 if (!priv
->ethBrExtInfo
.nat25sc_disable
&&
1532 (*((unsigned short *)(skb
->data
+ETH_ALEN
*2)) == __constant_htons(ETH_P_IP
)) &&
1533 !memcmp(priv
->scdb_ip
, skb
->data
+ETH_HLEN
+16, 4)) {
1534 memcpy(skb
->data
, priv
->scdb_mac
, ETH_ALEN
);
1536 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
1539 _exit_critical_bh(&priv
->br_ext_lock
, &irqL
);
1541 retval
= nat25_db_handle(priv
, skb
, NAT25_LOOKUP
);
1545 if (((*((unsigned short *)(skb
->data
+ETH_ALEN
*2)) == __constant_htons(ETH_P_IP
)) &&
1546 !memcmp(priv
->br_ip
, skb
->data
+ETH_HLEN
+16, 4)) ||
1547 ((*((unsigned short *)(skb
->data
+ETH_ALEN
*2)) == __constant_htons(ETH_P_ARP
)) &&
1548 !memcmp(priv
->br_ip
, skb
->data
+ETH_HLEN
+24, 4))) {
1549 // for traffic to upper TCP/IP
1550 retval
= nat25_db_handle(priv
, skb
, NAT25_LOOKUP
);
1557 *((unsigned short *)(skb
->data
+i
*2)) = *((unsigned short *)(skb
->data
+4+i
*2));
1558 *((unsigned short *)(skb
->data
+ETH_ALEN
*2)) = __constant_htons(ETH_P_8021Q
);
1559 *((unsigned short *)(skb
->data
+ETH_ALEN
*2+2)) = vlan_hdr
;
1563 //DEBUG_ERR("NAT25: Lookup fail!\n");
1572 void mac_clone(_adapter
*priv
, unsigned char *addr
)
1576 memcpy(sa
.sa_data
, addr
, ETH_ALEN
);
1577 DEBUG_INFO("MAC Clone: Addr=%02x%02x%02x%02x%02x%02x\n",
1578 addr
[0], addr
[1], addr
[2], addr
[3], addr
[4], addr
[5]);
1579 rtl8192cd_set_hwaddr(priv
->dev
, &sa
);
1583 int mac_clone_handle_frame(_adapter
*priv
, struct sk_buff
*skb
)
1585 if(priv
->ethBrExtInfo
.macclone_enable
&& !priv
->macclone_completed
)
1587 if(!(skb
->data
[ETH_ALEN
] & 1)) //// check any other particular MAC add
1589 if(memcmp(skb
->data
+ETH_ALEN
, GET_MY_HWADDR(priv
), ETH_ALEN
) &&
1590 ((priv
->dev
->br_port
) &&
1591 memcmp(skb
->data
+ETH_ALEN
, priv
->br_mac
, ETH_ALEN
)))
1593 mac_clone(priv
, skb
->data
+ETH_ALEN
);
1594 priv
->macclone_completed
= 1;
1603 #define SERVER_PORT 67
1604 #define CLIENT_PORT 68
1605 #define DHCP_MAGIC 0x63825363
1606 #define BROADCAST_FLAG 0x8000
1608 struct dhcpMessage
{
1620 u_int8_t chaddr
[16];
1624 u_int8_t options
[308]; /* 312 - cookie */
1627 void dhcp_flag_bcast(_adapter
*priv
, struct sk_buff
*skb
)
1632 if(!priv
->ethBrExtInfo
.dhcp_bcst_disable
)
1634 unsigned short protocol
= *((unsigned short *)(skb
->data
+ 2 * ETH_ALEN
));
1636 if(protocol
== __constant_htons(ETH_P_IP
)) // IP
1638 struct iphdr
* iph
= (struct iphdr
*)(skb
->data
+ ETH_HLEN
);
1640 if(iph
->protocol
== IPPROTO_UDP
) // UDP
1642 struct udphdr
*udph
= (struct udphdr
*)((SIZE_PTR
)iph
+ (iph
->ihl
<< 2));
1644 if((udph
->source
== __constant_htons(CLIENT_PORT
))
1645 && (udph
->dest
== __constant_htons(SERVER_PORT
))) // DHCP request
1647 struct dhcpMessage
*dhcph
=
1648 (struct dhcpMessage
*)((SIZE_PTR
)udph
+ sizeof(struct udphdr
));
1650 if(dhcph
->cookie
== __constant_htonl(DHCP_MAGIC
)) // match magic word
1652 if(!(dhcph
->flags
& htons(BROADCAST_FLAG
))) // if not broadcast
1654 register int sum
= 0;
1656 DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n");
1657 // or BROADCAST flag
1658 dhcph
->flags
|= htons(BROADCAST_FLAG
);
1659 // recalculate checksum
1660 sum
= ~(udph
->check
) & 0xffff;
1661 sum
+= dhcph
->flags
;
1663 sum
= (sum
& 0xffff) + (sum
>> 16);
1674 void *scdb_findEntry(_adapter
*priv
, unsigned char *macAddr
,
1675 unsigned char *ipAddr
)
1677 unsigned char networkAddr
[MAX_NETWORK_ADDR_LEN
];
1678 struct nat25_network_db_entry
*db
;
1681 //_enter_critical_bh(&priv->br_ext_lock, &irqL);
1683 __nat25_generate_ipv4_network_addr(networkAddr
, (unsigned int *)ipAddr
);
1684 hash
= __nat25_network_hash(networkAddr
);
1685 db
= priv
->nethash
[hash
];
1688 if(!memcmp(db
->networkAddr
, networkAddr
, MAX_NETWORK_ADDR_LEN
)) {
1689 //_exit_critical_bh(&priv->br_ext_lock, &irqL);
1696 //_exit_critical_bh(&priv->br_ext_lock, &irqL);
1700 #endif // CONFIG_BR_EXT