audit: Support multiple audit interfaces and interface options
[openafs.git] / src / audit / audit-sysvmq.c
index 6004c16..4acd347 100644 (file)
 
 #include "audit-api.h"
 
-/* solaris default is 2048 */
-#define MAXMSG 2048
-
 /* message queue size will be increased to this value
    if not already bigger */
 #define MSGMNB (2*1024*1024)
 
-static struct my_msgbuf {
+/* msgsnd requires a structure with the following layout. See manpage for
+ * msgsnd() for the details */
+struct my_msgbuf {
     long mtype;
-    char mtext[MAXMSG];
-} msgbuffer;
-
-static int mqid;
+    char mtext[OSI_AUDIT_MAXMSG];
+};
 
-static struct mqaudit_stats {
+struct mqaudit_stats {
     long all;
     long truncated;
     long lost;
-} myauditstats;
-
-static int truncated;
+};
 
-static void
-send_msg(void)
-{
-    /* +1 to send the trailing '\0' in the message too so the
-       receiver doesn't need to bother with it */
-    if (msgsnd(mqid, &msgbuffer, strlen(msgbuffer.mtext)+1, IPC_NOWAIT) == -1) {
-        myauditstats.lost++;
-    } else if (truncated) {
-        myauditstats.truncated++;
-    }
-    myauditstats.all++;
-    msgbuffer.mtext[0] = 0;
-    truncated = 0;
-}
+struct sysvmq_context {
+    int mqid;
+    struct my_msgbuf msgbuffer;
+    struct mqaudit_stats myauditstats;
+};
 
 static void
-append_msg(const char *format, ...)
+send_msg(void *rock, const char *message, int msglen, int truncated)
 {
-    va_list vaList;
-    int size, printed;
+    struct sysvmq_context *ctx = rock;
 
-    size = MAXMSG - strlen(msgbuffer.mtext);
+    if (msglen >= OSI_AUDIT_MAXMSG) {
+       truncated = 1;
+       msglen = OSI_AUDIT_MAXMSG - 1;
+    }
 
-    va_start(vaList, format);
-    printed = vsnprintf(&msgbuffer.mtext[strlen(msgbuffer.mtext)], size, format, vaList);
-    va_end(vaList);
+    /* Copy the data into the msgsnd structure */
+    memcpy(&ctx->msgbuffer.mtext, message, msglen+1);
+    ctx->msgbuffer.mtext[msglen] = '\0';
 
-    /* A return value of size or more means that the output was truncated.
-       If an output error is encountered, a negative value is returned. */
-    if (size <= printed || printed == -1) {
-        truncated = 1;
+    /* Include the trailing zero in the msgsnd */
+    if (msgsnd(ctx->mqid, &ctx->msgbuffer, msglen+1, IPC_NOWAIT) == -1) {
+       ctx->myauditstats.lost++;
+    } else if (truncated) {
+       ctx->myauditstats.truncated++;
     }
+    ctx->myauditstats.all++;
 }
 
 static int
-open_file(const char *fileName)
+open_file(void *rock, const char *fileName)
 {
+    struct sysvmq_context *ctx = rock;
     int tempfd;
     struct msqid_ds msqdesc;
 
-    msgbuffer.mtext[0] = 0;
-    msgbuffer.mtype = 1;
+    ctx->msgbuffer.mtext[0] = 0;
+    ctx->msgbuffer.mtype = 1;
 
-    truncated = 0;
-    myauditstats.all = 0;
-    myauditstats.lost = 0;
-    myauditstats.truncated = 0;
+    ctx->myauditstats.all = 0;
+    ctx->myauditstats.lost = 0;
+    ctx->myauditstats.truncated = 0;
 
     /* try to create file for ftok if it doesn't already exist */
     tempfd = open(fileName, O_WRONLY | O_CREAT | O_EXCL, S_IRUSR | S_IWUSR);
     if(tempfd != -1)
         close(tempfd);
 
-    mqid = msgget(ftok(fileName, 1), S_IRUSR | S_IWUSR | IPC_CREAT);
-    if (mqid == -1) {
+    ctx->mqid = msgget(ftok(fileName, 1), S_IRUSR | S_IWUSR | IPC_CREAT);
+    if (ctx->mqid == -1) {
         printf("Warning: auditlog message queue %s cannot be opened.\n", fileName);
         return 1;
     }
 
     /* increase message queue size */
-    msgctl(mqid, IPC_STAT, &msqdesc);
+    msgctl(ctx->mqid, IPC_STAT, &msqdesc);
     if (msqdesc.msg_qbytes < MSGMNB) {
         msqdesc.msg_qbytes = MSGMNB;
-        msgctl(mqid, IPC_SET, &msqdesc);
+       msgctl(ctx->mqid, IPC_SET, &msqdesc);
     }
 
     return 0;
 }
 
 static void
-print_interface_stats(FILE *out)
+print_interface_stats(void *rock, FILE *out)
 {
+    struct sysvmq_context *ctx = rock;
+
     fprintf(out, "audit statistics: %ld messages total, %ld truncated, %ld lost\n",
-        myauditstats.all, myauditstats.truncated, myauditstats.lost);
+       ctx->myauditstats.all, ctx->myauditstats.truncated, ctx->myauditstats.lost);
+}
+
+static void *
+create_interface(void)
+{
+    struct sysvmq_context *ctx;
+
+    ctx = calloc(1, sizeof(*ctx));
+    if (ctx == NULL) {
+       printf("error allocating memory\n");
+       return NULL;
+    }
+    return ctx;
+}
+
+static void
+close_interface(void **rock)
+{
+    struct sysvmq_context *ctx = *rock;
+    if (ctx == NULL)
+       return;
+
+    free(ctx);
+    *rock = NULL;
 }
 
 const struct osi_audit_ops audit_sysvmq_ops = {
     &send_msg,
-    &append_msg,
     &open_file,
     &print_interface_stats,
+    &create_interface,
+    &close_interface,
+    NULL,     /* set_option */
+    NULL,     /* open_interface */
 };
 
 #endif /* HAVE_SYS_IPC_H */