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; }
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; }
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); }
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); }
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); }
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); }
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); })
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); }
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; }
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)); }
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)); }
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); }
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))); }
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)); }
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; }
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)); }
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)); }
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; }
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); }
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; }
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); }
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); }
* 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); }
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; }
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); }
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);