提交 782fe820 编写于 作者: K Kozlov Dmitry

pppoe: TR-101 support (untested)

上级 72068986
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)
......@@ -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 {
......
......@@ -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
#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);
}
文件已添加
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册