3 sockspy desthost destservice
5 You install this program in /etc/inetd.conf and /etc/services
7 For example I have used these entries:
13 spy stream tcp nowait tridge /usr/local/smb/sockspy sockspy fjall netbios-ssn
15 This means any connection to port 8001 will be redirected to
16 netbios-ssn on fjall. By playing with these parameters you can easily
17 spy on most of the tcp protocols. All packets traversing the link will
20 NOTE: This program is totally unsupported. I haven't used it for 2
21 years, and don't intend to fix the obvious bugs/limitations. I will,
22 however, accept contributed patches - or even a total rewrite :-)
27 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <sys/ioctl.h>
31 #include <netinet/in.h>
42 #define LOGIN "/tmp/spy.in"
46 #define LOGOUT "/tmp/spy.out"
50 #define LOGCMD "/tmp/spy.cmd"
57 #define STREQL(a, b) (strcmp(a, b) == 0)
60 char DestHost[256]; /* Remote system to connect to */
61 char DestObj[256]; /* Remote object/service to connect to */
63 /* Signal handler for SIGPIPE (write on a disconnected socket) */
68 fprintf(cmd,"writing to disconnected socket!\n");
76 int argc; /* # of command line arguments */
77 char *argv[]; /* the command line arguments */
79 int client, /* Socket connected to client */
80 server; /* Socket to use for server */
84 login = fopen(LOGIN,"w");
85 logout = fopen(LOGOUT,"w");
86 cmd = fopen(LOGCMD,"w");
91 fprintf(cmd,"Started server\n");
99 strcpy(DestHost,argv[1]);
100 strcpy(DestObj,argv[2]);
102 /* Time to attempt the connection */
103 server = inet_conn(DestHost, DestObj);
109 /* Just to make the code more readable */
112 /* We will abort gracefully when the client or remote system
114 signal(SIGPIPE, abort);
116 /* Now just go and move raw data between client and
118 dowork(client, server);
119 /* ... NEVER RETURNS ... */
122 dowork(client, server)
126 /* select(2) masks for client and remote */
127 int ClientMask, ServerMask;
129 /* Combined ClientMask and ServerMask */
132 /* Initialize select(2) masks */
133 ClientMask = 1<<client;
134 ServerMask = 1<<server;
136 ReadMask = ClientMask | ServerMask;
138 /* Now move raw data for the rest of our life between
141 /* Local Variables */
142 int SelectReadMask;/* select(2) mask modifiable by select(2) */
143 int nready; /* status return from select(2) */
146 /* Intialize select(2) mask everytime
147 as select(2) always modifies it */
148 SelectReadMask = ReadMask;
150 /* Wait for data to be present to be moved */
152 nready = select(32,&SelectReadMask,(int *)0,(int *)0,NIL);
153 } while( nready < 0 && errno == EINTR );
155 /* select(2) failed, shouldn't happen. Exit abnormally */
159 /* Favor the client (for no particular reason)
160 if s/he is has data */
161 if( SelectReadMask & ClientMask )
164 fprintf(cmd,"client %d\n",nready);
165 xfer(client, server,login);
168 /* Then check on the other guy */
169 if( SelectReadMask & ServerMask )
172 fprintf(cmd,"server %d\n",nready);
173 xfer(server, client,logout);
180 #define BUFSIZE 20000 /* Max bytes to move at a time */
183 int from, to; /* Move data from "from" to "to" */
186 static char buf[BUFSIZE]; /* Buffer data to be moved */
187 int nready; /* # bytes readable */
188 int got; /* # bytes actually being moved */
191 /* Query the system how many bytes are ready to be read */
192 ioctl(from, FIONREAD, &nready);
195 fprintf(cmd,"nready = %d\n",nready);
197 /* Only try to get the smaller of nready and BUFSIZE */
198 got = read(from, buf, nready < BUFSIZE ? nready : BUFSIZE);
200 /* Zero bytes returned indicates end of stream, exit gracefully */
205 fprintf(cmd,"read 0 bytes exiting\n");
220 fprintf(file,"\nTransaction %d\n",trans_num);
221 fwrite(buf,got,1,file);
226 /* Now send it accross to the other side */
227 ret = write(to, buf, got);
231 fprintf(cmd,"wrote %d\n",ret);
233 fprintf(cmd,"error = %s\n",strerror(errno));
238 inet_conn(host, port)
243 int sock; /* Socket to use for the connection */
244 struct hostent *hostent; /* Destination host entry */
245 struct servent *servent; /* Destination service entry */
246 struct sockaddr_in addr; /* Formated destination for connect */
248 /* Fetch the requested host and service entries */
249 hostent = gethostbyname(host);
251 servent = getservbyport(80, "tcp");
253 servent = getservbyname(port, "tcp");
258 fprintf(cmd,"inet_conn %s %s\n",host,port);
261 fprintf(cmd,"servent is NIL\n");
263 fprintf(cmd,"hostent is NIL\n");
264 if (hostent->h_addrtype != AF_INET)
265 fprintf(cmd,"not inet type\n");
270 /* No host entry, no service entry, or host is not
272 if( servent == NIL ||
274 hostent->h_addrtype != AF_INET )
277 /* Get a socket from the system to use for the connection */
278 if( (sock = socket(AF_INET, SOCK_STREAM, 0)) < 0 )
281 /* Make sure we start with a clean address structure ... */
282 bzero(&addr, sizeof(addr));
284 /* ... then fill in the required fields */
285 addr.sin_family = AF_INET;
286 addr.sin_port = servent->s_port;
287 bcopy(hostent->h_addr, &addr.sin_addr, hostent->h_length);
289 /* Now try to connection to the destination */
290 if( connect(sock, &addr, sizeof(addr)) < 0 ) {
291 /* No go, release the socket, and then return error! */
296 /* Success. Return the connected socket descriptor */
298 fprintf(cmd,"returning %d\n",sock);