diff --git a/.gitignore b/.gitignore index 31fbd9ea0167665e3270149e99faca295aee5c10..0c47a9507a03cca914a75c91dd05994561b41c4a 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,4 @@ dongle_apn dongle_pin dongle_network ipkg* +test-parse* diff --git a/Makefile b/Makefile index 929c380927cbc3ab677b77db1b823e08b13ed70d..7e3cb732c1f1bc48232bfd00f64fc21cb75eeb56 100644 --- a/Makefile +++ b/Makefile @@ -2,14 +2,7 @@ CC = gcc CFLAGS = -g -Wall LIBS = -ljson-c -lubox -lubus -luci -lcurl -lmobile -all: libmobile1 libmobile2# common dongle_apn dongle_pin dongle_network - - -#gcc -shared -o libhello.so -fPIC hello.c -#MOBJS = libmobile.so -#MSRCS = libmobile.c -#libmobile: ${MOBJS} -# ${CC} -shared -o ${MOBJS} -fPIC ${MSRCS} +all: libmobile1 libmobile2 common dongle_apn dongle_pin dongle_network dongle MOBJS = libmobile.o MSRCS = libmobile.c @@ -21,25 +14,27 @@ MSRCS = libmobile.c libmobile2: ${MOBJS} ${CC} ${MOBJS} -shared -o libmobile.so -#COBJS = common.o -#CSRCS = common.c -#common: ${COBJS} -# ${CC} -c ${CSRCS} -o ${COBJS} -# -#DAOBJS = dongle_apn.o -#DASRCS = dongle_apn.c -#dongle_apn: ${DAOBJS} -# ${CC} ${CFLAGS} ${DAOBJS} ${COBJS} -o dongle_apn ${LIBS} -# -#DPOBJS = dongle_pin.o -#DPSRCS = dongle_pin.c -#dongle_pin: ${DPOBJS} -# ${CC} ${CFLAGS} ${DPOBJS} ${COBJS} -o dongle_pin ${LIBS} -# -#DNOBJS = dongle_network.o -#DNSRCS = dongle_network.c -#dongle_network: ${DNOBJS} -# ${CC} ${CFLAGS} ${DNOBJS} ${COBJS} -o dongle_network ${LIBS} +common: ${COBJS} + ${CC} -c ${CSRCS} -o ${COBJS} + +DAOBJS = dongle_apn.o +DASRCS = dongle_apn.c +dongle_apn: ${DAOBJS} + ${CC} -c ${CFLAGS} ${DASRCS} ${COBJS} -o ${DAOBJS} -L . ${LIBS} #${MOBJS} + +DPOBJS = dongle_pin.o +DPSRCS = dongle_pin.c +dongle_pin: ${DPOBJS} + ${CC} -c ${CFLAGS} ${DPSRCS} ${COBJS} -o ${DPOBJS} -L . ${LIBS} #${MOBJS} + +DNOBJS = dongle_network.o +DNSRCS = dongle_network.c +dongle_network: ${DNOBJS} + ${CC} -c ${CFLAGS} ${DNSRCS} ${COBJS} -o ${DNOBJS} -L . ${LIBS} #${MOBJS} + +dongle: dongle.o + ${CC} ${CFLAGS} dongle.o ${COBJS} ${DNOBJS} ${DPOBJS} ${DAOBJS} -o dongle -L . ${LIBS} #${MOBJS} + clean: rm -f dongle_apn dongle_pin dongle_network *.o *.so diff --git a/common.c b/common.c index 0353e8bdbb10556fe8d4a6d958f705c1509e38ba..2a0ede4d1b0f55da98d9b44d76b4a2e25a087197 100644 --- a/common.c +++ b/common.c @@ -1,35 +1,16 @@ #include "common.h" -int parse_and_print(char *dongle_response, struct ubus_context *ctx, struct ubus_request_data *req) -{ - if (!dongle_response) { - DEBUG("no respose!\n"); - goto fail; - } - struct json_object *parsed_response = json_tokener_parse(dongle_response); - - if (!parsed_response) { - DEBUG("No valid JSON, failed parsing!\n"); - goto free_response; - } - write_to_ubus(parsed_response, ctx, req); - - json_object_put(parsed_response); -free_response: - free(dongle_response); -fail: - return 0; -} - -int write_to_ubus(struct json_object *parsed_response, struct ubus_context *ctx, struct ubus_request_data *req) +int print_to_ubus(struct json_object *parsed_response, struct ubus_context *ctx, struct ubus_request_data *req) { struct blob_buf bb; + memset(&bb, 0, sizeof(struct blob_buf)); blob_buf_init(&bb, 0); bb = json_to_blob(parsed_response, bb); ubus_send_reply(ctx, req, bb.head); blob_buf_free(&bb); - //json_object_put(parsed_response); + + json_object_put(parsed_response); return 0; } @@ -37,8 +18,10 @@ struct blob_buf json_to_blob(struct json_object *response, struct blob_buf bb) { void *arr, *obj; int i; + json_object_object_foreach(response, key, val) { int val_type = json_object_get_type(val); + switch (val_type) { case json_type_int: blobmsg_add_u32(&bb, key, json_object_get_int(val)); diff --git a/common.h b/common.h index 3d918702beab9664007fdc3973a4dd80ff1bc265..3129be7189449711d2ce8dfe9b7020b35b2f5db3 100644 --- a/common.h +++ b/common.h @@ -1,38 +1,27 @@ #ifndef COMMON_H #define COMMON_H -#define DEBUG(message, ...) \ - do \ - { \ - fprintf(stdout, "\n(DEBUG)\t"); \ - fprintf(stdout, message, ##__VA_ARGS__);\ - } while (0) -#include "libtrace.h" + +#include <stdlib.h> +#include <stdio.h> +#include <stdbool.h> +#include <unistd.h> +#include <getopt.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <fcntl.h> +#include <signal.h> +#include <time.h> +#include <limits.h> +#include <libubox/list.h> + #include <libmobile.h> #include <json-c/json.h> #include <string.h> #include <libubox/blobmsg.h> #include <libubus.h> -/** - * Function: parse_and_print - * - * Parses a string to its corresponding JSON format, if available, then writes it on ubus through <write_to_ubus>. - * - * IMPORTANT NOTE - * Will free the input string! - * - * Parameters: - * dongle_response - A string of JSON format that should be printed on ubus. - * ctx - Ubus context containing connection. - * req - Information for from the ubus request. - * - * Returns: - * 0 On success. - * -1 On failure. - */ -int parse_and_print(char *dongle_response, struct ubus_context *ctx, struct ubus_request_data *req); /** - * Function: write_to_ubus + * Function: print_to_ubus * * Prints a json_object pointer's json structure to ubus. * @@ -45,7 +34,7 @@ int parse_and_print(char *dongle_response, struct ubus_context *ctx, struct ubus * 0 On success. * -1 On failure. */ -int write_to_ubus(struct json_object *parsed_response, struct ubus_context *ctx, struct ubus_request_data *req); +int print_to_ubus(struct json_object *parsed_response, struct ubus_context *ctx, struct ubus_request_data *req); /** * Function: json_to_blob diff --git a/dongle.c b/dongle.c new file mode 100644 index 0000000000000000000000000000000000000000..6fc47a41c8de3e5f5314ff8c88b98034e3a88ebd --- /dev/null +++ b/dongle.c @@ -0,0 +1,28 @@ +#include "common.h" +#include "dongle_apn.h" +#include "dongle_pin.h" +#include "dongle_network.h" + +struct ubus_context *ctx; + +void init_ubus(void) +{ + ctx = ubus_connect(NULL); + if (!ctx) { + perror("ubus"); + exit(1); + } + ubus_add_uloop(ctx); +} + +int main(int argc, char **argv) +{ + uloop_init(); + init_ubus(); + expose_apn_object(ctx); + expose_pin_object(ctx); + expose_network_object(ctx); + uloop_run(); + + return 0; +} \ No newline at end of file diff --git a/dongle_apn.c b/dongle_apn.c new file mode 100644 index 0000000000000000000000000000000000000000..6273ac25490af321bd2d17852b6168bcf36e6be5 --- /dev/null +++ b/dongle_apn.c @@ -0,0 +1,181 @@ +#include "dongle_apn.h" + +enum { + APN_NAME, + __APN_MAX, +}; + +enum { + PROFILE_NAME, + WAN_APN, + PDP_TYPE, + __CREATE_MAX, +}; + +const struct blobmsg_policy create_apn_policy[__CREATE_MAX] = { + [PROFILE_NAME] = {.name = "profile_name", .type = BLOBMSG_TYPE_STRING}, + [WAN_APN] = {.name = "wan_apn", .type = BLOBMSG_TYPE_STRING}, + [PDP_TYPE] = {.name = "pdp_type", .type = BLOBMSG_TYPE_STRING}, +}; + +const struct blobmsg_policy apn_policy[__APN_MAX] = { + [APN_NAME] = {.name = "profile_name", .type = BLOBMSG_TYPE_STRING}, +}; + +int list_apn_profiles(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_get_apn_profiles(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int delete_apn_profile(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__APN_MAX]; + char *name; //what is max available name length in dongle? + struct json_object *response; + + blobmsg_parse(apn_policy, __APN_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[APN_NAME]) + goto fail_argument; + + name = (char *)blobmsg_data(tb[APN_NAME]); + if (strlen(name) == 0) { + debug_print("Empty is not a name!\n"); + goto fail_argument; + } else if (strlen(name) > 1023) { + debug_print("name too long!\n"); + goto fail_argument; + } + + response = mobile_delete_apn(name); + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_argument: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int set_apn_profile(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__APN_MAX]; + char *name; + struct json_object *response; + + blobmsg_parse(apn_policy, __APN_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[APN_NAME]) + goto fail_argument; + + name = (char *)blobmsg_data(tb[APN_NAME]); + if (strlen(name) == 0) { + debug_print("Empty is not a name!\n"); + goto fail_argument; + } else if (strlen(name) > 1023) { + debug_print("name too long!\n"); + goto fail_argument; + } + + response = mobile_set_apn_profile(name); + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_argument: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int create_apn_profile(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__CREATE_MAX]; + char *profile_name, *wan_apn, *pdp_type; //what is max available name length in dongle? + struct json_object *response; + + blobmsg_parse(create_apn_policy, __CREATE_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[PROFILE_NAME] || !tb[WAN_APN] || !tb[PDP_TYPE]) { + debug_print("Need to provide all arguments!\n"); + goto fail_argument; + } + + profile_name = (char *)blobmsg_data(tb[PROFILE_NAME]); + wan_apn = (char *)blobmsg_data(tb[WAN_APN]); + pdp_type = (char *)blobmsg_data(tb[PDP_TYPE]); + if (strlen(profile_name) > 1023 || strlen(wan_apn) > 1023 || strlen(pdp_type) > 1023) { + debug_print("input may be max 1023 characters!\n"); + goto fail_argument; + } else if (strlen(profile_name) <= 0 || strlen(wan_apn) <= 0 || strlen(pdp_type) <= 0) { + debug_print("Empty string is not a valid input!\n"); + goto fail_argument; + } + + response = mobile_create_apn_profile(profile_name, wan_apn, pdp_type); + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_argument: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int show_current_apn(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_get_wan_apn(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +struct ubus_method apn_object_methods[] = { + UBUS_METHOD_NOARG("list", list_apn_profiles), + UBUS_METHOD("create", create_apn_profile, create_apn_policy), + UBUS_METHOD("delete", delete_apn_profile, apn_policy), + UBUS_METHOD("set_profile", set_apn_profile, apn_policy), + UBUS_METHOD_NOARG("current", show_current_apn), +}; + +struct ubus_object_type apn_object_type = UBUS_OBJECT_TYPE("dongle", apn_object_methods); + +struct ubus_object apn_object = { + .name = "dongle.apn", + .type = &apn_object_type, + .methods = apn_object_methods, + .n_methods = ARRAY_SIZE(apn_object_methods), +}; + +int expose_apn_object(struct ubus_context *ctx) +{ + int rv; + + rv = ubus_add_object(ctx, &apn_object); + if (rv) { + debug_print("failed to add dongle.pin to ubus!\n"); + return -1; + } + + return 0; +} diff --git a/dongle_apn.h b/dongle_apn.h new file mode 100644 index 0000000000000000000000000000000000000000..0b6a0bfabcde5d865718efed3090ffcb115472b5 --- /dev/null +++ b/dongle_apn.h @@ -0,0 +1,6 @@ +#ifndef APN_H +#define APN_H +#include "common.h" + +int expose_apn_object(struct ubus_context *ctx); +#endif \ No newline at end of file diff --git a/dongle_network.c b/dongle_network.c new file mode 100644 index 0000000000000000000000000000000000000000..da9a9449b8a5ef3f5911fca6c2b5bfd08a8f8b0e --- /dev/null +++ b/dongle_network.c @@ -0,0 +1,130 @@ +#include "dongle_network.h" + +int get_signal_strength(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_get_rssi(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} +int connect_network(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_connect_network(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int disconnect(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_disconnect_network(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int modem_state(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_get_modem_state(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int enable_roaming(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_enable_roaming(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int disable_roaming(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_disable_roaming(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int roam_status(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_get_roam_status(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +struct ubus_method network_object_methods[] = { + UBUS_METHOD_NOARG("signal_strength", get_signal_strength), + UBUS_METHOD_NOARG("connect", connect_network), + UBUS_METHOD_NOARG("disconnect", disconnect), + UBUS_METHOD_NOARG("modem_state", modem_state), + UBUS_METHOD_NOARG("enable_roaming", enable_roaming), + UBUS_METHOD_NOARG("disable_roaming", disable_roaming), + UBUS_METHOD_NOARG("roam_status", roam_status), +}; + +struct ubus_object_type network_object_type = UBUS_OBJECT_TYPE("dongle", network_object_methods); + +struct ubus_object network_object = { + .name = "dongle.network", + .type = &network_object_type, + .methods = network_object_methods, + .n_methods = ARRAY_SIZE(network_object_methods), +}; + +int expose_network_object(struct ubus_context *ctx) +{ + int rv; + + rv = ubus_add_object(ctx, &network_object); + if (rv) { + debug_print("failed to add dongle.pin to ubus!\n"); + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/dongle_network.h b/dongle_network.h new file mode 100644 index 0000000000000000000000000000000000000000..e6c3e9044518eef0c5cc2bf6b0111b3640c8ab0d --- /dev/null +++ b/dongle_network.h @@ -0,0 +1,6 @@ +#ifndef NETWORK_H +#define NETWORK_H +#include "common.h" + +int expose_network_object(struct ubus_context *ctx); +#endif \ No newline at end of file diff --git a/dongle_pin.c b/dongle_pin.c new file mode 100644 index 0000000000000000000000000000000000000000..61057949dbe8d8199b56c55c4784896c237f3cfa --- /dev/null +++ b/dongle_pin.c @@ -0,0 +1,349 @@ +#include "dongle_pin.h" + +static int isdigits(const char *pin); +static int validate_pin_format(char *pin); + +enum { + NEW_PIN, + CURRENT_PIN, + __SET_PIN_MAX, +}; + +enum { + PIN, + __PIN_MAX, +}; + +const struct blobmsg_policy set_pin_policy[__SET_PIN_MAX] = { + [NEW_PIN] = {.name = "new_pin", .type = BLOBMSG_TYPE_STRING}, + [CURRENT_PIN] = {.name = "current_pin", .type = BLOBMSG_TYPE_STRING}, +}; + +const struct blobmsg_policy pin_policy[__PIN_MAX] = { + [PIN] = {.name = "pin", .type = BLOBMSG_TYPE_STRING}, +}; + + +static int isdigits(const char *pin) +{ + while (*pin) { + if (isdigit(*pin++) == 0) + return false; + } + return true; +} + +static int validate_pin_format(char *pin) +{ + if (!isdigits(pin)) { + debug_print("Please enter digits only!\n"); + goto fail; + } else if (strlen(pin) > 8 || strlen(pin) < 4) { + debug_print("Please enter between 4 to 8 digits!\n"); + goto fail; + } else if (atoi(pin) == 0) { + debug_print("0000 is not a valid pin! Lowest available is 0001\n"); + goto fail; + } + + return 0; +fail: + return -1; +} + +int set_pin(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__SET_PIN_MAX]; + char *new_pin, *current_pin; + int rv; + struct json_object *response, *rv_json; + + blobmsg_parse(set_pin_policy, __SET_PIN_MAX, tb, blob_data(msg), blob_len(msg)); + + if (!tb[NEW_PIN] && !tb[CURRENT_PIN]) { + debug_print("Please enter both a new pin and old pin!\n"); + goto fail_input; + } + new_pin = (char *)blobmsg_data(tb[NEW_PIN]); + current_pin = (char *)blobmsg_data(tb[CURRENT_PIN]); + + rv = validate_pin_format(new_pin); + if (rv > 0) { + debug_print("invalid pin format\n"); + goto fail_input; + } + + rv = validate_pin_format(current_pin); + if (rv > 0) { + debug_print("invalid pin format\n"); + goto fail_input; + } + + response = mobile_get_pin_status(); + if (!response) { + debug_print("error getting pin_status\n"); + goto fail_data; + } + + json_object_object_get_ex(response, "pin_status", &rv_json); + if (!rv_json) { + debug_print("no pin_status available\n"); + goto fail_result; + } + + /* Enable PIN if it is disabled */ + if (!json_object_get_int(rv_json)) { + json_object_put(response); + + response = mobile_enable_pin(current_pin); + if (!response) { + debug_print("error enabling pin!\n"); + goto fail_unknown; + } + + json_object_object_get_ex(response, "result", &rv_json); + if (!rv_json) { + debug_print("error getting result!\n"); + goto fail_result; + } + + if (strncmp(json_object_get_string(rv_json), "failure", strlen("failure")) == 0) { + debug_print("Incorrect pin!\n"); + goto incorrect_pin; + } + } + + json_object_put(response); + response = mobile_set_pin(current_pin, new_pin); + if (!response) { + debug_print("error setting pin!\n"); + goto fail_data; + } + + json_object_object_get_ex(response, "result", &rv_json); + if (!rv_json) { + debug_print("no result available from %s!", __func__); + goto fail_result; + } + +incorrect_pin: + return print_to_ubus(response, ctx, req); +fail_input: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_data: + return UBUS_STATUS_NO_DATA; +fail_result: + json_object_put(response); + return UBUS_STATUS_UNKNOWN_ERROR; +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int disable_pin(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__PIN_MAX]; + char *pin; + int rv; + struct json_object *response, *rv_json; + + blobmsg_parse(pin_policy, __PIN_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[PIN]) { + debug_print("Please enter a pin!\n"); + goto fail_input; + } + pin = (char *)blobmsg_data(tb[PIN]); + rv = validate_pin_format(pin); + if (rv < 0) { + debug_print("invalid pin format!\n"); + goto fail_input; + } + + response = mobile_get_pin_status(); + if (!response) { + debug_print("no response from get_pin_status!\n"); + goto fail_data; + } + + json_object_object_get_ex(response, "pin_status", &rv_json); + if (!rv_json) { + debug_print("no pin_status available in response!\n"); + goto fail_result; + } + + if (!json_object_get_int(rv_json)) { + debug_print("already disabled!\n"); + goto success; //kind of... + } + + json_object_put(response); + response = mobile_disable_pin(pin); + if (!response) { + debug_print("error disabling pin!\n"); + goto fail_data; + } + + json_object_object_get_ex(response, "result", &rv_json); + if (!rv_json) { + debug_print("no result available in response!\n"); + goto fail_result; + } + + if (strncmp(json_object_get_string(rv_json), "failure", strlen("failure")) == 0) + debug_print("Incorrect pin!\n"); + +success: + return print_to_ubus(response, ctx, req); +fail_input: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_data: + return UBUS_STATUS_NO_DATA; +fail_result: + json_object_put(response); + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int enable_pin(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__PIN_MAX]; + char *pin; + int rv; + struct json_object *response, *rv_json; + + blobmsg_parse(pin_policy, __PIN_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[PIN]) { + debug_print("Please enter both a new pin and old pin!\n"); + goto fail_input; + } + + pin = (char *)blobmsg_data(tb[PIN]); + rv = validate_pin_format(pin); + if (rv < 0) { + debug_print("invalid pin format!\n"); + goto fail_input; + } + + response = mobile_get_pin_status(); + if (!response) { + debug_print("no response from get_pin_status!\n"); + goto fail_data; + } + + json_object_object_get_ex(response, "pin_status", &rv_json); + if (!rv_json) { + debug_print("no pin_status available in response!\n"); + goto fail_result; + } + if (!json_object_get_int(rv_json)) { + debug_print("already enabled!\n"); + goto success; + } + + json_object_put(response); + response = mobile_enable_pin(pin); + if (!response) { + debug_print("no response from get_pin_status!\n"); + goto fail_data; + } + + json_object_object_get_ex(response, "result", &rv_json); + if (!rv_json) { + debug_print("no result available in response!\n"); + goto fail_result; + } + + if (strncmp(json_object_get_string(rv_json), "failure", strlen("failure")) == 0) + debug_print("Incorrect pin!\n"); + +success: + return print_to_ubus(response, ctx, req); +fail_input: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_data: + return UBUS_STATUS_NO_DATA; +fail_result: + json_object_put(response); + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int verify_pin(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct blob_attr *tb[__PIN_MAX]; + char *pin; + int rv; + struct json_object *response; + + blobmsg_parse(pin_policy, __PIN_MAX, tb, blob_data(msg), blob_len(msg)); + if (!tb[PIN]) { + debug_print("Please enter a pin\n!"); + goto fail_input; + } + + pin = (char *)blobmsg_data(tb[PIN]); + rv = validate_pin_format(pin); + if (rv < 0) { + debug_print("invalid pin format!\n"); + goto fail_input; + } + + response = mobile_set_pin(pin, pin); + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_input: + return UBUS_STATUS_INVALID_ARGUMENT; +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +int remaining_tries(struct ubus_context *ctx, struct ubus_object *obj, + struct ubus_request_data *req, const char *method, + struct blob_attr *msg) +{ + struct json_object *response = mobile_get_remaining_tries(); + + if (!response) + goto fail_unknown; + + return print_to_ubus(response, ctx, req); +fail_unknown: + return UBUS_STATUS_UNKNOWN_ERROR; +} + +struct ubus_method pin_object_methods[] = { + UBUS_METHOD("set_pin", set_pin, set_pin_policy), + UBUS_METHOD("disable_pin", disable_pin, pin_policy), + UBUS_METHOD("enable_pin", enable_pin, pin_policy), + UBUS_METHOD("verify_pin", verify_pin, pin_policy), + UBUS_METHOD_NOARG("remaining_tries", remaining_tries), +}; + +struct ubus_object_type pin_object_type = UBUS_OBJECT_TYPE("dongle", pin_object_methods); + +struct ubus_object pin_object = { + .name = "dongle.pin", + .type = &pin_object_type, + .methods = pin_object_methods, + .n_methods = ARRAY_SIZE(pin_object_methods), +}; + +int expose_pin_object(struct ubus_context *ctx) +{ + int rv; + + rv = ubus_add_object(ctx, &pin_object); + if (rv) { + debug_print("failed to add dongle.pin to ubus!\n"); + return -1; + } + + return 0; +} \ No newline at end of file diff --git a/dongle_pin.h b/dongle_pin.h new file mode 100644 index 0000000000000000000000000000000000000000..8259165490fd8283fd54a1b6ee7d8338dce32264 --- /dev/null +++ b/dongle_pin.h @@ -0,0 +1,6 @@ +#ifndef PIN_H +#define PIN_H +#include "common.h" + +int expose_pin_object(struct ubus_context *ctx); +#endif