AIX: Fix undefined symbols
[openafs.git] / src / audit / audit-sysvmq.c
1 /*
2  * Copyright 2009, Sine Nomine Associates and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <afsconfig.h>
11 #include <afs/param.h>
12
13 #include <roken.h>
14
15 /* only build on platforms that have SysV IPC support; i.e., when we
16  * have sys/ipc.h */
17 #ifdef HAVE_SYS_IPC_H
18
19 #include <sys/ipc.h>
20 #include <sys/msg.h>
21
22 #include "audit-api.h"
23
24 /* message queue size will be increased to this value
25    if not already bigger */
26 #define MSGMNB (2*1024*1024)
27
28 /* msgsnd requires a structure with the following layout. See manpage for
29  * msgsnd() for the details */
30 struct my_msgbuf {
31     long mtype;
32     char mtext[OSI_AUDIT_MAXMSG];
33 };
34
35 struct mqaudit_stats {
36     long all;
37     long truncated;
38     long lost;
39 };
40
41 struct sysvmq_context {
42     int mqid;
43     struct my_msgbuf msgbuffer;
44     struct mqaudit_stats myauditstats;
45 };
46
47 static void
48 send_msg(void *rock, const char *message, int msglen, int truncated)
49 {
50     struct sysvmq_context *ctx = rock;
51
52     if (msglen >= OSI_AUDIT_MAXMSG) {
53         truncated = 1;
54         msglen = OSI_AUDIT_MAXMSG - 1;
55     }
56
57     /* Copy the data into the msgsnd structure */
58     memcpy(&ctx->msgbuffer.mtext, message, msglen+1);
59     ctx->msgbuffer.mtext[msglen] = '\0';
60
61     /* Include the trailing zero in the msgsnd */
62     if (msgsnd(ctx->mqid, &ctx->msgbuffer, msglen+1, IPC_NOWAIT) == -1) {
63         ctx->myauditstats.lost++;
64     } else if (truncated) {
65         ctx->myauditstats.truncated++;
66     }
67     ctx->myauditstats.all++;
68 }
69
70 static int
71 open_file(void *rock, const char *fileName)
72 {
73     struct sysvmq_context *ctx = rock;
74     int tempfd;
75     struct msqid_ds msqdesc;
76
77     ctx->msgbuffer.mtext[0] = 0;
78     ctx->msgbuffer.mtype = 1;
79
80     ctx->myauditstats.all = 0;
81     ctx->myauditstats.lost = 0;
82     ctx->myauditstats.truncated = 0;
83
84     /* try to create file for ftok if it doesn't already exist */
85     tempfd = open(fileName, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
86     if(tempfd != -1)
87         close(tempfd);
88
89     ctx->mqid = msgget(ftok(fileName, 1), S_IRUSR | S_IWUSR | IPC_CREAT);
90     if (ctx->mqid == -1) {
91         printf("Warning: auditlog message queue %s cannot be opened.\n", fileName);
92         return 1;
93     }
94
95     /* increase message queue size */
96     msgctl(ctx->mqid, IPC_STAT, &msqdesc);
97     if (msqdesc.msg_qbytes < MSGMNB) {
98         msqdesc.msg_qbytes = MSGMNB;
99         msgctl(ctx->mqid, IPC_SET, &msqdesc);
100     }
101
102     return 0;
103 }
104
105 static void
106 print_interface_stats(void *rock, FILE *out)
107 {
108     struct sysvmq_context *ctx = rock;
109
110     fprintf(out, "audit statistics: %ld messages total, %ld truncated, %ld lost\n",
111         ctx->myauditstats.all, ctx->myauditstats.truncated, ctx->myauditstats.lost);
112 }
113
114 static void *
115 create_interface(void)
116 {
117     struct sysvmq_context *ctx;
118
119     ctx = calloc(1, sizeof(*ctx));
120     if (ctx == NULL) {
121         printf("error allocating memory\n");
122         return NULL;
123     }
124     return ctx;
125 }
126
127 static void
128 close_interface(void **rock)
129 {
130     struct sysvmq_context *ctx = *rock;
131     if (ctx == NULL)
132         return;
133
134     free(ctx);
135     *rock = NULL;
136 }
137
138 const struct osi_audit_ops audit_sysvmq_ops = {
139     &send_msg,
140     &open_file,
141     &print_interface_stats,
142     &create_interface,
143     &close_interface,
144     NULL,     /* set_option */
145     NULL,     /* open_interface */
146 };
147
148 #endif /* HAVE_SYS_IPC_H */