add -B BIND_ADDR option

This option enables using multiple NICs to transfer files.
This commit is contained in:
Ryo Nakamura
2025-11-15 20:20:54 +09:00
parent 7b5a97092a
commit fe3c4e0a53
5 changed files with 59 additions and 8 deletions

View File

@@ -28,7 +28,7 @@ void usage(bool print_help)
"Usage: mscp [-46vqDpdNh] [-n nr_conns] [-m coremask] [-u max_startups]\n"
" [-I interval] [-W checkpoint] [-R checkpoint]\n"
" [-s min_chunk_sz] [-S max_chunk_sz] [-a nr_ahead]\n"
" [-b buf_sz] [-L limit_bitrate]\n"
" [-b buf_sz] [-L limit_bitrate] [-B bind_addr]\n"
" [-l login_name] [-P port] [-F ssh_config] [-o ssh_option]\n"
" [-i identity_file] [-J destination] [-c cipher_spec] [-M hmac_spec]\n"
" [-C compress] [-g congestion]\n"
@@ -51,7 +51,8 @@ void usage(bool print_help)
" -S MAX_CHUNK_SIZE max chunk size (default: filesize/nr_conn/4)\n"
" -a NR_AHEAD number of inflight SFTP commands (default: 32)\n"
" -b BUF_SZ buffer size for i/o and transfer\n"
" -L LIMIT_BITRATE Limit the bitrate, n[KMG] (default: 0, no limit)\n"
" -L LIMIT_BITRATE limit the bitrate, n[KMG] (default: 0, no limit)\n"
" -B BIND_ADDR bind address (accept multiple times)\n"
"\n"
" -4 use IPv4\n"
" -6 use IPv6\n"
@@ -360,13 +361,14 @@ int main(int argc, char **argv)
int direction = 0;
char *remote = NULL, *checkpoint_save = NULL, *checkpoint_load = NULL;
bool quiet = false, dryrun = false, resume = false;
int nr_baddrs = 0;
int nr_options = 0;
memset(&s, 0, sizeof(s));
memset(&o, 0, sizeof(o));
o.severity = MSCP_SEVERITY_WARN;
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:46vqDrl:P:F:o:i:J:c:M:C:g:pdNh"
#define mscpopts "n:m:u:I:W:R:s:S:a:b:L:B:46vqDrl:P:F:o:i:J:c:M:C:g:pdNh"
while ((ch = getopt(argc, argv, mscpopts)) != -1) {
switch (ch) {
case 'n':
@@ -407,6 +409,17 @@ int main(int argc, char **argv)
case 'L':
o.bitrate = atol_with_unit(optarg, false);
break;
case 'B':
nr_baddrs++;
s.bind_addrs = realloc(s.bind_addrs,
sizeof(char *) * (nr_baddrs + 1));
if (!s.bind_addrs) {
pr_err("realloc: %s", strerrno());
return 1;
}
s.bind_addrs[nr_baddrs - 1] = optarg;
s.bind_addrs[nr_baddrs] = NULL;
break;
case '4':
s.ai_family = AF_INET;
break;

View File

@@ -6,6 +6,7 @@
#include <ssh.h>
#include <mscp.h>
#include <atomic.h>
#include <strerrno.h>
#include "libssh/callbacks.h"
@@ -14,6 +15,9 @@
static int ssh_verify_known_hosts(ssh_session session);
static int ssh_authenticate_kbdint(ssh_session session);
static lock bind_addr_lock = PTHREAD_MUTEX_INITIALIZER;
static int bind_addr_idx;
static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
{
ssh_set_log_level(opts->debug_level);
@@ -29,6 +33,21 @@ static int ssh_set_opts(ssh_session ssh, struct mscp_ssh_opts *opts)
return -1;
}
if (opts->bind_addrs) {
/* ssh_set_opts can be called from multiple threads,
* thus protect bind_addr_idx with a lock. */
char *bind_addr;
LOCK_ACQUIRE(&bind_addr_lock);
bind_addr = opts->bind_addrs[bind_addr_idx];
bind_addr_idx = (opts->bind_addrs[bind_addr_idx + 1] == NULL ?
0 : bind_addr_idx + 1);
LOCK_RELEASE();
if (ssh_options_set(ssh, SSH_OPTIONS_BINDADDR, bind_addr) < 0) {
priv_set_errv("failed to set bind address %s", bind_addr);
return -1;
}
}
if (opts->ai_family &&
ssh_options_set(ssh, SSH_OPTIONS_AI_FAMILY, &opts->ai_family) < 0) {
priv_set_errv("failed to set address family");