source: abuse/tags/pd/abuse/src/net/mac/tcpip.c

Last change on this file was 49, checked in by Sam Hocevar, 11 years ago
  • Imported original public domain release, for future reference.
  • Property svn:keywords set to Id
File size: 13.5 KB
Line 
1#ifdef _AIX
2#include <strings.h>
3#endif
4
5#ifdef __POWERPC__
6#include "GUSI.h"
7#endif
8#include "tcpip.hpp"
9#include <ctype.h>
10
11#ifdef __POWERPC__
12extern tcpip_protocol tcpip;
13#else
14tcpip_protocol tcpip;
15#endif
16
17//#define TCPIP_DEBUG
18
19//{{{ net logging stuff
20/*
21FILE *log_file=NULL;
22extern int net_start();
23void net_log(char *st, void *buf, long size)
24{
25   
26  if (!log_file)
27  {
28    if (net_start())
29      log_file=fopen("client.log","wb");
30    else
31      log_file=fopen("server.log","wb");
32  }
33
34
35    fprintf(log_file,"%s%d - ",st,size);
36    int i;
37    for (i=0;i<size;i++)
38      if (isprint(*((unsigned char *)buf+i)))
39        fprintf(log_file,"%c",*((unsigned char *)buf+i));
40      else fprintf(log_file,"~");
41
42    fprintf(log_file," : ");
43
44    for (i=0;i<size;i++)
45    fprintf(log_file,"%02x, ",*((unsigned char *)buf+i),*((unsigned char *)buf+i));
46    fprintf(log_file,"\n");
47    fflush(log_file);
48
49} */
50//}}}
51
52////////////////////////////////////////////////////////////////////////
53//
54//  unix_fd methods
55//
56
57int unix_fd::read(void *buf, int size, net_address **addr)
58//{{{
59{
60  int tr=::read(fd,(char*)buf,size);
61  if (addr) *addr=NULL;
62  return tr;
63}
64//}}}///////////////////////////////////
65
66int unix_fd::write(void *buf, int size, net_address *addr)
67//{{{
68{
69  if (addr) fprintf(stderr,"Cannot change address for this socket type\n");
70  return ::write(fd,(char*)buf,size);
71}
72//}}}///////////////////////////////////
73
74void unix_fd::broadcastable()
75//{{{
76{
77  int zz;
78  if (setsockopt(fd,SOL_SOCKET,SO_BROADCAST,(char *)&zz,sizeof(zz))<0)
79  {
80    fprintf(stderr,"could not set socket option broadcast");
81    return;
82  }
83}
84//}}}///////////////////////////////////
85
86////////////////////////////////////////////////////////////////////////
87//
88//  tcpip_protocol methods
89//
90
91net_address *tcpip_protocol::get_local_address()
92//{{{
93{
94#if 0
95        struct hostent *l_hn=gethostent();
96
97        ip_address *a=new ip_address();
98        memset(&a->addr,0,sizeof(a->addr));
99        memcpy(&a->addr.sin_addr,*l_hn->h_addr_list,4); 
100
101        return a; 
102#else
103  char my_name[100];                                            // check to see if this address is 'hostname'
104  gethostname(my_name,100);
105  ip_address *ret = 0;
106 
107  if (my_name[0]<'0' || my_name[0]>'9')
108  {
109        struct hostent *l_hn=gethostbyname(my_name);
110       
111        if (l_hn)
112        {
113                ip_address *a=new ip_address();
114                memset(&a->addr,0,sizeof(a->addr));
115                memcpy(&a->addr.sin_addr,*l_hn->h_addr_list,4); 
116       
117                return a;
118          }
119          else
120          {
121                  printf("Enter ip address:");
122                  gets(my_name);
123          }
124        } 
125
126  char tmp[4],*np;
127        sockaddr_in host;
128 
129  np = my_name;
130  for (int i=0; i<4; i++)
131  {
132    int num = 0;
133    while (*np)
134    {
135      if (*np=='.')
136      {
137        np++;
138        break;
139      }
140      num = num*10 + *np - '0';
141      np++;
142    }
143    tmp[i] = num;
144  }
145 
146  memset( (char*) &host,0, sizeof(host));
147  host.sin_family = AF_INET;
148  host.sin_addr.s_addr = htonl(INADDR_ANY);
149  memcpy(&host.sin_addr,tmp,sizeof(in_addr));
150 
151        return new ip_address(&host);
152#endif
153}
154//}}}///////////////////////////////////
155
156net_address *tcpip_protocol::get_node_address(char *&server_name,
157                                                                                                                                                                                        int def_port, int force_port)
158//{{{
159{
160  sockaddr_in host;
161
162        if (server_name[0]>='0' && server_name[0]<='9')
163        {
164          char tmp[4],*np;
165         
166          np = server_name;
167          for (int i=0; i<4; i++)
168          {
169            int num = 0;
170            while (*np && *np!=':')
171            {
172              if (*np=='.')
173              {
174                np++;
175                break;
176              }
177              num = num*10 + *np - '0';
178              np++;
179            }
180            tmp[i] = num;
181            if (*np == ':' & !force_port)
182            {
183                int x;
184              if (sscanf(np+1,"%d",&x)==1)
185                def_port=x;
186                  }
187          }
188         
189          memset( (char*) &host,0, sizeof(host));
190          host.sin_family = AF_INET;
191          host.sin_port = htons(def_port);
192          host.sin_addr.s_addr = htonl(INADDR_ANY);
193          memcpy(&host.sin_addr,tmp,sizeof(in_addr));
194         
195          return new ip_address(&host);
196        }
197        else
198        {
199          char name[256],*np;
200
201          np=name;
202          while (*server_name && *server_name!=':' && *server_name!='/')
203            *(np++)=*(server_name)++;
204          *np=0;
205          if (*server_name==':')
206          {
207            server_name++;
208            char port[256],*p;
209            p=port;
210            while (*server_name && *server_name!='/')
211              *(p++)=*(server_name++);
212            *p=0;
213            int x;
214            if (!force_port)
215            {
216              if (sscanf(port,"%d",&x)==1) def_port=x;
217              else return 0;
218            }
219          }
220       
221          if (*server_name=='/') server_name++;
222       
223          hostent *hp=gethostbyname(name);
224          if (!hp)
225          {
226            fprintf(stderr,"unable to locate server named '%s'\n",name);
227            return 0;
228          }
229         
230          memset( (char*) &host,0, sizeof(host));
231          host.sin_family = AF_INET;
232          host.sin_port = htons(def_port);
233          host.sin_addr.s_addr = htonl(INADDR_ANY);
234          memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
235        }
236  return new ip_address(&host);
237}
238//}}}///////////////////////////////////
239
240net_socket *tcpip_protocol::connect_to_server(net_address *addr, net_socket::socket_type sock_type)
241//{{{
242{
243  if (addr->protocol_type()!=net_address::IP)
244  {
245    fprintf(stderr,"Procotol type not supported in the executable\n");
246    return NULL;
247  }
248
249  int socket_fd=socket(AF_INET,sock_type==net_socket::SOCKET_SECURE ? SOCK_STREAM : SOCK_DGRAM,0);
250  if (socket_fd<0)
251  {
252    fprintf(stderr,"unable to create socket (too many open files?)\n");
253    return 0;
254  }
255
256#ifndef __POWERPC__
257  int zz;
258  if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
259  {
260    fprintf(stderr,"could not set socket option reuseaddr");
261    return 0;
262  }
263#endif
264   
265  if (connect(socket_fd, (struct sockaddr *) &((ip_address *)addr)->addr, sizeof( ((ip_address *)addr)->addr ))==-1)
266  {
267    fprintf(stderr,"unable to connect\n");
268    close(socket_fd);
269    return 0;
270  }
271
272  if (sock_type==net_socket::SOCKET_SECURE)
273    return new tcp_socket(socket_fd);
274  else
275    return new udp_socket(socket_fd);
276}
277//}}}///////////////////////////////////
278
279net_socket *tcpip_protocol::create_listen_socket(int port, net_socket::socket_type sock_type)
280//{{{
281{
282  int socket_fd=socket(AF_INET,sock_type==net_socket::SOCKET_SECURE ? SOCK_STREAM : SOCK_DGRAM,0);
283  if (socket_fd<0)
284  {
285    fprintf(stderr,"unable to create socket (too many open files?)\n");
286    return 0;
287  }
288
289#ifndef __POWERPC__
290  int zz;
291  if (setsockopt(socket_fd,SOL_SOCKET,SO_REUSEADDR,(char *)&zz,sizeof(zz))<0)
292  {
293    fprintf(stderr,"could not set socket option reuseaddr");
294    return 0;
295  }
296#endif
297
298  net_socket *s;
299  if (sock_type==net_socket::SOCKET_SECURE)
300    s=new tcp_socket(socket_fd);
301  else s=new udp_socket(socket_fd);
302  if (s->listen(port)==0)
303  {   
304    delete s;
305    return 0;
306  }
307
308  return s;
309}
310//}}}///////////////////////////////////
311
312net_socket *tcpip_protocol::start_notify(int port, void *data, int len)
313//{{{
314{
315        if (responder)
316        {
317                delete responder;
318                delete bcast;
319                responder = 0;
320        }
321       
322        int resp_len = strlen(notify_response);
323  notify_len = len + resp_len + 1;
324  strcpy(notify_data,notify_response);
325        notify_data[resp_len] = '.';
326  memcpy(notify_data+resp_len+1,data,len);
327 
328  // create notifier socket
329#ifdef TCPIP_DEBUG
330        fprintf(stderr,"Creating notifier on port %d\n",port);
331#endif
332  notifier = create_listen_socket(port, net_socket::SOCKET_FAST);
333 
334  if (notifier)
335  {
336    notifier->read_selectable();
337    notifier->write_unselectable();
338  }
339  else
340                fprintf(stderr,"Couldn't start notifier\n");
341 
342  return notifier;
343}
344//}}}///////////////////////////////////
345
346void tcpip_protocol::end_notify()
347//{{{
348{
349  if (notifier)
350    delete notifier;
351  notifier = 0;
352
353  notify_len = 0;
354}
355//}}}///////////////////////////////////
356
357int tcpip_protocol::handle_notification()
358//{{{
359{
360  if (!notifier)
361    return 0;
362   
363  if (notifier->ready_to_read())
364  {
365    char buf[513];
366    int len;
367    // got a notification request "broadcast"
368    ip_address *addr;
369
370#ifdef TCPIP_DEBUG
371                printf("Notifier: ");
372#endif
373
374    len = notifier->read(buf, 512, (net_address**)&addr);
375#ifdef TCPIP_DEBUG
376                if (len>0) {
377                        buf[len] = 0;
378                        printf("[%s] ",buf);
379                }
380#endif
381    if (addr && len>0)
382    {
383                        buf[len] = 0;
384      if  (strcmp(buf, notify_signature)==0) {
385                                char s[256];
386#ifdef TCPIP_DEBUG
387                                addr->store_string(s,256);
388                                printf("responding to %s",s);
389#endif
390        // send notification data to requester
391        notifier->write(notify_data,notify_len,addr);
392                        }
393       
394      delete addr;
395    }
396#ifdef TCPIP_DEBUG
397                printf("\n");
398#endif
399    return 1;
400  }
401  if (notifier->error())
402  {
403    fprintf(stderr,"Error on notification socket!\n");
404    return 1;
405  }
406
407  return 0;
408}
409//}}}///////////////////////////////////
410
411net_address *tcpip_protocol::find_address(int port, char *name)
412//{{{
413{
414  // name should be a 256 byte buffer
415        char s[256];
416
417        end_notify();
418
419  if (!responder) {
420//#ifdef TCPIP_DEBUG
421                fprintf(stderr,"Creating responder on port %d\n",port);
422//#endif
423    responder = create_listen_socket(port, net_socket::SOCKET_FAST);
424                responder->read_selectable();
425                responder->write_unselectable();
426    bcast = (ip_address *)get_local_address();
427    bcast->set_port(port);
428   
429//#ifdef TCPIP_DEBUG
430                *((unsigned char *)(&bcast->addr.sin_addr)+3) = 255;
431                bcast->store_string(s,256);
432                fprintf(stderr,"Simulating broadcast to [%s]\n",s);
433//#endif
434
435                *((unsigned char *)(&bcast->addr.sin_addr)+3) = 0;             
436        }
437
438  if (responder)
439  {
440    int i;
441   
442    for (i=0; i<5; i++)
443    {
444#ifdef TCPIP_DEBUG
445                        bcast->store_string(s,256);
446                        fprintf(stderr,"\r[%s]",s);
447#endif
448            int found = 0;
449           
450            for (p_request p = servers.begin(); !found && p!=servers.end(); ++p)
451                if ( *((*p)->addr) == *bcast )
452                        found = 1;
453            for (p_request q = returned.begin(); !found && q!=returned.end(); ++q)
454                if ( *((*q)->addr) == *bcast )
455                        found = 1;
456                       
457                        if (!found) {
458                                responder->write((void*)notify_signature,
459                                                                                                 strlen(notify_signature),bcast);
460                                select(0);
461                        }
462            *((unsigned char *)(&bcast->addr.sin_addr)+3) += 1;
463       
464            select(0);
465           
466            if (!servers.empty())
467                break;
468                }
469  }
470 
471  if (servers.empty())
472    return 0;
473
474  servers.move_next(servers.begin_prev(), returned.begin_prev());
475        ip_address *ret = (ip_address*)(*returned.begin())->addr->copy();
476        strcpy(name,(*returned.begin())->name);
477
478#ifdef TCPIP_DEBUG
479        ret->store_string(s,256);
480        fprintf(stderr,"Found [%s]\n",s);
481#endif
482
483  return ret;
484}
485//}}}///////////////////////////////////
486
487void tcpip_protocol::reset_find_list()
488//{{{
489{
490        p_request p;
491       
492        for (p=servers.begin(); p!=servers.end(); ++p)
493                delete (*p)->addr;
494        for (p=returned.begin(); p!=returned.end(); ++p)
495                delete (*p)->addr;
496               
497  servers.erase_all();
498  returned.erase_all();
499}
500//}}}///////////////////////////////////
501
502int tcpip_protocol::handle_responder()
503//{{{
504{
505  if (!responder)
506    return 0;
507   
508  if (responder->ready_to_read())
509  {
510    char buf[513];
511    int len;
512    // got a notification response
513    ip_address *addr;
514
515#ifdef TCPIP_DEBUG
516                fprintf(stderr,"Responder: ");
517#endif
518
519    len = responder->read(buf, 512, (net_address**)&addr);
520
521#ifdef TCPIP_DEBUG
522                if (len>0) {
523                        buf[len] = 0;
524                        fprintf(stderr,"[%s] ",buf);
525                }
526#endif
527    if (addr && len>0)
528    {
529        buf[len] = 0;
530      buf[4] = 0;                                                                                               // ack! hard coded numbers for now
531      if (strcmp(buf,notify_response)==0)
532      {
533        int found=0;
534        for (p_request p = servers.begin(); !found && p!=servers.end(); ++p)
535                if ( *((*p)->addr) == *addr)
536                        found = 1;
537                    for (p_request q = returned.begin(); !found && q!=returned.end(); ++q)
538                        if ( *((*q)->addr) == *addr )
539                                found = 1;
540                       
541        if (!found)
542        {
543                                        char s[256];
544                                        RequestItem *r = new RequestItem;
545                                        r->addr = addr;
546                                        strcpy(r->name,buf+5);                                  // ack hard coded numbers for now
547              servers.insert(r);
548#ifdef TCPIP_DEBUG
549                                        addr->store_string(s,256);
550                                        fprintf(stderr,"accepted %s",s);
551#endif
552                                }
553                        }
554      else {
555        delete addr;
556                        }
557    }
558#ifdef TCPIP_DEBUG
559    fprintf(stderr,"\n");
560#endif
561
562    return 1;
563  }
564  if (responder->error())
565  {
566    fprintf(stderr,"Error on responder socket!\n");
567    return 1;
568  }
569
570  return 0;
571}
572//}}}///////////////////////////////////
573
574tcpip_protocol::tcpip_protocol()
575//{{{
576  : notifier(0), notify_len(0), responder(0)
577{
578#ifdef __POWERPC__
579  GUSISetup(GUSIwithSIOUXSockets);
580  GUSISetup(GUSIwithPPCSockets);
581#endif 
582  FD_ZERO(&master_set); 
583  FD_ZERO(&master_write_set); 
584  FD_ZERO(&read_set);
585  FD_ZERO(&exception_set);
586  FD_ZERO(&write_set);
587}
588//}}}///////////////////////////////////
589
590int tcpip_protocol::select(int block)
591//{{{
592{
593  int ret;
594 
595  memcpy(&read_set,&master_set,sizeof(master_set));
596  memcpy(&exception_set,&master_set,sizeof(master_set));
597  memcpy(&write_set,&master_write_set,sizeof(master_set));
598  if (block)
599  {
600    ret = 0;
601    while (ret == 0) {
602      // get number of sockets ready from system call
603      ret = ::select(FD_SETSIZE,&read_set,&write_set,&exception_set,NULL);
604
605      // remove notifier & responder events from the count of sockets selected
606      if (handle_notification())
607        ret--;
608      if (handle_responder())
609        ret--;
610    }
611  }
612  else
613  {
614    timeval tv={0,0};
615    // get number of sockets ready from system call
616    ret = ::select(FD_SETSIZE,&read_set,&write_set,&exception_set,&tv);
617
618    // remove notifier & responder events from the count of sockets selected
619    if (handle_notification())
620      ret--;
621    if (handle_responder())
622      ret--;
623  }
624  return ret;
625}
626//}}}///////////////////////////////////
627
628void tcpip_protocol::cleanup()
629//{{{
630{
631        if (notifier)
632                end_notify();
633               
634        reset_find_list();
635               
636        if (responder) {
637                delete responder;
638                delete bcast;
639                responder = 0;
640        }
641}
642//}}}///////////////////////////////////
643
644//{{{ Revision Log
645/*//////////////////////////////////////////////////////////////////////
646$Log$
647//////////////////////////////////////////////////////////////////////
648*/
649//}}}
650
651//{{{ Emacs Locals
652// Local Variables:
653// folded-file: t
654// End:
655//}}}
656
Note: See TracBrowser for help on using the repository browser.