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.
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.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
20 * Copyright 2000,2006 The FreeRADIUS server project
21 * Copyright 2000 your name <your address>
24 #include <freeradius-devel/ident.h>
27 #include <freeradius-devel/radiusd.h>
28 #include <freeradius-devel/modules.h>
31 static void cleanup(RADIUS_PACKET *packet)
34 if (packet->sockfd >= 0) close(packet->sockfd);
39 * Write accounting information to this modules database.
41 static int replicate_packet(void *instance, REQUEST *request)
43 int rcode = RLM_MODULE_NOOP;
44 VALUE_PAIR *vp, *last;
48 RADIUS_PACKET *packet = NULL;
50 instance = instance; /* -Wunused */
51 last = request->config_items;
54 * Send as many packets as necessary to different
58 vp = pairfind(last, PW_REPLICATE_TO_REALM);
63 realm = realm_find2(vp->vp_strvalue);
65 RDEBUG2("ERROR: Cannot Replicate to unknown realm %s", realm);
70 * We shouldn't really do this on every loop.
72 switch (request->packet->code) {
74 RDEBUG2("ERROR: Cannot replicate unknown packet code %d",
75 request->packet->code);
77 return RLM_MODULE_FAIL;
79 case PW_AUTHENTICATION_REQUEST:
80 pool = realm->auth_pool;
83 #ifdef WITH_ACCOUNTING
85 case PW_ACCOUNTING_REQUEST:
86 pool = realm->acct_pool;
92 case PW_DISCONNECT_REQUEST:
93 pool = realm->acct_pool;
99 RDEBUG2(" WARNING: Cancelling replication to Realm %s, as the realm is local.", realm->name);
103 home = home_server_ldb(realm->name, pool, request);
105 RDEBUG2("ERROR: Failed to find live home server for realm %s",
111 packet = rad_alloc(1);
112 if (!packet) return RLM_MODULE_FAIL;
114 packet->code = request->packet->code;
115 packet->id = fr_rand() & 0xff;
116 packet->vps = paircopy(request->packet->vps);
118 packet->sockfd = fr_socket(&home->src_ipaddr, 0);
119 if (packet->sockfd < 0) {
120 RDEBUG("ERROR: Failed opening socket: %s", fr_strerror());
122 return RLM_MODULE_FAIL;
127 for (i = 0; i < sizeof(packet->vector); i++) {
128 packet->vector[i] = fr_rand() & 0xff;
134 packet->data_len = 0;
140 packet->dst_ipaddr = home->ipaddr;
141 packet->dst_port = home->port;
142 memset(&packet->src_ipaddr, 0, sizeof(packet->src_ipaddr));
143 packet->src_port = 0;
146 * Encode, sign and then send the packet.
148 RDEBUG("Replicating packet to Realm %s", realm->name);
149 if (rad_send(packet, NULL, home->secret) < 0) {
150 RDEBUG("ERROR: Failed replicating packet: %s",
153 return RLM_MODULE_FAIL;
157 * We've sent it to at least one destination.
159 rcode = RLM_MODULE_OK;
167 * The module name should be the only globally exported symbol.
168 * That is, everything else should be 'static'.
170 * If the module needs to temporarily modify it's instantiation
171 * data, the type should be changed to RLM_TYPE_THREAD_UNSAFE.
172 * The server will then take care of ensuring that the module
173 * is single-threaded.
175 module_t rlm_replicate = {
178 RLM_TYPE_THREAD_SAFE, /* type */
179 NULL, /* instantiation */
182 NULL, /* authentication */
183 replicate_packet, /* authorization */
184 NULL, /* preaccounting */
185 replicate_packet, /* accounting */
186 NULL, /* checksimul */
187 NULL, /* pre-proxy */
188 NULL, /* post-proxy */