1
2
3
4#define _RTW_BR_EXT_C_
5
6#include "../include/linux/if_arp.h"
7#include "../include/net/ip.h"
8#include "../include/linux/atalk.h"
9#include "../include/linux/udp.h"
10#include "../include/linux/if_pppox.h"
11
12#include "../include/drv_types.h"
13#include "../include/rtw_br_ext.h"
14#include "../include/usb_osintf.h"
15#include "../include/recv_osdep.h"
16
17#ifndef csum_ipv6_magic
18#include "../include/net/ip6_checksum.h"
19#endif
20
21#include "../include/linux/ipv6.h"
22#include "../include/linux/icmpv6.h"
23#include "../include/net/ndisc.h"
24#include "../include/net/checksum.h"
25
26#define NAT25_IPV4 01
27#define NAT25_IPV6 02
28#define NAT25_IPX 03
29#define NAT25_APPLE 04
30#define NAT25_PPPOE 05
31
32#define RTL_RELAY_TAG_LEN (ETH_ALEN)
33#define TAG_HDR_LEN 4
34
35#define MAGIC_CODE 0x8186
36#define MAGIC_CODE_LEN 2
37#define WAIT_TIME_PPPOE 5
38
39
40
41
42
43
44
45
46
47
48
49
50
51static unsigned char *__nat25_find_pppoe_tag(struct pppoe_hdr *ph, unsigned short type)
52{
53 unsigned char *cur_ptr, *start_ptr;
54 unsigned short tagLen, tagType;
55
56 start_ptr = cur_ptr = (unsigned char *)ph->tag;
57 while ((cur_ptr - start_ptr) < ntohs(ph->length)) {
58
59 tagType = (unsigned short)((cur_ptr[0] << 8) + cur_ptr[1]);
60 tagLen = (unsigned short)((cur_ptr[2] << 8) + cur_ptr[3]);
61 if (tagType == type)
62 return cur_ptr;
63 cur_ptr = cur_ptr + TAG_HDR_LEN + tagLen;
64 }
65 return NULL;
66}
67
68static int __nat25_add_pppoe_tag(struct sk_buff *skb, struct pppoe_tag *tag)
69{
70 struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
71 int data_len;
72
73 data_len = tag->tag_len + TAG_HDR_LEN;
74 if (skb_tailroom(skb) < data_len) {
75 _DEBUG_ERR("skb_tailroom() failed in add SID tag!\n");
76 return -1;
77 }
78
79 skb_put(skb, data_len);
80
81 memmove(((unsigned char *)ph->tag + data_len), (unsigned char *)ph->tag, ntohs(ph->length));
82 ph->length = htons(ntohs(ph->length) + data_len);
83 memcpy((unsigned char *)ph->tag, tag, data_len);
84 return data_len;
85}
86
87static int skb_pull_and_merge(struct sk_buff *skb, unsigned char *src, int len)
88{
89 int tail_len;
90 unsigned long end, tail;
91
92 if ((src+len) > skb_tail_pointer(skb) || skb->len < len)
93 return -1;
94
95 tail = (unsigned long)skb_tail_pointer(skb);
96 end = (unsigned long)src+len;
97 if (tail < end)
98 return -1;
99
100 tail_len = (int)(tail-end);
101 if (tail_len > 0)
102 memmove(src, src+len, tail_len);
103
104 skb_trim(skb, skb->len-len);
105 return 0;
106}
107
108static unsigned long __nat25_timeout(struct adapter *priv)
109{
110 unsigned long timeout;
111
112 timeout = jiffies - NAT25_AGEING_TIME*HZ;
113
114 return timeout;
115}
116
117static int __nat25_has_expired(struct adapter *priv,
118 struct nat25_network_db_entry *fdb)
119{
120 if (time_before_eq(fdb->ageing_timer, __nat25_timeout(priv)))
121 return 1;
122
123 return 0;
124}
125
126static void __nat25_generate_ipv4_network_addr(unsigned char *networkAddr,
127 unsigned int *ipAddr)
128{
129 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
130
131 networkAddr[0] = NAT25_IPV4;
132 memcpy(networkAddr+7, (unsigned char *)ipAddr, 4);
133}
134
135static void __nat25_generate_pppoe_network_addr(unsigned char *networkAddr,
136 unsigned char *ac_mac, __be16 *sid)
137{
138 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
139
140 networkAddr[0] = NAT25_PPPOE;
141 memcpy(networkAddr+1, (unsigned char *)sid, 2);
142 memcpy(networkAddr+3, (unsigned char *)ac_mac, 6);
143}
144
145static void __nat25_generate_ipv6_network_addr(unsigned char *networkAddr,
146 unsigned int *ipAddr)
147{
148 memset(networkAddr, 0, MAX_NETWORK_ADDR_LEN);
149
150 networkAddr[0] = NAT25_IPV6;
151 memcpy(networkAddr+1, (unsigned char *)ipAddr, 16);
152}
153
154static unsigned char *scan_tlv(unsigned char *data, int len, unsigned char tag, unsigned char len8b)
155{
156 while (len > 0) {
157 if (*data == tag && *(data+1) == len8b && len >= len8b*8)
158 return data+2;
159
160 len -= (*(data+1))*8;
161 data += (*(data+1))*8;
162 }
163 return NULL;
164}
165
166static int update_nd_link_layer_addr(unsigned char *data, int len, unsigned char *replace_mac)
167{
168 struct icmp6hdr *icmphdr = (struct icmp6hdr *)data;
169 unsigned char *mac;
170
171 if (icmphdr->icmp6_type == NDISC_ROUTER_SOLICITATION) {
172 if (len >= 8) {
173 mac = scan_tlv(&data[8], len-8, 1, 1);
174 if (mac) {
175 _DEBUG_INFO("Router Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
176 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
177 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
178 memcpy(mac, replace_mac, 6);
179 return 1;
180 }
181 }
182 } else if (icmphdr->icmp6_type == NDISC_ROUTER_ADVERTISEMENT) {
183 if (len >= 16) {
184 mac = scan_tlv(&data[16], len-16, 1, 1);
185 if (mac) {
186 _DEBUG_INFO("Router Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
187 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
188 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
189 memcpy(mac, replace_mac, 6);
190 return 1;
191 }
192 }
193 } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_SOLICITATION) {
194 if (len >= 24) {
195 mac = scan_tlv(&data[24], len-24, 1, 1);
196 if (mac) {
197 _DEBUG_INFO("Neighbor Solicitation, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
198 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
199 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
200 memcpy(mac, replace_mac, 6);
201 return 1;
202 }
203 }
204 } else if (icmphdr->icmp6_type == NDISC_NEIGHBOUR_ADVERTISEMENT) {
205 if (len >= 24) {
206 mac = scan_tlv(&data[24], len-24, 2, 1);
207 if (mac) {
208 _DEBUG_INFO("Neighbor Advertisement, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
209 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
210 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
211 memcpy(mac, replace_mac, 6);
212 return 1;
213 }
214 }
215 } else if (icmphdr->icmp6_type == NDISC_REDIRECT) {
216 if (len >= 40) {
217 mac = scan_tlv(&data[40], len-40, 2, 1);
218 if (mac) {
219 _DEBUG_INFO("Redirect, replace MAC From: %02x:%02x:%02x:%02x:%02x:%02x, To: %02x:%02x:%02x:%02x:%02x:%02x\n",
220 mac[0], mac[1], mac[2], mac[3], mac[4], mac[5],
221 replace_mac[0], replace_mac[1], replace_mac[2], replace_mac[3], replace_mac[4], replace_mac[5]);
222 memcpy(mac, replace_mac, 6);
223 return 1;
224 }
225 }
226 }
227 return 0;
228}
229
230static int __nat25_network_hash(unsigned char *networkAddr)
231{
232 if (networkAddr[0] == NAT25_IPV4) {
233 unsigned long x;
234
235 x = networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
236
237 return x & (NAT25_HASH_SIZE - 1);
238 } else if (networkAddr[0] == NAT25_IPX) {
239 unsigned long x;
240
241 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
242 networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10];
243
244 return x & (NAT25_HASH_SIZE - 1);
245 } else if (networkAddr[0] == NAT25_APPLE) {
246 unsigned long x;
247
248 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3];
249
250 return x & (NAT25_HASH_SIZE - 1);
251 } else if (networkAddr[0] == NAT25_PPPOE) {
252 unsigned long x;
253
254 x = networkAddr[0] ^ networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^ networkAddr[6] ^ networkAddr[7] ^ networkAddr[8];
255
256 return x & (NAT25_HASH_SIZE - 1);
257 } else if (networkAddr[0] == NAT25_IPV6) {
258 unsigned long x;
259
260 x = networkAddr[1] ^ networkAddr[2] ^ networkAddr[3] ^ networkAddr[4] ^ networkAddr[5] ^
261 networkAddr[6] ^ networkAddr[7] ^ networkAddr[8] ^ networkAddr[9] ^ networkAddr[10] ^
262 networkAddr[11] ^ networkAddr[12] ^ networkAddr[13] ^ networkAddr[14] ^ networkAddr[15] ^
263 networkAddr[16];
264
265 return x & (NAT25_HASH_SIZE - 1);
266 } else {
267 unsigned long x = 0;
268 int i;
269
270 for (i = 0; i < MAX_NETWORK_ADDR_LEN; i++)
271 x ^= networkAddr[i];
272
273 return x & (NAT25_HASH_SIZE - 1);
274 }
275}
276
277static void __network_hash_link(struct adapter *priv,
278 struct nat25_network_db_entry *ent, int hash)
279{
280
281 ent->next_hash = priv->nethash[hash];
282 if (ent->next_hash)
283 ent->next_hash->pprev_hash = &ent->next_hash;
284 priv->nethash[hash] = ent;
285 ent->pprev_hash = &priv->nethash[hash];
286}
287
288static void __network_hash_unlink(struct nat25_network_db_entry *ent)
289{
290
291 *ent->pprev_hash = ent->next_hash;
292 if (ent->next_hash)
293 ent->next_hash->pprev_hash = ent->pprev_hash;
294 ent->next_hash = NULL;
295 ent->pprev_hash = NULL;
296}
297
298static void __nat25_db_network_insert(struct adapter *priv,
299 unsigned char *macAddr, unsigned char *networkAddr)
300{
301 struct nat25_network_db_entry *db;
302 int hash;
303
304 spin_lock_bh(&priv->br_ext_lock);
305 hash = __nat25_network_hash(networkAddr);
306 db = priv->nethash[hash];
307 while (db) {
308 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
309 memcpy(db->macAddr, macAddr, ETH_ALEN);
310 db->ageing_timer = jiffies;
311 spin_unlock_bh(&priv->br_ext_lock);
312 return;
313 }
314 db = db->next_hash;
315 }
316 db = kmalloc(sizeof(*db), GFP_ATOMIC);
317 if (!db) {
318 spin_unlock_bh(&priv->br_ext_lock);
319 return;
320 }
321 memcpy(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN);
322 memcpy(db->macAddr, macAddr, ETH_ALEN);
323 atomic_set(&db->use_count, 1);
324 db->ageing_timer = jiffies;
325
326 __network_hash_link(priv, db, hash);
327
328 spin_unlock_bh(&priv->br_ext_lock);
329}
330
331static void __nat25_db_print(struct adapter *priv)
332{
333}
334
335
336
337
338
339void nat25_db_cleanup(struct adapter *priv)
340{
341 int i;
342
343 spin_lock_bh(&priv->br_ext_lock);
344
345 for (i = 0; i < NAT25_HASH_SIZE; i++) {
346 struct nat25_network_db_entry *f;
347 f = priv->nethash[i];
348 while (f) {
349 struct nat25_network_db_entry *g;
350
351 g = f->next_hash;
352 if (priv->scdb_entry == f) {
353 memset(priv->scdb_mac, 0, ETH_ALEN);
354 memset(priv->scdb_ip, 0, 4);
355 priv->scdb_entry = NULL;
356 }
357 __network_hash_unlink(f);
358 kfree(f);
359 f = g;
360 }
361 }
362 spin_unlock_bh(&priv->br_ext_lock);
363}
364
365void nat25_db_expire(struct adapter *priv)
366{
367 int i;
368
369 spin_lock_bh(&priv->br_ext_lock);
370
371 for (i = 0; i < NAT25_HASH_SIZE; i++) {
372 struct nat25_network_db_entry *f;
373 f = priv->nethash[i];
374
375 while (f) {
376 struct nat25_network_db_entry *g;
377 g = f->next_hash;
378
379 if (__nat25_has_expired(priv, f)) {
380 if (atomic_dec_and_test(&f->use_count)) {
381 if (priv->scdb_entry == f) {
382 memset(priv->scdb_mac, 0, ETH_ALEN);
383 memset(priv->scdb_ip, 0, 4);
384 priv->scdb_entry = NULL;
385 }
386 __network_hash_unlink(f);
387 kfree(f);
388 }
389 }
390 f = g;
391 }
392 }
393 spin_unlock_bh(&priv->br_ext_lock);
394}
395
396int nat25_db_handle(struct adapter *priv, struct sk_buff *skb, int method)
397{
398 unsigned short protocol;
399 unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
400 unsigned int tmp;
401
402 if (!skb)
403 return -1;
404
405 if ((method <= NAT25_MIN) || (method >= NAT25_MAX))
406 return -1;
407
408 protocol = be16_to_cpu(*((__be16 *)(skb->data + 2 * ETH_ALEN)));
409
410
411
412
413 if (protocol == ETH_P_IP) {
414 struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
415
416 if (((unsigned char *)(iph) + (iph->ihl<<2)) >= (skb->data + ETH_HLEN + skb->len)) {
417 DEBUG_WARN("NAT25: malformed IP packet !\n");
418 return -1;
419 }
420
421 switch (method) {
422 case NAT25_CHECK:
423 return -1;
424 case NAT25_INSERT:
425
426
427 if (iph->saddr == 0)
428 return 0;
429 tmp = be32_to_cpu(iph->saddr);
430 DEBUG_INFO("NAT25: Insert IP, SA =%08x, DA =%08x\n", tmp, iph->daddr);
431 __nat25_generate_ipv4_network_addr(networkAddr, &tmp);
432
433 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
434
435 __nat25_db_print(priv);
436 return 0;
437 default:
438 return -1;
439 }
440 } else if (protocol == ETH_P_ARP) {
441
442
443
444 struct arphdr *arp = (struct arphdr *)(skb->data + ETH_HLEN);
445 unsigned char *arp_ptr = (unsigned char *)(arp + 1);
446 unsigned int *sender;
447
448 if (arp->ar_pro != __constant_htons(ETH_P_IP)) {
449 DEBUG_WARN("NAT25: arp protocol unknown (%4x)!\n", be16_to_cpu(arp->ar_pro));
450 return -1;
451 }
452
453 switch (method) {
454 case NAT25_CHECK:
455 return 0;
456 case NAT25_INSERT:
457 DEBUG_INFO("NAT25: Insert ARP, MAC =%02x%02x%02x%02x%02x%02x\n", arp_ptr[0],
458 arp_ptr[1], arp_ptr[2], arp_ptr[3], arp_ptr[4], arp_ptr[5]);
459
460
461 memcpy(arp_ptr, GET_MY_HWADDR(priv), ETH_ALEN);
462 arp_ptr += arp->ar_hln;
463 sender = (unsigned int *)arp_ptr;
464 __nat25_generate_ipv4_network_addr(networkAddr, sender);
465 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
466 __nat25_db_print(priv);
467 return 0;
468 default:
469 return -1;
470 }
471 } else if ((protocol == ETH_P_PPP_DISC) ||
472 (protocol == ETH_P_PPP_SES)) {
473
474
475
476 struct pppoe_hdr *ph = (struct pppoe_hdr *)(skb->data + ETH_HLEN);
477 unsigned short *pMagic;
478
479 switch (method) {
480 case NAT25_CHECK:
481 if (ph->sid == 0)
482 return 0;
483 return 1;
484 case NAT25_INSERT:
485 if (ph->sid == 0) {
486 if (ph->code == PADI_CODE || ph->code == PADR_CODE) {
487 if (priv->ethBrExtInfo.addPPPoETag) {
488 struct pppoe_tag *tag, *pOldTag;
489 unsigned char tag_buf[40];
490 int old_tag_len = 0;
491
492 tag = (struct pppoe_tag *)tag_buf;
493 pOldTag = (struct pppoe_tag *)__nat25_find_pppoe_tag(ph, ntohs(PTT_RELAY_SID));
494 if (pOldTag) {
495 old_tag_len = ntohs(pOldTag->tag_len);
496 if (old_tag_len+TAG_HDR_LEN+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN > sizeof(tag_buf)) {
497 DEBUG_ERR("SID tag length too long!\n");
498 return -1;
499 }
500
501 memcpy(tag->tag_data+MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN,
502 pOldTag->tag_data, old_tag_len);
503
504 if (skb_pull_and_merge(skb, (unsigned char *)pOldTag, TAG_HDR_LEN+old_tag_len) < 0) {
505 DEBUG_ERR("call skb_pull_and_merge() failed in PADI/R packet!\n");
506 return -1;
507 }
508 ph->length = htons(ntohs(ph->length)-TAG_HDR_LEN-old_tag_len);
509 }
510
511 tag->tag_type = PTT_RELAY_SID;
512 tag->tag_len = htons(MAGIC_CODE_LEN+RTL_RELAY_TAG_LEN+old_tag_len);
513
514
515 pMagic = (unsigned short *)tag->tag_data;
516 *pMagic = htons(MAGIC_CODE);
517 memcpy(tag->tag_data+MAGIC_CODE_LEN, skb->data+ETH_ALEN, ETH_ALEN);
518
519
520 if (__nat25_add_pppoe_tag(skb, tag) < 0)
521 return -1;
522
523 DEBUG_INFO("NAT25: Insert PPPoE, forward %s packet\n",
524 (ph->code == PADI_CODE ? "PADI" : "PADR"));
525 } else {
526 if (priv->pppoe_connection_in_progress &&
527 memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN)) {
528 DEBUG_ERR("Discard PPPoE packet due to another PPPoE connection is in progress!\n");
529 return -2;
530 }
531
532 if (priv->pppoe_connection_in_progress == 0)
533 memcpy(priv->pppoe_addr, skb->data+ETH_ALEN, ETH_ALEN);
534
535 priv->pppoe_connection_in_progress = WAIT_TIME_PPPOE;
536 }
537 } else {
538 return -1;
539 }
540 } else {
541 DEBUG_INFO("NAT25: Insert PPPoE, insert session packet to %s\n", skb->dev->name);
542
543 __nat25_generate_pppoe_network_addr(networkAddr, skb->data, &ph->sid);
544
545 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
546
547 __nat25_db_print(priv);
548
549 if (!priv->ethBrExtInfo.addPPPoETag &&
550 priv->pppoe_connection_in_progress &&
551 !memcmp(skb->data+ETH_ALEN, priv->pppoe_addr, ETH_ALEN))
552 priv->pppoe_connection_in_progress = 0;
553 }
554 return 0;
555 default:
556 return -1;
557 }
558 } else if (protocol == 0x888e) {
559
560
561
562 switch (method) {
563 case NAT25_CHECK:
564 return -1;
565 case NAT25_INSERT:
566 return 0;
567 default:
568 return -1;
569 }
570 } else if ((protocol == 0xe2ae) || (protocol == 0xe2af)) {
571
572
573
574 switch (method) {
575 case NAT25_CHECK:
576 return -1;
577 case NAT25_INSERT:
578 return 0;
579 default:
580 return -1;
581 }
582 } else if (protocol == ETH_P_IPV6) {
583
584
585
586 struct ipv6hdr *iph = (struct ipv6hdr *)(skb->data + ETH_HLEN);
587
588 if (sizeof(*iph) >= (skb->len - ETH_HLEN)) {
589 DEBUG_WARN("NAT25: malformed IPv6 packet !\n");
590 return -1;
591 }
592
593 switch (method) {
594 case NAT25_CHECK:
595 if (skb->data[0] & 1)
596 return 0;
597 return -1;
598 case NAT25_INSERT:
599 DEBUG_INFO("NAT25: Insert IP, SA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x,"
600 " DA =%4x:%4x:%4x:%4x:%4x:%4x:%4x:%4x\n",
601 iph->saddr.s6_addr16[0], iph->saddr.s6_addr16[1], iph->saddr.s6_addr16[2], iph->saddr.s6_addr16[3],
602 iph->saddr.s6_addr16[4], iph->saddr.s6_addr16[5], iph->saddr.s6_addr16[6], iph->saddr.s6_addr16[7],
603 iph->daddr.s6_addr16[0], iph->daddr.s6_addr16[1], iph->daddr.s6_addr16[2], iph->daddr.s6_addr16[3],
604 iph->daddr.s6_addr16[4], iph->daddr.s6_addr16[5], iph->daddr.s6_addr16[6], iph->daddr.s6_addr16[7]);
605
606 if (memcmp(&iph->saddr, "\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0\x0", 16)) {
607 __nat25_generate_ipv6_network_addr(networkAddr, (unsigned int *)&iph->saddr);
608 __nat25_db_network_insert(priv, skb->data+ETH_ALEN, networkAddr);
609 __nat25_db_print(priv);
610
611 if (iph->nexthdr == IPPROTO_ICMPV6 &&
612 skb->len > (ETH_HLEN + sizeof(*iph) + 4)) {
613 if (update_nd_link_layer_addr(skb->data + ETH_HLEN + sizeof(*iph),
614 skb->len - ETH_HLEN - sizeof(*iph), GET_MY_HWADDR(priv))) {
615 struct icmp6hdr *hdr = (struct icmp6hdr *)(skb->data + ETH_HLEN + sizeof(*iph));
616 hdr->icmp6_cksum = 0;
617 hdr->icmp6_cksum = csum_ipv6_magic(&iph->saddr, &iph->daddr,
618 iph->payload_len,
619 IPPROTO_ICMPV6,
620 csum_partial((__u8 *)hdr, iph->payload_len, 0));
621 }
622 }
623 }
624 return 0;
625 default:
626 return -1;
627 }
628 }
629 return -1;
630}
631
632#define SERVER_PORT 67
633#define CLIENT_PORT 68
634#define DHCP_MAGIC 0x63825363
635#define BROADCAST_FLAG 0x8000
636
637struct dhcpMessage {
638 u_int8_t op;
639 u_int8_t htype;
640 u_int8_t hlen;
641 u_int8_t hops;
642 u_int32_t xid;
643 __be16 secs;
644 __be16 flags;
645 __be32 ciaddr;
646 __be32 yiaddr;
647 __be32 siaddr;
648 __be32 giaddr;
649 u_int8_t chaddr[16];
650 u_int8_t sname[64];
651 u_int8_t file[128];
652 __be32 cookie;
653 u_int8_t options[308];
654};
655
656void dhcp_flag_bcast(struct adapter *priv, struct sk_buff *skb)
657{
658 if (!skb)
659 return;
660
661 if (!priv->ethBrExtInfo.dhcp_bcst_disable) {
662 __be16 protocol = *((__be16 *)(skb->data + 2 * ETH_ALEN));
663
664 if (protocol == __constant_htons(ETH_P_IP)) {
665 struct iphdr *iph = (struct iphdr *)(skb->data + ETH_HLEN);
666
667 if (iph->protocol == IPPROTO_UDP) {
668 struct udphdr *udph = (struct udphdr *)((size_t)iph + (iph->ihl << 2));
669
670 if ((udph->source == __constant_htons(CLIENT_PORT)) &&
671 (udph->dest == __constant_htons(SERVER_PORT))) {
672 struct dhcpMessage *dhcph =
673 (struct dhcpMessage *)((size_t)udph + sizeof(struct udphdr));
674 u32 cookie = be32_to_cpu((__be32)dhcph->cookie);
675
676 if (cookie == DHCP_MAGIC) {
677 if (!(dhcph->flags & htons(BROADCAST_FLAG))) {
678
679 register int sum = 0;
680
681 DEBUG_INFO("DHCP: change flag of DHCP request to broadcast.\n");
682
683 dhcph->flags |= htons(BROADCAST_FLAG);
684
685 sum = ~(udph->check) & 0xffff;
686 sum += be16_to_cpu(dhcph->flags);
687 while (sum >> 16)
688 sum = (sum & 0xffff) + (sum >> 16);
689 udph->check = ~sum;
690 }
691 }
692 }
693 }
694 }
695 }
696}
697
698void *scdb_findEntry(struct adapter *priv, unsigned char *macAddr,
699 unsigned char *ipAddr)
700{
701 unsigned char networkAddr[MAX_NETWORK_ADDR_LEN];
702 struct nat25_network_db_entry *db;
703 int hash;
704
705 __nat25_generate_ipv4_network_addr(networkAddr, (unsigned int *)ipAddr);
706 hash = __nat25_network_hash(networkAddr);
707 db = priv->nethash[hash];
708 while (db) {
709 if (!memcmp(db->networkAddr, networkAddr, MAX_NETWORK_ADDR_LEN)) {
710 return (void *)db;
711 }
712
713 db = db->next_hash;
714 }
715
716 return NULL;
717}
718