static int test_open(void *ctx, UNUSED void const *master_ctx) { fr_listen_test_t *io_ctx = talloc_get_type_abort(ctx, fr_listen_test_t); io_ctx->sockfd = fr_socket_server_udp(&io_ctx->ipaddr, &io_ctx->port, NULL, true); if (io_ctx->sockfd < 0) { fr_perror("radius_test: Failed creating socket"); exit(EXIT_FAILURE); } if (fr_socket_bind(io_ctx->sockfd, &io_ctx->ipaddr, &io_ctx->port, NULL) < 0) { fr_perror("radius_test: Failed binding to socket"); exit(EXIT_FAILURE); } return 0; }
static int send_with_socket(RADIUS_PACKET **reply, RADIUS_PACKET *request) { int on = 1; #ifdef HAVE_LINUX_IF_PACKET_H if (raw_mode) { sockfd = fr_dhcpv4_raw_socket_open(&ll, iface_ind); if (sockfd < 0) { ERROR("Error opening socket"); return -1; } } else #endif { sockfd = fr_socket_server_udp(&request->src_ipaddr, &request->src_port, NULL, false); if (sockfd < 0) { ERROR("Error opening socket: %s", fr_strerror()); return -1; } if (fr_socket_bind(sockfd, &request->src_ipaddr, &request->src_port, NULL) < 0) { ERROR("Error binding socket: %s", fr_strerror()); return -1; } } /* * Set option 'receive timeout' on socket. * Note: in case of a timeout, the error will be "Resource temporarily unavailable". */ if (setsockopt(sockfd, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv_timeout, sizeof(struct timeval)) == -1) { ERROR("Failed setting socket timeout: %s", fr_syserror(errno)); return -1; } if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { ERROR("Can't set broadcast option: %s", fr_syserror(errno)); return -1; } request->sockfd = sockfd; #ifdef HAVE_LINUX_IF_PACKET_H if (raw_mode) { if (fr_dhcpv4_raw_packet_send(sockfd, &ll, request) < 0) { ERROR("Failed sending (fr_dhcpv4_raw_packet_send): %s", fr_syserror(errno)); return -1; } if (!reply_expected) return 0; *reply = fr_dhcpv4_recv_raw_loop(sockfd, &ll, request); if (!*reply) { ERROR("Error receiving reply (fr_dhcpv4_recv_raw_loop)"); return -1; } } else #endif { if (fr_dhcpv4_udp_packet_send(request) < 0) { ERROR("Failed sending: %s", fr_syserror(errno)); return -1; } if (!reply_expected) return 0; *reply = fr_dhcpv4_udp_packet_recv(sockfd); if (!*reply) { if (errno == EAGAIN) { fr_strerror(); /* clear error */ ERROR("Timed out waiting for reply"); } else { ERROR("Error receiving reply"); } return -1; } } return 0; }
/** Open a UDP listener for DHCPV4 * */ static int mod_open(fr_listen_t *li) { proto_dhcpv4_udp_t const *inst = talloc_get_type_abort_const(li->app_io_instance, proto_dhcpv4_udp_t); proto_dhcpv4_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_dhcpv4_udp_thread_t); int sockfd, rcode; uint16_t port = inst->port; CONF_SECTION *server_cs; CONF_ITEM *ci; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); if (sockfd < 0) { PERROR("Failed opening UDP socket"); error: return -1; } /* * Set SO_REUSEPORT before bind, so that all packets can * listen on the same destination IP address. */ if (1) { int on = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) { ERROR("Failed to set socket 'reuseport': %s", fr_syserror(errno)); close(sockfd); return -1; } } if (inst->broadcast) { int on = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0) { ERROR("Failed to set broadcast option: %s", fr_syserror(errno)); close(sockfd); return -1; } } /* * SUID up is really only needed if interface is set, OR port <1024. */ rad_suid_up(); rcode = fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface); rad_suid_down(); if (rcode < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; } thread->sockfd = sockfd; ci = cf_parent(inst->cs); /* listen { ... } */ rad_assert(ci != NULL); ci = cf_parent(ci); rad_assert(ci != NULL); server_cs = cf_item_to_section(ci); thread->name = fr_app_io_socket_name(thread, &proto_dhcpv4_udp, NULL, 0, &inst->ipaddr, inst->port, inst->interface); DEBUG("Listening on dhcpv4 address %s bound to virtual server %s", thread->name, cf_section_name2(server_cs)); return 0; }
/** Open a UDP listener for RADIUS * */ static int mod_open(fr_listen_t *li) { proto_radius_udp_t const *inst = talloc_get_type_abort_const(li->app_io_instance, proto_radius_udp_t); proto_radius_udp_thread_t *thread = talloc_get_type_abort(li->thread_instance, proto_radius_udp_thread_t); int sockfd; uint16_t port = inst->port; CONF_SECTION *server_cs; CONF_ITEM *ci; li->fd = sockfd = fr_socket_server_udp(&inst->ipaddr, &port, inst->port_name, true); if (sockfd < 0) { PERROR("Failed opening UDP socket"); error: return -1; } /* * Set SO_REUSEPORT before bind, so that all packets can * listen on the same destination IP address. */ if (1) { int on = 1; if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, &on, sizeof(on)) < 0) { ERROR("Failed to set socket 'reuseport': %s", fr_syserror(errno)); return -1; } } #ifdef SO_RCVBUF if (inst->recv_buff_is_set) { int opt; opt = inst->recv_buff; if (setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &opt, sizeof(int)) < 0) { WARN("Failed setting 'recv_buf': %s", fr_syserror(errno)); } } #endif #ifdef SO_SNDBUF if (inst->send_buff_is_set) { int opt; opt = inst->send_buff; if (setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &opt, sizeof(int)) < 0) { WARN("Failed setting 'send_buf': %s", fr_syserror(errno)); } } #endif if (fr_socket_bind(sockfd, &inst->ipaddr, &port, inst->interface) < 0) { close(sockfd); PERROR("Failed binding socket"); goto error; } thread->sockfd = sockfd; ci = cf_parent(inst->cs); /* listen { ... } */ rad_assert(ci != NULL); ci = cf_parent(ci); rad_assert(ci != NULL); server_cs = cf_item_to_section(ci); thread->name = fr_app_io_socket_name(thread, &proto_radius_udp, NULL, 0, &inst->ipaddr, inst->port, inst->interface); // @todo - also print out auth / acct / coa, etc. DEBUG("Listening on radius address %s bound to virtual server %s", thread->name, cf_section_name2(server_cs)); return 0; }