1 /*
2 * Project: udptunnel
3 * File: message.c
4 *
5 * Copyright (C) 2009 Daniel Meekins
6 * Contact: dmeekins - gmail
7 *
8 * This program is free software: you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation, either version 3 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include <stdlib.h>
23 #include <string.h>
24
25 #ifndef WIN32
26 #include <sys/types.h>
27 #include <sys/socket.h>
28 #endif /*WIN32*/
29
30 #include "common.h"
31 #include "message.h"
32 #include "socket.h"
33
34 /*
35 * Sends a message to the UDP tunnel with the specified client ID, type, and
36 * data. The data can be NULL and data_len 0 if the type of message won't have
37 * a body, based on the protocol.
38 * Returns 0 for success, -1 on error, or -2 to close the connection.
39 */
msg_send_msg(socket_t * to,uint16_t client_id,uint8_t type,char * data,int data_len)40 int msg_send_msg(socket_t *to, uint16_t client_id, uint8_t type,
41 char *data, int data_len)
42 {
43 char buf[MSG_MAX_LEN + sizeof(msg_hdr_t)];
44 int len; /* length for entire packet */
45 //uint16_t tmp_id;
46
47 if(data_len > MSG_MAX_LEN)
48 return -1;
49
50 switch(type)
51 {
52 case MSG_TYPE_HELLO:
53 case MSG_TYPE_HELLOACK:
54 case MSG_TYPE_DATA0:
55 case MSG_TYPE_DATA1:
56 memcpy(buf+sizeof(msg_hdr_t), data, data_len);
57 break;
58
59 case MSG_TYPE_GOODBYE:
60 case MSG_TYPE_KEEPALIVE:
61 case MSG_TYPE_ACK0:
62 case MSG_TYPE_ACK1:
63 data_len = 0;
64 break;
65
66 default:
67 return -1;
68 }
69
70 len = data_len + sizeof(msg_hdr_t);
71 msg_init_header((msg_hdr_t *)buf, client_id, type, data_len);
72
73 len = sock_send(to, buf, len);
74 if(len < 0)
75 return -1;
76 else if(len == 0)
77 return -2;
78 else
79 return 0;
80 }
81
82 /*
83 * Sends a HELLO type message to the UDP tunnel with the specified host and
84 * port in the body.
85 * Returns 0 for success, -1 on error, or -2 to disconnect.
86 */
msg_send_hello(socket_t * to,char * host,char * port,uint16_t req_id)87 int msg_send_hello(socket_t *to, char *host, char *port, uint16_t req_id)
88 {
89 char *data;
90 int str_len;
91 int len;
92
93 str_len = strlen(host) + strlen(port) + 2;
94 len = str_len + sizeof(req_id);
95
96 data = malloc(len);
97 if(!data)
98 return -1;
99
100 *((uint16_t *)data) = htons(req_id);
101
102 #ifdef WIN32
103 _snprintf(data + sizeof(req_id), str_len, "%s %s", host, port);
104 #else
105 snprintf(data + sizeof(req_id), str_len, "%s %s", host, port);
106 #endif
107
108 len = msg_send_msg(to, 0, MSG_TYPE_HELLO, data, len-1);
109 free(data);
110
111 if(len < 0)
112 return -1;
113 else if(len == 0)
114 return -2;
115 else
116 return 0;
117 }
118
119 /*
120 * Receives a message that is ready to be read from the UDP socket. Writes the
121 * body of the message into data, and sets the client ID, type, and length
122 * of the message.
123 * Returns 0 for success, -1 on error, or -2 to disconnect.
124 */
msg_recv_msg(socket_t * sock,socket_t * from,char * data,int data_len,uint16_t * client_id,uint8_t * type,uint16_t * length)125 int msg_recv_msg(socket_t *sock, socket_t *from, char *data, int data_len,
126 uint16_t *client_id, uint8_t *type, uint16_t *length)
127 {
128 char buf[MSG_MAX_LEN + sizeof(msg_hdr_t)];
129 msg_hdr_t *hdr_ptr;
130 char *msg_ptr;
131 int ret;
132
133 hdr_ptr = (msg_hdr_t *)buf;
134 msg_ptr = buf + sizeof(msg_hdr_t);
135
136 ret = sock_recv(sock, from, buf, sizeof(buf));
137 if(ret < 0)
138 return -1;
139 else if(ret == 0)
140 return -2;
141
142 *client_id = msg_get_client_id(hdr_ptr);
143 *type = msg_get_type(hdr_ptr);
144 *length = msg_get_length(hdr_ptr);
145
146 if(ret-sizeof(msg_hdr_t) != *length)
147 return -1;
148
149 *length = MIN(data_len, *length);
150 memcpy(data, msg_ptr, *length);
151
152 return 0;
153 }
154