How can I configure a DHCP server to assign addresses based on the OS that is running
Ray Phillips
r.phillips at uq.edu.au
Fri May 28 09:07:42 UTC 2010
Marc:
>It may be that using the option dhcp-client-identifier along with the -
>
>deny duplicates;
>
>declaration you told me about will be sufficient, but it is damn
>hard to discover the value of the dhcp-client-identifier for some of
>our systems that are already configured to receive a static IP
>address based on their MAC address. If these systems go dual boot,
>then I will have to temporarily configure them to receive a dynamic
>IP address and look in the dhcpd.leases file to discover what they
>are sending as a client identifier.
It may not help you to know them, but Edwin Groothuis' dhcpdump [1]
shows the client identifier in hex, for example:
---------------------------------------------------------------------------
TIME: 2010-05-04 18:53:22.209
IP: 123.456.78.9 (00:13:72:4c:4d:03) > 255.255.255.255 (ff:ff:ff:ff:ff:ff)
OP: 1 (BOOTPREQUEST)
HTYPE: 1 (Ethernet)
HLEN: 6
HOPS: 0
XID: c597bc8c
SECS: 0
FLAGS: 0
CIADDR: 123.456.78.9
YIADDR: 0.0.0.0
SIADDR: 0.0.0.0
GIADDR: 0.0.0.0
CHADDR: 00:13:72:4c:4d:03:00:00:00:00:00:00:00:00:00:00
SNAME: .
FNAME: .
OPTION: 53 ( 1) DHCP message type 8 (DHCPINFORM)
OPTION: 61 ( 7) Client-identifier 01:00:13:72:4c:4d:03
OPTION: 12 ( 3) Host name happy
OPTION: 60 ( 8) Vendor class identifier MSFT 5.0
OPTION: 55 ( 12) Parameter Request List 1 (Subnet mask)
15 (Domainname)
3 (Routers)
6 (DNS server)
44 (NetBIOS name server)
46 (NetBIOS node type)
47 (NetBIOS scope)
31 (Perform router discovery)
33 (Static route)
249 (MSFT - Classless route)
43 (Vendor specific info)
252 (MSFT - WinSock Proxy
Auto Detec
t)
OPTION: 82 ( 24) Relay Agent Information
Circuit-ID 00:04:00:08:01:08
Remote-ID 01:01:6a:6b:6d:72:63:2d:73:74:61:67:65:32
---------------------------------------------------------------------------
I've made some small modifications to version 1.8's dhcpdump.c file
to get it to compile under NetBSD/i386 5.0.2. I'll append them to
this message in case they're of interest. [2]
>I tried to set up a log statement as you suggested -
>
>log (info, option vendor-class-identifier);
>log (info, option dhcp-client-identifier);
>
>and discovered, much to my chagrin, that Microsoft sends a null byte
>as the second byte of the dhcp-client-identifier, so the log
>function truncates the string and only puts out the first byte.
>Linux puts out a leading null byte so nothing gets reported in the
>log file.
Windows uses the client's MAC address preceded by the hardware type
as the client identifier, so the null value you observed in the
second byte will change if the first byte of the client's MAC is
non-null.
>How this gets properly put out in the dhcpd.leases files is an
>interesting question!
I noticed 4.1.1's dhcpd.leases man page says:
The client identifier is recorded as a colon-separated hexadecimal list
or as a quoted string. If it is recorded as a quoted string and it
contains one or more non-printable characters, those characters are
represented as octal escapes - a backslash character followed by three
octal digits.
I've never seen it in /var/db/dhcpd.leases in hex form, only as octal
values and printable characters. Does anyone know when it would be
printed as a colon-separated hex string? Is there a way to choose
which representation is used?
Ray
[1]
http://www.mavetju.org/unix/general.php
[2]
I've inserted comments in diff's output before each change to explain them.
% diff -c dhcpdump.c.orig dhcpdump.c
*** dhcpdump.c.orig Fri May 28 16:07:41 2010
--- dhcpdump.c Sun May 2 23:49:56 2010
***************
--------------------------------------------------------------------------------
NetBSD doesn't have the file /usr/include/net/ethernet.h.
/usr/include/net/if.h and /usr/include/net/if_ether.h seem to contain
what dhcpdump needs from it.
--------------------------------------------------------------------------------
*** 11,17 ****
--- 11,22 ----
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
+ #if defined(__NetBSD__)
+ #include <net/if.h>
+ #include <net/if_ether.h>
+ #else
#include <net/ethernet.h>
+ #endif /* __NetBSD__ */
#include <netinet/in_systm.h>
#include <netinet/in.h>
#include <netinet/ip.h>
***************
--------------------------------------------------------------------------------
These arrays don't need to be unsigned chars. Changing them to
signed chars prevents some "pointer targets in passing argument 1 of
'strlen' differ in signedness" compiler warnings.
--------------------------------------------------------------------------------
*** 38,48 ****
#define LARGESTRING 1024
// header variables
! u_char timestamp[40]; // timestamp on header
! u_char mac_origin[40]; // mac address of origin
! u_char mac_destination[40]; // mac address of destination
! u_char ip_origin[40]; // ip address of origin
! u_char ip_destination[40]; // ip address of destination
int max_data_len; // maximum size of a packet
int tcpdump_style = -1;
--- 43,53 ----
#define LARGESTRING 1024
// header variables
! char timestamp[40]; // timestamp on header
! char mac_origin[40]; // mac address of origin
! char mac_destination[40]; // mac address of destination
! char ip_origin[40]; // ip address of origin
! char ip_destination[40]; // ip address of destination
int max_data_len; // maximum size of a packet
int tcpdump_style = -1;
***************
--------------------------------------------------------------------------------
strcpy()'s second argument should be type char * so no need to cast
it to u_char *
--------------------------------------------------------------------------------
*** 160,167 ****
strcpy(mac_destination,
ether_ntoa((struct ether_addr *)eh->ether_dhost));
! strcpy(ip_origin, (u_char *)inet_ntoa(ip->ip_src));
! strcpy(ip_destination, (u_char *)inet_ntoa(ip->ip_dst));
if (hmask && check_ch((u_char *)(sp + offset), ntohs(udp->uh_ulen)))
return;
--- 165,172 ----
strcpy(mac_destination,
ether_ntoa((struct ether_addr *)eh->ether_dhost));
! strcpy(ip_origin, inet_ntoa(ip->ip_src));
! strcpy(ip_destination, inet_ntoa(ip->ip_dst));
if (hmask && check_ch((u_char *)(sp + offset), ntohs(udp->uh_ulen)))
return;
***************
--------------------------------------------------------------------------------
The CAVEATS section of isprint()'s man page says:
The argument to isprint() must be EOF or representable as an unsigned
char; otherwise, the behavior is undefined. See the CAVEATS section of
ctype(3) for more details.
The last paragraph of ctype()'s man page's CAVEATS section says:
Values of type char or signed char must first be cast to unsigned char,
to ensure that the values are within the correct range. The result
should then be cast to int to avoid warnings from some compilers. Cast-
ing a negative-valued char or signed char directly to int will produce a
negative-valued int, which will be outside the range of allowed values
(unless it happens to be equal to EOF, but even that would not give the
desired result).
So I cast isprint()'s argument first to u_char then to int
--------------------------------------------------------------------------------
*** 259,265 ****
for (j = 0; j < 8; j++) {
char c = data[i * 8 + j];
if (i * 8 + j >= len) break;
! printf("%c", isprint(c) ? c : '.');
}
if (i * 8 + j < len) printf("\n\t\t\t\t\t ");
}
--- 264,270 ----
for (j = 0; j < 8; j++) {
char c = data[i * 8 + j];
if (i * 8 + j >= len) break;
! printf("%c", isprint((int)(u_char)c) ? c : '.');
}
if (i * 8 + j < len) printf("\n\t\t\t\t\t ");
}
***************
--------------------------------------------------------------------------------
Spelling mistake
--------------------------------------------------------------------------------
*** 278,284 ****
}
}
! // print the data as a hex-list seperated by colons
void printHexColon(u_char *data, int len) {
int i;
--- 283,289 ----
}
}
! // print the data as a hex-list separated by colons
void printHexColon(u_char *data, int len) {
int i;
***************
--------------------------------------------------------------------------------
strncpy()'s first and second arguments should be char *
--------------------------------------------------------------------------------
*** 301,307 ****
// print the header and the options.
int printdata(u_char *data, int data_len) {
int j, i;
! u_char buf[LARGESTRING];
if (data_len == 0)
return 0;
--- 306,312 ----
// print the header and the options.
int printdata(u_char *data, int data_len) {
int j, i;
! char buf[LARGESTRING];
if (data_len == 0)
return 0;
***************
*** 364,370 ****
case 60: // Domain name
case 86: // NDS Tree name
case 87: // NDS context
! strncpy(buf, &data[j + 2], data[j + 1]);
buf[data[j + 1]] = 0;
printf("%s", buf);
break;
--- 369,375 ----
case 60: // Domain name
case 86: // NDS Tree name
case 87: // NDS context
! strncpy(buf, (char *)&data[j + 2], data[j + 1]);
buf[data[j + 1]] = 0;
printf("%s", buf);
break;
***************
--------------------------------------------------------------------------------
There should be a new line before each Option 82 sub option, not just
the first.
--------------------------------------------------------------------------------
*** 510,523 ****
printf("-");
print8bits(data + j + 4);
printf(" ");
! strncpy(buf, &data[j + 5], data[j + 1] - 3);
buf[data[j + 1] - 3]=0;
printf("%s", buf);
break;
case 82: // Relay Agent Information
- printf("\n");
for (i = j + 2; i < j + data[j + 1]; ) {
printf("%-17s %-13s ", " ",
data[i] > sizeof(relayagent_suboptions) ?
"*wrong value*" :
--- 515,528 ----
printf("-");
print8bits(data + j + 4);
printf(" ");
! strncpy(buf, (char *)(&data[j + 5]), data[j + 1] - 3);
buf[data[j + 1] - 3]=0;
printf("%s", buf);
break;
case 82: // Relay Agent Information
for (i = j + 2; i < j + data[j + 1]; ) {
+ printf("\n");
printf("%-17s %-13s ", " ",
data[i] > sizeof(relayagent_suboptions) ?
"*wrong value*" :
***************
--------------------------------------------------------------------------------
There was an off-by-two error when indexing in the Option 82 sub options.
Previously the Option 82 section of dhcpdump's output would be like this:
OPTION: 82 ( 24) Relay Agent Information
Circuit-ID 00:04:00:08:03:0b (null)
02:0e:01:0c:6a:6b:6d:72:63:2d:73 *wrong value*
*MALFORMED -- T
OO LARGE*
instead of:
OPTION: 82 ( 24) Relay Agent Information
Circuit-ID 00:04:00:08:03:0b
Remote-ID 01:0c:6a:6b:6d:72:63:2d:73:74:61:67:65:32
--------------------------------------------------------------------------------
*** 527,533 ****
break;
}
printHexColon(data + i + 2, data[i + 1]);
! i += data[i + 1];
}
break;
--- 532,538 ----
break;
}
printHexColon(data + i + 2, data[i + 1]);
! i += data[i + 1] + 2;
}
break;
%
Once more for convenience, without the comments:
% diff dhcpdump.c.orig dhcpdump.c
13a14,17
> #if defined(__NetBSD__)
> #include <net/if.h>
> #include <net/if_ether.h>
> #else
14a19
> #endif /* __NetBSD__ */
41,45c46,50
< u_char timestamp[40]; // timestamp on header
< u_char mac_origin[40]; // mac address of origin
< u_char mac_destination[40]; // mac address of destination
< u_char ip_origin[40]; // ip address of origin
< u_char ip_destination[40]; // ip address of destination
---
> char timestamp[40]; // timestamp on header
> char mac_origin[40]; // mac address of origin
> char mac_destination[40]; // mac address of destination
> char ip_origin[40]; // ip address of origin
> char ip_destination[40]; // ip address of destination
163,164c168,169
< strcpy(ip_origin, (u_char *)inet_ntoa(ip->ip_src));
< strcpy(ip_destination, (u_char *)inet_ntoa(ip->ip_dst));
---
> strcpy(ip_origin, inet_ntoa(ip->ip_src));
> strcpy(ip_destination, inet_ntoa(ip->ip_dst));
262c267
< printf("%c", isprint(c) ? c : '.');
---
> printf("%c", isprint((int)(u_char)c) ? c : '.');
281c286
< // print the data as a hex-list seperated by colons
---
> // print the data as a hex-list separated by colons
304c309
< u_char buf[LARGESTRING];
---
> char buf[LARGESTRING];
367c372
< strncpy(buf, &data[j + 2], data[j + 1]);
---
> strncpy(buf, (char *)&data[j + 2], data[j + 1]);
513c518
< strncpy(buf, &data[j + 5], data[j + 1] - 3);
---
> strncpy(buf, (char *)(&data[j + 5]), data[j + 1] - 3);
519d523
< printf("\n");
520a525
> printf("\n");
530c535
< i += data[i + 1];
---
> i += data[i + 1] + 2;
%
More information about the dhcp-users
mailing list