diff options
author | Kozlov Dmitry <dima@server> | 2010-12-29 17:20:29 +0300 |
---|---|---|
committer | Kozlov Dmitry <dima@server> | 2010-12-29 17:20:29 +0300 |
commit | 782fe82063670697d47a81e6ad97acb65b5c18ee (patch) | |
tree | f832d0342d401e80d73c82c17e1e5c98250459b3 | |
parent | 7206898657c84b6131103d127751e030513a1abc (diff) | |
download | accel-ppp-782fe82063670697d47a81e6ad97acb65b5c18ee.tar.gz accel-ppp-782fe82063670697d47a81e6ad97acb65b5c18ee.zip |
pppoe: TR-101 support (untested)
-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-- | rfc/TR-101.pdf | bin | 0 -> 970534 bytes |
5 files changed, 167 insertions, 4 deletions
diff --git a/accel-pptpd/ctrl/pppoe/CMakeLists.txt b/accel-pptpd/ctrl/pppoe/CMakeLists.txt index 5f5c5e4..f047936 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 2ec8bc2..3e6b0bf 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 323715d..b0e665d 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 0000000..cfb0fbc --- /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/rfc/TR-101.pdf b/rfc/TR-101.pdf Binary files differnew file mode 100644 index 0000000..3830202 --- /dev/null +++ b/rfc/TR-101.pdf |