Coverage Report

Created: 2026-05-14 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wireshark/epan/dissectors/packet-aol.c
Line
Count
Source
1
/* packet-aol.c
2
 *
3
 * Routines for dissecting the America Online protocol
4
 * Copyright (C) 2012 Tim Hentenaar <tim at hentenaar dot com>
5
 *
6
 * More information on the P3 frame protocol can be found on page 66 of:
7
 * http://koin.org/files/aol.aim/aol/fdo/manuals/WAOL.doc
8
 *
9
 * SPDX-License-Identifier: GPL-2.0-or-later
10
 */
11
12
#include "config.h"
13
14
#include <epan/packet.h>
15
#include <epan/prefs.h>
16
#include <epan/expert.h>
17
18
#include "packet-tcp.h"
19
20
void proto_register_aol(void);
21
void proto_reg_handoff_aol(void);
22
23
static dissector_handle_t aol_handle;
24
25
/* AOL's port */
26
15
#define AOL_PORT 5190
27
28
/* Frame markers */
29
0
#define AOL_P3_FRAME_START 0x5a
30
#define AOL_P3_FRAME_END   0x0d
31
32
/* Frame types */
33
#define AOL_P3_TYPE_DATA      0x20
34
#define AOL_P3_TYPE_SS        0x21
35
#define AOL_P3_TYPE_SSR       0x22
36
0
#define AOL_P3_TYPE_INIT      0x23
37
#define AOL_P3_TYPE_ACK       0x24
38
#define AOL_P3_TYPE_NAK       0x25
39
#define AOL_P3_TYPE_HEARTBEAT 0x26
40
41
static const value_string aol_p3_types[] = {
42
  { AOL_P3_TYPE_DATA,      "Data"        },
43
  { AOL_P3_TYPE_SS,        "SS Request"  },
44
  { AOL_P3_TYPE_SSR,       "SS Response" },
45
  { AOL_P3_TYPE_INIT,      "Init"        },
46
  { AOL_P3_TYPE_ACK,       "ACK"         },
47
  { AOL_P3_TYPE_NAK,       "NAK"         },
48
  { AOL_P3_TYPE_HEARTBEAT, "Heartbeat"   },
49
  { 0,                     NULL          }
50
};
51
52
/* Platforms */
53
#define AOL_PLATFORM_WINDOWS 0x03
54
#define AOL_PLATFORM_MAC     0x0c
55
56
static const value_string aol_platforms[] = {
57
  { AOL_PLATFORM_WINDOWS,  "Microsoft Windows" },
58
  { AOL_PLATFORM_MAC,      "Macintosh"         },
59
  { 0,                     NULL                }
60
};
61
62
/* Windows Memory Mode */
63
static const value_string aol_wmem_mode[] = {
64
  { 0, "Standard" },
65
  { 1, "Enhanced" },
66
  { 0, NULL       }
67
};
68
69
/* Protocol */
70
static int proto_aol;
71
72
/* Special fields */
73
static int hf_aol_udata;
74
static int hf_aol_init;
75
76
/* Header fields */
77
static int hf_aol_start;
78
static int hf_aol_crc;
79
static int hf_aol_len;
80
static int hf_aol_tx_seq;
81
static int hf_aol_rx_seq;
82
static int hf_aol_type;
83
static int hf_aol_token;
84
static int hf_aol_data;
85
static int hf_aol_end;
86
87
/* 'INIT' PDU Fields */
88
static int hf_aol_platform;
89
static int hf_aol_version;
90
static int hf_aol_subversion;
91
static int hf_aol_unused;
92
static int hf_aol_machine_mem;
93
static int hf_aol_app_mem;
94
static int hf_aol_pc_type;
95
static int hf_aol_rel_month;
96
static int hf_aol_rel_day;
97
static int hf_aol_cust_class;
98
static int hf_aol_udo_timestamp;
99
static int hf_aol_dos_ver;
100
static int hf_aol_sess_flags;
101
static int hf_aol_video_type;
102
static int hf_aol_cpu_type;
103
static int hf_aol_media_type;
104
static int hf_aol_win_ver;
105
static int hf_aol_wmem_mode;
106
static int hf_aol_horiz_res;
107
static int hf_aol_vert_res;
108
static int hf_aol_num_colors;
109
static int hf_aol_filler;
110
static int hf_aol_region;
111
static int hf_aol_lang;
112
static int hf_aol_conn_spd;
113
114
/* Subtrees */
115
static int ett_aol;
116
static int ett_aol_data;
117
118
static expert_field ei_aol_pdu_length_bad;
119
static expert_field ei_aol_end_missing;
120
121
/* Prefs */
122
static bool aol_desegment  = true;
123
124
/**
125
 * Dissect the 'INIT' PDU.
126
 */
127
0
static unsigned dissect_aol_init(tvbuff_t *tvb, packet_info *pinfo _U_, unsigned offset, proto_tree *tree) {
128
0
  proto_item *data_item;
129
0
  proto_tree *data_tree;
130
0
  uint16_t    dos_ver   = 0;
131
0
  uint16_t    win_ver   = 0;
132
133
  /* Add the Data subtree */
134
0
  data_item = proto_tree_add_item(tree,hf_aol_init,tvb,offset,tvb_reported_length_remaining(tvb,offset)-1,ENC_NA);
135
0
  data_tree = proto_item_add_subtree(data_item,ett_aol_data);
136
137
  /* Now, parse the structure */
138
0
  proto_tree_add_item(data_tree,hf_aol_platform,     tvb,offset,1,ENC_NA);            offset += 1;
139
0
  proto_tree_add_item(data_tree,hf_aol_version,      tvb,offset,1,ENC_NA);            offset += 1;
140
0
  proto_tree_add_item(data_tree,hf_aol_subversion,   tvb,offset,1,ENC_NA);            offset += 1;
141
0
  proto_tree_add_item(data_tree,hf_aol_unused,       tvb,offset,1,ENC_NA);            offset += 1;
142
0
  proto_tree_add_item(data_tree,hf_aol_machine_mem,  tvb,offset,1,ENC_NA);            offset += 1;
143
0
  proto_tree_add_item(data_tree,hf_aol_app_mem,      tvb,offset,1,ENC_NA);            offset += 1;
144
0
  proto_tree_add_item(data_tree,hf_aol_pc_type,      tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
145
0
  proto_tree_add_item(data_tree,hf_aol_rel_month,    tvb,offset,1,ENC_NA);            offset += 1;
146
0
  proto_tree_add_item(data_tree,hf_aol_rel_day,      tvb,offset,1,ENC_NA);            offset += 1;
147
0
  proto_tree_add_item(data_tree,hf_aol_cust_class,   tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
148
0
  proto_tree_add_item(data_tree,hf_aol_udo_timestamp,tvb,offset,4,ENC_LITTLE_ENDIAN); offset += 4;
149
150
0
  dos_ver = tvb_get_ntohs(tvb,offset);
151
0
  proto_tree_add_uint_format_value(data_tree,hf_aol_dos_ver,tvb,offset,2,dos_ver,"%d.%d",(dos_ver & 0xFF00) >> 8,dos_ver & 0xFF);
152
0
  offset += 2;
153
154
0
  proto_tree_add_item(data_tree,hf_aol_sess_flags,   tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
155
0
  proto_tree_add_item(data_tree,hf_aol_video_type,   tvb,offset,1,ENC_NA);            offset += 1;
156
0
  proto_tree_add_item(data_tree,hf_aol_cpu_type,     tvb,offset,1,ENC_NA);            offset += 1;
157
0
  proto_tree_add_item(data_tree,hf_aol_media_type,   tvb,offset,4,ENC_LITTLE_ENDIAN); offset += 4;
158
159
  /* Windows version is a 32-bit value, but only the lower 16 bits are populated */
160
0
  win_ver = tvb_get_ntohs(tvb,offset);
161
0
  proto_tree_add_uint_format_value(data_tree,hf_aol_win_ver,tvb,offset,2,dos_ver,"%d.%d",(win_ver & 0xFF00) >> 8,win_ver & 0xFF);
162
0
  offset += 4;
163
164
0
  proto_tree_add_item(data_tree,hf_aol_wmem_mode,    tvb,offset,1,ENC_NA);            offset += 1;
165
0
  proto_tree_add_item(data_tree,hf_aol_horiz_res,    tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
166
0
  proto_tree_add_item(data_tree,hf_aol_vert_res,     tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
167
0
  proto_tree_add_item(data_tree,hf_aol_num_colors,   tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2; /* 37b */
168
169
  /* WAOL 1.5 (48b), >= 2.5 (49b) */
170
0
  if (tvb_reported_length_remaining(tvb,offset) <= 13) { /* WAOL 1.5 - 3.0 */
171
0
    if (tvb_reported_length_remaining(tvb,offset) == 13) { /* WAOL > 1.5 */
172
0
      proto_tree_add_item(data_tree,hf_aol_filler,tvb,offset,1,ENC_BIG_ENDIAN); offset += 1;
173
0
    }
174
175
0
    proto_tree_add_item(data_tree,hf_aol_region,  tvb,offset,2,ENC_LITTLE_ENDIAN); offset += 2;
176
0
    proto_tree_add_item(data_tree,hf_aol_lang,    tvb,offset,8,ENC_LITTLE_ENDIAN); offset += 8;
177
0
    proto_tree_add_item(data_tree,hf_aol_conn_spd,tvb,offset,1,ENC_NA);            offset += 1;
178
0
  } else { /* WAOL >= 4.0 - ??? (52b) */
179
0
    ;
180
0
  }
181
182
0
  return offset;
183
0
}
184
185
/**
186
 * Get the length of a particular PDU (+6 bytes for the frame)
187
 */
188
static unsigned get_aol_pdu_len(packet_info *pinfo _U_, tvbuff_t *tvb,
189
                             int offset, void *data _U_)
190
0
{
191
0
  uint16_t plen;
192
193
  /* Get the PDU length */
194
0
  plen = tvb_get_ntohs(tvb,offset+3);
195
0
  return plen + 6;
196
0
}
197
198
/**
199
 * Dissect a PDU
200
 */
201
0
static int dissect_aol_pdu(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void* data _U_) {
202
0
  proto_item    *ti;
203
0
  proto_tree    *aol_tree;
204
0
  unsigned       offset     = 0;
205
0
  uint16_t       pdu_len;
206
0
  uint8_t        pdu_type   = 0;
207
208
  /* Set the protocol name, and info column text. */
209
0
  col_set_str(pinfo->cinfo,COL_PROTOCOL,"AOL");
210
0
  col_set_str(pinfo->cinfo,COL_INFO,"America Online");
211
212
  /* Add our tree item, and tree */
213
0
  ti       = proto_tree_add_item(tree,proto_aol,tvb,0,-1,ENC_NA);
214
0
  aol_tree = proto_item_add_subtree(ti,ett_aol);
215
0
  pdu_len  = tvb_get_ntohs(tvb,3);
216
217
  /* Add the first few P3 fields */
218
0
  proto_tree_add_item(aol_tree,hf_aol_start,tvb,offset,1,ENC_NA);         offset += 1;
219
0
  proto_tree_add_checksum(aol_tree, tvb, offset, hf_aol_crc, -1, NULL, pinfo, 0, ENC_BIG_ENDIAN, PROTO_CHECKSUM_NO_FLAGS); offset += 2;
220
0
  proto_tree_add_item(aol_tree,hf_aol_len,  tvb,offset,2,ENC_BIG_ENDIAN); offset += 2;
221
222
  /* Add sequence fields */
223
0
  if (pdu_len >= 2) {
224
0
    proto_tree_add_item(aol_tree,hf_aol_tx_seq,tvb,offset,1,ENC_NA); offset += 1;
225
0
    proto_tree_add_item(aol_tree,hf_aol_rx_seq,tvb,offset,1,ENC_NA); offset += 1;
226
0
    pdu_len -= 2;
227
0
  }
228
229
  /* Add type (and add it to the tree item / info column) */
230
0
  if (pdu_len >= 1) {
231
0
    pdu_type = tvb_get_uint8(tvb,offset) & 0x3f;
232
0
    col_append_fstr(pinfo->cinfo,COL_INFO," [Type: %s]",val_to_str_const(pdu_type,aol_p3_types,"Unknown"));
233
0
    proto_item_append_text(ti," [Type: %s]",val_to_str_const(pdu_type,aol_p3_types,"Unknown"));
234
0
    proto_tree_add_uint(aol_tree,hf_aol_type,tvb,offset,1,pdu_type);
235
0
    offset += 1; pdu_len -= 1;
236
0
  }
237
238
  /* Now for the data... */
239
0
  if (pdu_len > 0) {
240
0
    unsigned old_offset = offset;
241
242
0
    if (tvb_reported_length_remaining(tvb,offset) > pdu_len) {
243
      /* Init packets are a special case */
244
0
      if (pdu_type == AOL_P3_TYPE_INIT) {
245
0
        offset = dissect_aol_init(tvb,pinfo,offset,aol_tree);
246
0
      } else {
247
0
        if (pdu_len >= 2) {
248
0
          const uint8_t* token;
249
          /* Get the token */
250
0
          proto_tree_add_item_ret_string(aol_tree,hf_aol_token,tvb,offset,2,ENC_ASCII,pinfo->pool,&token);
251
          /* Add it */
252
0
          col_append_fstr(pinfo->cinfo,COL_INFO," [Token: '%s']", token);
253
0
          proto_item_append_text(ti," [Token: '%s']", token);
254
0
          offset += 2; pdu_len -= 2;
255
0
        }
256
257
        /* Add the data */
258
0
        if (pdu_len > 0) {
259
0
          proto_tree_add_item(aol_tree,hf_aol_data,tvb,offset,pdu_len,ENC_NA);
260
0
          offset += pdu_len;
261
0
        }
262
0
      }
263
264
0
      if (offset < (old_offset + pdu_len)) {
265
        /* We didn't parse the entire pdu... */
266
0
        proto_tree_add_item(aol_tree,hf_aol_udata,tvb,offset,(old_offset+pdu_len)-offset,ENC_NA);
267
0
        offset = old_offset + pdu_len;
268
0
      }
269
0
    } else {
270
      /* Malformed packet */
271
0
      expert_add_info(pinfo,ti,&ei_aol_pdu_length_bad);
272
0
    }
273
0
  }
274
275
  /* End-of-Frame Marker */
276
0
  if (tvb_reported_length_remaining(tvb,offset) >= 1) {
277
0
    proto_tree_add_item(aol_tree,hf_aol_end,tvb,offset,1,ENC_NA);/* offset += 1;*/
278
0
  } else {
279
    /* Malformed Packet */
280
0
    expert_add_info(pinfo,ti,&ei_aol_end_missing);
281
0
  }
282
283
0
  return tvb_reported_length(tvb);
284
0
}
285
286
/**
287
 * Dissect a packet
288
 */
289
0
static int dissect_aol(tvbuff_t *tvb, packet_info *pinfo, proto_tree *tree, void *data) {
290
  /* Ensure this really is an AOL packet */
291
0
  if (tvb_reported_length(tvb) >= 1 && tvb_get_uint8(tvb,0) != AOL_P3_FRAME_START) return 0;
292
293
  /* Dissect PDUs */
294
0
  tcp_dissect_pdus(tvb,pinfo,tree,aol_desegment,9,get_aol_pdu_len,dissect_aol_pdu,data);
295
0
  return tvb_reported_length(tvb);
296
0
}
297
298
/**
299
 * Protocol Registration Routine
300
 *
301
 * Registers our protocol.
302
 */
303
15
void proto_register_aol(void) {
304
  /* Header fields */
305
15
  static hf_register_info hf[] = {
306
    /* Special Stuff */
307
15
    { &hf_aol_udata, { "Unparsed Data",   "aol.udata",    FT_BYTES, BASE_NONE, NULL, 0x00, NULL, HFILL }},
308
15
    { &hf_aol_init,  { "AOL 'INIT' Data", "aol.init_data",FT_NONE,  BASE_NONE, NULL, 0x00, NULL, HFILL }},
309
310
    /* P3 Frame */
311
15
    { &hf_aol_start,  { "Start of Frame", "aol.start",    FT_UINT8,  BASE_HEX,  NULL,               0x00, NULL, HFILL }},
312
15
    { &hf_aol_crc,    { "Checksum",       "aol.checksum", FT_UINT16, BASE_HEX,  NULL,               0x00, NULL, HFILL }},
313
15
    { &hf_aol_len,    { "Length",         "aol.len",      FT_UINT16, BASE_DEC,  NULL,               0x00, NULL, HFILL }},
314
15
    { &hf_aol_tx_seq, { "Tx Sequence",    "aol.tx_seq",   FT_UINT8,  BASE_HEX,  NULL,               0x00, NULL, HFILL }},
315
15
    { &hf_aol_rx_seq, { "Rx Sequence",    "aol.rx_seq",   FT_UINT8,  BASE_HEX,  NULL,               0x00, NULL, HFILL }},
316
15
    { &hf_aol_type,   { "Type",           "aol.type",     FT_UINT8,  BASE_HEX,  VALS(aol_p3_types), 0x00, NULL, HFILL }},
317
15
    { &hf_aol_token,  { "Token",          "aol.token",    FT_STRING, BASE_NONE, NULL,               0x00, NULL, HFILL }},
318
15
    { &hf_aol_data,   { "Data",           "aol.data",     FT_BYTES,  BASE_NONE, NULL,               0x00, NULL, HFILL }},
319
15
    { &hf_aol_end,    { "End of Frame",   "aol.end",      FT_UINT8,  BASE_HEX,  NULL,               0x00, NULL, HFILL }},
320
321
    /* Init packet */
322
15
    { &hf_aol_platform,     { "Platform",         "aol.init.platform",   FT_UINT8,  BASE_HEX, VALS(aol_platforms),0x00, NULL, HFILL }},
323
15
    { &hf_aol_version,      { "Client Version",   "aol.init.version",    FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
324
15
    { &hf_aol_subversion,   { "Client Subversion","aol.init.subversion", FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
325
15
    { &hf_aol_unused,       { "Unused",           "aol.init.unused",     FT_UINT8,  BASE_HEX, NULL,               0x00, NULL, HFILL }},
326
15
    { &hf_aol_machine_mem,  { "Machine Memory",   "aol.init.memory",     FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
327
15
    { &hf_aol_app_mem,      { "App Memory",       "aol.init.app_memory", FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
328
15
    { &hf_aol_pc_type,      { "PC Type",          "aol.init.pc_type",    FT_UINT16, BASE_HEX, NULL,               0x00, NULL, HFILL }},
329
15
    { &hf_aol_rel_month,    { "Release Month",    "aol.init.rel_month",  FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
330
15
    { &hf_aol_rel_day,      { "Release Day",      "aol.init.rel_day",    FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
331
15
    { &hf_aol_cust_class,   { "Customer Class",   "aol.init.cust_class", FT_UINT16, BASE_HEX, NULL,               0x00, NULL, HFILL }},
332
15
    { &hf_aol_udo_timestamp,{ "UDO Timestamp",    "aol.init.udo_ts",     FT_UINT32, BASE_DEC, NULL,               0x00, NULL, HFILL }},
333
15
    { &hf_aol_dos_ver,      { "DOS Version",      "aol.init.dos_ver",    FT_UINT16, BASE_HEX, NULL,               0x00, NULL, HFILL }},
334
15
    { &hf_aol_sess_flags,   { "Session Flags",    "aol.init.sess_flags", FT_UINT16, BASE_HEX, NULL,               0x00, NULL, HFILL }},
335
15
    { &hf_aol_video_type,   { "Video Type",       "aol.init.video_type", FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
336
15
    { &hf_aol_cpu_type,     { "CPU Type",         "aol.init.cpu_type",   FT_UINT8,  BASE_DEC, NULL,               0x00, NULL, HFILL }},
337
15
    { &hf_aol_media_type,   { "Media Type",       "aol.init.media_type", FT_UINT32, BASE_HEX, NULL,               0x00, NULL, HFILL }},
338
15
    { &hf_aol_win_ver,      { "Windows Version",  "aol.init.win_ver",    FT_UINT32, BASE_HEX, NULL,               0x00, NULL, HFILL }},
339
15
    { &hf_aol_wmem_mode,    { "Windows Mem Type", "aol.init.wmem_mode",  FT_UINT8,  BASE_DEC, VALS(aol_wmem_mode),0x00, NULL, HFILL }},
340
15
    { &hf_aol_horiz_res,    { "Horizontal Res",   "aol.init.horiz_res",  FT_UINT16, BASE_DEC, NULL,               0x00, NULL, HFILL }},
341
15
    { &hf_aol_vert_res,     { "Vertical Res",     "aol.init.vert_res",   FT_UINT16, BASE_DEC, NULL,               0x00, NULL, HFILL }},
342
15
    { &hf_aol_num_colors,   { "Colors",           "aol.init.colors",     FT_UINT16, BASE_DEC, NULL,               0x00, NULL, HFILL }},
343
15
    { &hf_aol_filler,       { "Filler Byte",      "aol.init.filler",     FT_UINT8,  BASE_HEX, NULL,               0x00, NULL, HFILL }},
344
15
    { &hf_aol_region,       { "AOL Region",       "aol.init.region",     FT_UINT16, BASE_HEX, NULL,               0x00, NULL, HFILL }},
345
15
    { &hf_aol_lang,         { "AOL Language(s)",  "aol.init.langs",      FT_UINT64, BASE_HEX, NULL,               0x00, NULL, HFILL }},
346
15
    { &hf_aol_conn_spd,     { "Connection Speed", "aol.init.conn_spd",   FT_UINT8,  BASE_HEX, NULL,               0x00, NULL, HFILL }},
347
15
  };
348
349
  /* Trees */
350
15
  static int *ett[] = {
351
15
    &ett_aol,
352
15
    &ett_aol_data
353
15
  };
354
355
15
  static ei_register_info ei[] = {
356
15
    { &ei_aol_pdu_length_bad, { "aol.pdu_length_bad", PI_MALFORMED, PI_ERROR, "pdu length > tvb length", EXPFILL }},
357
15
    { &ei_aol_end_missing, { "aol.end_missing", PI_PROTOCOL, PI_WARN, "End of frame marker expected", EXPFILL }},
358
15
  };
359
360
  /* Module (for prefs) */
361
15
  module_t *aol_module;
362
15
  expert_module_t* expert_aol;
363
364
  /* Register the protocol and header fields */
365
15
  proto_aol = proto_register_protocol("America Online","AOL","aol");
366
15
  proto_register_field_array(proto_aol,hf,array_length(hf));
367
15
  proto_register_subtree_array(ett,array_length(ett));
368
369
15
  expert_aol = expert_register_protocol(proto_aol);
370
15
  expert_register_field_array(expert_aol, ei, array_length(ei));
371
372
  /* Register prefs */
373
15
  aol_module = prefs_register_protocol(proto_aol,NULL);
374
15
  prefs_register_bool_preference(aol_module,"desegment",
375
15
      "Reassemble AOL messages spanning multiple TCP segments",
376
15
      "Whether the AOL dissector should reassemble messages spanning multiple TCP segments. "
377
15
      "To use this option, you must also enable \"Allow subdissectors to reassemble TCP streams\" "
378
15
      "in the TCP protocol settings.",&aol_desegment);
379
380
  /* Register the dissector */
381
15
  aol_handle = register_dissector("aol", dissect_aol,proto_aol);
382
15
}
383
384
/**
385
 * Dissector Handoff Routine
386
 *
387
 * Initialize the dissector.
388
 */
389
15
void proto_reg_handoff_aol(void) {
390
15
  dissector_add_uint_with_preference("tcp.port",AOL_PORT,aol_handle);
391
15
}
392
393
/* vi:set ts=4: */
394
395
/*
396
 * Editor modelines  -  https://www.wireshark.org/tools/modelines.html
397
 *
398
 * Local variables:
399
 * c-basic-offset: 8
400
 * tab-width: 8
401
 * indent-tabs-mode: t
402
 * End:
403
 *
404
 * vi: set shiftwidth=8 tabstop=8 noexpandtab:
405
 * :indentSize=8:tabSize=8:noTabs=false:
406
 */