123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- #include "stdafx.h"
- #include <string.h>
- #include <util/generic/utility.h>
- #include <util/network/init.h>
- #include <util/system/defaults.h>
- #include <util/system/yassert.h>
- #include "socket.h"
- namespace NNetlibaSocket {
- void* CreateTos(const ui8 tos, void* buffer) {
- #ifdef _win_
- *(int*)buffer = (int)tos;
- #else
- // glibc bug: http://sourceware.org/bugzilla/show_bug.cgi?id=13500
- memset(buffer, 0, TOS_BUFFER_SIZE);
- msghdr dummy;
- Zero(dummy);
- dummy.msg_control = buffer;
- dummy.msg_controllen = TOS_BUFFER_SIZE;
- // TODO: in FreeBSD setting TOS for dual stack sockets does not affect ipv4 frames
- cmsghdr* cmsg = CMSG_FIRSTHDR(&dummy);
- cmsg->cmsg_level = IPPROTO_IPV6;
- cmsg->cmsg_type = IPV6_TCLASS;
- cmsg->cmsg_len = CMSG_LEN(sizeof(int));
- memcpy(CMSG_DATA(cmsg), &tos, sizeof(tos)); // memcpy shut ups alias restrict warning
- Y_ASSERT(CMSG_NXTHDR(&dummy, cmsg) == nullptr);
- #endif
- return buffer;
- }
- TMsgHdr* AddSockAuxData(TMsgHdr* header, const ui8 tos, const sockaddr_in6& myAddr, void* buffer, size_t bufferSize) {
- #ifdef _win_
- Y_UNUSED(header);
- Y_UNUSED(tos);
- Y_UNUSED(myAddr);
- Y_UNUSED(buffer);
- Y_UNUSED(bufferSize);
- return nullptr;
- #else
- header->msg_control = buffer;
- header->msg_controllen = bufferSize;
- size_t totalLen = 0;
- #ifdef _cygwin_
- Y_UNUSED(tos);
- #else
- // Cygwin does not support IPV6_TCLASS, so we ignore it
- cmsghdr* cmsgTos = CMSG_FIRSTHDR(header);
- if (cmsgTos == nullptr) {
- header->msg_control = nullptr;
- header->msg_controllen = 0;
- return nullptr;
- }
- cmsgTos->cmsg_level = IPPROTO_IPV6;
- cmsgTos->cmsg_type = IPV6_TCLASS;
- cmsgTos->cmsg_len = CMSG_LEN(sizeof(int));
- totalLen = CMSG_SPACE(sizeof(int));
- *(ui8*)CMSG_DATA(cmsgTos) = tos;
- #endif
- if (*(ui64*)myAddr.sin6_addr.s6_addr != 0u) {
- in6_pktinfo* pktInfo;
- #ifdef _cygwin_
- cmsghdr* cmsgAddr = CMSG_FIRSTHDR(header);
- #else
- cmsghdr* cmsgAddr = CMSG_NXTHDR(header, cmsgTos);
- #endif
- if (cmsgAddr == nullptr) {
- // leave only previous record
- header->msg_controllen = totalLen;
- return nullptr;
- }
- cmsgAddr->cmsg_level = IPPROTO_IPV6;
- cmsgAddr->cmsg_type = IPV6_PKTINFO;
- cmsgAddr->cmsg_len = CMSG_LEN(sizeof(*pktInfo));
- totalLen += CMSG_SPACE(sizeof(*pktInfo));
- pktInfo = (in6_pktinfo*)CMSG_DATA(cmsgAddr);
- pktInfo->ipi6_addr = myAddr.sin6_addr;
- pktInfo->ipi6_ifindex = 0; /* 0 = use interface specified in routing table */
- }
- header->msg_controllen = totalLen; //write right len
- return header;
- #endif
- }
- TIoVec CreateIoVec(char* data, const size_t dataSize) {
- TIoVec result;
- Zero(result);
- result.iov_base = data;
- result.iov_len = dataSize;
- return result;
- }
- TMsgHdr CreateSendMsgHdr(const sockaddr_in6& addr, const TIoVec& iov, void* tosBuffer) {
- TMsgHdr result;
- Zero(result);
- result.msg_name = (void*)&addr;
- result.msg_namelen = sizeof(addr);
- result.msg_iov = (TIoVec*)&iov;
- result.msg_iovlen = 1;
- if (tosBuffer) {
- #ifdef _win_
- result.Tos = *(int*)tosBuffer;
- #else
- result.msg_control = tosBuffer;
- result.msg_controllen = TOS_BUFFER_SIZE;
- #endif
- }
- return result;
- }
- TMsgHdr CreateRecvMsgHdr(sockaddr_in6* addrBuf, const TIoVec& iov, void* controllBuffer) {
- TMsgHdr result;
- Zero(result);
- Zero(*addrBuf);
- result.msg_name = addrBuf;
- result.msg_namelen = sizeof(*addrBuf);
- result.msg_iov = (TIoVec*)&iov;
- result.msg_iovlen = 1;
- #ifndef _win_
- if (controllBuffer) {
- memset(controllBuffer, 0, CTRL_BUFFER_SIZE);
- result.msg_control = controllBuffer;
- result.msg_controllen = CTRL_BUFFER_SIZE;
- }
- #endif
- return result;
- }
- }
|