Posted by ddn on Thu 25 Sep 16:03
report abuse | download | new post
- // mcastrouter.cpp : compiled and tested under Windows Server 2008 + VS 2008
- #include <windows.h>
- #include <winsock2.h>
- #include <mstcpip.h>
- #include <ws2tcpip.h>
- #define MULTICASTPORT 5050
- #define INPUTMULTICAST_IF "192.168.100.4"
- #define OUTPUTMULTICAST_IF "172.16.20.3"
- struct iphdr {
- BYTE h_len:4;
- BYTE version:4;
- UCHAR iph_tos;
- USHORT iph_length;
- USHORT iph_id;
- USHORT iph_offset;
- UCHAR iph_ttl;
- UCHAR ip_p;
- USHORT iph_xsum;
- in_addr ip_src;
- in_addr ip_dst;
- }ip;
- struct udphdr
- {
- USHORT source;
- USHORT dest;
- USHORT len;
- USHORT check;
- };
- int _tmain(int argc, _TCHAR* argv[])
- {
- SOCKET inSock;
- SOCKET outSock;
- SOCKADDR_IN inSockAddr = {0};
- SOCKADDR_IN outSockAddr = {0};
- SOCKADDR_IN iface_addr = {0};
- fd_set rdSet;
- WSADATA data;
- WORD version;
- int ret;
- int siomode = 1;
- int dwBytesReturned;
- struct sockaddr_in saddr;
- socklen_t saddr_size = sizeof(saddr);
- char buf[2000];
- struct sockaddr_in sa;
- version = (MAKEWORD(2, 2));
- ret = WSAStartup(version, &data);
- if(ret != 0)
- {
- printf("WinSock not initialised");
- return 1;
- }
- inSock = WSASocket(AF_INET, SOCK_RAW, IPPROTO_UDP, NULL, 0, 0);
- outSock = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, NULL, 0, 0);
- inSockAddr.sin_family = AF_INET;
- inSockAddr.sin_addr.s_addr = inet_addr(INPUTMULTICAST_IF);
- inSockAddr.sin_port = htons(5555); //not used because of RAW socket I/O...
- ret = bind(inSock, (struct sockaddr*)&inSockAddr, sizeof(inSockAddr));
- if(ret == SOCKET_ERROR)
- {
- printf ("bind1() Err: %d\n", WSAGetLastError());
- return 1;
- }
- outSockAddr.sin_family = AF_INET;
- outSockAddr.sin_addr.s_addr = inet_addr(OUTPUTMULTICAST_IF);
- outSockAddr.sin_port = htons(5050); //faked, used in output UDP packets as "source port"
- ret = bind(outSock, (struct sockaddr*)&outSockAddr, sizeof(outSockAddr));
- if(ret == SOCKET_ERROR)
- {
- printf ("bind2() Err: %d\n", WSAGetLastError());
- return 1;
- }
- iface_addr.sin_addr.s_addr = inet_addr(OUTPUTMULTICAST_IF);
- ret = setsockopt(outSock, IPPROTO_IP, IP_MULTICAST_IF, (char *)&iface_addr, sizeof(iface_addr));
- if(ret == SOCKET_ERROR)
- {
- printf("setsockopt() IP_MULTICAST_IF address Err: %d\n", WSAGetLastError());
- return 1;
- }
- unsigned char ttl = 1;
- ret = setsockopt(outSock, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
- if(ret == SOCKET_ERROR)
- {
- printf("setsockopt() IP_MULTICAST_TTL address Err: %d\n", WSAGetLastError());
- return 1;
- }
- unsigned char loopback = 1;
- ret = setsockopt(inSock, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loopback, sizeof(loopback));
- if(ret == SOCKET_ERROR)
- {
- printf("setsockopt() IP_MULTICAST_LOOP address Err: %d\n", WSAGetLastError());
- return 1;
- }
- ret = WSAIoctl(inSock, SIO_RCVALL_MCAST, &siomode, sizeof(siomode), NULL, 0, (LPDWORD)&dwBytesReturned, NULL, NULL);
- if(ret == SOCKET_ERROR)
- {
- printf ("WSAIoctl() Err: %d\n", WSAGetLastError());
- return 1;
- }
- sa.sin_family = AF_INET;
- FD_ZERO(&rdSet);
- FD_SET(inSock, &rdSet);
- while(1)
- {
- if(select(0, &rdSet, NULL, NULL, NULL) == 1)
- {
- int packet_len = recvfrom(inSock, buf, sizeof(buf), 0, (struct sockaddr *)&saddr, &saddr_size);
- iphdr* hdr = (iphdr*)buf;
- if(hdr->ip_p == IPPROTO_UDP)
- {
- udphdr* hdr2 = (udphdr*)(buf+(hdr->h_len*4));
- memcpy((void *)&sa.sin_addr, (void *)&hdr->ip_dst, sizeof(in_addr));
- sa.sin_port = hdr2->dest;
- if(ntohs(hdr2->dest) == MULTICASTPORT)
- sendto(outSock, buf+((hdr->h_len*4)+sizeof(udphdr)), packet_len-(hdr->h_len*4)-sizeof(udphdr), 0, (struct sockaddr *)&sa, sizeof(sa));
- }
- }
- else {
- break;
- }
- }
- closesocket(outSock);
- closesocket(inSock);
- WSACleanup();
- return 0;
- }
Submit a correction or amendment below (click here to make a fresh posting)
After submitting an amendment, you'll be able to view the differences between the old and new posts easily.