tcpip.cc 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698
  1. /********************************************************************** <BR>
  2. This file is part of Crack dot Com's free source code release of
  3. Golgotha. <a href="http://www.crack.com/golgotha_release"> <BR> for
  4. information about compiling & licensing issues visit this URL</a>
  5. <PRE> If that doesn't help, contact Jonathan Clark at
  6. golgotha_source@usa.net (Subject should have "GOLG" in it)
  7. ***********************************************************************/
  8. #define PTHREAD_KERNEL /* Needed for OK and NOTOK defines */
  9. #ifndef _WINDOWS
  10. #define SIZE_TYPE unsigned int
  11. #include <unistd.h>
  12. #include <pthread.h>
  13. #include <string.h>
  14. #include <stdio.h>
  15. #include <netdb.h>
  16. #include <errno.h>
  17. #include <netinet/in.h>
  18. #include <sys/time.h>
  19. #include <sys/types.h>
  20. #include <unistd.h>
  21. #define closesocket ::close
  22. #define OPTION_TYPE int
  23. #else
  24. #include <io.h>
  25. #include <windows.h>
  26. #define OPTION_TYPE BOOL
  27. #define SIZE_TYPE int
  28. #endif
  29. #include "error/error.hh"
  30. #include "network/net_prot.hh"
  31. #include "network/net_find.hh"
  32. #include "network/net_addr.hh"
  33. #include "network/net_sock.hh"
  34. #include "time/time.hh"
  35. #include "memory/array.hh"
  36. class i4_tcpip_protocol;
  37. extern i4_tcpip_protocol i4_tcpip_protocol_instance;
  38. static int i4_get_my_addr(sockaddr_in &host)
  39. {
  40. char buf[256];
  41. if (gethostname(buf, sizeof(buf))==0)
  42. {
  43. hostent *hp=gethostbyname(buf);
  44. if (hp)
  45. {
  46. memset( (char*) &host,0, sizeof(host));
  47. memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
  48. return 1;
  49. }
  50. }
  51. return 0;
  52. }
  53. class i4_tcpip_address : public i4_net_address
  54. {
  55. public:
  56. sockaddr_in addr;
  57. virtual i4_net_address *copy()
  58. {
  59. i4_tcpip_address *a=new i4_tcpip_address;
  60. a->addr=addr;
  61. a->protocol=protocol;
  62. return a;
  63. }
  64. virtual void set_port(int port)
  65. {
  66. addr.sin_port = htons(port);
  67. }
  68. virtual i4_bool equals(i4_net_address *other)
  69. {
  70. i4_tcpip_address *to=(i4_tcpip_address *)other;
  71. if (protocol==other->protocol && addr.sin_addr.s_addr==to->addr.sin_addr.s_addr)
  72. return i4_T;
  73. else return i4_F;
  74. }
  75. };
  76. class i4_tcpip_sock : public i4_net_socket
  77. {
  78. int fd;
  79. i4_socket_type stype;
  80. i4_net_protocol *protocol;
  81. i4_tcpip_protocol *prot() { return (i4_tcpip_protocol *)protocol; }
  82. public:
  83. int er;
  84. void set_select_status(i4_bool read, i4_bool write, i4_bool error);
  85. int listen(int port)
  86. {
  87. OPTION_TYPE opt=1;
  88. if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))!=0)
  89. {
  90. i4_warning("setsockopt reuse failed");
  91. return 0;
  92. }
  93. sockaddr_in host;
  94. memset( (char*) &host,0, sizeof(host));
  95. host.sin_family = AF_INET;
  96. host.sin_port = htons(port);
  97. host.sin_addr.s_addr = htonl (INADDR_ANY);
  98. if (bind(fd, (sockaddr *) &host, sizeof(host))==-1)
  99. {
  100. i4_warning("bind failed");
  101. return 0;
  102. }
  103. if (stype==I4_CONTINOUS_STREAM && ::listen(fd, 5)==-1)
  104. {
  105. i4_warning("listen failed");
  106. return 0;
  107. }
  108. return 1;
  109. }
  110. i4_bool connect(i4_net_address *addr)
  111. {
  112. i4_tcpip_address *a = (i4_tcpip_address *)addr;
  113. if ((i4_tcpip_protocol *)a->protocol==&i4_tcpip_protocol_instance)
  114. {
  115. if (::connect(fd, (sockaddr *) &(a->addr), sizeof(a->addr))==-1)
  116. return i4_F;
  117. return i4_T;
  118. }
  119. else
  120. i4_warning("address from another protocol");
  121. return i4_F;
  122. }
  123. i4_tcpip_sock(i4_socket_type stype,
  124. i4_net_protocol *protocol)
  125. : protocol(protocol), stype(stype)
  126. {
  127. fd=socket(AF_INET, stype==I4_CONTINOUS_STREAM ? SOCK_STREAM : SOCK_DGRAM, 0);
  128. if (fd<0)
  129. {
  130. i4_warning("out of sockets");
  131. er=1;
  132. }
  133. else er=0;
  134. }
  135. i4_tcpip_sock(int fd, i4_socket_type stype, i4_net_protocol *protocol)
  136. : fd(fd), stype(stype), protocol(protocol)
  137. { ; }
  138. i4_bool accept(i4_net_socket *&sock, i4_net_address *&addr)
  139. {
  140. sockaddr_in a;
  141. SIZE_TYPE size=sizeof(a);
  142. int new_fd=::accept(fd, (sockaddr *)&a, &size);
  143. if (new_fd==-1)
  144. return i4_F;
  145. sock=new i4_tcpip_sock(new_fd, stype, protocol);
  146. addr=new i4_tcpip_address;
  147. ((i4_tcpip_address *)addr)->addr=a;
  148. addr->protocol=protocol;
  149. return i4_T;
  150. }
  151. ~i4_tcpip_sock()
  152. {
  153. if (fd!=-1)
  154. closesocket(fd);
  155. }
  156. virtual w32 read_from(void *buffer, w32 size, i4_net_address *&addr)
  157. {
  158. sockaddr_in a;
  159. SIZE_TYPE as=sizeof(a);
  160. int s=recvfrom(fd, (char *)buffer, size, 0, (sockaddr *)&a, &as);
  161. addr=new i4_tcpip_address;
  162. ((i4_tcpip_address *)addr)->addr=a;
  163. addr->protocol=protocol;
  164. return s;
  165. }
  166. virtual w32 read (void *buffer, w32 size)
  167. {
  168. return recv(fd, (char *)buffer, size, 0);
  169. }
  170. virtual w32 write(const void *buffer, w32 size)
  171. {
  172. return send(fd, (char *)buffer, size, 0);
  173. }
  174. virtual i4_bool ready_to_read()
  175. {
  176. fd_set s;
  177. struct timeval tv={0,0};
  178. FD_ZERO(&s);
  179. FD_SET(fd, &s);
  180. select(fd+1, &s, NULL, NULL, &tv);
  181. return FD_ISSET(fd, &s);
  182. }
  183. virtual i4_bool ready_to_write()
  184. {
  185. fd_set s;
  186. struct timeval tv={0,0};
  187. FD_ZERO(&s);
  188. FD_SET(fd, &s);
  189. select(fd+1, NULL, &s, NULL, &tv);
  190. return FD_ISSET(fd, &s);
  191. }
  192. virtual i4_bool error_occurred()
  193. {
  194. fd_set s;
  195. struct timeval tv={0,0};
  196. FD_ZERO(&s);
  197. FD_SET(fd, &s);
  198. select(fd+1, NULL, NULL, &s, &tv);
  199. return FD_ISSET(fd, &s);
  200. }
  201. };
  202. class i4_reply_str : public i4_str
  203. {
  204. public:
  205. i4_reply_str(char *buf, int _len)
  206. : i4_str(_len)
  207. {
  208. len=_len;
  209. memcpy(ptr, buf, len);
  210. }
  211. void *data() { return ptr; }
  212. };
  213. class i4_tcpip_finder : public i4_finder_socket
  214. {
  215. int poll_fd, listen_fd, listen_port;
  216. int t;
  217. sockaddr_in my_addr;
  218. i4_array<server> replies;
  219. i4_time_class last_ping;
  220. i4_net_protocol *protocol;
  221. public:
  222. int er;
  223. int total_servers()
  224. {
  225. return replies.size();
  226. }
  227. virtual void get_server(int num, server &s)
  228. {
  229. s=replies[num];
  230. }
  231. ~i4_tcpip_finder()
  232. {
  233. if (poll_fd!=-1) closesocket(poll_fd);
  234. if (listen_fd!=-1) closesocket(listen_fd);
  235. for (int i=0; i<replies.size(); ++i)
  236. {
  237. delete replies[i].notification_string;
  238. delete replies[i].addr;
  239. }
  240. }
  241. int setup(int poll_port, int listen_port)
  242. {
  243. poll_fd=-1; listen_fd=-1;
  244. if (!i4_get_my_addr(my_addr))
  245. { i4_warning("couldn't get my ip"); return 0; }
  246. poll_fd=socket(AF_INET, SOCK_DGRAM, 0);
  247. if (poll_fd<0)
  248. { i4_warning("out of sockets"); return 0; }
  249. sockaddr_in host;
  250. memset( (char*) &host,0, sizeof(host));
  251. host.sin_family = AF_INET;
  252. host.sin_port = htons(poll_port);
  253. host.sin_addr.s_addr = htonl (INADDR_BROADCAST);
  254. OPTION_TYPE opt=1;
  255. if (setsockopt(poll_fd, SOL_SOCKET, SO_BROADCAST, (char *)&opt, sizeof(opt))!=0)
  256. { i4_warning("setsockopt broadcast failed"); return 0; }
  257. opt=1;
  258. if (setsockopt(poll_fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))!=0)
  259. { i4_warning("setsockopt reuse failed"); return 0; }
  260. if (connect(poll_fd, (sockaddr *) &host, sizeof(host))==-1)
  261. { i4_warning("connect failed"); return 0; }
  262. listen_fd=socket(AF_INET, SOCK_DGRAM, 0);
  263. if (listen_fd<0)
  264. { i4_warning("out of sockets"); return 0; }
  265. host.sin_port = htons(listen_port);
  266. host.sin_addr.s_addr = htonl (INADDR_ANY);
  267. if (bind(listen_fd, (sockaddr *) &host, sizeof(host))==-1)
  268. { i4_warning("bind failed"); return 0; }
  269. last_ping.get();
  270. return 1;
  271. }
  272. i4_tcpip_finder(int poll_port, int listen_port, i4_net_protocol *protocol)
  273. : replies(32, 64),
  274. listen_port(listen_port),
  275. protocol(protocol)
  276. {
  277. er=!setup(poll_port, listen_port);
  278. }
  279. i4_bool poll()
  280. {
  281. fd_set read_set;
  282. FD_ZERO(&read_set);
  283. FD_SET(listen_fd, &read_set);
  284. struct timeval tv={0,0};
  285. // see if there are any responses from servers
  286. select(FD_SETSIZE,&read_set,0, 0, &tv);
  287. if (FD_ISSET(listen_fd, &read_set))
  288. {
  289. w8 buf[512];
  290. i4_tcpip_address r;
  291. SIZE_TYPE from_len=sizeof(sockaddr_in);
  292. if (recvfrom(listen_fd, (char *)buf, sizeof(buf), 0, (sockaddr *)&r.addr, &from_len)>2)
  293. {
  294. w16 s_len=(buf[0]<<8) | buf[1];
  295. if (s_len<510) // if this more than 510 then bad data in packet
  296. {
  297. int found=0;
  298. if (r.addr.sin_addr.s_addr==my_addr.sin_addr.s_addr)
  299. found=1;
  300. // see if we already found heard from this guy
  301. for (int i=0; i<replies.size(); i++)
  302. if (r.addr.sin_addr.s_addr==
  303. ((i4_tcpip_address *)replies[i].addr)->addr.sin_addr.s_addr)
  304. found=1;
  305. if (!found)
  306. {
  307. server s;
  308. s.notification_string=new i4_reply_str((char *)buf+2, s_len);
  309. s.addr=new i4_tcpip_address(r);
  310. s.addr->protocol=protocol;
  311. replies.add(s);
  312. return i4_T;
  313. }
  314. }
  315. }
  316. }
  317. i4_time_class now;
  318. if (now.milli_diff(last_ping) > 1000) // ping once a second
  319. {
  320. w8 reply_port[2];
  321. reply_port[0]=(listen_port>>8);
  322. reply_port[1]=(listen_port&0xff);
  323. if (send(poll_fd, (char *)reply_port, 2, 0)!=2)
  324. i4_warning("ping server error");
  325. last_ping.get();
  326. }
  327. return i4_F;
  328. }
  329. };
  330. class i4_tcpip_notifier : public i4_notifier_socket
  331. {
  332. int fd;
  333. w8 reply_packet[512];
  334. public:
  335. int er;
  336. ~i4_tcpip_notifier()
  337. {
  338. if (fd==-1) closesocket(fd);
  339. }
  340. int setup(int port, const i4_const_str &notification_string)
  341. {
  342. fd=-1;
  343. fd=socket(AF_INET, SOCK_DGRAM, 0);
  344. if (fd<0)
  345. { i4_warning("out of sockets"); return 0; }
  346. OPTION_TYPE opt=1;
  347. if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))!=0)
  348. { i4_warning("setsockopt reuse failed"); return 0; }
  349. sockaddr_in host;
  350. memset( (char*) &host,0, sizeof(host));
  351. host.sin_family = AF_INET;
  352. host.sin_port = htons(port);
  353. host.sin_addr.s_addr = htonl (INADDR_ANY);
  354. if (bind(fd, (sockaddr *) &host, sizeof(host))==-1)
  355. { i4_warning("notify bind failed"); return 0; }
  356. int s_len=notification_string.length();
  357. reply_packet[0]=s_len>>8;
  358. reply_packet[1]=s_len&0xff;
  359. memcpy(reply_packet+2, ((i4_reply_str *)&notification_string)->data(), s_len);
  360. return 1;
  361. }
  362. i4_tcpip_notifier(int port, const i4_const_str &notification_string)
  363. {
  364. er=!setup(port, notification_string);
  365. }
  366. virtual int poll()
  367. {
  368. fd_set read_set;
  369. FD_ZERO(&read_set);
  370. FD_SET(fd, &read_set);
  371. struct timeval tv={0,0};
  372. // see if there are any clients pinging us
  373. select(FD_SETSIZE,&read_set,0, 0, &tv);
  374. if (FD_ISSET(fd, &read_set))
  375. {
  376. w8 buf[512];
  377. sockaddr_in host;
  378. SIZE_TYPE from_len=sizeof(sockaddr_in);
  379. if (recvfrom(fd, (char *)buf, sizeof(buf), 0, (sockaddr *)&host, &from_len)==2)
  380. {
  381. int reply_port=(buf[0]<<8)|buf[1];
  382. host.sin_port=htons(reply_port);
  383. sendto(fd, (char *)reply_packet, sizeof(reply_packet), 0, (sockaddr *)&host, sizeof(host));
  384. return 1;
  385. }
  386. }
  387. return 0;
  388. }
  389. };
  390. #ifdef __linux
  391. #include <stdio.h>
  392. #include <string.h>
  393. // linux gethostname doesn't seem to be thread-safe, so I'm making a system call
  394. int linux_name_to_address(char *hostname, unsigned int &ip)
  395. {
  396. char buf[200];
  397. sprintf(buf, "nslookup -ret=2 -timeout=2 %s", hostname);
  398. fprintf(stderr,"\n*** %s **\n",buf);
  399. FILE *fp=popen(buf, "rb");
  400. fprintf(stderr,"\n*** popen done fp=%p**\n",fp);
  401. if (!fp) return 0;
  402. while (!feof(fp))
  403. {
  404. fgets(buf,200,fp);
  405. fprintf(stderr,"\n*** fgets %s**\n",buf);
  406. if (strstr(buf, hostname))
  407. {
  408. fgets(buf,200,fp);
  409. buf[strlen(buf)-1]=0;
  410. char *c;
  411. for (c=buf; *c!=':'; c++); c++;
  412. for (; *c==' '; c++);
  413. int i1,i2,i3,i4;
  414. sscanf(c,"%d.%d.%d.%d", &i1,&i2,&i3,&i4);
  415. char ret[4];
  416. ret[0]=i1; ret[1]=i2; ret[2]=i3; ret[3]=i4;
  417. fclose(fp);
  418. ip= *((unsigned long *)ret);
  419. fprintf(stderr,"\n*** found ip **\n");
  420. return 1;
  421. }
  422. }
  423. fclose(fp);
  424. return 0;
  425. }
  426. #endif
  427. class i4_tcpip_protocol : public i4_net_protocol
  428. {
  429. int err;
  430. public:
  431. fd_set rfdset, wfdset, efdset;
  432. int max_fd;
  433. int select(int milli_sec_timeout)
  434. {
  435. if (!milli_sec_timeout)
  436. return ::select(max_fd, &rfdset, &wfdset, &efdset, 0);
  437. else
  438. {
  439. int secs=milli_sec_timeout/1000;
  440. int usecs=(milli_sec_timeout-(secs*1000)) *1000;
  441. struct timeval tv={secs, usecs};
  442. return ::select(max_fd, &rfdset, &wfdset, &efdset, &tv);
  443. }
  444. }
  445. i4_tcpip_protocol()
  446. {
  447. max_fd=0;
  448. FD_ZERO(&rfdset);
  449. FD_ZERO(&wfdset);
  450. FD_ZERO(&efdset);
  451. #ifdef _WINDOWS
  452. WSADATA wsaData;
  453. WORD ver=MAKEWORD(1,1);
  454. err=WSAStartup(ver, &wsaData);
  455. #else
  456. err=0;
  457. #endif
  458. }
  459. ~i4_tcpip_protocol()
  460. {
  461. #ifdef _WINDOWS
  462. if (!err)
  463. WSACleanup();
  464. #endif
  465. }
  466. i4_notifier_socket *create_notifier_socket(int port, const i4_const_str &notification_string)
  467. {
  468. if (err) return 0;
  469. i4_tcpip_notifier *n=new i4_tcpip_notifier(port, notification_string);
  470. if (n->er)
  471. {
  472. delete n;
  473. return 0;
  474. }
  475. else
  476. return n;
  477. }
  478. i4_finder_socket *create_finder_socket(int poll_port, int listen_port)
  479. {
  480. if (err) return 0;
  481. i4_tcpip_finder *f=new i4_tcpip_finder(poll_port, listen_port, this);
  482. if (f->er)
  483. {
  484. delete f;
  485. return 0;
  486. }
  487. else
  488. return f;
  489. }
  490. virtual i4_net_address *name_to_address(const i4_const_str &name)
  491. {
  492. if (err) return 0;
  493. sockaddr_in host;
  494. memset( (char*) &host,0, sizeof(host));
  495. char buf[256];
  496. i4_os_string(name, buf, 256);
  497. // if (linux_name_to_address(buf, host.sin_addr.s_addr))
  498. // {
  499. hostent *hp=gethostbyname(buf);
  500. if (hp)
  501. {
  502. memcpy(&host.sin_addr,hp->h_addr,hp->h_length);
  503. host.sin_family = AF_INET;
  504. i4_tcpip_address *a=new i4_tcpip_address;
  505. a->addr=host;
  506. a->protocol=this;
  507. return a;
  508. }
  509. return 0;
  510. }
  511. i4_net_socket *connect(i4_net_address *addr, i4_socket_type stype)
  512. {
  513. if (err) return 0;
  514. if (addr->protocol==this)
  515. {
  516. i4_tcpip_sock *s=new i4_tcpip_sock(stype, this);
  517. if (s->er || !s->connect((i4_tcpip_address *)addr))
  518. {
  519. delete s;
  520. return 0;
  521. } else return s;
  522. }
  523. else i4_warning("address from another protocol");
  524. return 0;
  525. }
  526. i4_net_socket *listen(int port, i4_socket_type stype)
  527. {
  528. if (err) return 0;
  529. i4_tcpip_sock *s=new i4_tcpip_sock(stype, this);
  530. if (s->er || !s->listen(port))
  531. {
  532. delete s;
  533. return 0;
  534. } else return s;
  535. }
  536. char *name() { return "TCP/IP"; }
  537. i4_protocol_type type() { return I4_TCPIP; }
  538. };
  539. i4_tcpip_protocol i4_tcpip_protocol_instance;
  540. void i4_tcpip_sock::set_select_status(i4_bool read, i4_bool write, i4_bool error)
  541. {
  542. i4_tcpip_protocol *p=prot();
  543. if (read)
  544. FD_SET(fd, &p->rfdset);
  545. else
  546. FD_CLR(fd, &p->rfdset);
  547. if (write)
  548. FD_SET(fd, &p->wfdset);
  549. else
  550. FD_CLR(fd, &p->wfdset);
  551. if (error)
  552. FD_SET(fd, &p->efdset);
  553. else
  554. FD_CLR(fd, &p->efdset);
  555. if (fd>=p->max_fd)
  556. p->max_fd=fd+1;
  557. }