/** Initialise a new outbound connection * * @param[out] fd_out Where to write the new file descriptor. * @param[in] uctx A #rlm_logtee_thread_t. */ static fr_connection_state_t _logtee_conn_init(int *fd_out, void *uctx) { rlm_logtee_thread_t *t = talloc_get_type_abort(uctx, rlm_logtee_thread_t); rlm_logtee_t const *inst = t->inst; int fd = -1; switch (inst->log_dst) { case LOGTEE_DST_UNIX: DEBUG2("Opening UNIX socket at \"%s\"", inst->unix_sock.path); fd = fr_socket_client_unix(inst->unix_sock.path, true); if (fd < 0) return FR_CONNECTION_STATE_FAILED; break; case LOGTEE_DST_TCP: DEBUG2("Opening TCP connection to %pV:%u", fr_box_ipaddr(inst->tcp.dst_ipaddr), inst->tcp.port); fd = fr_socket_client_tcp(NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true); if (fd < 0) return FR_CONNECTION_STATE_FAILED; break; case LOGTEE_DST_UDP: DEBUG2("Opening UDP connection to %pV:%u", fr_box_ipaddr(inst->udp.dst_ipaddr), inst->udp.port); fd = fr_socket_client_udp(NULL, NULL, &inst->udp.dst_ipaddr, inst->udp.port, true); if (fd < 0) return FR_CONNECTION_STATE_FAILED; break; /* * Are not connection oriented destinations */ case LOGTEE_DST_INVALID: case LOGTEE_DST_FILE: rad_assert(0); return FR_CONNECTION_STATE_FAILED; } *fd_out = fd; return FR_CONNECTION_STATE_CONNECTING; }
static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *timeout) { int fd; rlm_smsotp_t *inst = instance; int *fdp; fd = fr_socket_client_unix(inst->socket, false); if (fd < 0) { ERROR("Failed opening SMSOTP file %s: %s", inst->socket, fr_syserror(errno)); return NULL; } if (fr_socket_wait_for_connect(fd, timeout) < 0) { ERROR("Failed connecting to SMSOTP file %s: %s", inst->socket, fr_syserror(errno)); return NULL; } fdp = talloc_zero(ctx, int); talloc_set_destructor(fdp, _mod_conn_free); *fdp = fd; return fdp; }
static void *mod_conn_create(TALLOC_CTX *ctx, void *instance, struct timeval const *timeout) { linelog_instance_t *inst = instance; linelog_conn_t *conn; int sockfd = -1; switch (inst->log_dst) { case LINELOG_DST_UNIX: DEBUG2("rlm_linelog (%s): Opening UNIX socket at \"%s\"", inst->name, inst->unix.path); sockfd = fr_socket_client_unix(inst->unix.path, true); if (sockfd < 0) { ERROR("rlm_linelog (%s): Failed opening UNIX socket: %s", inst->name, fr_strerror()); return NULL; } break; case LINELOG_DST_TCP: if (DEBUG_ENABLED2) { char buff[INET6_ADDRSTRLEN + 4]; /* IPv6 + /<d><d><d> */ fr_ntop(buff, sizeof(buff), &inst->tcp.dst_ipaddr); DEBUG2("rlm_linelog (%s): Opening TCP connection to %s:%u", inst->name, buff, inst->tcp.port); } sockfd = fr_socket_client_tcp(NULL, &inst->tcp.dst_ipaddr, inst->tcp.port, true); if (sockfd < 0) { ERROR("rlm_linelog (%s): Failed opening TCP socket: %s", inst->name, fr_strerror()); return NULL; } break; case LINELOG_DST_UDP: if (DEBUG_ENABLED2) { char buff[INET6_ADDRSTRLEN + 4]; /* IPv6 + /<d><d><d> */ fr_ntop(buff, sizeof(buff), &inst->udp.dst_ipaddr); DEBUG2("rlm_linelog (%s): Opening UDP connection to %s:%u", inst->name, buff, inst->udp.port); } sockfd = fr_socket_client_udp(NULL, &inst->udp.dst_ipaddr, inst->udp.port, true); if (sockfd < 0) { ERROR("rlm_linelog (%s): Failed opening UDP socket: %s", inst->name, fr_strerror()); return NULL; } break; /* * Are not connection oriented destinations */ case LINELOG_DST_INVALID: case LINELOG_DST_FILE: case LINELOG_DST_SYSLOG: rad_assert(0); return NULL; } if (errno == EINPROGRESS) { if (FR_TIMEVAL_TO_MS(timeout)) { DEBUG2("rlm_linelog (%s): Waiting for connection to complete...", inst->name); } else { DEBUG2("rlm_linelog (%s): Blocking until connection complete...", inst->name); } if (fr_socket_wait_for_connect(sockfd, timeout) < 0) { ERROR("rlm_linelog (%s): %s", inst->name, fr_strerror()); close(sockfd); return NULL; } } DEBUG2("rlm_linelog (%s): Connection successful", inst->name); /* * Set blocking operation as we have no timeout set */ if (!FR_TIMEVAL_TO_MS(timeout) && (fr_blocking(sockfd) < 0)) { ERROR("rlm_linelog (%s): Failed setting nonblock flag on fd", inst->name); close(sockfd); return NULL; } conn = talloc_zero(ctx, linelog_conn_t); conn->sockfd = sockfd; talloc_set_destructor(conn, _mod_conn_free); return conn; }
static int do_connect(int *out, char const *file, char const *server) { int sockfd; ssize_t r; fr_channel_type_t channel; char buffer[65536]; uint32_t magic; /* * Close stale file descriptors */ if (*out != -1) { close(*out); *out = -1; } if (file) { /* * FIXME: Get destination from command line, if possible? */ sockfd = fr_socket_client_unix(file, false); if (sockfd < 0) { fr_perror("radmin"); if (errno == ENOENT) { fprintf(stderr, "Perhaps you need to run the commands:"); fprintf(stderr, "\tcd /etc/raddb\n"); fprintf(stderr, "\tln -s sites-available/control-socket " "sites-enabled/control-socket\n"); fprintf(stderr, "and then re-start the server?\n"); } return -1; } } else { sockfd = client_socket(server); } /* * Only works for BSD, but Linux allows us * to mask SIGPIPE, so that's fine. */ #ifdef SO_NOSIGPIPE { int set = 1; setsockopt(sockfd, SOL_SOCKET, SO_NOSIGPIPE, (void *)&set, sizeof(int)); } #endif /* * Set up the initial header data. */ magic = 0xf7eead16; magic = htonl(magic); memcpy(buffer, &magic, sizeof(magic)); memset(buffer + sizeof(magic), 0, sizeof(magic)); r = fr_channel_write(sockfd, FR_CHANNEL_INIT_ACK, buffer, 8); if (r <= 0) { do_close: fprintf(stderr, "%s: Error in socket: %s\n", progname, fr_syserror(errno)); close(sockfd); return -1; } r = fr_channel_read(sockfd, &channel, buffer + 8, 8); if (r <= 0) goto do_close; if ((r != 8) || (channel != FR_CHANNEL_INIT_ACK) || (memcmp(buffer, buffer + 8, 8) != 0)) { fprintf(stderr, "%s: Incompatible versions\n", progname); close(sockfd); return -1; } if (server && secret) { r = do_challenge(sockfd); if (r <= 0) goto do_close; } *out = sockfd; return 0; }