Branch data Line data Source code
1 : : /*
2 : : * Copyright (c) 2015, 2016 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 "dp-packet.h"
26 : :
27 : : enum icmp_state {
28 : : ICMPS_FIRST,
29 : : ICMPS_REPLY,
30 : : };
31 : :
32 : : struct conn_icmp {
33 : : struct conn up;
34 : : enum icmp_state state;
35 : : };
36 : :
37 : : static const enum ct_timeout icmp_timeouts[] = {
38 : : [ICMPS_FIRST] = CT_TM_ICMP_FIRST,
39 : : [ICMPS_REPLY] = CT_TM_ICMP_REPLY,
40 : : };
41 : :
42 : : static struct conn_icmp *
43 : 11 : conn_icmp_cast(const struct conn *conn)
44 : : {
45 : 11 : return CONTAINER_OF(conn, struct conn_icmp, up);
46 : : }
47 : :
48 : : static enum ct_update_res
49 : 11 : icmp_conn_update(struct conn *conn_, struct conntrack_bucket *ctb,
50 : : struct dp_packet *pkt OVS_UNUSED, bool reply, long long now)
51 : : {
52 : 11 : struct conn_icmp *conn = conn_icmp_cast(conn_);
53 : :
54 [ + + ][ + + ]: 11 : if (reply && conn->state != ICMPS_REPLY) {
55 : 3 : conn->state = ICMPS_REPLY;
56 : : }
57 : :
58 : 11 : conn_update_expiration(ctb, &conn->up, icmp_timeouts[conn->state], now);
59 : :
60 : 11 : return CT_UPDATE_VALID;
61 : : }
62 : :
63 : : static bool
64 : 10 : icmp4_valid_new(struct dp_packet *pkt)
65 : : {
66 : 10 : struct icmp_header *icmp = dp_packet_l4(pkt);
67 : :
68 : 10 : return icmp->icmp_type == ICMP4_ECHO_REQUEST
69 [ # # ]: 0 : || icmp->icmp_type == ICMP4_INFOREQUEST
70 [ - + ][ # # ]: 10 : || icmp->icmp_type == ICMP4_TIMESTAMP;
71 : : }
72 : :
73 : : static bool
74 : 9 : icmp6_valid_new(struct dp_packet *pkt)
75 : : {
76 : 9 : struct icmp6_header *icmp6 = dp_packet_l4(pkt);
77 : :
78 : 9 : return icmp6->icmp6_type == ICMP6_ECHO_REQUEST;
79 : : }
80 : :
81 : : static struct conn *
82 : 3 : icmp_new_conn(struct conntrack_bucket *ctb, struct dp_packet *pkt OVS_UNUSED,
83 : : long long now)
84 : : {
85 : : struct conn_icmp *conn;
86 : :
87 : 3 : conn = xzalloc(sizeof *conn);
88 : 3 : conn->state = ICMPS_FIRST;
89 : :
90 : 3 : conn_init_expiration(ctb, &conn->up, icmp_timeouts[conn->state], now);
91 : :
92 : 3 : return &conn->up;
93 : : }
94 : :
95 : : struct ct_l4_proto ct_proto_icmp4 = {
96 : : .new_conn = icmp_new_conn,
97 : : .valid_new = icmp4_valid_new,
98 : : .conn_update = icmp_conn_update,
99 : : };
100 : :
101 : : struct ct_l4_proto ct_proto_icmp6 = {
102 : : .new_conn = icmp_new_conn,
103 : : .valid_new = icmp6_valid_new,
104 : : .conn_update = icmp_conn_update,
105 : : };
|