%% options copyright owner = Dirk Krause copyright year = 2012-2014 license = bsd %% module #include "dk3all.h" #include "itadmin.h" $!trace-include /** Keywords used by the module. */ static char const * const itadmin_dhcp_c8_kw[] = { $!string-table # # 0: File name "dhcpd.conf" # dhcpd.conf # # 1: Indent level # # # 2: Line start option: # option: # # 3: option: must be replaced by option # option # # 4: Prefix for "not authorative" # not # # 5: File mode w # w # # 6: Start of dhcpd.conf class line # class " # # 7: End of dhcpd.conf class line # " { match hardware; } # # 8: Start of subclass line # subclass " # # 9: Center of subclass line # " 1: # # 10: End of subclass line # ; # # 11: Comment for machine in DHCP class # \# # # 12: Section start for shared-network # shared-network dhcpnet # # 13: Opening bracket # { # # 14: Closing bracket # } # # 15: Start of subnet line # subnet # # 16: Central part of subnet line # netmask # # 17: Network option router # option routers # # 18: Network option subnet-mask # option subnet-mask # # 19: Network option broadcast # option broadcast-address # # 20: Keyword pool # pool # # 21: Keyword range # range # # 22: Option "allow unknown clients" # allow unknown clients; # # 23: Option "deny unknown clients" # deny unknown clients; # # 24: Option "allow members of..." # allow members of " # # 25: Option deny members of ..." # deny members of " # # 26: End of allow/deny option # "; # # 27: DHCP group # group # # 28: Keyword host. # host # # 29: DHCP option host-name # option host-name " # # 30: Keyword hardware ethernet # hardware ethernet # # 31: Keyword fixed-address # fixed-address $!end }; /** Option names requiring special treatment. */ static char const * const itadmin_dhcp_option_names[] = { $!string-table authorative $!end }; /** Indent line. @param fipo Output file. @param ind Indent level. */ static void itadmin_dhcp_indent(FILE *fipo, int ind) { int i; for(i = 0; i < ind; i++) { fputs(itadmin_dhcp_c8_kw[1], fipo); } } /** Write DHCP options. @param job Job structure. @param fipo Output file. @param i_o Options storage iterator. @param objtype Object type (ignored). @param indent Indent level. */ static void itadmin_dhcp_write_options( itadmin_job *job, FILE *fipo, dk3_sto_it_t *i_o, int objtype, int indent ) { itadmin_dhcp_option *opt; char const *p1; size_t sl; int is_option; $? "+ itadmin_dhcp_write_options" dk3sto_it_reset(i_o); while(NULL != (opt = (itadmin_dhcp_option *)dk3sto_it_next(i_o))) { $? ". opt" is_option = 0; if(opt->k) { $? ". k" p1 = dk3str_c8_start(opt->k, NULL); if(p1) { $? ". text in k" sl = strlen(itadmin_dhcp_c8_kw[2]); if(dk3str_c8_len(p1) >= sl) { if(dk3str_c8_ncmp(p1, itadmin_dhcp_c8_kw[2], sl) == 0) { is_option = 1; p1 = dk3str_c8_start(&(p1[7]), NULL); } } } else { $? "! no text in k" } if(p1) { $? ". text in k" if(is_option) { $? ". option:" itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[3], fipo); fputs(p1, fipo); if(opt->v) { fputc('\t', fipo); fputs(opt->v, fipo); } fputc(';', fipo); fputc('\n', fipo); } else { $? ". not option:" switch(dk3str_c8_array_index(itadmin_dhcp_option_names, p1, 0)) { case 0: { $? ". authorative" is_option = 1; if(opt->v) { if(dk3str_c8_is_bool(opt->v)) { is_option = ((dk3str_c8_is_on(opt->v)) ? 1 : 0); } } itadmin_dhcp_indent(fipo, indent); if(!is_option) { fputs(itadmin_dhcp_c8_kw[4], fipo); } fputs(p1, fipo); fputc(';', fipo); fputc('\n', fipo); } break; default: { $? ". no special treatment" itadmin_dhcp_indent(fipo, indent); fputs(p1, fipo); if(opt->v) { fputc('\t', fipo); fputs(opt->v, fipo); fputc(';', fipo); fputc('\n', fipo); } } break; } } } else { $? "! no text in k" } } else { $? "! k" } } $? "- itadmin_dhcp_write_options" } /** Check DHCP pool for correct settings. @param job Job structure. @param dp Pool to check. @return 1 on success, 0 on error. */ static int itadmin_dhcp_check_pool( itadmin_job *job, itadmin_dhcp_pool *dp ) { int back = 0; char buffer[128]; $? "+ itadmin_dhcp_check_pool" if(dp->auc) { if(!(dp->duc)) { back = 1; } } else { if(dp->duc) { if(dp->acl) { back = 1; } } } if(!(back)) { /* ERROR: Inconsistent DHCP pool setup! */ sprintf( buffer, "%lu.%lu.%lu.%lu", (((dp->ip4s) >> 24) & 0x000000FFUL), (((dp->ip4s) >> 16) & 0x000000FFUL), (((dp->ip4s) >> 8) & 0x000000FFUL), ((dp->ip4s) & 0x000000FFUL) ); itadmin_tool_log_utf8_3(job, DK3_LL_ERROR, 134, 135, buffer); } $? "- itadmin_dhcp_check_pool %d", back return back; } /** Register DHCP group for all hosts in a class with a network. @param job Job structure. @param nw Network. @param dc DHCP class. @return 1 on success, 0 on error. */ static int itadmin_dhcp_register_class_groups( itadmin_job *job, itadmin_network *nw, itadmin_dhcp_class *dc ) { itadmin_host *ho; itadmin_dhcp_ginw *ginw; int back = 1; $? "+ itadmin_dhcp_register_class_groups" if(dc->i_ho) { dk3sto_it_reset(dc->i_ho); while(NULL != (ho = (itadmin_host *)dk3sto_it_next(dc->i_ho))) { if(ho->dg) { if(!(nw->s_dg)) { nw->s_dg = dk3sto_open_app(job->app); if(nw->s_dg) { dk3sto_set_comp(nw->s_dg, itadmin_comp_dhcp_ginw, 0); } } if(!(nw->i_dg)) { if(nw->s_dg) { nw->i_dg = dk3sto_it_open(nw->s_dg); } } if((nw->s_dg) && (nw->i_dg)) { ginw = (itadmin_dhcp_ginw *)dk3sto_it_find_like( nw->i_dg, (void *)((ho->dg)->sn), 1 ); if(!(ginw)) { ginw = itadmin_mem_dhcp_ginw_new(job, ho->dg); if(ginw) { if(!dk3sto_add(nw->s_dg, (void *)ginw)) { /* ERROR: Failed to add! */ back = 0; itadmin_mem_dhcp_ginw_del(ginw); } } else { back = 0; /* ERROR: Memory! */ } } } else { back = 0; } } } } $? "- itadmin_dhcp_register_class_groups %d", back return back; } /** Link DHCP classes to networks. @param job Job structure. @param i_nw Storage iterator for the networks. */ int itadmin_dhcp_link_classes( itadmin_job *job, dk3_sto_it_t *i_nw ) { char buffer[128]; itadmin_network *nw; itadmin_dhcp_pool *dp; itadmin_dhcp_class *dc; int back = 1; $? "+ itadmin_dhcp_link_classes" dk3sto_it_reset(i_nw); while(NULL != (nw = (itadmin_network *)dk3sto_it_next(i_nw))) { $? ".nw" if(nw->i_p) { $? ". have pools" dk3sto_it_reset(nw->i_p); while(NULL != (dp = (itadmin_dhcp_pool *)dk3sto_it_next(nw->i_p))) { if(!itadmin_dhcp_check_pool(job, dp)) { back = 0; } if(!(dp->auc)) { $? ". unknown clients not allowed" if(dp->duc) { $? ". unknown clients denied" if(dp->acl) { $? ". pool allows one class only" dc = dp->acl; $? ". class \"%s\"", TR_STR(dc->sn) if(!(dc->dhcpn)) { $? ". register new class to net" dc->dhcpn = nw; if(!(nw->s_dc)) { $? ". created storage" nw->s_dc = dk3sto_open_app(job->app); if(nw->s_dc) { $? ". storage ok" dk3sto_set_comp(nw->s_dc, itadmin_comp_dhcp_class, 0); } else { back = 0; $? "! storage" } } if(!(nw->i_dc)) { $? ". create iterator" if(nw->s_dc) { $? ". iterator ok" nw->i_dc = dk3sto_it_open(nw->s_dc); } else { $? "! iterator" back = 0; } } if((nw->s_dc) && (nw->i_dc)) { $? ". storage and iterator" if(!(dk3sto_it_find_like(nw->i_dc, (void *)dc, 0))) { $? ". must add" if(!(dk3sto_add(nw->s_dc, (void *)dc))) { back = 0; $? "! failed to add" } } } else { $? "! iterator or storage" back = 0; /* ERROR: Memory */ } } else { $? ". class already registered in a net" if(((dc->dhcpn)->ip4) != (nw->ip4)) { back = 0; $? "! class registered in another net" /* ERROR: Class assigned to pools in different nets! */ itadmin_tool_log_utf8_3(job, DK3_LL_ERROR, 136, 137, dc->sn); } } if(!itadmin_dhcp_register_class_groups(job, nw, dc)) { back = 0; } } else { $? "! no class specified" /* ERROR: No allowed class specified! */ sprintf( buffer, "%lu.%lu.%lu.%lu", (((dp->ip4s) >> 24) & 0x000000FFUL), (((dp->ip4s) >> 16) & 0x000000FFUL), (((dp->ip4s) >> 8) & 0x000000FFUL), ((dp->ip4s) & 0x000000FFUL) ); itadmin_tool_log_utf8_3(job, DK3_LL_ERROR, 134, 138, buffer); } } else { $? ". unknown clients not denied" } } else { $? ". unknown clients allowed" } } } else { $? ". no pools in network" } } $? "- itadmin_dhcp_link_classes %d", back return back; } /** Write DHCP classes to output file. @param job Job structure. @param fipo output file. */ static void itadmin_dhcp_write_classes(itadmin_job *job, FILE *fipo) { itadmin_dhcp_class *dc; itadmin_host *ho; int is_first; $? "+ itadmin_dhcp_write_classes" dk3sto_it_reset(job->i_dc); while(NULL != (dc = (itadmin_dhcp_class *)dk3sto_it_next(job->i_dc))) { $? ". class \"%s\" %s", TR_STR(dc->sn), TR_PTR(dc->dhcpn) if((dc->sn) && (dc->dhcpn)) { $? ". handle class" is_first = 1; if(dc->i_ho) { $? ". hosts iterator" dk3sto_it_reset(dc->i_ho); while(NULL != (ho = (itadmin_host *)dk3sto_it_next(dc->i_ho))) { if((ho->sn) && (ho->maca) && (!(ho->ipv4))) { if(is_first) { fputc('\n', fipo); fputs(itadmin_dhcp_c8_kw[6], fipo); fputs(dc->sn, fipo); fputs(itadmin_dhcp_c8_kw[7], fipo); fputc('\n', fipo); } is_first = 0; fputs(itadmin_dhcp_c8_kw[11], fipo); fputs(ho->sn, fipo); fputc('\n', fipo); fputs(itadmin_dhcp_c8_kw[8], fipo); fputs(dc->sn, fipo); fputs(itadmin_dhcp_c8_kw[9], fipo); fputs(ho->maca, fipo); fputs(itadmin_dhcp_c8_kw[10], fipo); fputc('\n', fipo); } } $? ". all hosts handled" } else { $? "! hosts iterator" } } } $? "- itadmin_dhcp_write_classes" } /** Write one DHCP pool to output. @param job Job structure. @param fipo Output file. @param dp Pool to write. @param indent Line indent level. */ static void itadmin_dhcp_write_pool( itadmin_job *job, FILE *fipo, itadmin_dhcp_pool *dp, int indent ) { itadmin_dhcp_class *dc; $? "+ itadmin_dhcp_write_pool" itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[20], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[13], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[21], fipo); itadmin_tool_write_ip(fipo, dp->ip4s); fputc('\t', fipo); itadmin_tool_write_ip(fipo, dp->ip4e); fputc(';', fipo); fputc('\n', fipo); if(dp->auc) { itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[22], fipo); fputc('\n', fipo); /* Fuer alle Klassen verbieten */ if(job->i_dc) { dk3sto_it_reset(job->i_dc); while(NULL != (dc = (itadmin_dhcp_class *)dk3sto_it_next(job->i_dc))) { itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[25], fipo); fputs(dc->sn, fipo); fputs(itadmin_dhcp_c8_kw[26], fipo); fputc('\n', fipo); } } } else { itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[23], fipo); fputc('\n', fipo); if(dp->acl) { itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[24], fipo); fputs((dp->acl)->sn, fipo); fputs(itadmin_dhcp_c8_kw[26], fipo); fputc('\n', fipo); } } /* POOL OPTIONS */ if(dp->i_do) { itadmin_dhcp_write_options(job, fipo, dp->i_do, 4, (indent+1)); } itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[14], fipo); fputc('\n', fipo); $? "- itadmin_dhcp_write_pool" } /** Write one host in group. @param job Job structure. @param fipo Output file. @param ho Host to write. @param ind Indent level at beginning of line. */ static void itadmin_dhcp_write_one_host( itadmin_job *job, FILE *fipo, itadmin_host *ho, int ind ) { $? "+ itadmin_dhcp_write_one_host \"%s\"", TR_STR(ho->sn) if((ho->sn) && (ho->maca)) { itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[28], fipo); fputs(ho->sn, fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[13], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, (ind + 1)); fputs(itadmin_dhcp_c8_kw[29], fipo); fputs(ho->sn, fipo); fputs(itadmin_dhcp_c8_kw[26], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, (ind + 1)); fputs(itadmin_dhcp_c8_kw[30], fipo); fputs(ho->maca, fipo); fputs(itadmin_dhcp_c8_kw[10], fipo); fputc('\n', fipo); if(ho->ipv4) { itadmin_dhcp_indent(fipo, (ind + 1)); fputs(itadmin_dhcp_c8_kw[31], fipo); itadmin_tool_write_ip(fipo, ho->ipv4); fputs(itadmin_dhcp_c8_kw[10], fipo); fputc('\n', fipo); } /* Added 2013-09-14: Must write host options too. */ if((ho->s_do) && (ho->i_do)) { itadmin_dhcp_write_options(job, fipo, ho->i_do, 3, (ind+1)); } itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[14], fipo); fputc('\n', fipo); } $? "- itadmin_dhcp_write_one_host" } /** Write hosts of one group for a network. */ static void itadmin_dhcp_write_group( itadmin_job *job, FILE *fipo, itadmin_network *nw, dk3_sto_it_t *i_ho, itadmin_dhcp_group *gr, int ind ) { itadmin_host *ho; itadmin_dhcp_class *dc; int is_first; int is_in_group; $? "+ itadmin_dhcp_write_group" if(gr) { $? ". group \"%s\"", TR_STR(gr->sn) } else { $? ". no group" } is_first = 1; if(i_ho) { dk3sto_it_reset(i_ho); while(NULL != (ho = (itadmin_host *)dk3sto_it_next(i_ho))) { if((ho->sn) && (ho->maca)) { if(is_first) { itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[27], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[13], fipo); fputc('\n', fipo); if(gr) { if(gr->i_do) { itadmin_dhcp_write_options(job, fipo, gr->i_do, 3, (ind+1)); fputc('\n', fipo); } } } is_first = 0; itadmin_dhcp_write_one_host(job, fipo, ho, (ind + 1)); } } } if(nw) { if(nw->i_dc) { dk3sto_it_reset(nw->i_dc); while(NULL != (dc = (itadmin_dhcp_class *)dk3sto_it_next(nw->i_dc))) { if(dc->i_ho) { dk3sto_it_reset(dc->i_ho); while(NULL != (ho = (itadmin_host *)dk3sto_it_next(dc->i_ho))) { is_in_group = 0; if(ho->dg) { if(gr) { if(itadmin_comp_dhcp_group((void *)(ho->dg),(void *)gr,0) == 0) { is_in_group = 1; } } } else { if(!(gr)) { is_in_group = 1; } } if(is_in_group) { if(is_first) { itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[27], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[13], fipo); fputc('\n', fipo); if(gr) { if(gr->i_do) { itadmin_dhcp_write_options(job,fipo,gr->i_do,3,(ind + 1)); fputc('\n', fipo); } } } is_first = 0; itadmin_dhcp_write_one_host(job, fipo, ho, (ind + 1)); } } } } } } if(!(is_first)) { itadmin_dhcp_indent(fipo, ind); fputs(itadmin_dhcp_c8_kw[14], fipo); fputc('\n', fipo); } $? "- itadmin_dhcp_write_group" } /** Write one network to output file. @param job Job structure. @param fipo Output file. @param nw Network to write. @param indent Indent at start of file. */ static void itadmin_dhcp_write_one_network( itadmin_job *job, FILE *fipo, itadmin_network *nw, int indent ) { itadmin_dhcp_pool *dp; itadmin_dhcp_ginw *ginw; $? "+ itadmin_dhcp_write_one_network" itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[15], fipo); itadmin_tool_write_ip(fipo, nw->ip4); fputs(itadmin_dhcp_c8_kw[16], fipo); itadmin_tool_write_ip(fipo, nw->ma4); fputc('\n', fipo); itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[13], fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[17], fipo); itadmin_tool_write_ip(fipo, nw->gw4); fputc(';', fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[18], fipo); itadmin_tool_write_ip(fipo, nw->ma4); fputc(';', fipo); fputc('\n', fipo); itadmin_dhcp_indent(fipo, (indent + 1)); fputs(itadmin_dhcp_c8_kw[19], fipo); itadmin_tool_write_ip(fipo, nw->bc4); fputc(';', fipo); fputc('\n', fipo); /* DHCP options */ if(nw->i_do) { itadmin_dhcp_write_options(job, fipo, nw->i_do, 2, (indent+1)); fputc('\n', fipo); } /* Pools */ if(nw->i_p) { dk3sto_it_reset(nw->i_p); while(NULL != (dp = (itadmin_dhcp_pool *)dk3sto_it_next(nw->i_p))) { itadmin_dhcp_write_pool(job, fipo, dp, (indent + 1)); } } /* Groups, direct for network and in DHCP classes */ if(nw->i_dg) { dk3sto_it_reset(nw->i_dg); while(NULL != (ginw = (itadmin_dhcp_ginw *)dk3sto_it_next(nw->i_dg))) { itadmin_dhcp_write_group(job,fipo,nw,ginw->i_h,ginw->gr,(indent + 1)); } } /* Hosts without groups, direct for network and in DHCP classes */ itadmin_dhcp_write_group(job, fipo, nw, nw->i_hoi, NULL, (indent + 1)); itadmin_dhcp_indent(fipo, indent); fputs(itadmin_dhcp_c8_kw[14], fipo); fputc('\n', fipo); $? "- itadmin_dhcp_write_one_network" } /** Write DHCP networks. @param job Job structure. @param fipo Output file. @param i_nw Iterator for networks storage. */ static void itadmin_dhcp_write_networks( itadmin_job *job, FILE *fipo, dk3_sto_it_t *i_nw ) { itadmin_network *nw; $? "+ itadmin_dhcp_write_networks" dk3sto_it_reset(i_nw); while(NULL != (nw = (itadmin_network *)dk3sto_it_next(i_nw))) { itadmin_dhcp_write_one_network(job, fipo, nw, 1); } $? "- itadmin_dhcp_write_networks" } /** Write data for one VLAN to output. @param job Job structure. @param fipo Output file. @param i_nw Networks iterator. @param i_do DHCP options storage iterator. */ static void itadmin_dhcp_write_vlan( itadmin_job *job, FILE *fipo, dk3_sto_it_t *i_nw, dk3_sto_it_t *i_do ) { itadmin_network *nw; int num_networks; $? "+ itadmin_dhcp_write_vlan" num_networks = 0; if(i_nw) { dk3sto_it_reset(i_nw); while(NULL != dk3sto_it_next(i_nw)) { num_networks++; } if(num_networks > 0) { dk3sto_it_reset(i_nw); if((num_networks > 1) || (i_do)) { fputs(itadmin_dhcp_c8_kw[12], fipo); fputc('\n', fipo); fputs(itadmin_dhcp_c8_kw[13], fipo); fputc('\n', fipo); if(i_do) { itadmin_dhcp_write_options(job, fipo, i_do, 1, 1); } itadmin_dhcp_write_networks(job, fipo, i_nw); fputs(itadmin_dhcp_c8_kw[14], fipo); fputc('\n', fipo); } else { nw = (itadmin_network *)dk3sto_it_next(i_nw); if(nw) { itadmin_dhcp_write_one_network(job, fipo, nw, 0); } } } } $? "- itadmin_dhcp_write_vlan" } /** Write output file for a VLAN or all networks. @param job Job structure. @param vlanname Name of VLAN (NULL if not specified). @param i_nw Iterator for all networks. @param i_do Iterator for VLAN DHCP options (may be NULL). @return 1 on success, 0 on error. */ static int itadmin_dhcpd_output( itadmin_job *job, dkChar const *vlanname, dk3_sto_it_t *i_nw, dk3_sto_it_t *i_do ) { FILE *fipo; int back = 0; $? "+ itadmin_dhcpd_output" if(itadmin_dhcp_link_classes(job, i_nw)) { $? ". link classes ok" fipo = dk3sf_c8_fopen_app( itadmin_dhcp_c8_kw[0], itadmin_dhcp_c8_kw[5], job->app ); if(fipo) { $? ". fopen" itadmin_dhcp_write_options(job, fipo, job->i_do, 0, 0); fputc('\n', fipo); itadmin_dhcp_write_classes(job, fipo); fputc('\n', fipo); itadmin_dhcp_write_vlan(job, fipo, i_nw, i_do); back = 1; #if DK3_CHAR_SIZE == 1 if(!dk3sf_fclose_fn_app(fipo, itadmin_dhcp_c8_kw[0], job->app)) { back = 0; } #else if(!dk3sf_fclose_fn_app(fipo, NULL, job->app)) { back = 0; } #endif } else { $? "! fopen" /* ERROR: Failed to open file. */ } } else { $? "! error while linking classes" } $? "- itadmin_dhcpd_output %d", back return back; } int itadmin_dhcpd_conf_output(itadmin_job *job) { char vlname[ITADMIN_CONFIG_LINE_SIZE]; itadmin_vlan *dhcpvl; int back = 0; int res; $? "+ itadmin_dhcpd_conf_output" if(job->vlan) { res = dk3str_str_to_c8u_app( vlname, sizeof(vlname), job->vlan, dk3app_get_encoding(job->app), job->app ); if(res) { dhcpvl = (itadmin_vlan *)dk3sto_it_find_like(job->i_vl, (void *)vlname, 1); if(dhcpvl) { back = itadmin_dhcpd_output(job, dhcpvl->s, dhcpvl->i_nw, dhcpvl->i_do); } else { dk3app_log_3(job->app, DK3_LL_ERROR, job->msg, 139, 140, job->vlan); } } else { /* ERROR: Failed to convert VLAN name! */ } } else { back = itadmin_dhcpd_output(job, NULL, job->i_nw, NULL); } $? "- itadmin_dhcpd_conf_output %d", back return back; }