summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gatchat/gatppp.c114
-rw-r--r--gatchat/ppp.h17
-rw-r--r--gatchat/ppp_ipcp.c5
-rw-r--r--gatchat/ppp_lcp.c6
4 files changed, 85 insertions, 57 deletions
diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c
index 4205a795..253b33fe 100644
--- a/gatchat/gatppp.c
+++ b/gatchat/gatppp.c
@@ -43,6 +43,15 @@
#define DEFAULT_MRU 1500
#define DEFAULT_MTU 1500
+enum ppp_phase {
+ PPP_PHASE_DEAD = 0, /* Link dead */
+ PPP_PHASE_ESTABLISHMENT, /* LCP started */
+ PPP_PHASE_AUTHENTICATION, /* Auth started */
+ PPP_PHASE_NETWORK, /* IPCP started */
+ PPP_PHASE_LINK_UP, /* IPCP negotiation succeded, link up */
+ PPP_PHASE_TERMINATION, /* LCP Terminate phase */
+};
+
struct _GAtPPP {
gint ref_count;
enum ppp_phase phase;
@@ -89,9 +98,12 @@ static inline gboolean ppp_drop_packet(GAtPPP *ppp, guint16 protocol)
case PPP_PHASE_DEAD:
return TRUE;
case PPP_PHASE_NETWORK:
- if (ppp->net == NULL && protocol == PPP_IP_PROTO)
+ if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL &&
+ protocol != IPCP_PROTO)
return TRUE;
break;
+ case PPP_PHASE_LINK_UP:
+ break;
}
return FALSE;
@@ -168,43 +180,13 @@ static void ppp_dead(GAtPPP *ppp)
ppp->disconnect_cb(ppp->disconnect_data);
}
-void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase)
+static inline void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase)
{
- /* don't do anything if we're already there */
- if (ppp->phase == phase)
- return;
-
- /* set new phase */
- ppp->phase = phase;
-
g_print("Entering new phase: %d\n", phase);
+ ppp->phase = phase;
- switch (phase) {
- case PPP_PHASE_ESTABLISHMENT:
- /* send an UP & OPEN events to the lcp layer */
- pppcp_signal_up(ppp->lcp);
- pppcp_signal_open(ppp->lcp);
- break;
- case PPP_PHASE_AUTHENTICATION:
- /* If we don't expect auth, move on to network phase */
- if (ppp->chap == NULL)
- ppp_enter_phase(ppp, PPP_PHASE_NETWORK);
-
- /* otherwise wait for the peer to send us a challenge */
- break;
- case PPP_PHASE_NETWORK:
- /* Send UP & OPEN events to the IPCP layer */
- pppcp_signal_open(ppp->ipcp);
- pppcp_signal_up(ppp->ipcp);
- break;
- case PPP_PHASE_TERMINATION:
- pppcp_signal_down(ppp->ipcp);
- pppcp_signal_close(ppp->ipcp);
- break;
- case PPP_PHASE_DEAD:
+ if (phase == PPP_PHASE_DEAD)
ppp_dead(ppp);
- break;
- }
}
void ppp_set_auth(GAtPPP *ppp, const guint8* auth_data)
@@ -226,13 +208,19 @@ void ppp_set_auth(GAtPPP *ppp, const guint8* auth_data)
void ppp_auth_notify(GAtPPP *ppp, gboolean success)
{
- if (success)
- ppp_enter_phase(ppp, PPP_PHASE_NETWORK);
- else
- ppp_enter_phase(ppp, PPP_PHASE_TERMINATION);
+ if (success == FALSE) {
+ pppcp_signal_close(ppp->lcp);
+ return;
+ }
+
+ ppp_enter_phase(ppp, PPP_PHASE_NETWORK);
+
+ /* Send UP & OPEN events to the IPCP layer */
+ pppcp_signal_open(ppp->ipcp);
+ pppcp_signal_up(ppp->ipcp);
}
-void ppp_net_up_notify(GAtPPP *ppp, const char *ip,
+void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip,
const char *dns1, const char *dns2)
{
ppp->net = ppp_net_new(ppp);
@@ -240,6 +228,8 @@ void ppp_net_up_notify(GAtPPP *ppp, const char *ip,
if (ppp_net_set_mtu(ppp->net, ppp->mtu) == FALSE)
g_printerr("Unable to set MTU\n");
+ ppp_enter_phase(ppp, PPP_PHASE_LINK_UP);
+
if (ppp->connect_cb == NULL)
return;
@@ -252,7 +242,7 @@ void ppp_net_up_notify(GAtPPP *ppp, const char *ip,
ip, dns1, dns2, ppp->connect_data);
}
-void ppp_net_down_notify(GAtPPP *ppp)
+void ppp_ipcp_down_notify(GAtPPP *ppp)
{
/* Most likely we failed to create the interface */
if (ppp->net == NULL)
@@ -262,6 +252,41 @@ void ppp_net_down_notify(GAtPPP *ppp)
ppp->net = NULL;
}
+void ppp_ipcp_finished_notify(GAtPPP *ppp)
+{
+ if (ppp->phase != PPP_PHASE_NETWORK)
+ return;
+
+ /* Our IPCP parameter negotiation failed */
+ pppcp_signal_close(ppp->ipcp);
+ pppcp_signal_close(ppp->lcp);
+}
+
+void ppp_lcp_up_notify(GAtPPP *ppp)
+{
+ /* Wait for the peer to send us a challenge if we expect auth */
+ if (ppp->chap != NULL) {
+ ppp_enter_phase(ppp, PPP_PHASE_AUTHENTICATION);
+ return;
+ }
+
+ /* Otherwise proceed as if auth succeeded */
+ ppp_auth_notify(ppp, TRUE);
+}
+
+void ppp_lcp_down_notify(GAtPPP *ppp)
+{
+ if (ppp->phase == PPP_PHASE_NETWORK || ppp->phase == PPP_PHASE_LINK_UP)
+ pppcp_signal_down(ppp->ipcp);
+
+ ppp_enter_phase(ppp, PPP_PHASE_TERMINATION);
+}
+
+void ppp_lcp_finished_notify(GAtPPP *ppp)
+{
+ ppp_dead(ppp);
+}
+
void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm)
{
g_at_hdlc_set_recv_accm(ppp->hdlc, accm);
@@ -288,13 +313,17 @@ static void io_disconnect(gpointer user_data)
GAtPPP *ppp = user_data;
pppcp_signal_down(ppp->lcp);
- ppp_enter_phase(ppp, PPP_PHASE_DEAD);
+ pppcp_signal_close(ppp->lcp);
}
/* Administrative Open */
void g_at_ppp_open(GAtPPP *ppp)
{
ppp_enter_phase(ppp, PPP_PHASE_ESTABLISHMENT);
+
+ /* send an UP & OPEN events to the lcp layer */
+ pppcp_signal_up(ppp->lcp);
+ pppcp_signal_open(ppp->lcp);
}
gboolean g_at_ppp_set_credentials(GAtPPP *ppp, const char *username,
@@ -367,6 +396,9 @@ void g_at_ppp_set_debug(GAtPPP *ppp, GAtDebugFunc func, gpointer user_data)
void g_at_ppp_shutdown(GAtPPP *ppp)
{
+ if (ppp->phase == PPP_PHASE_DEAD || ppp->phase == PPP_PHASE_TERMINATION)
+ return;
+
pppcp_signal_close(ppp->lcp);
}
diff --git a/gatchat/ppp.h b/gatchat/ppp.h
index 01092965..41cf50ae 100644
--- a/gatchat/ppp.h
+++ b/gatchat/ppp.h
@@ -27,14 +27,6 @@
#define PPP_IP_PROTO 0x0021
#define MD5 5
-enum ppp_phase {
- PPP_PHASE_DEAD = 0, /* Link dead */
- PPP_PHASE_ESTABLISHMENT, /* LCP started */
- PPP_PHASE_AUTHENTICATION, /* Auth started */
- PPP_PHASE_NETWORK, /* IPCP started */
- PPP_PHASE_TERMINATION, /* LCP Terminate phase */
-};
-
struct ppp_chap;
struct ppp_net;
@@ -107,13 +99,16 @@ gboolean ppp_net_set_mtu(struct ppp_net *net, guint16 mtu);
/* PPP functions related to main GAtPPP object */
void ppp_debug(GAtPPP *ppp, const char *str);
-void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase);
void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen);
void ppp_set_auth(GAtPPP *ppp, const guint8 *auth_data);
void ppp_auth_notify(GAtPPP *ppp, gboolean success);
-void ppp_net_up_notify(GAtPPP *ppp, const char *ip,
+void ppp_ipcp_up_notify(GAtPPP *ppp, const char *ip,
const char *dns1, const char *dns2);
-void ppp_net_down_notify(GAtPPP *ppp);
+void ppp_ipcp_down_notify(GAtPPP *ppp);
+void ppp_ipcp_finished_notify(GAtPPP *ppp);
+void ppp_lcp_up_notify(GAtPPP *ppp);
+void ppp_lcp_down_notify(GAtPPP *ppp);
+void ppp_lcp_finished_notify(GAtPPP *ppp);
void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm);
void ppp_set_xmit_accm(GAtPPP *ppp, guint32 accm);
void ppp_set_mtu(GAtPPP *ppp, const guint8 *data);
diff --git a/gatchat/ppp_ipcp.c b/gatchat/ppp_ipcp.c
index 7402f9a9..a1eacdfc 100644
--- a/gatchat/ppp_ipcp.c
+++ b/gatchat/ppp_ipcp.c
@@ -135,7 +135,7 @@ static void ipcp_up(struct pppcp_data *pppcp)
addr.s_addr = ipcp->dns2;
inet_ntop(AF_INET, &addr, dns2, INET_ADDRSTRLEN);
- ppp_net_up_notify(pppcp_get_ppp(pppcp), ip[0] ? ip : NULL,
+ ppp_ipcp_up_notify(pppcp_get_ppp(pppcp), ip[0] ? ip : NULL,
dns1[0] ? dns1 : NULL,
dns2[0] ? dns2 : NULL);
}
@@ -146,11 +146,12 @@ static void ipcp_down(struct pppcp_data *pppcp)
ipcp_reset_config_options(ipcp);
pppcp_set_local_options(pppcp, ipcp->options, ipcp->options_len);
- ppp_net_down_notify(pppcp_get_ppp(pppcp));
+ ppp_ipcp_down_notify(pppcp_get_ppp(pppcp));
}
static void ipcp_finished(struct pppcp_data *pppcp)
{
+ ppp_ipcp_finished_notify(pppcp_get_ppp(pppcp));
}
static void ipcp_rca(struct pppcp_data *pppcp,
diff --git a/gatchat/ppp_lcp.c b/gatchat/ppp_lcp.c
index 7c1ea50f..2a5370b9 100644
--- a/gatchat/ppp_lcp.c
+++ b/gatchat/ppp_lcp.c
@@ -116,7 +116,7 @@ static void lcp_reset_config_options(struct lcp_data *lcp)
*/
static void lcp_up(struct pppcp_data *pppcp)
{
- ppp_enter_phase(pppcp_get_ppp(pppcp), PPP_PHASE_AUTHENTICATION);
+ ppp_lcp_up_notify(pppcp_get_ppp(pppcp));
}
/*
@@ -128,7 +128,7 @@ static void lcp_down(struct pppcp_data *pppcp)
lcp_reset_config_options(lcp);
pppcp_set_local_options(pppcp, lcp->options, lcp->options_len);
- ppp_enter_phase(pppcp_get_ppp(pppcp), PPP_PHASE_TERMINATION);
+ ppp_lcp_down_notify(pppcp_get_ppp(pppcp));
}
/*
@@ -137,7 +137,7 @@ static void lcp_down(struct pppcp_data *pppcp)
*/
static void lcp_finished(struct pppcp_data *pppcp)
{
- ppp_enter_phase(pppcp_get_ppp(pppcp), PPP_PHASE_DEAD);
+ ppp_lcp_finished_notify(pppcp_get_ppp(pppcp));
}
static void lcp_rca(struct pppcp_data *pppcp, const struct pppcp_packet *packet)