/src/wireshark/epan/dissectors/packet-e164.c
Line | Count | Source |
1 | | /* packet-e164.c |
2 | | * Routines for output and filtering of E164 numbers common |
3 | | * to many dissectors. |
4 | | * Copyright 2004, Anders Broman <anders.broman@ericsson.com> |
5 | | * |
6 | | * Wireshark - Network traffic analyzer |
7 | | * By Gerald Combs <gerald@wireshark.org> |
8 | | * Copyright 1998 Gerald Combs |
9 | | * |
10 | | * SPDX-License-Identifier: GPL-2.0-or-later |
11 | | * |
12 | | * Ref ITU-T E.164 05/97 |
13 | | * Annex to ITU Operational Bulletin No. 991 - 1.XI.2011 |
14 | | * Amendment No. 10 ITU Operational Bulletin No. 1057 - 1.VIII.2014 |
15 | | * Find the bulletins here: |
16 | | * http://www.itu.int/pub/T-SP-OB |
17 | | */ |
18 | | |
19 | | #include "config.h" |
20 | | |
21 | | #include <epan/packet.h> |
22 | | #include "packet-e164.h" |
23 | | #include "expert.h" |
24 | | |
25 | | void proto_register_e164(void); |
26 | | |
27 | | const value_string E164_country_code_value[] = { |
28 | | { 0, "Reserved"}, |
29 | | { 1, "Americas"}, |
30 | | { 7, "Russian Federation, Kazakstan (Republic of)"}, |
31 | | { 20, "Egypt (Arab Republic of)"}, |
32 | | { 27, "South Africa (Republic of)"}, |
33 | | { 30, "Greece"}, |
34 | | { 31, "Netherlands (Kingdom of the)"}, |
35 | | { 32, "Belgium"}, |
36 | | { 33, "France"}, |
37 | | { 34, "Spain"}, |
38 | | { 36, "Hungary (Republic of)"}, |
39 | | { 39, "Italy"}, |
40 | | { 40, "Romania"}, |
41 | | { 41, "Switzerland (Confederation of)"}, |
42 | | { 43, "Austria"}, |
43 | | { 44, "United Kingdom of Great Britain and Northern Ireland"}, |
44 | | { 45, "Denmark"}, |
45 | | { 46, "Sweden"}, |
46 | | { 47, "Norway"}, |
47 | | { 48, "Poland (Republic of)"}, |
48 | | { 49, "Germany (Federal Republic of)"}, |
49 | | { 51, "Peru"}, |
50 | | { 52, "Mexico"}, |
51 | | { 53, "Cuba"}, |
52 | | { 54, "Argentine Republic"}, |
53 | | { 55, "Brazil (Federative Republic of)"}, |
54 | | { 56, "Chile"}, |
55 | | { 57, "Colombia (Republic of)"}, |
56 | | { 58, "Venezuela(Bolivarian Republic of)"}, |
57 | | { 60, "Malaysia"}, |
58 | | { 61, "Australia"}, |
59 | | { 62, "Indonesia (Republic of)"}, |
60 | | { 63, "Philippines (Republic of the)"}, |
61 | | { 64, "New Zealand"}, |
62 | | { 65, "Singapore (Republic of)"}, |
63 | | { 66, "Thailand"}, |
64 | | { 81, "Japan"}, |
65 | | { 82, "Korea (Republic of)"}, |
66 | | { 84, "Viet Nam (Socialist Republic of)"}, |
67 | | { 86, "China (People's Republic of)"}, |
68 | | { 90, "Turkey"}, |
69 | | { 91, "India (Republic of)"}, |
70 | | { 92, "Pakistan (Islamic Republic of)"}, |
71 | | { 93, "Afghanistan"}, |
72 | | { 94, "Sri Lanka (Democratic Socialist Republic of)"}, |
73 | | { 95, "Myanmar (the Republic of the Union of)"}, |
74 | | { 98, "Iran (Islamic Republic of)"}, |
75 | | { 210, "Spare code"}, |
76 | | { 211, "South Sudan (Republic of)"}, |
77 | | { 212, "Morocco (Kingdom of)"}, |
78 | | { 213, "Algeria (People's Democratic Republic of)"}, |
79 | | { 214, "Spare code"}, |
80 | | { 215, "Spare code"}, |
81 | | { 216, "Tunisia"}, |
82 | | { 217, "Spare code"}, |
83 | | { 218, "Libya (Socialist People's Libyan Arab Jamahiriya)"}, |
84 | | { 219, "Spare code"}, |
85 | | { 220, "Gambia (Republic of)"}, |
86 | | { 221, "Senegal (Republic of)"}, |
87 | | { 222, "Mauritania (Islamic Republic of)"}, |
88 | | { 223, "Mali (Republic of)"}, |
89 | | { 224, "Guinea (Republic of)"}, |
90 | | { 225, "Cote d'Ivoire (Republic of)"}, |
91 | | { 226, "Burkina Faso"}, |
92 | | { 227, "Niger (Republic of the)"}, |
93 | | { 228, "Togolese Republic"}, |
94 | | { 229, "Benin (Republic of)"}, |
95 | | { 230, "Mauritius (Republic of)"}, |
96 | | { 231, "Liberia (Republic of)"}, |
97 | | { 232, "Sierra Leone"}, |
98 | | { 233, "Ghana"}, |
99 | | { 234, "Nigeria (Federal Republic of)"}, |
100 | | { 235, "Chad (Republic of)"}, |
101 | | { 236, "Central African Republic"}, |
102 | | { 237, "Cameroon (Republic of)"}, |
103 | | { 238, "Cape Verde (Republic of)"}, |
104 | | { 239, "Sao Tome and Principe (Democratic Republic of)"}, |
105 | | { 240, "Equatorial Guinea (Republic of)"}, |
106 | | { 241, "Gabonese Republic"}, |
107 | | { 242, "Congo (Republic of the)"}, |
108 | | { 243, "Democratic Republic of Congo"}, |
109 | | { 244, "Angola (Republic of)"}, |
110 | | { 245, "Guinea-Bissau (Republic of)"}, |
111 | | { 246, "Diego Garcia"}, |
112 | | { 247, "Saint Helena, Ascension and Tristan da Cunha"}, |
113 | | { 248, "Seychelles (Republic of)"}, |
114 | | { 249, "Sudan (Republic of the)"}, |
115 | | { 250, "Rwanda (Republic of)"}, |
116 | | { 251, "Ethiopia (Federal Democratic Republic of)"}, |
117 | | { 252, "Somali Democratic Republic"}, |
118 | | { 253, "Djibouti (Republic of)"}, |
119 | | { 254, "Kenya (Republic of)"}, |
120 | | { 255, "Tanzania (United Republic of)"}, |
121 | | { 256, "Uganda (Republic of)"}, |
122 | | { 257, "Burundi (Republic of)"}, |
123 | | { 258, "Mozambique (Republic of)"}, |
124 | | { 259, "Spare code"}, |
125 | | { 260, "Zambia (Republic of)"}, |
126 | | { 261, "Madagascar (Republic of)"}, |
127 | | { 262, "French Departments and Territories in the Indian Ocean"}, |
128 | | { 263, "Zimbabwe (Republic of)"}, |
129 | | { 264, "Namibia (Republic of)"}, |
130 | | { 265, "Malawi"}, |
131 | | { 266, "Lesotho (Kingdom of)"}, |
132 | | { 267, "Botswana (Republic of)"}, |
133 | | { 268, "Swaziland (Kingdom of)"}, |
134 | | { 269, "Comoros (Union of the)"}, |
135 | | { 280, "Spare code"}, |
136 | | { 281, "Spare code"}, |
137 | | { 282, "Spare code"}, |
138 | | { 283, "Spare code"}, |
139 | | { 284, "Spare code"}, |
140 | | { 285, "Spare code"}, |
141 | | { 286, "Spare code"}, |
142 | | { 287, "Spare code"}, |
143 | | { 288, "Spare code"}, |
144 | | { 289, "Spare code"}, |
145 | | { 290, "Saint Helena, Ascension and Tristan da Cunha"}, |
146 | | { 291, "Eritrea"}, |
147 | | { 292, "Spare code"}, |
148 | | { 293, "Spare code"}, |
149 | | { 294, "Spare code"}, |
150 | | { 295, "Spare code"}, |
151 | | { 296, "Spare code"}, |
152 | | { 297, "Aruba"}, |
153 | | { 298, "Faroe Islands"}, |
154 | | { 299, "Greenland (Denmark)"}, |
155 | | { 350, "Gibraltar"}, |
156 | | { 351, "Portugal"}, |
157 | | { 352, "Luxembourg"}, |
158 | | { 353, "Ireland"}, |
159 | | { 354, "Iceland"}, |
160 | | { 355, "Albania (Republic of)"}, |
161 | | { 356, "Malta"}, |
162 | | { 357, "Cyprus (Republic of)"}, |
163 | | { 358, "Finland"}, |
164 | | { 359, "Bulgaria (Republic of)"}, |
165 | | { 370, "Lithuania (Republic of)"}, |
166 | | { 371, "Latvia (Republic of)"}, |
167 | | { 372, "Estonia (Republic of)"}, |
168 | | { 373, "Moldova (Republic of)"}, |
169 | | { 374, "Armenia (Republic of)"}, |
170 | | { 375, "Belarus (Republic of)"}, |
171 | | { 376, "Andorra (Principality of)"}, |
172 | | { 377, "Monaco (Principality of)"}, |
173 | | { 378, "San Marino (Republic of)"}, |
174 | | { 379, "Vatican City State"}, |
175 | | { 380, "Ukraine"}, |
176 | | { 381, "Serbia (Republic of)"}, |
177 | | { 382, "Montenegro (Republic of)"}, |
178 | | { 383, "Spare code"}, |
179 | | { 384, "Spare code"}, |
180 | | { 385, "Croatia (Republic of)"}, |
181 | | { 386, "Slovenia (Republic of)"}, |
182 | | { 387, "Bosnia and Herzegovina"}, |
183 | | { 388, "Group of countries, shared code"}, |
184 | | { 389, "The Former Yugoslav Republic of Macedonia"}, |
185 | | { 420, "Czech Republic"}, |
186 | | { 421, "Slovak Republic"}, |
187 | | { 422, "Spare code"}, |
188 | | { 423, "Liechtenstein (Principality of)"}, |
189 | | { 424, "Spare code"}, |
190 | | { 425, "Spare code"}, |
191 | | { 426, "Spare code"}, |
192 | | { 427, "Spare code"}, |
193 | | { 428, "Spare code"}, |
194 | | { 429, "Spare code"}, |
195 | | { 500, "Falkland Islands (Malvinas)"}, |
196 | | { 501, "Belize"}, |
197 | | { 502, "Guatemala (Republic of)"}, |
198 | | { 503, "El Salvador (Republic of)"}, |
199 | | { 504, "Honduras (Republic of)"}, |
200 | | { 505, "Nicaragua"}, |
201 | | { 506, "Costa Rica"}, |
202 | | { 507, "Panama (Republic of)"}, |
203 | | { 508, "Saint Pierre and Miquelon (Collectivite territoriale de la Republique francaise)"}, |
204 | | { 509, "Haiti (Republic of)"}, |
205 | | { 590, "Guadeloupe (French Department of)"}, |
206 | | { 591, "Bolivia (Plurinational State of)"}, |
207 | | { 592, "Guyana"}, |
208 | | { 593, "Ecuador"}, |
209 | | { 594, "French Guiana (French Department of)"}, |
210 | | { 595, "Paraguay (Republic of)"}, |
211 | | { 596, "Martinique (French Department of)"}, |
212 | | { 597, "Suriname (Republic of)"}, |
213 | | { 598, "Uruguay (Eastern Republic of)"}, |
214 | | { 599, "Bonaire, Saint Eustatius and Saba, Curacao"}, |
215 | | { 670, "Democratic Republic of Timor-Leste"}, |
216 | | { 671, "Spare code"}, |
217 | | { 672, "Australian External Territories"}, |
218 | | { 673, "Brunei Darussalam"}, |
219 | | { 674, "Nauru (Republic of)"}, |
220 | | { 675, "Papua New Guinea"}, |
221 | | { 676, "Tonga (Kingdom of)"}, |
222 | | { 677, "Solomon Islands"}, |
223 | | { 678, "Vanuatu (Republic of)"}, |
224 | | { 679, "Fiji (Republic of)"}, |
225 | | { 680, "Palau (Republic of)"}, |
226 | | { 681, "Wallis and Futuna (Territoire francais d'outre-mer)"}, |
227 | | { 682, "Cook Islands"}, |
228 | | { 683, "Niue"}, |
229 | | { 684, "Spare code"}, |
230 | | { 685, "Samoa (Independent State of)"}, |
231 | | { 686, "Kiribati (Republic of)"}, |
232 | | { 687, "New Caledonia (Territoire francais d'outre-mer)"}, |
233 | | { 688, "Tuvalu"}, |
234 | | { 689, "French Polynesia (Territoire francais d'outre-mer)"}, |
235 | | { 690, "Tokelau"}, |
236 | | { 691, "Micronesia (Federated States of)"}, |
237 | | { 692, "Marshall Islands (Republic of the)"}, |
238 | | { 693, "Spare code"}, |
239 | | { 694, "Spare code"}, |
240 | | { 695, "Spare code"}, |
241 | | { 696, "Spare code"}, |
242 | | { 697, "Spare code"}, |
243 | | { 698, "Spare code"}, |
244 | | { 699, "Spare code"}, |
245 | | { 800, "International Freephone Service"}, |
246 | | { 801, "Spare code"}, |
247 | | { 802, "Spare code"}, |
248 | | { 803, "Spare code"}, |
249 | | { 804, "Spare code"}, |
250 | | { 805, "Spare code"}, |
251 | | { 806, "Spare code"}, |
252 | | { 807, "Spare code"}, |
253 | | { 808, "International Shared Cost Service (ISCS)"}, |
254 | | { 809, "Spare code"}, |
255 | | { 830, "Spare code"}, |
256 | | { 831, "Spare code"}, |
257 | | { 832, "Spare code"}, |
258 | | { 833, "Spare code"}, |
259 | | { 834, "Spare code"}, |
260 | | { 835, "Spare code"}, |
261 | | { 836, "Spare code"}, |
262 | | { 837, "Spare code"}, |
263 | | { 838, "Spare code"}, |
264 | | { 839, "Spare code"}, |
265 | | { 850, "Democratic People's Republic of Korea"}, |
266 | | { 851, "Spare code"}, |
267 | | { 852, "Hong Kong, China"}, |
268 | | { 853, "Macau, China"}, |
269 | | { 854, "Spare code"}, |
270 | | { 855, "Cambodia (Kingdom of)"}, |
271 | | { 856, "Lao People's Democratic Republic"}, |
272 | | { 857, "Spare code"}, |
273 | | { 858, "Spare code"}, |
274 | | { 859, "Spare code"}, |
275 | | { 870, "Inmarsat SNAC"}, |
276 | | { 871, "Spare code"}, |
277 | | { 872, "Spare code"}, |
278 | | { 873, "Spare code"}, |
279 | | { 874, "Spare code"}, |
280 | | { 875, "Reserved - Maritime Mobile Service Applications"}, |
281 | | { 876, "Reserved - Maritime Mobile Service Applications"}, |
282 | | { 877, "Reserved - Maritime Mobile Service Applications"}, |
283 | | { 878, "Universal Personal Telecommunication Service (UPT)"}, |
284 | | { 879, "Reserved for national non-commercial purposes"}, |
285 | | { 880, "Bangladesh"}, |
286 | | { 881, "Global Mobile Satellite System (GMSS), shared code"}, |
287 | | { 882, "International Networks, shared code"}, |
288 | | { 883, "International Networks, shared code"}, |
289 | | { 884, "Spare code"}, |
290 | | { 885, "Spare code"}, |
291 | | { 886, "Taiwan, China"}, |
292 | | { 887, "Spare code"}, |
293 | | { 888, "Telecommunications for Disaster Relief (TDR)"}, |
294 | | { 889, "Spare code"}, |
295 | | { 890, "Spare code"}, |
296 | | { 891, "Spare code"}, |
297 | | { 892, "Spare code"}, |
298 | | { 893, "Spare code"}, |
299 | | { 894, "Spare code"}, |
300 | | { 895, "Spare code"}, |
301 | | { 896, "Spare code"}, |
302 | | { 897, "Spare code"}, |
303 | | { 898, "Spare code"}, |
304 | | { 899, "Spare code"}, |
305 | | { 960, "Maldives (Republic of)"}, |
306 | | { 961, "Lebanon"}, |
307 | | { 962, "Jordan (Hashemite Kingdom of)"}, |
308 | | { 963, "Syrian Arab Republic"}, |
309 | | { 964, "Iraq (Republic of)"}, |
310 | | { 965, "Kuwait (State of)"}, |
311 | | { 966, "Saudi Arabia (Kingdom of)"}, |
312 | | { 967, "Yemen (Republic of)"}, |
313 | | { 968, "Oman (Sultanate of)"}, |
314 | | { 969, "Reserved - reservation currently under investigation"}, |
315 | | { 970, "Reserved"}, |
316 | | { 971, "United Arab Emirates"}, |
317 | | { 972, "Israel (State of)"}, |
318 | | { 973, "Bahrain (Kingdom of)"}, |
319 | | { 974, "Qatar (State of)"}, |
320 | | { 975, "Bhutan (Kingdom of)"}, |
321 | | { 976, "Mongolia"}, |
322 | | { 977, "Nepal (Federal Democratic Republic of)"}, |
323 | | { 978, "Spare code"}, |
324 | | { 979, "International Premium Rate Service (IPRS)"}, |
325 | | { 990, "Spare code"}, |
326 | | { 991, "Trial of a proposed new international telecommunication public correspondence service, shared code"}, |
327 | | { 992, "Tajikstan (Republic of)"}, |
328 | | { 993, "Turkmenistan"}, |
329 | | { 994, "Azerbaijan"}, |
330 | | { 995, "Georgia"}, |
331 | | { 996, "Kyrgyz Republic"}, |
332 | | { 997, "Spare code"}, |
333 | | { 998, "Uzbekistan (Republic of)"}, |
334 | | { 999, "Reserved for future global service"}, |
335 | | { 0, NULL } |
336 | | }; |
337 | | static value_string_ext E164_country_code_value_ext = VALUE_STRING_EXT_INIT(E164_country_code_value); |
338 | | |
339 | | /* Country code from ITU-T E.164 to ISO 3166 two letters country name */ |
340 | | const value_string E164_ISO3166_country_code_short_value[] = { |
341 | | { 1, "us" }, { 7, "ru" }, { 20, "eg" }, { 27, "za" }, |
342 | | { 30, "gr" }, { 31, "nl" }, { 32, "be" }, { 33, "fr" }, |
343 | | { 34, "es" }, { 36, "hu" }, { 39, "it" }, { 40, "ro" }, |
344 | | { 41, "ch" }, { 43, "at" }, { 44, "gb" }, { 45, "dk" }, |
345 | | { 46, "se" }, { 47, "no" }, { 48, "pl" }, { 49, "de" }, |
346 | | { 51, "pe" }, { 52, "mx" }, { 53, "cu" }, { 54, "ar" }, |
347 | | { 55, "br" }, { 56, "cl" }, { 57, "co" }, { 58, "ve" }, |
348 | | { 60, "my" }, { 61, "au" }, { 62, "id" }, { 63, "ph" }, |
349 | | { 64, "nz" }, { 65, "sg" }, { 66, "th" }, { 81, "jp" }, |
350 | | { 82, "kr" }, { 84, "vn" }, { 86, "cn" }, { 90, "tr" }, |
351 | | { 91, "in" }, { 92, "pk" }, { 93, "af" }, { 94, "lk" }, |
352 | | { 98, "ir" }, { 95, "mm" }, |
353 | | |
354 | | { 212, "ma" }, { 213, "dz" }, { 216, "tn" }, { 218, "ly" }, |
355 | | { 220, "gm" }, { 221, "sn" }, { 222, "mr" }, { 223, "ml" }, |
356 | | { 224, "gn" }, { 225, "ci" }, { 226, "bf" }, { 227, "ne" }, |
357 | | { 228, "tg" }, { 229, "bj" }, { 230, "mu" }, { 231, "lr" }, |
358 | | { 232, "sl" }, { 233, "gh" }, { 234, "ng" }, { 235, "td" }, |
359 | | { 236, "cf" }, { 237, "cm" }, { 238, "cv" }, { 239, "st" }, |
360 | | { 240, "gq" }, { 241, "ga" }, { 242, "cg" }, { 243, "cd" }, |
361 | | { 244, "ao" }, { 245, "gw" }, { 248, "sc" }, { 249, "sd" }, |
362 | | { 250, "rw" }, { 251, "et" }, { 252, "so" }, { 253, "dj" }, |
363 | | { 254, "ke" }, { 255, "tz" }, { 256, "ug" }, { 257, "bi" }, |
364 | | { 258, "mz" }, { 260, "zm" }, { 261, "mg" }, { 262, "fr" }, |
365 | | { 263, "zw" }, { 264, "na" }, { 265, "mw" }, { 266, "ls" }, |
366 | | { 267, "bw" }, { 268, "sz" }, { 269, "km" }, { 290, "sh" }, |
367 | | { 291, "er" }, { 297, "aw" }, { 298, "fo" }, { 299, "gl" }, |
368 | | |
369 | | { 350, "gi" }, { 351, "pt" }, { 352, "lu" }, { 353, "ie" }, |
370 | | { 354, "is" }, { 355, "al" }, { 356, "mt" }, { 357, "cy" }, |
371 | | { 358, "fi" }, { 359, "bg" }, { 370, "lt" }, { 371, "lv" }, |
372 | | { 372, "ee" }, { 373, "md" }, { 374, "am" }, { 375, "by" }, |
373 | | { 376, "ad" }, { 377, "mc" }, { 378, "sm" }, { 379, "va" }, |
374 | | { 380, "ua" }, { 385, "hr" }, { 386, "si" }, { 387, "ba" }, |
375 | | |
376 | | { 420, "cz" }, { 421, "sk" }, { 423, "li" }, |
377 | | |
378 | | { 500, "fk" }, { 501, "bz" }, { 502, "gt" }, { 503, "sv" }, |
379 | | { 504, "hn" }, { 505, "ni" }, { 506, "cr" }, { 507, "pa" }, |
380 | | { 508, "pm" }, { 509, "ht" }, { 590, "gp" }, { 591, "bo" }, |
381 | | { 592, "gy" }, { 593, "ec" }, { 594, "gf" }, { 595, "py" }, |
382 | | { 596, "mq" }, { 597, "sr" }, { 598, "uy" }, |
383 | | |
384 | | { 673, "bn" }, { 682, "ck" }, { 670, "tl" }, { 674, "nr" }, |
385 | | { 675, "pg" }, { 676, "to" }, { 677, "sb" }, { 678, "vu" }, |
386 | | { 679, "fj" }, { 680, "pw" }, { 681, "wf" }, { 683, "nu" }, |
387 | | { 685, "ws" }, { 686, "ki" }, { 687, "nc" }, { 688, "tv" }, |
388 | | { 689, "pf" }, { 690, "tk" }, { 691, "fm" }, { 692, "mh" }, |
389 | | |
390 | | { 850, "kp" }, { 852, "hk" }, { 853, "mo" }, { 855, "kh" }, |
391 | | { 856, "la" }, { 880, "bd" }, |
392 | | |
393 | | { 960, "mv" }, { 961, "lb" }, { 962, "jo" }, { 963, "sy" }, |
394 | | { 964, "iq" }, { 965, "kw" }, { 966, "sa" }, { 967, "ye" }, |
395 | | { 968, "om" }, { 971, "ae" }, { 972, "il" }, { 973, "bh" }, |
396 | | { 974, "qa" }, { 975, "bt" }, { 976, "mn" }, { 977, "np" }, |
397 | | { 992, "tj" }, { 993, "tm" }, { 994, "az" }, { 995, "ge" }, |
398 | | { 996, "kg" }, { 998, "uz" }, |
399 | | |
400 | | { 0, NULL } |
401 | | }; |
402 | | value_string_ext E164_ISO3166_country_code_short_value_ext = VALUE_STRING_EXT_INIT(E164_ISO3166_country_code_short_value); |
403 | | |
404 | | static const value_string E164_GMSS_vals[] = { |
405 | | { 6, "Iridium Satellite LLC"}, |
406 | | { 7, "Iridium Satellite LLC"}, |
407 | | { 8, "Globalstar"}, |
408 | | { 9, "Globalstar"}, |
409 | | { 0, NULL } |
410 | | }; |
411 | | |
412 | | static const value_string E164_International_Networks_882_vals[] = { |
413 | | { 10, "Global Office Application"}, |
414 | | { 12, "HyperStream International (HSI) Data Network"}, |
415 | | { 13, "EMS Regional Mobile Satellite System"}, |
416 | | { 15, "Global international ATM Network"}, |
417 | | { 16, "Thuraya RMSS Network"}, |
418 | | { 20, "Garuda Mobile Telecommunication Satellite System"}, |
419 | | { 22, "Cable & Wireless Global Network"}, |
420 | | { 23, "Sita-Equant Network"}, |
421 | | { 24, "TeliaSonera Sverige AB"}, |
422 | | { 28, "Deutsche Telekom's Next Generation Network"}, |
423 | | { 31, "Global International ATM Network"}, |
424 | | { 32, "MCP network"}, |
425 | | { 33, "Oration Technologies Network"}, |
426 | | { 34, "BebbiCell AG"}, |
427 | | { 35, "Jasper System"}, |
428 | | { 36, "Jersey Telecom"}, |
429 | | { 37, "Cingular Wireless network"}, |
430 | | { 39, "Vodafone Malta"}, |
431 | | { 40, "Oy Communications"}, |
432 | | { 41, "Intermatica"}, |
433 | | { 42, "Seanet Maritime Communication"}, |
434 | | { 43, "Beeline"}, |
435 | | { 45, "Telecom Italia"}, |
436 | | { 46, "Tyntec GmbH"}, |
437 | | { 47, "Transatel"}, |
438 | | { 97, "Smart Communications Inc"}, |
439 | | { 98, "Onair GSM services"}, |
440 | | { 99, "Telenor GSM network - services in aircraft"}, |
441 | | { 0, NULL } |
442 | | }; |
443 | | static value_string_ext E164_International_Networks_882_vals_ext = VALUE_STRING_EXT_INIT(E164_International_Networks_882_vals); |
444 | | |
445 | | static const value_string E164_International_Networks_883_vals[] = { |
446 | | { 100, "MediaLincc Ltd"}, |
447 | | { 110, "Aicent Inc"}, |
448 | | { 120, "Telenor Connexion AB"}, |
449 | | { 130, "France Telecom Orange"}, |
450 | | { 140, "Multiregional TransitTelecom (MTT)"}, |
451 | | { 150, "BodyTrace Netherlands B.V"}, |
452 | | { 5100, "Voxbone SA"}, |
453 | | { 5110, "Bandwidth.com Inc"}, |
454 | | { 5120, "MTX Connect Ltd"}, |
455 | | { 5130, "SIMPE Ltd"}, |
456 | | { 5140, "Ellipsat Inc"}, |
457 | | { 5150, "Wins Limited"}, |
458 | | { 0, NULL } |
459 | | }; |
460 | | |
461 | | static int proto_e164; |
462 | | static int hf_E164_calling_party_number; |
463 | | static int hf_E164_called_party_number; |
464 | | static int hf_E164_msisdn; |
465 | | static int hf_E164_isdn; |
466 | | static int hf_E164_identification_code; |
467 | | static int hf_E164_country_code; |
468 | | |
469 | | static int ett_e164_msisdn; |
470 | | |
471 | | static expert_field ei_E164_country_code_non_decimal; |
472 | | static expert_field ei_E164_identification_code_non_decimal; |
473 | | |
474 | | void |
475 | | dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length, e164_info_t e164_info) |
476 | 148 | { |
477 | 148 | proto_item *pi; |
478 | | |
479 | 148 | switch (e164_info.e164_number_type) { |
480 | 41 | case CALLING_PARTY_NUMBER: |
481 | 41 | proto_tree_add_string(tree, hf_E164_calling_party_number, tvb, offset, |
482 | 41 | length, e164_info.E164_number_str); |
483 | 41 | break; |
484 | | |
485 | 107 | case CALLED_PARTY_NUMBER: |
486 | 107 | proto_tree_add_string(tree, hf_E164_called_party_number, tvb, offset, |
487 | 107 | length, e164_info.E164_number_str); |
488 | 107 | break; |
489 | | |
490 | 0 | default: |
491 | 0 | break; |
492 | 148 | } |
493 | | |
494 | 148 | if (e164_info.nature_of_address == E164_NA_INTERNATIONAL_NUMBER) { |
495 | 17 | pi = proto_tree_add_string(tree, hf_E164_msisdn, tvb, offset, length, e164_info.E164_number_str); |
496 | 17 | proto_item_set_hidden(pi); |
497 | 17 | } |
498 | 148 | } |
499 | | |
500 | | /** |
501 | | * Convert 16bit integer in BCD encoding to decimal. |
502 | | * @param bcd BCD value to convert. |
503 | | * @param[out] dec Pointer to decimal result. |
504 | | * @return true if ok, false if bcd contains a nibble > 9. |
505 | | */ |
506 | | static bool |
507 | | convert_bcd_to_dec(uint16_t bcd, uint16_t * dec) |
508 | 256 | { |
509 | 256 | bool rok = true; |
510 | 256 | uint16_t result = 0; |
511 | 256 | uint16_t mult = 1; |
512 | 785 | while (bcd) { |
513 | 529 | if ((bcd & 0x0f) > 9) |
514 | 113 | rok = false; |
515 | 529 | result += (bcd & 0x0f) * mult; |
516 | 529 | bcd >>= 4; |
517 | 529 | mult *= 10; |
518 | 529 | } |
519 | 256 | *dec = result; |
520 | 256 | return rok; |
521 | 256 | } |
522 | | |
523 | | void |
524 | | dissect_e164_cc(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset, e164_encoding_t encoding) |
525 | 257 | { |
526 | 257 | int cc_offset; |
527 | 257 | uint8_t address_digit_pair; |
528 | 257 | uint16_t id_code = 0; |
529 | 257 | uint8_t cc_length; |
530 | 257 | uint8_t length; |
531 | 257 | uint16_t cc = 0; |
532 | 257 | bool bcd_ok = false; |
533 | 257 | proto_item *item = NULL; |
534 | | |
535 | 257 | cc_offset = offset; |
536 | 257 | address_digit_pair = tvb_get_uint8(tvb, cc_offset); |
537 | | |
538 | | /* Get the first 3 digits of the MSISDN */ |
539 | 257 | switch (encoding) { |
540 | 0 | case E164_ENC_BINARY: |
541 | | /* Dissect country code after removing non significant zeros */ |
542 | 0 | while (address_digit_pair == 0) { |
543 | 0 | cc_offset = cc_offset + 1; |
544 | 0 | address_digit_pair = tvb_get_uint8(tvb, cc_offset); |
545 | 0 | } |
546 | 0 | cc = tvb_get_ntohs(tvb, cc_offset); |
547 | 0 | if ((address_digit_pair & 0xf0) != 0) { |
548 | 0 | cc = cc >> 4; |
549 | 0 | } |
550 | 0 | break; |
551 | 229 | case E164_ENC_BCD: |
552 | 229 | cc = address_digit_pair &0x0f; |
553 | 229 | cc = cc << 4; |
554 | 229 | cc = cc | (address_digit_pair &0xf0)>>4; |
555 | 229 | cc = cc << 4; |
556 | 229 | if (tvb_bytes_exist(tvb, cc_offset+1, 1)) { |
557 | 229 | address_digit_pair = tvb_get_uint8(tvb, cc_offset+1); |
558 | 229 | cc = cc | (address_digit_pair &0x0f); |
559 | 229 | } |
560 | 229 | break; |
561 | 27 | case E164_ENC_UTF8: |
562 | | /* XXX - do we need to worry about leading 0s? */ |
563 | 27 | cc = (tvb_get_uint8(tvb, cc_offset) - '0') << 8; |
564 | 27 | cc |= (tvb_get_uint8(tvb, cc_offset+1) - '0') << 4; |
565 | 27 | cc |= (tvb_get_uint8(tvb, cc_offset+2) - '0'); |
566 | 27 | break; |
567 | 257 | } |
568 | | |
569 | | /* Determine how many of those digits are the Country Code */ |
570 | 256 | switch (cc & 0x0f00) { |
571 | 33 | case 0x0: |
572 | 33 | cc_length = 1; |
573 | 33 | break; |
574 | 41 | case 0x0100: |
575 | 41 | cc_length = 1; |
576 | 41 | break; |
577 | 7 | case 0x0200: |
578 | 7 | switch (cc & 0x00f0) { |
579 | 4 | case 0: |
580 | 4 | case 0x70: |
581 | 4 | cc_length = 2; |
582 | 4 | break; |
583 | 3 | default: |
584 | 3 | cc_length = 3; |
585 | 3 | break; |
586 | 7 | } |
587 | 7 | break; |
588 | 17 | case 0x0300: |
589 | 17 | switch (cc & 0x00f0) { |
590 | 2 | case 0: |
591 | 4 | case 0x10: |
592 | 7 | case 0x20: |
593 | 12 | case 0x30: |
594 | 14 | case 0x40: |
595 | 14 | case 0x60: |
596 | 15 | case 0x90: |
597 | 15 | cc_length = 2; |
598 | 15 | break; |
599 | 2 | default: |
600 | 2 | cc_length = 3; |
601 | 2 | break; |
602 | 17 | } |
603 | 17 | break; |
604 | 17 | case 0x0400: |
605 | 4 | switch (cc & 0x00f0) { |
606 | 1 | case 0x20: |
607 | 1 | cc_length = 3; |
608 | 1 | break; |
609 | 3 | default: |
610 | 3 | cc_length = 2; |
611 | 3 | break; |
612 | 4 | } |
613 | 4 | break; |
614 | 4 | case 0x0500: |
615 | 4 | switch (cc & 0x00f0) { |
616 | 2 | case 0: |
617 | 2 | case 0x90: |
618 | 2 | cc_length = 3; |
619 | 2 | break; |
620 | 2 | default: |
621 | 2 | cc_length = 2; |
622 | 2 | break; |
623 | 4 | } |
624 | 4 | break; |
625 | 4 | case 0x0600: |
626 | 2 | switch (cc & 0x00f0) { |
627 | 0 | case 0x70: |
628 | 0 | case 0x80: |
629 | 0 | case 0x90: |
630 | 0 | cc_length = 3; |
631 | 0 | break; |
632 | 2 | default: |
633 | 2 | cc_length = 2; |
634 | 2 | break; |
635 | 2 | } |
636 | 2 | break; |
637 | 26 | case 0x0700: |
638 | 26 | cc_length = 1; |
639 | 26 | break; |
640 | 72 | case 0x0800: |
641 | 72 | switch (cc & 0x00f0) { |
642 | 0 | case 0x10: |
643 | 1 | case 0x20: |
644 | 1 | case 0x40: |
645 | 1 | case 0x60: |
646 | 1 | cc_length = 2; |
647 | 1 | break; |
648 | 71 | default: |
649 | 71 | cc_length = 3; |
650 | 71 | break; |
651 | 72 | } |
652 | 72 | break; |
653 | 72 | case 0x0900: |
654 | 8 | switch (cc & 0x00f0) { |
655 | 1 | case 0: |
656 | 3 | case 0x10: |
657 | 3 | case 0x20: |
658 | 3 | case 0x30: |
659 | 5 | case 0x40: |
660 | 5 | case 0x50: |
661 | 6 | case 0x80: |
662 | 6 | cc_length = 2; |
663 | 6 | break; |
664 | 2 | default: |
665 | 2 | cc_length = 3; |
666 | 2 | break; |
667 | 8 | } |
668 | 8 | break; |
669 | | |
670 | 42 | default: |
671 | 42 | cc_length = 0; |
672 | 42 | break; |
673 | 256 | } /* End switch cc */ |
674 | | |
675 | | /* (Now that we know how long the CC is,) |
676 | | * shift off any extra digits we got. |
677 | | */ |
678 | 256 | switch (cc_length) { |
679 | 100 | case 1: |
680 | 100 | cc = cc >> 8; |
681 | 100 | length = 1; |
682 | 100 | break; |
683 | 33 | case 2: |
684 | 33 | cc = cc >> 4; |
685 | 33 | length = 1; |
686 | 33 | break; |
687 | 123 | default: |
688 | 123 | length = 2; |
689 | 123 | break; |
690 | 256 | } /* end switch cc_length */ |
691 | | |
692 | | /* Now process the CC as decimal */ |
693 | 256 | bcd_ok = convert_bcd_to_dec(cc, &cc); |
694 | | |
695 | | /* Display the CC */ |
696 | 256 | if (encoding == E164_ENC_UTF8) |
697 | 27 | item = proto_tree_add_uint(tree, hf_E164_country_code, tvb, cc_offset, cc_length, cc); |
698 | 229 | else |
699 | 229 | item = proto_tree_add_uint(tree, hf_E164_country_code, tvb, cc_offset, length, cc); |
700 | 256 | if (!bcd_ok) { |
701 | 67 | expert_add_info(pinfo, item, &ei_E164_country_code_non_decimal); |
702 | 67 | } |
703 | | |
704 | | /* Handle special Country Codes */ |
705 | 256 | switch (cc) { |
706 | 0 | case 881: |
707 | | /* Get the 1-digit ID code */ |
708 | 0 | switch (encoding) { |
709 | 0 | case E164_ENC_BINARY: |
710 | 0 | id_code = tvb_get_uint8(tvb, cc_offset + 1) & 0x0f; |
711 | 0 | break; |
712 | 0 | case E164_ENC_BCD: |
713 | 0 | id_code = (tvb_get_uint8(tvb, cc_offset + 1) & 0xf0) >> 4; |
714 | 0 | break; |
715 | 0 | case E164_ENC_UTF8: |
716 | 0 | id_code = tvb_get_uint8(tvb, cc_offset + cc_length) - '0'; |
717 | 0 | break; |
718 | 0 | } |
719 | 0 | bcd_ok = (id_code <= 9); |
720 | 0 | item = proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 1, |
721 | 0 | id_code, "%d %s", id_code, val_to_str_const(id_code, E164_GMSS_vals, "Unknown")); |
722 | 0 | if (!bcd_ok) { |
723 | 0 | expert_add_info(pinfo, item, &ei_E164_identification_code_non_decimal); |
724 | 0 | } |
725 | 0 | break; |
726 | 0 | case 882: |
727 | | /* Get the 2-digit ID code */ |
728 | 0 | switch (encoding) { |
729 | 0 | case E164_ENC_BINARY: |
730 | 0 | id_code = tvb_get_ntohs(tvb, cc_offset + 1); |
731 | 0 | id_code = (id_code & 0x0ff0) >> 4; |
732 | 0 | break; |
733 | 0 | case E164_ENC_BCD: |
734 | 0 | id_code = tvb_get_uint8(tvb, cc_offset + 1) & 0xf0; |
735 | 0 | id_code |= tvb_get_uint8(tvb, cc_offset + 2) & 0x0f; |
736 | 0 | break; |
737 | 0 | case E164_ENC_UTF8: |
738 | 0 | id_code = (tvb_get_uint8(tvb, cc_offset+cc_length) - '0') << 4; |
739 | 0 | id_code |= (tvb_get_uint8(tvb, cc_offset+cc_length+1) - '0'); |
740 | 0 | break; |
741 | 0 | } |
742 | 0 | bcd_ok = convert_bcd_to_dec(id_code, &id_code); |
743 | 0 | item = proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 2, |
744 | 0 | id_code, "%d %s", id_code, val_to_str_ext_const(id_code, &E164_International_Networks_882_vals_ext, "Unknown")); |
745 | 0 | if (!bcd_ok) { |
746 | 0 | expert_add_info(pinfo, item, &ei_E164_identification_code_non_decimal); |
747 | 0 | } |
748 | 0 | break; |
749 | 0 | case 883: |
750 | | /* Get the 3-digit ID code */ |
751 | 0 | switch (encoding) { |
752 | 0 | case E164_ENC_BINARY: |
753 | 0 | id_code = tvb_get_ntohs(tvb, cc_offset + 1); |
754 | 0 | id_code = id_code & 0x0fff; |
755 | 0 | break; |
756 | 0 | case E164_ENC_BCD: |
757 | 0 | id_code = (tvb_get_uint8(tvb, cc_offset + 1) & 0xf0) << 4; |
758 | 0 | id_code |= (tvb_get_uint8(tvb, cc_offset + 2) & 0x0f) << 4; |
759 | 0 | id_code |= (tvb_get_uint8(tvb, cc_offset + 2) & 0xf0) >> 4; |
760 | 0 | break; |
761 | 0 | case E164_ENC_UTF8: |
762 | 0 | id_code = (tvb_get_uint8(tvb, cc_offset+cc_length) - '0') << 8; |
763 | 0 | id_code |= (tvb_get_uint8(tvb, cc_offset+cc_length+1) - '0') << 4; |
764 | 0 | id_code |= (tvb_get_uint8(tvb, cc_offset+cc_length+2) - '0'); |
765 | 0 | break; |
766 | 0 | } |
767 | 0 | if ((id_code & 0x0ff0) == 0x510) { |
768 | | /* Get the 4th digit of the ID code */ |
769 | 0 | switch (encoding) { |
770 | 0 | case E164_ENC_BINARY: |
771 | 0 | id_code = (id_code << 4) | ((tvb_get_uint8(tvb, cc_offset + 3) & 0xf0) >> 4); |
772 | 0 | break; |
773 | 0 | case E164_ENC_BCD: |
774 | 0 | id_code = (id_code << 4) | (tvb_get_uint8(tvb, cc_offset + 3) & 0x0f); |
775 | 0 | break; |
776 | 0 | case E164_ENC_UTF8: |
777 | 0 | id_code = (id_code << 4) | (tvb_get_uint8(tvb, cc_offset + cc_length + 3) - '0'); |
778 | 0 | break; |
779 | 0 | } |
780 | 0 | bcd_ok = convert_bcd_to_dec(id_code, &id_code); |
781 | 0 | item = proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 3, |
782 | 0 | id_code, "%d %s", id_code, val_to_str_const(id_code, E164_International_Networks_883_vals, "Unknown")); |
783 | 0 | if (!bcd_ok) { |
784 | 0 | expert_add_info(pinfo, item, &ei_E164_identification_code_non_decimal); |
785 | 0 | } |
786 | 0 | } else { |
787 | 0 | bcd_ok = convert_bcd_to_dec(id_code, &id_code); |
788 | 0 | item = proto_tree_add_uint_format_value(tree, hf_E164_identification_code, tvb, (cc_offset + 1), 2, |
789 | 0 | id_code, "%d %s", id_code, val_to_str_const(id_code, E164_International_Networks_883_vals, "Unknown")); |
790 | 0 | if (!bcd_ok) { |
791 | 0 | expert_add_info(pinfo, item, &ei_E164_identification_code_non_decimal); |
792 | 0 | } |
793 | 0 | } |
794 | 0 | break; |
795 | 256 | default: |
796 | 256 | break; |
797 | 256 | } |
798 | | |
799 | 256 | } |
800 | | |
801 | | static const char * |
802 | | dissect_e164(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset, int length, e164_encoding_t encoding, int name_type) |
803 | 267 | { |
804 | 267 | proto_item *pi; |
805 | 267 | proto_tree *subtree; |
806 | 267 | unsigned str_encoding; |
807 | 267 | char *number_str; |
808 | | |
809 | 267 | switch (encoding) { |
810 | 27 | case E164_ENC_UTF8: |
811 | 27 | str_encoding = ENC_UTF_8; |
812 | 27 | break; |
813 | 240 | case E164_ENC_BCD: |
814 | 240 | str_encoding = ENC_BCD_DIGITS_0_9|ENC_LITTLE_ENDIAN; |
815 | 240 | break; |
816 | 0 | case E164_ENC_BINARY: |
817 | 0 | default: |
818 | 0 | DISSECTOR_ASSERT_NOT_REACHED(); |
819 | 267 | } |
820 | | |
821 | 267 | pi = proto_tree_add_item_ret_display_string(tree, name_type, tvb, offset, length, str_encoding, pinfo->pool, &number_str); |
822 | | |
823 | 267 | subtree = proto_item_add_subtree(pi, ett_e164_msisdn); |
824 | | |
825 | 267 | dissect_e164_cc(tvb, pinfo, subtree, offset, encoding); |
826 | | |
827 | 267 | return number_str; |
828 | 267 | } |
829 | | |
830 | | const char * |
831 | | dissect_e164_msisdn(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset, int length, e164_encoding_t encoding) |
832 | 267 | { |
833 | 267 | return dissect_e164(tvb, pinfo, tree, offset, length, encoding, hf_E164_msisdn); |
834 | 267 | } |
835 | | |
836 | | const char * |
837 | | dissect_e164_isdn(tvbuff_t *tvb, packet_info* pinfo, proto_tree *tree, int offset, int length, e164_encoding_t encoding) |
838 | 0 | { |
839 | 0 | return dissect_e164(tvb, pinfo, tree, offset, length, encoding, hf_E164_isdn); |
840 | 0 | } |
841 | | |
842 | | /* |
843 | | * Register the protocol with Wireshark. |
844 | | */ |
845 | | |
846 | | void |
847 | | proto_register_e164(void) |
848 | 14 | { |
849 | | |
850 | | /* Setup list of header fields See Section 1.6.1 for details */ |
851 | 14 | static hf_register_info hf[] = { |
852 | 14 | { &hf_E164_calling_party_number, |
853 | 14 | { "E.164 Calling party number digits", "e164.calling_party_number.digits", |
854 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
855 | 14 | NULL, HFILL }}, |
856 | | |
857 | 14 | { &hf_E164_called_party_number, |
858 | 14 | { "E.164 Called party number digits", "e164.called_party_number.digits", |
859 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
860 | 14 | NULL, HFILL }}, |
861 | | |
862 | 14 | { &hf_E164_msisdn, |
863 | 14 | { "E.164 number (MSISDN)", "e164.msisdn", |
864 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
865 | 14 | NULL, HFILL }}, |
866 | | |
867 | 14 | { &hf_E164_isdn, |
868 | 14 | { "E.164 number (ISDN)", "e164.isdn", |
869 | 14 | FT_STRING, BASE_NONE, NULL, 0x0, |
870 | 14 | NULL, HFILL }}, |
871 | | |
872 | 14 | { &hf_E164_identification_code, |
873 | 14 | { "Identification Code", "e164.identification_code", |
874 | 14 | FT_UINT32, BASE_DEC, NULL, 0x0, |
875 | 14 | NULL, HFILL }}, |
876 | | |
877 | 14 | { &hf_E164_country_code, |
878 | 14 | { "Country Code", "e164.country_code", |
879 | 14 | FT_UINT16, BASE_DEC|BASE_EXT_STRING, &E164_country_code_value_ext, 0x0, |
880 | 14 | NULL, HFILL }}, |
881 | 14 | }; |
882 | | |
883 | 14 | static int *ett_e164_array[] = { |
884 | 14 | &ett_e164_msisdn, |
885 | 14 | }; |
886 | | |
887 | 14 | static ei_register_info ei[] = { |
888 | 14 | { &ei_E164_country_code_non_decimal, { "e164.country_code.non_decimal", PI_MALFORMED, PI_WARN, "Country Code contains non-decimal digits", EXPFILL }}, |
889 | 14 | { &ei_E164_identification_code_non_decimal, { "e164.identification_code.non_decimal", PI_MALFORMED, PI_WARN, "Identification Code contains non-decimal digits", EXPFILL }}, |
890 | 14 | }; |
891 | | |
892 | 14 | expert_module_t* expert_e164; |
893 | | |
894 | | |
895 | 14 | proto_e164 = proto_register_protocol("ITU-T E.164 number", "E.164", "e164"); |
896 | | |
897 | 14 | proto_register_field_array(proto_e164, hf, array_length(hf)); |
898 | 14 | proto_register_subtree_array(ett_e164_array, array_length(ett_e164_array)); |
899 | | |
900 | 14 | expert_e164 = expert_register_protocol(proto_e164); |
901 | 14 | expert_register_field_array(expert_e164, ei, array_length(ei)); |
902 | 14 | } |
903 | | |
904 | | /* |
905 | | * Editor modelines - https://www.wireshark.org/tools/modelines.html |
906 | | * |
907 | | * Local variables: |
908 | | * c-basic-offset: 8 |
909 | | * tab-width: 8 |
910 | | * indent-tabs-mode: t |
911 | | * End: |
912 | | * |
913 | | * vi: set shiftwidth=8 tabstop=8 noexpandtab: |
914 | | * :indentSize=8:tabSize=8:noTabs=false: |
915 | | */ |