88#include <netinet/if_ether.h>
99
1010#include "arp-util.h"
11+ #include "ether-addr-util.h"
1112#include "fd-util.h"
13+ #include "in-addr-util.h"
1214#include "unaligned.h"
1315#include "util.h"
1416
15- int arp_network_bind_raw_socket (int ifindex , be32_t address , const struct ether_addr * eth_mac ) {
17+ int arp_update_filter (int fd , const struct in_addr * a , const struct ether_addr * eth_mac ) {
1618 struct sock_filter filter [] = {
1719 BPF_STMT (BPF_LD + BPF_W + BPF_LEN , 0 ), /* A <- packet length */
1820 BPF_JUMP (BPF_JMP + BPF_JGE + BPF_K , sizeof (struct ether_arp ), 1 , 0 ), /* packet >= arp packet ? */
@@ -46,13 +48,13 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
4648 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K , 0 , 0 , 1 ), /* A == 0 ? */
4749 BPF_STMT (BPF_RET + BPF_K , 0 ), /* ignore */
4850 /* Sender Protocol Address or Target Protocol Address must be equal to the one we care about */
49- BPF_STMT (BPF_LD + BPF_IMM , htobe32 (address )), /* A <- clients IP */
51+ BPF_STMT (BPF_LD + BPF_IMM , htobe32 (a -> s_addr )), /* A <- clients IP */
5052 BPF_STMT (BPF_MISC + BPF_TAX , 0 ), /* X <- A */
5153 BPF_STMT (BPF_LD + BPF_W + BPF_ABS , offsetof(struct ether_arp , arp_spa )), /* A <- SPA */
5254 BPF_STMT (BPF_ALU + BPF_XOR + BPF_X , 0 ), /* X xor A */
5355 BPF_JUMP (BPF_JMP + BPF_JEQ + BPF_K , 0 , 0 , 1 ), /* A == 0 ? */
5456 BPF_STMT (BPF_RET + BPF_K , 65535 ), /* return all */
55- BPF_STMT (BPF_LD + BPF_IMM , htobe32 (address )), /* A <- clients IP */
57+ BPF_STMT (BPF_LD + BPF_IMM , htobe32 (a -> s_addr )), /* A <- clients IP */
5658 BPF_STMT (BPF_MISC + BPF_TAX , 0 ), /* X <- A */
5759 BPF_STMT (BPF_LD + BPF_W + BPF_ABS , offsetof(struct ether_arp , arp_tpa )), /* A <- TPA */
5860 BPF_STMT (BPF_ALU + BPF_XOR + BPF_X , 0 ), /* X xor A */
@@ -61,15 +63,25 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
6163 BPF_STMT (BPF_RET + BPF_K , 0 ), /* ignore */
6264 };
6365 struct sock_fprog fprog = {
64- .len = ELEMENTSOF (filter ),
65- .filter = (struct sock_filter * ) filter
66+ .len = ELEMENTSOF (filter ),
67+ .filter = (struct sock_filter * ) filter ,
6668 };
69+
70+ assert (fd >= 0 );
71+
72+ if (setsockopt (fd , SOL_SOCKET , SO_ATTACH_FILTER , & fprog , sizeof (fprog )) < 0 )
73+ return - errno ;
74+
75+ return 0 ;
76+ }
77+
78+ int arp_network_bind_raw_socket (int ifindex , const struct in_addr * a , const struct ether_addr * eth_mac ) {
6779 union sockaddr_union link = {
68- .ll .sll_family = AF_PACKET ,
80+ .ll .sll_family = AF_PACKET ,
6981 .ll .sll_protocol = htobe16 (ETH_P_ARP ),
70- .ll .sll_ifindex = ifindex ,
71- .ll .sll_halen = ETH_ALEN ,
72- .ll .sll_addr = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff },
82+ .ll .sll_ifindex = ifindex ,
83+ .ll .sll_halen = ETH_ALEN ,
84+ .ll .sll_addr = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff },
7385 };
7486 _cleanup_close_ int s = -1 ;
7587 int r ;
@@ -80,59 +92,57 @@ int arp_network_bind_raw_socket(int ifindex, be32_t address, const struct ether_
8092 if (s < 0 )
8193 return - errno ;
8294
83- r = setsockopt (s , SOL_SOCKET , SO_ATTACH_FILTER , & fprog , sizeof ( fprog ) );
95+ r = arp_update_filter (s , a , eth_mac );
8496 if (r < 0 )
85- return - errno ;
97+ return r ;
8698
87- r = bind (s , & link .sa , sizeof (link .ll ));
88- if (r < 0 )
99+ if (bind (s , & link .sa , sizeof (link .ll )) < 0 )
89100 return - errno ;
90101
91102 return TAKE_FD (s );
92103}
93104
94- static int arp_send_packet (int fd , int ifindex ,
95- be32_t pa , const struct ether_addr * ha ,
96- bool announce ) {
105+ int arp_send_packet (
106+ int fd ,
107+ int ifindex ,
108+ const struct in_addr * pa ,
109+ const struct ether_addr * ha ,
110+ bool announce ) {
111+
97112 union sockaddr_union link = {
98- .ll .sll_family = AF_PACKET ,
113+ .ll .sll_family = AF_PACKET ,
99114 .ll .sll_protocol = htobe16 (ETH_P_ARP ),
100- .ll .sll_ifindex = ifindex ,
101- .ll .sll_halen = ETH_ALEN ,
102- .ll .sll_addr = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff },
115+ .ll .sll_ifindex = ifindex ,
116+ .ll .sll_halen = ETH_ALEN ,
117+ .ll .sll_addr = { 0xff , 0xff , 0xff , 0xff , 0xff , 0xff },
103118 };
104119 struct ether_arp arp = {
105- .ea_hdr .ar_hrd = htobe16 (ARPHRD_ETHER ), /* HTYPE */
106- .ea_hdr .ar_pro = htobe16 (ETHERTYPE_IP ), /* PTYPE */
107- .ea_hdr .ar_hln = ETH_ALEN , /* HLEN */
108- .ea_hdr .ar_pln = sizeof (be32_t ), /* PLEN */
109- .ea_hdr .ar_op = htobe16 (ARPOP_REQUEST ), /* REQUEST */
120+ .ea_hdr .ar_hrd = htobe16 (ARPHRD_ETHER ), /* HTYPE */
121+ .ea_hdr .ar_pro = htobe16 (ETHERTYPE_IP ), /* PTYPE */
122+ .ea_hdr .ar_hln = ETH_ALEN , /* HLEN */
123+ .ea_hdr .ar_pln = sizeof (struct in_addr ), /* PLEN */
124+ .ea_hdr .ar_op = htobe16 (ARPOP_REQUEST ), /* REQUEST */
110125 };
111- int r ;
126+ ssize_t n ;
112127
113128 assert (fd >= 0 );
114- assert (pa != 0 );
129+ assert (ifindex > 0 );
130+ assert (pa );
131+ assert (in4_addr_is_set (pa ));
115132 assert (ha );
133+ assert (!ether_addr_is_null (ha ));
116134
117135 memcpy (& arp .arp_sha , ha , ETH_ALEN );
118- memcpy (& arp .arp_tpa , & pa , sizeof (pa ));
136+ memcpy (& arp .arp_tpa , pa , sizeof (struct in_addr ));
119137
120138 if (announce )
121- memcpy (& arp .arp_spa , & pa , sizeof (pa ));
139+ memcpy (& arp .arp_spa , pa , sizeof (struct in_addr ));
122140
123- r = sendto (fd , & arp , sizeof (struct ether_arp ), 0 , & link .sa , sizeof (link .ll ));
124- if (r < 0 )
141+ n = sendto (fd , & arp , sizeof (struct ether_arp ), 0 , & link .sa , sizeof (link .ll ));
142+ if (n < 0 )
125143 return - errno ;
144+ if (n != sizeof (struct ether_arp ))
145+ return - EIO ;
126146
127147 return 0 ;
128148}
129-
130- int arp_send_probe (int fd , int ifindex ,
131- be32_t pa , const struct ether_addr * ha ) {
132- return arp_send_packet (fd , ifindex , pa , ha , false);
133- }
134-
135- int arp_send_announcement (int fd , int ifindex ,
136- be32_t pa , const struct ether_addr * ha ) {
137- return arp_send_packet (fd , ifindex , pa , ha , true);
138- }
0 commit comments