📄 ip_masq.c
字号:
write_unlock(&__ip_masq_lock); } iph->saddr = ms->maddr; ip_send_check(iph); /* Rewrite port (id) */ (icmph->un).echo.id = ms->mport; icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *)icmph, len); IP_MASQ_DEBUG(2, "icmp request rwt %lX->%lX id %d type %d\n", ntohl(iph->saddr), ntohl(iph->daddr), ntohs(icmp_id(icmph)), icmph->type); masq_set_state(ms, 1, iph, icmph); ip_masq_put(ms); return 1; }#endif /* * Work through seeing if this is for us. * These checks are supposed to be in an order that * means easy things are checked first to speed up * processing.... however this means that some * packets will manage to get a long way down this * stack and then be rejected, but thats life */ if ((icmph->type != ICMP_DEST_UNREACH) && (icmph->type != ICMP_SOURCE_QUENCH) && (icmph->type != ICMP_TIME_EXCEEDED)) return 0; /* Now find the contained IP header */ ciph = (struct iphdr *) (icmph + 1);#ifdef CONFIG_IP_MASQUERADE_ICMP if (ciph->protocol == IPPROTO_ICMP) { /* * This section handles ICMP errors for ICMP packets */ struct icmphdr *cicmph = (struct icmphdr *)((char *)ciph + (ciph->ihl<<2)); IP_MASQ_DEBUG(2, "fw icmp/icmp rcv %lX->%lX id %d type %d\n", ntohl(ciph->saddr), ntohl(ciph->daddr), ntohs(icmp_id(cicmph)), cicmph->type); read_lock(&__ip_masq_lock); ms = __ip_masq_out_get(ciph->protocol, ciph->daddr, icmp_id(cicmph), ciph->saddr, icmp_hv_rep(cicmph)); read_unlock(&__ip_masq_lock); if (ms == NULL) return 0; /* Now we do real damage to this packet...! */ /* First change the source IP address, and recalc checksum */ iph->saddr = ms->maddr; ip_send_check(iph); /* Now change the *dest* address in the contained IP */ ciph->daddr = ms->maddr; __ip_masq_put(ms); ip_send_check(ciph); /* Change the ID to the masqed one! */ (cicmph->un).echo.id = ms->mport; /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); IP_MASQ_DEBUG(2, "fw icmp/icmp rwt %lX->%lX id %d type %d\n", ntohl(ciph->saddr), ntohl(ciph->daddr), ntohs(icmp_id(cicmph)), cicmph->type); return 1; }#endif /* CONFIG_IP_MASQUERADE_ICMP */ /* We are only interested ICMPs generated from TCP or UDP packets */ if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP)) return 0; /* * Find the ports involved - this packet was * incoming so the ports are right way round * (but reversed relative to outer IP header!) */ pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]);#if 0 if (ntohs(pptr[1]) < PORT_MASQ_BEGIN || ntohs(pptr[1]) > PORT_MASQ_END) return 0;#endif /* Ensure the checksum is correct */ if (ip_compute_csum((unsigned char *) icmph, len)) { /* Failed checksum! */ IP_MASQ_DEBUG(0, "forward ICMP: failed checksum from %d.%d.%d.%d!\n", NIPQUAD(iph->saddr)); return(-1); } IP_MASQ_DEBUG(2, "Handling forward ICMP for %08lX:%04X -> %08lX:%04X\n", ntohl(ciph->saddr), ntohs(pptr[0]), ntohl(ciph->daddr), ntohs(pptr[1]));#if 0 /* This is pretty much what __ip_masq_in_get_iph() does */ ms = __ip_masq_in_get(ciph->protocol, ciph->saddr, pptr[0], ciph->daddr, pptr[1]);#endif read_lock(&__ip_masq_lock); ms = __ip_masq_out_get(ciph->protocol, ciph->daddr, pptr[1], ciph->saddr, pptr[0]); read_unlock(&__ip_masq_lock); if (ms == NULL) return 0; /* Now we do real damage to this packet...! */ /* First change the source IP address, and recalc checksum */ iph->saddr = ms->maddr; ip_send_check(iph); /* Now change the *dest* address in the contained IP */ ciph->daddr = ms->maddr; ip_send_check(ciph); /* the TCP/UDP dest port - cannot redo check */ pptr[1] = ms->mport; __ip_masq_put(ms); /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); IP_MASQ_DEBUG(2, "Rewrote forward ICMP to %08lX:%04X -> %08lX:%04X\n", ntohl(ciph->saddr), ntohs(pptr[0]), ntohl(ciph->daddr), ntohs(pptr[1])); return 1;}/* * Own skb_cow() beast, tweaked for rewriting commonly * used pointers in masq code */static struct sk_buff * masq_skb_cow(struct sk_buff **skb_p, struct iphdr **iph_p, unsigned char **t_p) { struct sk_buff *skb=(*skb_p); if (skb_cloned(skb)) { skb = skb_copy(skb, GFP_ATOMIC); if (skb) { /* * skb changed, update other pointers */ struct iphdr *iph = skb->nh.iph; kfree_skb(*skb_p); *skb_p = skb; *iph_p = iph; *t_p = (char*) iph + iph->ihl * 4; } } return skb;}/* * Handle ICMP messages in reverse (demasquerade) direction. * Find any that might be relevant, check against existing connections, * forward to masqueraded host if relevant. * Currently handles error types - unreachable, quench, ttl exceeded */int ip_fw_demasq_icmp(struct sk_buff **skb_p){ struct sk_buff *skb = *skb_p; struct iphdr *iph = skb->nh.iph; struct icmphdr *icmph = (struct icmphdr *)((char *)iph + (iph->ihl<<2)); struct iphdr *ciph; /* The ip header contained within the ICMP */ __u16 *pptr; /* port numbers from TCP/UDP contained header */ struct ip_masq *ms; unsigned short len = ntohs(iph->tot_len) - (iph->ihl * 4); IP_MASQ_DEBUG(2, "icmp in/rev (%d,%d) %lX -> %lX\n", icmph->type, ntohs(icmp_id(icmph)), ntohl(iph->saddr), ntohl(iph->daddr));#ifdef CONFIG_IP_MASQUERADE_ICMP if ((icmph->type == ICMP_ECHOREPLY) || (icmph->type == ICMP_TIMESTAMPREPLY) || (icmph->type == ICMP_INFO_REPLY) || (icmph->type == ICMP_ADDRESSREPLY)) { IP_MASQ_DEBUG(2, "icmp reply rcv %lX->%lX id %d type %d, req %d\n", ntohl(iph->saddr), ntohl(iph->daddr), ntohs(icmp_id(icmph)), icmph->type, icmp_type_request(icmph->type)); ms = ip_masq_in_get(iph->protocol, iph->saddr, icmp_hv_rep(icmph), iph->daddr, icmp_id(icmph)); if (ms == NULL) return 0; /* * got reply, so clear flag */ ms->flags &= ~IP_MASQ_F_NO_REPLY; if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) { ip_masq_put(ms); return -1; } /* Reset source address */ iph->daddr = ms->saddr; /* Redo IP header checksum */ ip_send_check(iph); /* Set ID to fake port number */ (icmph->un).echo.id = ms->sport; /* Reset ICMP checksum and set expiry */ icmph->checksum=0; icmph->checksum=ip_compute_csum((unsigned char *)icmph,len); IP_MASQ_DEBUG(2, "icmp reply rwt %lX->%lX id %d type %d\n", ntohl(iph->saddr), ntohl(iph->daddr), ntohs(icmp_id(icmph)), icmph->type); masq_set_state(ms, 0, iph, icmph); ip_masq_put(ms); return 1; } else {#endif if ((icmph->type != ICMP_DEST_UNREACH) && (icmph->type != ICMP_SOURCE_QUENCH) && (icmph->type != ICMP_TIME_EXCEEDED)) return 0;#ifdef CONFIG_IP_MASQUERADE_ICMP }#endif /* * If we get here we have an ICMP error of one of the above 3 types * Now find the contained IP header */ ciph = (struct iphdr *) (icmph + 1);#ifdef CONFIG_IP_MASQUERADE_ICMP if (ciph->protocol == IPPROTO_ICMP) { /* * This section handles ICMP errors for ICMP packets * * First get a new ICMP header structure out of the IP packet */ struct icmphdr *cicmph = (struct icmphdr *)((char *)ciph + (ciph->ihl<<2)); IP_MASQ_DEBUG(2, "rv icmp/icmp rcv %lX->%lX id %d type %d\n", ntohl(ciph->saddr), ntohl(ciph->daddr), ntohs(icmp_id(cicmph)), cicmph->type); read_lock(&__ip_masq_lock); ms = __ip_masq_in_get(ciph->protocol, ciph->daddr, icmp_hv_req(cicmph), ciph->saddr, icmp_id(cicmph)); read_unlock(&__ip_masq_lock); if (ms == NULL) return 0; if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) { __ip_masq_put(ms); return -1; } ciph = (struct iphdr *) (icmph + 1); cicmph = (struct icmphdr *)((char *)ciph + (ciph->ihl<<2)); /* Now we do real damage to this packet...! */ /* First change the dest IP address, and recalc checksum */ iph->daddr = ms->saddr; ip_send_check(iph); /* Now change the *source* address in the contained IP */ ciph->saddr = ms->saddr; ip_send_check(ciph); /* Change the ID to the original one! */ (cicmph->un).echo.id = ms->sport; __ip_masq_put(ms); /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); IP_MASQ_DEBUG(2, "rv icmp/icmp rwt %lX->%lX id %d type %d\n", ntohl(ciph->saddr), ntohl(ciph->daddr), ntohs(icmp_id(cicmph)), cicmph->type); return 1; }#endif /* CONFIG_IP_MASQUERADE_ICMP */ /* We are only interested ICMPs generated from TCP or UDP packets */ if ((ciph->protocol != IPPROTO_UDP) && (ciph->protocol != IPPROTO_TCP)) return 0; /* * Find the ports involved - remember this packet was * *outgoing* so the ports are reversed (and addresses) */ pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]); if (ntohs(pptr[0]) < PORT_MASQ_BEGIN || ntohs(pptr[0]) > PORT_MASQ_END) return 0; /* Ensure the checksum is correct */ if (ip_compute_csum((unsigned char *) icmph, len)) { /* Failed checksum! */ IP_MASQ_ERR( "reverse ICMP: failed checksum from %d.%d.%d.%d!\n", NIPQUAD(iph->saddr)); return(-1); } IP_MASQ_DEBUG(2, "Handling reverse ICMP for %08lX:%04X -> %08lX:%04X\n", ntohl(ciph->saddr), ntohs(pptr[0]), ntohl(ciph->daddr), ntohs(pptr[1])); /* This is pretty much what __ip_masq_in_get_iph() does, except params are wrong way round */ read_lock(&__ip_masq_lock); ms = __ip_masq_in_get(ciph->protocol, ciph->daddr, pptr[1], ciph->saddr, pptr[0]); read_unlock(&__ip_masq_lock); if (ms == NULL) return 0; if ((skb=masq_skb_cow(skb_p, &iph, (unsigned char**)&icmph)) == NULL) { __ip_masq_put(ms); return -1; } ciph = (struct iphdr *) (icmph + 1); pptr = (__u16 *)&(((char *)ciph)[ciph->ihl*4]); /* Now we do real damage to this packet...! */ /* First change the dest IP address, and recalc checksum */ iph->daddr = ms->saddr; ip_send_check(iph); /* Now change the *source* address in the contained IP */ ciph->saddr = ms->saddr; ip_send_check(ciph); /* the TCP/UDP source port - cannot redo check */ pptr[0] = ms->sport; __ip_masq_put(ms); /* And finally the ICMP checksum */ icmph->checksum = 0; icmph->checksum = ip_compute_csum((unsigned char *) icmph, len); IP_MASQ_DEBUG(2, "Rewrote reverse ICMP to %08lX:%04X -> %08lX:%04X\n", ntohl(ciph->saddr), ntohs(pptr[0]), ntohl(ciph->daddr), ntohs(pptr[1])); return 1;} /* * Check if it's an masqueraded port, look it up, * and send it on its way... * * Better not have many hosts using the designated portrange * as 'normal' ports, or you'll be spending many time in * this function. */int ip_fw_demasquerade(struct sk_buff **skb_p){ struct sk_buff *skb = *skb_p; struct iphdr *iph = skb->nh.iph; union ip_masq_tphdr h; struct ip_masq *ms; unsigned short size; int doff = 0; int csum = 0; int csum_ok = 0; __u32 maddr; /* * Big tappo: only PACKET_HOST (nor loopback neither mcasts) * ... don't know why 1st test DOES NOT include 2nd (?) */ if (skb->pkt_type != PACKET_HOST || skb->dev == &loopback_dev) { IP_MASQ_DEBUG(2, "ip_fw_demasquerade(): packet type=%d proto=%d daddr=%d.%d.%d.%d ignored\n", skb->pkt_type, iph->protocol, NIPQUAD(iph->daddr)); return 0; } h.raw = (char*) iph + iph->ihl * 4; /* * IP payload size */ size = ntohs(iph->tot_len) - (iph->ihl * 4); doff = proto_doff(iph->protocol, h.raw, size); switch (doff) { case 0: /* * Input path: other IP protos Ok, will * reach local sockets path. */ return 0; case -1: IP_MASQ_DEBUG(0, "I-pkt invalid packet data size\n"); return -1; } maddr = iph->daddr; switch (iph->protocol) { case IPPROTO_ICMP: return(ip_fw_demasq_icmp(skb_p)); case IPPROTO_TCP: case IPPROTO_UDP: /* * Make sure packet is in the masq range * ... or some mod-ule relaxes input range * ... or there is still some `special' mport opened */ if ((ntohs(h.portp[1]) < PORT_MASQ_BEGIN || ntohs(h.portp[1]) > PORT_MASQ_END)#ifdef CONFIG_IP_MASQUERADE_MOD && (ip_masq_mod_in_rule(skb, iph) != 1) #endif && atomic_read(&mport_count) == 0 ) return 0; /* Check that the checksum is OK */ if ((iph->protocol == IPPROTO_UDP) && (h.uh->check == 0)) /* No UDP checksum */ break;#ifdef CONFIG_IP_MASQ_DEBUG if (ip_masq_get_debug_level() > 3) { skb->ip_summed = CHECKSUM_NONE; }#endif switch (skb->ip_summed) { case CHECKSUM_NONE: csum = csum_partial(h.raw + doff, size - doff, 0); csum_ok++; skb->csum = csum_partial(h.raw , doff, csum);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -