+ struct addrinfo* r = res;
+ udp_socket_t* prev_sock = sock->socks_;
+ while(prev_sock && prev_sock->next_) prev_sock = prev_sock->next_;
+ while(r) {
+ udp_socket_t* new_sock = malloc(sizeof(udp_socket_t));
+ if(!new_sock) {
+ log_printf(ERROR, "memory error at udp_init");
+ freeaddrinfo(res);
+ udp_close(sock);
+ return -2;
+ }
+ memset(&(new_sock->local_end_.addr_), 0, sizeof(new_sock->local_end_.addr_));
+ new_sock->local_end_.len_ = sizeof(new_sock->local_end_.addr_);
+ memset(&(new_sock->remote_end_.addr_), 0, sizeof(new_sock->remote_end_.addr_));
+ new_sock->remote_end_.len_ = sizeof(new_sock->remote_end_.addr_);
+ new_sock->remote_end_set_ = 0;
+ new_sock->next_ = NULL;
+ new_sock->idx_ = (*idx)++;
+
+ if(!sock->socks_) {
+ sock->socks_ = new_sock;
+ prev_sock = new_sock;
+ }
+ else {
+ prev_sock->next_ = new_sock;
+ prev_sock = new_sock;
+ }
+
+ memcpy(&(new_sock->local_end_.addr_), r->ai_addr, r->ai_addrlen);
+ new_sock->local_end_.len_ = r->ai_addrlen;
+ new_sock->fd_ = socket(new_sock->local_end_.addr_.ss_family, SOCK_DGRAM, 0);
+ if(new_sock->fd_ < 0) {
+ log_printf(ERROR, "Error on opening udp socket: %s", strerror(errno));
+ freeaddrinfo(res);
+ udp_close(sock);
+ return -1;
+ }
+
+ if(r->ai_family == AF_INET6) {
+ int on = 1;
+ if(setsockopt(new_sock->fd_, IPPROTO_IPV6, IPV6_V6ONLY, &on, sizeof(on)))
+ log_printf(ERROR, "Error on setting IPV6_V6ONLY socket option: %s", strerror(errno));
+ }
+
+ errcode = bind(new_sock->fd_, (struct sockaddr*)&(new_sock->local_end_.addr_), new_sock->local_end_.len_);
+ if(errcode) {
+ log_printf(ERROR, "Error on binding udp socket: %s", strerror(errno));
+ freeaddrinfo(res);
+ udp_close(sock);
+ return -1;
+ }
+
+ char* local_string = udp_endpoint_to_string(&(new_sock->local_end_));
+ if(local_string) {
+ log_printf(NOTICE, "socket[%d] listening on: %s", new_sock->idx_, local_string);
+ free(local_string);
+ }
+
+ r = r->ai_next;
+ }