/** * DNS: Sends a standard DNS-query (read request package) to a DNS-server. * DNS-server respones with host IP or signals some error condition. * Responses from the server are handled by handle_dns function. * * @param fd socket descriptor * @param domain_name the domain name given as series of labels preceded * with length(label) and terminated with 0 * <br>(e.g. "\3,w,w,w,\4,h,o,s,t,\3,o,r,g,\0") * @see handle_dns */ static void dns_send_query(int fd, int8_t * domain_name, uint8_t ip_version) { int qry_len = strlen((char *) domain_name) + 5; int iphdr_len = (ip_version == 4) ? sizeof(struct iphdr) : sizeof(struct ip6hdr); ip6_addr_t server_ipv6; uint32_t packetsize = iphdr_len + sizeof(struct udphdr) + sizeof(struct dnshdr) + qry_len; memset(ether_packet, 0, packetsize); fill_dnshdr(ðer_packet[ iphdr_len + sizeof(struct udphdr)], domain_name, ip_version); fill_udphdr(ðer_packet[iphdr_len], sizeof(struct dnshdr) + sizeof(struct udphdr) + qry_len, UDPPORT_DNSC, UDPPORT_DNSS); if (ip_version == 4) { fill_iphdr(ether_packet, sizeof(struct dnshdr) + sizeof(struct udphdr) + iphdr_len + qry_len, IPTYPE_UDP, 0, dns_server_ip); } else { memcpy(server_ipv6.addr, dns_server_ipv6, 16); fill_ip6hdr(ether_packet, sizeof(struct dnshdr) + sizeof(struct udphdr) + qry_len, IPTYPE_UDP, get_ipv6_address(), &server_ipv6); } send_ip(fd, ether_packet, packetsize); }
std::set<boost::asio::ip::address> getlist() { std::set<boost::asio::ip::address> result; struct nlmsg_list *linfo = NULL; struct nlmsg_list *ainfo = NULL; struct rtnl_handle rth; if (rtnl_open(&rth, 0) < 0) { std::cout << "rtnl_open failed\n"; return result; } if (rtnl_wilddump_request(&rth, AF_INET6, RTM_GETLINK) < 0) { std::cout << "cannot send dump request\n"; rtnl_close(&rth); return result; } if (rtnl_dump_filter(&rth, &store_nlmsg, &linfo, NULL, NULL) < 0) { std::cout << "dump terminated\n"; rtnl_close(&rth); return result; } if (rtnl_wilddump_request(&rth, AF_INET6, RTM_GETADDR) < 0) { std::cout << "cannot send dump request\n"; rtnl_close(&rth); return result; } if (rtnl_dump_filter(&rth, &store_nlmsg, &ainfo, NULL, NULL) < 0) { std::cout << "dump terminated\n"; rtnl_close(&rth); return result; } { struct nlmsg_list **lp; lp=&linfo; nlmsg_list* l; while ((l=*lp)!=NULL) { int ok = 0; struct ifinfomsg *ifi = (struct ifinfomsg *)NLMSG_DATA(&l->h); struct nlmsg_list *a; for (a=ainfo; a; a=a->next) { struct nlmsghdr *n = &a->h; struct ifaddrmsg *ifa = (struct ifaddrmsg *)NLMSG_DATA(n); /* NOTE: ifi_index and ifa_index should have the same type (int), but for * some reason they are not... So instead of a normal (in)equality comparison * we do a bit-wise compare. */ if (ifi->ifi_index ^ ifa->ifa_index) continue; if (ifa->ifa_family != AF_INET6) continue; ok = 1; break; } if (!ok) *lp = l->next; else lp = &l->next; } } for (nlmsg_list* l=linfo; l; l = l->next) { for (nlmsg_list* a=ainfo; a; a = a->next) { boost::asio::ip::address_v6 addr = get_ipv6_address(&l->h, &a->h); if (!addr.is_unspecified() && !addr.is_loopback()) result.insert(addr); } } rtnl_close(&rth); for (nlmsg_list* l=linfo; l; ) { nlmsg_list* o = l; l = l->next; free(o); } for (nlmsg_list* a=ainfo; a; ) { nlmsg_list* o = a; a = a->next; free(o); } return result; }
void *Reflector(void *threadarg) { int ioctl_s; struct thread_data *my_data; my_data = (struct thread_data *)threadarg; struct in_addr multicastaddress_in; //IPv4 multicast address from command line struct in_addr multicastaddress_out; struct sockaddr_in6 tmp_saddr6; struct ifreq ifr; struct ipaddr_str buf; int mcdataport4; //IPv4 multicast port 1 int mcdataport; //IPv4 multicast port 2 /*define variables*/ int mcdatarecvfd4; //multicast data receive socket side 1 int mcdatarecvfd; //multicast data receive socket side 2 int sendfd4; //local send socket IPv4 side 1 int sendfd; //local send socket IPv4 side 2 int ttl1; //time to live IPv4 side 1 int ttl2; //time to live IPv4 side 2 struct sockaddr_in mcdataaddr4; //reception IPv4 sockaddr struct sockaddr_in mcdataaddr; //reception IPv44 sockaddr char myhostnameipaddress4[20]; // IPv4 reflector's address string char myhostnameipaddress[20]; // IPv44 reflector's address string char addressstring4[20]; // IPv4 address string char addressstring[20]; // IPv44 address string struct sockaddr_in localsendaddr4; //IPv4 address of outgoing packets interface 1 struct sockaddr_in localsendaddr; //IPv4 address of outgoing packets interface 2 struct sockaddr_in sourceaddr4; //IPv4 address of incoming packets interface 1 struct sockaddr_in sourceaddr; //IPv4 address of incoming packets interface 2 struct ip_mreq mcdatareq4; //IPv4 join group structure struct ip_mreq mcdatareq; //IPv44 join group structure int mcdataaddrlen; //IPv4 multicast address length unsigned int sourceaddrlen; //IPv4 source address length char mcdatarecvbuf4[MSGBUF_SIZE]; //IPv4 multicast receive buffer char mcdatarecvbuf[MSGBUF_SIZE]; //IPv44 multicast receive buffer fd_set readfds; // file descriptors set int maxfds; // max number of file descriptors int nfds; int nr; // number of bytes read with recvfrom int ns; // number of bytes sent with sendto int chksrc; // asserts if source address is not the reflector's one int debugon=1; int n2; char inputbuf[32]; /* IPv4 multicast address */ if((inet_pton(AF_INET,my_data->multicast_addr1,&multicastaddress_in.s_addr))!=1){ printf("bad multicast IPv4 address format\n"); exit (1); } //printf("multicastaddress side 1 v4 =%s\n",my_data->multicast_addr1); /* IPv4 multicast address */ if((inet_pton(AF_INET,my_data->multicast_addr2,&multicastaddress_out.s_addr))!=1){ printf("bad multicast IPv4 address format\n"); exit (1); } //printf("multicastaddress side 2 v4 =%s\n",my_data->multicast_addr2); /* IPv4 multicast ports */ mcdataport4 = my_data->port1; mcdataport = my_data->port2; /* Time to live for IPv4 multicast */ ttl1 = my_data->ttl1; /* Time to live for IPv4 multicast */ ttl2 = my_data->ttl2; IP_VERSION=4; if (IP_VERSION==4 )// { ioctl_s = socket(AF_INET, SOCK_DGRAM, 0); if (ioctl_s < 0) { syslog(LOG_ERR, "ioctl socket: %m"); exit (0); } /* INTERFACE 1 */ memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, my_data->interface1, IFNAMSIZE); /* Check interface address (IPv4) */ if(ioctl(ioctl_s, SIOCGIFADDR, &ifr) < 0) { printf( "\tCould not get address of interface 1 - removing it\n"); exit(0); } sockaddr4_to_string(&myhostnameipaddress4, &ifr.ifr_addr); /* INTERFACE 2 */ memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, my_data->interface2, IFNAMSIZE); /* Check interface address (IPv4) */ if(ioctl(ioctl_s, SIOCGIFADDR, &ifr) < 0) { printf( "\tCould not get address of interface 2 - removing it\n"); exit(0); } sockaddr4_to_string(&myhostnameipaddress, &ifr.ifr_addr); } else { /* Global address mode */ int ipv6_addrtype = 0; /* global */ /* Get IPV6 GLOBAL interface address */ memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, my_data->interface2, IFNAMSIZE); if(get_ipv6_address(ifr.ifr_name, &tmp_saddr6, ipv6_addrtype ) <= 0) { printf( "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name); } memset(&ifr, 0, sizeof(struct ifreq)); strncpy(ifr.ifr_name, my_data->interface2, IFNAMSIZE); // printf("\n Adding interface : %s \n", my_data->interface2); /* Get IPV6 GLOBAL interface address */ if(get_ipv6_address(ifr.ifr_name, &tmp_saddr6, ipv6_addrtype ) <= 0) { printf( "\tCould not find site-local IPv6 address for %s\n", ifr.ifr_name); } } /* Structures initialization */ /*enter the address/port data into the mcdataaddr structure for IPv4*/ bzero((char *) &mcdataaddr4, sizeof(mcdataaddr4)); mcdataaddr4.sin_family=AF_INET; mcdataaddr4.sin_addr.s_addr = multicastaddress_in.s_addr; mcdataaddr4.sin_port = htons(mcdataport4); /*enter the address/port data into the mcdataaddr structure for IPv4*/ bzero((char *) &mcdataaddr, sizeof(mcdataaddr)); mcdataaddr.sin_family=AF_INET; mcdataaddr.sin_addr.s_addr = multicastaddress_out.s_addr; mcdataaddr.sin_port = htons(mcdataport); /*enter the address/port data into the localsendaddr structure for IPv4*/ bzero((char *) &localsendaddr4, sizeof(localsendaddr4)); localsendaddr4.sin_family=AF_INET; inet_pton(AF_INET, myhostnameipaddress4 , &localsendaddr4.sin_addr.s_addr); localsendaddr4.sin_port = htons(0); //LL // inet_ntop(AF_INET, &localsendaddr4.sin_addr.s_addr,addressstring ,sizeof(addressstring)); // printf("threaded function local sender addr side 1=%s \t",addressstring); /*enter the address/port data into the localsendaddr structure for IPv4*/ bzero((char *) &localsendaddr, sizeof(localsendaddr)); localsendaddr.sin_family=AF_INET; inet_pton(AF_INET, myhostnameipaddress , &localsendaddr.sin_addr.s_addr); localsendaddr.sin_port = htons(0); //LL // inet_ntop(AF_INET, &localsendaddr.sin_addr.s_addr,addressstring ,sizeof(addressstring)); // printf("threaded function local sender addr side 2=%s\n", addressstring); /*enter the address/port data into the mcdatareq structure for IPv4*/ bzero((char *) &mcdatareq4, sizeof(mcdatareq4)); // mcdatareq4.imr_interface.s_addr=htonl(INADDR_ANY); < force to add a multicast route inet_pton(AF_INET, myhostnameipaddress4 ,&mcdatareq4.imr_interface.s_addr ); mcdatareq4.imr_multiaddr.s_addr=multicastaddress_in.s_addr; // inet_pton(AF_INET, myhostnameipaddress4 , &mcdatareq4.imr_interface.s_addr); /*enter the address/port data into the mcdatareq structure for IPv4*/ bzero((char *) &mcdatareq, sizeof(mcdatareq)); inet_pton(AF_INET, myhostnameipaddress ,&mcdatareq.imr_interface.s_addr ); // mcdatareq.imr_interface.s_addr=htonl(INADDR_ANY); mcdatareq.imr_multiaddr.s_addr=multicastaddress_out.s_addr; /*get the sendfd socket linked to the first address of the current host */ if ((sendfd4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("can't open sendfd socket!"); exit (1); } if (bind(sendfd4, (struct sockaddr *) &localsendaddr4, \ sizeof(localsendaddr4)) < 0) { perror("can't bind localsendaddr v4 to socket!"); exit(1); } /*get the sendfd socket linked to the first address of the current host*/ if ((sendfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("can't open sendfd socket!"); exit (1); } if (bind(sendfd, (struct sockaddr *) &localsendaddr, \ sizeof(localsendaddr)) < 0) { perror("can't bind localsendaddr v4 side 2 to socket!"); exit(1); } if ((mcdatarecvfd4 = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("can't open mcdatarecvfd4 socket!"); exit(1); } /*allow multiple processes per host to read from IPv4 sockets side 2*/ if (setsockopt(mcdatarecvfd4, SOL_SOCKET, SO_REUSEADDR, &mcdataaddr4, sizeof(mcdataaddr4)) < 0) { perror("SO_REUSEADDR setsockopt v4\n"); } if (bind(mcdatarecvfd4, (struct sockaddr *) &mcdataaddr4, \ sizeof(mcdataaddr4)) < 0) { inet_ntop(AF_INET, &mcdataaddr4.sin_addr.s_addr,addressstring ,sizeof(addressstring)); printf("with address of bind %s\n", addressstring); perror("can't bind mcdataaddr v4 to socket!"); exit(1); } if (multicastaddress_out.s_addr!=multicastaddress_in.s_addr) { //multicast data receive socket side 2 /*get a mcdatarecvfd socket, bind to address for IPv4*/ if ((mcdatarecvfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { perror("can't open mcdatarecvfd4 socket!"); exit(1); } /*allow multiple processes per host to read from IPv4 sockets side 2*/ if (setsockopt(mcdatarecvfd, SOL_SOCKET, SO_REUSEADDR, &mcdataaddr, sizeof(mcdataaddr)) < 0) { perror("SO_REUSEADDR setsockopt v4\n"); } if (bind(mcdatarecvfd, (struct sockaddr *) &mcdataaddr, \ sizeof(mcdataaddr)) < 0) { perror("can't bind mcdataaddr v4 side 2 to socket!"); exit(1); } } else { mcdatarecvfd= mcdatarecvfd4; } /*set socket options to join multicast group in IPv4*/ if (setsockopt(mcdatarecvfd4, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcdatareq4,\ sizeof(mcdatareq4)) < 0) { perror("can't set socket options to join multicast group data v4 side 1!"); exit(1); } /*set socket options to join multicast group in IPv4*/ if (setsockopt(mcdatarecvfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mcdatareq,\ sizeof(mcdatareq)) < 0) { perror("can't set socket options to join multicast group data v4 side 2!"); exit(1); } /*now set multicast socket TTL option for IPv4*/ if (setsockopt(sendfd4, IPPROTO_IP, IP_MULTICAST_TTL, \ &ttl1, sizeof(ttl1)) < 0) perror("can't set multicast ttl v4 socket option!"); /*now set multicast socket TTL option for IPv4*/ if (setsockopt(sendfd, IPPROTO_IP, IP_MULTICAST_TTL, \ &ttl2, sizeof(ttl2)) < 0) perror("can't set multicast ttl v4 socket option!"); /*define the sizes of the address structures*/ mcdataaddrlen=sizeof(mcdataaddr4); sourceaddrlen=sizeof(sourceaddr4); /*start infinite while loop*/ /*and check for activity on sockets*/ /*set up the select sytem call parameters*/ /*zero out the readfds and writefds lists, then add*/ /*the file descriptors of interest*/ while(1) { FD_ZERO(&readfds); FD_SET(mcdatarecvfd4, &readfds); FD_SET(mcdatarecvfd, &readfds); if (debugon >= 1) { FD_SET(0, &readfds); } maxfds = mcdatarecvfd4 + 5; /*check for activity*/ nfds = select(maxfds, &readfds, NULL, NULL, NULL); /*if specified on the command line, check for input on stdin*/ if (debugon >= 1) { if (FD_ISSET(0, &readfds)) { n2 = read(0,inputbuf, sizeof(inputbuf)); inputbuf[n2>0? n2-1: 0] = '\0'; if (!strcmp(inputbuf,"q")) { programshutdown(); } } fflush(stdout); } /*1:receive from IPv4, send on IPv44 - data*/ if (FD_ISSET(mcdatarecvfd4, &readfds)) { nr = recvfrom(mcdatarecvfd4, mcdatarecvbuf4, MSGBUF_SIZE, 0, (struct sockaddr *) \ &sourceaddr4, &sourceaddrlen); if (debugon >= 2){ inet_ntop(AF_INET, &sourceaddr4.sin_addr.s_addr, addressstring4 , sizeof(addressstring4)); printf("\nreading from mcdatarecvfd4, got data from %s\n", addressstring4); } if (sourceaddr4.sin_addr.s_addr == localsendaddr4.sin_addr.s_addr){ chksrc = 0; if (debugon >= 2) printf("don't retransmit multicastv4 sourced from gateway machine\n"); } else { chksrc = 1; if (debugon >= 2) printf("retransmit to multicast address\n"); } if (chksrc) { if (nr < 0) printf ("mcdatarecvfd4:recvfrom over multicast v4 address error!(1)\n"); /*now send to IPv4*/ if (multicastaddress_out.s_addr != INADDR_ANY) { if (debugon >= 2) { inet_ntop(AF_INET, &mcdataaddr.sin_addr.s_addr,addressstring4 ,sizeof(addressstring4)); printf("sending to %s\n", addressstring4); } ns = sendto(sendfd, mcdatarecvbuf4, nr, 0, (struct sockaddr *)&mcdataaddr, \ sizeof(mcdataaddr)); } else { if (debugon >= 2) printf("not resending to ORIGINATOR! or array entry = 0\n"); } } } /*2:receive from IPv4 side 2, send on IPv44 side 1 - data*/ if (FD_ISSET(mcdatarecvfd, &readfds)) { nr = recvfrom(mcdatarecvfd, mcdatarecvbuf, MSGBUF_SIZE, 0, (struct sockaddr *) \ &sourceaddr, &sourceaddrlen); if (debugon >= 2){ inet_ntop(AF_INET, &sourceaddr.sin_addr.s_addr, addressstring , sizeof(addressstring)); printf("\nreading from mcdatarecvfd side 2, got data from %s\n", addressstring); } if (sourceaddr.sin_addr.s_addr == localsendaddr.sin_addr.s_addr){ chksrc = 0; if (debugon >= 2) printf("don't retransmit multicastv4 sourced from gateway machine\n"); } else { chksrc = 1; if (debugon >= 2) printf("retransmit to multicast address side 1\n"); } if (chksrc) { if (nr < 0) printf ("mcdatarecvfd:recvfrom over multicast v4 address error!(1)\n"); /*now send to IPv4*/ if (multicastaddress_in.s_addr != INADDR_ANY) { if (debugon >= 2) { inet_ntop(AF_INET, &mcdataaddr4.sin_addr.s_addr,addressstring ,sizeof(addressstring)); printf("sending to %s\n", addressstring); } ns = sendto(sendfd4, mcdatarecvbuf, nr, 0, (struct sockaddr *)&mcdataaddr4, \ sizeof(mcdataaddr4)); } else { if (debugon >= 2) printf("not resending to ORIGINATOR! or array entry = 0\n"); } } } } //end of while loop }