int ifc_configure(const char *ifname,
        in_addr_t address,
        in_addr_t gateway)
{
    in_addr_t netmask = ~0;
    (void) gateway;

    ifc_init();

    if (ifc_up(ifname)) {
	LOGE("%s() Failed to turn on interface %s: %s", __func__,
	     ifname,
	     strerror(errno));
	ifc_close();
	return -1;
    }
    if (ifc_set_addr(ifname, address)) {
	LOGE("%s() Failed to set ipaddr %s: %s", __func__,
	     ipaddr_to_string(address), strerror(errno));
	ifc_down(ifname);
	ifc_close();
	return -1;
    }
    if (ifc_set_mask(ifname, netmask)) {
	LOGE("%s() failed to set netmask %s: %s", __func__,
	     ipaddr_to_string(netmask), strerror(errno));
	ifc_down(ifname);
	ifc_close();
	return -1;
    }

    ifc_close();

    return 0;
}
int set_iface(const char *iface, int on)
{
    int u4Count = 0;

    if(ifc_init() != 0) {
        LOGE("[%s] interface set %d failed", iface, on);
        return -1;
    }
    if(on) {
        while(ifc_up(iface) == -1) {
            LOGD("[%s] interface is not ready, wait %dus", iface, SET_IFACE_DELAY);
            sched_yield();
            usleep(SET_IFACE_DELAY);
            if (++u4Count >= SET_IFACE_POLLING_LOOP) {
                LOGE("[%s] interface set %d failed", iface, on);
                ifc_close();
                return -1;
            }
        }
        LOGD("[%s] interface is up", iface);
        init_iface(iface);
    }
    else {
        ifc_down(iface);
        LOGD("[%s] interface is down", iface);
    }
    ifc_close();
    return 0;
}
int ifc_disable(const char *ifname)
{
    int result;

    ifc_init();
    result = ifc_down(ifname);
    ifc_set_addr(ifname, 0);
    ifc_close();
    return result;
}
示例#4
0
int ifc_disable(const char *ifname)
{
    unsigned addr, count;
    int result;

    ifc_init();
    result = ifc_down(ifname);

    ifc_set_addr(ifname, 0);
    for (count=0, addr=1; ((addr != 0) && (count < 255)); count++) {
        if (ifc_get_addr(ifname, &addr) < 0)
            break;
        if (addr)
            ifc_set_addr(ifname, 0);
    }

    ifc_close();
    return result;
}
示例#5
0
/* CHECK There are several error cases if PDP deactivation fails
 * 24.008: 8, 25, 36, 38, 39, 112
 */
void requestDeactivateDefaultPDP(void *data, size_t datalen, RIL_Token t)
{
    int e2napState = getE2napState();
    int cid = atoi(((const char **) data)[0]);
    (void) datalen;

    if (cid != s_ActiveCID) {
        ALOGD("%s() Not tearing down cid:%d since cid:%d is active", __func__,
                cid, s_ActiveCID);
        goto done;
    }

    s_DeactCalled = 1;

    if (e2napState == E2NAP_STATE_CONNECTING)
        ALOGW("%s() Tear down connection while connection setup in progress", __func__);

    if (e2napState != E2NAP_STATE_DISCONNECTED) {
        if (disconnect())
            goto error;

        e2napState = getE2napState();

        if (e2napState != E2NAP_STATE_DISCONNECTED)
            goto error;

        /* Bring down the interface as well. */
        if (ifc_init())
            goto error;

        if (ifc_down(ril_iface))
            goto error;

        ifc_close();
    }

done:
    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
}
示例#6
0
int ipc_gprs_connection_disable(struct ril_gprs_connection *gprs_connection)
{
	struct ipc_client *ipc_client;

	char *interface;
	int rc;

	ipc_client = ((struct ipc_client_object *) ipc_fmt_client->object)->ipc_client;

	if(gprs_connection->interface == NULL) {
		interface = ipc_client_gprs_get_iface(ipc_client, gprs_connection->cid);
		if(interface == NULL) {
			// This is not a critical issue, fallback to rmnet
			LOGE("Failed to get interface name!");
			asprintf(&interface, "rmnet%d", gprs_connection->cid);
		}
	} else {
		interface = gprs_connection->interface;
	}

	LOGD("Using net interface: %s\n", interface);

	rc = ifc_down(interface);

	if(gprs_connection->interface == NULL)
		free(interface);

	if(rc < 0) {
		LOGE("ifc_down failed");
	}

	if(ipc_client_gprs_handlers_available(ipc_client)) {
		rc = ipc_client_gprs_deactivate(ipc_client);
		if(rc < 0) {
			// This is not a critical issue
			LOGE("Failed to deactivate interface!");
		}
	}

	return 0;
}
示例#7
0
int SoftapController::stopDriver(char *iface) {
    int ret;

    if (mSock < 0) {
        LOGE("Softap driver stop - failed to open socket");
        return -1;
    }
    if (!iface || (iface[0] == '\0')) {
        LOGD("Softap driver stop - wrong interface");
        iface = mIface;
    }
    *mBuf = 0;
#ifdef HAVE_HOSTAPD
    ifc_init();
    ret = ifc_down(iface);
    ifc_close();
    if (ret < 0) {
        LOGE("Softap %s down: %d", iface, ret);
    }
#endif
    ret = setCommand(iface, "STOP");
    LOGD("Softap driver stop: %d", ret);
    return ret;
}
示例#8
0
int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
        return 0;
    }

    if (!strcmp(argv[1], "list")) {
        DIR *d;
        struct dirent *de;

        if (!(d = opendir("/sys/class/net"))) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
            return 0;
        }

        while((de = readdir(d))) {
            if (de->d_name[0] == '.')
                continue;
            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
        }
        closedir(d);
        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
        return 0;
    } else if (!strcmp(argv[1], "readrxcounter")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface readrxcounter <interface>", false);
            return 0;
        }
        unsigned long rx = 0, tx = 0;
        if (readInterfaceCounters(argv[2], &rx, &tx)) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
            return 0;
        }

        char *msg;
        asprintf(&msg, "%lu", rx);
        cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
        free(msg);

        return 0;
    } else if (!strcmp(argv[1], "readtxcounter")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface readtxcounter <interface>", false);
            return 0;
        }
        unsigned long rx = 0, tx = 0;
        if (readInterfaceCounters(argv[2], &rx, &tx)) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
            return 0;
        }

        char *msg = NULL;
        asprintf(&msg, "%lu", tx);
        cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
        free(msg);
        return 0;
    } else if (!strcmp(argv[1], "getthrottle")) {
        if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface getthrottle <interface> <rx|tx>", false);
            return 0;
        }
        int val = 0;
        int rc = 0;
        int voldRc = ResponseCode::InterfaceRxThrottleResult;

        if (!strcmp(argv[3], "rx")) {
            rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
        } else {
            rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
            voldRc = ResponseCode::InterfaceTxThrottleResult;
        }
        if (rc) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
        } else {
            char *msg = NULL;
            asprintf(&msg, "%u", val);
            cli->sendMsg(voldRc, msg, false);
            free(msg);
            return 0;
        }
        return 0;
    } else if (!strcmp(argv[1], "setthrottle")) {
        if (argc != 5) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
            return 0;
        }
        if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
        } else {
            cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
        }
        return 0;
    } else {
        /*
         * These commands take a minimum of 3 arguments
         */
        if (argc < 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
            return 0;
        }
        if (!strcmp(argv[1], "getcfg")) {
            struct in_addr addr, mask;
            unsigned char hwaddr[6];
            unsigned flags = 0;

            ifc_init();
            memset(hwaddr, 0, sizeof(hwaddr));

            if (ifc_get_info(argv[2], &addr.s_addr, &mask.s_addr, &flags)) {
                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
                return 0;
            }

            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
                LOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
            }

            char *addr_s = strdup(inet_ntoa(addr));
            char *mask_s = strdup(inet_ntoa(mask));
            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;

            updown =  (flags & IFF_UP)           ? "up" : "down";
            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
            running = (flags & IFF_RUNNING)      ? " running" : "";
            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";

            char *flag_s;

            asprintf(&flag_s, "[%s%s%s%s%s%s]", updown, brdcst, loopbk, ppp, running, multi);

            char *msg = NULL;
            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %s %s",
                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
                     addr_s, mask_s, flag_s);

            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);

            free(addr_s);
            free(mask_s);
            free(flag_s);
            free(msg);
            return 0;
        } else if (!strcmp(argv[1], "setcfg")) {
            // arglist: iface addr mask [flags]
            if (argc < 5) {
                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
                return 0;
            }
            LOGD("Setting iface cfg");

            struct in_addr addr, mask;
            unsigned flags = 0;

            if (!inet_aton(argv[3], &addr)) {
                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid address", false);
                return 0;
            }

            if (!inet_aton(argv[4], &mask)) {
                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid netmask", false);
                return 0;
            }

            ifc_init();
            if (ifc_set_addr(argv[2], addr.s_addr)) {
                cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
                return 0;
            }

            if (ifc_set_mask(argv[2], mask.s_addr)) {
                cli->sendMsg(ResponseCode::OperationFailed, "Failed to set netmask", true);
                return 0;
            }

            /* Process flags */
            /* read from "[XX" arg to "YY]" arg */
            bool bStarted = false;
            for (int i = 5; i < argc; i++) {
                char *flag = argv[i];
                if (!bStarted) {
                    if (*flag == '[') {
                        flag++;
                        bStarted = true;
                    } else {
                        continue;
                    }
                }
                int len = strlen(flag);
                if (flag[len-1] == ']') {
                    i = argc;  // stop after this loop
                    flag[len-1] = 0;
                }
                if (!strcmp(flag, "up")) {
                    LOGD("Trying to bring up %s", argv[2]);
                    if (ifc_up(argv[2])) {
                        LOGE("Error upping interface");
                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
                        return 0;
                    }
                } else if (!strcmp(flag, "down")) {
                    LOGD("Trying to bring down %s", argv[2]);
                    if (ifc_down(argv[2])) {
                        LOGE("Error downing interface");
                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
                        return 0;
                    }
                } else if (!strcmp(flag, "broadcast")) {
                    LOGD("broadcast flag ignored");
                } else if (!strcmp(flag, "multicast")) {
                    LOGD("multicast flag ignored");
                } else {
                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
                    return 0;
                }
            }
            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
            return 0;
        } else {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
            return 0;
        }
    }
    return 0;
}
/* CHECK There are several error cases if PDP deactivation fails
 * 24.008: 8, 25, 36, 38, 39, 112
 */
void requestDeactivateDefaultPDP(void *data, size_t datalen, RIL_Token t)
{
    ATResponse *p_response = NULL;
    int enap = 0;
    int err, i;
    char *line;
    (void) data;
    (void) datalen;

    err = at_send_command_singleline("AT*ENAP?", "*ENAP:", &p_response);
    if (err != AT_NOERROR)
        goto error;

    line = p_response->p_intermediates->line;
    err = at_tok_start(&line);
    if (err < 0)
        goto error;

    err = at_tok_nextint(&line, &enap);
    if (err < 0)
        goto error;

    if (enap == ENAP_T_CONN_IN_PROG)
        LOGE("%s() Tear down connection while connection setup in progress", __func__);

    if (enap == ENAP_T_CONNECTED) {
        err = at_send_command("AT*ENAP=0"); /* TODO: can return CME error */

        if (err != AT_NOERROR && at_get_error_type(err) != CME_ERROR)
            goto error;
        for (i = 0; i < MBM_ENAP_WAIT_TIME; i++) {
            at_response_free(p_response);
            p_response = NULL;
            err = at_send_command_singleline("AT*ENAP?", "*ENAP:", &p_response);

            if (err != AT_NOERROR)
                goto error;

            line = p_response->p_intermediates->line;

            err = at_tok_start(&line);
            if (err < 0)
                goto error;

            err = at_tok_nextint(&line, &enap);
            if (err < 0)
                goto error;

            if (enap == 0)
                break;

            sleep(1);
        }

        if (enap != ENAP_T_NOT_CONNECTED)
            goto error;

        /* Bring down the interface as well. */
        if (ifc_init())
            goto error;

        if (ifc_down(ril_iface))
            goto error;

        ifc_close();
    }

    RIL_onRequestComplete(t, RIL_E_SUCCESS, NULL, 0);
    at_response_free(p_response);
    return;

error:
    RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
    at_response_free(p_response);
}
void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t)
{
    in_addr_t addr;
    in_addr_t gateway;

    const char *apn, *user, *pass, *auth;
    char *addresses = NULL;
    char *gateways = NULL;
    char *dnses = NULL;
    const char *type = NULL;

    RIL_Data_Call_Response_v6 response;

    int err = -1;
    int cme_err, i;

    int e2napState = setE2napState(-1);
    int e2napCause = setE2napCause(-1);

    (void) data;
    (void) datalen;

    memset(&response, 0, sizeof(response));

    apn = ((const char **) data)[2];
    user = ((const char **) data)[3];
    pass = ((const char **) data)[4];
    auth = ((const char **) data)[5];
    type = getNWType(((const char **) data)[6]);

    s_lastPdpFailCause = PDP_FAIL_ERROR_UNSPECIFIED;

    LOGD("%s() requesting data connection to APN '%s'", __func__, apn);

    if (ifc_init()) {
        LOGE("%s() FAILED to set up ifc!", __func__);
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    if (ifc_down(ril_iface)) {
        LOGE("%s() Failed to bring down %s!", __func__, ril_iface);
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    err = at_send_command("AT+CGDCONT=%d,\"IP\",\"%s\"", RIL_CID_IP, apn);
    if (err != AT_NOERROR) {
        cme_err = at_get_cme_error(err);
        LOGE("%s() CGDCONT failed: %d, cme: %d", __func__, err, cme_err);
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    if (networkAuth(auth, user, pass, RIL_CID_IP)) {
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    /* Start data on PDP context for IP */
    err = at_send_command("AT*ENAP=1,%d", RIL_CID_IP);
    if (err != AT_NOERROR) {
        cme_err = at_get_cme_error(err);
        LOGE("requestSetupDefaultPDP: ENAP failed: %d  cme: %d", err, cme_err);
        goto error;
    }

    for (i = 0; i < MBM_ENAP_WAIT_TIME; i++) {
        e2napState = getE2napState();

        if (e2napState == E2NAP_ST_CONNECTED
                || e2napState == E2NAP_ST_DISCONNECTED) {
            LOGD("%s() %s", __func__, e2napStateToString(e2napState));
            break;
        }
        usleep(200 * 1000);
    }

    e2napState = getE2napState();
    e2napCause = getE2napCause();

    if (e2napState == E2NAP_ST_DISCONNECTED)
        goto error;

    if (parse_ip_information(&addresses, &gateways, &dnses, &addr, &gateway) < 0) {
        LOGE("%s() Failed to parse network interface data", __func__);
        goto error;
    }

    e2napState = getE2napState();
    response.addresses = addresses;
    response.gateways = gateways;
    response.dnses = dnses;
    LOGI("%s() Setting up interface %s,%s,%s",
        __func__, response.addresses, response.gateways, response.dnses);

    if (e2napState == E2NAP_ST_DISCONNECTED)
        goto error; /* we got disconnected */

    response.ifname = ril_iface;
    response.active = 2;
    response.type = (char *) type;
    response.status = 0;
    response.cid = 1;
    response.suggestedRetryTime = -1;

    /* Don't use android netutils. We use our own and get the routing correct.
     * Carl Nordbeck */
    if (ifc_configure(ril_iface, addr, gateway))
        LOGE("%s() Failed to configure the interface %s", __func__, ril_iface);

    e2napState = getE2napState();
    LOGI("IP Address %s, %s", addresses, e2napStateToString(e2napState));

    if (e2napState == E2NAP_ST_DISCONNECTED)
        goto error; /* we got disconnected */

    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));

    free(addresses);
    free(gateways);
    free(dnses);

    return;

error:

    response.status = getE2NAPFailCause();

    mbm_check_error_cause();

    /* Restore enap state and wait for enap to report disconnected*/
    at_send_command("AT*ENAP=0");
    for (i = 0; i < MBM_ENAP_WAIT_TIME; i++) {
        e2napState = getE2napState();
        if (e2napState == E2NAP_ST_DISCONNECTED)
            break;

        usleep(200 * 1000);
    }

    if (response.status > 0)
        RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
    else
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);

    free(addresses);
    free(gateways);
    free(dnses);
}
int CommandListener::InterfaceCmd::runCommand(SocketClient *cli,
                                                      int argc, char **argv) {
    if (argc < 2) {
        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
        return 0;
    }

    if (!strcmp(argv[1], "list")) {
        DIR *d;
        struct dirent *de;

        if (!(d = opendir("/sys/class/net"))) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to open sysfs dir", true);
            return 0;
        }

        while((de = readdir(d))) {
            if (de->d_name[0] == '.')
                continue;
            cli->sendMsg(ResponseCode::InterfaceListResult, de->d_name, false);
        }
        closedir(d);
        cli->sendMsg(ResponseCode::CommandOkay, "Interface list completed", false);
        return 0;
    } else if (!strcmp(argv[1], "readrxcounter")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface readrxcounter <interface>", false);
            return 0;
        }
        unsigned long rx = 0, tx = 0;
        if (readInterfaceCounters(argv[2], &rx, &tx)) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
            return 0;
        }

        char *msg;
        asprintf(&msg, "%lu", rx);
        cli->sendMsg(ResponseCode::InterfaceRxCounterResult, msg, false);
        free(msg);

        return 0;
    } else if (!strcmp(argv[1], "readtxcounter")) {
        if (argc != 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface readtxcounter <interface>", false);
            return 0;
        }
        unsigned long rx = 0, tx = 0;
        if (readInterfaceCounters(argv[2], &rx, &tx)) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to read counters", true);
            return 0;
        }

        char *msg = NULL;
        asprintf(&msg, "%lu", tx);
        cli->sendMsg(ResponseCode::InterfaceTxCounterResult, msg, false);
        free(msg);
        return 0;
    } else if (!strcmp(argv[1], "getthrottle")) {
        if (argc != 4 || (argc == 4 && (strcmp(argv[3], "rx") && (strcmp(argv[3], "tx"))))) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface getthrottle <interface> <rx|tx>", false);
            return 0;
        }
        int val = 0;
        int rc = 0;
        int voldRc = ResponseCode::InterfaceRxThrottleResult;

        if (!strcmp(argv[3], "rx")) {
            rc = ThrottleController::getInterfaceRxThrottle(argv[2], &val);
        } else {
            rc = ThrottleController::getInterfaceTxThrottle(argv[2], &val);
            voldRc = ResponseCode::InterfaceTxThrottleResult;
        }
        if (rc) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to get throttle", true);
        } else {
            char *msg = NULL;
            asprintf(&msg, "%u", val);
            cli->sendMsg(voldRc, msg, false);
            free(msg);
            return 0;
        }
        return 0;
    } else if (!strcmp(argv[1], "setthrottle")) {
        if (argc != 5) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface setthrottle <interface> <rx_kbps> <tx_kbps>", false);
            return 0;
        }
        if (ThrottleController::setInterfaceThrottle(argv[2], atoi(argv[3]), atoi(argv[4]))) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to set throttle", true);
        } else {
            cli->sendMsg(ResponseCode::CommandOkay, "Interface throttling set", false);
        }
        return 0;
    } else if (!strcmp(argv[1], "driver")) {
        int rc;
        char *rbuf;

        if (argc < 4) {
            cli->sendMsg(ResponseCode::CommandSyntaxError,
                    "Usage: interface driver <interface> <cmd> <args>", false);
            return 0;
        }
        rc = sInterfaceCtrl->interfaceCommand(argc, argv, &rbuf);
        if (rc) {
            cli->sendMsg(ResponseCode::OperationFailed, "Failed to execute command", true);
        } else {
            cli->sendMsg(ResponseCode::CommandOkay, rbuf, false);
        }
        return 0;
    } else {
        /*
         * These commands take a minimum of 3 arguments
         */
        if (argc < 3) {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
            return 0;
        }

        //     0       1       2        3          4           5     6      7
        // interface route add/remove iface default/secondary dest prefix gateway
        if (!strcmp(argv[1], "route")) {
            int prefix_length = 0;
            if (argc < 8) {
                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
                return 0;
            }
            if (sscanf(argv[6], "%d", &prefix_length) != 1) {
                cli->sendMsg(ResponseCode::CommandParameterError, "Invalid route prefix", false);
                return 0;
            }
            if (!strcmp(argv[2], "add")) {
                if (!strcmp(argv[4], "default")) {
                    if (ifc_add_route(argv[3], argv[5], prefix_length, argv[7])) {
                        cli->sendMsg(ResponseCode::OperationFailed,
                                "Failed to add route to default table", true);
                    } else {
                        cli->sendMsg(ResponseCode::CommandOkay,
                                "Route added to default table", false);
                    }
                } else if (!strcmp(argv[4], "secondary")) {
                    return sSecondaryTableCtrl->addRoute(cli, argv[3], argv[5],
                            prefix_length, argv[7]);
                } else {
                    cli->sendMsg(ResponseCode::CommandParameterError,
                            "Invalid route type, expecting 'default' or 'secondary'", false);
                    return 0;
                }
            } else if (!strcmp(argv[2], "remove")) {
                if (!strcmp(argv[4], "default")) {
                    if (ifc_remove_route(argv[3], argv[5], prefix_length, argv[7])) {
                        cli->sendMsg(ResponseCode::OperationFailed,
                                "Failed to remove route from default table", true);
                    } else {
                        cli->sendMsg(ResponseCode::CommandOkay,
                                "Route removed from default table", false);
                    }
                } else if (!strcmp(argv[4], "secondary")) {
                    return sSecondaryTableCtrl->removeRoute(cli, argv[3], argv[5],
                            prefix_length, argv[7]);
                } else {
                    cli->sendMsg(ResponseCode::CommandParameterError,
                            "Invalid route type, expecting 'default' or 'secondary'", false);
                    return 0;
                }
            } else {
                cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
            }
            return 0;
        }

        if (!strcmp(argv[1], "getcfg")) {
            struct in_addr addr;
            int prefixLength;
            unsigned char hwaddr[6];
            unsigned flags = 0;

            ifc_init();
            memset(hwaddr, 0, sizeof(hwaddr));

            if (ifc_get_info(argv[2], &addr.s_addr, &prefixLength, &flags)) {
                cli->sendMsg(ResponseCode::OperationFailed, "Interface not found", true);
                ifc_close();
                return 0;
            }

            if (ifc_get_hwaddr(argv[2], (void *) hwaddr)) {
                ALOGW("Failed to retrieve HW addr for %s (%s)", argv[2], strerror(errno));
            }

            char *addr_s = strdup(inet_ntoa(addr));
            const char *updown, *brdcst, *loopbk, *ppp, *running, *multi;

            updown =  (flags & IFF_UP)           ? "up" : "down";
            brdcst =  (flags & IFF_BROADCAST)    ? " broadcast" : "";
            loopbk =  (flags & IFF_LOOPBACK)     ? " loopback" : "";
            ppp =     (flags & IFF_POINTOPOINT)  ? " point-to-point" : "";
            running = (flags & IFF_RUNNING)      ? " running" : "";
            multi =   (flags & IFF_MULTICAST)    ? " multicast" : "";

            char *flag_s;

            asprintf(&flag_s, "%s%s%s%s%s%s", updown, brdcst, loopbk, ppp, running, multi);

            char *msg = NULL;
            asprintf(&msg, "%.2x:%.2x:%.2x:%.2x:%.2x:%.2x %s %d %s",
                     hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5],
                     addr_s, prefixLength, flag_s);

            cli->sendMsg(ResponseCode::InterfaceGetCfgResult, msg, false);

            free(addr_s);
            free(flag_s);
            free(msg);

            ifc_close();
            return 0;
        } else if (!strcmp(argv[1], "setcfg")) {
            // arglist: iface [addr prefixLength] flags
            if (argc < 4) {
                cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing argument", false);
                return 0;
            }
            ALOGD("Setting iface cfg");

            struct in_addr addr;
            unsigned flags = 0;
            int index = 5;

            ifc_init();

            if (!inet_aton(argv[3], &addr)) {
                // Handle flags only case
                index = 3;
            } else {
                if (ifc_set_addr(argv[2], addr.s_addr)) {
                    cli->sendMsg(ResponseCode::OperationFailed, "Failed to set address", true);
                    ifc_close();
                    return 0;
                }

                // Set prefix length on a non zero address
                if (addr.s_addr != 0 && ifc_set_prefixLength(argv[2], atoi(argv[4]))) {
                   cli->sendMsg(ResponseCode::OperationFailed, "Failed to set prefixLength", true);
                   ifc_close();
                   return 0;
               }
            }

            /* Process flags */
            for (int i = index; i < argc; i++) {
                char *flag = argv[i];
                if (!strcmp(flag, "up")) {
                    ALOGD("Trying to bring up %s", argv[2]);
                    if (ifc_up(argv[2])) {
                        ALOGE("Error upping interface");
                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to up interface", true);
                        ifc_close();
                        return 0;
                    }
                } else if (!strcmp(flag, "down")) {
                    ALOGD("Trying to bring down %s", argv[2]);
                    if (ifc_down(argv[2])) {
                        ALOGE("Error downing interface");
                        cli->sendMsg(ResponseCode::OperationFailed, "Failed to down interface", true);
                        ifc_close();
                        return 0;
                    }
                } else if (!strcmp(flag, "broadcast")) {
                    // currently ignored
                } else if (!strcmp(flag, "multicast")) {
                    // currently ignored
                } else if (!strcmp(flag, "running")) {
                    // currently ignored
                } else if (!strcmp(flag, "loopback")) {
                    // currently ignored
                } else if (!strcmp(flag, "point-to-point")) {
                    // currently ignored
                } else {
                    cli->sendMsg(ResponseCode::CommandParameterError, "Flag unsupported", false);
                    ifc_close();
                    return 0;
                }
            }

            cli->sendMsg(ResponseCode::CommandOkay, "Interface configuration set", false);
            ifc_close();
            return 0;
        } else if (!strcmp(argv[1], "clearaddrs")) {
            // arglist: iface
            ALOGD("Clearing all IP addresses on %s", argv[2]);

            ifc_clear_addresses(argv[2]);

            cli->sendMsg(ResponseCode::CommandOkay, "Interface IP addresses cleared", false);
            return 0;
        } else if (!strcmp(argv[1], "ipv6privacyextensions")) {
            if (argc != 4) {
                cli->sendMsg(ResponseCode::CommandSyntaxError,
                        "Usage: interface ipv6privacyextensions <interface> <enable|disable>",
                        false);
                return 0;
            }

            char *tmp;
            asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/use_tempaddr", argv[2]);

            if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "2" : "0", 1) < 0) {
                free(tmp);
                cli->sendMsg(ResponseCode::OperationFailed,
                        "Failed to set ipv6 privacy extensions", true);
                return 0;
            }

            free(tmp);
            cli->sendMsg(ResponseCode::CommandOkay, "IPv6 privacy extensions changed", false);
            return 0;
        } else if (!strcmp(argv[1], "ipv6")) {
            if (argc != 4) {
                cli->sendMsg(ResponseCode::CommandSyntaxError,
                        "Usage: interface ipv6 <interface> <enable|disable>",
                        false);
                return 0;
            }

            char *tmp;
            asprintf(&tmp, "/proc/sys/net/ipv6/conf/%s/disable_ipv6", argv[2]);

            if (writeFile(tmp, !strncmp(argv[3], "enable", 7) ? "0" : "1", 1) < 0) {
                free(tmp);
                cli->sendMsg(ResponseCode::OperationFailed,
                        "Failed to change IPv6 state", true);
                return 0;
            }

            free(tmp);
            cli->sendMsg(ResponseCode::CommandOkay, "IPv6 state changed", false);
            return 0;
        } else {
            cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown interface cmd", false);
            return 0;
        }
    }
    return 0;
}
示例#12
0
void onConnectionStateChanged(const char *s)
{
    int m_state = -1, m_cause = -1, err;
    int commas;

    err = at_tok_start((char **) &s);
    if (err < 0)
        return;

    /* Count number of commas */
    err = at_tok_charcounter((char *) s, ',', &commas);
    if (err < 0)
        return;

    err = at_tok_nextint((char **) &s, &m_state);
    if (err < 0 || m_state < E2NAP_STATE_DISCONNECTED
            || m_state > E2NAP_STATE_CONNECTING) {
        m_state = -1;
        return;
    }

    err = at_tok_nextint((char **) &s, &m_cause);
    /* The <cause> will only be indicated/considered when <state>
     * is disconnected */
    if (err < 0 || m_cause < E2NAP_CAUSE_SUCCESS || m_cause > E2NAP_CAUSE_MAXIMUM
            || m_state != E2NAP_STATE_DISCONNECTED)
        m_cause = -1;

    if (commas == 3) {
        int m_state2 = -1, m_cause2 = -1;
        err = at_tok_nextint((char **) &s, &m_state2);
        if (err < 0 || m_state2 < E2NAP_STATE_DISCONNECTED
                || m_state2 > E2NAP_STATE_CONNECTED) {
            m_state = -1;
            return;
        }

        if (m_state2 == E2NAP_STATE_DISCONNECTED) {
            err = at_tok_nextint((char **) &s, &m_cause2);
            if (err < 0 || m_cause2 < E2NAP_CAUSE_SUCCESS
                    || m_cause2 > E2NAP_CAUSE_MAXIMUM) {
                m_cause2 = -1;
            }
        }

        if ((err = pthread_mutex_lock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to take e2nap mutex: %s", __func__,
                    strerror(err));

        if (m_state == E2NAP_STATE_CONNECTING || m_state2 == E2NAP_STATE_CONNECTING) {
            s_e2napState = E2NAP_STATE_CONNECTING;
        } else if (m_state == E2NAP_STATE_CONNECTED) {
            s_e2napCause = m_cause2;
            s_e2napState = E2NAP_STATE_CONNECTED;
        } else if (m_state2 == E2NAP_STATE_CONNECTED) {
            s_e2napCause = m_cause;
            s_e2napState = E2NAP_STATE_CONNECTED;
        } else {
            s_e2napCause = m_cause;
            s_e2napState = E2NAP_STATE_DISCONNECTED;
        }
        if ((err = pthread_mutex_unlock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to release e2nap mutex: %s", __func__,
                    strerror(err));
    } else {
        if ((err = pthread_mutex_lock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to take e2nap mutex: %s", __func__,
                    strerror(err));

        s_e2napState = m_state;
        s_e2napCause = m_cause;
        if ((err = pthread_mutex_unlock(&s_e2nap_mutex)) != 0)
            ALOGE("%s() failed to release e2nap mutex: %s", __func__,
                    strerror(err));

    }

    mbm_check_error_cause();

    if (m_state == E2NAP_STATE_DISCONNECTED) {
        /* Bring down the interface as well. */
        if (!(ifc_init())) {
            ifc_down(ril_iface);
            ifc_close();
        } else
            ALOGE("%s() Failed to set up ifc!", __func__);
    }

    if ((m_state == E2NAP_STATE_DISCONNECTED) && (s_DeactCalled == 0)) {
        enqueueRILEvent(RIL_EVENT_QUEUE_PRIO, onPDPContextListChanged, NULL,
                NULL);
    }
    s_DeactCalled = 0;
}
示例#13
0
void requestSetupDefaultPDP(void *data, size_t datalen, RIL_Token t)
{
    in_addr_t addr;
    in_addr_t gateway;

    const char *apn, *user, *pass, *auth;
    char *addresses = NULL;
    char *gateways = NULL;
    char *dnses = NULL;
    const char *type = NULL;

    RIL_Data_Call_Response_v6 response;

    int e2napState = getE2napState();
    int err = -1;
    int cme_err, i, prof;

    (void) data;
    (void) datalen;

    prof = atoi(((const char **) data)[1]);
    apn = ((const char **) data)[2];
    user = ((const char **) data)[3];
    pass = ((const char **) data)[4];
    auth = ((const char **) data)[5];
    type = getNWType(((const char **) data)[6]);

    s_lastPdpFailCause = PDP_FAIL_ERROR_UNSPECIFIED;

    memset(&response, 0, sizeof(response));
    response.ifname = ril_iface;
    response.cid = prof + 1;
    response.active = 0;
    response.type = (char *) type;
    response.suggestedRetryTime = -1;

    /* Handle case where Android framework tries to setup multiple PDPs
       when sending/receiving MMS. Tear down the default context if any
       attempt is made to setup a new context with different DataProfile.
       Requires changes to Android framework (RILConstants.java and
       GsmDataConnectionTracker.java). This need to be in place until the
       framework properly handles priorities on APNs */
    if (e2napState > E2NAP_STATE_DISCONNECTED) {
        if (prof > RIL_DATA_PROFILE_DEFAULT) {
            ALOGD("%s() tearing down default cid:%d to allow cid:%d",
                        __func__, s_ActiveCID, prof + 1);
            s_DeactCalled = 1;
            if (disconnect()) {
                goto down;
            } else {
                e2napState = getE2napState();

                if (e2napState != E2NAP_STATE_DISCONNECTED)
                    goto error;

                if (ifc_init())
                    goto error;

                if (ifc_down(ril_iface))
                    goto error;

                ifc_close();
                requestOrSendPDPContextList(NULL);
            }
        } else {
            ALOGE("%s() denying data connection to APN '%s' Multiple PDP not supported!",
                                __func__, apn);
            response.status = PDP_FAIL_INSUFFICIENT_RESOURCES;
            RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));
            return;
        }
    }

down:
    e2napState = setE2napState(E2NAP_STATE_UNKNOWN);

    ALOGD("%s() requesting data connection to APN '%s'", __func__, apn);

    if (ifc_init()) {
        ALOGE("%s() Failed to set up ifc!", __func__);
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    if (ifc_down(ril_iface)) {
        ALOGE("%s() Failed to bring down %s!", __func__, ril_iface);
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    err = at_send_command("AT+CGDCONT=%d,\"IP\",\"%s\"", RIL_CID_IP, apn);
    if (err != AT_NOERROR) {
        cme_err = at_get_cme_error(err);
        ALOGE("%s() CGDCONT failed: %d, cme: %d", __func__, err, cme_err);
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    if (networkAuth(auth, user, pass, RIL_CID_IP)) {
        RIL_onRequestComplete(t, RIL_E_GENERIC_FAILURE, NULL, 0);
        return;
    }

    /* Start data on PDP context for IP */
    err = at_send_command("AT*ENAP=1,%d", RIL_CID_IP);
    if (err != AT_NOERROR) {
        cme_err = at_get_cme_error(err);
        ALOGE("requestSetupDefaultPDP: ENAP failed: %d  cme: %d", err, cme_err);
        goto error;
    }

    for (i = 0; i < MBM_ENAP_CONNECT_TIME * 5; i++) {
        e2napState = getE2napState();
        if (e2napState == E2NAP_STATE_CONNECTED
                || e2napState == E2NAP_STATE_DISCONNECTED
                || RADIO_STATE_UNAVAILABLE == getRadioState()) {
            ALOGD("%s() %s", __func__, e2napStateToString(e2napState));
            break;
        }
        usleep(200 * 1000);
    }

    e2napState = getE2napState();

    if (e2napState != E2NAP_STATE_CONNECTED)
        goto error;

    if (parse_ip_information(&addresses, &gateways, &dnses, &addr, &gateway) < 0) {
        ALOGE("%s() Failed to parse network interface data", __func__);
        goto error;
    }

    response.addresses = addresses;
    response.gateways = gateways;
    response.dnses = dnses;
    ALOGI("%s() Setting up interface %s,%s,%s",
        __func__, response.addresses, response.gateways, response.dnses);

    e2napState = getE2napState();

    if (e2napState == E2NAP_STATE_DISCONNECTED)
        goto error; /* we got disconnected */

    /* Don't use android netutils. We use our own and get the routing correct.
     * Carl Nordbeck */
    if (ifc_configure(ril_iface, addr, gateway))
        ALOGE("%s() Failed to configure the interface %s", __func__, ril_iface);

    ALOGI("IP Address %s, %s", addresses, e2napStateToString(e2napState));

    e2napState = getE2napState();

    if (e2napState == E2NAP_STATE_DISCONNECTED)
        goto error; /* we got disconnected */

    response.active = 2;
    response.status = 0;
    s_ActiveCID = response.cid;

    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));

    free(addresses);
    free(gateways);
    free(dnses);

    startPollFastDormancy();

    return;

error:

    mbm_check_error_cause();
    response.status = s_lastPdpFailCause;

    /* Restore enap state and wait for enap to report disconnected*/
    disconnect();

    RIL_onRequestComplete(t, RIL_E_SUCCESS, &response, sizeof(response));

    free(addresses);
    free(gateways);
    free(dnses);
}