Make get_manuf_name return a const string.
[metze/wireshark/wip.git] / epan / address_types.c
1 /* address_types.c
2  *
3  * Wireshark - Network traffic analyzer
4  * By Gerald Combs <gerald@wireshark.org>
5  * Copyright 1998 Gerald Combs
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include "config.h"
23
24 #ifdef HAVE_NETINET_IN_H
25 # include <netinet/in.h>        /* needed for <arpa/inet.h> on some platforms */
26 #endif
27
28 #ifdef HAVE_ARPA_INET_H
29 #include <arpa/inet.h>
30 #endif
31
32 #ifdef HAVE_SYS_SOCKET_H
33 #include <sys/socket.h>         /* needed to define AF_ values on UNIX */
34 #endif
35
36 #include <string.h>     /* for memcmp */
37 #include "packet.h"
38 #include "address_types.h"
39 #include "to_str.h"
40 #include "to_str-int.h"
41 #include "addr_resolv.h"
42 #include "wsutil/pint.h"
43 #include "wsutil/str_util.h"
44 #include "wsutil/inet_v6defs.h"
45
46 #include <epan/dissectors/packet-mtp3.h>
47
48 struct _address_type_t {
49     int                     addr_type; /* From address_type enumeration or registered value */
50     const char             *name;
51     const char             *pretty_name;
52     AddrValueToString       addr_to_str;
53     AddrValueToStringLen    addr_str_len;
54     AddrColFilterString     addr_col_filter;
55     AddrFixedLen            addr_fixed_len;
56
57     /* XXX - Some sort of compare functions (like ftype)? ***/
58     /* XXX - Include functions for name resolution? ***/
59 };
60
61 #define MAX_DISSECTOR_ADDR_TYPE     20
62 #define MAX_ADDR_TYPE_VALUE (AT_END_OF_LIST+MAX_DISSECTOR_ADDR_TYPE)
63
64 static int num_dissector_addr_type;
65 static address_type_t dissector_type_addresses[MAX_DISSECTOR_ADDR_TYPE];
66
67 /* Keep track of address_type_t's via their id number */
68 static address_type_t* type_list[MAX_ADDR_TYPE_VALUE];
69
70 /*
71  * If a user _does_ pass in a too-small buffer, this is probably
72  * going to be too long to fit.  However, even a partial string
73  * starting with "[Buf" should provide enough of a clue to be
74  * useful.
75  */
76 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
77
78 static void address_type_register(int addr_type, address_type_t *at)
79 {
80     /* Check input */
81     g_assert(addr_type < MAX_ADDR_TYPE_VALUE);
82     g_assert(addr_type == at->addr_type);
83
84     /* Don't re-register. */
85     g_assert(type_list[addr_type] == NULL);
86
87     type_list[addr_type] = at;
88 }
89
90 int address_type_dissector_register(const char* name, const char* pretty_name,
91                                     AddrValueToString to_str_func, AddrValueToStringLen str_len_func,
92                                     AddrColFilterString col_filter_str_func, AddrFixedLen fixed_len_func)
93 {
94     int addr_type;
95
96     /* Ensure valid data/functions for required fields */
97     DISSECTOR_ASSERT(name);
98     DISSECTOR_ASSERT(pretty_name);
99     DISSECTOR_ASSERT(to_str_func);
100     DISSECTOR_ASSERT(str_len_func);
101
102     /* This shouldn't happen, so flag it for fixing */
103     DISSECTOR_ASSERT(num_dissector_addr_type < MAX_DISSECTOR_ADDR_TYPE);
104
105     addr_type = AT_END_OF_LIST+num_dissector_addr_type;
106     dissector_type_addresses[num_dissector_addr_type].addr_type = addr_type;
107     dissector_type_addresses[num_dissector_addr_type].name = name;
108     dissector_type_addresses[num_dissector_addr_type].pretty_name = pretty_name;
109     dissector_type_addresses[num_dissector_addr_type].addr_to_str = to_str_func;
110     dissector_type_addresses[num_dissector_addr_type].addr_str_len = str_len_func;
111     dissector_type_addresses[num_dissector_addr_type].addr_col_filter = col_filter_str_func;
112     dissector_type_addresses[num_dissector_addr_type].addr_fixed_len = fixed_len_func;
113
114     type_list[addr_type] = &dissector_type_addresses[num_dissector_addr_type];
115
116     num_dissector_addr_type++;
117
118     return addr_type;
119 }
120
121 /******************************************************************************
122  * AT_NONE
123  ******************************************************************************/
124 gboolean none_addr_to_str(const address* addr _U_, gchar *buf, int buf_len _U_)
125 {
126     buf[0] = '\0';
127     return TRUE;
128 }
129
130 int none_addr_str_len(const address* addr _U_)
131 {
132     return 1; /* NULL character for empty string */
133 }
134
135 int none_addr_len(void)
136 {
137     return 0;
138 }
139
140 /******************************************************************************
141  * AT_ETHER
142  ******************************************************************************/
143 gboolean ether_to_str(const address* addr, gchar *buf, int buf_len _U_)
144 {
145     bytes_to_hexstr_punct(buf, (const guint8*)addr->data, 6, ':');
146     buf[17] = '\0';
147     return TRUE;
148 }
149
150 int ether_str_len(const address* addr _U_)
151 {
152     return 18;
153 }
154
155 static const char* ether_col_filter_str(const address* addr _U_, gboolean is_src)
156 {
157     if (is_src)
158         return "eth.src";
159
160     return "eth.dst";
161 }
162
163 int ether_len(void)
164 {
165     return 6;
166 }
167
168 /******************************************************************************
169  * AT_IPv4
170  ******************************************************************************/
171 static gboolean ipv4_to_str(const address* addr, gchar *buf, int buf_len)
172 {
173     ip_to_str_buf((const guint8*)addr->data, buf, buf_len);
174     return TRUE;
175 }
176
177 static int ipv4_str_len(const address* addr _U_)
178 {
179     return MAX_IP_STR_LEN;
180 }
181
182 static const char* ipv4_col_filter_str(const address* addr _U_, gboolean is_src)
183 {
184     if (is_src)
185         return "ip.src";
186
187     return "ip.dst";
188 }
189
190 static int ipv4_len(void)
191 {
192     return 4;
193 }
194
195 /******************************************************************************
196  * AT_IPv6
197  ******************************************************************************/
198 /* const char *
199  * inet_ntop6(src, dst, size)
200  *  convert IPv6 binary address into presentation (printable) format
201  * author:
202  *  Paul Vixie, 1996.
203  */
204 static void
205 ip6_to_str_buf_len(const guchar* src, char *buf, size_t buf_len)
206 {
207     struct { int base, len; } best, cur;
208     guint words[8];
209     int i;
210
211     if (buf_len < MAX_IP6_STR_LEN) { /* buf_len < 40 */
212         g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
213         return;
214     }
215
216     /*
217      * Preprocess:
218      *  Copy the input (bytewise) array into a wordwise array.
219      *  Find the longest run of 0x00's in src[] for :: shorthanding.
220      */
221     for (i = 0; i < 16; i += 2) {
222         words[i / 2] = (src[i+1] << 0);
223         words[i / 2] |= (src[i] << 8);
224     }
225     best.base = -1; best.len = 0;
226     cur.base = -1;  cur.len = 0;
227     for (i = 0; i < 8; i++) {
228         if (words[i] == 0) {
229             if (cur.base == -1) {
230                 cur.base = i;
231                 cur.len = 1;
232             } else
233                 cur.len++;
234         } else {
235             if (cur.base != -1) {
236                 if (best.base == -1 || cur.len > best.len)
237                     best = cur;
238                 cur.base = -1;
239             }
240         }
241     }
242     if (cur.base != -1) {
243         if (best.base == -1 || cur.len > best.len)
244             best = cur;
245     }
246     if (best.base != -1 && best.len < 2)
247         best.base = -1;
248
249     /* Is this address an encapsulated IPv4? */
250     /* XXX,
251      * Orginal code dated 1996 uses ::/96 as a valid IPv4-compatible addresses
252      * but since Feb 2006 ::/96 is deprecated one.
253      * Quoting wikipedia [0]:
254      * > The 96-bit zero-value prefix ::/96, originally known as IPv4-compatible
255      * > addresses, was mentioned in 1995[35] but first described in 1998.[41]
256      * > This class of addresses was used to represent IPv4 addresses within
257      * > an IPv6 transition technology. Such an IPv6 address has its first
258      * > (most significant) 96 bits set to zero, while its last 32 bits are the
259      * > IPv4 address that is represented.
260      * > In February 2006 the Internet Engineering Task Force (IETF) has deprecated
261      * > the use of IPv4-compatible addresses.[1] The only remaining use of this address
262      * > format is to represent an IPv4 address in a table or database with fixed size
263      * > members that must also be able to store an IPv6 address.
264      *
265      * If needed it can be fixed by changing next line:
266      *   if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
267      * to:
268      *   if (best.base == 0 && best.len == 5 && words[5] == 0xffff)
269      *
270      * [0] http://en.wikipedia.org/wiki/IPv6_address#Historical_notes
271      */
272
273     if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
274     {
275         /* best.len == 6 -> ::IPv4; 5 -> ::ffff:IPv4 */
276         buf = g_stpcpy(buf, "::");
277         if (best.len == 5)
278         buf = g_stpcpy(buf, "ffff:");
279         ip_to_str_buf(src + 12, buf, MAX_IP_STR_LEN);
280         /* max: 2 + 5 + 16 == 23 bytes */
281         return;
282     }
283
284     /*
285      * Format the result.
286      */
287     for (i = 0; i < 8; i++) {
288         /* Are we inside the best run of 0x00's? */
289         if (i == best.base) {
290             *buf++ = ':';
291             i += best.len;
292
293             /* Was it a trailing run of 0x00's? */
294             if (i == 8) {
295                 *buf++ = ':';
296                 break;
297             }
298         }
299         /* Are we following an initial run of 0x00s or any real hex? */
300         if (i != 0)
301             *buf++ = ':';
302
303         buf = word_to_hex_npad(buf, words[i]); /* max: 4B */
304         /* max: 8 * 4 + 7 == 39 bytes */
305     }
306     *buf = '\0'; /* 40 byte */
307 }
308
309 void
310 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
311 {
312     ip6_to_str_buf_len((const guchar*)ad, buf, MAX_IP6_STR_LEN);
313 }
314
315 static gboolean ipv6_to_str(const address* addr, gchar *buf, int buf_len)
316 {
317     ip6_to_str_buf_len((const guchar*)addr->data, buf, buf_len);
318     return TRUE;
319 }
320
321 static int ipv6_str_len(const address* addr _U_)
322 {
323     return MAX_IP6_STR_LEN;
324 }
325
326 static const char* ipv6_col_filter_str(const address* addr _U_, gboolean is_src)
327 {
328     if (is_src)
329         return "ipv6.src";
330
331     return "ipv6.dst";
332 }
333
334 static int ipv6_len(void)
335 {
336     return 16;
337 }
338
339 /******************************************************************************
340  * AT_IPX
341  ******************************************************************************/
342 static gboolean ipx_to_str(const address* addr, gchar *buf, int buf_len _U_)
343 {
344     const guint8 *addrdata = (const guint8 *)addr->data;
345
346     buf = bytes_to_hexstr(buf, &addrdata[0], 4); /* 8 bytes */
347     *buf++ = '.'; /*1 byte */
348     buf = bytes_to_hexstr(buf, &addrdata[4], 6); /* 12 bytes */
349     *buf++ = '\0'; /* NULL terminate */
350     return TRUE;
351 }
352
353 static int ipx_str_len(const address* addr _U_)
354 {
355     return 22;
356 }
357
358 static int ipx_len(void)
359 {
360     return 10;
361 }
362
363 /******************************************************************************
364  * AT_VINES
365  * XXX - This functionality should really be in packet-vines.c as a dissector
366  * address type, but need to resolve "address type" as "field type"
367  ******************************************************************************/
368 static gboolean vines_to_str(const address* addr, gchar *buf, int buf_len _U_)
369 {
370     const guint8 *addr_data = (const guint8 *)addr->data;
371
372     buf = dword_to_hex(buf, pntoh32(&addr_data[0])); /* 8 bytes */
373     *buf++ = '.'; /* 1 byte */
374     buf = word_to_hex(buf, pntoh16(&addr_data[4])); /* 4 bytes */
375     *buf = '\0'; /* NULL terminate */
376
377     return TRUE;
378 }
379
380 static int vines_str_len(const address* addr _U_)
381 {
382     return 14;
383 }
384
385 static int vines_len(void)
386 {
387     return VINES_ADDR_LEN;
388 }
389
390 /******************************************************************************
391  * AT_FC
392  ******************************************************************************/
393 static gboolean fc_to_str(const address* addr, gchar *buf, int buf_len _U_)
394 {
395     buf = bytes_to_hexstr_punct(buf, (const guint8 *)addr->data, 3, '.');
396     *buf = '\0'; /* NULL terminate */
397
398     return TRUE;
399 }
400
401 static int fc_str_len(const address* addr _U_)
402 {
403     return 9;
404 }
405
406 static int fc_len(void)
407 {
408     return 3;
409 }
410
411 /******************************************************************************
412  * AT_FCWWN
413  * XXX - Doubles as a "field type", should it be defined here?
414  * XXX - currently this has some address resolution worked into the "base" string
415  ******************************************************************************/
416 /* FC Network Header Network Address Authority Identifiers */
417 #define FC_NH_NAA_IEEE          1   /* IEEE 802.1a */
418 #define FC_NH_NAA_IEEE_E        2   /* IEEE Exteneded */
419 #define FC_NH_NAA_LOCAL         3
420 #define FC_NH_NAA_IP            4   /* 32-bit IP address */
421 #define FC_NH_NAA_IEEE_R        5   /* IEEE Registered */
422 #define FC_NH_NAA_IEEE_R_E      6   /* IEEE Registered Exteneded */
423 /* according to FC-PH 3 draft these are now reclaimed and reserved */
424 #define FC_NH_NAA_CCITT_INDV    12  /* CCITT 60 bit individual address */
425 #define FC_NH_NAA_CCITT_GRP     14  /* CCITT 60 bit group address */
426
427 static gboolean fcwwn_to_str(const address* addr, gchar *buf, int buf_len)
428 {
429     const guint8 *addrp = (const guint8*)addr->data;
430     int fmt;
431     guint8 oui[6];
432     gchar *ethptr;
433
434     if (buf_len < 200) {  /* This is mostly for manufacturer name */
435         g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
436         return FALSE;
437     }
438
439     ethptr = bytes_to_hexstr_punct(buf, addrp, 8, ':'); /* 23 bytes */
440     fmt = (addrp[0] & 0xF0) >> 4;
441     switch (fmt) {
442
443     case FC_NH_NAA_IEEE:
444     case FC_NH_NAA_IEEE_E:
445         memcpy (oui, &addrp[2], 6);
446
447         g_snprintf (ethptr, buf_len-23, " (%s)", get_manuf_name(oui));
448         break;
449
450     case FC_NH_NAA_IEEE_R:
451         oui[0] = ((addrp[0] & 0x0F) << 4) | ((addrp[1] & 0xF0) >> 4);
452         oui[1] = ((addrp[1] & 0x0F) << 4) | ((addrp[2] & 0xF0) >> 4);
453         oui[2] = ((addrp[2] & 0x0F) << 4) | ((addrp[3] & 0xF0) >> 4);
454         oui[3] = ((addrp[3] & 0x0F) << 4) | ((addrp[4] & 0xF0) >> 4);
455         oui[4] = ((addrp[4] & 0x0F) << 4) | ((addrp[5] & 0xF0) >> 4);
456         oui[5] = ((addrp[5] & 0x0F) << 4) | ((addrp[6] & 0xF0) >> 4);
457
458         g_snprintf (ethptr, buf_len-23, " (%s)", get_manuf_name(oui));
459         break;
460
461     default:
462         *ethptr = '\0';
463         break;
464     }
465
466     return TRUE;
467 }
468
469 static int fcwwn_str_len(const address* addr _U_)
470 {
471     return 200;
472 }
473
474 static int fcwwn_len(void)
475 {
476     return FCWWN_ADDR_LEN;
477 }
478
479 /******************************************************************************
480  * AT_SS7PC
481  * XXX - This should really be a dissector address type as its address string
482  * is partially determined by a dissector preference.
483  ******************************************************************************/
484 static gboolean ss7pc_to_str(const address* addr, gchar *buf, int buf_len)
485 {
486     mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
487     return TRUE;
488 }
489
490 static int ss7pc_str_len(const address* addr _U_)
491 {
492     return 50;
493 }
494
495 /******************************************************************************
496  * AT_STRINGZ
497  ******************************************************************************/
498 static gboolean stringz_addr_to_str(const address* addr, gchar *buf, int buf_len)
499 {
500     g_strlcpy(buf, (const gchar *)addr->data, buf_len);
501     return TRUE;
502 }
503
504 static int stringz_addr_str_len(const address* addr)
505 {
506     return addr->len+1;
507 }
508
509 /******************************************************************************
510  * AT_EUI64
511  ******************************************************************************/
512 static gboolean eui64_addr_to_str(const address* addr, gchar *buf, int buf_len _U_)
513 {
514     buf = bytes_to_hexstr_punct(buf, (const guint8 *)addr->data, 8, ':');
515     *buf = '\0'; /* NULL terminate */
516     return TRUE;
517 }
518
519 static int eui64_str_len(const address* addr _U_)
520 {
521     return EUI64_STR_LEN;
522 }
523
524 static int eui64_len(void)
525 {
526     return 8;
527 }
528
529 /******************************************************************************
530  * AT_IB
531  ******************************************************************************/
532 static gboolean
533 ib_addr_to_str( const address *addr, gchar *buf, int buf_len){
534     if (addr->len >= 16) { /* GID is 128bits */
535         #define PREAMBLE_STR_LEN ((int)(sizeof("GID: ") - 1))
536         g_strlcpy(buf, "GID: ", buf_len);
537         if (buf_len < PREAMBLE_STR_LEN ||
538                 inet_ntop(AF_INET6, addr->data, buf + PREAMBLE_STR_LEN,
539                           buf_len - PREAMBLE_STR_LEN) == NULL ) /* Returns NULL if no space and does not touch buf */
540             g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
541     } else {    /* this is a LID (16 bits) */
542         guint16 lid_number;
543
544         memcpy((void *)&lid_number, addr->data, sizeof lid_number);
545         g_snprintf(buf,buf_len,"LID: %u",lid_number);
546     }
547
548     return TRUE;
549 }
550
551 static int ib_str_len(const address* addr _U_)
552 {
553     return MAX_ADDR_STR_LEN; /* XXX - This is overkill */
554 }
555
556 /******************************************************************************
557  * AT_USB
558  * XXX - This functionality should really be in packet-usb.c as a dissector
559  * address type, but currently need support of AT_USB in conversation_table.c
560  ******************************************************************************/
561 static gboolean usb_addr_to_str(const address* addr, gchar *buf, int buf_len _U_)
562 {
563     const guint8 *addrp = (const guint8 *)addr->data;
564
565     if(pletoh32(&addrp[0])==0xffffffff){
566         g_strlcpy(buf, "host", buf_len);
567     } else {
568         g_snprintf(buf, buf_len, "%d.%d.%d", pletoh16(&addrp[8]),
569                         pletoh32(&addrp[0]), pletoh32(&addrp[4]));
570     }
571
572     return TRUE;
573 }
574
575 static int usb_addr_str_len(const address* addr _U_)
576 {
577     return 50;
578 }
579
580 /******************************************************************************
581  * AT_AX25
582  ******************************************************************************/
583 static gboolean ax25_addr_to_str(const address* addr, gchar *buf, int buf_len _U_)
584 {
585     const guint8 *addrdata = (const guint8 *)addr->data;
586
587     *buf++ = printable_char_or_period(addrdata[0] >> 1);
588     *buf++ = printable_char_or_period(addrdata[1] >> 1);
589     *buf++ = printable_char_or_period(addrdata[2] >> 1);
590     *buf++ = printable_char_or_period(addrdata[3] >> 1);
591     *buf++ = printable_char_or_period(addrdata[4] >> 1);
592     *buf++ = printable_char_or_period(addrdata[5] >> 1);
593     *buf++ = '-';
594     buf = uint_to_str_back(buf, (addrdata[6] >> 1) & 0x0f);
595     *buf = '\0'; /* NULL terminate */
596
597     return TRUE;
598 }
599
600 static int ax25_addr_str_len(const address* addr _U_)
601 {
602     return 21; /* Leaves extra space (10 bytes) just for uint_to_str_back() */
603 }
604
605 static const char* ax25_col_filter_str(const address* addr _U_, gboolean is_src)
606 {
607     if (is_src)
608         return "ax25.src";
609
610     return "ax25.dst";
611 }
612
613 static int ax25_len(void)
614 {
615     return AX25_ADDR_LEN;
616 }
617
618 /******************************************************************************
619  * END OF PROVIDED ADDRESS TYPES
620  ******************************************************************************/
621
622
623
624
625 void address_types_initialize(void)
626 {
627     static address_type_t none_address = {
628         AT_NONE,            /* addr_type */
629         "AT_NONE",          /* name */
630         "No address",       /* pretty_name */
631         none_addr_to_str,   /* addr_to_str */
632         none_addr_str_len,  /* addr_str_len */
633         NULL,               /* addr_col_filter */
634         none_addr_len       /* addr_fixed_len */
635     };
636
637     static address_type_t ether_address = {
638         AT_ETHER,           /* addr_type */
639         "AT_ETHER",         /* name */
640         "Ethernet address", /* pretty_name */
641         ether_to_str,       /* addr_to_str */
642         ether_str_len,      /* addr_str_len */
643         ether_col_filter_str, /* addr_col_filter */
644         ether_len           /* addr_fixed_len */
645     };
646
647     static address_type_t ipv4_address = {
648         AT_IPv4,            /* addr_type */
649         "AT_IPv4",          /* name */
650         "IPv4 address",     /* pretty_name */
651         ipv4_to_str,        /* addr_to_str */
652         ipv4_str_len,       /* addr_str_len */
653         ipv4_col_filter_str, /* addr_col_filter */
654         ipv4_len            /* addr_fixed_len */
655     };
656
657     static address_type_t ipv6_address = {
658         AT_IPv6,            /* addr_type */
659         "AT_IPv6",          /* name */
660         "IPv6 address",     /* pretty_name */
661         ipv6_to_str,        /* addr_to_str */
662         ipv6_str_len,       /* addr_str_len */
663         ipv6_col_filter_str, /* addr_col_filter */
664         ipv6_len            /* addr_fixed_len */
665    };
666
667     static address_type_t ipx_address = {
668         AT_IPX,             /* addr_type */
669         "AT_IPX",           /* name */
670         "IPX address",      /* pretty_name */
671         ipx_to_str,         /* addr_to_str */
672         ipx_str_len,        /* addr_str_len */
673         NULL,               /* addr_col_filter */
674         ipx_len             /* addr_fixed_len */
675     };
676
677     static address_type_t vines_address = {
678         AT_VINES,           /* addr_type */
679         "AT_VINES",         /* name */
680         "Banyan Vines address", /* pretty_name */
681         vines_to_str,       /* addr_to_str */
682         vines_str_len,      /* addr_str_len */
683         NULL,                /* addr_col_filter */
684         vines_len          /*addr_fixed_len */
685     };
686
687     static address_type_t fc_address = {
688         AT_FC,          /* addr_type */
689         "AT_FC",        /* name */
690         "FC address",   /* pretty_name */
691         fc_to_str,      /* addr_to_str */
692         fc_str_len,     /* addr_str_len */
693         NULL,           /* addr_col_filter */
694         fc_len          /*addr_fixed_len */
695     };
696
697     static address_type_t fcwwn_address = {
698         AT_FCWWN,       /* addr_type */
699         "AT_FCWWN",     /* name */
700         "Fibre Channel WWN",    /* pretty_name */
701         fcwwn_to_str,   /* addr_to_str */
702         fcwwn_str_len,  /* addr_str_len */
703         NULL,           /* addr_col_filter */
704         fcwwn_len          /* addr_fixed_len */
705     };
706
707     static address_type_t ss7pc_address = {
708         AT_SS7PC,          /* addr_type */
709         "AT_SS7PC",        /* name */
710         "SS7 Point Code",  /* pretty_name */
711         ss7pc_to_str,      /* addr_to_str */
712         ss7pc_str_len,     /* addr_str_len */
713         NULL,              /* addr_col_filter */
714         NULL               /* addr_fixed_len */
715     };
716
717     static address_type_t stringz_address = {
718         AT_STRINGZ,          /* addr_type */
719         "AT_STRINGZ",        /* name */
720         "String address",   /* pretty_name */
721         stringz_addr_to_str, /* addr_to_str */
722         stringz_addr_str_len, /* addr_str_len */
723         NULL,              /* addr_col_filter */
724         NULL               /* addr_fixed_len */
725     };
726
727     static address_type_t eui64_address = {
728         AT_EUI64,          /* addr_type */
729         "AT_EUI64",        /* name */
730         "IEEE EUI-64",     /* pretty_name */
731         eui64_addr_to_str, /* addr_to_str */
732         eui64_str_len,     /* addr_str_len */
733         NULL,              /* addr_col_filter */
734         eui64_len          /* addr_fixed_len */
735     };
736
737     static address_type_t ib_address = {
738         AT_IB,           /* addr_type */
739         "AT_IB",         /* name */
740         "Infiniband GID/LID",   /* pretty_name */
741         ib_addr_to_str,  /* addr_to_str */
742         ib_str_len,      /* addr_str_len */
743         NULL,              /* addr_col_filter */
744         NULL               /* addr_fixed_len */
745     };
746
747     static address_type_t usb_address = {
748         AT_USB,          /* addr_type */
749         "AT_USB",        /* name */
750         "USB Address",   /* pretty_name */
751         usb_addr_to_str, /* addr_to_str */
752         usb_addr_str_len, /* addr_str_len */
753         NULL,              /* addr_col_filter */
754         NULL               /* addr_fixed_len */
755     };
756
757     static address_type_t ax25_address = {
758         AT_AX25,          /* addr_type */
759         "AT_AX25",        /* name */
760         "AX.25 Address",  /* pretty_name */
761         ax25_addr_to_str, /* addr_to_str */
762         ax25_addr_str_len,/* addr_str_len */
763         ax25_col_filter_str, /* addr_col_filter */
764         ax25_len          /* addr_fixed_len */
765     };
766
767     num_dissector_addr_type = 0;
768
769     /* Initialize the type array.  This is mostly for handling
770        "dissector registered" address type range (for NULL checking) */
771     memset(type_list, 0, MAX_ADDR_TYPE_VALUE*sizeof(address_type_t*));
772
773     address_type_register(AT_NONE, &none_address );
774     address_type_register(AT_ETHER, &ether_address );
775     address_type_register(AT_IPv4, &ipv4_address );
776     address_type_register(AT_IPv6, &ipv6_address );
777     address_type_register(AT_IPX, &ipx_address );
778     address_type_register(AT_VINES, &vines_address );
779     address_type_register(AT_FC, &fc_address );
780     address_type_register(AT_FCWWN, &fcwwn_address );
781     address_type_register(AT_SS7PC, &ss7pc_address );
782     address_type_register(AT_STRINGZ, &stringz_address );
783     address_type_register(AT_EUI64, &eui64_address );
784     address_type_register(AT_IB, &ib_address );
785     address_type_register(AT_USB, &usb_address );
786     address_type_register(AT_AX25, &ax25_address );
787 }
788
789 /* Given an address type id, return an address_type_t* */
790 #define ADDR_TYPE_LOOKUP(addr_type, result)    \
791     /* Check input */                          \
792     g_assert(addr_type < MAX_ADDR_TYPE_VALUE); \
793     result = type_list[addr_type];
794
795 static int address_type_get_length(const address* addr)
796 {
797     address_type_t *at;
798
799     ADDR_TYPE_LOOKUP(addr->type, at);
800
801     if ((at == NULL) || (at->addr_str_len == NULL))
802         return 0;
803
804     return at->addr_str_len(addr);
805 }
806
807 /*XXX FIXME the code below may be called very very frequently in the future.
808   optimize it for speed and get rid of the slow sprintfs */
809 /* XXX - perhaps we should have individual address types register
810    a table of routines to do operations such as address-to-name translation,
811    address-to-string translation, and the like, and have this call them,
812    and also have an address-to-string-with-a-name routine */
813 /* convert an address struct into a printable string */
814
815 gchar*
816 address_to_str(wmem_allocator_t *scope, const address *addr)
817 {
818     gchar *str;
819     int len = address_type_get_length(addr);
820
821     if (len <= 0)
822         len = MAX_ADDR_STR_LEN;
823
824     str=(gchar *)wmem_alloc(scope, len);
825     address_to_str_buf(addr, str, len);
826     return str;
827 }
828
829 void address_to_str_buf(const address* addr, gchar *buf, int buf_len)
830 {
831     address_type_t *at;
832
833     if (!buf || !buf_len)
834         return;
835
836     ADDR_TYPE_LOOKUP(addr->type, at);
837
838     if ((at == NULL) || (at->addr_to_str == NULL))
839     {
840         buf[0] = '\0';
841         return;
842     }
843
844     at->addr_to_str(addr, buf, buf_len);
845 }
846
847 const char* address_type_column_filter_string(const address* addr, gboolean src)
848 {
849     address_type_t *at;
850
851     ADDR_TYPE_LOOKUP(addr->type, at);
852
853     if ((at == NULL) || (at->addr_col_filter == NULL))
854     {
855         return "";
856     }
857
858     return at->addr_col_filter(addr, src);
859 }
860
861 gchar*
862 tvb_address_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, int type, const gint offset)
863 {
864     address addr;
865     address_type_t *at;
866
867     ADDR_TYPE_LOOKUP(type, at);
868
869     if (at == NULL)
870     {
871         return NULL;
872     }
873
874     /* The address type must have a fixed length to use this function */
875     /* For variable length fields, use tvb_address_var_to_str() */
876     if (at->addr_fixed_len == NULL)
877     {
878         g_assert_not_reached();
879         return NULL;
880     }
881
882     TVB_SET_ADDRESS(&addr, type, tvb, offset, at->addr_fixed_len());
883
884     return address_to_str(scope, &addr);
885 }
886
887 gchar* tvb_address_var_to_str(wmem_allocator_t *scope, tvbuff_t *tvb, address_type type, const gint offset, int length)
888 {
889     address addr;
890
891     TVB_SET_ADDRESS(&addr, type, tvb, offset, length);
892
893     return address_to_str(scope, &addr);
894 }
895
896
897 /*
898  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
899  *
900  * Local variables:
901  * c-basic-offset: 4
902  * tab-width: 8
903  * indent-tabs-mode: nil
904  * End:
905  *
906  * vi: set shiftwidth=4 tabstop=8 expandtab:
907  * :indentSize=4:tabSize=8:noTabs=true:
908  */