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