c8b8ff79efd7cac7f7b5d14fe8e327a4ed6cb9a1
[freeradius.git] / src / modules / rlm_linelog / rlm_linelog.c
1 /*
2  * rlm_linelog.c
3  *
4  * Version:     $Id$
5  *
6  *   This program is free software; you can redistribute it and/or modify
7  *   it under the terms of the GNU General Public License as published by
8  *   the Free Software Foundation; either version 2 of the License, or
9  *   (at your option) any later version.
10  *
11  *   This program is distributed in the hope that it will be useful,
12  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *   GNU General Public License for more details.
15  *
16  *   You should have received a copy of the GNU General Public License
17  *   along with this program; if not, write to the Free Software
18  *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  *
20  * Copyright 2004  The FreeRADIUS server project
21  * Copyright 2004  Alan DeKok <aland@freeradius.org>
22  */
23
24 #include "autoconf.h"
25
26 #include <stdio.h>
27 #include <stdlib.h>
28
29 #ifdef HAVE_UNISTD_H
30 #include <unistd.h>
31 #endif
32
33 #ifdef HAVE_FCNTL_H
34 #include <fcntl.h>
35 #endif
36
37 #include "radiusd.h"
38 #include "modules.h"
39 #include "conffile.h"
40
41
42 static const char rcsid[] = "$Id$";
43
44 /*
45  *      Define a structure for our module configuration.
46  *
47  *      These variables do not need to be in a structure, but it's
48  *      a lot cleaner to do so, and a pointer to the structure can
49  *      be used as the instance handle.
50  */
51 typedef struct rlm_linelog_t {
52         char            *filename;
53         char            *line;
54 } rlm_linelog_t;
55
56 /*
57  *      A mapping of configuration file names to internal variables.
58  *
59  *      Note that the string is dynamically allocated, so it MUST
60  *      be freed.  When the configuration file parse re-reads the string,
61  *      it free's the old one, and strdup's the new one, placing the pointer
62  *      to the strdup'd string into 'config.string'.  This gets around
63  *      buffer over-flows.
64  */
65 static const CONF_PARSER module_config[] = {
66         { "filename",  PW_TYPE_STRING_PTR,
67           offsetof(rlm_linelog_t,filename), NULL,  NULL},
68         { "format",  PW_TYPE_STRING_PTR,
69           offsetof(rlm_linelog_t,line), NULL,  NULL},
70         { NULL, -1, 0, NULL, NULL }             /* end the list */
71 };
72
73
74 static int linelog_detach(void *instance)
75 {
76         rlm_linelog_t *inst = instance;
77
78         if (inst->filename) free(inst->filename);
79         if (inst->line) free(inst->line);
80         
81         free(inst);
82         return 0;
83 }
84
85 /*
86  *      Instantiate the module.
87  */
88 static int linelog_instantiate(CONF_SECTION *conf, void **instance)
89 {
90         rlm_linelog_t *inst;
91
92         /*
93          *      Set up a storage area for instance data
94          */
95         inst = rad_malloc(sizeof(*inst));
96         memset(inst, 0, sizeof(*inst));
97
98         /*
99          *      If the configuration parameters can't be parsed, then
100          *      fail.
101          */
102         if (cf_section_parse(conf, inst, module_config) < 0) {
103                 linelog_detach(inst);
104                 return -1;
105         }
106
107         *instance = inst;
108
109         return 0;
110 }
111
112 static int do_linelog(rlm_linelog_t *inst, REQUEST *request)
113 {
114         int fd;
115         char *p;
116         char buffer[4096];
117         char line[1024];
118
119         /*
120          *      FIXME: Check length.
121          */
122         radius_xlat(buffer, sizeof(buffer), inst->filename, request, NULL);
123
124         fd = open(buffer, O_WRONLY | O_APPEND | O_CREAT, 0600);
125         if (fd == -1) {
126                 radlog(L_ERR, "rlm_linelog: Failed to open %s: %s",
127                        buffer, strerror(errno));
128                 return RLM_MODULE_FAIL;
129         }
130
131         /*
132          *      FIXME: Check length.
133          */
134         radius_xlat(line, sizeof(line) - 1, inst->line, request, NULL);
135
136         p = strchr(line, '\n');
137         if (!p) strcat(line, "\n");
138         
139         write(fd, line, strlen(line));
140         close(fd);
141
142         return RLM_MODULE_OK;
143 }
144
145
146 /*
147  *      Externally visible module definition.
148  */
149 module_t rlm_linelog = {
150         "example",
151         RLM_TYPE_THREAD_SAFE,           /* type */
152         NULL,                           /* initialization */
153         linelog_instantiate,            /* instantiation */
154         {
155                 do_linelog,     /* authentication */
156                 do_linelog,     /* authorization */
157                 do_linelog,     /* preaccounting */
158                 do_linelog,     /* accounting */
159                 NULL,                   /* checksimul */
160                 do_linelog,     /* pre-proxy */
161                 do_linelog,     /* post-proxy */
162                 do_linelog      /* post-auth */
163         },
164         linelog_detach,                 /* detach */
165         NULL,                           /* destroy */
166 };