BOOL ProcessIpv6Msg(LPWSAMSG pWSAMsg) { PWSACMSGHDR pCtrlInfo = NULL; PIN6_PKTINFO pPktInfo = NULL; pCtrlInfo = WSA_CMSG_FIRSTHDR(pWSAMsg); if ((IPPROTO_IPV6 == pCtrlInfo->cmsg_level) && (IPV6_PKTINFO == pCtrlInfo->cmsg_type)) { pPktInfo = (PIN6_PKTINFO)WSA_CMSG_DATA(pCtrlInfo); //do something with pPktInfo return TRUE; } return FALSE; }
int MDDSocket_Recvfrom(MDDSocket_t sockets, unsigned char *buf, int buf_len, MDDSocketAddr_t *from, MDDIface_t *iface) { struct sockaddr_in sa; struct sockaddr_in6 sa6; WSAMSG msg; WSABUF io; char aux[1024]; DWORD recv_len = 0; if (sockets == INVALID_SOCKET) { return MDD_ERROR; } io.buf = (CHAR *)buf; io.len = buf_len; SecureZeroMemory (&msg, sizeof(msg)); msg.lpBuffers = &io; msg.dwBufferCount = 1; msg.dwFlags = 0; msg.Control.buf = aux; msg.Control.len = sizeof(aux); if (from->family == MDDNet_INET) { msg.name = (LPSOCKADDR)&sa; msg.namelen = sizeof(sa); } else if (from->family == MDDNet_INET6) { msg.name = (LPSOCKADDR)&sa6; msg.namelen = sizeof(sa6); } else { LOG_ERROR("MDDSocket_Recvfrom error, need to specific family on from address\n"); return MDD_ERROR; } if (SOCKET_ERROR == fpWSARecvMsg(sockets, &msg, &recv_len, NULL, NULL)) { if (WSAGetLastError() != WSAEWOULDBLOCK) { LOG_ERROR("MDDSocket_Recvfrom fatal error, error: %d\n", WSAGetLastError()); return MDD_ERROR; } return 0; } else { WSACMSGHDR *cmsg; if (from->family == MDDNet_INET) { from->port = sa.sin_port; from->addr.ip.ipv4 = (unsigned long int)sa.sin_addr.s_addr; } else if (from->family == MDDNet_INET6) { from->port = sa6.sin6_port; memcpy(from->addr.ip.ipv6, sa6.sin6_addr.u.Word, 16); } for (cmsg = WSA_CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = WSA_CMSG_NXTHDR(&msg, cmsg)) { if (cmsg->cmsg_level == IPPROTO_IP) { switch (cmsg->cmsg_type) { case IP_TTL: LOG_TRACE("MDDSocket_Recvfrom got ttl: %d\n", (*(int *) WSA_CMSG_DATA(cmsg))); break; case IP_PKTINFO: { PIN_PKTINFO i = (PIN_PKTINFO) WSA_CMSG_DATA(cmsg); LOG_TRACE("MDDSocket_Recvfrom got ifindex: %d\n", i->ipi_ifindex); if (iface != NULL) { iface->ifindex = i->ipi_ifindex; iface->addr.family = MDDNet_INET; iface->addr.ip.ipv4 = i->ipi_addr.S_un.S_addr; } break; } default: LOG_DEBUG("Unhandled cmsg_type: %d", cmsg->cmsg_type); break; } } else if (cmsg->cmsg_level == IPPROTO_IPV6) { switch (cmsg->cmsg_type) { case IPV6_HOPLIMIT: LOG_TRACE("MDDSocket_Recvfrom got ttl: %d\n", (*(int *) WSA_CMSG_DATA(cmsg))); break; case IPV6_PKTINFO: { PIN6_PKTINFO i = (PIN6_PKTINFO) WSA_CMSG_DATA(cmsg); LOG_TRACE("MDDSocket_Recvfrom got ifindex: %d\n", i->ipi6_ifindex); if (iface != NULL) { iface->ifindex = i->ipi6_ifindex; iface->addr.family = MDDNet_INET6; memcpy(iface->addr.ip.ipv6, i->ipi6_addr.u.Byte, 16); } break; } default: LOG_DEBUG("Unhandled cmsg_type: %d", cmsg->cmsg_type); break; } } } LOG_TRACE("MDDSocket_Recvfrom recv_len: %d\n", recv_len); return recv_len; } }
int MDDSocket_Sendto(MDDSocket_t socket, unsigned char *buf, int buf_len, MDDSocketAddr_t *to, MDDIface_t *iface) { struct sockaddr_in sa; struct sockaddr_in6 sa6; WSAMSG msg; WSABUF io; DWORD sent_len = 0; INT nRet = 0; if (socket == INVALID_SOCKET) { return MDD_ERROR; } SecureZeroMemory(&io, sizeof(io)); io.buf = (char *)buf; io.len = buf_len; SecureZeroMemory (&msg, sizeof(msg)); msg.lpBuffers = &io; msg.dwBufferCount = 1; msg.dwFlags = 0; if (to->family == MDDNet_INET) { memset(&sa, 0, sizeof(sa)); sa.sin_family = AF_INET; sa.sin_port = to->port; sa.sin_addr.s_addr = to->addr.ip.ipv4; msg.name = (LPSOCKADDR)(&sa); msg.namelen = sizeof(sa); } else if (to->family == MDDNet_INET6) { memset(&sa6, 0, sizeof(sa6)); sa6.sin6_family = AF_INET6; sa6.sin6_port = to->port; memcpy(sa6.sin6_addr.s6_addr, to->addr.ip.ipv6, 16); msg.name = (LPSOCKADDR)(&sa6); msg.namelen = sizeof(sa6); } else { return MDD_ERROR; } if (iface != NULL && iface->ifindex > 0) { if (to->family == MDDNet_INET) { PIN_PKTINFO pkti; WSACMSGHDR *cmsg; char in[WSA_CMSG_SPACE(sizeof(struct in_pktinfo))]; int sum = 0; memset(in, 0, sizeof(in)); msg.Control.buf = (char *)∈ msg.Control.len = sizeof(in); cmsg = WSA_CMSG_FIRSTHDR(&msg); memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in_pktinfo))); cmsg->cmsg_level = IPPROTO_IP; cmsg->cmsg_type = IP_PKTINFO; cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in_pktinfo)); pkti = (PIN_PKTINFO) WSA_CMSG_DATA(cmsg); if (iface->ifindex > 0) { pkti->ipi_ifindex = iface->ifindex; pkti->ipi_addr.S_un.S_addr = iface->addr.ip.ipv4; // [email protected], 2012/07/24, workaround to resolve can't sent in release mode. DO NOT remove this printf until find solution printf(""); } sum += WSA_CMSG_SPACE(sizeof(struct in_pktinfo)); msg.Control.len = sum; } else if (to->family == MDDNet_INET6) { PIN6_PKTINFO pkti; WSACMSGHDR *cmsg; char in[WSA_CMSG_SPACE(sizeof(struct in6_pktinfo))]; int sum = 0; memset(in, 0, sizeof(in)); msg.Control.buf = (char *)∈ msg.Control.len = sizeof(in); cmsg = WSA_CMSG_FIRSTHDR(&msg); memset(cmsg, 0, WSA_CMSG_SPACE(sizeof(struct in6_pktinfo))); cmsg->cmsg_level = IPPROTO_IPV6; cmsg->cmsg_type = IPV6_PKTINFO; cmsg->cmsg_len = WSA_CMSG_LEN(sizeof(struct in6_pktinfo)); pkti = (PIN6_PKTINFO) WSA_CMSG_DATA(cmsg); if (iface->ifindex > 0) { pkti->ipi6_ifindex = iface->ifindex; memcpy(&pkti->ipi6_addr.u.Byte, iface->addr.ip.ipv6, 16); // [email protected], 2012/07/24, workaround to resolve can't sent in release mode. DO NOT remove this printf until find solution printf(""); } sum += WSA_CMSG_SPACE(sizeof(struct in6_pktinfo)); msg.Control.len = sum; } } if (SOCKET_ERROR == (nRet = fpWSASendMsg(socket, &msg, 0, &sent_len, NULL, NULL))) { LOG_ERROR("MDDSocket_Sendto by WSASendMsg error %d\n", WSAGetLastError()); return MDD_ERROR; } else { return sent_len; } }