1 /* (C) 1999-2001 Paul `Rusty' Russell 2 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org> 3 * (C) 2006-2010 Patrick McHardy <kaber@trash.net> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License version 2 as 7 * published by the Free Software Foundation. 8 */ 9 10 #include <linux/types.h> 11 #include <linux/timer.h> 12 #include <linux/netfilter.h> 13 #include <linux/in.h> 14 #include <linux/icmp.h> 15 #include <linux/seq_file.h> 16 #include <net/ip.h> 17 #include <net/checksum.h> 18 #include <linux/netfilter_ipv4.h> 19 #include <net/netfilter/nf_conntrack_tuple.h> 20 #include <net/netfilter/nf_conntrack_l4proto.h> 21 #include <net/netfilter/nf_conntrack_core.h> 22 #include <net/netfilter/nf_conntrack_timeout.h> 23 #include <net/netfilter/nf_conntrack_zones.h> 24 #include <net/netfilter/nf_log.h> 25 26 static const unsigned int nf_ct_icmp_timeout = 30*HZ; 27 28 bool icmp_pkt_to_tuple(const struct sk_buff *skb, unsigned int dataoff, 29 struct net *net, struct nf_conntrack_tuple *tuple) 30 { 31 const struct icmphdr *hp; 32 struct icmphdr _hdr; 33 34 hp = skb_header_pointer(skb, dataoff, sizeof(_hdr), &_hdr); 35 if (hp == NULL) 36 return false; 37 38 tuple->dst.u.icmp.type = hp->type; 39 tuple->src.u.icmp.id = hp->un.echo.id; 40 tuple->dst.u.icmp.code = hp->code; 41 42 return true; 43 } 44 45 /* Add 1; spaces filled with 0. */ 46 static const u_int8_t invmap[] = { 47 [ICMP_ECHO] = ICMP_ECHOREPLY + 1, 48 [ICMP_ECHOREPLY] = ICMP_ECHO + 1, 49 [ICMP_TIMESTAMP] = ICMP_TIMESTAMPREPLY + 1, 50 [ICMP_TIMESTAMPREPLY] = ICMP_TIMESTAMP + 1, 51 [ICMP_INFO_REQUEST] = ICMP_INFO_REPLY + 1, 52 [ICMP_INFO_REPLY] = ICMP_INFO_REQUEST + 1, 53 [ICMP_ADDRESS] = ICMP_ADDRESSREPLY + 1, 54 [ICMP_ADDRESSREPLY] = ICMP_ADDRESS + 1 55 }; 56 57 bool nf_conntrack_invert_icmp_tuple(struct nf_conntrack_tuple *tuple, 58 const struct nf_conntrack_tuple *orig) 59 { 60 if (orig->dst.u.icmp.type >= sizeof(invmap) || 61 !invmap[orig->dst.u.icmp.type]) 62 return false; 63 64 tuple->src.u.icmp.id = orig->src.u.icmp.id; 65 tuple->dst.u.icmp.type = invmap[orig->dst.u.icmp.type] - 1; 66 tuple->dst.u.icmp.code = orig->dst.u.icmp.code; 67 return true; 68 } 69 70 /* Returns verdict for packet, or -1 for invalid. */ 71 int nf_conntrack_icmp_packet(struct nf_conn *ct, 72 struct sk_buff *skb, 73 enum ip_conntrack_info ctinfo, 74 const struct nf_hook_state *state) 75 { 76 /* Do not immediately delete the connection after the first 77 successful reply to avoid excessive conntrackd traffic 78 and also to handle correctly ICMP echo reply duplicates. */ 79 unsigned int *timeout = nf_ct_timeout_lookup(ct); 80 static const u_int8_t valid_new[] = { 81 [ICMP_ECHO] = 1, 82 [ICMP_TIMESTAMP] = 1, 83 [ICMP_INFO_REQUEST] = 1, 84 [ICMP_ADDRESS] = 1 85 }; 86 87 if (state->pf != NFPROTO_IPV4) 88 return -NF_ACCEPT; 89 90 if (ct->tuplehash[0].tuple.dst.u.icmp.type >= sizeof(valid_new) || 91 !valid_new[ct->tuplehash[0].tuple.dst.u.icmp.type]) { 92 /* Can't create a new ICMP `conn' with this. */ 93 pr_debug("icmp: can't create new conn with type %u\n", 94 ct->tuplehash[0].tuple.dst.u.icmp.type); 95 nf_ct_dump_tuple_ip(&ct->tuplehash[0].tuple); 96 return -NF_ACCEPT; 97 } 98 99 if (!timeout) 100 timeout = &nf_icmp_pernet(nf_ct_net(ct))->timeout; 101 102 nf_ct_refresh_acct(ct, ctinfo, skb, *timeout); 103 return NF_ACCEPT; 104 } 105 106 /* Check inner header is related to any of the existing connections */ 107 int nf_conntrack_inet_error(struct nf_conn *tmpl, struct sk_buff *skb, 108 unsigned int dataoff, 109 const struct nf_hook_state *state, 110 u8 l4proto, union nf_inet_addr *outer_daddr) 111 { 112 struct nf_conntrack_tuple innertuple, origtuple; 113 const struct nf_conntrack_tuple_hash *h; 114 const struct nf_conntrack_zone *zone; 115 enum ip_conntrack_info ctinfo; 116 struct nf_conntrack_zone tmp; 117 union nf_inet_addr *ct_daddr; 118 enum ip_conntrack_dir dir; 119 struct nf_conn *ct; 120 121 WARN_ON(skb_nfct(skb)); 122 zone = nf_ct_zone_tmpl(tmpl, skb, &tmp); 123 124 /* Are they talking about one of our connections? */ 125 if (!nf_ct_get_tuplepr(skb, dataoff, 126 state->pf, state->net, &origtuple)) 127 return -NF_ACCEPT; 128 129 /* Ordinarily, we'd expect the inverted tupleproto, but it's 130 been preserved inside the ICMP. */ 131 if (!nf_ct_invert_tuple(&innertuple, &origtuple)) 132 return -NF_ACCEPT; 133 134 h = nf_conntrack_find_get(state->net, zone, &innertuple); 135 if (!h) 136 return -NF_ACCEPT; 137 138 /* Consider: A -> T (=This machine) -> B 139 * Conntrack entry will look like this: 140 * Original: A->B 141 * Reply: B->T (SNAT case) OR A 142 * 143 * When this function runs, we got packet that looks like this: 144 * iphdr|icmphdr|inner_iphdr|l4header (tcp, udp, ..). 145 * 146 * Above nf_conntrack_find_get() makes lookup based on inner_hdr, 147 * so we should expect that destination of the found connection 148 * matches outer header destination address. 149 * 150 * In above example, we can consider these two cases: 151 * 1. Error coming in reply direction from B or M (middle box) to 152 * T (SNAT case) or A. 153 * Inner saddr will be B, dst will be T or A. 154 * The found conntrack will be reply tuple (B->T/A). 155 * 2. Error coming in original direction from A or M to B. 156 * Inner saddr will be A, inner daddr will be B. 157 * The found conntrack will be original tuple (A->B). 158 * 159 * In both cases, conntrack[dir].dst == inner.dst. 160 * 161 * A bogus packet could look like this: 162 * Inner: B->T 163 * Outer: B->X (other machine reachable by T). 164 * 165 * In this case, lookup yields connection A->B and will 166 * set packet from B->X as *RELATED*, even though no connection 167 * from X was ever seen. 168 */ 169 ct = nf_ct_tuplehash_to_ctrack(h); 170 dir = NF_CT_DIRECTION(h); 171 ct_daddr = &ct->tuplehash[dir].tuple.dst.u3; 172 if (!nf_inet_addr_cmp(outer_daddr, ct_daddr)) { 173 if (state->pf == AF_INET) { 174 nf_l4proto_log_invalid(skb, state->net, state->pf, 175 l4proto, 176 "outer daddr %pI4 != inner %pI4", 177 &outer_daddr->ip, &ct_daddr->ip); 178 } else if (state->pf == AF_INET6) { 179 nf_l4proto_log_invalid(skb, state->net, state->pf, 180 l4proto, 181 "outer daddr %pI6 != inner %pI6", 182 &outer_daddr->ip6, &ct_daddr->ip6); 183 } 184 nf_ct_put(ct); 185 return -NF_ACCEPT; 186 } 187 188 ctinfo = IP_CT_RELATED; 189 if (dir == IP_CT_DIR_REPLY) 190 ctinfo += IP_CT_IS_REPLY; 191 192 /* Update skb to refer to this connection */ 193 nf_ct_set(skb, ct, ctinfo); 194 return NF_ACCEPT; 195 } 196 197 static void icmp_error_log(const struct sk_buff *skb, 198 const struct nf_hook_state *state, 199 const char *msg) 200 { 201 nf_l4proto_log_invalid(skb, state->net, state->pf, 202 IPPROTO_ICMP, "%s", msg); 203 } 204 205 /* Small and modified version of icmp_rcv */ 206 int nf_conntrack_icmpv4_error(struct nf_conn *tmpl, 207 struct sk_buff *skb, unsigned int dataoff, 208 const struct nf_hook_state *state) 209 { 210 union nf_inet_addr outer_daddr; 211 const struct icmphdr *icmph; 212 struct icmphdr _ih; 213 214 /* Not enough header? */ 215 icmph = skb_header_pointer(skb, dataoff, sizeof(_ih), &_ih); 216 if (icmph == NULL) { 217 icmp_error_log(skb, state, "short packet"); 218 return -NF_ACCEPT; 219 } 220 221 /* See ip_conntrack_proto_tcp.c */ 222 if (state->net->ct.sysctl_checksum && 223 state->hook == NF_INET_PRE_ROUTING && 224 nf_ip_checksum(skb, state->hook, dataoff, 0)) { 225 icmp_error_log(skb, state, "bad hw icmp checksum"); 226 return -NF_ACCEPT; 227 } 228 229 /* 230 * 18 is the highest 'known' ICMP type. Anything else is a mystery 231 * 232 * RFC 1122: 3.2.2 Unknown ICMP messages types MUST be silently 233 * discarded. 234 */ 235 if (icmph->type > NR_ICMP_TYPES) { 236 icmp_error_log(skb, state, "invalid icmp type"); 237 return -NF_ACCEPT; 238 } 239 240 /* Need to track icmp error message? */ 241 if (icmph->type != ICMP_DEST_UNREACH && 242 icmph->type != ICMP_SOURCE_QUENCH && 243 icmph->type != ICMP_TIME_EXCEEDED && 244 icmph->type != ICMP_PARAMETERPROB && 245 icmph->type != ICMP_REDIRECT) 246 return NF_ACCEPT; 247 248 memset(&outer_daddr, 0, sizeof(outer_daddr)); 249 outer_daddr.ip = ip_hdr(skb)->daddr; 250 251 dataoff += sizeof(*icmph); 252 return nf_conntrack_inet_error(tmpl, skb, dataoff, state, 253 IPPROTO_ICMP, &outer_daddr); 254 } 255 256 #if IS_ENABLED(CONFIG_NF_CT_NETLINK) 257 258 #include <linux/netfilter/nfnetlink.h> 259 #include <linux/netfilter/nfnetlink_conntrack.h> 260 261 static int icmp_tuple_to_nlattr(struct sk_buff *skb, 262 const struct nf_conntrack_tuple *t) 263 { 264 if (nla_put_be16(skb, CTA_PROTO_ICMP_ID, t->src.u.icmp.id) || 265 nla_put_u8(skb, CTA_PROTO_ICMP_TYPE, t->dst.u.icmp.type) || 266 nla_put_u8(skb, CTA_PROTO_ICMP_CODE, t->dst.u.icmp.code)) 267 goto nla_put_failure; 268 return 0; 269 270 nla_put_failure: 271 return -1; 272 } 273 274 static const struct nla_policy icmp_nla_policy[CTA_PROTO_MAX+1] = { 275 [CTA_PROTO_ICMP_TYPE] = { .type = NLA_U8 }, 276 [CTA_PROTO_ICMP_CODE] = { .type = NLA_U8 }, 277 [CTA_PROTO_ICMP_ID] = { .type = NLA_U16 }, 278 }; 279 280 static int icmp_nlattr_to_tuple(struct nlattr *tb[], 281 struct nf_conntrack_tuple *tuple) 282 { 283 if (!tb[CTA_PROTO_ICMP_TYPE] || 284 !tb[CTA_PROTO_ICMP_CODE] || 285 !tb[CTA_PROTO_ICMP_ID]) 286 return -EINVAL; 287 288 tuple->dst.u.icmp.type = nla_get_u8(tb[CTA_PROTO_ICMP_TYPE]); 289 tuple->dst.u.icmp.code = nla_get_u8(tb[CTA_PROTO_ICMP_CODE]); 290 tuple->src.u.icmp.id = nla_get_be16(tb[CTA_PROTO_ICMP_ID]); 291 292 if (tuple->dst.u.icmp.type >= sizeof(invmap) || 293 !invmap[tuple->dst.u.icmp.type]) 294 return -EINVAL; 295 296 return 0; 297 } 298 299 static unsigned int icmp_nlattr_tuple_size(void) 300 { 301 static unsigned int size __read_mostly; 302 303 if (!size) 304 size = nla_policy_len(icmp_nla_policy, CTA_PROTO_MAX + 1); 305 306 return size; 307 } 308 #endif 309 310 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 311 312 #include <linux/netfilter/nfnetlink.h> 313 #include <linux/netfilter/nfnetlink_cttimeout.h> 314 315 static int icmp_timeout_nlattr_to_obj(struct nlattr *tb[], 316 struct net *net, void *data) 317 { 318 unsigned int *timeout = data; 319 struct nf_icmp_net *in = nf_icmp_pernet(net); 320 321 if (tb[CTA_TIMEOUT_ICMP_TIMEOUT]) { 322 if (!timeout) 323 timeout = &in->timeout; 324 *timeout = 325 ntohl(nla_get_be32(tb[CTA_TIMEOUT_ICMP_TIMEOUT])) * HZ; 326 } else if (timeout) { 327 /* Set default ICMP timeout. */ 328 *timeout = in->timeout; 329 } 330 return 0; 331 } 332 333 static int 334 icmp_timeout_obj_to_nlattr(struct sk_buff *skb, const void *data) 335 { 336 const unsigned int *timeout = data; 337 338 if (nla_put_be32(skb, CTA_TIMEOUT_ICMP_TIMEOUT, htonl(*timeout / HZ))) 339 goto nla_put_failure; 340 return 0; 341 342 nla_put_failure: 343 return -ENOSPC; 344 } 345 346 static const struct nla_policy 347 icmp_timeout_nla_policy[CTA_TIMEOUT_ICMP_MAX+1] = { 348 [CTA_TIMEOUT_ICMP_TIMEOUT] = { .type = NLA_U32 }, 349 }; 350 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 351 352 void nf_conntrack_icmp_init_net(struct net *net) 353 { 354 struct nf_icmp_net *in = nf_icmp_pernet(net); 355 356 in->timeout = nf_ct_icmp_timeout; 357 } 358 359 const struct nf_conntrack_l4proto nf_conntrack_l4proto_icmp = 360 { 361 .l4proto = IPPROTO_ICMP, 362 #if IS_ENABLED(CONFIG_NF_CT_NETLINK) 363 .tuple_to_nlattr = icmp_tuple_to_nlattr, 364 .nlattr_tuple_size = icmp_nlattr_tuple_size, 365 .nlattr_to_tuple = icmp_nlattr_to_tuple, 366 .nla_policy = icmp_nla_policy, 367 #endif 368 #ifdef CONFIG_NF_CONNTRACK_TIMEOUT 369 .ctnl_timeout = { 370 .nlattr_to_obj = icmp_timeout_nlattr_to_obj, 371 .obj_to_nlattr = icmp_timeout_obj_to_nlattr, 372 .nlattr_max = CTA_TIMEOUT_ICMP_MAX, 373 .obj_size = sizeof(unsigned int), 374 .nla_policy = icmp_timeout_nla_policy, 375 }, 376 #endif /* CONFIG_NF_CONNTRACK_TIMEOUT */ 377 }; 378