Example #1
0
static int func_getvar2 (void *vo, NCD_string_id_t name, NCDValMem *mem, NCDValRef *out)
{
    struct instance *o = vo;
    
    if (name == NCD_STRING_EMPTY) {
        *out = NCDVal_NewList(mem, o->num);
        if (NCDVal_IsInvalid(*out)) {
            goto fail;
        }
        for (size_t j = 0; j < o->num; j++) {
            struct substring *elem = &((struct substring *)o->arr.v)[j];
            NCDValRef str = NCDVal_NewStringBin(mem, (uint8_t *)elem->data, elem->len);
            if (NCDVal_IsInvalid(str)) {
                goto fail;
            }
            if (!NCDVal_ListAppend(*out, str)) {
                goto fail;
            }
        }
        return 1;
    }
    
    return 0;
    
fail:
    *out = NCDVal_NewInvalid();
    return 1;
}
Example #2
0
static int parse_options (NCDModuleInst *i, NCDValRef options, size_t *out_read_size)
{
    ASSERT(out_read_size)
    
    *out_read_size = DEFAULT_READ_BUF_SIZE;
    
    if (!NCDVal_IsInvalid(options)) {
        if (!NCDVal_IsMap(options)) {
            ModuleLog(i, BLOG_ERROR, "options argument is not a map");
            return 0;
        }
        
        int num_recognized = 0;
        NCDValRef value;
        
        if (!NCDVal_IsInvalid(value = NCDVal_MapGetValue(options, "read_size"))) {
            uintmax_t read_size;
            if (!ncd_read_uintmax(value, &read_size) || read_size > SIZE_MAX || read_size == 0) {
                ModuleLog(i, BLOG_ERROR, "wrong read_size");
                return 0;
            }
            num_recognized++;
            *out_read_size = read_size;
        }
        
        if (NCDVal_MapCount(options) > num_recognized) {
            ModuleLog(i, BLOG_ERROR, "unrecognized options present");
            return 0;
        }
    }
    
    return 1;
}
Example #3
0
static void ifel_eval (NCDCall call)
{
    size_t count = NCDCall_ArgCount(&call);
    if (count % 2 == 0) {
        return FunctionLog(&call, BLOG_ERROR, "ifel: need an odd number of arguments");
    }
    NCDValRef value;
    size_t j = 0;
    while (1) {
        NCDValRef arg = NCDCall_EvalArg(&call, j, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(arg)) {
            return;
        }
        if (j == count - 1) {
            value = arg;
            break;
        }
        NCDValRef arg2 = NCDCall_EvalArg(&call, j + 1, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(arg2)) {
            return;
        }
        int arg_val;
        if (!ncd_read_boolean(arg, &arg_val)) {
            return FunctionLog(&call, BLOG_ERROR, "ifel: bad condition");
        }
        if (arg_val) {
            value = arg2;
            break;
        }
        j += 2;
    }
    NCDCall_SetResult(&call, value);
}
Example #4
0
static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
{
    struct instance *o = vo;
    o->i = i;
    
    // read arguments
    NCDValRef ifname_arg;
    NCDValRef addr_arg;
    NCDValRef prefix_arg = NCDVal_NewInvalid();
    if (!NCDVal_ListRead(params->args, 2, &ifname_arg, &addr_arg) &&
        !NCDVal_ListRead(params->args, 3, &ifname_arg, &addr_arg, &prefix_arg)
    ) {
        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    if (!NCDVal_IsStringNoNulls(ifname_arg) || !NCDVal_IsString(addr_arg) ||
        (!NCDVal_IsInvalid(prefix_arg) && !NCDVal_IsString(prefix_arg))
    ) {
        ModuleLog(o->i, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    // null terminate ifname
    if (!NCDVal_StringNullTerminate(ifname_arg, &o->ifname_nts)) {
        ModuleLog(i, BLOG_ERROR, "NCDVal_StringNullTerminate failed");
        goto fail0;
    }
    
    if (NCDVal_IsInvalid(prefix_arg)) {
        if (!ipaddr_parse_ipv4_ifaddr(NCDVal_StringMemRef(addr_arg), &o->ifaddr)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong CIDR notation address");
            goto fail1;
        }
    } else {
        if (!ipaddr_parse_ipv4_addr(NCDVal_StringMemRef(addr_arg), &o->ifaddr.addr)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong address");
            goto fail1;
        }
        
        if (!ipaddr_parse_ipv4_prefix(NCDVal_StringMemRef(prefix_arg), &o->ifaddr.prefix)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong prefix");
            goto fail1;
        }
    }
    
    // add address
    if (!NCDIfConfig_add_ipv4_addr(o->ifname_nts.data, o->ifaddr)) {
        ModuleLog(o->i, BLOG_ERROR, "failed to add IP address");
        goto fail1;
    }
    
    // signal up
    NCDModuleInst_Backend_Up(o->i);
    return;
    
fail1:
    NCDValNullTermString_Free(&o->ifname_nts);
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #5
0
static void decode_value_eval (NCDCall call)
{
    if (NCDCall_ArgCount(&call) != 1) {
        return FunctionLog(&call, BLOG_ERROR, "decode_value: need one argument");
    }
    // Evaluate the string to a temporary mem, not ResMem.
    // Otherwise the ResMem could get resized while we're
    // parsing a string within it, and boom.
    NCDValMem temp_mem;
    NCDValMem_Init(&temp_mem, NCDCall_Iparams(&call)->string_index);
    NCDValRef arg = NCDCall_EvalArg(&call, 0, &temp_mem);
    if (NCDVal_IsInvalid(arg)) {
        goto fail1;
    }
    if (!NCDVal_IsString(arg)) {
        FunctionLog(&call, BLOG_ERROR, "decode_value: argument not a string");
        goto fail1;
    }
    NCDValRef value;
    int res = NCDValParser_Parse(NCDVal_StringMemRef(arg), NCDCall_ResMem(&call), &value);
    if (!res) {
        FunctionLog(&call, BLOG_ERROR, "decode_value: NCDValParser_Parse failed");
        goto fail1;
    }
    NCDCall_SetResult(&call, value);
fail1:
    NCDValMem_Free(&temp_mem);
}
Example #6
0
File: sleep.c Project: AmVPN/badvpn
static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
{
    struct instance *o = vo;
    o->i = i;
    
    // check arguments
    NCDValRef ms_start_arg;
    NCDValRef ms_stop_arg = NCDVal_NewInvalid();
    if (!NCDVal_ListRead(params->args, 1, &ms_start_arg) &&
        !NCDVal_ListRead(params->args, 2, &ms_start_arg, &ms_stop_arg)) {
        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    
    uintmax_t ms;
    btime_t ms_start;
    
    if (NCDVal_IsString(ms_start_arg) && NCDVal_StringEqualsId(ms_start_arg, NCD_STRING_EMPTY)) {
        ms_start = -1;
    } else {
        if (!ncd_read_uintmax(ms_start_arg, &ms) || ms > INT64_MAX) {
            ModuleLog(o->i, BLOG_ERROR, "wrong start time");
            goto fail0;
        }
        ms_start = ms;
    }
    
    if (NCDVal_IsInvalid(ms_stop_arg) || (NCDVal_IsString(ms_stop_arg) && NCDVal_StringEqualsId(ms_stop_arg, NCD_STRING_EMPTY))) {
        o->ms_stop = -1;
    } else {
        if (!ncd_read_uintmax(ms_stop_arg, &ms) || ms > INT64_MAX) {
            ModuleLog(o->i, BLOG_ERROR, "wrong stop time");
            goto fail0;
        }
        o->ms_stop = ms;
    }
    
    // init timer
    BTimer_Init(&o->timer, 0, timer_handler, o);
    
    // set not dying
    o->dying = 0;
    
    if (ms_start < 0) {
        // go up
        NCDModuleInst_Backend_Up(i);
    } else {
        // set timer
        BReactor_SetTimerAfter(o->i->params->iparams->reactor, &o->timer, ms_start);
    }
    
    return;
    
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #7
0
static void perchar_eval (NCDCall call, perchar_func func)
{
    if (NCDCall_ArgCount(&call) != 1) {
        return FunctionLog(&call, BLOG_ERROR, "tolower: need one argument");
    }
    NCDValRef arg = NCDCall_EvalArg(&call, 0, NCDCall_ResMem(&call));
    if (NCDVal_IsInvalid(arg)) {
        return;
    }
    if (!NCDVal_IsString(arg)) {
        return FunctionLog(&call, BLOG_ERROR, "tolower: argument not a string");
    }
    NCDValRef value = NCDVal_NewStringUninitialized(NCDCall_ResMem(&call), NCDVal_StringLength(arg));
    if (NCDVal_IsInvalid(value)) {
        return;
    }
    char *out_data = (char *)NCDVal_StringData(value);
    MEMREF_LOOP_CHARS(NCDVal_StringMemRef(arg), i, ch, {
        out_data[i] = func(ch);
    })
Example #8
0
static void concatlist_eval (NCDCall call)
{
    NCDValRef args_list;
    if (!ncd_eval_func_args(&call, NCDCall_ResMem(&call), &args_list)) {
        return;
    }
    size_t arg_count = NCDVal_ListCount(args_list);
    bsize_t elem_count = bsize_fromsize(0);
    for (size_t i = 0; i < arg_count; i++) {
        NCDValRef arg = NCDVal_ListGet(args_list, i);
        if (!NCDVal_IsList(arg)) {
            return FunctionLog(&call, BLOG_ERROR, "concatlist: argument is not a list");
        }
        elem_count = bsize_add(elem_count, bsize_fromsize(NCDVal_ListCount(arg)));
    }
    if (elem_count.is_overflow) {
        return FunctionLog(&call, BLOG_ERROR, "concatlist: count overflow");
    }
    NCDValRef res = NCDVal_NewList(NCDCall_ResMem(&call), elem_count.value);
    if (NCDVal_IsInvalid(res)) {
        return;
    }
    for (size_t i = 0; i < arg_count; i++) {
        NCDValRef arg = NCDVal_ListGet(args_list, i);
        size_t arg_list_count = NCDVal_ListCount(arg);
        for (size_t j = 0; j < arg_list_count; j++) {
            NCDValRef copy = NCDVal_NewCopy(NCDCall_ResMem(&call), NCDVal_ListGet(arg, j));
            if (NCDVal_IsInvalid(copy)) {
                return;
            }
            if (!NCDVal_ListAppend(res, copy)) {
                return;
            }
        }
    }
    NCDCall_SetResult(&call, res);
}
Example #9
0
static int parse_number (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
{
    uintmax_t n;
    if (!parse_unsigned_integer(str, &n)) {
        ModuleLog(i, BLOG_ERROR, "failed to parse number");
        return 0;
    }
    
    *out = ncd_make_uintmax(mem, n);
    if (NCDVal_IsInvalid(*out)) {
        return 0;
    }
    
    return 1;
}
Example #10
0
static void value_compare_eval (NCDCall call, value_compare_func func)
{
    if (NCDCall_ArgCount(&call) != 2) {
        return FunctionLog(&call, BLOG_ERROR, "value_compare: need two arguments");
    }
    NCDValRef vals[2];
    for (int i = 0; i < 2; i++) {
        vals[i] = NCDCall_EvalArg(&call, i, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(vals[i])) {
            return;
        }
    }
    int res = func(NCDVal_Compare(vals[0], vals[1]));
    NCDCall_SetResult(&call, ncd_make_boolean(NCDCall_ResMem(&call), res));
}
Example #11
0
static void bool_not_eval (NCDCall call, int negate, char const *name)
{
    if (NCDCall_ArgCount(&call) != 1) {
        return FunctionLog(&call, BLOG_ERROR, "%s: need one argument", name);
    }
    NCDValRef arg = NCDCall_EvalArg(&call, 0, NCDCall_ResMem(&call));
    if (NCDVal_IsInvalid(arg)) {
        return;
    }
    int arg_val;
    if (!ncd_read_boolean(arg, &arg_val)) {
        return FunctionLog(&call, BLOG_ERROR, "%s: bad argument", name);
    }
    int res = (arg_val != negate);
    NCDCall_SetResult(&call, ncd_make_boolean(NCDCall_ResMem(&call), res));
}
Example #12
0
static void encode_value_eval (NCDCall call)
{
    if (NCDCall_ArgCount(&call) != 1) {
        return FunctionLog(&call, BLOG_ERROR, "encode_value: need one argument");
    }
    NCDValRef arg = NCDCall_EvalArg(&call, 0, NCDCall_ResMem(&call));
    if (NCDVal_IsInvalid(arg)) {
        return;
    }
    char *str = NCDValGenerator_Generate(arg);
    if (!str) {
        return FunctionLog(&call, BLOG_ERROR, "encode_value: NCDValGenerator_Generate failed");
    }
    NCDCall_SetResult(&call, NCDVal_NewString(NCDCall_ResMem(&call), str));
    free(str);
}
Example #13
0
static void if_eval (NCDCall call)
{
    if (NCDCall_ArgCount(&call) != 3) {
        return FunctionLog(&call, BLOG_ERROR, "if: need three arguments");
    }
    NCDValRef cond = NCDCall_EvalArg(&call, 0, NCDCall_ResMem(&call));
    if (NCDVal_IsInvalid(cond)) {
        return;
    }
    int cond_val;
    if (!ncd_read_boolean(cond, &cond_val)) {
        return FunctionLog(&call, BLOG_ERROR, "if: bad condition");
    }
    int eval_arg = 2 - cond_val;
    NCDCall_SetResult(&call, NCDCall_EvalArg(&call, eval_arg, NCDCall_ResMem(&call)));
}
Example #14
0
static void integer_compare_eval (NCDCall call, integer_compare_func func)
{
    if (NCDCall_ArgCount(&call) != 2) {
        return FunctionLog(&call, BLOG_ERROR, "integer_compare: need two arguments");
    }
    uintmax_t ints[2];
    for (int i = 0; i < 2; i++) {
        NCDValRef arg = NCDCall_EvalArg(&call, i, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(arg)) {
            return;
        }
        if (!ncd_read_uintmax(arg, &ints[i])) {
            return FunctionLog(&call, BLOG_ERROR, "integer_compare: wrong value");
        }
    }
    int res = func(ints[0], ints[1]);
    NCDCall_SetResult(&call, ncd_make_boolean(NCDCall_ResMem(&call), res));
}
Example #15
0
static int parse_ipv6_addr (NCDModuleInst *i, MemRef str, NCDValMem *mem, NCDValRef *out)
{
    struct ipv6_addr addr;
    if (!ipaddr6_parse_ipv6_addr(str, &addr)) {
        ModuleLog(i, BLOG_ERROR, "failed to parse ipv6 addresss");
        return 0;
    }
    
    char buf[IPADDR6_PRINT_MAX];
    ipaddr6_print_addr(addr, buf);
    
    *out = NCDVal_NewString(mem, buf);
    if (NCDVal_IsInvalid(*out)) {
        return 0;
    }
    
    return 1;
}
Example #16
0
static void and_or_eval (NCDCall call, int is_and, char const *name)
{
    size_t count = NCDCall_ArgCount(&call);
    int res = is_and;
    for (size_t i = 0; i < count; i++) {
        NCDValRef arg = NCDCall_EvalArg(&call, i, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(arg)) {
            return;
        }
        int arg_val;
        if (!ncd_read_boolean(arg, &arg_val)) {
            return FunctionLog(&call, BLOG_ERROR, "%s: bad argument", name);
        }
        if (arg_val != is_and) {
            res = !is_and;
            break;
        }
    }
    NCDCall_SetResult(&call, ncd_make_boolean(NCDCall_ResMem(&call), res));
}
Example #17
0
static void imp_eval (NCDCall call)
{
    if (NCDCall_ArgCount(&call) != 2) {
        return FunctionLog(&call, BLOG_ERROR, "imp: need two arguments");
    }
    int res = 0;
    for (size_t i = 0; i < 2; i++) {
        NCDValRef arg = NCDCall_EvalArg(&call, i, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(arg)) {
            return;
        }
        int arg_val;
        if (!ncd_read_boolean(arg, &arg_val)) {
            return FunctionLog(&call, BLOG_ERROR, "imp: bad argument");
        }
        if (arg_val == i) {
            res = 1;
            break;
        }
    }
    NCDCall_SetResult(&call, ncd_make_boolean(NCDCall_ResMem(&call), res));
}
Example #18
0
static void concat_eval (NCDCall call)
{
    ExpString estr;
    if (!ExpString_Init(&estr)) {
        FunctionLog(&call, BLOG_ERROR, "ExpString_Init failed");
        goto fail0;
    }
    size_t count = NCDCall_ArgCount(&call);
    for (size_t i = 0; i < count; i++) {
        NCDValRef arg = NCDCall_EvalArg(&call, i, NCDCall_ResMem(&call));
        if (NCDVal_IsInvalid(arg)) {
            goto fail1;
        }
        if (!concat_recurser(&estr, arg, &call)) {
            goto fail1;
        }
    }
    NCDCall_SetResult(&call, NCDVal_NewStringBinMr(NCDCall_ResMem(&call), ExpString_GetMr(&estr)));
fail1:
    ExpString_Free(&estr);
fail0:
    return;
}
Example #19
0
static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
{
    struct instance *o = vo;
    o->i = i;
    
    // read arguments
    NCDValRef dest_arg;
    NCDValRef dest_prefix_arg = NCDVal_NewInvalid();
    NCDValRef gateway_arg;
    NCDValRef metric_arg;
    NCDValRef ifname_arg;
    if (!NCDVal_ListRead(params->args, 4, &dest_arg, &gateway_arg, &metric_arg, &ifname_arg) &&
        !NCDVal_ListRead(params->args, 5, &dest_arg, &dest_prefix_arg, &gateway_arg, &metric_arg, &ifname_arg)
    ) {
        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    if (!NCDVal_IsString(dest_arg) || !NCDVal_IsString(gateway_arg) ||
        !NCDVal_IsStringNoNulls(ifname_arg) ||
        (!NCDVal_IsInvalid(dest_prefix_arg) && !NCDVal_IsString(dest_prefix_arg))
    ) {
        ModuleLog(o->i, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    // read dest
    if (NCDVal_IsInvalid(dest_prefix_arg)) {
        if (!ipaddr6_parse_ipv6_ifaddr_bin(NCDVal_StringData(dest_arg), NCDVal_StringLength(dest_arg), &o->dest)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong CIDR notation dest");
            goto fail0;
        }
    } else {
        if (!ipaddr6_parse_ipv6_addr_bin(NCDVal_StringData(dest_arg), NCDVal_StringLength(dest_arg), &o->dest.addr)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong dest addr");
            goto fail0;
        }
        if (!ipaddr6_parse_ipv6_prefix_bin(NCDVal_StringData(dest_prefix_arg), NCDVal_StringLength(dest_prefix_arg), &o->dest.prefix)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong dest prefix");
            goto fail0;
        }
    }
    
    // read gateway and choose type
    if (NCDVal_StringEquals(gateway_arg, "none")) {
        o->type = TYPE_IFONLY;
    }
    else if (NCDVal_StringEquals(gateway_arg, "blackhole")) {
        o->type = TYPE_BLACKHOLE;
    } else {
        if (!ipaddr6_parse_ipv6_addr_bin(NCDVal_StringData(gateway_arg), NCDVal_StringLength(gateway_arg), &o->gateway)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong gateway");
            goto fail0;
        }
        o->type = TYPE_NORMAL;
    }
    
    // read metric
    uintmax_t metric;
    if (!ncd_read_uintmax(metric_arg, &metric) || metric > INT_MAX) {
        ModuleLog(i, BLOG_ERROR, "bad metric");
        goto fail0;
    }
    o->metric = metric;
    
    // null terminate ifname
    if (!NCDVal_StringNullTerminate(ifname_arg, &o->ifname_nts)) {
        ModuleLog(i, BLOG_ERROR, "NCDVal_StringNullTerminate failed");
        goto fail0;
    }
    
    // add route
    int res = 0; // to remove warning
    switch (o->type) {
        case TYPE_NORMAL:
            res = NCDIfConfig_add_ipv6_route(o->dest, &o->gateway, o->metric, o->ifname_nts.data);
            break;
        case TYPE_IFONLY:
            res = NCDIfConfig_add_ipv6_route(o->dest, NULL, o->metric, o->ifname_nts.data);
            break;
        case TYPE_BLACKHOLE:
            res = NCDIfConfig_add_ipv6_blackhole_route(o->dest, o->metric);
            break;
        default: ASSERT(0);
    }
    if (!res) {
        ModuleLog(o->i, BLOG_ERROR, "failed to add route");
        goto fail1;
    }
    
    // signal up
    NCDModuleInst_Backend_Up(o->i);
    return;
    
fail1:
    NCDValNullTermString_Free(&o->ifname_nts);
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #20
0
int NCDBProcessOpts_Init2 (NCDBProcessOpts *o, NCDValRef opts_arg, NCDBProcessOpts_func_unknown func_unknown, void *func_unknown_user, NCDModuleInst *i, int blog_channel,
                           int *out_keep_stdout, int *out_keep_stderr)
{
    if (!NCDVal_IsInvalid(opts_arg) && !NCDVal_IsMap(opts_arg)) {
        NCDModuleInst_Backend_Log(i, blog_channel, BLOG_ERROR, "options must be a map");
        goto fail0;
    }
    
    o->username = NULL;
    o->do_setsid = 0;
    
    int keep_stdout = 0;
    int keep_stderr = 0;
    
    if (!NCDVal_IsInvalid(opts_arg)) {
        for (NCDValMapElem me = NCDVal_MapFirst(opts_arg); !NCDVal_MapElemInvalid(me); me = NCDVal_MapNext(opts_arg, me)) {
            NCDValRef key = NCDVal_MapElemKey(opts_arg, me);
            NCDValRef val = NCDVal_MapElemVal(opts_arg, me);
            
            if (NCDVal_IsString(key) && NCDVal_StringEquals(key, "keep_stdout")) {
                keep_stdout = ncd_read_boolean(val);
            }
            else if (NCDVal_IsString(key) && NCDVal_StringEquals(key, "keep_stderr")) {
                keep_stderr = ncd_read_boolean(val);
            }
            else if (NCDVal_IsString(key) && NCDVal_StringEquals(key, "do_setsid")) {
                o->do_setsid = ncd_read_boolean(val);
            }
            else if (NCDVal_IsString(key) && NCDVal_StringEquals(key, "username")) {
                if (!NCDVal_IsStringNoNulls(val)) {
                    NCDModuleInst_Backend_Log(i, blog_channel, BLOG_ERROR, "username must be a string without nulls");
                    goto fail1;
                }
                b_cstring cstr = NCDVal_StringCstring(val);
                o->username = b_cstring_strdup(cstr, 0, cstr.length);
                if (!o->username) {
                    NCDModuleInst_Backend_Log(i, blog_channel, BLOG_ERROR, "b_cstring_strdup failed");
                    goto fail1;
                }
            }
            else {
                if (!func_unknown || !func_unknown(func_unknown_user, key, val)) {
                    NCDModuleInst_Backend_Log(i, blog_channel, BLOG_ERROR, "unknown option");
                    goto fail1;
                }
            }
        }
    }
    
    o->nfds = 0;
    if (keep_stdout) {
        o->fds[o->nfds] = 1;
        o->fds_map[o->nfds++] = 1;
    }
    if (keep_stderr) {
        o->fds[o->nfds] = 2;
        o->fds_map[o->nfds++] = 2;
    }
    o->fds[o->nfds] = -1;
    
    if (out_keep_stdout) {
        *out_keep_stdout = keep_stdout;
    }
    if (out_keep_stderr) {
        *out_keep_stderr = keep_stderr;
    }
    
    return 1;
    
fail1:
    if (o->username) {
        BFree(o->username);
    }
fail0:
    return 0;
}
Example #21
0
static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
{
    struct instance *o = vo;
    o->i = i;
    
    // check arguments
    NCDValRef ifname_arg;
    NCDValRef opts_arg = NCDVal_NewInvalid();
    if (!NCDVal_ListRead(params->args, 1, &ifname_arg) && !NCDVal_ListRead(params->args, 2, &ifname_arg, &opts_arg)) {
        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    if (!NCDVal_IsStringNoNulls(ifname_arg) || (!NCDVal_IsInvalid(opts_arg) && !NCDVal_IsList(opts_arg))) {
        ModuleLog(o->i, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    NCDValNullTermString hostname_nts = NCDValNullTermString_NewDummy();
    NCDValNullTermString vendorclassid_nts = NCDValNullTermString_NewDummy();
    
    struct BDHCPClient_opts opts = {};
    
    // read options
    size_t count = NCDVal_IsInvalid(opts_arg) ? 0 : NCDVal_ListCount(opts_arg);
    for (size_t j = 0; j < count; j++) {
        NCDValRef opt = NCDVal_ListGet(opts_arg, j);
        
        // read name
        if (!NCDVal_IsString(opt)) {
            ModuleLog(o->i, BLOG_ERROR, "wrong option name type");
            goto fail1;
        }
        
        if (NCDVal_StringEquals(opt, "hostname") || NCDVal_StringEquals(opt, "vendorclassid")) {
            int is_hostname = NCDVal_StringEquals(opt, "hostname");
            
            // read value
            if (j == count) {
                ModuleLog(o->i, BLOG_ERROR, "option value missing");
                goto fail1;
            }
            NCDValRef val = NCDVal_ListGet(opts_arg, j + 1);
            if (!NCDVal_IsStringNoNulls(val)) {
                ModuleLog(o->i, BLOG_ERROR, "wrong option value type");
                goto fail1;
            }
            
            // null terminate
            NCDValNullTermString nts;
            if (!NCDVal_StringNullTerminate(val, &nts)) {
                ModuleLog(o->i, BLOG_ERROR, "NCDVal_StringNullTerminate failed");
                goto fail1;
            }
            NCDValNullTermString *nts_ptr = (is_hostname ? &hostname_nts : &vendorclassid_nts);
            NCDValNullTermString_Free(nts_ptr);
            *nts_ptr = nts;
            
            if (is_hostname) {
                opts.hostname = nts.data;
            } else {
                opts.vendorclassid = nts.data;
            }
            
            j++;
        }
        else if (NCDVal_StringEquals(opt, "auto_clientid")) {
            opts.auto_clientid = 1;
        }
        else {
            ModuleLog(o->i, BLOG_ERROR, "unknown option name");
            goto fail1;
        }
    }
    
    // null terminate ifname
    NCDValNullTermString ifname_nts;
    if (!NCDVal_StringNullTerminate(ifname_arg, &ifname_nts)) {
        ModuleLog(i, BLOG_ERROR, "NCDVal_StringNullTerminate failed");
        goto fail1;
    }
    
    // init DHCP
    int res = BDHCPClient_Init(&o->dhcp, ifname_nts.data, opts, o->i->params->iparams->reactor, o->i->params->iparams->random2, (BDHCPClient_handler)dhcp_handler, o);
    NCDValNullTermString_Free(&ifname_nts);
    if (!res) {
        ModuleLog(o->i, BLOG_ERROR, "BDHCPClient_Init failed");
        goto fail1;
    }
    
    // set not up
    o->up = 0;
    
    // free options nts's
    NCDValNullTermString_Free(&hostname_nts);
    NCDValNullTermString_Free(&vendorclassid_nts);
    return;
    
fail1:
    NCDValNullTermString_Free(&hostname_nts);
    NCDValNullTermString_Free(&vendorclassid_nts);
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #22
0
static void func_new_substr (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
{
    NCDValRef str_arg;
    NCDValRef start_arg;
    NCDValRef max_arg = NCDVal_NewInvalid();
    if (!NCDVal_ListRead(params->args, 2, &str_arg, &start_arg) &&
        !NCDVal_ListRead(params->args, 3, &str_arg, &start_arg, &max_arg)
    ) {
        ModuleLog(i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    if (!NCDVal_IsString(str_arg) || !NCDVal_IsString(start_arg) ||
        (!NCDVal_IsInvalid(max_arg) && !NCDVal_IsString(max_arg))
    ) {
        ModuleLog(i, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    uintmax_t start;
    if (!ncd_read_uintmax(start_arg, &start) || start > SIZE_MAX) {
        ModuleLog(i, BLOG_ERROR, "wrong size");
        goto fail0;
    }
    
    uintmax_t max = SIZE_MAX;
    if (!NCDVal_IsInvalid(max_arg)) {
        if (!ncd_read_uintmax(max_arg, &max) || max > SIZE_MAX) {
            ModuleLog(i, BLOG_ERROR, "wrong max");
            goto fail0;
        }
    }
    
    const char *str_data = NCDVal_StringData(str_arg);
    size_t str_length = NCDVal_StringLength(str_arg);
    
    if (start > str_length) {
        ModuleLog(i, BLOG_ERROR, "start is beyond the end of the string");
        goto fail0;
    }
    
    const char *sub_data = str_data + start;
    size_t sub_length = str_length - start;
    if (sub_length > max) {
        sub_length = max;
    }
    
    int is_external = 0;
    BRefTarget *external_ref_target = NULL;
    
    if (NCDVal_IsExternalString(str_arg)) {
        is_external = 1;
        external_ref_target = NCDVal_ExternalStringTarget(str_arg);
    }
    else if (NCDVal_IsIdString(str_arg)) {
        is_external = 1;
    }
    
    substr_func_new_common(vo, i, sub_data, sub_length, is_external, external_ref_target);
    return;
    
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #23
0
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include <stdlib.h>

#include <misc/debug.h>
#include <ncd/extra/value_utils.h>

#include "build_cmdline.h"

int ncd_build_cmdline (NCDModuleInst *i, int log_channel, NCDValRef cmd_arg, char **out_exec, CmdLine *out_cl)
{
    ASSERT(!NCDVal_IsInvalid(cmd_arg))
    ASSERT(out_exec)
    ASSERT(out_cl)
    
    if (!NCDVal_IsList(cmd_arg)) {
        NCDModuleInst_Backend_Log(i, log_channel, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    size_t count = NCDVal_ListCount(cmd_arg);
    
    // read exec
    if (count == 0) {
        NCDModuleInst_Backend_Log(i, log_channel, BLOG_ERROR, "missing executable name");
        goto fail0;
    }
static void func_new_common (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params, int is_ifnot)
{
    struct instance *o = vo;
    o->i = i;
    
    // read arguments
    NCDValRef arg_addr;
    NCDValRef arg_net_addr;
    NCDValRef arg_net_prefix = NCDVal_NewInvalid();
    if (!NCDVal_ListRead(params->args, 2, &arg_addr, &arg_net_addr) &&
        !NCDVal_ListRead(params->args, 3, &arg_addr, &arg_net_addr, &arg_net_prefix) 
    ) {
        ModuleLog(o->i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    if (!NCDVal_IsString(arg_addr) || !NCDVal_IsString(arg_net_addr) ||
        (!NCDVal_IsInvalid(arg_net_prefix) && !NCDVal_IsString(arg_net_prefix))
    ) {
        ModuleLog(o->i, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    // parse addr
    struct ipv6_addr addr;
    if (!ipaddr6_parse_ipv6_addr_bin(NCDVal_StringData(arg_addr), NCDVal_StringLength(arg_addr), &addr)) {
        ModuleLog(o->i, BLOG_ERROR, "bad address");
        goto fail0;
    }
    
    // parse network
    struct ipv6_ifaddr network;
    if (NCDVal_IsInvalid(arg_net_prefix)) {
        if (!ipaddr6_parse_ipv6_ifaddr_bin(NCDVal_StringData(arg_net_addr), NCDVal_StringLength(arg_net_addr), &network)) {
            ModuleLog(o->i, BLOG_ERROR, "bad network in CIDR notation");
            goto fail0;
        }
    } else {
        if (!ipaddr6_parse_ipv6_addr_bin(NCDVal_StringData(arg_net_addr), NCDVal_StringLength(arg_net_addr), &network.addr)) {
            ModuleLog(o->i, BLOG_ERROR, "bad network address");
            goto fail0;
        }
        if (!ipaddr6_parse_ipv6_prefix_bin(NCDVal_StringData(arg_net_prefix), NCDVal_StringLength(arg_net_prefix), &network.prefix)) {
            ModuleLog(o->i, BLOG_ERROR, "bad network prefix");
            goto fail0;
        }
    }
    
    // test
    o->value = ipaddr6_ipv6_addrs_in_network(addr, network.addr, network.prefix);
    
    if (is_ifnot && o->value) {
        ModuleLog(o->i, BLOG_ERROR, "addresses belong to same subnet, not proceeding");
    }
    
    // signal up
    if (!is_ifnot || !o->value) {
        NCDModuleInst_Backend_Up(o->i);
    }
    
    return;
    
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #25
0
static int func_getvar (void *vo, const char *name, NCDValMem *mem, NCDValRef *out)
{
    struct instance *o = vo;
    ASSERT(o->up)
    
    if (!strcmp(name, "addr")) {
        uint32_t addr;
        BDHCPClient_GetClientIP(&o->dhcp, &addr);
        
        char str[IPADDR_PRINT_MAX];
        ipaddr_print_addr(addr, str);
        
        *out = NCDVal_NewString(mem, str);
        return 1;
    }
    
    if (!strcmp(name, "prefix")) {
        uint32_t addr;
        BDHCPClient_GetClientIP(&o->dhcp, &addr);
        uint32_t mask;
        BDHCPClient_GetClientMask(&o->dhcp, &mask);
        
        struct ipv4_ifaddr ifaddr;
        if (!ipaddr_ipv4_ifaddr_from_addr_mask(addr, mask, &ifaddr)) {
            ModuleLog(o->i, BLOG_ERROR, "bad netmask");
            return 0;
        }
        
        char str[10];
        sprintf(str, "%d", ifaddr.prefix);
        
        *out = NCDVal_NewString(mem, str);
        return 1;
    }
    
    if (!strcmp(name, "cidr_addr")) {
        uint32_t addr;
        BDHCPClient_GetClientIP(&o->dhcp, &addr);
        uint32_t mask;
        BDHCPClient_GetClientMask(&o->dhcp, &mask);
        
        struct ipv4_ifaddr ifaddr;
        if (!ipaddr_ipv4_ifaddr_from_addr_mask(addr, mask, &ifaddr)) {
            ModuleLog(o->i, BLOG_ERROR, "bad netmask");
            return 0;
        }
        
        char str[IPADDR_PRINT_MAX];
        ipaddr_print_ifaddr(ifaddr, str);
        
        *out = NCDVal_NewString(mem, str);
        return 1;
    }
    
    if (!strcmp(name, "gateway")) {
        char str[IPADDR_PRINT_MAX];
        
        uint32_t addr;
        if (!BDHCPClient_GetRouter(&o->dhcp, &addr)) {
            strcpy(str, "none");
        } else {
            ipaddr_print_addr(addr, str);
        }
        
        *out = NCDVal_NewString(mem, str);
        return 1;
    }
    
    if (!strcmp(name, "dns_servers")) {
        uint32_t servers[BDHCPCLIENT_MAX_DOMAIN_NAME_SERVERS];
        int num_servers = BDHCPClient_GetDNS(&o->dhcp, servers, BDHCPCLIENT_MAX_DOMAIN_NAME_SERVERS);
        
        *out = NCDVal_NewList(mem, num_servers);
        if (NCDVal_IsInvalid(*out)) {
            goto fail;
        }
        
        for (int i = 0; i < num_servers; i++) {
            char str[IPADDR_PRINT_MAX];
            ipaddr_print_addr(servers[i], str);
            
            NCDValRef server = NCDVal_NewString(mem, str);
            if (NCDVal_IsInvalid(server)) {
                goto fail;
            }
            
            if (!NCDVal_ListAppend(*out, server)) {
                goto fail;
            }
        }
        
        return 1;
    }
    
    if (!strcmp(name, "server_mac")) {
        uint8_t mac[6];
        BDHCPClient_GetServerMAC(&o->dhcp, mac);
        
        char str[18];
        sprintf(str, "%02"PRIX8":%02"PRIX8":%02"PRIX8":%02"PRIX8":%02"PRIX8":%02"PRIX8,
                mac[0], mac[1], mac[2], mac[3], mac[4], mac[5]);
        
        *out = NCDVal_NewString(mem, str);
        return 1;
    }
    
    return 0;
    
fail:
    *out = NCDVal_NewInvalid();
    return 1;
}
Example #26
0
static void func_new (void *vo, NCDModuleInst *i, const struct NCDModuleInst_new_params *params)
{
    struct instance *o = vo;
    o->i = i;
    
    // read arguments
    NCDValRef delimiter_arg;
    NCDValRef input_arg;
    NCDValRef limit_arg = NCDVal_NewInvalid();
    if (!NCDVal_ListRead(params->args, 2, &delimiter_arg, &input_arg) && !NCDVal_ListRead(params->args, 3, &delimiter_arg, &input_arg, &limit_arg)) {
        ModuleLog(i, BLOG_ERROR, "wrong arity");
        goto fail0;
    }
    if (!NCDVal_IsString(delimiter_arg) || !NCDVal_IsString(input_arg) || (!NCDVal_IsInvalid(limit_arg) && !NCDVal_IsString(limit_arg))) {
        ModuleLog(i, BLOG_ERROR, "wrong type");
        goto fail0;
    }
    
    size_t limit = SIZE_MAX;
    if (!NCDVal_IsInvalid(limit_arg)) {
        uintmax_t n;
        if (!ncd_read_uintmax(limit_arg, &n) || n == 0) {
            ModuleLog(i, BLOG_ERROR, "bad limit argument");
            goto fail0;
        }
        n--;
        limit = (n <= SIZE_MAX ? n : SIZE_MAX);
    }
    
    const char *del_data = NCDVal_StringData(delimiter_arg);
    size_t del_len = NCDVal_StringLength(delimiter_arg);
    
    if (del_len == 0) {
        ModuleLog(i, BLOG_ERROR, "delimiter must be nonempty");
        goto fail0;
    }
    
    size_t *table = BAllocArray(del_len, sizeof(table[0]));
    if (!table) {
        ModuleLog(i, BLOG_ERROR, "ExpArray_init failed");
        goto fail0;
    }
    
    build_substring_backtrack_table(del_data, del_len, table);
    
    if (!ExpArray_init(&o->arr, sizeof(struct substring), 8)) {
        ModuleLog(i, BLOG_ERROR, "ExpArray_init failed");
        goto fail1;
    }
    o->num = 0;
    
    const char *data = NCDVal_StringData(input_arg);
    size_t len = NCDVal_StringLength(input_arg);
    
    while (1) {
        size_t start;
        int is_end = 0;
        if (limit == 0 || !find_substring(data, len, del_data, del_len, table, &start)) {
            start = len;
            is_end = 1;
        }
        
        if (!ExpArray_resize(&o->arr, o->num + 1)) {
            ModuleLog(i, BLOG_ERROR, "ExpArray_init failed");
            goto fail2;
        }
        
        struct substring *elem = &((struct substring *)o->arr.v)[o->num];
        
        if (!(elem->data = BAlloc(start))) {
            ModuleLog(i, BLOG_ERROR, "BAlloc failed");
            goto fail2;
        }
        
        memcpy(elem->data, data, start);
        elem->len = start;
        o->num++;
        
        if (is_end) {
            break;
        }
        
        data += start + del_len;
        len -= start + del_len;
        limit--;
    }
    
    BFree(table);
    
    // signal up
    NCDModuleInst_Backend_Up(i);
    return;

fail2:
    while (o->num-- > 0) {
        BFree(((struct substring *)o->arr.v)[o->num].data);
    }
    free(o->arr.v);
fail1:
    BFree(table);
fail0:
    NCDModuleInst_Backend_DeadError(i);
}
Example #27
0
struct find_instance {
    NCDModuleInst *i;
    int is_found;
    uint64_t found_pos;
};

static uint64_t list_count (struct instance *o)
{
    return IndexedList_Count(&o->il);
}

static struct elem * insert_value (NCDModuleInst *i, struct instance *o, NCDValRef val, uint64_t idx)
{
    ASSERT(idx <= list_count(o))
    ASSERT(!NCDVal_IsInvalid(val))
    
    struct elem *e = malloc(sizeof(*e));
    if (!e) {
        ModuleLog(i, BLOG_ERROR, "malloc failed");
        goto fail0;
    }
    
    NCDValMem_Init(&e->mem);
    
    e->val = NCDVal_NewCopy(&e->mem, val);
    if (NCDVal_IsInvalid(e->val)) {
        goto fail1;
    }
    
    IndexedList_InsertAt(&o->il, &e->il_node, idx);