1cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/*
2cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Copyright (C) 2013 The Android Open Source Project
3cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti *
4cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Licensed under the Apache License, Version 2.0 (the "License");
5cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * you may not use this file except in compliance with the License.
6cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * You may obtain a copy of the License at
7cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti *
8cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti *      http://www.apache.org/licenses/LICENSE-2.0
9cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti *
10cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Unless required by applicable law or agreed to in writing, software
11cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * distributed under the License is distributed on an "AS IS" BASIS,
12cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * See the License for the specific language governing permissions and
14cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * limitations under the License.
15cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti *
16cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * icmp.c - convenience functions for translating ICMP and ICMPv6 packets.
17cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
18cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
19cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti#include <netinet/in.h>
20cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti#include <netinet/ip_icmp.h>
21cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti#include <netinet/icmp6.h>
22cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti#include <linux/icmp.h>
23cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
24cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti#include "logging.h"
25cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti#include "icmp.h"
26cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
27cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: icmp_guess_ttl
28cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Guesses the number of hops a received packet has traversed based on its TTL.
29cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * ttl - the ttl of the received packet.
30cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
31cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiuint8_t icmp_guess_ttl(uint8_t ttl) {
32cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  if (ttl > 128) {
33cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    return 255 - ttl;
34cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  } else if (ttl > 64) {
35cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    return 128 - ttl;
36cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  } else if (ttl > 32) {
37cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    return 64 - ttl;
38cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  } else {
39cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    return 32 - ttl;
40cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  }
41cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
42cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
43cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: is_icmp_error
44cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Determines whether an ICMP type is an error message.
45cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * type: the ICMP type
46cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
47cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiint is_icmp_error(uint8_t type) {
48cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  return type == 3 || type == 11 || type == 12;
49cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
50cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
51cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: is_icmp6_error
52cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Determines whether an ICMPv6 type is an error message.
53cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * type: the ICMPv6 type
54cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
55cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiint is_icmp6_error(uint8_t type) {
56cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  return type < 128;
57cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
58cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
59cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: icmp_to_icmp6_type
60cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Maps ICMP types to ICMPv6 types. Partial implementation of RFC 6145, section 4.2.
61cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * type - the ICMPv6 type
62cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
63cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiuint8_t icmp_to_icmp6_type(uint8_t type, uint8_t code) {
64cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  switch (type) {
65cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_ECHO:
66cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP6_ECHO_REQUEST;
67cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
68cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_ECHOREPLY:
69cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP6_ECHO_REPLY;
70cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
71cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_TIME_EXCEEDED:
72cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP6_TIME_EXCEEDED;
73cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
74cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_DEST_UNREACH:
75cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      // These two types need special translation which we don't support yet.
76cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      if (code != ICMP_UNREACH_PROTOCOL && code != ICMP_UNREACH_NEEDFRAG) {
77cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        return ICMP6_DST_UNREACH;
78cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      }
79cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  }
80cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
81cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  // We don't understand this ICMP type. Return parameter problem so the caller will bail out.
82cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  logmsg_dbg(ANDROID_LOG_DEBUG, "icmp_to_icmp6_type: unhandled ICMP type %d", type);
83cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  return ICMP6_PARAM_PROB;
84cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
85cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
86cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: icmp_to_icmp6_code
87cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Maps ICMP codes to ICMPv6 codes. Partial implementation of RFC 6145, section 4.2.
88cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * type - the ICMP type
89cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * code - the ICMP code
90cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
91cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiuint8_t icmp_to_icmp6_code(uint8_t type, uint8_t code) {
92cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  switch (type) {
93cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_ECHO:
94cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_ECHOREPLY:
95cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return 0;
96cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
97cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_TIME_EXCEEDED:
98cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return code;
99cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
100cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP_DEST_UNREACH:
101cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      switch (code) {
102cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_NET:
103cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_HOST:
104cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP6_DST_UNREACH_NOROUTE;
105cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
106cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_PORT:
107cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP6_DST_UNREACH_NOPORT;
108cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
109cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_NET_PROHIB:
110cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_HOST_PROHIB:
111cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_FILTER_PROHIB:
112cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP_UNREACH_PRECEDENCE_CUTOFF:
113cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP6_DST_UNREACH_ADMIN;
114cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
115cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        // Otherwise, we don't understand this ICMP type/code combination. Fall through.
116cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      }
117cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  }
118cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  logmsg_dbg(ANDROID_LOG_DEBUG, "icmp_to_icmp6_code: unhandled ICMP type/code %d/%d", type, code);
119cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  return 0;
120cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
121cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
122cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: icmp6_to_icmp_type
123cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Maps ICMPv6 types to ICMP types. Partial implementation of RFC 6145, section 5.2.
124cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * type - the ICMP type
125cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
126cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiuint8_t icmp6_to_icmp_type(uint8_t type, uint8_t code) {
127cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  switch (type) {
128cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_ECHO_REQUEST:
129cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP_ECHO;
130cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
131cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_ECHO_REPLY:
132cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP_ECHOREPLY;
133cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
134cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_DST_UNREACH:
135cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP_DEST_UNREACH;
136cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
137cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_TIME_EXCEEDED:
138cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return ICMP_TIME_EXCEEDED;
139cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  }
140cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
141cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  // We don't understand this ICMP type. Return parameter problem so the caller will bail out.
142a33592bd08a20c6a521b8508975b7a74ecdf4f03Bernhard Rosenkränzer  logmsg_dbg(ANDROID_LOG_DEBUG, "icmp6_to_icmp_type: unhandled ICMP type/code %d/%d", type, code);
143cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  return ICMP_PARAMETERPROB;
144cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
145cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
146cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti/* function: icmp6_to_icmp_code
147cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * Maps ICMPv6 codes to ICMP codes. Partial implementation of RFC 6145, section 5.2.
148cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * type - the ICMPv6 type
149cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti * code - the ICMPv6 code
150cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti */
151cd70b354eb985678175904a937085bed6094af77Lorenzo Colittiuint8_t icmp6_to_icmp_code(uint8_t type, uint8_t code) {
152cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  switch (type) {
153cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_ECHO_REQUEST:
154cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_ECHO_REPLY:
155cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_TIME_EXCEEDED:
156cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      return code;
157cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
158cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti    case ICMP6_DST_UNREACH:
159cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      switch (code) {
160cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP6_DST_UNREACH_NOROUTE:
161cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP_UNREACH_HOST;
162cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
163cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP6_DST_UNREACH_ADMIN:
164cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP_UNREACH_HOST_PROHIB;
165cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
166cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP6_DST_UNREACH_BEYONDSCOPE:
167cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP_UNREACH_HOST;
168cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
169cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP6_DST_UNREACH_ADDR:
170cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP_HOST_UNREACH;
171cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
172cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        case ICMP6_DST_UNREACH_NOPORT:
173cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti          return ICMP_UNREACH_PORT;
174cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
175cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti        // Otherwise, we don't understand this ICMPv6 type/code combination. Fall through.
176cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti      }
177cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  }
178cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti
179cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  logmsg_dbg(ANDROID_LOG_DEBUG, "icmp6_to_icmp_code: unhandled ICMP type/code %d/%d", type, code);
180cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti  return 0;
181cd70b354eb985678175904a937085bed6094af77Lorenzo Colitti}
182