summaryrefslogtreecommitdiff
path: root/irc.c
diff options
context:
space:
mode:
authormultiplexd2020-02-12 01:02:37 +0000
committerC. McEnroe2020-02-13 00:05:52 +0000
commit1e544ce482ba97f9c4e2be114f88f11e49bdbf1b (patch)
tree5c25157df46e06fe062edb0d91809653b8587c25 /irc.c
parent489df70c37d49ab17b396dcffc6776e2ba7829ed (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.c35
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;