comparison src/common.c @ 47:e896392f7e03

Added support for connecting over IPv6
author Ivo Smits <Ivo@UCIS.nl>
date Fri, 24 May 2013 17:14:10 +0200
parents 54d28a81ca99
children b4de2326e9f7
comparison
equal deleted inserted replaced
46:3f04a72ce035 47:e896392f7e03
49 #endif 49 #endif
50 #endif 50 #endif
51 51
52 #define MAX_PACKET_LEN (ETH_FRAME_LEN+4) //Some space for optional packet information 52 #define MAX_PACKET_LEN (ETH_FRAME_LEN+4) //Some space for optional packet information
53 53
54 typedef union {
55 struct sockaddr any;
56 struct sockaddr_in ip4;
57 struct sockaddr_in6 ip6;
58 } sockaddr_any;
59
54 struct qtsession; 60 struct qtsession;
55 struct qtproto { 61 struct qtproto {
56 int encrypted; 62 int encrypted;
57 int buffersize_raw; 63 int buffersize_raw;
58 int buffersize_enc; 64 int buffersize_enc;
68 struct qtproto protocol; 74 struct qtproto protocol;
69 void* protocol_data; 75 void* protocol_data;
70 int fd_socket; 76 int fd_socket;
71 int fd_dev; 77 int fd_dev;
72 int remote_float; 78 int remote_float;
73 struct sockaddr_in remote_addr; 79 sockaddr_any remote_addr;
74 int use_pi; 80 int use_pi;
75 int poll_timeout; 81 int poll_timeout;
76 void (*sendnetworkpacket)(struct qtsession* sess, char* msg, int len); 82 void (*sendnetworkpacket)(struct qtsession* sess, char* msg, int len);
77 }; 83 };
78 84
102 void print_header() { 108 void print_header() {
103 fprintf(stderr, "UCIS QuickTun "QT_VERSION" (c) 2010-2013 Ivo Smits <Ivo@UCIS.nl>\n"); 109 fprintf(stderr, "UCIS QuickTun "QT_VERSION" (c) 2010-2013 Ivo Smits <Ivo@UCIS.nl>\n");
104 fprintf(stderr, "More information: http://wiki.ucis.nl/QuickTun\n"); 110 fprintf(stderr, "More information: http://wiki.ucis.nl/QuickTun\n");
105 } 111 }
106 112
113 static int is_all_zero(void* buf, int size) {
114 int i;
115 char* bb = (char*)buf;
116 for (i = 0; i < size; i++) if (bb[i] != 0) return 0;
117 return 1;
118 }
119 static int sockaddr_is_zero_address(sockaddr_any* sa) {
120 int af = sa->any.sa_family;
121 if (af == AF_INET) return is_all_zero(&sa->ip4.sin_addr, sizeof(struct in_addr));
122 if (af == AF_INET6) return is_all_zero(&sa->ip6.sin6_addr, sizeof(struct in6_addr));
123 return is_all_zero(sa, sizeof(sockaddr_any));
124 }
125 static int sockaddr_set_port(sockaddr_any* sa, int port) {
126 port = htons(port);
127 int af = sa->any.sa_family;
128 if (af == AF_INET) sa->ip4.sin_port = port;
129 else if (af == AF_INET6) sa->ip6.sin6_port = port;
130 else return errorexit("Unknown address family");
131 return 0;
132 }
133 static int sockaddr_equal(sockaddr_any* a, sockaddr_any* b) {
134 if (a->any.sa_family != b->any.sa_family) return 0;
135 if (a->any.sa_family == AF_INET) return a->ip4.sin_port == b->ip4.sin_port && a->ip4.sin_addr.s_addr == b->ip4.sin_addr.s_addr;
136 if (a->any.sa_family == AF_INET6) return a->ip6.sin6_port == b->ip6.sin6_port && memcmp(&a->ip6.sin6_addr, &b->ip6.sin6_addr, sizeof(struct in6_addr)) == 0 && a->ip6.sin6_scope_id == b->ip6.sin6_scope_id;
137 return memcmp(a, b, sizeof(sockaddr_any)) == 0;
138 }
139 static void sockaddr_to_string(sockaddr_any* sa, char* str, int strbuflen) {
140 if (sa->any.sa_family == AF_INET) {
141 if (!inet_ntop(AF_INET, &sa->ip4.sin_addr, str, strbuflen)) str[0] = 0;
142 int i = strlen(str);
143 snprintf(str + i, strbuflen - i, ":%u", ntohs(sa->ip4.sin_port));
144 } else if (sa->any.sa_family == AF_INET6) {
145 if (!inet_ntop(AF_INET6, &sa->ip6.sin6_addr, str, strbuflen)) str[0] = 0;
146 int i = strlen(str);
147 snprintf(str + i, strbuflen - i, "%%%d:%u", sa->ip6.sin6_scope_id, ntohs(sa->ip6.sin6_port));
148 } else {
149 strncpy(str, "Unknown AF", strbuflen);
150 }
151 str[strbuflen - 1] = 0;
152 }
153
107 static int init_udp(struct qtsession* session) { 154 static int init_udp(struct qtsession* session) {
108 char* envval; 155 char* envval;
109 fprintf(stderr, "Initializing UDP socket...\n"); 156 fprintf(stderr, "Initializing UDP socket...\n");
110 int sfd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP); 157 struct addrinfo *ai_local = NULL, *ai_remote = NULL;
158 unsigned short af = 0;
159 if (envval = getconf("LOCAL_ADDRESS")) {
160 if (getaddrinfo(envval, NULL, NULL, &ai_local)) return errorexitp("getaddrinfo(LOCAL_ADDRESS)");
161 if (!ai_local) return errorexit("LOCAL_ADDRESS lookup failed");
162 if (ai_local->ai_addrlen > sizeof(sockaddr_any)) return errorexit("Resolved LOCAL_ADDRESS is too big");
163 af = ai_local->ai_family;
164 }
165 if (envval = getconf("REMOTE_ADDRESS")) {
166 if (getaddrinfo(envval, NULL, NULL, &ai_remote)) return errorexitp("getaddrinfo(REMOTE_ADDRESS)");
167 if (!ai_remote) return errorexit("REMOTE_ADDRESS lookup failed");
168 if (ai_remote->ai_addrlen > sizeof(sockaddr_any)) return errorexit("Resolved REMOTE_ADDRESS is too big");
169 if (af && af != ai_remote->ai_family) return errorexit("Address families do not match");
170 af = ai_remote->ai_family;
171 }
172 if (!af) af = AF_INET;
173 int sfd = socket(af, SOCK_DGRAM, IPPROTO_UDP);
111 if (sfd < 0) return errorexitp("Could not create UDP socket"); 174 if (sfd < 0) return errorexitp("Could not create UDP socket");
112 struct sockaddr_in udpaddr; 175 sockaddr_any udpaddr;
113 struct hostent *he; 176 memset(&udpaddr, 0, sizeof(udpaddr));
114 udpaddr.sin_family = AF_INET; 177 udpaddr.any.sa_family = af;
115 udpaddr.sin_addr.s_addr = INADDR_ANY; 178 if (ai_local) memcpy(&udpaddr, ai_local->ai_addr, ai_local->ai_addrlen);
116 udpaddr.sin_port = htons(2998); 179 int port = 2998;
117 if (envval = getconf("LOCAL_ADDRESS")) { 180 if (envval = getconf("LOCAL_PORT")) port = atoi(envval);
118 he = gethostbyname(envval); 181 if (sockaddr_set_port(&udpaddr, port)) return -1;
119 if (!he) return errorexit("bind address lookup failed"); 182 if (bind(sfd, (struct sockaddr*)&udpaddr, sizeof(udpaddr))) return errorexitp("Could not bind socket");
120 else if (!he->h_addr_list[0]) return errorexit("no address to bind to"); 183 memset(&udpaddr, 0, sizeof(udpaddr));
121 udpaddr.sin_addr.s_addr = *((unsigned long*)he->h_addr_list[0]); 184 udpaddr.any.sa_family = af;
122 udpaddr.sin_family = he->h_addrtype; 185 if (ai_remote) memcpy(&udpaddr, ai_remote->ai_addr, ai_remote->ai_addrlen);
123 } 186 if (!ai_remote || sockaddr_is_zero_address(&udpaddr)) {
124 if (envval = getconf("LOCAL_PORT")) {
125 udpaddr.sin_port = htons(atoi(envval));
126 }
127 if (bind(sfd, (struct sockaddr*)&udpaddr, sizeof(struct sockaddr_in))) return errorexitp("Could not bind socket");
128 if (!(envval = getconf("REMOTE_ADDRESS"))) {
129 session->remote_float = 1; 187 session->remote_float = 1;
130 //return errorexit("Missing REMOTE_ADDRESS");
131 } else { 188 } else {
132 session->remote_float = getconf("REMOTE_FLOAT") ? 1 : 0; 189 session->remote_float = getconf("REMOTE_FLOAT") ? 1 : 0;
133 he = gethostbyname(envval); 190 port = 2998;
134 if (!he) return errorexit("remote address lookup failed"); 191 if (envval = getconf("REMOTE_PORT")) port = atoi(envval);
135 else if (!he->h_addr_list[0]) return errorexit("no address to connect to"); 192 if (sockaddr_set_port(&udpaddr, port)) return -1;
136 udpaddr.sin_family = he->h_addrtype; 193 session->remote_addr = udpaddr;
137 udpaddr.sin_addr.s_addr = *((unsigned long*)he->h_addr_list[0]); 194 if (session->remote_float) {
138 if (udpaddr.sin_addr.s_addr == 0) { 195 session->remote_float = 2;
139 session->remote_float = 1;
140 } else { 196 } else {
141 if (envval = getconf("REMOTE_PORT")) { 197 if (connect(sfd, (struct sockaddr*)&udpaddr, sizeof(udpaddr))) return errorexitp("Could not connect socket");
142 udpaddr.sin_port = htons(atoi(envval));
143 }
144 if (connect(sfd, (struct sockaddr*)&udpaddr, sizeof(struct sockaddr_in))) return errorexitp("Could not connect socket");
145 session->remote_addr = udpaddr;
146 } 198 }
147 } 199 }
200 if (ai_local) freeaddrinfo(ai_local);
201 if (ai_remote) freeaddrinfo(ai_remote);
148 session->fd_socket = sfd; 202 session->fd_socket = sfd;
149 return sfd; 203 return sfd;
150 } 204 }
151 205
152 static int init_tuntap(struct qtsession* session) { 206 static int init_tuntap(struct qtsession* session) {
221 275
222 static void qtsendnetworkpacket(struct qtsession* session, char* msg, int len) { 276 static void qtsendnetworkpacket(struct qtsession* session, char* msg, int len) {
223 if (session->remote_float == 0) { 277 if (session->remote_float == 0) {
224 len = write(session->fd_socket, msg, len); 278 len = write(session->fd_socket, msg, len);
225 } else if (session->remote_float == 2) { 279 } else if (session->remote_float == 2) {
226 len = sendto(session->fd_socket, msg, len, 0, (struct sockaddr*)&session->remote_addr, sizeof(struct sockaddr_in)); 280 len = sendto(session->fd_socket, msg, len, 0, (struct sockaddr*)&session->remote_addr, sizeof(sockaddr_any));
227 } 281 }
228 } 282 }
229 283
230 int qtrun(struct qtproto* p) { 284 int qtrun(struct qtproto* p) {
231 if (getconf("DEBUG")) debug = 1; 285 if (getconf("DEBUG")) debug = 1;
253 struct pollfd fds[2]; 307 struct pollfd fds[2];
254 fds[0].fd = ttfd; 308 fds[0].fd = ttfd;
255 fds[0].events = POLLIN; 309 fds[0].events = POLLIN;
256 fds[1].fd = sfd; 310 fds[1].fd = sfd;
257 fds[1].events = POLLIN; 311 fds[1].events = POLLIN;
258
259 struct sockaddr_in recvaddr;
260 312
261 int pi_length = 0; 313 int pi_length = 0;
262 if (session.use_pi == 2) pi_length = 4; 314 if (session.use_pi == 2) pi_length = 4;
263 315
264 char buffer_raw_a[p->buffersize_raw + pi_length]; 316 char buffer_raw_a[p->buffersize_raw + pi_length];
287 len = sizeof(out); 339 len = sizeof(out);
288 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); 340 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len);
289 fprintf(stderr, "Received error %d on udp socket\n", out); 341 fprintf(stderr, "Received error %d on udp socket\n", out);
290 } 342 }
291 if (fds[1].revents & POLLIN) { 343 if (fds[1].revents & POLLIN) {
344 sockaddr_any recvaddr;
292 socklen_t recvaddr_len = sizeof(recvaddr); 345 socklen_t recvaddr_len = sizeof(recvaddr);
293 if (session.remote_float == 0) { 346 if (session.remote_float == 0) {
294 len = read(sfd, buffer_enc + p->offset_enc, p->buffersize_enc); 347 len = read(sfd, buffer_enc + p->offset_enc, p->buffersize_enc);
295 } else { 348 } else {
296 len = recvfrom(sfd, buffer_enc + p->offset_enc, p->buffersize_enc, 0, (struct sockaddr*)&recvaddr, &recvaddr_len); 349 len = recvfrom(sfd, buffer_enc + p->offset_enc, p->buffersize_enc, 0, (struct sockaddr*)&recvaddr, &recvaddr_len);
301 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len); 354 getsockopt(sfd, SOL_SOCKET, SO_ERROR, &out, &len);
302 fprintf(stderr, "Received end of file on udp socket (error %lld)\n", out); 355 fprintf(stderr, "Received end of file on udp socket (error %lld)\n", out);
303 } else { 356 } else {
304 len = p->decode(&session, buffer_enc, buffer_raw + pi_length, len); 357 len = p->decode(&session, buffer_enc, buffer_raw + pi_length, len);
305 if (len < 0) continue; 358 if (len < 0) continue;
306 if (session.remote_float != 0 && (session.remote_addr.sin_addr.s_addr != recvaddr.sin_addr.s_addr || session.remote_addr.sin_port != recvaddr.sin_port)) { 359 if (session.remote_float != 0 && !sockaddr_equal(&session.remote_addr, &recvaddr)) {
307 fprintf(stderr, "Remote endpoint has changed to %08X:%d\n", ntohl(recvaddr.sin_addr.s_addr), ntohs(recvaddr.sin_port)); 360 char epname[INET6_ADDRSTRLEN + 1 + 2 + 1 + 5]; //addr%scope:port
361 sockaddr_to_string(&recvaddr, epname, sizeof(epname));
362 fprintf(stderr, "Remote endpoint has changed to %s\n", epname);
308 session.remote_addr = recvaddr; 363 session.remote_addr = recvaddr;
309 session.remote_float = 2; 364 session.remote_float = 2;
310 } 365 }
311 if (len > 0 && session.use_pi == 2) { 366 if (len > 0 && session.use_pi == 2) {
312 int ipver = (buffer_raw[p->offset_raw + pi_length] >> 4) & 0xf; 367 int ipver = (buffer_raw[p->offset_raw + pi_length] >> 4) & 0xf;