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.master
parent
489df70c37
commit
1e544ce482
|
@ -12,6 +12,7 @@
|
|||
.Op Fl C Ar copy
|
||||
.Op Fl H Ar hash
|
||||
.Op Fl O Ar open
|
||||
.Op Fl S Ar bind
|
||||
.Op Fl a Ar auth
|
||||
.Op Fl c Ar cert
|
||||
.Op Fl h Ar host
|
||||
|
@ -85,6 +86,11 @@ Disable the
|
|||
.Ic /quote
|
||||
commands.
|
||||
.
|
||||
.It Fl S Ar host , Cm bind = Ar host
|
||||
Bind to source address
|
||||
.Ar host
|
||||
when connecting to the server.
|
||||
.
|
||||
.It Fl a Ar user Ns : Ns Ar pass , Cm sasl-plain = Ar user Ns : Ns Ar pass
|
||||
Authenticate as
|
||||
.Ar user
|
||||
|
|
7
chat.c
7
chat.c
|
@ -82,6 +82,7 @@ int main(int argc, char *argv[]) {
|
|||
setlocale(LC_CTYPE, "");
|
||||
|
||||
bool insecure = false;
|
||||
const char *bind = NULL;
|
||||
const char *host = NULL;
|
||||
const char *port = "6697";
|
||||
const char *cert = NULL;
|
||||
|
@ -93,13 +94,14 @@ int main(int argc, char *argv[]) {
|
|||
const char *user = NULL;
|
||||
const char *real = NULL;
|
||||
|
||||
const char *Opts = "!C:H:O:Ra:c:eh:j:k:n:p:r:s:u:vw:";
|
||||
const char *Opts = "!C:H:O:RS:a:c:eh:j:k:n:p:r:s:u:vw:";
|
||||
const struct option LongOpts[] = {
|
||||
{ "insecure", no_argument, NULL, '!' },
|
||||
{ "copy", required_argument, NULL, 'C' },
|
||||
{ "hash", required_argument, NULL, 'H' },
|
||||
{ "open", required_argument, NULL, 'O' },
|
||||
{ "restrict", no_argument, NULL, 'R' },
|
||||
{ "bind", required_argument, NULL, 'S' },
|
||||
{ "sasl-plain", required_argument, NULL, 'a' },
|
||||
{ "cert", required_argument, NULL, 'c' },
|
||||
{ "sasl-external", no_argument, NULL, 'e' },
|
||||
|
@ -124,6 +126,7 @@ int main(int argc, char *argv[]) {
|
|||
break; case 'H': hashInit = strtoul(optarg, NULL, 0);
|
||||
break; case 'O': utilPush(&urlOpenUtil, optarg);
|
||||
break; case 'R': self.restricted = true;
|
||||
break; case 'S': bind = optarg;
|
||||
break; case 'a': sasl = true; self.plain = optarg;
|
||||
break; case 'c': cert = optarg;
|
||||
break; case 'e': sasl = true;
|
||||
|
@ -182,7 +185,7 @@ int main(int argc, char *argv[]) {
|
|||
uiFormat(Network, Cold, NULL, "Traveling...");
|
||||
uiDraw();
|
||||
|
||||
int irc = ircConnect(host, port);
|
||||
int irc = ircConnect(bind, host, port);
|
||||
if (pass) ircFormat("PASS :%s\r\n", pass);
|
||||
if (sasl) ircFormat("CAP REQ :sasl\r\n");
|
||||
ircFormat("CAP LS\r\n");
|
||||
|
|
2
chat.h
2
chat.h
|
@ -125,7 +125,7 @@ struct Message {
|
|||
};
|
||||
|
||||
void ircConfig(bool insecure, FILE *cert, FILE *priv);
|
||||
int ircConnect(const char *host, const char *port);
|
||||
int ircConnect(const char *bind, const char *host, const char *port);
|
||||
void ircRecv(void);
|
||||
void ircSend(const char *ptr, size_t len);
|
||||
void ircFormat(const char *format, ...)
|
||||
|
|
33
irc.c
33
irc.c
|
@ -97,23 +97,48 @@ 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 (error) errx(EX_NOHOST, "%s:%s: %s", host, port, gai_strerror(error));
|
||||
|
||||
int sock = -1;
|
||||
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));
|
||||
|
||||
for (struct addrinfo *ai = head; ai; ai = ai->ai_next) {
|
||||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue