summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKozlov Dmitry <dima@server>2010-08-23 14:34:37 +0400
committerDmitry Kozlov <xeb@mail.ru>2010-08-23 20:44:24 +0400
commit3c82158dca0e01aca17749a4c017e19d744f159e (patch)
treec5025ea42ff1e998afc3a687562238ceccd0efd2
parent29bfdacc0e5321df6d05b93359a49419a2f59670 (diff)
downloadaccel-ppp-xebd-3c82158dca0e01aca17749a4c017e19d744f159e.tar.gz
accel-ppp-xebd-3c82158dca0e01aca17749a4c017e19d744f159e.zip
implemented IPCP primary/secondary dns configuration option
-rw-r--r--accel-pptpd/CMakeLists.txt1
-rw-r--r--accel-pptpd/ipcp_opt_dns.c146
-rw-r--r--accel-pptpd/ppp.c11
-rw-r--r--accel-pptpd/ppp.h1
-rw-r--r--accel-pptpd/ppp_ipcp.c26
-rw-r--r--accel-pptpd/ppp_ipcp.h2
-rw-r--r--accel-pptpd/ppp_lcp.c29
7 files changed, 191 insertions, 25 deletions
diff --git a/accel-pptpd/CMakeLists.txt b/accel-pptpd/CMakeLists.txt
index 452f914..e97d916 100644
--- a/accel-pptpd/CMakeLists.txt
+++ b/accel-pptpd/CMakeLists.txt
@@ -24,6 +24,7 @@ ADD_EXECUTABLE(pptpd
ppp_ccp.c
ppp_ipcp.c
ipcp_opt_ipaddr.c
+ ipcp_opt_dns.c
pwdb.c
ipdb.c
diff --git a/accel-pptpd/ipcp_opt_dns.c b/accel-pptpd/ipcp_opt_dns.c
new file mode 100644
index 0000000..b741798
--- /dev/null
+++ b/accel-pptpd/ipcp_opt_dns.c
@@ -0,0 +1,146 @@
+#include <stdlib.h>
+#include <string.h>
+#include <arpa/inet.h>
+
+#include "ppp.h"
+#include "ppp_ipcp.h"
+#include "log.h"
+#include "ipdb.h"
+
+static struct ipcp_option_t *dns1_init(struct ppp_ipcp_t *ipcp);
+static struct ipcp_option_t *dns2_init(struct ppp_ipcp_t *ipcp);
+static void dns_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt);
+static int dns_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
+static int dns_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
+static int dns_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr);
+static void dns1_print(void (*print)(const char *fmt,...),struct ipcp_option_t*, uint8_t *ptr);
+static void dns2_print(void (*print)(const char *fmt,...),struct ipcp_option_t*, uint8_t *ptr);
+
+struct dns_option_t
+{
+ struct ipcp_option_t opt;
+ in_addr_t addr;
+};
+
+static struct ipcp_option_handler_t dns1_opt_hnd=
+{
+ .init=dns1_init,
+ .send_conf_req=dns_send_conf_req,
+ .send_conf_nak=dns_send_conf_nak,
+ .recv_conf_req=dns_recv_conf_req,
+ .free=dns_free,
+ .print=dns1_print,
+};
+static struct ipcp_option_handler_t dns2_opt_hnd=
+{
+ .init=dns2_init,
+ .send_conf_req=dns_send_conf_req,
+ .send_conf_nak=dns_send_conf_nak,
+ .recv_conf_req=dns_recv_conf_req,
+ .free=dns_free,
+ .print=dns2_print,
+};
+
+static struct ipcp_option_t *dns1_init(struct ppp_ipcp_t *ipcp)
+{
+ struct dns_option_t *dns_opt=malloc(sizeof(*dns_opt));
+ memset(dns_opt,0,sizeof(*dns_opt));
+ dns_opt->opt.id=CI_DNS1;
+ dns_opt->opt.len=6;
+
+ return &dns_opt->opt;
+}
+
+static struct ipcp_option_t *dns2_init(struct ppp_ipcp_t *ipcp)
+{
+ struct dns_option_t *dns_opt=malloc(sizeof(*dns_opt));
+ memset(dns_opt,0,sizeof(*dns_opt));
+ dns_opt->opt.id=CI_DNS2;
+ dns_opt->opt.len=6;
+
+ return &dns_opt->opt;
+}
+
+static void dns_free(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt)
+{
+ struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
+
+ free(dns_opt);
+}
+
+static int dns_send_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
+{
+ struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
+ struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+
+ if (!dns_opt->addr)
+ return 0;
+ opt32->hdr.id=dns_opt->opt.id;
+ opt32->hdr.len=6;
+ opt32->val=dns_opt->addr;
+ return 6;
+}
+
+static int dns_send_conf_nak(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
+{
+ struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
+ struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+ opt32->hdr.id=dns_opt->opt.id;
+ opt32->hdr.len=6;
+ opt32->val=dns_opt->addr;
+ return 6;
+}
+
+static int dns_recv_conf_req(struct ppp_ipcp_t *ipcp, struct ipcp_option_t *opt, uint8_t *ptr)
+{
+ struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
+ struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+
+ if (!dns_opt->addr)
+ {
+ if (dns_opt->opt.id==CI_DNS1) dns_opt->addr=inet_addr("10.0.0.1");
+ else dns_opt->addr=inet_addr("10.0.0.2");
+
+ if (!dns_opt->addr)
+ {
+ dns_opt->addr=opt32->val;
+ return IPCP_OPT_ACK;
+ }
+ }
+
+ if (dns_opt->addr==opt32->val)
+ return IPCP_OPT_ACK;
+
+ return IPCP_OPT_NAK;
+}
+
+static void dns1_print(void (*print)(const char *fmt,...),struct ipcp_option_t *opt, uint8_t *ptr)
+{
+ struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
+ struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+ struct in_addr in;
+
+ if (ptr) in.s_addr=opt32->val;
+ else in.s_addr=dns_opt->addr;
+
+ print("<dns1 %s>",inet_ntoa(in));
+}
+
+static void dns2_print(void (*print)(const char *fmt,...),struct ipcp_option_t *opt, uint8_t *ptr)
+{
+ struct dns_option_t *dns_opt=container_of(opt,typeof(*dns_opt),opt);
+ struct ipcp_opt32_t *opt32=(struct ipcp_opt32_t*)ptr;
+ struct in_addr in;
+
+ if (ptr) in.s_addr=opt32->val;
+ else in.s_addr=dns_opt->addr;
+
+ print("<dns2 %s>",inet_ntoa(in));
+}
+
+static void __init dns_opt_init()
+{
+ ipcp_option_register(&dns1_opt_hnd);
+ ipcp_option_register(&dns2_opt_hnd);
+}
+
diff --git a/accel-pptpd/ppp.c b/accel-pptpd/ppp.c
index 40f5ff7..518f757 100644
--- a/accel-pptpd/ppp.c
+++ b/accel-pptpd/ppp.c
@@ -255,7 +255,10 @@ void ppp_layer_started(struct ppp_t *ppp, struct ppp_layer_data_t *d)
{
n=list_entry(n->entry.next,typeof(*n),entry);
list_for_each_entry(d,&n->items,entry)
+ {
+ d->starting=1;
d->layer->start(d);
+ }
}
}
@@ -263,13 +266,14 @@ void ppp_layer_finished(struct ppp_t *ppp, struct ppp_layer_data_t *d)
{
struct layer_node_t *n=d->node;
+ d->starting=0;
d->started=0;
list_for_each_entry(n,&ppp->layers,entry)
{
list_for_each_entry(d,&n->items,entry)
{
- if (d->started)
+ if (d->starting)
return;
}
}
@@ -288,7 +292,7 @@ void ppp_terminate(struct ppp_t *ppp)
{
list_for_each_entry(d,&n->items,entry)
{
- if (d->started)
+ if (d->starting)
{
s=1;
d->layer->finish(d);
@@ -394,7 +398,10 @@ static void start_first_layer(struct ppp_t *ppp)
n=list_entry(ppp->layers.next,typeof(*n),entry);
list_for_each_entry(d,&n->items,entry)
+ {
+ d->starting=1;
d->layer->start(d);
+ }
}
struct ppp_layer_data_t *ppp_find_layer_data(struct ppp_t *ppp, struct ppp_layer_t *layer)
diff --git a/accel-pptpd/ppp.h b/accel-pptpd/ppp.h
index 9d8cdf1..39a0d41 100644
--- a/accel-pptpd/ppp.h
+++ b/accel-pptpd/ppp.h
@@ -95,6 +95,7 @@ struct ppp_layer_data_t
struct list_head entry;
struct ppp_layer_t *layer;
struct layer_node_t *node;
+ int starting:1;
int started:1;
};
diff --git a/accel-pptpd/ppp_ipcp.c b/accel-pptpd/ppp_ipcp.c
index e008117..5a37546 100644
--- a/accel-pptpd/ppp_ipcp.c
+++ b/accel-pptpd/ppp_ipcp.c
@@ -107,6 +107,8 @@ void ipcp_layer_finish(struct ppp_layer_data_t *ld)
log_debug("ipcp_layer_finish\n");
+ ppp_fsm_lower_down(&ipcp->fsm);
+
ppp_unregister_handler(ipcp->ppp,&ipcp->hnd);
ipcp_options_free(ipcp);
@@ -118,7 +120,7 @@ void ipcp_layer_free(struct ppp_layer_data_t *ld)
struct ppp_ipcp_t *ipcp=container_of(ld,typeof(*ipcp),ld);
log_debug("ipcp_layer_free\n");
-
+
free(ipcp);
}
@@ -146,7 +148,7 @@ static void print_ropt(struct recv_opt_t *ropt)
{
log_debug(" %x",ptr[i]);
}
- log_debug(">");
+ log_debug(" >");
}
static void send_conf_req(struct ppp_fsm_t *fsm)
@@ -199,7 +201,7 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
struct ppp_ipcp_t *ipcp=container_of(fsm,typeof(*ipcp),fsm);
uint8_t *buf=malloc(ipcp->conf_req_len), *ptr=buf;
struct ipcp_hdr_t *ipcp_hdr=(struct ipcp_hdr_t*)ptr;
- struct ipcp_option_t *lopt;
+ struct recv_opt_t *ropt;
log_debug("send [IPCP ConfNak id=%x",ipcp->fsm.recv_id);
@@ -210,13 +212,13 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
ptr+=sizeof(*ipcp_hdr);
- list_for_each_entry(lopt,&ipcp->options,entry)
+ list_for_each_entry(ropt,&ipcp->ropt_list,entry)
{
- if (lopt->state==IPCP_OPT_NAK)
+ if (ropt->state==IPCP_OPT_NAK)
{
log_debug(" ");
- lopt->h->print(log_debug,lopt,NULL);
- ptr+=lopt->h->send_conf_nak(ipcp,lopt,ptr);
+ ropt->lopt->h->print(log_debug,ropt->lopt,NULL);
+ ptr+=ropt->lopt->h->send_conf_nak(ipcp,ropt->lopt,ptr);
}
}
@@ -361,7 +363,9 @@ static int ipcp_recv_conf_rej(struct ppp_ipcp_t *ipcp,uint8_t *data,int size)
{
if (lopt->id==hdr->id)
{
- if (lopt->h->recv_conf_rej(ipcp,lopt,data))
+ if (!lopt->h->recv_conf_rej)
+ res=-1;
+ else if (lopt->h->recv_conf_rej(ipcp,lopt,data))
res=-1;
break;
}
@@ -498,8 +502,10 @@ static void ipcp_recv(struct ppp_handler_t*h)
ppp_fsm_recv_conf_rej(&ipcp->fsm);
break;
case CONFREJ:
- ipcp_recv_conf_rej(ipcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
- ppp_fsm_recv_conf_rej(&ipcp->fsm);
+ if (ipcp_recv_conf_rej(ipcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
+ ppp_terminate(ipcp->ppp);
+ else
+ ppp_fsm_recv_conf_rej(&ipcp->fsm);
break;
case TERMREQ:
term_msg=strndup((uint8_t*)(hdr+1),ntohs(hdr->len));
diff --git a/accel-pptpd/ppp_ipcp.h b/accel-pptpd/ppp_ipcp.h
index 0f83d44..a2ce3b3 100644
--- a/accel-pptpd/ppp_ipcp.h
+++ b/accel-pptpd/ppp_ipcp.h
@@ -10,7 +10,7 @@
*/
#define CI_COMP 2 /* IP-Compress-Protocol */
#define CI_ADDR 3 /* IP-Address */
-#define CI_DNS1 128 /* Primary-DNS-Address */
+#define CI_DNS1 129 /* Primary-DNS-Address */
#define CI_DNS2 131 /* Secondary-DNS-Address */
struct ipcp_hdr_t
diff --git a/accel-pptpd/ppp_lcp.c b/accel-pptpd/ppp_lcp.c
index 2bb7e38..da0034c 100644
--- a/accel-pptpd/ppp_lcp.c
+++ b/accel-pptpd/ppp_lcp.c
@@ -106,9 +106,7 @@ void lcp_layer_finish(struct ppp_layer_data_t *ld)
struct ppp_lcp_t *lcp=container_of(ld,typeof(*lcp),ld);
log_debug("lcp_layer_finish\n");
-
- ppp_unregister_handler(lcp->ppp,&lcp->hnd);
- lcp_options_free(lcp);
+ ppp_fsm_close(&lcp->fsm);
}
void lcp_layer_free(struct ppp_layer_data_t *ld)
@@ -117,6 +115,9 @@ void lcp_layer_free(struct ppp_layer_data_t *ld)
log_debug("lcp_layer_free\n");
+ ppp_unregister_handler(lcp->ppp,&lcp->hnd);
+ lcp_options_free(lcp);
+
free(lcp);
}
@@ -144,7 +145,7 @@ static void print_ropt(struct recv_opt_t *ropt)
{
log_debug(" %x",ptr[i]);
}
- log_debug(">");
+ log_debug(" >");
}
static void send_conf_req(struct ppp_fsm_t *fsm)
@@ -197,7 +198,7 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
struct ppp_lcp_t *lcp=container_of(fsm,typeof(*lcp),fsm);
uint8_t *buf=malloc(lcp->conf_req_len), *ptr=buf;
struct lcp_hdr_t *lcp_hdr=(struct lcp_hdr_t*)ptr;
- struct lcp_option_t *lopt;
+ struct recv_opt_t *ropt;
log_debug("send [LCP ConfNak id=%x",lcp->fsm.recv_id);
@@ -208,13 +209,13 @@ static void send_conf_nak(struct ppp_fsm_t *fsm)
ptr+=sizeof(*lcp_hdr);
- list_for_each_entry(lopt,&lcp->options,entry)
+ list_for_each_entry(ropt,&lcp->ropt_list,entry)
{
- if (lopt->state==LCP_OPT_NAK)
+ if (ropt->state==LCP_OPT_NAK)
{
log_debug(" ");
- lopt->h->print(log_debug,lopt,NULL);
- ptr+=lopt->h->send_conf_nak(lcp,lopt,ptr);
+ ropt->lopt->h->print(log_debug,ropt->lopt,NULL);
+ ptr+=ropt->lopt->h->send_conf_nak(lcp,ropt->lopt,ptr);
}
}
@@ -358,7 +359,9 @@ static int lcp_recv_conf_rej(struct ppp_lcp_t *lcp,uint8_t *data,int size)
{
if (lopt->id==hdr->id)
{
- if (lopt->h->recv_conf_rej(lcp,lopt,data))
+ if (!lopt->h->recv_conf_rej)
+ res=-1;
+ else if (lopt->h->recv_conf_rej(lcp,lopt,data))
res=-1;
break;
}
@@ -518,8 +521,10 @@ static void lcp_recv(struct ppp_handler_t*h)
ppp_fsm_recv_conf_rej(&lcp->fsm);
break;
case CONFREJ:
- lcp_recv_conf_rej(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN);
- ppp_fsm_recv_conf_rej(&lcp->fsm);
+ if (lcp_recv_conf_rej(lcp,(uint8_t*)(hdr+1),ntohs(hdr->len)-PPP_HDRLEN))
+ ppp_terminate(lcp->ppp);
+ else
+ ppp_fsm_recv_conf_rej(&lcp->fsm);
break;
case TERMREQ:
term_msg=strndup((uint8_t*)(hdr+1),ntohs(hdr->len));