client_connect.c
上传用户:tany51
上传日期:2013-06-12
资源大小:1397k
文件大小:16k
源码类别:

MySQL数据库

开发平台:

Visual C++

  1. /*
  2.  * Copyright (C) 1998,1999,2000,2001  Ross Combs (rocombs@cs.nmsu.edu)
  3.  *
  4.  * This program is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU General Public License
  6.  * as published by the Free Software Foundation; either version 2
  7.  * of the License, or (at your option) any later version.
  8.  *
  9.  * This program is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12.  * GNU General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU General Public License
  15.  * along with this program; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  17.  */
  18. #include "common/setup_before.h"
  19. #include <stdio.h>
  20. #ifdef STDC_HEADERS
  21. # include <stdlib.h>
  22. #endif
  23. #ifdef HAVE_MEMORY_H
  24. # include <memory.h>
  25. #endif
  26. #include "compat/memset.h"
  27. #include "compat/memcpy.h"
  28. #include <ctype.h>
  29. #ifdef HAVE_STRING_H
  30. # include <string.h>
  31. #endif
  32. #include <errno.h>
  33. #include "compat/strerror.h"
  34. #ifdef TIME_WITH_SYS_TIME
  35. # include <sys/time.h>
  36. # include <time.h>
  37. #else
  38. # ifdef HAVE_SYS_TIME_H
  39. #  include <sys/time.h>
  40. # else
  41. #  include <time.h>
  42. # endif
  43. #endif
  44. #ifdef HAVE_UNISTD_H
  45. # include <unistd.h>
  46. #endif
  47. #include "compat/gethostname.h"
  48. #ifdef HAVE_SYS_TYPES_H
  49. # include <sys/types.h>
  50. #endif
  51. #ifdef HAVE_SYS_SOCKET_H
  52. # include <sys/socket.h>
  53. #endif
  54. #include "compat/socket.h"
  55. #ifdef HAVE_SYS_PARAM_H
  56. # include <sys/param.h>
  57. #endif
  58. #ifdef HAVE_NETINET_IN_H
  59. # include <netinet/in.h>
  60. #endif
  61. #include "compat/netinet_in.h"
  62. #ifdef HAVE_ARPA_INET_H
  63. # include <arpa/inet.h>
  64. #endif
  65. #include "compat/inet_ntoa.h"
  66. #ifdef HAVE_NETDB_H
  67. # include <netdb.h>
  68. #endif
  69. #include "compat/psock.h"
  70. #include "common/packet.h"
  71. #include "common/init_protocol.h"
  72. #include "common/udp_protocol.h"
  73. #include "common/bnet_protocol.h"
  74. #include "common/file_protocol.h"
  75. #include "common/tag.h"
  76. #include "common/bn_type.h"
  77. #include "common/field_sizes.h"
  78. #include "common/bnethash.h"
  79. #include "common/bnethashconv.h"
  80. #include "common/util.h"
  81. #ifdef CLIENTDEBUG
  82. # include "common/eventlog.h"
  83. #endif
  84. #include "client.h"
  85. #include "udptest.h"
  86. #include "common/bnettime.h"
  87. #include "common/proginfo.h"
  88. #include "client_connect.h"
  89. #include "common/setup_after.h"
  90. #define COMPNAMELEN 128
  91. #ifdef CLIENTDEBUG
  92. # define dprintf printf
  93. #else
  94. # define dprintf if (0) printf
  95. #endif
  96. static int key_interpret(char const * cdkey, unsigned int * productid, unsigned int * keyvalue1, unsigned int * keyvalue2)
  97. {
  98.     /* FIXME: implement... have example code from Eurijk! */
  99.     *productid = 0;
  100.     *keyvalue1 = 0;
  101.     *keyvalue2 = 0;
  102.     return 0;
  103. }
  104. static int get_defversioninfo(char const * progname, char const * clienttag, unsigned int * versionid, unsigned int * gameversion, char const * * exeinfo, unsigned int * checksum)
  105. {
  106.     if (strcmp(clienttag,CLIENTTAG_DIABLORTL)==0)
  107.     {
  108. *versionid = CLIENT_VERSIONID_DRTL;
  109. *gameversion = CLIENT_GAMEVERSION_DRTL;
  110. *exeinfo = CLIENT_EXEINFO_DRTL;
  111. *checksum = CLIENT_CHECKSUM_DRTL;
  112. return 0;
  113.     }
  114.     
  115.     if (strcmp(clienttag,CLIENTTAG_STARCRAFT)==0)
  116.     {
  117. *versionid = CLIENT_VERSIONID_STAR;
  118. *gameversion = CLIENT_GAMEVERSION_STAR;
  119. *exeinfo = CLIENT_EXEINFO_STAR;
  120. *checksum = CLIENT_CHECKSUM_STAR;
  121. return 0;
  122.     }
  123.     
  124.     if (strcmp(clienttag,CLIENTTAG_SHAREWARE)==0)
  125.     {
  126. *versionid = CLIENT_VERSIONID_SSHR;
  127. *gameversion = CLIENT_GAMEVERSION_SSHR;
  128. *exeinfo = CLIENT_EXEINFO_SSHR;
  129. *checksum = CLIENT_CHECKSUM_SSHR;
  130. return 0;
  131.     }
  132.     
  133.     if (strcmp(clienttag,CLIENTTAG_BROODWARS)==0)
  134.     {
  135. *versionid = CLIENT_VERSIONID_SEXP;
  136. *gameversion = CLIENT_GAMEVERSION_SEXP;
  137. *exeinfo = CLIENT_EXEINFO_SEXP;
  138. *checksum = CLIENT_CHECKSUM_SEXP;
  139. return 0;
  140.     }
  141.     
  142.     if (strcmp(clienttag,CLIENTTAG_WARCIIBNE)==0)
  143.     {
  144. *versionid = CLIENT_VERSIONID_W2BN;
  145. *gameversion = CLIENT_GAMEVERSION_W2BN;
  146. *exeinfo = CLIENT_EXEINFO_W2BN;
  147. *checksum = CLIENT_CHECKSUM_W2BN;
  148. return 0;
  149.     }
  150.     
  151.     if (strcmp(clienttag,CLIENTTAG_DIABLO2DV)==0)
  152.     {
  153. *versionid = CLIENT_VERSIONID_D2DV;
  154. *gameversion = CLIENT_GAMEVERSION_D2DV;
  155. *exeinfo = CLIENT_EXEINFO_D2DV;
  156. *checksum = CLIENT_CHECKSUM_D2DV;
  157. return 0;
  158.     }
  159.     
  160.     if (strcmp(clienttag,CLIENTTAG_DIABLO2XP)==0)
  161.     {
  162. *versionid = CLIENT_VERSIONID_D2XP;
  163. *gameversion = CLIENT_GAMEVERSION_D2XP;
  164. *exeinfo = CLIENT_EXEINFO_D2XP;
  165. *checksum = CLIENT_CHECKSUM_D2XP;
  166. return 0;
  167.     }
  168.     
  169.     if (strcmp(clienttag,CLIENTTAG_WARCRAFT3)==0)
  170.     {
  171. *versionid = CLIENT_VERSIONID_WAR3;
  172. *gameversion = CLIENT_GAMEVERSION_WAR3;
  173. *exeinfo = CLIENT_EXEINFO_WAR3;
  174. *checksum = CLIENT_CHECKSUM_WAR3;
  175. return 0;
  176.     }
  177.     
  178.     *versionid = 0;
  179.     *gameversion = 0;
  180.     *exeinfo = "";
  181.     *checksum = 0;
  182.     
  183.     fprintf(stderr,"%s: unsupported clienttag "%s"n",progname,clienttag);
  184.     // aaron: dunno what we should return in case of this.. but returning nothing was definetly wrong
  185.     return -1;
  186. }
  187. extern int client_connect(char const * progname, char const * servname, unsigned short servport, char const * cdowner, char const * cdkey, char const * clienttag, struct sockaddr_in * saddr, unsigned int * sessionkey, unsigned int * sessionnum, char const * archtag)
  188. {
  189.     struct hostent * host;
  190.     char const *     username;
  191.     int              sd;
  192.     t_packet *       packet;
  193.     t_packet *       rpacket;
  194.     char             compname[COMPNAMELEN];
  195.     int              lsock;
  196.     unsigned short   lsock_port;
  197.     unsigned int     versionid;
  198.     unsigned int     gameversion;
  199.     char const *     exeinfo;
  200.     unsigned int     checksum;
  201.     
  202.     if (!progname)
  203.     {
  204. fprintf(stderr,"got NULL prognamen");
  205. return -1;
  206.     }
  207.     if (!saddr)
  208.     {
  209. fprintf(stderr,"%s: got NULL saddrn",progname);
  210. return -1;
  211.     }
  212.     if (!sessionkey)
  213.     {
  214. fprintf(stderr,"%s: got NULL sessionkeyn",progname);
  215. return -1;
  216.     }
  217.     if (!sessionnum)
  218.     {
  219. fprintf(stderr,"%s: got NULL sessionnumn",progname);
  220. return -1;
  221.     }
  222.     
  223.     if (psock_init()<0)
  224.     {
  225. fprintf(stderr,"%s: could not inialialize socket functionsn",progname);
  226. return -1;
  227.     }
  228.     
  229.     if (!(host = gethostbyname(servname)))
  230.     {
  231. fprintf(stderr,"%s: unknown host "%s"n",progname,servname);
  232. return -1;
  233.     }
  234.     if (host->h_addrtype!=PSOCK_AF_INET)
  235. fprintf(stderr,"%s: host "%s" is not in IPv4 address familyn",progname,servname);
  236.     
  237.     if (gethostname(compname,COMPNAMELEN)<0)
  238.     {
  239. fprintf(stderr,"%s: could not get host name (gethostname: %s)n",progname,strerror(errno));
  240. return -1;
  241.     }
  242. #ifdef HAVE_GETLOGIN
  243.     if (!(username = getlogin()))
  244. #endif
  245.     {
  246. username = "unknown";
  247. dprintf("%s: could not get login name, using "%s" (getlogin: %s)n",progname,username,strerror(errno));
  248.     }
  249.     
  250.     if ((sd = psock_socket(PSOCK_PF_INET,PSOCK_SOCK_STREAM,PSOCK_IPPROTO_TCP))<0)
  251.     {
  252. fprintf(stderr,"%s: could not create socket (psock_socket: %s)n",progname,strerror(psock_errno()));
  253. return -1;
  254.     }
  255.     
  256.     memset(saddr,0,sizeof(*saddr));
  257.     saddr->sin_family = PSOCK_AF_INET;
  258.     saddr->sin_port   = htons(servport);
  259.     memcpy(&saddr->sin_addr.s_addr,host->h_addr_list[0],host->h_length);
  260.     if (psock_connect(sd,(struct sockaddr *)saddr,sizeof(*saddr))<0)
  261.     {
  262. fprintf(stderr,"%s: could not connect to server "%s" port %hu (psock_connect: %s)n",progname,servname,servport,strerror(psock_errno()));
  263. goto error_sd;
  264.     }
  265.     
  266.     printf("Connected to %s:%hu.n",inet_ntoa(saddr->sin_addr),servport);
  267.     
  268. #ifdef CLIENTDEBUG
  269.     eventlog_set(stderr);
  270. #endif
  271.         
  272.     if ((lsock = client_udptest_setup(progname,&lsock_port))>=0)
  273. dprintf("Got UDP data on port %hun",lsock_port);
  274.     
  275.     if (!(packet = packet_create(packet_class_init)))
  276.     {
  277. fprintf(stderr,"%s: could not create packetn",progname);
  278. goto error_lsock;
  279.     }
  280.     bn_byte_set(&packet->u.client_initconn.class,CLIENT_INITCONN_CLASS_DEFER); /* == bnet */
  281.     client_blocksend_packet(sd,packet);
  282.     packet_del_ref(packet);
  283.     
  284.     /* reuse this same packet over and over */
  285.     if (!(rpacket = packet_create(packet_class_bnet)))
  286.     {
  287. fprintf(stderr,"%s: could not create packetn",progname);
  288. goto error_lsock;
  289.     }
  290.     
  291.     get_defversioninfo(progname,clienttag,&versionid,&gameversion,&exeinfo,&checksum);
  292.     if (strcmp(clienttag,CLIENTTAG_DIABLOSHR)==0 ||
  293.         strcmp(clienttag,CLIENTTAG_DIABLORTL)==0)
  294.     {
  295. if (!(packet = packet_create(packet_class_bnet)))
  296. {
  297.     fprintf(stderr,"%s: could not create packetn",progname);
  298.     goto error_rpacket;
  299. }
  300. packet_set_size(packet,sizeof(t_client_unknown_1b));
  301. packet_set_type(packet,CLIENT_UNKNOWN_1B);
  302. bn_short_set(&packet->u.client_unknown_1b.unknown1,CLIENT_UNKNOWN_1B_UNKNOWN3);
  303. bn_short_nset(&packet->u.client_unknown_1b.port,lsock_port);
  304. bn_int_nset(&packet->u.client_unknown_1b.ip,0); /* FIXME */
  305. bn_int_set(&packet->u.client_unknown_1b.unknown2,CLIENT_UNKNOWN_1B_UNKNOWN3);
  306. bn_int_set(&packet->u.client_unknown_1b.unknown3,CLIENT_UNKNOWN_1B_UNKNOWN3);
  307. client_blocksend_packet(sd,packet);
  308. packet_del_ref(packet);
  309.     }
  310.     
  311.     if (!(packet = packet_create(packet_class_bnet)))
  312.     {
  313. fprintf(stderr,"%s: could not create packetn",progname);
  314. goto error_rpacket;
  315.     }
  316.     packet_set_size(packet,sizeof(t_client_countryinfo_109));
  317.     packet_set_type(packet,CLIENT_COUNTRYINFO_109);
  318.     bn_int_set(&packet->u.client_countryinfo_109.protocol,CLIENT_COUNTRYINFO_109_PROTOCOL);
  319.     bn_int_tag_set(&packet->u.client_countryinfo_109.archtag,archtag);
  320.     bn_int_tag_set(&packet->u.client_countryinfo_109.clienttag,clienttag);
  321.    //AARON 
  322.     bn_int_set(&packet->u.client_countryinfo_109.versionid,versionid);
  323.     bn_int_set(&packet->u.client_countryinfo_109.gamelang,CLIENT_COUNTRYINFO_109_GAMELANG);
  324.     bn_int_set(&packet->u.client_countryinfo_109.localip,CLIENT_COUNTRYINFO_109_LOCALIP);
  325.     {
  326. int bias;
  327.         bias = local_tzbias();
  328.         
  329. bn_int_set(&packet->u.client_countryinfo_109.bias,(unsigned int)bias); /* rely on 2's complement */
  330. dprintf("my tzbias = %d (0x%08hx)n",bias,(unsigned int)bias);
  331.     }
  332.     /* FIXME: determine from locale */
  333.     bn_int_set(&packet->u.client_countryinfo_109.lcid,CLIENT_COUNTRYINFO_109_LANGID_USENGLISH);
  334.     bn_int_set(&packet->u.client_countryinfo_109.langid,CLIENT_COUNTRYINFO_109_LANGID_USENGLISH);
  335.     packet_append_string(packet,CLIENT_COUNTRYINFO_109_LANGSTR_USENGLISH);
  336.     /* FIXME: determine from locale+timezone... from domain name... nothing really would
  337.        work.  Maybe add some command-line options */
  338.     packet_append_string(packet,CLIENT_COUNTRYINFO_109_COUNTRYNAME_USA);
  339.     client_blocksend_packet(sd,packet);
  340.     packet_del_ref(packet);
  341.    
  342.     do
  343.         if (client_blockrecv_packet(sd,rpacket)<0)
  344. {
  345.     fprintf(stderr,"%s: server closed connectionn",progname);
  346.     goto error_rpacket;
  347. }
  348.     while (packet_get_type(rpacket)!=SERVER_AUTHREQ_109 &&
  349.    packet_get_type(rpacket)!=SERVER_AUTHREPLY_109);
  350.     
  351.     if (packet_get_type(rpacket)==SERVER_AUTHREQ_109) /* hmm... server wants to check the version number */
  352.     {
  353. dprintf("Got AUTHREQ_109n");
  354. *sessionkey = bn_int_get(rpacket->u.server_authreq_109.sessionkey);
  355. *sessionnum = bn_int_get(rpacket->u.server_authreq_109.sessionnum);
  356. /* FIXME: also get filename and equation */
  357. if (!(packet = packet_create(packet_class_bnet)))
  358. {
  359.     fprintf(stderr,"%s: could not create packetn",progname);
  360.     goto error_rpacket;
  361. }
  362. packet_set_size(packet,sizeof(t_client_authreq_109));
  363. packet_set_type(packet,CLIENT_AUTHREQ_109);
  364. bn_int_set(&packet->u.client_authreq_109.ticks,time(NULL));
  365. {
  366.             t_cdkey_info cdkey_info;
  367.     
  368.     bn_int_set(&packet->u.client_authreq_109.gameversion,gameversion);
  369.     bn_int_set(&packet->u.client_authreq_109.cdkey_number,1); /* only one */
  370.     memset(&cdkey_info,'0',sizeof(cdkey_info));
  371.     packet_append_data(packet,&cdkey,sizeof(cdkey_info)); /* cdkey - bogus for now */
  372.     packet_append_string(packet,exeinfo);
  373.     packet_append_string(packet,cdowner);
  374. }
  375. bn_int_set(&packet->u.client_authreq_109.checksum,checksum);
  376. client_blocksend_packet(sd,packet);
  377. packet_del_ref(packet);
  378. /* now wait for reply */
  379. do
  380.     if (client_blockrecv_packet(sd,rpacket)<0)
  381.     {
  382. fprintf(stderr,"%s: server closed connectionn",progname);
  383. goto error_rpacket;
  384.     }
  385. while (packet_get_type(rpacket)!=SERVER_AUTHREPLY_109);
  386.       //FIXME: check if AUTHREPLY_109 is success or fail
  387.       if (bn_int_get(rpacket->u.server_authreply_109.message)!=SERVER_AUTHREPLY_109_MESSAGE_OK)
  388.       {
  389.          fprintf(stderr,"AUTHREPLY_109 failed - closing connectionn");
  390.          goto error_rpacket;
  391.       }
  392.     }
  393.     else
  394. fprintf(stderr,"We didn't get a sessionkey, don't expect login to work!");
  395.     dprintf("Got AUTHREPLY_109n");
  396.     
  397.     if (!(packet = packet_create(packet_class_bnet)))
  398.     {
  399. fprintf(stderr,"%s: could not create packetn",progname);
  400. goto error_rpacket;
  401.     }
  402.     packet_set_size(packet,sizeof(t_client_iconreq));
  403.     packet_set_type(packet,CLIENT_ICONREQ);
  404.     client_blocksend_packet(sd,packet);
  405.     packet_del_ref(packet);
  406.     
  407.     do
  408.         if (client_blockrecv_packet(sd,rpacket)<0)
  409. {
  410.     fprintf(stderr,"%s: server closed connectionn",progname);
  411.     goto error_rpacket;
  412. }
  413.     while (packet_get_type(rpacket)!=SERVER_ICONREPLY);
  414.     dprintf("Got ICONREPLYn");
  415.     
  416.     if (strcmp(clienttag,CLIENTTAG_STARCRAFT)==0 ||
  417. strcmp(clienttag,CLIENTTAG_BROODWARS)==0 ||
  418. strcmp(clienttag,CLIENTTAG_WARCIIBNE)==0)
  419.     {
  420. if (!(packet = packet_create(packet_class_bnet)))
  421. {
  422.     fprintf(stderr,"%s: could not create packetn",progname);
  423.     goto error_rpacket;
  424. }
  425.         {
  426.             struct
  427.             {
  428.                 bn_int sessionkey;
  429.                 bn_int ticks;
  430.                 bn_int productid;
  431.                 bn_int keyvalue1;
  432.                 bn_int keyvalue2;
  433.             }            temp;
  434.             t_hash       key_hash;
  435.             unsigned int ticks;
  436.             unsigned int keyvalue1,keyvalue2,productid;
  437.             
  438.             if (key_interpret(cdkey,&productid,&keyvalue1,&keyvalue2)<0)
  439.     {
  440.                 fprintf(stderr,"%s: specified key is not valid, sending junkn",progname);
  441.                 productid = 0;
  442.                 keyvalue1 = 0;
  443.                 keyvalue2 = 0;
  444.     }
  445.     
  446.     ticks = 0; /* FIXME: what to use here? */
  447.     bn_int_set(&temp.ticks,ticks);
  448.     bn_int_set(&temp.sessionkey,*sessionkey);
  449.     bn_int_set(&temp.productid,productid);
  450.     bn_int_set(&temp.keyvalue1,keyvalue1);
  451.     bn_int_set(&temp.keyvalue2,keyvalue2);
  452.     bnet_hash(&key_hash,sizeof(temp),&temp);
  453.     
  454.     packet_set_size(packet,sizeof(t_client_cdkey2));
  455.     packet_set_type(packet,CLIENT_CDKEY2);
  456.     bn_int_set(&packet->u.client_cdkey2.spawn,CLIENT_CDKEY2_SPAWN_FALSE); /* FIXME: add option */
  457.     bn_int_set(&packet->u.client_cdkey2.keylen,strlen(cdkey));
  458.     bn_int_set(&packet->u.client_cdkey2.productid,productid);
  459.     bn_int_set(&packet->u.client_cdkey2.keyvalue1,keyvalue1);
  460.     bn_int_set(&packet->u.client_cdkey2.sessionkey,*sessionkey);
  461.     bn_int_set(&packet->u.client_cdkey2.ticks,ticks);
  462.     hash_to_bnhash((t_hash const *)&key_hash,packet->u.client_cdkey2.key_hash); /* avoid warning */
  463.     packet_append_string(packet,cdowner);
  464.     client_blocksend_packet(sd,packet);
  465.     packet_del_ref(packet);
  466. }
  467.         do
  468.             if (client_blockrecv_packet(sd,rpacket)<0)
  469.             {
  470.                 fprintf(stderr,"%s: server closed connectionn",progname);
  471. goto error_rpacket;
  472.             }
  473.         while (packet_get_type(rpacket)!=SERVER_CDKEYREPLY2);
  474.         dprintf("Got CDKEYREPLY2 (%u)n",bn_int_get(rpacket->u.server_cdkeyreply2.message));
  475.     }
  476.     
  477.     packet_destroy(rpacket);
  478.     return sd;
  479.     
  480.     /* error cleanup */
  481.     
  482.     error_rpacket:
  483.     
  484. packet_destroy(rpacket);
  485.     
  486.     error_lsock:
  487.     
  488. if (lsock>=0)
  489.     psock_close(lsock);
  490.     
  491.     error_sd:
  492.     
  493. psock_close(sd);
  494.     
  495.     return -1;
  496. }