1 /*
2  * Copyright (C) 2000  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 HAVE_UNISTD_H
21 # include <unistd.h>
22 #endif
23 #ifdef HAVE_STRING_H
24 # include <string.h>
25 #else
26 # ifdef HAVE_STRINGS_H
27 #  include <strings.h>
28 # endif
29 # ifdef HAVE_MEMORY_H
30 #  include <memory.h>
31 # endif
32 #endif
33 #include "compat/memset.h"
34 #include <errno.h>
35 #include "compat/strerror.h"
36 #ifdef HAVE_SYS_TYPES_H
37 # include <sys/types.h>
38 #endif
39 #ifdef HAVE_SYS_SOCKET_H
40 # include <sys/socket.h>
41 #endif
42 #include "compat/socket.h"
43 #ifdef HAVE_SYS_PARAM_H
44 # include <sys/param.h>
45 #endif
46 #ifdef HAVE_NETINET_IN_H
47 # include <netinet/in.h>
48 #endif
49 #include "compat/netinet_in.h"
50 #ifdef HAVE_ARPA_INET_H
51 # include <arpa/inet.h> /* FIXME: probably not needed... do some systems put types in here or something? */
52 #endif
53 #include "compat/psock.h"
54 #include "common/packet.h"
55 #include "common/bn_type.h"
56 #include "common/udp_protocol.h"
57 #include "connection.h"
58 #include "common/addr.h"
59 #include "common/tag.h"
60 #include "common/hexdump.h"
61 #include "common/eventlog.h"
62 #include "udptest_send.h"
63 #include "common/setup_after.h"
64 
65 
66 extern FILE * hexstrm; /* from main.c */
67 
68 
udptest_send(t_connection const * c)69 extern int udptest_send(t_connection const * c)
70 {
71     t_packet *         upacket;
72     struct sockaddr_in caddr;
73     unsigned int       tries,successes;
74 
75     memset(&caddr,0,sizeof(caddr));
76     caddr.sin_family = PSOCK_AF_INET;
77     caddr.sin_port = htons(conn_get_game_port(c));
78     caddr.sin_addr.s_addr = htonl(conn_get_game_addr(c));
79 
80     for (tries=successes=0; successes!=2 && tries<5; tries++)
81     {
82 	if (!(upacket = packet_create(packet_class_udp)))
83 	{
84             eventlog(eventlog_level_error,__FUNCTION__,"[%d] could not allocate memory for packet",conn_get_socket(c));
85 	    continue;
86 	}
87 	packet_set_size(upacket,sizeof(t_server_udptest));
88 	packet_set_type(upacket,SERVER_UDPTEST);
89 	bn_int_tag_set(&upacket->u.server_udptest.bnettag,BNETTAG);
90 
91 	if (hexstrm)
92 	{
93 	    fprintf(hexstrm,"%d: send class=%s[0x%02x] type=%s[0x%04x] ",
94 		    conn_get_game_socket(c),
95 		    packet_get_class_str(upacket),(unsigned int)packet_get_class(upacket),
96 		    packet_get_type_str(upacket,packet_dir_from_server),packet_get_type(upacket));
97 	    fprintf(hexstrm,"from=%s ",
98 		    addr_num_to_addr_str(conn_get_game_addr(c),conn_get_game_port(c)));
99 	    fprintf(hexstrm,"to=%s ",
100 		    addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),ntohs(caddr.sin_port)));
101 	    fprintf(hexstrm,"length=%u\n",
102 		    packet_get_size(upacket));
103 	    hexdump(hexstrm,packet_get_raw_data(upacket,0),packet_get_size(upacket));
104 	}
105 
106         if (psock_sendto(conn_get_game_socket(c),
107 			 packet_get_raw_data_const(upacket,0),packet_get_size(upacket),
108 			 0,(struct sockaddr *)&caddr,(psock_t_socklen)sizeof(caddr))!=(int)packet_get_size(upacket))
109             eventlog(eventlog_level_error,__FUNCTION__,"[%d] failed to send UDPTEST to %s (attempt %u) (psock_sendto: %s)",conn_get_socket(c),addr_num_to_addr_str(ntohl(caddr.sin_addr.s_addr),conn_get_game_port(c)),tries+1,pstrerror(psock_errno()));
110 	else
111 	    successes++;
112 
113 	packet_del_ref(upacket);
114     }
115 
116     if (successes!=2)
117 	return -1;
118 
119     return 0;
120 }
121