linux/net/netfilter/ipvs/ip_vs_proto_ah_esp.c
<<
>>
Prefs
   1/*
   2 * ip_vs_proto_ah_esp.c:        AH/ESP IPSec load balancing support for IPVS
   3 *
   4 * Authors:     Julian Anastasov <ja@ssi.bg>, February 2002
   5 *              Wensong Zhang <wensong@linuxvirtualserver.org>
   6 *
   7 *              This program is free software; you can redistribute it and/or
   8 *              modify it under the terms of the GNU General Public License
   9 *              version 2 as published by the Free Software Foundation;
  10 *
  11 */
  12
  13#define KMSG_COMPONENT "IPVS"
  14#define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  15
  16#include <linux/in.h>
  17#include <linux/ip.h>
  18#include <linux/module.h>
  19#include <linux/kernel.h>
  20#include <linux/netfilter.h>
  21#include <linux/netfilter_ipv4.h>
  22
  23#include <net/ip_vs.h>
  24
  25
  26/* TODO:
  27
  28struct isakmp_hdr {
  29        __u8            icookie[8];
  30        __u8            rcookie[8];
  31        __u8            np;
  32        __u8            version;
  33        __u8            xchgtype;
  34        __u8            flags;
  35        __u32           msgid;
  36        __u32           length;
  37};
  38
  39*/
  40
  41#define PORT_ISAKMP     500
  42
  43
  44static struct ip_vs_conn *
  45ah_esp_conn_in_get(int af, const struct sk_buff *skb, struct ip_vs_protocol *pp,
  46                   const struct ip_vs_iphdr *iph, unsigned int proto_off,
  47                   int inverse)
  48{
  49        struct ip_vs_conn *cp;
  50
  51        if (likely(!inverse)) {
  52                cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
  53                                       &iph->saddr,
  54                                       htons(PORT_ISAKMP),
  55                                       &iph->daddr,
  56                                       htons(PORT_ISAKMP));
  57        } else {
  58                cp = ip_vs_conn_in_get(af, IPPROTO_UDP,
  59                                       &iph->daddr,
  60                                       htons(PORT_ISAKMP),
  61                                       &iph->saddr,
  62                                       htons(PORT_ISAKMP));
  63        }
  64
  65        if (!cp) {
  66                /*
  67                 * We are not sure if the packet is from our
  68                 * service, so our conn_schedule hook should return NF_ACCEPT
  69                 */
  70                IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet "
  71                              "%s%s %s->%s\n",
  72                              inverse ? "ICMP+" : "",
  73                              pp->name,
  74                              IP_VS_DBG_ADDR(af, &iph->saddr),
  75                              IP_VS_DBG_ADDR(af, &iph->daddr));
  76        }
  77
  78        return cp;
  79}
  80
  81
  82static struct ip_vs_conn *
  83ah_esp_conn_out_get(int af, const struct sk_buff *skb,
  84                    struct ip_vs_protocol *pp,
  85                    const struct ip_vs_iphdr *iph,
  86                    unsigned int proto_off,
  87                    int inverse)
  88{
  89        struct ip_vs_conn *cp;
  90
  91        if (likely(!inverse)) {
  92                cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
  93                                        &iph->saddr,
  94                                        htons(PORT_ISAKMP),
  95                                        &iph->daddr,
  96                                        htons(PORT_ISAKMP));
  97        } else {
  98                cp = ip_vs_conn_out_get(af, IPPROTO_UDP,
  99                                        &iph->daddr,
 100                                        htons(PORT_ISAKMP),
 101                                        &iph->saddr,
 102                                        htons(PORT_ISAKMP));
 103        }
 104
 105        if (!cp) {
 106                IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet "
 107                              "%s%s %s->%s\n",
 108                              inverse ? "ICMP+" : "",
 109                              pp->name,
 110                              IP_VS_DBG_ADDR(af, &iph->saddr),
 111                              IP_VS_DBG_ADDR(af, &iph->daddr));
 112        }
 113
 114        return cp;
 115}
 116
 117
 118static int
 119ah_esp_conn_schedule(int af, struct sk_buff *skb, struct ip_vs_protocol *pp,
 120                     int *verdict, struct ip_vs_conn **cpp)
 121{
 122        /*
 123         * AH/ESP is only related traffic. Pass the packet to IP stack.
 124         */
 125        *verdict = NF_ACCEPT;
 126        return 0;
 127}
 128
 129
 130static void
 131ah_esp_debug_packet_v4(struct ip_vs_protocol *pp, const struct sk_buff *skb,
 132                       int offset, const char *msg)
 133{
 134        char buf[256];
 135        struct iphdr _iph, *ih;
 136
 137        ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
 138        if (ih == NULL)
 139                sprintf(buf, "%s TRUNCATED", pp->name);
 140        else
 141                sprintf(buf, "%s %pI4->%pI4",
 142                        pp->name, &ih->saddr, &ih->daddr);
 143
 144        pr_debug("%s: %s\n", msg, buf);
 145}
 146
 147#ifdef CONFIG_IP_VS_IPV6
 148static void
 149ah_esp_debug_packet_v6(struct ip_vs_protocol *pp, const struct sk_buff *skb,
 150                       int offset, const char *msg)
 151{
 152        char buf[256];
 153        struct ipv6hdr _iph, *ih;
 154
 155        ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph);
 156        if (ih == NULL)
 157                sprintf(buf, "%s TRUNCATED", pp->name);
 158        else
 159                sprintf(buf, "%s %pI6->%pI6",
 160                        pp->name, &ih->saddr, &ih->daddr);
 161
 162        pr_debug("%s: %s\n", msg, buf);
 163}
 164#endif
 165
 166static void
 167ah_esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb,
 168                    int offset, const char *msg)
 169{
 170#ifdef CONFIG_IP_VS_IPV6
 171        if (skb->protocol == htons(ETH_P_IPV6))
 172                ah_esp_debug_packet_v6(pp, skb, offset, msg);
 173        else
 174#endif
 175                ah_esp_debug_packet_v4(pp, skb, offset, msg);
 176}
 177
 178
 179static void ah_esp_init(struct ip_vs_protocol *pp)
 180{
 181        /* nothing to do now */
 182}
 183
 184
 185static void ah_esp_exit(struct ip_vs_protocol *pp)
 186{
 187        /* nothing to do now */
 188}
 189
 190
 191#ifdef CONFIG_IP_VS_PROTO_AH
 192struct ip_vs_protocol ip_vs_protocol_ah = {
 193        .name =                 "AH",
 194        .protocol =             IPPROTO_AH,
 195        .num_states =           1,
 196        .dont_defrag =          1,
 197        .init =                 ah_esp_init,
 198        .exit =                 ah_esp_exit,
 199        .conn_schedule =        ah_esp_conn_schedule,
 200        .conn_in_get =          ah_esp_conn_in_get,
 201        .conn_out_get =         ah_esp_conn_out_get,
 202        .snat_handler =         NULL,
 203        .dnat_handler =         NULL,
 204        .csum_check =           NULL,
 205        .state_transition =     NULL,
 206        .register_app =         NULL,
 207        .unregister_app =       NULL,
 208        .app_conn_bind =        NULL,
 209        .debug_packet =         ah_esp_debug_packet,
 210        .timeout_change =       NULL,           /* ISAKMP */
 211        .set_state_timeout =    NULL,
 212};
 213#endif
 214
 215#ifdef CONFIG_IP_VS_PROTO_ESP
 216struct ip_vs_protocol ip_vs_protocol_esp = {
 217        .name =                 "ESP",
 218        .protocol =             IPPROTO_ESP,
 219        .num_states =           1,
 220        .dont_defrag =          1,
 221        .init =                 ah_esp_init,
 222        .exit =                 ah_esp_exit,
 223        .conn_schedule =        ah_esp_conn_schedule,
 224        .conn_in_get =          ah_esp_conn_in_get,
 225        .conn_out_get =         ah_esp_conn_out_get,
 226        .snat_handler =         NULL,
 227        .dnat_handler =         NULL,
 228        .csum_check =           NULL,
 229        .state_transition =     NULL,
 230        .register_app =         NULL,
 231        .unregister_app =       NULL,
 232        .app_conn_bind =        NULL,
 233        .debug_packet =         ah_esp_debug_packet,
 234        .timeout_change =       NULL,           /* ISAKMP */
 235};
 236#endif
 237