int privsep_privpart_bindresport(const int psfd, const PrivSepQuery * const query) { static const in_port_t portlist[] = FTP_ACTIVE_SOURCE_PORTS; const in_port_t *portlistpnt = portlist; int fd; int on = 1; int ret; if ((fd = socket(query->bindresport.protocol, SOCK_STREAM, IPPROTO_TCP)) == -1) { goto bye; } # ifdef SO_REUSEPORT (void) setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *) &on, sizeof on); # else (void) setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof on); # endif privsep_priv_user(); for (;;) { if (query->bindresport.protocol == PF_INET6) { STORAGE_PORT6(query->bindresport.ss) = htons(*portlistpnt); } else { STORAGE_PORT(query->bindresport.ss) = htons(*portlistpnt); } if (bind(fd, (struct sockaddr *) &query->bindresport.ss, STORAGE_LEN(query->bindresport.ss)) == 0) { break; } # ifdef USE_ONLY_FIXED_DATA_PORT (void) sleep(1U); # else if (*portlistpnt == (in_port_t) 0U) { break; } portlistpnt++; # endif } privsep_unpriv_user(); bye: ret = privsep_sendfd(psfd, fd); ret |= close(fd); return ret; }
int filter_overwrite_sa_with_reply_map(const msgpack_object_map * const map, const char * const key_host, const char * const key_port, struct sockaddr_storage * const sa, socklen_t * const sa_len) { if (sa == NULL) { return 0; } const msgpack_object * const obj_host = msgpack_get_map_value_for_key(map, key_host); if (obj_host != NULL && obj_host->type == MSGPACK_OBJECT_RAW && obj_host->via.raw.size > 0 && obj_host->via.raw.size < NI_MAXHOST) { struct addrinfo *ai, hints; memset(&hints, 0, sizeof hints); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = NI_NUMERICHOST | AI_ADDRCONFIG; char new_host[NI_MAXHOST]; memcpy(new_host, obj_host->via.raw.ptr, obj_host->via.raw.size); new_host[obj_host->via.raw.size] = 0; const int gai_err = getaddrinfo(new_host, NULL, &hints, &ai); if (gai_err == 0) { assert(ai->ai_addrlen <= sizeof *sa); if (ai->ai_family == AF_INET && *sa_len >= (socklen_t) sizeof(STORAGE_SIN_ADDR(*sa))) { assert((size_t) ai->ai_addrlen >= sizeof(STORAGE_SIN_ADDR(*sa))); memcpy(&STORAGE_SIN_ADDR(*sa), &STORAGE_SIN_ADDR(* (struct sockaddr_storage *) (void *) ai->ai_addr), sizeof(STORAGE_SIN_ADDR(*sa))); *sa_len = ai->ai_addrlen; STORAGE_FAMILY(*sa) = ai->ai_family; SET_STORAGE_LEN(*sa, ai->ai_addrlen); } else if (ai->ai_family == AF_INET6 && *sa_len >= (socklen_t) sizeof(STORAGE_SIN_ADDR6(*sa))) { assert((size_t) ai->ai_addrlen >= sizeof(STORAGE_SIN_ADDR6(*sa))); memcpy(&STORAGE_SIN_ADDR6(*sa), &STORAGE_SIN_ADDR6(* (struct sockaddr_storage *) (void *) ai->ai_addr), sizeof(STORAGE_SIN_ADDR6(*sa))); *sa_len = ai->ai_addrlen; STORAGE_FAMILY(*sa) = ai->ai_family; SET_STORAGE_LEN(*sa, ai->ai_addrlen); } freeaddrinfo(ai); } } const msgpack_object * const obj_port = msgpack_get_map_value_for_key(map, key_port); if (obj_port != NULL && obj_port->type == MSGPACK_OBJECT_POSITIVE_INTEGER) { if (obj_port->via.i64 >= 0 && obj_port->via.i64 <= 65535) { if (STORAGE_FAMILY(*sa) == AF_INET) { STORAGE_PORT(*sa) = htons((in_port_t) obj_port->via.i64); } else if (STORAGE_FAMILY(*sa) == AF_INET6) { STORAGE_PORT6(*sa) = htons((in_port_t) obj_port->via.i64); } } } return 0; }