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 */ + g_print("Entering new phase: %d\n", phase); ppp->phase = phase; - g_print("Entering new phase: %d\n", 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)