/*
* dnsutl - utilities to make DNS easier to configure
* Copyright (C) 2001, 2003, 2006, 2007 Peter Miller
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at
* your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <ac/ctype.h>
#include <ac/string.h>
#include <error.h>
#include <output.h>
#include <srrf.h>
#include <srrf/address.h>
#include <srrf/dhcp.h>
#include <srrf/origin.h>
#include <srrf/private.h>
#include <symtab.h>
static void
check_list_of_one_or_more_machines(srrf_t *rp)
{
string_ty *tmp;
size_t j;
if (rp->arg.nstrings < 1)
srrf_lex_error("at least one machine must be named");
for (j = 0; j < rp->arg.nstrings; ++j)
{
tmp = rp->arg.string[j];
rp->arg.string[j] = srrf_relative_to_absolute(tmp);
str_free(tmp);
}
}
/* ---------- filename -------------------------------------------*/
static void
filename_check_arguments(srrf_t *rp)
{
if (rp->arg.string[0]->str_text[0] != '/')
srrf_lex_error("the boot file must be an absolute path");
}
static void
filename_print(srrf_t *rp, void *p)
{
(void)p;
if (rp->arg.nstrings == 1)
{
output_printf
(
" filename = \"%s\";\n",
rp->arg.string[0]->str_text
);
}
}
/* ---------- hardware ethernet ----------------------------------*/
static void
hardware_ethernet_check_arguments(srrf_t * rp)
{
check_list_of_one_or_more_machines(rp);
srrf_lex_error
(
"you may not specify \"dhcp hardware-ethernet\" explicitly, "
"it is generated from the \"ether a\" fields"
);
}
static int
hex(int c)
{
static char digit[] = "0123456789ABCDEFabcdef";
static int value[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
10, 11, 12, 13, 14, 15,
10, 11, 12, 13, 14, 15,
};
char *cp;
cp = strchr(digit, c);
if (!cp)
return 0; /* should not happen */
return value[cp - digit];
}
static string_ty *
is_legal_ether_address(string_ty *s)
{
size_t nbytes;
unsigned char buffer[6 + 1]; /* must be more than 6 */
const char *cp;
cp = s->str_text;
nbytes = 0;
while (nbytes < SIZEOF(buffer))
{
if (!isxdigit(cp[0]))
return 0;
if (isxdigit(cp[1]))
{
buffer[nbytes++] = (hex(cp[0]) << 4) | hex(cp[1]);
cp += 2;
}
else
buffer[nbytes++] = hex(*cp++);
if (*cp != ':')
break;
++cp;
}
if (*cp != 0 || nbytes != 6)
return 0;
return
str_format
(
"%2.2x:%2.2x:%2.2x:%2.2x:%2.2x:%2.2x",
buffer[0],
buffer[1],
buffer[2],
buffer[3],
buffer[4],
buffer[5]
);
}
static void
hardware_ethernet_print(srrf_t *rp, void *arg)
{
dhcp_aux_ty *a;
string_ty *s;
srrf_t *rp2;
a = arg;
s = rp->arg.string[0];
rp2 = symtab_query(a->ether_a_stp, s);
if (!rp2)
{
output_error_locn
(
rp->file_name->str_text,
rp->line_number,
"host \"%s\" has no Ethernet address",
s->str_text
);
return;
}
s = is_legal_ether_address(rp2->arg.string[0]);
if (!s)
{
output_error_locn
(
rp2->file_name->str_text,
rp2->line_number,
"the string \"%s\" is not a legal Ethernet address",
rp2->arg.string[0]->str_text
);
return;
}
output_printf(" hardware ethernet %s;\n", s->str_text);
str_free(s);
}
/* ---------- fixed-address -------------------------------------*/
static void
fixed_address_check_arguments(srrf_t *rp)
{
check_list_of_one_or_more_machines(rp);
srrf_lex_error
(
"you may not specify \"fixed-address\" explicitly, "
"it is generated from the \"in a\" fields"
);
}
static void
fixed_address_print(srrf_t *rp, void *arg)
{
dhcp_aux_ty *a;
srrf_t *rp2;
a = arg;
rp2 = symtab_query(a->in_a_stp, rp->arg.string[0]);
if (!rp2)
{
output_error_locn
(
rp->file_name->str_text,
rp->line_number,
"host \"%s\" has no IP address",
rp->arg.string[0]->str_text
);
return;
}
output_printf(" fixed-address %s;\n", rp2->arg.string[0]->str_text);
}
/* ----------------------------------------------------------------*/
static srrf_type_ty type[] =
{
{
"filename",
1,
filename_check_arguments,
0, /* local_test */
0, /* print */
0, /* abs_to_rel */
filename_print, /* aux1 */
0,
},
{
"hardware-ethernet",
1,
hardware_ethernet_check_arguments,
0, /* local_test */
0, /* print */
0, /* abs_to_rel */
hardware_ethernet_print, /* aux1 */
0,
},
{
"fixed-address",
1,
fixed_address_check_arguments,
0, /* local_test */
0, /* print */
0, /* abs_to_rel */
fixed_address_print, /* aux1 */
0,
},
};
/*
* This symbol describes the class.
* It should be the only symbol exported from this file.
*/
srrf_class_ty srrf_class_dhcp =
{
"dhcp",
type,
SIZEOF(type)
};
syntax highlighted by Code2HTML, v. 0.9.1