Skip to content

Commit f807fda

Browse files
refactor: Reduce setsockopt() calls to improve performance
1 parent 5066042 commit f807fda

1 file changed

Lines changed: 60 additions & 26 deletions

File tree

src/rawsend.c

Lines changed: 60 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,9 @@ static uint8_t *payload = NULL;
4747
static size_t payload_len = 0;
4848
static int sockfd = -1;
4949
static int sock4fd = -1;
50+
static int sock4if = -1;
5051
static int sock6fd = -1;
52+
static int sock6if = -1;
5153

5254
void 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

Comments
 (0)