/*! @file port.c * @brief Test socket with/without setsockopt(..,SO_BINDTODEVICE,..) * * * * @b Usage: ./port -port portNum * * * @b Author/Date: Michael Yuniverg, 17 March 2011 * */ #include #include #include #include #include #include #include #include #include #include #include static char *pid_file = NULL; static int s = -1; struct addrinfo *paddrp = NULL; void exitcleanup() { if (pid_file) { unlink(pid_file); } if (paddrp) { freeaddrinfo(paddrp); } } void terminationHandler(int signum, siginfo_t *sinfo, void *dummy) { //printf("Received termination signal:%d Err:(%d) Code:(%d)\n", signum, sinfo->si_errno, sinfo->si_code); if (-1 != s) { close(s); } exit(EXIT_SUCCESS); } void setTerminationHandler() { int sigSet = 0; // Termination signal handler. struct sigaction terminateAction; // Set up the structure to specify the termination action. terminateAction.sa_sigaction = terminationHandler; sigemptyset(&terminateAction.sa_mask); terminateAction.sa_flags = SA_SIGINFO; sigSet &= sigaction(SIGTERM, &terminateAction, NULL); sigSet &= sigaction(SIGQUIT, &terminateAction, NULL); sigSet &= sigaction(SIGINT, &terminateAction, NULL); sigSet &= sigaction(SIGHUP, &terminateAction, NULL); sigSet &= sigaction(SIGPIPE, &terminateAction, NULL); sigSet &= sigaction(SIGALRM, &terminateAction, NULL); sigSet &= sigaction(SIGUSR1, &terminateAction, NULL); sigSet &= sigaction(SIGUSR2, &terminateAction, NULL); if (sigSet != 0) { printf("Failed to register terminate signal handler\n"); } } void Usage() { printf ("usage: port [options]\n"); printf (" -port : indicate which port to listen at\n"); } int main(int argc, char* argv[]) { char *port = NULL; struct addrinfo hints, *paddr; int backlog = 5; int i, err; int res = -1; // ---------------- Parse Options ----------------------------- if (argc < 2) { Usage(); return -1; } for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-port")) { port = argv[++i]; } else if (!strcmp(argv[i], "-file")) { pid_file = argv[++i]; } else { Usage(); return -1; } } if (port == NULL) { Usage(); return -1; } setTerminationHandler(); atexit(exitcleanup); memset(&hints, 0, sizeof(hints)); hints.ai_family = PF_INET6; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = 0; #ifdef AI_NUMERICSERV hints.ai_flags |= AI_NUMERICSERV; #endif hints.ai_flags |= AI_PASSIVE; if (getaddrinfo(NULL, port, &hints, &paddrp) != 0) { goto error; } for (paddr = paddrp; paddr != NULL; paddr = paddr->ai_next) { struct sockaddr_in *sinp; sinp = (struct sockaddr_in *)paddr->ai_addr; printf ("Attempt to listening at port: %d ...", ntohs(sinp->sin_port)); s= socket(paddr->ai_family, paddr->ai_socktype, paddr->ai_protocol); if (s < 0) { goto error; } /* the problematic system call */ const char *device = "lo"; struct ifreq ifr; strcpy(ifr.ifr_name, device); if(setsockopt(s,SOL_SOCKET,SO_BINDTODEVICE, &ifr,sizeof(ifr)) == -1) { //error = errno; perror("SO_BINDTODEVICE"); close(s); return -1; } printf("successfully binded local\n"); /* end of problematic system call */ if (bind(s, paddr->ai_addr, paddr->ai_addrlen) == -1) { close(s); printf ("bind failed. Exiting\n"); return -1; } if (listen(s, backlog) == -1) { close(s); goto error; } printf ("Block until interrupted by a signal (Ctrl+C or kill) ...\n"); select(1, NULL, NULL, NULL, NULL); } close(s); return 0; error: //err = GetLastError(); //printf ("FAIL (0x%x)\n", err); //DisplayError(err) ; return -1; }