diff -u --new-file linux-2.0.30-clean/net/ipv4/Config.in linux/net/ipv4/Config.in --- linux-2.0.30-clean/net/ipv4/Config.in Sat Apr 26 11:53:11 1997 +++ linux/net/ipv4/Config.in Tue Jun 3 03:48:13 1997 @@ -16,6 +16,7 @@ comment 'Protocol-specific masquerading support will be built as modules.' bool 'IP: ipautofw masq support' CONFIG_IP_MASQUERADE_IPAUTOFW bool 'IP: ICMP masquerading' CONFIG_IP_MASQUERADE_ICMP + bool 'IP: masquerading GRE' CONFIG_IP_MASQUERADE_GRE fi if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then bool 'IP: transparent proxy support (EXPERIMENTAL)' CONFIG_IP_TRANSPARENT_PROXY diff -u --new-file linux-2.0.30-clean/net/ipv4/Makefile linux/net/ipv4/Makefile --- linux-2.0.30-clean/net/ipv4/Makefile Sat Apr 26 11:53:11 1997 +++ linux/net/ipv4/Makefile Tue Jun 3 03:49:21 1997 @@ -40,6 +40,9 @@ ifeq ($(CONFIG_IP_MASQUERADE),y) IPV4_OBJS += ip_masq.o ip_masq_app.o +ifeq ($(CONFIG_IP_MASQUERADE_GRE),y) +IPV4_OBJS += ip_masq_gre.o +endif M_OBJS += ip_masq_ftp.o ip_masq_irc.o ip_masq_raudio.o ip_masq_cuseeme.o M_OBJS += ip_masq_vdolive.o ip_masq_quake.o endif diff -u --new-file linux-2.0.30-clean/net/ipv4/ip_masq.c linux/net/ipv4/ip_masq.c --- linux-2.0.30-clean/net/ipv4/ip_masq.c Sat Apr 26 11:53:11 1997 +++ linux/net/ipv4/ip_masq.c Tue Jun 3 04:09:58 1997 @@ -43,6 +43,10 @@ #include #include +#define IPPROTO_GRE 47 +extern int ip_fw_masq_gre(struct sk_buff **skb_ptr, struct device *dev); +extern int ip_fw_demasq_gre(struct sk_buff **skb_p, struct device *dev); + #define IP_MASQ_TAB_SIZE 256 /* must be power of 2 */ /* @@ -638,6 +642,17 @@ /* get masq address from rif */ ms->maddr = dev->pa_addr; +#ifdef CONFIG_IP_MASQUERADE_GRE + if (proto == IPPROTO_GRE) { + ms->mport = 0; + ip_masq_hash(ms); + + ip_masq_bind_app(ms); + n_fails = 0; + return ms; + } +#endif + for (ports_tried = 0; ports_tried < *free_ports_p; ports_tried++){ save_flags(flags); cli(); @@ -727,11 +742,20 @@ unsigned long timeout; /* - * We can only masquerade protocols with ports... + * Normally, we only masquerade protocols with ports... + * except for the GRE protocol. It is portless, so just remap the + * source address. Since it is portless, only one instance of GRE + * remapping is allowed to a given machine. Map back to the last + * address that sent a GRE packet to a given machine. * [TODO] * We may need to consider masq-ing some ICMP related to masq-ed protocols */ +#ifdef CONFIG_IP_MASQUERADE_GRE + if (iph->protocol==IPPROTO_GRE) + return ip_fw_masq_gre(skb_ptr, dev); +#endif + if (iph->protocol==IPPROTO_ICMP) return (ip_fw_masq_icmp(skb_ptr,dev)); if (iph->protocol!=IPPROTO_UDP && iph->protocol!=IPPROTO_TCP) @@ -1307,6 +1331,10 @@ #endif /* CONFIG_IP_MASQUERADE_IPAUTOFW */ switch (iph->protocol) { +#ifdef CONFIG_IP_MASQUERADE_GRE + case IPPROTO_GRE: + return(ip_fw_demasq_gre(skb_p, dev)); +#endif case IPPROTO_ICMP: return(ip_fw_demasq_icmp(skb_p, dev)); case IPPROTO_TCP: diff -u --new-file linux-2.0.30-clean/net/ipv4/ip_masq_gre.c linux/net/ipv4/ip_masq_gre.c --- linux-2.0.30-clean/net/ipv4/ip_masq_gre.c Wed Dec 31 16:00:00 1969 +++ linux/net/ipv4/ip_masq_gre.c Tue Jun 3 04:12:08 1997 @@ -0,0 +1,117 @@ +/* + * ip_masq_pptp.c + * + * Masquerading for PPTP (Point to Point Tunneling Protocol). + * PPTP is a a protocol for creating virtual private networks. + * It is a specification defined by Microsoft and some vendors + * working with Microsoft. PPTP is built on top of a modified + * version of the Internet Generic Routing Encapsulation Protocol. + * GRE is defined in RFC 1701 and RFC 1702. Documentation of + * PPTP can be found on the Microsoft web site. + * + * Copyright (c) 1997 Gordon Chaffee + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +int ip_fw_masq_gre(struct sk_buff **skb_ptr, struct device *dev) +{ + struct sk_buff *skb=*skb_ptr; + struct iphdr *iph = skb->h.iph; + struct ip_masq *ms; + +#ifdef DEBUG_CONFIG_IP_MASQUERADE_GRE + printk("Outgoing GRE %lX -> %lX\n", + ntohl(iph->saddr), ntohl(iph->daddr)); +#endif + + /* + * Now hunt the list to see if we have an old entry + */ + + ms = ip_masq_out_get_2(iph->protocol, iph->saddr, 0, iph->daddr, 0); + if (ms!=NULL) + ip_masq_set_expire(ms,0); + + /* + * Nope, not found, create a new entry for it + */ + + if (ms==NULL) + { + ms = ip_masq_new(dev, iph->protocol, + iph->saddr, 0, iph->daddr, 0, 0); + if (ms == NULL) + return -1; + } + + /* + * Change the fragments origin + * Set iph addr from ip_masq obj. + */ + + iph->saddr = ms->maddr; + + iph->check=0; + iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl); + + ip_send_check(iph); + +#ifdef DEBUG_CONFIG_IP_MASQUERADE_GRE + printk("O-routed from %lX over %s\n",ntohl(ms->maddr),dev->name); +#endif + + return 0; +} + +int ip_fw_demasq_gre(struct sk_buff **skb_p, struct device *dev) +{ + struct sk_buff *skb = *skb_p; + struct iphdr *iph = skb->h.iph; + struct ip_masq *ms; + + /* + * XXX: Do we need to see if the checksum is good? Since we + * are only dealing at an IP level, I don't think so. + */ + +#ifdef DEBUG_CONFIG_IP_MASQUERADE_GRE + printk("Incoming GRE %lX -> %lX\n", + ntohl(iph->saddr), ntohl(iph->daddr)); +#endif + /* + * reroute to original host if found... + */ + + ms = ip_masq_in_get_2(iph->protocol, iph->saddr, 0, iph->daddr, 0); + + if (ms != NULL) + { + iph->daddr = ms->saddr; + + /* + * Adjust IP checksums. + */ + iph->check=0; + iph->check=ip_fast_csum((unsigned char *)iph, iph->ihl); + ip_send_check(iph); +#ifdef DEBUG_CONFIG_IP_MASQUERADE_GRE + printk("I-routed GRE to %lX\n",ntohl(iph->daddr)); +#endif + return 1; + } + + /* sorry, all this trouble for a no-hit :) */ + return 0; +}