diff options
-rw-r--r-- | accel-pptpd/cli/cli.c | 4 | ||||
-rw-r--r-- | accel-pptpd/cli/show_sessions.c | 2 | ||||
-rw-r--r-- | accel-pptpd/cli/tcp.c | 4 | ||||
-rw-r--r-- | accel-pptpd/cli/telnet.c | 12 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/CMakeLists.txt | 7 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/pppoe.c | 61 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/pppoe.h | 6 | ||||
-rw-r--r-- | accel-pptpd/ctrl/pppoe/tr101.c | 97 | ||||
-rw-r--r-- | accel-pptpd/extra/chap-secrets.c | 41 | ||||
-rw-r--r-- | accel-pptpd/extra/pppd_compat.c | 3 | ||||
-rw-r--r-- | accel-pptpd/ppp/ipcp_opt_ipaddr.c | 6 | ||||
-rw-r--r-- | accel-pptpd/radius/acct.c | 40 | ||||
-rw-r--r-- | accel-pptpd/radius/auth.c | 54 | ||||
-rw-r--r-- | accel-pptpd/radius/dict/dictionary | 1 | ||||
-rw-r--r-- | accel-pptpd/radius/dm_coa.c | 2 | ||||
-rw-r--r-- | accel-pptpd/radius/packet.c | 208 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.c | 12 | ||||
-rw-r--r-- | accel-pptpd/radius/radius.h | 32 | ||||
-rw-r--r-- | accel-pptpd/radius/radius_p.h | 2 | ||||
-rw-r--r-- | accel-pptpd/radius/req.c | 58 | ||||
-rw-r--r-- | accel-pptpd/triton/loader.c | 2 | ||||
-rw-r--r-- | accel-pptpd/triton/md.c | 4 | ||||
-rw-r--r-- | accel-pptpd/triton/timer.c | 4 | ||||
-rw-r--r-- | rfc/TR-101.pdf | bin | 0 -> 970534 bytes |
24 files changed, 434 insertions, 228 deletions
diff --git a/accel-pptpd/cli/cli.c b/accel-pptpd/cli/cli.c index 048809c1..ef168ded 100644 --- a/accel-pptpd/cli/cli.c +++ b/accel-pptpd/cli/cli.c @@ -181,7 +181,7 @@ int cli_process_cmd(struct cli_client_t *cln) case CLI_CMD_EXIT: cln->disconnect(cln); case CLI_CMD_FAILED: - return -1; + return 0; case CLI_CMD_SYNTAX: cli_send(cln, MSG_SYNTAX_ERROR); return 0; @@ -206,7 +206,7 @@ static void load_config(void) _free(conf_cli_passwd); opt = conf_get_opt("cli", "password"); if (opt) - conf_cli_passwd = _strdup(conf_cli_passwd); + conf_cli_passwd = _strdup(opt); else conf_cli_passwd = NULL; diff --git a/accel-pptpd/cli/show_sessions.c b/accel-pptpd/cli/show_sessions.c index 5bdf64fe..f8fb3d00 100644 --- a/accel-pptpd/cli/show_sessions.c +++ b/accel-pptpd/cli/show_sessions.c @@ -14,7 +14,7 @@ #include "memdebug.h" #define CELL_SIZE 128 -#define DEF_COLUMNS "ifname,username,ip,type,state,uptime" +#define DEF_COLUMNS "ifname,username,calling-sid,ip,type,state,uptime" struct column_t { diff --git a/accel-pptpd/cli/tcp.c b/accel-pptpd/cli/tcp.c index 435752aa..260225f1 100644 --- a/accel-pptpd/cli/tcp.c +++ b/accel-pptpd/cli/tcp.c @@ -73,7 +73,7 @@ static void disconnect(struct tcp_client_t *cln) static void cli_client_disconnect(struct cli_client_t *tcln) { struct tcp_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - disconnect(cln); + cln->disconnect = 1; } static void queue_buffer(struct tcp_client_t *cln, struct buffer_t *b) @@ -184,7 +184,7 @@ static int cln_read(struct triton_md_handler_t *h) drop: disconnect(cln); - return 0; + return -1; } static int cln_write(struct triton_md_handler_t *h) diff --git a/accel-pptpd/cli/telnet.c b/accel-pptpd/cli/telnet.c index a91418a9..0ea19fb1 100644 --- a/accel-pptpd/cli/telnet.c +++ b/accel-pptpd/cli/telnet.c @@ -120,7 +120,7 @@ static void disconnect(struct telnet_client_t *cln) static void cli_client_disconnect(struct cli_client_t *tcln) { struct telnet_client_t *cln = container_of(tcln, typeof(*cln), cli_client); - disconnect(cln); + cln->disconnect = 1; } static void queue_buffer(struct telnet_client_t *cln, struct buffer_t *b) @@ -286,7 +286,7 @@ static int telnet_input_char(struct telnet_client_t *cln, uint8_t c) if (strcmp((char *)cln->cmdline, conf_cli_passwd)) { if (telnet_send(cln, MSG_AUTH_FAILED, sizeof(MSG_AUTH_FAILED))) return -1; - disconnect(cln); + cln->disconnect = 1; return -1; } cln->auth = 1; @@ -430,7 +430,7 @@ static int telnet_input_char(struct telnet_client_t *cln, uint8_t c) } return 0; case 3: - disconnect(cln); + cln->disconnect = 1; return -1; } @@ -473,7 +473,7 @@ static int cln_read(struct triton_md_handler_t *h) n = read(h->fd, recv_buf, RECV_BUF_SIZE); if (n == 0) { disconnect(cln); - return 0; + return -1; } if (n < 0) { if (errno != EAGAIN) @@ -484,11 +484,11 @@ static int cln_read(struct triton_md_handler_t *h) print_buf(cln->recv_buf + cln->recv_pos, n);*/ for (i = 0; i < n; i++) { if (telnet_input_char(cln, recv_buf[i])) - return -1; + break; } if (cln->disconnect) { disconnect(cln); - return 0; + return -1; } } diff --git a/accel-pptpd/ctrl/pppoe/CMakeLists.txt b/accel-pptpd/ctrl/pppoe/CMakeLists.txt index 5f5c5e4d..f047936e 100644 --- a/accel-pptpd/ctrl/pppoe/CMakeLists.txt +++ b/accel-pptpd/ctrl/pppoe/CMakeLists.txt @@ -1,12 +1,17 @@ INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR}) -ADD_LIBRARY(pppoe SHARED +SET(sources pppoe.c mac_filter.c dpado.c cli.c ) +IF (RADIUS) +SET(sources ${sources} tr101.c) +ENDIF(RADIUS) + +ADD_LIBRARY(pppoe SHARED ${sources}) TARGET_LINK_LIBRARIES(pppoe crypto) INSTALL(TARGETS pppoe LIBRARY DESTINATION lib/accel-pptp) diff --git a/accel-pptpd/ctrl/pppoe/pppoe.c b/accel-pptpd/ctrl/pppoe/pppoe.c index 2ec8bc26..3e6b0bf2 100644 --- a/accel-pptpd/ctrl/pppoe/pppoe.c +++ b/accel-pptpd/ctrl/pppoe/pppoe.c @@ -22,6 +22,10 @@ #include "mempool.h" #include "cli.h" +#ifdef RADIUS +#include "radius.h" +#endif + #include "pppoe.h" #include "memdebug.h" @@ -39,10 +43,14 @@ struct pppoe_conn_t struct pppoe_tag *relay_sid; struct pppoe_tag *host_uniq; struct pppoe_tag *service_name; + struct pppoe_tag *tr101; uint8_t cookie[COOKIE_LENGTH]; struct ppp_ctrl_t ctrl; struct ppp_t ppp; +#ifdef RADIUS + struct rad_plugin_t radius; +#endif }; struct delayed_pado_t @@ -146,7 +154,29 @@ static void pppoe_conn_close(struct triton_context_t *ctx) disconnect(conn); } -static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const uint8_t *addr, const struct pppoe_tag *host_uniq, const struct pppoe_tag *relay_sid, const struct pppoe_tag *service_name, const uint8_t *cookie) +#ifdef RADIUS +static int pppoe_rad_send_access_request(struct rad_plugin_t *rad, struct rad_packet_t *pack) +{ + struct pppoe_conn_t *conn = container_of(rad, typeof(*conn), radius); + + if (conn->tr101) + return tr101_send_access_request(conn->tr101, pack); + + return 0; +} + +static int pppoe_rad_send_accounting_request(struct rad_plugin_t *rad, struct rad_packet_t *pack) +{ + struct pppoe_conn_t *conn = container_of(rad, typeof(*conn), radius); + + if (conn->tr101) + return tr101_send_accounting_request(conn->tr101, pack); + + return 0; +} +#endif + +static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const uint8_t *addr, const struct pppoe_tag *host_uniq, const struct pppoe_tag *relay_sid, const struct pppoe_tag *service_name, const struct pppoe_tag *tr101, const uint8_t *cookie) { struct pppoe_conn_t *conn; int sid; @@ -193,6 +223,11 @@ static struct pppoe_conn_t *allocate_channel(struct pppoe_serv_t *serv, const ui memcpy(conn->relay_sid, relay_sid, sizeof(*relay_sid) + ntohs(relay_sid->tag_len)); } + if (tr101) { + conn->tr101 = _malloc(sizeof(*tr101) + ntohs(tr101->tag_len)); + memcpy(conn->tr101, tr101, sizeof(*tr101) + ntohs(tr101->tag_len)); + } + conn->service_name = _malloc(sizeof(*service_name) + ntohs(service_name->tag_len)); memcpy(conn->service_name, service_name, sizeof(*service_name) + ntohs(service_name->tag_len)); @@ -268,6 +303,14 @@ static void connect_channel(struct pppoe_conn_t *conn) if (establish_ppp(&conn->ppp)) goto out_err_close; +#ifdef RADIUS + if (conn->tr101) { + conn->radius.send_access_request = pppoe_rad_send_access_request; + conn->radius.send_accounting_request = pppoe_rad_send_accounting_request; + rad_register_plugin(&conn->ppp, &conn->radius); + } +#endif + conn->ppp_started = 1; dpado_check_next(__sync_add_and_fetch(&stat_active, 1)); @@ -367,7 +410,10 @@ static void print_packet(uint8_t *pack) log_info2(">"); break; case TAG_VENDOR_SPECIFIC: - log_info2(" <Vendor-Specific>"); + if (ntohs(tag->tag_len) < 4) + log_info2(" <Vendor-Specific invalid>"); + else + log_info2(" <Vendor-Specific %x>", ntohl(*(uint32_t *)tag->tag_data)); break; case TAG_RELAY_SESSION_ID: log_info2(" <Relay-Session-Id"); @@ -740,8 +786,10 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) struct pppoe_tag *relay_sid_tag = NULL; struct pppoe_tag *ac_cookie_tag = NULL; struct pppoe_tag *service_name_tag = NULL; + struct pppoe_tag *tr101_tag = NULL; int n, service_match = 0; struct pppoe_conn_t *conn; + int vendor_id; if (ppp_shutdown) return; @@ -791,6 +839,13 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) case TAG_RELAY_SESSION_ID: relay_sid_tag = tag; break; + case TAG_VENDOR_SPECIFIC: + if (ntohs(tag->tag_len) < 4) + continue; + vendor_id = ntohl(*(uint32_t *)tag->tag_data); + if (vendor_id == VENDOR_ADSL_FORUM) + tr101_tag = tag; + break; } } @@ -828,7 +883,7 @@ static void pppoe_recv_PADR(struct pppoe_serv_t *serv, uint8_t *pack, int size) if (conn) return; - conn = allocate_channel(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, service_name_tag, (uint8_t *)ac_cookie_tag->tag_data); + conn = allocate_channel(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, service_name_tag, tr101_tag, (uint8_t *)ac_cookie_tag->tag_data); if (!conn) pppoe_send_err(serv, ethhdr->h_source, host_uniq_tag, relay_sid_tag, CODE_PADS, TAG_AC_SYSTEM_ERROR); else { diff --git a/accel-pptpd/ctrl/pppoe/pppoe.h b/accel-pptpd/ctrl/pppoe/pppoe.h index 323715d8..b0e665d7 100644 --- a/accel-pptpd/ctrl/pppoe/pppoe.h +++ b/accel-pptpd/ctrl/pppoe/pppoe.h @@ -41,6 +41,8 @@ #define MAX_PPPOE_PAYLOAD (ETH_DATA_LEN - PPPOE_OVERHEAD) #define MAX_PPPOE_MTU (MAX_PPPOE_PAYLOAD - 2) +#define VENDOR_ADSL_FORUM 0xde9 + #define MAX_SID 65534 #define SECRET_LENGTH 16 #define COOKIE_LENGTH 24 @@ -102,5 +104,9 @@ void dpado_check_next(int conn_cnt); void dpado_check_prev(int conn_cnt); int dpado_parse(const char *str); +struct rad_packet_t; +int tr101_send_access_request(struct pppoe_tag *tr101, struct rad_packet_t *pack); +int tr101_send_accounting_request(struct pppoe_tag *tr101, struct rad_packet_t *pack); + #endif diff --git a/accel-pptpd/ctrl/pppoe/tr101.c b/accel-pptpd/ctrl/pppoe/tr101.c new file mode 100644 index 00000000..cfb0fbcf --- /dev/null +++ b/accel-pptpd/ctrl/pppoe/tr101.c @@ -0,0 +1,97 @@ +#include <string.h> +#include <stdlib.h> +#include <netinet/in.h> +#include <net/ethernet.h> + +#include "triton.h" +#include "ppp.h" +#include "log.h" +#include "radius.h" +#include "memdebug.h" + +#include "pppoe.h" + +#define OPT_CIRCUIT_ID 0x01 +#define OPT_REMOTE_AGENT_ID 0x02 +#define OPT_ACTUAL_DATA_RATE_UP 0x81 +#define OPT_ACTUAL_DATA_RATE_DOWN 0x82 +#define OPT_MIN_DATA_RATE_UP 0x83 +#define OPT_MAX_DATA_RATE_DOWN 0x84 + +static int tr101_send_request(struct pppoe_tag *tr101, struct rad_packet_t *pack, int type) +{ + uint8_t *ptr = (uint8_t *)tr101->tag_data + 4; + uint8_t *endptr = (uint8_t *)tr101->tag_data + ntohs(tr101->tag_len); + int id, len; + char str[64]; + + while (ptr < endptr) { + if (ptr + 2 > endptr) + goto inval; + id = *ptr++; + len = *ptr++; + if (ptr + len - 2 > endptr) + goto inval; + if (type && id > 0x80) + continue; + switch (id) { + case OPT_CIRCUIT_ID: + if (len - 2 > 63) + goto inval; + memcpy(str, ptr, len); + str[len - 2] = 0; + if (rad_packet_add_str(pack, "ADSL-Forum", "ADSL-Agent-Circuit-Id", str)) + return -1; + break; + case OPT_REMOTE_AGENT_ID: + if (len - 2 > 63) + goto inval; + memcpy(str, ptr, len); + str[len - 2] = 0; + if (rad_packet_add_str(pack, "ADSL-Forum", "ADSL-Agent-Remote-Id", str)) + return -1; + break; + case OPT_ACTUAL_DATA_RATE_UP: + if (len != 6) + goto inval; + if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + return -1; + break; + case OPT_ACTUAL_DATA_RATE_DOWN: + if (len != 6) + goto inval; + if (rad_packet_add_int(pack, "ADSL-Forum", "Actual-Data-Rate-Downstream", ntohl(*(uint32_t *)ptr))) + return -1; + break; + case OPT_MIN_DATA_RATE_UP: + if (len != 6) + goto inval; + if (rad_packet_add_int(pack, "ADSL-Forum", "Minimum-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + return -1; + break; + case OPT_MAX_DATA_RATE_DOWN: + if (len != 6) + goto inval; + if (rad_packet_add_int(pack, "ADSL-Forum", "Maximum-Data-Rate-Upstream", ntohl(*(uint32_t *)ptr))) + return -1; + break; + } + ptr += len - 2; + } + + return 0; + +inval: + log_ppp_warn("pppoe:tr101: invalid tag received\n"); + return -1; +} + +int tr101_send_access_request(struct pppoe_tag *tr101, struct rad_packet_t *pack) +{ + return tr101_send_request(tr101, pack, 1); +} + +int tr101_send_accounting_request(struct pppoe_tag *tr101, struct rad_packet_t *pack) +{ + return tr101_send_request(tr101, pack, 0); +} diff --git a/accel-pptpd/extra/chap-secrets.c b/accel-pptpd/extra/chap-secrets.c index 8983f90e..35503473 100644 --- a/accel-pptpd/extra/chap-secrets.c +++ b/accel-pptpd/extra/chap-secrets.c @@ -30,9 +30,28 @@ struct cs_pd_t static char *skip_word(char *ptr) { - for(; *ptr; ptr++) - if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') + char quote = 0; + + if (*ptr == '\'' || *ptr == '"') { + quote = *ptr; + ptr++; + } + + for(; *ptr; ptr++) { + if (quote) { + if (*ptr == '\n') + break; + if (*ptr == '\\' && ptr[1] && ptr[1] != '\n') { + memmove(ptr, ptr + 1, strlen(ptr)); + continue; + } + if (*ptr == quote) { + *ptr = ' '; + break; + } + } else if (*ptr == ' ' || *ptr == '\t' || *ptr == '\n') break; + } return ptr; } static char *skip_space(char *ptr) @@ -50,14 +69,17 @@ static int split(char *buf, char **ptr) buf = skip_word(buf); if (!*buf) return i; - + *buf = 0; buf = skip_space(buf + 1); if (!*buf) return i; - ptr[i] = buf; + if (*buf == '"' || *buf == '\'') + ptr[i] = buf + 1; + else + ptr[i] = buf; } buf = skip_word(buf); @@ -95,11 +117,18 @@ static struct cs_pd_t *create_pd(struct ppp_t *ppp, const char *username) } while (fgets(buf, 4096, f)) { + if (buf[0] == '#') + continue; n = split(buf, ptr); if (n < 3) continue; - if (!strcmp(buf, username)) - goto found; + if (*buf == '\'' || *buf == '"') { + if (!strcmp(buf + 1, username)) + goto found; + } else { + if (!strcmp(buf, username)) + goto found; + } } out: diff --git a/accel-pptpd/extra/pppd_compat.c b/accel-pptpd/extra/pppd_compat.c index f6e85b02..f897dd68 100644 --- a/accel-pptpd/extra/pppd_compat.c +++ b/accel-pptpd/extra/pppd_compat.c @@ -476,8 +476,7 @@ static void fill_env(char **env, struct pppd_compat_pd_t *pd) { snprintf(env[0], 64, "PEERNAME=%s", pd->ppp->username); - if (pd->ppp->stop_time) { - + if (pd->ppp->stop_time && env[1]) { snprintf(env[1], 24, "CONNECT_TIME=%lu", pd->ppp->stop_time - pd->ppp->start_time); snprintf(env[2], 24, "BYTES_SENT=%u", pd->bytes_sent); snprintf(env[3], 24, "BYTES_RCVD=%u", pd->bytes_rcvd); diff --git a/accel-pptpd/ppp/ipcp_opt_ipaddr.c b/accel-pptpd/ppp/ipcp_opt_ipaddr.c index 05120eb4..334f4256 100644 --- a/accel-pptpd/ppp/ipcp_opt_ipaddr.c +++ b/accel-pptpd/ppp/ipcp_opt_ipaddr.c @@ -63,14 +63,14 @@ static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt) _free(ipaddr_opt); } -static int check_exists(in_addr_t addr) +static int check_exists(struct ppp_t *self_ppp, in_addr_t addr) { struct ppp_t *ppp; int r = 0; pthread_rwlock_rdlock(&ppp_lock); list_for_each_entry(ppp, &ppp_list, entry) { - if (!ppp->terminating && ppp->peer_ipaddr == addr) { + if (!ppp->terminating && ppp->peer_ipaddr == addr && ppp != self_ppp) { log_ppp_warn("ppp:ipcp: requested IP already assigned to %s\n", ppp->ifname); r = 1; break; @@ -103,7 +103,7 @@ static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o return -1; } - if (conf_check_exists && check_exists(ipaddr_opt->ip->peer_addr)) + if (conf_check_exists && check_exists(ipcp->ppp, ipaddr_opt->ip->peer_addr)) return -1; opt32->hdr.id=CI_ADDR; diff --git a/accel-pptpd/radius/acct.c b/accel-pptpd/radius/acct.c index 86dd0cd0..f2c0ebb4 100644 --- a/accel-pptpd/radius/acct.c +++ b/accel-pptpd/radius/acct.c @@ -58,13 +58,13 @@ static void req_set_stat(struct rad_req_t *req, struct ppp_t *ppp) req->rpd->acct_output_gigawords++; req->rpd->acct_output_octets = ifreq.stats.p.ppp_obytes; - rad_packet_change_int(req->pack, "Acct-Input-Octets", ifreq.stats.p.ppp_ibytes); - rad_packet_change_int(req->pack, "Acct-Output-Octets", ifreq.stats.p.ppp_obytes); - rad_packet_change_int(req->pack, "Acct-Input-Packets", ifreq.stats.p.ppp_ipackets); - rad_packet_change_int(req->pack, "Acct-Output-Packets", ifreq.stats.p.ppp_opackets); - rad_packet_change_int(req->pack, "Acct-Input-Gigawords", req->rpd->acct_input_gigawords); - rad_packet_change_int(req->pack, "Acct-Output-Gigawords", req->rpd->acct_output_gigawords); - rad_packet_change_int(req->pack, "Acct-Session-Time", stop_time - ppp->start_time); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Octets", ifreq.stats.p.ppp_ibytes); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Octets", ifreq.stats.p.ppp_obytes); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Packets", ifreq.stats.p.ppp_ipackets); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Packets", ifreq.stats.p.ppp_opackets); + rad_packet_change_int(req->pack, NULL, "Acct-Input-Gigawords", req->rpd->acct_input_gigawords); + rad_packet_change_int(req->pack, NULL, "Acct-Output-Gigawords", req->rpd->acct_output_gigawords); + rad_packet_change_int(req->pack, NULL, "Acct-Session-Time", stop_time - ppp->start_time); } static int rad_acct_read(struct triton_md_handler_t *h) @@ -135,7 +135,7 @@ static void rad_acct_timeout(struct triton_timer_t *t) req->pack->id++; - rad_packet_change_int(req->pack, "Acct-Delay-Time", dt); + 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); } @@ -154,8 +154,8 @@ static void rad_acct_interim_update(struct triton_timer_t *t) time(&rpd->acct_timestamp); rpd->acct_req->pack->id++; - rad_packet_change_val(rpd->acct_req->pack, "Acct-Status-Type", "Interim-Update"); - rad_packet_change_int(rpd->acct_req->pack, "Acct-Delay-Time", 0); + 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_timeout) { @@ -194,7 +194,7 @@ int rad_acct_start(struct radius_pd_t *rpd) for (i = 0; i < conf_max_try; i++) { time(&ts); - rad_packet_change_int(rpd->acct_req->pack, "Acct-Delay-Time", ts - rpd->acct_timestamp); + 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)) @@ -256,29 +256,29 @@ void rad_acct_stop(struct radius_pd_t *rpd) switch (rpd->ppp->terminate_cause) { case TERM_USER_REQUEST: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "User-Request"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "User-Request"); break; case TERM_SESSION_TIMEOUT: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "Session-Timeout"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "Session-Timeout"); break; case TERM_ADMIN_RESET: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "Admin-Reset"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "Admin-Reset"); break; case TERM_USER_ERROR: case TERM_AUTH_ERROR: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "User-Error"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "User-Error"); break; case TERM_NAS_ERROR: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "NAS-Error"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "NAS-Error"); break; case TERM_NAS_REQUEST: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "NAS-Request"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "NAS-Request"); break; case TERM_NAS_REBOOT: - rad_packet_add_val(rpd->acct_req->pack, "Acct-Terminate-Cause", "NAS-Reboot"); + rad_packet_add_val(rpd->acct_req->pack, NULL, "Acct-Terminate-Cause", "NAS-Reboot"); break; } - rad_packet_change_val(rpd->acct_req->pack, "Acct-Status-Type", "Stop"); + 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); /// !!! rad_req_add_val(rpd->acct_req, "Acct-Terminate-Cause", ""); @@ -292,7 +292,7 @@ void rad_acct_stop(struct radius_pd_t *rpd) for(i = 0; i < conf_max_try; i++) { time(&ts); - rad_packet_change_int(rpd->acct_req->pack, "Acct-Delay-Time", ts - rpd->acct_timestamp); + 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; diff --git a/accel-pptpd/radius/auth.c b/accel-pptpd/radius/auth.c index 94a82698..244cb6e0 100644 --- a/accel-pptpd/radius/auth.c +++ b/accel-pptpd/radius/auth.c @@ -190,7 +190,7 @@ int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args) if (!epasswd) goto out; - if (rad_packet_add_octets(req->pack, "User-Password", epasswd, epasswd_len)) { + if (rad_packet_add_octets(req->pack, NULL, "User-Password", epasswd, epasswd_len)) { if (epasswd_len) _free(epasswd); goto out; @@ -200,7 +200,7 @@ int rad_auth_pap(struct radius_pd_t *rpd, const char *username, va_list args) _free(epasswd); if (conf_sid_in_auth) - if (rad_packet_add_str(req->pack, "Acct-Session-Id", rpd->ppp->sessionid, PPP_SESSIONID_LEN)) + if (rad_packet_add_str(req->pack, NULL, "Acct-Session-Id", rpd->ppp->sessionid)) return -1; r = rad_auth_send(req); @@ -240,29 +240,29 @@ 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, "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, "CHAP-Password", chap_password, 17)) + 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, "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, "CHAP-Password", chap_password, 17)) + if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "CHAP-Password", chap_password, 17)) goto out; if (rpd->attr_state) { - if (rad_packet_find_attr(rpd->auth_req->pack, "State")) { - if (rad_packet_change_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len)) + if (rad_packet_find_attr(rpd->auth_req->pack, NULL, "State")) { + if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len)) goto out; } else { - if (rad_packet_add_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len)) + if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len)) goto out; } } @@ -272,7 +272,7 @@ int rad_auth_chap_md5(struct radius_pd_t *rpd, const char *username, va_list arg } if (conf_sid_in_auth) - if (rad_packet_add_str(rpd->auth_req->pack, "Acct-Session-Id", rpd->ppp->sessionid, PPP_SESSIONID_LEN)) + 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); @@ -358,24 +358,24 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar if (!rpd->auth_req) return PWDB_DENIED; - if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len)) + if (rad_packet_add_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len)) goto out; - if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response))) + if (rad_packet_add_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response))) goto out; } else { - if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len)) + if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, challenge_len)) goto out; - if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response))) + if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Response", response, sizeof(response))) goto out; if (rpd->attr_state) { - if (rad_packet_find_attr(rpd->auth_req->pack, "State")) { - if (rad_packet_change_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len)) + if (rad_packet_find_attr(rpd->auth_req->pack, NULL, "State")) { + if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len)) goto out; } else { - if (rad_packet_add_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len)) + if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len)) goto out; } } @@ -385,7 +385,7 @@ int rad_auth_mschap_v1(struct radius_pd_t *rpd, const char *username, va_list ar } if (conf_sid_in_auth) - if (rad_packet_add_str(rpd->auth_req->pack, "Acct-Session-Id", rpd->ppp->sessionid, PPP_SESSIONID_LEN)) + 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); @@ -433,24 +433,24 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar if (!rpd->auth_req) return PWDB_DENIED; - if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16)) + if (rad_packet_add_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16)) goto out; - if (rad_packet_add_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response))) + if (rad_packet_add_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response))) goto out; } else { - if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16)) + if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP-Challenge", challenge, 16)) goto out; - if (rad_packet_change_vendor_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response))) + if (rad_packet_change_octets(rpd->auth_req->pack, "Microsoft", "MS-CHAP2-Response", mschap_response, sizeof(mschap_response))) goto out; if (rpd->attr_state) { - if (rad_packet_find_attr(rpd->auth_req->pack, "State")) { - if (rad_packet_change_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len)) + if (rad_packet_find_attr(rpd->auth_req->pack, NULL, "State")) { + if (rad_packet_change_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len)) goto out; } else { - if (rad_packet_add_octets(rpd->auth_req->pack, "State", rpd->attr_state, rpd->attr_state_len)) + if (rad_packet_add_octets(rpd->auth_req->pack, NULL, "State", rpd->attr_state, rpd->attr_state_len)) goto out; } } @@ -460,12 +460,12 @@ int rad_auth_mschap_v2(struct radius_pd_t *rpd, const char *username, va_list ar } if (conf_sid_in_auth) - if (rad_packet_add_str(rpd->auth_req->pack, "Acct-Session-Id", rpd->ppp->sessionid, PPP_SESSIONID_LEN)) + 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) { - ra = rad_packet_find_vendor_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP2-Success"); + ra = rad_packet_find_attr(rpd->auth_req->reply, "Microsoft", "MS-CHAP2-Success"); if (!ra) { log_error("radius:auth:mschap-v2: 'MS-CHAP-Success' not found in radius response\n"); r = PWDB_DENIED; diff --git a/accel-pptpd/radius/dict/dictionary b/accel-pptpd/radius/dict/dictionary index 02006a63..27973105 100644 --- a/accel-pptpd/radius/dict/dictionary +++ b/accel-pptpd/radius/dict/dictionary @@ -70,6 +70,7 @@ $INCLUDE dictionary.rfc3576 $INCLUDE dictionary.rfc3580 $INCLUDE dictionary.rfc4072 $INCLUDE dictionary.rfc4372 +$INCLUDE dictionary.rfc4679 $INCLUDE dictionary.rfc5176 $INCLUDE dictionary.microsoft diff --git a/accel-pptpd/radius/dm_coa.c b/accel-pptpd/radius/dm_coa.c index baf51b51..366bb417 100644 --- a/accel-pptpd/radius/dm_coa.c +++ b/accel-pptpd/radius/dm_coa.c @@ -102,7 +102,7 @@ static int dm_coa_send_nak(int fd, struct rad_packet_t *req, struct sockaddr_in reply->id = req->id; if (err_code) - rad_packet_add_int(reply, "Error-Cause", err_code); + rad_packet_add_int(reply, NULL, "Error-Cause", err_code); if (rad_packet_build(reply, RA)) { rad_packet_free(reply); diff --git a/accel-pptpd/radius/packet.c b/accel-pptpd/radius/packet.c index 08991ddd..4e24dedc 100644 --- a/accel-pptpd/radius/packet.c +++ b/accel-pptpd/radius/packet.c @@ -324,15 +324,25 @@ void rad_packet_print(struct rad_packet_t *pack, void (*print)(const char *fmt, print("]\n"); } -int rad_packet_add_int(struct rad_packet_t *pack, const char *name, int val) +int __export rad_packet_add_int(struct rad_packet_t *pack, const char *vendor_name, const char *name, int val) { struct rad_attr_t *ra; struct rad_dict_attr_t *attr; + struct rad_dict_vendor_t *vendor; - if (pack->len + 2 + 4 >= REQ_LENGTH_MAX) + if (pack->len + (vendor_name ? 8 : 2) + 4 >= REQ_LENGTH_MAX) return -1; - attr = rad_dict_find_attr(name); + if (vendor_name) { + vendor = rad_dict_find_vendor_name(vendor_name); + if (!vendor) + return -1; + attr = rad_dict_find_vendor_attr(vendor, name); + } else { + vendor = NULL; + attr = rad_dict_find_attr(name); + } + if (!attr) return -1; @@ -341,20 +351,21 @@ int rad_packet_add_int(struct rad_packet_t *pack, const char *name, int val) return -1; memset(ra, 0, sizeof(*ra)); + ra->vendor = vendor; ra->attr = attr; ra->len = 4; ra->val.integer = val; list_add_tail(&ra->entry, &pack->attrs); - pack->len += 2 + 4; + pack->len += (vendor_name ? 8 : 2) + 4; return 0; } -int rad_packet_change_int(struct rad_packet_t *pack, const char *name, int val) +int __export rad_packet_change_int(struct rad_packet_t *pack, const char *vendor_name, const char *name, int val) { struct rad_attr_t *ra; - ra = rad_packet_find_attr(pack, name); + ra = rad_packet_find_attr(pack, vendor_name, name); if (!ra) return -1; @@ -363,15 +374,25 @@ int rad_packet_change_int(struct rad_packet_t *pack, const char *name, int val) return 0; } -int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len) +int __export rad_packet_add_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len) { struct rad_attr_t *ra; struct rad_dict_attr_t *attr; + struct rad_dict_vendor_t *vendor; - if (pack->len + 2 + len >= REQ_LENGTH_MAX) + if (pack->len + (vendor_name ? 8 : 2) + len >= REQ_LENGTH_MAX) return -1; - attr = rad_dict_find_attr(name); + if (vendor_name) { + vendor = rad_dict_find_vendor_name(vendor_name); + if (!vendor) + return -1; + attr = rad_dict_find_vendor_attr(vendor, name); + } else { + vendor = NULL; + attr = rad_dict_find_attr(name); + } + if (!attr) return -1; @@ -382,6 +403,7 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, const uin } memset(ra, 0, sizeof(*ra)); + ra->vendor = vendor; ra->attr = attr; ra->len = len; ra->val.octets = _malloc(len); @@ -392,16 +414,16 @@ int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, const uin } memcpy(ra->val.octets, val, len); list_add_tail(&ra->entry, &pack->attrs); - pack->len += 2 + len; + pack->len += (vendor_name ? 8 : 2) + len; return 0; } -int rad_packet_change_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len) +int __export rad_packet_change_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len) { struct rad_attr_t *ra; - ra = rad_packet_find_attr(pack, name); + ra = rad_packet_find_attr(pack, vendor_name, name); if (!ra) return -1; @@ -425,15 +447,26 @@ int rad_packet_change_octets(struct rad_packet_t *pack, const char *name, const } -int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *val, int len) +int __export rad_packet_add_str(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val) { struct rad_attr_t *ra; struct rad_dict_attr_t *attr; + struct rad_dict_vendor_t *vendor; + int len = strlen(val); - if (pack->len + 2 + len >= REQ_LENGTH_MAX) + if (pack->len + (vendor_name ? 8 : 2) + len >= REQ_LENGTH_MAX) return -1; - attr = rad_dict_find_attr(name); + if (vendor_name) { + vendor = rad_dict_find_vendor_name(vendor_name); + if (!vendor) + return -1; + attr = rad_dict_find_vendor_attr(vendor, name); + } else { + vendor = NULL; + attr = rad_dict_find_attr(name); + } + if (!attr) return -1; @@ -444,9 +477,10 @@ int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char * } memset(ra, 0, sizeof(*ra)); + ra->vendor = vendor; ra->attr = attr; ra->len = len; - ra->val.string = _malloc(len+1); + ra->val.string = _malloc(len + 1); if (!ra->val.string) { log_emerg("radius: out of memory\n"); _free(ra); @@ -455,16 +489,16 @@ int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char * memcpy(ra->val.string, val, len); ra->val.string[len] = 0; list_add_tail(&ra->entry, &pack->attrs); - pack->len += 2 + len; + pack->len += (vendor_name ? 8 : 2) + len; return 0; } -int rad_packet_change_str(struct rad_packet_t *pack, const char *name, const char *val, int len) +int __export rad_packet_change_str(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val, int len) { struct rad_attr_t *ra; - ra = rad_packet_find_attr(pack, name); + ra = rad_packet_find_attr(pack, vendor_name, name); if (!ra) return -1; @@ -488,19 +522,29 @@ int rad_packet_change_str(struct rad_packet_t *pack, const char *name, const cha return 0; } -int rad_packet_add_val(struct rad_packet_t *pack, const char *name, const char *val) +int __export rad_packet_add_val(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val) { struct rad_attr_t *ra; struct rad_dict_attr_t *attr; struct rad_dict_value_t *v; + struct rad_dict_vendor_t *vendor; - if (pack->len + 2 + 4 >= REQ_LENGTH_MAX) + if (pack->len + (vendor_name ? 8 : 2) + 4 >= REQ_LENGTH_MAX) return -1; - attr = rad_dict_find_attr(name); + if (vendor_name) { + vendor = rad_dict_find_vendor_name(vendor_name); + if (!vendor) + return -1; + attr = rad_dict_find_vendor_attr(vendor, name); + } else { + vendor = NULL; + attr = rad_dict_find_attr(name); + } + if (!attr) return -1; - + v = rad_dict_find_val_name(attr, val); if (!v) return -1; @@ -510,21 +554,22 @@ int rad_packet_add_val(struct rad_packet_t *pack, const char *name, const char * return -1; memset(ra, 0, sizeof(*ra)); + ra->vendor = vendor; ra->attr = attr; ra->len = 4; ra->val = v->val; list_add_tail(&ra->entry, &pack->attrs); - pack->len += 2 + 4; + pack->len += (vendor_name ? 8 : 2) + 4; return 0; } -int rad_packet_change_val(struct rad_packet_t *pack, const char *name, const char *val) +int __export rad_packet_change_val(struct rad_packet_t *pack, const char *vendor_name, const char *name, const char *val) { struct rad_attr_t *ra; struct rad_dict_value_t *v; - ra = rad_packet_find_attr(pack, name); + ra = rad_packet_find_attr(pack, vendor_name, name); if (!ra) return -1; @@ -537,19 +582,33 @@ int rad_packet_change_val(struct rad_packet_t *pack, const char *name, const cha return 0; } -int rad_packet_add_ipaddr(struct rad_packet_t *pack, const char *name, in_addr_t ipaddr) +int __export rad_packet_add_ipaddr(struct rad_packet_t *pack, const char *vendor_name, const char *name, in_addr_t ipaddr) { - return rad_packet_add_int(pack, name, ipaddr); + return rad_packet_add_int(pack, vendor_name, name, ipaddr); } -struct rad_attr_t *rad_packet_find_attr(struct rad_packet_t *pack, const char *name) +struct rad_attr_t __export *rad_packet_find_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name) { struct rad_attr_t *ra; + struct rad_dict_vendor_t *vendor; - list_for_each_entry(ra, &pack->attrs, entry) - if (!strcmp(ra->attr->name, name)) - return ra; + if (vendor_name) { + vendor = rad_dict_find_vendor_name(vendor_name); + if (!vendor) + return NULL; + } else + vendor = NULL; + + list_for_each_entry(ra, &pack->attrs, entry) { + if (vendor && vendor != ra->vendor) + continue; + + if (strcmp(ra->attr->name, name)) + continue; + + return ra; + } return NULL; } @@ -578,91 +637,6 @@ int rad_packet_send(struct rad_packet_t *pack, int fd, struct sockaddr_in *addr) return 0; } -int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len) -{ - struct rad_attr_t *ra; - struct rad_dict_attr_t *attr; - struct rad_dict_vendor_t *vendor; - - if (pack->len + 6 + 2 + len >= REQ_LENGTH_MAX) - return -1; - - vendor = rad_dict_find_vendor_name(vendor_name); - if (!vendor) - return -1; - - attr = rad_dict_find_vendor_attr(vendor, name); - if (!attr) - return -1; - - ra = mempool_alloc(attr_pool); - if (!ra) { - log_emerg("radius: out of memory\n"); - return -1; - } - - memset(ra, 0, sizeof(*ra)); - ra->vendor = vendor; - ra->attr = attr; - ra->len = len; - ra->val.octets = _malloc(len); - if (!ra->val.octets) { - log_emerg("radius: out of memory\n"); - _free(ra); - return -1; - } - memcpy(ra->val.octets, val, len); - list_add_tail(&ra->entry, &pack->attrs); - pack->len += 6 + 2 + len; - - return 0; -} - -int rad_packet_change_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len) -{ - struct rad_attr_t *ra; - - ra = rad_packet_find_vendor_attr(pack, vendor_name, name); - if (!ra) - return -1; - - if (ra->len != len) { - if (pack->len - ra->len + len >= REQ_LENGTH_MAX) - return -1; - - ra->val.octets = _realloc(ra->val.octets, len); - if (!ra->val.octets) { - log_emerg("radius: out of memory\n"); - return -1; - } - - pack->len += len - ra->len; - ra->len = len; - } - - memcpy(ra->val.octets, val, len); - - return 0; -} - -struct rad_attr_t *rad_packet_find_vendor_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name) -{ - struct rad_attr_t *ra; - - list_for_each_entry(ra, &pack->attrs, entry) { - if (!ra->vendor) - continue; - if (strcmp(ra->vendor->name, vendor_name)) - continue; - if (strcmp(ra->attr->name, name)) - continue; - - return ra; - } - - return NULL; -} - static void __init init(void) { attr_pool = mempool_create(sizeof(struct rad_attr_t)); diff --git a/accel-pptpd/radius/radius.c b/accel-pptpd/radius/radius.c index 8d0c8878..f081cf4f 100644 --- a/accel-pptpd/radius/radius.c +++ b/accel-pptpd/radius/radius.c @@ -173,6 +173,7 @@ static void ppp_starting(struct ppp_t *ppp) rpd->pd.key = &pd_key; rpd->ppp = ppp; pthread_mutex_init(&rpd->lock, NULL); + INIT_LIST_HEAD(&rpd->plugin_list); list_add_tail(&rpd->pd.entry, &ppp->pd_list); pthread_rwlock_wrlock(&sessions_lock); @@ -331,12 +332,23 @@ int rad_check_nas_pack(struct rad_packet_t *pack) if (conf_nas_identifier && ident && strcmp(conf_nas_identifier, ident)) return -1; + if (conf_nas_ip_address && ipaddr && conf_nas_ip_address != ipaddr) return -1; return 0; } +void __export rad_register_plugin(struct ppp_t *ppp, struct rad_plugin_t *plugin) +{ + struct radius_pd_t *rpd = find_pd(ppp); + + if (!rpd) + return; + + list_add_tail(&plugin->entry, &rpd->plugin_list); +} + static struct ipdb_t ipdb = { .get = get_ip, }; diff --git a/accel-pptpd/radius/radius.h b/accel-pptpd/radius/radius.h index c42989e4..ad229d22 100644 --- a/accel-pptpd/radius/radius.h +++ b/accel-pptpd/radius/radius.h @@ -84,6 +84,17 @@ struct rad_packet_t void *buf; }; +struct rad_plugin_t +{ + struct list_head entry; + int (*send_access_request)(struct rad_plugin_t *, struct rad_packet_t *pack); + int (*send_accounting_request)(struct rad_plugin_t *, struct rad_packet_t *pack); +}; + +struct ppp_t; + +void rad_register_plugin(struct ppp_t *, struct rad_plugin_t *); + struct rad_dict_attr_t *rad_dict_find_attr(const char *name); struct rad_dict_attr_t *rad_dict_find_attr_id(struct rad_dict_vendor_t *vendor, int type); struct rad_dict_value_t *rad_dict_find_val_name(struct rad_dict_attr_t *, const char *name); @@ -92,18 +103,15 @@ struct rad_dict_vendor_t *rad_dict_find_vendor_name(const char *name); struct rad_dict_vendor_t *rad_dict_find_vendor_id(int id); struct rad_dict_attr_t *rad_dict_find_vendor_attr(struct rad_dict_vendor_t *vendor, const char *name); -struct rad_attr_t *rad_packet_find_attr(struct rad_packet_t *pack, const char *name); -int rad_packet_add_int(struct rad_packet_t *pack, const char *name, int val); -int rad_packet_add_val(struct rad_packet_t *pack, const char *name, const char *val); -int rad_packet_add_str(struct rad_packet_t *pack, const char *name, const char *val, int len); -int rad_packet_add_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len); -int rad_packet_change_int(struct rad_packet_t *pack, const char *name, int val); -int rad_packet_change_val(struct rad_packet_t *pack, const char *name, const char *val); -int rad_packet_change_octets(struct rad_packet_t *pack, const char *name, const uint8_t *val, int len); -int rad_packet_add_ipaddr(struct rad_packet_t *pack, const char *name, in_addr_t ipaddr); -int rad_packet_add_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len); -int rad_packet_change_vendor_octets(struct rad_packet_t *pack, const char *vendor_name, const char *name, const uint8_t *val, int len); -struct rad_attr_t *rad_packet_find_vendor_attr(struct rad_packet_t *pack, const char *vendor_name, const char *name); +struct rad_attr_t *rad_packet_find_attr(struct rad_packet_t *pack, const char *vendor, const char *name); +int rad_packet_add_int(struct rad_packet_t *pack, const char *vendor, const char *name, int val); +int rad_packet_add_val(struct rad_packet_t *pack, const char *vendor, const char *name, const char *val); +int rad_packet_add_str(struct rad_packet_t *pack, const char *vendor, const char *name, const char *val); +int rad_packet_add_octets(struct rad_packet_t *pack, const char *vendor, const char *name, const uint8_t *val, int len); +int rad_packet_change_int(struct rad_packet_t *pack, const char *vendor, const char *name, int val); +int rad_packet_change_val(struct rad_packet_t *pack, const char *vendor, const char *name, const char *val); +int rad_packet_change_octets(struct rad_packet_t *pack, const char *vendor, const char *name, const uint8_t *val, int len); +int rad_packet_add_ipaddr(struct rad_packet_t *pack, const char *vendor, const char *name, in_addr_t ipaddr); #endif diff --git a/accel-pptpd/radius/radius_p.h b/accel-pptpd/radius/radius_p.h index 2bd3ff84..9fd0b74c 100644 --- a/accel-pptpd/radius/radius_p.h +++ b/accel-pptpd/radius/radius_p.h @@ -38,6 +38,8 @@ struct radius_pd_t uint8_t *attr_state; int attr_state_len; int termination_action; + + struct list_head plugin_list; }; struct rad_req_t diff --git a/accel-pptpd/radius/req.c b/accel-pptpd/radius/req.c index 94c10c3e..a384f236 100644 --- a/accel-pptpd/radius/req.c +++ b/accel-pptpd/radius/req.c @@ -21,6 +21,7 @@ static void rad_req_timeout(struct triton_timer_t *t); struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *username) { + struct rad_plugin_t *plugin; struct rad_req_t *req = _malloc(sizeof(*req)); if (!req) @@ -48,32 +49,45 @@ struct rad_req_t *rad_req_alloc(struct radius_pd_t *rpd, int code, const char *u if (!req->pack) goto out_err; - if (rad_packet_add_str(req->pack, "User-Name", username, strlen(username))) + if (rad_packet_add_str(req->pack, NULL, "User-Name", username)) goto out_err; if (conf_nas_identifier) - if (rad_packet_add_str(req->pack, "NAS-Identifier", conf_nas_identifier, strlen(conf_nas_identifier))) + if (rad_packet_add_str(req->pack, NULL, "NAS-Identifier", conf_nas_identifier)) goto out_err; if (conf_nas_ip_address) - if (rad_packet_add_ipaddr(req->pack, "NAS-IP-Address", conf_nas_ip_address)) + if (rad_packet_add_ipaddr(req->pack, NULL, "NAS-IP-Address", conf_nas_ip_address)) goto out_err; - if (rad_packet_add_int(req->pack, "NAS-Port", rpd->ppp->unit_idx)) + if (rad_packet_add_int(req->pack, NULL, "NAS-Port", rpd->ppp->unit_idx)) goto out_err; - if (rad_packet_add_val(req->pack, "NAS-Port-Type", "Virtual")) + if (rad_packet_add_val(req->pack, NULL, "NAS-Port-Type", "Virtual")) goto out_err; - if (rad_packet_add_val(req->pack, "Service-Type", "Framed-User")) + if (rad_packet_add_val(req->pack, NULL, "Service-Type", "Framed-User")) goto out_err; - if (rad_packet_add_val(req->pack, "Framed-Protocol", "PPP")) + if (rad_packet_add_val(req->pack, NULL, "Framed-Protocol", "PPP")) goto out_err; if (rpd->ppp->ctrl->calling_station_id) - if (rad_packet_add_str(req->pack, "Calling-Station-Id", rpd->ppp->ctrl->calling_station_id, strlen(rpd->ppp->ctrl->calling_station_id))) + if (rad_packet_add_str(req->pack, NULL, "Calling-Station-Id", rpd->ppp->ctrl->calling_station_id)) goto out_err; if (rpd->ppp->ctrl->called_station_id) - if (rad_packet_add_str(req->pack, "Called-Station-Id", rpd->ppp->ctrl->called_station_id, strlen(rpd->ppp->ctrl->called_station_id))) + if (rad_packet_add_str(req->pack, NULL, "Called-Station-Id", rpd->ppp->ctrl->called_station_id)) goto out_err; if (rpd->attr_class) - if (rad_packet_add_octets(req->pack, "Class", rpd->attr_class, rpd->attr_class_len)) + if (rad_packet_add_octets(req->pack, NULL, "Class", rpd->attr_class, rpd->attr_class_len)) goto out_err; + list_for_each_entry(plugin, &req->rpd->plugin_list, entry) { + switch (code) { + case CODE_ACCESS_REQUEST: + if (plugin->send_access_request && plugin->send_access_request(plugin, req->pack)) + goto out_err; + break; + case CODE_ACCOUNTING_REQUEST: + if (plugin->send_accounting_request && plugin->send_accounting_request(plugin, req->pack)) + goto out_err; + break; + } + } + return req; out_err: @@ -88,29 +102,29 @@ int rad_req_acct_fill(struct rad_req_t *req) memset(req->RA, 0, sizeof(req->RA)); - if (rad_packet_add_val(req->pack, "Acct-Status-Type", "Start")) + if (rad_packet_add_val(req->pack, NULL, "Acct-Status-Type", "Start")) return -1; - if (rad_packet_add_val(req->pack, "Acct-Authentic", "RADIUS")) + if (rad_packet_add_val(req->pack, NULL, "Acct-Authentic", "RADIUS")) return -1; - if (rad_packet_add_str(req->pack, "Acct-Session-Id", req->rpd->ppp->sessionid, PPP_SESSIONID_LEN)) + if (rad_packet_add_str(req->pack, NULL, "Acct-Session-Id", req->rpd->ppp->sessionid)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Session-Time", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Session-Time", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Input-Octets", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Input-Octets", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Output-Octets", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Output-Octets", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Input-Packets", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Input-Packets", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Output-Packets", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Output-Packets", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Input-Gigawords", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Input-Gigawords", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Output-Gigawords", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Output-Gigawords", 0)) return -1; - if (rad_packet_add_int(req->pack, "Acct-Delay-Time", 0)) + if (rad_packet_add_int(req->pack, NULL, "Acct-Delay-Time", 0)) return -1; - if (rad_packet_add_ipaddr(req->pack, "Framed-IP-Address", req->rpd->ppp->peer_ipaddr)) + if (rad_packet_add_ipaddr(req->pack, NULL, "Framed-IP-Address", req->rpd->ppp->peer_ipaddr)) return -1; return 0; diff --git a/accel-pptpd/triton/loader.c b/accel-pptpd/triton/loader.c index b6c1914e..2a2a2e2f 100644 --- a/accel-pptpd/triton/loader.c +++ b/accel-pptpd/triton/loader.c @@ -48,7 +48,7 @@ int load_modules(const char *name) } } - if (!dlopen(fname, RTLD_NOW | RTLD_GLOBAL)) { + if (!dlopen(fname, RTLD_LAZY | RTLD_GLOBAL)) { triton_log_error("loader: failed to load '%s': %s\n", opt->name, dlerror()); _free(fname); return -1; diff --git a/accel-pptpd/triton/md.c b/accel-pptpd/triton/md.c index d8453896..84073d05 100644 --- a/accel-pptpd/triton/md.c +++ b/accel-pptpd/triton/md.c @@ -140,8 +140,10 @@ void __export triton_md_unregister_handler(struct triton_md_handler_t *ud) spin_lock(&h->ctx->lock); h->ud = NULL; list_del(&h->entry); - if (h->pending) + if (h->pending) { list_del(&h->entry2); + __sync_sub_and_fetch(&triton_stat.md_handler_pending, 1); + } spin_unlock(&h->ctx->lock); sched_yield(); diff --git a/accel-pptpd/triton/timer.c b/accel-pptpd/triton/timer.c index 4e37754c..7d117308 100644 --- a/accel-pptpd/triton/timer.c +++ b/accel-pptpd/triton/timer.c @@ -202,8 +202,10 @@ void __export triton_timer_del(struct triton_timer_t *ud) spin_lock(&t->ctx->lock); t->ud = NULL; list_del(&t->entry); - if (t->pending) + if (t->pending) { list_del(&t->entry2); + __sync_sub_and_fetch(&triton_stat.timer_pending, 1); + } spin_unlock(&t->ctx->lock); sched_yield(); diff --git a/rfc/TR-101.pdf b/rfc/TR-101.pdf Binary files differnew file mode 100644 index 00000000..38302020 --- /dev/null +++ b/rfc/TR-101.pdf |