Hi Oleg, On 11/08/2011 06:46 AM, Oleg Zhurakivskyy wrote: > --- > gatchat/gatppp.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++++- > gatchat/gatppp.h | 3 ++ > gatchat/ppp.h | 3 ++ > gatchat/ppp_ipv6cp.c | 17 ++++++++++++- > 4 files changed, 81 insertions(+), 3 deletions(-) > > diff --git a/gatchat/gatppp.c b/gatchat/gatppp.c > index f767f4a..c425eae 100644 > --- a/gatchat/gatppp.c > +++ b/gatchat/gatppp.c > @@ -62,6 +62,7 @@ struct _GAtPPP { > enum ppp_phase phase; > struct pppcp_data *lcp; > struct pppcp_data *ipcp; > + struct pppcp_data *ipv6cp; > struct ppp_net *net; > struct ppp_chap *chap; > GAtHDLC *hdlc; > @@ -157,7 +158,8 @@ static inline gboolean ppp_drop_packet(GAtPPP *ppp, guint16 protocol) > return TRUE; > case PPP_PHASE_NETWORK: > if (protocol != LCP_PROTOCOL && protocol != CHAP_PROTOCOL && > - protocol != IPCP_PROTO) > + protocol != IPCP_PROTO && > + protocol != IPV6CP_PROTO) This looks fine > return TRUE; > break; > case PPP_PHASE_LINK_UP: > @@ -222,6 +224,10 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data) > case IPCP_PROTO: > pppcp_process_packet(ppp->ipcp, packet, len - offset); > break; > + case IPV6CP_PROTO: > + if (ppp->ipv6cp) > + pppcp_process_packet(ppp->ipv6cp, packet, len - offset); > + break; Are you sure you don't want to send a protocol reject here? > case CHAP_PROTOCOL: > if (ppp->chap) { > ppp_chap_process_packet(ppp->chap, packet, > @@ -381,6 +387,12 @@ void ppp_auth_notify(GAtPPP *ppp, gboolean success) > > ppp_enter_phase(ppp, PPP_PHASE_NETWORK); > > + /* Send UP & OPEN events to the IPv6 CP */ > + if (ppp->ipv6cp) { > + pppcp_signal_open(ppp->ipv6cp); > + pppcp_signal_up(ppp->ipv6cp); > + } > + This looks fine > /* Send UP & OPEN events to the IPCP layer */ > pppcp_signal_open(ppp->ipcp); > pppcp_signal_up(ppp->ipcp); > @@ -431,6 +443,34 @@ void ppp_ipcp_finished_notify(GAtPPP *ppp) > > /* Our IPCP parameter negotiation failed */ > ppp->disconnect_reason = G_AT_PPP_REASON_IPCP_FAIL; > + > + if (ppp->ipv6cp) > + pppcp_signal_close(ppp->ipv6cp); This also looks fine, but please add a newline here > + pppcp_signal_close(ppp->ipcp); > + pppcp_signal_close(ppp->lcp); > +} > + > +void ppp_ipv6cp_up_notify(GAtPPP *ppp, const char *local, const char *peer) > +{ > + DBG(ppp, "local: %s, peer: %s", local, peer); > + > + ppp_enter_phase(ppp, PPP_PHASE_LINK_UP); > +} > + > +void ppp_ipv6cp_down_notify(GAtPPP *ppp) > +{ > + DBG(ppp, ""); > +} > + > +void ppp_ipv6cp_finished_notify(GAtPPP *ppp) > +{ > + DBG(ppp, ""); > + > + if (ppp->phase != PPP_PHASE_NETWORK) > + return; > + > + ppp->disconnect_reason = G_AT_PPP_REASON_IPV6CP_FAIL; > + pppcp_signal_close(ppp->ipv6cp); > pppcp_signal_close(ppp->ipcp); We probably only want to close ipcp if it exists, see my later comments > pppcp_signal_close(ppp->lcp); > } > @@ -732,6 +772,8 @@ void g_at_ppp_unref(GAtPPP *ppp) > > lcp_free(ppp->lcp); > ipcp_free(ppp->ipcp); > + if (ppp->ipv6cp) > + ipv6cp_free(ppp->ipv6cp); > > if (ppp->ppp_dead_source) { > g_source_remove(ppp->ppp_dead_source); > @@ -772,6 +814,23 @@ void g_at_ppp_set_pfc_enabled(GAtPPP *ppp, gboolean enabled) > lcp_set_pfc_enabled(ppp->lcp, enabled); > } > > +gboolean g_at_ppp_set_ipv6cp_info(GAtPPP *ppp, gboolean is_server, > + const char *local, const char *peer) > +{ > + GError *error = NULL; > + > + ppp->ipv6cp = ipv6cp_new(ppp, is_server, local, peer, &error); > + if (ppp->ipv6cp == NULL) { > + if (error != NULL) { > + DBG(ppp, "%s", error->message); > + g_error_free(error); > + } > + return FALSE; > + } > + > + return TRUE; > +} > + > static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip) > { > GAtPPP *ppp; > diff --git a/gatchat/gatppp.h b/gatchat/gatppp.h > index b5a2234..a41bf08 100644 > --- a/gatchat/gatppp.h > +++ b/gatchat/gatppp.h > @@ -37,6 +37,7 @@ typedef enum _GAtPPPDisconnectReason { > G_AT_PPP_REASON_UNKNOWN, > G_AT_PPP_REASON_AUTH_FAIL, /* Failed to authenticate */ > G_AT_PPP_REASON_IPCP_FAIL, /* Failed to negotiate IPCP */ > + G_AT_PPP_REASON_IPV6CP_FAIL, /* Failed to negotiate IPV6CP */ > G_AT_PPP_REASON_NET_FAIL, /* Failed to create tun */ > G_AT_PPP_REASON_PEER_CLOSED, /* Peer initiated a close */ > G_AT_PPP_REASON_LINK_DEAD, /* Link to the peer died */ > @@ -81,6 +82,8 @@ void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip, > > void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled); > void g_at_ppp_set_pfc_enabled(GAtPPP *ppp, gboolean enabled); > +gboolean g_at_ppp_set_ipv6cp_info(GAtPPP *ppp, gboolean is_server, > + const char *local, const char *peer); So for consistency sake I think we should introduce g_at_ppp_set_ipv6_server_info(GAtPPP *ppp, const char *remote_prefix); For the local prefix, I'm leaning towards creating a new set of v6 and dual-stack specific constructors: g_at_ppp_ipv6_new(const char *local_prefix); g_at_ppp_ipv6_server_new(const char *local_prefix); g_at_ppp_ipv4v6_new(const char *local_prefix); g_at_ppp_ipv4v6_server_new(const char *local_ip, const char *local_prefix); The key difference between constructors being whether to create ipcp, ipv6cp or both. We might need a _full version of the server constructors as well. I'm not entirely happy with this, so if you have better ideas, I'd love to hear them. > > #ifdef __cplusplus > } > diff --git a/gatchat/ppp.h b/gatchat/ppp.h > index 718575b..a21ebbc 100644 > --- a/gatchat/ppp.h > +++ b/gatchat/ppp.h > @@ -128,6 +128,9 @@ void ppp_ipcp_up_notify(GAtPPP *ppp, const char *local, const char *peer, > const char *dns1, const char *dns2); > void ppp_ipcp_down_notify(GAtPPP *ppp); > void ppp_ipcp_finished_notify(GAtPPP *ppp); > +void ppp_ipv6cp_up_notify(GAtPPP *ppp, const char *local, const char *peer); > +void ppp_ipv6cp_down_notify(GAtPPP *ppp); > +void ppp_ipv6cp_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); > diff --git a/gatchat/ppp_ipv6cp.c b/gatchat/ppp_ipv6cp.c > index ec89fb7..75ce8f2 100644 > --- a/gatchat/ppp_ipv6cp.c > +++ b/gatchat/ppp_ipv6cp.c > @@ -95,7 +95,19 @@ static void ipv6cp_reset_config_options(struct ipv6cp_data *ipv6cp) > > static void ipv6cp_up(struct pppcp_data *pppcp) > { > + struct ipv6cp_data *ipv6cp = pppcp_get_data(pppcp); > + struct in6_addr local_addr, peer_addr; > + char local[INET6_ADDRSTRLEN], peer[INET6_ADDRSTRLEN]; > > + memset(&local_addr, 0, sizeof(local_addr)); > + memcpy(&local_addr.s6_addr[8], &ipv6cp->local_addr, > + sizeof(ipv6cp->local_addr)); > + memset(&peer_addr, 0, sizeof(peer_addr)); > + memcpy(&peer_addr.s6_addr[8], &ipv6cp->peer_addr, > + sizeof(ipv6cp->peer_addr)); > + ppp_ipv6cp_up_notify(pppcp_get_ppp(pppcp), > + inet_ntop(AF_INET6, &local_addr, local, INET6_ADDRSTRLEN), > + inet_ntop(AF_INET6, &peer_addr, peer, INET6_ADDRSTRLEN)); > } > > static void ipv6cp_down(struct pppcp_data *pppcp) > @@ -105,11 +117,12 @@ static void ipv6cp_down(struct pppcp_data *pppcp) > ipv6cp_reset_config_options(ipv6cp); > > pppcp_set_local_options(pppcp, ipv6cp->options, ipv6cp->options_len); > + ppp_ipv6cp_down_notify(pppcp_get_ppp(pppcp)); > } > > static void ipv6cp_finished(struct pppcp_data *pppcp) > { > - > + ppp_ipv6cp_finished_notify(pppcp_get_ppp(pppcp)); > } > > static enum rcr_result ipv6cp_server_rcr(struct ipv6cp_data *ipv6cp, Regards, -Denis