Implement COMPLEMENT TO ITU-T RECOMMENDATION E.164 (02/2005):
[obnox/wireshark/wip.git] / epan / dissectors / packet-e164.c
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  * $Id$
7  *
8  * Wireshark - Network traffic analyzer
9  * By Gerald Combs <gerald@wireshark.org>
10  * Copyright 1998 Gerald Combs
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This program is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU General Public License for more details.
21  *
22  * You should have received a copy of the GNU General Public License
23  * along with this program; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
25  *
26  * Ref ITU-T E.164 05/97 
27  *     Annex to ITU Operational Bulletin No. 835 - 1.V.2005
28  */
29
30 #ifdef HAVE_CONFIG_H
31 # include "config.h"
32 #endif
33
34 #include <glib.h>
35 #include <epan/packet.h>
36 #include "packet-e164.h"
37
38 const value_string E164_country_code_value[] = {
39         { 0x00, "Reserved (Assignment of all 0XX codes will be feasible after 31 December 2000. This question is currently under study.)"}, 
40         { 0x01, "Americas"}, 
41         { 0x020,"Egypt"},
42         { 0x0210,"Spare code"},
43         { 0x0211,"Spare code"},
44         { 0x0212,"Morocco"},
45         { 0x0213,"Algeria"},
46         { 0x0214,"spare code"},
47         { 0x0215,"spare code"}, 
48         { 0x0216,"Tunisia"}, 
49         { 0x0217,"Spare code"}, 
50         { 0x0218,"Libya"},
51         { 0x0219,"Spare code"}, 
52         { 0x0220,"Gambia"},
53         { 0x0221,"Senegal"},
54         { 0x0222,"Mauritania"}, 
55         { 0x0223,"Mali"},
56         { 0x0224,"Guinea"},
57         { 0x0225,"Ivory Coast"}, 
58         { 0x0226,"Burkina Faso"},
59         { 0x0227,"Niger"},
60         { 0x0228,"Togolese Republic"},
61         { 0x0229,"Benin"},
62         { 0x0230,"Mauritius"}, 
63         { 0x0231,"Liberia "},
64         { 0x0232,"Sierra Leone"},
65         { 0x0233,"Ghana"},
66         { 0x0234,"Nigeria"},
67         { 0x0235,"Chad"},
68         { 0x0236,"Central African Republic"},
69         { 0x0237,"Cameroon"},
70         { 0x0238,"Cape Verde"},
71         { 0x0239,"Sao Tome and Principe"},
72         { 0x0240,"Equatorial Guinea"},
73         { 0x0241,"Gabonese Republic"},
74         { 0x0242,"Republic of Congo"},
75         { 0x0243,"Democratic Republic of Congo"},
76         { 0x0244,"Angola"},
77         { 0x0245,"Guinea-Bissau"},
78         { 0x0246,"Diego Garcia"},
79         { 0x0247,"Ascension"},
80         { 0x0248,"Seychelles"},
81         { 0x0249,"Sudan"},
82         { 0x0250,"Rwandese Republic"},
83         { 0x0251,"Ethiopia"},
84         { 0x0252,"Somali"},
85         { 0x0253,"Djibouti"},
86         { 0x0254,"Kenya"},
87         { 0x0255,"Tanzania"}, 
88         { 0x0256,"Uganda"},
89         { 0x0257,"Burundi"},
90         { 0x0258,"Mozambique"}, 
91         { 0x0259,"Spare code"},
92         { 0x0260,"Zambia"},
93         { 0x0261,"Madagascar"}, 
94         { 0x0262,"Reunion Island"}, 
95         { 0x0263,"Zimbabwe"},
96         { 0x0264,"Namibia"},
97         { 0x0265,"Malawi"},
98         { 0x0266,"Lesotho"},
99         { 0x0267,"Botswana"},
100         { 0x0268,"Swaziland"},
101         { 0x0269,"Comoros Mayotte"},
102         { 0x027,"South Africa"},
103         { 0x0280,"spare code"},
104         { 0x0281,"spare code"},
105         { 0x0282,"spare code"},
106         { 0x0283,"spare code"},
107         { 0x0284,"spare code"},
108         { 0x0285,"spare code"},
109         { 0x0286,"spare code"},
110         { 0x0287,"spare code"},
111         { 0x0288,"spare code"},
112         { 0x0289,"spare code"},
113         { 0x0290,"Saint Helena"},
114         { 0x0291,"Eritrea"},
115         { 0x0292,"spare code"}, 
116         { 0x0293,"spare code"},
117         { 0x0294,"spare code"},
118         { 0x0295,"spare code"},
119         { 0x0296,"spare code"},
120         { 0x0297,"Aruba"}, 
121         { 0x0298,"Faroe Islands"},
122         { 0x0299,"Greenland"},
123         { 0x030,"Greece"},
124         { 0x031,"Netherlands"}, 
125         { 0x032,"Belgium"},
126         { 0x033,"France"},
127         { 0x034,"Spain"},
128         { 0x0350,"Gibraltar"}, 
129         { 0x0351,"Portugal"},
130         { 0x0352,"Luxembourg"}, 
131         { 0x0353,"Ireland"},
132         { 0x0354,"Iceland"},
133         { 0x0355,"Albania"},
134         { 0x0356,"Malta"},
135         { 0x0357,"Cyprus"},
136         { 0x0358,"Finland"},
137         { 0x0359,"Bulgaria"},
138         { 0x036,"Hungary"},
139         { 0x0370,"Lithuania"}, 
140         { 0x0371,"Latvia"},
141         { 0x0372,"Estonia"},
142         { 0x0373,"Moldova"},
143         { 0x0374,"Armenia"},
144         { 0x0375,"Belarus"},
145         { 0x0376,"Andorra"},
146         { 0x0377,"Monaco"},
147         { 0x0378,"San Marino"}, 
148         { 0x0379,"Vatican"},
149         { 0x0380,"Ukraine"},
150         { 0x0381,"Serbia and Montenegro"}, 
151         { 0x0382,"spare code"},
152         { 0x0383,"spare code"},
153         { 0x0384,"spare code"},
154         { 0x0385,"Croatia"},
155         { 0x0386,"Slovenia"},
156         { 0x0387,"Bosnia and Herzegovina"},
157         { 0x0388,"Groups of contries:"},  
158         { 0x0389,"Macedonia"},
159         { 0x039,"Italy"},
160         { 0x040,"Romania"}, 
161         { 0x041,"Switzerland"}, 
162         { 0x0420,"Czech Republic"}, 
163         { 0x0421,"Slovak Republic"},
164         { 0x0422,"Spare code"},
165         { 0x0423,"Liechtenstein"}, 
166         { 0x0424,"spare code"},
167         { 0x0425,"spare code"},
168         { 0x0426,"spare code"},
169         { 0x0427,"spare code"},
170         { 0x0428,"spare code"},
171         { 0x0429,"spare code"}, 
172         { 0x043,"Austria"},
173         { 0x044,"United Kingdom"},
174         { 0x045,"Denmark"},
175         { 0x046,"Sweden"},
176         { 0x047,"Norway"},
177         { 0x048,"Poland"},
178         { 0x049,"Germany"},
179         { 0x0500,"Falkland Islands (Malvinas)"},
180         { 0x0501,"Belize"},
181         { 0x0502,"Guatemala"}, 
182         { 0x0503,"El Salvador"}, 
183         { 0x0504,"Honduras"},
184         { 0x0505,"Nicaragua"},
185         { 0x0506,"Costa Rica"},
186         { 0x0507,"Panama"},
187         { 0x0508,"Saint Pierre and Miquelon"}, 
188         { 0x0509,"Haiti"},
189         { 0x051,"Peru"},
190         { 0x052,"Mexico"}, 
191         { 0x053,"Cuba"},
192         { 0x054,"Argentina"},
193         { 0x055,"Brazil"},
194         { 0x056,"Chile"},
195         { 0x057,"Colombia"}, 
196         { 0x058,"Venezuela"},
197         { 0x0590,"Guadeloupe"}, 
198         { 0x0591,"Bolivia"},
199         { 0x0592,"Guyana"},
200         { 0x0593,"Ecuador"},
201         { 0x0594,"French Guiana"}, 
202         { 0x0595,"Paraguay"},
203         { 0x0596,"Martinique"}, 
204         { 0x0597,"Suriname"},
205         { 0x0598,"Uruguay"},
206         { 0x0599,"Netherlands Antilles"}, 
207         { 0x060,"Malaysia"},
208         { 0x061,"Australia"},
209         { 0x062,"Indonesia"},
210         { 0x063,"Philippines"}, 
211         { 0x064,"New Zealand"},
212         { 0x065,"Singapore"},
213         { 0x066,"Thailand"},
214         { 0x0670,"East Timor"}, 
215         { 0x0671,"Spare code"},
216         { 0x0672,"Australian External Territories"}, 
217         { 0x0673,"Brunei Darussalam"},
218         { 0x0674,"Nauru"},
219         { 0x0675,"Papua New Guinea"},
220         { 0x0676,"Tonga"},
221         { 0x0677,"Solomon Islands"},
222         { 0x0678,"Vanuatu"},
223         { 0x0679,"Fiji"},
224         { 0x0680,"Palau"},
225         { 0x0681,"Wallis and Futuna"},
226         { 0x0682,"Cook Islands"},
227         { 0x0683,"Niue"},
228         { 0x0684,"Spare code"},
229         { 0x0685,"Samoa"},
230         { 0x0686,"Kiribati"},
231         { 0x0687,"New Caledonia"},
232         { 0x0688,"Tuvalu"},
233         { 0x0689,"French Polynesia"},
234         { 0x0690,"Tokelau"},
235         { 0x0691,"Micronesia"}, 
236         { 0x0692,"Marshall Islands"},
237         { 0x0693,"spare code"},
238         { 0x0694,"spare code"},
239         { 0x0695,"spare code"},
240         { 0x0696,"spare code"},
241         { 0x0697,"spare code"},
242         { 0x0698,"spare code"},
243         { 0x0699,"spare code"},
244         { 0x07,"Russian Federation,Kazakstan"}, 
245         { 0x0800,"International Freephone Service (see E.169.1)"}, 
246         { 0x0801,"spare code"},
247         { 0x0802,"spare code"},
248         { 0x0803,"spare code"},
249         { 0x0804,"spare code"},
250         { 0x0805,"spare code"},
251         { 0x0806,"spare code"},
252         { 0x0807,"spare code"},
253         { 0x0808,"Universal International Shared Cost Number (see E.169.3)"}, 
254         { 0x0809,"Spare code"},
255         { 0x081,"Japan"},
256         { 0x082,"Korea (Republic of)"}, 
257         { 0x0830,"Spare code"},
258         { 0x0831,"Spare code"},
259         { 0x0832,"Spare code"},
260         { 0x0833,"Spare code"},
261         { 0x0834,"Spare code"},
262         { 0x0835,"Spare code"},
263         { 0x0836,"Spare code"},
264         { 0x0837,"Spare code"},
265         { 0x0838,"Spare code"},
266         { 0x0839,"Spare code"},
267         { 0x084,"Viet Nam"},
268         { 0x0850,"Democratic People's Republic of Korea"}, 
269         { 0x0851,"Spare code"},
270         { 0x0852,"Hong Kong, China"}, 
271         { 0x0853,"Macau, China"},
272         { 0x0854,"Spare code"},
273         { 0x0855,"Cambodia"},
274         { 0x0856,"Laos"},
275         { 0x0857,"Spare code"},
276         { 0x0858,"Spare code"},
277         { 0x0859,"Spare code"},
278         { 0x086,"China (People's Republic of)"},
279         { 0x0870,"Inmarsat SNAC"},
280         { 0x0871,"Inmarsat (Atlantic Ocean-East)"}, 
281         { 0x0872,"Inmarsat (Pacific Ocean)"},
282         { 0x0873,"Inmarsat (Indian Ocean)"},
283         { 0x0874,"Inmarsat (Atlantic Ocean-West)"},
284         { 0x0875,"Reserved - Maritime Mobile Service Applications"},
285         { 0x0876,"Reserved - Maritime Mobile Service Applications"},
286         { 0x0877,"Reserved - Maritime Mobile Service Applications"}, 
287         { 0x0878,"Reserved - Universal Personal Telecommunication Service (UPT)"}, 
288         { 0x0879,"Reserved for national non-commercial purposes"},
289         { 0x0880,"Bangladesh"},
290         { 0x0881,"Global Mobile Satellite System (GMSS), shared code:"}, 
291         { 0x0882,"International Networks: (see E.164)"},
292         { 0x0883,"Spare code"},
293         { 0x0884,"Spare code"},
294         { 0x0885,"Spare code"},
295         { 0x0886,"Reserved"}, 
296         { 0x0887,"Spare code"},
297         { 0x0888,"Reserved for future global services (see E.164)"}, 
298         { 0x0889,"Spare code"},
299         { 0x0890,"Spare code"},
300         { 0x0891,"Spare code"},
301         { 0x0892,"Spare code"},
302         { 0x0893,"Spare code"},
303         { 0x0894,"Spare code"},
304         { 0x0895,"Spare code"},
305         { 0x0896,"Spare code"},
306         { 0x0897,"Spare code"},
307         { 0x0898,"Spare code"},
308         { 0x0899,"Spare code"}, 
309         { 0x090,"Turkey"}, 
310         { 0x091,"India"},
311         { 0x092,"Pakistan"}, 
312         { 0x093,"Afghanistan"}, 
313         { 0x094,"Sri Lanka"},
314         { 0x095,"Myanmar"},
315         { 0x0960,"Maldives"}, 
316         { 0x0961,"Lebanon"},
317         { 0x0962,"Jordan"},
318         { 0x0963,"Syrian Arab Republic"}, 
319         { 0x0964,"Iraq"},
320         { 0x0965,"Kuwait"}, 
321         { 0x0966,"Saudi Arabia"}, 
322         { 0x0967,"Yemen"},
323         { 0x0968,"Oman"},
324         { 0x0969,"Reserved"}, 
325         { 0x0970,"Reserved"},
326         { 0x0971,"United Arab Emirates"}, 
327         { 0x0972,"Israel"},
328         { 0x0973,"Bahrain"},
329         { 0x0974,"Qatar"},
330         { 0x0975,"Bhutan"},
331         { 0x0976,"Mongolia"}, 
332         { 0x0977,"Nepal"},
333         { 0x0978,"Spare code"}, 
334         { 0x0979,"Universal International Premium Rate Number (see E.169.2)"}, 
335         { 0x098,"Iran"},
336         { 0x0990,"Spare code"}, 
337         { 0x0991,"Trial service (see E.164.2)"}, 
338         { 0x0992,"Tajikstan"},
339         { 0x0993,"Turkmenistan"}, 
340         { 0x0994,"Azerbaijani Republic"}, 
341         { 0x0995,"Georgia"},
342         { 0x0996,"Kyrgyz Republic"}, 
343         { 0x0997,"Spare code"},
344         { 0x0998,"Uzbekistan"},
345         { 0x0999,"Reserved"},
346         { 0,    NULL }
347 };    
348 const value_string E164_International_Networks_vals[] = {
349         {   0x10, "British Telecommunications"}, 
350         {   0x11, "Singapore Telecommunications"},
351         {   0x12, "MCI"},
352         {   0x13, "Telespazio"},
353         {   0x14, "GTE"},
354         {   0x15, "Reach"}, 
355         {   0x16, "United Arab Emirates"}, 
356         {   0x17, "AT&T"},
357         {   0x18, "Teledesic"}, 
358         {   0x19, "Telecom Italia"}, 
359         {   0x20, "Asia Cellular Satellite"}, 
360         {   0x21, "Ameritech"},
361         {   0x22, "Cable & Wireless"}, 
362         {   0x23, "Sita-Equant"},
363         {   0x24, "TeliaSonera AB"},
364         {   0x25, "Constellation Communications"}, 
365         {   0x26, "SBC Communications"},
366         {   0x28, "Deutsche Telekom"},
367         {   0x29, "Q-Tel"},
368         {   0x30, "Singapore Telecom"},
369         {   0x31, "Telekom Malaysia"},
370         {   0x32, "Maritime Communications Partners"},
371         {   0x33, "Oration Technologies"},
372         {   0x34, "Global Networks"},
373         {   0x98, "SITA"},
374         {   0x99, "Telenor"},
375         { 0,    NULL }
376 };    
377
378 static int proto_e164                                           = -1;
379 static int hf_E164_calling_party_number         = -1;
380 static int hf_E164_called_party_number          = -1;
381
382
383
384 void
385 dissect_e164_number(tvbuff_t *tvb, proto_tree *tree, int offset, int length,e164_info_t e164_info)
386 {
387         switch (e164_info.e164_number_type){
388         case CALLING_PARTY_NUMBER :
389                 proto_tree_add_string(tree, hf_E164_calling_party_number, tvb, offset,
390                                 length, e164_info.E164_number_str);
391                 break;
392
393         case CALLED_PARTY_NUMBER :
394                 proto_tree_add_string(tree, hf_E164_called_party_number, tvb, offset,
395                                 length, e164_info.E164_number_str);
396                 break;
397
398         default:
399                 break;
400         }
401
402 }
403 void
404 dissect_e164_cc(tvbuff_t *tvb, proto_tree *tree, int offset, gboolean bcd_coded){
405
406         int     cc_offset;
407         guint8  address_digit_pair;
408         guint16 id_code;
409         guint8  cc_length;
410         guint8  length;
411         guint16 cc;
412
413         cc_offset = offset;
414         address_digit_pair = tvb_get_guint8(tvb, cc_offset);
415
416         if(!bcd_coded){
417                 /* Dissect country code after removing non significant zeros */
418                 while ( address_digit_pair == 0 ) {
419                         cc_offset = cc_offset + 1;
420                         address_digit_pair = tvb_get_guint8(tvb, cc_offset);
421                 }
422                 cc = tvb_get_ntohs(tvb, cc_offset);
423                 if (( address_digit_pair & 0xf0 ) != 0 ){
424                         cc = cc >> 4;
425                 }
426         }else{
427                 cc = address_digit_pair &0x0f;
428                 cc = cc << 4;
429                 cc = cc | (address_digit_pair &0xf0)>>4;
430                 cc = cc << 4;
431                 cc_offset = cc_offset + 1;
432                 address_digit_pair = tvb_get_guint8(tvb, cc_offset);
433                 cc = cc | (address_digit_pair &0x0f);
434
435         }
436
437         switch ( cc & 0x0f00 ) {
438
439         case 0x0:
440                 cc_length = 1;  
441                 break;
442
443         case 0x0100:
444                 cc_length = 1;  
445                 break;
446
447         case 0x0200:
448                 switch ( cc & 0x00f0 ) {
449                 case 0: 
450                 case 7 : 
451                         cc_length = 2;  
452                         break;
453                 default : 
454                         cc_length = 3;
455                         break;
456                 }
457                 break;
458                                 
459         case 0x0300 :
460                 switch ( cc & 0x00f0 ) {
461                 case 0 : 
462                 case 0x10 : 
463                 case 0x20 : 
464                 case 0x30 : 
465                 case 0x40 : 
466                 case 0x60 : 
467                 case 0x90 : 
468                         cc_length = 2;
469                         break;  
470                 default :
471                         cc_length = 3;
472                         break;
473                 }
474                 break;
475         case 0x0400 : 
476                 switch ( cc & 0x00f0 ) {
477                 case 0x20 :
478                         cc_length = 3;
479                         break;  
480                 default :
481                         cc_length = 2;
482                         break;
483                 }
484                 break;
485
486         case 0x0500 : 
487                 switch ( cc & 0x00f0 ) {
488                 case 0 : 
489                 case 0x90 :
490                         cc_length = 3;
491                         break;  
492                 default :
493                         cc_length = 2;
494                         break;
495                 }
496                 break;
497
498         case 0x0600 : 
499                 switch ( cc & 0x00f0 ) {
500                 case 0x70 : 
501                 case 0x80 : 
502                 case 0x90 :
503                         cc_length = 3; 
504                         break;  
505                 default :
506                         cc_length = 2;
507                         break;
508                 }
509                 break;
510
511         case 0x0700 : 
512                 cc_length = 1;  
513                 break;
514
515         case 0x0800 : 
516                 switch ( cc & 0x00f0 ) {
517                 case 0x10: 
518                 case 0x20: 
519                 case 0x40: 
520                 case 0x60:
521                         cc_length = 2; 
522                         break;  
523                 default :
524                         cc_length = 3;
525                         break;
526                 }
527                 break;
528
529         case 0x0900 : 
530                 switch ( cc & 0x00f0 ) {
531                 case 0 : 
532                 case 0x10 : 
533                 case 0x20 :  
534                 case 0x30 :  
535                 case 0x40 :  
536                 case 0x50 :  
537                 case 0x80 : 
538                         cc_length = 2; 
539                         break;  
540                 default : 
541                         cc_length = 3;
542                         break;
543                 }
544                 break;
545
546         default :
547                 cc_length = 0;
548                 break;
549         }/* End switch cc */
550
551         switch ( cc_length ) {
552         case 1 :
553                 cc = cc >> 8;
554                 length = 1;
555                 break;
556         case 2 :
557                 cc = cc >> 4;
558                 length = 1;
559                 break;
560         default:
561                 length = 2;
562                 break;
563         }/* end switch cc_length */
564
565         proto_tree_add_text(tree,tvb, cc_offset, length,"Country Code: %x %s length %u",cc,
566                                 val_to_str(cc,E164_country_code_value,"unknown (%x)"),cc_length);
567         switch ( cc ) {
568         case 0x882 :
569                 id_code = tvb_get_ntohs(tvb, cc_offset + 1);
570                 id_code = (id_code & 0x0fff) >> 4;
571                 proto_tree_add_text(tree,tvb, (cc_offset + 1), 2,"Identification Code: %x %s ",id_code,
572                                                 val_to_str(id_code,E164_International_Networks_vals,"unknown (%x)"));
573                 break;
574         default:
575                 break;
576         }
577
578 }
579
580 /*
581  * Register the protocol with Wireshark.
582  *
583  * This format is required because a script is used to build the C function
584  * that calls all the protocol registration.
585  */
586
587 void
588 proto_register_e164(void)
589 {
590
591         /* Setup list of header fields  See Section 1.6.1 for details */
592         static hf_register_info hf[] = {
593                 { &hf_E164_calling_party_number,
594                   { "E.164 Calling party number digits", "e164.calling_party_number.digits",
595                   FT_STRING, BASE_NONE, NULL, 0x0,
596                         "", HFILL }},
597
598                 { &hf_E164_called_party_number,
599                   { "E.164 Called party number digits", "e164.called_party_number.digits",
600                   FT_STRING, BASE_NONE, NULL, 0x0,
601                         "", HFILL }}
602         };
603
604         /*
605          * Register the protocol name and description
606          */
607         proto_e164 = proto_register_protocol(
608                         "ITU-T E.164 number",
609                         "E.164",
610                         "e164");
611
612         /*
613          * Required function calls to register
614          * the header fields and subtrees used.
615          */
616         proto_register_field_array(proto_e164, hf, array_length(hf));
617
618 }