summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp
diff options
context:
space:
mode:
authorKozlov Dmitry <xeb@mail.ru>2012-06-05 14:24:31 +0400
committerKozlov Dmitry <xeb@mail.ru>2012-06-05 14:27:57 +0400
commitfa315a7a7584f6f4954888c010e3cc84c2b33330 (patch)
tree778396449f9e19c52d8b83e7fabdb1c37706e16f /accel-pppd/ppp
parent6f01783f2b67cd0b82805240f2aeea9a39606d65 (diff)
downloadaccel-ppp-fa315a7a7584f6f4954888c010e3cc84c2b33330.tar.gz
accel-ppp-fa315a7a7584f6f4954888c010e3cc84c2b33330.zip
ppp: implemented unit cache
If enabled accel-pppd will not destroy interface immediately after corresponding session is terminated, instead interface will be brought down and placed to cache for later use for new sessions. It should reduce kernel interface creation/deletion rate lack and increase responsibility of daemon
Diffstat (limited to 'accel-pppd/ppp')
-rw-r--r--accel-pppd/ppp/ipcp_opt_ipaddr.c29
-rw-r--r--accel-pppd/ppp/ipv6cp_opt_intfid.c81
-rw-r--r--accel-pppd/ppp/ppp.c144
-rw-r--r--accel-pppd/ppp/ppp.h3
-rw-r--r--accel-pppd/ppp/ppp_auth.c12
-rw-r--r--accel-pppd/ppp/ppp_ifcfg.c182
-rw-r--r--accel-pppd/ppp/ppp_ipcp.c6
-rw-r--r--accel-pppd/ppp/ppp_ipv6cp.c6
8 files changed, 286 insertions, 177 deletions
diff --git a/accel-pppd/ppp/ipcp_opt_ipaddr.c b/accel-pppd/ppp/ipcp_opt_ipaddr.c
index 14557440..e965f5c2 100644
--- a/accel-pppd/ppp/ipcp_opt_ipaddr.c
+++ b/accel-pppd/ppp/ipcp_opt_ipaddr.c
@@ -58,8 +58,10 @@ 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);
- if (ipcp->ppp->ipv4)
+ if (ipcp->ppp->ipv4) {
ipdb_put_ipv4(ipcp->ppp, ipcp->ppp->ipv4);
+ ipcp->ppp->ipv4 = NULL;
+ }
_free(ipaddr_opt);
}
@@ -137,8 +139,6 @@ static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
{
struct ipaddr_option_t *ipaddr_opt = container_of(opt, typeof(*ipaddr_opt), opt);
struct ipcp_opt32_t *opt32 = (struct ipcp_opt32_t *)ptr;
- struct ifreq ifr;
- struct sockaddr_in addr;
int r;
if (!ipcp->ppp->ipv4) {
@@ -152,31 +152,10 @@ static int ipaddr_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *o
if (ipcp->ppp->ipv4->peer_addr == opt32->val) {
ipcp->delay_ack = ccp_ipcp_started(ipcp->ppp);
- goto ack;
+ return IPCP_OPT_ACK;
}
return IPCP_OPT_NAK;
-
-ack:
- memset(&ifr, 0, sizeof(ifr));
- memset(&addr, 0, sizeof(addr));
-
- strcpy(ifr.ifr_name, ipcp->ppp->ifname);
-
- addr.sin_family = AF_INET;
- addr.sin_addr.s_addr = ipcp->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 = ipcp->ppp->ipv4->peer_addr;
- memcpy(&ifr.ifr_dstaddr,&addr,sizeof(addr));
-
- if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr))
- log_ppp_error("ipcp: failed to set remote PA address: %s\n", strerror(errno));
-
- return IPCP_OPT_ACK;
}
static void ipaddr_print(void (*print)(const char *fmt,...),struct ipcp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pppd/ppp/ipv6cp_opt_intfid.c b/accel-pppd/ppp/ipv6cp_opt_intfid.c
index 0d3d7513..9a2ddee0 100644
--- a/accel-pppd/ppp/ipv6cp_opt_intfid.c
+++ b/accel-pppd/ppp/ipv6cp_opt_intfid.c
@@ -30,13 +30,6 @@ static int conf_peer_intf_id = INTF_ID_FIXED;
static uint64_t conf_peer_intf_id_val = 2;
static int conf_accept_peer_intf_id;
-// from /usr/include/linux/ipv6.h
-struct in6_ifreq {
- struct in6_addr ifr6_addr;
- __u32 ifr6_prefixlen;
- int ifr6_ifindex;
-};
-
static struct ipv6cp_option_t *ipaddr_init(struct ppp_ipv6cp_t *ipv6cp);
static void ipaddr_free(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt);
static int ipaddr_send_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt, uint8_t *ptr);
@@ -79,8 +72,10 @@ static void ipaddr_free(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt
{
struct ipaddr_option_t *ipaddr_opt=container_of(opt,typeof(*ipaddr_opt),opt);
- if (ipv6cp->ppp->ipv6)
+ if (ipv6cp->ppp->ipv6) {
ipdb_put_ipv6(ipv6cp->ppp, ipv6cp->ppp->ipv6);
+ ipv6cp->ppp->ipv6 = NULL;
+ }
_free(ipaddr_opt);
}
@@ -211,39 +206,10 @@ static int ipaddr_send_conf_nak(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
return 10;
}
-static void devconf(struct ppp_t *ppp, const char *attr, const char *val)
-{
- int fd;
- char fname[PATH_MAX];
-
- sprintf(fname, "/proc/sys/net/ipv6/conf/%s/%s", ppp->ifname, attr);
- fd = open(fname, O_WRONLY);
- if (!fd) {
- log_ppp_error("ppp:ipv6cp: failed to open '%s': %s\n", fname, strerror(errno));
- return;
- }
-
- write(fd, val, strlen(val));
-
- close(fd);
-}
-
-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 int ipaddr_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_option_t *opt, uint8_t *ptr)
{
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;
int r;
if (opt64->hdr.len != 10)
@@ -265,48 +231,11 @@ static int ipaddr_recv_conf_req(struct ppp_ipv6cp_t *ipv6cp, struct ipv6cp_optio
if (opt64->val && ipv6cp->ppp->ipv6->peer_intf_id == opt64->val && opt64->val != ipv6cp->ppp->ipv6->intf_id) {
ipv6cp->delay_ack = ccp_ipcp_started(ipv6cp->ppp);
- goto ack;
+ ipaddr_opt->started = 1;
+ return IPV6CP_OPT_ACK;
}
return IPV6CP_OPT_NAK;
-
-ack:
- if (ipaddr_opt->started)
- return IPV6CP_OPT_ACK;
-
- ipaddr_opt->started = 1;
-
- devconf(ipv6cp->ppp, "accept_ra", "0");
- devconf(ipv6cp->ppp, "autoconf", "0");
- devconf(ipv6cp->ppp, "forwarding", "1");
-
- memset(&ifr6, 0, sizeof(ifr6));
- ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80);
- *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ipv6cp->ppp->ipv6->intf_id;
- ifr6.ifr6_prefixlen = 64;
- ifr6.ifr6_ifindex = ipv6cp->ppp->ifindex;
-
- if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) {
- log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno));
- return IPV6CP_OPT_REJ;
- }
-
- list_for_each_entry(a, &ipv6cp->ppp->ipv6->addr_list, entry) {
- if (a->prefix_len == 128)
- continue;
-
- build_addr(a, ipv6cp->ppp->ipv6->intf_id, &ifr6.ifr6_addr);
- ifr6.ifr6_prefixlen = a->prefix_len;
-
- if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6)) {
- log_ppp_error("ppp:ipv6cp: ioctl(SIOCSIFADDR): %s\n", strerror(errno));
- return IPV6CP_OPT_REJ;
- }
-
-
- }
-
- return IPV6CP_OPT_ACK;
}
static void ipaddr_print(void (*print)(const char *fmt,...), struct ipv6cp_option_t *opt, uint8_t *ptr)
diff --git a/accel-pppd/ppp/ppp.c b/accel-pppd/ppp/ppp.c
index 4f3beb9e..814240cd 100644
--- a/accel-pppd/ppp/ppp.c
+++ b/accel-pppd/ppp/ppp.c
@@ -5,10 +5,11 @@
#include <stdint.h>
#include <string.h>
#include <errno.h>
-#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <features.h>
#include <signal.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
#include "linux_ppp.h"
#include "crypto.h"
@@ -18,6 +19,7 @@
#include "events.h"
#include "ppp.h"
#include "ppp_fsm.h"
+#include "ipdb.h"
#include "log.h"
#include "spinlock.h"
#include "mempool.h"
@@ -27,6 +29,7 @@
int __export conf_ppp_verbose;
int conf_sid_ucase;
int conf_single_session = -1;
+int conf_unit_cache = 0;
pthread_rwlock_t __export ppp_lock = PTHREAD_RWLOCK_INITIALIZER;
__export LIST_HEAD(ppp_list);
@@ -55,6 +58,18 @@ struct layer_node_t
struct list_head items;
};
+struct pppunit_cache
+{
+ struct list_head entry;
+ int fd;
+ int unit_idx;
+};
+
+static pthread_mutex_t uc_lock = PTHREAD_MUTEX_INITIALIZER;
+static LIST_HEAD(uc_list);
+static int uc_size;
+static mempool_t uc_pool;
+
static int ppp_chan_read(struct triton_md_handler_t*);
static int ppp_unit_read(struct triton_md_handler_t*);
static void init_layers(struct ppp_t *);
@@ -68,6 +83,9 @@ void __export ppp_init(struct ppp_t *ppp)
INIT_LIST_HEAD(&ppp->chan_handlers);
INIT_LIST_HEAD(&ppp->unit_handlers);
INIT_LIST_HEAD(&ppp->pd_list);
+ ppp->fd = -1;
+ ppp->chan_fd = -1;
+ ppp->unit_fd = -1;
}
static void generate_sessionid(struct ppp_t *ppp)
@@ -91,6 +109,7 @@ static void generate_sessionid(struct ppp_t *ppp)
int __export establish_ppp(struct ppp_t *ppp)
{
struct ifreq ifr;
+ struct pppunit_cache *uc = NULL;
/* Open an instance of /dev/ppp and connect the channel to it */
if (ioctl(ppp->fd, PPPIOCGCHAN, &ppp->chan_idx) == -1) {
@@ -111,18 +130,39 @@ int __export establish_ppp(struct ppp_t *ppp)
goto exit_close_chan;
}
- ppp->unit_fd = open("/dev/ppp", O_RDWR);
- if (ppp->unit_fd < 0) {
- log_ppp_error("open(unit) /dev/ppp: %s\n", strerror(errno));
- goto exit_close_chan;
+ if (uc_size) {
+ pthread_mutex_lock(&uc_lock);
+ if (!list_empty(&uc_list)) {
+ uc = list_entry(uc_list.next, typeof(*uc), entry);
+ list_del(&uc->entry);
+ --uc_size;
+ }
+ pthread_mutex_unlock(&uc_lock);
}
-
- fcntl(ppp->unit_fd, F_SETFD, fcntl(ppp->unit_fd, F_GETFD) | FD_CLOEXEC);
- ppp->unit_idx = -1;
- if (ioctl(ppp->unit_fd, PPPIOCNEWUNIT, &ppp->unit_idx) < 0) {
- log_ppp_error("ioctl(PPPIOCNEWUNIT): %s\n", strerror(errno));
- goto exit_close_unit;
+ if (uc) {
+ ppp->unit_fd = uc->fd;
+ ppp->unit_idx = uc->unit_idx;
+ mempool_free(uc);
+ } else {
+ ppp->unit_fd = open("/dev/ppp", O_RDWR);
+ if (ppp->unit_fd < 0) {
+ log_ppp_error("open(unit) /dev/ppp: %s\n", strerror(errno));
+ goto exit_close_chan;
+ }
+
+ fcntl(ppp->unit_fd, F_SETFD, fcntl(ppp->unit_fd, F_GETFD) | FD_CLOEXEC);
+
+ ppp->unit_idx = -1;
+ if (ioctl(ppp->unit_fd, PPPIOCNEWUNIT, &ppp->unit_idx) < 0) {
+ log_ppp_error("ioctl(PPPIOCNEWUNIT): %s\n", strerror(errno));
+ goto exit_close_unit;
+ }
+
+ if (fcntl(ppp->unit_fd, F_SETFL, O_NONBLOCK)) {
+ log_ppp_error("ppp: cann't to set nonblocking mode: %s\n", strerror(errno));
+ goto exit_close_unit;
+ }
}
if (ioctl(ppp->chan_fd, PPPIOCCONNECT, &ppp->unit_idx) < 0) {
@@ -135,11 +175,6 @@ int __export establish_ppp(struct ppp_t *ppp)
goto exit_close_unit;
}
- if (fcntl(ppp->unit_fd, F_SETFL, O_NONBLOCK)) {
- log_ppp_error("ppp: cann't to set nonblocking mode: %s\n", strerror(errno));
- goto exit_close_unit;
- }
-
ppp->start_time = time(NULL);
generate_sessionid(ppp);
sprintf(ppp->ifname, "ppp%i", ppp->unit_idx);
@@ -202,6 +237,8 @@ exit_close_chan:
static void destablish_ppp(struct ppp_t *ppp)
{
+ struct pppunit_cache *uc;
+
triton_event_fire(EV_PPP_PRE_FINISHED, ppp);
pthread_rwlock_wrlock(&ppp_lock);
@@ -223,7 +260,18 @@ static void destablish_ppp(struct ppp_t *ppp)
triton_md_unregister_handler(&ppp->chan_hnd);
triton_md_unregister_handler(&ppp->unit_hnd);
- close(ppp->unit_fd);
+ if (uc_size < conf_unit_cache) {
+ uc = mempool_alloc(uc_pool);
+ uc->fd = ppp->unit_fd;
+ uc->unit_idx = ppp->unit_idx;
+
+ pthread_mutex_lock(&uc_lock);
+ list_add_tail(&uc->entry, &uc_list);
+ ++uc_size;
+ pthread_mutex_unlock(&uc_lock);
+ } else
+ close(ppp->unit_fd);
+
close(ppp->chan_fd);
close(ppp->fd);
@@ -356,13 +404,15 @@ cont:
return 0;
}
- //printf("ppp_unit_read: ");
+ //printf("ppp_unit_read: %i\n", ppp->buf_size);
+ if (ppp->buf_size == 0)
+ return 0;
//print_buf(ppp->buf,ppp->buf_size);
- if (ppp->buf_size == 0) {
+ /*if (ppp->buf_size == 0) {
ppp_terminate(ppp, TERM_NAS_ERROR, 1);
return 1;
- }
+ }*/
if (ppp->buf_size < 2) {
log_ppp_error("ppp_unit_read: short read %i\n", ppp->buf_size);
@@ -406,51 +456,6 @@ void ppp_recv_proto_rej(struct ppp_t *ppp, uint16_t proto)
}
}
-static void ppp_ifup(struct ppp_t *ppp)
-{
- struct ifreq ifr;
- struct npioctl np;
-
- triton_event_fire(EV_PPP_ACCT_START, ppp);
- if (ppp->stop_time)
- return;
-
- triton_event_fire(EV_PPP_PRE_UP, ppp);
- if (ppp->stop_time)
- return;
-
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ppp->ifname);
-
- if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr))
- log_ppp_error("ppp: failed to get interface flags: %s\n", strerror(errno));
-
- ifr.ifr_flags |= IFF_UP | IFF_POINTOPOINT;
-
- if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr))
- log_ppp_error("ppp: failed to set interface flags: %s\n", strerror(errno));
-
- if (ppp->ipv4) {
- np.protocol = PPP_IP;
- np.mode = NPMODE_PASS;
-
- if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
- log_ppp_error("ppp: failed to set NP (IPv4) mode: %s\n", strerror(errno));
- }
-
- if (ppp->ipv6) {
- np.protocol = PPP_IPV6;
- np.mode = NPMODE_PASS;
-
- if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
- log_ppp_error("ppp: failed to set NP (IPv6) mode: %s\n", strerror(errno));
- }
-
- ppp->ctrl->started(ppp);
-
- triton_event_fire(EV_PPP_STARTED, ppp);
-}
-
static void __ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d)
{
struct layer_node_t *n = d->node;
@@ -553,6 +558,8 @@ void __export ppp_terminate(struct ppp_t *ppp, int cause, int hard)
log_ppp_debug("ppp_terminate\n");
+ ppp_ifdown(ppp);
+
triton_event_fire(EV_PPP_FINISHING, ppp);
if (hard) {
@@ -749,6 +756,12 @@ static void load_config(void)
conf_single_session = 1;
} else
conf_single_session = -1;
+
+ opt = conf_get_opt("ppp", "unit-cache");
+ if (opt && atoi(opt) > 0)
+ conf_unit_cache = atoi(opt);
+ else
+ conf_unit_cache = 0;
}
static void init(void)
@@ -757,6 +770,7 @@ static void init(void)
FILE *f;
buf_pool = mempool_create(PPP_MRU);
+ uc_pool = mempool_create(sizeof(struct pppunit_cache));
sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
if (sock_fd < 0) {
diff --git a/accel-pppd/ppp/ppp.h b/accel-pppd/ppp/ppp.h
index f831242f..e37c75d3 100644
--- a/accel-pppd/ppp/ppp.h
+++ b/accel-pppd/ppp/ppp.h
@@ -181,6 +181,9 @@ int ppp_unit_send(struct ppp_t *ppp, void *data, int size);
void lcp_send_proto_rej(struct ppp_t *ppp, uint16_t proto);
void ppp_recv_proto_rej(struct ppp_t *ppp, uint16_t proto);
+void ppp_ifup(struct ppp_t *ppp);
+void ppp_ifdown(struct ppp_t *ppp);
+
struct ppp_fsm_t* ppp_lcp_init(struct ppp_t *ppp);
void ppp_layer_started(struct ppp_t *ppp,struct ppp_layer_data_t*);
void ppp_layer_finished(struct ppp_t *ppp,struct ppp_layer_data_t*);
diff --git a/accel-pppd/ppp/ppp_auth.c b/accel-pppd/ppp/ppp_auth.c
index f78b6522..7603d8cf 100644
--- a/accel-pppd/ppp/ppp_auth.c
+++ b/accel-pppd/ppp/ppp_auth.c
@@ -337,16 +337,6 @@ static void __ppp_auth_started(struct ppp_t *ppp)
triton_event_fire(EV_PPP_AUTHORIZED, ppp);
}
-static void ifdown(struct ppp_t *ppp)
-{
- struct ifreq ifr;
-
- memset(&ifr, 0, sizeof(ifr));
- strcpy(ifr.ifr_name, ppp->ifname);
-
- ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
-}
-
int __export ppp_auth_successed(struct ppp_t *ppp, char *username)
{
struct ppp_t *p;
@@ -362,7 +352,7 @@ int __export ppp_auth_successed(struct ppp_t *ppp, char *username)
return -1;
} else {
if (conf_single_session == 1) {
- ifdown(p);
+ ppp_ifdown(p);
triton_context_call(p->ctrl->ctx, (triton_event_func)ppp_terminate_sec, p);
}
}
diff --git a/accel-pppd/ppp/ppp_ifcfg.c b/accel-pppd/ppp/ppp_ifcfg.c
new file mode 100644
index 00000000..f916251d
--- /dev/null
+++ b/accel-pppd/ppp/ppp_ifcfg.c
@@ -0,0 +1,182 @@
+#include <unistd.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+#include <limits.h>
+#include <arpa/inet.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include "linux_ppp.h"
+
+#include "triton.h"
+#include "events.h"
+#include "ppp.h"
+#include "ipdb.h"
+#include "log.h"
+
+// from /usr/include/linux/ipv6.h
+struct in6_ifreq {
+ struct in6_addr ifr6_addr;
+ __u32 ifr6_prefixlen;
+ int ifr6_ifindex;
+};
+
+static void devconf(struct ppp_t *ppp, const char *attr, const char *val)
+{
+ int fd;
+ char fname[PATH_MAX];
+
+ sprintf(fname, "/proc/sys/net/ipv6/conf/%s/%s", ppp->ifname, attr);
+ fd = open(fname, O_WRONLY);
+ if (!fd) {
+ log_ppp_error("ppp: failed to open '%s': %s\n", fname, strerror(errno));
+ return;
+ }
+
+ write(fd, val, strlen(val));
+
+ close(fd);
+}
+
+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);
+}
+
+void ppp_ifup(struct ppp_t *ppp)
+{
+ struct ipv6db_addr_t *a;
+ struct ifreq ifr;
+ struct in6_ifreq ifr6;
+ struct npioctl np;
+ struct sockaddr_in addr;
+
+ triton_event_fire(EV_PPP_ACCT_START, ppp);
+ if (ppp->stop_time)
+ return;
+
+ triton_event_fire(EV_PPP_PRE_UP, ppp);
+ if (ppp->stop_time)
+ return;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ppp->ifname);
+
+ if (ppp->ipv4) {
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = ppp->ipv4->addr;
+ memcpy(&ifr.ifr_addr,&addr,sizeof(addr));
+
+ if (ioctl(sock_fd, SIOCSIFADDR, &ifr))
+ log_ppp_error("ppp: failed to set IPv4 address: %s\n", strerror(errno));
+
+ addr.sin_addr.s_addr = ppp->ipv4->peer_addr;
+ memcpy(&ifr.ifr_dstaddr,&addr,sizeof(addr));
+
+ if (ioctl(sock_fd, SIOCSIFDSTADDR, &ifr))
+ log_ppp_error("ppp: failed to set peer IPv4 address: %s\n", strerror(errno));
+ }
+
+ if (ppp->ipv6) {
+ devconf(ppp, "accept_ra", "0");
+ devconf(ppp, "autoconf", "0");
+ devconf(ppp, "forwarding", "1");
+
+ memset(&ifr6, 0, sizeof(ifr6));
+ ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80);
+ *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ppp->ipv6->intf_id;
+ ifr6.ifr6_prefixlen = 64;
+ ifr6.ifr6_ifindex = ppp->ifindex;
+
+ if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6))
+ log_ppp_error("ppp: faild to set LL IPv6 address: %s\n", strerror(errno));
+
+ list_for_each_entry(a, &ppp->ipv6->addr_list, entry) {
+ if (a->prefix_len == 128)
+ continue;
+
+ build_addr(a, ppp->ipv6->intf_id, &ifr6.ifr6_addr);
+ ifr6.ifr6_prefixlen = a->prefix_len;
+
+ if (ioctl(sock6_fd, SIOCSIFADDR, &ifr6))
+ log_ppp_error("ppp: failed to add IPv6 address: %s\n", strerror(errno));
+ }
+ }
+
+ if (ioctl(sock_fd, SIOCGIFFLAGS, &ifr))
+ log_ppp_error("ppp: failed to get interface flags: %s\n", strerror(errno));
+
+ ifr.ifr_flags |= IFF_UP | IFF_POINTOPOINT;
+
+ if (ioctl(sock_fd, SIOCSIFFLAGS, &ifr))
+ log_ppp_error("ppp: failed to set interface flags: %s\n", strerror(errno));
+
+ if (ppp->ipv4) {
+ np.protocol = PPP_IP;
+ np.mode = NPMODE_PASS;
+
+ if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
+ log_ppp_error("ppp: failed to set NP (IPv4) mode: %s\n", strerror(errno));
+ }
+
+ if (ppp->ipv6) {
+ np.protocol = PPP_IPV6;
+ np.mode = NPMODE_PASS;
+
+ if (ioctl(ppp->unit_fd, PPPIOCSNPMODE, &np))
+ log_ppp_error("ppp: failed to set NP (IPv6) mode: %s\n", strerror(errno));
+ }
+
+ ppp->ctrl->started(ppp);
+
+ triton_event_fire(EV_PPP_STARTED, ppp);
+}
+
+void __export ppp_ifdown(struct ppp_t *ppp)
+{
+ struct ifreq ifr;
+ struct sockaddr_in addr;
+ struct in6_ifreq ifr6;
+ struct ipv6db_addr_t *a;
+
+ memset(&ifr, 0, sizeof(ifr));
+ strcpy(ifr.ifr_name, ppp->ifname);
+ ioctl(sock_fd, SIOCSIFFLAGS, &ifr);
+
+ if (ppp->ipv4) {
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ memcpy(&ifr.ifr_addr,&addr,sizeof(addr));
+ ioctl(sock_fd, SIOCSIFADDR, &ifr);
+ }
+
+ if (ppp->ipv6) {
+ memset(&ifr6, 0, sizeof(ifr6));
+ ifr6.ifr6_addr.s6_addr32[0] = htons(0xfe80);
+ *(uint64_t *)(ifr6.ifr6_addr.s6_addr + 8) = ppp->ipv6->intf_id;
+ ifr6.ifr6_prefixlen = 64;
+ ifr6.ifr6_ifindex = ppp->ifindex;
+
+ ioctl(sock6_fd, SIOCDIFADDR, &ifr6);
+
+ list_for_each_entry(a, &ppp->ipv6->addr_list, entry) {
+ if (a->prefix_len == 128)
+ continue;
+
+ build_addr(a, ppp->ipv6->intf_id, &ifr6.ifr6_addr);
+ ifr6.ifr6_prefixlen = a->prefix_len;
+
+ ioctl(sock6_fd, SIOCDIFADDR, &ifr6);
+ }
+ }
+}
+
diff --git a/accel-pppd/ppp/ppp_ipcp.c b/accel-pppd/ppp/ppp_ipcp.c
index 625358aa..9ec92d49 100644
--- a/accel-pppd/ppp/ppp_ipcp.c
+++ b/accel-pppd/ppp/ppp_ipcp.c
@@ -11,6 +11,7 @@
#include "ppp.h"
#include "ppp_ipcp.h"
+#include "ipdb.h"
#include "memdebug.h"
@@ -208,6 +209,11 @@ static void ipcp_layer_finished(struct ppp_fsm_t *fsm)
ppp_terminate(ipcp->ppp, TERM_USER_ERROR, 0);
fsm->fsm_state = FSM_Closed;
+
+ if (ipcp->ppp->ipv4) {
+ ipdb_put_ipv4(ipcp->ppp, ipcp->ppp->ipv4);
+ ipcp->ppp->ipv4 = NULL;
+ }
}
static void ipcp_layer_down(struct ppp_fsm_t *fsm)
diff --git a/accel-pppd/ppp/ppp_ipv6cp.c b/accel-pppd/ppp/ppp_ipv6cp.c
index ffffa1e8..9e7bf784 100644
--- a/accel-pppd/ppp/ppp_ipv6cp.c
+++ b/accel-pppd/ppp/ppp_ipv6cp.c
@@ -11,6 +11,7 @@
#include "ppp.h"
#include "ppp_ipv6cp.h"
+#include "ipdb.h"
#include "memdebug.h"
@@ -208,6 +209,11 @@ static void ipv6cp_layer_finished(struct ppp_fsm_t *fsm)
ppp_terminate(ipv6cp->ppp, TERM_USER_ERROR, 0);
fsm->fsm_state = FSM_Closed;
+
+ if (ipv6cp->ppp->ipv6) {
+ ipdb_put_ipv6(ipv6cp->ppp, ipv6cp->ppp->ipv6);
+ ipv6cp->ppp->ipv6 = NULL;
+ }
}
static void ipv6cp_layer_down(struct ppp_fsm_t *fsm)