⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unix2tcp.c

📁 unix接口转换为tcp接口
💻 C
字号:
/*  * Copyright (C) 2002,2003  Mihai RUSU (dizzy@roedu.net)  *  * This program is free software; you can redistribute it and/or  * modify it under the terms of the GNU General Public License  * as published by the Free Software Foundation; either version 2  * of the License, or (at your option) any later version.  *  * This program is distributed in the hope that it will be useful,  * but WITHOUT ANY WARRANTY; without even the implied warranty of  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the  * GNU General Public License for more details.  *  * You should have received a copy of the GNU General Public License  * along with this program; if not, write to the Free Software  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.*/#include <stdio.h>#include <sys/types.h>#include <sys/socket.h>#include <sys/stat.h>#include <sys/un.h>#include <netinet/in.h>#include <arpa/inet.h>#include <unistd.h>#include <fcntl.h>#include <signal.h>#include <errno.h>#include <string.h>#include "list.h"#include "unix2tcp.h"/* Global Variable Definitions */static int listensock;static struct sockaddr_in raddr;static char *unixpath;static fd_set trfds, twfds;static int maxsocket = 0, findmax;static t_list *connlist = NULL;volatile static int quitasap = 0;static void dostop(int);static void usage(void);static void packet_destroy(t_packet *);/* Connection handling routines */static int connection_new(int);static int connection_establish(t_connection *);static void connection_destroy(t_connection *);static int socket_nonblock(int);static int init_socket(char *, char *, char *);static void close_socket(void);static int server_read(t_mysocket *, t_mysocket *);static int server_write(t_mysocket *);static void mainloop(void);int main(int argc, char **argv){   if (argc != 4) usage();   signal(SIGINT, dostop);   signal(SIGTERM, dostop);   fprintf(stderr, "STARTUP\n");   if (init_socket(argv[1], argv[2], argv[3]) < 0) {      printf("Error in init_socket()!\n");      return -1;   }   mainloop();   close_socket();   fprintf(stderr, "SHUTDOWN\n");   return 0;}static int init_socket(char *upath, char *remoteip, char *remoteport){   struct sockaddr_un unixaddr;      if (upath == NULL || remoteip == NULL || remoteport == NULL) return -1;      if (inet_aton(remoteip, &raddr.sin_addr) == 0) return -1;      raddr.sin_family = AF_INET;   raddr.sin_port = htons(atoi(remoteport));   unixpath = upath;      listensock = socket(PF_UNIX, SOCK_STREAM, 0);   if (listensock < 0) {      fprintf(stderr, "Error doing socket()\n");      return -1;   }      if (socket_nonblock(listensock) < 0) {      fprintf(stderr, "Error trying to set O_NONBLOCK\n");      close(listensock);      return -1;   }   unixaddr.sun_family = AF_UNIX;   strcpy(unixaddr.sun_path, unixpath);   if (bind(listensock, (struct sockaddr *)&unixaddr, sizeof(unixaddr))) {      fprintf(stderr, "Error doing bind()\n");      close(listensock);      return -1;   }   if (chmod(unixpath, S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IWGRP | S_IXGRP | S_IROTH | S_IWOTH | S_IXOTH) < 0) {      fprintf(stderr, "Error chmod() (%s)\n", strerror(errno));      close(listensock);      return -1;   }   if (listen(listensock, 5)) {      printf("Eroare doing listen()\n");      close(listensock);      unlink(unixpath);      return -1;   }      FD_ZERO(&trfds); FD_ZERO(&twfds);   FD_SET(listensock, &trfds);   if (maxsocket < listensock) maxsocket = listensock;      findmax = 100;   return 0;}static void close_socket(void){   t_list_elem *elem;      /* FIXME: close all incoming/outgoing connections */   if (listensock) close(listensock);   unlink(unixpath);   if (connlist) {      for(elem = LIST_FIRST(connlist); elem ; elem = LIST_NEXT(elem)) {	 t_connection *c = elem_get_data(elem);	 if (c) connection_destroy(c);	 else fprintf(stderr, "close_socket : found NULL entry in conn list\n");      }      list_free(connlist);      connlist = NULL;   }   FD_ZERO(&trfds); FD_ZERO(&twfds);}static void mainloop(void){   fd_set rfds, wfds;   int res;   t_list_elem *elem, *next;   if (connlist == NULL && (connlist = list_init()) == NULL) return;   while(!quitasap) {      memmove(&rfds, &trfds, sizeof(fd_set));      memmove(&wfds, &twfds, sizeof(fd_set));      res = select(maxsocket + 1, &rfds, &wfds, NULL, NULL);      if (res == 0)	fprintf(stderr, "mainloop() : select returned with 0 fds!\n");      else if (res < 0)	switch(errno) {	 case EINTR: /* got signal */	   break;	 default:	   fprintf(stderr, "mainloop() : got error in select()(%s)\n", strerror(errno));	}      else {	 if (FD_ISSET(listensock, &rfds)) {	    int newsock;	    struct sockaddr addr;	    socklen_t size;	    	    memset(&addr, 0, sizeof(addr));	    size = 0;	    newsock = accept(listensock, &addr, &size);	    if (newsock < 0)	      switch(errno) {	       case EAGAIN:		 fprintf(stderr, "mainloop() : select returned rdy but accept() would block\n");		 break;	       default:		 fprintf(stderr, "mainloop() : got error in accept()(%s)\n", strerror(errno));	      }	    else if (connection_new(newsock) < 0)	       /* could not creat the proxy connection, close the source */	      close(newsock);	 }	 	 for(elem = LIST_FIRST(connlist); elem ; elem = next) {	    t_connection *c = elem_get_data(elem);	    next = LIST_NEXT(elem);	    if (c) {	       res = 0;	       if (FD_ISSET(c->in.sock, &rfds)) res = server_read(&c->in, &c->out);	       if (res == 0 && FD_ISSET(c->in.sock, &wfds)) res = server_write(&c->in);	       if (res == 0 && FD_ISSET(c->out.sock, &rfds)) res = server_read(&c->out, &c->in);	       if (res == 0 && FD_ISSET(c->out.sock, &wfds)) {		  if (c->inprogress) res = connection_establish(c);		  else res = server_write(&c->out);	       }	       if (res < 0) quitasap = 1;	       else if (res > 0) {		  connection_destroy(c);		  list_delete_by_elem(connlist, elem);	       }	    } else fprintf(stderr, "mainloop() : got NULL entry in in_conn list\n");	 }      }   }}static int server_read(t_mysocket *in, t_mysocket *out){   static char buffer[4096];   t_packet *packet;   int res, len;   if (in == NULL || out == NULL) {      fprintf(stderr, "server_read : Got NULL in/out sockets\n");      return -1;   }   res = read(in->sock, buffer, sizeof(buffer));   if (res < 0) {      switch(errno) {       case EAGAIN: /* no data available */       case EINTR: /* call was interupted by a signel before any data was read */	 return 0;       case ECONNRESET:	 return 1;       default:	 fprintf(stderr, "server_read : got error in read() (%s)\n", strerror(errno));	 return -1;      }   }   if (res == 0) return 1; /* connection closed by peer */   res = write(out->sock, buffer, len = res);   if (res == len) return 0;   if (res < 0) {      switch(errno) {       case EPIPE: /* connection closed */       case ECONNRESET:	 return 1;       case EAGAIN: /* would block */       case EINTR: /* interupted in write() */	 break;       default: 	 fprintf(stderr, "server_read : error in write() (%s)\n", strerror(errno));	 return -1;      }   } else if (res && res < len) { /* sent a part of original data */      len -= res;      memmove(buffer, buffer + res, len);   }   /* could not send read data, so we queue it for later send */   if (out->outqueue == NULL && (out->outqueue = list_init()) == NULL) {      fprintf(stderr, "server_read : could not init the outqueue\n");      return -1;   }   if ((packet = malloc(sizeof(t_packet))) == NULL) {      fprintf(stderr, "server_read : could not allocate new packet\n");      return -1;   }      if ((packet->data = malloc(len)) == NULL) {      fprintf(stderr, "server_read : could not allocate for data\n");      free(packet);      return -1;   }   memmove(packet->data, buffer, len);   packet->len = len;   if (list_append_data(out->outqueue, packet) < 0) {      fprintf(stderr, "server_read : could not append packet to out\n");      free(packet->data);      free(packet);      return -1;   }   FD_SET(out->sock, &twfds); /* next select() will need to check for writing */   return 0;}static int server_write(t_mysocket *con){   int res;   t_list_elem *elem;   t_packet *packet;      if (con == NULL) {      fprintf(stderr, "server_write : got NULL con\n");      return -1;   }   if (con->outqueue == NULL) {      fprintf(stderr, "server_write : got NULL outqueue\n");      return -1;   }   elem = LIST_FIRST(con->outqueue);   if (elem == NULL) {      fprintf(stderr, "server_write : outqueue is empty\n");      return -1;   }      packet = elem_get_data(elem);   if (packet == NULL || packet->data == NULL) {      fprintf(stderr, "server_write : found NULL packet in outqueue\n");      return -1;   }      res = write(con->sock, packet->data, packet->len);   if (res < 0) {      switch(errno) {       case EPIPE: /* connection closed */       case ECONNRESET:	 return 1;       case EAGAIN: /* would block */       case EINTR: /* interupted in write() */	 return 0;       default: 	 fprintf(stderr, "server_write : error in write() (%s)\n", strerror(errno));	 return -1;      }   }   if (!res) return 0; /* nothing written */   if (res < packet->len) { /* we wrote fewer bytes than requested */      memmove(packet->data, (char *)packet->data + res, packet->len - res);      packet->len -= res;      return 0;   }   packet_destroy(packet);   if (list_delete_by_elem(con->outqueue, elem) < 0) {      fprintf(stderr, "server_write : could not remove sent packet from outqueue\n");      return -1;   }   /* outqueue is empty so next select() wont need to check for write */   if (list_get_size(con->outqueue) == 0) FD_CLR(con->sock, &twfds);    return 0;}static int connection_new(int newsock){   t_connection *c;   int outsock;   if (connlist == NULL) return -1;   if (newsock < 1) {      fprintf(stderr, "connection_new() : got invalid socket\n");      return -1;   }   c = malloc(sizeof(t_connection));   if (c == NULL) {      fprintf(stderr, "connection_new() : could not allocate for new connections\n");      return -1;   }   outsock = socket(PF_INET, SOCK_STREAM, 0);   if (outsock < 1) {      fprintf(stderr, "connection_new() : could not create new socket\n");      free(c);      return -1;   }      if (socket_nonblock(outsock) < 0) {      fprintf(stderr, "connection_new() : could not set O_NONBLOCK on socket\n");      free(c);      close(outsock);      return -1;   }      if (connect(outsock, (struct sockaddr *) &raddr, sizeof(raddr))) {      switch(errno) {       case EINPROGRESS: /* note a in progress connection */	 c->inprogress = 1;	 break;       default:	 fprintf(stderr, "connection_new() : could not connect()(%s)\n", strerror(errno));	 close(outsock);	 free(c);	 return -1;      }   } else c->inprogress = 0;   c->in.sock = newsock;   c->in.outqueue = NULL;   c->out.sock = outsock;   c->out.outqueue = NULL;   if (list_append_data(connlist, c) < 0) {      fprintf(stderr, "connection_new() : could not append new connection to list\n");      close(outsock);      free(c);      return -1;   }   if (maxsocket < c->in.sock) maxsocket = c->in.sock;   if (maxsocket < c->out.sock) maxsocket = c->out.sock;   if (!c->inprogress) { /* connection fully established */      FD_SET(c->in.sock, &trfds);      FD_SET(c->out.sock, &trfds);   } else FD_SET(c->out.sock, &twfds); /* connection in progress, wait for write */   return 0;}static int connection_establish(t_connection *c){   int error;   socklen_t len;   if (c == NULL) {      fprintf(stderr, "connection_establish() : found NULL connection\n");      return -1;   }   if (!c->inprogress || c->out.sock <= 0) {      fprintf(stderr, "connection_establish() : got invalid connection\n");      return -1;   }   len = sizeof(error);   if (getsockopt(c->out.sock, SOL_SOCKET, SO_ERROR, &error, &len) < 0) {      fprintf(stderr, "connection_establish() : could not getsockopt()\n");      return -1;   }   if (error) /* could not establish remote connection */     return 1; /* close this connection */      c->inprogress = 0; /* connection established */   FD_CLR(c->out.sock, &twfds);   FD_SET(c->in.sock, &trfds); FD_SET(c->out.sock, &trfds);   return 0;}static void connection_destroy(t_connection *c){   t_list_elem *elem;   t_packet *packet;   if (c == NULL) return;   close(c->in.sock);   close(c->out.sock);   FD_CLR(c->in.sock, &trfds); FD_CLR(c->out.sock, &trfds);   FD_CLR(c->in.sock, &twfds); FD_CLR(c->out.sock, &twfds);   if (--findmax == 0) {      t_connection *con;      maxsocket = listensock;      for(elem = LIST_FIRST(connlist); elem; elem = LIST_NEXT(elem)) {	 con = elem_get_data(elem);	 	 if (con && con != c) {	    if (con->in.sock > maxsocket) maxsocket = con->in.sock;	    if (con->out.sock > maxsocket) maxsocket = con->out.sock;	 }      }      findmax = 100;   }      if (c->in.outqueue) {      for(elem = LIST_FIRST(c->in.outqueue); elem; elem = LIST_NEXT(elem)) {	 packet = elem_get_data(elem);	 	 if (packet) packet_destroy(packet);	 else fprintf(stderr, "connection_destroy : found NULL entry in outqueue\n");      }      list_free(c->in.outqueue);   }   if (c->out.outqueue) {      for(elem = LIST_FIRST(c->out.outqueue); elem; elem = LIST_NEXT(elem)) {	 packet = elem_get_data(elem);	 	 if (packet) packet_destroy(packet);	 else fprintf(stderr, "connection_destroy : found NULL entry in outqueue\n");      }      list_free(c->out.outqueue);   }      free(c);}static void packet_destroy(t_packet *packet){   if (packet == NULL) return;      if (packet->data) free(packet->data);   free(packet);}static int socket_nonblock(int fd){   int flags;   flags = fcntl(fd, F_GETFL);   if (flags < 0) return -1;   flags |= O_NONBLOCK;   if (fcntl(fd, F_SETFL, flags) < 0) return -1;   return 0;}static void usage(void){   printf("Usage: unix2tcp <unix-socket> <remote-ip> <remote-port>\n");   exit(-1);}static void dostop(int n){   quitasap = 1;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -