// unix2inet-bridge (C) 2008 hcsw.org and Doug Hoyte // // Compilation: gcc -Wall -O3 unix2inet-bridge.c -o unix2inet-bridge // // Usage: unix2inet-bridge // // This will then bridge all connections to port with the specified // unix domain socket, suitable for scanning with Nmap, bridging unix // sockets across the network, etc. // // Uncomment the #define DEBUG line to see connection logs on stdout. // // TODO: // * Currently only supports STREAM sockets // * Would be interesting to report if the unix end ever sends // messages (see man cmsg) #include #include #include #include #include #include #include #include #include #include #include #include //#define DEBUG int conn_unix(char *path) { struct sockaddr_un address; size_t address_len; int sd; sd = socket(PF_UNIX, SOCK_STREAM, 0); if (sd < 0) { fprintf(stderr, "Error creating socket: %s\n", strerror(errno)); return -1; } address.sun_family = AF_UNIX; strcpy(address.sun_path, path); address_len = sizeof(address.sun_family) + strlen(path) + 1; if(connect(sd, (struct sockaddr *) &address, address_len) != 0) { fprintf(stderr, "Error connecting to '%s': %s\n", path, strerror(errno)); close(sd); return -1; } return sd; } int listen_inet(int port) { struct sockaddr_in my_addr; int sd, tp=0; if ((sd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "Error creating socket: %s\n", strerror(errno)); return -1; } setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, &tp, sizeof(tp)); my_addr.sin_family = AF_INET; my_addr.sin_port = htons(port); my_addr.sin_addr.s_addr = INADDR_ANY; memset(&(my_addr.sin_zero), 0, 8); if (bind(sd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1) { fprintf(stderr, "Error binding to port %d: %s\n", port, strerror(errno)); close(sd); return -1; } if (listen(sd, 5) == -1) { fprintf(stderr, "Error listening: %s\n", strerror(errno)); close(sd); return -1; } return sd; } void proc_bridge(int insd, int unsd) { fd_set rfds; int rv; char buf[4096]; int offset, len; while(1) { FD_ZERO(&rfds); FD_SET(insd, &rfds); FD_SET(unsd, &rfds); rv = select(insd>unsd ? insd+1 : unsd+1, &rfds, NULL, NULL, NULL); if (rv == -1) return; if (FD_ISSET(insd, &rfds)) { offset = 0; len = read(insd, buf, sizeof(buf)); if (len<=0) return; while (len) { rv = write(unsd, buf+offset, len); if (rv<=0) return; offset+=rv; len-=rv; } } else if (FD_ISSET(unsd, &rfds)) { offset = 0; len = read(unsd, buf, sizeof(buf)); if (len<=0) return; while (len) { rv = write(insd, buf+offset, len); if (rv<=0) return; offset+=rv; len-=rv; } } } } int main(int argc, char **argv) { int mainsd, insd, unsd; struct sockaddr_in their_addr; socklen_t tp; char ipbuf[100]; if (argc != 3 || atoi(argv[1])<=0 || atoi(argv[1])>=65536) { fprintf(stderr, "unix2inet-bridge (C) 2008 hcsw.org and Doug Hoyte\n"); fprintf(stderr, " Usage: unix2inet-bridge \n"); return -1; } mainsd = listen_inet(atoi(argv[1])); if (mainsd == -1) exit(-1); while(1) { tp = sizeof(struct sockaddr_in); insd = accept(mainsd, (struct sockaddr *)&their_addr, &tp); if (insd == -1) { fprintf(stderr, "Error accepting: %s\n", strerror(errno)); exit(-1); } inet_ntop(AF_INET, &(((struct sockaddr_in *)&their_addr)->sin_addr), ipbuf, sizeof(ipbuf)); #ifdef DEBUG printf("Bridging connection from %s to %s\n", ipbuf, argv[2]); #endif unsd = conn_unix(argv[2]); if (unsd == -1) exit(-1); if (fork() == 0) { proc_bridge(insd, unsd); #ifdef DEBUG printf("Killing connection from %s\n", ipbuf); #endif exit(0); } close(insd); close(unsd); } }