00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063 #include <unistd.h>
00064 #include <string.h>
00065
00066 #include "gwlib/gwlib.h"
00067 #include "radius/radius_pdu.h"
00068
00069
00070
00071
00072
00073
00074
00075 static int update_table(RADIUS_PDU *pdu, Dict **table)
00076 {
00077 Octstr *client_ip, *msisdn;
00078 Octstr *type;
00079 int ret = 0;
00080
00081 client_ip = msisdn = NULL;
00082
00083
00084 if (pdu->type == 0x04) {
00085
00086
00087 type = dict_get(pdu->attr, octstr_imm("Acct-Status-Type"));
00088
00089
00090 client_ip = dict_get(pdu->attr, octstr_imm("Framed-IP-Address"));
00091 msisdn = dict_get(pdu->attr, octstr_imm("Calling-Station-Id"));
00092
00093 if (octstr_compare(type, octstr_imm("1")) == 0) {
00094
00095 if (dict_get(*table, client_ip) == NULL) {
00096 dict_put(*table, client_ip, msisdn);
00097 info(0, "RADIUS: Mapping `%s <-> %s' added.",
00098 octstr_get_cstr(client_ip), octstr_get_cstr(msisdn));
00099 ret = 1;
00100 } else {
00101 warning(0, "RADIUS: Duplicate mapping for `%s <-> %s' received",
00102 octstr_get_cstr(client_ip), octstr_get_cstr(msisdn));
00103 }
00104 }
00105 else if (octstr_compare(type, octstr_imm("2")) == 0) {
00106
00107 msisdn = dict_get(*table, client_ip);
00108 dict_remove(*table, client_ip);
00109 }
00110 else {
00111 error(0, "RADIUS: unknown Acct-Status-Type `%s' received.",
00112 octstr_get_cstr(type));
00113 }
00114 }
00115
00116 octstr_destroy(client_ip);
00117 octstr_destroy(msisdn);
00118
00119 return ret;
00120 }
00121
00122 static void server(int lport, int pport)
00123 {
00124 int i;
00125 int ss, cs;
00126 Octstr *data, *from, *addr;
00127
00128 Dict *radius_table;
00129
00130
00131 cs = udp_client_socket();
00132 addr = udp_create_address(octstr_create("localhost"), pport);
00133
00134
00135 ss = udp_bind(lport, "0.0.0.0");
00136 if (ss == -1)
00137 panic(0, "Couldn't set up server socket for port %d.", lport);
00138
00139
00140 radius_table = dict_create(30, (void (*)(void *))octstr_destroy);
00141
00142 i = 1;
00143 while (1) {
00144 RADIUS_PDU *pdu, *r;
00145 Octstr *rdata;
00146 int forward = 0;
00147
00148
00149 if (udp_recvfrom(ss, &data, &from) == -1)
00150 panic(0, "Couldn't receive request data from NAS");
00151 info(0, "Got data from NAS <%s:%d>",
00152 octstr_get_cstr(udp_get_ip(from)), udp_get_port(from));
00153
00154
00155
00156
00157
00158
00159
00160
00161 pdu = radius_pdu_unpack(data);
00162 info(0, "PDU type: %s", pdu->type_name);
00163
00164
00165
00166
00167
00168 forward = update_table(pdu, &radius_table);
00169
00170
00171 r = radius_pdu_create(0x05, pdu);
00172
00173
00174
00175
00176
00177 r->u.Accounting_Response.identifier = pdu->u.Accounting_Request.identifier;
00178 r->u.Accounting_Response.authenticator =
00179 octstr_duplicate(pdu->u.Accounting_Request.authenticator);
00180
00181 rdata = radius_pdu_pack(r);
00182
00183
00184 radius_authenticate_pdu(r, &rdata, octstr_imm("radius"));
00185
00186
00187 if (forward) {
00188 if (udp_sendto(cs, data, addr) == -1)
00189 panic(0, "Couldn't send to remote RADIUS.");
00190 if (udp_recvfrom(cs, &data, &from) == -1)
00191 panic(0, "Couldn't receive from remote RADIUS.");
00192 info(0, "Got data from remote RADIUS <%s:%d>",
00193 octstr_get_cstr(udp_get_ip(from)), udp_get_port(from));
00194 }
00195
00196
00197 if (udp_sendto(ss, rdata, from) == -1)
00198 panic(0, "Couldn't send response data to NAS.");
00199
00200 radius_pdu_destroy(pdu);
00201 radius_pdu_destroy(r);
00202
00203 octstr_destroy(rdata);
00204 i++;
00205
00206 debug("",0,"Mapping table contains %ld elements",
00207 dict_key_count(radius_table));
00208 }
00209 }
00210
00211 int main(int argc, char **argv) {
00212 int lport, pport;
00213
00214 gwlib_init();
00215
00216 if (argc != 3)
00217 panic(0, "usage: test_radius_acct <your RADIUS acct port> <remote RADIUS port>");
00218
00219 lport = atoi(argv[1]);
00220 pport = atoi(argv[2]);
00221
00222 server(lport, pport);
00223
00224 return 0;
00225 }
See file LICENSE for details about the license agreement for using,
modifying, copying or deriving work from this software.