@@ -47,7 +47,9 @@ static uint8_t *payload = NULL;
4747static size_t payload_len = 0 ;
4848static int sockfd = -1 ;
4949static int sock4fd = -1 ;
50+ static int sock4if = -1 ;
5051static int sock6fd = -1 ;
52+ static int sock6if = -1 ;
5153
5254void fs_rawsend_cleanup (void );
5355
@@ -108,52 +110,84 @@ static void ipaddr_to_str(struct sockaddr *addr, char ipstr[INET6_ADDRSTRLEN])
108110}
109111
110112
111- static int sendto_snat (struct sockaddr_ll * sll , struct sockaddr * daddr ,
112- uint8_t * pkt_buff , int pkt_len )
113+ static int bind_iface (int fd , int ifindex )
113114{
115+ static int use_bindtoifindex = 1 ;
116+
114117 int res ;
115- ssize_t nbytes ;
116118 char * iface , iface_buf [IF_NAMESIZE ];
117119
118- iface = if_indextoname (sll -> sll_ifindex , iface_buf );
120+ if (use_bindtoifindex ) {
121+ res = setsockopt (fd , SOL_SOCKET , SO_BINDTOIFINDEX , & ifindex ,
122+ sizeof (ifindex ));
123+ if (res < 0 && errno == ENOPROTOOPT ) {
124+ use_bindtoifindex = 0 ;
125+ } else if (res < 0 ) {
126+ E ("ERROR: setsockopt(): SO_BINDTOIFINDEX: %s" , strerror (errno ));
127+ return -1 ;
128+ } else {
129+ return 0 ;
130+ }
131+ }
132+
133+ iface = if_indextoname (ifindex , iface_buf );
119134 if (!iface ) {
120135 E ("ERROR: if_indextoname(): %s" , strerror (errno ));
121136 return -1 ;
122137 }
123138
139+ res = setsockopt (fd , SOL_SOCKET , SO_BINDTODEVICE , iface , strlen (iface ));
140+ if (res < 0 ) {
141+ E ("ERROR: setsockopt(): SO_BINDTODEVICE: %s" , strerror (errno ));
142+ return -1 ;
143+ }
144+
145+ return 0 ;
146+ }
147+
148+
149+ static int sendto_snat (struct sockaddr_ll * sll , struct sockaddr * daddr ,
150+ uint8_t * pkt_buff , int pkt_len )
151+ {
152+ int res , fd ;
153+ size_t daddrlen ;
154+ ssize_t nbytes ;
155+
124156 if (daddr -> sa_family == AF_INET ) {
125- res = setsockopt (sock4fd , SOL_SOCKET , SO_BINDTODEVICE , iface ,
126- strlen (iface ));
127- if (res < 0 ) {
128- E ("ERROR: setsockopt(): SO_BINDTODEVICE: %s" , strerror (errno ));
129- return -1 ;
130- }
157+ daddrlen = sizeof (struct sockaddr_in );
158+ fd = sock4fd ;
131159
132- nbytes = sendto (sock4fd , pkt_buff , pkt_len , 0 , daddr ,
133- sizeof (struct sockaddr_in ));
134- if (nbytes < 0 && errno != EPERM ) {
135- E ("ERROR: sendto(): %s" , strerror (errno ));
136- return -1 ;
160+ if (sll -> sll_ifindex != sock4if ) {
161+ res = bind_iface (fd , sll -> sll_ifindex );
162+ if (res < 0 ) {
163+ E (T (bind_iface ));
164+ return -1 ;
165+ }
166+ sock4if = sll -> sll_ifindex ;
137167 }
138168 } else if (daddr -> sa_family == AF_INET6 ) {
139- res = setsockopt (sock6fd , SOL_SOCKET , SO_BINDTODEVICE , iface ,
140- strlen (iface ));
141- if (res < 0 ) {
142- E ("ERROR: setsockopt(): SO_BINDTODEVICE: %s" , strerror (errno ));
143- return -1 ;
144- }
169+ daddrlen = sizeof (struct sockaddr_in6 );
170+ fd = sock6fd ;
145171
146- nbytes = sendto (sock6fd , pkt_buff , pkt_len , 0 , daddr ,
147- sizeof (struct sockaddr_in6 ));
148- if (nbytes < 0 && errno != EPERM ) {
149- E ("ERROR: sendto(): %s" , strerror (errno ));
150- return -1 ;
172+ if (sll -> sll_ifindex != sock6if ) {
173+ res = bind_iface (fd , sll -> sll_ifindex );
174+ if (res < 0 ) {
175+ E (T (bind_iface ));
176+ return -1 ;
177+ }
178+ sock6if = sll -> sll_ifindex ;
151179 }
152180 } else {
153181 E ("ERROR: Unknown sa_family: %d" , (int ) daddr -> sa_family );
154182 return -1 ;
155183 }
156184
185+ nbytes = sendto (fd , pkt_buff , pkt_len , 0 , daddr , daddrlen );
186+ if (nbytes < 0 && errno != EPERM ) {
187+ E ("ERROR: sendto(): %s" , strerror (errno ));
188+ return -1 ;
189+ }
190+
157191 return 0 ;
158192}
159193
0 commit comments