00001
00002
00003
00004
00005 #include <stdio.h>
00006 #include <stdlib.h>
00007 #include <stdarg.h>
00008 #include <assert.h>
00009 #include <string.h>
00010 #include <libgen.h>
00011 #include <linux/netfilter.h>
00012 #include "libipq.h"
00013 #include <linux/ip.h>
00014 #include <arpa/inet.h>
00015 #include <signal.h>
00016 #include <pthread.h>
00017
00018 #include "misc.h"
00019 #include "tcp.h"
00020 #include "scheduler.h"
00021 #include "tcptimer.h"
00022 #include "tcpproxy.h"
00023
00024 #define IPQ_BUF_SIZE 10240
00025
00026
00027
00028
00029
00030 static struct ipq_handle *qh;
00031 static __u32 mob_ip;
00032 static pthread_t sched_thread;
00033 static pthread_t timer_thread;
00034
00035 volatile sig_atomic_t request_exit = 0;
00036 pthread_t main_thread;
00037
00038
00039
00040
00041
00042 inline Tpacket_data *alloc_packet_data(ipq_packet_msg_t *p)
00043 {
00044 Tpacket_data *pd;
00045 pd = (Tpacket_data*) xmalloc(sizeof(Tpacket_data));
00046 pd->payload = (unsigned char*) xmalloc(p->data_len);
00047
00048
00049 memcpy(&pd->ipq_pm, p, sizeof(ipq_packet_msg_t));
00050 memcpy(pd->payload, p->payload, p->data_len);
00051 pd->ip = (struct iphdr*) pd->payload;
00052 pd->trans.hdr = (pd->payload + (pd->ip->ihl*4));
00053
00054 return pd;
00055 }
00056
00057
00058
00059
00060
00061 inline void dealloc_packet_data(Tpacket_data *pd)
00062 {
00063 assert(pd != NULL);
00064 xfree(pd->payload);
00065 xfree(pd);
00066 }
00067
00068
00069
00070
00071
00072
00073
00074
00075 unsigned short ip_chksum(ipq_packet_msg_t *p, unsigned int words)
00076 {
00077 unsigned short *buf = (unsigned short*)p->payload;
00078 unsigned long chksum;
00079
00080 for(chksum=0; words>0; words--)
00081 chksum += *buf++;
00082
00083 chksum = (chksum >> 16) + (chksum & 0xffff);
00084 chksum += (chksum >> 16);
00085 chksum = ~chksum & 0xffff;
00086
00087 return chksum;
00088 }
00089
00090
00091
00092
00093
00094
00095 int handle_icmp(Tpacket_data *pd)
00096 {
00097 queue_hipri(pd);
00098 return 0;
00099 }
00100
00101
00102
00103
00104
00105 int handle_other(Tpacket_data *pd)
00106 {
00107 queue_lowpri(pd);
00108 return 0;
00109 }
00110
00111
00112
00113
00114
00115
00116 int handle_packet(ipq_packet_msg_t *p)
00117 {
00118 Tpacket_data *pd;
00119 struct iphdr *ip;
00120 int ret;
00121
00122 if(p->data_len == 0) {
00123 EPRINT("handle_packet: message does not contain any data.\n");
00124 return -1;
00125 }
00126
00127 ip = (struct iphdr*) p->payload;
00128 if(p->data_len < ip->ihl*4) {
00129 IPRINT("handle_packet: ip hlen value too big for packet length: %d\n", ip->ihl);
00130 return -1;
00131 }
00132
00133 if(p->data_len != ntohs(ip->tot_len)) {
00134 IPRINT("handle_packet: ip packet has incorrect length field: %d\n",
00135 ntohs(ip->tot_len));
00136 return -1;
00137 }
00138
00139
00140
00141
00142 if(ip_chksum(p, ip->ihl*2)) {
00143 DPRINT("handle_packet: bad ip checksum: %u\n", ntohs(ip->check));
00144 return -1;
00145 }
00146
00147 pd = alloc_packet_data(p);
00148
00149 if(DEBUG) {
00150 int frag = ntohs(pd->ip->frag_off);
00151 IPRINT("\n");
00152
00153
00154
00155 IPRINT("ip ver: %u, ihl: %u, tos: %u, id: %u, ttl: %u, frag: %c%c%c %u\n",
00156 pd->ip->version, pd->ip->ihl, pd->ip->tos, pd->ip->id,
00157 pd->ip->ttl, (frag&0x80?'R':'.'), (frag&0x4000?'D':'.'),
00158 (frag&0x2000?'M':'.'), (frag&0x1fff));
00159 IPRINT("ip len: %u, proto: %u, ", ntohs(pd->ip->tot_len), pd->ip->protocol);
00160 IPRINT("%s->", inet_ntoa(*(struct in_addr*)&(pd->ip->saddr)));
00161 IPRINT("%s\n", inet_ntoa(*(struct in_addr*)&(pd->ip->daddr)));
00162 }
00163
00164 if(pd->ip->version != 4) {
00165 EPRINT("handle_packet: error: packet not IPv4.\n");
00166 exit(EXIT_ERR_WRONG_IP_VER);
00167 }
00168
00169
00170
00171 if(pd->ip->daddr == mob_ip) {
00172 pd->dir = PACKET_DIR_IN;
00173 } else if(pd->ip->saddr == mob_ip) {
00174 pd->dir = PACKET_DIR_OUT;
00175 } else {
00176 EPRINT("handle_packet: neither src nor dst correspond to mobile ip - allowing through.\n");
00177 dealloc_packet_data(pd);
00178 ret = ipq_set_verdict(qh, p->packet_id, NF_ACCEPT, 0, 0);
00179 if (ret < 0) {
00180 EPRINT("handle_packet: error setting ipq verdict.\n");
00181 ipq_perror("handle_packet");
00182 }
00183 return -1;
00184 }
00185
00186 switch(pd->ip->protocol)
00187 {
00188 case 1:
00189 handle_icmp(pd);
00190 break;
00191 case 6:
00192 handle_tcp(pd);
00193 break;
00194 default:
00195 handle_other(pd);
00196 break;
00197 }
00198
00199 ret = ipq_set_verdict(qh, p->packet_id, NF_DROP, 0, 0);
00200
00201 if (ret < 0) {
00202 EPRINT("handle_packet: error setting ipq verdict.\n");
00203 ipq_perror("handle_packet");
00204 }
00205 return 0;
00206 }
00207
00208
00209
00210
00211
00212 void cleanup ()
00213 {
00214 IPRINT("Quiting.\n");
00215
00216 if(!request_exit)
00217 request_exit = 1;
00218
00219 pthread_cancel(timer_thread);
00220 pthread_cancel(sched_thread);
00221
00222 if(ipq_destroy_handle(qh) == -1) {
00223 EPRINT("cleanup: error destroying ipq handle.\n");
00224 ipq_perror("cleanup");
00225 exit(EXIT_ERR_IPQ_DESTROY_HANDLE);
00226 }
00227 }
00228
00229
00230
00231
00232
00233 void signal_handler (int signum)
00234 {
00235
00236
00237 switch(signum)
00238 {
00239 case SIGTERM:
00240 DPRINT("\nReceived SIGTERM\n");
00241 break;
00242 case SIGINT:
00243 DPRINT("\nReceived SIGINT\n");
00244 break;
00245 case SIGHUP:
00246 DPRINT("\nReceived SIGHUP\n");
00247 break;
00248 default:
00249 EPRINT("\nsignal_handler: invalid signal received");
00250 break;
00251 }
00252
00253 exit(request_exit);
00254 }
00255
00256
00257
00258
00259
00260 int main(int argc, const char* argv[])
00261 {
00262 struct sigaction sact, soldact;
00263 pthread_attr_t thread_attr;
00264
00265 int sigs [] = { SIGTERM, SIGINT, SIGHUP, 0};
00266 int i;
00267 char buf[IPQ_BUF_SIZE];
00268 ssize_t len;
00269 int mtype;
00270 int error;
00271 ipq_packet_msg_t *packet;
00272 struct in_addr mob_addr;
00273
00274 main_thread = pthread_self();
00275
00276 if(argc != 2) {
00277 printf("Invalid number of arguments.\n");
00278 printf("Usage: %s mobile_ip\n", argv[0]);
00279 exit(EXIT_ERR_USAGE);
00280 }
00281
00282 if(inet_aton(argv[1], &mob_addr) == 0) {
00283 printf("Bad mobile IP address: %s\n", argv[1]);
00284 exit(EXIT_ERR_BAD_MOBILE_IP);
00285 }
00286 mob_ip = mob_addr.s_addr;
00287 DPRINT("main: starting proxy for mobile host '%s'.\n", argv[1]);
00288
00289 if(pthread_attr_init(&thread_attr) ||
00290 pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)) {
00291 EPRINT("main: error setting pthread attr.\n");
00292 exit(EXIT_ERR_PTHREAD_ATTR);
00293 }
00294
00295 if(sigemptyset(&sact.sa_mask)) {
00296 EPRINT("main: error calling segemptyset.\n");
00297 }
00298 for(i=0; sigs[i] != 0; i++) {
00299 if(sigaddset(&sact.sa_mask, sigs[i])) {
00300 EPRINT("main: error calling segaddset.\n");
00301 }
00302 }
00303
00304 sact.sa_handler = signal_handler;
00305 sact.sa_flags = 0;
00306
00307 for(i=0; sigs[i]; i++) {
00308 if(sigaction(sigs[i], &sact, &soldact)) {
00309 EPRINT("main: error setting signal handler.\n");
00310 exit(EXIT_ERR_SET_SIG_HANDLER);
00311 } else if(soldact.sa_handler == SIG_IGN) {
00312 sigaction(sigs[i], &soldact, NULL);
00313 }
00314 }
00315
00316
00317
00318 qh = ipq_create_handle(0, PF_INET);
00319 if(!qh) {
00320 EPRINT("main: error creating netlink handle.\n");
00321 ipq_perror("main");
00322 exit(EXIT_ERR_IPQ_CREATE_HANDLE);
00323 }
00324
00325 if(ipq_set_mode(qh, IPQ_COPY_PACKET, IPQ_BUF_SIZE) < 0) {
00326 EPRINT("main: error setting netlink mode.\n");
00327 ipq_perror("main");
00328 exit(EXIT_ERR_IPQ_SET_MODE);
00329 }
00330
00331 atexit(cleanup);
00332
00333 init_sched();
00334 atexit(cleanup_sched);
00335 init_timer();
00336 atexit(cleanup_timer);
00337 init_tcp();
00338 atexit(cleanup_tcp);
00339
00340 if(pthread_create(&sched_thread, NULL, (void*)scheduler, &sact.sa_mask)) {
00341 EPRINT("main: error creating scheduler thread.\n");
00342 perror("main");
00343 exit(EXIT_ERR_CREATE_THREAD);
00344 }
00345
00346 if(pthread_create(&timer_thread, NULL, (void*)tcp_timer, &sact.sa_mask)) {
00347 EPRINT("main: error creating TCP timer thread.\n");
00348 perror("main");
00349 exit(EXIT_ERR_CREATE_THREAD);
00350 }
00351
00352 DPRINT("main: ready to receive packets.\n");
00353
00354 while (!request_exit) {
00355
00356 len = ipq_read(qh, buf, IPQ_BUF_SIZE, 0);
00357
00358
00359 if(len <= 0) {
00360 EPRINT("main: error returned from ipq_read.\n");
00361 ipq_perror("main");
00362
00363 } else {
00364 mtype = ipq_message_type(buf);
00365 switch(mtype)
00366 {
00367 case IPQM_PACKET:
00368 packet = ipq_get_packet(buf);
00369 handle_packet(packet);
00370 break;
00371 case NLMSG_ERROR:
00372 error = ipq_get_msgerr(buf);
00373
00374
00375 exit(EXIT_ERR_IPQ_ERR_MESSAGE);
00376 break;
00377 default:
00378 EPRINT("main: invalid message type received.\n");
00379 exit(EXIT_ERR_IPQ_MESSAGE_TYPE);
00380 break;
00381 }
00382 }
00383 }
00384
00385 exit(0);
00386 }