isimodem: IPv6 support

This commit is contained in:
Mika Liljeberg 2011-03-07 16:02:32 +02:00 committed by Denis Kenzior
parent 247df07644
commit cf334808be
1 changed files with 72 additions and 47 deletions

View File

@ -62,10 +62,7 @@ struct context_data {
uint16_t gpds; /* GPDS object handle */
unsigned cid; /* oFono core context ID */
struct ofono_gprs_context *context;
union {
ofono_gprs_context_up_cb_t up_cb;
ofono_gprs_context_cb_t down_cb;
};
ofono_gprs_context_cb_t cb;
void *data;
GIsiPEP *pep;
@ -112,15 +109,14 @@ typedef void (*ContextFailFunc)(struct context_data *cd);
static void gprs_up_fail(struct context_data *cd)
{
CALLBACK_WITH_FAILURE(cd->up_cb, NULL, 0, NULL, NULL, NULL, NULL,
cd->data);
reset_context(cd);
CALLBACK_WITH_FAILURE(cd->cb, cd->data);
}
static void gprs_down_fail(struct context_data *cd)
{
CALLBACK_WITH_FAILURE(cd->down_cb, cd->data);
reset_context(cd);
CALLBACK_WITH_FAILURE(cd->cb, cd->data);
}
static gboolean check_resp(const GIsiMessage *msg, uint8_t id, size_t minlen,
@ -206,12 +202,12 @@ static void activate_ind_cb(const GIsiMessage *msg, void *opaque)
{
struct context_data *cd = opaque;
GIsiSubBlockIter iter;
const char *dns[5];
int dns_count = 0;
char ifname[IF_NAMESIZE];
char *ip = NULL;
char *pdns = NULL;
char *sdns = NULL;
const char *dns[3];
char *ip_addr = NULL;
char *ipv6_addr = NULL;
if (!check_ind(msg, 2, cd))
return;
@ -225,8 +221,6 @@ static void activate_ind_cb(const GIsiMessage *msg, void *opaque)
switch (g_isi_sb_iter_get_id(&iter)) {
/* TODO: IPv6 address support */
case GPDS_PDP_ADDRESS_INFO:
if (!g_isi_sb_iter_get_byte(&iter, &addr_len, 3))
@ -236,9 +230,15 @@ static void activate_ind_cb(const GIsiMessage *msg, void *opaque)
4))
goto error;
ip = alloca(INET_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)addr_value, ip,
INET_ADDRSTRLEN);
if (addr_len == 4) {
ip_addr = alloca(INET_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)addr_value,
ip_addr, INET_ADDRSTRLEN);
} else if (addr_len == 16) {
ipv6_addr = alloca(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, (const void *)addr_value,
ipv6_addr, INET6_ADDRSTRLEN);
}
break;
case GPDS_PDNS_ADDRESS_INFO:
@ -250,9 +250,17 @@ static void activate_ind_cb(const GIsiMessage *msg, void *opaque)
4))
break;
pdns = alloca(INET_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)addr_value, pdns,
INET_ADDRSTRLEN);
if (addr_len == 4) {
char *addr = alloca(INET_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)addr_value,
addr, INET_ADDRSTRLEN);
dns[dns_count++] = addr;
} else if (addr_len == 16) {
char *addr = alloca(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, (const void *)addr_value,
addr, INET6_ADDRSTRLEN);
dns[dns_count++] = addr;
}
break;
case GPDS_SDNS_ADDRESS_INFO:
@ -264,9 +272,17 @@ static void activate_ind_cb(const GIsiMessage *msg, void *opaque)
4))
break;
sdns = alloca(INET_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)addr_value, sdns,
INET_ADDRSTRLEN);
if (addr_len == 4) {
char *addr = alloca(INET_ADDRSTRLEN);
inet_ntop(AF_INET, (const void *)addr_value,
addr, INET_ADDRSTRLEN);
dns[dns_count++] = addr;
} else if (addr_len == 16) {
char *addr = alloca(INET6_ADDRSTRLEN);
inet_ntop(AF_INET6, (const void *)addr_value,
addr, INET6_ADDRSTRLEN);
dns[dns_count++] = addr;
}
break;
default:
@ -279,29 +295,27 @@ static void activate_ind_cb(const GIsiMessage *msg, void *opaque)
if (!g_isi_pep_get_ifname(cd->pep, ifname))
goto error;
dns[0] = pdns;
dns[1] = sdns;
dns[2] = 0;
dns[dns_count] = 0;
CALLBACK_WITH_SUCCESS(cd->up_cb, ifname, TRUE, (const char *)ip,
STATIC_IP_NETMASK, NULL,
dns, cd->data);
ofono_gprs_context_set_interface(cd->context, ifname);
if (ip_addr != NULL) {
ofono_gprs_context_set_ipv4_address(cd->context, ip_addr, TRUE);
ofono_gprs_context_set_ipv4_netmask(cd->context,
STATIC_IP_NETMASK);
ofono_gprs_context_set_ipv4_dns_servers(cd->context, dns);
} else if (ipv6_addr != NULL) {
ofono_gprs_context_set_ipv6_address(cd->context, ipv6_addr);
ofono_gprs_context_set_ipv6_dns_servers(cd->context, dns);
}
CALLBACK_WITH_SUCCESS(cd->cb, cd->data);
return;
error:
gprs_up_fail(cd);
}
static void activate_fail_ind_cb(const GIsiMessage *msg, void *opaque)
{
struct context_data *cd = opaque;
if (!check_ind(msg, 2, cd))
return;
gprs_up_fail(cd);
}
static void context_activate_cb(const GIsiMessage *msg, void *cd)
{
check_resp(msg, GPDS_CONTEXT_ACTIVATE_RESP, 6, cd, gprs_up_fail);
@ -319,8 +333,6 @@ static void send_context_activate(GIsiClient *client, void *opaque)
g_isi_client_ind_subscribe(client, GPDS_CONTEXT_ACTIVATE_IND,
activate_ind_cb, cd);
g_isi_client_ind_subscribe(client, GPDS_CONTEXT_ACTIVATE_FAIL_IND,
activate_fail_ind_cb, cd);
g_isi_client_ind_subscribe(client, GPDS_CONTEXT_DEACTIVATE_IND,
deactivate_ind_cb, cd);
@ -478,7 +490,7 @@ static void create_pipe_cb(GIsiPipe *pipe)
static void isi_gprs_activate_primary(struct ofono_gprs_context *gc,
const struct ofono_gprs_primary_context *ctx,
ofono_gprs_context_up_cb_t cb, void *data)
ofono_gprs_context_cb_t cb, void *data)
{
struct context_data *cd = ofono_gprs_context_get_data(gc);
@ -486,8 +498,7 @@ static void isi_gprs_activate_primary(struct ofono_gprs_context *gc,
if (cd == NULL || !cd->gpds) {
/* GPDS is not reachable */
CALLBACK_WITH_FAILURE(cb, NULL, 0, NULL, NULL, NULL,
NULL, data);
CALLBACK_WITH_FAILURE(cb, data);
return;
}
@ -498,12 +509,26 @@ static void isi_gprs_activate_primary(struct ofono_gprs_context *gc,
}
cd->cid = ctx->cid;
cd->up_cb = cb;
cd->cb = cb;
cd->data = data;
cd->pep = NULL;
cd->pipe = NULL;
cd->handle = INVALID_ID;
cd->type = GPDS_PDP_TYPE_IPV4;
switch (ctx->proto) {
case OFONO_GPRS_PROTO_IP:
cd->type = GPDS_PDP_TYPE_IPV4;
break;
case OFONO_GPRS_PROTO_IPV6:
cd->type = GPDS_PDP_TYPE_IPV6;
break;
case OFONO_GPRS_PROTO_IPV4V6:
/* Not supported by modem */
CALLBACK_WITH_FAILURE(cb, data);
return;
}
if (strlen(ctx->apn) >= GPDS_MAX_APN_STRING_LENGTH
|| strlen(ctx->username) >= GPDS_MAX_USERNAME_LENGTH
@ -545,7 +570,7 @@ static void context_deactivate_cb(const GIsiMessage *msg, void *opaque)
gprs_down_fail))
return;
CALLBACK_WITH_SUCCESS(cd->down_cb, cd->data);
CALLBACK_WITH_SUCCESS(cd->cb, cd->data);
reset_context(cd);
}
@ -563,7 +588,7 @@ static void isi_gprs_deactivate_primary(struct ofono_gprs_context *gc,
if (cd == NULL)
return;
cd->down_cb = cb;
cd->cb = cb;
cd->data = data;
msg[1] = cd->handle;