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 28 struct 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 static void 44 ah_esp_conn_fill_param_proto(struct netns_ipvs *ipvs, int af, 45 const struct ip_vs_iphdr *iph, 46 struct ip_vs_conn_param *p) 47 { 48 if (likely(!ip_vs_iph_inverse(iph))) 49 ip_vs_conn_fill_param(ipvs, af, IPPROTO_UDP, 50 &iph->saddr, htons(PORT_ISAKMP), 51 &iph->daddr, htons(PORT_ISAKMP), p); 52 else 53 ip_vs_conn_fill_param(ipvs, af, IPPROTO_UDP, 54 &iph->daddr, htons(PORT_ISAKMP), 55 &iph->saddr, htons(PORT_ISAKMP), p); 56 } 57 58 static struct ip_vs_conn * 59 ah_esp_conn_in_get(struct netns_ipvs *ipvs, int af, const struct sk_buff *skb, 60 const struct ip_vs_iphdr *iph) 61 { 62 struct ip_vs_conn *cp; 63 struct ip_vs_conn_param p; 64 65 ah_esp_conn_fill_param_proto(ipvs, af, iph, &p); 66 cp = ip_vs_conn_in_get(&p); 67 if (!cp) { 68 /* 69 * We are not sure if the packet is from our 70 * service, so our conn_schedule hook should return NF_ACCEPT 71 */ 72 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for outin packet " 73 "%s%s %s->%s\n", 74 ip_vs_iph_icmp(iph) ? "ICMP+" : "", 75 ip_vs_proto_get(iph->protocol)->name, 76 IP_VS_DBG_ADDR(af, &iph->saddr), 77 IP_VS_DBG_ADDR(af, &iph->daddr)); 78 } 79 80 return cp; 81 } 82 83 84 static struct ip_vs_conn * 85 ah_esp_conn_out_get(struct netns_ipvs *ipvs, int af, const struct sk_buff *skb, 86 const struct ip_vs_iphdr *iph) 87 { 88 struct ip_vs_conn *cp; 89 struct ip_vs_conn_param p; 90 91 ah_esp_conn_fill_param_proto(ipvs, af, iph, &p); 92 cp = ip_vs_conn_out_get(&p); 93 if (!cp) { 94 IP_VS_DBG_BUF(12, "Unknown ISAKMP entry for inout packet " 95 "%s%s %s->%s\n", 96 ip_vs_iph_icmp(iph) ? "ICMP+" : "", 97 ip_vs_proto_get(iph->protocol)->name, 98 IP_VS_DBG_ADDR(af, &iph->saddr), 99 IP_VS_DBG_ADDR(af, &iph->daddr)); 100 } 101 102 return cp; 103 } 104 105 106 static int 107 ah_esp_conn_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb, 108 struct ip_vs_proto_data *pd, 109 int *verdict, struct ip_vs_conn **cpp, 110 struct ip_vs_iphdr *iph) 111 { 112 /* 113 * AH/ESP is only related traffic. Pass the packet to IP stack. 114 */ 115 *verdict = NF_ACCEPT; 116 return 0; 117 } 118 119 #ifdef CONFIG_IP_VS_PROTO_AH 120 struct ip_vs_protocol ip_vs_protocol_ah = { 121 .name = "AH", 122 .protocol = IPPROTO_AH, 123 .num_states = 1, 124 .dont_defrag = 1, 125 .init = NULL, 126 .exit = NULL, 127 .conn_schedule = ah_esp_conn_schedule, 128 .conn_in_get = ah_esp_conn_in_get, 129 .conn_out_get = ah_esp_conn_out_get, 130 .snat_handler = NULL, 131 .dnat_handler = NULL, 132 .state_transition = NULL, 133 .register_app = NULL, 134 .unregister_app = NULL, 135 .app_conn_bind = NULL, 136 .debug_packet = ip_vs_tcpudp_debug_packet, 137 .timeout_change = NULL, /* ISAKMP */ 138 }; 139 #endif 140 141 #ifdef CONFIG_IP_VS_PROTO_ESP 142 struct ip_vs_protocol ip_vs_protocol_esp = { 143 .name = "ESP", 144 .protocol = IPPROTO_ESP, 145 .num_states = 1, 146 .dont_defrag = 1, 147 .init = NULL, 148 .exit = NULL, 149 .conn_schedule = ah_esp_conn_schedule, 150 .conn_in_get = ah_esp_conn_in_get, 151 .conn_out_get = ah_esp_conn_out_get, 152 .snat_handler = NULL, 153 .dnat_handler = NULL, 154 .state_transition = NULL, 155 .register_app = NULL, 156 .unregister_app = NULL, 157 .app_conn_bind = NULL, 158 .debug_packet = ip_vs_tcpudp_debug_packet, 159 .timeout_change = NULL, /* ISAKMP */ 160 }; 161 #endif 162