initialize tree variables
[metze/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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  */
24
25 #include "config.h"
26
27 #include <stdlib.h>
28 #include <string.h>
29
30 #ifdef HAVE_SYS_TYPES_H
31 # include <sys/types.h>         /* needed for <netinet/in.h> */
32 #endif
33
34 #ifdef HAVE_NETINET_IN_H
35 # include <netinet/in.h>        /* needed for <arpa/inet.h> on some platforms */
36 #endif
37
38 #ifdef HAVE_ARPA_INET_H
39 #include <arpa/inet.h>
40 #endif
41
42 #ifdef HAVE_SYS_SOCKET_H
43 #include <sys/socket.h>         /* needed to define AF_ values on UNIX */
44 #endif
45
46 #ifdef HAVE_WINSOCK2_H
47 #include <winsock2.h>           /* needed to define AF_ values on Windows */
48 #endif
49
50 #ifdef NEED_INET_V6DEFS_H
51 # include "wsutil/inet_v6defs.h"
52 #endif
53
54 #include "to_str.h"
55 #include "value_string.h"
56 #include "addr_resolv.h"
57 #include "wsutil/pint.h"
58 #include "atalk-utils.h"
59 #include "sna-utils.h"
60 #include "osi-utils.h"
61 #include <epan/dissectors/packet-mtp3.h>
62 #include <stdio.h>
63 #include "emem.h"
64
65 /* private to_str.c API, don't export to .h! */
66 char *word_to_hex(char *out, guint16 word);
67 char *word_to_hex_npad(char *out, guint16 word);
68 char *dword_to_hex_punct(char *out, guint32 dword, char punct);
69 char *dword_to_hex(char *out, guint32 dword);
70 char *bytes_to_hexstr(char *out, const guint8 *ad, guint32 len);
71 char *bytes_to_hexstr_punct(char *out, const guint8 *ad, guint32 len, char punct);
72
73 /*
74  * If a user _does_ pass in a too-small buffer, this is probably
75  * going to be too long to fit.  However, even a partial string
76  * starting with "[Buf" should provide enough of a clue to be
77  * useful.
78  */
79 #define BUF_TOO_SMALL_ERR "[Buffer too small]"
80
81 /* Wrapper for the most common case of asking
82  * for a string using a colon as the hex-digit separator.
83  */
84 /* XXX FIXME
85 remove this one later when every call has been converted to ep_address_to_str()
86 */
87 const gchar *
88 ether_to_str(const guint8 *ad)
89 {
90     return bytestring_to_str(ad, 6, ':');
91 }
92
93 const gchar *
94 tvb_ether_to_str(tvbuff_t *tvb, const gint offset)
95 {
96     return bytestring_to_str(tvb_get_ptr(tvb, offset, 6), 6, ':');
97 }
98
99 /*
100  This function is very fast and this function is called a lot.
101  XXX update the ep_address_to_str stuff to use this function.
102 */
103 const gchar *
104 ip_to_str(const guint8 *ad) {
105     gchar *buf;
106
107     buf=(gchar *)ep_alloc(MAX_IP_STR_LEN);
108     ip_to_str_buf(ad, buf, MAX_IP_STR_LEN);
109     return buf;
110 }
111
112 #define IPV4_LENGTH 4
113 const gchar *
114 tvb_ip_to_str(tvbuff_t *tvb, const gint offset)
115 {
116     gchar *buf;
117
118     buf=(gchar *)ep_alloc(MAX_IP_STR_LEN);
119     ip_to_str_buf(tvb_get_ptr(tvb, offset, IPV4_LENGTH), buf, MAX_IP_STR_LEN);
120     return buf;
121 }
122
123 /* XXX FIXME
124 remove this one later when every call has been converted to ep_address_to_str()
125 */
126 gchar *
127 ip6_to_str(const struct e_in6_addr *ad) {
128     gchar *str;
129
130     str=(gchar *)ep_alloc(MAX_IP6_STR_LEN);
131     ip6_to_str_buf(ad, str);
132     return str;
133 }
134
135 #define IPV6_LENGTH 16
136 gchar *
137 tvb_ip6_to_str(tvbuff_t *tvb, const gint offset)
138 {
139     gchar *buf;
140
141     buf=(gchar *)ep_alloc(MAX_IP6_STR_LEN);
142     ip6_to_str_buf((const struct e_in6_addr *)tvb_get_ptr(tvb, offset, IPV6_LENGTH), buf);
143     return buf;
144 }
145
146 /* const char *
147  * inet_ntop6(src, dst, size)
148  *  convert IPv6 binary address into presentation (printable) format
149  * author:
150  *  Paul Vixie, 1996.
151  */
152 static void
153 ip6_to_str_buf_len(const guchar* src, char *buf, size_t buf_len)
154 {
155     struct { int base, len; } best, cur;
156     guint words[8];
157     int i;
158
159     if (buf_len < MAX_IP6_STR_LEN) { /* buf_len < 40 */
160         g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
161         return;
162     }
163
164     /*
165      * Preprocess:
166      *  Copy the input (bytewise) array into a wordwise array.
167      *  Find the longest run of 0x00's in src[] for :: shorthanding.
168      */
169     for (i = 0; i < 16; i += 2) {
170         words[i / 2] = (src[i+1] << 0);
171         words[i / 2] |= (src[i] << 8);
172     }
173     best.base = -1; best.len = 0;
174     cur.base = -1;  cur.len = 0;
175     for (i = 0; i < 8; i++) {
176         if (words[i] == 0) {
177             if (cur.base == -1) {
178                 cur.base = i;
179                 cur.len = 1;
180             } else
181                 cur.len++;
182         } else {
183             if (cur.base != -1) {
184                 if (best.base == -1 || cur.len > best.len)
185                     best = cur;
186                 cur.base = -1;
187             }
188         }
189     }
190     if (cur.base != -1) {
191         if (best.base == -1 || cur.len > best.len)
192             best = cur;
193     }
194     if (best.base != -1 && best.len < 2)
195         best.base = -1;
196
197     /* Is this address an encapsulated IPv4? */
198     /* XXX,
199      * Orginal code dated 1996 uses ::/96 as a valid IPv4-compatible addresses
200      * but since Feb 2006 ::/96 is deprecated one.
201      * Quoting wikipedia [0]:
202      * > The 96-bit zero-value prefix ::/96, originally known as IPv4-compatible
203      * > addresses, was mentioned in 1995[35] but first described in 1998.[41]
204      * > This class of addresses was used to represent IPv4 addresses within
205      * > an IPv6 transition technology. Such an IPv6 address has its first
206      * > (most significant) 96 bits set to zero, while its last 32 bits are the
207      * > IPv4 address that is represented.
208      * > In February 2006 the Internet Engineering Task Force (IETF) has deprecated
209      * > the use of IPv4-compatible addresses.[1] The only remaining use of this address
210      * > format is to represent an IPv4 address in a table or database with fixed size
211      * > members that must also be able to store an IPv6 address.
212      *
213      * If needed it can be fixed by changing next line:
214      *   if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
215      * to:
216      *   if (best.base == 0 && best.len == 5 && words[5] == 0xffff)
217      *
218      * [0] http://en.wikipedia.org/wiki/IPv6_address#Historical_notes
219      */
220
221     if (best.base == 0 && (best.len == 6 || (best.len == 5 && words[5] == 0xffff)))
222     {
223         /* best.len == 6 -> ::IPv4; 5 -> ::ffff:IPv4 */
224         buf = g_stpcpy(buf, "::");
225         if (best.len == 5)
226         buf = g_stpcpy(buf, "ffff:");
227         ip_to_str_buf(src + 12, buf, MAX_IP_STR_LEN);
228         /* max: 2 + 5 + 16 == 23 bytes */
229         return;
230     }
231
232     /*
233      * Format the result.
234      */
235     for (i = 0; i < 8; i++) {
236         /* Are we inside the best run of 0x00's? */
237         if (i == best.base) {
238             *buf++ = ':';
239             i += best.len;
240
241             /* Was it a trailing run of 0x00's? */
242             if (i == 8) {
243                 *buf++ = ':';
244                 break;
245             }
246         }
247         /* Are we following an initial run of 0x00s or any real hex? */
248         if (i != 0)
249             *buf++ = ':';
250
251         buf = word_to_hex_npad(buf, words[i]); /* max: 4B */
252         /* max: 8 * 4 + 7 == 39 bytes */
253     }
254     *buf = '\0'; /* 40 byte */
255 }
256
257 void
258 ip6_to_str_buf(const struct e_in6_addr *ad, gchar *buf)
259 {
260     ip6_to_str_buf_len((const guchar*)ad, buf, MAX_IP6_STR_LEN);
261 }
262
263 gchar*
264 ipx_addr_to_str(const guint32 net, const guint8 *ad)
265 {
266     gchar   *buf;
267     char    *name;
268
269     name = get_ether_name_if_known(ad);
270
271     if (name) {
272         buf = ep_strdup_printf("%s.%s", get_ipxnet_name(net), name);
273     }
274     else {
275         buf = ep_strdup_printf("%s.%s", get_ipxnet_name(net),
276             bytestring_to_str(ad, 6, '\0'));
277     }
278     return buf;
279 }
280
281 gchar*
282 ipxnet_to_string(const guint8 *ad)
283 {
284     guint32 addr = pntohl(ad);
285     return ipxnet_to_str_punct(addr, ' ');
286 }
287
288 gchar *
289 ipxnet_to_str_punct(const guint32 ad, const char punct)
290 {
291     gchar *buf = (gchar *)ep_alloc(12);
292
293     *dword_to_hex_punct(buf, ad, punct) = '\0';
294     return buf;
295 }
296
297 static void
298 vines_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
299 {
300     if (buf_len < 14) {
301         g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len); /* Let the unexpected value alert user */
302         return;
303     }
304
305     buf = dword_to_hex(buf, pntohl(&addrp[0])); /* 8 bytes */
306     *buf++ = '.'; /* 1 byte */
307     buf = word_to_hex(buf, pntohs(&addrp[4])); /* 4 bytes */
308     *buf = '\0'; /* 1 byte */
309 }
310
311 gchar *
312 tvb_vines_addr_to_str(tvbuff_t *tvb, const gint offset)
313 {
314     gchar *buf;
315
316     buf=(gchar *)ep_alloc(214); /* XXX, 14 here? */
317
318     vines_addr_to_str_buf(tvb_get_ptr(tvb, offset, VINES_ADDR_LEN), buf, 214);
319     return buf;
320 }
321
322 /*
323  This function is very fast and this function is called a lot.
324  XXX update the ep_address_to_str stuff to use this function.
325 */
326 gchar *
327 eui64_to_str(const guint64 ad) {
328     gchar *buf;
329     guint8 *p_eui64;
330
331     p_eui64 = (guint8 *)ep_alloc(8);
332     buf=(gchar *)ep_alloc(EUI64_STR_LEN);
333
334     /* Copy and convert the address to network byte order. */
335     *(guint64 *)(void *)(p_eui64) = pntoh64(&(ad));
336
337     g_snprintf(buf, EUI64_STR_LEN, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x:%.2x",
338     p_eui64[0], p_eui64[1], p_eui64[2], p_eui64[3],
339     p_eui64[4], p_eui64[5], p_eui64[6], p_eui64[7] );
340     return buf;
341 }
342 gchar *
343 tvb_eui64_to_str(tvbuff_t *tvb, const gint offset, const guint encoding)
344 {
345     if(encoding)
346     {
347         return eui64_to_str(tvb_get_letoh64(tvb, offset));
348     }else {
349         return eui64_to_str(tvb_get_ntoh64(tvb, offset));
350     }
351 }
352
353 static void
354 usb_addr_to_str_buf(const guint8 *addrp, gchar *buf, int buf_len)
355 {
356     if(pletohl(&addrp[0])==0xffffffff){
357         g_snprintf(buf, buf_len, "host");
358     } else {
359         g_snprintf(buf, buf_len, "%d.%d", pletohl(&addrp[0]), pletohl(&addrp[4]));
360     }
361 }
362
363 static void
364 tipc_addr_to_str_buf( const guint8 *data, gchar *buf, int buf_len){
365     guint8 zone;
366     guint16 subnetwork;
367     guint16 processor;
368     guint32 tipc_address;
369
370     tipc_address = data[0];
371     tipc_address = (tipc_address << 8) ^ data[1];
372     tipc_address = (tipc_address << 8) ^ data[2];
373     tipc_address = (tipc_address << 8) ^ data[3];
374
375     processor = tipc_address & 0x0fff;
376
377     tipc_address = tipc_address >> 12;
378     subnetwork = tipc_address & 0x0fff;
379
380     tipc_address = tipc_address >> 12;
381     zone = tipc_address & 0xff;
382
383     g_snprintf(buf,buf_len,"%u.%u.%u",zone,subnetwork,processor);
384 }
385
386 static void
387 ib_addr_to_str_buf( const address *addr, gchar *buf, int buf_len){
388     if (addr->len >= 16) { /* GID is 128bits */
389         #define PREAMBLE_STR_LEN ((int)(sizeof("GID: ") - 1))
390         g_snprintf(buf,buf_len,"GID: ");
391         if (buf_len < PREAMBLE_STR_LEN ||
392                 inet_ntop(AF_INET6, addr->data, buf + PREAMBLE_STR_LEN,
393                           buf_len - PREAMBLE_STR_LEN) == NULL ) /* Returns NULL if no space and does not touch buf */
394             g_snprintf ( buf, buf_len, BUF_TOO_SMALL_ERR ); /* Let the unexpected value alert user */
395     } else {    /* this is a LID (16 bits) */
396         guint16 lid_number;
397
398         memcpy((void *)&lid_number, addr->data, sizeof lid_number);
399         g_snprintf(buf,buf_len,"LID: %u",lid_number);
400     }
401 }
402
403 /* XXX FIXME
404 remove this one later when every call has been converted to ep_address_to_str()
405 */
406 const gchar *
407 fc_to_str(const guint8 *ad)
408 {
409     return bytestring_to_str (ad, 3, '.');
410 }
411
412 const gchar *
413 tvb_fc_to_str(tvbuff_t *tvb, const gint offset)
414 {
415     return bytestring_to_str (tvb_get_ptr(tvb, offset, 3), 3, '.');
416 }
417
418 /* FC Network Header Network Address Authority Identifiers */
419
420 #define FC_NH_NAA_IEEE          1   /* IEEE 802.1a */
421 #define FC_NH_NAA_IEEE_E        2   /* IEEE Exteneded */
422 #define FC_NH_NAA_LOCAL         3
423 #define FC_NH_NAA_IP            4   /* 32-bit IP address */
424 #define FC_NH_NAA_IEEE_R        5   /* IEEE Registered */
425 #define FC_NH_NAA_IEEE_R_E      6   /* IEEE Registered Exteneded */
426 /* according to FC-PH 3 draft these are now reclaimed and reserved */
427 #define FC_NH_NAA_CCITT_INDV    12  /* CCITT 60 bit individual address */
428 #define FC_NH_NAA_CCITT_GRP     14  /* CCITT 60 bit group address */
429
430 gchar *
431 fcwwn_to_str (const guint8 *ad)
432 {
433     int fmt;
434     guint8 oui[6];
435     gchar *ethstr;
436     gchar *ethptr;
437
438     if (ad == NULL) return NULL;
439
440     ethstr=(gchar *)ep_alloc(512);
441     ethptr = bytes_to_hexstr_punct(ethstr, ad, 8, ':'); /* 23 bytes */
442
443     fmt = (ad[0] & 0xF0) >> 4;
444
445     switch (fmt) {
446
447     case FC_NH_NAA_IEEE:
448     case FC_NH_NAA_IEEE_E:
449         memcpy (oui, &ad[2], 6);
450
451         g_snprintf (ethptr, 512-23, " (%s)", get_manuf_name (oui));
452         break;
453
454     case FC_NH_NAA_IEEE_R:
455         oui[0] = ((ad[0] & 0x0F) << 4) | ((ad[1] & 0xF0) >> 4);
456         oui[1] = ((ad[1] & 0x0F) << 4) | ((ad[2] & 0xF0) >> 4);
457         oui[2] = ((ad[2] & 0x0F) << 4) | ((ad[3] & 0xF0) >> 4);
458         oui[3] = ((ad[3] & 0x0F) << 4) | ((ad[4] & 0xF0) >> 4);
459         oui[4] = ((ad[4] & 0x0F) << 4) | ((ad[5] & 0xF0) >> 4);
460         oui[5] = ((ad[5] & 0x0F) << 4) | ((ad[6] & 0xF0) >> 4);
461
462         g_snprintf (ethptr, 512-23, " (%s)", get_manuf_name (oui));
463         break;
464
465     default:
466         *ethptr = '\0';
467         break;
468     }
469     return (ethstr);
470 }
471
472 gchar *
473 tvb_fcwwn_to_str(tvbuff_t *tvb, const gint offset)
474 {
475     return fcwwn_to_str (tvb_get_ptr(tvb, offset, 8));
476 }
477
478 /* XXX FIXME
479 remove this one later when every call has been converted to address_to_str()
480 */
481 const gchar *
482 ax25_to_str(const guint8 *ad)
483 {
484     return bytestring_to_str(ad, 7, ':');
485 }
486
487 /* XXX FIXME
488 remove this one later when every call has been converted to address_to_str()
489 */
490 gchar *
491 get_ax25_name(const guint8 *ad)
492 {
493     address addr;
494
495     addr.type = AT_AX25;
496     addr.len  = 7;
497     addr.data = ad;
498
499     return address_to_str( &addr );
500 }
501
502 /*XXX FIXME the code below may be called very very frequently in the future.
503   optimize it for speed and get rid of the slow sprintfs */
504 /* XXX - perhaps we should have individual address types register
505    a table of routines to do operations such as address-to-name translation,
506    address-to-string translation, and the like, and have this call them,
507    and also have an address-to-string-with-a-name routine */
508 /* XXX - use this, and that future address-to-string-with-a-name routine,
509    in "col_set_addr()"; it might also be useful to have address types
510    export the names of the source and destination address fields, so
511    that "col_set_addr()" need know nothing whatsoever about particular
512    address types */
513 /* convert an address struct into a printable string */
514
515 gchar*
516 ep_address_to_str(const address *addr)
517 {
518     gchar *str;
519
520     str=(gchar *)ep_alloc(MAX_ADDR_STR_LEN);
521     address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
522     return str;
523 }
524
525 /* The called routines use se_alloc'ed memory */
526 gchar*
527 se_address_to_str(const address *addr)
528 {
529     gchar *str;
530
531     str=(gchar *)se_alloc(MAX_ADDR_STR_LEN);
532     address_to_str_buf(addr, str, MAX_ADDR_STR_LEN);
533     return str;
534 }
535
536 void
537 address_to_str_buf(const address *addr, gchar *buf, int buf_len)
538 {
539     const guint8 *addrdata;
540     struct atalk_ddp_addr ddp_addr;
541     guint16 ieee_802_15_4_short_addr;
542
543     char temp[32];
544     char *tempptr = temp;
545
546     if (!buf || !buf_len)
547         return;
548
549     switch(addr->type){
550     case AT_NONE:
551         buf[0] = '\0';
552         break;
553     case AT_ETHER: /* 18 bytes */
554         tempptr = bytes_to_hexstr_punct(tempptr, (const guint8 *)addr->data, 6, ':'); /* 17 bytes */
555         break;
556     case AT_IPv4:
557         ip_to_str_buf((const guint8 *)addr->data, buf, buf_len);
558         break;
559     case AT_IPv6:
560         ip6_to_str_buf_len((const guchar *)addr->data, buf, buf_len);
561         break;
562     case AT_IPX: /* 22 bytes */
563         addrdata = (const guint8 *)addr->data;
564         tempptr = bytes_to_hexstr(tempptr, &addrdata[0], 4); /* 8 bytes */
565         *tempptr++ = '.'; /*1 byte */
566         tempptr = bytes_to_hexstr(tempptr, &addrdata[4], 6); /* 12 bytes */
567         break;
568     case AT_SNA:
569         sna_fid_to_str_buf(addr, buf, buf_len);
570         break;
571     case AT_ATALK:
572         memcpy(&ddp_addr, addr->data, sizeof ddp_addr);
573         atalk_addr_to_str_buf(&ddp_addr, buf, buf_len);
574         break;
575     case AT_VINES:
576         vines_addr_to_str_buf((const guint8 *)addr->data, buf, buf_len);
577         break;
578     case AT_USB:
579         usb_addr_to_str_buf((const guint8 *)addr->data, buf, buf_len);
580         break;
581     case AT_OSI:
582         print_nsap_net_buf((const guint8 *)addr->data, addr->len, buf, buf_len);
583         break;
584     case AT_ARCNET: /* 5 bytes */
585         tempptr = g_stpcpy(tempptr, "0x"); /* 2 bytes */
586         tempptr = bytes_to_hexstr(tempptr, (const guint8 *)addr->data, 1); /* 2 bytes */
587         break;
588     case AT_FC: /* 9 bytes */
589         tempptr = bytes_to_hexstr_punct(tempptr, (const guint8 *)addr->data, 3, '.'); /* 8 bytes */
590         break;
591     case AT_SS7PC:
592         mtp3_addr_to_str_buf((const mtp3_addr_pc_t *)addr->data, buf, buf_len);
593         break;
594     case AT_STRINGZ:
595         g_strlcpy(buf, (const gchar *)addr->data, buf_len);
596         break;
597         case AT_EUI64: /* 24 bytes */
598         tempptr = bytes_to_hexstr_punct(tempptr, (const guint8 *)addr->data, 8, ':'); /* 23 bytes */
599         break;
600     case AT_URI: {
601         int copy_len = addr->len < (buf_len - 1) ? addr->len : (buf_len - 1);
602         memcpy(buf, addr->data, copy_len );
603         buf[copy_len] = '\0';
604         }
605         break;
606     case AT_TIPC:
607         tipc_addr_to_str_buf((const guint8 *)addr->data, buf, buf_len);
608         break;
609     case AT_IB:
610         ib_addr_to_str_buf(addr, buf, buf_len);
611         break;
612     case AT_AX25:
613         addrdata = (const guint8 *)addr->data;
614         g_snprintf(buf, buf_len, "%c%c%c%c%c%c-%02d",
615                 (addrdata[0] >> 1) & 0x7f, (addrdata[1] >> 1) & 0x7f, (addrdata[2] >> 1) & 0x7f,
616                 (addrdata[3] >> 1) & 0x7f, (addrdata[4] >> 1) & 0x7f, (addrdata[5] >> 1) & 0x7f,
617                 (addrdata[6] >> 1) & 0x0f );
618         break;
619     case AT_IEEE_802_15_4_SHORT:
620         ieee_802_15_4_short_addr = pletohs(addr->data);
621         if (ieee_802_15_4_short_addr == 0xffff)
622             g_snprintf(buf, buf_len, "Broadcast");
623         else
624             g_snprintf(buf, buf_len, "0x%04x", ieee_802_15_4_short_addr);
625         break;
626     default:
627         g_assert_not_reached();
628     }
629
630     /* copy to output buffer */
631     if (tempptr != temp) {
632         size_t temp_len = (size_t) (tempptr - temp);
633
634         if (temp_len < (size_t) buf_len) {
635             memcpy(buf, temp, temp_len);
636             buf[temp_len] = '\0';
637         } else
638          g_strlcpy(buf, BUF_TOO_SMALL_ERR, buf_len);/* Let the unexpected value alert user */
639     }
640 }
641
642 /*
643  * Editor modelines  -  http://www.wireshark.org/tools/modelines.html
644  *
645  * Local variables:
646  * c-basic-offset: 4
647  * tab-width: 8
648  * indent-tabs-mode: nil
649  * End:
650  *
651  * vi: set shiftwidth=4 tabstop=8 expandtab:
652  * :indentSize=4:tabSize=8:noTabs=true:
653  */