2 * ip_vs_proto_icmp.c: ICMP load balancing support for IP Virtual Server
4 * Authors: Julian Anastasov <ja@ssi.bg>, March 2002
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation;
12 #include <linux/module.h>
13 #include <linux/kernel.h>
14 #include <linux/icmp.h>
15 #include <linux/netfilter.h>
16 #include <linux/netfilter_ipv4.h>
18 #include <net/ip_vs.h>
21 static int icmp_timeouts
[1] = { 1*60*HZ
};
23 static char * icmp_state_name_table
[1] = { "ICMP" };
25 static struct ip_vs_conn
*
26 icmp_conn_in_get(const struct sk_buff
*skb
,
27 struct ip_vs_protocol
*pp
,
28 const struct iphdr
*iph
,
29 unsigned int proto_off
,
33 struct ip_vs_conn
*cp
;
35 if (likely(!inverse
)) {
36 cp
= ip_vs_conn_in_get(iph
->protocol
,
40 cp
= ip_vs_conn_in_get(iph
->protocol
,
52 static struct ip_vs_conn
*
53 icmp_conn_out_get(const struct sk_buff
*skb
,
54 struct ip_vs_protocol
*pp
,
55 const struct iphdr
*iph
,
56 unsigned int proto_off
,
60 struct ip_vs_conn
*cp
;
62 if (likely(!inverse
)) {
63 cp
= ip_vs_conn_out_get(iph
->protocol
,
67 cp
= ip_vs_conn_out_get(IPPROTO_UDP
,
79 icmp_conn_schedule(struct sk_buff
*skb
, struct ip_vs_protocol
*pp
,
80 int *verdict
, struct ip_vs_conn
**cpp
)
87 icmp_csum_check(struct sk_buff
*skb
, struct ip_vs_protocol
*pp
)
89 if (!(skb
->nh
.iph
->frag_off
& __constant_htons(IP_OFFSET
))) {
90 if (skb
->ip_summed
!= CHECKSUM_UNNECESSARY
) {
91 if (ip_vs_checksum_complete(skb
, skb
->nh
.iph
->ihl
* 4)) {
92 IP_VS_DBG_RL_PKT(0, pp
, skb
, 0, "Failed checksum for");
101 icmp_debug_packet(struct ip_vs_protocol
*pp
,
102 const struct sk_buff
*skb
,
107 struct iphdr _iph
, *ih
;
109 ih
= skb_header_pointer(skb
, offset
, sizeof(_iph
), &_iph
);
111 sprintf(buf
, "%s TRUNCATED", pp
->name
);
112 else if (ih
->frag_off
& __constant_htons(IP_OFFSET
))
113 sprintf(buf
, "%s %u.%u.%u.%u->%u.%u.%u.%u frag",
114 pp
->name
, NIPQUAD(ih
->saddr
),
117 struct icmphdr _icmph
, *ic
;
119 ic
= skb_header_pointer(skb
, offset
+ ih
->ihl
*4,
120 sizeof(_icmph
), &_icmph
);
122 sprintf(buf
, "%s TRUNCATED to %u bytes\n",
123 pp
->name
, skb
->len
- offset
);
125 sprintf(buf
, "%s %u.%u.%u.%u->%u.%u.%u.%u T:%d C:%d",
126 pp
->name
, NIPQUAD(ih
->saddr
),
130 printk(KERN_DEBUG
"IPVS: %s: %s\n", msg
, buf
);
134 icmp_state_transition(struct ip_vs_conn
*cp
, int direction
,
135 const struct sk_buff
*skb
,
136 struct ip_vs_protocol
*pp
)
138 cp
->timeout
= pp
->timeout_table
[IP_VS_ICMP_S_NORMAL
];
143 icmp_set_state_timeout(struct ip_vs_protocol
*pp
, char *sname
, int to
)
148 num
= IP_VS_ICMP_S_LAST
;
149 names
= icmp_state_name_table
;
150 return ip_vs_set_state_timeout(pp
->timeout_table
, num
, names
, sname
, to
);
154 static void icmp_init(struct ip_vs_protocol
*pp
)
156 pp
->timeout_table
= icmp_timeouts
;
159 static void icmp_exit(struct ip_vs_protocol
*pp
)
163 struct ip_vs_protocol ip_vs_protocol_icmp
= {
165 .protocol
= IPPROTO_ICMP
,
169 .conn_schedule
= icmp_conn_schedule
,
170 .conn_in_get
= icmp_conn_in_get
,
171 .conn_out_get
= icmp_conn_out_get
,
172 .snat_handler
= NULL
,
173 .dnat_handler
= NULL
,
174 .csum_check
= icmp_csum_check
,
175 .state_transition
= icmp_state_transition
,
176 .register_app
= NULL
,
177 .unregister_app
= NULL
,
178 .app_conn_bind
= NULL
,
179 .debug_packet
= icmp_debug_packet
,
180 .timeout_change
= NULL
,
181 .set_state_timeout
= icmp_set_state_timeout
,