blob: f9ba113eee6b2a98f3d18a6b4962243464aaa8a2 [file] [log] [blame]
Lorenzo Colitticd70b352013-04-10 12:24:56 +09001/*
2 * Copyright (C) 2013 The Android Open Source Project
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 * icmp.c - convenience functions for translating ICMP and ICMPv6 packets.
17 */
18
junyulaic4e591a2018-11-26 22:36:10 +090019#include <linux/icmp.h>
20#include <netinet/icmp6.h>
Lorenzo Colitticd70b352013-04-10 12:24:56 +090021#include <netinet/in.h>
22#include <netinet/ip_icmp.h>
Lorenzo Colitticd70b352013-04-10 12:24:56 +090023
Lorenzo Colitticd70b352013-04-10 12:24:56 +090024#include "icmp.h"
junyulaic4e591a2018-11-26 22:36:10 +090025#include "logging.h"
Lorenzo Colitticd70b352013-04-10 12:24:56 +090026
27/* function: icmp_guess_ttl
28 * Guesses the number of hops a received packet has traversed based on its TTL.
29 * ttl - the ttl of the received packet.
30 */
31uint8_t icmp_guess_ttl(uint8_t ttl) {
32 if (ttl > 128) {
33 return 255 - ttl;
34 } else if (ttl > 64) {
35 return 128 - ttl;
36 } else if (ttl > 32) {
37 return 64 - ttl;
38 } else {
39 return 32 - ttl;
40 }
41}
42
43/* function: is_icmp_error
44 * Determines whether an ICMP type is an error message.
45 * type: the ICMP type
46 */
junyulaic4e591a2018-11-26 22:36:10 +090047int is_icmp_error(uint8_t type) { return type == 3 || type == 11 || type == 12; }
Lorenzo Colitticd70b352013-04-10 12:24:56 +090048
49/* function: is_icmp6_error
50 * Determines whether an ICMPv6 type is an error message.
51 * type: the ICMPv6 type
52 */
junyulaic4e591a2018-11-26 22:36:10 +090053int is_icmp6_error(uint8_t type) { return type < 128; }
Lorenzo Colitticd70b352013-04-10 12:24:56 +090054
55/* function: icmp_to_icmp6_type
56 * Maps ICMP types to ICMPv6 types. Partial implementation of RFC 6145, section 4.2.
57 * type - the ICMPv6 type
58 */
59uint8_t icmp_to_icmp6_type(uint8_t type, uint8_t code) {
60 switch (type) {
61 case ICMP_ECHO:
62 return ICMP6_ECHO_REQUEST;
63
64 case ICMP_ECHOREPLY:
65 return ICMP6_ECHO_REPLY;
66
67 case ICMP_TIME_EXCEEDED:
68 return ICMP6_TIME_EXCEEDED;
69
70 case ICMP_DEST_UNREACH:
71 // These two types need special translation which we don't support yet.
72 if (code != ICMP_UNREACH_PROTOCOL && code != ICMP_UNREACH_NEEDFRAG) {
73 return ICMP6_DST_UNREACH;
74 }
75 }
76
77 // We don't understand this ICMP type. Return parameter problem so the caller will bail out.
78 logmsg_dbg(ANDROID_LOG_DEBUG, "icmp_to_icmp6_type: unhandled ICMP type %d", type);
79 return ICMP6_PARAM_PROB;
80}
81
82/* function: icmp_to_icmp6_code
83 * Maps ICMP codes to ICMPv6 codes. Partial implementation of RFC 6145, section 4.2.
84 * type - the ICMP type
85 * code - the ICMP code
86 */
87uint8_t icmp_to_icmp6_code(uint8_t type, uint8_t code) {
88 switch (type) {
89 case ICMP_ECHO:
90 case ICMP_ECHOREPLY:
91 return 0;
92
93 case ICMP_TIME_EXCEEDED:
94 return code;
95
96 case ICMP_DEST_UNREACH:
97 switch (code) {
98 case ICMP_UNREACH_NET:
99 case ICMP_UNREACH_HOST:
100 return ICMP6_DST_UNREACH_NOROUTE;
101
102 case ICMP_UNREACH_PORT:
103 return ICMP6_DST_UNREACH_NOPORT;
104
105 case ICMP_UNREACH_NET_PROHIB:
106 case ICMP_UNREACH_HOST_PROHIB:
107 case ICMP_UNREACH_FILTER_PROHIB:
108 case ICMP_UNREACH_PRECEDENCE_CUTOFF:
109 return ICMP6_DST_UNREACH_ADMIN;
110
junyulaic4e591a2018-11-26 22:36:10 +0900111 // Otherwise, we don't understand this ICMP type/code combination. Fall through.
Lorenzo Colitticd70b352013-04-10 12:24:56 +0900112 }
113 }
114 logmsg_dbg(ANDROID_LOG_DEBUG, "icmp_to_icmp6_code: unhandled ICMP type/code %d/%d", type, code);
115 return 0;
116}
117
118/* function: icmp6_to_icmp_type
119 * Maps ICMPv6 types to ICMP types. Partial implementation of RFC 6145, section 5.2.
120 * type - the ICMP type
121 */
122uint8_t icmp6_to_icmp_type(uint8_t type, uint8_t code) {
123 switch (type) {
124 case ICMP6_ECHO_REQUEST:
125 return ICMP_ECHO;
126
127 case ICMP6_ECHO_REPLY:
128 return ICMP_ECHOREPLY;
129
130 case ICMP6_DST_UNREACH:
131 return ICMP_DEST_UNREACH;
132
133 case ICMP6_TIME_EXCEEDED:
134 return ICMP_TIME_EXCEEDED;
135 }
136
137 // We don't understand this ICMP type. Return parameter problem so the caller will bail out.
Bernhard Rosenkränzera33592b2013-12-12 10:28:16 +0100138 logmsg_dbg(ANDROID_LOG_DEBUG, "icmp6_to_icmp_type: unhandled ICMP type/code %d/%d", type, code);
Lorenzo Colitticd70b352013-04-10 12:24:56 +0900139 return ICMP_PARAMETERPROB;
140}
141
142/* function: icmp6_to_icmp_code
143 * Maps ICMPv6 codes to ICMP codes. Partial implementation of RFC 6145, section 5.2.
144 * type - the ICMPv6 type
145 * code - the ICMPv6 code
146 */
147uint8_t icmp6_to_icmp_code(uint8_t type, uint8_t code) {
148 switch (type) {
149 case ICMP6_ECHO_REQUEST:
150 case ICMP6_ECHO_REPLY:
151 case ICMP6_TIME_EXCEEDED:
152 return code;
153
154 case ICMP6_DST_UNREACH:
155 switch (code) {
156 case ICMP6_DST_UNREACH_NOROUTE:
157 return ICMP_UNREACH_HOST;
158
159 case ICMP6_DST_UNREACH_ADMIN:
160 return ICMP_UNREACH_HOST_PROHIB;
161
162 case ICMP6_DST_UNREACH_BEYONDSCOPE:
163 return ICMP_UNREACH_HOST;
164
165 case ICMP6_DST_UNREACH_ADDR:
166 return ICMP_HOST_UNREACH;
167
168 case ICMP6_DST_UNREACH_NOPORT:
169 return ICMP_UNREACH_PORT;
170
junyulaic4e591a2018-11-26 22:36:10 +0900171 // Otherwise, we don't understand this ICMPv6 type/code combination. Fall through.
Lorenzo Colitticd70b352013-04-10 12:24:56 +0900172 }
173 }
174
175 logmsg_dbg(ANDROID_LOG_DEBUG, "icmp6_to_icmp_code: unhandled ICMP type/code %d/%d", type, code);
176 return 0;
177}