summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-12-29 17:20:29 +0300
committerKozlov Dmitry <dima@server>2010-12-29 17:20:29 +0300
commit782fe82063670697d47a81e6ad97acb65b5c18ee (patch)
treef832d0342d401e80d73c82c17e1e5c98250459b3
parent7206898657c84b6131103d127751e030513a1abc (diff)
downloadaccel-ppp-782fe82063670697d47a81e6ad97acb65b5c18ee.tar.gz
accel-ppp-782fe82063670697d47a81e6ad97acb65b5c18ee.zip
pppoe: TR-101 support (untested)
-rw-r--r--accel-pptpd/ctrl/pppoe/CMakeLists.txt7
-rw-r--r--accel-pptpd/ctrl/pppoe/pppoe.c61
-rw-r--r--accel-pptpd/ctrl/pppoe/pppoe.h6
-rw-r--r--accel-pptpd/ctrl/pppoe/tr101.c97
-rw-r--r--rfc/TR-101.pdfbin0 -> 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 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/rfc/TR-101.pdf b/rfc/TR-101.pdf
new file mode 100644
index 00000000..38302020
--- /dev/null
+++ b/rfc/TR-101.pdf
Binary files differ