*/
if (my->cb.shutdown) my->user_shutdown = my->cb.shutdown;
my->cb.shutdown = fr_bio_fd_unix_shutdown;
+ if (dirfd != AT_FDCWD) close(dirfd);
return 0;
}
opt = my->info.socket.inet.ifindex;
switch (my->info.socket.af) {
- case AF_LOCAL:
+ case AF_INET:
rcode = setsockopt(my->info.socket.fd, IPPROTO_IP, IP_BOUND_IF, &opt, sizeof(opt));
break;
static int fr_bio_fd_socket_bind(fr_bio_fd_t *my, fr_bio_fd_config_t const *cfg)
{
bool do_suid;
+ int rcode;
socklen_t salen;
struct sockaddr_storage salocal;
/*
* Ranges must be a high value.
*/
- if (my->info.cfg->src_port_start && (my->info.cfg->src_port_start < 1024)) {
- fr_strerror_const("Cannot set src_port_start in the range 1..1023");
- return -1;
+ if (my->info.cfg->src_port_start) {
+ if (my->info.cfg->src_port_start < 1024) {
+ fr_strerror_const("Cannot set src_port_start in the range 1..1023");
+ return -1;
+ }
+
+ if (my->info.cfg->src_port_end <= my->info.cfg->src_port_start) {
+ fr_strerror_const("Invalid range src_port_end <= src_port_start");
+ return -1;
+ }
}
/*
* We don't have a source port range, just bind to whatever source port that we're given.
*/
if (!my->info.cfg->src_port_start) {
- if (bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen) < 0) {
+ rcode = bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen);
+ if (do_suid) fr_suid_down();
+
+ if (rcode < 0) {
fr_strerror_printf("Failed binding to socket: %s", fr_syserror(errno));
goto down;
}
- if (do_suid) fr_suid_down();
} else {
uint16_t src_port, current, range;
* We've picked a random port in what is hopefully a large range. If that works, we're
* done.
*/
- if (bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen) == 0) goto done;
+ rcode = bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen);
+ if (rcode == 0) {
+ if (do_suid) fr_suid_down();
+ goto done;
+ }
/*
* Hunt & peck. Which is horrible.
sin->sin_port = htons(my->info.cfg->src_port_start + current);
- if (bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen) == 0) goto done;
+ rcode = bind(my->info.socket.fd, (struct sockaddr *) &salocal, salen);
+ if (rcode == 0) {
+ if (do_suid) fr_suid_down();
+ goto done;
+ }
}
/*
* The error is a good hint at _why_ we failed to bind.
* We expect errno to be EADDRINUSE, anything else is a surprise.
*/
+ if (do_suid) fr_suid_down();
fr_strerror_printf("Failed binding port between 'src_port_start' and 'src_port_end': %s", fr_syserror(errno));
return -1;
}
*/
int fr_bio_fd_check_config(fr_bio_fd_config_t const *cfg)
{
- /*
- * Unix sockets and files are OK.
- */
- if (cfg->path || cfg->filename) return 0;
-
/*
* Sanitize the IP addresses.
*
*/
switch (cfg->type) {
case FR_BIO_FD_INVALID:
- return -1;
+ goto fail;
/*
* Unconnected UDP or datagram AF_LOCAL server sockets.
case FR_BIO_FD_UNCONNECTED:
if (my->info.socket.type != SOCK_DGRAM) {
fr_strerror_const("Failed configuring socket: unconnected sockets must be UDP");
- return -1;
+ goto fail;
}
switch (my->info.socket.af) {
break;
default:
- return -1;
+ goto fail;
}
if ((rcode = fr_bio_fd_init_connected(my)) < 0) goto fail;
close(dir_fd);
goto failed_open;
}
+
+ close(dir_fd);
}
/*