1/* 2 * ip_vs_proto_esp.c: ESP IPSec load balancing support for IPVS 3 * 4 * Version: $Id: ip_vs_proto_esp.c,v 1.1.1.1 2007/08/03 18:53:52 Exp $ 5 * 6 * Authors: Julian Anastasov <ja@ssi.bg>, February 2002 7 * Wensong Zhang <wensong@linuxvirtualserver.org> 8 * 9 * This program is free software; you can redistribute it and/or 10 * modify it under the terms of the GNU General Public License 11 * version 2 as published by the Free Software Foundation; 12 * 13 */ 14 15#include <linux/in.h> 16#include <linux/ip.h> 17#include <linux/module.h> 18#include <linux/kernel.h> 19#include <linux/netfilter.h> 20#include <linux/netfilter_ipv4.h> 21 22#include <net/ip_vs.h> 23 24 25/* TODO: 26 27struct isakmp_hdr { 28 __u8 icookie[8]; 29 __u8 rcookie[8]; 30 __u8 np; 31 __u8 version; 32 __u8 xchgtype; 33 __u8 flags; 34 __u32 msgid; 35 __u32 length; 36}; 37 38*/ 39 40#define PORT_ISAKMP 500 41 42 43static struct ip_vs_conn * 44esp_conn_in_get(const struct sk_buff *skb, 45 struct ip_vs_protocol *pp, 46 const struct iphdr *iph, 47 unsigned int proto_off, 48 int inverse) 49{ 50 struct ip_vs_conn *cp; 51 52 if (likely(!inverse)) { 53 cp = ip_vs_conn_in_get(IPPROTO_UDP, 54 iph->saddr, 55 __constant_htons(PORT_ISAKMP), 56 iph->daddr, 57 __constant_htons(PORT_ISAKMP)); 58 } else { 59 cp = ip_vs_conn_in_get(IPPROTO_UDP, 60 iph->daddr, 61 __constant_htons(PORT_ISAKMP), 62 iph->saddr, 63 __constant_htons(PORT_ISAKMP)); 64 } 65 66 if (!cp) { 67 /* 68 * We are not sure if the packet is from our 69 * service, so our conn_schedule hook should return NF_ACCEPT 70 */ 71 IP_VS_DBG(12, "Unknown ISAKMP entry for outin packet " 72 "%s%s %u.%u.%u.%u->%u.%u.%u.%u\n", 73 inverse ? "ICMP+" : "", 74 pp->name, 75 NIPQUAD(iph->saddr), 76 NIPQUAD(iph->daddr)); 77 } 78 79 return cp; 80} 81 82 83static struct ip_vs_conn * 84esp_conn_out_get(const struct sk_buff *skb, struct ip_vs_protocol *pp, 85 const struct iphdr *iph, unsigned int proto_off, int inverse) 86{ 87 struct ip_vs_conn *cp; 88 89 if (likely(!inverse)) { 90 cp = ip_vs_conn_out_get(IPPROTO_UDP, 91 iph->saddr, 92 __constant_htons(PORT_ISAKMP), 93 iph->daddr, 94 __constant_htons(PORT_ISAKMP)); 95 } else { 96 cp = ip_vs_conn_out_get(IPPROTO_UDP, 97 iph->daddr, 98 __constant_htons(PORT_ISAKMP), 99 iph->saddr, 100 __constant_htons(PORT_ISAKMP)); 101 } 102 103 if (!cp) { 104 IP_VS_DBG(12, "Unknown ISAKMP entry for inout packet " 105 "%s%s %u.%u.%u.%u->%u.%u.%u.%u\n", 106 inverse ? "ICMP+" : "", 107 pp->name, 108 NIPQUAD(iph->saddr), 109 NIPQUAD(iph->daddr)); 110 } 111 112 return cp; 113} 114 115 116static int 117esp_conn_schedule(struct sk_buff *skb, struct ip_vs_protocol *pp, 118 int *verdict, struct ip_vs_conn **cpp) 119{ 120 /* 121 * ESP is only related traffic. Pass the packet to IP stack. 122 */ 123 *verdict = NF_ACCEPT; 124 return 0; 125} 126 127 128static void 129esp_debug_packet(struct ip_vs_protocol *pp, const struct sk_buff *skb, 130 int offset, const char *msg) 131{ 132 char buf[256]; 133 struct iphdr _iph, *ih; 134 135 ih = skb_header_pointer(skb, offset, sizeof(_iph), &_iph); 136 if (ih == NULL) 137 sprintf(buf, "%s TRUNCATED", pp->name); 138 else 139 sprintf(buf, "%s %u.%u.%u.%u->%u.%u.%u.%u", 140 pp->name, NIPQUAD(ih->saddr), 141 NIPQUAD(ih->daddr)); 142 143 printk(KERN_DEBUG "IPVS: %s: %s\n", msg, buf); 144} 145 146 147static void esp_init(struct ip_vs_protocol *pp) 148{ 149 /* nothing to do now */ 150} 151 152 153static void esp_exit(struct ip_vs_protocol *pp) 154{ 155 /* nothing to do now */ 156} 157 158 159struct ip_vs_protocol ip_vs_protocol_esp = { 160 .name = "ESP", 161 .protocol = IPPROTO_ESP, 162 .dont_defrag = 1, 163 .init = esp_init, 164 .exit = esp_exit, 165 .conn_schedule = esp_conn_schedule, 166 .conn_in_get = esp_conn_in_get, 167 .conn_out_get = esp_conn_out_get, 168 .snat_handler = NULL, 169 .dnat_handler = NULL, 170 .csum_check = NULL, 171 .state_transition = NULL, 172 .register_app = NULL, 173 .unregister_app = NULL, 174 .app_conn_bind = NULL, 175 .debug_packet = esp_debug_packet, 176 .timeout_change = NULL, /* ISAKMP */ 177}; 178