mirror of git://git.sysmocom.de/ofono
ppp: Add rca callback
When the other side acks our options, then let us apply these options locally and start using them
This commit is contained in:
parent
5f361d7de9
commit
4e01f9921e
|
@ -997,8 +997,7 @@ static guint8 pppcp_process_configure_ack(struct pppcp_data *data,
|
||||||
{
|
{
|
||||||
guint len;
|
guint len;
|
||||||
GList *list;
|
GList *list;
|
||||||
struct ppp_option *acked_option;
|
guint i;
|
||||||
guint i = 0;
|
|
||||||
const struct pppcp_action *action = data->action;
|
const struct pppcp_action *action = data->action;
|
||||||
|
|
||||||
pppcp_trace(data);
|
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,
|
* First we must sanity check that all config options acked are
|
||||||
* then we can apply these option values.
|
* equal to the config options sent and are in the same order.
|
||||||
*
|
* If this is not the case, then silently drop the packet
|
||||||
* XXX what if it isn't? Do this correctly -- for now
|
|
||||||
* we are just going to assume that all options matched
|
|
||||||
* and apply them.
|
|
||||||
*/
|
*/
|
||||||
while (i < len) {
|
for (i = 0, list = data->config_options; list; list = list->next) {
|
||||||
acked_option = extract_ppp_option(data, &packet->data[i]);
|
struct ppp_option *sent_option = list->data;
|
||||||
if (acked_option == NULL)
|
|
||||||
break;
|
|
||||||
|
|
||||||
list = g_list_find_custom(data->config_options,
|
if (sent_option->type != packet->data[i])
|
||||||
GUINT_TO_POINTER((guint) acked_option->type),
|
return 0;
|
||||||
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);
|
|
||||||
|
|
||||||
g_free(list->data);
|
if (sent_option->length != packet->data[i + 1])
|
||||||
data->config_options =
|
return 0;
|
||||||
g_list_delete_link(data->config_options, list);
|
|
||||||
} else
|
|
||||||
g_printerr("oops -- found acked option %d we didn't request\n", acked_option->type);
|
|
||||||
|
|
||||||
/* skip ahead to the next option */
|
if (memcmp(sent_option->data, packet->data + i + 2,
|
||||||
i += acked_option->length;
|
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;
|
return RCA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,13 @@ enum pppcp_code {
|
||||||
PPPCP_CODE_TYPE_DISCARD_REQUEST
|
PPPCP_CODE_TYPE_DISCARD_REQUEST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct pppcp_packet {
|
||||||
|
guint8 code;
|
||||||
|
guint8 identifier;
|
||||||
|
guint16 length;
|
||||||
|
guint8 data[0];
|
||||||
|
} __attribute__((packed));
|
||||||
|
|
||||||
struct ppp_option_iter {
|
struct ppp_option_iter {
|
||||||
guint16 max;
|
guint16 max;
|
||||||
guint16 pos;
|
guint16 pos;
|
||||||
|
@ -63,19 +70,14 @@ struct pppcp_action {
|
||||||
void (*this_layer_down)(struct pppcp_data *data);
|
void (*this_layer_down)(struct pppcp_data *data);
|
||||||
void (*this_layer_started)(struct pppcp_data *data);
|
void (*this_layer_started)(struct pppcp_data *data);
|
||||||
void (*this_layer_finished)(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,
|
enum option_rval (*option_scan)(struct pppcp_data *pppcp,
|
||||||
struct ppp_option *option);
|
struct ppp_option *option);
|
||||||
void (*option_process)(struct pppcp_data *data,
|
void (*option_process)(struct pppcp_data *data,
|
||||||
struct ppp_option *option);
|
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,
|
void ppp_option_iter_init(struct ppp_option_iter *iter,
|
||||||
const struct pppcp_packet *packet);
|
const struct pppcp_packet *packet);
|
||||||
gboolean ppp_option_iter_next(struct ppp_option_iter *iter);
|
gboolean ppp_option_iter_next(struct ppp_option_iter *iter);
|
||||||
|
|
|
@ -108,6 +108,26 @@ static void ipcp_finished(struct pppcp_data *data)
|
||||||
g_print("ipcp finished\n");
|
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
|
* 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);
|
struct ipcp_data *ipcp = pppcp_get_data(pppcp);
|
||||||
|
|
||||||
switch (option->type) {
|
switch (option->type) {
|
||||||
case IP_ADDRESS:
|
|
||||||
memcpy(ipcp->ip_address, option->data, 4);
|
|
||||||
break;
|
|
||||||
case PRIMARY_DNS_SERVER:
|
case PRIMARY_DNS_SERVER:
|
||||||
memcpy(ipcp->primary_dns, option->data, 4);
|
memcpy(ipcp->primary_dns, option->data, 4);
|
||||||
break;
|
break;
|
||||||
|
@ -162,6 +179,7 @@ struct pppcp_action ipcp_action = {
|
||||||
.this_layer_down = ipcp_down,
|
.this_layer_down = ipcp_down,
|
||||||
.this_layer_started = ipcp_started,
|
.this_layer_started = ipcp_started,
|
||||||
.this_layer_finished = ipcp_finished,
|
.this_layer_finished = ipcp_finished,
|
||||||
|
.rca = ipcp_rca,
|
||||||
.option_scan = ipcp_option_scan,
|
.option_scan = ipcp_option_scan,
|
||||||
.option_process = ipcp_option_process,
|
.option_process = ipcp_option_process,
|
||||||
};
|
};
|
||||||
|
|
|
@ -96,6 +96,23 @@ static void lcp_finished(struct pppcp_data *pppcp)
|
||||||
ppp_generate_event(pppcp_get_ppp(pppcp), PPP_DOWN);
|
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
|
* 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_down = lcp_down,
|
||||||
.this_layer_started = lcp_started,
|
.this_layer_started = lcp_started,
|
||||||
.this_layer_finished = lcp_finished,
|
.this_layer_finished = lcp_finished,
|
||||||
|
.rca = lcp_rca,
|
||||||
.option_scan = lcp_option_scan,
|
.option_scan = lcp_option_scan,
|
||||||
.option_process = lcp_option_process,
|
.option_process = lcp_option_process,
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in New Issue