diff options
author | multiplexd | 2020-02-12 01:02:37 +0000 |
---|---|---|
committer | C. McEnroe | 2020-02-13 00:05:52 +0000 |
commit | 1e544ce482ba97f9c4e2be114f88f11e49bdbf1b (patch) | |
tree | 5c25157df46e06fe062edb0d91809653b8587c25 /irc.c | |
parent | 489df70c37d49ab17b396dcffc6776e2ba7829ed (diff) |
Implement source address selection
This commit adds a '-S' command line option and a "bind" configuration file option to specify the source address to bind to when connecting to the IRC server.
Diffstat (limited to 'irc.c')
-rw-r--r-- | irc.c | 35 |
1 files changed, 30 insertions, 5 deletions
diff --git a/irc.c b/irc.c index 05f8f9d..3ecc582 100644 --- a/irc.c +++ b/irc.c @@ -97,22 +97,47 @@ void ircConfig(bool insecure, FILE *cert, FILE *priv) { tls_config_free(config); } -int ircConnect(const char *host, const char *port) { +int ircConnect(const char *bindHost, const char *host, const char *port) { assert(client); + int error; + int sock = -1; struct addrinfo *head; struct addrinfo hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP, }; - int error = getaddrinfo(host, port, &hints, &head); + + if (bindHost) { + error = getaddrinfo(bindHost, NULL, &hints, &head); + if (error) errx(EX_NOHOST, "%s: %s", host, gai_strerror(error)); + + for (struct addrinfo *ai = head; ai; ai = ai->ai_next) { + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) err(EX_OSERR, "socket"); + + error = bind(sock, ai->ai_addr, ai->ai_addrlen); + if (!error) { + hints.ai_family = ai->ai_family; + break; + } + + close(sock); + sock = -1; + } + if (sock < 0) err(EX_UNAVAILABLE, "%s", bindHost); + freeaddrinfo(head); + } + + error = getaddrinfo(host, port, &hints, &head); if (error) errx(EX_NOHOST, "%s:%s: %s", host, port, gai_strerror(error)); - int sock = -1; for (struct addrinfo *ai = head; ai; ai = ai->ai_next) { - sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); - if (sock < 0) err(EX_OSERR, "socket"); + if (sock < 0) { + sock = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol); + if (sock < 0) err(EX_OSERR, "socket"); + } error = connect(sock, ai->ai_addr, ai->ai_addrlen); if (!error) break; |