source: abuse/tags/pd/abuse/net/abuse_ndrv.c @ 161

Last change on this file since 161 was 49, checked in by Sam Hocevar, 15 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 29.1 KB
Line 
1#include <stdio.h>
2#include <stdlib.h>
3#include <fcntl.h>
4#include <unistd.h>
5#include <sys/ioctl.h>
6#include <sys/stat.h>
7#include <sys/types.h>
8#include <sys/time.h>
9#include <string.h>
10#include <signal.h>
11#include <netinet/in.h>
12#include <sys/socket.h>
13
14
15
16#include <sys/types.h>
17#include <sys/ipc.h>
18#include <sys/shm.h>
19
20
21
22
23#include <bstring.h>
24
25#include <netdb.h>
26
27
28#include "netface.hpp"      // net interface structures to the engine will use
29
30// these are the names of the fifos to create in tmp
31// that communitcate with the engine
32
33#ifdef __sgi
34#define BIGUNS             // big endian word ordering
35#endif
36
37
38// these macros swap the "endians" of a word to intel form... this should be done for anything sent
39// across the net as the other computer might have a different endianess
40
41#ifdef BIGUNS
42#define swap_short(x) (((((unsigned short) (x)))<<8)|((((unsigned short) (x)))>>8))
43#define swap_long(x) \
44   ((( ((unsigned long)(x)) )>>24)|((( ((unsigned long)(x)) )&0x00ff0000)>>8)| \
45   ((( ((unsigned long)(x)) )&0x0000ff00)<<8)|(( ((unsigned long)(x)) )<<24))
46#else
47#define swap_short(x) (x)
48#define swap_long(x) (x)
49
50#endif
51
52
53#define DIN_NAME "/tmp/.abuse_ndrv_in"
54#define DOUT_NAME "/tmp/.abuse_ndrv_out"
55
56
57// the lock files is used in case a previous net driver is
58// already running
59
60#define DLOCK_NAME "/tmp/.abuse_ndrv_lock"
61
62
63#define MAX_CLIENTS 32  // change this if you need more
64#define MAX_JOINERS 32  // maximum clients that can join at the same time
65
66#define DEFAULT_COMM_PORT 20202
67#define DEFAULT_GAME_PORT 20203
68
69#define uchar unsigned char
70
71void net_watch();
72void setup_ports(int comm_port, int game_port);
73
74int no_security=0;
75int driver_out_fd,driver_in_fd;
76int shm_seg_id=-1;
77void *shm_addr=(void *)-1;  // shmat returns -1 on failure
78base_memory_struct *base;   // points to shm_addr
79int comm_fd=-1,             // listening socket for commincation port
80    game_fd=-1;
81char *active_server=NULL;   // if -net option, fetch all files from "active server"
82int stand_alone=0;          // if we are running this stand-alone (not interfacing with the engine)
83
84fd_set master_set;
85fd_set master_write_set;    // set a socket here if you detect a write_full
86
87client_struct *client_array;  // points to an array of possible clients in shared memory
88join_struct *join_array;      // points to an array of possible joining clients in shared memory
89char default_fs_name[256];    // default file server name (set with parm -fs)
90
91
92void clean_up()      // on exit unattach all shared memory links
93
94  fprintf(stderr,"clean up......\n");
95  if (shm_seg_id!=-1)
96    shmctl(shm_seg_id,IPC_RMID,NULL);
97
98  if (shm_addr!=(void *)-1)
99  {
100    shmdt((char *)shm_addr);
101    shm_addr=(void *)-1;
102  }
103
104  unlink(DIN_NAME);
105  unlink(DOUT_NAME);
106  unlink(DLOCK_NAME);
107}
108
109#ifdef __sgi
110void die(...)
111#else
112void die(int why)
113#endif
114{
115  fprintf(stderr,"dieing\n");
116  clean_up();
117  exit(0);
118}
119
120void mdie(char *reason)
121{
122  fprintf(stderr,"net driver : %s\n",reason);
123  die(0);
124}
125
126void comm_failed()  // general communication failure with engine
127{
128  fprintf(stderr,"net driver : Error occured while trying to communicate with the engine\n");
129  clean_up();
130  exit(0);
131}
132
133
134main(int argc, char **argv)
135{
136  int i;
137  strcpy(default_fs_name,"");          // initially no default file server
138
139  for (i=1;i<argc;i++)
140    if (!strcmp(argv[i],"-bastard"))   // this bypasses filename security features
141    {
142      fprintf(stderr,"Warning : Security measures bypassed (-bastard)\n");
143      no_security=1;
144    }
145
146
147  // make sure this program was run by the abuse engine
148  if (argc<2 || strcmp(argv[1],"runme"))   
149  {
150    stand_alone=1;
151    fprintf(stderr,"%s is normally run by abuse, running stand-alone file server\n"
152                   "Server will be killed by running abuse\n",argv[0]);
153  }
154
155
156  // see if we are already running, if so kill old driver
157  FILE *fp=fopen(DLOCK_NAME,"rb");
158  if (fp)
159  {
160    int pid;
161    if (fscanf(fp,"%d",&pid)==1)
162    {
163      struct stat st;
164      char proc_path[50];
165      sprintf(proc_path,"/proc/%d",pid);
166      if (!stat(proc_path,&st))
167      {
168        fprintf(stderr,"net driver : warning, %s already running, attempting to kill...\n",argv[0]);
169        if (kill(pid,SIGKILL))
170        {
171          fprintf(stderr,"net driver : unable to kill process %d, cannot run net-abuse\n",pid);
172          fclose(fp);
173          return 0;
174        }
175        fprintf(stderr,"killed process %d\n",pid);
176      }
177    }
178    fclose(fp);
179    unlink(DLOCK_NAME);   
180  }
181
182
183  unlink(DIN_NAME);    // remove any previous files if they exsists
184  unlink(DOUT_NAME);
185
186
187  if (!stand_alone)
188  {
189    if (mkfifo(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
190    { perror("Net driver : unable to make fifo in /tmp");
191      return 0;
192    }
193    chmod(DIN_NAME,S_IRWXU | S_IRWXG | S_IRWXO);   // just to be sure umask doesn't screw us
194
195    if (mkfifo(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO))
196    { perror("Net driver : unable to make fifo in /tmp");
197      return 0;
198    }
199    chmod(DOUT_NAME,S_IRWXU | S_IRWXG | S_IRWXO);
200
201    int i,no_fork=0;
202    for (i=1;i<argc;i++)
203    if (!strcmp(argv[i],"-no_fork"))    // use this to debug easier
204      no_fork=1;
205   
206    if (!no_fork)      // use this for debugging
207    {
208      int child_pid=fork();
209      if (child_pid)
210      {
211        FILE *fp=fopen(DLOCK_NAME,"wb");
212        if (!fp)
213        {
214          fprintf(stderr,"Unable to open %s for writing, killing child\n",DLOCK_NAME);
215          kill(child_pid,SIGKILL);
216          return 0;
217        }
218        fprintf(fp,"%d\n",child_pid);
219        fclose(fp);
220        printf("%d\n",child_pid);         // tell parent the sound driver's process number
221        return 0;                         // exit, child will continue
222      }
223    } 
224
225    driver_out_fd=open(DOUT_NAME,O_RDWR);  // open the pipe
226    if (driver_out_fd<0)
227    { perror(DOUT_NAME);
228      exit(1);
229    }
230
231    driver_in_fd=open(DIN_NAME,O_RDWR);
232    if (driver_in_fd<0)
233    { perror(DIN_NAME);
234      exit(1);
235    }
236  } else driver_in_fd=driver_out_fd=-1;
237
238
239
240  int catch_sigs[]={SIGHUP,SIGINT,SIGQUIT,SIGILL,SIGABRT,
241                  SIGIOT,SIGFPE,SIGKILL,SIGUSR1,SIGSEGV,
242                  SIGUSR2,SIGPIPE,SIGTERM,SIGCHLD,
243                  SIGCONT,SIGSTOP,SIGTSTP,SIGTTIN,SIGTTOU,-1};
244
245  for (i=0;catch_sigs[i]!=-1;i++)     // catch all signals in case we get
246    signal(catch_sigs[i],die);            // interrupted before we remove shmid
247
248
249  int alloc_size=sizeof(client_struct)*MAX_CLIENTS+
250                 sizeof(join_struct)*MAX_JOINERS+
251                 sizeof(base_memory_struct);
252
253  shm_seg_id=shmget(IPC_PRIVATE,alloc_size,IPC_CREAT | 0777);
254  if (shm_seg_id==-1)
255    mdie("Unable to allocate shared memory");
256
257
258  shm_addr=shmat(shm_seg_id,NULL,0);  // attach as read/write
259  if (shm_addr==(void *)-1)
260    mdie("could not attach shm seg");
261
262  base=(base_memory_struct *)shm_addr;
263  base->active_clients=NULL;
264  base->join_list=NULL;
265  base->mem_lock=0;
266  base->calc_crcs=0;
267
268  if (!stand_alone)
269  {
270    // see if we can attach this memory with the abuse engine
271    if (write(driver_out_fd,&shm_seg_id,sizeof(shm_seg_id))!=sizeof(shm_seg_id))
272      comm_failed();
273
274    // wait for engine to ack it has attached
275    uchar ack=0;
276    if (read(driver_in_fd,&ack,1)!=1 || ack!=1)
277      comm_failed();
278  }
279
280 
281  if (shmctl(shm_seg_id,IPC_RMID,NULL))  // remove the shm id
282    mdie("could not remove shm id");
283
284  shm_seg_id=-1;                      // mark as not allocated
285
286
287  int comm_port=DEFAULT_COMM_PORT;
288  int game_port=-1;
289  for (i=1;i<argc-1;i++)
290    if (!strcmp(argv[i],"-port"))
291    {
292      comm_port=atoi(argv[i+1]);
293      if (game_port==-1)
294        game_port=comm_port+1;
295    }
296    else if (!strcmp(argv[i],"-game_port"))
297      game_port=atoi(argv[i+1]);
298    else if (!strcmp(argv[i],"-net"))
299      active_server=argv[i+1];
300
301  if (game_port==-1) game_port=DEFAULT_GAME_PORT;
302
303  setup_ports(comm_port,game_port);
304
305
306  net_watch();                        // now go into infinite block/read/process cycle
307
308  return 0;
309}
310
311
312void secure_filename(char *filename, char *mode)
313{
314  if (!no_security)
315  {   
316    if (filename[0]=='/') { filename[0]=0; return ; }
317    int level=0;
318    char *f=filename;
319    while (*f)
320    {
321      if (*f=='/') { f++; level++; }
322      else if (*f=='.' && f[1]=='.')
323      {
324        if (f[3]=='.') while (*f!='.') f++;
325        else
326        {
327          f+=2;
328          level--;
329        }
330      } else f++;
331     
332    }
333    if (level<0)
334      filename[0]=0;
335  }
336}
337
338int total_clients=0;
339int total_joiners=0;
340
341class client
342{
343public :
344  int socket_fd;
345  int client_id;       // index into client_struct
346  int has_joined;
347  client *next;
348  client(int sock, int id, client *Next) { socket_fd=sock; client_id=id; next=Next; has_joined=0; }
349} *first_client=NULL;
350
351
352class nfs_client    // this is a client only read's a file
353{
354  public :
355  int socket_fd;
356  int file_fd;
357
358  long size_to_read; 
359  long size;
360  nfs_client *next;
361  nfs_client(int Socket_fd, int File_fd, nfs_client *Next)
362  {
363    socket_fd=Socket_fd;
364    file_fd=File_fd;
365    next=Next;
366    size_to_read=0;
367    FD_SET(socket_fd,&master_set);
368  } 
369  int send_read();             // flushes as much of size_to_read as possible
370  ~nfs_client()
371  {
372    if (socket_fd>=0)
373      close(socket_fd);
374    if (file_fd>=0)
375      close(file_fd);
376    FD_CLR(socket_fd,&master_set);
377  }
378} *first_nfs_client=NULL;
379
380
381void setup_ports(int comm_port, int game_port)
382{
383  // the comminication socket is a STREAM
384  comm_fd=socket(AF_INET,SOCK_STREAM,0);
385  if (comm_fd==-1)
386    mdie("net driver : could not create a socket.  (too many open files?)");
387
388
389  sockaddr_in host;
390  memset( (char*) &host,0, sizeof(host));
391  host.sin_family = AF_INET;
392  host.sin_port = htons(comm_port);
393  host.sin_addr.s_addr = htonl (INADDR_ANY);
394  if (bind(comm_fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
395  {
396    fprintf(stderr,"net driver : could not bind socket to port %d",comm_port);
397    die(0);
398  }
399
400  if (listen(comm_fd,5)==-1)
401  {
402    fprintf(stderr,"net driver : could not listen to socket on port %d\n",comm_port);   
403    die(0);
404  }
405
406
407  game_fd=socket(AF_INET,SOCK_DGRAM,0);
408  if (game_fd==-1)
409    mdie("net driver : could not create a socket.  (too many open files?)");
410
411  memset( (char*) &host,0, sizeof(host));
412  host.sin_family = AF_INET;
413  host.sin_port = htons(game_port);
414  host.sin_addr.s_addr = htonl (INADDR_ANY);
415  if (bind(game_fd, (struct sockaddr *) &host, sizeof(sockaddr_in))==-1)
416  {
417    fprintf(stderr,"net driver : could not bind socket to port %d\n",game_port);
418    die(0);
419  }
420}
421
422
423void delete_client(client *c)
424{
425  FD_CLR(c->socket_fd,&master_set);   // don't listen to this client anymore
426
427  client_array[c->client_id].input_state=WAIT_DELETE;  // inform server to delete this client
428}
429
430
431int aquire_mem_lock()
432{
433  if (base->mem_lock==0 || base->mem_lock==1)
434  {
435    base->mem_lock=1;
436    if (base->mem_lock==1)
437      return 1;
438  }
439  sleep(0);   // probably just gonna loop until we get the lock so halt for next preocess
440  return 0;
441}
442
443int local_address(char *server_name)    // returns 1 if server name is ourself
444{
445  struct hostent *hn=gethostbyname(server_name);    // first check to see if this address is 127.0.0.1
446  if (!hn) return 0;                                // if bad server_name, return false
447  char **ip_address=hn->h_addr_list;
448  while (*ip_address)
449  {
450    char *a=*ip_address;
451    if (a[0]==127 && a[1]==0 && a[2]==0 && a[3]==1)
452      return 1;
453    ip_address++;
454  }
455 
456  char my_name[100];                              // now check to see if this address is 'hostname'
457  gethostname(my_name,100);
458  struct hostent *l_hn=gethostbyname(my_name); 
459  char **l_ip_address=l_hn->h_addr_list;
460
461  while (*l_ip_address)  // local ip_address
462  {
463    char *a=*l_ip_address;         // scan through all local ip's
464    ip_address=hn->h_addr_list;
465    while (*ip_address)            // scan through all ip's for server_name
466    {
467      char *b=*ip_address;
468      if (a[0]==b[0] && a[1]==b[1] && a[2]==b[2] && a[3]==b[3])    // check for match
469        return 1;
470      ip_address++;
471    }
472    l_ip_address++;
473  }
474
475  return 0;       // didn't match localhost nor hostname, must be somewhere else
476}
477
478int nfs_client::send_read()   // return 0 if failure on socket, not failure to read
479{
480  if (file_fd>=0 && socket_fd>=0)
481  {
482    // first make sure the socket isn't 'full'
483
484    struct timeval tv={0,0};     // don't wait
485    fd_set write_check; 
486    FD_ZERO(&write_check); 
487    FD_SET(socket_fd,&write_check);     
488    select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
489
490    if (FD_ISSET(socket_fd,&write_check))            // ready to write?
491    {
492      char buf[READ_PACKET_SIZE];   
493      short read_total;
494      short actual;
495
496      do
497      {     
498        read_total=size_to_read>(READ_PACKET_SIZE-2) ? (READ_PACKET_SIZE-2) : size_to_read;
499        actual=read(file_fd,buf,read_total);
500        actual=swap_short(actual);
501        if (write(socket_fd,&actual,sizeof(actual))!=sizeof(actual))
502        {
503          fprintf(stderr,"write failed\n");
504          return 0;
505        }
506        actual=swap_short(actual);
507
508        int write_amount=write(socket_fd,buf,actual);
509        if (write_amount!=actual)
510        {
511          fprintf(stderr,"write failed\n");
512          return 0;
513        }
514
515        size_to_read-=actual;
516
517        FD_ZERO(&write_check); 
518        FD_SET(socket_fd,&write_check);     
519        select(FD_SETSIZE,NULL,&write_check,NULL,&tv);
520
521        if (!FD_ISSET(socket_fd,&write_check))
522        {
523          FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
524          FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
525          return 1;    // not ok to write anymore, try again latter
526        }
527
528      } while (size_to_read && actual==read_total);
529      size_to_read=0;
530      FD_CLR(socket_fd,&master_write_set);       // don't check this socket for write ok
531      FD_SET(socket_fd,&master_set);             // check it for reading
532      return 1;
533    } else
534    {
535      FD_SET(socket_fd,&master_write_set);      // socket is full, wait for it empty
536      FD_CLR(socket_fd,&master_set);            // don't check for reading or process commands till read is done
537      return 1;
538    }
539  }
540  return 0;
541}
542
543class remote_file
544{
545
546  public :
547  int socket_fd;
548  void r_close(char *reason)
549  {
550    if (reason)
551       fprintf(stderr,"remote_file : %s\n",reason);
552    if (socket_fd>=0)
553    {
554      uchar cmd=NFCMD_CLOSE;
555      write(socket_fd,&cmd,1);
556      close(socket_fd);
557    }
558    socket_fd=-1;
559  }
560
561  long size;   // server tells us the size of the file when we open it
562  remote_file *next;
563  remote_file(char *server, int port, char *filename, char *mode, remote_file *Next);
564
565  int unbuffered_read(int out_fd, size_t count);
566  int unbuffered_write(void *buf, size_t count) { return 0; } // not supported
567  int unbuffered_tell();
568  int unbuffered_seek(long offset);
569  int file_size() { return size; }
570  int open_failure() { return socket_fd<0; }
571  ~remote_file() { r_close(NULL); }
572  int fd() { return socket_fd; }
573} ;
574
575remote_file *remote_file_list;
576
577remote_file::remote_file(char *server, int port, char *filename, char *mode, remote_file *Next)
578{
579  next=Next;
580  socket_fd=socket(AF_INET,SOCK_STREAM,0);
581  if (socket_fd<0)
582  {
583    fprintf(stderr,"unable to open socket\n");
584    return ;
585  }
586
587  hostent *hp=gethostbyname(server);
588  if (!hp)
589  {
590    fprintf(stderr,"unable to locate server named '%s'\n",server);
591    close(socket_fd); socket_fd=-1; return ;
592  }
593 
594
595  sockaddr_in host;
596  memset( (char*) &host,0, sizeof(host));
597  host.sin_family = AF_INET;
598  host.sin_port = htons(port);
599  host.sin_addr.s_addr = htonl (INADDR_ANY);
600  memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
601   
602  if (connect(socket_fd, (struct sockaddr *) &host, sizeof(host))==-1)
603  {
604    fprintf(stderr,"unable to connect\n");
605    close(socket_fd);
606    socket_fd=-1;
607    return ;
608  }
609
610  uchar sizes[3]={CLIENT_NFS,strlen(filename)+1,strlen(mode)+1};
611  if (write(socket_fd,sizes,3)!=3) { r_close("could not send open info"); return ; }
612  if (write(socket_fd,filename,sizes[1])!=sizes[1]) { r_close("could not send filename"); return ; }
613  if (write(socket_fd,mode,sizes[2])!=sizes[2]) { r_close("could not send mode"); return ; }
614
615  long remote_file_fd;
616  if (read(socket_fd,&remote_file_fd,sizeof(remote_file_fd))!=sizeof(remote_file_fd))
617  { r_close("could not read remote fd"); return ; }   
618  remote_file_fd=swap_long(remote_file_fd);
619  if (remote_file_fd<0) { r_close("remote fd is bad"); return ; }
620
621  if (read(socket_fd,&size,sizeof(size))!=sizeof(size)) { r_close("could not read remote filesize"); return ; }
622  size=swap_long(size);
623}
624
625int remote_file::unbuffered_read(int out_fd, size_t count)
626{
627  if (socket_fd>=0 && count)
628  {
629    uchar cmd=NFCMD_READ;
630    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("read : could not send command"); return 0; }
631
632    long rsize=swap_long(count);
633    if (write(socket_fd,&rsize,sizeof(rsize))!=sizeof(rsize)) { r_close("read : could not send size"); return 0; }
634
635    long total_read=0,total;
636    char buf[READ_PACKET_SIZE];
637    ushort size;
638
639    ushort packet_size;   
640    do
641    {
642      if (read(socket_fd,&packet_size,sizeof(packet_size))!=sizeof(packet_size))
643      {
644        fprintf(stderr,"could not read packet size\n");
645        return 0;
646      }
647      packet_size=swap_short(packet_size);
648
649      ushort size_read=read(socket_fd,buf+2,packet_size);   
650
651      if (size_read!=packet_size)
652      {
653        if (read(socket_fd,buf+2+size_read,packet_size-size_read)!=packet_size-size_read)
654        {
655          fprintf(stderr,"incomplete packet\n");
656          return 0;
657        }
658      }
659
660      *((short *)buf)=packet_size;
661      if (write(out_fd,buf,packet_size+2)!=packet_size+2) comm_failed();
662
663      total_read+=packet_size;
664      count-=packet_size;
665    } while (packet_size==READ_PACKET_SIZE-2 && count);     
666    return total_read;
667  }
668  return 0;
669}
670
671int remote_file::unbuffered_tell()   // ask server where the offset of the file pointer is
672{
673  if (socket_fd>=0)
674  {
675    uchar cmd=NFCMD_TELL;
676    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("tell : could not send command"); return 0; }
677
678    long offset;
679    if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("tell : could not read offset"); return 0; }   
680    return swap_long(offset);
681  }   
682  return 0;
683}
684
685int remote_file::unbuffered_seek(long offset)  // tell server to seek to a spot in a file
686{
687  if (socket_fd>=0)
688  {
689    uchar cmd=NFCMD_SEEK;
690    if (write(socket_fd,&cmd,sizeof(cmd))!=sizeof(cmd)) { r_close("seek : could not send command"); return 0; }
691
692    long off=swap_long(offset);
693    if (write(socket_fd,&off,sizeof(off))!=sizeof(off)) { r_close("seek : could not send offset"); return 0; }
694
695    if (read(socket_fd,&offset,sizeof(offset))!=sizeof(offset)) { r_close("seek : could not read offset"); return 0; }   
696    return swap_long(offset);
697  }   
698  return 0;
699}
700
701int open_file(char *&filename, char *mode)
702{
703  if (filename[0]!='/' && filename[1]!='/' && default_fs_name[0])   // default file server?
704  {
705    char tmp_fn[500]; 
706    sprintf(tmp_fn,"//%s/%s",default_fs_name,filename);
707    strcpy(filename,tmp_fn);
708  }
709
710  if (filename[0]=='/' && filename[1]=='/')   // passive server file refrence?
711  {
712    int use_port=DEFAULT_COMM_PORT;
713
714    char server_name[100],*sn;
715    filename+=2;
716    sn=server_name;
717    while (*filename && *filename!='/' && *filename!=':')
718      *(sn++)=*(filename++);   
719    *sn=0;
720
721    if (*filename==':')    // a port is included in the filename
722    {
723      filename++;
724      char port[100],*p; p=port;
725      while (*filename && *filename!='/')
726      { *(p++)=*(filename++); }
727      *p=0;
728      if (!sscanf(port,"%d",&use_port) || use_port<0 || use_port>0x7fff) return -1;
729    }
730
731    filename++;
732
733
734   
735
736    if (!local_address(server_name))
737    {
738      remote_file *rf=new remote_file(server_name,use_port,filename,mode,remote_file_list);
739      if (rf->open_failure())
740      {
741        delete rf;
742        return -1;
743      }
744      else
745      {
746        remote_file_list=rf;
747        return rf->socket_fd;
748      }     
749    }     
750  }
751
752  secure_filename(filename,mode);
753  if (filename[0]==0) return -1;
754
755  int flags=0;
756  while (*mode)
757  {
758    if (*mode=='w') flags|=O_CREAT|O_RDWR;
759    else if (*mode=='r') flags|=O_RDONLY;
760    mode++;
761  }
762
763  int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
764  if (f>=0)
765  { close(f);
766    return -2;
767  }
768 
769  return -1;
770}
771
772remote_file *find_rfile(int fd)
773{
774  remote_file *r=remote_file_list;
775  for (;r && r->socket_fd!=fd;r=r->next)
776  {
777    if (r->socket_fd==-1)
778    {
779      fprintf(stderr,"bad sock\n");
780    }
781  }
782  return r;
783}
784
785void unlink_remote_file(remote_file *rf)
786{
787  if (rf==remote_file_list)
788    remote_file_list=rf->next;
789  else
790  {
791    remote_file *last=remote_file_list;
792    while (last->next && last->next!=rf) last=last->next;
793    last->next=rf->next;
794  }
795}
796
797void process_engine_command()
798{
799  uchar cmd;
800  if (read(driver_in_fd,&cmd,1)!=1) { mdie("could not read command from engine"); }
801  switch (cmd)
802  {
803    case EGCMD_DIE :
804    {
805      mdie("received die command");
806    } break;
807
808    case NFCMD_SET_FS :
809    {
810      uchar size;
811      char sn[256];
812      if (read(driver_in_fd,&size,1)!=1) mdie("could not read filename length");
813      if (read(driver_in_fd,sn,size)!=size) mdie("could not read server name");
814      strcpy(default_fs_name,sn);
815      size=1;  // return success
816      if (write(driver_out_fd,&size,1)!=1) mdie("could not send ok to engine");
817    } break;   
818
819    case NFCMD_OPEN :
820    {
821      uchar size[2];
822      char filename[300],mode[20],*fn;
823      fn=filename;
824      if (read(driver_in_fd,size,2)!=2) mdie("could not read fd on open");
825      if (read(driver_in_fd,filename,size[0])!=size[0]) mdie("incomplete filename");
826      if (read(driver_in_fd,mode,size[1])!=size[1]) mdie("incomplete mode string");
827     
828      int fd=open_file(fn,mode);
829      if (fd==-2)
830      {
831        uchar st[2];
832        st[0]=NF_OPEN_LOCAL_FILE;
833        st[1]=strlen(fn)+1;
834        if (write(driver_out_fd,st,2)!=2) comm_failed();
835        if (write(driver_out_fd,fn,st[1])!=st[1]) comm_failed();
836      } else if (fd==-1)
837      {
838        uchar st=NF_OPEN_FAILED;
839        if (write(driver_out_fd,&st,1)!=1) comm_failed();
840      } else
841      {
842        uchar st=NF_OPEN_REMOTE_FILE;
843        if (write(driver_out_fd,&st,1)!=1) comm_failed();       
844        if (write(driver_out_fd,&fd,sizeof(fd))!=sizeof(fd)) comm_failed();     
845      }
846
847    } break;
848    case NFCMD_CLOSE :
849    case NFCMD_SIZE :
850    case NFCMD_TELL :
851    case NFCMD_SEEK :
852    case NFCMD_READ :
853    {
854      int fd;
855      if (read(driver_in_fd,&fd,sizeof(fd))!=sizeof(fd)) comm_failed();
856      remote_file *rf=find_rfile(fd);
857      if (!rf)
858        mdie("bad fd for engine command");
859
860      switch (cmd)
861      {
862        case NFCMD_CLOSE :
863        {
864          unlink_remote_file(rf);
865          delete rf;
866          uchar st=1;
867          if (write(driver_out_fd,&st,1)!=1) comm_failed();     
868        } break;
869        case NFCMD_SIZE  :
870        {
871          if (write(driver_out_fd,&rf->size,sizeof(rf->size))!=sizeof(rf->size)) comm_failed();                   
872        } break;
873        case NFCMD_TELL :
874        {
875          long offset=rf->unbuffered_tell();
876          if (write(driver_out_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed(); 
877        } break;
878        case NFCMD_SEEK :
879        {
880          long offset;
881          if (read(driver_in_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed();
882          offset=rf->unbuffered_seek(offset);
883          if (write(driver_out_fd,&offset,sizeof(offset))!=sizeof(offset)) comm_failed(); 
884        } break;
885        case NFCMD_READ :
886        {
887          long size;
888          if (read(driver_in_fd,&size,sizeof(size))!=sizeof(size)) comm_failed();
889          rf->unbuffered_read(driver_out_fd,size);
890        } break;
891      }
892    } break;   
893    default :
894    { fprintf(stderr,"net driver : unknown net command %d\n",cmd); die(0); }
895  }
896 
897}
898
899int process_nfs_command(nfs_client *c)
900{
901  char cmd;
902  if (read(c->socket_fd,&cmd,1)!=1) return 0;
903  switch (cmd)
904  {
905    case NFCMD_READ :
906    {
907      long size;
908      if (read(c->socket_fd,&size,sizeof(size))!=sizeof(size)) return 0;
909      size=swap_long(size);
910
911      c->size_to_read=size;
912      return c->send_read();
913    } break;
914    case NFCMD_CLOSE :
915    {
916      return 0;
917    } break;
918    case NFCMD_SEEK :
919    {
920      long offset;
921      if (read(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
922      offset=swap_long(offset);
923      offset=lseek(c->file_fd,offset,0);
924      offset=swap_long(offset);
925      if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
926      return 1;
927    } break;
928    case NFCMD_TELL :
929    {
930      long offset=lseek(c->file_fd,0,SEEK_CUR);
931      offset=swap_long(offset);
932      if (write(c->socket_fd,&offset,sizeof(offset))!=sizeof(offset)) return 0;
933      return 1;
934    } break;
935   
936    default :
937    { fprintf(stderr,"net driver : bad command from nfs client\n");
938      return 0;
939    }
940  }
941}
942
943void get_game_data(client *c)
944{
945  fprintf(stderr,"Get game data from client id %d\n",c->client_id);
946}
947
948
949void add_nfs_client(int fd)
950{
951  uchar size[2];
952  char filename[300],mode[20],*mp;
953  if (read(fd,size,2)!=2) { close(fd); return ; }
954  if (read(fd,filename,size[0])!=size[0]) { close(fd); return ; }
955  if (read(fd,mode,size[1])!=size[1]) { close(fd); return ; }
956 
957  fprintf(stderr,"remote request for %s ",filename);
958
959  secure_filename(filename,mode);  // make sure this filename isn't a security risk
960  if (filename[0]==0) { fprintf(stderr,"(denied)\n"); close(fd); return ; }
961
962  mp=mode;
963  int flags=0;
964
965  while (*mp)
966  {
967    if (*mp=='w') flags|=O_CREAT|O_RDWR;
968    else if (*mp=='r') flags|=O_RDONLY;
969    mp++;
970  }
971     
972  int f=open(filename,flags,S_IRWXU | S_IRWXG | S_IRWXO);
973 
974  if (f<0)
975  {
976    fprintf(stderr,"(not found)\n");
977    f=-1;  // make sure this is -1
978  } else fprintf(stderr,"(granted, fd=%d)\n",f);
979
980  long ret=swap_long(f);
981  if (write(fd,&ret,sizeof(ret))!=sizeof(ret)) { close(fd); return ; }
982
983  if (f<0)    // no file, sorry
984    close(fd);
985  else
986  {
987    long cur_pos=lseek(f,0,SEEK_CUR);
988    long size=lseek(f,0,SEEK_END);
989    lseek(f,cur_pos,SEEK_SET);
990    size=swap_long(size);
991    if (write(fd,&size,sizeof(size))!=sizeof(size)) {  close(f); close(fd); return ; }
992
993    first_nfs_client=new nfs_client(fd,f,first_nfs_client);
994    first_nfs_client->size=size;
995  }
996}
997
998int isa_client(int client_id)    // sreach the list of active clients for this id and return 1 if found
999{
1000  int i;
1001  client *c=first_client;
1002  for (;c;c=c->next)
1003    if (c->client_id==client_id) return 1;
1004  return 0; 
1005}
1006
1007void insert_client(int client_id)  // add the client_id into the list of active clients
1008{
1009//  client_array[client_id]
1010//  if (!base->active_clients)
1011   
1012}
1013
1014int add_game_client(int fd)     // returns false if could not join client
1015
1016  fprintf(stderr,"add game client\n");
1017
1018  int i,first_free=-1;
1019  for (i=0;first_free==-1 && i<MAX_JOINERS;i++)
1020    if (join_array[i].client_id==-1)
1021      first_free=i;
1022
1023  if (first_free==-1) return 0;
1024
1025  int first_free_client=-1;
1026  for (i=0;first_free_client==-1 && i<MAX_CLIENTS;i++)
1027    if (!isa_client(i))
1028      first_free_client=i;
1029
1030  if (first_free_client==-1) return 0; 
1031
1032
1033  join_array[first_free].next=base->join_list;
1034  base->join_list=&join_array[first_free];     
1035  join_array[first_free].client_id=first_free_client;
1036 
1037  first_client=new client(fd,first_free_client,first_client);
1038
1039}
1040
1041
1042void add_client()
1043{
1044  struct sockaddr from;
1045  int addr_len=sizeof(from);
1046  int new_fd=accept(comm_fd,&from,&addr_len);
1047  if (new_fd>=0)
1048  {
1049    char client_type;
1050    if (read(new_fd,&client_type,1)!=1 ||
1051        !(client_type==CLIENT_NFS ||
1052        client_type==CLIENT_ABUSE)) { close(new_fd); return ; }
1053
1054    if (client_type==CLIENT_NFS)
1055      add_nfs_client(new_fd);
1056    else add_game_client(new_fd);   
1057  }
1058}
1059
1060void net_watch()
1061{
1062  int i;
1063  client_array=(client_struct *)(base+1);
1064  join_array=(join_struct *) (client_array+MAX_CLIENTS);
1065
1066  for (i=0;i<MAX_JOINERS;i++)
1067    join_array[i].client_id=-1;
1068
1069  for (i=0;i<MAX_CLIENTS;i++)
1070    client_array[i].client_id=i;
1071
1072  fd_set read_set,exception_set,write_set;
1073 
1074  FD_ZERO(&master_set); 
1075  FD_ZERO(&master_write_set); 
1076  FD_SET(comm_fd,&master_set);     // new incoming connections & nfs data
1077  FD_SET(game_fd,&master_set);     // game data
1078
1079  if (!stand_alone)
1080  {
1081    FD_SET(driver_in_fd,&master_set);  // request from engine
1082    FD_SET(driver_out_fd,&master_set); // check for error on messages to engine
1083  }
1084
1085  while (1)
1086  {
1087    // first lets set up a select that will cover all of our fd's so if nothing is happening
1088    // we can block and take no CPU time.
1089
1090    memcpy(&read_set,&master_set,sizeof(master_set));
1091    memcpy(&exception_set,&master_set,sizeof(master_set));
1092    memcpy(&write_set,&master_write_set,sizeof(master_set));
1093   
1094
1095    select(FD_SETSIZE,&read_set,&write_set,&exception_set,NULL);
1096
1097    if (!stand_alone)
1098    {
1099      // see if we had any errors talking to the engine
1100      if (FD_ISSET(driver_in_fd,&exception_set) ||
1101          FD_ISSET(driver_out_fd,&exception_set))
1102      comm_failed();
1103     
1104      // see if the engine has anything to say before getting to anyone else
1105      if (FD_ISSET(driver_in_fd,&read_set))
1106        process_engine_command();
1107    }
1108
1109    if (aquire_mem_lock())  // we need to change shared memory, make sure server is not using it.
1110    {
1111      client *c;
1112      for (c=first_client;c;c=c->next)
1113      {
1114        if (FD_ISSET(c->socket_fd,&exception_set))  // error?
1115          delete_client(c);
1116        else if (FD_ISSET(c->socket_fd,&read_set))  // in comming game data from client?
1117          get_game_data(c);
1118      }
1119
1120      if (FD_ISSET(comm_fd,&read_set))
1121        add_client();
1122
1123      nfs_client *nc,*last=NULL;
1124      for (nc=first_nfs_client;nc;)      // check for nfs request
1125      {
1126
1127        int ok=1;
1128
1129        if (FD_ISSET(nc->socket_fd,&exception_set))
1130        {
1131          ok=0;
1132          fprintf(stderr,"Killing nfs client, socket went bad\n");
1133        }
1134        else if (nc->size_to_read)
1135        {
1136          if (FD_ISSET(nc->socket_fd,&write_set))
1137            ok=nc->send_read();
1138        }           
1139        else if (FD_ISSET(nc->socket_fd,&read_set))
1140          ok=process_nfs_command(nc);    // if we couldn't process the packeted, delete the connection
1141           
1142        if (ok)
1143        {
1144          last=nc;
1145          nc=nc->next;
1146        } else
1147        {
1148          if (last) last->next=nc->next;
1149          else first_nfs_client=nc->next;
1150          nfs_client *c=nc;
1151          nc=nc->next;
1152          delete c;
1153        }
1154      }
1155
1156      base->mem_lock=0;
1157    }       
1158
1159
1160  }
1161}
1162
1163
1164
Note: See TracBrowser for help on using the repository browser.