Many modules have been updated to be able to process CoA packets.
The server core has been updated to process CoA packets. However,
it does not yet actually listen on a CoA port.
mod_accounting = radiusd_test
func_accounting = accounting
- mod_preproxy = radiusd_test
- func_preproxy = preproxy
+ mod_pre_proxy = radiusd_test
+ func_pre_proxy = pre_proxy
- mod_postproxy = radiusd_test
- func_postproxy = postproxy
+ mod_post_proxy = radiusd_test
+ func_post_proxy = post_proxy
- mod_postauth = radiusd_test
- func_postauth = postauth
+ mod_post_auth = radiusd_test
+ func_post_auth = post_auth
+
+ mod_recv_coa = radiusd_test
+ func_recv_coa = recv_coa
+
+ mod_send_coa = radiusd_test
+ func_send_coa = send_coa
mod_detach = radiusd_test
func_detach = detach
#func_pre_proxy = pre_proxy
#func_post_proxy = post_proxy
#func_post_auth = post_auth
+ #func_recv_coa = recv_coa
+ #func_send_coa = send_coa
#func_xlat = xlat
#func_detach = detach
# raddb/sites-available/copy-acct-to-home-server
# status listen for Status-Server packets. For examples,
# see raddb/sites-available/status
+ # coa listen for CoA-Request and Disconnect-Request
+ # packets. For examples, see the file
+ # raddb/sites-available/coa-server
#
type = auth
home_server_pool coa {
type = fail-over
- # Point to the CoA server aboce.
+ # Point to the CoA server above.
home_server = localhost-coa
# CoA requests are run through the pre-proxy section.
ATTRIBUTE EAP-EMSK 1130 octets
#
+# For send/recv CoA packets (like Auth-Type, Acct-Type, etc.)
+#
+ATTRIBUTE Recv-CoA-Type 1131 integer
+ATTRIBUTE Send-CoA-Type 1132 integer
+
+#
# Range: 1200-1279
# EAP-SIM (and other EAP type) weirdness.
#
RLM_COMPONENT_PRE_PROXY, /* 5 */
RLM_COMPONENT_POST_PROXY, /* 6 */
RLM_COMPONENT_POST_AUTH, /* 7 */
- RLM_COMPONENT_COUNT /* 8: How many components are there */
+#ifdef WITH_COA
+ RLM_COMPONENT_RECV_COA, /* 8 */
+ RLM_COMPONENT_SEND_COA, /* 9 */
+#endif
+ RLM_COMPONENT_COUNT /* 8 / 10: How many components are there */
};
#define RLM_TYPE_THREAD_SAFE (0 << 0)
int module_pre_proxy(int type, REQUEST *request);
int module_post_proxy(int type, REQUEST *request);
int module_post_auth(int type, REQUEST *request);
+#ifdef WITH_COA
+int module_recv_coa(int type, REQUEST *request);
+int module_send_coa(int type, REQUEST *request);
+#define MODULE_NULL_COA_FUNCS ,NULL,NULL
+#else
+#define MODULE_NULL_COA_FUNCS
+#endif
int indexed_modcall(int comp, int idx, REQUEST *request);
/*
#define PW_MODULE_RETURN_CODE 1108
#define PW_PACKET_ORIGINAL_TIMESTAMP 1109
#define PW_HOME_SERVER_POOL 1111
+#define PW_RECV_COA_TYPE 1131
+#define PW_SEND_COA_TYPE 1132
/*
* Integer Translations
RLM_MODULE_FAIL, /* SESS */
RLM_MODULE_NOOP, /* PRE_PROXY */
RLM_MODULE_NOOP, /* POST_PROXY */
- RLM_MODULE_NOOP /* POST_AUTH */
+ RLM_MODULE_NOOP /* POST_AUTH */
+#ifdef WITH_COA
+ ,
+ RLM_MODULE_NOOP, /* RECV_COA_TYPE */
+ RLM_MODULE_NOOP /* SEND_COA_TYPE */
+#endif
};
MOD_ACTION_RETURN /* updated */
}
}
+#ifdef WITH_COA
+ ,
+ /* recv-coa */
+ {
+ /* group */
+ {
+ MOD_ACTION_RETURN, /* reject */
+ MOD_ACTION_RETURN, /* fail */
+ 3, /* ok */
+ MOD_ACTION_RETURN, /* handled */
+ MOD_ACTION_RETURN, /* invalid */
+ MOD_ACTION_RETURN, /* userlock */
+ 1, /* notfound */
+ 2, /* noop */
+ 4 /* updated */
+ },
+ /* redundant */
+ {
+ MOD_ACTION_RETURN, /* reject */
+ 1, /* fail */
+ MOD_ACTION_RETURN, /* ok */
+ MOD_ACTION_RETURN, /* handled */
+ MOD_ACTION_RETURN, /* invalid */
+ MOD_ACTION_RETURN, /* userlock */
+ MOD_ACTION_RETURN, /* notfound */
+ MOD_ACTION_RETURN, /* noop */
+ MOD_ACTION_RETURN /* updated */
+ },
+ /* append */
+ {
+ MOD_ACTION_RETURN, /* reject */
+ 1, /* fail */
+ MOD_ACTION_RETURN, /* ok */
+ MOD_ACTION_RETURN, /* handled */
+ MOD_ACTION_RETURN, /* invalid */
+ MOD_ACTION_RETURN, /* userlock */
+ 2, /* notfound */
+ MOD_ACTION_RETURN, /* noop */
+ MOD_ACTION_RETURN /* updated */
+ }
+ },
+ /* send-coa */
+ {
+ /* group */
+ {
+ MOD_ACTION_RETURN, /* reject */
+ MOD_ACTION_RETURN, /* fail */
+ 3, /* ok */
+ MOD_ACTION_RETURN, /* handled */
+ MOD_ACTION_RETURN, /* invalid */
+ MOD_ACTION_RETURN, /* userlock */
+ 1, /* notfound */
+ 2, /* noop */
+ 4 /* updated */
+ },
+ /* redundant */
+ {
+ MOD_ACTION_RETURN, /* reject */
+ 1, /* fail */
+ MOD_ACTION_RETURN, /* ok */
+ MOD_ACTION_RETURN, /* handled */
+ MOD_ACTION_RETURN, /* invalid */
+ MOD_ACTION_RETURN, /* userlock */
+ MOD_ACTION_RETURN, /* notfound */
+ MOD_ACTION_RETURN, /* noop */
+ MOD_ACTION_RETURN /* updated */
+ },
+ /* append */
+ {
+ MOD_ACTION_RETURN, /* reject */
+ 1, /* fail */
+ MOD_ACTION_RETURN, /* ok */
+ MOD_ACTION_RETURN, /* handled */
+ MOD_ACTION_RETURN, /* invalid */
+ MOD_ACTION_RETURN, /* userlock */
+ 2, /* notfound */
+ MOD_ACTION_RETURN, /* noop */
+ MOD_ACTION_RETURN /* updated */
+ }
+ }
+#endif
};
{ "session", "Session-Type", PW_SESSION_TYPE },
{ "pre-proxy", "Pre-Proxy-Type", PW_PRE_PROXY_TYPE },
{ "post-proxy", "Post-Proxy-Type", PW_POST_PROXY_TYPE },
- { "post-auth", "Post-Auth-Type", PW_POST_AUTH_TYPE },
+ { "post-auth", "Post-Auth-Type", PW_POST_AUTH_TYPE }
+#ifdef WITH_COA
+ ,
+ { "recv-coa", "Recv-CoA-Type", PW_RECV_COA_TYPE },
+ { "send-coa", "Send-CoA-Type", PW_SEND_COA_TYPE }
+#endif
};
{
return indexed_modcall(RLM_COMPONENT_POST_AUTH, postauth_type, request);
}
+
+#ifdef WITH_COA
+int module_recv_coa(int recv_coa_type, REQUEST *request)
+{
+ return indexed_modcall(RLM_COMPONENT_RECV_COA, recv_coa_type, request);
+}
+
+int module_send_coa(int send_coa_type, REQUEST *request)
+{
+ return indexed_modcall(RLM_COMPONENT_SEND_COA, send_coa_type, request);
+}
+#endif
packet_code = PW_STATUS_SERVER;
} else if (strcmp(argv[2], "disconnect") == 0) {
- if (server_port == 0) server_port = PW_POD_UDP_PORT;
+ if (server_port == 0) server_port = PW_COA_UDP_PORT;
packet_code = PW_DISCONNECT_REQUEST;
} else if (strcmp(argv[2], "coa") == 0) {
- if (server_port == 0) server_port = PW_POD_UDP_PORT;
+ if (server_port == 0) server_port = PW_COA_UDP_PORT;
packet_code = PW_COA_REQUEST;
} else if (strcmp(argv[2], "auto") == 0) {
{
if (!request || request->coa) return NULL;
+ /*
+ * Originate CoA requests only when necessary.
+ */
+ if ((request->packet->code != PW_AUTHENTICATION_REQUEST) &&
+ (request->packet->code != PW_ACCOUNTING_REQUEST)) return NULL;
+
request->coa = request_alloc_fake(request);
request->coa->packet->code = 0; /* unknown, as of yet */
request->coa->child_state = REQUEST_RUNNING;
always_return, /* pre-proxy */
always_return, /* post-proxy */
always_return /* post-auth */
+#ifdef WITH_COA
+ ,
+ always_return, /* recv-coa */
+ always_return /* send-coa */
+#endif
},
};
"Password-Reject",
"Accounting-Message",
"Access-Challenge"
+ "Status-Server",
+ "Status-Client",
+ "14",
+ "15",
+ "16",
+ "17",
+ "18",
+ "19",
+ "20",
+ "Resource-Free-Request",
+ "Resource-Free-Response",
+ "Resource-Query-Request",
+ "Resource-Query-Response",
+ "Alternate-Resource-Reclaim-Request",
+ "NAS-Reboot-Request",
+ "NAS-Reboot-Response",
+ "28",
+ "Next-Passcode",
+ "New-Pin",
+ "Terminate-Session",
+ "Password-Expired",
+ "Event-Request",
+ "Event-Response",
+ "35",
+ "36",
+ "37",
+ "38",
+ "39",
+ "Disconnect-Request",
+ "Disconnect-ACK",
+ "Disconnect-NAK",
+ "CoA-Request",
+ "CoA-ACK",
+ "CoA-NAK",
+ "46",
+ "47",
+ "48",
+ "49",
+ "IP-Address-Allocate",
+ "IP-Address-Release"
};
* Numbers, if not.
*/
if ((packet->code > 0) &&
- (packet->code <= PW_ACCESS_CHALLENGE)) {
+ (packet->code < 52)) {
fprintf(outfp, "\tPacket-Type = %s\n",
packet_codes[packet->code]);
} else {
return do_detail(instance,request,request->reply, FALSE);
}
+#ifdef WITH_COA
+/*
+ * Incoming CoA - write the detail files.
+ */
+static int detail_recv_coa(void *instance, REQUEST *request)
+{
+ return do_detail(instance,request,request->packet, FALSE);
+}
+
+/*
+ * Outgoing CoA - write the detail files.
+ */
+static int detail_send_coa(void *instance, REQUEST *request)
+{
+ return do_detail(instance,request,request->reply, FALSE);
+}
+#endif
/*
* Outgoing Access-Request to home server - write the detail files.
detail_pre_proxy, /* pre-proxy */
detail_post_proxy, /* post-proxy */
detail_postauth /* post-auth */
+#ifdef WITH_COA
+ , detail_recv_coa,
+ detail_send_coa
+#endif
},
};
static const int JRADIUS_pre_proxy = 6;
static const int JRADIUS_post_proxy = 7;
static const int JRADIUS_post_auth = 8;
+#ifdef WITH_COA
+static const int JRADIUS_recv_coa = 9;
+static const int JRADIUS_send_coa = 10;
+#endif
#define LOG_PREFIX "rlm_jradius: "
#define MAX_HOSTS 4
return rlm_jradius_call(JRADIUS_post_auth, instance, request, 0);
}
+#ifdef WITH_COA
+static int jradius_recv_coa(void *instance, REQUEST *request)
+{
+ return rlm_jradius_call(JRADIUS_recv_coa, instance, request, 0);
+}
+static int jradius_send_coa(void *instance, REQUEST *request)
+{
+ return rlm_jradius_call(JRADIUS_send_coa, instance, request, 0);
+}
+#endif
+
static int jradius_detach(void *instance)
{
JRADIUS *inst = (JRADIUS *) instance;
jradius_pre_proxy,
jradius_post_proxy,
jradius_post_auth
+#ifdef WITH_COA
+ , jradius_recv_coa,
+ jradius_send_coa
+#endif
},
};
do_linelog, /* pre-proxy */
do_linelog, /* post-proxy */
do_linelog /* post-auth */
+#ifdef WITH_COA
+ , do_linelog, /* recv-coa */
+ do_linelog /* send-coa */
+#endif
},
};
char *func_pre_proxy;
char *func_post_proxy;
char *func_post_auth;
+#ifdef WITH_COA
+ char *func_recv_coa;
+ char *func_send_coa;
+#endif
char *xlat_name;
char *perl_flags;
PerlInterpreter *perl;
offsetof(PERL_INST,func_post_proxy), NULL, "post_proxy"},
{ "func_post_auth", PW_TYPE_STRING_PTR,
offsetof(PERL_INST,func_post_auth), NULL, "post_auth"},
+#ifdef WITH_COA
+ { "func_recv_coa", PW_TYPE_STRING_PTR,
+ offsetof(PERL_INST,func_recv_coa), NULL, "recv_coa"},
+ { "func_send_coa", PW_TYPE_STRING_PTR,
+ offsetof(PERL_INST,func_send_coa), NULL, "send_coa"},
+#endif
{ "perl_flags", PW_TYPE_STRING_PTR,
offsetof(PERL_INST,perl_flags), NULL, NULL},
{ "func_start_accounting", PW_TYPE_STRING_PTR,
return rlmperl_call(instance, request,
((PERL_INST *)instance)->func_post_auth);
}
+#ifdef WITH_COA
+/*
+ * Recv CoA request
+ */
+static int perl_recv_coa(void *instance, REQUEST *request)
+{
+ return rlmperl_call(instance, request,
+ ((PERL_INST *)instance)->func_recv_coa);
+}
+/*
+ * Send CoA request
+ */
+static int perl_send_coa(void *instance, REQUEST *request)
+{
+ return rlmperl_call(instance, request,
+ ((PERL_INST *)instance)->func_send_coa);
+}
+#endif
/*
* Detach a instance give a chance to a module to make some internal setup ...
*/
perl_pre_proxy, /* pre-proxy */
perl_post_proxy, /* post-proxy */
perl_post_auth /* post-auth */
+#ifdef WITH_COA
+ , perl_recv_coa,
+ perl_send_coa
+#endif
},
};
{ "pre-proxy", RLM_COMPONENT_PRE_PROXY },
{ "post-proxy", RLM_COMPONENT_POST_PROXY },
{ "post-auth", RLM_COMPONENT_POST_AUTH },
+#ifdef WITH_COA
+ { "recv-coa", RLM_COMPONENT_RECV_COA },
+ { "send-coa", RLM_COMPONENT_SEND_COA },
+#endif
{ NULL, RLM_COMPONENT_COUNT }
};
"post-proxy");
}
+#ifdef WITH_COA
+static int policy_recv_coa(void *instance, REQUEST *request)
+{
+ return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+ "recv-coa");
+}
+static int policy_send_coa(void *instance, REQUEST *request)
+{
+ return rlm_policy_evaluate((rlm_policy_t *) instance, request,
+ "send-coa");
+}
+#endif
+
/*
* The "free" functions are here, for no particular reason.
*/
policy_pre_proxy, /* pre-proxy */
policy_post_proxy, /* post-proxy */
policy_post_auth /* post-auth */
+#ifdef WITH_COA
+ , policy_recv_coa,
+ policy_send_coa
+#endif
},
};
print p
return radiusd.RLM_MODULE_OK
-def preproxy(p):
- print "*** preproxy ***"
+def pre_proxy(p):
+ print "*** pre_proxy ***"
print p
return radiusd.RLM_MODULE_OK
-def postproxy(p):
- print "*** postproxy ***"
+def post_proxy(p):
+ print "*** post_proxy ***"
print p
return radiusd.RLM_MODULE_OK
-def postauth(p):
- print "*** postauth ***"
+def post_auth(p):
+ print "*** post_auth ***"
+ print p
+ return radiusd.RLM_MODULE_OK
+
+def recv_coa(p):
+ print "*** recv_coa ***"
+ print p
+ return radiusd.RLM_MODULE_OK
+
+def send_coa(p):
+ print "*** send_coa ***"
print p
return radiusd.RLM_MODULE_OK
preacct,
accounting,
checksimul,
+ pre_proxy,
+ post_proxy,
+ post_auth,
+#ifdef WITH_COA
+ recv_coa,
+ send_coa,
+#endif
detach;
};
A(preacct)
A(accounting)
A(checksimul)
+ A(pre_proxy)
+ A(post_proxy)
+ A(post_auth)
+#ifdef WITH_COA
+ A(recv_coa)
+ A(send_coa)
+#endif
A(detach)
#undef A
A(preacct);
A(accounting);
A(checksimul);
+ A(pre_proxy);
+ A(post_proxy);
+ A(post_auth);
+#ifdef WITH_COA
+ A(recv_coa);
+ A(send_coa);
+#endif
A(detach);
#undef A
A(preacct)
A(accounting)
A(checksimul)
+A(pre_proxy)
+A(post_proxy)
+A(post_auth)
+#ifdef WITH_COA
+A(recv_coa)
+A(send_coa)
+#endif
#undef A
python_preacct, /* preaccounting */
python_accounting, /* accounting */
python_checksimul, /* checksimul */
- NULL, /* pre-proxy */
- NULL, /* post-proxy */
- NULL /* post-auth */
+ python_pre_proxy, /* pre-proxy */
+ python_post_proxy, /* post-proxy */
+ python_post_auth /* post-auth */
+#ifdef WITH_COA
+ , python_recv_coa,
+ python_send_coa
+#endif
}
};
RLM_RUBY_STRUCT(preproxy);
RLM_RUBY_STRUCT(postproxy);
RLM_RUBY_STRUCT(postauth);
+#ifdef WITH_COA
+ RLM_RUBY_STRUCT(recvcoa);
+ RLM_RUBY_STRUCT(sendcoa);
+#endif
RLM_RUBY_STRUCT(detach);
char *scriptFile;
RLM_RUBY_LOAD(preproxy);
RLM_RUBY_LOAD(postproxy);
RLM_RUBY_LOAD(postauth);
+#ifdef WITH_COA
+ RLM_RUBY_LOAD(recvcoa);
+ RLM_RUBY_LOAD(sendcoa);
+#endif
RLM_RUBY_LOAD(detach);
*instance = data;
RLM_RUBY_FUNC(preproxy)
RLM_RUBY_FUNC(postproxy)
RLM_RUBY_FUNC(postauth)
+#ifdef WITH_COA
+RLM_RUBY_FUNC(recvcoa)
+RLM_RUBY_FUNC(sendcoa)
+#endif
static int ruby_detach(void *instance) {
int return_value;
ruby_preproxy, /* pre-proxy */
ruby_postproxy, /* post-proxy */
ruby_postauth /* post-auth */
+#ifdef WITH_COA
+ , ruby_recv_coa,
+ ruby_send_coa
+#endif
},
};