/* * This file is part of uIRCd. (https://git.redxen.eu/caskd/uIRCd) * Copyright (c) 2019, 2020 Alex-David Denes * * uIRCd is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * any later version. * * uIRCd is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with uIRCd. If not, see . */ #include "connection.h" #include "buffer.h" #include "channels.h" #include "limits.h" #include "logging.h" #include "memory.h" #include // errno #include // ?? #include // getaddrinfo() gai_strerror() #include // bool #include // snprintf() #include // strerror() #include // sockaddr connect() #include // size_t ssize_t socklen_t #include #include #include // Assm_mesg Assm_cmd... #include // ?? signed int init_connection(Connection* conn) { int sockfd, getaddrres, connectres; struct addrinfo* addr_info; if ((getaddrres = getaddrinfo(conn->data.address, conn->data.service, NULL, &addr_info)) != 0) { freeaddrinfo(addr_info); LOG(LOG_WARNING, "Failed to get address info for " ADDRFMT ": " ERRNOFMT, conn->data.address, conn->data.service, gai_strerror(getaddrres), getaddrres); if (getaddrres != EAI_AGAIN && getaddrres != EAI_NONAME) return INIT_HARDFAIL; else return INIT_SOFTFAIL; } if ((sockfd = socket(addr_info->ai_family, addr_info->ai_socktype, addr_info->ai_protocol)) < 0) { LOG(LOG_WARNING, "Failed to open a socket for " ADDRFMT ": " ERRNOFMT, conn->data.address, conn->data.service, strerror(errno), errno); freeaddrinfo(addr_info); return INIT_HARDFAIL; } if ((connectres = connect(sockfd, addr_info->ai_addr, addr_info->ai_addrlen)) == -1) { close(sockfd); freeaddrinfo(addr_info); LOG(LOG_WARNING, "Failed to connect to host " ADDRFMT ": " ERRNOFMT, conn->data.address, conn->data.service, strerror(errno), errno); if (errno != EADDRNOTAVAIL && errno != ETIMEDOUT && errno != ECONNRESET && errno != ECONNREFUSED) return INIT_HARDFAIL; else return INIT_SOFTFAIL; } freeaddrinfo(addr_info); return sockfd; } bool register_user(char* buf, size_t len, int fd, Connection_User* user) { ssize_t tmp; IRC_Message build_buf; if (user->password != NULL && (tmp = Assm_mesg(buf, Assm_cmd_PASS(&build_buf, user->password), len)) > 0) { if (write_buffer(buf, fd, (size_t) tmp, true) != -1) { LOG(LOG_INFO, "Sent PASS authentication"); } else return false; } if ((tmp = Assm_mesg(buf, Assm_cmd_NICK(&build_buf, user->nickname), len)) > 0) { if (write_buffer(buf, fd, (size_t) tmp, true) != -1) { LOG(LOG_INFO, "Sent NICK registration with nickname \"%s\".", user->nickname); } else return false; } if ((tmp = Assm_mesg(buf, Assm_cmd_USER(&build_buf, user->username, user->realname, 0), len)) > 0) { if (write_buffer(buf, fd, (size_t) tmp, true) != -1) { LOG(LOG_INFO, "Sent USER registration with username \"%s\" and realname \"%s\".", user->username, user->realname); } else return false; } return true; } bool commit_channelist(char* buf, size_t len, int fd, Channel* chans) { ssize_t tmp; for (unsigned int i = 0; chans != NULL && chans[i].name != NULL; i++) { IRC_Message msg = { .args = { chans[i].name, chans[i].key, NULL }, .trailing = true, .cmd = (chans[i].joined) ? JOIN : PART }; if ((tmp = Assm_mesg(buf, &msg, len)) > 0) { if (write_buffer(buf, fd, (size_t) tmp, true) == -1) { LOG(LOG_WARNING, "Couldn't auto-join channel \"%s\": " ERRNOFMT, chans[i].name, strerror(errno), errno); return false; } } } return true; }