summaryrefslogtreecommitdiff
path: root/accel-pppd
diff options
context:
space:
mode:
Diffstat (limited to 'accel-pppd')
-rw-r--r--accel-pppd/cli/show_sessions.c3
-rw-r--r--accel-pppd/cli/std_cmd.c3
-rw-r--r--accel-pppd/extra/ipv6pool.c37
-rw-r--r--accel-pppd/extra/net-snmp/sessionTable_data_access.c3
-rw-r--r--accel-pppd/extra/net-snmp/terminate.c3
-rw-r--r--accel-pppd/extra/pppd_compat.c5
-rw-r--r--accel-pppd/ipdb.h12
-rw-r--r--accel-pppd/ppp/ipcp_opt_ipaddr.c102
-rw-r--r--accel-pppd/ppp/ipv6_nd.c207
-rw-r--r--accel-pppd/ppp/ipv6cp_opt_intfid.c49
-rw-r--r--accel-pppd/ppp/ppp.h9
-rw-r--r--accel-pppd/radius/radius.c4
-rw-r--r--accel-pppd/radius/req.c6
13 files changed, 265 insertions, 178 deletions
diff --git a/accel-pppd/cli/show_sessions.c b/accel-pppd/cli/show_sessions.c
index d7a8a824..90199864 100644
--- a/accel-pppd/cli/show_sessions.c
+++ b/accel-pppd/cli/show_sessions.c
@@ -8,6 +8,7 @@
#include "triton.h"
#include "events.h"
#include "ppp.h"
+#include "ipdb.h"
#include "cli.h"
#include "utils.h"
#include "log.h"
@@ -382,7 +383,7 @@ static void print_username(const struct ppp_t *ppp, char *buf)
static void print_ip(const struct ppp_t *ppp, char *buf)
{
- u_inet_ntoa(ppp->peer_ipaddr, buf);
+ u_inet_ntoa(ppp->ipv4 ? ppp->ipv4->peer_addr : 0, buf);
}
static void print_type(const struct ppp_t *ppp, char *buf)
diff --git a/accel-pppd/cli/std_cmd.c b/accel-pppd/cli/std_cmd.c
index 1c8e149f..24e52283 100644
--- a/accel-pppd/cli/std_cmd.c
+++ b/accel-pppd/cli/std_cmd.c
@@ -9,6 +9,7 @@
#include "triton.h"
#include "events.h"
#include "ppp.h"
+#include "ipdb.h"
#include "cli.h"
#include "utils.h"
#include "log.h"
@@ -166,7 +167,7 @@ static int terminate_exec2(int key, char * const *f, int f_cnt, void *cli)
continue;
break;
case 1:
- if (ppp->peer_ipaddr != ipaddr)
+ if (ppp->ipv4 && ppp->ipv4->peer_addr != ipaddr)
continue;
break;
case 2:
diff --git a/accel-pppd/extra/ipv6pool.c b/accel-pppd/extra/ipv6pool.c
index 306d5bdd..5a1a6065 100644
--- a/accel-pppd/extra/ipv6pool.c
+++ b/accel-pppd/extra/ipv6pool.c
@@ -39,6 +39,7 @@ static void generate_pool(struct in6_addr *addr, int mask, int prefix_len)
{
struct ippool_item_t *it;
uint64_t ip, endip, step;
+ struct ipv6db_addr_t *a;
ip = be64toh(*(uint64_t *)addr->s6_addr);
endip = ip | ((1llu << (64 - mask)) - 1);
@@ -46,8 +47,13 @@ static void generate_pool(struct in6_addr *addr, int mask, int prefix_len)
for (; ip <= endip; ip += step) {
it = malloc(sizeof(*it));
- *(uint64_t *)it->it.addr.s6_addr = htobe64(ip);
- it->it.prefix_len = prefix_len;
+ INIT_LIST_HEAD(&it->it.addr_list);
+ INIT_LIST_HEAD(&it->it.route_list);
+ a = malloc(sizeof(*a));
+ memset(a, 0, sizeof(*a));
+ *(uint64_t *)a->addr.s6_addr = htobe64(ip);
+ a->prefix_len = prefix_len;
+ list_add_tail(&a->entry, &it->it.addr_list);
list_add_tail(&it->entry, &ippool);
}
}
@@ -97,27 +103,36 @@ err:
_free(val);
}
-static void generate_intf_id(struct ppp_t *ppp, struct in6_addr *addr)
+static uint64_t generate_intf_id(struct ppp_t *ppp)
{
char str[4];
int i, n;
+ union {
+ uint64_t intf_id;
+ uint16_t addr16[4];
+ } u;
switch (conf_intf_id) {
case INTF_ID_FIXED:
- *(uint64_t *)(&addr->s6_addr32[2]) = conf_intf_id_val;
+ return conf_intf_id_val;
break;
case INTF_ID_RANDOM:
- read(urandom_fd, &addr->s6_addr32[2], 8);
+ read(urandom_fd, &u, sizeof(u));
break;
case INTF_ID_CSID:
break;
case INTF_ID_IPV4:
- for (i = 0; i < 4; i++) {
- sprintf(str, "%i", (ppp->peer_ipaddr >> (i*8)) & 0xff);
- sscanf(str, "%x", &n);
- addr->s6_addr16[4 + i] = htons(n);
- }
+ if (ppp->ipv4) {
+ for (i = 0; i < 4; i++) {
+ sprintf(str, "%i", (ppp->ipv4->peer_addr >> (i*8)) & 0xff);
+ sscanf(str, "%x", &n);
+ u.addr16[i] = htons(n);
+ }
+ } else
+ read(urandom_fd, &u, sizeof(u));
}
+
+ return u.intf_id;
}
static struct ipv6db_item_t *get_ip(struct ppp_t *ppp)
@@ -133,7 +148,7 @@ static struct ipv6db_item_t *get_ip(struct ppp_t *ppp)
spin_unlock(&pool_lock);
if (it)
- generate_intf_id(ppp, &it->it.addr);
+ it->it.intf_id = generate_intf_id(ppp);
return it ? &it->it : NULL;
}
diff --git a/accel-pppd/extra/net-snmp/sessionTable_data_access.c b/accel-pppd/extra/net-snmp/sessionTable_data_access.c
index 847197af..0d38e5df 100644
--- a/accel-pppd/extra/net-snmp/sessionTable_data_access.c
+++ b/accel-pppd/extra/net-snmp/sessionTable_data_access.c
@@ -16,6 +16,7 @@
#include "sessionTable_data_access.h"
#include "ppp.h"
+#include "ipdb.h"
/** @ingroup interface
* @addtogroup data_access data_access: Routines to access data
@@ -227,7 +228,7 @@ sessionTable_container_load(netsnmp_container *container)
else
ppp->username = strdup("");
- rowreq_ctx->data->peer_addr = ppp->peer_ipaddr;
+ rowreq_ctx->data->peer_addr = ppp->ipv4 ? ppp->ipv4->peer_addr : 0;
rowreq_ctx->data->type = ppp->ctrl->type;
rowreq_ctx->data->state = ppp->state;
rowreq_ctx->data->uptime = (ppp->stop_time ? ppp->stop_time : t) - ppp->start_time;
diff --git a/accel-pppd/extra/net-snmp/terminate.c b/accel-pppd/extra/net-snmp/terminate.c
index bd385772..abe92df0 100644
--- a/accel-pppd/extra/net-snmp/terminate.c
+++ b/accel-pppd/extra/net-snmp/terminate.c
@@ -12,6 +12,7 @@
#include "triton.h"
#include "ppp.h"
+#include "ipdb.h"
#include "terminate.h"
@@ -65,7 +66,7 @@ static void terminate_by_ip(const char *val, size_t len)
pthread_rwlock_rdlock(&ppp_lock);
list_for_each_entry(ppp, &ppp_list, entry) {
- if (ppp->peer_ipaddr != addr)
+ if (!ppp->ipv4 || ppp->ipv4->peer_addr != addr)
continue;
triton_context_call(ppp->ctrl->ctx, (triton_event_func)__terminate, ppp);
break;
diff --git a/accel-pppd/extra/pppd_compat.c b/accel-pppd/extra/pppd_compat.c
index aa6f6b59..32a5def9 100644
--- a/accel-pppd/extra/pppd_compat.c
+++ b/accel-pppd/extra/pppd_compat.c
@@ -14,6 +14,7 @@
#include "events.h"
#include "ppp.h"
+#include "ipdb.h"
#include "log.h"
#include "utils.h"
#include "sigchld.h"
@@ -480,8 +481,8 @@ static void fill_argv(char **argv, struct ppp_t *ppp, char *path)
argv[1] = ppp->ifname;
argv[2] = "none";
argv[3] = "0";
- u_inet_ntoa(ppp->ipaddr, argv[4]);
- u_inet_ntoa(ppp->peer_ipaddr, argv[5]);
+ u_inet_ntoa(ppp->ipv4 ? ppp->ipv4->addr : 0, argv[4]);
+ u_inet_ntoa(ppp->ipv4 ? ppp->ipv4->peer_addr : 0, argv[5]);
argv[6] = ppp->ctrl->calling_station_id;
argv[7] = NULL;
}
diff --git a/accel-pppd/ipdb.h b/accel-pppd/ipdb.h
index 3a717a15..69d54792 100644
--- a/accel-pppd/ipdb.h
+++ b/accel-pppd/ipdb.h
@@ -13,13 +13,21 @@ struct ipv4db_item_t
in_addr_t peer_addr;
};
-struct ipv6db_item_t
+struct ipv6db_addr_t
{
- struct ipdb_t *owner;
+ struct list_head entry;
struct in6_addr addr;
int prefix_len;
};
+struct ipv6db_item_t
+{
+ struct ipdb_t *owner;
+ uint64_t intf_id;
+ struct list_head addr_list;
+ struct list_head route_list;
+};
+
struct ipdb_t
{
diff --git a/accel-pppd/ppp/ipcp_opt_ipaddr.c b/accel-pppd/ppp/ipcp_opt_ipaddr.c
index ac45ac7c..f3870691 100644
--- a/accel-pppd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pppd/ppp/ipcp_opt_ipaddr.c
@@ -30,36 +30,36 @@ static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t
struct ipaddr_option_t
{
struct ipcp_option_t opt;
- struct ipv4db_item_t *ip;
+ struct ppp_t *ppp;
int started:1;
};
-static struct ipcp_option_handler_t ipaddr_opt_hnd=
-{
- .init=ipaddr_init,
- .send_conf_req=ipaddr_send_conf_req,
- .send_conf_nak=ipaddr_send_conf_nak,
- .recv_conf_req=ipaddr_recv_conf_req,
- .free=ipaddr_free,
- .print=ipaddr_print,
+static struct ipcp_option_handler_t ipaddr_opt_hnd = {
+ .init = ipaddr_init,
+ .send_conf_req = ipaddr_send_conf_req,
+ .send_conf_nak = ipaddr_send_conf_nak,
+ .recv_conf_req = ipaddr_recv_conf_req,
+ .free = ipaddr_free,
+ .print = ipaddr_print,
};
static struct ipcp_option_t *ipaddr_init(struct ppp_ipcp_t *ipcp)
{
- struct ipaddr_option_t *ipaddr_opt=_malloc(sizeof(*ipaddr_opt));
- memset(ipaddr_opt,0,sizeof(*ipaddr_opt));
- ipaddr_opt->opt.id=CI_ADDR;
- ipaddr_opt->opt.len=6;
+ struct ipaddr_option_t *ipaddr_opt = _malloc(sizeof(*ipaddr_opt));
+ memset(ipaddr_opt, 0, sizeof(*ipaddr_opt));
+ ipaddr_opt->opt.id = CI_ADDR;
+ ipaddr_opt->opt.len = 6;
+ ipaddr_opt->ppp = ipcp->ppp;
return &ipaddr_opt->opt;
}
static void ipaddr_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt)
{
- struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt);
+ struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
- if (ipaddr_opt->ip)
- ipdb_put_ipv4(ipcp->ppp, ipaddr_opt->ip);
+ if (ipcp->ppp->ipv4)
+ ipdb_put_ipv4(ipcp->ppp, ipcp->ppp->ipv4);
_free(ipaddr_opt);
}
@@ -71,8 +71,8 @@ static int check_exists(struct ppp_t *self_ppp, in_addr_t addr)
pthread_rwlock_rdlock(&ppp_lock);
list_for_each_entry(ppp, &ppp_list, entry) {
- if (!ppp->terminating && ppp->peer_ipaddr == addr && ppp != self_ppp) {
- log_ppp_warn("ppp:ipcp: requested IP already assigned to %s\n", ppp->ifname);
+ if (!ppp->terminating && ppp->ipv4 && ppp->ipv4->peer_addr == addr && ppp != self_ppp) {
+ log_ppp_warn("ppp: requested IPv4 address already assigned to %s\n", ppp->ifname);
r = 1;
break;
}
@@ -84,74 +84,63 @@ static int check_exists(struct ppp_t *self_ppp, in_addr_t addr)
static int ipaddr_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
{
- struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt);
- struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+ struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
+ struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr;
- if (!ipaddr_opt->ip) {
- ipaddr_opt->ip = ipdb_get_ipv4(ipcp->ppp);
- if (!ipaddr_opt->ip) {
- log_ppp_warn("ppp:ipcp: no free IP address\n");
+ if (!ipcp->ppp->ipv4) {
+ ipcp->ppp->ipv4 = ipdb_get_ipv4(ipcp->ppp);
+ if (!ipcp->ppp->ipv4) {
+ log_ppp_warn("ppp: no free IPv4 address\n");
return -1;
}
}
- if (iprange_tunnel_check(ipaddr_opt->ip->peer_addr)) {
+ if (iprange_tunnel_check(ipcp->ppp->ipv4->peer_addr)) {
log_ppp_warn("ppp:ipcp: to avoid kernel soft lockup requested IP cannot be assigned (%i.%i.%i.%i)\n",
- ipaddr_opt->ip->peer_addr&0xff,
- (ipaddr_opt->ip->peer_addr >> 8)&0xff,
- (ipaddr_opt->ip->peer_addr >> 16)&0xff,
- (ipaddr_opt->ip->peer_addr >> 24)&0xff);
+ ipcp->ppp->ipv4->peer_addr&0xff,
+ (ipcp->ppp->ipv4->peer_addr >> 8)&0xff,
+ (ipcp->ppp->ipv4->peer_addr >> 16)&0xff,
+ (ipcp->ppp->ipv4->peer_addr >> 24)&0xff);
return -1;
}
- if (conf_check_exists && check_exists(ipcp->ppp, ipaddr_opt->ip->peer_addr))
+ if (conf_check_exists && check_exists(ipcp->ppp, ipcp->ppp->ipv4->peer_addr))
return -1;
- ipcp->ppp->ipaddr = ipaddr_opt->ip->addr;
- ipcp->ppp->peer_ipaddr = ipaddr_opt->ip->peer_addr;
-
- opt32->hdr.id=CI_ADDR;
- opt32->hdr.len=6;
- opt32->val=ipaddr_opt->ip->addr;
+ opt32->hdr.id = CI_ADDR;
+ opt32->hdr.len = 6;
+ opt32->val = ipcp->ppp->ipv4->addr;
return 6;
}
static int ipaddr_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
{
- struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt);
- struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
- opt32->hdr.id=CI_ADDR;
- opt32->hdr.len=6;
- opt32->val=ipaddr_opt->ip->peer_addr;
+ struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
+ struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr;
+ opt32->hdr.id = CI_ADDR;
+ opt32->hdr.len = 6;
+ opt32->val = ipcp->ppp->ipv4->peer_addr;
return 6;
}
static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
{
- struct ipaddr_option_t *ipaddr_opt = container_of(opt,typeof(*ipaddr_opt), opt);
- struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t*)ptr;
+ struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
+ struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr;
if (opt32->hdr.len != 6)
return IPCP_OPT_REJ;
- if (ipaddr_opt->ip->peer_addr == opt32->val) {
- //ipcp->ppp->ipaddr = ipaddr_opt->ip->addr;
- //ipcp->ppp->peer_ipaddr = ipaddr_opt->ip->peer_addr;
+ if (ipcp->ppp->ipv4->peer_addr == opt32->val) {
ipcp->delay_ack = ccp_ipcp_started(ipcp->ppp);
return IPCP_OPT_ACK;
}
- /*if (!ipaddr_opt->peer_addr) {
- ipaddr_opt->peer_addr = opt32->val;
- goto ack;
- }*/
-
return IPCP_OPT_NAK;
}
static void if_up(struct ppp_t *ppp)
{
- struct ipaddr_option_t *ipaddr_opt = container_of(ipcp_find_option(ppp, &ipaddr_opt_hnd), typeof(*ipaddr_opt), opt);
struct ifreq ifr;
struct sockaddr_in addr;
struct npioctl np;
@@ -162,13 +151,13 @@ static void if_up(struct ppp_t *ppp)
strcpy(ifr.ifr_name, ppp->ifname);
addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = ipaddr_opt->ip->addr;
+ addr.sin_addr.s_addr = ppp->ipv4->addr;
memcpy(&ifr.ifr_addr,&addr,sizeof(addr));
if (ioctl(sock_fd, SIOCSIFADDR, &ifr))
log_ppp_error("ipcp: failed to set PA address: %s\n", strerror(errno));
- addr.sin_addr.s_addr = ipaddr_opt->ip->peer_addr;
+ addr.sin_addr.s_addr = ppp->ipv4->peer_addr;
memcpy(&ifr.ifr_dstaddr,&addr,sizeof(addr));
if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr))
@@ -205,8 +194,8 @@ static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t
if (ptr)
in.s_addr = opt32->val;
- else if (ipaddr_opt->ip)
- in.s_addr = ipaddr_opt->ip->addr;
+ else if (ipaddr_opt->ppp->ipv4)
+ in.s_addr = ipaddr_opt->ppp->ipv4->addr;
print("<addr %s>",inet_ntoa(in));
}
@@ -229,3 +218,4 @@ static void ipaddr_opt_init()
}
DEFINE_INIT(4, ipaddr_opt_init);
+
diff --git a/accel-pppd/ppp/ipv6_nd.c b/accel-pppd/ppp/ipv6_nd.c
index bec0ea3c..e0ec842e 100644
--- a/accel-pppd/ppp/ipv6_nd.c
+++ b/accel-pppd/ppp/ipv6_nd.c
@@ -7,18 +7,50 @@
#include <pthread.h>
#include <netinet/in.h>
#include <netinet/icmp6.h>
+#include <arpa/inet.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include "log.h"
#include "ppp.h"
#include "events.h"
+#include "mempool.h"
+#include "ipdb.h"
#include "memdebug.h"
+#define MAX_DNS_COUNT 3
+
static int conf_init_ra = 3;
static int conf_init_ra_interval = 1;
static int conf_ra_interval = 60;
+static int conf_router_lifetime = 300;
+static int conf_rdnss_lifetime = 300;
+static struct in6_addr conf_dns[MAX_DNS_COUNT];
+static int conf_dns_count;
+
+#undef ND_OPT_ROUTE_INFORMATION
+#define ND_OPT_ROUTE_INFORMATION 24
+struct nd_opt_route_info_local /* route information */
+{
+ uint8_t nd_opt_ri_type;
+ uint8_t nd_opt_ri_len;
+ uint8_t nd_opt_ri_prefix_len;
+ uint8_t nd_opt_ri_flags_reserved;
+ uint32_t nd_opt_ri_lifetime;
+ struct in6_addr nd_opt_ri_prefix;
+};
+
+#undef ND_OPT_RDNSS_INFORMATION
+#define ND_OPT_RDNSS_INFORMATION 25
+struct nd_opt_rdnss_info_local
+{
+ uint8_t nd_opt_rdnssi_type;
+ uint8_t nd_opt_rdnssi_len;
+ uint16_t nd_opt_rdnssi_pref_flag_reserved;
+ uint32_t nd_opt_rdnssi_lifetime;
+ struct in6_addr nd_opt_rdnssi[0];
+};
struct ipv6_nd_handler_t
{
@@ -32,84 +64,112 @@ struct ipv6_nd_handler_t
static void *pd_key;
#define BUF_SIZE 1024
+static mempool_t buf_pool;
-static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h)
+static void ipv6_nd_send_ra(struct ipv6_nd_handler_t *h, struct sockaddr_in6 *addr)
{
- void *buf = _malloc(BUF_SIZE);
+ void *buf = mempool_alloc(buf_pool), *endptr;
struct nd_router_advert *adv = buf;
struct nd_opt_prefix_info *pinfo;
- //struct nd_opt_route_info *rinfo;
- //struct nd_opt_rdnss_info_local *rdnssinfo;
+ struct nd_opt_route_info_local *rinfo;
+ struct nd_opt_rdnss_info_local *rdnssinfo;
+ struct in6_addr *rdnss_addr;
//struct nd_opt_mtu *mtu;
- struct sockaddr_in6 addr;
+ struct ipv6db_addr_t *a;
+ int i;
+
+ if (!buf) {
+ log_emerg("out of memory\n");
+ return;
+ }
memset(adv, 0, sizeof(*adv));
adv->nd_ra_type = ND_ROUTER_ADVERT;
adv->nd_ra_curhoplimit = 64;
- adv->nd_ra_router_lifetime = htons(1);
+ adv->nd_ra_router_lifetime = htons(conf_router_lifetime);
//adv->nd_ra_reachable = 0;
//adv->nd_ra_retransmit = 0;
pinfo = (struct nd_opt_prefix_info *)(adv + 1);
- memset(pinfo, 0, sizeof(*pinfo));
- pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
- pinfo->nd_opt_pi_len = 4;
- pinfo->nd_opt_pi_prefix_len = h->ppp->ipv6_prefix_len;
- pinfo->nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO;
- pinfo->nd_opt_pi_valid_time = 0xffffffff;
- pinfo->nd_opt_pi_preferred_time = 0xffffffff;
- memcpy(&pinfo->nd_opt_pi_prefix, &h->ppp->ipv6_addr, 8);
+ list_for_each_entry(a, &h->ppp->ipv6->addr_list, entry) {
+ memset(pinfo, 0, sizeof(*pinfo));
+ pinfo->nd_opt_pi_type = ND_OPT_PREFIX_INFORMATION;
+ pinfo->nd_opt_pi_len = 4;
+ pinfo->nd_opt_pi_prefix_len = a->prefix_len;
+ pinfo->nd_opt_pi_flags_reserved = ND_OPT_PI_FLAG_ONLINK | ND_OPT_PI_FLAG_AUTO;
+ pinfo->nd_opt_pi_valid_time = 0xffffffff;
+ pinfo->nd_opt_pi_preferred_time = 0xffffffff;
+ memcpy(&pinfo->nd_opt_pi_prefix, &a->addr, 8);
+ pinfo++;
+ }
+
+ rinfo = (struct nd_opt_route_info_local *)pinfo;
+ list_for_each_entry(a, &h->ppp->ipv6->route_list, entry) {
+ memset(rinfo, 0, sizeof(*rinfo));
+ rinfo->nd_opt_ri_type = ND_OPT_ROUTE_INFORMATION;
+ rinfo->nd_opt_ri_len = 3;
+ rinfo->nd_opt_ri_prefix_len = a->prefix_len;
+ rinfo->nd_opt_ri_lifetime = 0xffffffff;
+ memcpy(&rinfo->nd_opt_ri_prefix, &a->addr, 8);
+ rinfo++;
+ }
+
+ if (conf_dns_count) {
+ rdnssinfo = (struct nd_opt_rdnss_info_local *)rinfo;
+ memset(rdnssinfo, 0, sizeof(*rdnssinfo));
+ rdnssinfo->nd_opt_rdnssi_type = ND_OPT_RDNSS_INFORMATION;
+ rdnssinfo->nd_opt_rdnssi_len = 1 + 2 * conf_dns_count;
+ rdnssinfo->nd_opt_rdnssi_lifetime = htonl(conf_rdnss_lifetime);
+ rdnss_addr = (struct in6_addr *)rdnssinfo->nd_opt_rdnssi;
+ for (i = 0; i < conf_dns_count; i++) {
+ memcpy(rdnss_addr, &conf_dns[i], sizeof(*rdnss_addr));
+ rdnss_addr++;
+ }
+ } else
+ rdnss_addr = (struct in6_addr *)rinfo;
+
+ endptr = rdnss_addr;
- memset(&addr, 0, sizeof(addr));
- addr.sin6_family = AF_INET6;
- addr.sin6_addr.s6_addr32[0] = htonl(0xff020000);
- addr.sin6_addr.s6_addr32[3] = htonl(0x1);
- addr.sin6_scope_id = h->ppp->ifindex;
- sendto(h->hnd.fd, buf, (void *)(pinfo + 1) - buf, 0, (struct sockaddr *)&addr, sizeof(addr));
+ sendto(h->hnd.fd, buf, endptr - buf, 0, (struct sockaddr *)addr, sizeof(*addr));
- _free(buf);
+ mempool_free(buf);
}
static void send_ra_timer(struct triton_timer_t *t)
{
struct ipv6_nd_handler_t *h = container_of(t, typeof(*h), timer);
+ struct sockaddr_in6 addr;
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin6_family = AF_INET6;
+ addr.sin6_addr.s6_addr32[0] = htonl(0xff020000);
+ addr.sin6_addr.s6_addr32[3] = htonl(0x1);
+ addr.sin6_scope_id = h->ppp->ifindex;
if (h->ra_sent++ == conf_init_ra) {
h->timer.period = conf_ra_interval * 1000;
triton_timer_mod(t, 0);
}
- ipv6_nd_send_ra(h);
+ ipv6_nd_send_ra(h, &addr);
}
static int ipv6_nd_read(struct triton_md_handler_t *_h)
{
struct ipv6_nd_handler_t *h = container_of(_h, typeof(*h), hnd);
- struct msghdr mhdr;
- int chdr_len;
- struct iovec iov;
- struct cmsghdr *chdr, *cmsg;
- struct in6_pktinfo *pkt_info;
- struct icmp6_hdr *icmph;
- void *buf;
+ struct icmp6_hdr *icmph = mempool_alloc(buf_pool);
int n;
+ struct sockaddr_in6 addr;
+ socklen_t addr_len = sizeof(addr);
- chdr_len = CMSG_SPACE(sizeof(struct in6_pktinfo)) + CMSG_SPACE(sizeof(int));
- chdr = _malloc(chdr_len);
- buf = _malloc(BUF_SIZE);
-
- iov.iov_len = BUF_SIZE;
- iov.iov_base = buf;
-
- memset(&mhdr, 0, sizeof(mhdr));
- mhdr.msg_iov = &iov;
- mhdr.msg_iovlen = 1;
- mhdr.msg_control = chdr;
- mhdr.msg_controllen = chdr_len;
+ if (!icmph) {
+ log_emerg("out of memory\n");
+ return 0;
+ }
while (1) {
- n = recvmsg(h->hnd.fd, &mhdr, 0);
+ n = recvfrom(h->hnd.fd, icmph, BUF_SIZE, 0, &addr, &addr_len);
if (n == -1) {
if (errno == EAGAIN)
break;
@@ -117,50 +177,30 @@ static int ipv6_nd_read(struct triton_md_handler_t *_h)
continue;
}
- pkt_info = NULL;
- for (cmsg = CMSG_FIRSTHDR(&mhdr); cmsg != NULL; cmsg = CMSG_NXTHDR(&mhdr, cmsg)) {
- if (cmsg->cmsg_level == IPPROTO_IPV6 &&
- cmsg->cmsg_type == IPV6_PKTINFO) {
- if (cmsg->cmsg_len != CMSG_LEN(sizeof(*pkt_info)))
- log_ppp_warn("ipv6_nd: received invalid IPV6_PKTINFO\n");
- else
- pkt_info = (struct in6_pktinfo *)CMSG_DATA(cmsg);
- break;
- }
- }
-
- if (!pkt_info) {
- log_ppp_warn("ipv6_nd: no IPV6_PKTINFO\n");
- continue;
- }
-
if (n < sizeof(*icmph)) {
log_ppp_warn("ipv6_nd: received short icmp packet (%i)\n", n);
continue;
}
- icmph = buf;
-
if (icmph->icmp6_type != ND_ROUTER_SOLICIT) {
log_ppp_warn("ipv6_nd: received unexcpected icmp packet (%i)\n", icmph->icmp6_type);
continue;
}
- /*if (!IN6_IS_ADDR_LINKLOCAL(&pkt_info->ipi6_addr)) {
+ if (!IN6_IS_ADDR_LINKLOCAL(&addr.sin6_addr)) {
log_ppp_warn("ipv6_nd: received icmp packet from non link-local address\n");
continue;
- }*/
+ }
- /*if (*(uint64_t *)(pkt_info->ipi6_addr.s6_addr + 8) != *(uint64_t *)(h->ppp->ipv6_addr.s6_addr + 8)) {
+ /*if (*(uint64_t *)(addr.sin6_addr.s6_addr + 8) != *(uint64_t *)(h->ppp->ipv6_addr.s6_addr + 8)) {
log_ppp_warn("ipv6_nd: received icmp packet from unknown address\n");
continue;
}*/
- ipv6_nd_send_ra(h);
+ ipv6_nd_send_ra(h, &addr);
}
- _free(chdr);
- _free(buf);
+ mempool_free(icmph);
return 0;
}
@@ -192,12 +232,6 @@ int ppp_ipv6_nd_start(struct ppp_t *ppp, uint64_t intf_id)
goto out_err;
}
- val = 1;
- if (setsockopt(sock, IPPROTO_IPV6, IPV6_RECVPKTINFO, &val, sizeof(val))) {
- log_ppp_error("ipv6_nd: setsockopt(IPV6_PKTINFO): %s\n", strerror(errno));
- goto out_err;
- }
-
val = 2;
if (setsockopt(sock, IPPROTO_RAW, IPV6_CHECKSUM, &val, sizeof(val))) {
log_ppp_error("ipv6_nd: setsockopt(IPV6_CHECKSUM): %s\n", strerror(errno));
@@ -299,10 +333,35 @@ static void ev_ppp_finishing(struct ppp_t *ppp)
_free(h);
}
+static void load_config(void)
+{
+ struct conf_sect_t *s = conf_get_section("dnsv6");
+ struct conf_option_t *opt;
+
+ if (!s)
+ return;
+
+ conf_dns_count = 0;
+
+ list_for_each_entry(opt, &s->items, entry) {
+ if (inet_pton(AF_INET6, opt->name, &conf_dns[conf_dns_count]) == 0) {
+ log_error("dnsv6: faild to parse '%s'\n", opt->name);
+ continue;
+ }
+ if (++conf_dns_count == MAX_DNS_COUNT)
+ break;
+ }
+}
+
static void init(void)
{
+ buf_pool = mempool_create(BUF_SIZE);
+
+ load_config();
+
+ triton_event_register_handler(EV_CONFIG_RELOAD, (triton_event_func)load_config);
triton_event_register_handler(EV_PPP_STARTED, (triton_event_func)ev_ppp_started);
triton_event_register_handler(EV_PPP_FINISHING, (triton_event_func)ev_ppp_finishing);
}
-DEFINE_INIT(0, init);
+DEFINE_INIT(5, init);
diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c
index b55d3fff..9a9b9e37 100644
--- a/accel-pppd/ppp/ipv6cp_opt_intfid.c
+++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c
@@ -45,7 +45,6 @@ struct ipaddr_option_t
{
struct ipv6cp_option_t opt;
uint64_t intf_id;
- struct ipv6db_item_t *ip;
int started:1;
};
@@ -87,25 +86,33 @@ static void ipaddr_free(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt
_free(ipaddr_opt);
}
-static int check_exists(struct ppp_t *self_ppp, struct in6_addr *addr)
+static int check_exists(struct ppp_t *self_ppp)
{
struct ppp_t *ppp;
+ struct ipv6db_addr_t *a1, *a2;
int r = 0;
pthread_rwlock_rdlock(&ppp_lock);
list_for_each_entry(ppp, &ppp_list, entry) {
if (ppp->terminating)
continue;
+ if (!ppp->ipv6)
+ continue;
if (ppp == self_ppp)
continue;
- if (addr->s6_addr32[0] == ppp->ipv6_addr.s6_addr32[0] &&
- addr->s6_addr32[1] == ppp->ipv6_addr.s6_addr32[1]) {
- log_ppp_warn("ppp:ipv6cp: requested IP already assigned to %s\n", ppp->ifname);
- r = 1;
- break;
+ list_for_each_entry(a1, &ppp->ipv6->addr_list, entry) {
+ list_for_each_entry(a2, &self_ppp->ipv6->addr_list, entry) {
+ if (a1->addr.s6_addr32[0] == a2->addr.s6_addr32[0] &&
+ a1->addr.s6_addr32[1] == a2->addr.s6_addr32[1]) {
+ log_ppp_warn("ppp: requested IPv6 address already assigned to %s\n", ppp->ifname);
+ r = 1;
+ goto out;
+ }
+ }
}
}
+out:
pthread_rwlock_unlock(&ppp_lock);
return r;
@@ -116,20 +123,17 @@ static int ipaddr_send_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t *)ptr;
- if (!ipaddr_opt->ip) {
- ipaddr_opt->ip = ipdb_get_ipv6(ipv6cp->ppp);
- if (!ipaddr_opt->ip) {
- log_ppp_warn("ppp:ipv6cp: no free IP address\n");
+ if (!ipv6cp->ppp->ipv6) {
+ ipv6cp->ppp->ipv6 = ipdb_get_ipv6(ipv6cp->ppp);
+ if (!ipv6cp->ppp->ipv6) {
+ log_ppp_warn("ppp: no free IPv6 address\n");
return -1;
}
}
- if (conf_check_exists && check_exists(ipv6cp->ppp, &ipaddr_opt->ip->addr))
+ if (conf_check_exists && check_exists(ipv6cp->ppp))
return -1;
- ipv6cp->ppp->ipv6_addr = ipaddr_opt->ip->addr;
- ipv6cp->ppp->ipv6_prefix_len = ipaddr_opt->ip->prefix_len;
-
opt64->hdr.id = CI_INTFID;
opt64->hdr.len = 10;
opt64->val = ipaddr_opt->intf_id;
@@ -142,7 +146,7 @@ static int ipaddr_send_conf_nak(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t *)ptr;
opt64->hdr.id = CI_INTFID;
opt64->hdr.len = 10;
- opt64->val = *(uint64_t *)(&ipaddr_opt->ip->addr.s6_addr32[2]);
+ opt64->val = ipv6cp->ppp->ipv6->intf_id;
return 10;
}
@@ -151,11 +155,12 @@ static int ipaddr_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
struct ipv6cp_opt64_t *opt64 = (struct ipv6cp_opt64_t* )ptr;
struct in6_ifreq ifr6;
+ struct ipv6db_addr_t *a;
if (opt64->hdr.len != 10)
return IPV6CP_OPT_REJ;
- if (*(uint64_t *)(&ipaddr_opt->ip->addr.s6_addr32[2]) == opt64->val)
+ if (ipv6cp->ppp->ipv6->intf_id == opt64->val)
goto ack;
return IPV6CP_OPT_NAK;
@@ -188,11 +193,13 @@ ack:
return IPV6CP_OPT_REJ;
}
- memcpy(ifr6.ifr6_addr.s6_addr, ipaddr_opt->ip->addr.s6_addr, 8);
+ list_for_each_entry(a, &ipv6cp->ppp->ipv6->addr_list, entry) {
+ memcpy(ifr6.ifr6_addr.s6_addr, a->addr.s6_addr, 8);
- if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) {
- log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno));
- return IPV6CP_OPT_REJ;
+ if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) {
+ log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno));
+ return IPV6CP_OPT_REJ;
+ }
}
if (ppp_ipv6_nd_start(ipv6cp->ppp, ipaddr_opt->intf_id))
diff --git a/accel-pppd/ppp/ppp.h b/accel-pppd/ppp/ppp.h
index 4708578e..f95893ab 100644
--- a/accel-pppd/ppp/ppp.h
+++ b/accel-pppd/ppp/ppp.h
@@ -62,6 +62,9 @@
struct ppp_t;
+struct ipv4db_item_t;
+struct ipv6db_item_t;
+
struct ppp_ctrl_t
{
struct triton_context_t *ctx;
@@ -100,10 +103,8 @@ struct ppp_t
time_t start_time;
time_t stop_time;
char *username;
- in_addr_t ipaddr;
- in_addr_t peer_ipaddr;
- struct in6_addr ipv6_addr;
- int ipv6_prefix_len;
+ struct ipv4db_item_t *ipv4;
+ struct ipv6db_item_t *ipv6;
struct ppp_ctrl_t *ctrl;
diff --git a/accel-pppd/radius/radius.c b/accel-pppd/radius/radius.c
index ae5948b0..4200d621 100644
--- a/accel-pppd/radius/radius.c
+++ b/accel-pppd/radius/radius.c
@@ -174,7 +174,7 @@ static struct ipv4db_item_t *get_ipv4(struct ppp_t *ppp)
static struct ipv6db_item_t *get_ipv6(struct ppp_t *ppp)
{
- struct radius_pd_t *rpd = find_pd(ppp);
+ //struct radius_pd_t *rpd = find_pd(ppp);
//if (memcmp(&rpd->ipv6_addr.peer_addr, &in6addr_any, sizeof(in6addr_any)))
// return &rpd->ipv6_addr;
@@ -302,7 +302,7 @@ struct radius_pd_t *rad_find_session(const char *sessionid, const char *username
continue;
if (port_id >= 0 && port_id != rpd->ppp->unit_idx)
continue;
- if (ipaddr && ipaddr != rpd->ppp->peer_ipaddr)
+ if (ipaddr && rpd->ppp->ipv4 && ipaddr != rpd->ppp->ipv4->peer_addr)
continue;
if (csid && rpd->ppp->ctrl->calling_station_id && strcmp(csid, rpd->ppp->ctrl->calling_station_id))
continue;
diff --git a/accel-pppd/radius/req.c b/accel-pppd/radius/req.c
index b45a601b..462e656b 100644
--- a/accel-pppd/radius/req.c
+++ b/accel-pppd/radius/req.c
@@ -130,8 +130,10 @@ int rad_req_acct_fill(struct rad_req_t *req)
if (rad_packet_add_int(req->pack, NULL, "Acct-Delay-Time", 0))
return -1;
}
- if (rad_packet_add_ipaddr(req->pack, NULL, "Framed-IP-Address", req->rpd->ppp->peer_ipaddr))
- return -1;
+ if (req->rpd->ppp->ipv4) {
+ if (rad_packet_add_ipaddr(req->pack, NULL, "Framed-IP-Address", req->rpd->ppp->ipv4->peer_addr))
+ return -1;
+ }
return 0;
}