/** * Do all socket creation and initialization */ void create_sockets() { struct sockaddr_in sin; int fdflag, i; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(port); if ((listener = socket(AF_INET,SOCK_DGRAM,0)) == INVALID_SOCKET) { sockerror(0, 0, "Error creating socket for listener"); exit(1); } if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR) { sockerror(0, 0, "Error binding socket for listener"); exit(1); } #ifndef BLOCKING #ifdef WINDOWS fdflag = 1; if (ioctlsocket(listener, FIONBIO, &fdflag) == SOCKET_ERROR) { sockerror(0, 0, "Error setting non-blocking option"); closesocket(listener); exit(1); } #else if ((fdflag = fcntl(listener, F_GETFL)) == SOCKET_ERROR) { sockerror(0, 0, "Error getting socket descriptor flags"); closesocket(listener); exit(1); } fdflag |= O_NONBLOCK; if (fcntl(listener, F_SETFL, fdflag) == SOCKET_ERROR) { sockerror(0, 0, "Error setting non-blocking option"); closesocket(listener); exit(1); } #endif #endif // BLOCKING if (setsockopt(listener, IPPROTO_IP, IP_TOS, (char *)&dscp, sizeof(dscp)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting dscp"); closesocket(listener); exit(1); } #ifdef IP_MTU_DISCOVER { int mtuflag = IP_PMTUDISC_DONT; if (setsockopt(listener, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&mtuflag, sizeof(mtuflag)) == SOCKET_ERROR) { sockerror(0, 0, "Error disabling MTU discovery"); closesocket(listener); exit(1); } } #endif if (buffer) { if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting receive buffer size"); exit(1); } } else { buffer = DEF_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { buffer = DEF_BSD_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting receive buffer size"); exit(1); } } } for (i = 0; i < pub_multi_count; i++) { if (server_count > 0) { log(0, 0, "joining ssm for server IPs"); if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, server_keys, server_count)) { exit(1); } if (has_proxy) { log(0, 0, "joining ssm for proxy IPs"); if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, &proxy_info, 1)) { exit(1); } } } else { if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, NULL, 0)) { exit(1); } } } }
/** * Do all socket creation and initialization */ void create_sockets() { struct sockaddr_in sin; int fdflag, found_if, i; memset(&sin, 0, sizeof(sin)); sin.sin_family = AF_INET; sin.sin_addr.s_addr = htonl(INADDR_ANY); sin.sin_port = htons(port); if ((listener = socket(AF_INET,SOCK_DGRAM,0)) == INVALID_SOCKET) { sockerror(0, 0, "Error creating socket for listener"); exit(1); } if (bind(listener, (struct sockaddr *)&sin, sizeof(sin)) == SOCKET_ERROR) { sockerror(0, 0, "Error binding socket for listener"); exit(1); } #ifndef BLOCKING #ifdef WINDOWS fdflag = 1; if (ioctlsocket(listener, FIONBIO, &fdflag) == SOCKET_ERROR) { sockerror(0, 0, "Error setting non-blocking option"); closesocket(listener); exit(1); } #else if ((fdflag = fcntl(listener, F_GETFL)) == SOCKET_ERROR) { sockerror(0, 0, "Error getting socket descriptor flags"); closesocket(listener); exit(1); } fdflag |= O_NONBLOCK; if (fcntl(listener, F_SETFL, fdflag) == SOCKET_ERROR) { sockerror(0, 0, "Error setting non-blocking option"); closesocket(listener); exit(1); } #endif #endif // BLOCKING if (setsockopt(listener, IPPROTO_IP, IP_TOS, (char *)&dscp, sizeof(dscp)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting dscp"); closesocket(listener); exit(1); } if (buffer) { if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting receive buffer size"); exit(1); } if (setsockopt(listener, SOL_SOCKET, SO_SNDBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting send buffer size"); exit(1); } } else { buffer = DEF_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { buffer = DEF_BSD_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting receive buffer size"); exit(1); } } buffer = DEF_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_SNDBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { buffer = DEF_BSD_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_SNDBUF, (char *)&buffer, sizeof(buffer)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting send buffer size"); exit(1); } } } if (setsockopt(listener, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting ttl"); closesocket(listener); exit(1); } if (out_addr.s_addr == INADDR_NONE) { for (i = 0, found_if = 0; (i < ifl_len) && !found_if; i++) { if (!ifl[i].isloopback) { found_if = 1; out_addr.s_addr = ifl[i].addr.s_addr; } } if (!found_if) { if (ifl_len > 0) { out_addr.s_addr = ifl[0].addr.s_addr; } else { fprintf(stderr, "ERROR: no network interfaces found!\n"); exit(1); } } } if (setsockopt(listener, IPPROTO_IP, IP_MULTICAST_IF, (char *)&out_addr, sizeof(out_addr)) == SOCKET_ERROR) { sockerror(0, 0, "Error setting outgoing interface"); closesocket(listener); exit(1); } for (i = 0; i < pub_multi_count; i++) { if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, server_fp, server_fp_count)) { exit(1); } } }
/** * Processes a new incoming ANNOUNCE */ void handle_announce(union sockaddr_u *src, unsigned char *packet, unsigned packetlen, struct timeval rxtime) { struct uftp_h *header; struct announce_h *announce; uint32_t *addrlist; int addrlen, rval; struct group_list_t *group; time_t t; struct tm *start_time; char privname[INET6_ADDRSTRLEN], srcname[INET6_ADDRSTRLEN]; char srcfqdn[DESTNAME_LEN]; header = (struct uftp_h *)packet; announce = (struct announce_h *)(packet + sizeof(struct uftp_h)); addrlist = (uint32_t *)((unsigned char *)announce + (announce->hlen * 4)); addrlen = (packetlen - sizeof(struct uftp_h) - (announce->hlen * 4)) / 4; if ((packetlen < sizeof(struct uftp_h) + (announce->hlen * 4U)) || ((announce->hlen * 4U) < sizeof(struct announce_h))) { log1(ntohl(header->group_id), header->group_inst, 0, "Rejecting ANNOUNCE from %08X: invalid message size", ntohl(header->src_id)); return; } if ((addrlen != 0) && (!uid_in_list(addrlist, addrlen))) { log1(ntohl(header->group_id), header->group_inst, 0, "Name not in host list"); return; } if ((group = find_open_slot()) == NULL ) { log0(ntohl(header->group_id), header->group_inst, 0, "Error: maximum number of incoming files exceeded: %d\n", MAXLIST); return; } t = time(NULL); start_time = localtime(&t); snprintf(group->start_date, sizeof(group->start_date), "%04d%02d%02d", start_time->tm_year + 1900, start_time->tm_mon + 1, start_time->tm_mday); snprintf(group->start_time, sizeof(group->start_time), "%02d%02d%02d", start_time->tm_hour, start_time->tm_min, start_time->tm_sec); if (!read_announce(group, packet, src, rxtime, packetlen)) { return; } if ((rval = getnameinfo((struct sockaddr *)src, family_len(*src), srcname, sizeof(srcname), NULL, 0, NI_NUMERICHOST)) != 0) { glog1(group, "getnameinfo failed: %s", gai_strerror(rval)); } if (!noname) { if ((rval = getnameinfo((struct sockaddr *)src, family_len(*src), srcfqdn, sizeof(srcfqdn), NULL, 0, 0)) != 0) { glog1(group, "getnameinfo failed: %s", gai_strerror(rval)); } } else { strncpy(srcfqdn, srcname, sizeof(srcfqdn) - 1); } if ((rval = getnameinfo((struct sockaddr *)&group->multi, family_len(group->multi), privname, sizeof(privname), NULL, 0, NI_NUMERICHOST)) != 0) { glog1(group, "getnameinfo failed: %s", gai_strerror(rval)); } glog2(group, "Received request from %08X at %s (%s)", ntohl(group->src_id), srcfqdn, srcname); glog2(group, "Using private multicast address %s", privname); glog3(group, "grtt = %.6f", group->grtt); glog3(group, "send time: %d.%06d", group->last_server_ts.tv_sec, group->last_server_ts.tv_usec); glog3(group, "receive time: %d.%06d", group->last_server_rx_ts.tv_sec, group->last_server_rx_ts.tv_usec); if (status_file) { fprintf(status_file, "CONNECT;%04d/%02d/%02d-%02d:%02d:%02d;%08X;%08X;%s;%s\n", start_time->tm_year + 1900, start_time->tm_mon + 1, start_time->tm_mday, start_time->tm_hour, start_time->tm_min, start_time->tm_sec, ntohl(group->src_id), group->group_id, srcname, srcfqdn); fflush(status_file); } if (group->restart) { if (group->sync_mode) { glog1(group, "Sync mode and restart mode incompatible"); send_abort(group, "Sync mode and restart mode incompatible"); return; } } if (!addr_blank(&group->multi)) { if (server_count > 0) { if (!is_multicast(&group->multi, 1)) { glog1(group, "Invalid source specific multicast address: %s", privname); send_abort(group, "Invalid source specific multicast address"); return; } if (!other_mcast_users(group)) { if (!multicast_join(listener, group->group_id, &group->multi, m_interface, interface_count, server_keys, server_count)) { send_abort(group, "Error joining multicast group"); return; } if (has_proxy) { if (!multicast_join(listener,group->group_id, &group->multi, m_interface, interface_count, &proxy_info, 1)) { send_abort(group, "Error joining multicast group"); return; } } } } else { if (!is_multicast(&group->multi, 0)) { glog1(group, "Invalid multicast address: %s", privname); send_abort(group, "Invalid multicast address"); return; } if (!other_mcast_users(group)) { if (!multicast_join(listener, group->group_id, &group->multi, m_interface, interface_count, NULL, 0)) { send_abort(group, "Error joining multicast group"); return; } } } group->multi_join = 1; } send_register(group); }
/** * Do all socket creation and initialization */ void create_sockets(void) { struct addrinfo ai_hints, *ai_rval; int family, rval, fdflag, i; #if (defined IPV6_RECVTCLASS || defined IP_RECVTCLASS || defined IP_RECVTOS) &&\ !(defined WINDOWS && _WIN32_WINNT < _WIN32_WINNT_LONGHORN) int tosflag; #endif family = AF_INET; for (i = 0; i < pub_multi_count; i++) { if (pub_multi[i].ss.ss_family == AF_INET6) { family = AF_INET6; break; } } if ((listener = socket(family, SOCK_DGRAM, 0)) == INVALID_SOCKET) { sockerror(0, 0, 0, "Error creating socket for listener"); exit(ERR_SOCKET); } #if (defined WINDOWS && _WIN32_WINNT >= _WIN32_WINNT_LONGHORN) ||\ (!defined WINDOWS && !defined NO_DUAL) if (family == AF_INET6) { int v6flag = 0; if (setsockopt(listener, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&v6flag, sizeof(v6flag)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting v6only"); closesocket(listener); exit(ERR_SOCKET); } } #endif memset(&ai_hints, 0, sizeof(ai_hints)); ai_hints.ai_family = family; ai_hints.ai_socktype = SOCK_DGRAM; ai_hints.ai_protocol = 0; ai_hints.ai_flags = AI_PASSIVE | AI_NUMERICSERV; if ((rval = getaddrinfo(NULL, portname, &ai_hints, &ai_rval)) != 0) { log0(0, 0, 0, "Error getting bind address: %s", gai_strerror(rval)); exit(ERR_SOCKET); } if (bind(listener, ai_rval->ai_addr, ai_rval->ai_addrlen) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error binding socket for listener"); closesocket(listener); exit(ERR_SOCKET); } freeaddrinfo(ai_rval); #ifdef WINDOWS fdflag = 1; if (ioctlsocket(listener, FIONBIO, &fdflag) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting non-blocking option"); closesocket(listener); exit(ERR_SOCKET); } #else if ((fdflag = fcntl(listener, F_GETFL)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error getting socket descriptor flags"); closesocket(listener); exit(ERR_SOCKET); } fdflag |= O_NONBLOCK; if (fcntl(listener, F_SETFL, fdflag) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting non-blocking option"); closesocket(listener); exit(ERR_SOCKET); } #endif if (family == AF_INET6) { #if defined IPV6_TCLASS && !defined WINDOWS if (setsockopt(listener, IPPROTO_IPV6, IPV6_TCLASS, (char *)&dscp, sizeof(dscp)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting dscp"); closesocket(listener); exit(ERR_SOCKET); } #endif #ifdef IPV6_RECVTCLASS #if !(defined WINDOWS && _WIN32_WINNT < _WIN32_WINNT_LONGHORN) tosflag = 1; if (setsockopt(listener, IPPROTO_IPV6, IPV6_RECVTCLASS, (char *)&tosflag, sizeof(tosflag)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting recv tos"); closesocket(listener); exit(ERR_SOCKET); } #endif #endif #ifdef IPV6_MTU_DISCOVER { int mtuflag = IP_PMTUDISC_DONT; if (setsockopt(listener, IPPROTO_IPV6, IPV6_MTU_DISCOVER, (char *)&mtuflag, sizeof(mtuflag)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error disabling MTU discovery"); closesocket(listener); exit(ERR_SOCKET); } } #endif } #if (defined WINDOWS && _WIN32_WINNT < _WIN32_WINNT_LONGHORN) ||\ (defined NO_DUAL) if (family == AF_INET) { #endif if (setsockopt(listener, IPPROTO_IP, IP_TOS, (char *)&dscp, sizeof(dscp)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting dscp"); closesocket(listener); exit(ERR_SOCKET); } #ifdef IP_RECVTCLASS #if !(defined WINDOWS && _WIN32_WINNT < _WIN32_WINNT_LONGHORN) tosflag = 1; if (setsockopt(listener, IPPROTO_IP, IP_RECVTCLASS, (char *)&tosflag, sizeof(tosflag)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting recv tos"); closesocket(listener); exit(ERR_SOCKET); } #endif #elif defined IP_RECVTOS tosflag = 1; if (setsockopt(listener, IPPROTO_IP, IP_RECVTOS, (char *)&tosflag, sizeof(tosflag)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting recv tos"); closesocket(listener); exit(ERR_SOCKET); } #endif #ifdef IP_MTU_DISCOVER { int mtuflag = IP_PMTUDISC_DONT; if (setsockopt(listener, IPPROTO_IP, IP_MTU_DISCOVER, (char *)&mtuflag, sizeof(mtuflag)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error disabling MTU discovery"); closesocket(listener); exit(ERR_SOCKET); } } #endif #if (defined WINDOWS && _WIN32_WINNT < _WIN32_WINNT_LONGHORN) ||\ (defined NO_DUAL) } #endif if (rcvbuf) { if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf, sizeof(rcvbuf)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting receive buffer size"); exit(ERR_SOCKET); } } else { rcvbuf = DEF_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf, sizeof(rcvbuf)) == SOCKET_ERROR) { rcvbuf = DEF_BSD_RCVBUF; if (setsockopt(listener, SOL_SOCKET, SO_RCVBUF, (char *)&rcvbuf, sizeof(rcvbuf)) == SOCKET_ERROR) { sockerror(0, 0, 0, "Error setting receive buffer size"); exit(ERR_SOCKET); } } } for (i = 0; i < pub_multi_count; i++) { if (server_count > 0) { log3(0, 0, 0, "joining ssm for server IPs"); if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, server_keys, server_count)) { exit(ERR_SOCKET); } if (has_proxy) { log3(0, 0, 0, "joining ssm for proxy IPs"); if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, &proxy_info, 1)) { exit(ERR_SOCKET); } } } else { if (!multicast_join(listener, 0, &pub_multi[i], m_interface, interface_count, NULL, 0)) { exit(ERR_SOCKET); } } } }