mirror of
https://github.com/systemd/systemd.git
synced 2024-10-28 11:55:44 +03:00
sd-dhcp6-client: Add functions to bind to DHCPv6 UDP socket
Add a function that creates a UDP socket bound to the given interface and optionally to an IPv6 address. Add another function that will send the DHCPv6 UDP packet to its destination. Using IPV6_PKTINFO in setsockopt to bind the IPv6 socket to an interface is documented in section 4. of RFC 3542, "Advanced Sockets Application Program Interface (API) for IPv6" Add a define for DHCPv6 Relay Agents and Servers multicast address as its not available elsewhere.
This commit is contained in:
parent
f12ed3bf0b
commit
34e8c5a23c
@ -65,3 +65,7 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
|
||||
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, DHCP6IA *ia);
|
||||
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
|
||||
size_t *optlen, uint8_t **optvalue);
|
||||
|
||||
int dhcp6_network_bind_udp_socket(int index, struct in6_addr *address);
|
||||
int dhcp6_network_send_udp_socket(int s, struct in6_addr *address,
|
||||
const void *packet, size_t len);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "socket-util.h"
|
||||
|
||||
#include "dhcp6-internal.h"
|
||||
#include "dhcp6-protocol.h"
|
||||
|
||||
#define IN6ADDR_ALL_ROUTERS_MULTICAST_INIT \
|
||||
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
@ -129,3 +130,65 @@ int dhcp_network_icmp6_send_router_solicitation(int s, const struct ether_addr *
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int dhcp6_network_bind_udp_socket(int index, struct in6_addr *local_address) {
|
||||
struct in6_pktinfo pktinfo = {
|
||||
.ipi6_ifindex = index,
|
||||
};
|
||||
union sockaddr_union src = {
|
||||
.in6.sin6_family = AF_INET6,
|
||||
.in6.sin6_port = htobe16(DHCP6_PORT_CLIENT),
|
||||
.in6.sin6_addr = IN6ADDR_ANY_INIT,
|
||||
};
|
||||
_cleanup_close_ int s = -1;
|
||||
int r, off = 0, on = 1;
|
||||
|
||||
if (local_address)
|
||||
memcpy(&src.in6.sin6_addr, local_address,
|
||||
sizeof(src.in6.sin6_addr));
|
||||
|
||||
s = socket(AF_INET6, SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK,
|
||||
IPPROTO_UDP);
|
||||
if (s < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_IPV6, IPV6_PKTINFO, &pktinfo,
|
||||
sizeof(pktinfo));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &off, sizeof(off));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = bind(s, &src.sa, sizeof(src.in6));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
r = s;
|
||||
s = -1;
|
||||
return r;
|
||||
}
|
||||
|
||||
int dhcp6_network_send_udp_socket(int s, struct in6_addr *server_address,
|
||||
const void *packet, size_t len) {
|
||||
union sockaddr_union dest = {
|
||||
.in6.sin6_family = AF_INET6,
|
||||
.in6.sin6_port = htobe16(DHCP6_PORT_SERVER),
|
||||
};
|
||||
int r;
|
||||
|
||||
assert(server_address);
|
||||
|
||||
memcpy(&dest.in6.sin6_addr, server_address, sizeof(dest.in6.sin6_addr));
|
||||
|
||||
r = sendto(s, packet, len, 0, &dest.sa, sizeof(dest.in6));
|
||||
if (r < 0)
|
||||
return -errno;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -36,6 +36,10 @@ struct DHCP6Message {
|
||||
|
||||
typedef struct DHCP6Message DHCP6Message;
|
||||
|
||||
#define IN6ADDR_ALL_DHCP6_RELAY_AGENTS_AND_SERVERS_INIT \
|
||||
{ { { 0xff, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02 } } }
|
||||
|
||||
enum {
|
||||
DHCP6_PORT_SERVER = 547,
|
||||
DHCP6_PORT_CLIENT = 546,
|
||||
|
Loading…
Reference in New Issue
Block a user