int mcast_get_loop(int sockfd) { switch (sockfd_to_family(sockfd)) { case AF_INET: { u_char flag; socklen_t len; len = sizeof(flag); if (getsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, &len) < 0) return(-1); return(flag); } #ifdef IPV6 case AF_INET6: { u_int flag; socklen_t len; len = sizeof(flag); if (getsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &flag, &len) < 0) return(-1); return(flag); } #endif default: errno = EAFNOSUPPORT; return(-1); } }
int mcast_get_ttl(int sockfd) { switch (sockfd_to_family(sockfd)) { case AF_INET: { u_char ttl; socklen_t len; len = sizeof(ttl); if (getsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, &len) < 0) return(-1); return(ttl); } #ifdef IPV6 case AF_INET6: { int hop; socklen_t len; len = sizeof(hop); if (getsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hop, &len) < 0) return(-1); return(hop); } #endif default: errno = EAFNOSUPPORT; return(-1); } }
int mcast_set_loop(int sockfd, int onoff) { switch (sockfd_to_family(sockfd)) { case AF_INET: { u_char flag; flag = onoff; return(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_LOOP, &flag, sizeof(flag))); } #ifdef IPV6 case AF_INET6: { u_int flag; flag = onoff; return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, &flag, sizeof(flag))); } #endif default: errno = EPROTONOSUPPORT; return(-1); } }
int mcast_set_ttl(int sockfd, int val) { switch (sockfd_to_family(sockfd)) { case AF_INET: { u_char ttl; ttl = val; return(setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl))); } #ifdef IPV6 case AF_INET6: { int hop; hop = val; return(setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &hop, sizeof(hop))); } #endif default: errno = EPROTONOSUPPORT; return(-1); } }
int mcast_get_if(int sockfd) { switch (sockfd_to_family(sockfd)) { case AF_INET: { /* TODO: similar to mcast_set_if() */ return(-1); } #ifdef IPV6 case AF_INET6: { u_int index; socklen_t len; len = sizeof(index); if (getsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &index, &len) < 0) return(-1); return(index); } #endif default: errno = EPROTONOSUPPORT; return(-1); } }
int Sockfd_to_family(int sockfd) { int rc; if ( (rc = sockfd_to_family(sockfd)) < 0) err_sys("sockfd_to_family error"); return(rc); }
int mcast_set_if(int sockfd, const char* ifname, u_int ifindex) { switch (sockfd_to_family(sockfd)) { case AF_INET: { struct in_addr inaddr; struct ifreq ifreq; if (ifindex > 0) { if (if_indextoname(ifindex, ifreq.ifr_name) == NULL) { errno = ENXIO; /* i/f index not found */ return (-1); } goto doioctl; } else if (ifname != NULL) { strncpy(ifreq.ifr_name, ifname, IFNAMSIZ); doioctl: if (ioctl(sockfd, SIOCGIFADDR, &ifreq) < 0) return (-1); memcpy(&inaddr, &((struct sockaddr_in*)&ifreq.ifr_addr)->sin_addr, sizeof(struct in_addr)); } else inaddr.s_addr = htonl(INADDR_ANY); /* remove prev. set default */ return (setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &inaddr, sizeof(struct in_addr))); } #ifdef IPV6 case AF_INET6: { u_int idx; if ((idx = ifindex) == 0) { if (ifname == NULL) { errno = EINVAL; /* must supply either index or name */ return (-1); } if ((idx = if_nametoindex(ifname)) == 0) { errno = ENXIO; /* i/f name not found */ return (-1); } } return (setsockopt(sockfd, IPPROTO_IPV6, IPV6_MULTICAST_IF, &idx, sizeof(idx))); } #endif default: errno = EAFNOSUPPORT; return (-1); } }
int main(int argc, char **argv) { pid_t pid; int listenfd; int connfd; socklen_t len; struct sockaddr_in servaddr, cliaddr; char buff[MAXLINE]; time_t ticks; listenfd = socket(AF_INET, SOCK_STREAM, 0); handleerr(listenfd); bzero(&servaddr, sizeof(servaddr)); servaddr.sin_family = AF_INET; servaddr.sin_addr.s_addr = htonl(INADDR_ANY); servaddr.sin_port = htons(1025); int bres = bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr)); handleerr(bres); int lres = listen(listenfd, MAXQLEN); handleerr(lres); for(;;) { len = sizeof(cliaddr); printf("Listening...\n"); connfd = accept(listenfd, (struct sockaddr *)&cliaddr, &len); handleerr(connfd); if((pid = fork()) == 0) {//child proc close(listenfd); printf("Connection from %s, port %d\n", inet_ntop(AF_INET, &(cliaddr.sin_addr), buff, sizeof(buff)), ntohs(cliaddr.sin_port)); int f = sockfd_to_family(connfd); printf("Local family: %d\n", f); ticks = time(NULL); snprintf(buff, sizeof buff, "%.24s\r\n", ctime(&ticks)); write(connfd, buff, strlen(buff)); close(connfd); exit(0); } close(connfd); } }