]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/libsystemd-network/dhcp-network.c
2 This file is part of systemd.
4 Copyright (C) 2013 Intel Corporation. All rights reserved.
6 systemd is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as published by
8 the Free Software Foundation; either version 2.1 of the License, or
9 (at your option) any later version.
11 systemd is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Lesser General Public License for more details.
16 You should have received a copy of the GNU Lesser General Public License
17 along with systemd; If not, see <http://www.gnu.org/licenses/>.
21 #include <sys/types.h>
22 #include <sys/socket.h>
24 #include <linux/if_packet.h>
25 #include <net/ethernet.h>
26 #include <net/if_arp.h>
29 #include <linux/filter.h>
31 #include "socket-util.h"
33 #include "dhcp-internal.h"
35 int dhcp_network_bind_raw_socket(int index
, union sockaddr_union
*link
,
37 struct sock_filter filter
[] = {
38 BPF_STMT(BPF_LD
+ BPF_W
+ BPF_LEN
, 0), /* A <- packet length */
39 BPF_JUMP(BPF_JMP
+ BPF_JGE
+ BPF_K
, sizeof(DHCPPacket
), 1, 0), /* packet >= DHCPPacket ? */
40 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
41 /* TODO: match ip.version */
42 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_ABS
, offsetof(DHCPPacket
, ip
.protocol
)), /* A <- IP protocol */
43 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, IPPROTO_UDP
, 1, 0), /* IP protocol == UDP ? */
44 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
45 BPF_STMT(BPF_LD
+ BPF_H
+ BPF_ABS
, offsetof(DHCPPacket
, udp
.dest
)), /* A <- UDP destination port */
46 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, DHCP_PORT_CLIENT
, 1, 0), /* UDP destination port == DHCP client port ? */
47 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
48 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_ABS
, offsetof(DHCPPacket
, dhcp
.op
)), /* A <- DHCP op */
49 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, BOOTREPLY
, 1, 0), /* op == BOOTREPLY ? */
50 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
51 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_ABS
, offsetof(DHCPPacket
, dhcp
.htype
)), /* A <- DHCP header type */
52 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ARPHRD_ETHER
, 1, 0), /* header type == ARPHRD_ETHER ? */
53 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
54 BPF_STMT(BPF_LD
+ BPF_B
+ BPF_ABS
, offsetof(DHCPPacket
, dhcp
.hlen
)), /* A <- mac address length */
55 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, ETHER_ADDR_LEN
, 1, 0), /* address length == ETHER_ADDR_LEN ? */
56 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
57 BPF_STMT(BPF_LD
+ BPF_W
+ BPF_ABS
, offsetof(DHCPPacket
, dhcp
.xid
)), /* A <- client identifier */
58 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, xid
, 1, 0), /* client identifier == xid ? */
59 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
60 /* TODO: match chaddr */
61 BPF_STMT(BPF_LD
+ BPF_W
+ BPF_ABS
, offsetof(DHCPPacket
, dhcp
.magic
)), /* A <- DHCP magic cookie */
62 BPF_JUMP(BPF_JMP
+ BPF_JEQ
+ BPF_K
, DHCP_MAGIC_COOKIE
, 1, 0), /* cookie == DHCP magic cookie ? */
63 BPF_STMT(BPF_RET
+ BPF_K
, 0), /* ignore */
64 BPF_STMT(BPF_RET
+ BPF_K
, 65535), /* return all */
66 struct sock_fprog fprog
= {
67 .len
= ELEMENTSOF(filter
),
70 _cleanup_close_
int s
= -1;
76 s
= socket(AF_PACKET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
80 r
= setsockopt (s
, SOL_PACKET
, PACKET_AUXDATA
, &one
, sizeof(one
));
84 r
= setsockopt(s
, SOL_SOCKET
, SO_ATTACH_FILTER
, &fprog
, sizeof(fprog
));
88 link
->ll
.sll_family
= AF_PACKET
;
89 link
->ll
.sll_protocol
= htons(ETH_P_IP
);
90 link
->ll
.sll_ifindex
= index
;
91 link
->ll
.sll_halen
= ETH_ALEN
;
92 memset(link
->ll
.sll_addr
, 0xff, ETH_ALEN
);
94 r
= bind(s
, &link
->sa
, sizeof(link
->ll
));
104 int dhcp_network_bind_udp_socket(be32_t address
, uint16_t port
) {
105 union sockaddr_union src
= {
106 .in
.sin_family
= AF_INET
,
107 .in
.sin_port
= htobe16(port
),
108 .in
.sin_addr
.s_addr
= address
,
110 _cleanup_close_
int s
= -1;
111 int r
, tos
= IPTOS_CLASS_CS6
;
113 s
= socket(AF_INET
, SOCK_DGRAM
| SOCK_CLOEXEC
| SOCK_NONBLOCK
, 0);
117 r
= setsockopt(s
, IPPROTO_IP
, IP_TOS
, &tos
, sizeof(tos
));
121 r
= bind(s
, &src
.sa
, sizeof(src
.in
));
131 int dhcp_network_send_raw_socket(int s
, const union sockaddr_union
*link
,
132 const void *packet
, size_t len
) {
139 r
= sendto(s
, packet
, len
, 0, &link
->sa
, sizeof(link
->ll
));
146 int dhcp_network_send_udp_socket(int s
, be32_t address
, uint16_t port
,
147 const void *packet
, size_t len
) {
148 union sockaddr_union dest
= {
149 .in
.sin_family
= AF_INET
,
150 .in
.sin_port
= htobe16(port
),
151 .in
.sin_addr
.s_addr
= address
,
159 r
= sendto(s
, packet
, len
, 0, &dest
.sa
, sizeof(dest
.in
));