/*! @decl string query_address() *! *! Get the address and port of the local socket end-point. *! *! @returns *! This function returns the address and port of a socket end-point *! on the form @expr{"x.x.x.x port"@} (IPv4) or *! @expr{"x:x:x:x:x:x:x:x port"@} (IPv6). *! *! If there is some error querying or formatting the address, *! @expr{0@} (zero) is returned and @[errno()] will return the *! error code. *! *! @throws *! An error is thrown if the socket isn't bound. */ static void socket_query_address(INT32 args) { PIKE_SOCKADDR addr; int i; char buffer[496]; ACCEPT_SIZE_T len; if(THIS->box.fd <0) Pike_error("Stdio.Port->query_address(): Socket not bound yet.\n"); len=sizeof(addr); i=fd_getsockname(THIS->box.fd,(struct sockaddr *)&addr,&len); pop_n_elems(args); if(i < 0 || len < (int)sizeof(addr.ipv4)) { THIS->my_errno=errno; push_int(0); return; } #ifdef fd_inet_ntop if(!fd_inet_ntop(SOCKADDR_FAMILY(addr), SOCKADDR_IN_ADDR(addr), buffer, sizeof(buffer)-20)) { THIS->my_errno = errno; push_int(0); return; } #else if(SOCKADDR_FAMILY(addr) == AF_INET) { char *q = inet_ntoa(*SOCKADDR_IN_ADDR(addr)); strncpy(buffer,q,sizeof(buffer)-20); buffer[sizeof(buffer)-20]=0; }else{ #ifdef EAFNOSUPPORT THIS->my_errno = EAFNOSUPPORT; #else THIS->my_errno = EINVAL; #endif push_int(0); return; } #endif sprintf(buffer+strlen(buffer)," %d",(int)(ntohs(addr.ipv4.sin_port))); push_text(buffer); }
static void push_log_entry(struct log_entry *le) { struct object *o = clone_object( aap_log_object_program, 0 ); struct log_object *lo = (struct log_object*)o->storage; lo->time = le->t; lo->sent_bytes = le->sent_bytes; lo->reply = le->reply; lo->received_bytes = le->received_bytes; lo->raw = make_shared_binary_string(le->raw.str, le->raw.len); lo->url = make_shared_binary_string(le->url.str, le->url.len); lo->method = make_shared_binary_string(le->method.str, le->method.len); lo->protocol = le->protocol; le->protocol->refs++; #ifdef HAVE_INET_NTOP { char buffer[64]; lo->from = make_shared_string( inet_ntop(SOCKADDR_FAMILY(le->from), SOCKADDR_IN_ADDR(le->from), buffer, sizeof(buffer)) ); } #else lo->from = make_shared_string( inet_ntoa(*SOCKADDR_IN_ADDR(le->from)) ); #endif push_object( o ); }
static rc_vchar_t * natt_create_hash(isakmp_index_t *index, struct sockaddr *addr, int use_spi_r) { rc_vchar_t *hash; rc_vchar_t *buf; char *ptr; void *addr_ptr, *addr_port; size_t buf_size, addr_size; switch (SOCKADDR_FAMILY(addr)) { case AF_INET: addr_size = sizeof(struct in_addr); addr_ptr = &((struct sockaddr_in *)addr)->sin_addr; addr_port = &((struct sockaddr_in *)addr)->sin_port; break; #ifdef INET6 case AF_INET6: addr_size = sizeof(struct in6_addr); addr_ptr = &((struct sockaddr_in6 *)addr)->sin6_addr; addr_port = &((struct sockaddr_in6 *)addr)->sin6_port; break; #endif default: plog(PLOG_PROTOERR, PLOGLOC, NULL, "Unsupported address family %d\n", addr->sa_family); return NULL; } buf_size = 2 * sizeof(isakmp_cookie_t); buf_size += addr_size + 2; /* address + port */ if ((buf = rc_vmalloc(buf_size)) == NULL) { plog(PLOG_INTERR, PLOGLOC, NULL, "failed to rc_vmalloc in natt_create_hash\n"); return NULL; } ptr = buf->v; memcpy(ptr, &index->i_ck, sizeof(isakmp_cookie_t)); ptr += sizeof(isakmp_cookie_t); if (use_spi_r) { memcpy(ptr, &index->r_ck, sizeof(isakmp_cookie_t)); } ptr += sizeof(isakmp_cookie_t); memcpy(ptr, addr_ptr, addr_size); ptr += addr_size; memcpy(ptr, addr_port, 2); hash = eay_sha1_one(buf); rc_vfree(buf); return hash; }
static void send_keepalive_msg(void) { XdmcpHeader header; int socketfd = xdmcpSocket; header.version = XDM_PROTOCOL_VERSION; header.opcode = (CARD16) KEEPALIVE; header.length = 6; XdmcpWriteHeader(&buffer, &header); XdmcpWriteCARD16(&buffer, DisplayNumber); XdmcpWriteCARD32(&buffer, SessionID); state = XDM_AWAIT_ALIVE_RESPONSE; #if defined(IPv6) && defined(AF_INET6) if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) socketfd = xdmcpSocket6; #endif XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen); }
static void send_manage_msg(void) { XdmcpHeader header; int socketfd = xdmcpSocket; header.version = XDM_PROTOCOL_VERSION; header.opcode = (CARD16) MANAGE; header.length = 8 + DisplayClass.length; if (!XdmcpWriteHeader(&buffer, &header)) return; XdmcpWriteCARD32(&buffer, SessionID); XdmcpWriteCARD16(&buffer, DisplayNumber); XdmcpWriteARRAY8(&buffer, &DisplayClass); state = XDM_AWAIT_MANAGE_RESPONSE; #if defined(IPv6) && defined(AF_INET6) if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) socketfd = xdmcpSocket6; #endif XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen); }
void XdmcpRegisterConnection(int type, const char *address, int addrlen) { int i; CARD8 *newAddress; if (xdmcpGeneration != serverGeneration) { XdmcpDisposeARRAY16(&ConnectionTypes); XdmcpDisposeARRAYofARRAY8(&ConnectionAddresses); xdmcpGeneration = serverGeneration; } if (xdm_from != NULL) { /* Only register the requested address */ const void *regAddr = address; const void *fromAddr = NULL; int regAddrlen = addrlen; if (addrlen == sizeof(struct in_addr)) { if (SOCKADDR_FAMILY(FromAddress) == AF_INET) { fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr; } #if defined(IPv6) && defined(AF_INET6) else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) && IN6_IS_ADDR_V4MAPPED(& ((struct sockaddr_in6 *) &FromAddress)->sin6_addr)) { fromAddr = &((struct sockaddr_in6 *) &FromAddress)->sin6_addr. s6_addr[12]; } #endif } #if defined(IPv6) && defined(AF_INET6) else if (addrlen == sizeof(struct in6_addr)) { if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) { fromAddr = &((struct sockaddr_in6 *) &FromAddress)->sin6_addr; } else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) && IN6_IS_ADDR_V4MAPPED((const struct in6_addr *) address)) { fromAddr = &((struct sockaddr_in *) &FromAddress)->sin_addr; regAddr = &((struct sockaddr_in6 *) &address)->sin6_addr.s6_addr[12]; regAddrlen = sizeof(struct in_addr); } } #endif if (!fromAddr || memcmp(regAddr, fromAddr, regAddrlen) != 0) { return; } } if (ConnectionAddresses.length + 1 == 256) return; newAddress = malloc(addrlen * sizeof(CARD8)); if (!newAddress) return; if (!XdmcpReallocARRAY16(&ConnectionTypes, ConnectionTypes.length + 1)) { free(newAddress); return; } if (!XdmcpReallocARRAYofARRAY8(&ConnectionAddresses, ConnectionAddresses.length + 1)) { free(newAddress); return; } ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type; for (i = 0; i < addrlen; i++) newAddress[i] = address[i]; ConnectionAddresses.data[ConnectionAddresses.length - 1].data = newAddress; ConnectionAddresses.data[ConnectionAddresses.length - 1].length = addrlen; }
static void send_request_msg(void) { XdmcpHeader header; int length; int i; CARD16 XdmcpConnectionType; ARRAY8 authenticationData; int socketfd = xdmcpSocket; switch (SOCKADDR_FAMILY(ManagerAddress)) { case AF_INET: XdmcpConnectionType = FamilyInternet; break; #if defined(IPv6) && defined(AF_INET6) case AF_INET6: XdmcpConnectionType = FamilyInternet6; break; #endif default: XdmcpConnectionType = 0xffff; break; } header.version = XDM_PROTOCOL_VERSION; header.opcode = (CARD16) REQUEST; length = 2; /* display number */ length += 1 + 2 * ConnectionTypes.length; /* connection types */ length += 1; /* connection addresses */ for (i = 0; i < ConnectionAddresses.length; i++) length += 2 + ConnectionAddresses.data[i].length; authenticationData.length = 0; authenticationData.data = 0; if (AuthenticationFuncs) { (*AuthenticationFuncs->Generator) (AuthenticationData, &authenticationData, REQUEST); } length += 2 + AuthenticationName->length; /* authentication name */ length += 2 + authenticationData.length; /* authentication data */ length += 1; /* authorization names */ for (i = 0; i < AuthorizationNames.length; i++) length += 2 + AuthorizationNames.data[i].length; length += 2 + ManufacturerDisplayID.length; /* display ID */ header.length = length; if (!XdmcpWriteHeader(&buffer, &header)) { XdmcpDisposeARRAY8(&authenticationData); return; } XdmcpWriteCARD16(&buffer, DisplayNumber); XdmcpWriteCARD8(&buffer, ConnectionTypes.length); /* The connection array is send reordered, so that connections of */ /* the same address type as the XDMCP manager connection are send */ /* first. This works around a bug in xdm. [email protected] */ for (i = 0; i < (int) ConnectionTypes.length; i++) if (ConnectionTypes.data[i] == XdmcpConnectionType) XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]); for (i = 0; i < (int) ConnectionTypes.length; i++) if (ConnectionTypes.data[i] != XdmcpConnectionType) XdmcpWriteCARD16(&buffer, ConnectionTypes.data[i]); XdmcpWriteCARD8(&buffer, ConnectionAddresses.length); for (i = 0; i < (int) ConnectionAddresses.length; i++) if ((i < ConnectionTypes.length) && (ConnectionTypes.data[i] == XdmcpConnectionType)) XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]); for (i = 0; i < (int) ConnectionAddresses.length; i++) if ((i >= ConnectionTypes.length) || (ConnectionTypes.data[i] != XdmcpConnectionType)) XdmcpWriteARRAY8(&buffer, &ConnectionAddresses.data[i]); XdmcpWriteARRAY8(&buffer, AuthenticationName); XdmcpWriteARRAY8(&buffer, &authenticationData); XdmcpDisposeARRAY8(&authenticationData); XdmcpWriteARRAYofARRAY8(&buffer, &AuthorizationNames); XdmcpWriteARRAY8(&buffer, &ManufacturerDisplayID); #if defined(IPv6) && defined(AF_INET6) if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6) socketfd = xdmcpSocket6; #endif if (XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen)) state = XDM_AWAIT_REQUEST_RESPONSE; }
static void send_query_msg(void) { XdmcpHeader header; Bool broadcast = FALSE; #if defined(IPv6) && defined(AF_INET6) Bool multicast = FALSE; #endif int i; int socketfd = xdmcpSocket; header.version = XDM_PROTOCOL_VERSION; switch (state) { case XDM_QUERY: header.opcode = (CARD16) QUERY; state = XDM_COLLECT_QUERY; break; case XDM_BROADCAST: header.opcode = (CARD16) BROADCAST_QUERY; state = XDM_COLLECT_BROADCAST_QUERY; broadcast = TRUE; break; #if defined(IPv6) && defined(AF_INET6) case XDM_MULTICAST: header.opcode = (CARD16) BROADCAST_QUERY; state = XDM_COLLECT_MULTICAST_QUERY; multicast = TRUE; break; #endif case XDM_INDIRECT: header.opcode = (CARD16) INDIRECT_QUERY; state = XDM_COLLECT_INDIRECT_QUERY; break; default: break; } header.length = 1; for (i = 0; i < AuthenticationNames.length; i++) header.length += 2 + AuthenticationNames.data[i].length; XdmcpWriteHeader(&buffer, &header); XdmcpWriteARRAYofARRAY8(&buffer, &AuthenticationNames); if (broadcast) { for (i = 0; i < NumBroadcastAddresses; i++) XdmcpFlush(xdmcpSocket, &buffer, (XdmcpNetaddr) &BroadcastAddresses[i], sizeof(struct sockaddr_in)); } #if defined(IPv6) && defined(AF_INET6) else if (multicast) { struct multicastinfo *mcl; struct addrinfo *ai; for (mcl = mcastlist; mcl != NULL; mcl = mcl->next) { for (ai = mcl->ai; ai != NULL; ai = ai->ai_next) { if (ai->ai_family == AF_INET) { unsigned char hopflag = (unsigned char) mcl->hops; socketfd = xdmcpSocket; setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL, &hopflag, sizeof(hopflag)); } else if (ai->ai_family == AF_INET6) { int hopflag6 = mcl->hops; socketfd = xdmcpSocket6; setsockopt(socketfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hopflag6, sizeof(hopflag6)); } else { continue; } XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) ai->ai_addr, ai->ai_addrlen); break; } } } #endif else { #if defined(IPv6) && defined(AF_INET6) if (SOCKADDR_FAMILY(ManagerAddress) == AF_INET6) socketfd = xdmcpSocket6; #endif XdmcpFlush(socketfd, &buffer, (XdmcpNetaddr) &ManagerAddress, ManagerAddressLen); } }
/* send packet, with fixing src/dst address pair. */ int sendfromto(int s, const void *buf, size_t buflen, struct sockaddr *src, struct sockaddr *dst, int cnt) { struct sockaddr_storage ss; socklen_t sslen; int len = 0, i; extern struct rcf_interface *rcf_interface_head; if (cnt <= 0) { TRACE((PLOGLOC, "cnt: %d\n", cnt)); return 0; } if (src->sa_family != dst->sa_family) { plog(PLOG_INTERR, PLOGLOC, NULL, "address family mismatch\n"); return -1; } memset(&ss, 0, sizeof(ss)); sslen = sizeof(ss); if (getsockname(s, (struct sockaddr *)&ss, &sslen) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "getsockname (%s)\n", strerror(errno)); return -1; } plog(PLOG_DEBUG, PLOGLOC, NULL, "sockname %s\n", rcs_sa2str((struct sockaddr *)&ss)); plog(PLOG_DEBUG, PLOGLOC, NULL, "send packet from %s\n", rcs_sa2str(src)); plog(PLOG_DEBUG, PLOGLOC, NULL, "send packet to %s\n", rcs_sa2str(dst)); if (src->sa_family != SOCKADDR_FAMILY(&ss)) { plog(PLOG_INTERR, PLOGLOC, NULL, "address family mismatch\n"); return -1; } switch (src->sa_family) { #if defined(INET6) && defined(ADVAPI) && !defined(IPV6_INRIA_VERSION) case AF_INET6: { struct msghdr m; struct cmsghdr *cm; struct iovec iov[2]; unsigned char cmsgbuf[256]; struct in6_pktinfo *pi; int ifindex; struct sockaddr_in6 src6, dst6; memcpy(&src6, src, sizeof(src6)); memcpy(&dst6, dst, sizeof(dst6)); /* XXX take care of other cases, such as site-local */ ifindex = 0; if (IN6_IS_ADDR_LINKLOCAL(&src6.sin6_addr) || IN6_IS_ADDR_MULTICAST(&src6.sin6_addr)) { ifindex = src6.sin6_scope_id; /*??? */ } /* XXX some sanity check on dst6.sin6_scope_id */ /* flowinfo for IKE? mmm, maybe useful but for now make it 0 */ src6.sin6_flowinfo = dst6.sin6_flowinfo = 0; memset(&m, 0, sizeof(m)); m.msg_name = (caddr_t)&dst6; m.msg_namelen = sizeof(dst6); iov[0].iov_base = (char *)buf; iov[0].iov_len = buflen; m.msg_iov = iov; m.msg_iovlen = 1; memset(cmsgbuf, 0, sizeof(cmsgbuf)); cm = (struct cmsghdr *)cmsgbuf; m.msg_control = (caddr_t)cm; m.msg_controllen = CMSG_SPACE(sizeof(struct in6_pktinfo)); cm->cmsg_len = CMSG_LEN(sizeof(struct in6_pktinfo)); cm->cmsg_level = IPPROTO_IPV6; cm->cmsg_type = IPV6_PKTINFO; pi = (struct in6_pktinfo *)CMSG_DATA(cm); memcpy(&pi->ipi6_addr, &src6.sin6_addr, sizeof(src6.sin6_addr)); pi->ipi6_ifindex = ifindex; plog(PLOG_DEBUG, PLOGLOC, NULL, "src6 %s %d\n", rcs_sa2str((struct sockaddr *)&src6), src6.sin6_scope_id); plog(PLOG_DEBUG, PLOGLOC, NULL, "dst6 %s %d\n", rcs_sa2str((struct sockaddr *)&dst6), dst6.sin6_scope_id); for (i = 0; i < cnt; i++) { len = sendmsg(s, &m, 0 /*MSG_DONTROUTE */ ); if (len < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "sendmsg (%s)\n", strerror(errno)); return -1; } plog(PLOG_DEBUG, PLOGLOC, NULL, "%d times of %d bytes message will be sent " "to %s\n", i + 1, len, rcs_sa2str(dst)); } plogdump(PLOG_DEBUG, PLOGLOC, 0, (char *)buf, buflen); return len; } #endif default: { int needclose = 0; int sendsock; if (rcs_cmpsa((struct sockaddr *)&ss, src) == 0) { sendsock = s; needclose = 0; } else { int yes = 1; /* * Use newly opened socket for sending packets. * NOTE: this is unsafe, because if the peer is quick enough * the packet from the peer may be queued into sendsock. * Better approach is to prepare bind'ed udp sockets for * each of the interface addresses. */ sendsock = socket(src->sa_family, SOCK_DGRAM, 0); if (sendsock < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "socket (%s)\n", strerror(errno)); return -1; } #ifdef SO_REUSEPORT if (setsockopt(sendsock, SOL_SOCKET, SO_REUSEPORT, (void *)&yes, sizeof(yes)) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "setsockopt (%s)\n", strerror(errno)); close(sendsock); return -1; } #else #ifdef SO_REUSEADDR if (setsockopt(sendsock, SOL_SOCKET, SO_REUSEADDR, (void *)&yes, sizeof(yes)) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "setsockopt (%s)\n", strerror(errno)); close(sendsock); return -1; } #else #error #endif #endif #ifdef IPV6_USE_MIN_MTU if (src->sa_family == AF_INET6 && setsockopt(sendsock, IPPROTO_IPV6, IPV6_USE_MIN_MTU, (void *)&yes, sizeof(yes)) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "setsockopt (%s)\n", strerror(errno)); close(sendsock); return -1; } #endif if (rcf_interface_head->application_bypass != RCT_BOOL_OFF && setsockopt_bypass(sendsock, src->sa_family) < 0) { close(sendsock); return -1; } if (bind (sendsock, (struct sockaddr *)src, SOCKADDR_LEN(src)) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "bind 1 (%s)\n", strerror(errno)); close(sendsock); return -1; } needclose = 1; } for (i = 0; i < cnt; i++) { #ifdef DEBUG extern uint32_t debug_send; static int send_count = 0; if (debug_send & (1 << (send_count++ % 32))) { /* simulate a network packet drop */ TRACE((PLOGLOC, "debug_send %d drop\n", send_count)); len = buflen; } else #endif len = sendto(sendsock, buf, buflen, 0, dst, SOCKADDR_LEN(dst)); if (len < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "sendto (%s)\n", strerror(errno)); if (needclose) close(sendsock); return len; } plog(PLOG_DEBUG, PLOGLOC, NULL, "%d times of %d bytes message will be sent " "to %s\n", i + 1, len, rcs_sa2str(dst)); } plogdump(PLOG_DEBUG, PLOGLOC, 0, (char *)buf, buflen); if (needclose) close(sendsock); return len; } } }
/* * Receive packet, with src/dst information. It is assumed that necessary * setsockopt() have already performed on socket. */ int recvfromto(int s, void *buf, size_t buflen, int flags, struct sockaddr *from, int *fromlen, struct sockaddr *to, int *tolen) { int otolen; int len; socklen_t sslen; struct sockaddr_storage ss; struct msghdr m; struct cmsghdr *cm; struct iovec iov[2]; unsigned char cmsgbuf[256]; #if defined(INET6) && defined(ADVAPI) struct in6_pktinfo *pi; #endif /*ADVAPI*/ #ifdef INET6 struct sockaddr_in6 *sin6; #endif sslen = sizeof(ss); if (getsockname(s, (struct sockaddr *)&ss, &sslen) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "getsockname (%s)\n", strerror(errno)); return -1; } #if 1 /* quick hack */ memcpy(to, &ss, sslen < *tolen ? sslen : *tolen); #endif m.msg_name = (caddr_t)from; m.msg_namelen = *fromlen; iov[0].iov_base = (caddr_t)buf; iov[0].iov_len = buflen; m.msg_iov = iov; m.msg_iovlen = 1; memset(cmsgbuf, 0, sizeof(cmsgbuf)); cm = (struct cmsghdr *)cmsgbuf; m.msg_control = (caddr_t)cm; m.msg_controllen = sizeof(cmsgbuf); if ((len = recvmsg(s, &m, flags)) < 0) { plog(PLOG_INTERR, PLOGLOC, NULL, "recvmsg (%s)\n", strerror(errno)); return -1; } *fromlen = m.msg_namelen; otolen = *tolen; *tolen = 0; for (cm = (struct cmsghdr *)CMSG_FIRSTHDR(&m); m.msg_controllen != 0 && cm; cm = (struct cmsghdr *)CMSG_NXTHDR(&m, cm)) { #if 1 plog(PLOG_DEBUG, PLOGLOC, NULL, "cmsg %d %d\n", cm->cmsg_level, cm->cmsg_type); #endif #if defined(INET6) && defined(ADVAPI) if (SOCKADDR_FAMILY(&ss) == AF_INET6 && cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_PKTINFO && otolen >= (int)sizeof(*sin6)) { pi = (struct in6_pktinfo *)(CMSG_DATA(cm)); *tolen = sizeof(*sin6); sin6 = (struct sockaddr_in6 *)to; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; SET_SOCKADDR_LEN(sin6, sizeof(*sin6)); memcpy(&sin6->sin6_addr, &pi->ipi6_addr, sizeof(sin6->sin6_addr)); /* XXX other cases, such as site-local? */ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) sin6->sin6_scope_id = pi->ipi6_ifindex; else sin6->sin6_scope_id = 0; sin6->sin6_port = ((struct sockaddr_in6 *)&ss)->sin6_port; otolen = -1; /* "to" already set */ continue; } #endif #if defined(INET6) && defined(IPV6_RECVDSTADDR) if (ss.ss_family == AF_INET6 && cm->cmsg_level == IPPROTO_IPV6 && cm->cmsg_type == IPV6_RECVDSTADDR && otolen >= sizeof(*sin6)) { *tolen = sizeof(*sin6); sin6 = (struct sockaddr_in6 *)to; memset(sin6, 0, sizeof(*sin6)); sin6->sin6_family = AF_INET6; sin6->sin6_len = sizeof(*sin6); memcpy(&sin6->sin6_addr, CMSG_DATA(cm), sizeof(sin6->sin6_addr)); sin6->sin6_port = ((struct sockaddr_in6 *)&ss)->sin6_port; otolen = -1; /* "to" already set */ continue; } #endif #ifdef IP_RECVDSTADDR if (ss.ss_family == AF_INET && cm->cmsg_level == IPPROTO_IP && cm->cmsg_type == IP_RECVDSTADDR && otolen >= (int)sizeof(struct sockaddr_in)) { struct sockaddr_in *sin; *tolen = sizeof(*sin); sin = (struct sockaddr_in *)to; memset(sin, 0, sizeof(*sin)); sin->sin_family = AF_INET; sin->sin_len = sizeof(*sin); memcpy(&sin->sin_addr, CMSG_DATA(cm), sizeof(sin->sin_addr)); sin->sin_port = ((struct sockaddr_in *)&ss)->sin_port; otolen = -1; /* "to" already set */ continue; } #else #if defined(IP_PKTINFO) #else #error #endif #endif } return len; }
/*! @decl int bind(int|string port, void|function accept_callback, @ *! void|string ip, void|string reuse_port) *! *! Opens a socket and binds it to port number on the local machine. *! If the second argument is present, the socket is set to *! nonblocking and the callback funcition is called whenever *! something connects to it. The callback will receive the id for *! this port as argument and should typically call @[accept] to *! establish a connection. *! *! If the optional argument @[ip] is given, @[bind] will try to bind *! to an interface with that host name or IP number. Omitting this *! will bind to all available IPv4 addresses; specifying "::" will *! bind to all IPv4 and IPv6 addresses. *! *! If the OS supports TCP_FASTOPEN it is enabled automatically. *! *! If the OS supports SO_REUSEPORT it is enabled if the fourth argument is true. *! *! @returns *! 1 is returned on success, zero on failure. @[errno] provides *! further details about the error in the latter case. *! *! @seealso *! @[accept], @[set_id] */ static void port_bind(INT32 args) { struct port *p = THIS; PIKE_SOCKADDR addr; int addr_len,fd,tmp; do_close(p); if(args < 1) SIMPLE_WRONG_NUM_ARGS_ERROR("bind", 1); if(TYPEOF(Pike_sp[-args]) != PIKE_T_INT && (TYPEOF(Pike_sp[-args]) != PIKE_T_STRING || Pike_sp[-args].u.string->size_shift)) SIMPLE_ARG_TYPE_ERROR("bind", 1, "int|string(8bit)"); addr_len = get_inet_addr(&addr, (args > 2 && TYPEOF(Pike_sp[2-args])==PIKE_T_STRING? Pike_sp[2-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_STRING? Pike_sp[-args].u.string->str : NULL), (TYPEOF(Pike_sp[-args]) == PIKE_T_INT? Pike_sp[-args].u.integer : -1), 0); INVALIDATE_CURRENT_TIME(); fd=fd_socket(SOCKADDR_FAMILY(addr), SOCK_STREAM, 0); if(fd < 0) { p->my_errno=errno; pop_n_elems(args); push_int(0); return; } #ifdef SO_REUSEPORT if( args > 3 && Pike_sp[3-args].u.integer ) { /* FreeBSD 7.x wants this to reuse portnumbers. * Linux 2.6.x seems to have reserved a slot for the option, but not * enabled it. Survive libc's with the option on kernels without. * * The emulated Linux runtime on MS Windows 10 fails this with EINVAL. */ int o=1; if((fd_setsockopt(fd, SOL_SOCKET, SO_REUSEPORT, (char *)&o, sizeof(int)) < 0) #ifdef ENOPROTOOPT && (errno != ENOPROTOOPT) #endif #ifdef EINVAL && (errno != EINVAL) #endif #ifdef WSAENOPROTOOPT && (errno != WSAENOPROTOOPT) #endif ){ p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } } #endif #ifndef __NT__ { int o=1; if(fd_setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&o, sizeof(int)) < 0) { p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } } #endif #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6) if (SOCKADDR_FAMILY(addr) == AF_INET6) { /* Attempt to enable dual-stack (ie mapped IPv4 adresses). * Needed on WIN32. * cf http://msdn.microsoft.com/en-us/library/windows/desktop/bb513665(v=vs.85).aspx */ int o = 0; fd_setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, (char *)&o, sizeof(int)); } #endif my_set_close_on_exec(fd,1); THREADS_ALLOW_UID(); if( !(tmp=fd_bind(fd, (struct sockaddr *)&addr, addr_len) < 0) ) #ifdef TCP_FASTOPEN tmp = 256, setsockopt(fd,SOL_TCP, TCP_FASTOPEN, &tmp, sizeof(tmp)), #endif (tmp = fd_listen(fd, 16384) < 0); THREADS_DISALLOW_UID(); if(!Pike_fp->current_object->prog) { if (fd >= 0) while (fd_close(fd) && errno == EINTR) {} Pike_error("Object destructed in Stdio.Port->bind()\n"); } if(tmp) { p->my_errno=errno; while (fd_close(fd) && errno == EINTR) {} errno = p->my_errno; pop_n_elems(args); push_int(0); return; } change_fd_for_box (&p->box, fd); if(args > 1) assign_accept_cb (p, Pike_sp+1-args); p->my_errno=0; pop_n_elems(args); push_int(1); }
void f_aap_log_as_commonlog_to_file(INT32 args) { struct log_entry *le; struct log *l = LTHIS->log; int n = 0; int mfd, ot=0; struct object *f; struct tm tm; FILE *foo; static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Oct", "Sep", "Nov", "Dec", }; get_all_args("log_as_commonlog_to_file", args, "%o", &f); f->refs++; pop_n_elems(args); apply(f, "query_fd", 0); mfd = fd_dup(sp[-1].u.integer); if(mfd < 1)Pike_error("Bad fileobject to ->log_as_commonlog_to_file\n"); pop_stack(); foo = fdopen( mfd, "w" ); if(!foo) Pike_error("Bad fileobject to ->log_as_commonlog_to_file\n"); THREADS_ALLOW(); mt_lock( &l->log_lock ); le = l->log_head; l->log_head = l->log_tail = 0; mt_unlock( &l->log_lock ); while(le) { int i; struct tm *tm_p; struct log_entry *l = le->next; /* remotehost rfc931 authuser [date] "request" status bytes */ if(le->t != ot) { time_t t = (time_t)le->t; #ifdef HAVE_GMTIME_R gmtime_r( &t, &tm ); #else #ifdef HAVE_GMTIME tm_p = gmtime( &t ); /* This will break if two threads run gmtime() at once. */ #else #ifdef HAVE_LOCALTIME tm_p = localtime( &t ); /* This will break if two threads run localtime() at once. */ #endif #endif if (tm_p) tm = *tm_p; #endif ot = le->t; } /* date format: [03/Feb/1998:23:08:20 +0000] */ /* GET [URL] HTTP/1.0 */ for(i=13; i<le->raw.len; i++) if(le->raw.str[i] == '\r') { le->raw.str[i] = 0; break; } #ifdef HAVE_INET_NTOP if(SOCKADDR_FAMILY(le->from) != AF_INET) { char buffer[64]; fprintf(foo, "%s - %s [%02d/%s/%d:%02d:%02d:%02d +0000] \"%s\" %d %ld\n", inet_ntop(SOCKADDR_FAMILY(le->from), SOCKADDR_IN_ADDR(le->from), buffer, sizeof(buffer)), /* hostname */ "-", /* remote-user */ tm.tm_mday, month[tm.tm_mon], tm.tm_year+1900, tm.tm_hour, tm.tm_min, tm.tm_sec, /* date */ le->raw.str, /* request line */ le->reply, /* reply code */ DO_NOT_WARN((long)le->sent_bytes)); /* bytes transfered */ } else #endif /* HAVE_INET_NTOP */ fprintf(foo, "%d.%d.%d.%d - %s [%02d/%s/%d:%02d:%02d:%02d +0000] \"%s\" %d %ld\n", ((unsigned char *)&le->from.ipv4.sin_addr)[ 0 ], ((unsigned char *)&le->from.ipv4.sin_addr)[ 1 ], ((unsigned char *)&le->from.ipv4.sin_addr)[ 2 ], ((unsigned char *)&le->from.ipv4.sin_addr)[ 3 ], /* hostname */ "-", /* remote-user */ tm.tm_mday, month[tm.tm_mon], tm.tm_year+1900, tm.tm_hour, tm.tm_min, tm.tm_sec, /* date */ le->raw.str, /* request line */ le->reply, /* reply code */ DO_NOT_WARN((long)le->sent_bytes)); /* bytes transfered */ free_log_entry( le ); n++; le = l; } fclose(foo); fd_close(mfd); THREADS_DISALLOW(); push_int(n); }