Kannel: Open Source WAP and SMS gateway  $Revision: 5037 $
radius_acct.c File Reference
#include <string.h>
#include <fcntl.h>
#include <errno.h>
#include "gwlib/gwlib.h"
#include "radius/radius_acct.h"
#include "radius/radius_pdu.h"

Go to the source code of this file.

Macros

#define RADIUS_NAS_PORTS   30
 

Functions

static int update_tables (RADIUS_PDU *pdu)
 
static void proxy_thread (void *arg)
 
Octstrradius_acct_get_msisdn (Octstr *client_ip)
 
void radius_acct_init (CfgGroup *grp)
 
void radius_acct_shutdown (void)
 

Variables

static Dictradius_table = NULL
 
static Dictsession_table = NULL
 
static Dictclient_table = NULL
 
static Mutexradius_mutex = NULL
 
static int run_thread = 0
 
static Octstrour_host = NULL
 
static long our_port = 1813
 
static Octstrremote_host = NULL
 
static long remote_port = 1813
 
static Octstrsecret_nas = NULL
 
static Octstrsecret_radius = NULL
 
static Octstrunified_prefix = NULL
 
static long remote_timeout = 40000
 

Macro Definition Documentation

#define RADIUS_NAS_PORTS   30

Definition at line 76 of file radius_acct.c.

Referenced by radius_acct_init().

Function Documentation

static void proxy_thread ( void *  arg)
static

Definition at line 215 of file radius_acct.c.

References debug(), dict_key_count(), error(), info(), mutex_lock, mutex_unlock, octstr_destroy(), octstr_dump, octstr_duplicate, octstr_get_cstr, our_port, panic, radius_authenticate_pdu(), radius_pdu_create(), radius_pdu_destroy(), radius_pdu_pack(), radius_pdu_unpack(), read_available(), remote_port, remote_timeout, run_thread, RADIUS_PDU::type_name, RADIUS_PDU::u, udp_bind(), udp_client_socket(), udp_create_address(), udp_get_ip(), udp_get_port(), udp_recvfrom(), udp_sendto(), update_tables(), and warning().

Referenced by radius_acct_init(), and radius_acct_shutdown().

216 {
217  int ss, cs; /* server and client sockets */
218  int fl; /* socket flags */
219  Octstr *addr = NULL;
220  int forward;
221  Octstr *tmp;
222 
223  run_thread = 1;
224  ss = cs = -1;
225 
226  /* create client binding, only if we have a remote server
227  * and make the client socet non-blocking */
228  if (remote_host != NULL) {
229  cs = udp_client_socket();
230  fl = fcntl(cs, F_GETFL);
231  fcntl(cs, F_SETFL, fl | O_NONBLOCK);
233  }
234 
235  /* create server binding */
237 
238  /* make the server socket non-blocking */
239  fl = fcntl(ss, F_GETFL);
240  fcntl(ss, F_SETFL, fl | O_NONBLOCK);
241 
242  if (ss == -1)
243  panic(0, "RADIUS: Couldn't set up server socket for port %ld.", our_port);
244 
245  while (run_thread) {
246  RADIUS_PDU *pdu, *r;
247  Octstr *data, *rdata;
248  Octstr *from_nas, *from_radius;
249 
250  pdu = r = NULL;
251  data = rdata = from_nas = from_radius = NULL;
252 
253  if (read_available(ss, 100000) < 1)
254  continue;
255 
256  /* get request from NAS */
257  if (udp_recvfrom(ss, &data, &from_nas) == -1) {
258  if (errno == EAGAIN)
259  /* No datagram available, don't block. */
260  continue;
261 
262  error(0, "RADIUS: Couldn't receive request data from NAS");
263  continue;
264  }
265 
266  tmp = udp_get_ip(from_nas);
267  info(0, "RADIUS: Got data from NAS <%s:%d>",
268  octstr_get_cstr(tmp), udp_get_port(from_nas));
269  octstr_destroy(tmp);
270  octstr_dump(data, 0);
271 
272  /* unpacking the RADIUS PDU */
273  if ((pdu = radius_pdu_unpack(data)) == NULL) {
274  warning(0, "RADIUS: Couldn't unpack PDU from NAS, ignoring.");
275  goto error;
276  }
277  info(0, "RADIUS: from NAS: PDU type: %s", pdu->type_name);
278 
279  /* authenticate the Accounting-Request packet */
280  if (radius_authenticate_pdu(pdu, &data, secret_nas) == 0) {
281  warning(0, "RADIUS: Authentication failed for PDU from NAS, ignoring.");
282  goto error;
283  }
284 
285  /* store to hash table if not present yet */
287  forward = update_tables(pdu);
289 
290  /* create response PDU for NAS */
291  r = radius_pdu_create(0x05, pdu);
292 
293  /*
294  * create response authenticator
295  * code+identifier(req)+length+authenticator(req)+(attributes)+secret
296  */
297  r->u.Accounting_Response.identifier = pdu->u.Accounting_Request.identifier;
298  r->u.Accounting_Response.authenticator =
299  octstr_duplicate(pdu->u.Accounting_Request.authenticator);
300 
301  /* pack response for NAS */
302  rdata = radius_pdu_pack(r);
303 
304  /* creates response autenticator in encoded PDU */
306 
307  /*
308  * forward request to remote RADIUS server only if updated
309  * and if we have a configured remote RADIUS server
310  */
311  if ((remote_host != NULL) && forward) {
312  if (udp_sendto(cs, data, addr) == -1) {
313  error(0, "RADIUS: Couldn't send to remote RADIUS <%s:%ld>.",
315  } else
316  if (read_available(cs, remote_timeout) < 1) {
317  error(0, "RADIUS: Timeout for response from remote RADIUS <%s:%ld>.",
319  } else
320  if (udp_recvfrom(cs, &data, &from_radius) == -1) {
321  error(0, "RADIUS: Couldn't receive from remote RADIUS <%s:%ld>.",
323  } else {
324  info(0, "RADIUS: Got data from remote RADIUS <%s:%d>.",
325  octstr_get_cstr(udp_get_ip(from_radius)), udp_get_port(from_radius));
326  octstr_dump(data, 0);
327 
328  /* XXX unpack the response PDU and check if the response
329  * authenticator is valid */
330  }
331  }
332 
333  /* send response to NAS */
334  if (udp_sendto(ss, rdata, from_nas) == -1)
335  error(0, "RADIUS: Couldn't send response data to NAS <%s:%d>.",
336  octstr_get_cstr(udp_get_ip(from_nas)), udp_get_port(from_nas));
337 
338 error:
339  radius_pdu_destroy(pdu);
341 
342  octstr_destroy(rdata);
343  octstr_destroy(data);
344  octstr_destroy(from_nas);
345 
346  debug("radius.proxy", 0, "RADIUS: Mapping table contains %ld elements",
348  debug("radius.proxy", 0, "RADIUS: Session table contains %ld elements",
350  debug("radius.proxy", 0, "RADIUS: Client table contains %ld elements",
352 
353  }
354 
355  octstr_destroy(addr);
356 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
static long our_port
Definition: radius_acct.c:87
static Mutex * radius_mutex
Definition: radius_acct.c:78
#define mutex_unlock(m)
Definition: thread.h:136
RADIUS_PDU * radius_pdu_unpack(Octstr *data_without_len)
Definition: radius_pdu.c:360
union RADIUS_PDU::@72 u
int udp_get_port(Octstr *addr)
Definition: socket.c:547
static int update_tables(RADIUS_PDU *pdu)
Definition: radius_acct.c:110
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void radius_pdu_destroy(RADIUS_PDU *pdu)
Definition: radius_pdu.c:156
static Octstr * our_host
Definition: radius_acct.c:86
int radius_authenticate_pdu(RADIUS_PDU *pdu, Octstr **data, Octstr *secret)
Definition: radius_pdu.c:416
int udp_bind(int port, const char *source_addr)
Definition: socket.c:478
int udp_client_socket(void)
Definition: socket.c:464
#define octstr_duplicate(ostr)
Definition: octstr.h:187
#define octstr_dump(ostr, level,...)
Definition: octstr.h:564
long dict_key_count(Dict *dict)
Definition: dict.c:335
static Dict * session_table
Definition: radius_acct.c:72
void warning(int err, const char *fmt,...)
Definition: log.c:624
static int run_thread
Definition: radius_acct.c:79
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
RADIUS_PDU * radius_pdu_create(int type, RADIUS_PDU *req)
Definition: radius_pdu.c:123
Definition: octstr.c:118
static Dict * radius_table
Definition: radius_acct.c:71
int read_available(int fd, long wait_usec)
Definition: socket.c:406
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:690
#define panic
Definition: log.h:87
static Octstr * secret_nas
Definition: radius_acct.c:92
static long remote_timeout
Definition: radius_acct.c:99
static long remote_port
Definition: radius_acct.c:89
int udp_sendto(int s, Octstr *datagram, Octstr *addr)
Definition: socket.c:567
Octstr * radius_pdu_pack(RADIUS_PDU *pdu)
Definition: radius_pdu.c:237
const char * type_name
Definition: radius_pdu.h:92
#define mutex_lock(m)
Definition: thread.h:130
static Octstr * remote_host
Definition: radius_acct.c:88
static Dict * client_table
Definition: radius_acct.c:73
int udp_recvfrom(int s, Octstr **datagram, Octstr **addr)
Definition: socket.c:582
Octstr * udp_create_address(Octstr *host_or_ip, int port)
Definition: socket.c:517
Octstr * udp_get_ip(Octstr *addr)
Definition: socket.c:557
Octstr* radius_acct_get_msisdn ( Octstr client_ip)

Definition at line 363 of file radius_acct.c.

References dict_get(), mutex_lock, mutex_unlock, normalize_number(), octstr_duplicate, and octstr_get_cstr.

Referenced by add_msisdn(), and start_fetch().

364 {
365  Octstr *m, *r;
366  char *uf;
367 
368  /* if no proxy thread is running, then pass NULL as result */
369  if (radius_table == NULL || client_ip == NULL)
370  return NULL;
371 
373  m = dict_get(radius_table, client_ip);
375  r = m ? octstr_duplicate(m) : NULL;
376 
377  /* apply number normalization */
379  normalize_number(uf, &r);
380 
381  return r;
382 }
static Mutex * radius_mutex
Definition: radius_acct.c:78
#define mutex_unlock(m)
Definition: thread.h:136
static Octstr * unified_prefix
Definition: radius_acct.c:96
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
#define octstr_duplicate(ostr)
Definition: octstr.h:187
Definition: octstr.c:118
static Dict * radius_table
Definition: radius_acct.c:71
int normalize_number(char *dial_prefixes, Octstr **number)
Definition: utils.c:882
#define mutex_lock(m)
Definition: thread.h:130
void radius_acct_init ( CfgGroup grp)

Definition at line 384 of file radius_acct.c.

References cfg_get, cfg_get_integer(), dict_create(), gwthread_create, info(), mutex_create, octstr_create, octstr_destroy(), octstr_get_cstr, octstr_imm(), our_port, panic, proxy_thread(), RADIUS_NAS_PORTS, remote_port, and remote_timeout.

Referenced by init_wapbox().

385 {
386  long nas_ports = 0;
387 
388  /* get configured parameters */
389  if ((our_host = cfg_get(grp, octstr_imm("our-host"))) == NULL) {
390  our_host = octstr_create("0.0.0.0");
391  }
392  if ((remote_host = cfg_get(grp, octstr_imm("remote-host"))) != NULL) {
393  cfg_get_integer(&remote_port, grp, octstr_imm("remote-port"));
394  if ((secret_radius = cfg_get(grp, octstr_imm("secret-radius"))) == NULL) {
395  panic(0, "RADIUS: No shared secret `secret-radius' for remote RADIUS in `radius-acct' provided.");
396  }
397  }
398  cfg_get_integer(&our_port, grp, octstr_imm("our-port"));
399  cfg_get_integer(&remote_timeout, grp, octstr_imm("remote-timeout"));
400 
401  if ((cfg_get_integer(&nas_ports, grp, octstr_imm("nas-ports"))) == -1) {
402  nas_ports = RADIUS_NAS_PORTS;
403  }
404 
405  if ((secret_nas = cfg_get(grp, octstr_imm("secret-nas"))) == NULL) {
406  panic(0, "RADIUS: No shared secret `secret-nas' for NAS in `radius-acct' provided.");
407  }
408 
409  unified_prefix = cfg_get(grp, octstr_imm("unified-prefix"));
410 
411  info(0, "RADIUS: local RADIUS accounting proxy at <%s:%ld>",
413  if (remote_host == NULL) {
414  info(0, "RADIUS: remote RADIUS accounting server is absent");
415  } else {
416  info(0, "RADIUS: remote RADIUS accounting server at <%s:%ld>",
418  }
419 
420  info(0, "RADIUS: initializing internal hash tables with %ld buckets.", nas_ports);
421 
423 
424  /* init hash tables */
425  radius_table = dict_create(nas_ports, (void (*)(void *))octstr_destroy);
426  session_table = dict_create(nas_ports, (void (*)(void *))octstr_destroy);
427  client_table = dict_create(nas_ports, (void (*)(void *))octstr_destroy);
428 
430 }
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
void info(int err, const char *fmt,...)
Definition: log.c:636
static long our_port
Definition: radius_acct.c:87
static Mutex * radius_mutex
Definition: radius_acct.c:78
static Octstr * unified_prefix
Definition: radius_acct.c:96
#define mutex_create()
Definition: thread.h:96
#define cfg_get(grp, varname)
Definition: cfg.h:86
static void proxy_thread(void *arg)
Definition: radius_acct.c:215
static Octstr * secret_radius
Definition: radius_acct.c:93
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
static Octstr * our_host
Definition: radius_acct.c:86
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
#define RADIUS_NAS_PORTS
Definition: radius_acct.c:76
static Dict * session_table
Definition: radius_acct.c:72
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
#define gwthread_create(func, arg)
Definition: gwthread.h:90
#define octstr_create(cstr)
Definition: octstr.h:125
static Dict * radius_table
Definition: radius_acct.c:71
int cfg_get_integer(long *n, CfgGroup *grp, Octstr *varname)
Definition: cfg.c:739
#define panic
Definition: log.h:87
static Octstr * secret_nas
Definition: radius_acct.c:92
static long remote_timeout
Definition: radius_acct.c:99
static long remote_port
Definition: radius_acct.c:89
static Octstr * remote_host
Definition: radius_acct.c:88
static Dict * client_table
Definition: radius_acct.c:73
void radius_acct_shutdown ( void  )

Definition at line 432 of file radius_acct.c.

References dict_destroy(), gwthread_join_every(), info(), mutex_destroy(), mutex_lock, mutex_unlock, octstr_destroy(), proxy_thread(), and run_thread.

Referenced by main().

433 {
434  if (radius_mutex == NULL) /* haven't init'ed at all */
435  return ;
436 
438  run_thread = 0;
440 
442 
446 
448 
454 
455  info(0, "RADIUS: accounting proxy stopped.");
456 }
void info(int err, const char *fmt,...)
Definition: log.c:636
static Mutex * radius_mutex
Definition: radius_acct.c:78
#define mutex_unlock(m)
Definition: thread.h:136
static Octstr * unified_prefix
Definition: radius_acct.c:96
static void proxy_thread(void *arg)
Definition: radius_acct.c:215
static Octstr * secret_radius
Definition: radius_acct.c:93
void gwthread_join_every(gwthread_func_t *func)
static Octstr * our_host
Definition: radius_acct.c:86
static Dict * session_table
Definition: radius_acct.c:72
static int run_thread
Definition: radius_acct.c:79
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
void mutex_destroy(Mutex *mutex)
Definition: thread.c:97
void dict_destroy(Dict *dict)
Definition: dict.c:215
static Dict * radius_table
Definition: radius_acct.c:71
static Octstr * secret_nas
Definition: radius_acct.c:92
#define mutex_lock(m)
Definition: thread.h:130
static Octstr * remote_host
Definition: radius_acct.c:88
static Dict * client_table
Definition: radius_acct.c:73
static int update_tables ( RADIUS_PDU pdu)
static

Definition at line 110 of file radius_acct.c.

References RADIUS_PDU::attr, dict_get(), dict_put(), dict_remove(), error(), info(), octstr_compare(), octstr_destroy(), octstr_duplicate, octstr_get_cstr, octstr_imm(), RADIUS_PDU::type, type, and warning().

Referenced by proxy_thread().

111 {
112  Octstr *client_ip, *msisdn;
113  Octstr *type, *session_id;
114  int ret = 0;
115  Octstr *rm_item;
116 
117  client_ip = msisdn = type = session_id = NULL;
118 
119  /* only add if we have a Accounting-Request PDU */
120  if (pdu->type == 0x04) {
121 
122  /* check if we have a START or STOP event */
123  type = dict_get(pdu->attr, octstr_imm("Acct-Status-Type"));
124 
125  /* get the sesion id */
126  session_id = dict_get(pdu->attr, octstr_imm("Acct-Session-Id"));
127 
128  /* grep the needed data */
129  client_ip = dict_get(pdu->attr, octstr_imm("Framed-IP-Address"));
130  msisdn = dict_get(pdu->attr, octstr_imm("Calling-Station-Id"));
131 
132  /* we can't add mapping without both components */
133  if (client_ip == NULL || msisdn == NULL) {
134  warning(0, "RADIUS: NAS did either not send 'Framed-IP-Address' or/and "
135  "'Calling-Station-Id', dropping mapping but will forward.");
136  /* anyway forward the packet to remote RADIUS server */
137  return 1;
138  }
139 
140  if (octstr_compare(type, octstr_imm("1")) == 0 && session_id && msisdn) {
141  /* session START */
142  if (dict_get(radius_table, client_ip) == NULL &&
143  dict_get(session_table, session_id) == NULL) {
144  Octstr *put_msisdn = octstr_duplicate(msisdn);
145  Octstr *put_client_ip = octstr_duplicate(client_ip);
146  Octstr *put_session_id = octstr_duplicate(session_id);
147  Octstr *old_session_id, *old_client_ip;
148 
149  /* ok, this is a new session. If it contains an IP that is still
150  * in the session/client tables then remove the old session from the
151  * two tables session/client */
152  if ((old_session_id = dict_get(client_table, client_ip)) != NULL &&
153  (old_client_ip = dict_get(session_table, old_session_id)) != NULL &&
154  octstr_compare(old_session_id, session_id) != 0) {
155  rm_item = dict_remove(client_table, client_ip);
156  octstr_destroy(rm_item);
157  rm_item = dict_remove(session_table, old_session_id);
158  octstr_destroy(rm_item);
159  octstr_destroy(old_session_id);
160  octstr_destroy(old_client_ip);
161  }
162 
163  /* insert both, new client IP and session to mapping tables */
164  dict_put(radius_table, client_ip, put_msisdn);
165  dict_put(session_table, session_id, put_client_ip);
166  dict_put(client_table, client_ip, put_session_id);
167 
168  info(0, "RADIUS: Mapping `%s <-> %s' for session id <%s> added.",
169  octstr_get_cstr(client_ip), octstr_get_cstr(msisdn),
170  octstr_get_cstr(session_id));
171  ret = 1;
172  } else {
173  warning(0, "RADIUS: Duplicate mapping `%s <-> %s' for session "
174  "id <%s> received, ignoring.",
175  octstr_get_cstr(client_ip), octstr_get_cstr(msisdn),
176  octstr_get_cstr(session_id));
177  }
178  } else if (octstr_compare(type, octstr_imm("2")) == 0) {
179  /* session STOP */
180  Octstr *comp_client_ip;
181  if ((msisdn = dict_get(radius_table, client_ip)) != NULL &&
182  (comp_client_ip = dict_get(session_table, session_id)) != NULL &&
183  octstr_compare(client_ip, comp_client_ip) == 0) {
184  dict_remove(radius_table, client_ip);
185  rm_item = dict_remove(client_table, client_ip);
186  octstr_destroy(rm_item);
187  dict_remove(session_table, session_id);
188  info(0, "RADIUS: Mapping `%s <-> %s' for session id <%s> removed.",
189  octstr_get_cstr(client_ip), octstr_get_cstr(msisdn),
190  octstr_get_cstr(session_id));
191  octstr_destroy(msisdn);
192  octstr_destroy(comp_client_ip);
193 
194  ret = 1;
195  } else {
196  warning(0, "RADIUS: Could not find mapping for `%s' session "
197  "id <%s>, ignoring.",
198  octstr_get_cstr(client_ip), octstr_get_cstr(session_id));
199  }
200 
201  } else {
202  error(0, "RADIUS: unknown Acct-Status-Type `%s' received, ignoring.",
203  octstr_get_cstr(type));
204  }
205  }
206 
207  return ret;
208 }
void error(int err, const char *fmt,...)
Definition: log.c:612
void info(int err, const char *fmt,...)
Definition: log.c:636
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
Dict * attr
Definition: radius_pdu.h:93
int type
Definition: smsc_cimd2.c:215
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:281
void * dict_remove(Dict *dict, Octstr *key)
Definition: dict.c:307
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
#define octstr_duplicate(ostr)
Definition: octstr.h:187
static Dict * session_table
Definition: radius_acct.c:72
void warning(int err, const char *fmt,...)
Definition: log.c:624
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:322
Definition: octstr.c:118
static Dict * radius_table
Definition: radius_acct.c:71
static Dict * client_table
Definition: radius_acct.c:73
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:869

Variable Documentation

Dict* client_table = NULL
static

Definition at line 73 of file radius_acct.c.

Octstr* our_host = NULL
static

Definition at line 86 of file radius_acct.c.

long our_port = 1813
static
Mutex* radius_mutex = NULL
static

Definition at line 78 of file radius_acct.c.

Dict* radius_table = NULL
static

Definition at line 71 of file radius_acct.c.

Referenced by server().

Octstr* remote_host = NULL
static

Definition at line 88 of file radius_acct.c.

long remote_port = 1813
static

Definition at line 89 of file radius_acct.c.

Referenced by proxy_thread(), and radius_acct_init().

long remote_timeout = 40000
static

Definition at line 99 of file radius_acct.c.

Referenced by proxy_thread(), and radius_acct_init().

int run_thread = 0
static

Definition at line 79 of file radius_acct.c.

Referenced by proxy_thread(), and radius_acct_shutdown().

Octstr* secret_nas = NULL
static

Definition at line 92 of file radius_acct.c.

Octstr* secret_radius = NULL
static

Definition at line 93 of file radius_acct.c.

Dict* session_table = NULL
static

Definition at line 72 of file radius_acct.c.

Octstr* unified_prefix = NULL
static

Definition at line 96 of file radius_acct.c.

See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.