diff -ur orig/ipvs/ip_vs.h ipvs/ip_vs.h --- orig/ipvs/ip_vs.h Wed Jan 10 07:42:53 2001 +++ ipvs/ip_vs.h Sat Jan 20 20:18:02 2001 @@ -95,6 +95,7 @@ #define IP_VS_CONN_F_IN_SEQ 0x0400 /* must do input seq adjust */ #define IP_VS_CONN_F_NO_CPORT 0x0800 /* no client port set yet */ +#define NFMARK_IPVS_PROPERTY -0x100 #ifdef __KERNEL__ diff -ur orig/ipvs/ip_vs_conn.c ipvs/ip_vs_conn.c --- orig/ipvs/ip_vs_conn.c Mon Jan 15 13:43:46 2001 +++ ipvs/ip_vs_conn.c Sat Jan 20 17:56:52 2001 @@ -645,6 +645,7 @@ #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 1 << NF_IP_LOCAL_OUT; #endif /* CONFIG_NETFILTER_DEBUG */ + skb->nfmark = NFMARK_IPVS_PROPERTY; ip_send(skb); LeaveFunction(10); @@ -835,6 +836,7 @@ #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 1 << NF_IP_LOCAL_OUT; #endif /* CONFIG_NETFILTER_DEBUG */ + skb->nfmark = NFMARK_IPVS_PROPERTY; ip_send(skb); LeaveFunction(10); @@ -972,6 +974,7 @@ #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 1 << NF_IP_LOCAL_OUT; #endif /* CONFIG_NETFILTER_DEBUG */ + skb->nfmark = NFMARK_IPVS_PROPERTY; ip_send(skb); LeaveFunction(10); @@ -1033,6 +1036,7 @@ #ifdef CONFIG_NETFILTER_DEBUG skb->nf_debug = 1 << NF_IP_LOCAL_OUT; #endif /* CONFIG_NETFILTER_DEBUG */ + skb->nfmark = NFMARK_IPVS_PROPERTY; ip_send(skb); #if 0000 diff -ur orig/ipvs/ip_vs_core.c ipvs/ip_vs_core.c --- orig/ipvs/ip_vs_core.c Wed Jan 10 07:42:53 2001 +++ ipvs/ip_vs_core.c Sun Jan 21 14:00:36 2001 @@ -498,6 +498,20 @@ return NF_STOLEN; } +static unsigned int ip_vs_post_routing(unsigned int hooknum, + struct sk_buff **skb_p, + const struct net_device *in, + const struct net_device *out, + int (*okfn)(struct sk_buff *)) +{ +struct sk_buff *skb = *skb_p; + + if (skb->nfmark != NFMARK_IPVS_PROPERTY) return NF_ACCEPT; + + /* The packet was sent from IPVS, exit this chain */ + (*okfn)(skb); + return NF_STOLEN; +} /* * Handle ICMP messages in the inside-to-outside direction (outgoing). @@ -594,6 +608,8 @@ NIPQUAD(ciph->saddr), ntohs(pptr[0]), NIPQUAD(ciph->daddr), ntohs(pptr[1])); + skb->nfmark = NFMARK_IPVS_PROPERTY; + return NF_ACCEPT; } @@ -610,22 +626,21 @@ int (*okfn)(struct sk_buff *)) { struct sk_buff *skb = *skb_p; - struct iphdr *iph = skb->nh.iph; + struct iphdr *iph; union ip_vs_tphdr h; struct ip_vs_conn *cp; - int size; - + int size, doff, csum, csum_ok; /* * doff holds transport protocol data offset * csum holds its checksum * csum_ok says if csum is valid */ - int doff = 0; - int csum = 0; - int csum_ok = 0; + + if (skb->nfmark == NFMARK_IPVS_PROPERTY) return NF_ACCEPT; EnterFunction(11); + iph = skb->nh.iph; h.raw = (char*) iph + iph->ihl * 4; size = ntohs(iph->tot_len) - (iph->ihl * 4); doff = ip_vs_proto_doff(iph->protocol, h.raw, size); @@ -676,6 +691,9 @@ } /* Check if the checksum is OK, when it is not UDP or check!=0 */ + csum = 0; + csum_ok = 0; + if ((iph->protocol != IPPROTO_UDP) || (h.uh->check != 0)) { switch (skb->ip_summed) { @@ -782,6 +800,8 @@ ip_vs_set_state(cp, VS_STATE_OUTPUT, iph, h.portp); ip_vs_conn_put(cp); + skb->nfmark = NFMARK_IPVS_PROPERTY; + LeaveFunction(11); return NF_ACCEPT; } @@ -959,7 +979,7 @@ union ip_vs_tphdr h; struct ip_vs_conn *cp; unsigned short size; - int doff = 0; + int doff; struct ip_vs_service *svc; /* @@ -1084,6 +1104,12 @@ ip_vs_out, PF_INET, /* NF_IP_POST_ROUTING */NF_IP_FORWARD, 100 }; +/* Before the netfilter NAT code, exit from POST_ROUTING */ +static struct nf_hook_ops ip_vs_post_routing_ops = { + { NULL, NULL }, + ip_vs_post_routing, PF_INET, NF_IP_POST_ROUTING, NF_IP_PRI_NAT_SRC-1 +}; + /* * Initialize IP Virtual Server @@ -1122,10 +1148,17 @@ IP_VS_ERR("can't register out hook.\n"); goto cleanup_inops; } + ret = nf_register_hook(&ip_vs_post_routing_ops); + if (ret < 0) { + IP_VS_ERR("can't register post_routing hook.\n"); + goto cleanup_outops; + } IP_VS_INFO("ipvs loaded.\n"); return ret; + cleanup_outops: + nf_unregister_hook(&ip_vs_out_ops); cleanup_inops: nf_unregister_hook(&ip_vs_in_ops); cleanup_app: @@ -1141,6 +1174,7 @@ static void __exit ip_vs_cleanup(void) { + nf_unregister_hook(&ip_vs_post_routing_ops); nf_unregister_hook(&ip_vs_out_ops); nf_unregister_hook(&ip_vs_in_ops); ip_vs_app_cleanup();