~ubuntu-branches/ubuntu/utopic/suricata/utopic

« back to all changes in this revision

Viewing changes to src/alert-syslog.c

  • Committer: Package Import Robot
  • Author(s): Pierre Chifflier
  • Date: 2011-11-17 23:20:51 UTC
  • mfrom: (1.1.10)
  • Revision ID: package-import@ubuntu.com-20111117232051-wlo0g2fyinx0zi25
Tags: 1.1-1
* Imported Upstream version 1.1
* Add instructions on getting new rules using oinkmaster
* Add Recommends on oinkmaster
* Move snort-rules-default to Recommends

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2007-2010 Open Information Security Foundation
 
2
 *
 
3
 * You can copy, redistribute or modify this Program under the terms of
 
4
 * the GNU General Public License version 2 as published by the Free
 
5
 * Software Foundation.
 
6
 *
 
7
 * This program is distributed in the hope that it will be useful,
 
8
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
 * GNU General Public License for more details.
 
11
 *
 
12
 * You should have received a copy of the GNU General Public License
 
13
 * version 2 along with this program; if not, write to the Free Software
 
14
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
 
15
 * 02110-1301, USA.
 
16
 */
 
17
 
 
18
/**
 
19
 * \file
 
20
 *
 
21
 * \author Gurvinder Singh <gurvindersinghdahiya@gmail.com>
 
22
 *
 
23
 * Logs alerts in a line based text format in to syslog.
 
24
 *
 
25
 */
 
26
 
 
27
#include "suricata-common.h"
 
28
#include "debug.h"
 
29
#include "flow.h"
 
30
#include "conf.h"
 
31
 
 
32
#include "threads.h"
 
33
#include "tm-threads.h"
 
34
#include "threadvars.h"
 
35
 
 
36
#include "detect.h"
 
37
#include "detect-parse.h"
 
38
#include "detect-engine.h"
 
39
#include "detect-engine-mpm.h"
 
40
#include "detect-reference.h"
 
41
 
 
42
#include "output.h"
 
43
#include "alert-syslog.h"
 
44
 
 
45
#include "util-classification-config.h"
 
46
#include "util-debug.h"
 
47
#include "util-print.h"
 
48
#include "util-proto-name.h"
 
49
#include "util-syslog.h"
 
50
#include "util-optimize.h"
 
51
 
 
52
#define DEFAULT_ALERT_SYSLOG_FACILITY_STR       "local0"
 
53
#define DEFAULT_ALERT_SYSLOG_FACILITY           LOG_LOCAL0
 
54
#define DEFAULT_ALERT_SYSLOG_LEVEL              LOG_ERR
 
55
#define MODULE_NAME                             "AlertSyslog"
 
56
 
 
57
extern uint8_t engine_mode;
 
58
#ifndef OS_WIN32
 
59
static int alert_syslog_level = DEFAULT_ALERT_SYSLOG_LEVEL;
 
60
#endif /* OS_WIN32 */
 
61
 
 
62
typedef struct AlertSyslogThread_ {
 
63
    /** LogFileCtx has the pointer to the file and a mutex to allow multithreading */
 
64
    LogFileCtx* file_ctx;
 
65
} AlertSyslogThread;
 
66
 
 
67
TmEcode AlertSyslog (ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
 
68
TmEcode AlertSyslogIPv4(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
 
69
TmEcode AlertSyslogIPv6(ThreadVars *, Packet *, void *, PacketQueue *, PacketQueue *);
 
70
TmEcode AlertSyslogThreadInit(ThreadVars *, void *, void **);
 
71
TmEcode AlertSyslogThreadDeinit(ThreadVars *, void *);
 
72
void AlertSyslogExitPrintStats(ThreadVars *, void *);
 
73
void AlertSyslogRegisterTests(void);
 
74
OutputCtx *AlertSyslogInitCtx(ConfNode *);
 
75
#ifndef OS_WIN32
 
76
static void AlertSyslogDeInitCtx(OutputCtx *);
 
77
#endif /* OS_WIN32 */
 
78
 
 
79
/** \brief   Function to register the AlertSyslog module */
 
80
void TmModuleAlertSyslogRegister (void) {
 
81
#ifndef OS_WIN32
 
82
    tmm_modules[TMM_ALERTSYSLOG].name = MODULE_NAME;
 
83
    tmm_modules[TMM_ALERTSYSLOG].ThreadInit = AlertSyslogThreadInit;
 
84
    tmm_modules[TMM_ALERTSYSLOG].Func = AlertSyslog;
 
85
    tmm_modules[TMM_ALERTSYSLOG].ThreadExitPrintStats = AlertSyslogExitPrintStats;
 
86
    tmm_modules[TMM_ALERTSYSLOG].ThreadDeinit = AlertSyslogThreadDeinit;
 
87
    tmm_modules[TMM_ALERTSYSLOG].RegisterTests = NULL;
 
88
    tmm_modules[TMM_ALERTSYSLOG].cap_flags = 0;
 
89
 
 
90
    OutputRegisterModule(MODULE_NAME, "syslog", AlertSyslogInitCtx);
 
91
#endif /* !OS_WIN32 */
 
92
}
 
93
 
 
94
/** \brief   Function to register the AlertSyslog module for IPv4 */
 
95
void TmModuleAlertSyslogIPv4Register (void) {
 
96
#ifndef OS_WIN32
 
97
    tmm_modules[TMM_ALERTSYSLOG4].name = "AlertSyslogIPv4";
 
98
    tmm_modules[TMM_ALERTSYSLOG4].ThreadInit = AlertSyslogThreadInit;
 
99
    tmm_modules[TMM_ALERTSYSLOG4].Func = AlertSyslogIPv4;
 
100
    tmm_modules[TMM_ALERTSYSLOG4].ThreadExitPrintStats = AlertSyslogExitPrintStats;
 
101
    tmm_modules[TMM_ALERTSYSLOG4].ThreadDeinit = AlertSyslogThreadDeinit;
 
102
    tmm_modules[TMM_ALERTSYSLOG4].RegisterTests = NULL;
 
103
#endif /* !OS_WIN32 */
 
104
}
 
105
 
 
106
/** \brief   Function to register the AlertSyslog module for IPv6 */
 
107
void TmModuleAlertSyslogIPv6Register (void) {
 
108
#ifndef OS_WIN32
 
109
    tmm_modules[TMM_ALERTSYSLOG6].name = "AlertSyslogIPv6";
 
110
    tmm_modules[TMM_ALERTSYSLOG6].ThreadInit = AlertSyslogThreadInit;
 
111
    tmm_modules[TMM_ALERTSYSLOG6].Func = AlertSyslogIPv6;
 
112
    tmm_modules[TMM_ALERTSYSLOG6].ThreadExitPrintStats = AlertSyslogExitPrintStats;
 
113
    tmm_modules[TMM_ALERTSYSLOG6].ThreadDeinit = AlertSyslogThreadDeinit;
 
114
    tmm_modules[TMM_ALERTSYSLOG6].RegisterTests = NULL;
 
115
#endif /* !OS_WIN32 */
 
116
}
 
117
 
 
118
#ifndef OS_WIN32
 
119
/**
 
120
 * \brief Create a new LogFileCtx for "syslog" output style.
 
121
 *
 
122
 * \param conf The configuration node for this output.
 
123
 * \return A OutputCtx pointer on success, NULL on failure.
 
124
 */
 
125
OutputCtx *AlertSyslogInitCtx(ConfNode *conf)
 
126
{
 
127
    const char *facility_s = ConfNodeLookupChildValue(conf, "facility");
 
128
    if (facility_s == NULL) {
 
129
        facility_s = DEFAULT_ALERT_SYSLOG_FACILITY_STR;
 
130
    }
 
131
 
 
132
    LogFileCtx *logfile_ctx = LogFileNewCtx();
 
133
    if (logfile_ctx == NULL) {
 
134
        SCLogDebug("AlertSyslogInitCtx: Could not create new LogFileCtx");
 
135
        return NULL;
 
136
    }
 
137
 
 
138
    int facility = SCMapEnumNameToValue(facility_s, SCSyslogGetFacilityMap());
 
139
    if (facility == -1) {
 
140
        SCLogWarning(SC_ERR_INVALID_ARGUMENT, "Invalid syslog facility: \"%s\","
 
141
                " now using \"%s\" as syslog facility", facility_s,
 
142
                DEFAULT_ALERT_SYSLOG_FACILITY_STR);
 
143
        facility = DEFAULT_ALERT_SYSLOG_FACILITY;
 
144
    }
 
145
 
 
146
    const char *level_s = ConfNodeLookupChildValue(conf, "level");
 
147
    if (level_s != NULL) {
 
148
        int level = SCMapEnumNameToValue(level_s, SCSyslogGetLogLevelMap());
 
149
        if (level != -1) {
 
150
            alert_syslog_level = level;
 
151
        }
 
152
    }
 
153
 
 
154
    const char *ident = ConfNodeLookupChildValue(conf, "identity");
 
155
    /* if null we just pass that to openlog, which will then
 
156
     * figure it out by itself. */
 
157
 
 
158
    openlog(ident, LOG_PID|LOG_NDELAY, facility);
 
159
 
 
160
    OutputCtx *output_ctx = SCMalloc(sizeof(OutputCtx));
 
161
    if (output_ctx == NULL) {
 
162
        SCLogDebug("AlertSyslogInitCtx: Could not create new OutputCtx");
 
163
        return NULL;
 
164
    }
 
165
    memset(output_ctx, 0x00, sizeof(OutputCtx));
 
166
 
 
167
    output_ctx->data = logfile_ctx;
 
168
    output_ctx->DeInit = AlertSyslogDeInitCtx;
 
169
 
 
170
    SCLogInfo("Syslog output initialized");
 
171
 
 
172
    return output_ctx;
 
173
}
 
174
 
 
175
/**
 
176
 * \brief Function to clear the memory of the output context and closes the
 
177
 *        syslog interface
 
178
 *
 
179
 * \param output_ctx pointer to the output context to be cleared
 
180
 */
 
181
static void AlertSyslogDeInitCtx(OutputCtx *output_ctx)
 
182
{
 
183
    if (output_ctx != NULL) {
 
184
        LogFileCtx *logfile_ctx = (LogFileCtx *)output_ctx->data;
 
185
        if (logfile_ctx != NULL) {
 
186
            LogFileFreeCtx(logfile_ctx);
 
187
        }
 
188
        SCFree(output_ctx);
 
189
    }
 
190
    closelog();
 
191
}
 
192
 
 
193
/**
 
194
 * \brief Function to initialize the AlertSystlogThread and sets the output
 
195
 *        context pointer
 
196
 *
 
197
 * \param tv            Pointer to the threadvars
 
198
 * \param initdata      Pointer to the output context
 
199
 * \param data          pointer to pointer to point to the AlertSyslogThread
 
200
 */
 
201
TmEcode AlertSyslogThreadInit(ThreadVars *t, void *initdata, void **data)
 
202
{
 
203
    if(initdata == NULL) {
 
204
        SCLogDebug("Error getting context for AlertSyslog. \"initdata\" "
 
205
                "argument NULL");
 
206
        return TM_ECODE_FAILED;
 
207
    }
 
208
 
 
209
    AlertSyslogThread *ast = SCMalloc(sizeof(AlertSyslogThread));
 
210
    if (ast == NULL)
 
211
        return TM_ECODE_FAILED;
 
212
 
 
213
    memset(ast, 0, sizeof(AlertSyslogThread));
 
214
 
 
215
    /** Use the Ouptut Context (file pointer and mutex) */
 
216
    ast->file_ctx = ((OutputCtx *)initdata)->data;
 
217
 
 
218
    *data = (void *)ast;
 
219
    return TM_ECODE_OK;
 
220
}
 
221
 
 
222
/**
 
223
 * \brief Function to deinitialize the AlertSystlogThread
 
224
 *
 
225
 * \param tv            Pointer to the threadvars
 
226
 * \param data          pointer to the AlertSyslogThread to be cleared
 
227
 */
 
228
TmEcode AlertSyslogThreadDeinit(ThreadVars *t, void *data)
 
229
{
 
230
    AlertSyslogThread *ast = (AlertSyslogThread *)data;
 
231
    if (ast == NULL) {
 
232
        return TM_ECODE_OK;
 
233
    }
 
234
 
 
235
    /* clear memory */
 
236
    memset(ast, 0, sizeof(AlertSyslogThread));
 
237
 
 
238
    SCFree(ast);
 
239
    return TM_ECODE_OK;
 
240
}
 
241
 
 
242
/**
 
243
 * \brief   Function which is called to print the IPv4 alerts to the syslog
 
244
 *
 
245
 * \param tv    Pointer to the threadvars
 
246
 * \param p     Pointer to the packet
 
247
 * \param data  pointer to the AlertSyslogThread
 
248
 * \param pq    pointer the to packet queue
 
249
 * \param postpq pointer to the post processed packet queue
 
250
 *
 
251
 * \return On succes return TM_ECODE_OK
 
252
 */
 
253
TmEcode AlertSyslogIPv4(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
 
254
                        PacketQueue *postpq)
 
255
{
 
256
    AlertSyslogThread *ast = (AlertSyslogThread *)data;
 
257
    int i;
 
258
    char *action = "";
 
259
 
 
260
    if (p->alerts.cnt == 0)
 
261
        return TM_ECODE_OK;
 
262
 
 
263
    SCMutexLock(&ast->file_ctx->fp_mutex);
 
264
 
 
265
    ast->file_ctx->alerts += p->alerts.cnt;
 
266
 
 
267
    for (i = 0; i < p->alerts.cnt; i++) {
 
268
        PacketAlert *pa = &p->alerts.alerts[i];
 
269
        if (unlikely(pa->s == NULL)) {
 
270
            continue;
 
271
        }
 
272
 
 
273
        char srcip[16], dstip[16];
 
274
 
 
275
        PrintInet(AF_INET, (const void *)GET_IPV4_SRC_ADDR_PTR(p), srcip, sizeof(srcip));
 
276
        PrintInet(AF_INET, (const void *)GET_IPV4_DST_ADDR_PTR(p), dstip, sizeof(dstip));
 
277
 
 
278
        if (pa->action == ACTION_DROP && IS_ENGINE_MODE_IPS(engine_mode)) {
 
279
            action = "[Drop] ";
 
280
        } else if (pa->action == ACTION_DROP) {
 
281
            action = "[wDrop] ";
 
282
        }
 
283
 
 
284
        if (SCProtoNameValid(IPV4_GET_IPPROTO(p)) == TRUE) {
 
285
            syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
 
286
                    PRIu32 "] %s [Classification: %s] [Priority: %"PRIu32"]"
 
287
                    " {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "", action, pa->s->gid,
 
288
                    pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg, pa->s->prio,
 
289
                    known_proto[IPV4_GET_IPPROTO(p)], srcip, p->sp, dstip, p->dp);
 
290
        } else {
 
291
            syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
 
292
                    PRIu32 "] %s [Classification: %s] [Priority: %"PRIu32"]"
 
293
                    " {PROTO:%03" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "",
 
294
                    action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
 
295
                    pa->s->prio, IPV4_GET_IPPROTO(p), srcip, p->sp, dstip, p->dp);
 
296
        }
 
297
    }
 
298
    SCMutexUnlock(&ast->file_ctx->fp_mutex);
 
299
 
 
300
    return TM_ECODE_OK;
 
301
}
 
302
 
 
303
/**
 
304
 * \brief   Function which is called to print the IPv6 alerts to the syslog
 
305
 *
 
306
 * \param tv    Pointer to the threadvars
 
307
 * \param p     Pointer to the packet
 
308
 * \param data  pointer to the AlertSyslogThread
 
309
 * \param pq    pointer the to packet queue
 
310
 * \param postpq pointer to the post processed packet queue
 
311
 *
 
312
 * \return On succes return TM_ECODE_OK
 
313
 */
 
314
TmEcode AlertSyslogIPv6(ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
 
315
                        PacketQueue *postpq)
 
316
{
 
317
    AlertSyslogThread *ast = (AlertSyslogThread *)data;
 
318
    int i;
 
319
    char *action = "";
 
320
 
 
321
    if (p->alerts.cnt == 0)
 
322
        return TM_ECODE_OK;
 
323
 
 
324
    SCMutexLock(&ast->file_ctx->fp_mutex);
 
325
 
 
326
    ast->file_ctx->alerts += p->alerts.cnt;
 
327
 
 
328
    for (i = 0; i < p->alerts.cnt; i++) {
 
329
        PacketAlert *pa = &p->alerts.alerts[i];
 
330
        if (unlikely(pa->s == NULL)) {
 
331
            continue;
 
332
        }
 
333
 
 
334
        char srcip[46], dstip[46];
 
335
 
 
336
        PrintInet(AF_INET6, (const void *)GET_IPV6_SRC_ADDR(p), srcip, sizeof(srcip));
 
337
        PrintInet(AF_INET6, (const void *)GET_IPV6_DST_ADDR(p), dstip, sizeof(dstip));
 
338
 
 
339
        if (pa->action == ACTION_DROP && IS_ENGINE_MODE_IPS(engine_mode)) {
 
340
            action = "[Drop] ";
 
341
        } else if (pa->action == ACTION_DROP) {
 
342
            action = "[wDrop] ";
 
343
        }
 
344
 
 
345
        if (SCProtoNameValid(IPV6_GET_L4PROTO(p)) == TRUE) {
 
346
            syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
 
347
                    "" PRIu32 "] %s [Classification: %s] [Priority: %"
 
348
                    "" PRIu32 "] {%s} %s:%" PRIu32 " -> %s:%" PRIu32 "",
 
349
                    action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
 
350
                    pa->s->prio, known_proto[IPV6_GET_L4PROTO(p)], srcip, p->sp,
 
351
                    dstip, p->dp);
 
352
 
 
353
        } else {
 
354
            syslog(alert_syslog_level, "%s[%" PRIu32 ":%" PRIu32 ":%"
 
355
                    "" PRIu32 "] %s [Classification: %s] [Priority: %"
 
356
                    "" PRIu32 "] {PROTO:%03" PRIu32 "} %s:%" PRIu32 " -> %s:%" PRIu32 "",
 
357
                    action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg, pa->s->class_msg,
 
358
                    pa->s->prio, IPV6_GET_L4PROTO(p), srcip, p->sp, dstip, p->dp);
 
359
        }
 
360
 
 
361
    }
 
362
    SCMutexUnlock(&ast->file_ctx->fp_mutex);
 
363
 
 
364
    return TM_ECODE_OK;
 
365
}
 
366
 
 
367
/**
 
368
 * \brief   Function which is called to print the decode alerts to the syslog
 
369
 *
 
370
 * \param tv    Pointer to the threadvars
 
371
 * \param p     Pointer to the packet
 
372
 * \param data  pointer to the AlertSyslogThread
 
373
 * \param pq    pointer the to packet queue
 
374
 * \param postpq pointer to the post processed packet queue
 
375
 *
 
376
 * \return On succes return TM_ECODE_OK
 
377
 */
 
378
TmEcode AlertSyslogDecoderEvent(ThreadVars *tv, Packet *p, void *data,
 
379
                                    PacketQueue *pq, PacketQueue *postpq)
 
380
{
 
381
    AlertSyslogThread *ast = (AlertSyslogThread *)data;
 
382
    int i;
 
383
    char *action = "";
 
384
 
 
385
    if (p->alerts.cnt == 0)
 
386
        return TM_ECODE_OK;
 
387
 
 
388
    SCMutexLock(&ast->file_ctx->fp_mutex);
 
389
 
 
390
    ast->file_ctx->alerts += p->alerts.cnt;
 
391
    char temp_buf_hdr[512];
 
392
    char temp_buf_pkt[65] = "";
 
393
    char temp_buf_tail[32];
 
394
    char alert[2048] = "";
 
395
 
 
396
    for (i = 0; i < p->alerts.cnt; i++) {
 
397
        PacketAlert *pa = &p->alerts.alerts[i];
 
398
        if (unlikely(pa->s == NULL)) {
 
399
            continue;
 
400
        }
 
401
 
 
402
        if (pa->action == ACTION_DROP && IS_ENGINE_MODE_IPS(engine_mode)) {
 
403
            action = "[Drop] ";
 
404
        } else if (pa->action == ACTION_DROP) {
 
405
            action = "[wDrop] ";
 
406
        }
 
407
 
 
408
        snprintf(temp_buf_hdr, sizeof(temp_buf_hdr), "%s[%" PRIu32 ":%" PRIu32
 
409
                ":%" PRIu32 "] %s [Classification: %s] [Priority: %" PRIu32
 
410
                "] [**] [Raw pkt: ", action, pa->s->gid, pa->s->id, pa->s->rev, pa->s->msg,
 
411
                pa->s->class_msg, pa->s->prio);
 
412
        strlcpy(alert, temp_buf_hdr, sizeof(alert));
 
413
 
 
414
        PrintRawLineHexBuf(temp_buf_pkt, sizeof(temp_buf_pkt), GET_PKT_DATA(p), GET_PKT_LEN(p) < 32 ? GET_PKT_LEN(p) : 32);
 
415
        strlcat(alert, temp_buf_pkt, sizeof(alert));
 
416
 
 
417
        if (p->pcap_cnt != 0) {
 
418
            snprintf(temp_buf_tail, sizeof(temp_buf_tail), "] [pcap file packet: %"PRIu64"]",
 
419
                    p->pcap_cnt);
 
420
        } else {
 
421
            temp_buf_tail[0] = ']';
 
422
            temp_buf_tail[1] = '\0';
 
423
        }
 
424
        strlcat(alert, temp_buf_tail, sizeof(alert));
 
425
 
 
426
        syslog(alert_syslog_level, "%s", alert);
 
427
    }
 
428
    SCMutexUnlock(&ast->file_ctx->fp_mutex);
 
429
 
 
430
    return TM_ECODE_OK;
 
431
}
 
432
 
 
433
/**
 
434
 * \brief   Function which is called to print the alerts to the syslog
 
435
 *
 
436
 * \param tv    Pointer to the threadvars
 
437
 * \param p     Pointer to the packet
 
438
 * \param data  pointer to the AlertSyslogThread
 
439
 * \param pq    pointer the to packet queue
 
440
 * \param postpq pointer to the post processed packet queue
 
441
 *
 
442
 * \return On succes return TM_ECODE_OK
 
443
 */
 
444
TmEcode AlertSyslog (ThreadVars *tv, Packet *p, void *data, PacketQueue *pq,
 
445
                        PacketQueue *postpq)
 
446
{
 
447
    if (PKT_IS_IPV4(p)) {
 
448
        return AlertSyslogIPv4(tv, p, data, pq, NULL);
 
449
    } else if (PKT_IS_IPV6(p)) {
 
450
        return AlertSyslogIPv6(tv, p, data, pq, NULL);
 
451
    } else if (p->events.cnt > 0) {
 
452
        return AlertSyslogDecoderEvent(tv, p, data, pq, NULL);
 
453
    }
 
454
 
 
455
    return TM_ECODE_OK;
 
456
}
 
457
 
 
458
/**
 
459
 * \brief   Function to print the total alert while closing the engine
 
460
 *
 
461
 * \param tv    Pointer to the output threadvars
 
462
 * \param data  Pointer to the AlertSyslogThread data
 
463
 */
 
464
void AlertSyslogExitPrintStats(ThreadVars *tv, void *data) {
 
465
    AlertSyslogThread *ast = (AlertSyslogThread *)data;
 
466
    if (ast == NULL) {
 
467
        return;
 
468
    }
 
469
 
 
470
    SCLogInfo("(%s) Alerts %" PRIu64 "", tv->name, ast->file_ctx->alerts);
 
471
}
 
472
#endif /* !OS_WIN32 */
 
473