Main Page | Alphabetical List | Data Structures | Directories | File List | Data Fields | Globals

test_radius_acct.c

Go to the documentation of this file.
00001 /* ==================================================================== 
00002  * The Kannel Software License, Version 1.0 
00003  * 
00004  * Copyright (c) 2001-2008 Kannel Group  
00005  * Copyright (c) 1998-2001 WapIT Ltd.   
00006  * All rights reserved. 
00007  * 
00008  * Redistribution and use in source and binary forms, with or without 
00009  * modification, are permitted provided that the following conditions 
00010  * are met: 
00011  * 
00012  * 1. Redistributions of source code must retain the above copyright 
00013  *    notice, this list of conditions and the following disclaimer. 
00014  * 
00015  * 2. Redistributions in binary form must reproduce the above copyright 
00016  *    notice, this list of conditions and the following disclaimer in 
00017  *    the documentation and/or other materials provided with the 
00018  *    distribution. 
00019  * 
00020  * 3. The end-user documentation included with the redistribution, 
00021  *    if any, must include the following acknowledgment: 
00022  *       "This product includes software developed by the 
00023  *        Kannel Group (http://www.kannel.org/)." 
00024  *    Alternately, this acknowledgment may appear in the software itself, 
00025  *    if and wherever such third-party acknowledgments normally appear. 
00026  * 
00027  * 4. The names "Kannel" and "Kannel Group" must not be used to 
00028  *    endorse or promote products derived from this software without 
00029  *    prior written permission. For written permission, please  
00030  *    contact org@kannel.org. 
00031  * 
00032  * 5. Products derived from this software may not be called "Kannel", 
00033  *    nor may "Kannel" appear in their name, without prior written 
00034  *    permission of the Kannel Group. 
00035  * 
00036  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED 
00037  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 
00038  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
00039  * DISCLAIMED.  IN NO EVENT SHALL THE KANNEL GROUP OR ITS CONTRIBUTORS 
00040  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,  
00041  * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT  
00042  * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR  
00043  * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
00044  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE  
00045  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,  
00046  * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
00047  * ==================================================================== 
00048  * 
00049  * This software consists of voluntary contributions made by many 
00050  * individuals on behalf of the Kannel Group.  For more information on  
00051  * the Kannel Group, please see <http://www.kannel.org/>. 
00052  * 
00053  * Portions of this software are based upon software originally written at  
00054  * WapIT Ltd., Helsinki, Finland for the Kannel project.  
00055  */ 
00056 
00057 /*
00058  * test_radius_acct.c - program to test RADIUS accounting proxy thread
00059  *
00060  * Stipe Tolj <stolj@wapme.de>
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  * Updates the internal RADIUS mapping table. Returns 1 if the 
00072  * mapping has been new and put into the table, otherwise if it's 
00073  * a duplicate returns 0.
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     /* only add if we have a Accounting-Request PDU */
00084     if (pdu->type == 0x04) {
00085 
00086         /* check if we have a START or STOP event */
00087         type = dict_get(pdu->attr, octstr_imm("Acct-Status-Type"));
00088         
00089         /* grep the needed data */
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             /* START */
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             /* STOP */
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; /* server and client socket */
00126     Octstr *data, *from, *addr;
00127     /* pid_t pid = getpid(); */
00128     Dict *radius_table;
00129 
00130     /* create client binding */
00131     cs = udp_client_socket();
00132     addr = udp_create_address(octstr_create("localhost"), pport);
00133 
00134     /* create server binding */
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     /* init hash table */
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         /* get request */
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         debug("",0,"Saving PDU packet");
00156         f = fopen(octstr_get_cstr(octstr_format("/tmp/radius-pdu.%ld.%d", pid, i)), "w");
00157         octstr_print(f, data);
00158         fclose(f);
00159         */
00160         
00161         pdu = radius_pdu_unpack(data);
00162         info(0, "PDU type: %s", pdu->type_name);
00163 
00164         /* XXX authenticator md5 check does not work?! */
00165         /* radius_authenticate_pdu(pdu, data, octstr_imm("radius")); */
00166 
00167         /* store to hash table if not present yet */
00168         forward = update_table(pdu, &radius_table);
00169 
00170         /* create response PDU for NAS */
00171         r = radius_pdu_create(0x05, pdu);
00172 
00173         /* 
00174          * create response authenticator 
00175          * code+identifier(req)+length+authenticator(req)+(attributes)+secret 
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         /* creates response autenticator in encoded PDU */
00184         radius_authenticate_pdu(r, &rdata, octstr_imm("radius"));
00185 
00186         /* forward request to remote RADIUS server only if table updated */
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         /* send response to NAS */
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.