summaryrefslogtreecommitdiff
path: root/accel-pptpd/ctrl/pppoe/pppoe.c
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pptpd/ctrl/pppoe/pppoe.c')
-rw-r--r--accel-pptpd/ctrl/pppoe/pppoe.c61
1 files changed, 58 insertions, 3 deletions
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 {