/src/openvswitch/lib/conntrack-icmp.c
Line | Count | Source (jump to first uncovered line) |
1 | | /* |
2 | | * Copyright (c) 2015-2019 Nicira, Inc. |
3 | | * |
4 | | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | * you may not use this file except in compliance with the License. |
6 | | * You may obtain a copy of the License at: |
7 | | * |
8 | | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | | * |
10 | | * Unless required by applicable law or agreed to in writing, software |
11 | | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | * See the License for the specific language governing permissions and |
14 | | * limitations under the License. |
15 | | */ |
16 | | |
17 | | #include <config.h> |
18 | | |
19 | | #include <errno.h> |
20 | | #include <sys/types.h> |
21 | | #include <netinet/in.h> |
22 | | #include <netinet/icmp6.h> |
23 | | |
24 | | #include "conntrack-private.h" |
25 | | #include "conntrack-tp.h" |
26 | | #include "dp-packet.h" |
27 | | |
28 | | enum OVS_PACKED_ENUM icmp_state { |
29 | | ICMPS_FIRST, |
30 | | ICMPS_REPLY, |
31 | | }; |
32 | | |
33 | | struct conn_icmp { |
34 | | struct conn up; |
35 | | enum icmp_state state; /* 'conn' lock protected. */ |
36 | | }; |
37 | | |
38 | | static const enum ct_timeout icmp_timeouts[] = { |
39 | | [ICMPS_FIRST] = CT_TM_ICMP_FIRST, |
40 | | [ICMPS_REPLY] = CT_TM_ICMP_REPLY, |
41 | | }; |
42 | | |
43 | | static struct conn_icmp * |
44 | | conn_icmp_cast(const struct conn *conn) |
45 | 0 | { |
46 | 0 | return CONTAINER_OF(conn, struct conn_icmp, up); |
47 | 0 | } |
48 | | |
49 | | static enum ct_update_res |
50 | | icmp_conn_update(struct conntrack *ct, struct conn *conn_, |
51 | | struct dp_packet *pkt OVS_UNUSED, bool reply, long long now) |
52 | 0 | { |
53 | 0 | struct conn_icmp *conn = conn_icmp_cast(conn_); |
54 | 0 | enum ct_update_res ret = CT_UPDATE_VALID; |
55 | |
|
56 | 0 | if (reply && conn->state == ICMPS_FIRST) { |
57 | 0 | conn->state = ICMPS_REPLY; |
58 | 0 | } else if (conn->state == ICMPS_FIRST) { |
59 | 0 | ret = CT_UPDATE_VALID_NEW; |
60 | 0 | } |
61 | |
|
62 | 0 | conn_update_expiration(ct, &conn->up, icmp_timeouts[conn->state], now); |
63 | 0 | return ret; |
64 | 0 | } |
65 | | |
66 | | static bool |
67 | | icmp4_valid_new(struct dp_packet *pkt) |
68 | 0 | { |
69 | 0 | struct icmp_header *icmp = dp_packet_l4(pkt); |
70 | |
|
71 | 0 | return icmp->icmp_type == ICMP4_ECHO_REQUEST |
72 | 0 | || icmp->icmp_type == ICMP4_INFOREQUEST |
73 | 0 | || icmp->icmp_type == ICMP4_TIMESTAMP; |
74 | 0 | } |
75 | | |
76 | | static bool |
77 | | icmp6_valid_new(struct dp_packet *pkt) |
78 | 0 | { |
79 | 0 | struct icmp6_header *icmp6 = dp_packet_l4(pkt); |
80 | |
|
81 | 0 | return icmp6->icmp6_type == ICMP6_ECHO_REQUEST; |
82 | 0 | } |
83 | | |
84 | | static struct conn * |
85 | | icmp_new_conn(struct conntrack *ct, struct dp_packet *pkt OVS_UNUSED, |
86 | | long long now, uint32_t tp_id) |
87 | 0 | { |
88 | 0 | struct conn_icmp *conn = xzalloc(sizeof *conn); |
89 | 0 | conn->state = ICMPS_FIRST; |
90 | 0 | conn->up.tp_id = tp_id; |
91 | |
|
92 | 0 | conn_init_expiration(ct, &conn->up, icmp_timeouts[conn->state], now); |
93 | 0 | return &conn->up; |
94 | 0 | } |
95 | | |
96 | | struct ct_l4_proto ct_proto_icmp4 = { |
97 | | .new_conn = icmp_new_conn, |
98 | | .valid_new = icmp4_valid_new, |
99 | | .conn_update = icmp_conn_update, |
100 | | }; |
101 | | |
102 | | struct ct_l4_proto ct_proto_icmp6 = { |
103 | | .new_conn = icmp_new_conn, |
104 | | .valid_new = icmp6_valid_new, |
105 | | .conn_update = icmp_conn_update, |
106 | | }; |