diff options
-rw-r--r-- | gatchat/ppp_cp.c | 53 | ||||
-rw-r--r-- | gatchat/ppp_cp.h | 16 | ||||
-rw-r--r-- | gatchat/ppp_ipcp.c | 24 | ||||
-rw-r--r-- | gatchat/ppp_lcp.c | 18 |
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, }; |