summaryrefslogtreecommitdiff
path: root/accel-pppd/ppp
diff options
context:
space:
mode:
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)