All messages converted to the "GSM style" dissection.
[obnox/wireshark/wip.git] / epan / address_to_str.c
1 /* address_to_str.c
2  * Routines for utilities to convert addresses to strings.
3  *
4  * $Id$
5  *
6  * Wireshark - Network traffic analyzer
7  * By Gerald Combs <gerald@wireshark.org>
8  * Copyright 1998 Gerald Combs
9  *
10  * This program is free software; you can redistribute it and/or
11  * modify it under the terms of the GNU General Public License
12  * as published by the Free Software Foundation; either version 2
13  * of the License, or (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
23  */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #include <stdlib.h>
30 #include <string.h>
31
32 #ifdef HAVE_SYS_TYPES_H
33 # include <sys/types.h>         /* needed for <netinet/in.h> */
34 #endif
35
36 #ifdef HAVE_NETINET_IN_H
37 # include <netinet/in.h>        /* needed for <arpa/inet.h> on some platforms */
38 #endif
39
40 #ifdef HAVE_ARPA_INET_H
41 #include <arpa/inet.h>
42 #endif
43
44 #ifdef HAVE_SYS_SOCKET_H
45 #include <sys/socket.h>         /* needed to define AF_ values on UNIX */
46 #endif
47
48 #ifdef HAVE_WINSOCK2_H
49 #include <winsock2.h>           /* needed to define AF_ values on Windows */
50 #endif
51
52 #ifdef NEED_INET_V6DEFS_H
53 # include "wsutil/inet_v6defs.h"
54 #endif
55
56 #include "to_str.h"
57 #include "value_string.h"
58 #include "addr_resolv.h"
59 #include "pint.h"
60 #include "atalk-utils.h"
61 #include "sna-utils.h"
62 #include "osi-utils.h"
63 #include <epan/dissectors/packet-mtp3.h>
64 #include <stdio.h>
65 #include "emem.h"
66
67 /* private to_str.c API, don't export to .h! */
68 char *word_to_hex(char *out, guint16 word);
69 char *dword_to_hex_punct(char *out, guint32 dword, char punct);
70 char *dword_to_hex(char *out, guint32 dword);
71 char *bytes_to_hexstr(char *out, const guint8 *ad, guint32 len);
72 char *bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct);
73
74 /*
75  * If a user _does_ pass in a too-small buffer, this is probably
76  * going to be too long to fit.  However, even a partial string
77  * starting with "[Buf" should provide enough of a clue to be
78  * useful.
79  */
80 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
81
82 /* Wrapper for the most common case of asking
83  * for a string using a colon as the hex-digit separator.
84  */
85 /* XXX FIXME
86 remove this one later when every call has been converted to ep_address_to_str()
87 */
88 gchar *
89 ether_to_str(const guint8 *ad)
90 {
91         return bytestring_to_str(ad, 6, ':');
92 }
93
94 gchar *
95 tvb_ether_to_str(tvbuff_t *tvb, const gint offset)
96 {
97         return bytestring_to_str(tvb_get_ptr(tvb, offset, 6), 6, ':');
98 }
99
100 /*
101  This function is very fast and this function is called a lot.
102  XXX update the ep_address_to_str stuff to use this function.
103 */
104 const gchar *
105 ip_to_str(const guint8 *ad) {
106   gchar *buf;
107
108   buf=ep_alloc(MAX_IP_STR_LEN);
109   ip_to_str_buf(ad, buf, MAX_IP_STR_LEN);
110   return buf;
111 }
112
113 #define IPV4_LENGTH 4
114 const gchar *
115 tvb_ip_to_str(tvbuff_t *tvb, const gint offset)
116 {
117   gchar *buf;
118
119   buf=ep_alloc(MAX_IP_STR_LEN);
120   ip_to_str_buf(tvb_get_ptr(tvb, offset, IPV4_LENGTH), buf, MAX_IP_STR_LEN);
121   return buf;
122 }
123
124 /* XXX FIXME
125 remove this one later when every call has been converted to ep_address_to_str()
126 */
127 gchar *
128 ip6_to_str(const struct e_in6_addr *ad) {
129 #ifndef INET6_ADDRSTRLEN
130 #define INET6_ADDRSTRLEN 46
131 #endif
132   gchar *str;
133
134   str=ep_alloc(INET6_ADDRSTRLEN+1);
135
136   ip6_to_str_buf(ad, str);
137   return str;
138 }
139
140 #define IPV6_LENGTH 16
141 gchar *
142 tvb_ip6_to_str(tvbuff_t *tvb, const gint offset)
143 {
144   gchar *buf;
145
146   buf=ep_alloc(INET6_ADDRSTRLEN+1);
147   ip6_to_str_buf((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, IPV6_LENGTH), buf);
148   return buf;
149 }
150
151 void
152 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
153 {
154   inet_ntop(AF_INET6, (const guchar*)ad, buf, INET6_ADDRSTRLEN);
155 }
156
157 gchar*
158 ipx_addr_to_str(const guint32 net, const guint8 *ad)
159 {
160         gchar   *buf;
161         char    *name;
162
163         name = get_ether_name_if_known(ad);
164
165         if (name) {
166                 buf = ep_strdup_printf("%s.%s", get_ipxnet_name(net), name);
167         }
168         else {
169                 buf = ep_strdup_printf("%s.%s", get_ipxnet_name(net),
170                     bytestring_to_str(ad, 6, '\0'));
171         }
172         return buf;
173 }
174
175 gchar*
176 ipxnet_to_string(const guint8 *ad)
177 {
178         guint32 addr = pntohl(ad);
179         return ipxnet_to_str_punct(addr, ' ');
180 }
181
182 gchar *
183 ipxnet_to_str_punct(const guint32 ad, const char punct)
184 {
185   gchar *buf = ep_alloc(12);
186
187   *dword_to_hex_punct(buf, ad, punct) = '\0';
188   return buf;
189 }
190
191 static void
192 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
193 {
194   if (buf_len < 14) {
195      g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);        /* Let the unexpected value alert user */
196      return;
197   }
198
199   buf    = dword_to_hex(buf, pntohl(&addrp[0]));        /* 8 bytes */
200   *buf++ = '.';                                         /* 1 byte */
201   buf    = word_to_hex(buf, pntohs(&addrp[4]));         /* 4 bytes */
202   *buf   = '\0';                                        /* 1 byte */
203 }
204
205 gchar *
206 tvb_vines_addr_to_str(tvbuff_t *tvb, const gint offset)
207 {
208   gchar *buf;
209
210   buf=ep_alloc(214); /* XXX, 14 here? */
211
212   vines_addr_to_str_buf(tvb_get_ptr(tvb, offset, VINES_ADDR_LEN), buf, 214);
213   return buf;
214 }
215
216 static void
217 usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
218 {
219   if(pletohl(&addrp[0])==0xffffffff){
220     g_snprintf(buf, buf_len, "host");
221   } else {
222     g_snprintf(buf, buf_len, "%d.%d", pletohl(&addrp[0]), pletohl(&addrp[4]));
223   }
224 }
225
226 static void
227 tipc_addr_to_str_buf( const guint8 *data, gchar *buf, int buf_len){
228         guint8 zone;
229         guint16 subnetwork;
230         guint16 processor;
231         guint32 tipc_address;
232
233         tipc_address = data[0];
234         tipc_address = (tipc_address << 8) ^ data[1];
235         tipc_address = (tipc_address << 8) ^ data[2];
236         tipc_address = (tipc_address << 8) ^ data[3];
237
238         processor = tipc_address & 0x0fff;
239
240         tipc_address = tipc_address >> 12;
241         subnetwork = tipc_address & 0x0fff;
242
243         tipc_address = tipc_address >> 12;
244         zone = tipc_address & 0xff;
245
246         g_snprintf(buf,buf_len,"%u.%u.%u",zone,subnetwork,processor);
247 }
248
249 static void
250 ib_addr_to_str_buf( const address *addr, gchar *buf, int buf_len){
251         if (addr->len >= 16) {  /* GID is 128bits */
252                 #define PREAMBLE_STR_LEN                (sizeof("GID: ") - 1)
253                 g_snprintf(buf,buf_len,"GID: ");
254                 if (    inet_ntop(AF_INET6, addr->data, buf + PREAMBLE_STR_LEN,
255                                                   buf_len + PREAMBLE_STR_LEN) == NULL ) /* Returns NULL if no space and does not touch buf */
256                         g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
257         } else {        /* this is a LID (16 bits) */
258                 guint16 lid_number = *((guint16*) addr->data);
259                 g_snprintf(buf,buf_len,"LID: %u",lid_number);
260         }
261 }
262
263 /* XXX FIXME
264 remove this one later when every call has been converted to ep_address_to_str()
265 */
266 gchar *
267 fc_to_str(const guint8 *ad)
268 {
269     return bytestring_to_str (ad, 3, '.');
270 }
271
272 gchar *
273 tvb_fc_to_str(tvbuff_t *tvb, const gint offset)
274 {
275     return bytestring_to_str (tvb_get_ptr(tvb, offset, 3), 3, '.');
276 }
277
278 /* FC Network Header Network Address Authority Identifiers */
279
280 #define FC_NH_NAA_IEEE          1       /* IEEE 802.1a */
281 #define FC_NH_NAA_IEEE_E        2       /* IEEE Exteneded */
282 #define FC_NH_NAA_LOCAL         3
283 #define FC_NH_NAA_IP            4       /* 32-bit IP address */
284 #define FC_NH_NAA_IEEE_R        5       /* IEEE Registered */
285 #define FC_NH_NAA_IEEE_R_E      6       /* IEEE Registered Exteneded */
286 /* according to FC-PH 3 draft these are now reclaimed and reserved */
287 #define FC_NH_NAA_CCITT_INDV    12      /* CCITT 60 bit individual address */
288 #define FC_NH_NAA_CCITT_GRP     14      /* CCITT 60 bit group address */
289
290 gchar *
291 fcwwn_to_str (const guint8 *ad)
292 {
293     int fmt;
294     guint8 oui[6];
295     gchar *ethstr;
296     gchar *ethptr;
297
298     if (ad == NULL) return NULL;
299
300     ethstr=ep_alloc(512);
301     ethptr = bytes_to_hexstr_punct(ethstr, ad, 8, ':'); /* 23 bytes */
302
303     fmt = (ad[0] & 0xF0) >> 4;
304
305     switch (fmt) {
306
307     case FC_NH_NAA_IEEE:
308     case FC_NH_NAA_IEEE_E:
309         memcpy (oui, &ad[2], 6);
310
311         g_snprintf (ethptr, 512-23, " (%s)", get_manuf_name (oui));
312         break;
313
314     case FC_NH_NAA_IEEE_R:
315         oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
316         oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
317         oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
318         oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
319         oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
320         oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
321
322         g_snprintf (ethptr, 512-23, " (%s)", get_manuf_name (oui));
323         break;
324
325     default:
326         *ethptr = '\0';
327         break;
328     }
329     return (ethstr);
330 }
331
332 gchar *
333 tvb_fcwwn_to_str(tvbuff_t *tvb, const gint offset)
334 {
335         return fcwwn_to_str (tvb_get_ptr(tvb, offset, 8));
336 }
337
338 /*XXX FIXME the code below may be called very very frequently in the future.
339   optimize it for speed and get rid of the slow sprintfs */
340 /* XXX - perhaps we should have individual address types register
341    a table of routines to do operations such as address-to-name translation,
342    address-to-string translation, and the like, and have this call them,
343    and also have an address-to-string-with-a-name routine */
344 /* XXX - use this, and that future address-to-string-with-a-name routine,
345    in "col_set_addr()"; it might also be useful to have address types
346    export the names of the source and destination address fields, so
347    that "col_set_addr()" need know nothing whatsoever about particular
348    address types */
349 /* convert an address struct into a printable string */
350
351 gchar*
352 ep_address_to_str(const address *addr)
353 {
354   gchar *str;
355
356   str=ep_alloc(MAX_ADDR_STR_LEN);
357   address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
358   return str;
359 }
360
361 /* The called routines use se_alloc'ed memory */
362 gchar*
363 se_address_to_str(const address *addr)
364 {
365   gchar *str;
366
367   str=se_alloc(MAX_ADDR_STR_LEN);
368   address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
369   return str;
370 }
371
372 void
373 address_to_str_buf(const address *addr, gchar *buf, int buf_len)
374 {
375   const guint8 *addrdata;
376   struct atalk_ddp_addr ddp_addr;
377
378   char temp[32];
379   char *tempptr = temp;
380
381   if (!buf || !buf_len)
382     return;
383
384   switch(addr->type){
385   case AT_NONE:
386     buf[0] = '\0';
387     break;
388   case AT_ETHER:                                        /* 18 bytes */
389     tempptr = bytes_to_hexstr_punct(tempptr, addr->data, 6, ':');       /* 17 bytes */
390     break;
391   case AT_IPv4:
392     ip_to_str_buf(addr->data, buf, buf_len);
393     break;
394   case AT_IPv6:
395     if ( inet_ntop(AF_INET6, addr->data, buf, buf_len) == NULL ) /* Returns NULL if no space and does not touch buf */
396         g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR );                 /* Let the unexpected value alert user */
397     break;
398   case AT_IPX:                                          /* 22 bytes */
399     addrdata = addr->data;
400     tempptr = bytes_to_hexstr(tempptr, &addrdata[0], 4);                /*  8 bytes */
401     *tempptr++ = '.';                                                   /*  1 byte  */
402     tempptr = bytes_to_hexstr(tempptr, &addrdata[4], 6);                /* 12 bytes */
403     break;
404   case AT_SNA:
405     sna_fid_to_str_buf(addr, buf, buf_len);
406     break;
407   case AT_ATALK:
408     memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
409     atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
410     break;
411   case AT_VINES:
412     vines_addr_to_str_buf(addr->data, buf, buf_len);
413     break;
414   case AT_USB:
415     usb_addr_to_str_buf(addr->data, buf, buf_len);
416     break;
417   case AT_OSI:
418     print_nsap_net_buf(addr->data, addr->len, buf, buf_len);
419     break;
420   case AT_ARCNET:                                       /* 5 bytes */
421     tempptr = g_stpcpy(tempptr, "0x");                                  /* 2 bytes */
422     tempptr = bytes_to_hexstr(tempptr, addr->data, 1);                  /* 2 bytes */
423     break;
424   case AT_FC:                                           /* 9 bytes */
425     tempptr = bytes_to_hexstr_punct(tempptr, addr->data, 3, '.');       /* 8 bytes */
426     break;
427   case AT_SS7PC:
428     mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
429     break;
430   case AT_STRINGZ:
431     g_strlcpy(buf, addr->data, buf_len);
432     break;
433   case AT_EUI64:                                        /* 24 bytes */
434     tempptr = bytes_to_hexstr_punct(tempptr, addr->data, 8, ':');       /* 23 bytes */
435     break;
436   case AT_URI: {
437     int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
438     memcpy(buf, addr->data, copy_len );
439     buf[copy_len] = '\0';
440     }
441     break;
442   case AT_TIPC:
443     tipc_addr_to_str_buf(addr->data, buf, buf_len);
444     break;
445   case AT_IB:
446     ib_addr_to_str_buf(addr, buf, buf_len);
447     break;
448   default:
449     g_assert_not_reached();
450   }
451
452   /* copy to output buffer */
453   if (tempptr != temp) {
454     size_t temp_len = (size_t) (tempptr - temp);
455
456     if (temp_len < (size_t) buf_len) {
457       memcpy(buf, temp, temp_len);
458       buf[temp_len] = '\0';
459     } else
460      g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
461   }
462 }
463