From cf334808be3aa6e7346955009ef503fe24b02326 Mon Sep 17 00:00:00 2001 From: Mika Liljeberg Date: Mon, 7 Mar 2011 16:02:32 +0200 Subject: [PATCH] isimodem: IPv6 support --- drivers/isimodem/gprs-context.c | 119 +++++++++++++++++++------------- 1 file changed, 72 insertions(+), 47 deletions(-) diff --git a/drivers/isimodem/gprs-context.c b/drivers/isimodem/gprs-context.c index ad7abad1..329ef218 100644 --- a/drivers/isimodem/gprs-context.c +++ b/drivers/isimodem/gprs-context.c @@ -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;