📄 options.c
字号:
/*
* Number of bytes left to store (some may already have
* been stored by a previous pass).
*/
int length;
/* If no data is available for this option, skip it. */
if (!options[code]) {
continue;
}
/*
* The client could ask for things that are mandatory,
* in which case we should avoid storing them twice...
*/
if (option_stored[code])
continue;
option_stored[code] = 1;
/* We should now have a constant length for the option. */
length = options[code]->len;
/* Do we add a NUL? */
if (terminate && dhcp_options[code].format[0] == 't') {
length++;
tto = 1;
} else
tto = 0;
/* Try to store the option. */
/*
* If the option's length is more than 255, we must
* store it in multiple hunks. Store 255-byte hunks
* first. However, in any case, if the option data will
* cross a buffer boundary, split it across that
* boundary.
*/
ix = 0;
optstart = bufix;
while (length) {
unsigned char incr = length > 255 ? 255 : length;
/*
* If this hunk of the buffer will cross a
* boundary, only go up to the boundary in this
* pass.
*/
if (bufix < first_cutoff &&
bufix + incr > first_cutoff)
incr = first_cutoff - bufix;
else if (bufix < second_cutoff &&
bufix + incr > second_cutoff)
incr = second_cutoff - bufix;
/*
* If this option is going to overflow the
* buffer, skip it.
*/
if (bufix + 2 + incr > buflen) {
bufix = optstart;
break;
}
/* Everything looks good - copy it in! */
buffer[bufix] = code;
buffer[bufix + 1] = incr;
if (tto && incr == length) {
memcpy(buffer + bufix + 2,
options[code]->value + ix, incr - 1);
buffer[bufix + 2 + incr - 1] = 0;
} else
memcpy(buffer + bufix + 2,
options[code]->value + ix, incr);
length -= incr;
ix += incr;
bufix += 2 + incr;
}
}
return (bufix);
}
/*
* Format the specified option so that a human can easily read it.
*/
char *
pretty_print_option(unsigned int code, unsigned char *data, int len,
int emit_commas, int emit_quotes)
{
static char optbuf[32768]; /* XXX */
int hunksize = 0, numhunk = -1, numelem = 0;
char fmtbuf[32], *op = optbuf;
int i, j, k, opleft = sizeof(optbuf);
unsigned char *dp = data;
struct in_addr foo;
char comma;
/* Code should be between 0 and 255. */
if (code > 255)
error("pretty_print_option: bad code %d", code);
if (emit_commas)
comma = ',';
else
comma = ' ';
/* Figure out the size of the data. */
for (i = 0; dhcp_options[code].format[i]; i++) {
if (!numhunk) {
warning("%s: Excess information in format string: %s",
dhcp_options[code].name,
&(dhcp_options[code].format[i]));
break;
}
numelem++;
fmtbuf[i] = dhcp_options[code].format[i];
switch (dhcp_options[code].format[i]) {
case 'A':
--numelem;
fmtbuf[i] = 0;
numhunk = 0;
break;
case 'X':
for (k = 0; k < len; k++)
if (!isascii(data[k]) ||
!isprint(data[k]))
break;
if (k == len) {
fmtbuf[i] = 't';
numhunk = -2;
} else {
fmtbuf[i] = 'x';
hunksize++;
comma = ':';
numhunk = 0;
}
fmtbuf[i + 1] = 0;
break;
case 't':
fmtbuf[i] = 't';
fmtbuf[i + 1] = 0;
numhunk = -2;
break;
case 'I':
case 'l':
case 'L':
hunksize += 4;
break;
case 's':
case 'S':
hunksize += 2;
break;
case 'b':
case 'B':
case 'f':
hunksize++;
break;
case 'e':
break;
default:
warning("%s: garbage in format string: %s",
dhcp_options[code].name,
&(dhcp_options[code].format[i]));
break;
}
}
/* Check for too few bytes... */
if (hunksize > len) {
warning("%s: expecting at least %d bytes; got %d",
dhcp_options[code].name, hunksize, len);
return ("<error>");
}
/* Check for too many bytes... */
if (numhunk == -1 && hunksize < len)
warning("%s: %d extra bytes",
dhcp_options[code].name, len - hunksize);
/* If this is an array, compute its size. */
if (!numhunk)
numhunk = len / hunksize;
/* See if we got an exact number of hunks. */
if (numhunk > 0 && numhunk * hunksize < len)
warning("%s: %d extra bytes at end of array",
dhcp_options[code].name, len - numhunk * hunksize);
/* A one-hunk array prints the same as a single hunk. */
if (numhunk < 0)
numhunk = 1;
/* Cycle through the array (or hunk) printing the data. */
for (i = 0; i < numhunk; i++) {
for (j = 0; j < numelem; j++) {
int opcount;
switch (fmtbuf[j]) {
case 't':
if (emit_quotes) {
*op++ = '"';
opleft--;
}
for (; dp < data + len; dp++) {
if (!isascii(*dp) ||
!isprint(*dp)) {
if (dp + 1 != data + len ||
*dp != 0) {
_snprintf(op, opleft,
"\\%03o", *dp);
op += 4;
opleft -= 4;
}
} else if (*dp == '"' ||
*dp == '\'' ||
*dp == '$' ||
*dp == '`' ||
*dp == '\\') {
*op++ = '\\';
*op++ = *dp;
opleft -= 2;
} else {
*op++ = *dp;
opleft--;
}
}
if (emit_quotes) {
*op++ = '"';
opleft--;
}
*op = 0;
break;
case 'I':
foo.s_addr = htonl(getULong(dp));
strncpy(op, inet_ntoa(foo), opleft - 1);
op[opleft - 1] = ANSI_NULL;
opcount = strlen(op);
if (opcount >= opleft)
goto toobig;
opleft -= opcount;
dp += 4;
break;
case 'l':
opcount = _snprintf(op, opleft, "%ld",
(long)getLong(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 4;
break;
case 'L':
opcount = _snprintf(op, opleft, "%ld",
(unsigned long)getULong(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 4;
break;
case 's':
opcount = _snprintf(op, opleft, "%d",
getShort(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 2;
break;
case 'S':
opcount = _snprintf(op, opleft, "%d",
getUShort(dp));
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
dp += 2;
break;
case 'b':
opcount = _snprintf(op, opleft, "%d",
*(char *)dp++);
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
break;
case 'B':
opcount = _snprintf(op, opleft, "%d", *dp++);
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
break;
case 'x':
opcount = _snprintf(op, opleft, "%x", *dp++);
if (opcount >= opleft || opcount == -1)
goto toobig;
opleft -= opcount;
break;
case 'f':
opcount = (size_t) strncpy(op, *dp++ ? "true" : "false", opleft - 1);
op[opleft - 1] = ANSI_NULL;
if (opcount >= opleft)
goto toobig;
opleft -= opcount;
break;
default:
warning("Unexpected format code %c", fmtbuf[j]);
}
op += strlen(op);
opleft -= strlen(op);
if (opleft < 1)
goto toobig;
if (j + 1 < numelem && comma != ':') {
*op++ = ' ';
opleft--;
}
}
if (i + 1 < numhunk) {
*op++ = comma;
opleft--;
}
if (opleft < 1)
goto toobig;
}
return (optbuf);
toobig:
warning("dhcp option too large");
return ("<error>");
}
void
do_packet(struct interface_info *interface, struct dhcp_packet *packet,
int len, unsigned int from_port, struct iaddr from, struct hardware *hfrom)
{
struct packet tp;
int i;
if (packet->hlen > sizeof(packet->chaddr)) {
note("Discarding packet with invalid hlen.");
return;
}
memset(&tp, 0, sizeof(tp));
tp.raw = packet;
tp.packet_length = len;
tp.client_port = from_port;
tp.client_addr = from;
tp.interface = interface;
tp.haddr = hfrom;
parse_options(&tp);
if (tp.options_valid &&
tp.options[DHO_DHCP_MESSAGE_TYPE].data)
tp.packet_type = tp.options[DHO_DHCP_MESSAGE_TYPE].data[0];
if (tp.packet_type)
dhcp(&tp);
else
bootp(&tp);
/* Free the data associated with the options. */
for (i = 0; i < 256; i++)
if (tp.options[i].len && tp.options[i].data)
free(tp.options[i].data);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -