diff options
100 files changed, 6262 insertions, 738 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f61780a..40f2f1a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.6) cmake_policy(SET CMP0005 NEW) cmake_policy(SET CMP0003 OLD) -PROJECT (accel-pppd C) +PROJECT (accel-ppp C) include(cmake/cpack.cmake) @@ -1,10 +1,8 @@ Overview -------- -The ACCEL-PPTP v1.0 is completly new implementation of PPTP/PPPoE/L2TP which was written from null. +The ACCEL-PPP v1.0 is completly new implementation of PPTP/PPPoE/L2TP which was written from scratch. Userspace daemon has its own PPP implementation, so it does not uses pppd and one process (multi-threaded) manages all connections. -ACCEL-PPTP uses kernel module to increase performance and decrease system usage. -It is not fully tested yet so not recomended to use in production. -Also v1.0 is oriented for servers and does not containes client part, if you need client please use v0.8.x +ACCEL-PPP uses only kernel-mode implementations of pptp/l2tp/pppoe. Features @@ -12,7 +10,7 @@ Features 1. Modular architecture 2. High-performance multi-threaded I/O core 3. Supported PPTP -4. Supported PPPoE +4. Supported PPPoE (including TR-101 extension) 5. Supported L2TPv2 (without IPsec) 5. Radius authentication/accounting 6. Radius DM/CoA extention @@ -25,6 +23,7 @@ Features 13. Supported pppd compatible ip-up/ip-down scripts 14. Builtin tbf shaper manager 15. Command line interface via telnet +16. SNMP support (master or subagent via AgentX) Requirment @@ -33,16 +32,19 @@ Requirment 2. kernel-2.6.25 or later 4. cmake-2.6 or later 5. libnl-2.0 or probably later (required for builtin shaper) +6. libcrypto-0.9.8 or probably later (openssl-0.9.8) +7. libpcre +8. net-snmp-5.x Compilation and instalation ----------- Make sure you have configured kernel headers in /usr/src/linux, or specify other location via KDIR. -1. cd /path/to/accel-pptp-1.3.1 +1. cd /path/to/accel-ppp-1.3.5 2. mkdir build 3. cd build -4. cmake [-DBUILD_DRIVER=FALSE] [-DKDIR=/usr/src/linux] [-DCMAKE_INSTALL_PREFIX=/usr/local] [-DCMAKE_BUILD_TYPE=Release] [-DLOG_PGSQL=FALSE] [-DSHAPER=FALSE] [-DRADIUS=TRUE] .. +4. cmake [-DBUILD_DRIVER=FALSE] [-DKDIR=/usr/src/linux] [-DCMAKE_INSTALL_PREFIX=/usr/local] [-DCMAKE_BUILD_TYPE=Release] [-DLOG_PGSQL=FALSE] [-DSHAPER=FALSE] [-DRADIUS=TRUE] [-DNETSNMP=FALSE] .. Please note that the double dot record in the end of the command is essential. You'll probably get error or misconfigured sources if you miss it. BUILD_DRIVER, KDIR, CMAKE_INSTALL_PREFIX, CMAKE_BUILD_TYPE, LOG_PGSQL, SHAPER, RADIUS are optional, But while pptp is not present in mainline kernel you probably need BUILD_DRIVER. @@ -59,13 +61,14 @@ or specify other location via KDIR. Configuration ------------- -read man accel-pptp.conf +read man accel-ppp.conf + Built-in shaper -------------- -accel-pptp supports tbf based shaper manager. +accel-ppp supports tbf based shaper manager. To enable it uncomment shaper_tbf in [modules] section. -It accepts radius attrbutes in various formats: rate, down-rate/up-rate and cisco-like. Values have to be in kilobits except cisco-like. +It accepts radius attributes in various formats: rate, down-rate/up-rate and cisco-like. Values have to be in kilobits except cisco-like. For example: Filter-Id=1000 (means 1000Kbit both up-stream and down-stream rate) Filter-Id=2000/3000 (means 2000Kbit down-stream rate and 3000Kbit up-stream rate) @@ -78,7 +81,7 @@ To specify different attributes for down-stream and up-stream rates use 'attr-do attr-down=PPPD-Downstream-Speed attr-up=PPPD-Upstream-Speed -If you want to use cisco-like format configure accel-pptp as following: +If you want to use cisco-like format configure accel-ppp as following: [tbf] vendor=Cisco attr=Cisco-AVPair @@ -86,10 +89,11 @@ and send two attributes: Cisco-AVPair=lcp:interface-config#1=rate-limit input 2000000 8000 8000 conform-action transmit exceed-action drop (which means 2000Kbit up-stream rate and 8Kb burst) Cisco-AVPair=lcp:interface-config#1=rate-limit output 2000000 8000 8000 conform-action transmit exceed-action drop (which means 2000Kbit down-stream rate and 8Kb burst) + Advanced shaper using --------------------- 1. Burst configuration. -If you not using cisco-format then burst calculates from rate and specified burst factors. +If you not using cisco-like format then burst calculates from rate and specified burst factors. To specify burst factors use 'down-burst-factor' and 'up-burst-factor' options, for example: [tbf] down-burst-factor=1.0 @@ -114,15 +118,45 @@ You have to pass multiple Filter-Id attributes to utilize this functionality. Or cisco-like: Cisco-AVPair=lcp:interface-config#1=rate-limit output access-group 1 1000000 8000 8000 conform-action transmit exceed-action drop Cisco-AVPair=lcp:interface-config#1=rate-limit input access-group 1 1000000 8000 8000 conform-action transmit exceed-action drop -ans so on... +and so on... + +3. chap-secrets. +If you use chap-secrets instead of radius then there is way to utilize built-in shaper too. +The optional fifth column in chap-secrets file is used to pass rate information to shaper. +Its format is same as for radius attributes, except you cann't utilize time ranges functionality. + + +SNMP +---- +SNMP is implemented using net-snmp libraries. By default accel-ppp starts in subagent mode, +so make sure that net-snmp configured with subagent control turned on (read net-snmp's README.agentx for more details). +Also you can start accel-ppp as master agent using following configuration: +[snmp] +master=1 + +Usage: +Place accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt to your mibs directory. +Also you can find used numerical oids in this file. +1. Requesting statistics: +snmpwalk -m +ACCEL-PPP-MIB -v 2c -c local 127.0.0.1 ACCEL-PPP-MIB::accelPPPStat +2. Requesting sessions: +snmptable -m +ACCEL-PPP-MIB -v 2c -c local 127.0.0.1 ACCEL-PPP-MIB::sessionsTable +3. Terminate session by session identifier (Acct-Session-ID): +snmpset -m +ACCEL-PPP-MIB -v 2c -c local 127.0.0.1 ACCEL-PPP-MIB::termBySID.0 = 0000000000000001 +4. Terminate session by interface name: +snmpset -m +ACCEL-PPP-MIB -v 2c -c local 127.0.0.1 ACCEL-PPP-MIB::termByIfName = ppp2 +5. Terminaten session by IP address (Framed-IP-Address): +snmpset -m +ACCEL-PPP-MIB -v 2c -c local 127.0.0.1 ACCEL-PPP-MIB::termByIP = 192.168.10.10 +6. Terminate session by username: +snmpset -m +ACCEL-PPP-MIB -v 2c -c local 127.0.0.1 ACCEL-PPP-MIB::termByUsername = user1 Warning !!! ----------- 1. The pptp driver conflicts with ip_gre driver (in kernel), so make sure that ip_gre is not built-in or loaded at run time (don't matter if you have 2.6.37 or later kernel). -2. Never mix connections of accel-pptp and original pptpd, before starting accel-pptp make sure that no connections - of original pptpd exists. +2. Don't mix connections of accel-ppp and poptop's pptpd, before starting accel-ppp make sure that no connections + of pptpd exists. Thanks diff --git a/accel-pppd/CMakeLists.txt b/accel-pppd/CMakeLists.txt index aaafbd9..45a070f 100644 --- a/accel-pppd/CMakeLists.txt +++ b/accel-pppd/CMakeLists.txt @@ -14,7 +14,7 @@ ENDIF (NOT HAVE_SSL) SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -fvisibility=hidden -fno-strict-aliasing -D_GNU_SOURCE -DPTHREAD_SPINLOCK -fPIC") -IF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git) +IF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git AND NOT DEFINED IGNORE_GIT) EXECUTE_PROCESS( COMMAND git log COMMAND head -n1 @@ -23,9 +23,9 @@ IF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git) OUTPUT_VARIABLE ACCEL_PPP_VERSION ) STRING(STRIP ${ACCEL_PPP_VERSION} ACCEL_PPP_VERSION) -ELSE (EXISTS ${CMAKE_HOME_DIRECTORY}/.git) - SET (ACCEL_PPP_VERSION 1.3.4) -ENDIF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git) +ELSE (EXISTS ${CMAKE_HOME_DIRECTORY}/.git AND NOT DEFINED IGNORE_GIT) + SET (ACCEL_PPP_VERSION 1.3.7) +ENDIF (EXISTS ${CMAKE_HOME_DIRECTORY}/.git AND NOT DEFINED IGNORE_GIT) ADD_DEFINITIONS(-DACCEL_PPP_VERSION="${ACCEL_PPP_VERSION}") diff --git a/accel-pppd/accel-ppp.conf b/accel-pppd/accel-ppp.conf index 31ad4e0..3193242 100644 --- a/accel-pppd/accel-ppp.conf +++ b/accel-pppd/accel-ppp.conf @@ -29,13 +29,15 @@ mru=1400 #ccp=0 #sid-case=upper #check-ip=0 +#single-session=replace +#mppe=require [lcp] echo-interval=30 echo-failure=3 [pptp] -echo-interval=30 +#echo-interval=30 verbose=1 [pppoe] @@ -45,6 +47,7 @@ interface=eth0 #pado-delay=0 #pado-delay=0,100:100,200:200,-1:500 #ifname-in-sid=called-sid +#tr101=1 verbose=1 [l2tp] @@ -65,14 +68,15 @@ verbose=1 nas-identifier=accel-ppp nas-ip-address=127.0.0.1 gw-ip-address=192.168.100.1 -auth-server=127.0.0.1:1812,testing123 -acct-server=127.0.0.1:1813,testing123 +#auth-server=127.0.0.1:1812,testing123 (obsolete) +#acct-server=127.0.0.1:1813,testing123 (obsolete) +server=127.0.0.1,testing123 dae-server=127.0.0.1:3799,testing123 -#dm_coa_secret=testing123 (deprecated) verbose=1 #timeout=3 #max-try=3 #acct-timeout=120 +#acct-delay-time=0 [client-ip-range] 10.0.0.0/8 @@ -88,6 +92,7 @@ gw-ip-address=192.168.0.1 [log] log-file=/var/log/accel-ppp/accel-ppp.log log-emerg=/var/log/accel-ppp/emerg.log +log-fail-file=/var/log/accel-ppp/auth-fail.log #log-debug=/dev/stdout #log-tcp=127.0.0.1:3000 copy=1 @@ -110,6 +115,10 @@ ip-change=/etc/ppp/ip-change radattr-prefix=/var/run/radattr verbose=1 +[chap-secrets] +gw-ip-address=192.168.100.1 +#chap-secrets=/etc/ppp/chap-secrets + [tbf] #attr=Filter-Id #down-burst-factor=0.1 @@ -119,4 +128,8 @@ verbose=1 [cli] telnet=127.0.0.1:2000 tcp=127.0.0.1:2001 -#passwd=123 +#password=123 + +[snmp] +master=0 +agent-name=accel-ppp diff --git a/accel-pppd/accel-ppp.conf.5 b/accel-pppd/accel-ppp.conf.5 index d9aaadb..aee1354 100644 --- a/accel-pppd/accel-ppp.conf.5 +++ b/accel-pppd/accel-ppp.conf.5 @@ -104,6 +104,32 @@ Specifies in which case generate session identifier (default lower). .BI "check-ip=" 0|1 Specifies whether accel-ppp should check if IP already assigned to other ppp interface (default 0). .TP +.BI "single-session=" replace|deny +Specifies whether accel-ppp should control sessions count. +.br +If this option is absent session count control is turned off. +If this option is +.B replace +then accel-ppp will terminate first session when second is authorized. +If this option is +.B deny +then accel-ppp will deny second session authorization. +.TP +.BI "mppe=" require|prefere|deny +Specifies mppe negotioation preference. +.br +.B require +- ask client for mppe, if it rejects drop connection +.br +.B prefere +- ask client for mppe, if it rejects don't fail. +.br +.B deny +- deny mppe. +.br +Default behavior - don't ask client for mppe, but allow it if client wants. +Please note that RADIUS may override this option by MS-MPPE-Encryption-Policy attribute. +.TP .SH [lcp] .br PPP LCP module configuration @@ -190,6 +216,10 @@ If this option is given and .B n is greater of zero then pppoe module will produce verbose logging. .TP +.TP +.BI "tr101=" 0|1 +Specifies whether to handle TR101 tags. +.TP .SH [l2tp] .br Configuration of L2TP module. @@ -232,10 +262,15 @@ Also DM/CoA server will bind to that address. Specifies address to use as local address of ppp interfaces if Framed-IP-Address received from RADIUS server. .TP .BI "auth-server=" x.x.x.x:port,secret -Specifies IP address, port and secret of authentication RADIUS server. +Specifies IP address, port and secret of authentication RADIUS server. (obsolete) .TP .BI "acct-server=" x.x.x.x:port,secret -Specifies IP address, port and secret of accounting RADIUS server. +Specifies IP address, port and secret of accounting RADIUS server. (obsolete) +.TP +.BI "server=" address,secret[,auth-port[,acct-port]] +Specifies IP address, ports and secret of RADIUS server. +If you want to specify only authentication or accounting server then set auth-port/acct-port to zero. +You may specify multiple radius servers. .TP .BI "dae-server=" x.x.x.x:port,secret Specifies IP address, port to bind and secret for Dynamic Authorization Extension server (DM/CoA). @@ -265,6 +300,9 @@ Specifies number of tries to send Access-Request/Accounting-Request queries. .BI "acct-timeout=" n Specifies timeout of accounting interim update. .TP +.BI "acct-delay-time=" 0|1 +Specifies whether radius client should include Acct-Delay-Time attribute to accounting requests (default 0). +.TP .SH [log] .br Configuration of log and log_file modules. @@ -275,6 +313,9 @@ Path to file to write general log. .BI "log-emerg=" file Path to file to write emergency messages. .TP +.BI "log-fail-file=" file +Path to file to write authentication failed session log. +.TP .BI "log-tcp=" x.x.x.x:port Send logs to specified host. .TP @@ -357,6 +398,16 @@ Prefix of radattr files (for example /var/run/radattr, resulting files will be / .BI "verbose=" n If specified and greated then zero pppd_module will produce verbose logging. .TP +.SH [chap-secrets] +.br +Configuration of chap-secrets module. +.TP +.BI "gw-ip-address=" x.x.x.x +Specifies address to use as local address of ppp interfaces if chap-secrets is used for IP address assignment. +.TP +.BI "chap-secrets=" file +Specifies alternate chap-secrets file location (default is /etc/ppp/chap-secrets). +.TP .SH [ip-pool] .br Configuration of ippool module. diff --git a/accel-pppd/auth/auth_chap_md5.c b/accel-pppd/auth/auth_chap_md5.c index 2ea60ba..2307f14 100644 --- a/accel-pppd/auth/auth_chap_md5.c +++ b/accel-pppd/auth/auth_chap_md5.c @@ -289,9 +289,14 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h name = _strndup(msg->name,ntohs(msg->hdr.len) - sizeof(*msg) + 2); if (conf_any_login) { + if (ppp_auth_successed(ad->ppp, name)) { + chap_send_failure(ad); + ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); + _free(name); + return; + } chap_send_success(ad); ad->started = 1; - ppp_auth_successed(ad->ppp, name); return; } @@ -325,12 +330,17 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h ppp_auth_failed(ad->ppp, name); _free(name); } else { - chap_send_success(ad); if (!ad->started) { - ad->started = 1; - if (conf_interval) - triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); - ppp_auth_successed(ad->ppp, name); + if (ppp_auth_successed(ad->ppp, name)) { + chap_send_failure(ad); + ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); + _free(name); + } else { + chap_send_success(ad); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); + } } else _free(name); } @@ -343,14 +353,21 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h ppp_auth_failed(ad->ppp, name); _free(name); } else { - chap_send_success(ad); if (!ad->started) { - ad->started = 1; - if (conf_interval) - triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); - ppp_auth_successed(ad->ppp, name); - } else + if (ppp_auth_successed(ad->ppp, name)) { + chap_send_failure(ad); + ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); + _free(name); + } else { + chap_send_success(ad); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); + } + } else { + chap_send_success(ad); _free(name); + } } } @@ -397,7 +414,7 @@ static void chap_recv(struct ppp_handler_t *h) log_ppp_warn("chap-md5: unknown code received %x\n", hdr->code); } -static void __init auth_chap_md5_init() +static void auth_chap_md5_init() { char *opt; @@ -428,3 +445,4 @@ static void __init auth_chap_md5_init() log_emerg("chap-md5: failed to register handler\n"); } +DEFINE_INIT(6, auth_chap_md5_init); diff --git a/accel-pppd/auth/auth_mschap_v1.c b/accel-pppd/auth/auth_mschap_v1.c index 4308300..10d5fe8 100644 --- a/accel-pppd/auth/auth_mschap_v1.c +++ b/accel-pppd/auth/auth_mschap_v1.c @@ -31,15 +31,15 @@ #define VALUE_SIZE 8 #define RESPONSE_VALUE_SIZE (24+24+1) -#define MSG_FAILURE "E=691 R=0" -#define MSG_SUCCESS "Authentication successed" - #define HDR_LEN (sizeof(struct chap_hdr_t)-2) static int conf_timeout = 5; static int conf_interval = 0; static int conf_max_failure = 3; static int conf_any_login = 0; +static char *conf_msg_failure = "E=691 R=0"; +static char *conf_msg_success = "Authentication successed"; +; static int urandom_fd; @@ -69,19 +69,6 @@ struct chap_response_t char name[0]; } __attribute__((packed)); -struct chap_failure_t -{ - struct chap_hdr_t hdr; - char message[sizeof(MSG_FAILURE)]; -} __attribute__((packed)); - -struct chap_success_t -{ - struct chap_hdr_t hdr; - char message[sizeof(MSG_SUCCESS)]; -} __attribute__((packed)); - - struct chap_auth_data_t { struct auth_data_t auth; @@ -210,36 +197,38 @@ static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t * return LCP_OPT_NAK; } -static void chap_send_failure(struct chap_auth_data_t *ad) +static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error) { - struct chap_failure_t msg = { - .hdr.proto = htons(PPP_CHAP), - .hdr.code = CHAP_FAILURE, - .hdr.id = ad->id, - .hdr.len = htons(sizeof(msg)-1-2), - .message = MSG_FAILURE, - }; - + struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + 1); + hdr->proto = htons(PPP_CHAP); + hdr->code = CHAP_FAILURE; + hdr->id = ad->id; + hdr->len = htons(HDR_LEN + strlen(mschap_error)); + strcpy((char *)(hdr + 1), mschap_error); + if (conf_ppp_verbose) - log_ppp_info2("send [MSCHAP-v1 Failure id=%x \"%s\"]\n", msg.hdr.id, MSG_FAILURE); + log_ppp_info2("send [MSCHAP-v1 Failure id=%x \"%s\"]\n", hdr->id, mschap_error); - ppp_chan_send(ad->ppp,&msg,ntohs(msg.hdr.len)+2); + ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2); + + _free(hdr); } static void chap_send_success(struct chap_auth_data_t *ad) { - struct chap_success_t msg = { - .hdr.proto = htons(PPP_CHAP), - .hdr.code = CHAP_SUCCESS, - .hdr.id = ad->id, - .hdr.len = htons(sizeof(msg)-1-2), - .message = MSG_SUCCESS, - }; + struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1); + hdr->proto = htons(PPP_CHAP); + hdr->code = CHAP_SUCCESS; + hdr->id = ad->id; + hdr->len = htons(HDR_LEN + strlen(conf_msg_success)); + strcpy((char *)(hdr + 1), conf_msg_success); if (conf_ppp_verbose) - log_ppp_info2("send [MSCHAP-v1 Success id=%x \"%s\"]\n", msg.hdr.id, MSG_SUCCESS); + log_ppp_info2("send [MSCHAP-v1 Success id=%x \"%s\"]\n", hdr->id, conf_msg_success); - ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); + ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2); + + _free(hdr); } static void chap_send_challenge(struct chap_auth_data_t *ad) @@ -271,6 +260,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h { struct chap_response_t *msg = (struct chap_response_t*)hdr; char *name; + char *mschap_error = conf_msg_failure; int r; if (ad->timeout.tpd) @@ -312,33 +302,45 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h } if (conf_any_login) { + if (ppp_auth_successed(ad->ppp, name)) { + chap_send_failure(ad, mschap_error); + ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); + _free(name); + return; + } chap_send_success(ad); ad->started = 1; - ppp_auth_successed(ad->ppp, name); return; } - r = pwdb_check(ad->ppp, name, PPP_CHAP, MSCHAP_V1, ad->id, ad->val, VALUE_SIZE, msg->lm_hash, msg->nt_hash, msg->flags); + r = pwdb_check(ad->ppp, name, PPP_CHAP, MSCHAP_V1, ad->id, ad->val, VALUE_SIZE, msg->lm_hash, msg->nt_hash, msg->flags, &mschap_error); if (r == PWDB_NO_IMPL) if (chap_check_response(ad, msg, name)) r = PWDB_DENIED; if (r == PWDB_DENIED) { - chap_send_failure(ad); + chap_send_failure(ad, mschap_error); if (ad->started) ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); else ppp_auth_failed(ad->ppp, name); _free(name); } else { - chap_send_success(ad); if (!ad->started) { - ad->started = 1; - if (conf_interval) - triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); - ppp_auth_successed(ad->ppp, name); - } else + if (ppp_auth_successed(ad->ppp, name)) { + chap_send_failure(ad, mschap_error); + ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); + _free(name); + } else { + chap_send_success(ad); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); + } + } else { + chap_send_success(ad); _free(name); + } } } @@ -384,7 +386,7 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response if (!passwd) { if (conf_ppp_verbose) log_ppp_warn("mschap-v1: user not found\n"); - chap_send_failure(ad); + chap_send_failure(ad, conf_msg_failure); return PWDB_DENIED; } @@ -424,8 +426,7 @@ static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash) struct ev_mppe_keys_t ev_mppe = { .ppp = ad->ppp, - .type = 1 << 2, - .policy = 1, + .policy = -1, .recv_key = digest, .send_key = digest, }; @@ -482,7 +483,7 @@ static void chap_recv(struct ppp_handler_t *h) log_ppp_warn("mschap-v1: unknown code received %x\n", hdr->code); } -static void __init auth_mschap_v1_init() +static void auth_mschap_v1_init() { char *opt; @@ -511,3 +512,4 @@ static void __init auth_mschap_v1_init() log_emerg("mschap-v1: failed to register handler\n"); } +DEFINE_INIT(5, auth_mschap_v1_init); diff --git a/accel-pppd/auth/auth_mschap_v2.c b/accel-pppd/auth/auth_mschap_v2.c index 644f70b..ebcffb7 100644 --- a/accel-pppd/auth/auth_mschap_v2.c +++ b/accel-pppd/auth/auth_mschap_v2.c @@ -31,14 +31,14 @@ #define VALUE_SIZE 16 #define RESPONSE_VALUE_SIZE (16+8+24+1) -#define MSG_FAILURE "E=691 R=0 C=cccccccccccccccccccccccccccccccc V=3 M=Authentication failure" -#define MSG_SUCCESS "S=cccccccccccccccccccccccccccccccccccccccc M=Authentication successed" - #define HDR_LEN (sizeof(struct chap_hdr_t)-2) static int conf_timeout = 5; static int conf_interval = 0; static int conf_max_failure = 3; +static char *conf_msg_failure = "E=691 R=0 V=3"; +static char *conf_msg_failure2 = "Authentication failure"; +static char *conf_msg_success = "Authentication successed"; static int urandom_fd; @@ -69,19 +69,6 @@ struct chap_response_t char name[0]; } __attribute__((packed)); -struct chap_failure_t -{ - struct chap_hdr_t hdr; - char message[sizeof(MSG_FAILURE)]; -} __attribute__((packed)); - -struct chap_success_t -{ - struct chap_hdr_t hdr; - char message[sizeof(MSG_SUCCESS)]; -} __attribute__((packed)); - - struct chap_auth_data_t { struct auth_data_t auth; @@ -211,20 +198,40 @@ static int lcp_recv_conf_req(struct ppp_t *ppp, struct auth_data_t *d, uint8_t * return LCP_OPT_NAK; } -static void chap_send_failure(struct chap_auth_data_t *ad) +static void chap_send_failure(struct chap_auth_data_t *ad, char *mschap_error, char *reply_msg) { - struct chap_failure_t msg = { - .hdr.proto = htons(PPP_CHAP), - .hdr.code = CHAP_FAILURE, - .hdr.id = ad->id, - .hdr.len = htons(sizeof(msg) - 1 - 2), - .message = MSG_FAILURE, - }; + struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(mschap_error) + strlen(reply_msg) + 4); + hdr->proto = htons(PPP_CHAP); + hdr->code = CHAP_FAILURE; + hdr->id = ad->id; + hdr->len = htons(HDR_LEN + strlen(mschap_error) + strlen(reply_msg) + 3); + + sprintf((char *)(hdr + 1), "%s M=%s", mschap_error, reply_msg); if (conf_ppp_verbose) - log_ppp_info2("send [MSCHAP-v2 Failure id=%x \"%s\"]\n", msg.hdr.id, MSG_FAILURE); + log_ppp_info2("send [MSCHAP-v2 Failure id=%x \"%s\"]\n", hdr->id, hdr + 1); - ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); + ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2); + + _free(hdr); +} + +static void chap_send_success(struct chap_auth_data_t *ad, struct chap_response_t *res_msg, const char *authenticator) +{ + struct chap_hdr_t *hdr = _malloc(sizeof(*hdr) + strlen(conf_msg_success) + 1 + 45); + hdr->proto = htons(PPP_CHAP), + hdr->code = CHAP_SUCCESS, + hdr->id = ad->id, + hdr->len = htons(HDR_LEN + strlen(conf_msg_success) + 45), + + sprintf((char *)(hdr + 1), "S=%s M=%s", authenticator, conf_msg_success); + + if (conf_ppp_verbose) + log_ppp_info2("send [MSCHAP-v2 Success id=%x \"%s\"]\n", hdr->id, hdr + 1); + + ppp_chan_send(ad->ppp, hdr, ntohs(hdr->len) + 2); + + _free(hdr); } static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t *msg, const char *name, char *authenticator) @@ -297,24 +304,6 @@ static int generate_response(struct chap_auth_data_t *ad, struct chap_response_t return 0; } -static void chap_send_success(struct chap_auth_data_t *ad, struct chap_response_t *res_msg, const char *authenticator) -{ - struct chap_success_t msg = { - .hdr.proto = htons(PPP_CHAP), - .hdr.code = CHAP_SUCCESS, - .hdr.id = ad->id, - .hdr.len = htons(sizeof(msg) - 1 - 2), - .message = MSG_SUCCESS, - }; - - memcpy(msg.message + 2, authenticator, 40); - - if (conf_ppp_verbose) - log_ppp_info2("send [MSCHAP-v2 Success id=%x \"%s\"]\n", msg.hdr.id, msg.message); - - ppp_chan_send(ad->ppp, &msg, ntohs(msg.hdr.len) + 2); -} - static void chap_send_challenge(struct chap_auth_data_t *ad) { struct chap_challenge_t msg = { @@ -346,6 +335,10 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h char *name; char authenticator[41]; int r; + char *mschap_error = conf_msg_failure; + char *reply_msg = conf_msg_failure2; + + authenticator[40] = 0; if (ad->timeout.tpd) triton_timer_del(&ad->timeout); @@ -368,7 +361,7 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h if (msg->val_size != RESPONSE_VALUE_SIZE) { log_ppp_error("mschap-v2: incorrect value-size (%i)\n", msg->val_size); - chap_send_failure(ad); + chap_send_failure(ad, mschap_error, reply_msg); if (ad->started) ppp_terminate(ad->ppp, TERM_USER_ERROR, 0); else @@ -386,9 +379,9 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h return; } - r = pwdb_check(ad->ppp, name, PPP_CHAP, MSCHAP_V2, ad->id, ad->val, msg->peer_challenge, msg->reserved, msg->nt_hash, msg->flags, authenticator); + r = pwdb_check(ad->ppp, name, PPP_CHAP, MSCHAP_V2, ad->id, ad->val, msg->peer_challenge, msg->reserved, msg->nt_hash, msg->flags, authenticator, &mschap_error, &reply_msg); - if (r == PWDB_NO_IMPL) { + if (r == PWDB_NO_IMPL) { r = chap_check_response(ad, msg, name); if (r) r = PWDB_DENIED; @@ -397,21 +390,28 @@ static void chap_recv_response(struct chap_auth_data_t *ad, struct chap_hdr_t *h } if (r == PWDB_DENIED) { - chap_send_failure(ad); + chap_send_failure(ad, mschap_error, reply_msg); if (ad->started) ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); else ppp_auth_failed(ad->ppp, name); _free(name); } else { - chap_send_success(ad, msg, authenticator); if (!ad->started) { - ad->started = 1; - if (conf_interval) - triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); - ppp_auth_successed(ad->ppp, name); - } else + if (ppp_auth_successed(ad->ppp, name)) { + chap_send_failure(ad, mschap_error, reply_msg); + ppp_terminate(ad->ppp, TERM_AUTH_ERROR, 0); + _free(name); + } else { + chap_send_success(ad, msg, authenticator); + ad->started = 1; + if (conf_interval) + triton_timer_add(ad->ppp->ctrl->ctx, &ad->interval, 0); + } + } else { + chap_send_success(ad, msg, authenticator); _free(name); + } } } @@ -459,38 +459,37 @@ static int chap_check_response(struct chap_auth_data_t *ad, struct chap_response if (!passwd) { if (conf_ppp_verbose) log_ppp_warn("mschap-v2: user not found\n"); - chap_send_failure(ad); + chap_send_failure(ad, conf_msg_failure, conf_msg_failure2); return -1; } - u_passwd=_malloc(strlen(passwd)*2); - for(i=0; i<strlen(passwd); i++) - { + u_passwd = _malloc(strlen(passwd) * 2); + for (i = 0; i < strlen(passwd); i++) { u_passwd[i*2]=passwd[i]; u_passwd[i*2+1]=0; } SHA1_Init(&sha_ctx); - SHA1_Update(&sha_ctx,msg->peer_challenge,16); - SHA1_Update(&sha_ctx,ad->val,16); - SHA1_Update(&sha_ctx,name,strlen(name)); - SHA1_Final(c_hash,&sha_ctx); + SHA1_Update(&sha_ctx, msg->peer_challenge, 16); + SHA1_Update(&sha_ctx, ad->val, 16); + SHA1_Update(&sha_ctx, name, strlen(name)); + SHA1_Final(c_hash, &sha_ctx); - memset(z_hash,0,sizeof(z_hash)); + memset(z_hash, 0, sizeof(z_hash)); MD4_Init(&md4_ctx); - MD4_Update(&md4_ctx,u_passwd,strlen(passwd)*2); - MD4_Final(z_hash,&md4_ctx); + MD4_Update(&md4_ctx, u_passwd, strlen(passwd) * 2); + MD4_Final(z_hash, &md4_ctx); - des_encrypt(c_hash,z_hash,nt_hash); - des_encrypt(c_hash,z_hash+7,nt_hash+8); - des_encrypt(c_hash,z_hash+14,nt_hash+16); + des_encrypt(c_hash, z_hash, nt_hash); + des_encrypt(c_hash, z_hash + 7, nt_hash + 8); + des_encrypt(c_hash, z_hash + 14, nt_hash + 16); set_mppe_keys(ad, z_hash, msg->nt_hash); _free(passwd); _free(u_passwd); - return memcmp(nt_hash,msg->nt_hash,24); + return memcmp(nt_hash, msg->nt_hash, 24); } static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash, uint8_t *nt_hash) @@ -542,8 +541,7 @@ static void set_mppe_keys(struct chap_auth_data_t *ad, uint8_t *z_hash, uint8_t struct ev_mppe_keys_t ev_mppe = { .ppp = ad->ppp, - .type = 1 << 2, - .policy = 1, + .policy = -1, .recv_key = recv_key, .send_key = send_key, }; @@ -622,7 +620,7 @@ static void chap_recv(struct ppp_handler_t *h) log_ppp_warn("mschap-v2: unknown code received %x\n",hdr->code); } -static void __init auth_mschap_v2_init() +static void auth_mschap_v2_init() { urandom_fd = open("/dev/urandom", O_RDONLY); if (urandom_fd < 0) { @@ -634,3 +632,4 @@ static void __init auth_mschap_v2_init() log_emerg("mschap-v2: failed to register handler\n"); } +DEFINE_INIT(4, auth_mschap_v2_init); diff --git a/accel-pppd/auth/auth_pap.c b/accel-pppd/auth/auth_pap.c index 70e8081..e051dd7 100644 --- a/accel-pppd/auth/auth_pap.c +++ b/accel-pppd/auth/auth_pap.c @@ -198,9 +198,14 @@ static int pap_recv_req(struct pap_auth_data_t *p, struct pap_hdr_t *hdr) peer_id = _strndup((const char*)peer_id, peer_id_len); if (conf_any_login) { + if (ppp_auth_successed(p->ppp, peer_id)) { + pap_send_nak(p, hdr->id); + ppp_terminate(p->ppp, TERM_AUTH_ERROR, 0); + _free(peer_id); + return -1; + } pap_send_ack(p, hdr->id); p->started = 1; - ppp_auth_successed(p->ppp, peer_id); return 0; } @@ -223,15 +228,19 @@ static int pap_recv_req(struct pap_auth_data_t *p, struct pap_hdr_t *hdr) ppp_terminate(p->ppp, TERM_AUTH_ERROR, 0); else ppp_auth_failed(p->ppp, peer_id); - ret=-1; + ret = -1; _free(peer_id); } else { - pap_send_ack(p, hdr->id); - if (!p->started) { + if (ppp_auth_successed(p->ppp, peer_id)) { + pap_send_nak(p, hdr->id); + ppp_terminate(p->ppp, TERM_AUTH_ERROR, 0); + _free(peer_id); + ret = -1; + } else { + pap_send_ack(p, hdr->id); p->started = 1; - ppp_auth_successed(p->ppp, peer_id); + ret = 0; } - ret = 0; } _free(passwd); @@ -256,7 +265,7 @@ static void pap_recv(struct ppp_handler_t *h) } } -static void __init auth_pap_init() +static void auth_pap_init() { char *opt; @@ -271,3 +280,4 @@ static void __init auth_pap_init() ppp_auth_register_handler(&pap); } +DEFINE_INIT(7, auth_pap_init); diff --git a/accel-pppd/cli/cli.c b/accel-pppd/cli/cli.c index 5009a74..00d5ffb 100644 --- a/accel-pppd/cli/cli.c +++ b/accel-pppd/cli/cli.c @@ -219,9 +219,11 @@ static void load_config(void) conf_cli_prompt = (char *)def_cli_prompt; } -static void __init init(void) +static void init(void) { load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } + +DEFINE_INIT(10, init); diff --git a/accel-pppd/cli/show_sessions.c b/accel-pppd/cli/show_sessions.c index 555fa88..d7a8a82 100644 --- a/accel-pppd/cli/show_sessions.c +++ b/accel-pppd/cli/show_sessions.c @@ -29,6 +29,7 @@ struct col_t struct list_head entry; struct column_t *column; int width; + int hidden; }; struct row_t @@ -131,6 +132,7 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) int i, n, total_width, def_columns = 0; struct ppp_t *ppp; char *buf = NULL; + int match_key_f = 0, order_key_f = 0; LIST_HEAD(c_list); LIST_HEAD(r_list); LIST_HEAD(t_list); @@ -179,10 +181,15 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) if (ptr2) *ptr2 = 0; column = find_column(ptr1); + if (column == match_key) + match_key_f = 1; + if (column == order_key) + order_key_f = 1; if (column) { col = _malloc(sizeof(*col)); col->column = column; col->width = strlen(column->name); + col->hidden = 0; list_add_tail(&col->entry, &c_list); } else { if (!def_columns) { @@ -197,6 +204,22 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) } _free(columns); + if (match_key && !match_key_f) { + col = _malloc(sizeof(*col)); + col->column = match_key; + col->width = 0; + col->hidden = 1; + list_add_tail(&col->entry, &c_list); + } + + if (order_key && !order_key_f) { + col = _malloc(sizeof(*col)); + col->column = order_key; + col->width = 0; + col->hidden = 1; + list_add_tail(&col->entry, &c_list); + } + pthread_rwlock_rdlock(&ppp_lock); list_for_each_entry(ppp, &ppp_list, entry) { row = _malloc(sizeof(*row)); @@ -244,8 +267,11 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) } total_width = -1; - list_for_each_entry(col, &c_list, entry) + list_for_each_entry(col, &c_list, entry) { + if (col->hidden) + continue; total_width += col->width + 3; + } buf = _malloc(total_width + 3); if (!buf) @@ -253,6 +279,8 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) ptr1 = buf; list_for_each_entry(col, &c_list, entry) { + if (col->hidden) + continue; n = strlen(col->column->name); if (col->width > n + 1) { ptr2 = ptr1; @@ -278,6 +306,8 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) ptr1 = buf; list_for_each_entry(col, &c_list, entry) { + if (col->hidden) + continue; memset(ptr1, '-', col->width + 2); ptr1 += col->width + 2; *ptr1 = '+'; @@ -291,6 +321,8 @@ static int show_ses_exec(const char *cmd, char * const *f, int f_cnt, void *cli) row = list_entry(r_list.next, typeof(*row), entry); ptr1 = buf; list_for_each_entry(cell, &row->cell_list, entry) { + if (cell->col->hidden) + continue; ptr2 = ptr1; sprintf(ptr1, " %s ", cell->buf); ptr1 = strchr(ptr1, 0); @@ -417,7 +449,7 @@ static void print_sid(const struct ppp_t *ppp, char *buf) snprintf(buf, CELL_SIZE, "%s", ppp->sessionid); } -void __init init(void) +static void init(void) { cli_register_simple_cmd2(show_ses_exec, show_ses_help, 2, "show", "sessions"); @@ -432,3 +464,4 @@ void __init init(void) cli_show_ses_register("sid", "session id", print_sid); } +DEFINE_INIT(12, init); diff --git a/accel-pppd/cli/std_cmd.c b/accel-pppd/cli/std_cmd.c index 43407f1..1c8e149 100644 --- a/accel-pppd/cli/std_cmd.c +++ b/accel-pppd/cli/std_cmd.c @@ -16,6 +16,7 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, void *client) { + struct timespec ts; time_t dt; int day,hour; char statm_fname[128]; @@ -33,8 +34,8 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, fclose(f); } - time(&dt); - dt -= triton_stat.start_time; + clock_gettime(CLOCK_MONOTONIC, &ts); + dt = ts.tv_sec - triton_stat.start_time; day = dt / (60 * 60 * 24); dt %= 60 * 60 * 24; hour = dt / (60 * 60); @@ -161,7 +162,7 @@ static int terminate_exec2(int key, char * const *f, int f_cnt, void *cli) list_for_each_entry(ppp, &ppp_list, entry) { switch (key) { case 0: - if (strcmp(ppp->username, f[2])) + if (!ppp->username || strcmp(ppp->username, f[2])) continue; break; case 1: @@ -326,7 +327,7 @@ static void reload_help(char * const *fields, int fields_cnt, void *client) cli_send(client, "reload - reload config file\r\n"); } -static void __init init(void) +static void init(void) { cli_register_simple_cmd2(show_stat_exec, show_stat_help, 2, "show", "stat"); cli_register_simple_cmd2(terminate_exec, terminate_help, 1, "terminate"); @@ -335,3 +336,4 @@ static void __init init(void) cli_register_simple_cmd2(exit_exec, exit_help, 1, "exit"); } +DEFINE_INIT(12, init); diff --git a/accel-pppd/cli/tcp.c b/accel-pppd/cli/tcp.c index 260225f..fea0e4e 100644 --- a/accel-pppd/cli/tcp.c +++ b/accel-pppd/cli/tcp.c @@ -339,7 +339,7 @@ static void start_server(const char *host, int port) triton_context_wakeup(&serv_ctx); } -static void __init init(void) +static void init(void) { const char *opt; char *host, *d; @@ -369,3 +369,4 @@ err_fmt: free(host); } +DEFINE_INIT(11, init); diff --git a/accel-pppd/cli/telnet.c b/accel-pppd/cli/telnet.c index 82bcb0d..2643692 100644 --- a/accel-pppd/cli/telnet.c +++ b/accel-pppd/cli/telnet.c @@ -718,7 +718,7 @@ static void load_history_file(void) fclose(f); } -static void __init init(void) +static void init(void) { const char *opt; char *host, *d; @@ -757,3 +757,4 @@ err_fmt: free(host); } +DEFINE_INIT(11, init); diff --git a/accel-pppd/ctrl/l2tp/dict.c b/accel-pppd/ctrl/l2tp/dict.c index c93ccd4..aaa7da4 100644 --- a/accel-pppd/ctrl/l2tp/dict.c +++ b/accel-pppd/ctrl/l2tp/dict.c @@ -257,7 +257,7 @@ static int l2tp_dict_load(const char *fname) return r; } -static void __init dict_init(void) +static void dict_init(void) { char *opt; @@ -269,3 +269,4 @@ static void __init dict_init(void) _exit(EXIT_FAILURE); } +DEFINE_INIT(20, dict_init); diff --git a/accel-pppd/ctrl/l2tp/l2tp.c b/accel-pppd/ctrl/l2tp/l2tp.c index ca56051..c9ed08e 100644 --- a/accel-pppd/ctrl/l2tp/l2tp.c +++ b/accel-pppd/ctrl/l2tp/l2tp.c @@ -48,6 +48,7 @@ int conf_timeout = 60; int conf_rtimeout = 5; int conf_retransmit = 5; int conf_hello_interval = 60; +int conf_dir300_quirk = 0; char *conf_host_name = NULL; static unsigned int stat_active; @@ -300,6 +301,7 @@ static int l2tp_tunnel_alloc(struct l2tp_serv_t *serv, struct l2tp_packet_t *pac conn->hello_timer.expire = l2tp_send_HELLO; conn->hello_timer.period = conf_hello_interval * 1000; conn->ctrl.ctx = &conn->ctx; + conn->ctrl.type = CTRL_TYPE_L2TP; conn->ctrl.name = "l2tp"; conn->ctrl.started = l2tp_ppp_started; conn->ctrl.finished = l2tp_ppp_finished; @@ -838,7 +840,7 @@ static int l2tp_conn_read(struct triton_md_handler_t *h) if (!pack) continue; - if (ntohs(pack->hdr.tid) != conn->tid) { + if (ntohs(pack->hdr.tid) != conn->tid && (pack->hdr.tid || !conf_dir300_quirk)) { if (conf_verbose) log_warn("l2tp: incorrect tid %i in tunnel %i\n", ntohs(pack->hdr.tid), conn->tid); l2tp_packet_free(pack); @@ -1090,6 +1092,12 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, return CLI_CMD_OK; } +void __export l2tp_get_stat(unsigned int **starting, unsigned int **active) +{ + *starting = &stat_starting; + *active = &stat_active; +} + static void load_config(void) { char *opt; @@ -1121,9 +1129,13 @@ static void load_config(void) conf_host_name = _strdup(opt); else conf_host_name = NULL; + + opt = conf_get_opt("l2tp", "dir300_quirk"); + if (opt) + conf_dir300_quirk = atoi(opt); } -static void __init l2tp_init(void) +static void l2tp_init(void) { l2tp_conn = malloc(L2TP_MAX_TID * sizeof(void *)); memset(l2tp_conn, 0, L2TP_MAX_TID * sizeof(void *)); @@ -1139,3 +1151,4 @@ static void __init l2tp_init(void) triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(22, l2tp_init); diff --git a/accel-pppd/ctrl/l2tp/netlink.c b/accel-pppd/ctrl/l2tp/netlink.c index 7c8c79a..c8dce89 100644 --- a/accel-pppd/ctrl/l2tp/netlink.c +++ b/accel-pppd/ctrl/l2tp/netlink.c @@ -80,7 +80,7 @@ void l2tp_nl_create_session(int tid, int sid, int peer_sid) nl_socket_free(nl_sock); } -static void __init init(void) +static void init(void) { struct nl_sock *nl_sock = nl_socket_alloc(); @@ -92,3 +92,4 @@ static void __init init(void) nl_socket_free(nl_sock); } +DEFINE_INIT(21, init); diff --git a/accel-pppd/ctrl/l2tp/packet.c b/accel-pppd/ctrl/l2tp/packet.c index e3f6896..d312118 100644 --- a/accel-pppd/ctrl/l2tp/packet.c +++ b/accel-pppd/ctrl/l2tp/packet.c @@ -485,10 +485,11 @@ int l2tp_packet_add_octets(struct l2tp_packet_t *pack, int id, const uint8_t *va return 0; } -static void __init init(void) +static void init(void) { attr_pool = mempool_create(sizeof(struct l2tp_attr_t)); pack_pool = mempool_create(sizeof(struct l2tp_packet_t)); buf_pool = mempool_create(L2TP_MAX_PACKET_SIZE); } +DEFINE_INIT(21, init); diff --git a/accel-pppd/ctrl/pppoe/cli.c b/accel-pppd/ctrl/pppoe/cli.c index 9929f66..37aec3a 100644 --- a/accel-pppd/ctrl/pppoe/cli.c +++ b/accel-pppd/ctrl/pppoe/cli.c @@ -189,7 +189,7 @@ static int set_ac_name_exec(const char *cmd, char * const *f, int f_cnt, void *c //=================================== -static void __init init(void) +static void init(void) { cli_register_simple_cmd2(show_stat_exec, NULL, 2, "show", "stat"); cli_register_simple_cmd2(intf_exec, intf_help, 2, "pppoe", "interface"); @@ -203,3 +203,4 @@ static void __init init(void) cli_register_simple_cmd2(show_ac_name_exec, NULL, 3, "pppoe", "show", "AC-Name"); } +DEFINE_INIT(22, init); diff --git a/accel-pppd/ctrl/pppoe/mac_filter.c b/accel-pppd/ctrl/pppoe/mac_filter.c index 9b101c6..8d72c31 100644 --- a/accel-pppd/ctrl/pppoe/mac_filter.c +++ b/accel-pppd/ctrl/pppoe/mac_filter.c @@ -244,7 +244,7 @@ static void cmd_help(char * const *fields, int fields_cnt, void *client) cli_send(client, "pppoe mac-filter show - show current mac-filter list\r\n"); } -static void __init init(void) +static void init(void) { const char *opt = conf_get_opt("pppoe", "mac-filter"); if (!opt || mac_filter_load(opt)) @@ -253,3 +253,4 @@ static void __init init(void) cli_register_simple_cmd2(cmd_exec, cmd_help, 2, "pppoe", "mac-filter"); } +DEFINE_INIT(20, init); diff --git a/accel-pppd/ctrl/pppoe/pppoe.c b/accel-pppd/ctrl/pppoe/pppoe.c index c7612e2..031766b 100644 --- a/accel-pppd/ctrl/pppoe/pppoe.c +++ b/accel-pppd/ctrl/pppoe/pppoe.c @@ -69,10 +69,12 @@ char *conf_service_name; char *conf_ac_name; int conf_ifname_in_sid; char *conf_pado_delay; +int conf_tr101 = 1; static mempool_t conn_pool; static mempool_t pado_pool; +unsigned int stat_starting; unsigned int stat_active; unsigned int stat_delayed_pado; unsigned long stat_PADI_recv; @@ -246,6 +248,7 @@ static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const ui conn->ctrl.started = ppp_started; conn->ctrl.finished = ppp_finished; conn->ctrl.max_mtu = MAX_PPPOE_MTU; + conn->ctrl.type = CTRL_TYPE_PPPOE; conn->ctrl.name = "pppoe"; conn->ctrl.calling_station_id = _malloc(IFNAMSIZ + 19); @@ -857,7 +860,8 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) continue; vendor_id = ntohl(*(uint32_t *)tag->tag_data); if (vendor_id == VENDOR_ADSL_FORUM) - tr101_tag = tag; + if (conf_tr101) + tr101_tag = tag; break; } } @@ -1215,6 +1219,12 @@ void pppoe_server_stop(const char *ifname) pthread_rwlock_unlock(&serv_lock); } +void __export pppoe_get_stat(unsigned int **starting, unsigned int **active) +{ + *starting = &stat_starting; + *active = &stat_active; +} + static int init_secret(struct pppoe_serv_t *serv) { int fd; @@ -1241,7 +1251,57 @@ static int init_secret(struct pppoe_serv_t *serv) return 0; } -static void __init pppoe_init(void) +static void load_config(void) +{ + char *opt; + + opt = conf_get_opt("pppoe", "verbose"); + if (opt) + conf_verbose = atoi(opt); + + opt = conf_get_opt("pppoe", "ac-name"); + if (!opt) + opt = conf_get_opt("pppoe", "AC-Name"); + if (opt) { + if (conf_ac_name) + _free(conf_ac_name); + conf_ac_name = _strdup(opt); + } else + conf_ac_name = _strdup("accel-ppp"); + + opt = conf_get_opt("pppoe", "service-name"); + if (!opt) + opt = conf_get_opt("pppoe", "Service-Name"); + if (opt) { + if (conf_service_name) + _free(conf_service_name); + conf_service_name = _strdup(opt); + } + + opt = conf_get_opt("pppoe", "ifname-in-sid"); + if (opt) { + if (!strcmp(opt, "called-sid")) + conf_ifname_in_sid = 1; + else if (!strcmp(opt, "calling-sid")) + conf_ifname_in_sid = 2; + else if (!strcmp(opt, "both")) + conf_ifname_in_sid = 3; + else if (atoi(opt) >= 0) + conf_ifname_in_sid = atoi(opt); + } + + opt = conf_get_opt("pppoe", "pado-delay"); + if (!opt) + opt = conf_get_opt("pppoe", "PADO-Delay"); + if (opt) + dpado_parse(opt); + + opt = conf_get_opt("pppoe", "tr101"); + if (opt) + conf_tr101 = atoi(opt); +} + +static void pppoe_init(void) { struct conf_sect_t *s = conf_get_section("pppoe"); struct conf_option_t *opt; @@ -1258,33 +1318,12 @@ static void __init pppoe_init(void) if (!strcmp(opt->name, "interface")) { if (opt->val) pppoe_server_start(opt->val, NULL); - } else if (!strcmp(opt->name, "verbose")) { - if (atoi(opt->val) > 0) - conf_verbose = 1; - } else if (!strcmp(opt->name, "ac-name") || !strcmp(opt->name, "AC-Name")) { - if (opt->val && strlen(opt->val)) - conf_ac_name = _strdup(opt->val); - } else if (!strcmp(opt->name, "service-name") || !strcmp(opt->name, "Service-Name")) { - if (opt->val && strlen(opt->val)) - conf_service_name = _strdup(opt->val); - } else if (!strcmp(opt->name, "pado-delay") || !strcmp(opt->name, "PADO-delay")) { - if (dpado_parse(opt->val)) - _exit(EXIT_FAILURE); - } else if (!strcmp(opt->name, "ifname-in-sid")) { - if (!opt->val) - continue; - if (!strcmp(opt->val, "called-sid")) - conf_ifname_in_sid = 1; - else if (!strcmp(opt->val, "calling-sid")) - conf_ifname_in_sid = 2; - else if (!strcmp(opt->val, "both")) - conf_ifname_in_sid = 3; - else if (atoi(opt->val) >= 0) - conf_ifname_in_sid = atoi(opt->val); } } - if (!conf_ac_name) - conf_ac_name = _strdup("accel-ppp"); + load_config(); + + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(21, pppoe_init); diff --git a/accel-pppd/ctrl/pptp/pptp.c b/accel-pppd/ctrl/pptp/pptp.c index 17087fa..715a77b 100644 --- a/accel-pppd/ctrl/pptp/pptp.c +++ b/accel-pppd/ctrl/pptp/pptp.c @@ -402,10 +402,10 @@ static int pptp_echo_rply(struct pptp_conn_t *conn) if (conf_verbose) log_ppp_debug("recv [PPTP Echo-Reply <Identifier %x>]\n", msg->identifier); - if (msg->identifier != conn->echo_sent) { + /*if (msg->identifier != conn->echo_sent) { log_ppp_warn("pptp:echo: identifier mismatch\n"); //return -1; - } + }*/ conn->echo_sent = 0; return 0; } @@ -656,6 +656,7 @@ static int pptp_connect(struct triton_md_handler_t *h) conn->ctrl.started = ppp_started; conn->ctrl.finished = ppp_finished; conn->ctrl.max_mtu = PPTP_MAX_MTU; + conn->ctrl.type = CTRL_TYPE_PPTP; conn->ctrl.name = "pptp"; conn->ctrl.calling_station_id = _malloc(17); @@ -703,6 +704,12 @@ static int show_stat_exec(const char *cmd, char * const *fields, int fields_cnt, return CLI_CMD_OK; } +void __export pptp_get_stat(unsigned int **starting, unsigned int **active) +{ + *starting = &stat_starting; + *active = &stat_active; +} + static void load_config(void) { char *opt; @@ -724,7 +731,7 @@ static void load_config(void) conf_verbose = 1; } -static void __init pptp_init(void) +static void pptp_init(void) { struct sockaddr_in addr; char *opt; @@ -776,3 +783,4 @@ static void __init pptp_init(void) triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(20, pptp_init); diff --git a/accel-pppd/extra/CMakeLists.txt b/accel-pppd/extra/CMakeLists.txt index 03d857a..2144906 100644 --- a/accel-pppd/extra/CMakeLists.txt +++ b/accel-pppd/extra/CMakeLists.txt @@ -17,3 +17,7 @@ IF (SHAPER) INSTALL(TARGETS shaper_tbf LIBRARY DESTINATION lib/accel-ppp) ENDIF (SHAPER) + +IF (NETSNMP) + ADD_SUBDIRECTORY(net-snmp) +ENDIF (NETSNMP) diff --git a/accel-pppd/extra/chap-secrets.c b/accel-pppd/extra/chap-secrets.c index 3a299cc..61cd2a9 100644 --- a/accel-pppd/extra/chap-secrets.c +++ b/accel-pppd/extra/chap-secrets.c @@ -154,11 +154,11 @@ found: } pd->ip.addr = conf_gw_ip_address; - if (n >= 3) + if (n >= 3 && ptr[2][0] != '*') pd->ip.peer_addr = inet_addr(ptr[2]); pd->ip.owner = &ipdb; - if (n == 4) + if (n >= 4) pd->rate = _strdup(ptr[3]); list_add_tail(&pd->pd.entry, &ppp->pd_list); @@ -224,7 +224,7 @@ static struct ipv4db_item_t *get_ip(struct ppp_t *ppp) if (!pd) return NULL; - if (!pd->ip.addr) + if (!pd->ip.peer_addr) return NULL; return &pd->ip; @@ -268,7 +268,7 @@ static void load_config(void) conf_gw_ip_address = inet_addr(opt); } -static void __init init(void) +static void init(void) { load_config(); @@ -280,3 +280,4 @@ static void __init init(void) triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(100, init); diff --git a/accel-pppd/extra/ippool.c b/accel-pppd/extra/ippool.c index 2637c6a..d49f0f4 100644 --- a/accel-pppd/extra/ippool.c +++ b/accel-pppd/extra/ippool.c @@ -182,7 +182,7 @@ static struct ipdb_t ipdb = { .put_ipv4 = put_ip, }; -static void __init ipool_init(void) +static void ippool_init(void) { struct conf_sect_t *s = conf_get_section("ip-pool"); struct conf_option_t *opt; @@ -206,3 +206,5 @@ static void __init ipool_init(void) ipdb_register(&ipdb); } +DEFINE_INIT(101, ippool_init); + diff --git a/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt b/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt new file mode 100644 index 0000000..5af38e8 --- /dev/null +++ b/accel-pppd/extra/net-snmp/ACCEL-PPP-MIB.txt @@ -0,0 +1,326 @@ +ACCEL-PPP-MIB DEFINITIONS ::= BEGIN + +IMPORTS + MODULE-IDENTITY, OBJECT-TYPE, Gauge32 + NOTIFICATION-TYPE FROM SNMPv2-SMI + netSnmp FROM NET-SNMP-MIB + InetAddressIPv4 FROM INET-ADDRESS-MIB + IANAtunnelType FROM IANAifType-MIB +; + +accelPPP MODULE-IDENTITY + LAST-UPDATED "201108180000Z" + ORGANIZATION "accel-ppp.sourceforge.net" + CONTACT-INFO + "email: xeb@mail.ru" + DESCRIPTION + "MIB objects for accel-ppp" + REVISION "201108180000Z" + DESCRIPTION + "First draft" + ::= { netSnmp 100 } + +-- +-- top level structure +-- +accelPPPStat OBJECT IDENTIFIER ::= { accelPPP 1 } +accelPPPSessions OBJECT IDENTIFIER ::= { accelPPP 2 } +accelPPPAdmin OBJECT IDENTIFIER ::= { accelPPP 3 } +--accelPPPNotifications OBJECT IDENTIFIER ::= { accelPPP 4 } + +statCore OBJECT IDENTIFIER ::= { accelPPPStat 1 } +statPPP OBJECT IDENTIFIER ::= { accelPPPStat 2 } +statPPTP OBJECT IDENTIFIER ::= { accelPPPStat 3 } +statL2TP OBJECT IDENTIFIER ::= { accelPPPStat 4 } +statPPPOE OBJECT IDENTIFIER ::= { accelPPPStat 5 } +--statRadius OBJECT IDENTIFIER ::= { accelPPPStat 6 } + + +statCoreUpTime OBJECT-TYPE + SYNTAX Gauge32 + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "accel-ppp uptime" + ::= { statCore 1 } + +statCoreCPU OBJECT-TYPE + SYNTAX INTEGER (0..100) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "cpu utilization" + ::= { statCore 2 } + +statCoreMemRss OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "memory rss size" + ::= { statCore 3 } + + +-- +-- PPP stats +-- + +statPPPStarting OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of sessions which are + in starting phase" + ::= { statPPP 1 } + +statPPPActive OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of active sessions" + ::= { statPPP 2 } + +statPPPFinishing OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of active which are + in finishing phase" + ::= { statPPP 3 } + +-- +-- PPTP stats +-- + +statPPTPStarting OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of connections which are + in starting phase" + ::= { statPPTP 1 } + +statPPTPActive OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of active connections" + ::= { statPPTP 2 } + +-- +-- L2TP stats +-- + +statL2TPStarting OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of connections which are + in starting phase" + ::= { statL2TP 1 } + +statL2TPActive OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of active connections" + ::= { statL2TP 2 } + +-- +-- PPPOE stats +-- + +statPPPOEStarting OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of connections which are + in starting phase" + ::= { statPPPOE 1 } + +statPPPOEActive OBJECT-TYPE + SYNTAX INTEGER + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "count of active connections" + ::= { statPPPOE 2 } + + +-- +-- PPP session table +-- + +sessionTable OBJECT-TYPE + SYNTAX SEQUENCE OF sessionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "this table contains information about + connected sessions" + ::= { accelPPPSessions 1 } + +sessionEntry OBJECT-TYPE + SYNTAX sessionEntry + MAX-ACCESS not-accessible + STATUS current + DESCRIPTION + "A row describing a given session" + INDEX { sesSID } + ::= { sessionTable 1 } + +sessionEntry ::= SEQUENCE { + sesSID OCTET STRING, + sesIfName OCTET STRING, + sesUsername OCTET STRING, + sesIP InetAddress, + sesType IANAtunnelType, + sesState INTEGER, + sesUptime TimeTicks, + sesCallingSID OCTET STRING, + sesCalledSID OCTET STRING +} + +sesSID OBJECT-TYPE + SYNTAX OCTET STRING (SIZE(16)) + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Acct-Session-ID" + ::= { sessionEntry 1 } + +sesIfName OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "name of ppp interface" + ::= { sessionEntry 2 } + +sesUsername OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "session user name" + ::= { sessionEntry 3 } + +sesIP OBJECT-TYPE + SYNTAX InetAddressIPv4 + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "assigned IP address" + ::= { sessionEntry 4 } + +sesType OBJECT-TYPE + SYNTAX INTEGER { + pptp(1), + l2tp(2), + pppoe(3) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "name of ppp interface" + ::= { sessionEntry 5 } + +sesState OBJECT-TYPE + SYNTAX INTEGER { + starting(1), + active(2), + finishing(3) + } + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "state of session" + ::= { sessionEntry 6 } + +sesUptime OBJECT-TYPE + SYNTAX Gauge32 + UNITS "seconds" + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "uptime of session" + ::= { sessionEntry 7 } + +sesCallingSID OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Calling-Station-ID" + ::= { sessionEntry 8 } + +sesCalledSID OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS read-only + STATUS current + DESCRIPTION + "Called-Station-ID" + ::= { sessionEntry 9 } + +-- +-- Administration +-- + +terminate OBJECT IDENTIFIER ::= { accelPPPAdmin 1 } + +termBySID OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS write-only + STATUS current + DESCRIPTION + "Terminate session softly identified by Acct-Session-ID" + ::= { terminate 1 } + +termByIfName OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS write-only + STATUS current + DESCRIPTION + "Terminate session softly identified by interface name" + ::= { terminate 2 } + +termByIP OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS write-only + STATUS current + DESCRIPTION + "Terminate session softly identified by Framed-IP-Address" + ::= { terminate 3 } + +termByUsername OBJECT-TYPE + SYNTAX OCTET STRING + MAX-ACCESS write-only + STATUS current + DESCRIPTION + "Terminate session softly identified by username" + ::= { terminate 4 } + + +shutdown OBJECT-TYPE + SYNTAX INTEGER { + normal(0), + soft(1), + hard(2), + cancel(3) + } + MAX-ACCESS write-only + STATUS current + DESCRIPTION + "shutdown accel-ppp" + ::= { accelPPPAdmin 2 } + +END diff --git a/accel-pppd/extra/net-snmp/CMakeLists.txt b/accel-pppd/extra/net-snmp/CMakeLists.txt new file mode 100644 index 0000000..4dadb2c --- /dev/null +++ b/accel-pppd/extra/net-snmp/CMakeLists.txt @@ -0,0 +1,23 @@ +SET(sources + agent.c + sessionTable.c + sessionTable_data_access.c + sessionTable_data_get.c + sessionTable_data_set.c + sessionTable_interface.c + statCore.c + statL2TP.c + statPPP.c + statPPPOE.c + statPPTP.c + terminate.c + shutdown.c +) + +ADD_LIBRARY(net-snmp SHARED ${sources}) +TARGET_LINK_LIBRARIES(net-snmp netsnmpagent netsnmphelpers netsnmpmibs +netsnmp) + +INSTALL(TARGETS net-snmp + LIBRARY DESTINATION lib/accel-ppp +) diff --git a/accel-pppd/extra/net-snmp/agent.c b/accel-pppd/extra/net-snmp/agent.c new file mode 100644 index 0000000..dd38b44 --- /dev/null +++ b/accel-pppd/extra/net-snmp/agent.c @@ -0,0 +1,150 @@ +#include <pthread.h> +#include <signal.h> + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "log.h" +#include "triton.h" + +#include "statCore.h" +#include "statPPP.h" +#include "statPPTP.h" +#include "statL2TP.h" +#include "statPPPOE.h" +#include "terminate.h" +#include "shutdown.h" +#include "sessionTable.h" + +static const char *conf_agent_name = "accel-ppp"; +static int conf_master = 0; +/*static const char *conf_oid_prefix = "1.3.6.1.4.1.8072.100"; + +static oid* oid_prefix; +static size_t oid_prefix_size;*/ + +static pthread_t snmp_thr; +static int snmp_term = 0; + +/*int accel_ppp_alloc_oid(oid tail, size_t size, oid **oid) +{ + *oid = malloc(sizeof(oid) * (oid_prefix_size + size)); + + memcpy(*oid, oid_prefix, oid_prefix_size); + memcpy((*oid) + oid_prefix_size, tail, size); + + return oid_prefix_size + size; +}*/ + +static int agent_log(int major, int minor, void *serv_arg, void *cl_arg) +{ + struct snmp_log_message *m = serv_arg; + + switch (m->priority) { + case LOG_EMERG: + log_emerg("net-snmp: %s", m->msg); + break; + case LOG_ALERT: + case LOG_CRIT: + case LOG_ERR: + log_error("net-snmp: %s", m->msg); + break; + case LOG_WARNING: + log_warn("net-snmp: %s", m->msg); + break; + case LOG_NOTICE: + log_info1("net-snmp: %s", m->msg); + break; + case LOG_INFO: + log_info2("net-snmp: %s", m->msg); + break; + case LOG_DEBUG: + log_debug("net-snmp: %s", m->msg); + break; + default: + log_msg("net-snmp: %s", m->msg); + } + return 0; +} + +static void *snmp_thread(void *a) +{ + sigset_t set; + + sigfillset(&set); + sigdelset(&set, SIGKILL); + sigdelset(&set, SIGSTOP); + pthread_sigmask(SIG_BLOCK, &set, NULL); + + snmp_register_callback(SNMP_CALLBACK_LIBRARY, SNMP_CALLBACK_LOGGING, agent_log, NULL); + snmp_disable_log(); + snmp_enable_calllog(); + //snmp_set_do_debugging(1); + //netsnmp_ds_set_boolean(NETSNMP_DS_APPLICATION_ID, NETSNMP_DS_AGENT_ROLE, 1); + + if (!conf_master) + netsnmp_enable_subagent(); + + init_agent(conf_agent_name); + + init_statCore(); + init_statPPP(); + init_statPPTP(); + init_statL2TP(); + init_statPPPOE(); + init_terminate(); + init_shutdown(); + init_sessionTable(); + + init_snmp(conf_agent_name); + + if (conf_master) + init_master_agent(); + + while (!snmp_term) { + agent_check_and_process(1); + } + + snmp_shutdown(conf_agent_name); + + SOCK_CLEANUP; + + return NULL; +} + +static void snmp_ctx_close(struct triton_context_t *ctx) +{ + snmp_term = 1; + snmp_shutdown(conf_agent_name); + triton_context_unregister(ctx); +} + +static struct triton_context_t ctx = { + .close = snmp_ctx_close, +}; + +static void init(void) +{ + const char *opt; + + opt = conf_get_opt("snmp", "master"); + if (opt) + conf_master = atoi(opt); + + opt = conf_get_opt("snmp", "agent-name"); + if (opt) + conf_agent_name = opt; + + /*opt = conf_get_opt("snmp", "oid-prefix") + if (opt) + conf_oid_prefix = opt;*/ + + pthread_create(&snmp_thr, NULL, snmp_thread, NULL); + triton_context_register(&ctx, NULL); + triton_context_wakeup(&ctx); + triton_collect_cpu_usage(); +} + +DEFINE_INIT(100, init); + diff --git a/accel-pppd/extra/net-snmp/sessionTable.c b/accel-pppd/extra/net-snmp/sessionTable.c new file mode 100644 index 0000000..dc7d62b --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable.c @@ -0,0 +1,201 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 14170 $ of $ + * + * $Id:$ + */ +/** \page MFD helper for sessionTable + * + * \section intro Introduction + * Introductory text. + * + */ +/* standard Net-SNMP includes */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +/* include our parent header */ +#include "sessionTable.h" + +#include <net-snmp/agent/mib_modules.h> + +#include "sessionTable_interface.h" + +oid sessionTable_oid[] = { SESSIONTABLE_OID }; +int sessionTable_oid_size = OID_LENGTH(sessionTable_oid); + + sessionTable_registration sessionTable_user_context; + +void initialize_table_sessionTable(void); +void shutdown_table_sessionTable(void); + + +/** + * Initializes the sessionTable module + */ +void +init_sessionTable(void) +{ + DEBUGMSGTL(("verbose:sessionTable:init_sessionTable","called\n")); + + /* + * TODO:300:o: Perform sessionTable one-time module initialization. + */ + + /* + * here we initialize all the tables we're planning on supporting + */ + if (should_init("sessionTable")) + initialize_table_sessionTable(); + +} /* init_sessionTable */ + +/** + * Shut-down the sessionTable module (agent is exiting) + */ +void +shutdown_sessionTable(void) +{ + if (should_init("sessionTable")) + shutdown_table_sessionTable(); + +} + +/** + * Initialize the table sessionTable + * (Define its contents and how it's structured) + */ +void +initialize_table_sessionTable(void) +{ + sessionTable_registration * user_context; + u_long flags; + + DEBUGMSGTL(("verbose:sessionTable:initialize_table_sessionTable","called\n")); + + /* + * TODO:301:o: Perform sessionTable one-time table initialization. + */ + + /* + * TODO:302:o: |->Initialize sessionTable user context + * if you'd like to pass in a pointer to some data for this + * table, allocate or set it up here. + */ + /* + * a netsnmp_data_list is a simple way to store void pointers. A simple + * string token is used to add, find or remove pointers. + */ + user_context = netsnmp_create_data_list("sessionTable", NULL, NULL); + + /* + * No support for any flags yet, but in the future you would + * set any flags here. + */ + flags = 0; + + /* + * call interface initialization code + */ + _sessionTable_initialize_interface(user_context, flags); +} /* initialize_table_sessionTable */ + +/** + * Shutdown the table sessionTable + */ +void +shutdown_table_sessionTable(void) +{ + /* + * call interface shutdown code + */ + _sessionTable_shutdown_interface(&sessionTable_user_context); +} + +/** + * extra context initialization (eg default values) + * + * @param rowreq_ctx : row request context + * @param user_init_ctx : void pointer for user (parameter to rowreq_ctx_allocate) + * + * @retval MFD_SUCCESS : no errors + * @retval MFD_ERROR : error (context allocate will fail) + */ +int +sessionTable_rowreq_ctx_init(sessionTable_rowreq_ctx *rowreq_ctx, + void *user_init_ctx) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_rowreq_ctx_init","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + /* + * TODO:210:o: |-> Perform extra sessionTable rowreq initialization. (eg DEFVALS) + */ + + return MFD_SUCCESS; +} /* sessionTable_rowreq_ctx_init */ + +/** + * extra context cleanup + * + */ +void sessionTable_rowreq_ctx_cleanup(sessionTable_rowreq_ctx *rowreq_ctx) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_rowreq_ctx_cleanup","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + /* + * TODO:211:o: |-> Perform extra sessionTable rowreq cleanup. + */ +} /* sessionTable_rowreq_ctx_cleanup */ + +/** + * pre-request callback + * + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : other error + */ +int +sessionTable_pre_request(sessionTable_registration * user_context) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_pre_request","called\n")); + + /* + * TODO:510:o: Perform sessionTable pre-request actions. + */ + + return MFD_SUCCESS; +} /* sessionTable_pre_request */ + +/** + * post-request callback + * + * Note: + * New rows have been inserted into the container, and + * deleted rows have been removed from the container and + * released. + * + * @param user_context + * @param rc : MFD_SUCCESS if all requests succeeded + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : other error (ignored) + */ +int +sessionTable_post_request(sessionTable_registration * user_context, int rc) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_post_request","called\n")); + + /* + * TODO:511:o: Perform sessionTable post-request actions. + */ + + return MFD_SUCCESS; +} /* sessionTable_post_request */ + + +/** @{ */ diff --git a/accel-pppd/extra/net-snmp/sessionTable.h b/accel-pppd/extra/net-snmp/sessionTable.h new file mode 100644 index 0000000..f5619d9 --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable.h @@ -0,0 +1,195 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 14170 $ of $ + * + * $Id:$ + */ +#ifndef SESSIONTABLE_H +#define SESSIONTABLE_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/** @addtogroup misc misc: Miscellaneous routines + * + * @{ + */ +#include <net-snmp/library/asn1.h> + +#include "ppp.h" + +/* other required module components */ + /* *INDENT-OFF* */ +config_add_mib(ACCEL-PPP-MIB) +config_require(ACCEL-PPP-MIB/sessionTable/sessionTable_interface) +config_require(ACCEL-PPP-MIB/sessionTable/sessionTable_data_access) +config_require(ACCEL-PPP-MIB/sessionTable/sessionTable_data_get) +config_require(ACCEL-PPP-MIB/sessionTable/sessionTable_data_set) + /* *INDENT-ON* */ + +/* OID and column number definitions for sessionTable */ +#include "sessionTable_oids.h" + +/* enum definions */ +#include "sessionTable_enums.h" + +/* ********************************************************************* + * function declarations + */ +void init_sessionTable(void); +void shutdown_sessionTable(void); + +/* ********************************************************************* + * Table declarations + */ +/********************************************************************** + ********************************************************************** + *** + *** Table sessionTable + *** + ********************************************************************** + **********************************************************************/ +/* + * ACCEL-PPP-MIB::sessionTable is subid 1 of accelPPPSessions. + * Its status is Current. + * OID: .1.3.6.1.4.1.8072.100.2.1, length: 10 +*/ +/* ********************************************************************* + * When you register your mib, you get to provide a generic + * pointer that will be passed back to you for most of the + * functions calls. + * + * TODO:100:r: Review all context structures + */ + /* + * TODO:101:o: |-> Review sessionTable registration context. + */ +typedef netsnmp_data_list sessionTable_registration; + +/**********************************************************************/ +/* + * TODO:110:r: |-> Review sessionTable data context structure. + * This structure is used to represent the data for sessionTable. + */ +struct sessionTable_data_s +{ + char ifname[PPP_IFNAME_LEN]; + char *username; + in_addr_t peer_addr; + int type; + int state; + unsigned long uptime; + char *calling_sid; + char *called_sid; +}; +typedef struct sessionTable_data_s sessionTable_data; + + +/* + * TODO:120:r: |-> Review sessionTable mib index. + * This structure is used to represent the index for sessionTable. + */ +typedef struct sessionTable_mib_index_s { + + /* + * sesSID(1)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/h + */ + char sesSID[PPP_SESSIONID_LEN]; + size_t sesSID_len; + + +} sessionTable_mib_index; + + /* + * TODO:121:r: | |-> Review sessionTable max index length. + * If you KNOW that your indexes will never exceed a certain + * length, update this macro to that length. + * + * BE VERY CAREFUL TO TAKE INTO ACCOUNT THE MAXIMUM + * POSSIBLE LENGHT FOR EVERY VARIABLE LENGTH INDEX! + * Guessing 128 - col/entry(2) - oid len(10) +*/ +#define MAX_sessionTable_IDX_LEN PPP_SESSIONID_LEN + 1 + + +/* ********************************************************************* + * TODO:130:o: |-> Review sessionTable Row request (rowreq) context. + * When your functions are called, you will be passed a + * sessionTable_rowreq_ctx pointer. + */ +typedef struct sessionTable_rowreq_ctx_s { + + /** this must be first for container compare to work */ + netsnmp_index oid_idx; + oid oid_tmp[MAX_sessionTable_IDX_LEN]; + + sessionTable_mib_index tbl_idx; + + sessionTable_data * data; + + /* + * flags per row. Currently, the first (lower) 8 bits are reserved + * for the user. See mfd.h for other flags. + */ + u_int rowreq_flags; + + /* + * TODO:131:o: | |-> Add useful data to sessionTable rowreq context. + */ + + /* + * storage for future expansion + */ + netsnmp_data_list *sessionTable_data_list; + +} sessionTable_rowreq_ctx; + +typedef struct sessionTable_ref_rowreq_ctx_s { + sessionTable_rowreq_ctx *rowreq_ctx; +} sessionTable_ref_rowreq_ctx; + +/* ********************************************************************* + * function prototypes + */ + int sessionTable_pre_request(sessionTable_registration * user_context); + int sessionTable_post_request(sessionTable_registration * user_context, + int rc); + + int sessionTable_rowreq_ctx_init(sessionTable_rowreq_ctx *rowreq_ctx, + void *user_init_ctx); + void sessionTable_rowreq_ctx_cleanup(sessionTable_rowreq_ctx *rowreq_ctx); + + sessionTable_data * sessionTable_allocate_data(void); + void sessionTable_release_data(sessionTable_data *data); + + + sessionTable_rowreq_ctx * + sessionTable_row_find_by_mib_index(sessionTable_mib_index *mib_idx); + +extern oid sessionTable_oid[]; +extern int sessionTable_oid_size; + + +#include "sessionTable_interface.h" +#include "sessionTable_data_access.h" +#include "sessionTable_data_get.h" +#include "sessionTable_data_set.h" + +/* + * DUMMY markers, ignore + * + * TODO:099:x: ************************************************************* + * TODO:199:x: ************************************************************* + * TODO:299:x: ************************************************************* + * TODO:399:x: ************************************************************* + * TODO:499:x: ************************************************************* + */ + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_H */ +/** @} */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_access.c b/accel-pppd/extra/net-snmp/sessionTable_data_access.c new file mode 100644 index 0000000..847197a --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_data_access.c @@ -0,0 +1,304 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 14170 $ of $ + * + * $Id:$ + */ +/* standard Net-SNMP includes */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +/* include our parent header */ +#include "sessionTable.h" + + +#include "sessionTable_data_access.h" + +#include "ppp.h" + +/** @ingroup interface + * @addtogroup data_access data_access: Routines to access data + * + * These routines are used to locate the data used to satisfy + * requests. + * + * @{ + */ +/********************************************************************** + ********************************************************************** + *** + *** Table sessionTable + *** + ********************************************************************** + **********************************************************************/ +/* + * ACCEL-PPP-MIB::sessionTable is subid 1 of accelPPPSessions. + * Its status is Current. + * OID: .1.3.6.1.4.1.8072.100.2.1, length: 10 +*/ + +/** + * initialization for sessionTable data access + * + * This function is called during startup to allow you to + * allocate any resources you need for the data table. + * + * @param sessionTable_reg + * Pointer to sessionTable_registration + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : unrecoverable error. + */ +int +sessionTable_init_data(sessionTable_registration * sessionTable_reg) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_init_data","called\n")); + + /* + * TODO:303:o: Initialize sessionTable data-> + */ + /* + *************************************************** + *** START EXAMPLE CODE *** + ***---------------------------------------------***/ + /* + * if you are the sole writer for the file, you could + * open it here. However, as stated earlier, we are assuming + * the worst case, which in this case means that the file is + * written to by someone else, and might not even exist when + * we start up. So we can't do anything here. + */ + /* + ***---------------------------------------------*** + *** END EXAMPLE CODE *** + ***************************************************/ + + return MFD_SUCCESS; +} /* sessionTable_init_data */ + +/** + * container overview + * + */ + +/** + * container initialization + * + * @param container_ptr_ptr A pointer to a container pointer. If you + * create a custom container, use this parameter to return it + * to the MFD helper. If set to NULL, the MFD helper will + * allocate a container for you. + * + * This function is called at startup to allow you to customize certain + * aspects of the access method. For the most part, it is for advanced + * users. The default code should suffice for most cases. If no custom + * container is allocated, the MFD code will create one for your. + * + * @remark + * This would also be a good place to do any initialization needed + * for you data source. For example, opening a connection to another + * process that will supply the data, opening a database, etc. + */ +void +sessionTable_container_init(netsnmp_container **container_ptr_ptr, + netsnmp_cache *cache) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_container_init","called\n")); + + if (NULL == container_ptr_ptr) { + snmp_log(LOG_ERR,"bad container param to sessionTable_container_init\n"); + return; + } + + /* + * For advanced users, you can use a custom container. If you + * do not create one, one will be created for you. + */ + *container_ptr_ptr = NULL; + + if (NULL == cache) { + snmp_log(LOG_ERR,"bad cache param to sessionTable_container_init\n"); + return; + } + + /* + * TODO:345:A: Set up sessionTable cache properties. + * + * Also for advanced users, you can set parameters for the + * cache. Do not change the magic pointer, as it is used + * by the MFD helper. To completely disable caching, set + * cache->enabled to 0. + */ + cache->timeout = -1; /* seconds */ +} /* sessionTable_container_init */ + +/** + * container shutdown + * + * @param container_ptr A pointer to the container. + * + * This function is called at shutdown to allow you to customize certain + * aspects of the access method. For the most part, it is for advanced + * users. The default code should suffice for most cases. + * + * This function is called before sessionTable_container_free(). + * + * @remark + * This would also be a good place to do any cleanup needed + * for you data source. For example, closing a connection to another + * process that supplied the data, closing a database, etc. + */ +void +sessionTable_container_shutdown(netsnmp_container *container_ptr) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_container_shutdown","called\n")); + + if (NULL == container_ptr) { + snmp_log(LOG_ERR,"bad params to sessionTable_container_shutdown\n"); + return; + } + +} /* sessionTable_container_shutdown */ + +/** + * load initial data + * + * TODO:350:M: Implement sessionTable data load + * + * @param container container to which items should be inserted + * + * @retval MFD_SUCCESS : success. + * @retval MFD_RESOURCE_UNAVAILABLE : Can't access data source + * @retval MFD_ERROR : other error. + * + * This function is called to load the index(es) (and data, optionally) + * for the every row in the data set. + * + * @remark + * While loading the data, the only important thing is the indexes. + * If access to your data is cheap/fast (e.g. you have a pointer to a + * structure in memory), it would make sense to update the data here. + * If, however, the accessing the data invovles more work (e.g. parsing + * some other existing data, or peforming calculations to derive the data), + * then you can limit yourself to setting the indexes and saving any + * information you will need later. Then use the saved information in + * sessionTable_row_prep() for populating data-> + * + * @note + * If you need consistency between rows (like you want statistics + * for each row to be from the same time frame), you should set all + * data here. + * + */ +int +sessionTable_container_load(netsnmp_container *container) +{ + sessionTable_rowreq_ctx *rowreq_ctx; + size_t count = 0; + struct ppp_t *ppp; + time_t t; + + time(&t); + + DEBUGMSGTL(("verbose:sessionTable:sessionTable_container_load","called\n")); + + pthread_rwlock_rdlock(&ppp_lock); + list_for_each_entry(ppp, &ppp_list, entry) { + rowreq_ctx = sessionTable_allocate_rowreq_ctx(NULL, NULL); + if (NULL == rowreq_ctx) { + pthread_rwlock_unlock(&ppp_lock); + snmp_log(LOG_ERR, "memory allocation failed\n"); + return MFD_RESOURCE_UNAVAILABLE; + } + if(MFD_SUCCESS != sessionTable_indexes_set(rowreq_ctx + , ppp->sessionid, PPP_SESSIONID_LEN + )) { + snmp_log(LOG_ERR,"error setting index while loading " + "sessionTable data->\n"); + sessionTable_release_rowreq_ctx(rowreq_ctx); + continue; + } + + strcpy(rowreq_ctx->data->ifname, ppp->ifname); + + if (ppp->username) + rowreq_ctx->data->username = strdup(ppp->username); + else + ppp->username = strdup(""); + + rowreq_ctx->data->peer_addr = ppp->peer_ipaddr; + rowreq_ctx->data->type = ppp->ctrl->type; + rowreq_ctx->data->state = ppp->state; + rowreq_ctx->data->uptime = (ppp->stop_time ? ppp->stop_time : t) - ppp->start_time; + rowreq_ctx->data->calling_sid = strdup(ppp->ctrl->calling_station_id); + rowreq_ctx->data->called_sid = strdup(ppp->ctrl->called_station_id); + + CONTAINER_INSERT(container, rowreq_ctx); + ++count; + } + pthread_rwlock_unlock(&ppp_lock); + + DEBUGMSGT(("verbose:sessionTable:sessionTable_container_load", + "inserted %d records\n", count)); + + return MFD_SUCCESS; +} /* sessionTable_container_load */ + +/** + * container clean up + * + * @param container container with all current items + * + * This optional callback is called prior to all + * item's being removed from the container. If you + * need to do any processing before that, do it here. + * + * @note + * The MFD helper will take care of releasing all the row contexts. + * If you did not pass a data context pointer when allocating + * the rowreq context, the one that was allocated will be deleted. + * If you did pass one in, it will not be deleted and that memory + * is your responsibility. + * + */ +void +sessionTable_container_free(netsnmp_container *container) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_container_free","called\n")); + + /* + * TODO:380:M: Free sessionTable container data-> + */ +} /* sessionTable_container_free */ + +/** + * prepare row for processing. + * + * When the agent has located the row for a request, this function is + * called to prepare the row for processing. If you fully populated + * the data context during the index setup phase, you may not need to + * do anything. + * + * @param rowreq_ctx pointer to a context. + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : other error. + */ +int +sessionTable_row_prep( sessionTable_rowreq_ctx *rowreq_ctx) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_row_prep","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + /* + * TODO:390:o: Prepare row for request. + * If populating row data was delayed, this is the place to + * fill in the row for this request. + */ + + return MFD_SUCCESS; +} /* sessionTable_row_prep */ + +/** @} */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_access.h b/accel-pppd/extra/net-snmp/sessionTable_data_access.h new file mode 100644 index 0000000..1c420ce --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_data_access.h @@ -0,0 +1,76 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 14170 $ of $ + * + * $Id:$ + */ +#ifndef SESSIONTABLE_DATA_ACCESS_H +#define SESSIONTABLE_DATA_ACCESS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* ********************************************************************* + * function declarations + */ + +/* ********************************************************************* + * Table declarations + */ +/********************************************************************** + ********************************************************************** + *** + *** Table sessionTable + *** + ********************************************************************** + **********************************************************************/ +/* + * ACCEL-PPP-MIB::sessionTable is subid 1 of accelPPPSessions. + * Its status is Current. + * OID: .1.3.6.1.4.1.8072.100.2.1, length: 10 +*/ + + + int sessionTable_init_data(sessionTable_registration * sessionTable_reg); + + + /* + * TODO:180:o: Review sessionTable cache timeout. + * The number of seconds before the cache times out + */ +#define SESSIONTABLE_CACHE_TIMEOUT 60 + +void sessionTable_container_init(netsnmp_container **container_ptr_ptr, + netsnmp_cache *cache); +void sessionTable_container_shutdown(netsnmp_container *container_ptr); + +int sessionTable_container_load(netsnmp_container *container); +void sessionTable_container_free(netsnmp_container *container); + +int sessionTable_cache_load(netsnmp_container *container); +void sessionTable_cache_free(netsnmp_container *container); + + /* + *************************************************** + *** START EXAMPLE CODE *** + ***---------------------------------------------***/ +/* ********************************************************************* + * Since we have no idea how you really access your data, we'll go with + * a worst case example: a flat text file. + */ +#define MAX_LINE_SIZE 256 + /* + ***---------------------------------------------*** + *** END EXAMPLE CODE *** + ***************************************************/ + int sessionTable_row_prep( sessionTable_rowreq_ctx *rowreq_ctx); + + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_DATA_ACCESS_H */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_get.c b/accel-pppd/extra/net-snmp/sessionTable_data_get.c new file mode 100644 index 0000000..1dcea1e --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_data_get.c @@ -0,0 +1,696 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 12088 $ of $ + * + * $Id:$ + */ +/* standard Net-SNMP includes */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +/* include our parent header */ +#include "sessionTable.h" + + +/** @defgroup data_get data_get: Routines to get data + * + * TODO:230:M: Implement sessionTable get routines. + * TODO:240:M: Implement sessionTable mapping routines (if any). + * + * These routine are used to get the value for individual objects. The + * row context is passed, along with a pointer to the memory where the + * value should be copied. + * + * @{ + */ +/********************************************************************** + ********************************************************************** + *** + *** Table sessionTable + *** + ********************************************************************** + **********************************************************************/ +/* + * ACCEL-PPP-MIB::sessionTable is subid 1 of accelPPPSessions. + * Its status is Current. + * OID: .1.3.6.1.4.1.8072.100.2.1, length: 10 +*/ + +/* --------------------------------------------------------------------- + * TODO:200:r: Implement sessionTable data context functions. + */ +/* + * sessionTable_allocate_data + * + * Purpose: create new sessionTable_data-> + */ +sessionTable_data * +sessionTable_allocate_data(void) +{ + sessionTable_data *rtn = SNMP_MALLOC_TYPEDEF(sessionTable_data); + + DEBUGMSGTL(("verbose:sessionTable:sessionTable_allocate_data","called\n")); + + if(NULL == rtn) { + snmp_log(LOG_ERR, "unable to malloc memory for new " + "sessionTable_data->\n"); + } + + memset(rtn, 0, sizeof(*rtn)); + + return rtn; +} /* sessionTable_allocate_data */ + +/* + * sessionTable_release_data + * + * Purpose: release sessionTable data-> + */ +void +sessionTable_release_data(sessionTable_data *data) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_release_data","called\n")); + + if (data->username) + free(data->username); + + if (data->calling_sid) + free(data->calling_sid); + + if (data->called_sid) + free(data->called_sid); + + free(data); +} /* sessionTable_release_data */ + + + +/** + * set mib index(es) + * + * @param tbl_idx mib index structure + * @param sesSID_ptr + * @param sesSID_ptr_len + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : other error. + * + * @remark + * This convenience function is useful for setting all the MIB index + * components with a single function call. It is assume that the C values + * have already been mapped from their native/rawformat to the MIB format. + */ +int +sessionTable_indexes_set_tbl_idx(sessionTable_mib_index *tbl_idx, char *sesSID_val_ptr, size_t sesSID_val_ptr_len) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_indexes_set_tbl_idx","called\n")); + + /* sesSID(1)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/h */ + tbl_idx->sesSID_len = sizeof(tbl_idx->sesSID)/sizeof(tbl_idx->sesSID[0]); /* max length */ + /** WARNING: this code might not work for struct sessionTable_data_s */ + /* + * make sure there is enough space for sesSID data + */ + if ((NULL == tbl_idx->sesSID) || + (tbl_idx->sesSID_len < + (sesSID_val_ptr_len))) { + snmp_log(LOG_ERR,"not enough space for value\n"); + return MFD_ERROR; + } + tbl_idx->sesSID_len = sesSID_val_ptr_len; + memcpy( tbl_idx->sesSID, sesSID_val_ptr, sesSID_val_ptr_len* sizeof(sesSID_val_ptr[0]) ); + + + return MFD_SUCCESS; +} /* sessionTable_indexes_set_tbl_idx */ + +/** + * @internal + * set row context indexes + * + * @param reqreq_ctx the row context that needs updated indexes + * + * @retval MFD_SUCCESS : success. + * @retval MFD_ERROR : other error. + * + * @remark + * This function sets the mib indexs, then updates the oid indexs + * from the mib index. + */ +int +sessionTable_indexes_set(sessionTable_rowreq_ctx *rowreq_ctx, char *sesSID_val_ptr, size_t sesSID_val_ptr_len) +{ + DEBUGMSGTL(("verbose:sessionTable:sessionTable_indexes_set","called\n")); + + if(MFD_SUCCESS != sessionTable_indexes_set_tbl_idx(&rowreq_ctx->tbl_idx + , sesSID_val_ptr, sesSID_val_ptr_len + )) + return MFD_ERROR; + + /* + * convert mib index to oid index + */ + rowreq_ctx->oid_idx.len = sizeof(rowreq_ctx->oid_tmp) / sizeof(oid); + if(0 != sessionTable_index_to_oid(&rowreq_ctx->oid_idx, + &rowreq_ctx->tbl_idx)) { + return MFD_ERROR; + } + + return MFD_SUCCESS; +} /* sessionTable_indexes_set */ + + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesIfName + * sesIfName is subid 2 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.2 + * Description: +name of ppp interface + * + * Attributes: + * accessible 1 isscalar 0 enums 0 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * + * Its syntax is OCTETSTR (based on perltype OCTETSTR) + * The net-snmp type is ASN_OCTET_STR. The C type decl is char (char) + * This data type requires a length. + */ +/** + * Extract the current value of the sesIfName data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesIfName_val_ptr_ptr + * Pointer to storage for a char variable + * @param sesIfName_val_ptr_len_ptr + * Pointer to a size_t. On entry, it will contain the size (in bytes) + * pointed to by sesIfName. + * On exit, this value should contain the data size (in bytes). + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error +* + * @note If you need more than (*sesIfName_val_ptr_len_ptr) bytes of memory, + * allocate it using malloc() and update sesIfName_val_ptr_ptr. + * <b>DO NOT</b> free the previous pointer. + * The MFD helper will release the memory you allocate. + * + * @remark If you call this function yourself, you are responsible + * for checking if the pointer changed, and freeing any + * previously allocated memory. (Not necessary if you pass + * in a pointer to static memory, obviously.) + */ +int +sesIfName_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesIfName_val_ptr_ptr, size_t *sesIfName_val_ptr_len_ptr ) +{ + int len; + /** we should have a non-NULL pointer and enough storage */ + netsnmp_assert( (NULL != sesIfName_val_ptr_ptr) && (NULL != *sesIfName_val_ptr_ptr)); + netsnmp_assert( NULL != sesIfName_val_ptr_len_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesIfName_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + len = strlen(rowreq_ctx->data->ifname); + + if ((NULL == (* sesIfName_val_ptr_ptr )) || + ((* sesIfName_val_ptr_len_ptr ) < len)) { + /* + * allocate space for sesIfName data + */ + (* sesIfName_val_ptr_ptr ) = malloc(len); + if(NULL == (* sesIfName_val_ptr_ptr )) { + snmp_log(LOG_ERR,"could not allocate memory\n"); + return MFD_ERROR; + } + } + (* sesIfName_val_ptr_len_ptr ) = len; + memcpy( (* sesIfName_val_ptr_ptr ), rowreq_ctx->data->ifname, len); + + return MFD_SUCCESS; +} /* sesIfName_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesUsername + * sesUsername is subid 3 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.3 + * Description: +session user name + * + * Attributes: + * accessible 1 isscalar 0 enums 0 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * + * Its syntax is OCTETSTR (based on perltype OCTETSTR) + * The net-snmp type is ASN_OCTET_STR. The C type decl is char (char) + * This data type requires a length. + */ +/** + * Extract the current value of the sesUsername data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesUsername_val_ptr_ptr + * Pointer to storage for a char variable + * @param sesUsername_val_ptr_len_ptr + * Pointer to a size_t. On entry, it will contain the size (in bytes) + * pointed to by sesUsername. + * On exit, this value should contain the data size (in bytes). + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error +* + * @note If you need more than (*sesUsername_val_ptr_len_ptr) bytes of memory, + * allocate it using malloc() and update sesUsername_val_ptr_ptr. + * <b>DO NOT</b> free the previous pointer. + * The MFD helper will release the memory you allocate. + * + * @remark If you call this function yourself, you are responsible + * for checking if the pointer changed, and freeing any + * previously allocated memory. (Not necessary if you pass + * in a pointer to static memory, obviously.) + */ +int +sesUsername_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesUsername_val_ptr_ptr, size_t *sesUsername_val_ptr_len_ptr ) +{ + int len; + /** we should have a non-NULL pointer and enough storage */ + netsnmp_assert( (NULL != sesUsername_val_ptr_ptr) && (NULL != *sesUsername_val_ptr_ptr)); + netsnmp_assert( NULL != sesUsername_val_ptr_len_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesUsername_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + len = strlen(rowreq_ctx->data->username); + + if ((NULL == (* sesUsername_val_ptr_ptr )) || + ((* sesUsername_val_ptr_len_ptr ) < len)) { + /* + * allocate space for sesIfName data + */ + (* sesUsername_val_ptr_ptr ) = malloc(len); + if(NULL == (* sesUsername_val_ptr_ptr )) { + snmp_log(LOG_ERR,"could not allocate memory\n"); + return MFD_ERROR; + } + } + (* sesUsername_val_ptr_len_ptr ) = len; + memcpy( (* sesUsername_val_ptr_ptr ), rowreq_ctx->data->username, len); + + return MFD_SUCCESS; +} /* sesUsername_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesIP + * sesIP is subid 4 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.4 + * Description: +assigned IP address + * + * Attributes: + * accessible 1 isscalar 0 enums 0 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * + * Its syntax is OCTETSTR (based on perltype OCTETSTR) + * The net-snmp type is ASN_OCTET_STR. The C type decl is char (char) + * This data type requires a length. + */ +/** + * Extract the current value of the sesIP data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesIP_val_ptr_ptr + * Pointer to storage for a char variable + * @param sesIP_val_ptr_len_ptr + * Pointer to a size_t. On entry, it will contain the size (in bytes) + * pointed to by sesIP. + * On exit, this value should contain the data size (in bytes). + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error +* + * @note If you need more than (*sesIP_val_ptr_len_ptr) bytes of memory, + * allocate it using malloc() and update sesIP_val_ptr_ptr. + * <b>DO NOT</b> free the previous pointer. + * The MFD helper will release the memory you allocate. + * + * @remark If you call this function yourself, you are responsible + * for checking if the pointer changed, and freeing any + * previously allocated memory. (Not necessary if you pass + * in a pointer to static memory, obviously.) + */ +int +sesIP_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesIP_val_ptr_ptr, size_t *sesIP_val_ptr_len_ptr ) +{ + int len = 4; + /** we should have a non-NULL pointer and enough storage */ + netsnmp_assert( (NULL != sesIP_val_ptr_ptr) && (NULL != *sesIP_val_ptr_ptr)); + netsnmp_assert( NULL != sesIP_val_ptr_len_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesIP_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + if ((NULL == (* sesIP_val_ptr_ptr )) || + ((* sesIP_val_ptr_len_ptr ) < len)) { + /* + * allocate space for sesIfName data + */ + (* sesIP_val_ptr_ptr ) = malloc(len); + if(NULL == (* sesIP_val_ptr_ptr )) { + snmp_log(LOG_ERR,"could not allocate memory\n"); + return MFD_ERROR; + } + } + (* sesIP_val_ptr_len_ptr ) = len; + memcpy( (* sesIP_val_ptr_ptr ), &rowreq_ctx->data->peer_addr, len); + + return MFD_SUCCESS; +} /* sesIP_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesType + * sesType is subid 5 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.5 + * Description: +name of ppp interface + * + * Attributes: + * accessible 1 isscalar 0 enums 1 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * Enum range: 10/16. Values: other(1), direct(2), gre(3), minimal(4), l2tp(5), pptp(6), l2f(7), udp(8), atmp(9), msdp(10), sixToFour(11), sixOverFour(12), isatap(13), teredo(14) + * + * Its syntax is IANAtunnelType (based on perltype INTEGER) + * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long) + */ +/** + * Extract the current value of the sesType data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesType_val_ptr + * Pointer to storage for a long variable + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error + */ +int +sesType_get( sessionTable_rowreq_ctx *rowreq_ctx, u_long * sesType_val_ptr ) +{ + /** we should have a non-NULL pointer */ + netsnmp_assert( NULL != sesType_val_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesType_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + (* sesType_val_ptr ) = rowreq_ctx->data->type; + + return MFD_SUCCESS; +} /* sesType_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesState + * sesState is subid 6 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.6 + * Description: +state of session + * + * Attributes: + * accessible 1 isscalar 0 enums 1 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * Enum range: 3/8. Values: starting(1), active(2), finishing(3) + * + * Its syntax is INTEGER (based on perltype INTEGER) + * The net-snmp type is ASN_INTEGER. The C type decl is long (u_long) + */ +/** + * Extract the current value of the sesState data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesState_val_ptr + * Pointer to storage for a long variable + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error + */ +int +sesState_get( sessionTable_rowreq_ctx *rowreq_ctx, u_long * sesState_val_ptr ) +{ + /** we should have a non-NULL pointer */ + netsnmp_assert( NULL != sesState_val_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesState_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + (* sesState_val_ptr ) = rowreq_ctx->data->state; + + return MFD_SUCCESS; +} /* sesState_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesUptime + * sesUptime is subid 7 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.7 + * Description: +uptime of session + * + * Attributes: + * accessible 1 isscalar 0 enums 0 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * + * Its syntax is TICKS (based on perltype TICKS) + * The net-snmp type is ASN_TIMETICKS. The C type decl is u_long (u_long) + */ +/** + * Extract the current value of the sesUptime data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesUptime_val_ptr + * Pointer to storage for a u_long variable + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error + */ +int +sesUptime_get( sessionTable_rowreq_ctx *rowreq_ctx, u_long * sesUptime_val_ptr ) +{ + /** we should have a non-NULL pointer */ + netsnmp_assert( NULL != sesUptime_val_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesUptime_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + (* sesUptime_val_ptr ) = rowreq_ctx->data->uptime; + + return MFD_SUCCESS; +} /* sesUptime_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesCallingSID + * sesCallingSID is subid 8 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.8 + * Description: +Calling-Station-ID + * + * Attributes: + * accessible 1 isscalar 0 enums 0 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * + * Its syntax is OCTETSTR (based on perltype OCTETSTR) + * The net-snmp type is ASN_OCTET_STR. The C type decl is char (char) + * This data type requires a length. + */ +/** + * Extract the current value of the sesCallingSID data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesCallingSID_val_ptr_ptr + * Pointer to storage for a char variable + * @param sesCallingSID_val_ptr_len_ptr + * Pointer to a size_t. On entry, it will contain the size (in bytes) + * pointed to by sesCallingSID. + * On exit, this value should contain the data size (in bytes). + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error +* + * @note If you need more than (*sesCallingSID_val_ptr_len_ptr) bytes of memory, + * allocate it using malloc() and update sesCallingSID_val_ptr_ptr. + * <b>DO NOT</b> free the previous pointer. + * The MFD helper will release the memory you allocate. + * + * @remark If you call this function yourself, you are responsible + * for checking if the pointer changed, and freeing any + * previously allocated memory. (Not necessary if you pass + * in a pointer to static memory, obviously.) + */ +int +sesCallingSID_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesCallingSID_val_ptr_ptr, size_t *sesCallingSID_val_ptr_len_ptr ) +{ + int len; + /** we should have a non-NULL pointer and enough storage */ + netsnmp_assert( (NULL != sesCallingSID_val_ptr_ptr) && (NULL != *sesCallingSID_val_ptr_ptr)); + netsnmp_assert( NULL != sesCallingSID_val_ptr_len_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesCallingSID_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + len = strlen(rowreq_ctx->data->calling_sid); + + if ((NULL == (* sesCallingSID_val_ptr_ptr )) || + ((* sesCallingSID_val_ptr_len_ptr ) < len)) { + /* + * allocate space for sesCallingSID data + */ + (* sesCallingSID_val_ptr_ptr ) = malloc(len); + if(NULL == (* sesCallingSID_val_ptr_ptr )) { + snmp_log(LOG_ERR,"could not allocate memory\n"); + return MFD_ERROR; + } + } + (* sesCallingSID_val_ptr_len_ptr ) = len; + memcpy( (* sesCallingSID_val_ptr_ptr ), rowreq_ctx->data->calling_sid, len); + + return MFD_SUCCESS; +} /* sesCallingSID_get */ + +/*--------------------------------------------------------------------- + * ACCEL-PPP-MIB::sessionEntry.sesCalledSID + * sesCalledSID is subid 9 of sessionEntry. + * Its status is Current, and its access level is ReadOnly. + * OID: .1.3.6.1.4.1.8072.100.2.1.1.9 + * Description: +Called-Station-ID + * + * Attributes: + * accessible 1 isscalar 0 enums 0 hasdefval 0 + * readable 1 iscolumn 1 ranges 0 hashint 0 + * settable 0 + * + * + * Its syntax is OCTETSTR (based on perltype OCTETSTR) + * The net-snmp type is ASN_OCTET_STR. The C type decl is char (char) + * This data type requires a length. + */ +/** + * Extract the current value of the sesCalledSID data-> + * + * Set a value using the data context for the row. + * + * @param rowreq_ctx + * Pointer to the row request context. + * @param sesCalledSID_val_ptr_ptr + * Pointer to storage for a char variable + * @param sesCalledSID_val_ptr_len_ptr + * Pointer to a size_t. On entry, it will contain the size (in bytes) + * pointed to by sesCalledSID. + * On exit, this value should contain the data size (in bytes). + * + * @retval MFD_SUCCESS : success + * @retval MFD_SKIP : skip this node (no value for now) + * @retval MFD_ERROR : Any other error +* + * @note If you need more than (*sesCalledSID_val_ptr_len_ptr) bytes of memory, + * allocate it using malloc() and update sesCalledSID_val_ptr_ptr. + * <b>DO NOT</b> free the previous pointer. + * The MFD helper will release the memory you allocate. + * + * @remark If you call this function yourself, you are responsible + * for checking if the pointer changed, and freeing any + * previously allocated memory. (Not necessary if you pass + * in a pointer to static memory, obviously.) + */ +int +sesCalledSID_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesCalledSID_val_ptr_ptr, size_t *sesCalledSID_val_ptr_len_ptr ) +{ + int len; + + /** we should have a non-NULL pointer and enough storage */ + netsnmp_assert( (NULL != sesCalledSID_val_ptr_ptr) && (NULL != *sesCalledSID_val_ptr_ptr)); + netsnmp_assert( NULL != sesCalledSID_val_ptr_len_ptr ); + + + DEBUGMSGTL(("verbose:sessionTable:sesCalledSID_get","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + len = strlen(rowreq_ctx->data->called_sid); + + if ((NULL == (* sesCalledSID_val_ptr_ptr )) || + ((* sesCalledSID_val_ptr_len_ptr ) < len)) { + /* + * allocate space for sesCalledSID data + */ + (* sesCalledSID_val_ptr_ptr ) = malloc(len); + if(NULL == (* sesCalledSID_val_ptr_ptr )) { + snmp_log(LOG_ERR,"could not allocate memory\n"); + return MFD_ERROR; + } + } + (* sesCalledSID_val_ptr_len_ptr ) = len; + memcpy( (* sesCalledSID_val_ptr_ptr ), rowreq_ctx->data->called_sid, len); + + return MFD_SUCCESS; +} /* sesCalledSID_get */ + +/** @} */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_get.h b/accel-pppd/extra/net-snmp/sessionTable_data_get.h new file mode 100644 index 0000000..e5a3ae6 --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_data_get.h @@ -0,0 +1,66 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 12088 $ of $ + * + * $Id:$ + * + * @file sessionTable_data_get.h + * + * @addtogroup get + * + * Prototypes for get functions + * + * @{ + */ +#ifndef SESSIONTABLE_DATA_GET_H +#define SESSIONTABLE_DATA_GET_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ********************************************************************* + * GET function declarations + */ + +/* ********************************************************************* + * GET Table declarations + */ +/********************************************************************** + ********************************************************************** + *** + *** Table sessionTable + *** + ********************************************************************** + **********************************************************************/ +/* + * ACCEL-PPP-MIB::sessionTable is subid 1 of accelPPPSessions. + * Its status is Current. + * OID: .1.3.6.1.4.1.8072.100.2.1, length: 10 +*/ + /* + * indexes + */ + + int sesIfName_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesIfName_val_ptr_ptr, size_t *sesIfName_val_ptr_len_ptr ); + int sesUsername_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesUsername_val_ptr_ptr, size_t *sesUsername_val_ptr_len_ptr ); + int sesIP_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesIP_val_ptr_ptr, size_t *sesIP_val_ptr_len_ptr ); + int sesType_get( sessionTable_rowreq_ctx *rowreq_ctx, u_long * sesType_val_ptr ); + int sesState_get( sessionTable_rowreq_ctx *rowreq_ctx, u_long * sesState_val_ptr ); + int sesUptime_get( sessionTable_rowreq_ctx *rowreq_ctx, u_long * sesUptime_val_ptr ); + int sesCallingSID_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesCallingSID_val_ptr_ptr, size_t *sesCallingSID_val_ptr_len_ptr ); + int sesCalledSID_get( sessionTable_rowreq_ctx *rowreq_ctx, char **sesCalledSID_val_ptr_ptr, size_t *sesCalledSID_val_ptr_len_ptr ); + + +int sessionTable_indexes_set_tbl_idx(sessionTable_mib_index *tbl_idx, char *sesSID_val_ptr, size_t sesSID_val_ptr_len); +int sessionTable_indexes_set(sessionTable_rowreq_ctx *rowreq_ctx, char *sesSID_val_ptr, size_t sesSID_val_ptr_len); + + + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_DATA_GET_H */ +/** @} */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_set.c b/accel-pppd/extra/net-snmp/sessionTable_data_set.c new file mode 100644 index 0000000..ebfeeea --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_data_set.c @@ -0,0 +1,24 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 12077 $ of $ + * + * $Id:$ + * + */ +/* standard Net-SNMP includes */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +/* include our parent header */ +#include "sessionTable.h" + + +/** @defgroup data_set data_set: Routines to set data + * + * These routines are used to set the value for individual objects. The + * row context is passed, along with the new value. + * + * @{ + */ +/** @} */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_set.h b/accel-pppd/extra/net-snmp/sessionTable_data_set.h new file mode 100644 index 0000000..70534ba --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_data_set.h @@ -0,0 +1,27 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 12077 $ of $ + * + * $Id:$ + */ +#ifndef SESSIONTABLE_DATA_SET_H +#define SESSIONTABLE_DATA_SET_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* ********************************************************************* + * SET function declarations + */ + +/* ********************************************************************* + * SET Table declarations + */ + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_DATA_SET_H */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_enums.h b/accel-pppd/extra/net-snmp/sessionTable_enums.h new file mode 100644 index 0000000..c7ce845 --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_enums.h @@ -0,0 +1,85 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : generic-table-enums.m2c 12526 2005-07-15 22:41:16Z rstory $ + * + * $Id:$ + */ +#ifndef SESSIONTABLE_ENUMS_H +#define SESSIONTABLE_ENUMS_H + +#ifdef __cplusplus +extern "C" { +#endif + + /* + * NOTES on enums + * ============== + * + * Value Mapping + * ------------- + * If the values for your data type don't exactly match the + * possible values defined by the mib, you should map them + * below. For example, a boolean flag (1/0) is usually represented + * as a TruthValue in a MIB, which maps to the values (1/2). + * + */ +/************************************************************************* + ************************************************************************* + * + * enum definitions for table sessionTable + * + ************************************************************************* + *************************************************************************/ + +/************************************************************* + * constants for enums for the MIB node + * sesType (IANAtunnelType / ASN_INTEGER) + * + * since a Textual Convention may be referenced more than once in a + * MIB, protect againt redefinitions of the enum values. + */ +#ifndef IANATUNNELTYPE_ENUMS +#define IANATUNNELTYPE_ENUMS + +#define IANATUNNELTYPE_OTHER 1 +#define IANATUNNELTYPE_DIRECT 2 +#define IANATUNNELTYPE_GRE 3 +#define IANATUNNELTYPE_MINIMAL 4 +#define IANATUNNELTYPE_L2TP 5 +#define IANATUNNELTYPE_PPTP 6 +#define IANATUNNELTYPE_L2F 7 +#define IANATUNNELTYPE_UDP 8 +#define IANATUNNELTYPE_ATMP 9 +#define IANATUNNELTYPE_MSDP 10 +#define IANATUNNELTYPE_SIXTOFOUR 11 +#define IANATUNNELTYPE_SIXOVERFOUR 12 +#define IANATUNNELTYPE_ISATAP 13 +#define IANATUNNELTYPE_TEREDO 14 + +#endif /* IANATUNNELTYPE_ENUMS */ + + +/************************************************************* + * constants for enums for the MIB node + * sesState (INTEGER / ASN_INTEGER) + * + * since a Textual Convention may be referenced more than once in a + * MIB, protect againt redefinitions of the enum values. + */ +#ifndef SESSTATE_ENUMS +#define SESSTATE_ENUMS + +#define SESSTATE_STARTING 1 +#define SESSTATE_ACTIVE 2 +#define SESSTATE_FINISHING 3 + +#endif /* SESSTATE_ENUMS */ + + + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_ENUMS_H */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_interface.c b/accel-pppd/extra/net-snmp/sessionTable_interface.c new file mode 100644 index 0000000..cf60f91 --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_interface.c @@ -0,0 +1,946 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 15899 $ of $ + * + * $Id:$ + */ +/* + * ********************************************************************* + * ********************************************************************* + * ********************************************************************* + * *** *** + * *** NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE *** + * *** *** + * *** *** + * *** THIS FILE DOES NOT CONTAIN ANY USER EDITABLE CODE. *** + * *** *** + * *** *** + * *** THE GENERATED CODE IS INTERNAL IMPLEMENTATION, AND *** + * *** *** + * *** *** + * *** IS SUBJECT TO CHANGE WITHOUT WARNING IN FUTURE RELEASES. *** + * *** *** + * *** *** + * ********************************************************************* + * ********************************************************************* + * ********************************************************************* + */ + +/* standard Net-SNMP includes */ +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +/* include our parent header */ +#include "sessionTable.h" + + +#include <net-snmp/agent/table_container.h> +#include <net-snmp/library/container.h> + +#include "sessionTable_interface.h" + +#include <ctype.h> + +/********************************************************************** + ********************************************************************** + *** + *** Table sessionTable + *** + ********************************************************************** + **********************************************************************/ +/* + * ACCEL-PPP-MIB::sessionTable is subid 1 of accelPPPSessions. + * Its status is Current. + * OID: .1.3.6.1.4.1.8072.100.2.1, length: 10 +*/ +typedef struct sessionTable_interface_ctx_s { + + netsnmp_container *container; + netsnmp_cache *cache; + + sessionTable_registration * user_ctx; + + netsnmp_table_registration_info tbl_info; + + netsnmp_baby_steps_access_methods access_multiplexer; + +} sessionTable_interface_ctx; + +static sessionTable_interface_ctx sessionTable_if_ctx; + +static void _sessionTable_container_init( + sessionTable_interface_ctx *if_ctx); +static void _sessionTable_container_shutdown( + sessionTable_interface_ctx *if_ctx); + + +netsnmp_container * +sessionTable_container_get( void ) +{ + return sessionTable_if_ctx.container; +} + +sessionTable_registration * +sessionTable_registration_get( void ) +{ + return sessionTable_if_ctx.user_ctx; +} + +sessionTable_registration * +sessionTable_registration_set( sessionTable_registration * newreg ) +{ + sessionTable_registration * old = sessionTable_if_ctx.user_ctx; + sessionTable_if_ctx.user_ctx = newreg; + return old; +} + +int +sessionTable_container_size( void ) +{ + return CONTAINER_SIZE(sessionTable_if_ctx.container); +} + +/* + * mfd multiplexer modes + */ +static Netsnmp_Node_Handler _mfd_sessionTable_pre_request; +static Netsnmp_Node_Handler _mfd_sessionTable_post_request; +static Netsnmp_Node_Handler _mfd_sessionTable_object_lookup; +static Netsnmp_Node_Handler _mfd_sessionTable_get_values; +/** + * @internal + * Initialize the table sessionTable + * (Define its contents and how it's structured) + */ +void +_sessionTable_initialize_interface(sessionTable_registration * reg_ptr, u_long flags) +{ + netsnmp_baby_steps_access_methods *access_multiplexer = + &sessionTable_if_ctx.access_multiplexer; + netsnmp_table_registration_info *tbl_info = &sessionTable_if_ctx.tbl_info; + netsnmp_handler_registration *reginfo; + netsnmp_mib_handler *handler; + int mfd_modes = 0; + + DEBUGMSGTL(("internal:sessionTable:_sessionTable_initialize_interface","called\n")); + + + /************************************************* + * + * save interface context for sessionTable + */ + /* + * Setting up the table's definition + */ + netsnmp_table_helper_add_indexes(tbl_info, + ASN_OCTET_STR, /** index: sesSID */ + 0); + + /* Define the minimum and maximum accessible columns. This + optimizes retrival. */ + tbl_info->min_column = SESSIONTABLE_MIN_COL; + tbl_info->max_column = SESSIONTABLE_MAX_COL; + + /* + * save users context + */ + sessionTable_if_ctx.user_ctx = reg_ptr; + + /* + * call data access initialization code + */ + sessionTable_init_data(reg_ptr); + + /* + * set up the container + */ + _sessionTable_container_init(&sessionTable_if_ctx); + if (NULL == sessionTable_if_ctx.container) { + snmp_log(LOG_ERR,"could not initialize container for sessionTable\n"); + return; + } + + /* + * access_multiplexer: REQUIRED wrapper for get request handling + */ + access_multiplexer->object_lookup = _mfd_sessionTable_object_lookup; + access_multiplexer->get_values = _mfd_sessionTable_get_values; + + /* + * no wrappers yet + */ + access_multiplexer->pre_request = _mfd_sessionTable_pre_request; + access_multiplexer->post_request = _mfd_sessionTable_post_request; + + + /************************************************* + * + * Create a registration, save our reg data, register table. + */ + DEBUGMSGTL(("sessionTable:init_sessionTable", + "Registering sessionTable as a mibs-for-dummies table.\n")); + handler = netsnmp_baby_steps_access_multiplexer_get(access_multiplexer); + reginfo = netsnmp_handler_registration_create("sessionTable", handler, + sessionTable_oid, + sessionTable_oid_size, + HANDLER_CAN_BABY_STEP | + HANDLER_CAN_RONLY + ); + if(NULL == reginfo) { + snmp_log(LOG_ERR,"error registering table sessionTable\n"); + return; + } + reginfo->my_reg_void = &sessionTable_if_ctx; + + /************************************************* + * + * set up baby steps handler, create it and inject it + */ + if( access_multiplexer->object_lookup ) + mfd_modes |= BABY_STEP_OBJECT_LOOKUP; + if( access_multiplexer->set_values ) + mfd_modes |= BABY_STEP_SET_VALUES; + if( access_multiplexer->irreversible_commit ) + mfd_modes |= BABY_STEP_IRREVERSIBLE_COMMIT; + if( access_multiplexer->object_syntax_checks ) + mfd_modes |= BABY_STEP_CHECK_OBJECT; + + if( access_multiplexer->pre_request ) + mfd_modes |= BABY_STEP_PRE_REQUEST; + if( access_multiplexer->post_request ) + mfd_modes |= BABY_STEP_POST_REQUEST; + + if( access_multiplexer->undo_setup ) + mfd_modes |= BABY_STEP_UNDO_SETUP; + if( access_multiplexer->undo_cleanup ) + mfd_modes |= BABY_STEP_UNDO_CLEANUP; + if( access_multiplexer->undo_sets ) + mfd_modes |= BABY_STEP_UNDO_SETS; + + if( access_multiplexer->row_creation ) + mfd_modes |= BABY_STEP_ROW_CREATE; + if( access_multiplexer->consistency_checks ) + mfd_modes |= BABY_STEP_CHECK_CONSISTENCY; + if( access_multiplexer->commit ) + mfd_modes |= BABY_STEP_COMMIT; + if( access_multiplexer->undo_commit ) + mfd_modes |= BABY_STEP_UNDO_COMMIT; + + handler = netsnmp_baby_steps_handler_get(mfd_modes); + netsnmp_inject_handler(reginfo, handler); + + /************************************************* + * + * inject row_merge helper with prefix rootoid_len + 2 (entry.col) + */ + handler = netsnmp_get_row_merge_handler(reginfo->rootoid_len + 2); + netsnmp_inject_handler(reginfo, handler); + + /************************************************* + * + * inject container_table helper + */ + handler = + netsnmp_container_table_handler_get(tbl_info, + sessionTable_if_ctx.container, + TABLE_CONTAINER_KEY_NETSNMP_INDEX); + netsnmp_inject_handler( reginfo, handler ); + + /************************************************* + * + * inject cache helper + */ + if(NULL != sessionTable_if_ctx.cache) { + handler = netsnmp_cache_handler_get(sessionTable_if_ctx.cache); + netsnmp_inject_handler( reginfo, handler ); + } + + /* + * register table + */ + netsnmp_register_table(reginfo, tbl_info); + +} /* _sessionTable_initialize_interface */ + +/** + * @internal + * Shutdown the table sessionTable + */ +void +_sessionTable_shutdown_interface(sessionTable_registration * reg_ptr) +{ + /* + * shutdown the container + */ + _sessionTable_container_shutdown(&sessionTable_if_ctx); +} + +void +sessionTable_valid_columns_set(netsnmp_column_info *vc) +{ + sessionTable_if_ctx.tbl_info.valid_columns = vc; +} /* sessionTable_valid_columns_set */ + +/** + * @internal + * convert the index component stored in the context to an oid + */ +int +sessionTable_index_to_oid(netsnmp_index *oid_idx, + sessionTable_mib_index *mib_idx) +{ + int err = SNMP_ERR_NOERROR; + + /* + * temp storage for parsing indexes + */ + /* + * sesSID(1)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/h + */ + netsnmp_variable_list var_sesSID; + + /* + * set up varbinds + */ + memset( &var_sesSID, 0x00, sizeof(var_sesSID) ); + var_sesSID.type = ASN_OCTET_STR; + + /* + * chain temp index varbinds together + */ + var_sesSID.next_variable = NULL; + + + DEBUGMSGTL(("verbose:sessionTable:sessionTable_index_to_oid","called\n")); + + /* sesSID(1)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/h */ + snmp_set_var_value(&var_sesSID, (u_char*)&mib_idx->sesSID, + mib_idx->sesSID_len * sizeof(mib_idx->sesSID[0])); + + + err = build_oid_noalloc(oid_idx->oids, oid_idx->len, &oid_idx->len, + NULL, 0, &var_sesSID); + if(err) + snmp_log(LOG_ERR,"error %d converting index to oid\n", err); + + /* + * parsing may have allocated memory. free it. + */ + snmp_reset_var_buffers( &var_sesSID ); + + return err; +} /* sessionTable_index_to_oid */ + +/** + * extract sessionTable indexes from a netsnmp_index + * + * @retval SNMP_ERR_NOERROR : no error + * @retval SNMP_ERR_GENERR : error + */ +int +sessionTable_index_from_oid(netsnmp_index *oid_idx, + sessionTable_mib_index *mib_idx) +{ + int err = SNMP_ERR_NOERROR; + + /* + * temp storage for parsing indexes + */ + /* + * sesSID(1)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/h + */ + netsnmp_variable_list var_sesSID; + + /* + * set up varbinds + */ + memset( &var_sesSID, 0x00, sizeof(var_sesSID) ); + var_sesSID.type = ASN_OCTET_STR; + + /* + * chain temp index varbinds together + */ + var_sesSID.next_variable = NULL; + + + DEBUGMSGTL(("verbose:sessionTable:sessionTable_index_from_oid","called\n")); + + /* + * parse the oid into the individual index components + */ + err = parse_oid_indexes( oid_idx->oids, oid_idx->len, + &var_sesSID ); + if (err == SNMP_ERR_NOERROR) { + /* + * copy out values + */ + /* + * NOTE: val_len is in bytes, sesSID_len might not be + */ + if(var_sesSID.val_len > sizeof(mib_idx->sesSID)) + err = SNMP_ERR_GENERR; + else { + memcpy(mib_idx->sesSID, var_sesSID.val.string, var_sesSID.val_len); + mib_idx->sesSID_len = var_sesSID.val_len / sizeof(mib_idx->sesSID[0]); + } + + + } + + /* + * parsing may have allocated memory. free it. + */ + snmp_reset_var_buffers( &var_sesSID ); + + return err; +} /* sessionTable_index_from_oid */ + + +/* ********************************************************************* + * @internal + * allocate resources for a sessionTable_rowreq_ctx + */ +sessionTable_rowreq_ctx * +sessionTable_allocate_rowreq_ctx(sessionTable_data *data, void *user_init_ctx) +{ + sessionTable_rowreq_ctx *rowreq_ctx = + SNMP_MALLOC_TYPEDEF(sessionTable_rowreq_ctx); + + DEBUGMSGTL(("internal:sessionTable:sessionTable_allocate_rowreq_ctx","called\n")); + + if(NULL == rowreq_ctx) { + snmp_log(LOG_ERR,"Couldn't allocate memory for a " + "sessionTable_rowreq_ctx.\n"); + return NULL; + } + else { + if(NULL != data) { + /* + * track if we got data from user + */ + rowreq_ctx->rowreq_flags |= MFD_ROW_DATA_FROM_USER; + rowreq_ctx->data = data; + } + else if (NULL == (rowreq_ctx->data = sessionTable_allocate_data())) { + SNMP_FREE(rowreq_ctx); + return NULL; + } + } + + /* + * undo context will be allocated when needed (in *_undo_setup) + */ + + rowreq_ctx->oid_idx.oids = rowreq_ctx->oid_tmp; + + rowreq_ctx->sessionTable_data_list = NULL; + + /* + * if we allocated data, call init routine + */ + if (!(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER)) { + if(SNMPERR_SUCCESS != + sessionTable_rowreq_ctx_init(rowreq_ctx, user_init_ctx)) { + sessionTable_release_rowreq_ctx(rowreq_ctx); + rowreq_ctx = NULL; + } + } + + return rowreq_ctx; +} /* sessionTable_allocate_rowreq_ctx */ + +/* + * @internal + * release resources for a sessionTable_rowreq_ctx + */ +void +sessionTable_release_rowreq_ctx(sessionTable_rowreq_ctx *rowreq_ctx) +{ + DEBUGMSGTL(("internal:sessionTable:sessionTable_release_rowreq_ctx","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + sessionTable_rowreq_ctx_cleanup(rowreq_ctx); + + /* + * for non-transient data, don't free data we got from the user + */ + if ((rowreq_ctx->data) && + !(rowreq_ctx->rowreq_flags & MFD_ROW_DATA_FROM_USER)) + sessionTable_release_data(rowreq_ctx->data); + + /* + * free index oid pointer + */ + if(rowreq_ctx->oid_idx.oids != rowreq_ctx->oid_tmp) + free(rowreq_ctx->oid_idx.oids); + + SNMP_FREE(rowreq_ctx); +} /* sessionTable_release_rowreq_ctx */ + +/** + * @internal + * wrapper + */ +static int +_mfd_sessionTable_pre_request(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *agtreq_info, + netsnmp_request_info *requests) +{ + int rc; + + DEBUGMSGTL(("internal:sessionTable:_mfd_sessionTable_pre_request", + "called\n")); + + if (1 != netsnmp_row_merge_status_first(reginfo, agtreq_info)) { + DEBUGMSGTL(("internal:sessionTable", + "skipping additional pre_request\n")); + return SNMP_ERR_NOERROR; + } + + rc = sessionTable_pre_request(sessionTable_if_ctx.user_ctx); + if (MFD_SUCCESS != rc) { + /* + * nothing we can do about it but log it + */ + DEBUGMSGTL(("sessionTable","error %d from " + "sessionTable_pre_request\n", rc)); + netsnmp_request_set_error_all(requests, SNMP_VALIDATE_ERR(rc)); + } + + return SNMP_ERR_NOERROR; +} /* _mfd_sessionTable_pre_request */ + +/** + * @internal + * wrapper + */ +static int +_mfd_sessionTable_post_request(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *agtreq_info, + netsnmp_request_info *requests) +{ + sessionTable_rowreq_ctx *rowreq_ctx = + netsnmp_container_table_row_extract(requests); + int rc, packet_rc; + + DEBUGMSGTL(("internal:sessionTable:_mfd_sessionTable_post_request", + "called\n")); + + /* + * release row context, if deleted + */ + if (rowreq_ctx && (rowreq_ctx->rowreq_flags & MFD_ROW_DELETED)) + sessionTable_release_rowreq_ctx(rowreq_ctx); + + /* + * wait for last call before calling user + */ + if (1 != netsnmp_row_merge_status_last(reginfo, agtreq_info)) { + DEBUGMSGTL(("internal:sessionTable", + "waiting for last post_request\n")); + return SNMP_ERR_NOERROR; + } + + packet_rc = netsnmp_check_all_requests_error(agtreq_info->asp, 0); + rc = sessionTable_post_request(sessionTable_if_ctx.user_ctx,packet_rc); + if (MFD_SUCCESS != rc) { + /* + * nothing we can do about it but log it + */ + DEBUGMSGTL(("sessionTable","error %d from " + "sessionTable_post_request\n", rc)); + } + + return SNMP_ERR_NOERROR; +} /* _mfd_sessionTable_post_request */ + +/** + * @internal + * wrapper + */ +static int +_mfd_sessionTable_object_lookup(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *agtreq_info, + netsnmp_request_info *requests) +{ + int rc = SNMP_ERR_NOERROR; + sessionTable_rowreq_ctx *rowreq_ctx = + netsnmp_container_table_row_extract(requests); + + DEBUGMSGTL(("internal:sessionTable:_mfd_sessionTable_object_lookup","called\n")); + + /* + * get our context from mfd + * sessionTable_interface_ctx *if_ctx = + * (sessionTable_interface_ctx *)reginfo->my_reg_void; + */ + + if(NULL == rowreq_ctx) { + rc = SNMP_ERR_NOCREATION; + } + + if (MFD_SUCCESS != rc) + netsnmp_request_set_error_all(requests, rc); + else + sessionTable_row_prep(rowreq_ctx); + + return SNMP_VALIDATE_ERR(rc); +} /* _mfd_sessionTable_object_lookup */ + +/*********************************************************************** + * + * GET processing + * + ***********************************************************************/ +/* + * @internal + * Retrieve the value for a particular column + */ +NETSNMP_STATIC_INLINE int +_sessionTable_get_column( sessionTable_rowreq_ctx *rowreq_ctx, + netsnmp_variable_list *var, int column ) +{ + int rc = SNMPERR_SUCCESS; + + DEBUGMSGTL(("internal:sessionTable:_mfd_sessionTable_get_column", + "called for %d\n", column)); + + + netsnmp_assert(NULL != rowreq_ctx); + + switch(column) { + + /* (INDEX) sesSID(1)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/h */ + case COLUMN_SESSID: + var->type = ASN_OCTET_STR; + /* + * NOTE: val_len is in bytes, sesSID_len might not be (e.g. oids) + */ + if (var->val_len < (rowreq_ctx->tbl_idx.sesSID_len * + sizeof(rowreq_ctx->tbl_idx.sesSID[0]))) { + var->val.string = malloc(rowreq_ctx->tbl_idx.sesSID_len * + sizeof(rowreq_ctx->tbl_idx.sesSID[0])); + } + var->val_len = rowreq_ctx->tbl_idx.sesSID_len * sizeof(rowreq_ctx->tbl_idx.sesSID[0]); + memcpy( var->val.string, rowreq_ctx->tbl_idx.sesSID, var->val_len ); + break; + + /* sesIfName(2)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/r/d/h */ + case COLUMN_SESIFNAME: + var->type = ASN_OCTET_STR; +rc = sesIfName_get(rowreq_ctx, (char **)&var->val.string, &var->val_len ); + break; + + /* sesUsername(3)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/r/d/h */ + case COLUMN_SESUSERNAME: + var->type = ASN_OCTET_STR; +rc = sesUsername_get(rowreq_ctx, (char **)&var->val.string, &var->val_len ); + break; + + /* sesIP(4)/InetAddressIPv4/ASN_OCTET_STR/char(char)//L/A/w/e/R/d/H */ + case COLUMN_SESIP: + var->type = ASN_OCTET_STR; +rc = sesIP_get(rowreq_ctx, (char **)&var->val.string, &var->val_len ); + break; + + /* sesType(5)/INTEGER/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h */ + case COLUMN_SESTYPE: + var->val_len = sizeof(u_long); + var->type = ASN_INTEGER; +rc = sesType_get(rowreq_ctx, (u_long *)var->val.string ); + break; + + /* sesState(6)/INTEGER/ASN_INTEGER/long(u_long)//l/A/w/E/r/d/h */ + case COLUMN_SESSTATE: + var->val_len = sizeof(u_long); + var->type = ASN_INTEGER; +rc = sesState_get(rowreq_ctx, (u_long *)var->val.string ); + break; + + /* sesUptime(7)/GAUGE/ASN_GAUGE/u_long(u_long)//l/A/w/e/r/d/h */ + case COLUMN_SESUPTIME: + var->val_len = sizeof(u_long); + var->type = ASN_GAUGE; +rc = sesUptime_get(rowreq_ctx, (u_long *)var->val.string ); + break; + + /* sesCallingSID(8)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/r/d/h */ + case COLUMN_SESCALLINGSID: + var->type = ASN_OCTET_STR; +rc = sesCallingSID_get(rowreq_ctx, (char **)&var->val.string, &var->val_len ); + break; + + /* sesCalledSID(9)/OCTETSTR/ASN_OCTET_STR/char(char)//L/A/w/e/r/d/h */ + case COLUMN_SESCALLEDSID: + var->type = ASN_OCTET_STR; +rc = sesCalledSID_get(rowreq_ctx, (char **)&var->val.string, &var->val_len ); + break; + + default: + if (SESSIONTABLE_MIN_COL <= column && column <= SESSIONTABLE_MAX_COL) { + DEBUGMSGTL(("internal:sessionTable:_mfd_sessionTable_get_column", + "assume column %d is reserved\n", column)); + rc = MFD_SKIP; + } else { + snmp_log(LOG_ERR, + "unknown column %d in _sessionTable_get_column\n", column); + } + break; + } + + return rc; +} /* _sessionTable_get_column */ + +int +_mfd_sessionTable_get_values(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *agtreq_info, + netsnmp_request_info *requests) +{ + sessionTable_rowreq_ctx *rowreq_ctx = + netsnmp_container_table_row_extract(requests); + netsnmp_table_request_info * tri; + u_char * old_string; + void (*dataFreeHook)(void *); + int rc; + + DEBUGMSGTL(("internal:sessionTable:_mfd_sessionTable_get_values","called\n")); + + netsnmp_assert(NULL != rowreq_ctx); + + for(;requests; requests = requests->next) { + /* + * save old pointer, so we can free it if replaced + */ + old_string = requests->requestvb->val.string; + dataFreeHook = requests->requestvb->dataFreeHook; + if(NULL == requests->requestvb->val.string) { + requests->requestvb->val.string = requests->requestvb->buf; + requests->requestvb->val_len = sizeof(requests->requestvb->buf); + } + else if(requests->requestvb->buf == requests->requestvb->val.string) { + if(requests->requestvb->val_len != sizeof(requests->requestvb->buf)) + requests->requestvb->val_len = sizeof(requests->requestvb->buf); + } + + /* + * get column data + */ + tri = netsnmp_extract_table_info(requests); + if(NULL == tri) + continue; + + rc = _sessionTable_get_column(rowreq_ctx, requests->requestvb, tri->colnum); + if(rc) { + if(MFD_SKIP == rc) { + requests->requestvb->type = SNMP_NOSUCHINSTANCE; + rc = SNMP_ERR_NOERROR; + } + } + else if (NULL == requests->requestvb->val.string) { + snmp_log(LOG_ERR,"NULL varbind data pointer!\n"); + rc = SNMP_ERR_GENERR; + } + if(rc) + netsnmp_request_set_error(requests, SNMP_VALIDATE_ERR(rc)); + + /* + * if the buffer wasn't used previously for the old data (i.e. it + * was allcoated memory) and the get routine replaced the pointer, + * we need to free the previous pointer. + */ + if(old_string && (old_string != requests->requestvb->buf) && + (requests->requestvb->val.string != old_string)) { + if(dataFreeHook) + (*dataFreeHook)(old_string); + else + free(old_string); + } + } /* for results */ + + return SNMP_ERR_NOERROR; +} /* _mfd_sessionTable_get_values */ + + +/*********************************************************************** + * + * SET processing + * + ***********************************************************************/ + +/* + * SET PROCESSING NOT APPLICABLE (per MIB or user setting) + */ +/*********************************************************************** + * + * DATA ACCESS + * + ***********************************************************************/ +static void _container_free(netsnmp_container *container); + +/** + * @internal + */ +static int +_cache_load(netsnmp_cache *cache, void *vmagic) +{ + DEBUGMSGTL(("internal:sessionTable:_cache_load","called\n")); + + if((NULL == cache) || (NULL == cache->magic)) { + snmp_log(LOG_ERR, "invalid cache for sessionTable_cache_load\n"); + return -1; + } + + /** should only be called for an invalid or expired cache */ + netsnmp_assert((0 == cache->valid) || (1 == cache->expired)); + + /* + * call user code + */ + return sessionTable_container_load((netsnmp_container*)cache->magic); +} /* _cache_load */ + +/** + * @internal + */ +static void +_cache_free(netsnmp_cache *cache, void *magic) +{ + netsnmp_container *container; + + DEBUGMSGTL(("internal:sessionTable:_cache_free","called\n")); + + if((NULL == cache) || (NULL == cache->magic)) { + snmp_log(LOG_ERR, "invalid cache in sessionTable_cache_free\n"); + return; + } + + container = (netsnmp_container*)cache->magic; + + _container_free(container); +} /* _cache_free */ + +/** + * @internal + */ +static void +_container_item_free(sessionTable_rowreq_ctx *rowreq_ctx, void *context) +{ + DEBUGMSGTL(("internal:sessionTable:_container_item_free","called\n")); + + if(NULL == rowreq_ctx) + return; + + sessionTable_release_rowreq_ctx(rowreq_ctx); +} /* _container_item_free */ + +/** + * @internal + */ +static void +_container_free(netsnmp_container *container) +{ + DEBUGMSGTL(("internal:sessionTable:_container_free","called\n")); + + if (NULL == container) { + snmp_log(LOG_ERR, "invalid container in sessionTable_container_free\n"); + return; + } + + /* + * call user code + */ + sessionTable_container_free(container); + + /* + * free all items. inefficient, but easy. + */ + CONTAINER_CLEAR(container, + (netsnmp_container_obj_func *)_container_item_free, + NULL); +} /* _container_free */ + +/** + * @internal + * initialize the container with functions or wrappers + */ +void +_sessionTable_container_init(sessionTable_interface_ctx *if_ctx) +{ + DEBUGMSGTL(("internal:sessionTable:_sessionTable_container_init","called\n")); + + /* + * cache init + */ + if_ctx->cache = netsnmp_cache_create(30, /* timeout in seconds */ + _cache_load, _cache_free, + sessionTable_oid, + sessionTable_oid_size); + + if(NULL == if_ctx->cache) { + snmp_log(LOG_ERR, "error creating cache for sessionTable\n"); + return; + } + + if_ctx->cache->flags = NETSNMP_CACHE_DONT_INVALIDATE_ON_SET; + + sessionTable_container_init(&if_ctx->container, if_ctx->cache); + if(NULL == if_ctx->container) + if_ctx->container = netsnmp_container_find("sessionTable:table_container"); + if(NULL == if_ctx->container) { + snmp_log(LOG_ERR,"error creating container in " + "sessionTable_container_init\n"); + return; + } + + if (NULL != if_ctx->cache) + if_ctx->cache->magic = (void*)if_ctx->container; +} /* _sessionTable_container_init */ + +/** + * @internal + * shutdown the container with functions or wrappers + */ +void +_sessionTable_container_shutdown(sessionTable_interface_ctx *if_ctx) +{ + DEBUGMSGTL(("internal:sessionTable:_sessionTable_container_shutdown","called\n")); + + sessionTable_container_shutdown(if_ctx->container); + + _container_free(if_ctx->container); + +} /* _sessionTable_container_shutdown */ + + +sessionTable_rowreq_ctx * +sessionTable_row_find_by_mib_index(sessionTable_mib_index *mib_idx) +{ + sessionTable_rowreq_ctx *rowreq_ctx; + oid oid_tmp[MAX_OID_LEN]; + netsnmp_index oid_idx; + int rc; + + /* + * set up storage for OID + */ + oid_idx.oids = oid_tmp; + oid_idx.len = sizeof(oid_tmp)/sizeof(oid); + + /* + * convert + */ + rc = sessionTable_index_to_oid(&oid_idx, mib_idx); + if (MFD_SUCCESS != rc) + return NULL; + + rowreq_ctx = CONTAINER_FIND(sessionTable_if_ctx.container, &oid_idx); + + return rowreq_ctx; +} + diff --git a/accel-pppd/extra/net-snmp/sessionTable_interface.h b/accel-pppd/extra/net-snmp/sessionTable_interface.h new file mode 100644 index 0000000..ebd1143 --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_interface.h @@ -0,0 +1,84 @@ +/* + * Note: this file originally auto-generated by mib2c using + * version : 15899 $ of $ + * + * $Id:$ + */ +/** @ingroup interface: Routines to interface to Net-SNMP + * + * \warning This code should not be modified, called directly, + * or used to interpret functionality. It is subject to + * change at any time. + * + * @{ + */ +/* + * ********************************************************************* + * ********************************************************************* + * ********************************************************************* + * *** *** + * *** NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE NOTE *** + * *** *** + * *** *** + * *** THIS FILE DOES NOT CONTAIN ANY USER EDITABLE CODE. *** + * *** *** + * *** *** + * *** THE GENERATED CODE IS INTERNAL IMPLEMENTATION, AND *** + * *** *** + * *** *** + * *** IS SUBJECT TO CHANGE WITHOUT WARNING IN FUTURE RELEASES. *** + * *** *** + * *** *** + * ********************************************************************* + * ********************************************************************* + * ********************************************************************* + */ +#ifndef SESSIONTABLE_INTERFACE_H +#define SESSIONTABLE_INTERFACE_H + +#ifdef __cplusplus +extern "C" { +#endif + + +#include "sessionTable.h" + + +/* ******************************************************************** + * Table declarations + */ + +/* PUBLIC interface initialization routine */ +void _sessionTable_initialize_interface(sessionTable_registration * user_ctx, + u_long flags); +void _sessionTable_shutdown_interface(sessionTable_registration * user_ctx); + +sessionTable_registration * +sessionTable_registration_get( void ); + +sessionTable_registration * +sessionTable_registration_set( sessionTable_registration * newreg ); + +netsnmp_container *sessionTable_container_get( void ); +int sessionTable_container_size( void ); + + sessionTable_rowreq_ctx * sessionTable_allocate_rowreq_ctx(sessionTable_data *, void *); +void sessionTable_release_rowreq_ctx(sessionTable_rowreq_ctx *rowreq_ctx); + +int sessionTable_index_to_oid(netsnmp_index *oid_idx, + sessionTable_mib_index *mib_idx); +int sessionTable_index_from_oid(netsnmp_index *oid_idx, + sessionTable_mib_index *mib_idx); + +/* + * access to certain internals. use with caution! + */ +void sessionTable_valid_columns_set(netsnmp_column_info *vc); + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_INTERFACE_H */ +/** @} */ diff --git a/accel-pppd/extra/net-snmp/sessionTable_oids.h b/accel-pppd/extra/net-snmp/sessionTable_oids.h new file mode 100644 index 0000000..42ec6e5 --- /dev/null +++ b/accel-pppd/extra/net-snmp/sessionTable_oids.h @@ -0,0 +1,46 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : generic-table-oids.m2c 12855 2005-09-27 15:56:08Z rstory $ + * + * $Id:$ + */ +#ifndef SESSIONTABLE_OIDS_H +#define SESSIONTABLE_OIDS_H + +#ifdef __cplusplus +extern "C" { +#endif + + +/* column number definitions for table sessionTable */ +#define SESSIONTABLE_OID 1,3,6,1,4,1,8072,100,2,1 + +#define COLUMN_SESSID 1 + +#define COLUMN_SESIFNAME 2 + +#define COLUMN_SESUSERNAME 3 + +#define COLUMN_SESIP 4 + +#define COLUMN_SESTYPE 5 + +#define COLUMN_SESSTATE 6 + +#define COLUMN_SESUPTIME 7 + +#define COLUMN_SESCALLINGSID 8 + +#define COLUMN_SESCALLEDSID 9 + + +#define SESSIONTABLE_MIN_COL COLUMN_SESSID +#define SESSIONTABLE_MAX_COL COLUMN_SESCALLEDSID + + + +#ifdef __cplusplus +} +#endif + +#endif /* SESSIONTABLE_OIDS_H */ diff --git a/accel-pppd/extra/net-snmp/shutdown.c b/accel-pppd/extra/net-snmp/shutdown.c new file mode 100644 index 0000000..82f8540 --- /dev/null +++ b/accel-pppd/extra/net-snmp/shutdown.c @@ -0,0 +1,88 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $ + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include "shutdown.h" + +/** Initializes the shutdown module */ +void +init_shutdown(void) +{ + static oid shutdown_oid[] = { 1,3,6,1,4,1,8072,100,3,2 }; + + DEBUGMSGTL(("shutdown", "Initializing\n")); + + netsnmp_register_scalar( + netsnmp_create_handler_registration("shutdown", handle_shutdown, + shutdown_oid, OID_LENGTH(shutdown_oid), + HANDLER_CAN_RWRITE + )); +} + +int +handle_shutdown(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int ret; + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE ); + break; + + /* + * SET REQUEST + * + * multiple states in the transaction. See: + * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg + */ + case MODE_SET_RESERVE1: + /* or you could use netsnmp_check_vb_type_and_size instead */ + ret = netsnmp_check_vb_type(requests->requestvb, ASN_INTEGER); + if ( ret != SNMP_ERR_NOERROR ) { + netsnmp_set_request_error(reqinfo, requests, ret ); + } + break; + + case MODE_SET_RESERVE2: + /* XXX malloc "undo" storage buffer */ + break; + + case MODE_SET_FREE: + /* XXX: free resources allocated in RESERVE1 and/or + RESERVE2. Something failed somewhere, and the states + below won't be called. */ + break; + + case MODE_SET_ACTION: + /* XXX: perform the value change here */ + break; + + case MODE_SET_COMMIT: + /* XXX: delete temporary storage */ + break; + + case MODE_SET_UNDO: + /* XXX: UNDO and return to previous value for the object */ + break; + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_shutdown\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} diff --git a/accel-pppd/extra/net-snmp/shutdown.h b/accel-pppd/extra/net-snmp/shutdown.h new file mode 100644 index 0000000..02bda94 --- /dev/null +++ b/accel-pppd/extra/net-snmp/shutdown.h @@ -0,0 +1,12 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $ + */ +#ifndef SHUTDOWN_H +#define SHUTDOWN_H + +/* function declarations */ +void init_shutdown(void); +Netsnmp_Node_Handler handle_shutdown; + +#endif /* SHUTDOWN_H */ diff --git a/accel-pppd/extra/net-snmp/statCore.c b/accel-pppd/extra/net-snmp/statCore.c new file mode 100644 index 0000000..74a6b35 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statCore.c @@ -0,0 +1,147 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $ + */ + +#include <time.h> + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "triton.h" +#include "statCore.h" + +/** Initializes the statCore module */ +void +init_statCore(void) +{ + static oid statCoreUpTime_oid[] = { 1,3,6,1,4,1,8072,100,1,1,1 }; + static oid statCoreCPU_oid[] = { 1,3,6,1,4,1,8072,100,1,1,2 }; + static oid statCoreMemRss_oid[] = { 1,3,6,1,4,1,8072,100,1,1,3 }; + + DEBUGMSGTL(("statCore", "Initializing\n")); + + netsnmp_register_scalar( + netsnmp_create_handler_registration("statCoreUpTime", handle_statCoreUpTime, + statCoreUpTime_oid, OID_LENGTH(statCoreUpTime_oid), + HANDLER_CAN_RONLY + )); + netsnmp_register_scalar( + netsnmp_create_handler_registration("statCoreCPU", handle_statCoreCPU, + statCoreCPU_oid, OID_LENGTH(statCoreCPU_oid), + HANDLER_CAN_RONLY + )); + netsnmp_register_scalar( + netsnmp_create_handler_registration("statCoreMemRss", handle_statCoreMemRss, + statCoreMemRss_oid, OID_LENGTH(statCoreMemRss_oid), + HANDLER_CAN_RONLY + )); +} + +int +handle_statCoreUpTime(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + ts.tv_sec -= triton_stat.start_time; + + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + snmp_set_var_typed_value(requests->requestvb, ASN_GAUGE, + (u_char *)&ts.tv_sec /* XXX: a pointer to the scalar's data */, + sizeof(ts.tv_sec)/* XXX: the length of the data in bytes */); + break; + + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_statCoreUpTime\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} +int +handle_statCoreCPU(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, + (u_char *)&triton_stat.cpu /* XXX: a pointer to the scalar's data */, + sizeof(triton_stat.cpu)/* XXX: the length of the data in bytes */); + break; + + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_statCoreCPU\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} +int +handle_statCoreMemRss(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + char statm_fname[128]; + FILE *f; + unsigned long vmsize = 0, vmrss = 0; + unsigned long page_size = sysconf(_SC_PAGE_SIZE); + + sprintf(statm_fname, "/proc/%i/statm", getpid()); + f = fopen(statm_fname, "r"); + if (f) { + fscanf(f, "%lu %lu", &vmsize, &vmrss); + fclose(f); + } + + vmrss *= page_size; + + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + snmp_set_var_typed_value(requests->requestvb, ASN_INTEGER, + (u_char *)&vmrss /* XXX: a pointer to the scalar's data */, + sizeof(vmrss)/* XXX: the length of the data in bytes */); + break; + + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_statCoreMemRss\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} diff --git a/accel-pppd/extra/net-snmp/statCore.h b/accel-pppd/extra/net-snmp/statCore.h new file mode 100644 index 0000000..1a09685 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statCore.h @@ -0,0 +1,14 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $ + */ +#ifndef STATCORE_H +#define STATCORE_H + +/* function declarations */ +void init_statCore(void); +Netsnmp_Node_Handler handle_statCoreUpTime; +Netsnmp_Node_Handler handle_statCoreCPU; +Netsnmp_Node_Handler handle_statCoreMemRss; + +#endif /* STATCORE_H */ diff --git a/accel-pppd/extra/net-snmp/statL2TP.c b/accel-pppd/extra/net-snmp/statL2TP.c new file mode 100644 index 0000000..a91d336 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statL2TP.c @@ -0,0 +1,94 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "triton.h" +#include "statL2TP.h" + + +/* + * The variables we want to tie the relevant OIDs to. + * The agent will handle all GET and (if applicable) SET requests + * to these variables automatically, changing the values as needed. + */ + +void l2tp_get_stat(unsigned int **, unsigned int **); + +static unsigned int *stat_starting; +static unsigned int *stat_active; + +/* + * Our initialization routine, called automatically by the agent + * (Note that the function name must match init_FILENAME()) + */ +void +init_statL2TP(void) +{ + netsnmp_handler_registration *reg; + netsnmp_watcher_info *winfo; + + static oid statL2TPStarting_oid[] = { 1,3,6,1,4,1,8072,100,1,4,1 }; + static oid statL2TPActive_oid[] = { 1,3,6,1,4,1,8072,100,1,4,2 }; + + /* + * a debugging statement. Run the agent with -DstatL2TP to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("statL2TP", "Initializing the statL2TP module\n")); + + if (!triton_module_loaded("l2tp")) + return; + + l2tp_get_stat(&stat_starting, &stat_active); + + /* + * Register scalar watchers for each of the MIB objects. + * The ASN type and RO/RW status are taken from the MIB definition, + * but can be adjusted if needed. + * + * In most circumstances, the scalar watcher will handle all + * of the necessary processing. But the NULL parameter in the + * netsnmp_create_handler_registration() call can be used to + * supply a user-provided handler if necessary. + * + * This approach can also be used to handle Counter64, string- + * and OID-based watched scalars (although variable-sized writeable + * objects will need some more specialised initialisation). + */ + DEBUGMSGTL(("statL2TP", + "Initializing statL2TPStarting scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statL2TPStarting", NULL, + statL2TPStarting_oid, OID_LENGTH(statL2TPStarting_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_starting, sizeof(*stat_starting), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statL2TPStarting" ); + } + + DEBUGMSGTL(("statL2TP", + "Initializing statL2TPActive scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statL2TPActive", NULL, + statL2TPActive_oid, OID_LENGTH(statL2TPActive_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_active, sizeof(*stat_active), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statL2TPActive" ); + } + + + DEBUGMSGTL(("statL2TP", + "Done initalizing statL2TP module\n")); +} diff --git a/accel-pppd/extra/net-snmp/statL2TP.h b/accel-pppd/extra/net-snmp/statL2TP.h new file mode 100644 index 0000000..e038906 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statL2TP.h @@ -0,0 +1,11 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ +#ifndef STATL2TP_H +#define STATL2TP_H + +/* function declarations */ +void init_statL2TP(void); + +#endif /* STATL2TP_H */ diff --git a/accel-pppd/extra/net-snmp/statPPP.c b/accel-pppd/extra/net-snmp/statPPP.c new file mode 100644 index 0000000..7199b57 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statPPP.c @@ -0,0 +1,93 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include "statPPP.h" + +#include "ppp.h" + +/* + * Our initialization routine, called automatically by the agent + * (Note that the function name must match init_FILENAME()) + */ +void +init_statPPP(void) +{ + netsnmp_handler_registration *reg; + netsnmp_watcher_info *winfo; + + static oid statPPPStarting_oid[] = { 1,3,6,1,4,1,8072,100,1,2,1 }; + static oid statPPPActive_oid[] = { 1,3,6,1,4,1,8072,100,1,2,2 }; + static oid statPPPFinishing_oid[] = { 1,3,6,1,4,1,8072,100,1,2,3 }; + + /* + * a debugging statement. Run the agent with -DstatPPP to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("statPPP", "Initializing the statPPP module\n")); + + + /* + * Register scalar watchers for each of the MIB objects. + * The ASN type and RO/RW status are taken from the MIB definition, + * but can be adjusted if needed. + * + * In most circumstances, the scalar watcher will handle all + * of the necessary processing. But the NULL parameter in the + * netsnmp_create_handler_registration() call can be used to + * supply a user-provided handler if necessary. + * + * This approach can also be used to handle Counter64, string- + * and OID-based watched scalars (although variable-sized writeable + * objects will need some more specialised initialisation). + */ + DEBUGMSGTL(("statPPP", + "Initializing statPPPStarting scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPPStarting", NULL, + statPPPStarting_oid, OID_LENGTH(statPPPStarting_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + &ppp_stat.starting, sizeof(ppp_stat.starting), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPPStarting" ); + } + + DEBUGMSGTL(("statPPP", + "Initializing statPPPActive scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPPActive", NULL, + statPPPActive_oid, OID_LENGTH(statPPPActive_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + &ppp_stat.active, sizeof(ppp_stat.active), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPPActive" ); + } + + DEBUGMSGTL(("statPPP", + "Initializing statPPPFinishing scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPPFinishing", NULL, + statPPPFinishing_oid, OID_LENGTH(statPPPFinishing_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + &ppp_stat.finishing, sizeof(ppp_stat.finishing), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPPFinishing" ); + } + + + DEBUGMSGTL(("statPPP", + "Done initalizing statPPP module\n")); +} diff --git a/accel-pppd/extra/net-snmp/statPPP.h b/accel-pppd/extra/net-snmp/statPPP.h new file mode 100644 index 0000000..15a1bf3 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statPPP.h @@ -0,0 +1,11 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ +#ifndef STATPPP_H +#define STATPPP_H + +/* function declarations */ +void init_statPPP(void); + +#endif /* STATPPP_H */ diff --git a/accel-pppd/extra/net-snmp/statPPPOE.c b/accel-pppd/extra/net-snmp/statPPPOE.c new file mode 100644 index 0000000..0ca2dd8 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statPPPOE.c @@ -0,0 +1,93 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "triton.h" +#include "statPPPOE.h" + +/* + * The variables we want to tie the relevant OIDs to. + * The agent will handle all GET and (if applicable) SET requests + * to these variables automatically, changing the values as needed. + */ + +void pppoe_get_stat(unsigned int **, unsigned int **); + +static unsigned int *stat_starting; +static unsigned int *stat_active; + +/* + * Our initialization routine, called automatically by the agent + * (Note that the function name must match init_FILENAME()) + */ +void +init_statPPPOE(void) +{ + netsnmp_handler_registration *reg; + netsnmp_watcher_info *winfo; + + static oid statPPPOEStarting_oid[] = { 1,3,6,1,4,1,8072,100,1,5,1 }; + static oid statPPPOEActive_oid[] = { 1,3,6,1,4,1,8072,100,1,5,2 }; + + /* + * a debugging statement. Run the agent with -DstatPPPOE to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("statPPPOE", "Initializing the statPPPOE module\n")); + + if (!triton_module_loaded("pppoe")) + return; + + pppoe_get_stat(&stat_starting, &stat_active); + + /* + * Register scalar watchers for each of the MIB objects. + * The ASN type and RO/RW status are taken from the MIB definition, + * but can be adjusted if needed. + * + * In most circumstances, the scalar watcher will handle all + * of the necessary processing. But the NULL parameter in the + * netsnmp_create_handler_registration() call can be used to + * supply a user-provided handler if necessary. + * + * This approach can also be used to handle Counter64, string- + * and OID-based watched scalars (although variable-sized writeable + * objects will need some more specialised initialisation). + */ + DEBUGMSGTL(("statPPPOE", + "Initializing statPPPOEStarting scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPPOEStarting", NULL, + statPPPOEStarting_oid, OID_LENGTH(statPPPOEStarting_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_starting, sizeof(*stat_starting), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPPOEStarting" ); + } + + DEBUGMSGTL(("statPPPOE", + "Initializing statPPPOEActive scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPPOEActive", NULL, + statPPPOEActive_oid, OID_LENGTH(statPPPOEActive_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_active, sizeof(*stat_active), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPPOEActive" ); + } + + + DEBUGMSGTL(("statPPPOE", + "Done initalizing statPPPOE module\n")); +} diff --git a/accel-pppd/extra/net-snmp/statPPPOE.h b/accel-pppd/extra/net-snmp/statPPPOE.h new file mode 100644 index 0000000..bb0bcc0 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statPPPOE.h @@ -0,0 +1,11 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ +#ifndef STATPPPOE_H +#define STATPPPOE_H + +/* function declarations */ +void init_statPPPOE(void); + +#endif /* STATPPPOE_H */ diff --git a/accel-pppd/extra/net-snmp/statPPTP.c b/accel-pppd/extra/net-snmp/statPPTP.c new file mode 100644 index 0000000..1a13ad0 --- /dev/null +++ b/accel-pppd/extra/net-snmp/statPPTP.c @@ -0,0 +1,92 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> +#include "statPPTP.h" + +#include "triton.h" + +/* + * The variables we want to tie the relevant OIDs to. + * The agent will handle all GET and (if applicable) SET requests + * to these variables automatically, changing the values as needed. + */ + +void pptp_get_stat(unsigned int **, unsigned int **); + +static unsigned int *stat_starting; +static unsigned int *stat_active; + +/* + * Our initialization routine, called automatically by the agent + * (Note that the function name must match init_FILENAME()) + */ +void +init_statPPTP(void) +{ + netsnmp_handler_registration *reg; + netsnmp_watcher_info *winfo; + + static oid statPPTPStarting_oid[] = { 1,3,6,1,4,1,8072,100,1,3,1 }; + static oid statPPTPActive_oid[] = { 1,3,6,1,4,1,8072,100,1,3,2 }; + + /* + * a debugging statement. Run the agent with -DstatPPTP to see + * the output of this debugging statement. + */ + DEBUGMSGTL(("statPPTP", "Initializing the statPPTP module\n")); + + if (!triton_module_loaded("pptp")) + return; + + pptp_get_stat(&stat_starting, &stat_active); + /* + * Register scalar watchers for each of the MIB objects. + * The ASN type and RO/RW status are taken from the MIB definition, + * but can be adjusted if needed. + * + * In most circumstances, the scalar watcher will handle all + * of the necessary processing. But the NULL parameter in the + * netsnmp_create_handler_registration() call can be used to + * supply a user-provided handler if necessary. + * + * This approach can also be used to handle Counter64, string- + * and OID-based watched scalars (although variable-sized writeable + * objects will need some more specialised initialisation). + */ + DEBUGMSGTL(("statPPTP", + "Initializing statPPTPStarting scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPTPStarting", NULL, + statPPTPStarting_oid, OID_LENGTH(statPPTPStarting_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_starting, sizeof(*stat_starting), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPTPStarting" ); + } + + DEBUGMSGTL(("statPPTP", + "Initializing statPPTPActive scalar integer. Default value = %d\n", + 0)); + reg = netsnmp_create_handler_registration( + "statPPTPActive", NULL, + statPPTPActive_oid, OID_LENGTH(statPPTPActive_oid), + HANDLER_CAN_RONLY); + winfo = netsnmp_create_watcher_info( + stat_active, sizeof(*stat_active), + ASN_INTEGER, WATCHER_FIXED_SIZE); + if (netsnmp_register_watched_scalar( reg, winfo ) < 0 ) { + snmp_log( LOG_ERR, "Failed to register watched statPPTPActive" ); + } + + + DEBUGMSGTL(("statPPTP", + "Done initalizing statPPTP module\n")); +} diff --git a/accel-pppd/extra/net-snmp/statPPTP.h b/accel-pppd/extra/net-snmp/statPPTP.h new file mode 100644 index 0000000..d3a9e0a --- /dev/null +++ b/accel-pppd/extra/net-snmp/statPPTP.h @@ -0,0 +1,11 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.int_watch.conf 13957 2005-12-20 15:33:08Z tanders $ + */ +#ifndef STATPPTP_H +#define STATPPTP_H + +/* function declarations */ +void init_statPPTP(void); + +#endif /* STATPPTP_H */ diff --git a/accel-pppd/extra/net-snmp/terminate.c b/accel-pppd/extra/net-snmp/terminate.c new file mode 100644 index 0000000..bd38577 --- /dev/null +++ b/accel-pppd/extra/net-snmp/terminate.c @@ -0,0 +1,379 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $ + */ + +#include <netinet/in.h> +#include <arpa/inet.h> + +#include <net-snmp/net-snmp-config.h> +#include <net-snmp/net-snmp-includes.h> +#include <net-snmp/agent/net-snmp-agent-includes.h> + +#include "triton.h" +#include "ppp.h" + +#include "terminate.h" + +static void __terminate(struct ppp_t *ppp) +{ + ppp_terminate(ppp, TERM_ADMIN_RESET, 0); +} + +static void terminate_by_sid(const char *val) +{ + struct ppp_t *ppp; + + pthread_rwlock_rdlock(&ppp_lock); + list_for_each_entry(ppp, &ppp_list, entry) { + if (strncmp(ppp->sessionid, val, PPP_SESSIONID_LEN)) + continue; + triton_context_call(ppp->ctrl->ctx, (triton_event_func)__terminate, ppp); + break; + } + pthread_rwlock_unlock(&ppp_lock); +} + +static void terminate_by_ifname(const char *val, size_t len) +{ + struct ppp_t *ppp; + size_t n; + + pthread_rwlock_rdlock(&ppp_lock); + list_for_each_entry(ppp, &ppp_list, entry) { + n = strlen(ppp->ifname); + if (n != len) + continue; + if (strncmp(ppp->ifname, val, len)) + continue; + triton_context_call(ppp->ctrl->ctx, (triton_event_func)__terminate, ppp); + break; + } + pthread_rwlock_unlock(&ppp_lock); +} + +static void terminate_by_ip(const char *val, size_t len) +{ + char str[len + 1]; + in_addr_t addr; + struct ppp_t *ppp; + + strncpy(str, val, len); + str[len] = 0; + + addr = inet_addr(str); + + pthread_rwlock_rdlock(&ppp_lock); + list_for_each_entry(ppp, &ppp_list, entry) { + if (ppp->peer_ipaddr != addr) + continue; + triton_context_call(ppp->ctrl->ctx, (triton_event_func)__terminate, ppp); + break; + } + pthread_rwlock_unlock(&ppp_lock); +} + +static void terminate_by_username(const char *val, size_t len) +{ + struct ppp_t *ppp; + size_t n; + + pthread_rwlock_rdlock(&ppp_lock); + list_for_each_entry(ppp, &ppp_list, entry) { + if (!ppp->username) + continue; + n = strlen(ppp->username); + if (n != len) + continue; + if (strncmp(ppp->username, val, len)) + continue; + triton_context_call(ppp->ctrl->ctx, (triton_event_func)__terminate, ppp); + } + pthread_rwlock_unlock(&ppp_lock); +} + + +/** Initializes the terminate module */ +void +init_terminate(void) +{ + static oid termBySID_oid[] = { 1,3,6,1,4,1,8072,100,3,1,1 }; + static oid termByIfName_oid[] = { 1,3,6,1,4,1,8072,100,3,1,2 }; + static oid termByIP_oid[] = { 1,3,6,1,4,1,8072,100,3,1,3 }; + static oid termByUsername_oid[] = { 1,3,6,1,4,1,8072,100,3,1,4 }; + + DEBUGMSGTL(("terminate", "Initializing\n")); + + netsnmp_register_scalar( + netsnmp_create_handler_registration("termBySID", handle_termBySID, + termBySID_oid, OID_LENGTH(termBySID_oid), + HANDLER_CAN_RWRITE + )); + netsnmp_register_scalar( + netsnmp_create_handler_registration("termByIfName", handle_termByIfName, + termByIfName_oid, OID_LENGTH(termByIfName_oid), + HANDLER_CAN_RWRITE + )); + netsnmp_register_scalar( + netsnmp_create_handler_registration("termByIP", handle_termByIP, + termByIP_oid, OID_LENGTH(termByIP_oid), + HANDLER_CAN_RWRITE + )); + netsnmp_register_scalar( + netsnmp_create_handler_registration("termByUsername", handle_termByUsername, + termByUsername_oid, OID_LENGTH(termByUsername_oid), + HANDLER_CAN_RWRITE + )); +} + +int +handle_termBySID(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int ret; + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE ); + break; + + /* + * SET REQUEST + * + * multiple states in the transaction. See: + * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg + */ + case MODE_SET_RESERVE1: + /* or you could use netsnmp_check_vb_type_and_size instead */ + ret = netsnmp_check_vb_type_and_size(requests->requestvb, ASN_OCTET_STR, PPP_SESSIONID_LEN); + if ( ret != SNMP_ERR_NOERROR ) { + netsnmp_set_request_error(reqinfo, requests, ret ); + } + break; + + case MODE_SET_RESERVE2: + break; + + case MODE_SET_FREE: + /* XXX: free resources allocated in RESERVE1 and/or + RESERVE2. Something failed somewhere, and the states + below won't be called. */ + break; + + case MODE_SET_ACTION: + terminate_by_sid((char *)requests->requestvb->val.string); + /* XXX: perform the value change here */ + break; + + case MODE_SET_COMMIT: + break; + + case MODE_SET_UNDO: + break; + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_termBySID\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} +int +handle_termByIfName(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int ret; + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE ); + break; + + /* + * SET REQUEST + * + * multiple states in the transaction. See: + * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg + */ + case MODE_SET_RESERVE1: + /* or you could use netsnmp_check_vb_type_and_size instead */ + ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR); + if ( ret != SNMP_ERR_NOERROR ) { + netsnmp_set_request_error(reqinfo, requests, ret ); + } + break; + + case MODE_SET_RESERVE2: + /* XXX malloc "undo" storage buffer */ + break; + + case MODE_SET_FREE: + /* XXX: free resources allocated in RESERVE1 and/or + RESERVE2. Something failed somewhere, and the states + below won't be called. */ + break; + + case MODE_SET_ACTION: + terminate_by_ifname((char *)requests->requestvb->val.string, requests->requestvb->val_len); + /* XXX: perform the value change here */ + break; + + case MODE_SET_COMMIT: + break; + + case MODE_SET_UNDO: + break; + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_termByIfName\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} +int +handle_termByIP(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int ret; + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE ); + break; + + /* + * SET REQUEST + * + * multiple states in the transaction. See: + * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg + */ + case MODE_SET_RESERVE1: + /* or you could use netsnmp_check_vb_type_and_size instead */ + ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR); + if ( ret != SNMP_ERR_NOERROR ) { + netsnmp_set_request_error(reqinfo, requests, ret ); + } + break; + + case MODE_SET_RESERVE2: + /* XXX malloc "undo" storage buffer */ + break; + + case MODE_SET_FREE: + /* XXX: free resources allocated in RESERVE1 and/or + RESERVE2. Something failed somewhere, and the states + below won't be called. */ + break; + + case MODE_SET_ACTION: + terminate_by_ip((char *)requests->requestvb->val.string, requests->requestvb->val_len); + /* XXX: perform the value change here */ + break; + + case MODE_SET_COMMIT: + /* XXX: delete temporary storage */ + break; + + case MODE_SET_UNDO: + /* XXX: UNDO and return to previous value for the object */ + break; + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_termByIP\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} +int +handle_termByUsername(netsnmp_mib_handler *handler, + netsnmp_handler_registration *reginfo, + netsnmp_agent_request_info *reqinfo, + netsnmp_request_info *requests) +{ + int ret; + /* We are never called for a GETNEXT if it's registered as a + "instance", as it's "magically" handled for us. */ + + /* a instance handler also only hands us one request at a time, so + we don't need to loop over a list of requests; we'll only get one. */ + + switch(reqinfo->mode) { + + case MODE_GET: + netsnmp_set_request_error(reqinfo, requests, SNMP_NOSUCHINSTANCE ); + break; + + /* + * SET REQUEST + * + * multiple states in the transaction. See: + * http://www.net-snmp.org/tutorial-5/toolkit/mib_module/set-actions.jpg + */ + case MODE_SET_RESERVE1: + /* or you could use netsnmp_check_vb_type_and_size instead */ + ret = netsnmp_check_vb_type(requests->requestvb, ASN_OCTET_STR); + if ( ret != SNMP_ERR_NOERROR ) { + netsnmp_set_request_error(reqinfo, requests, ret ); + } + break; + + case MODE_SET_RESERVE2: + /* XXX malloc "undo" storage buffer */ + break; + + case MODE_SET_FREE: + /* XXX: free resources allocated in RESERVE1 and/or + RESERVE2. Something failed somewhere, and the states + below won't be called. */ + break; + + case MODE_SET_ACTION: + terminate_by_username((char *)requests->requestvb->val.string, requests->requestvb->val_len); + /* XXX: perform the value change here */ + break; + + case MODE_SET_COMMIT: + /* XXX: delete temporary storage */ + break; + + case MODE_SET_UNDO: + /* XXX: UNDO and return to previous value for the object */ + break; + + default: + /* we should never get here, so this is a really bad error */ + snmp_log(LOG_ERR, "unknown mode (%d) in handle_termByUsername\n", reqinfo->mode ); + return SNMP_ERR_GENERR; + } + + return SNMP_ERR_NOERROR; +} diff --git a/accel-pppd/extra/net-snmp/terminate.h b/accel-pppd/extra/net-snmp/terminate.h new file mode 100644 index 0000000..7013182 --- /dev/null +++ b/accel-pppd/extra/net-snmp/terminate.h @@ -0,0 +1,15 @@ +/* + * Note: this file originally auto-generated by mib2c using + * : mib2c.scalar.conf 11805 2005-01-07 09:37:18Z dts12 $ + */ +#ifndef TERMINATE_H +#define TERMINATE_H + +/* function declarations */ +void init_terminate(void); +Netsnmp_Node_Handler handle_termBySID; +Netsnmp_Node_Handler handle_termByIfName; +Netsnmp_Node_Handler handle_termByIP; +Netsnmp_Node_Handler handle_termByUsername; + +#endif /* TERMINATE_H */ diff --git a/accel-pppd/extra/pppd_compat.c b/accel-pppd/extra/pppd_compat.c index 5fa9beb..aa6f6b5 100644 --- a/accel-pppd/extra/pppd_compat.c +++ b/accel-pppd/extra/pppd_compat.c @@ -497,7 +497,7 @@ static void fill_env(char **env, struct pppd_compat_pd_t *pd) } } -static void __init init(void) +static void init(void) { char *opt; @@ -537,3 +537,5 @@ static void __init init(void) } #endif } + +DEFINE_INIT(101, init); diff --git a/accel-pppd/extra/shaper_tbf.c b/accel-pppd/extra/shaper_tbf.c index cc0ff22..6060027 100644 --- a/accel-pppd/extra/shaper_tbf.c +++ b/accel-pppd/extra/shaper_tbf.c @@ -48,6 +48,7 @@ static int temp_up_speed; static pthread_rwlock_t shaper_lock = PTHREAD_RWLOCK_INITIALIZER; static LIST_HEAD(shaper_list); +static pthread_mutex_t nl_lock = PTHREAD_MUTEX_INITIALIZER; static double tick_in_usec = 1; static double clock_factor = 1; @@ -87,7 +88,7 @@ struct time_range_t static void *pd_key; static LIST_HEAD(time_range_list); -static int time_range_id; +static int time_range_id = 0; static void shaper_ctx_close(struct triton_context_t *); static struct triton_context_t shaper_ctx = { @@ -384,11 +385,14 @@ static int install_shaper(const char *ifname, int down_speed, int down_burst, in strcpy(ifr.ifr_name, ifname); if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) { - log_ppp_error("tbf: ioctl(SIOCGIFINDEX)", strerror(errno)); + log_ppp_error("tbf: ioctl(SIOCGIFINDEX): %s\n", strerror(errno)); return -1; } + pthread_mutex_lock(&nl_lock); h = nl_socket_alloc(); + pthread_mutex_unlock(&nl_lock); + if (!h) { log_ppp_error("tbf: nl_socket_alloc failed\n"); return -1; @@ -396,7 +400,7 @@ static int install_shaper(const char *ifname, int down_speed, int down_burst, in err = nl_connect(h, NETLINK_ROUTE); if (err < 0) { - log_ppp_error("tbf: nl_connect: %s", strerror(errno)); + log_ppp_error("tbf: nl_connect: %s\n", strerror(errno)); goto out; } @@ -413,7 +417,10 @@ static int install_shaper(const char *ifname, int down_speed, int down_burst, in nl_close(h); out: + + pthread_mutex_lock(&nl_lock); nl_socket_free(h); + pthread_mutex_unlock(&nl_lock); return 0; } @@ -463,7 +470,7 @@ static int remove_shaper(const char *ifname) strcpy(ifr.ifr_name, ifname); if (ioctl(sock_fd, SIOCGIFINDEX, &ifr)) { - log_ppp_error("tbf: ioctl(SIOCGIFINDEX)", strerror(errno)); + log_ppp_error("tbf: ioctl(SIOCGIFINDEX): %s\n", strerror(errno)); return -1; } @@ -481,7 +488,10 @@ static int remove_shaper(const char *ifname) .tcm_parent = TC_H_INGRESS, }; + pthread_mutex_lock(&nl_lock); h = nl_socket_alloc(); + pthread_mutex_unlock(&nl_lock); + if (!h) { log_ppp_error("tbf: nl_socket_alloc failed\n"); return -1; @@ -489,9 +499,8 @@ static int remove_shaper(const char *ifname) err = nl_connect(h, NETLINK_ROUTE); if (err < 0) { - log_ppp_error("tbf: nl_connect: %s", strerror(errno)); - nl_socket_free(h); - return -1; + log_ppp_error("tbf: nl_connect: %s\n", strerror(errno)); + goto out_err1; } pmsg = nlmsg_alloc_simple(RTM_DELQDISC, NLM_F_CREATE | NLM_F_REPLACE); @@ -525,17 +534,25 @@ static int remove_shaper(const char *ifname) nlmsg_free(pmsg); nl_close(h); + + pthread_mutex_lock(&nl_lock); nl_socket_free(h); + pthread_mutex_unlock(&nl_lock); + return 0; out_err: - log_ppp_error("tbf: failed to remove shaper\n"); - if (pmsg) nlmsg_free(pmsg); nl_close(h); + +out_err1: + pthread_mutex_lock(&nl_lock); nl_socket_free(h); + pthread_mutex_unlock(&nl_lock); + + log_ppp_error("tbf: failed to remove shaper\n"); return -1; } @@ -619,7 +636,7 @@ static struct time_range_pd_t *get_tr_pd(struct shaper_pd_t *pd, int id) memset(tr_pd, 0, sizeof(*tr_pd)); tr_pd->id = id; - if (id == time_range_id) + if (id == time_range_id || id == 0) pd->cur_tr = tr_pd; list_add_tail(&tr_pd->entry, &pd->tr_list); @@ -818,13 +835,18 @@ static void shaper_change_help(char * const *f, int f_cnt, void *cli) static void shaper_change(struct shaper_pd_t *pd) { - if ((pd->temp_down_speed && pd->temp_up_speed) || (pd->down_speed && pd->up_speed)) + if (pd->down_speed && pd->up_speed) remove_shaper(pd->ppp->ifname); - if (pd->temp_down_speed && pd->temp_up_speed) + if (pd->temp_down_speed && pd->temp_up_speed) { + pd->down_speed = pd->temp_down_speed; + pd->up_speed = pd->temp_up_speed; install_shaper(pd->ppp->ifname, pd->temp_down_speed, 0, pd->temp_up_speed, 0); - else if (pd->down_speed && pd->up_speed) + } else if (pd->cur_tr->down_speed && pd->cur_tr->up_speed) { + pd->down_speed = pd->cur_tr->down_speed; + pd->up_speed = pd->cur_tr->up_speed; install_shaper(pd->ppp->ifname, pd->cur_tr->down_speed, pd->cur_tr->down_burst, pd->cur_tr->up_speed, pd->cur_tr->up_burst); + } } static int shaper_change_exec(const char *cmd, char * const *f, int f_cnt, void *cli) @@ -973,6 +995,9 @@ static void update_shaper_tr(struct shaper_pd_t *pd) { struct time_range_pd_t *tr; + if (pd->ppp->terminating) + return; + list_for_each_entry(tr, &pd->tr_list, entry) { if (tr->id != time_range_id) continue; @@ -998,8 +1023,7 @@ static void update_shaper_tr(struct shaper_pd_t *pd) } } else if (conf_verbose) - log_ppp_info2("tbf: removed shaper\n"); - + log_ppp_info2("tbf: removed shaper\n"); } static void time_range_begin_timer(struct triton_timer_t *t) @@ -1251,7 +1275,7 @@ static int clock_init(void) return 0; } -static void __init init(void) +static void init(void) { if (clock_init()) return; @@ -1276,3 +1300,4 @@ static void __init init(void) cli_show_ses_register("rate-limit", "rate limit down-stream/up-stream (Kbit)", print_rate); } +DEFINE_INIT(100, init); diff --git a/accel-pppd/extra/sigchld.c b/accel-pppd/extra/sigchld.c index 08bab93..8f1a979 100644 --- a/accel-pppd/extra/sigchld.c +++ b/accel-pppd/extra/sigchld.c @@ -109,8 +109,10 @@ void __export sigchld_unlock() pthread_mutex_unlock(&handlers_lock); } -static void __init init(void) +static void init(void) { if (pthread_create(&sigchld_thr, NULL, sigchld_thread, NULL)) log_emerg("sigchld: pthread_create: %s\n", strerror(errno)); } + +DEFINE_INIT(100, init);
\ No newline at end of file diff --git a/accel-pppd/include/events.h b/accel-pppd/include/events.h index 6a8caf0..a59ee31 100644 --- a/accel-pppd/include/events.h +++ b/accel-pppd/include/events.h @@ -14,6 +14,7 @@ #define EV_PPP_PRE_UP 9 #define EV_PPP_ACCT_START 10 #define EV_CONFIG_RELOAD 11 +#define EV_PPP_AUTH_FAILED 12 #define EV_IP_CHANGED 100 #define EV_SHAPER 101 #define EV_MPPE_KEYS 102 diff --git a/accel-pppd/iprange.c b/accel-pppd/iprange.c index 411dcb7..315a572 100644 --- a/accel-pppd/iprange.c +++ b/accel-pppd/iprange.c @@ -138,9 +138,10 @@ int __export iprange_tunnel_check(in_addr_t ipaddr) return !check_range(&client_ranges, ipaddr); } -static void __init iprange_init(void) +static void iprange_init(void) { load_ranges(&client_ranges, "client-ip-range"); //load_ranges(&tunnel_ranges, "tunnel-ip-range"); } +DEFINE_INIT(10, iprange_init); diff --git a/accel-pppd/log.c b/accel-pppd/log.c index fc50d27..53612e9 100644 --- a/accel-pppd/log.c +++ b/accel-pppd/log.c @@ -16,6 +16,15 @@ #include "memdebug.h" +#define LOG_MSG 0 +#define LOG_ERROR 1 +#define LOG_WARN 2 +#define LOG_INFO1 3 +#define LOG_INFO2 4 +#define LOG_DEBUG 5 + +#define LOG_CHUNK_SIZE 128 + struct log_pd_t { struct ppp_pd_t pd; @@ -490,7 +499,7 @@ static void load_config(void) } } -static void __init log_init(void) +static void log_init(void) { struct sigaction sa = { .sa_handler = sighup, @@ -509,3 +518,4 @@ static void __init log_init(void) sigaction(SIGHUP, &sa, NULL); } +DEFINE_INIT(0, log_init); diff --git a/accel-pppd/log.h b/accel-pppd/log.h index d87c42c..3545cb1 100644 --- a/accel-pppd/log.h +++ b/accel-pppd/log.h @@ -5,14 +5,6 @@ #include <sys/time.h> #include "list.h" -#define LOG_MSG 0 -#define LOG_ERROR 1 -#define LOG_WARN 2 -#define LOG_INFO1 3 -#define LOG_INFO2 4 -#define LOG_DEBUG 5 - -#define LOG_CHUNK_SIZE 128 #define LOG_MAX_SIZE 4096 struct ppp_t; diff --git a/accel-pppd/logs/log_file.c b/accel-pppd/logs/log_file.c index e435757..f1a5018 100644 --- a/accel-pppd/logs/log_file.c +++ b/accel-pppd/logs/log_file.c @@ -47,20 +47,32 @@ struct log_file_pd_t unsigned long tmp; }; +struct fail_log_pd_t +{ + struct ppp_pd_t pd; + struct list_head msgs; +}; + + static int conf_color; static int conf_per_session; static char *conf_per_user_dir; static char *conf_per_session_dir; static int conf_copy; +static int conf_fail_log; static const char* level_name[]={" msg", "error", " warn", " info", " info", "debug"}; static const char* level_color[]={NORMAL_COLOR, RED_COLOR, YELLOW_COLOR, GREEN_COLOR, GREEN_COLOR, BLUE_COLOR}; static void *pd_key1; static void *pd_key2; +static void *pd_key3; + static struct log_file_t *log_file; +static struct log_file_t *fail_log_file; static mempool_t lpd_pool; +static mempool_t fpd_pool; static char *log_buf; static struct aiocb aiocb = { @@ -248,6 +260,29 @@ static void queue_log(struct log_file_t *lf, struct log_msg_t *msg) queue_lf(lf); } +static void queue_log_list(struct log_file_t *lf, struct list_head *l) +{ + int r; + struct log_msg_t *msg; + + spin_lock(&lf->lock); + while (!list_empty(l)) { + msg = list_entry(l->next, typeof(*msg), entry); + list_del(&msg->entry); + list_add_tail(&msg->entry, &lf->msgs); + } + if (lf->fd != -1) { + r = lf->queued; + lf->queued = 1; + } else + r = 1; + spin_unlock(&lf->lock); + + if (!r) + queue_lf(lf); +} + + static void set_hdr(struct log_msg_t *msg, struct ppp_t *ppp) { struct tm tm; @@ -275,20 +310,40 @@ static void general_log(struct log_target_t *t, struct log_msg_t *msg, struct pp queue_log(log_file, msg); } -static struct log_file_pd_t *find_pd(struct ppp_t *ppp, void *pd_key) +static struct ppp_pd_t *find_pd(struct ppp_t *ppp, void *pd_key) { struct ppp_pd_t *pd; - struct log_file_pd_t *lpd; list_for_each_entry(pd, &ppp->pd_list, entry) { if (pd->key == pd_key) { - lpd = container_of(pd, typeof(*lpd), pd); - return lpd; + return pd; } } + return NULL; } +static struct log_file_pd_t *find_lpd(struct ppp_t *ppp, void *pd_key) +{ + struct ppp_pd_t *pd = find_pd(ppp, pd_key); + + if (!pd) + return NULL; + + return container_of(pd, struct log_file_pd_t, pd); +} + +static struct fail_log_pd_t *find_fpd(struct ppp_t *ppp, void *pd_key) +{ + struct ppp_pd_t *pd = find_pd(ppp, pd_key); + + if (!pd) + return NULL; + + return container_of(pd, struct fail_log_pd_t, pd); +} + + static void per_user_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp) { struct log_file_pd_t *lpd; @@ -298,7 +353,7 @@ static void per_user_log(struct log_target_t *t, struct log_msg_t *msg, struct p return; } - lpd = find_pd(ppp, &pd_key1); + lpd = find_lpd(ppp, &pd_key1); if (!lpd) { log_free_msg(msg); @@ -318,7 +373,7 @@ static void per_session_log(struct log_target_t *t, struct log_msg_t *msg, struc return; } - lpd = find_pd(ppp, &pd_key2); + lpd = find_lpd(ppp, &pd_key2); if (!lpd) { log_free_msg(msg); @@ -329,6 +384,38 @@ static void per_session_log(struct log_target_t *t, struct log_msg_t *msg, struc queue_log(&lpd->lf, msg); } +static void fail_log(struct log_target_t *t, struct log_msg_t *msg, struct ppp_t *ppp) +{ + struct fail_log_pd_t *fpd; + + if (!ppp || !conf_fail_log) { + log_free_msg(msg); + return; + } + + fpd = find_fpd(ppp, &pd_key3); + + if (!fpd) { + log_free_msg(msg); + return; + } + + set_hdr(msg, ppp); + list_add_tail(&msg->entry, &fpd->msgs); +} + +static void fail_reopen(void) +{ + char *fname = conf_get_opt("log", "log-fail-file"); + int fd = open(fname, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + if (fd < 0) { + log_emerg("log_file: open '%s': %s\n", fname, strerror(errno)); + return; + } + fail_log_file->new_fd = fd; +} + + static void general_reopen(void) { char *fname = conf_get_opt("log", "log-file"); @@ -362,9 +449,75 @@ static void free_lpd(struct log_file_pd_t *lpd) } } +static void ev_ppp_authorized2(struct ppp_t *ppp) +{ + struct fail_log_pd_t *fpd; + struct log_msg_t *msg; + + fpd = find_fpd(ppp, &pd_key3); + if (!fpd) + return; + + while (!list_empty(&fpd->msgs)) { + msg = list_entry(fpd->msgs.next, typeof(*msg), entry); + list_del(&msg->entry); + log_free_msg(msg); + } + + list_del(&fpd->pd.entry); + mempool_free(fpd); +} + +static void ev_ppp_authorized1(struct ppp_t *ppp) +{ + struct log_file_pd_t *lpd; + char *fname; + + lpd = find_lpd(ppp, &pd_key1); + if (!lpd) + return; + + fname = _malloc(PATH_MAX); + if (!fname) { + log_emerg("log_file: out of memory\n"); + return; + } + + strcpy(fname, conf_per_user_dir); + strcat(fname, "/"); + strcat(fname, ppp->username); + if (conf_per_session) { + if (mkdir(fname, S_IRWXU) && errno != EEXIST) { + log_emerg("log_file: mkdir '%s': %s'\n", fname, strerror(errno)); + goto out_err; + } + strcat(fname, "/"); + strcat(fname, ppp->sessionid); + } + strcat(fname, ".log"); + + if (log_file_open(&lpd->lf, fname)) + goto out_err; + + _free(fname); + + if (!list_empty(&lpd->lf.msgs)) { + lpd->lf.queued = 1; + queue_lf(&lpd->lf); + } + + return; + +out_err: + _free(fname); + list_del(&lpd->pd.entry); + free_lpd(lpd); +} + static void ev_ctrl_started(struct ppp_t *ppp) { struct log_file_pd_t *lpd; + struct fail_log_pd_t *fpd; char *fname; if (conf_per_user_dir) { @@ -413,19 +566,38 @@ static void ev_ctrl_started(struct ppp_t *ppp) list_add_tail(&lpd->pd.entry, &ppp->pd_list); } + + if (conf_fail_log) { + fpd = mempool_alloc(fpd_pool); + if (!fpd) { + log_emerg("log_file: out of memory\n"); + return; + } + memset(fpd, 0, sizeof(*fpd)); + fpd->pd.key = &pd_key3; + list_add_tail(&fpd->pd.entry, &ppp->pd_list); + INIT_LIST_HEAD(&fpd->msgs); + } } static void ev_ctrl_finished(struct ppp_t *ppp) { struct log_file_pd_t *lpd; + struct fail_log_pd_t *fpd; char *fname; - lpd = find_pd(ppp, &pd_key1); + fpd = find_fpd(ppp, &pd_key3); + if (fpd) { + queue_log_list(fail_log_file, &fpd->msgs); + list_del(&fpd->pd.entry); + mempool_free(fpd); + } + + lpd = find_lpd(ppp, &pd_key1); if (lpd) free_lpd(lpd); - - lpd = find_pd(ppp, &pd_key2); + lpd = find_lpd(ppp, &pd_key2); if (lpd) { if (lpd->tmp) { fname = _malloc(PATH_MAX); @@ -448,7 +620,7 @@ static void ev_ppp_starting(struct ppp_t *ppp) struct log_file_pd_t *lpd; char *fname1, *fname2; - lpd = find_pd(ppp, &pd_key2); + lpd = find_lpd(ppp, &pd_key2); if (!lpd) return; @@ -483,52 +655,6 @@ static void ev_ppp_starting(struct ppp_t *ppp) _free(fname2); } -static void ev_ppp_authorized(struct ppp_t *ppp) -{ - struct log_file_pd_t *lpd; - char *fname; - - lpd = find_pd(ppp, &pd_key1); - if (!lpd) - return; - - fname = _malloc(PATH_MAX); - if (!fname) { - log_emerg("log_file: out of memory\n"); - return; - } - - strcpy(fname, conf_per_user_dir); - strcat(fname, "/"); - strcat(fname, ppp->username); - if (conf_per_session) { - if (mkdir(fname, S_IRWXU) && errno != EEXIST) { - log_emerg("log_file: mkdir '%s': %s'\n", fname, strerror(errno)); - goto out_err; - } - strcat(fname, "/"); - strcat(fname, ppp->sessionid); - } - strcat(fname, ".log"); - - if (log_file_open(&lpd->lf, fname)) - goto out_err; - - _free(fname); - - if (!list_empty(&lpd->lf.msgs)) { - lpd->lf.queued = 1; - queue_lf(&lpd->lf); - } - - return; - -out_err: - _free(fname); - list_del(&lpd->pd.entry); - free_lpd(lpd); -} - static struct log_target_t general_target = { .log = general_log, @@ -545,7 +671,14 @@ static struct log_target_t per_session_target = .log = per_session_log, }; -static void __init init(void) +static struct log_target_t fail_log_target = +{ + .log = fail_log, + .reopen = fail_reopen, +}; + + +static void init(void) { char *opt; @@ -560,6 +693,7 @@ static void __init init(void) }; lpd_pool = mempool_create(sizeof(struct log_file_pd_t)); + fpd_pool = mempool_create(sizeof(struct fail_log_pd_t)); log_buf = malloc(LOG_BUF_SIZE); aiocb.aio_buf = log_buf; @@ -579,6 +713,18 @@ static void __init init(void) } } + opt = conf_get_opt("log", "log-fail-file"); + if (opt) { + fail_log_file = malloc(sizeof(*fail_log_file)); + memset(fail_log_file, 0, sizeof(*fail_log_file)); + log_file_init(fail_log_file); + if (log_file_open(fail_log_file, opt)) { + free(fail_log_file); + _exit(EXIT_FAILURE); + } + conf_fail_log = 1; + } + opt = conf_get_opt("log","color"); if (opt && atoi(opt) > 0) conf_color = 1; @@ -601,14 +747,23 @@ static void __init init(void) log_register_target(&general_target); - if (conf_per_user_dir) + if (conf_per_user_dir) { log_register_target(&per_user_target); + triton_event_register_handler(EV_PPP_AUTHORIZED, (triton_event_func)ev_ppp_authorized1); + } - if (conf_per_session_dir) + if (conf_per_session_dir) { log_register_target(&per_session_target); + triton_event_register_handler(EV_PPP_STARTING, (triton_event_func)ev_ppp_starting); + } + + if (conf_fail_log) { + log_register_target(&fail_log_target); + triton_event_register_handler(EV_PPP_AUTHORIZED, (triton_event_func)ev_ppp_authorized2); + } triton_event_register_handler(EV_CTRL_STARTED, (triton_event_func)ev_ctrl_started); triton_event_register_handler(EV_CTRL_FINISHED, (triton_event_func)ev_ctrl_finished); - triton_event_register_handler(EV_PPP_STARTING, (triton_event_func)ev_ppp_starting); - triton_event_register_handler(EV_PPP_AUTHORIZED, (triton_event_func)ev_ppp_authorized); } + +DEFINE_INIT(1, init); diff --git a/accel-pppd/logs/log_pgsql.c b/accel-pppd/logs/log_pgsql.c index af67e0b..742ee62 100644 --- a/accel-pppd/logs/log_pgsql.c +++ b/accel-pppd/logs/log_pgsql.c @@ -280,7 +280,7 @@ static struct log_target_t target = { .log = general_log, }; -static void __init init(void) +static void init(void) { char *opt; @@ -319,3 +319,5 @@ static void __init init(void) log_register_target(&target); } + +DEFINE_INIT(1, init); diff --git a/accel-pppd/logs/log_tcp.c b/accel-pppd/logs/log_tcp.c index 306c450..ceaeb1c 100644 --- a/accel-pppd/logs/log_tcp.c +++ b/accel-pppd/logs/log_tcp.c @@ -301,7 +301,7 @@ static struct triton_context_t tcp_ctx ={ .before_switch = log_switch, }; -static void __init init(void) +static void init(void) { struct conf_sect_t *s = conf_get_section("log"); struct conf_option_t *opt; @@ -321,3 +321,4 @@ static void __init init(void) triton_context_wakeup(&tcp_ctx); } +DEFINE_INIT(1, init); diff --git a/accel-pppd/main.c b/accel-pppd/main.c index 2e48c45..e153caf 100644 --- a/accel-pppd/main.c +++ b/accel-pppd/main.c @@ -14,43 +14,52 @@ #include "log.h" #include "events.h" -static int goto_daemon; static char *pid_file; static char *conf_file; -#define ARG_MAX 128 -static int parse_cmdline(char ***argv) -{ +static void change_limits(void) +{ FILE *f; - int i; - size_t len; + struct rlimit lim; + unsigned int file_max = 1024*1024; + unsigned int nr_open = 1024*1024; - f = fopen("/proc/self/cmdline", "r"); - if (!f) { - perror("open cmdline"); - _exit(EXIT_FAILURE); + f = fopen("/proc/sys/fs/nr_open", "r"); + if (f) { + fscanf(f, "%d", &nr_open); + fclose(f); } - *argv = _malloc(ARG_MAX * sizeof(void *)); - memset(*argv, 0, ARG_MAX * sizeof(void *)); - - for(i = 0; i < ARG_MAX; i++) { - len = 0; - if (getdelim(&(*argv)[i], &len, 0, f) < 0) - break; + f = fopen("/proc/sys/fs/file-max", "r"); + if (f) { + fscanf(f, "%d", &file_max); + fclose(f); } - fclose(f); + if (file_max > nr_open) + file_max = nr_open; - return i; + lim.rlim_cur = file_max; + lim.rlim_max = file_max; + if (setrlimit(RLIMIT_NOFILE, &lim)) + log_emerg("main: setrlimit: %s\n", strerror(errno)); } -static void __init __main(void) + +static void config_reload_notify(int r) +{ + if (!r) + triton_event_fire(EV_CONFIG_RELOAD, NULL); +} +static void config_reload(int num) { - int i,argc; - char **argv; + triton_conf_reload(config_reload_notify); +} + +int main(int argc, char **argv) +{ + sigset_t set; + int i, sig, goto_daemon = 0; - argc=parse_cmdline(&argv); - if (argc < 2) goto usage; @@ -74,51 +83,6 @@ static void __init __main(void) if (triton_init(conf_file)) _exit(EXIT_FAILURE); - return; - -usage: - printf("usage: accel-pppd [-d] [-p <file>] -c <file>\n\ - where:\n\ - -d - daemon mode\n\ - -p - write pid to <file>\n\ - -c - config file\n"); - _exit(EXIT_FAILURE); -} - -static void change_limits(void) -{ - FILE *f; - struct rlimit lim; - unsigned int file_max; - - f = fopen("/proc/sys/fs/file-max", "r"); - if (f) { - fscanf(f, "%d", &file_max); - fclose(f); - - lim.rlim_cur = file_max; - lim.rlim_max = file_max; - if (setrlimit(RLIMIT_NOFILE, &lim)) - log_emerg("main: setrlimit: %s\n", strerror(errno)); - } else - log_emerg("main: failed to open '/proc/sys/fs/file-max': %s\n", strerror(errno)); -} - -static void config_reload_notify(int r) -{ - if (!r) - triton_event_fire(EV_CONFIG_RELOAD, NULL); -} -static void config_reload(int num) -{ - triton_conf_reload(config_reload_notify); -} - -int main(int argc, char **argv) -{ - sigset_t set; - int sig; - if (goto_daemon) { /*pid_t pid = fork(); if (pid > 0) @@ -148,9 +112,6 @@ int main(int argc, char **argv) } } - //signal(SIGTERM, sigterm); - //signal(SIGPIPE, sigterm); - change_limits(); if (triton_load_modules("modules")) @@ -197,5 +158,13 @@ int main(int argc, char **argv) triton_terminate(); return EXIT_SUCCESS; + +usage: + printf("usage: accel-pppd [-d] [-p <file>] -c <file>\n\ + where:\n\ + -d - daemon mode\n\ + -p - write pid to <file>\n\ + -c - config file\n"); + _exit(EXIT_FAILURE); } diff --git a/accel-pppd/ppp/ccp_mppe.c b/accel-pppd/ppp/ccp_mppe.c index cf83d2d..7d9aab2 100644 --- a/accel-pppd/ppp/ccp_mppe.c +++ b/accel-pppd/ppp/ccp_mppe.c @@ -24,16 +24,21 @@ static struct ccp_option_t *mppe_init(struct ppp_ccp_t *ccp); static void mppe_free(struct ppp_ccp_t *ccp, struct ccp_option_t *opt); +static int __mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr, int setup_key); static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr); +static int mppe_send_conf_nak(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr); static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr); static int mppe_recv_conf_nak(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr); static int mppe_recv_conf_rej(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr); static void mppe_print(void (*print)(const char *fmt,...),struct ccp_option_t*, uint8_t *ptr); +static int conf_mppe = -1; + struct mppe_option_t { struct ccp_option_t opt; int mppe; + int enabled; uint8_t recv_key[16]; uint8_t send_key[16]; int policy; // 1 - allowed, 2 - required @@ -42,7 +47,7 @@ struct mppe_option_t static struct ccp_option_handler_t mppe_opt_hnd = { .init = mppe_init, .send_conf_req = mppe_send_conf_req, - .send_conf_nak = mppe_send_conf_req, + .send_conf_nak = mppe_send_conf_nak, .recv_conf_req = mppe_recv_conf_req, .recv_conf_nak = mppe_recv_conf_nak, .recv_conf_rej = mppe_recv_conf_rej, @@ -54,7 +59,20 @@ static struct ccp_option_t *mppe_init(struct ppp_ccp_t *ccp) { struct mppe_option_t *mppe_opt = _malloc(sizeof(*mppe_opt)); memset(mppe_opt, 0, sizeof(*mppe_opt)); - mppe_opt->mppe = -1; + + if (conf_mppe != -1) + mppe_opt->policy = conf_mppe; + else + mppe_opt->policy = 1; + + if (conf_mppe > 0) + mppe_opt->mppe = 1; + else + mppe_opt->mppe = -1; + + if (conf_mppe == 2) + ccp->passive = 0; + mppe_opt->opt.id = CI_MPPE; mppe_opt->opt.len = 6; @@ -114,7 +132,7 @@ static int decrease_mtu(struct ppp_t *ppp) return 0; } -static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr) +static int __mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr, int setup_key) { struct mppe_option_t *mppe_opt = container_of(opt,typeof(*mppe_opt),opt); struct ccp_opt32_t *opt32 = (struct ccp_opt32_t*)ptr; @@ -124,7 +142,7 @@ static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, u opt32->hdr.len = 6; opt32->val = mppe_opt->mppe ? htonl(MPPE_S | MPPE_H) : 0; - if (mppe_opt->mppe && setup_mppe_key(ccp->ppp->unit_fd, 0, mppe_opt->recv_key)) + if (setup_key && mppe_opt->mppe && setup_mppe_key(ccp->ppp->unit_fd, 0, mppe_opt->recv_key)) return 0; return 6; @@ -132,16 +150,27 @@ static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, u return 0; } +static int mppe_send_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr) +{ + return __mppe_send_conf_req(ccp, opt, ptr, 1); +} + +static int mppe_send_conf_nak(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr) +{ + return __mppe_send_conf_req(ccp, opt, ptr, 0); +} + + static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, uint8_t *ptr) { struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt); struct ccp_opt32_t *opt32 = (struct ccp_opt32_t *)ptr; - /*if (!ptr) { + if (!ptr) { if (mppe_opt->policy == 2) return CCP_OPT_NAK; return CCP_OPT_ACK; - }*/ + } if (opt32->hdr.len != 6) return CCP_OPT_REJ; @@ -152,7 +181,7 @@ static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, u } else if (mppe_opt->policy == 1) { if (ntohl(opt32->val) == (MPPE_S | MPPE_H)) mppe_opt->mppe = 1; - else if ((ntohl(opt32->val) & (MPPE_S | MPPE_H)) == (MPPE_S | MPPE_H)) { + else if ((ntohl(opt32->val) & (MPPE_S | MPPE_H)) || conf_mppe == 1) { mppe_opt->mppe = 1; return CCP_OPT_NAK; } else if (opt32->val) { @@ -167,7 +196,10 @@ static int mppe_recv_conf_req(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, u if (setup_mppe_key(ccp->ppp->unit_fd, 1, mppe_opt->send_key)) return CCP_OPT_REJ; - decrease_mtu(ccp->ppp); + if (!mppe_opt->enabled) { + decrease_mtu(ccp->ppp); + mppe_opt->enabled = 1; + } log_ppp_debug(" (mppe enabled)"); } @@ -179,7 +211,7 @@ static int mppe_recv_conf_rej(struct ppp_ccp_t *ccp, struct ccp_option_t *opt, u { struct mppe_option_t *mppe_opt = container_of(opt, typeof(*mppe_opt), opt); - if (mppe_opt->mppe != 2) { + if (mppe_opt->policy != 2) { mppe_opt->mppe = -1; return 0; } @@ -237,24 +269,60 @@ static void mppe_print(void (*print)(const char *fmt,...),struct ccp_option_t *o static void ev_mppe_keys(struct ev_mppe_keys_t *ev) { + struct ppp_ccp_t *ccp = ccp_find_layer_data(ev->ppp); struct mppe_option_t *mppe_opt = container_of(ccp_find_option(ev->ppp, &mppe_opt_hnd), typeof(*mppe_opt), opt); + memcpy(mppe_opt->recv_key, ev->recv_key, 16); + memcpy(mppe_opt->send_key, ev->send_key, 16); + + if (ev->policy == -1) + return; + if ((ev->type & 0x04) == 0) { log_ppp_warn("mppe: 128-bit session keys not allowed, disabling mppe ...\n"); + mppe_opt->mppe = 0; return; } - memcpy(mppe_opt->recv_key, ev->recv_key, 16); - memcpy(mppe_opt->send_key, ev->send_key, 16); mppe_opt->policy = ev->policy; - if (ev->policy == 2) + if (ev->policy == 2) { mppe_opt->mppe = 1; + ccp->passive = 0; + } else if (ev->policy == 1) { + if (conf_mppe == 1) + mppe_opt->mppe = 1; + else + mppe_opt->mppe = -1; + + if (conf_mppe == 2) + ccp->passive = 1; + } +} + +static void load_config(void) +{ + const char *opt; + + opt = conf_get_opt("ppp", "mppe"); + if (opt) { + if (!strcmp(opt,"require")) + conf_mppe = 2; + else if (!strcmp(opt,"prefere")) + conf_mppe = 1; + else if (!strcmp(opt,"deny")) + conf_mppe = 0; + } else + conf_mppe = -1; } -static void __init mppe_opt_init() +static void mppe_opt_init() { ccp_option_register(&mppe_opt_hnd); triton_event_register_handler(EV_MPPE_KEYS, (triton_event_func)ev_mppe_keys); + + load_config(); + triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(4, mppe_opt_init); diff --git a/accel-pppd/ppp/ipcp_opt_dns.c b/accel-pppd/ppp/ipcp_opt_dns.c index f488f3c..4427b0e 100644 --- a/accel-pppd/ppp/ipcp_opt_dns.c +++ b/accel-pppd/ppp/ipcp_opt_dns.c @@ -152,7 +152,7 @@ static void load_config(void) conf_dns2 = inet_addr(opt); } -static void __init dns_opt_init() +static void dns_opt_init() { ipcp_option_register(&dns1_opt_hnd); ipcp_option_register(&dns2_opt_hnd); @@ -160,3 +160,5 @@ static void __init dns_opt_init() load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } + +DEFINE_INIT(4, dns_opt_init); diff --git a/accel-pppd/ppp/ipcp_opt_ipaddr.c b/accel-pppd/ppp/ipcp_opt_ipaddr.c index de1186e..217a080 100644 --- a/accel-pppd/ppp/ipcp_opt_ipaddr.c +++ b/accel-pppd/ppp/ipcp_opt_ipaddr.c @@ -9,6 +9,7 @@ #include "ppp.h" #include "ppp_ipcp.h" +#include "ppp_ccp.h" #include "log.h" #include "ipdb.h" #include "iprange.h" @@ -126,15 +127,16 @@ static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o { struct ipaddr_option_t *ipaddr_opt = container_of(opt,typeof(*ipaddr_opt), opt); struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t*)ptr; - struct ifreq ifr; - struct sockaddr_in addr; - struct npioctl np; if (opt32->hdr.len != 6) return IPCP_OPT_REJ; - if (ipaddr_opt->ip->peer_addr == opt32->val) - goto ack; + if (ipaddr_opt->ip->peer_addr == opt32->val) { + ipcp->ppp->ipaddr = ipaddr_opt->ip->addr; + ipcp->ppp->peer_ipaddr = ipaddr_opt->ip->peer_addr; + ipcp->delay_ack = ccp_ipcp_started(ipcp->ppp); + return IPCP_OPT_ACK; + } /*if (!ipaddr_opt->peer_addr) { ipaddr_opt->peer_addr = opt32->val; @@ -142,28 +144,19 @@ static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o }*/ return IPCP_OPT_NAK; +} -ack: - if (ipaddr_opt->started) - return IPCP_OPT_ACK; +static void if_up(struct ppp_t *ppp) +{ + struct ipaddr_option_t *ipaddr_opt = container_of(ipcp_find_option(ppp, &ipaddr_opt_hnd), typeof(*ipaddr_opt), opt); + struct ifreq ifr; + struct sockaddr_in addr; + struct npioctl np; - ipaddr_opt->started = 1; - - ipcp->ppp->ipaddr = ipaddr_opt->ip->addr; - ipcp->ppp->peer_ipaddr = ipaddr_opt->ip->peer_addr; - - triton_event_fire(EV_PPP_ACCT_START, ipcp->ppp); - if (ipcp->ppp->stop_time) - return IPCP_OPT_ACK; - - triton_event_fire(EV_PPP_PRE_UP, ipcp->ppp); - if (ipcp->ppp->stop_time) - return IPCP_OPT_ACK; - memset(&ifr, 0, sizeof(ifr)); memset(&addr, 0, sizeof(addr)); - strcpy(ifr.ifr_name, ipcp->ppp->ifname); + strcpy(ifr.ifr_name, ppp->ifname); addr.sin_family = AF_INET; addr.sin_addr.s_addr = ipaddr_opt->ip->addr; @@ -177,6 +170,14 @@ ack: if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr)) log_ppp_error("ipcp: failed to set remote PA address: %s\n", strerror(errno)); + + triton_event_fire(EV_PPP_ACCT_START, ppp); + if (ppp->stop_time) + return; + + triton_event_fire(EV_PPP_PRE_UP, ppp); + if (ppp->stop_time) + return; if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr)) log_ppp_error("ipcp: failed to get interface flags: %s\n", strerror(errno)); @@ -189,10 +190,8 @@ ack: np.protocol = PPP_IP; np.mode = NPMODE_PASS; - if (ioctl(ipcp->ppp->unit_fd, PPPIOCSNPMODE, &np)) + if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np)) log_ppp_error("ipcp: failed to set NP mode: %s\n", strerror(errno)); - - return IPCP_OPT_ACK; } static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t *opt, uint8_t *ptr) @@ -218,10 +217,12 @@ static void load_config(void) conf_check_exists = 1; } -static void __init ipaddr_opt_init() +static void ipaddr_opt_init() { ipcp_option_register(&ipaddr_opt_hnd); load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); + triton_event_register_handler(EV_PPP_STARTED, (triton_event_func)if_up); } +DEFINE_INIT(4, ipaddr_opt_init); diff --git a/accel-pppd/ppp/lcp_opt_accomp.c b/accel-pppd/ppp/lcp_opt_accomp.c index 241b0e0..33347d8 100644 --- a/accel-pppd/ppp/lcp_opt_accomp.c +++ b/accel-pppd/ppp/lcp_opt_accomp.c @@ -99,8 +99,9 @@ static void accomp_print(void (*print)(const char *fmt,...),struct lcp_option_t print("<accomp>"); } -static void __init accomp_opt_init() +static void accomp_opt_init() { lcp_option_register(&accomp_opt_hnd); } +DEFINE_INIT(4, accomp_opt_init); diff --git a/accel-pppd/ppp/lcp_opt_magic.c b/accel-pppd/ppp/lcp_opt_magic.c index 6c0deb5..3e694d2 100644 --- a/accel-pppd/ppp/lcp_opt_magic.c +++ b/accel-pppd/ppp/lcp_opt_magic.c @@ -99,7 +99,9 @@ static void magic_print(void (*print)(const char *fmt,...),struct lcp_option_t * print("<magic %04x>", magic_opt->magic); } -static void __init magic_opt_init() +static void magic_opt_init() { lcp_option_register(&magic_opt_hnd); } + +DEFINE_INIT(4, magic_opt_init); diff --git a/accel-pppd/ppp/lcp_opt_mru.c b/accel-pppd/ppp/lcp_opt_mru.c index 78e06b5..577e019 100644 --- a/accel-pppd/ppp/lcp_opt_mru.c +++ b/accel-pppd/ppp/lcp_opt_mru.c @@ -186,10 +186,11 @@ static void load_config(void) } } -static void __init mru_opt_init() +static void mru_opt_init() { load_config(); lcp_option_register(&mru_opt_hnd); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(4, mru_opt_init); diff --git a/accel-pppd/ppp/lcp_opt_pcomp.c b/accel-pppd/ppp/lcp_opt_pcomp.c index 1f8532b..fec5e7b 100644 --- a/accel-pppd/ppp/lcp_opt_pcomp.c +++ b/accel-pppd/ppp/lcp_opt_pcomp.c @@ -99,8 +99,9 @@ static void pcomp_print(void (*print)(const char *fmt,...),struct lcp_option_t * print("<pcomp>"); } -static void __init pcomp_opt_init() +static void pcomp_opt_init() { lcp_option_register(&pcomp_opt_hnd); } +DEFINE_INIT(4, pcomp_opt_init); diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c index 7ce3b4b..b541ba5 100644 --- a/accel-pppd/ppp/ppp.c +++ b/accel-pppd/ppp/ppp.c @@ -25,7 +25,8 @@ #include "memdebug.h" int __export conf_ppp_verbose; -static int conf_sid_ucase; +int conf_sid_ucase; +int conf_single_session = -1; pthread_rwlock_t __export ppp_lock = PTHREAD_RWLOCK_INITIALIZER; __export LIST_HEAD(ppp_list); @@ -43,7 +44,7 @@ static unsigned long long seq; static spinlock_t seq_lock; #endif -struct ppp_stat_t ppp_stat; +__export struct ppp_stat_t ppp_stat; struct layer_node_t { @@ -399,7 +400,7 @@ void __export ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d) list_for_each_entry(d, &n->items, entry) { d->starting = 1; if (d->layer->start(d)) { - ppp_terminate(ppp, TERM_NAS_ERROR, 0); + ppp_terminate(ppp, 1, TERM_NAS_ERROR); return; } } @@ -641,9 +642,18 @@ static void load_config(void) else if (strcmp(opt, "lower")) log_emerg("ppp: sid-case: invalid format\n"); } + + opt = conf_get_opt("ppp", "single-session"); + if (opt) { + if (!strcmp(opt, "deny")) + conf_single_session = 0; + else if (!strcmp(opt, "replace")) + conf_single_session = 1; + } else + conf_single_session = -1; } -static void __init init(void) +static void init(void) { char *opt; FILE *f; @@ -673,3 +683,4 @@ static void __init init(void) atexit(save_seq); } +DEFINE_INIT(2, init); diff --git a/accel-pppd/ppp/ppp.h b/accel-pppd/ppp/ppp.h index e8141cc..ae2a7c9 100644 --- a/accel-pppd/ppp/ppp.h +++ b/accel-pppd/ppp/ppp.h @@ -55,12 +55,16 @@ #define TERM_AUTH_ERROR 8 #define TERM_LOST_CARRIER 9 +#define CTRL_TYPE_PPTP 1 +#define CTRL_TYPE_L2TP 2 +#define CTRL_TYPE_PPPOE 3 struct ppp_t; struct ppp_ctrl_t { struct triton_context_t *ctx; + int type; const char *name; int max_mtu; char *calling_station_id; @@ -177,6 +181,7 @@ extern int ppp_shutdown; void ppp_shutdown_soft(void); extern int conf_ppp_verbose; +extern int conf_single_session; extern pthread_rwlock_t ppp_lock; extern struct list_head ppp_list; diff --git a/accel-pppd/ppp/ppp_auth.c b/accel-pppd/ppp/ppp_auth.c index 32413c6..b69c759 100644 --- a/accel-pppd/ppp/ppp_auth.c +++ b/accel-pppd/ppp/ppp_auth.c @@ -28,6 +28,8 @@ static int auth_layer_start(struct ppp_layer_data_t *); static void auth_layer_finish(struct ppp_layer_data_t *); static void auth_layer_free(struct ppp_layer_data_t *); +static void __ppp_auth_started(struct ppp_t *ppp); + struct auth_option_t { struct lcp_option_t opt; @@ -296,24 +298,66 @@ static void auth_layer_free(struct ppp_layer_data_t *ld) log_ppp_debug("auth_layer_free\n"); + triton_cancel_call(ad->ppp->ctrl->ctx, (triton_event_func)__ppp_auth_started); + _free(ad); } -void __export ppp_auth_successed(struct ppp_t *ppp, char *username) +static void ppp_terminate_sec(struct ppp_t *ppp) +{ + ppp_terminate(ppp, TERM_NAS_REQUEST, 0); +} + +static void __ppp_auth_started(struct ppp_t *ppp) { struct auth_layer_data_t *ad = container_of(ppp_find_layer_data(ppp, &auth_layer), typeof(*ad), ld); + log_ppp_debug("auth_layer_started\n"); - ppp->username = username; ppp_layer_started(ppp, &ad->ld); - log_ppp_info1("%s: authentication successed\n", username); + log_ppp_info1("%s: authentication successed\n", ppp->username); triton_event_fire(EV_PPP_AUTHORIZED, ppp); } -void __export ppp_auth_failed(struct ppp_t *ppp, const char *username) +int __export ppp_auth_successed(struct ppp_t *ppp, char *username) +{ + struct ppp_t *p; + struct auth_layer_data_t *ad = container_of(ppp_find_layer_data(ppp, &auth_layer), typeof(*ad), ld); + + pthread_rwlock_rdlock(&ppp_lock); + list_for_each_entry(p, &ppp_list, entry) { + if (p->username && !strcmp(p->username, username)) { + if (conf_single_session == 0) { + pthread_rwlock_unlock(&ppp_lock); + log_ppp_info1("%s: second session denied\n", username); + return -1; + } else { + if (conf_single_session == 1) + triton_context_call(p->ctrl->ctx, (triton_event_func)ppp_terminate_sec, p); + } + } + } + pthread_rwlock_unlock(&ppp_lock); + + pthread_rwlock_wrlock(&ppp_lock); + ppp->username = username; + pthread_rwlock_unlock(&ppp_lock); + + triton_context_call(ppp->ctrl->ctx, (triton_event_func)__ppp_auth_started, ppp); + + return 0; +} + +void __export ppp_auth_failed(struct ppp_t *ppp, char *username) { - if (username) + if (username) { + pthread_rwlock_wrlock(&ppp_lock); + if (!ppp->username) + ppp->username = _strdup(username); + pthread_rwlock_unlock(&ppp_lock); log_ppp_info1("%s: authentication failed\n", username); - else + log_info1("%s: authentication failed\n", username); + triton_event_fire(EV_PPP_AUTH_FAILED, ppp); + } else log_ppp_info1("authentication failed\n"); ppp_terminate(ppp, TERM_AUTH_ERROR, 0); } @@ -338,9 +382,10 @@ int __export ppp_auth_restart(struct ppp_t *ppp) return 0; } -static void __init ppp_auth_init() +static void ppp_auth_init() { ppp_register_layer("auth", &auth_layer); lcp_option_register(&auth_opt_hnd); } +DEFINE_INIT(3, ppp_auth_init); diff --git a/accel-pppd/ppp/ppp_auth.h b/accel-pppd/ppp/ppp_auth.h index 87cc742..6f86d26 100644 --- a/accel-pppd/ppp/ppp_auth.h +++ b/accel-pppd/ppp/ppp_auth.h @@ -29,8 +29,8 @@ struct ppp_auth_handler_t int ppp_auth_register_handler(struct ppp_auth_handler_t*); -void ppp_auth_successed(struct ppp_t *ppp, char *username); -void ppp_auth_failed(struct ppp_t *ppp, const char *username); +int ppp_auth_successed(struct ppp_t *ppp, char *username); +void ppp_auth_failed(struct ppp_t *ppp, char *username); int ppp_auth_restart(struct ppp_t *ppp); #endif diff --git a/accel-pppd/ppp/ppp_ccp.c b/accel-pppd/ppp/ppp_ccp.c index 58a4abf..79b0c32 100644 --- a/accel-pppd/ppp/ppp_ccp.c +++ b/accel-pppd/ppp/ppp_ccp.c @@ -26,12 +26,14 @@ struct recv_opt_t }; static int conf_ccp = 1; +static int conf_ccp_max_configure = 3; static struct ppp_layer_t ccp_layer; static LIST_HEAD(option_handlers); static void ccp_layer_up(struct ppp_fsm_t*); static void ccp_layer_down(struct ppp_fsm_t*); +static void ccp_layer_finished(struct ppp_fsm_t*); static int send_conf_req(struct ppp_fsm_t*); static void send_conf_ack(struct ppp_fsm_t*); static void send_conf_nak(struct ppp_fsm_t*); @@ -105,16 +107,19 @@ static struct ppp_layer_data_t *ccp_layer_init(struct ppp_t *ppp) ppp_register_unit_handler(ppp, &ccp->hnd); + ccp->passive = 1; + INIT_LIST_HEAD(&ccp->options); ccp_options_init(ccp); - - ccp->passive = 0; ccp->fsm.proto = PPP_CCP; ppp_fsm_init(&ccp->fsm); + ccp->fsm.max_configure = conf_ccp_max_configure; + ccp->fsm.layer_up = ccp_layer_up; - ccp->fsm.layer_finished = ccp_layer_down; + ccp->fsm.layer_finished = ccp_layer_finished; + ccp->fsm.layer_down = ccp_layer_down; ccp->fsm.send_conf_req = send_conf_req; ccp->fsm.send_conf_ack = send_conf_ack; ccp->fsm.send_conf_nak = send_conf_nak; @@ -134,13 +139,18 @@ int ccp_layer_start(struct ppp_layer_data_t *ld) log_ppp_debug("ccp_layer_start\n"); if (list_empty(&ccp->options) || !conf_ccp) { + ccp->started = 1; ppp_layer_started(ccp->ppp, &ccp->ld); return 0; } - - ppp_fsm_lower_up(&ccp->fsm); - if (ppp_fsm_open(&ccp->fsm)) - return -1; + + ccp->starting = 1; + + if (!ccp->passive) { + ppp_fsm_lower_up(&ccp->fsm); + if (ppp_fsm_open(&ccp->fsm)) + return -1; + } if (ccp_set_flags(ccp->ppp->unit_fd, 1, 0)) { ppp_fsm_close(&ccp->fsm); @@ -159,7 +169,7 @@ void ccp_layer_finish(struct ppp_layer_data_t *ld) ccp_set_flags(ccp->ppp->unit_fd, 0, 0); ccp->fsm.fsm_state = FSM_Closed; - + log_ppp_debug("ccp_layer_finished\n"); ppp_layer_finished(ccp->ppp, &ccp->ld); } @@ -181,9 +191,8 @@ static void ccp_layer_up(struct ppp_fsm_t *fsm) { struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm); - log_ppp_debug("ccp_layer_started\n"); - if (!ccp->started) { + log_ppp_debug("ccp_layer_started\n"); ccp->started = 1; if (ccp_set_flags(ccp->ppp->unit_fd, 1, 1)) { ppp_terminate(ccp->ppp, TERM_NAS_ERROR, 0); @@ -193,18 +202,28 @@ static void ccp_layer_up(struct ppp_fsm_t *fsm) } } -static void ccp_layer_down(struct ppp_fsm_t *fsm) +static void ccp_layer_finished(struct ppp_fsm_t *fsm) { struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm); log_ppp_debug("ccp_layer_finished\n"); - if (!ccp->started) + if (!ccp->started) { + ccp->started = 1; ppp_layer_started(ccp->ppp, &ccp->ld); - ccp->started = 0; - ppp_layer_finished(ccp->ppp, &ccp->ld); + } } +static void ccp_layer_down(struct ppp_fsm_t *fsm) +{ + struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm); + + log_ppp_debug("ccp_layer_down\n"); + + ppp_fsm_close(fsm); +} + + static void print_ropt(struct recv_opt_t *ropt) { int i; @@ -225,19 +244,15 @@ static int send_conf_req(struct ppp_fsm_t *fsm) struct ccp_option_t *lopt; int n; - ccp->need_req = 0; - - if (ccp->passive) { - ccp->passive--; + if (ccp->passive) return 0; - } buf = _malloc(ccp->conf_req_len); ccp_hdr = (struct ccp_hdr_t*)buf; ccp_hdr->proto = htons(PPP_CCP); ccp_hdr->code = CONFREQ; - ccp_hdr->id = ++ccp->fsm.id; + ccp_hdr->id = ccp->fsm.id; ccp_hdr->len = 0; ptr = (uint8_t*)(ccp_hdr + 1); @@ -287,7 +302,7 @@ static void send_conf_nak(struct ppp_fsm_t *fsm) struct ppp_ccp_t *ccp = container_of(fsm, typeof(*ccp), fsm); uint8_t *buf = _malloc(ccp->conf_req_len), *ptr = buf; struct ccp_hdr_t *ccp_hdr = (struct ccp_hdr_t*)ptr; - struct recv_opt_t *ropt; + struct ccp_option_t *lopt; if (conf_ppp_verbose) log_ppp_info2("send [CCP ConfNak id=%x", ccp->fsm.recv_id); @@ -299,13 +314,13 @@ static void send_conf_nak(struct ppp_fsm_t *fsm) ptr += sizeof(*ccp_hdr); - list_for_each_entry(ropt, &ccp->ropt_list, entry) { - if (ropt->state == CCP_OPT_NAK) { + list_for_each_entry(lopt, &ccp->options, entry) { + if (lopt->state == CCP_OPT_NAK) { if (conf_ppp_verbose) { log_ppp_info2(" "); - ropt->lopt->h->print(log_ppp_info2, ropt->lopt, NULL); + lopt->h->print(log_ppp_info2, lopt, NULL); } - ptr += ropt->lopt->h->send_conf_nak(ccp, ropt->lopt, ptr); + ptr += lopt->h->send_conf_nak(ccp, lopt, ptr); } } @@ -365,7 +380,6 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size) struct ccp_option_t *lopt; int r, ret = 1, ack = 0; - ccp->need_req = 0; ccp->ropt_len = size; while (size > 0) { @@ -402,8 +416,6 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size) lopt->state = CCP_OPT_REJ; ropt->state = CCP_OPT_REJ; } else { - /*if (lopt->state == CCP_OPT_NAK && r == CCP_OPT_ACK) - ccp->need_req = 1;*/ lopt->state = r; ropt->state = r; } @@ -428,15 +440,14 @@ static int ccp_recv_conf_req(struct ppp_ccp_t *ccp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("]\n"); - /*list_for_each_entry(lopt,&ccp->options,entry) - { - if (lopt->state==CCP_OPT_NONE) - { - r=lopt->h->recv_conf_req(ccp,lopt,NULL); - lopt->state=r; - if (r<ret) ret=r; + list_for_each_entry(lopt, &ccp->options, entry) { + if (lopt->state == CCP_OPT_NONE) { + r = lopt->h->recv_conf_req(ccp, lopt, NULL); + lopt->state = r; + if (r < ret) + ret = r; } - }*/ + } return ret; } @@ -461,11 +472,11 @@ static int ccp_recv_conf_rej(struct ppp_ccp_t *ccp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("recv [CCP ConfRej id=%x", ccp->fsm.recv_id); - if (ccp->fsm.recv_id != ccp->fsm.id) { + /*if (ccp->fsm.recv_id != ccp->fsm.id) { if (conf_ppp_verbose) log_ppp_info2(": id mismatch ]\n"); return 0; - } + }*/ while (size > 0) { hdr = (struct ccp_opt_hdr_t *)data; @@ -499,11 +510,11 @@ static int ccp_recv_conf_nak(struct ppp_ccp_t *ccp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("recv [CCP ConfNak id=%x", ccp->fsm.recv_id); - if (ccp->fsm.recv_id != ccp->fsm.id) { + /*if (ccp->fsm.recv_id != ccp->fsm.id) { if (conf_ppp_verbose) log_ppp_info2(": id mismatch ]\n"); return 0; - } + }*/ while (size > 0) { hdr = (struct ccp_opt_hdr_t *)data; @@ -516,8 +527,6 @@ static int ccp_recv_conf_nak(struct ppp_ccp_t *ccp, uint8_t *data, int size) } if (lopt->h->recv_conf_nak && lopt->h->recv_conf_nak(ccp, lopt, data)) res = -1; - //lopt->state = CCP_OPT_NAK; - //ccp->need_req = 1; break; } } @@ -541,11 +550,11 @@ static int ccp_recv_conf_ack(struct ppp_ccp_t *ccp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("recv [CCP ConfAck id=%x", ccp->fsm.recv_id); - if (ccp->fsm.recv_id != ccp->fsm.id) { + /*if (ccp->fsm.recv_id != ccp->fsm.id) { if (conf_ppp_verbose) log_ppp_info2(": id mismatch ]\n"); return 0; - } + }*/ while (size > 0) { hdr = (struct ccp_opt_hdr_t *)data; @@ -612,7 +621,7 @@ static void ccp_recv(struct ppp_handler_t*h) struct ppp_ccp_t *ccp = container_of(h, typeof(*ccp), hnd); int r; - if (ccp->fsm.fsm_state == FSM_Initial || ccp->fsm.fsm_state == FSM_Closed || ccp->ppp->terminating) { + if (!ccp->starting || ccp->fsm.fsm_state == FSM_Closed || ccp->ppp->terminating) { if (conf_ppp_verbose) log_ppp_warn("CCP: discarding packet\n"); if (ccp->fsm.fsm_state == FSM_Closed || !conf_ccp) @@ -631,38 +640,51 @@ static void ccp_recv(struct ppp_handler_t*h) return; } + if ((hdr->code == CONFACK || hdr->code == CONFNAK || hdr->code == CONFREJ) && hdr->id != ccp->fsm.id) + return; + ccp->fsm.recv_id = hdr->id; + switch(hdr->code) { - case CONFREQ: + case CONFREQ: r = ccp_recv_conf_req(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); - switch(r) { - case CCP_OPT_ACK: - ppp_fsm_recv_conf_req_ack(&ccp->fsm); - break; - case CCP_OPT_NAK: - ppp_fsm_recv_conf_req_nak(&ccp->fsm); - break; - case CCP_OPT_REJ: - ppp_fsm_recv_conf_req_rej(&ccp->fsm); - break; + if (ccp->passive) { + ccp->passive = 0; + ppp_fsm_lower_up(&ccp->fsm); + ppp_fsm_open(&ccp->fsm); + } + if (ccp->started) { + if (r == CCP_OPT_ACK) + send_conf_ack(&ccp->fsm); + else + r = CCP_OPT_FAIL; + } else { + switch(r) { + case CCP_OPT_ACK: + ppp_fsm_recv_conf_req_ack(&ccp->fsm); + break; + case CCP_OPT_NAK: + ppp_fsm_recv_conf_req_nak(&ccp->fsm); + break; + case CCP_OPT_REJ: + ppp_fsm_recv_conf_req_rej(&ccp->fsm); + break; + } } ccp_free_conf_req(ccp); - if (r == CCP_OPT_ACK && ccp->passive) { + /*if (r == CCP_OPT_ACK && ccp->passive) { ccp->passive = 0; send_conf_req(&ccp->fsm); - } + }*/ if (r == CCP_OPT_FAIL) ppp_terminate(ccp->ppp, TERM_USER_ERROR, 0); break; case CONFACK: if (ccp_recv_conf_ack(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN)) ppp_terminate(ccp->ppp, TERM_USER_ERROR, 0); - else { + else ppp_fsm_recv_conf_ack(&ccp->fsm); - if (ccp->need_req) - send_conf_req(&ccp->fsm); - } break; case CONFNAK: ccp_recv_conf_nak(ccp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); @@ -720,6 +742,10 @@ int ccp_option_register(struct ccp_option_handler_t *h) return 0; } +struct ppp_ccp_t *ccp_find_layer_data(struct ppp_t *ppp) +{ + return container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(struct ppp_ccp_t), ld); +} struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h) { struct ppp_ccp_t *ccp = container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(*ccp), ld); @@ -733,6 +759,21 @@ struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handle abort(); } +int ccp_ipcp_started(struct ppp_t *ppp) +{ + struct ppp_ccp_t *ccp = container_of(ppp_find_layer_data(ppp, &ccp_layer), typeof(*ccp), ld); + + if (ccp->passive) { + ccp->fsm.fsm_state = FSM_Closed; + ccp->started = 1; + ppp_layer_started(ccp->ppp, &ccp->ld); + + return 0; + } + + return !ccp->started; +} + static struct ppp_layer_t ccp_layer= { .init = ccp_layer_init, @@ -748,9 +789,13 @@ static void load_config(void) opt = conf_get_opt("ppp", "ccp"); if (opt && atoi(opt) >= 0) conf_ccp = atoi(opt); + + opt = conf_get_opt("ppp", "ccp-max-configure"); + if (opt && atoi(opt) > 0) + conf_ccp_max_configure = atoi(opt); } -static void __init ccp_init(void) +static void ccp_init(void) { ppp_register_layer("ccp", &ccp_layer); @@ -758,3 +803,4 @@ static void __init ccp_init(void) triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(3, ccp_init); diff --git a/accel-pppd/ppp/ppp_ccp.h b/accel-pppd/ppp/ppp_ccp.h index 2c2dc6d..3a48816 100644 --- a/accel-pppd/ppp/ppp_ccp.h +++ b/accel-pppd/ppp/ppp_ccp.h @@ -84,13 +84,16 @@ struct ppp_ccp_t int ropt_len; int conf_req_len; - int passive; + int passive:1; + int starting:1; int started:1; - int need_req:1; }; int ccp_option_register(struct ccp_option_handler_t *h); struct ccp_option_t *ccp_find_option(struct ppp_t *ppp, struct ccp_option_handler_t *h); +struct ppp_ccp_t *ccp_find_layer_data(struct ppp_t *ppp); +int ccp_ipcp_started(struct ppp_t *ppp); + #endif diff --git a/accel-pppd/ppp/ppp_fsm.c b/accel-pppd/ppp/ppp_fsm.c index c6bc430..b43945b 100644 --- a/accel-pppd/ppp/ppp_fsm.c +++ b/accel-pppd/ppp/ppp_fsm.c @@ -14,7 +14,7 @@ static int conf_max_terminate = 2; static int conf_max_configure = 10; static int conf_max_failure = 10; -static int conf_timeout = 5; +static int conf_timeout = 3; void send_term_req(struct ppp_fsm_t *layer); void send_term_ack(struct ppp_fsm_t *layer); @@ -35,7 +35,8 @@ void ppp_fsm_init(struct ppp_fsm_t *layer) layer->max_terminate = conf_max_terminate; layer->max_configure = conf_max_configure; layer->max_failure = conf_max_failure; - layer->timeout = conf_timeout; + + layer->id = 1; } void ppp_fsm_free(struct ppp_fsm_t *layer) { @@ -96,7 +97,7 @@ int ppp_fsm_open(struct ppp_fsm_t *layer) switch(layer->fsm_state) { case FSM_Initial: - if (layer->layer_started) layer->layer_started(layer); + //if (layer->layer_started) layer->layer_started(layer); layer->fsm_state=FSM_Starting; break; case FSM_Starting: @@ -168,7 +169,6 @@ void ppp_fsm_timeout0(struct ppp_fsm_t *layer) case FSM_Req_Sent: case FSM_Ack_Sent: --layer->restart_counter; - --layer->id; if (layer->send_conf_req) layer->send_conf_req(layer); break; default: @@ -315,6 +315,7 @@ void ppp_fsm_recv_conf_req_rej(struct ppp_fsm_t *layer) void ppp_fsm_recv_conf_ack(struct ppp_fsm_t *layer) { + ++layer->id; switch(layer->fsm_state) { case FSM_Closed: @@ -351,6 +352,7 @@ void ppp_fsm_recv_conf_ack(struct ppp_fsm_t *layer) void ppp_fsm_recv_conf_rej(struct ppp_fsm_t *layer) { + ++layer->id; switch(layer->fsm_state) { case FSM_Closed: @@ -373,7 +375,10 @@ void ppp_fsm_recv_conf_rej(struct ppp_fsm_t *layer) layer->fsm_state=FSM_Req_Sent; break; case FSM_Ack_Sent: - //if (layer->init_req_cnt) layer->init_req_cnt(layer); + if (++layer->conf_failure == layer->max_failure) { + if (layer->layer_down) layer->layer_down(layer); + return; + } init_req_counter(layer,layer->max_configure); --layer->restart_counter; if (layer->send_conf_req) layer->send_conf_req(layer); @@ -536,9 +541,10 @@ static void load_config(void) conf_timeout = atoi(opt); } -void __init fsm_init(void) +static void fsm_init(void) { load_config(); triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(3, fsm_init); diff --git a/accel-pppd/ppp/ppp_fsm.h b/accel-pppd/ppp/ppp_fsm.h index 6010240..6d2fb14 100644 --- a/accel-pppd/ppp/ppp_fsm.h +++ b/accel-pppd/ppp/ppp_fsm.h @@ -30,7 +30,6 @@ struct ppp_fsm_t int max_terminate; int max_configure; int max_failure; - int timeout; int conf_failure; int id; diff --git a/accel-pppd/ppp/ppp_ipcp.c b/accel-pppd/ppp/ppp_ipcp.c index 5d66c9d..bd9f50d 100644 --- a/accel-pppd/ppp/ppp_ipcp.c +++ b/accel-pppd/ppp/ppp_ipcp.c @@ -23,6 +23,7 @@ struct recv_opt_t }; static LIST_HEAD(option_handlers); +static struct ppp_layer_t ipcp_layer; static void ipcp_layer_up(struct ppp_fsm_t*); static void ipcp_layer_down(struct ppp_fsm_t*); @@ -134,10 +135,8 @@ void ipcp_layer_free(struct ppp_layer_data_t *ld) _free(ipcp); } -static void ipcp_layer_up(struct ppp_fsm_t *fsm) +static void __ipcp_layer_up(struct ppp_ipcp_t *ipcp) { - struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm); - log_ppp_debug("ipcp_layer_started\n"); if (!ipcp->started) { @@ -146,6 +145,14 @@ static void ipcp_layer_up(struct ppp_fsm_t *fsm) } } +static void ipcp_layer_up(struct ppp_fsm_t *fsm) +{ + struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm); + + if (!ipcp->delay_ack) + __ipcp_layer_up(ipcp); +} + static void ipcp_layer_down(struct ppp_fsm_t *fsm) { struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm); @@ -181,7 +188,7 @@ static int send_conf_req(struct ppp_fsm_t *fsm) ipcp_hdr->proto = htons(PPP_IPCP); ipcp_hdr->code = CONFREQ; - ipcp_hdr->id = ++ipcp->fsm.id; + ipcp_hdr->id = ipcp->fsm.id; ipcp_hdr->len = 0; ptr += sizeof(*ipcp_hdr); @@ -221,6 +228,11 @@ static void send_conf_ack(struct ppp_fsm_t *fsm) struct ppp_ipcp_t *ipcp = container_of(fsm, typeof(*ipcp), fsm); struct ipcp_hdr_t *hdr = (struct ipcp_hdr_t*)ipcp->ppp->buf; + if (ipcp->delay_ack) { + send_term_ack(fsm); + return; + } + hdr->code = CONFACK; if (conf_ppp_verbose) @@ -409,11 +421,11 @@ static int ipcp_recv_conf_rej(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("recv [IPCP ConfRej id=%x", ipcp->fsm.recv_id); - if (ipcp->fsm.recv_id != ipcp->fsm.id) { + /*if (ipcp->fsm.recv_id != ipcp->fsm.id) { if (conf_ppp_verbose) log_ppp_info2(": id mismatch ]\n"); return 0; - } + }*/ while (size > 0) { hdr = (struct ipcp_opt_hdr_t *)data; @@ -447,11 +459,11 @@ static int ipcp_recv_conf_nak(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("recv [IPCP ConfNak id=%x", ipcp->fsm.recv_id); - if (ipcp->fsm.recv_id != ipcp->fsm.id) { + /*if (ipcp->fsm.recv_id != ipcp->fsm.id) { if (conf_ppp_verbose) log_ppp_info2(": id mismatch ]\n"); return 0; - } + }*/ while (size > 0) { hdr = (struct ipcp_opt_hdr_t *)data; @@ -487,11 +499,11 @@ static int ipcp_recv_conf_ack(struct ppp_ipcp_t *ipcp, uint8_t *data, int size) if (conf_ppp_verbose) log_ppp_info2("recv [IPCP ConfAck id=%x", ipcp->fsm.recv_id); - if (ipcp->fsm.recv_id != ipcp->fsm.id) { + /*if (ipcp->fsm.recv_id != ipcp->fsm.id) { if (conf_ppp_verbose) log_ppp_info2(": id mismatch ]\n"); return 0; - } + }*/ while (size > 0) { hdr = (struct ipcp_opt_hdr_t *)data; @@ -557,6 +569,7 @@ static void ipcp_recv(struct ppp_handler_t*h) struct ipcp_hdr_t *hdr; struct ppp_ipcp_t *ipcp = container_of(h, typeof(*ipcp), hnd); int r; + int delay_ack = ipcp->delay_ack; if (ipcp->fsm.fsm_state == FSM_Initial || ipcp->fsm.fsm_state == FSM_Closed || ipcp->ppp->terminating) { if (conf_ppp_verbose) @@ -574,8 +587,12 @@ static void ipcp_recv(struct ppp_handler_t*h) log_ppp_warn("IPCP: short packet received\n"); return; } + + if ((hdr->code == CONFACK || hdr->code == CONFNAK || hdr->code == CONFREJ) && hdr->id != ipcp->fsm.id) + return; ipcp->fsm.recv_id = hdr->id; + switch(hdr->code) { case CONFREQ: r = ipcp_recv_conf_req(ipcp,(uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); @@ -583,16 +600,25 @@ static void ipcp_recv(struct ppp_handler_t*h) ipcp_free_conf_req(ipcp); return; } - switch(r) { - case IPCP_OPT_ACK: - ppp_fsm_recv_conf_req_ack(&ipcp->fsm); - break; - case IPCP_OPT_NAK: - ppp_fsm_recv_conf_req_nak(&ipcp->fsm); - break; - case IPCP_OPT_REJ: - ppp_fsm_recv_conf_req_rej(&ipcp->fsm); - break; + if (delay_ack && !ipcp->delay_ack) + __ipcp_layer_up(ipcp); + if (ipcp->started || delay_ack) { + if (r == IPCP_OPT_ACK) + send_conf_ack(&ipcp->fsm); + else + r = IPCP_OPT_FAIL; + } else { + switch(r) { + case IPCP_OPT_ACK: + ppp_fsm_recv_conf_req_ack(&ipcp->fsm); + break; + case IPCP_OPT_NAK: + ppp_fsm_recv_conf_req_nak(&ipcp->fsm); + break; + case IPCP_OPT_REJ: + ppp_fsm_recv_conf_req_rej(&ipcp->fsm); + break; + } } ipcp_free_conf_req(ipcp); if (r == IPCP_OPT_FAIL) @@ -650,6 +676,19 @@ int ipcp_option_register(struct ipcp_option_handler_t *h) return 0; } +struct ipcp_option_t *ipcp_find_option(struct ppp_t *ppp, struct ipcp_option_handler_t *h) +{ + struct ppp_ipcp_t *ipcp = container_of(ppp_find_layer_data(ppp, &ipcp_layer), typeof(*ipcp), ld); + struct ipcp_option_t *opt; + + list_for_each_entry(opt, &ipcp->options, entry) + if (opt->h == h) + return opt; + + log_emerg("ipcp: BUG: option not found\n"); + abort(); +} + static struct ppp_layer_t ipcp_layer = { .init = ipcp_layer_init, @@ -658,8 +697,9 @@ static struct ppp_layer_t ipcp_layer = .free = ipcp_layer_free, }; -static void __init ipcp_init(void) +static void ipcp_init(void) { ppp_register_layer("ipcp", &ipcp_layer); } +DEFINE_INIT(3, ipcp_init); diff --git a/accel-pppd/ppp/ppp_ipcp.h b/accel-pppd/ppp/ppp_ipcp.h index c955987..f955461 100644 --- a/accel-pppd/ppp/ppp_ipcp.h +++ b/accel-pppd/ppp/ppp_ipcp.h @@ -88,9 +88,11 @@ struct ppp_ipcp_t int conf_req_len; int started:1; + int delay_ack:1; }; int ipcp_option_register(struct ipcp_option_handler_t *h); +struct ipcp_option_t *ipcp_find_option(struct ppp_t *ppp, struct ipcp_option_handler_t *h); #endif diff --git a/accel-pppd/ppp/ppp_lcp.c b/accel-pppd/ppp/ppp_lcp.c index c46c5a4..fa23436 100644 --- a/accel-pppd/ppp/ppp_lcp.c +++ b/accel-pppd/ppp/ppp_lcp.c @@ -171,7 +171,7 @@ static void lcp_layer_down(struct ppp_fsm_t *fsm) { struct ppp_lcp_t *lcp = container_of(fsm, typeof(*lcp), fsm); //ppp_fsm_close(&lcp->fsm); - stop_echo(lcp); + //stop_echo(lcp); //ppp_layer_finished(lcp->ppp,&lcp->ld); } @@ -214,7 +214,7 @@ static int send_conf_req(struct ppp_fsm_t *fsm) lcp_hdr->proto = htons(PPP_LCP); lcp_hdr->code = CONFREQ; - lcp_hdr->id = ++lcp->fsm.id; + lcp_hdr->id = lcp->fsm.id; lcp_hdr->len = 0; ptr += sizeof(*lcp_hdr); @@ -569,34 +569,39 @@ static int lcp_recv_conf_ack(struct ppp_lcp_t *lcp, uint8_t *data, int size) static void lcp_recv_echo_repl(struct ppp_lcp_t *lcp, uint8_t *data, int size) { - uint32_t magic = *(uint32_t *)data; + uint32_t magic; if (size != 4) { - log_ppp_error("lcp:echo: magic number size mismatch\n"); - ppp_terminate(lcp->ppp, TERM_USER_ERROR, 0); - } + if (conf_ppp_verbose) + log_ppp_debug("recv [LCP EchoRep id=%x]\n", lcp->fsm.recv_id); + } else { + magic = *(uint32_t *)data; - if (conf_ppp_verbose) - log_ppp_debug("recv [LCP EchoRep id=%x <magic %x>]\n", lcp->fsm.recv_id, magic); + if (conf_ppp_verbose) + log_ppp_debug("recv [LCP EchoRep id=%x <magic %x>]\n", lcp->fsm.recv_id, magic); - if (magic == lcp->magic) { - log_ppp_error("lcp: echo: loop-back detected\n"); - ppp_terminate(lcp->ppp, TERM_NAS_ERROR, 0); + if (magic == lcp->magic) { + log_ppp_error("lcp: echo: loop-back detected\n"); + ppp_terminate(lcp->ppp, TERM_NAS_ERROR, 0); + } } + lcp->fsm.id++; lcp->echo_sent = 0; } static void send_echo_reply(struct ppp_lcp_t *lcp) { struct lcp_hdr_t *hdr = (struct lcp_hdr_t*)lcp->ppp->buf; - uint32_t magic = *(uint32_t *)(hdr + 1); + //uint32_t magic = *(uint32_t *)(hdr + 1); + + lcp->echo_sent = 0; hdr->code = ECHOREP; - *(uint32_t *)(hdr + 1) = lcp->magic; + *(uint32_t *)(hdr + 1) = htonl(lcp->magic); if (conf_ppp_verbose) - log_ppp_debug("send [LCP EchoRep id=%x <magic %x>]\n", hdr->id, magic); + log_ppp_debug("send [LCP EchoRep id=%x <magic %x>]\n", hdr->id, htonl(lcp->magic)); ppp_chan_send(lcp->ppp, hdr, ntohs(hdr->len) + 2); } @@ -611,7 +616,7 @@ static void send_echo_request(struct triton_timer_t *t) } __attribute__((packed)) msg = { .hdr.proto = htons(PPP_LCP), .hdr.code = ECHOREQ, - .hdr.id = ++lcp->fsm.id, + .hdr.id = lcp->fsm.id, .hdr.len = htons(8), .magic = lcp->magic, }; @@ -702,25 +707,29 @@ static void lcp_recv(struct ppp_handler_t*h) int r; char *term_msg; - if (lcp->fsm.fsm_state == FSM_Initial || lcp->fsm.fsm_state == FSM_Closed || lcp->ppp->terminating) { - /*if (conf_ppp_verbose) - log_ppp_warn("LCP: discaring packet\n"); - lcp_send_proto_rej(ccp->ppp, htons(PPP_CCP));*/ - return; - } - if (lcp->ppp->buf_size < PPP_HEADERLEN + 2) { log_ppp_warn("LCP: short packet received\n"); return; } - hdr = (struct lcp_hdr_t *)lcp->ppp->buf; + hdr = (struct lcp_hdr_t *)lcp->ppp->buf; if (ntohs(hdr->len) < PPP_HEADERLEN) { log_ppp_warn("LCP: short packet received\n"); return; } + if ((hdr->code == CONFACK || hdr->code == CONFNAK || hdr->code == CONFREJ) && hdr->id != lcp->fsm.id) + return; + + if (lcp->fsm.fsm_state == FSM_Initial || lcp->fsm.fsm_state == FSM_Closed || (lcp->ppp->terminating && (hdr->code != TERMACK && hdr->code != TERMREQ))) { + /*if (conf_ppp_verbose) + log_ppp_warn("LCP: discaring packet\n"); + lcp_send_proto_rej(ccp->ppp, htons(PPP_CCP));*/ + return; + } + lcp->fsm.recv_id = hdr->id; + switch(hdr->code) { case CONFREQ: r = lcp_recv_conf_req(lcp, (uint8_t*)(hdr + 1), ntohs(hdr->len) - PPP_HDRLEN); @@ -839,7 +848,7 @@ static void load_config(void) conf_echo_failure = atoi(opt); } -static void __init lcp_init(void) +static void lcp_init(void) { load_config(); @@ -848,3 +857,4 @@ static void __init lcp_init(void) triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config); } +DEFINE_INIT(3, lcp_init); diff --git a/accel-pppd/radius/CMakeLists.txt b/accel-pppd/radius/CMakeLists.txt index d85d60c..0c1789e 100644 --- a/accel-pppd/radius/CMakeLists.txt +++ b/accel-pppd/radius/CMakeLists.txt @@ -5,6 +5,7 @@ SET(sources packet.c auth.c acct.c + serv.c dm_coa.c radius.c ) diff --git a/accel-pppd/radius/acct.c b/accel-pppd/radius/acct.c index 6238793..4f1d901 100644 --- a/accel-pppd/radius/acct.c +++ b/accel-pppd/radius/acct.c @@ -116,6 +116,30 @@ static int rad_acct_read(struct triton_md_handler_t *h) return 0; } +static void __rad_req_send(struct rad_req_t *req) +{ + while (1) { + + if (rad_server_req_enter(req)) { + if (rad_server_realloc(req, 1)) { + log_ppp_warn("radius:acct: no servers available, terminating session...\n"); + if (conf_acct_timeout) { + ppp_terminate(req->rpd->ppp, TERM_NAS_ERROR, 0); + return; + } + break; + } + continue; + } + + rad_req_send(req, conf_interim_verbose); + + rad_server_req_exit(req); + + break; + } +} + static void rad_acct_timeout(struct triton_timer_t *t) { struct rad_req_t *req = container_of(t, typeof(*req), timeout); @@ -130,9 +154,13 @@ static void rad_acct_timeout(struct triton_timer_t *t) dt = ts - req->rpd->acct_timestamp; if (dt > conf_acct_timeout) { - log_ppp_warn("radius:acct: no response, terminating session...\n"); - ppp_terminate(req->rpd->ppp, TERM_NAS_ERROR, 0); - return; + rad_server_fail(req->serv); + if (rad_server_realloc(req, 1)) { + log_ppp_warn("radius:acct: no servers available, terminating session...\n"); + ppp_terminate(req->rpd->ppp, TERM_NAS_ERROR, 0); + return; + } + time(&req->rpd->acct_timestamp); } if (dt > conf_acct_timeout / 2) { req->timeout.period += 1000; @@ -144,11 +172,14 @@ static void rad_acct_timeout(struct triton_timer_t *t) } } - req->pack->id++; - - rad_packet_change_int(req->pack, NULL, "Acct-Delay-Time", dt); - req_set_RA(req, conf_acct_secret); - rad_req_send(req, conf_interim_verbose); + if (conf_acct_delay_time) { + req->pack->id++; + rad_packet_change_int(req->pack, NULL, "Acct-Delay-Time", dt); + req_set_RA(req, req->serv->acct_secret); + } + + __rad_req_send(req); + __sync_add_and_fetch(&stat_interim_sent, 1); } @@ -171,9 +202,12 @@ static void rad_acct_interim_update(struct triton_timer_t *t) rpd->acct_req->pack->id++; rad_packet_change_val(rpd->acct_req->pack, NULL, "Acct-Status-Type", "Interim-Update"); - rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", 0); - req_set_RA(rpd->acct_req, conf_acct_secret); - rad_req_send(rpd->acct_req, conf_interim_verbose); + if (conf_acct_delay_time) + rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", 0); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); + + __rad_req_send(rpd->acct_req); + __sync_add_and_fetch(&stat_interim_sent, 1); if (conf_acct_timeout) { rpd->acct_req->timeout.period = conf_timeout * 1000; @@ -186,6 +220,9 @@ int rad_acct_start(struct radius_pd_t *rpd) int i; time_t ts; unsigned int dt; + + if (!conf_accounting) + return 0; rpd->acct_req = rad_req_alloc(rpd, CODE_ACCOUNTING_REQUEST, rpd->ppp->username); if (!rpd->acct_req) { @@ -210,44 +247,75 @@ int rad_acct_start(struct radius_pd_t *rpd) time(&rpd->acct_timestamp); - for (i = 0; i < conf_max_try; i++) { - time(&ts); - rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); - if (req_set_RA(rpd->acct_req, conf_acct_secret)) - goto out_err; - if (rad_req_send(rpd->acct_req, conf_verbose)) - goto out_err; - __sync_add_and_fetch(&stat_acct_sent, 1); - rad_req_wait(rpd->acct_req, conf_timeout); - if (!rpd->acct_req->reply) { - rpd->acct_req->pack->id++; - __sync_add_and_fetch(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; + + while (1) { + + if (rad_server_req_enter(rpd->acct_req)) { + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_start: no servers available\n"); + goto out_err; + } + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; continue; } - dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + - (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; - stat_accm_add(stat_acct_query_1m, dt); - stat_accm_add(stat_acct_query_5m, dt); + for (i = 0; i < conf_max_try; i++) { + if (conf_acct_delay_time) { + time(&ts); + rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; + } - if (rpd->acct_req->reply->id != rpd->acct_req->pack->id || rpd->acct_req->reply->code != CODE_ACCOUNTING_RESPONSE) { - rad_packet_free(rpd->acct_req->reply); - rpd->acct_req->reply = NULL; - rpd->acct_req->pack->id++; - __sync_add_and_fetch(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); - } else + if (rad_req_send(rpd->acct_req, conf_verbose)) + goto out_err; + + __sync_add_and_fetch(&stat_acct_sent, 1); + + rad_req_wait(rpd->acct_req, conf_timeout); + + if (!rpd->acct_req->reply) { + if (conf_acct_delay_time) + rpd->acct_req->pack->id++; + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + continue; + } + + dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + + (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; + stat_accm_add(stat_acct_query_1m, dt); + stat_accm_add(stat_acct_query_5m, dt); + + if (rpd->acct_req->reply->id != rpd->acct_req->pack->id || rpd->acct_req->reply->code != CODE_ACCOUNTING_RESPONSE) { + rad_packet_free(rpd->acct_req->reply); + rpd->acct_req->reply = NULL; + rpd->acct_req->pack->id++; + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + } else + break; + } + + rad_server_req_exit(rpd->acct_req); + + if (rpd->acct_req->reply) break; - } - if (!rpd->acct_req->reply) { - log_ppp_warn("radius:acct_start: no response\n"); - goto out_err; + rad_server_fail(rpd->acct_req->serv); + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_start: no servers available\n"); + goto out_err; + } + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + goto out_err; } - + rpd->acct_req->hnd.read = rad_acct_read; triton_md_register_handler(rpd->ppp->ctrl->ctx, &rpd->acct_req->hnd); @@ -278,6 +346,9 @@ void rad_acct_stop(struct radius_pd_t *rpd) time_t ts; unsigned int dt; + if (!rpd->acct_req || !rpd->acct_req->serv) + return; + if (rpd->acct_interim_timer.tpd) triton_timer_del(&rpd->acct_interim_timer); @@ -315,7 +386,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) } rad_packet_change_val(rpd->acct_req->pack, NULL, "Acct-Status-Type", "Stop"); req_set_stat(rpd->acct_req, rpd->ppp); - req_set_RA(rpd->acct_req, conf_acct_secret); + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); /// !!! rad_req_add_val(rpd->acct_req, "Acct-Terminate-Cause", ""); if (rpd->acct_req->reply) { @@ -325,39 +396,63 @@ void rad_acct_stop(struct radius_pd_t *rpd) time(&rpd->acct_timestamp); - for(i = 0; i < conf_max_try; i++) { - time(&ts); - rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); - rpd->acct_req->pack->id++; - if (req_set_RA(rpd->acct_req, conf_acct_secret)) - break; - if (rad_req_send(rpd->acct_req, conf_verbose)) - break; - __sync_add_and_fetch(&stat_acct_sent, 1); - rad_req_wait(rpd->acct_req, conf_timeout); - if (!rpd->acct_req->reply) { - __sync_add_and_fetch(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); + while (1) { + + if (rad_server_req_enter(rpd->acct_req)) { + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_stop: no servers available\n"); + break; + } + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); continue; } - dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + - (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; - stat_accm_add(stat_acct_query_1m, dt); - stat_accm_add(stat_acct_query_5m, dt); + for(i = 0; i < conf_max_try; i++) { + if (conf_acct_delay_time) { + time(&ts); + rad_packet_change_int(rpd->acct_req->pack, NULL, "Acct-Delay-Time", ts - rpd->acct_timestamp); + rpd->acct_req->pack->id++; + if (req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret)) + break; + } + if (rad_req_send(rpd->acct_req, conf_verbose)) + break; + __sync_add_and_fetch(&stat_acct_sent, 1); + rad_req_wait(rpd->acct_req, conf_timeout); + if (!rpd->acct_req->reply) { + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + continue; + } + + dt = (rpd->acct_req->reply->tv.tv_sec - rpd->acct_req->pack->tv.tv_sec) * 1000 + + (rpd->acct_req->reply->tv.tv_usec - rpd->acct_req->pack->tv.tv_usec) / 1000; + stat_accm_add(stat_acct_query_1m, dt); + stat_accm_add(stat_acct_query_5m, dt); + + if (rpd->acct_req->reply->id != rpd->acct_req->pack->id || rpd->acct_req->reply->code != CODE_ACCOUNTING_RESPONSE) { + rad_packet_free(rpd->acct_req->reply); + rpd->acct_req->reply = NULL; + __sync_add_and_fetch(&stat_acct_lost, 1); + stat_accm_add(stat_acct_lost_1m, 1); + stat_accm_add(stat_acct_lost_5m, 1); + } else + break; + } - if (rpd->acct_req->reply->id != rpd->acct_req->pack->id || rpd->acct_req->reply->code != CODE_ACCOUNTING_RESPONSE) { - rad_packet_free(rpd->acct_req->reply); - rpd->acct_req->reply = NULL; - __sync_add_and_fetch(&stat_acct_lost, 1); - stat_accm_add(stat_acct_lost_1m, 1); - stat_accm_add(stat_acct_lost_5m, 1); - } else + rad_server_req_exit(rpd->acct_req); + + if (rpd->acct_req->reply) break; + + rad_server_fail(rpd->acct_req->serv); + if (rad_server_realloc(rpd->acct_req, 1)) { + log_ppp_warn("radius:acct_stop: no servers available\n"); + break; + } + req_set_RA(rpd->acct_req, rpd->acct_req->serv->acct_secret); } - if (!rpd->acct_req->reply) - log_ppp_warn("radius:acct_stop: no response\n"); rad_req_free(rpd->acct_req); rpd->acct_req = NULL; diff --git a/accel-pppd/radius/auth.c b/accel-pppd/radius/auth.c index 70ecbbe..e4810fa 100644 --- a/accel-pppd/radius/auth.c +++ b/accel-pppd/radius/auth.c @@ -30,7 +30,7 @@ static int decrypt_chap_mppe_keys(struct rad_req_t *req, struct rad_attr_t *attr memcpy(plain, attr->val.octets, 32); MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, req->pack->buf + 4, 16); MD5_Final(md5, &md5_ctx); @@ -38,7 +38,7 @@ static int decrypt_chap_mppe_keys(struct rad_req_t *req, struct rad_attr_t *attr plain[i] ^= md5[i]; MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, attr->val.octets, 16); MD5_Final(md5, &md5_ctx); @@ -74,7 +74,7 @@ static int decrypt_mppe_key(struct rad_req_t *req, struct rad_attr_t *attr, uint } MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, req->pack->buf + 4, 16); MD5_Update(&md5_ctx, attr->val.octets, 2); MD5_Final(md5, &md5_ctx); @@ -90,7 +90,7 @@ static int decrypt_mppe_key(struct rad_req_t *req, struct rad_attr_t *attr, uint } MD5_Init(&md5_ctx); - MD5_Update(&md5_ctx, conf_auth_secret, strlen(conf_auth_secret)); + MD5_Update(&md5_ctx, req->serv->auth_secret, strlen(req->serv->auth_secret)); MD5_Update(&md5_ctx, attr->val.octets + 2, 16); MD5_Final(md5, &md5_ctx); @@ -145,42 +145,71 @@ static uint8_t* encrypt_password(const char *passwd, const char *secret, const u static int rad_auth_send(struct rad_req_t *req) { int i; - struct timeval tv; + struct timeval tv, tv2; unsigned int dt; + int timeout; - for(i = 0; i < conf_max_try; i++) { - __sync_add_and_fetch(&stat_auth_sent, 1); - gettimeofday(&tv, NULL); - if (rad_req_send(req, conf_verbose)) - goto out; + while (1) { + if (rad_server_req_enter(req)) { + if (rad_server_realloc(req, 0)) { + log_ppp_warn("radius: no available servers\n"); + break; + } + continue; + } - rad_req_wait(req, conf_timeout); + for(i = 0; i < conf_max_try; i++) { + __sync_add_and_fetch(&stat_auth_sent, 1); + gettimeofday(&tv, NULL); + if (rad_req_send(req, conf_verbose)) + goto out; - if (req->reply) { - if (req->reply->id != req->pack->id) { - __sync_add_and_fetch(&stat_auth_lost, 1); - stat_accm_add(stat_auth_lost_1m, 1); - stat_accm_add(stat_auth_lost_5m, 1); - rad_packet_free(req->reply); - req->reply = NULL; - } else { + timeout = conf_timeout; + + while (timeout > 0) { + + rad_req_wait(req, timeout); + + if (req->reply) { + if (req->reply->id != req->pack->id) { + rad_packet_free(req->reply); + req->reply = NULL; + gettimeofday(&tv2, NULL); + timeout = conf_timeout - ((tv2.tv_sec - tv.tv_sec) * 1000 + (tv2.tv_usec - tv.tv_usec) / 1000); + } else + break; + } else + break; + } + + if (req->reply) { dt = (req->reply->tv.tv_sec - tv.tv_sec) * 1000 + (req->reply->tv.tv_usec - tv.tv_usec) / 1000; stat_accm_add(stat_auth_query_1m, dt); stat_accm_add(stat_auth_query_5m, dt); break; + } else { + __sync_add_and_fetch(&stat_auth_lost, 1); + stat_accm_add(stat_auth_lost_1m, 1); + stat_accm_add(stat_auth_lost_5m, 1); } - } else - __sync_add_and_fetch(&stat_auth_lost, 1); - stat_accm_add(stat_auth_lost_1m, 1); - stat_accm_add(stat_auth_lost_5m, 1); - } + } + + rad_server_req_exit(req); - if (!req->reply) - log_ppp_warn("radius:auth: no response\n"); - else if (req->reply->code == CODE_ACCESS_ACCEPT) { - if (rad_proc_attrs(req)) - return PWDB_DENIED; - return PWDB_SUCCESS; + if (!req->reply) { + rad_server_fail(req->serv); + if (rad_server_realloc(req, 0)) { + log_ppp_warn("radius: no available servers\n"); + break; + } + } else { + if (req->reply->code == CODE_ACCESS_ACCEPT) { + if (rad_proc_attrs(req)) + return PWDB_DENIED; + return PWDB_SUCCESS; + } else + break; + } } out: @@ -200,7 +229,7 @@ int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args) if (!req) return PWDB_DENIED; - epasswd = encrypt_password(passwd, conf_auth_secret, req->RA, &epasswd_len); + epasswd = encrypt_password(passwd, req->serv->auth_secret, req->RA, &epasswd_len); if (!epasswd) goto out; @@ -253,20 +282,16 @@ int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list arg if (challenge_len == 16) memcpy(rpd->auth_req->RA, challenge, 16); - else { - if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "CHAP-Challenge", challenge, challenge_len)) + if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "CHAP-Challenge", challenge, challenge_len)) goto out; - } if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "CHAP-Password", chap_password, 17)) goto out; } else { if (challenge_len == 16) memcpy(rpd->auth_req->RA, challenge, 16); - else { - if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "CHAP-Challenge", challenge, challenge_len)) + if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "CHAP-Challenge", challenge, challenge_len)) goto out; - } if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "CHAP-Password", chap_password, 17)) goto out; @@ -354,6 +379,7 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar { int r = PWDB_DENIED; uint8_t response[50]; + struct rad_attr_t *ra; int id = va_arg(args, int); const uint8_t *challenge = va_arg(args, const uint8_t *); @@ -361,6 +387,7 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar const uint8_t *lm_response = va_arg(args, const uint8_t *); const uint8_t *nt_response = va_arg(args, const uint8_t *); int flags = va_arg(args, int); + char **mschap_error = va_arg(args, char **); response[0] = id; response[1] = flags; @@ -402,6 +429,7 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar if (rad_packet_add_str(rpd->auth_req->pack, NULL, "Acct-Session-Id", rpd->ppp->sessionid)) goto out; + r = rad_auth_send(rpd->auth_req); if (r == PWDB_SUCCESS) { struct ev_radius_t ev = { @@ -412,6 +440,10 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev); setup_mppe(rpd->auth_req, challenge); rpd->auth_req->pack->id++; + } else if (rpd->auth_req->reply) { + ra = rad_packet_find_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP-Error"); + if (ra) + *mschap_error = ra->val.string; } return r; @@ -435,6 +467,8 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar const uint8_t *response = va_arg(args, const uint8_t *); int flags = va_arg(args, int); uint8_t *authenticator = va_arg(args, uint8_t *); + char **mschap_error = va_arg(args, char **); + char **reply_msg = va_arg(args, char **); mschap_response[0] = id; mschap_response[1] = flags; @@ -495,8 +529,17 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar triton_event_fire(EV_RADIUS_ACCESS_ACCEPT, &ev); setup_mppe(rpd->auth_req, NULL); rpd->auth_req->pack->id++; + } else if (rpd->auth_req->reply) { + ra = rad_packet_find_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP-Error"); + if (ra) + *mschap_error = ra->val.string; + ra = rad_packet_find_attr(rpd->auth_req->reply, NULL, "Reply-Message"); + if (ra) + *reply_msg = ra->val.string; } + + return r; out: rad_req_free(rpd->auth_req); diff --git a/accel-pppd/radius/dm_coa.c b/accel-pppd/radius/dm_coa.c index 366bb41..481f2f5 100644 --- a/accel-pppd/radius/dm_coa.c +++ b/accel-pppd/radius/dm_coa.c @@ -256,7 +256,7 @@ static struct dm_coa_serv_t serv = { .hnd.read = dm_coa_read, }; -static void __init init(void) +static void init(void) { struct sockaddr_in addr; @@ -293,3 +293,5 @@ static void __init init(void) triton_md_enable_handler(&serv.hnd, MD_MODE_READ); triton_context_wakeup(&serv.ctx); } + +DEFINE_INIT(52, init); diff --git a/accel-pppd/radius/packet.c b/accel-pppd/radius/packet.c index b6230d6..892cc49 100644 --- a/accel-pppd/radius/packet.c +++ b/accel-pppd/radius/packet.c @@ -648,9 +648,11 @@ int rad_packet_send(struct rad_packet_t *pack, int fd, struct sockaddr_in *addr) return 0; } -static void __init init(void) +static void init(void) { attr_pool = mempool_create(sizeof(struct rad_attr_t)); packet_pool = mempool_create(sizeof(struct rad_packet_t)); buf_pool = mempool_create(REQ_LENGTH_MAX); } + +DEFINE_INIT(50, init); diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c index 64ce90f..5f507cb 100644 --- a/accel-pppd/radius/radius.c +++ b/accel-pppd/radius/radius.c @@ -25,7 +25,8 @@ int conf_max_try = 3; int conf_timeout = 3; -int conf_acct_timeout = 600; +int conf_acct_timeout = 3; +int conf_acct_delay_time; char *conf_nas_identifier; in_addr_t conf_nas_ip_address; in_addr_t conf_gw_ip_address; @@ -33,14 +34,6 @@ in_addr_t conf_bind; int conf_verbose; int conf_interim_verbose; -in_addr_t conf_auth_server; -int conf_auth_server_port = 1812; -char *conf_auth_secret; - -in_addr_t conf_acct_server; -int conf_acct_server_port = 1813; -char *conf_acct_secret; - in_addr_t conf_dm_coa_server; int conf_dm_coa_port = 3799; char *conf_dm_coa_secret; @@ -49,6 +42,9 @@ int conf_sid_in_auth; int conf_require_nas_ident; int conf_acct_interim_interval; +int conf_accounting; +int conf_fail_time = 60; + unsigned long stat_auth_sent; unsigned long stat_auth_lost; unsigned long stat_acct_sent; @@ -471,7 +467,7 @@ static int load_config(void) conf_timeout = atoi(opt); opt = conf_get_opt("radius", "acct-timeout"); - if (opt && atoi(opt) > 0) + if (opt && atoi(opt) >= 0) conf_acct_timeout = atoi(opt); opt = conf_get_opt("radius", "verbose"); @@ -504,27 +500,6 @@ static int load_config(void) else if (conf_nas_ip_address) conf_bind = conf_nas_ip_address; - opt = conf_get_opt("radius", "auth-server"); - if (!opt) - opt = conf_get_opt("radius", "auth_server"); - if (!opt) { - log_emerg("radius: auth-server not specified\n"); - return -1; - } else if (parse_server(opt, &conf_auth_server, &conf_auth_server_port, &conf_auth_secret)) { - log_emerg("radius: failed to parse auth_server\n"); - return -1; - } - - opt = conf_get_opt("radius", "acct-server"); - if (!opt) - opt = conf_get_opt("radius", "acct_server"); - if (!opt) - log_emerg("radius: acct-server not specified\n"); - if (opt && parse_server(opt, &conf_acct_server, &conf_acct_server_port, &conf_acct_secret)) { - log_emerg("radius: failed to parse acct_server\n"); - return -1; - } - opt = conf_get_opt("radius", "dae-server"); if (opt && parse_server(opt, &conf_dm_coa_server, &conf_dm_coa_port, &conf_dm_coa_secret)) { log_emerg("radius: failed to parse dae-server\n"); @@ -532,21 +507,29 @@ static int load_config(void) } opt = conf_get_opt("radius", "sid_in_auth"); - if (opt && atoi(opt) > 0) - conf_sid_in_auth = 1; + if (opt) + conf_sid_in_auth = atoi(opt); opt = conf_get_opt("radius", "require-nas-identification"); - if (opt && atoi(opt) > 0) - conf_require_nas_ident = 1; + if (opt) + conf_require_nas_ident = atoi(opt); opt = conf_get_opt("radius", "acct-interim-interval"); if (opt && atoi(opt) > 0) conf_acct_interim_interval = atoi(opt); + opt = conf_get_opt("radius", "acct-delay-time"); + if (opt) + conf_acct_delay_time = atoi(opt); + + opt = conf_get_opt("radius", "fail-time"); + if (opt) + conf_fail_time = atoi(opt); + return 0; } -static void __init radius_init(void) +static void radius_init(void) { char *opt; char *dict = DICTIONARY; @@ -590,3 +573,4 @@ static void __init radius_init(void) stat_interim_query_5m = stat_accm_create(5 * 60); } +DEFINE_INIT(51, radius_init); diff --git a/accel-pppd/radius/radius_p.h b/accel-pppd/radius/radius_p.h index 5450b7d..578c777 100644 --- a/accel-pppd/radius/radius_p.h +++ b/accel-pppd/radius/radius_p.h @@ -10,6 +10,8 @@ #include "ppp.h" #include "ipdb.h" +struct rad_server_t; + struct radius_pd_t { struct list_head entry; @@ -47,22 +49,44 @@ struct radius_pd_t struct rad_req_t { + struct list_head entry; struct triton_context_t ctx; struct triton_md_handler_t hnd; struct triton_timer_t timeout; uint8_t RA[16]; struct rad_packet_t *pack; struct rad_packet_t *reply; + + struct radius_pd_t *rpd; + struct rad_server_t *serv; + in_addr_t server_addr; int server_port; +}; - struct radius_pd_t *rpd; +struct rad_server_t +{ + struct list_head entry; + in_addr_t auth_addr; + int auth_port; + char *auth_secret; + in_addr_t acct_addr; + int acct_port; + char *acct_secret; + int max_req_cnt; + int req_cnt; + struct list_head req_queue; + int client_cnt; + time_t fail_time; + int conf_fail_time; + pthread_mutex_t lock; }; extern int conf_max_try; extern int conf_timeout; extern int conf_acct_timeout; +extern int conf_acct_delay_time; extern int conf_verbose; extern int conf_interim_verbose; extern char *conf_nas_identifier; @@ -70,17 +94,14 @@ extern in_addr_t conf_nas_ip_address; extern in_addr_t conf_bind; extern in_addr_t conf_gw_ip_address; extern in_addr_t conf_auth_server; -extern char *conf_auth_secret; -extern int conf_auth_server_port; -extern in_addr_t conf_acct_server; -extern char *conf_acct_secret; -extern int conf_acct_server_port; extern char *conf_dm_coa_secret; extern int conf_sid_in_auth; extern int conf_require_nas_ident; extern in_addr_t conf_dm_coa_server; extern int conf_dm_coa_port; extern int conf_acct_interim_interval; +extern int conf_accounting; +extern int conf_fail_time; extern unsigned long stat_auth_sent; extern unsigned long stat_auth_lost; @@ -122,6 +143,13 @@ int rad_packet_send(struct rad_packet_t *pck, int fd, struct sockaddr_in *addr); void dm_coa_cancel(struct radius_pd_t *pd); +struct rad_server_t *rad_server_get(int); +void rad_server_put(struct rad_server_t *); +int rad_server_req_enter(struct rad_req_t *); +void rad_server_req_exit(struct rad_req_t *); +int rad_server_realloc(struct rad_req_t *, int); +void rad_server_fail(struct rad_server_t *); + struct stat_accm_t; struct stat_accm_t *stat_accm_create(unsigned int time); void stat_accm_add(struct stat_accm_t *, unsigned int); diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c index a384f23..b45a601 100644 --- a/accel-pppd/radius/req.c +++ b/accel-pppd/radius/req.c @@ -32,8 +32,12 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u req->hnd.fd = -1; req->ctx.before_switch = log_switch; - req->server_addr = conf_auth_server; - req->server_port = conf_auth_server_port; + req->serv = rad_server_get(code == CODE_ACCOUNTING_REQUEST); + if (!req->serv) + goto out_err; + + req->server_addr = req->serv->auth_addr; + req->server_port = req->serv->auth_port; while (1) { if (read(urandom_fd, req->RA, 16) != 16) { @@ -97,8 +101,8 @@ out_err: int rad_req_acct_fill(struct rad_req_t *req) { - req->server_addr = conf_acct_server; - req->server_port = conf_acct_server_port; + req->server_addr = req->serv->acct_addr; + req->server_port = req->serv->acct_port; memset(req->RA, 0, sizeof(req->RA)); @@ -122,8 +126,10 @@ int rad_req_acct_fill(struct rad_req_t *req) return -1; if (rad_packet_add_int(req->pack, NULL, "Acct-Output-Gigawords", 0)) return -1; - if (rad_packet_add_int(req->pack, NULL, "Acct-Delay-Time", 0)) - return -1; + if (conf_acct_delay_time) { + if (rad_packet_add_int(req->pack, NULL, "Acct-Delay-Time", 0)) + return -1; + } if (rad_packet_add_ipaddr(req->pack, NULL, "Framed-IP-Address", req->rpd->ppp->peer_ipaddr)) return -1; @@ -132,6 +138,8 @@ int rad_req_acct_fill(struct rad_req_t *req) void rad_req_free(struct rad_req_t *req) { + if (req->serv) + rad_server_put(req->serv); if (req->hnd.fd >= 0 ) close(req->hnd.fd); if (req->pack) @@ -209,7 +217,8 @@ out_err: static void req_wakeup(struct rad_req_t *req) { struct triton_context_t *ctx = req->rpd->ppp->ctrl->ctx; - triton_timer_del(&req->timeout); + if (req->timeout.tpd) + triton_timer_del(&req->timeout); triton_md_unregister_handler(&req->hnd); triton_context_unregister(&req->ctx); triton_context_wakeup(ctx); @@ -267,7 +276,7 @@ int rad_req_wait(struct rad_req_t *req, int timeout) return 0; } -void __init req_init(void) +static void req_init(void) { urandom_fd = open("/dev/urandom", O_RDONLY); if (!urandom_fd) { @@ -275,3 +284,5 @@ void __init req_init(void) _exit(EXIT_FAILURE); } } + +DEFINE_INIT(50, req_init); diff --git a/accel-pppd/radius/serv.c b/accel-pppd/radius/serv.c new file mode 100644 index 0000000..bcdce14 --- /dev/null +++ b/accel-pppd/radius/serv.c @@ -0,0 +1,331 @@ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <errno.h> +#include <fcntl.h> +#include <unistd.h> +#include <sched.h> +#include <time.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> + +#include "log.h" +#include "triton.h" +#include "radius_p.h" + +#include "memdebug.h" + +static LIST_HEAD(serv_list); + +struct rad_server_t *rad_server_get(int type) +{ + struct rad_server_t *s, *s0 = NULL; + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + list_for_each_entry(s, &serv_list, entry) { + if (s->fail_time && ts.tv_sec < s->fail_time) + continue; + + if (type == 0 && !s->auth_addr) + continue; + else if (type == 1 && !s->acct_addr) + continue; + + if (!s0) { + s0 = s; + continue; + } + + if (s->client_cnt < s0->client_cnt) + s0 = s; + } + + if (!s0) + return NULL; + + __sync_add_and_fetch(&s0->client_cnt, 1); + + return s0; +} + +void rad_server_put(struct rad_server_t *s) +{ + __sync_sub_and_fetch(&s->client_cnt, 1); +} + +int rad_server_req_enter(struct rad_req_t *req) +{ + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + if (!req->serv->max_req_cnt) + return 0; + + pthread_mutex_lock(&req->serv->lock); + + if (ts.tv_sec < req->serv->fail_time) { + pthread_mutex_unlock(&req->serv->lock); + return -1; + } + + if (req->serv->req_cnt >= req->serv->max_req_cnt) { + list_add_tail(&req->entry, &req->serv->req_queue); + pthread_mutex_unlock(&req->serv->lock); + triton_context_schedule(); + pthread_mutex_lock(&req->serv->lock); + + if (ts.tv_sec < req->serv->fail_time) { + pthread_mutex_unlock(&req->serv->lock); + return -1; + } + } + + req->serv->req_cnt++; + pthread_mutex_unlock(&req->serv->lock); + + return 0; +} + +void rad_server_req_exit(struct rad_req_t *req) +{ + struct rad_req_t *r = NULL; + + if (!req->serv->max_req_cnt) + return; + + pthread_mutex_lock(&req->serv->lock); + req->serv->req_cnt--; + if (req->serv->req_cnt < req->serv->max_req_cnt && !list_empty(&req->serv->req_queue)) { + r = list_entry(req->serv->req_queue.next, typeof(*r), entry); + list_del(&r->entry); + } + pthread_mutex_unlock(&req->serv->lock); + + if (r) + triton_context_wakeup(r->rpd->ppp->ctrl->ctx); +} + +int rad_server_realloc(struct rad_req_t *req, int type) +{ + if (req->hnd.fd != -1) { + close(req->hnd.fd); + req->hnd.fd = -1; + } + + if (req->serv) + rad_server_put(req->serv); + + req->serv = rad_server_get(type); + + if (!req->serv) + return -1; + + if (type) { + req->server_addr = req->serv->acct_addr; + req->server_port = req->serv->acct_port; + } else { + req->server_addr = req->serv->auth_addr; + req->server_port = req->serv->auth_port; + } + + return 0; +} + +void rad_server_fail(struct rad_server_t *s) +{ + struct rad_req_t *r; + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); + + pthread_mutex_lock(&s->lock); + + if (ts.tv_sec > s->fail_time) { + s->fail_time = ts.tv_sec + s->conf_fail_time; + log_ppp_warn("radius: server not responding\n"); + log_warn("radius: server noy responding\n"); + } + + while (!list_empty(&s->req_queue)) { + r = list_entry(s->req_queue.next, typeof(*r), entry); + list_del(&r->entry); + triton_context_wakeup(r->rpd->ppp->ctrl->ctx); + } + pthread_mutex_unlock(&s->lock); +} + +static void __add_server(struct rad_server_t *s) +{ + INIT_LIST_HEAD(&s->req_queue); + pthread_mutex_init(&s->lock, NULL); + s->conf_fail_time = conf_fail_time; + list_add_tail(&s->entry, &serv_list); +} + +static int parse_server_old(const char *opt, in_addr_t *addr, int *port, char **secret) +{ + char *str = _strdup(opt); + char *p1, *p2; + + p1 = strstr(str, ":"); + p2 = strstr(str, ","); + + if (p1) + *p1 = 0; + if (p2) + *p2 = 0; + else + return -1; + + *addr = inet_addr(str); + + if (p1) { + *port = atoi(p1 + 1); + if (*port <=0 ) + return -1; + } + + p1 = _strdup(p2 + 1); + p2 = *secret; + *secret = p1; + if (p2) + _free(p2); + + _free(str); + + return 0; +} + +static void add_server_old(void) +{ + const char *opt; + struct rad_server_t *s = _malloc(sizeof(*s)); + + memset(s, 0, sizeof(*s)); + + opt = conf_get_opt("radius", "auth-server"); + if (opt) { + if (parse_server_old(opt, &s->auth_addr, &s->auth_port, &s->auth_secret)) { + log_emerg("radius: failed to parse 'auth-server'\n"); + goto out; + } + } + + opt = conf_get_opt("radius", "acct-server"); + if (opt) { + if (parse_server_old(opt, &s->acct_addr, &s->acct_port, &s->acct_secret)) { + log_emerg("radius: failed to parse 'acct-server'\n"); + goto out; + } + conf_accounting = 1; + } + + if (s->auth_addr || s->acct_addr) { + __add_server(s); + return; + } + +out: + _free(s); +} + +static int parse_server(const char *_opt, struct rad_server_t *s) +{ + char *opt = _strdup(_opt); + char *ptr1, *ptr2, *ptr3, *endptr; + + ptr1 = strchr(opt, ','); + if (!ptr1) + goto out; + + ptr2 = strchr(ptr1 + 1, ','); + + if (ptr2) + ptr3 = strchr(ptr2 + 1, ','); + else + ptr3 = NULL; + + *ptr1 = 0; + if (ptr2) + *ptr2 = 0; + if (ptr3) + *ptr3 = 0; + + s->auth_addr = s->acct_addr = inet_addr(opt); + + if (ptr2) { + if (ptr2[1]) { + s->auth_port = strtol(ptr2 + 1, &endptr, 10); + if (*endptr) + goto out; + } + if (!s->auth_port) + s->auth_addr = 0; + } else + s->auth_port = 1812; + + if (ptr3) { + if (ptr3[1]) { + s->acct_port = strtol(ptr3 + 1, &endptr, 10); + if (*endptr) + goto out; + } + if (!s->acct_port) + s->acct_addr = 0; + } else + s->acct_port = 1813; + + if (!s->auth_addr && !s->acct_addr) + goto out; + + if (s->auth_addr) + s->auth_secret = _strdup(ptr1 + 1); + + if (s->acct_addr) { + s->acct_secret = _strdup(ptr1 + 1); + conf_accounting = 1; + } + + return 0; + +out: + _free(opt); + + return -1; +} + +static void add_server(const char *opt) +{ + struct rad_server_t *s = _malloc(sizeof(*s)); + + memset(s, 0, sizeof(*s)); + + if (parse_server(opt, s)) { + log_emerg("radius: failed to parse '%s'\n", opt); + _free(s); + return; + } + + __add_server(s); +} + +static void init(void) +{ + struct conf_sect_t *s = conf_get_section("radius"); + struct conf_option_t *opt; + + add_server_old(); + + + list_for_each_entry(opt, &s->items, entry) { + if (strcmp(opt->name, "server")) + continue; + add_server(opt->val); + } +} + +DEFINE_INIT(21, init); diff --git a/accel-pppd/radius/stat_accm.c b/accel-pppd/radius/stat_accm.c index 8d4ad3d..34935a1 100644 --- a/accel-pppd/radius/stat_accm.c +++ b/accel-pppd/radius/stat_accm.c @@ -38,11 +38,13 @@ struct stat_accm_t *stat_accm_create(unsigned int time) static void stat_accm_clean(struct stat_accm_t *s) { struct item_t *it; - time_t ts = time(NULL); + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); while (!list_empty(&s->items)) { it = list_entry(s->items.next, typeof(*it), entry); - if (ts - it->ts > s->time) { + if (ts.tv_sec - it->ts > s->time) { list_del(&it->entry); --s->items_cnt; s->total -= it->val; @@ -55,13 +57,16 @@ static void stat_accm_clean(struct stat_accm_t *s) void stat_accm_add(struct stat_accm_t *s, unsigned int val) { struct item_t *it; + struct timespec ts; + + clock_gettime(CLOCK_MONOTONIC, &ts); pthread_mutex_lock(&s->lock); stat_accm_clean(s); it = mempool_alloc(item_pool); - it->ts = time(NULL); + it->ts = ts.tv_sec; it->val = val; list_add_tail(&it->entry, &s->items); ++s->items_cnt; @@ -90,8 +95,9 @@ unsigned long stat_accm_get_avg(struct stat_accm_t *s) return val; } -static void __init init(void) +static void init(void) { item_pool = mempool_create(sizeof(struct item_t)); } +DEFINE_INIT(50, init); diff --git a/accel-pppd/triton/triton.c b/accel-pppd/triton/triton.c index 0740591..aa2183e 100644 --- a/accel-pppd/triton/triton.c +++ b/accel-pppd/triton/triton.c @@ -4,6 +4,7 @@ #include <stdio.h> #include <string.h> #include <unistd.h> +#include <limits.h> #include <sys/resource.h> #include "triton_p.h" @@ -21,6 +22,8 @@ static LIST_HEAD(ctx_queue); static spinlock_t ctx_list_lock = SPINLOCK_INITIALIZER; static LIST_HEAD(ctx_list); +static LIST_HEAD(init_list); + static int terminate; static int need_terminate; @@ -121,8 +124,12 @@ static void* triton_thread(struct _triton_thread_t *thread) } else spin_unlock(&threads_lock); - if (terminate) + if (terminate) { + spin_lock(&threads_lock); + list_del(&thread->entry); + spin_unlock(&threads_lock); return NULL; + } //printf("thread %p: enter sigwait\n", thread); sigwait(&set, &sig); @@ -188,7 +195,8 @@ static void ctx_thread(struct _triton_context_t *ctx) spin_unlock(&ctx->lock); __sync_sub_and_fetch(&triton_stat.timer_pending, 1); read(t->fd, &tt, sizeof(tt)); - t->ud->expire(t->ud); + if (t->ud) + t->ud->expire(t->ud); continue; } if (!list_empty(&ctx->pending_handlers)) { @@ -226,17 +234,21 @@ static void ctx_thread(struct _triton_context_t *ctx) struct _triton_thread_t *create_thread() { + pthread_attr_t attr; struct _triton_thread_t *thread = _malloc(sizeof(*thread)); if (!thread) { triton_log_error("out of memory"); return NULL; } + pthread_attr_init(&attr); + pthread_attr_setstacksize(&attr, PTHREAD_STACK_MIN); + memset(thread, 0, sizeof(*thread)); pthread_mutex_init(&thread->sleep_lock, NULL); pthread_cond_init(&thread->sleep_cond, NULL); pthread_mutex_lock(&thread->sleep_lock); - if (pthread_create(&thread->thread, NULL, (void*(*)(void*))triton_thread, thread)) { + if (pthread_create(&thread->thread, &attr, (void*(*)(void*))triton_thread, thread)) { triton_log_error("pthread_create: %s", strerror(errno)); return NULL; } @@ -505,14 +517,31 @@ static void ru_update(struct triton_timer_t *t) val = (double)((rusage.ru_utime.tv_sec - ru_utime.tv_sec) * 1000000 + (rusage.ru_utime.tv_usec - ru_utime.tv_usec) + (rusage.ru_stime.tv_sec - ru_stime.tv_sec) * 1000000 + (rusage.ru_stime.tv_usec - ru_stime.tv_usec)) / dt * 100; - if (val <= 100) - triton_stat.cpu = val; + triton_stat.cpu = val; ru_timestamp = ts; ru_utime = rusage.ru_utime; ru_stime = rusage.ru_stime; } +void __export triton_register_init(int order, void (*func)(void)) +{ + struct _triton_init_t *i1, *i = _malloc(sizeof(*i)); + struct list_head *p = init_list.prev; + + + i->order = order; + i->func = func; + + while (p != &init_list) { + i1 = list_entry(p, typeof(*i1), entry); + if (order > i1->order) + break; + p = p->prev; + } + list_add(&i->entry, p); +} + int __export triton_init(const char *conf_file) { ctx_pool = mempool_create(sizeof(struct _triton_context_t)); @@ -533,13 +562,24 @@ int __export triton_init(const char *conf_file) if (event_init()) return -1; + triton_context_register(&default_ctx, NULL); + return 0; } int __export triton_load_modules(const char *mod_sect) { + struct _triton_init_t *i; + if (load_modules(mod_sect)) return -1; + + while (!list_empty(&init_list)) { + i = list_entry(init_list.next, typeof(*i), entry); + i->func(); + list_del(&i->entry); + _free(i); + } return 0; } @@ -561,6 +601,7 @@ void __export triton_run() struct _triton_thread_t *t; int i; char *opt; + struct timespec ts; opt = conf_get_opt("core", "thread-count"); if (opt && atoi(opt) > 0) @@ -575,19 +616,18 @@ void __export triton_run() pthread_mutex_unlock(&t->sleep_lock); } - time(&triton_stat.start_time); + clock_gettime(CLOCK_MONOTONIC, &ts); + triton_stat.start_time = ts.tv_sec; md_run(); timer_run(); - triton_context_register(&default_ctx, NULL); triton_context_wakeup(&default_ctx); } void __export triton_terminate() { struct _triton_context_t *ctx; - struct _triton_thread_t *t; int r; need_terminate = 1; @@ -603,8 +643,15 @@ void __export triton_terminate() } spin_unlock(&ctx_list_lock); - list_for_each_entry(t, &threads, entry) - pthread_join(t->thread, NULL); + while (1) { + spin_lock(&threads_lock); + if (list_empty(&threads)) { + spin_unlock(&threads_lock); + break; + } + spin_unlock(&threads_lock); + sleep(1); + } md_terminate(); timer_terminate(); diff --git a/accel-pppd/triton/triton.h b/accel-pppd/triton/triton.h index 98ef111..95851c2 100644 --- a/accel-pppd/triton/triton.h +++ b/accel-pppd/triton/triton.h @@ -106,6 +106,8 @@ void triton_stop_collect_cpu_usage(void); int triton_module_loaded(const char *name); +void triton_register_init(int order, void (*func)(void)); + #define TRITON_OK 0 #define TRITON_ERR_NOCOMP -1 @@ -137,4 +139,6 @@ void triton_terminate(void); const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) +#define DEFINE_INIT(o, func) static void __init __init__(void){triton_register_init(o,func);} + #endif diff --git a/accel-pppd/triton/triton_p.h b/accel-pppd/triton/triton_p.h index 235eb70..2eb2e62 100644 --- a/accel-pppd/triton/triton_p.h +++ b/accel-pppd/triton/triton_p.h @@ -82,6 +82,14 @@ struct _triton_ctx_call_t void (*func)(void *); }; +struct _triton_init_t +{ + struct list_head entry; + + int order; + void (*func)(void); +}; + int log_init(void); int md_init(); int timer_init(); diff --git a/cmake/cpack.cmake b/cmake/cpack.cmake index 3de94d7..a8804dc 100644 --- a/cmake/cpack.cmake +++ b/cmake/cpack.cmake @@ -2,7 +2,7 @@ INCLUDE(InstallRequiredSystemLibraries) SET(CPACK_PACKAGE_VERSION_MAJOR "1") SET(CPACK_PACKAGE_VERSION_MINOR "3") -SET(CPACK_PACKAGE_VERSION_PATCH "4") +SET(CPACK_PACKAGE_VERSION_PATCH "7") SET(CPACK_PACKAGE_NAME "accel-ppp") SET(CPACK_PACKAGE_CONTACT "Dmitry Kozlov <xeb@mail.ru>") @@ -12,14 +12,14 @@ SET(CPACK_PACKAGE_VENDOR "Dmitry Kozlov") SET(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README") SET(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/COPYING") -IF(CPACK_TYPE STREQUAL Debian) +IF(CPACK_TYPE STREQUAL Debian5) SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.7), libssl0.9.8 (>= 0.9.8), libpcre3 (>= 7.6)") INCLUDE(${CMAKE_HOME_DIRECTORY}/cmake/debian/debian.cmake) -ENDIF(CPACK_TYPE STREQUAL Debian) +ENDIF(CPACK_TYPE STREQUAL Debian5) -IF(CPACK_TYPE STREQUAL Ubuntu) - SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.12.1), libssl0.9.8 (>= 0.9.8), libpcre3 (>= 8.02), libnl2 (>= 1.99)") +IF(CPACK_TYPE STREQUAL Debian6) + SET(CPACK_DEBIAN_PACKAGE_DEPENDS "libc6 (>= 2.11.2), libssl0.9.8 (>= 0.9.8), libpcre3 (>= 8.02), libnl2 (>= 1.99)") INCLUDE(${CMAKE_HOME_DIRECTORY}/cmake/debian/debian.cmake) -ENDIF(CPACK_TYPE STREQUAL Ubuntu) +ENDIF(CPACK_TYPE STREQUAL Debian6) INCLUDE(CPack) diff --git a/cmake/debian/debian.cmake b/cmake/debian/debian.cmake index b7bd029..0fcc2d5 100644 --- a/cmake/debian/debian.cmake +++ b/cmake/debian/debian.cmake @@ -10,7 +10,7 @@ if (BUILD_DRIVER_ONLY) SET(CPACK_PACKAGE_DESCRIPTION_SUMMARY "accel-pptp kernel module") SET(CPACK_DEBIAN_PACKAGE_DEPENDS "") SET(CPACK_DEBIAN_PACKAGE_CONTROL_EXTRA "${CMAKE_CURRENT_SOURCE_DIR}/cmake/debian-kmod/postinst") - INSTALL(DIRECTORY lib/modules/${DEBIAN_KDIR}/extra) + #INSTALL(DIRECTORY lib/modules/${DEBIAN_KDIR}/extra) INSTALL(FILES ${CMAKE_CURRENT_BINARY_DIR}/driver/driver/pptp.ko DESTINATION lib/modules/${DEBIAN_KDIR}/extra) #SET(CPACK_DEBIAN_PACKAGE_DEPENDS "linux-image (= ${LINUX_IMAGE})") else (BUILD_DRIVER_ONLY) @@ -21,4 +21,5 @@ else (BUILD_DRIVER_ONLY) INSTALL(FILES ${CMAKE_HOME_DIRECTORY}/accel-pppd/accel-ppp.conf DESTINATION ${CMAKE_BINARY_DIR}/_CPack_Packages/Linux/DEB/${CPACK_PACKAGE_FILE_NAME}/etc RENAME accel-ppp.conf.dist) INSTALL(FILES ${CMAKE_HOME_DIRECTORY}/contrib/debian/accel-ppp-init DESTINATION ${CMAKE_BINARY_DIR}/_CPack_Packages/Linux/DEB/${CPACK_PACKAGE_FILE_NAME}/etc/init.d RENAME accel-ppp) INSTALL(FILES ${CMAKE_HOME_DIRECTORY}/contrib/debian/accel-ppp-default DESTINATION ${CMAKE_BINARY_DIR}/_CPack_Packages/Linux/DEB/${CPACK_PACKAGE_FILE_NAME}/etc/default RENAME accel-ppp) + endif (BUILD_DRIVER_ONLY) diff --git a/cmake/debian/postinst b/cmake/debian/postinst index a039b4f..5d516cd 100755 --- a/cmake/debian/postinst +++ b/cmake/debian/postinst @@ -2,7 +2,7 @@ chmod +x /etc/init.d/accel-ppp -mkdir /var/log/accel-ppp &> /dev/null -mkdir /var/run/accel-ppp &> /dev/null +mkdir /var/log/accel-ppp > /dev/null 2>&1 +mkdir /var/run/accel-ppp > /dev/null 2>&1 exit 0 diff --git a/contrib/gentoo/net-dialup/accel-ppp/accel-ppp-1.3.3.ebuild b/contrib/gentoo/net-dialup/accel-ppp/accel-ppp-1.3.5.ebuild index 395dd6b..395dd6b 100644 --- a/contrib/gentoo/net-dialup/accel-ppp/accel-ppp-1.3.3.ebuild +++ b/contrib/gentoo/net-dialup/accel-ppp/accel-ppp-1.3.5.ebuild |