mirror of git://git.sysmocom.de/ofono
PPP LCP support
Implement LCP support for the PPP protocol.
This commit is contained in:
parent
31e99d9d78
commit
cd5ddc2bee
|
@ -58,7 +58,7 @@ gatchat_sources = gatchat/gatchat.h gatchat/gatchat.c \
|
|||
gatchat/gatserver.h gatchat/gatserver.c \
|
||||
gatchat/gatppp.c gatchat/gatppp.h \
|
||||
gatchat/ppp.c gatchat/ppp.h gatchat/ppp_cp.h \
|
||||
gatchat/ppp_cp.c
|
||||
gatchat/ppp_cp.c gatchat/ppp_lcp.c
|
||||
|
||||
udev_files = plugins/ofono.rules
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
void g_at_ppp_open(GAtPPP *ppp)
|
||||
{
|
||||
/* send an OPEN event to the lcp layer */
|
||||
lcp_open(ppp->lcp);
|
||||
}
|
||||
|
||||
void g_at_ppp_set_connect_function(GAtPPP *ppp,
|
||||
|
@ -69,6 +70,9 @@ void g_at_ppp_shutdown(GAtPPP *ppp)
|
|||
/* cleanup modem channel */
|
||||
g_source_remove(ppp->modem_watch);
|
||||
g_io_channel_unref(ppp->modem);
|
||||
|
||||
/* remove lcp */
|
||||
lcp_free(ppp->lcp);
|
||||
}
|
||||
|
||||
void g_at_ppp_ref(GAtPPP *ppp)
|
||||
|
@ -117,7 +121,7 @@ GAtPPP *g_at_ppp_new(GIOChannel *modem)
|
|||
ppp->index = 0;
|
||||
|
||||
/* initialize the lcp state */
|
||||
|
||||
ppp->lcp = lcp_new(ppp);
|
||||
|
||||
/* initialize the autentication state */
|
||||
|
||||
|
|
|
@ -350,16 +350,19 @@ gboolean ppp_cb(GIOChannel *channel, GIOCondition cond, gpointer data)
|
|||
void ppp_close(GAtPPP *ppp)
|
||||
{
|
||||
/* send a CLOSE event to the lcp layer */
|
||||
lcp_close(ppp->lcp);
|
||||
}
|
||||
|
||||
static void ppp_link_establishment(GAtPPP *ppp)
|
||||
{
|
||||
/* signal UP event to LCP */
|
||||
lcp_establish(ppp->lcp);
|
||||
}
|
||||
|
||||
static void ppp_terminate(GAtPPP *ppp)
|
||||
{
|
||||
/* signal DOWN event to LCP */
|
||||
lcp_terminate(ppp->lcp);
|
||||
}
|
||||
|
||||
static void ppp_authenticate(GAtPPP *ppp)
|
||||
|
@ -452,3 +455,47 @@ void ppp_generate_event(GAtPPP *ppp, enum ppp_event event)
|
|||
g_queue_push_tail(ppp->event_queue, GUINT_TO_POINTER(event));
|
||||
ppp_handle_event(ppp);
|
||||
}
|
||||
|
||||
void ppp_set_auth(GAtPPP *ppp, guint8* auth_data)
|
||||
{
|
||||
guint16 proto = get_host_short(auth_data);
|
||||
|
||||
switch (proto) {
|
||||
case CHAP_PROTOCOL:
|
||||
/* get the algorithm */
|
||||
break;
|
||||
default:
|
||||
g_printerr("unknown authentication proto\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm)
|
||||
{
|
||||
ppp->recv_accm = accm;
|
||||
}
|
||||
|
||||
guint32 ppp_get_xmit_accm(GAtPPP *ppp)
|
||||
{
|
||||
return ppp->xmit_accm[0];
|
||||
}
|
||||
|
||||
void ppp_set_pfc(GAtPPP *ppp, gboolean pfc)
|
||||
{
|
||||
ppp->pfc = pfc;
|
||||
}
|
||||
|
||||
gboolean ppp_get_pfc(GAtPPP *ppp)
|
||||
{
|
||||
return ppp->pfc;
|
||||
}
|
||||
|
||||
void ppp_set_acfc(GAtPPP *ppp, gboolean acfc)
|
||||
{
|
||||
ppp->acfc = acfc;
|
||||
}
|
||||
|
||||
gboolean ppp_get_acfc(GAtPPP *ppp)
|
||||
{
|
||||
return ppp->acfc;
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ static inline guint16 __get_unaligned_short(const gpointer p)
|
|||
struct _GAtPPP {
|
||||
gint ref_count;
|
||||
enum ppp_phase phase;
|
||||
struct pppcp_data *lcp;
|
||||
guint8 buffer[BUFFERSZ];
|
||||
int index;
|
||||
gint mru;
|
||||
|
@ -130,3 +131,9 @@ void ppp_set_pfc(GAtPPP *ppp, gboolean pfc);
|
|||
gboolean ppp_get_pfc(GAtPPP *ppp);
|
||||
void ppp_set_acfc(GAtPPP *ppp, gboolean acfc);
|
||||
gboolean ppp_get_acfc(GAtPPP *ppp);
|
||||
struct pppcp_data * lcp_new(GAtPPP *ppp);
|
||||
void lcp_free(struct pppcp_data *lcp);
|
||||
void lcp_open(struct pppcp_data *data);
|
||||
void lcp_close(struct pppcp_data *data);
|
||||
void lcp_establish(struct pppcp_data *data);
|
||||
void lcp_terminate(struct pppcp_data *data);
|
||||
|
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
*
|
||||
* PPP library with GLib integration
|
||||
*
|
||||
* Copyright (C) 2009-2010 Intel Corporation. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <termios.h>
|
||||
#include <glib.h>
|
||||
#include <arpa/inet.h>
|
||||
#include "gatppp.h"
|
||||
#include "ppp.h"
|
||||
|
||||
enum lcp_options {
|
||||
RESERVED = 0,
|
||||
MRU = 1,
|
||||
ACCM = 2,
|
||||
AUTH_PROTO = 3,
|
||||
QUAL_PROTO = 4,
|
||||
MAGIC_NUMBER = 5,
|
||||
DEPRECATED_QUAL_PROTO = 6,
|
||||
PFC = 7,
|
||||
ACFC = 8,
|
||||
};
|
||||
|
||||
#define LCP_SUPPORTED_CODES ((1 << CONFIGURE_REQUEST) | \
|
||||
(1 << CONFIGURE_ACK) | \
|
||||
(1 << CONFIGURE_NAK) | \
|
||||
(1 << CONFIGURE_REJECT) | \
|
||||
(1 << TERMINATE_REQUEST) | \
|
||||
(1 << TERMINATE_ACK) | \
|
||||
(1 << CODE_REJECT) | \
|
||||
(1 << PROTOCOL_REJECT) | \
|
||||
(1 << ECHO_REQUEST) | \
|
||||
(1 << ECHO_REPLY) | \
|
||||
(1 << DISCARD_REQUEST))
|
||||
|
||||
/*
|
||||
* signal the Up event to the NCP
|
||||
*/
|
||||
static void lcp_up(struct pppcp_data *pppcp)
|
||||
{
|
||||
ppp_generate_event(pppcp->ppp, PPP_OPENED);
|
||||
}
|
||||
|
||||
/*
|
||||
* signal the Down event to the NCP
|
||||
*/
|
||||
static void lcp_down(struct pppcp_data *pppcp)
|
||||
{
|
||||
ppp_generate_event(pppcp->ppp, PPP_DOWN);
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate that the lower layer is now needed
|
||||
* Should trigger Up event
|
||||
*/
|
||||
static void lcp_started(struct pppcp_data *pppcp)
|
||||
{
|
||||
ppp_generate_event(pppcp->ppp, PPP_UP);
|
||||
}
|
||||
|
||||
/*
|
||||
* Indicate that the lower layer is not needed
|
||||
* Should trigger Down event
|
||||
*/
|
||||
static void lcp_finished(struct pppcp_data *pppcp)
|
||||
{
|
||||
ppp_generate_event(pppcp->ppp, PPP_CLOSING);
|
||||
}
|
||||
|
||||
/*
|
||||
* Scan the option to see if it is acceptable, unacceptable, or rejected
|
||||
*
|
||||
* We need to use a default case here because this option type value
|
||||
* could be anything.
|
||||
*/
|
||||
static guint lcp_option_scan(struct ppp_option *option, gpointer user)
|
||||
{
|
||||
switch (option->type) {
|
||||
case ACCM:
|
||||
case AUTH_PROTO:
|
||||
/* XXX check to make sure it's a proto we recognize */
|
||||
case MAGIC_NUMBER:
|
||||
case PFC:
|
||||
case ACFC:
|
||||
return OPTION_ACCEPT;
|
||||
break;
|
||||
default:
|
||||
return OPTION_REJECT;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* act on an acceptable option
|
||||
*
|
||||
* We need to use a default case here because this option type value
|
||||
* could be anything.
|
||||
*/
|
||||
static void lcp_option_process(gpointer data, gpointer user)
|
||||
{
|
||||
struct ppp_option *option = data;
|
||||
struct pppcp_data *pppcp = user;
|
||||
GAtPPP *ppp = pppcp->ppp;
|
||||
guint32 magic;
|
||||
|
||||
switch (option->type) {
|
||||
case ACCM:
|
||||
ppp_set_recv_accm(ppp, get_host_long(option->data));
|
||||
break;
|
||||
case AUTH_PROTO:
|
||||
ppp_set_auth(ppp, option->data);
|
||||
break;
|
||||
case MAGIC_NUMBER:
|
||||
/* XXX handle loopback */
|
||||
magic = get_host_long(option->data);
|
||||
if (magic != pppcp->magic_number)
|
||||
pppcp->magic_number = magic;
|
||||
else
|
||||
g_print("looped back? I should do something\n");
|
||||
break;
|
||||
case PFC:
|
||||
ppp_set_pfc(ppp, TRUE);
|
||||
break;
|
||||
case ACFC:
|
||||
ppp_set_acfc(ppp, TRUE);
|
||||
break;
|
||||
default:
|
||||
g_printerr("unhandled option %d\n", option->type);
|
||||
}
|
||||
}
|
||||
|
||||
struct ppp_packet_handler lcp_packet_handler = {
|
||||
.proto = LCP_PROTOCOL,
|
||||
.handler = pppcp_process_packet,
|
||||
};
|
||||
|
||||
struct pppcp_action lcp_action = {
|
||||
.this_layer_up = lcp_up,
|
||||
.this_layer_down = lcp_down,
|
||||
.this_layer_started = lcp_started,
|
||||
.this_layer_finished = lcp_finished,
|
||||
.option_scan = lcp_option_scan,
|
||||
.option_process = lcp_option_process,
|
||||
};
|
||||
|
||||
void lcp_open(struct pppcp_data *data)
|
||||
{
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
/* send an open event to the lcp layer */
|
||||
pppcp_generate_event(data, OPEN, NULL, 0);
|
||||
}
|
||||
|
||||
void lcp_close(struct pppcp_data *data)
|
||||
{
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
/* send a CLOSE event to the lcp layer */
|
||||
pppcp_generate_event(data, CLOSE, NULL, 0);
|
||||
}
|
||||
|
||||
void lcp_establish(struct pppcp_data *data)
|
||||
{
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
/* send an UP event to the lcp layer */
|
||||
pppcp_generate_event(data, UP, NULL, 0);
|
||||
}
|
||||
|
||||
void lcp_terminate(struct pppcp_data *data)
|
||||
{
|
||||
if (data == NULL)
|
||||
return;
|
||||
|
||||
/* send a DOWN event to the lcp layer */
|
||||
pppcp_generate_event(data, DOWN, NULL, 0);
|
||||
}
|
||||
|
||||
void lcp_free(struct pppcp_data *lcp)
|
||||
{
|
||||
if (lcp == NULL)
|
||||
return;
|
||||
|
||||
/* TBD unregister packet handler */
|
||||
|
||||
pppcp_free(lcp);
|
||||
}
|
||||
|
||||
struct pppcp_data * lcp_new(GAtPPP *ppp)
|
||||
{
|
||||
struct pppcp_data *pppcp;
|
||||
struct ppp_option *option;
|
||||
guint16 codes = LCP_SUPPORTED_CODES;
|
||||
|
||||
pppcp = pppcp_new(ppp, LCP_PROTOCOL, NULL);
|
||||
if (!pppcp) {
|
||||
g_print("Failed to allocate PPPCP struct\n");
|
||||
return NULL;
|
||||
}
|
||||
pppcp_set_valid_codes(pppcp, codes);
|
||||
pppcp->priv = pppcp;
|
||||
|
||||
/* set the actions */
|
||||
pppcp->action = &lcp_action;
|
||||
|
||||
/* add the default config options */
|
||||
option = g_try_malloc0(6);
|
||||
if (option == NULL) {
|
||||
pppcp_free(pppcp);
|
||||
return NULL;
|
||||
}
|
||||
option->type = ACCM;
|
||||
option->length = 6;
|
||||
pppcp_add_config_option(pppcp, option);
|
||||
|
||||
/* register packet handler for LCP protocol */
|
||||
lcp_packet_handler.priv = pppcp;
|
||||
ppp_register_packet_handler(&lcp_packet_handler);
|
||||
return pppcp;
|
||||
}
|
Loading…
Reference in New Issue