summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Kozlov <xeb@mail.ru>2014-11-05 13:20:23 +0300
committerDmitry Kozlov <xeb@mail.ru>2014-11-05 13:20:23 +0300
commitd856a2895ab85fedb2886d9ed0deb173201e34fa (patch)
tree9e55a2b61d41c2ea4204c7c07757d53556bb3791
parent4376d7feecf8e8dec02eb1f19f4b21929441f184 (diff)
downloadaccel-ppp-d856a2895ab85fedb2886d9ed0deb173201e34fa.tar.gz
accel-ppp-d856a2895ab85fedb2886d9ed0deb173201e34fa.zip
pppd_compat: pass IPV6_PREFIX and IPV6_DELEGATED_PREFIX to ip-up/ip-down scripts
-rw-r--r--accel-pppd/extra/pppd_compat.c119
1 files changed, 66 insertions, 53 deletions
diff --git a/accel-pppd/extra/pppd_compat.c b/accel-pppd/extra/pppd_compat.c
index e005e8b..e48029b 100644
--- a/accel-pppd/extra/pppd_compat.c
+++ b/accel-pppd/extra/pppd_compat.c
@@ -9,6 +9,7 @@
#include <inttypes.h>
#include <sys/ioctl.h>
#include <netinet/in.h>
+#include <arpa/inet.h>
#include "linux_ppp.h"
#include "triton.h"
@@ -27,6 +28,9 @@
#include "memdebug.h"
+#define ENV_MEM 1024
+#define ENV_MAX 16
+
static char *conf_ip_up = "/etc/ppp/ip-up";
static char *conf_ip_pre_up;
static char *conf_ip_down = "/etc/ppp/ip-down";
@@ -56,7 +60,7 @@ struct pppd_compat_pd
static struct pppd_compat_pd *find_pd(struct ap_session *ses);
static void fill_argv(char **argv, struct pppd_compat_pd *pd, char *path);
-static void fill_env(char **env, struct pppd_compat_pd *pd);
+static void fill_env(char **env, char *mem, struct pppd_compat_pd *pd);
#ifdef RADIUS
static void remove_radattr(struct pppd_compat_pd *);
static void write_radattr(struct pppd_compat_pd *, struct rad_packet_t *pack);
@@ -130,12 +134,10 @@ static void ev_ses_pre_up(struct ap_session *ses)
{
pid_t pid;
char *argv[8];
- char *env[4];
+ char *env[ENV_MAX];
+ char env_mem[ENV_MEM];
char ipaddr[17];
char peer_ipaddr[17];
- char peername[64];
- char calling_sid[64];
- char called_sid[64];
struct pppd_compat_pd *pd = find_pd(ses);
if (!pd)
@@ -168,11 +170,7 @@ static void ev_ses_pre_up(struct ap_session *ses)
argv[5] = peer_ipaddr;
fill_argv(argv, pd, conf_ip_up);
- env[0] = peername;
- env[1] = calling_sid;
- env[2] = called_sid;
- env[3] = NULL;
- fill_env(env, pd);
+ fill_env(env, env_mem, pd);
if (conf_ip_pre_up) {
sigchld_lock();
@@ -207,12 +205,10 @@ static void ev_ses_started(struct ap_session *ses)
{
pid_t pid;
char *argv[8];
- char *env[4];
+ char *env[ENV_MAX];
+ char env_mem[ENV_MEM];
char ipaddr[17];
char peer_ipaddr[17];
- char peername[64];
- char calling_sid[64];
- char called_sid[64];
struct pppd_compat_pd *pd = find_pd(ses);
if (!pd)
@@ -222,11 +218,7 @@ static void ev_ses_started(struct ap_session *ses)
argv[5] = peer_ipaddr;
fill_argv(argv, pd, conf_ip_up);
- env[0] = peername;
- env[1] = calling_sid;
- env[2] = called_sid;
- env[3] = NULL;
- fill_env(env, pd);
+ fill_env(env, env_mem, pd);
if (conf_ip_up) {
sigchld_lock();
@@ -256,15 +248,10 @@ static void ev_ses_finished(struct ap_session *ses)
{
pid_t pid;
char *argv[8];
- char *env[7];
+ char *env[ENV_MAX];
+ char env_mem[ENV_MEM];
char ipaddr[17];
char peer_ipaddr[17];
- char peername[64];
- char calling_sid[64];
- char called_sid[64];
- char connect_time[24];
- char bytes_sent[24];
- char bytes_rcvd[24];
struct pppd_compat_pd *pd = find_pd(ses);
if (!pd)
@@ -284,14 +271,7 @@ static void ev_ses_finished(struct ap_session *ses)
argv[5] = peer_ipaddr;
fill_argv(argv, pd, conf_ip_down);
- env[0] = peername;
- env[1] = calling_sid;
- env[2] = called_sid;
- env[3] = connect_time;
- env[4] = bytes_sent;
- env[5] = bytes_rcvd;
- env[6] = NULL;
- fill_env(env, pd);
+ fill_env(env, env_mem, pd);
if (conf_ip_down) {
sigchld_lock();
@@ -354,12 +334,10 @@ static void ev_radius_coa(struct ev_radius_t *ev)
{
pid_t pid;
char *argv[8];
- char *env[4];
+ char *env[ENV_MAX];
+ char env_mem[ENV_MEM];
char ipaddr[17];
char peer_ipaddr[17];
- char peername[64];
- char calling_sid[64];
- char called_sid[64];
struct pppd_compat_pd *pd = find_pd(ev->ses);
if (!pd)
@@ -371,11 +349,7 @@ static void ev_radius_coa(struct ev_radius_t *ev)
argv[5] = peer_ipaddr;
fill_argv(argv, pd, conf_ip_change);
- env[0] = peername;
- env[1] = calling_sid;
- env[2] = called_sid;
- env[3] = NULL;
- fill_env(env, pd);
+ fill_env(env, env_mem, pd);
sigchld_lock();
pid = fork();
@@ -527,23 +501,62 @@ static void fill_argv(char **argv, struct pppd_compat_pd *pd, char *path)
argv[7] = NULL;
}
-static void fill_env(char **env, struct pppd_compat_pd *pd)
+static void build_addr(struct ipv6db_addr_t *a, uint64_t intf_id, struct in6_addr *addr)
+{
+ memcpy(addr, &a->addr, sizeof(*addr));
+
+ if (a->prefix_len <= 64)
+ *(uint64_t *)(addr->s6_addr + 8) = intf_id;
+ else
+ *(uint64_t *)(addr->s6_addr + 8) |= intf_id & ((1 << (128 - a->prefix_len)) - 1);
+}
+
+static void fill_env(char **env, char *mem, struct pppd_compat_pd *pd)
{
struct ap_session *ses = pd->ses;
uint64_t tx_bytes, rx_bytes;
+ int n = 0;
- tx_bytes = (uint64_t)ses->acct_tx_bytes + ses->acct_output_gigawords*4294967296llu;
- rx_bytes = (uint64_t)ses->acct_rx_bytes + ses->acct_input_gigawords*4294967296llu;
+ tx_bytes = (uint64_t)ses->acct_tx_bytes + 4294967296llu*ses->acct_output_gigawords;
+ rx_bytes = (uint64_t)ses->acct_rx_bytes + 4294967296llu*ses->acct_input_gigawords;
- snprintf(env[0], 64, "PEERNAME=%s", pd->ses->username);
- snprintf(env[1], 64, "CALLING_SID=%s", pd->ses->ctrl->calling_station_id);
- snprintf(env[2], 64, "CALLED_SID=%s", pd->ses->ctrl->called_station_id);
+ env[n++] = mem;
+ mem += sprintf(mem, "PEERNAME=%s", pd->ses->username) + 1;
+ env[n++] = mem;
+ mem += sprintf(mem, "CALLING_SID=%s", pd->ses->ctrl->calling_station_id) + 1;
+ env[n++] = mem;
+ mem += sprintf(mem, "CALLED_SID=%s", pd->ses->ctrl->called_station_id) + 1;
+
+ if (ses->ipv6) {
+ ///FIXME only first address is passed to env
+ struct ipv6db_addr_t *a = list_first_entry(&ses->ipv6->addr_list, typeof(*a), entry);
+ struct in6_addr addr;
+ build_addr(a, ses->ipv6->peer_intf_id, &addr);
+ env[n++] = mem;
+ strcpy(mem, "IPV6_PREFIX="); mem += 12;
+ inet_ntop(AF_INET6, &addr, mem, ENV_MEM); mem = strchr(mem, 0);
+ mem += sprintf(mem, "/%i", a->prefix_len) + 1;
+ }
+
+ if (ses->ipv6_dp) {
+ ///FIXME only first prefix is passed to env
+ struct ipv6db_addr_t *a = list_first_entry(&ses->ipv6_dp->prefix_list, typeof(*a), entry);
+ env[n++] = mem;
+ strcpy(mem, "IPV6_DELEGATED_PREFIX="); mem += 22;
+ inet_ntop(AF_INET6, &a->addr, mem, ENV_MEM); mem = strchr(mem, 0);
+ mem += sprintf(mem, "/%i", a->prefix_len) + 1;
+ }
- if (pd->ses->stop_time && env[3]) {
- snprintf(env[3], 24, "CONNECT_TIME=%lu", pd->ses->stop_time - pd->ses->start_time);
- snprintf(env[4], 24, "BYTES_SENT=%" PRIu64, tx_bytes);
- snprintf(env[5], 24, "BYTES_RCVD=%" PRIu64, rx_bytes);
+ if (pd->ses->stop_time) {
+ env[n++] = mem;
+ mem += sprintf(mem, "CONNECT_TIME=%lu", pd->ses->stop_time - pd->ses->start_time) + 1;
+ env[n++] = mem;
+ mem += sprintf(mem, "BYTES_SENT=%" PRIu64, tx_bytes) + 1;
+ env[n++] = mem;
+ mem += sprintf(mem, "BYTES_RCVD=%" PRIu64, rx_bytes) + 1;
}
+
+ env[n++] = NULL;
}
static void init(void)