diff options
Diffstat (limited to 'accel-pppd/ppp')
-rw-r--r-- | accel-pppd/ppp/ipcp_opt_ipaddr.c | 29 | ||||
-rw-r--r-- | accel-pppd/ppp/ipv6cp_opt_intfid.c | 81 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.c | 144 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp.h | 3 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_auth.c | 12 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_ifcfg.c | 182 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_ipcp.c | 6 | ||||
-rw-r--r-- | accel-pppd/ppp/ppp_ipv6cp.c | 6 |
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 1455744..e965f5c 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 0d3d751..9a2ddee 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 4f3beb9..814240c 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 f831242..e37c75d 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 f78b652..7603d8c 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 0000000..f916251 --- /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 625358a..9ec92d4 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 ffffa1e..9e7bf78 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) |