mirror of
https://github.com/LiBwrt/nss-packages.git
synced 2025-12-16 17:15:09 +00:00
170 lines
5.7 KiB
Diff
170 lines
5.7 KiB
Diff
--- a/map/map-t/nss_connmgr_map_t.c
|
|
+++ b/map/map-t/nss_connmgr_map_t.c
|
|
@@ -531,7 +531,7 @@ static void nss_connmgr_map_t_decap_exce
|
|
/*
|
|
* nss_connmgr_map_t_encap_exception()
|
|
* Exception handler registered to NSS for handling map_t ipv4 pkts
|
|
- * Translates ipv4 packet back to ipv6 and send to nat46 device directly.
|
|
+ * Send the translated ipv4 packets to the stack directly.
|
|
*/
|
|
static void nss_connmgr_map_t_encap_exception(struct net_device *dev,
|
|
struct sk_buff *skb,
|
|
@@ -539,23 +539,7 @@ static void nss_connmgr_map_t_encap_exce
|
|
|
|
{
|
|
struct iphdr *ip4_hdr;
|
|
- struct ipv6hdr *ip6_hdr;
|
|
- uint8_t v6saddr[16], v6daddr[16];
|
|
- struct tcphdr *tcph = NULL;
|
|
- struct udphdr *udph = NULL;
|
|
- struct iphdr ip4_hdr_r;
|
|
- __be16 sport, dport;
|
|
- uint8_t nexthdr, hop_limit, tos;
|
|
- int payload_len;
|
|
- bool df_bit = false;
|
|
- uint16_t append_hdr_sz = 0;
|
|
- uint16_t identifier;
|
|
- uint32_t l4_csum, orig_csum;
|
|
- uint16_t csum;
|
|
|
|
- /*
|
|
- * Discard L2 header.
|
|
- */
|
|
skb_pull(skb, sizeof(struct ethhdr));
|
|
skb_reset_mac_header(skb);
|
|
skb_reset_network_header(skb);
|
|
@@ -563,123 +547,24 @@ static void nss_connmgr_map_t_encap_exce
|
|
ip4_hdr = ip_hdr(skb);
|
|
skb_set_transport_header(skb, ip4_hdr->ihl * 4);
|
|
|
|
- if (ip4_hdr->protocol == IPPROTO_TCP) {
|
|
- tcph = tcp_hdr(skb);
|
|
- l4_csum = tcph->check;
|
|
- sport = tcph->source;
|
|
- dport = tcph->dest;
|
|
- } else if (ip4_hdr->protocol == IPPROTO_UDP) {
|
|
- udph = udp_hdr(skb);
|
|
- orig_csum = l4_csum = udph->check;
|
|
- sport = udph->source;
|
|
- dport = udph->dest;
|
|
- } else {
|
|
- nss_connmgr_map_t_warning("%px: Unsupported protocol, free it up\n", dev);
|
|
- dev_kfree_skb_any(skb);
|
|
- return;
|
|
- }
|
|
-
|
|
- /*
|
|
- * Undo the checksum of the IPv4 source and destinationIPv4 address.
|
|
- */
|
|
- csum = ip_compute_csum(&ip4_hdr->saddr, 2 * sizeof(ip4_hdr->saddr));
|
|
- l4_csum += ((~csum) & 0xFFFF);
|
|
-
|
|
- /*`
|
|
- * IPv6 packet is xlated to ipv4 packet by acceleration engine. But there is no ipv4 rule.
|
|
- * Call xlate_4_to_6() [ which is exported by nat46.ko ] to find original ipv6 src and ipv6 dest address.
|
|
- * These functions is designed for packets from lan to wan. Since this packet is from wan, need to call
|
|
- * this function with parameters reversed. ipv4_hdr_r is used for reversing ip addresses.
|
|
- */
|
|
- ip4_hdr_r.daddr = ip4_hdr->saddr;
|
|
- ip4_hdr_r.saddr = ip4_hdr->daddr;
|
|
-
|
|
- if (unlikely(!xlate_4_to_6(dev, &ip4_hdr_r, dport, sport, v6saddr, v6daddr))) { /* exception happened after packet got xlated */
|
|
- nss_connmgr_map_t_warning("%px: Martian ipv4 packet !!..free it. (saddr = 0x%x daddr = 0x%x sport = %d dport = %d)\n", dev,\
|
|
- ip4_hdr->saddr, ip4_hdr->daddr, sport, dport);
|
|
- dev_kfree_skb_any(skb);
|
|
- return;
|
|
- }
|
|
-
|
|
- nexthdr = ip4_hdr->protocol;
|
|
- payload_len = ntohs(ip4_hdr->tot_len) - sizeof(struct iphdr);
|
|
- hop_limit = ip4_hdr->ttl;
|
|
- tos = ip4_hdr->tos;
|
|
- identifier = ntohs(ip4_hdr->id);
|
|
-
|
|
- if (ip4_hdr->frag_off & htons(IP_DF)) {
|
|
- df_bit = true;
|
|
- } else if (map_t_flags & MAPT_FLAG_ADD_DUMMY_HDR) {
|
|
- append_hdr_sz = sizeof(struct frag_hdr);
|
|
- }
|
|
-
|
|
- if (!pskb_may_pull(skb, sizeof(struct ipv6hdr) + append_hdr_sz - sizeof(struct iphdr))) {
|
|
- nss_connmgr_map_t_warning("%px: Not enough headroom for ipv6 packet...Freeing the packet\n", dev);
|
|
- dev_kfree_skb_any(skb);
|
|
- return;
|
|
- }
|
|
-
|
|
- skb_push(skb, sizeof(struct ipv6hdr) + append_hdr_sz - sizeof(struct iphdr));
|
|
- skb_reset_network_header(skb);
|
|
- skb_reset_mac_header(skb);
|
|
-
|
|
- skb->protocol = htons(ETH_P_IPV6);
|
|
-
|
|
- ip6_hdr = ipv6_hdr(skb);
|
|
- memset(ip6_hdr, 0, sizeof(struct ipv6hdr));
|
|
-
|
|
- ip6_hdr->version = 6;
|
|
- ip6_hdr->payload_len = htons(payload_len + append_hdr_sz);
|
|
- ip6_hdr->hop_limit = hop_limit;
|
|
-
|
|
- nss_connmgr_map_t_ipv6_set_tclass(ip6_hdr, tos);
|
|
- memcpy(&ip6_hdr->daddr, v6saddr, sizeof(struct in6_addr));
|
|
- memcpy(&ip6_hdr->saddr, v6daddr, sizeof(struct in6_addr));
|
|
-
|
|
- if (unlikely(df_bit) || !(map_t_flags & MAPT_FLAG_ADD_DUMMY_HDR)) {
|
|
- ip6_hdr->nexthdr = nexthdr;
|
|
- } else {
|
|
- struct frag_hdr tmp_fh, *fh;
|
|
- const __be32 *fh_addr = skb_header_pointer(skb, sizeof(struct ipv6hdr), sizeof(struct frag_hdr), &tmp_fh);
|
|
- if (!fh_addr) {
|
|
- nss_connmgr_map_t_warning("%px: Not able to offset to frag header\n", dev);
|
|
- dev_kfree_skb_any(skb);
|
|
- return;
|
|
- }
|
|
- fh = (struct frag_hdr *)fh_addr;
|
|
- memset(fh, 0, sizeof(struct frag_hdr));
|
|
- fh->identification = htonl(identifier);
|
|
- fh->nexthdr = nexthdr;
|
|
- ip6_hdr->nexthdr = NEXTHDR_FRAGMENT;
|
|
- }
|
|
-
|
|
- skb_set_transport_header(skb, sizeof(struct ipv6hdr) + append_hdr_sz);
|
|
-
|
|
/*
|
|
- * Add the checksum of the IPv6 source and destination address.
|
|
+ * IP Header checksum is not generated yet, calculate it now.
|
|
*/
|
|
- l4_csum += ip_compute_csum(ip6_hdr->saddr.s6_addr16, 2 * sizeof(ip6_hdr->saddr));
|
|
- /*
|
|
- * Fold the 32 bits checksum to 16 bits
|
|
- */
|
|
- l4_csum = (l4_csum & 0x0000FFFF) + (l4_csum >> 16);
|
|
- l4_csum = (l4_csum & 0x0000FFFF) + (l4_csum >> 16);
|
|
-
|
|
- if (nexthdr == IPPROTO_TCP) {
|
|
- tcph->check = (uint16_t)l4_csum;
|
|
- } else {
|
|
- udph->check = (orig_csum == 0)? 0:(uint16_t)l4_csum;
|
|
- }
|
|
+ ip4_hdr->check = 0;
|
|
+ ip4_hdr->check = ip_fast_csum((unsigned char *)ip4_hdr, ip4_hdr->ihl);
|
|
|
|
+ skb->protocol = htons(ETH_P_IP);
|
|
skb->pkt_type = PACKET_HOST;
|
|
skb->skb_iif = dev->ifindex;
|
|
skb->ip_summed = CHECKSUM_NONE;
|
|
skb->dev = dev;
|
|
|
|
- nss_connmgr_map_t_trace("%p: ipv4 packet exceptioned after v6 ---> v4 xlate, created original ipv6 packet\n", dev);
|
|
- nss_connmgr_map_t_trace("%p: Calculted ipv6 params: src_addr=%pI6, dest_addr=%pI6, payload_len=%d, checksum=%x\n", dev, v6saddr, v6daddr, payload_len, l4_csum);
|
|
-
|
|
- dev_queue_xmit(skb);
|
|
+ nss_connmgr_map_t_trace("%px: ipv4 packet exceptioned after v6/v4xlat src=%pI4 dest=%pI4 proto=%d\n",
|
|
+ dev, &ip4_hdr->saddr, &ip4_hdr->daddr, ip4_hdr->protocol);
|
|
+ /*
|
|
+ * Go through Linux network stack.
|
|
+ */
|
|
+ netif_receive_skb(skb);
|
|
return;
|
|
}
|
|
|