Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
D
Dnsmasq
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
nanahira
Dnsmasq
Commits
e9817081
Commit
e9817081
authored
Jan 22, 2012
by
Simon Kelley
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dhcpv6'
parents
a2761754
52b92f4d
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
675 additions
and
170 deletions
+675
-170
src/NOTES
src/NOTES
+13
-0
src/config.h
src/config.h
+1
-1
src/dhcp.c
src/dhcp.c
+1
-2
src/dhcp6.c
src/dhcp6.c
+161
-18
src/dhcp6_protocol.h
src/dhcp6_protocol.h
+9
-0
src/dnsmasq.c
src/dnsmasq.c
+59
-12
src/dnsmasq.h
src/dnsmasq.h
+30
-7
src/lease.c
src/lease.c
+46
-6
src/netlink.c
src/netlink.c
+2
-2
src/network.c
src/network.c
+4
-3
src/option.c
src/option.c
+79
-44
src/rfc2131.c
src/rfc2131.c
+2
-2
src/rfc3315.c
src/rfc3315.c
+245
-73
src/util.c
src/util.c
+23
-0
No files found.
src/NOTES
View file @
e9817081
Worry about IPv6 leases and DUID in script-storage.
dhcpv6-range
dhcpv6-option
dhcpv6-option-force
dhcpv6-script ?
dhcpv6-optsfile
dhcpv6-hostsfile
dhcp-host =
[<hwaddr>][,id:<client_id>|*][,net:<netid>][,<ipv4addr>][\[ipv6addr\]][,<hostname>][,<lease_time>][,ignore]
IPv6 address like [2001:db8:do::2]
src/config.h
View file @
e9817081
...
...
@@ -116,7 +116,7 @@ RESOLVFILE
has no library dependencies other than libc */
#define HAVE_DHCP
/* #define HAVE_DHCP6 */
#define HAVE_DHCP6
#define HAVE_TFTP
#define HAVE_SCRIPT
/* #define HAVE_LUASCRIPT */
...
...
src/dhcp.c
View file @
e9817081
...
...
@@ -120,8 +120,7 @@ void dhcp_init(void)
check_dhcp_hosts
(
1
);
daemon
->
dhcp_packet
.
iov_len
=
sizeof
(
struct
dhcp_packet
);
daemon
->
dhcp_packet
.
iov_base
=
safe_malloc
(
daemon
->
dhcp_packet
.
iov_len
);
expand_buf
(
&
daemon
->
dhcp_packet
,
sizeof
(
struct
dhcp_packet
));
}
ssize_t
recv_dhcp_packet
(
int
fd
,
struct
msghdr
*
msg
)
...
...
src/dhcp6.c
View file @
e9817081
...
...
@@ -24,10 +24,10 @@ struct iface_param {
};
static
int
join_multicast
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
void
*
vparam
);
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
);
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
void
*
vparam
);
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
);
void
dhcp6_init
(
void
)
{
...
...
@@ -58,10 +58,15 @@ void dhcp6_init(void)
daemon
->
dhcp6fd
=
fd
;
/* If we've already inited DHCPv4, this becomes a no-op,
othewise sizeof(struct dhcp_packet) is as good an initial
size as any. */
expand_buf
(
&
daemon
->
dhcp_packet
,
sizeof
(
struct
dhcp_packet
));
expand_buf
(
&
daemon
->
outpacket
,
sizeof
(
struct
dhcp_packet
));
}
static
int
join_multicast
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
{
char
ifrn_name
[
IFNAMSIZ
];
struct
ipv6_mreq
mreq
;
...
...
@@ -71,7 +76,10 @@ static int join_multicast(struct in6_addr *local, int prefix,
struct
iname
*
tmp
;
(
void
)
prefix
;
(
void
)
scope
;
/* warnings */
/* scope == link */
if
(
scope
!=
253
)
return
1
;
if
(
!
indextoname
(
fd
,
if_index
,
ifrn_name
))
return
0
;
...
...
@@ -85,7 +93,7 @@ static int join_multicast(struct in6_addr *local, int prefix,
return
1
;
/* weird libvirt-inspired access control */
for
(
context
=
daemon
->
dhcp
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp
6
;
context
;
context
=
context
->
next
)
if
(
!
context
->
interface
||
strcmp
(
context
->
interface
,
ifrn_name
)
==
0
)
break
;
...
...
@@ -93,14 +101,14 @@ static int join_multicast(struct in6_addr *local, int prefix,
return
1
;
mreq
.
ipv6mr_interface
=
if_index
;
inet_pton
(
AF_INET6
,
ALL_RELAY_AGENTS_AND_SERVERS
,
&
maddr
);
inet_pton
(
AF_INET6
,
ALL_RELAY_AGENTS_AND_SERVERS
,
&
m
req
.
ipv6mr_multi
addr
);
if
(
!
setsockopt
(
fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
if
(
setsockopt
(
fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
inet_pton
(
AF_INET6
,
ALL_SERVERS
,
&
maddr
);
inet_pton
(
AF_INET6
,
ALL_SERVERS
,
&
m
req
.
ipv6mr_multi
addr
);
if
(
!
setsockopt
(
fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
if
(
setsockopt
(
fd
,
IPPROTO_IPV6
,
IPV6_JOIN_GROUP
,
&
mreq
,
sizeof
(
mreq
))
==
-
1
)
return
0
;
return
1
;
...
...
@@ -135,7 +143,7 @@ void dhcp6_packet(time_t now)
msg
.
msg_iov
=
&
daemon
->
dhcp_packet
;
msg
.
msg_iovlen
=
1
;
if
((
sz
=
recv_dhcp_packet
(
daemon
->
dhcp6fd
,
&
msg
)
==
-
1
)
||
sz
<=
4
)
if
((
sz
=
recv_dhcp_packet
(
daemon
->
dhcp6fd
,
&
msg
)
)
==
-
1
||
sz
<=
4
)
return
;
for
(
cmptr
=
CMSG_FIRSTHDR
(
&
msg
);
cmptr
;
cmptr
=
CMSG_NXTHDR
(
&
msg
,
cmptr
))
...
...
@@ -153,7 +161,7 @@ void dhcp6_packet(time_t now)
if
(
!
indextoname
(
daemon
->
dhcp6fd
,
if_index
,
ifr
.
ifr_name
))
return
;
ls
-
l
if
(
!
iface_check
(
AF_INET6
,
(
struct
all_addr
*
)
&
dest
,
ifr
.
ifr_name
))
return
;
...
...
@@ -162,7 +170,7 @@ ls -l
return
;
/* weird libvirt-inspired access control */
for
(
context
=
daemon
->
dhcp
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp
6
;
context
;
context
=
context
->
next
)
if
(
!
context
->
interface
||
strcmp
(
context
->
interface
,
ifr
.
ifr_name
)
==
0
)
break
;
...
...
@@ -170,7 +178,7 @@ ls -l
return
;
/* unlinked contexts are marked by context->current == context */
for
(
context
=
daemon
->
dhcp
;
context
;
context
=
context
->
next
)
for
(
context
=
daemon
->
dhcp
6
;
context
;
context
=
context
->
next
)
context
->
current
=
context
;
parm
.
current
=
NULL
;
...
...
@@ -182,7 +190,7 @@ ls -l
lease_prune
(
NULL
,
now
);
/* lose any expired leases */
msg
.
msg_iov
=
&
daemon
->
dhcp_packet
;
sz
=
dhcp6_reply
(
parm
.
current
,
sz
);
sz
=
dhcp6_reply
(
parm
.
current
,
sz
,
now
);
/* ifr.ifr_name, if_index, (size_t)sz,
now, unicast_dest, &is_inform, pxe_fd, iface_addr); */
lease_update_file
(
now
);
...
...
@@ -193,15 +201,15 @@ ls -l
}
static
int
complete_context6
(
struct
in6_addr
*
local
,
int
prefix
,
int
scope
,
int
if_index
,
void
*
vparam
)
int
scope
,
int
if_index
,
int
dad
,
void
*
vparam
)
{
struct
dhcp_context
*
context
;
struct
iface_param
*
param
=
vparam
;
(
void
)
scope
;
/* warning */
for
(
context
=
daemon
->
dhcp6
;
context
;
context
=
context
->
next
)
{
if
((
context
->
flags
&
CONTEXT_IPV6
)
&&
prefix
==
context
->
prefix
&&
if
(
prefix
==
context
->
prefix
&&
is_same_net6
(
local
,
&
context
->
start6
,
prefix
)
&&
is_same_net6
(
local
,
&
context
->
end6
,
prefix
))
{
...
...
@@ -215,6 +223,141 @@ static int complete_context6(struct in6_addr *local, int prefix,
}
return
1
;
}
struct
dhcp_config
*
config_find_by_address6
(
struct
dhcp_config
*
configs
,
struct
in6_addr
*
net
,
int
prefix
,
u64
addr
)
{
struct
dhcp_config
*
config
;
for
(
config
=
configs
;
config
;
config
=
config
->
next
)
if
((
config
->
flags
&
CONFIG_ADDR6
)
&&
is_same_net6
(
&
config
->
addr6
,
net
,
prefix
)
&&
(
prefix
==
128
||
addr6part
(
&
config
->
addr6
)
==
addr
))
return
config
;
return
NULL
;
}
int
address6_allocate
(
struct
dhcp_context
*
context
,
unsigned
char
*
clid
,
int
clid_len
,
struct
dhcp_netid
*
netids
,
struct
in6_addr
*
ans
)
{
/* Find a free address: exclude anything in use and anything allocated to
a particular hwaddr/clientid/hostname in our configuration.
Try to return from contexts which match netids first.
Note that we assume the address prefix lengths are 64 or greater, so we can
get by with 64 bit arithmetic.
*/
u64
start
,
addr
;
struct
dhcp_context
*
c
,
*
d
;
int
i
,
pass
;
u64
j
;
/* hash hwaddr: use the SDBM hashing algorithm. This works
for MAC addresses, let's see how it manages with client-ids! */
for
(
j
=
0
,
i
=
0
;
i
<
clid_len
;
i
++
)
j
+=
clid
[
i
]
+
(
j
<<
6
)
+
(
j
<<
16
)
-
j
;
for
(
pass
=
0
;
pass
<=
1
;
pass
++
)
for
(
c
=
context
;
c
;
c
=
c
->
current
)
if
(
c
->
flags
&
(
CONTEXT_STATIC
|
CONTEXT_PROXY
))
continue
;
else
if
(
!
match_netid
(
c
->
filter
,
netids
,
pass
))
continue
;
else
{
start
=
addr6part
(
&
c
->
start6
)
+
((
j
+
c
->
addr_epoch
)
%
(
1
+
addr6part
(
&
c
->
end6
)
-
addr6part
(
&
c
->
start6
)));
/* iterate until we find a free address. */
addr
=
start
;
do
{
/* eliminate addresses in use by the server. */
for
(
d
=
context
;
d
;
d
=
d
->
current
)
if
(
addr
==
addr6part
(
&
d
->
router6
))
break
;
if
(
!
d
&&
!
lease6_find_by_addr
(
&
c
->
start6
,
c
->
prefix
,
addr
)
&&
!
config_find_by_address6
(
daemon
->
dhcp_conf
,
&
c
->
start6
,
c
->
prefix
,
addr
))
{
*
ans
=
c
->
start6
;
setaddr6part
(
ans
,
addr
);
return
1
;
}
addr
++
;
if
(
addr
==
addr6part
(
&
c
->
end6
)
+
1
)
addr
=
addr6part
(
&
c
->
start6
);
}
while
(
addr
!=
start
);
}
return
0
;
}
struct
dhcp_context
*
address6_available
(
struct
dhcp_context
*
context
,
struct
in6_addr
*
taddr
,
struct
dhcp_netid
*
netids
)
{
u64
start
,
end
,
addr
=
addr6part
(
taddr
);
struct
dhcp_context
*
tmp
;
for
(
tmp
=
context
;
tmp
;
tmp
=
tmp
->
current
)
{
start
=
addr6part
(
&
tmp
->
start6
);
end
=
addr6part
(
&
tmp
->
end6
);
if
(
!
(
tmp
->
flags
&
(
CONTEXT_STATIC
|
CONTEXT_PROXY
))
&&
is_same_net6
(
&
context
->
start6
,
taddr
,
context
->
prefix
)
&&
is_same_net6
(
&
context
->
end6
,
taddr
,
context
->
prefix
)
&&
addr
>=
start
&&
addr
<=
end
&&
match_netid
(
tmp
->
filter
,
netids
,
1
))
return
tmp
;
}
return
NULL
;
}
struct
dhcp_context
*
narrow_context6
(
struct
dhcp_context
*
context
,
struct
in6_addr
*
taddr
,
struct
dhcp_netid
*
netids
)
{
/* We start of with a set of possible contexts, all on the current physical interface.
These are chained on ->current.
Here we have an address, and return the actual context correponding to that
address. Note that none may fit, if the address came a dhcp-host and is outside
any dhcp-range. In that case we return a static range if possible, or failing that,
any context on the correct subnet. (If there's more than one, this is a dodgy
configuration: maybe there should be a warning.) */
struct
dhcp_context
*
tmp
;
if
(
!
(
tmp
=
address6_available
(
context
,
taddr
,
netids
)))
{
for
(
tmp
=
context
;
tmp
;
tmp
=
tmp
->
current
)
if
(
match_netid
(
tmp
->
filter
,
netids
,
1
)
&&
is_same_net6
(
taddr
,
&
tmp
->
start6
,
tmp
->
prefix
)
&&
(
tmp
->
flags
&
CONTEXT_STATIC
))
break
;
if
(
!
tmp
)
for
(
tmp
=
context
;
tmp
;
tmp
=
tmp
->
current
)
if
(
match_netid
(
tmp
->
filter
,
netids
,
1
)
&&
is_same_net6
(
taddr
,
&
tmp
->
start6
,
tmp
->
prefix
)
&&
!
(
tmp
->
flags
&
CONTEXT_PROXY
))
break
;
}
/* Only one context allowed now */
if
(
tmp
)
tmp
->
current
=
NULL
;
return
tmp
;
}
#endif
src/dhcp6_protocol.h
View file @
e9817081
...
...
@@ -53,3 +53,12 @@
#define OPTION6_INTERFACE_ID 18
#define OPTION6_RECONFIGURE_MSG 19
#define OPTION6_RECONF_ACCEPT 20
#define DHCP6SUCCESS 0
#define DHCP6UNSPEC 1
#define DHCP6NOADDRS 2
#define DHCP6NOBINDING 3
#define DHCP6NOTONLINK 4
#define DHCP6USEMULTI 5
src/dnsmasq.c
View file @
e9817081
...
...
@@ -87,7 +87,7 @@ int main (int argc, char **argv)
#ifdef HAVE_DHCP
if
(
!
daemon
->
lease_file
)
{
if
(
daemon
->
dhcp
)
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
daemon
->
lease_file
=
LEASEFILE
;
}
#endif
...
...
@@ -146,13 +146,18 @@ int main (int argc, char **argv)
now
=
dnsmasq_time
();
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
)
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
{
/* Note that order matters here, we must call lease_init before
creating any file descriptors which shouldn't be leaked
to the lease-script init process. */
lease_init
(
now
);
dhcp_init
();
if
(
daemon
->
dhcp
)
dhcp_init
();
#ifdef HAVE_DHCP6
if
(
daemon
->
dhcp6
)
dhcp6_init
();
#endif
}
#endif
...
...
@@ -198,7 +203,7 @@ int main (int argc, char **argv)
#if defined(HAVE_SCRIPT)
/* Note getpwnam returns static storage */
if
(
daemon
->
dhcp
&&
daemon
->
scriptuser
&&
if
(
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
&&
daemon
->
scriptuser
&&
(
daemon
->
lease_change_command
||
daemon
->
luascript
))
{
if
((
ent_pw
=
getpwnam
(
daemon
->
scriptuser
)))
...
...
@@ -350,7 +355,7 @@ int main (int argc, char **argv)
/* if we are to run scripts, we need to fork a helper before dropping root. */
daemon
->
helperfd
=
-
1
;
#ifdef HAVE_SCRIPT
if
(
daemon
->
dhcp
&&
(
daemon
->
lease_change_command
||
daemon
->
luascript
))
if
(
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
&&
(
daemon
->
lease_change_command
||
daemon
->
luascript
))
daemon
->
helperfd
=
create_helper
(
pipewrite
,
err_pipe
[
1
],
script_uid
,
script_gid
,
max_fd
);
#endif
...
...
@@ -490,25 +495,51 @@ int main (int argc, char **argv)
my_syslog
(
LOG_INFO
,
_
(
"asynchronous logging enabled, queue limit is %d messages"
),
daemon
->
max_logs
);
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
)
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
{
struct
dhcp_context
*
dhcp_tmp
;
for
(
dhcp_tmp
=
daemon
->
dhcp
;
dhcp_tmp
;
dhcp_tmp
=
dhcp_tmp
->
next
)
int
family
=
AF_INET
;
dhcp_tmp
=
daemon
->
dhcp
;
again:
for
(;
dhcp_tmp
;
dhcp_tmp
=
dhcp_tmp
->
next
)
{
void
*
start
=
&
dhcp_tmp
->
start
;
void
*
end
=
&
dhcp_tmp
->
end
;
#ifdef HAVE_DHCP6
if
(
family
==
AF_INET6
)
{
start
=
&
dhcp_tmp
->
start6
;
end
=
&
dhcp_tmp
->
end6
;
}
#endif
prettyprint_time
(
daemon
->
dhcp_buff2
,
dhcp_tmp
->
lease_time
);
strcpy
(
daemon
->
dhcp_buff
,
inet_ntoa
(
dhcp_tmp
->
start
));
inet_ntop
(
family
,
start
,
daemon
->
dhcp_buff
,
256
);
inet_ntop
(
family
,
end
,
daemon
->
dhcp_buff3
,
256
);
my_syslog
(
MS_DHCP
|
LOG_INFO
,
(
dhcp_tmp
->
flags
&
CONTEXT_STATIC
)
?
_
(
"DHCP, static leases only on %.0s%s, lease time %s"
)
:
(
dhcp_tmp
->
flags
&
CONTEXT_PROXY
)
?
_
(
"DHCP, proxy on subnet %.0s%s%.0s"
)
:
_
(
"DHCP, IP range %s -- %s, lease time %s"
),
daemon
->
dhcp_buff
,
inet_ntoa
(
dhcp_tmp
->
end
),
daemon
->
dhcp_buff2
);
daemon
->
dhcp_buff
,
daemon
->
dhcp_buff3
,
daemon
->
dhcp_buff2
);
}
#ifdef HAVE_DHCP6
if
(
family
==
AF_INET
)
{
family
=
AF_INET6
;
dhcp_tmp
=
daemon
->
dhcp6
;
goto
again
;
}
#endif
}
#endif
#ifdef HAVE_TFTP
if
(
daemon
->
tftp_unlimited
||
daemon
->
tftp_interfaces
)
{
...
...
@@ -613,6 +644,14 @@ int main (int argc, char **argv)
}
#endif
#ifdef HAVE_DHCP6
if
(
daemon
->
dhcp6
)
{
FD_SET
(
daemon
->
dhcp6fd
,
&
rset
);
bump_maxfd
(
daemon
->
dhcp6fd
,
&
maxfd
);
}
#endif
#ifdef HAVE_LINUX_NETWORK
FD_SET
(
daemon
->
netlinkfd
,
&
rset
);
bump_maxfd
(
daemon
->
netlinkfd
,
&
maxfd
);
...
...
@@ -708,6 +747,14 @@ int main (int argc, char **argv)
dhcp_packet
(
now
,
1
);
}
#ifdef HAVE_DHCP6
if
(
daemon
->
dhcp6
)
{
if
(
FD_ISSET
(
daemon
->
dhcp6fd
,
&
rset
))
dhcp6_packet
(
now
);
}
#endif
# ifdef HAVE_SCRIPT
if
(
daemon
->
helperfd
!=
-
1
&&
FD_ISSET
(
daemon
->
helperfd
,
&
wset
))
helper_write
();
...
...
@@ -869,7 +916,7 @@ static void async_event(int pipe, time_t now)
case
EVENT_ALARM
:
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
)
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
{
lease_prune
(
NULL
,
now
);
lease_update_file
(
now
);
...
...
@@ -1027,7 +1074,7 @@ void clear_cache_and_reload(time_t now)
cache_reload
();
#ifdef HAVE_DHCP
if
(
daemon
->
dhcp
)
if
(
daemon
->
dhcp
||
daemon
->
dhcp6
)
{
if
(
option_bool
(
OPT_ETHERS
))
dhcp_read_ethers
();
...
...
src/dnsmasq.h
View file @
e9817081
...
...
@@ -54,6 +54,7 @@
typedef
unsigned
char
u8
;
typedef
unsigned
short
u16
;
typedef
unsigned
int
u32
;
typedef
unsigned
long
long
u64
;
#include "dns_protocol.h"
#include "dhcp_protocol.h"
...
...
@@ -448,8 +449,8 @@ struct dhcp_lease {
#ifdef HAVE_BROKEN_RTC
unsigned
int
length
;
#endif
int
hwaddr_len
,
hwaddr_type
;
unsigned
char
hwaddr
[
DHCP_CHADDR_MAX
];
int
hwaddr_len
,
hwaddr_type
;
/* hw_type used for iaid in v6 */
unsigned
char
hwaddr
[
DHCP_CHADDR_MAX
];
/* also IPv6 address */
struct
in_addr
addr
,
override
,
giaddr
;
unsigned
char
*
extradata
;
unsigned
int
extradata_len
,
extradata_size
;
...
...
@@ -489,6 +490,9 @@ struct dhcp_config {
unsigned
char
*
clid
;
/* clientid */
char
*
hostname
,
*
domain
;
struct
dhcp_netid_list
*
netid
;
#ifdef HAVE_DHCP6
struct
in6_addr
addr6
;
#endif
struct
in_addr
addr
;
time_t
decline_time
;
unsigned
int
lease_time
;
...
...
@@ -506,6 +510,7 @@ struct dhcp_config {
#define CONFIG_ADDR_HOSTS 512
/* address added by from /etc/hosts */
#define CONFIG_DECLINED 1024
/* address declined by client */
#define CONFIG_BANK 2048
/* from dhcp hosts file */
#define CONFIG_ADDR6 4096
struct
dhcp_opt
{
int
opt
,
len
,
flags
;
...
...
@@ -588,6 +593,7 @@ struct dhcp_context {
struct
in_addr
start
,
end
;
/* range of available addresses */
#ifdef HAVE_DHCP6
struct
in6_addr
start6
,
end6
;
/* range of available addresses */
struct
in6_addr
local6
,
router6
;
int
prefix
;
#endif
int
flags
;
...
...
@@ -600,7 +606,6 @@ struct dhcp_context {
#define CONTEXT_NETMASK 2
#define CONTEXT_BRDCAST 4
#define CONTEXT_PROXY 8
#define CONTEXT_IPV6 16
struct
ping_result
{
struct
in_addr
addr
;
...
...
@@ -681,7 +686,7 @@ extern struct daemon {
struct
hostsfile
*
addn_hosts
;
struct
dhcp_context
*
dhcp
,
*
dhcp6
;
struct
dhcp_config
*
dhcp_conf
;
struct
dhcp_opt
*
dhcp_opts
,
*
dhcp_match
;
struct
dhcp_opt
*
dhcp_opts
,
*
dhcp_match
,
*
dhcp_opts6
;
struct
dhcp_vendor
*
dhcp_vendors
;
struct
dhcp_mac
*
dhcp_macs
;
struct
dhcp_boot
*
boot_config
;
...
...
@@ -814,6 +819,8 @@ time_t dnsmasq_time(void);
int
is_same_net
(
struct
in_addr
a
,
struct
in_addr
b
,
struct
in_addr
mask
);
#ifdef HAVE_IPV6
int
is_same_net6
(
struct
in6_addr
*
a
,
struct
in6_addr
*
b
,
int
prefixlen
);
u64
addr6part
(
struct
in6_addr
*
addr
);
void
setaddr6part
(
struct
in6_addr
*
addr
,
u64
host
);
#endif
int
retry_send
(
void
);
void
prettyprint_time
(
char
*
buf
,
unsigned
int
t
);
...
...
@@ -908,9 +915,11 @@ char *get_domain(struct in_addr addr);
void
lease_update_file
(
time_t
now
);
void
lease_update_dns
();
void
lease_init
(
time_t
now
);
struct
dhcp_lease
*
lease
_allocate4
(
struct
in_addr
addr
);
struct
dhcp_lease
*
lease
4_allocate
(
struct
in_addr
addr
);
#ifdef HAVE_DHCP6
struct
dhcp_lease
*
lease_allocate6
(
struct
in6_addr
*
addrp
);
struct
dhcp_lease
*
lease6_allocate
(
struct
in6_addr
*
addrp
);
struct
dhcp_lease
*
lease6_find_by_addr
(
struct
in6_addr
*
net
,
int
prefix
,
u64
addr
);
struct
dhcp_lease
*
lease6_find_by_client
(
unsigned
char
*
clid
,
int
clid_len
,
int
iaid
);
#endif
void
lease_set_hwaddr
(
struct
dhcp_lease
*
lease
,
unsigned
char
*
hwaddr
,
unsigned
char
*
clid
,
int
hw_len
,
int
hw_type
,
int
clid_len
);
...
...
@@ -991,8 +1000,22 @@ int get_incoming_mark(union mysockaddr *peer_addr, struct all_addr *local_addr,
int
istcp
,
unsigned
int
*
markp
);
#endif
/* dhcp6.c */
#ifdef HAVE_DHCP6
void
dhcp6_init
(
void
);
void
dhcp6_packet
(
time_t
now
);
int
address6_allocate
(
struct
dhcp_context
*
context
,
unsigned
char
*
clid
,
int
clid_len
,
struct
dhcp_netid
*
netids
,
struct
in6_addr
*
ans
);
struct
dhcp_context
*
address6_available
(
struct
dhcp_context
*
context
,
struct
in6_addr
*
taddr
,
struct
dhcp_netid
*
netids
);
struct
dhcp_context
*
narrow_context6
(
struct
dhcp_context
*
context
,
struct
in6_addr
*
taddr
,
struct
dhcp_netid
*
netids
);
#endif
/* rfc3315.c */
#ifdef HAVE_DHCP6
void
make_duid
(
time_t
now
);
size_t
dhcp6_reply
(
struct
dhcp_context
*
context
,
size_t
sz
);
size_t
dhcp6_reply
(
struct
dhcp_context
*
context
,
size_t
sz
,
time_t
now
);
#endif
src/lease.c
View file @
e9817081
...
...
@@ -85,7 +85,9 @@ void lease_init(time_t now)
daemon
->
dhcp_buff
,
daemon
->
packet
)
==
5
)
{
#ifdef HAVE_DHCP6
if
(
!
v6pass
)
if
(
v6pass
)
hw_type
=
atoi
(
daemon
->
dhcp_buff2
);
else
#endif
{
hw_len
=
parse_hex
(
daemon
->
dhcp_buff2
,
(
unsigned
char
*
)
daemon
->
dhcp_buff2
,
DHCP_CHADDR_MAX
,
NULL
,
&
hw_type
);
...
...
@@ -107,10 +109,10 @@ void lease_init(time_t now)
#ifdef HAVE_DHCP6
if
(
v6pass
)
lease
=
lease
_allocate6
(
&
addr
.
addr
.
addr6
);
lease
=
lease
6_allocate
(
&
addr
.
addr
.
addr6
);
else
#endif
lease
=
lease
_allocate4
(
addr
.
addr
.
addr4
);
lease
=
lease
4_allocate
(
addr
.
addr
.
addr4
);
if
(
!
lease
)
die
(
_
(
"too many stored leases"
),
NULL
,
EC_MISC
);
...
...
@@ -288,7 +290,7 @@ void lease_update_file(time_t now)
inet_ntop
(
AF_INET6
,
lease
->
hwaddr
,
daemon
->
addrbuff
,
ADDRSTRLEN
);
ourprintf
(
&
err
,
"
* %s "
,
daemon
->
addrbuff
);
ourprintf
(
&
err
,
"
%u %s "
,
lease
->
hwaddr_type
,
daemon
->
addrbuff
);
ourprintf
(
&
err
,
"%s "
,
lease
->
hostname
?
lease
->
hostname
:
"*"
);
if
(
lease
->
clid
&&
lease
->
clid_len
!=
0
)
...
...
@@ -431,6 +433,44 @@ struct dhcp_lease *lease_find_by_addr(struct in_addr addr)
return
NULL
;
}
#ifdef HAVE_DHCP6
struct
dhcp_lease
*
lease6_find_by_client
(
unsigned
char
*
clid
,
int
clid_len
,
int
iaid
)
{
struct
dhcp_lease
*
lease
;
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
{
if
(
!
lease
->
is_ipv6
)
continue
;
if
(
lease
->
hwaddr_type
==
iaid
&&
lease
->
clid
&&
clid_len
==
lease
->
clid_len
&&
memcmp
(
clid
,
lease
->
clid
,
clid_len
)
==
0
)
return
lease
;
}
return
NULL
;
}
struct
dhcp_lease
*
lease6_find_by_addr
(
struct
in6_addr
*
net
,
int
prefix
,
u64
addr
)
{
struct
dhcp_lease
*
lease
;
for
(
lease
=
leases
;
lease
;
lease
=
lease
->
next
)
{
if
(
!
lease
->
is_ipv6
)
continue
;
if
(
is_same_net6
((
struct
in6_addr
*
)
lease
->
hwaddr
,
net
,
prefix
)
&&
(
prefix
==
128
||
addr6part
((
struct
in6_addr
*
)
lease
->
hwaddr
)
==
addr
))
return
lease
;
}
return
NULL
;
}
#endif
/* Find largest assigned address in context */
struct
in_addr
lease_find_max_addr
(
struct
dhcp_context
*
context
)
{
...
...
@@ -474,7 +514,7 @@ static struct dhcp_lease *lease_allocate(void)
return
lease
;
}
struct
dhcp_lease
*
lease
_allocate4
(
struct
in_addr
addr
)
struct
dhcp_lease
*
lease
4_allocate
(
struct
in_addr
addr
)
{
struct
dhcp_lease
*
lease
=
lease_allocate
();
lease
->
addr
=
addr
;
...
...
@@ -484,7 +524,7 @@ struct dhcp_lease *lease_allocate4(struct in_addr addr)
}
#ifdef HAVE_DHCP6
struct
dhcp_lease
*
lease
_allocate6
(
struct
in6_addr
*
addrp
)
struct
dhcp_lease
*
lease
6_allocate
(
struct
in6_addr
*
addrp
)
{
struct
dhcp_lease
*
lease
=
lease_allocate
();
memcpy
(
lease
->
hwaddr
,
addrp
,
sizeof
(
*
addrp
))
;
...
...
src/netlink.c
View file @
e9817081
...
...
@@ -230,8 +230,8 @@ int iface_enumerate(int family, void *parm, int (*callback)())
}
if
(
addrp
)
if
(
!
((
*
callback
)(
addrp
,
ifa
->
ifa_prefixlen
,
ifa
->
ifa_index
,
ifa
->
ifa_index
,
ifa
->
ifa_flags
&
IFA_F_TENTATIVE
,
parm
)))
if
(
!
((
*
callback
)(
addrp
,
(
int
)(
ifa
->
ifa_prefixlen
),
(
int
)(
ifa
->
ifa_scope
)
,
(
int
)(
ifa
->
ifa_index
),
(
int
)(
ifa
->
ifa_flags
&
IFA_F_TENTATIVE
)
,
parm
)))
return
0
;
}
#endif
...
...
src/network.c
View file @
e9817081
...
...
@@ -274,9 +274,10 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
{
union
mysockaddr
addr
;
struct
in_addr
netmask
;
/* dummy */
(
void
)
prefix
;
/* warning */
netmask
.
s_addr
=
0
;
(
void
)
prefix
;
/* warning */
(
void
)
scope
;
/* warning */
memset
(
&
addr
,
0
,
sizeof
(
addr
));
#ifdef HAVE_SOCKADDR_SA_LEN
...
...
@@ -285,7 +286,7 @@ static int iface_allowed_v6(struct in6_addr *local, int prefix,
addr
.
in6
.
sin6_family
=
AF_INET6
;
addr
.
in6
.
sin6_addr
=
*
local
;
addr
.
in6
.
sin6_port
=
htons
(
daemon
->
port
);
addr
.
in6
.
sin6_scope_id
=
scope
;
addr
.
in6
.
sin6_scope_id
=
if_index
;
return
iface_allowed
((
struct
irec
**
)
vparam
,
if_index
,
&
addr
,
netmask
,
dad
);
}
...
...
src/option.c
View file @
e9817081
...
...
@@ -1870,18 +1870,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
char
*
cp
,
*
a
[
5
]
=
{
NULL
,
NULL
,
NULL
,
NULL
,
NULL
};
struct
dhcp_context
*
new
=
opt_malloc
(
sizeof
(
struct
dhcp_context
));
new
->
next
=
daemon
->
dhcp
;
memset
(
new
,
0
,
sizeof
(
*
new
))
;
new
->
lease_time
=
DEFLEASE
;
new
->
addr_epoch
=
0
;
new
->
netmask
.
s_addr
=
0
;
new
->
broadcast
.
s_addr
=
0
;
new
->
router
.
s_addr
=
0
;
new
->
local
.
s_addr
=
0
;
new
->
netid
.
net
=
NULL
;
new
->
filter
=
NULL
;
new
->
flags
=
0
;
new
->
interface
=
NULL
;
gen_prob
=
_
(
"bad dhcp-range"
);
if
(
!
arg
)
...
...
@@ -1893,7 +1884,9 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
while
(
1
)
{
for
(
cp
=
arg
;
*
cp
;
cp
++
)
if
(
!
(
*
cp
==
' '
||
*
cp
==
'.'
||
(
*
cp
>=
'0'
&&
*
cp
<=
'9'
)))
if
(
!
(
*
cp
==
' '
||
*
cp
==
'.'
||
*
cp
==
':'
||
(
*
cp
>=
'a'
&&
*
cp
<=
'f'
)
||
(
*
cp
>=
'A'
&&
*
cp
<=
'F'
)
||
(
*
cp
>=
'0'
&&
*
cp
<=
'9'
)))
break
;
if
(
*
cp
!=
','
&&
(
comma
=
split
(
arg
)))
...
...
@@ -1929,44 +1922,86 @@ static char *one_opt(int option, char *arg, char *gen_prob, int command_line)
if
(
!
(
a
[
k
]
=
split
(
a
[
k
-
1
])))
break
;
if
((
k
<
2
)
||
((
new
->
start
.
s_addr
=
inet_addr
(
a
[
0
]))
==
(
in_addr_t
)
-
1
))
option
=
'?'
;
else
if
(
strcmp
(
a
[
1
],
"static"
)
==
0
)
{
new
->
end
=
new
->
start
;
new
->
flags
|=
CONTEXT_STATIC
;
}
else
if
(
strcmp
(
a
[
1
],
"proxy"
)
==
0
)
{
new
->
end
=
new
->
start
;
new
->
flags
|=
CONTEXT_PROXY
;
}
else
if
((
new
->
end
.
s_addr
=
inet_addr
(
a
[
1
]))
==
(
in_addr_t
)
-
1
)
if
(
k
<
2
)
option
=
'?'
;
if
(
ntohl
(
new
->
start
.
s_addr
)
>
ntohl
(
new
->
end
.
s_addr
))
else
if
(
inet_pton
(
AF_INET
,
a
[
0
],
&
new
->
start
))
{
struct
in_addr
tmp
=
new
->
start
;
new
->
start
=
new
->
end
;
new
->
end
=
tmp
;
new
->
next
=
daemon
->
dhcp
;
daemon
->
dhcp
=
new
;
if
(
strcmp
(
a
[
1
],
"static"
)
==
0
)
{
new
->
end
=
new
->
start
;
new
->
flags
|=
CONTEXT_STATIC
;
}
else
if
(
strcmp
(
a
[
1
],
"proxy"
)
==
0
)
{
new
->
end
=
new
->
start
;
new
->
flags
|=
CONTEXT_PROXY
;
}
else
if
((
new
->
end
.
s_addr
=
inet_addr
(
a
[
1
]))
==
(
in_addr_t
)
-
1
)
option
=
'?'
;
if
(
ntohl
(
new
->
start
.
s_addr
)
>
ntohl
(
new
->
end
.
s_addr
))
{
struct
in_addr
tmp
=
new
->
start
;
new
->
start
=
new
->
end
;
new
->
end
=
tmp
;
}
if
(
option
!=
'?'
&&
k
>=
3
&&
strchr
(
a
[
2
],
'.'
)
&&
((
new
->
netmask
.
s_addr
=
inet_addr
(
a
[
2
]))
!=
(
in_addr_t
)
-
1
))
{
new
->
flags
|=
CONTEXT_NETMASK
;
leasepos
=
3
;
if
(
!
is_same_net
(
new
->
start
,
new
->
end
,
new
->
netmask
))
problem
=
_
(
"inconsistent DHCP range"
);
}
if
(
k
>=
4
&&
strchr
(
a
[
3
],
'.'
)
&&
((
new
->
broadcast
.
s_addr
=
inet_addr
(
a
[
3
]))
!=
(
in_addr_t
)
-
1
))
{
new
->
flags
|=
CONTEXT_BRDCAST
;
leasepos
=
4
;
}
}
if
(
option
!=
'?'
&&
k
>=
3
&&
strchr
(
a
[
2
],
'.'
)
&&
((
new
->
netmask
.
s_addr
=
inet_addr
(
a
[
2
]))
!=
(
in_addr_t
)
-
1
))
#ifdef HAVE_DHCP6
else
if
(
inet_pton
(
AF_INET6
,
a
[
0
],
&
new
->
start6
))
{
new
->
flags
|=
CONTEXT_NETMASK
;
leasepos
=
3
;
if
(
!
is_same_net
(
new
->
start
,
new
->
end
,
new
->
netmask
))
new
->
next
=
daemon
->
dhcp6
;
new
->
prefix
=
64
;
/* default */
daemon
->
dhcp6
=
new
;
if
(
strcmp
(
a
[
1
],
"static"
)
==
0
)
{
new
->
end
=
new
->
start
;
new
->
flags
|=
CONTEXT_STATIC
;
}
else
if
(
!
inet_pton
(
AF_INET6
,
a
[
1
],
&
new
->
end6
))
option
=
'?'
;
/* bare integer < 128 is prefix value */
if
(
option
!=
'?'
&&
k
>=
3
)
{
int
pref
;
for
(
cp
=
a
[
2
];
*
cp
;
cp
++
)
if
(
!
(
*
cp
>=
'0'
&&
*
cp
<=
'9'
))
break
;
if
(
!*
cp
&&
(
pref
=
atoi
(
a
[
2
]))
<=
128
)
{
new
->
prefix
=
pref
;
leasepos
=
3
;
}
}
if
(
!
is_same_net6
(
&
new
->
start6
,
&
new
->
end6
,
new
->
prefix
))
problem
=
_
(
"inconsistent DHCP range"
);
if
(
addr6part
(
&
new
->
start6
)
>
addr6part
(
&
new
->
end6
))
{
struct
in6_addr
tmp
=
new
->
start6
;
new
->
start6
=
new
->
end6
;
new
->
end6
=
tmp
;
}
}
daemon
->
dhcp
=
new
;
if
(
k
>=
4
&&
strchr
(
a
[
3
],
'.'
)
&&
((
new
->
broadcast
.
s_addr
=
inet_addr
(
a
[
3
]))
!=
(
in_addr_t
)
-
1
))
{
new
->
flags
|=
CONTEXT_BRDCAST
;
leasepos
=
4
;
}
#endif
if
(
k
>=
leasepos
+
1
)
{
...
...
src/rfc2131.c
View file @
e9817081
...
...
@@ -481,7 +481,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
if
(
!
message
&&
!
lease
&&
(
!
(
lease
=
lease
_allocate4
(
mess
->
yiaddr
))))
(
!
(
lease
=
lease
4_allocate
(
mess
->
yiaddr
))))
message
=
_
(
"no leases left"
);
if
(
!
message
)
...
...
@@ -1189,7 +1189,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
else
if
(
!
lease
)
{
if
((
lease
=
lease
_allocate4
(
mess
->
yiaddr
)))
if
((
lease
=
lease
4_allocate
(
mess
->
yiaddr
)))
do_classes
=
1
;
else
message
=
_
(
"no leases left"
);
...
...
src/rfc3315.c
View file @
e9817081
...
...
@@ -23,6 +23,7 @@ static size_t outpacket_counter;
static
int
make_duid1
(
unsigned
short
type
,
unsigned
int
flags
,
char
*
mac
,
size_t
maclen
,
void
*
parm
);
static
void
do_options6
(
struct
dhcp_context
*
context
,
void
*
oro
);
void
make_duid
(
time_t
now
)
{
...
...
@@ -96,9 +97,8 @@ void *opt6_next(void *opts, void *end)
return
opts
+
opt_len
;
}
#define opt6_len(opt) ((int)(((unsigned short *)(opt))[1]))
#define opt6_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[4u+(unsigned int)(i)]))
#define opt6_len(opt) (opt6_uint(opt, -2, 2))
#define opt6_ptr(opt, i) ((void *)&(((unsigned char *)(opt))[4+(i)]))
static
unsigned
int
opt6_uint
(
unsigned
char
*
opt
,
int
offset
,
int
size
)
...
...
@@ -115,40 +115,73 @@ static unsigned int opt6_uint(unsigned char *opt, int offset, int size)
}
/*
daemon->outpacket_counter = 4; message type and ID
elapsed time:
int o = new_opt(OPTION_ELAPSED_TIME);
put_opt_short(o, 100)
set of routines to build arbitrarily nested options: eg
int o = new_opt(OPTION_IA_NA);
put_opt_long(IAID);
put_opt_long(T1);
put_opt_long(T2);
int o1 = new_opt(OPTION_IAADDR);
put_opt(o1, &addr, sizeof(addr));
put_opt_long(preferred_lifetime);
put_opt_long(valid_lifetime);
finalise_opt(o1);
finalise_opt(o);
IA_NA
to go back and fill in fields
int o = new_opt(OPTION_IA_NA);
put_opt_long(o, IAID);
put_opt_long(o, T1);
put_opt_long(0, T2);
put_opt_long(IAID);
int t1sav = save_counter(-1);
put_opt_long(0);
put_opt_long(0);
int o1 = new_opt(OPTION_IAADDR);
put_opt(o1, &addr, sizeof(addr));
put_opt_long(o1, preferred_lifetime);
put_opt_long(o1, valid_lifetime);
finalise_opt(o1);
int sav = save_counter(t1sav);
put_opt_long(T1);
save_counter(sav);
finalise_opt(o);
to abandon an option
int o = new_opt(OPTION_IA_NA);
put_opt_long(IAID);
put_opt_long(T1);
put_opt_long(T2);
if (err)
save_counter(o);
*/
void
end_opt6
(
int
container
)
static
void
end_opt6
(
int
container
)
{
void
*
p
=
daemon
->
outpacket
.
iov_base
+
container
+
2
;
u16
len
=
outpacket_counter
-
container
-
4
;
PUTSHORT
(
len
,
p
);
}
static
int
save_counter
(
int
newval
)
{
int
ret
=
outpacket_counter
;
if
(
newval
!=
-
1
)
outpacket_counter
=
newval
;
return
ret
;
}
static
void
*
expand
(
size_t
headroom
)
{
...
...
@@ -164,7 +197,7 @@ static void *expand(size_t headroom)
return
NULL
;
}
int
new_opt6
(
int
opt
)
static
int
new_opt6
(
int
opt
)
{
int
ret
=
outpacket_counter
;
void
*
p
;
...
...
@@ -181,7 +214,7 @@ int new_opt6(int opt)
void
*
put_opt6
(
void
*
data
,
size_t
len
)
static
void
*
put_opt6
(
void
*
data
,
size_t
len
)
{
void
*
p
;
...
...
@@ -191,15 +224,15 @@ void *put_opt6(void *data, size_t len)
return
p
;
}
void
put_opt6_long
(
unsigned
int
val
)
static
void
put_opt6_long
(
unsigned
int
val
)
{
void
*
p
;
if
((
p
=
expand
(
4
)))
PUTLONG
(
p
,
val
);
PUTLONG
(
val
,
p
);
}
void
put_opt6_short
(
unsigned
int
val
)
static
void
put_opt6_short
(
unsigned
int
val
)
{
void
*
p
;
...
...
@@ -207,92 +240,231 @@ void put_opt6_short(unsigned int val)
PUTSHORT
(
val
,
p
);
}
void
put_opt6_byte
(
unsigned
int
val
)
static
void
put_opt6_byte
(
unsigned
int
val
)
{
void
*
p
;
if
((
p
=
expand
(
1
)))
*
((
unsigned
char
*
)
p
)
=
val
;
}
static
void
put_opt6_string
(
char
*
s
)
{
put_opt6
(
s
,
strlen
(
s
));
}
size_t
dhcp6_reply
(
struct
dhcp_context
*
context
,
size_t
sz
)
size_t
dhcp6_reply
(
struct
dhcp_context
*
context
,
size_t
sz
,
time_t
now
)
{
void
*
packet_options
=
((
void
*
)
daemon
->
dhcp_packet
.
iov_base
)
+
4
;
void
*
end
=
((
void
*
)
daemon
->
dhcp_packet
.
iov_base
)
+
sz
;
void
*
na_option
,
*
na_end
;
void
*
opt
,
*
p
;
int
o
;
outpacket_counter
=
4
;
/* skip message type and transaction-id */
int
o
,
msg_type
=
*
((
unsigned
char
*
)
daemon
->
dhcp_packet
.
iov_base
);
int
make_lease
=
(
msg_type
==
DHCP6REQUEST
||
opt6_find
(
packet_options
,
end
,
OPTION6_RAPID_COMMIT
,
0
));
unsigned
char
*
clid
;
int
clid_len
;
struct
dhcp_netid
*
tags
;
/* copy over transaction-id */
memcpy
(
daemon
->
outpacket
.
iov_base
,
daemon
->
dhcp_packet
.
iov_base
,
4
);
/* set reply message type */
*
((
unsigned
char
*
)
daemon
->
outpacket
.
iov_base
)
=
make_lease
?
DHCP6REPLY
:
DHCP6ADVERTISE
;
/* skip message type and transaction-id */
outpacket_counter
=
4
;
if
(
!
(
opt
=
opt6_find
(
packet_options
,
end
,
OPTION6_CLIENT_ID
,
1
)))
return
;
return
0
;
clid
=
opt6_ptr
(
opt
,
0
);
clid_len
=
opt6_len
(
opt
);
o
=
new_opt6
(
OPTION6_CLIENT_ID
);
put_opt6
(
opt6_ptr
(
opt
,
0
),
opt6_len
(
opt
)
);
put_opt6
(
clid
,
clid_len
);
end_opt6
(
o
);
/* server-id must match except for SOLICIT meesages */
if
(
msg_type
!=
DHCP6SOLICIT
&&
(
!
(
opt
=
opt6_find
(
packet_options
,
end
,
OPTION6_SERVER_ID
,
1
))
||
opt6_len
(
opt
)
!=
daemon
->
duid_len
||
memcmp
(
opt6_ptr
(
opt
,
0
),
daemon
->
duid
,
daemon
->
duid_len
)
!=
0
))
return
0
;
o
=
new_opt6
(
OPTION6_SERVER_ID
);
put_opt6
(
daemon
->
duid
,
daemon
->
duid_len
);
end_opt6
(
o
);
if
((
opt
=
opt6_find
(
packet_options
,
end
,
OPTION6_IA_NA
,
12
)))
{
while
(
opt
=
opt6_find
(
opt
,
end
,
OPTION6_IA_NA
,
12
))
{
void
*
ia_end
=
opt6_ptr
(
opt
,
opt6_len
(
opt
));
void
*
ia_option
=
opt6_find
(
opt6_ptr
(
opt
,
12
),
ia_end
,
OPTION6_IAADDR
,
24
);
unsigned
int
iaid
=
opt6_uint
(
opt
,
0
,
4
);
unsigned
int
t1
=
opt6_uint
(
opt
,
4
,
4
);
unsigned
int
t2
=
opt6_uint
(
opt
,
8
,
4
);
if
(
ia_option
)
while
((
ia_option
=
ia_option
,
ia_end
,
OPTION6_IAADDR
,
24
))
switch
(
msg_type
)
{
case
DHCP6SOLICIT
:
case
DHCP6REQUEST
:
{
u16
*
req_options
=
NULL
;
for
(
opt
=
opt6_find
(
packet_options
,
end
,
OPTION6_IA_NA
,
12
);
opt
;
opt
=
opt6_find
(
opt6_next
(
opt
,
end
),
end
,
OPTION6_IA_NA
,
12
))
{
void
*
ia_end
=
opt6_ptr
(
opt
,
opt6_len
(
opt
));
void
*
ia_option
=
opt6_find
(
opt6_ptr
(
opt
,
12
),
ia_end
,
OPTION6_IAADDR
,
24
);
unsigned
int
min_time
=
0xffffffff
;
int
t1cntr
;
unsigned
int
iaid
=
opt6_uint
(
opt
,
0
,
4
);
int
address_assigned
=
0
;
struct
dhcp_lease
*
lease
=
NULL
;
o
=
new_opt6
(
OPTION6_IA_NA
);
put_opt6_long
(
iaid
);
/* save pointer */
t1cntr
=
save_counter
(
-
1
);
/* so we can fill these in later */
put_opt6_long
(
0
);
put_opt6_long
(
0
);
while
(
1
)
{
/* do address option */
struct
in6_addr
alloced_addr
,
*
addrp
=
NULL
;
ia_option
=
opt6_next
(
ia_option
,
ia_end
);
}
else
{
/* no preferred address call address allocate */
}
opt
=
opt6_next
(
opt
,
end
);
}
}
else
if
((
opt
=
opt6_find
(
packet_options
,
end
,
OPTION6_IA_TA
,
4
)))
while
(
opt
=
opt6_find
(
opt
,
end
,
OPTION6_IA_TA
,
4
))
{
void
*
ia_end
=
opt6_ptr
(
opt
,
opt6_len
(
opt
));
void
*
ia_option
=
opt6_find
(
opt6_ptr
(
opt
,
4
),
ia_end
,
OPTION6_IAADDR
,
24
);
unsigned
int
iaid
=
opt6_uint
(
opt
,
0
,
4
);
if
(
ia_option
)
{
struct
in6_addr
*
req_addr
=
opt6_ptr
(
ia_option
,
0
);
u32
preferred_lifetime
=
opt6_uint
(
ia_option
,
16
,
4
);
u32
valid_lifetime
=
opt6_uint
(
ia_option
,
20
,
4
);
if
((
lease
=
lease6_find_by_addr
(
req_addr
,
128
,
0
)))
{
/* check if existing lease for host */
if
(
clid_len
==
lease
->
clid_len
&&
memcmp
(
clid
,
lease
->
clid
,
clid_len
)
==
0
)
addrp
=
req_addr
;
}
else
if
(
address6_available
(
context
,
req_addr
,
tags
))
addrp
=
req_addr
;
}
else
{
/* must have an address to CONFIRM */
if
(
msg_type
==
DHCP6REQUEST
)
return
0
;
/* existing lease */
if
((
lease
=
lease6_find_by_client
(
clid
,
clid_len
,
iaid
)))
addrp
=
(
struct
in6_addr
*
)
&
lease
->
hwaddr
;
else
if
(
address6_allocate
(
context
,
clid
,
clid_len
,
tags
,
&
alloced_addr
))
addrp
=
&
alloced_addr
;
}
if
(
addrp
)
{
unsigned
int
lease_time
;
address_assigned
=
1
;
context
=
narrow_context6
(
context
,
addrp
,
tags
);
lease_time
=
context
->
lease_time
;
if
(
lease_time
<
min_time
)
min_time
=
lease_time
;
/* May fail to create lease */
if
(
!
lease
&&
make_lease
)
lease
=
lease6_allocate
(
addrp
);
if
(
lease
)
{
lease_set_expires
(
lease
,
lease_time
,
now
);
lease_set_hwaddr
(
lease
,
NULL
,
clid
,
0
,
iaid
,
clid_len
);
}
if
(
lease
||
!
make_lease
)
{
int
o1
=
new_opt6
(
OPTION6_IAADDR
);
put_opt6
(
addrp
,
sizeof
(
*
addrp
));
put_opt6_long
(
lease_time
);
put_opt6_long
(
lease_time
);
end_opt6
(
o1
);
}
}
if
(
!
ia_option
||
!
(
ia_option
=
opt6_find
(
opt6_next
(
ia_option
,
ia_end
),
ia_end
,
OPTION6_IAADDR
,
24
)))
{
if
(
address_assigned
)
{
/* go back an fill in fields in IA_NA option */
unsigned
int
t1
=
min_time
==
0xffffffff
?
0xffffffff
:
min_time
/
2
;
unsigned
int
t2
=
min_time
==
0xffffffff
?
0xffffffff
:
(
min_time
/
8
)
*
7
;
int
sav
=
save_counter
(
t1cntr
);
put_opt6_long
(
t1
);
put_opt6_long
(
t2
);
save_counter
(
sav
);
}
else
{
/* no address, return erro */
int
o1
=
new_opt6
(
OPTION6_STATUS_CODE
);
put_opt6_short
(
DHCP6NOADDRS
);
put_opt6_string
(
"No addresses available"
);
end_opt6
(
o1
);
}
end_opt6
(
o
);
break
;
}
}
}
if
(
ia_option
)
while
((
ia_option
=
ia_option
,
ia_end
,
OPTION6_IAADDR
,
24
))
{
/* do address option */
ia_option
=
opt6_next
(
ia_option
,
ia_end
);
}
else
/* same again for TA */
for
(
opt
=
packet_options
;
opt
;
opt
=
opt6_find
(
opt6_next
(
opt
,
end
),
end
,
OPTION6_IA_TA
,
4
))
{
/* no preferred address */
}
opt
=
opt6_next
(
opt
,
end
);
do_options6
(
context
,
opt6_find
(
packet_options
,
end
,
OPTION6_ORO
,
0
));
}
else
return
;
/* no IA_NA and no IA_TA */
}
return
outpacket_counter
;
}
/* TODO tags to select options, and encapsualted options. */
static
void
do_options6
(
struct
dhcp_context
*
context
,
void
*
oro
)
{
unsigned
char
*
req_options
=
NULL
;
int
req_options_len
,
i
,
o
;
struct
dhcp_opt
*
opt
,
*
config_opts
=
daemon
->
dhcp_opts6
;
if
(
oro
)
{
req_options
=
opt6_ptr
(
oro
,
0
);
req_options_len
=
opt6_len
(
oro
);
}
for
(
opt
=
config_opts
;
opt
;
opt
=
opt
->
next
)
{
if
(
req_options
)
{
/* required options are not aligned... */
for
(
i
=
0
;
i
<
req_options_len
-
1
;
i
+=
2
)
if
(((
req_options
[
i
]
<<
8
)
|
req_options
[
i
+
1
])
==
opt
->
opt
)
break
;
/* option not requested */
if
(
i
==
req_options_len
)
continue
;
}
o
=
new_opt6
(
opt
->
opt
);
put_opt6
(
opt
->
val
,
opt
->
len
);
end_opt6
(
o
);
}
}
#endif
src/util.c
View file @
e9817081
...
...
@@ -336,6 +336,29 @@ int is_same_net6(struct in6_addr *a, struct in6_addr *b, int prefixlen)
return
0
;
}
/* return least signigicant 64 bits if IPv6 address */
u64
addr6part
(
struct
in6_addr
*
addr
)
{
int
i
;
u64
ret
=
0
;
for
(
i
=
8
;
i
<
16
;
i
++
)
ret
=
(
ret
<<
8
)
+
addr
->
s6_addr
[
i
];
return
ret
;
}
void
setaddr6part
(
struct
in6_addr
*
addr
,
u64
host
)
{
int
i
;
for
(
i
=
15
;
i
>=
8
;
i
--
)
{
addr
->
s6_addr
[
i
]
=
host
;
host
=
host
>>
8
;
}
}
#endif
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment