*** net/ipv4/ip_masq.c.orig Thu Jun 6 15:23:49 1996 --- net/ipv4/ip_masq.c Tue Oct 8 12:35:49 1996 *************** *** 1,3 **** --- 1,5 ---- + #define CONFIG_IP_MASQUERADE_ICMP + /*#define DEBUG_CONFIG_IP_MASQUERADE_ICMP*/ /* * * Masquerading functionality *************** *** 15,20 **** --- 17,23 ---- * Nigel Metheringham : Added ICMP handling for demasquerade * Nigel Metheringham : Checksum checking of masqueraded data * Nigel Metheringham : Better handling of timeouts of TCP conns + * Delian Delchev : Added support for ICMP requests and replys * * */ *************** *** 44,54 **** * Implement IP packet masquerading */ ! static const char *strProt[] = {"UDP","TCP"}; ! static __inline__ const char * masq_proto_name(unsigned proto) { ! return strProt[proto==IPPROTO_TCP]; } /* --- 47,86 ---- * Implement IP packet masquerading */ ! static const char *strProt[] = {"UDP","TCP","ICMP"}; ! /* ! * masq_proto_num returns 0 for UDP, 1 for TCP, 2 for ICMP ! */ ! ! static int masq_proto_num(unsigned proto) { ! switch (proto) ! { ! case IPPROTO_UDP: return (0); break; ! case IPPROTO_TCP: return (1); break; ! case IPPROTO_ICMP: return (2); break; ! default: return (-1); break; ! } ! } ! ! #ifdef CONFIG_IP_MASQUERADE_ICMP ! static __u8 icmp_type_request(__u8 type) ! { ! switch (type) ! { ! case ICMP_ECHOREPLY: return ICMP_ECHO; break; ! case ICMP_TIMESTAMPREPLY: return ICMP_TIMESTAMP; break; ! case ICMP_INFO_REPLY: return ICMP_INFO_REQUEST; break; ! case ICMP_ADDRESSREPLY: return ICMP_ADDRESS; break; ! default: return (255); break; ! } ! } ! #endif ! ! static __inline__ const char *masq_proto_name(unsigned proto) ! { ! return strProt[masq_proto_num(proto)]; } /* *************** static __u16 masq_port = PORT_MASQ_BEGIN *** 69,77 **** * */ ! int ip_masq_free_ports[2] = { PORT_MASQ_END - PORT_MASQ_BEGIN, /* UDP */ ! PORT_MASQ_END - PORT_MASQ_BEGIN /* TCP */ }; static struct symbol_table ip_masq_syms = { --- 101,110 ---- * */ ! int ip_masq_free_ports[3] = { PORT_MASQ_END - PORT_MASQ_BEGIN, /* UDP */ ! PORT_MASQ_END - PORT_MASQ_BEGIN, /* TCP */ ! PORT_MASQ_END - PORT_MASQ_BEGIN /* ICMP */ }; static struct symbol_table ip_masq_syms = { *************** struct ip_masq *ip_masq_s_tab[IP_MASQ_TA *** 98,104 **** static struct ip_fw_masq ip_masq_dummy = { MASQUERADE_EXPIRE_TCP, MASQUERADE_EXPIRE_TCP_FIN, ! MASQUERADE_EXPIRE_UDP }; struct ip_fw_masq *ip_masq_expire = &ip_masq_dummy; --- 131,138 ---- static struct ip_fw_masq ip_masq_dummy = { MASQUERADE_EXPIRE_TCP, MASQUERADE_EXPIRE_TCP_FIN, ! MASQUERADE_EXPIRE_UDP, ! MASQUERADE_EXPIRE_ICMP }; struct ip_fw_masq *ip_masq_expire = &ip_masq_dummy; *************** ip_masq_out_get_2(int protocol, __u32 s_ *** 282,287 **** --- 316,322 ---- unsigned hash; struct ip_masq *ms; + hash = ip_masq_hash_key(protocol, s_addr, s_port); for(ms = ip_masq_s_tab[hash]; ms ; ms = ms->s_link) { if (protocol == ms->protocol && *************** ip_masq_out_get_2(int protocol, __u32 s_ *** 289,295 **** d_addr == ms->daddr && d_port == ms->dport ) return ms; } - return NULL; } --- 324,329 ---- *************** static void masq_expire(unsigned long da *** 319,335 **** unsigned long flags; #ifdef DEBUG_CONFIG_IP_MASQUERADE ! printk("Masqueraded %s %lX:%X expired\n", ! masq_proto_name(ms->protocol), ! ntohl(ms->saddr),ntohs(ms->sport)); #endif save_flags(flags); cli(); if (ip_masq_unhash(ms)) { ! ip_masq_free_ports[ms->protocol==IPPROTO_TCP]++; ! ip_masq_unbind_app(ms); kfree_s(ms,sizeof(*ms)); } --- 353,368 ---- unsigned long flags; #ifdef DEBUG_CONFIG_IP_MASQUERADE ! printk("Masqueraded %s %lX:%X expired\n",masq_proto_name(ms->protocol),ntohl(ms->saddr),ntohs(ms->sport)); #endif save_flags(flags); cli(); if (ip_masq_unhash(ms)) { ! ip_masq_free_ports[masq_proto_num(ms->protocol)]++; ! if (ms->protocol != IPPROTO_ICMP) ! ip_masq_unbind_app(ms); kfree_s(ms,sizeof(*ms)); } *************** struct ip_masq * ip_masq_new(struct devi *** 349,355 **** unsigned long flags; static int n_fails = 0; ! free_ports_p = &ip_masq_free_ports[proto==IPPROTO_TCP]; if (*free_ports_p == 0) { if (++n_fails < 5) --- 382,388 ---- unsigned long flags; static int n_fails = 0; ! free_ports_p = &ip_masq_free_ports[masq_proto_num(proto)]; if (*free_ports_p == 0) { if (++n_fails < 5) *************** struct ip_masq * ip_masq_new(struct devi *** 413,419 **** restore_flags(flags); ! ip_masq_bind_app(ms); n_fails = 0; return ms; } --- 446,453 ---- restore_flags(flags); ! if (proto != IPPROTO_ICMP) ! ip_masq_bind_app(ms); n_fails = 0; return ms; } *************** int ip_fw_masquerade(struct sk_buff **sk *** 467,472 **** --- 501,508 ---- * We may need to consider masq-ing some ICMP related to masq-ed protocols */ + if (iph->protocol==IPPROTO_ICMP) + return (ip_fw_masq_icmp(skb_ptr,dev)); if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP) return -1; *************** int ip_fw_masquerade(struct sk_buff **sk *** 530,536 **** * Adjust packet accordingly to protocol */ ! if (iph->protocol==IPPROTO_UDP) { timeout = ip_masq_expire->udp_timeout; recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size); --- 566,572 ---- * Adjust packet accordingly to protocol */ ! if (masq_proto_num(iph->protocol)==0) { timeout = ip_masq_expire->udp_timeout; recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,size); *************** int ip_fw_masq_icmp(struct sk_buff **skb *** 612,619 **** */ 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); --- 648,694 ---- */ if ((icmph->type != ICMP_DEST_UNREACH) && (icmph->type != ICMP_SOURCE_QUENCH) && ! (icmph->type != ICMP_TIME_EXCEEDED) ! #ifdef CONFIG_IP_MASQUERADE_ICMP ! && (icmph->type != ICMP_ECHO ) && ! (icmph->type != ICMP_TIMESTAMP ) && ! (icmph->type != ICMP_INFO_REQUEST ) && ! (icmph->type != ICMP_ADDRESS ) ! #endif ! ) return 0; ! #ifdef CONFIG_IP_MASQUERADE_ICMP ! if ((icmph->type == ICMP_ECHO ) || ! (icmph->type == ICMP_TIMESTAMP ) || ! (icmph->type == ICMP_INFO_REQUEST ) || ! (icmph->type == ICMP_ADDRESS )) ! { ! if ((ms=ip_masq_out_get_2(iph->protocol,iph->saddr,(icmph->un).echo.id, ! iph->daddr,(__u16)(icmph->code+(__u16)((__u16)(icmph->type)<<8))))==NULL) ! { ! if((ms=ip_masq_new(dev,iph->protocol,iph->saddr,(icmph->un).echo.id, ! iph->daddr,(__u16)(icmph->code+(__u16)((__u16)(icmph->type)<<8)),0))==NULL) ! return (-1); ! #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP ! printk("MASQ: Create new icmp entry\n"); ! #endif ! } ! ip_masq_set_expire(ms,0); ! #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP ! printk("MASQ: receive icmp request from %lX to %lX id %d type %d\n", ! ntohl(iph->saddr),ntohl(iph->daddr),(icmph->un).echo.id,icmph->type); ! #endif ! iph->saddr=ms->maddr;ip_send_check(iph); ! (icmph->un).echo.id=ms->mport; ! icmph->checksum=0; ! icmph->checksum=ip_compute_csum((unsigned char *)icmph,len); ! ip_masq_set_expire(ms,ip_masq_expire->icmp_timeout); ! #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP ! printk("MASQ: process it like from %lX to %lX id %d type %d\n", ! ntohl(iph->saddr),ntohl(iph->daddr),(icmph->un).echo.id,icmph->type); ! #endif ! return (1); ! } ! #endif /* Now find the contained IP header */ ciph = (struct iphdr *) (icmph + 1); *************** int ip_fw_demasq_icmp(struct sk_buff **s *** 703,710 **** 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); --- 778,818 ---- if ((icmph->type != ICMP_DEST_UNREACH) && (icmph->type != ICMP_SOURCE_QUENCH) && ! (icmph->type != ICMP_TIME_EXCEEDED) ! #ifdef CONFIG_IP_MASQUERADE_ICMP ! && (icmph->type != ICMP_ECHOREPLY) && ! (icmph->type != ICMP_TIMESTAMPREPLY) && ! (icmph->type != ICMP_INFO_REPLY) && ! (icmph->type != ICMP_ADDRESSREPLY) ! #endif ! ) return 0; ! #ifdef CONFIG_IP_MASQUERADE_ICMP ! if ((icmph->type == ICMP_ECHOREPLY) || ! (icmph->type == ICMP_TIMESTAMPREPLY) || ! (icmph->type == ICMP_INFO_REPLY) || ! (icmph->type == ICMP_ADDRESSREPLY)) ! { ! #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP ! printk("MASQ: receive icmp reply from %lX to %lX id %d type %d,ntype %d\n", ! ntohl(iph->saddr),ntohl(iph->daddr),(icmph->un).echo.id,icmph->type, ! icmp_type_request(icmph->type)); ! #endif ! if ((ms=ip_masq_in_get_2(iph->protocol,iph->saddr, ! (__u16)(icmph->code+(__u16)(icmp_type_request(icmph->type)<<8)), ! iph->daddr,(icmph->un).echo.id))==NULL) return 0; ! ip_masq_set_expire(ms,0); ! iph->daddr=ms->saddr;ip_send_check(iph); ! (icmph->un).echo.id=ms->sport; ! icmph->checksum=0; ! icmph->checksum=ip_compute_csum((unsigned char *)icmph,len); ! ip_masq_set_expire(ms,ip_masq_expire->icmp_timeout); ! #ifdef DEBUG_CONFIG_IP_MASQUERADE_ICMP ! printk("MASQ: process it like from %lX to %lX with id %d and type %d\n", ! ntohl(iph->saddr),ntohl(iph->daddr),(icmph->un).echo.id,icmph->type); ! #endif ! return (1); ! } ! #endif /* Now find the contained IP header */ ciph = (struct iphdr *) (icmph + 1); *************** int ip_fw_demasquerade(struct sk_buff ** *** 886,892 **** * timeouts. * If a TCP RST is seen collapse the tunnel (by using short timeout)! */ ! if (iph->protocol==IPPROTO_UDP) { recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,len); timeout = ip_masq_expire->udp_timeout; --- 994,1000 ---- * timeouts. * If a TCP RST is seen collapse the tunnel (by using short timeout)! */ ! if (masq_proto_num(iph->protocol)==0) { recalc_check((struct udphdr *)portptr,iph->saddr,iph->daddr,len); timeout = ip_masq_expire->udp_timeout; *** net/ipv4/ip_forward.c.orig Tue Oct 8 12:36:14 1996 --- net/ipv4/ip_forward.c Tue Oct 8 13:15:45 1996 *************** *** 1,3 **** --- 1,4 ---- + #define CONFIG_IP_MASQUERADE_ICMP /* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket *************** int ip_forward(struct sk_buff *skb, stru *** 263,268 **** --- 264,276 ---- */ if (iph->protocol == IPPROTO_ICMP) { + #ifdef CONFIG_IP_MASQUERADE_ICMP + #define icmph ((struct icmphdr *)((char *)iph + (iph->ihl<<2))) + if ((icmph->type==ICMP_DEST_UNREACH)|| + (icmph->type==ICMP_SOURCE_QUENCH)|| + (icmph->type==ICMP_TIME_EXCEEDED)) + { + #endif if ((fw_res = ip_fw_masq_icmp(&skb, dev2)) < 0) /* Problem - ie bad checksum */ return -1; *************** int ip_forward(struct sk_buff *skb, stru *** 270,275 **** --- 278,286 ---- if (fw_res) /* ICMP matched - skip firewall */ goto skip_call_fw_firewall; + #ifdef CONFIG_IP_MASQUERADE_ICMP + } + #endif } #endif fw_res=call_fw_firewall(PF_INET, dev2, iph, NULL); *** net/ipv4/ip_fw.c.orig Tue Oct 8 12:36:23 1996 --- net/ipv4/ip_fw.c Tue Oct 8 13:11:36 1996 *************** int ip_fw_ctl(int stage, void *m, int le *** 998,1003 **** --- 998,1008 ---- { ip_masq_expire->udp_timeout = masq->udp_timeout; } + + if (masq->icmp_timeout) + { + ip_masq_expire->icmp_timeout = masq->icmp_timeout; + } return 0; #else *** include/net/ip_masq.h.orig Tue Oct 8 13:16:07 1996 --- include/net/ip_masq.h Tue Oct 8 14:19:29 1996 *************** *** 20,25 **** --- 20,26 ---- #define MASQUERADE_EXPIRE_TCP 15*60*HZ #define MASQUERADE_EXPIRE_TCP_FIN 2*60*HZ #define MASQUERADE_EXPIRE_UDP 5*60*HZ + #define MASQUERADE_EXPIRE_ICMP 2*60*HZ #define IP_MASQ_F_OUT_SEQ 0x01 /* must do output seq adjust */ #define IP_MASQ_F_IN_SEQ 0x02 /* must do input seq adjust */ *************** struct ip_fw_masq { *** 69,74 **** --- 70,76 ---- int tcp_timeout; int tcp_fin_timeout; int udp_timeout; + int icmp_timeout; }; extern struct ip_fw_masq *ip_masq_expire; *************** extern struct ip_fw_masq *ip_masq_expire *** 76,84 **** /* * [0]: UDP free_ports * [1]: TCP free_ports */ ! extern int ip_masq_free_ports[2]; /* * ip_masq initializer (registers symbols and /proc/net entries) --- 78,87 ---- /* * [0]: UDP free_ports * [1]: TCP free_ports + * [2]: ICMP free ids */ ! extern int ip_masq_free_ports[3]; /* * ip_masq initializer (registers symbols and /proc/net entries)