GAtPPP: Add ACFC option support

This commit is contained in:
Guillaume Zajac 2011-06-29 10:20:23 +02:00 committed by Denis Kenzior
parent 00bd7f8735
commit 84ccc874da
4 changed files with 114 additions and 25 deletions

View File

@ -83,6 +83,7 @@ struct _GAtPPP {
int fd; int fd;
guint guard_timeout_source; guint guard_timeout_source;
gboolean suspended; gboolean suspended;
gboolean xmit_acfc;
}; };
void ppp_debug(GAtPPP *ppp, const char *str) void ppp_debug(GAtPPP *ppp, const char *str)
@ -168,8 +169,19 @@ static inline gboolean ppp_drop_packet(GAtPPP *ppp, guint16 protocol)
static void ppp_receive(const unsigned char *buf, gsize len, void *data) static void ppp_receive(const unsigned char *buf, gsize len, void *data)
{ {
GAtPPP *ppp = data; GAtPPP *ppp = data;
guint16 protocol = ppp_proto(buf); struct ppp_header *header = (struct ppp_header *) buf;
const guint8 *packet = ppp_info(buf); gboolean acfc_frame = (header->address != PPP_ADDR_FIELD
|| header->control != PPP_CTRL);
guint16 protocol;
const guint8 *packet;
if (acfc_frame) {
protocol = ppp_acfc_proto(buf);
packet = ppp_acfc_info(buf);
} else {
protocol = ppp_proto(buf);
packet = ppp_info(buf);
}
if (ppp_drop_packet(ppp, protocol)) if (ppp_drop_packet(ppp, protocol))
return; return;
@ -196,37 +208,29 @@ static void ppp_receive(const unsigned char *buf, gsize len, void *data)
}; };
} }
/* static void ppp_send_lcp_frame(GAtPPP *ppp, guint8 *packet, guint infolen)
* transmit out through the lower layer interface
*
* infolen - length of the information part of the packet
*/
void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen)
{ {
struct ppp_header *header = (struct ppp_header *) packet; struct ppp_header *header = (struct ppp_header *) packet;
guint16 proto = ppp_proto(packet);
guint8 code; guint8 code;
gboolean lcp = (proto == LCP_PROTOCOL);
guint32 xmit_accm = 0; guint32 xmit_accm = 0;
gboolean sta = FALSE; gboolean sta = FALSE;
gboolean lcp;
/* /*
* all LCP Link Configuration, Link Termination, and Code-Reject * all LCP Link Configuration, Link Termination, and Code-Reject
* packets must be sent with the default sending ACCM * packets must be sent with the default sending ACCM
*/ */
if (lcp) { code = pppcp_get_code(packet);
code = pppcp_get_code(packet); lcp = code > 0 && code < 8;
lcp = code > 0 && code < 8;
/* /*
* If we're going down, we try to make sure to send the final * If we're going down, we try to make sure to send the final
* ack before informing the upper layers via the ppp_disconnect * ack before informing the upper layers via the ppp_disconnect
* function. Once we enter PPP_DEAD phase, no further packets * function. Once we enter PPP_DEAD phase, no further packets
* will be sent * will be sent
*/ */
if (code == PPPCP_CODE_TYPE_TERMINATE_ACK) if (code == PPPCP_CODE_TYPE_TERMINATE_ACK)
sta = TRUE; sta = TRUE;
}
if (lcp) { if (lcp) {
xmit_accm = g_at_hdlc_get_xmit_accm(ppp->hdlc); xmit_accm = g_at_hdlc_get_xmit_accm(ppp->hdlc);
@ -251,6 +255,42 @@ void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen)
g_at_hdlc_set_xmit_accm(ppp->hdlc, xmit_accm); g_at_hdlc_set_xmit_accm(ppp->hdlc, xmit_accm);
} }
static void ppp_send_acfc_frame(GAtPPP *ppp, guint8 *packet,
guint infolen)
{
struct ppp_header *header = (struct ppp_header *) packet;
guint offset = 0;
if (ppp->xmit_acfc)
offset = 2;
if (g_at_hdlc_send(ppp->hdlc, packet + offset,
infolen + sizeof(*header) - offset)
== FALSE)
DBG(ppp, "Failed to send a frame\n");
}
/*
* transmit out through the lower layer interface
*
* infolen - length of the information part of the packet
*/
void ppp_transmit(GAtPPP *ppp, guint8 *packet, guint infolen)
{
guint16 proto = ppp_proto(packet);
switch (proto) {
case LCP_PROTOCOL:
ppp_send_lcp_frame(ppp, packet, infolen);
break;
case CHAP_PROTOCOL:
case IPCP_PROTO:
case PPP_IP_PROTO:
ppp_send_acfc_frame(ppp, packet, infolen);
break;
}
}
static inline void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase) static inline void ppp_enter_phase(GAtPPP *ppp, enum ppp_phase phase)
{ {
DBG(ppp, "%d", phase); DBG(ppp, "%d", phase);
@ -390,6 +430,11 @@ void ppp_set_mtu(GAtPPP *ppp, const guint8 *data)
ppp->mtu = mtu; ppp->mtu = mtu;
} }
void ppp_set_xmit_acfc(GAtPPP *ppp, gboolean acfc)
{
ppp->xmit_acfc = acfc;
}
static void io_disconnect(gpointer user_data) static void io_disconnect(gpointer user_data)
{ {
GAtPPP *ppp = user_data; GAtPPP *ppp = user_data;
@ -658,6 +703,11 @@ void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote,
ipcp_set_server_info(ppp->ipcp, r, d1, d2); ipcp_set_server_info(ppp->ipcp, r, d1, d2);
} }
void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled)
{
lcp_set_acfc_enabled(ppp->lcp, enabled);
}
static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip) static GAtPPP *ppp_init_common(gboolean is_server, guint32 ip)
{ {
GAtPPP *ppp; GAtPPP *ppp;

View File

@ -79,6 +79,8 @@ void g_at_ppp_set_recording(GAtPPP *ppp, const char *filename);
void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip, void g_at_ppp_set_server_info(GAtPPP *ppp, const char *remote_ip,
const char *dns1, const char *dns2); const char *dns1, const char *dns2);
void g_at_ppp_set_acfc_enabled(GAtPPP *ppp, gboolean enabled);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif #endif

View File

@ -85,10 +85,17 @@ static inline void __put_unaligned_short(void *p, guint16 val)
#define ppp_proto(packet) \ #define ppp_proto(packet) \
(get_host_short(packet + 2)) (get_host_short(packet + 2))
#define ppp_acfc_info(packet) \
(packet + 2)
#define ppp_acfc_proto(packet) \
(get_host_short(packet))
/* LCP related functions */ /* LCP related functions */
struct pppcp_data *lcp_new(GAtPPP *ppp, gboolean dormant); struct pppcp_data *lcp_new(GAtPPP *ppp, gboolean dormant);
void lcp_free(struct pppcp_data *lcp); void lcp_free(struct pppcp_data *lcp);
void lcp_protocol_reject(struct pppcp_data *lcp, guint8 *packet, gsize len); void lcp_protocol_reject(struct pppcp_data *lcp, guint8 *packet, gsize len);
void lcp_set_acfc_enabled(struct pppcp_data *pppcp, gboolean enabled);
/* IPCP related functions */ /* IPCP related functions */
struct pppcp_data *ipcp_new(GAtPPP *ppp, gboolean is_server, guint32 ip); struct pppcp_data *ipcp_new(GAtPPP *ppp, gboolean is_server, guint32 ip);
@ -125,4 +132,5 @@ void ppp_lcp_finished_notify(GAtPPP *ppp);
void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm); void ppp_set_recv_accm(GAtPPP *ppp, guint32 accm);
void ppp_set_xmit_accm(GAtPPP *ppp, guint32 accm); void ppp_set_xmit_accm(GAtPPP *ppp, guint32 accm);
void ppp_set_mtu(GAtPPP *ppp, const guint8 *data); void ppp_set_mtu(GAtPPP *ppp, const guint8 *data);
void ppp_set_xmit_acfc(GAtPPP *ppp, gboolean acfc);
struct ppp_header *ppp_packet_new(gsize infolen, guint16 protocol); struct ppp_header *ppp_packet_new(gsize infolen, guint16 protocol);

View File

@ -58,11 +58,12 @@ enum lcp_options {
ACFC = 8, ACFC = 8,
}; };
/* Maximum size of all options, we only ever request ACCM and MRU */ /* Maximum size of all options, we only ever request ACCM, MRU and ACFC */
#define MAX_CONFIG_OPTION_SIZE 10 #define MAX_CONFIG_OPTION_SIZE 12
#define REQ_OPTION_ACCM 0x1 #define REQ_OPTION_ACCM 0x1
#define REQ_OPTION_MRU 0x2 #define REQ_OPTION_MRU 0x2
#define REQ_OPTION_ACFC 0x4
struct lcp_data { struct lcp_data {
guint8 options[MAX_CONFIG_OPTION_SIZE]; guint8 options[MAX_CONFIG_OPTION_SIZE];
@ -100,6 +101,13 @@ static void lcp_generate_config_options(struct lcp_data *lcp)
len += 4; len += 4;
} }
if (lcp->req_options & REQ_OPTION_ACFC) {
lcp->options[len] = ACFC;
lcp->options[len + 1] = 2;
len += 2;
}
lcp->options_len = len; lcp->options_len = len;
} }
@ -286,9 +294,17 @@ static enum rcr_result lcp_rcr(struct pppcp_data *pppcp,
break; break;
case MAGIC_NUMBER: case MAGIC_NUMBER:
case PFC: case PFC:
case ACFC:
/* don't care */ /* don't care */
break; break;
case ACFC:
{
struct lcp_data *lcp = pppcp_get_data(pppcp);
if (lcp->req_options & REQ_OPTION_ACFC)
ppp_set_xmit_acfc(ppp, TRUE);
break;
}
} }
} }
@ -338,3 +354,16 @@ struct pppcp_data *lcp_new(GAtPPP *ppp, gboolean is_server)
return pppcp; return pppcp;
} }
void lcp_set_acfc_enabled(struct pppcp_data *pppcp, gboolean enabled)
{
struct lcp_data *lcp = pppcp_get_data(pppcp);
if (enabled == TRUE)
lcp->req_options |= REQ_OPTION_ACFC;
else
lcp->req_options &= ~REQ_OPTION_ACFC;
lcp_generate_config_options(lcp);
pppcp_set_local_options(pppcp, lcp->options, lcp->options_len);
}