Kannel: Open Source WAP and SMS gateway  svn-r5335
test_radius_acct.c
Go to the documentation of this file.
1 /* ====================================================================
2  * The Kannel Software License, Version 1.0
3  *
4  * Copyright (c) 2001-2018 Kannel Group
5  * Copyright (c) 1998-2001 WapIT Ltd.
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
12  * 1. Redistributions of source code must retain the above copyright
13  * notice, this list of conditions and the following disclaimer.
14  *
15  * 2. Redistributions in binary form must reproduce the above copyright
16  * notice, this list of conditions and the following disclaimer in
17  * the documentation and/or other materials provided with the
18  * distribution.
19  *
20  * 3. The end-user documentation included with the redistribution,
21  * if any, must include the following acknowledgment:
22  * "This product includes software developed by the
23  * Kannel Group (http://www.kannel.org/)."
24  * Alternately, this acknowledgment may appear in the software itself,
25  * if and wherever such third-party acknowledgments normally appear.
26  *
27  * 4. The names "Kannel" and "Kannel Group" must not be used to
28  * endorse or promote products derived from this software without
29  * prior written permission. For written permission, please
30  * contact org@kannel.org.
31  *
32  * 5. Products derived from this software may not be called "Kannel",
33  * nor may "Kannel" appear in their name, without prior written
34  * permission of the Kannel Group.
35  *
36  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39  * DISCLAIMED. IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS
40  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
41  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
42  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
43  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
44  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
45  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
46  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
47  * ====================================================================
48  *
49  * This software consists of voluntary contributions made by many
50  * individuals on behalf of the Kannel Group. For more information on
51  * the Kannel Group, please see <http://www.kannel.org/>.
52  *
53  * Portions of this software are based upon software originally written at
54  * WapIT Ltd., Helsinki, Finland for the Kannel project.
55  */
56 
57 /*
58  * test_radius_acct.c - program to test RADIUS accounting proxy thread
59  *
60  * Stipe Tolj <stolj@wapme.de>
61  */
62 
63 #include <unistd.h>
64 #include <string.h>
65 
66 #include "gwlib/gwlib.h"
67 #include "radius/radius_pdu.h"
68 
69 
70 /*
71  * Updates the internal RADIUS mapping table. Returns 1 if the
72  * mapping has been new and put into the table, otherwise if it's
73  * a duplicate returns 0.
74  */
75 static int update_table(RADIUS_PDU *pdu, Dict **table)
76 {
77  Octstr *client_ip, *msisdn;
78  Octstr *type;
79  int ret = 0;
80 
81  client_ip = msisdn = NULL;
82 
83  /* only add if we have a Accounting-Request PDU */
84  if (pdu->type == 0x04) {
85 
86  /* check if we have a START or STOP event */
87  type = dict_get(pdu->attr, octstr_imm("Acct-Status-Type"));
88 
89  /* grep the needed data */
90  client_ip = dict_get(pdu->attr, octstr_imm("Framed-IP-Address"));
91  msisdn = dict_get(pdu->attr, octstr_imm("Calling-Station-Id"));
92 
93  if (octstr_compare(type, octstr_imm("1")) == 0) {
94  /* START */
95  if (dict_get(*table, client_ip) == NULL) {
96  dict_put(*table, client_ip, msisdn);
97  info(0, "RADIUS: Mapping `%s <-> %s' added.",
98  octstr_get_cstr(client_ip), octstr_get_cstr(msisdn));
99  ret = 1;
100  } else {
101  warning(0, "RADIUS: Duplicate mapping for `%s <-> %s' received",
102  octstr_get_cstr(client_ip), octstr_get_cstr(msisdn));
103  }
104  }
105  else if (octstr_compare(type, octstr_imm("2")) == 0) {
106  /* STOP */
107  msisdn = dict_get(*table, client_ip);
108  dict_remove(*table, client_ip);
109  }
110  else {
111  error(0, "RADIUS: unknown Acct-Status-Type `%s' received.",
113  }
114  }
115 
116  octstr_destroy(client_ip);
117  octstr_destroy(msisdn);
118 
119  return ret;
120 }
121 
122 static void server(int lport, int pport)
123 {
124  int i;
125  int ss, cs; /* server and client socket */
126  Octstr *data, *from, *addr;
127  /* pid_t pid = getpid(); */
129 
130  /* create client binding */
131  cs = udp_client_socket();
132  addr = udp_create_address(octstr_create("localhost"), pport);
133 
134  /* create server binding */
135  ss = udp_bind(lport, "0.0.0.0");
136  if (ss == -1)
137  panic(0, "Couldn't set up server socket for port %d.", lport);
138 
139  /* init hash table */
140  radius_table = dict_create(30, (void (*)(void *))octstr_destroy);
141 
142  i = 1;
143  while (1) {
144  RADIUS_PDU *pdu, *r;
145  Octstr *rdata;
146  int forward = 0;
147 
148  /* get request */
149  if (udp_recvfrom(ss, &data, &from) == -1)
150  panic(0, "Couldn't receive request data from NAS");
151  info(0, "Got data from NAS <%s:%d>",
153 
154  /*
155  debug("",0,"Saving PDU packet");
156  f = fopen(octstr_get_cstr(octstr_format("/tmp/radius-pdu.%ld.%d", pid, i)), "w");
157  octstr_print(f, data);
158  fclose(f);
159  */
160 
161  pdu = radius_pdu_unpack(data);
162  info(0, "PDU type: %s", pdu->type_name);
163 
164  /* XXX authenticator md5 check does not work?! */
165  /* radius_authenticate_pdu(pdu, data, octstr_imm("radius")); */
166 
167  /* store to hash table if not present yet */
168  forward = update_table(pdu, &radius_table);
169 
170  /* create response PDU for NAS */
171  r = radius_pdu_create(0x05, pdu);
172 
173  /*
174  * create response authenticator
175  * code+identifier(req)+length+authenticator(req)+(attributes)+secret
176  */
177  r->u.Accounting_Response.identifier = pdu->u.Accounting_Request.identifier;
178  r->u.Accounting_Response.authenticator =
179  octstr_duplicate(pdu->u.Accounting_Request.authenticator);
180 
181  rdata = radius_pdu_pack(r);
182 
183  /* creates response autenticator in encoded PDU */
184  radius_authenticate_pdu(r, &rdata, octstr_imm("radius"));
185 
186  /* forward request to remote RADIUS server only if table updated */
187  if (forward) {
188  if (udp_sendto(cs, data, addr) == -1)
189  panic(0, "Couldn't send to remote RADIUS.");
190  if (udp_recvfrom(cs, &data, &from) == -1)
191  panic(0, "Couldn't receive from remote RADIUS.");
192  info(0, "Got data from remote RADIUS <%s:%d>",
194  }
195 
196  /* send response to NAS */
197  if (udp_sendto(ss, rdata, from) == -1)
198  panic(0, "Couldn't send response data to NAS.");
199 
200  radius_pdu_destroy(pdu);
202 
203  octstr_destroy(rdata);
204  i++;
205 
206  debug("",0,"Mapping table contains %ld elements",
208  }
209 }
210 
211 int main(int argc, char **argv) {
212  int lport, pport;
213 
214  gwlib_init();
215 
216  if (argc != 3)
217  panic(0, "usage: test_radius_acct <your RADIUS acct port> <remote RADIUS port>");
218 
219  lport = atoi(argv[1]);
220  pport = atoi(argv[2]);
221 
222  server(lport, pport);
223 
224  return 0;
225 }
Dict * dict_create(long size_hint, void(*destroy_value)(void *))
Definition: dict.c:192
void error(int err, const char *fmt,...)
Definition: log.c:648
void info(int err, const char *fmt,...)
Definition: log.c:672
void dict_put(Dict *dict, Octstr *key, void *value)
Definition: dict.c:240
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
Dict * attr
Definition: radius_pdu.h:93
int type
Definition: smsc_cimd2.c:215
#define octstr_get_cstr(ostr)
Definition: octstr.h:233
void radius_pdu_destroy(RADIUS_PDU *pdu)
Definition: radius_pdu.c:156
int radius_authenticate_pdu(RADIUS_PDU *pdu, Octstr **data, Octstr *secret)
Definition: radius_pdu.c:416
static Octstr * from
Definition: mtbatch.c:95
Octstr * octstr_imm(const char *cstr)
Definition: octstr.c:283
void * dict_remove(Dict *dict, Octstr *key)
Definition: dict.c:307
int udp_bind(int port, const char *source_addr)
Definition: socket.c:478
int udp_client_socket(void)
Definition: socket.c:464
void * dict_get(Dict *dict, Octstr *key)
Definition: dict.c:286
Definition: dict.c:116
#define octstr_duplicate(ostr)
Definition: octstr.h:187
long dict_key_count(Dict *dict)
Definition: dict.c:335
void warning(int err, const char *fmt,...)
Definition: log.c:660
void octstr_destroy(Octstr *ostr)
Definition: octstr.c:324
#define octstr_create(cstr)
Definition: octstr.h:125
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
void debug(const char *place, int err, const char *fmt,...)
Definition: log.c:726
#define panic
Definition: log.h:87
static void server(int lport, int pport)
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
void gwlib_init(void)
Definition: gwlib.c:78
int main(int argc, char **argv)
static int update_table(RADIUS_PDU *pdu, Dict **table)
const char * type_name
Definition: radius_pdu.h:92
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
int octstr_compare(const Octstr *ostr1, const Octstr *ostr2)
Definition: octstr.c:871
See file LICENSE for details about the license agreement for using, modifying, copying or deriving work from this software.