summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--gatchat/ppp_cp.c53
-rw-r--r--gatchat/ppp_cp.h16
-rw-r--r--gatchat/ppp_ipcp.c24
-rw-r--r--gatchat/ppp_lcp.c18
4 files changed, 71 insertions, 40 deletions
diff --git a/gatchat/ppp_cp.c b/gatchat/ppp_cp.c
index 1c86bee4..fbfe5159 100644
--- a/gatchat/ppp_cp.c
+++ b/gatchat/ppp_cp.c
@@ -997,8 +997,7 @@ static guint8 pppcp_process_configure_ack(struct pppcp_data *data,
{
guint len;
GList *list;
- struct ppp_option *acked_option;
- guint i = 0;
+ guint i;
const struct pppcp_action *action = data->action;
pppcp_trace(data);
@@ -1013,40 +1012,34 @@ static guint8 pppcp_process_configure_ack(struct pppcp_data *data,
}
/*
- * check each acked option. If it is what we requested,
- * then we can apply these option values.
- *
- * XXX what if it isn't? Do this correctly -- for now
- * we are just going to assume that all options matched
- * and apply them.
+ * First we must sanity check that all config options acked are
+ * equal to the config options sent and are in the same order.
+ * If this is not the case, then silently drop the packet
*/
- while (i < len) {
- acked_option = extract_ppp_option(data, &packet->data[i]);
- if (acked_option == NULL)
- break;
+ for (i = 0, list = data->config_options; list; list = list->next) {
+ struct ppp_option *sent_option = list->data;
- list = g_list_find_custom(data->config_options,
- GUINT_TO_POINTER((guint) acked_option->type),
- is_option);
- if (list) {
- /*
- * once we've applied the option, delete it from
- * the config_options list.
- */
- if (action->option_process)
- action->option_process(data, acked_option);
+ if (sent_option->type != packet->data[i])
+ return 0;
- g_free(list->data);
- data->config_options =
- g_list_delete_link(data->config_options, list);
- } else
- g_printerr("oops -- found acked option %d we didn't request\n", acked_option->type);
+ if (sent_option->length != packet->data[i + 1])
+ return 0;
- /* skip ahead to the next option */
- i += acked_option->length;
+ if (memcmp(sent_option->data, packet->data + i + 2,
+ sent_option->length) != 0)
+ return 0;
- g_free(acked_option);
+ i += packet->data[i + 1];
}
+
+ /* Otherwise, apply local options */
+ if (action->rca)
+ action->rca(data, packet);
+
+ g_list_foreach(data->config_options, (GFunc)g_free, NULL);
+ g_list_free(data->config_options);
+ data->config_options = NULL;
+
return RCA;
}
diff --git a/gatchat/ppp_cp.h b/gatchat/ppp_cp.h
index 407cbd7e..71ad1de5 100644
--- a/gatchat/ppp_cp.h
+++ b/gatchat/ppp_cp.h
@@ -49,6 +49,13 @@ enum pppcp_code {
PPPCP_CODE_TYPE_DISCARD_REQUEST
};
+struct pppcp_packet {
+ guint8 code;
+ guint8 identifier;
+ guint16 length;
+ guint8 data[0];
+} __attribute__((packed));
+
struct ppp_option_iter {
guint16 max;
guint16 pos;
@@ -63,19 +70,14 @@ struct pppcp_action {
void (*this_layer_down)(struct pppcp_data *data);
void (*this_layer_started)(struct pppcp_data *data);
void (*this_layer_finished)(struct pppcp_data *data);
+ /* Remote side acked these options, we can now use them */
+ void (*rca)(struct pppcp_data *pppcp, const struct pppcp_packet *pkt);
enum option_rval (*option_scan)(struct pppcp_data *pppcp,
struct ppp_option *option);
void (*option_process)(struct pppcp_data *data,
struct ppp_option *option);
};
-struct pppcp_packet {
- guint8 code;
- guint8 identifier;
- guint16 length;
- guint8 data[0];
-} __attribute__((packed));
-
void ppp_option_iter_init(struct ppp_option_iter *iter,
const struct pppcp_packet *packet);
gboolean ppp_option_iter_next(struct ppp_option_iter *iter);
diff --git a/gatchat/ppp_ipcp.c b/gatchat/ppp_ipcp.c
index 19bd4fea..b8610666 100644
--- a/gatchat/ppp_ipcp.c
+++ b/gatchat/ppp_ipcp.c
@@ -108,6 +108,26 @@ static void ipcp_finished(struct pppcp_data *data)
g_print("ipcp finished\n");
}
+static void ipcp_rca(struct pppcp_data *pppcp,
+ const struct pppcp_packet *packet)
+{
+ struct ipcp_data *ipcp = pppcp_get_data(pppcp);
+ struct ppp_option_iter iter;
+
+ ppp_option_iter_init(&iter, packet);
+
+ while (ppp_option_iter_next(&iter) == TRUE) {
+ switch (ppp_option_iter_get_type(&iter)) {
+ case IP_ADDRESS:
+ memcpy(ipcp->ip_address,
+ ppp_option_iter_get_data(&iter), 4);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/*
* Scan the option to see if it is acceptable, unacceptable, or rejected
*/
@@ -136,9 +156,6 @@ static void ipcp_option_process(struct pppcp_data *pppcp,
struct ipcp_data *ipcp = pppcp_get_data(pppcp);
switch (option->type) {
- case IP_ADDRESS:
- memcpy(ipcp->ip_address, option->data, 4);
- break;
case PRIMARY_DNS_SERVER:
memcpy(ipcp->primary_dns, option->data, 4);
break;
@@ -162,6 +179,7 @@ struct pppcp_action ipcp_action = {
.this_layer_down = ipcp_down,
.this_layer_started = ipcp_started,
.this_layer_finished = ipcp_finished,
+ .rca = ipcp_rca,
.option_scan = ipcp_option_scan,
.option_process = ipcp_option_process,
};
diff --git a/gatchat/ppp_lcp.c b/gatchat/ppp_lcp.c
index 05acdfa2..4aec88dc 100644
--- a/gatchat/ppp_lcp.c
+++ b/gatchat/ppp_lcp.c
@@ -96,6 +96,23 @@ static void lcp_finished(struct pppcp_data *pppcp)
ppp_generate_event(pppcp_get_ppp(pppcp), PPP_DOWN);
}
+static void lcp_rca(struct pppcp_data *pppcp, const struct pppcp_packet *packet)
+{
+ struct ppp_option_iter iter;
+
+ ppp_option_iter_init(&iter, packet);
+
+ while (ppp_option_iter_next(&iter) == TRUE) {
+ switch (ppp_option_iter_get_type(&iter)) {
+ case ACCM:
+ ppp_set_xmit_accm(pppcp_get_ppp(pppcp), 0);
+ break;
+ default:
+ break;
+ }
+ }
+}
+
/*
* Scan the option to see if it is acceptable, unacceptable, or rejected
*
@@ -189,6 +206,7 @@ struct pppcp_action lcp_action = {
.this_layer_down = lcp_down,
.this_layer_started = lcp_started,
.this_layer_finished = lcp_finished,
+ .rca = lcp_rca,
.option_scan = lcp_option_scan,
.option_process = lcp_option_process,
};