char* dir_where_exe(char *exename, char *pathbuf, int pathlen) { int i, err=-1; char exebuf[4096], *p; HINSTANCE h=0; do { i = snprintf(exebuf, sizeof(exebuf), "%s", exename); assertb(i>0); p = dir_filename(exebuf, 0); assertb(p); if( !strchr(p, '.') ) { strncat(exebuf, ".exe", sizeof(exebuf)-strlen(exebuf)-1); } for(p=exebuf; *p; p++) { if( *p == '\\' ) *p = '/'; } h = LoadLibrary(exebuf); assertb_syserr(h); i = GetModuleFileName((HMODULE)h, pathbuf, pathlen); assertb_syserr(i>0); err = 0; } while(0); if( h ) { FreeLibrary(h); } return err ? 0 : pathbuf; }
void http_redirect_select_accept(fdselect_t *sel, fd_t fd, int state, void *arg) { http_redirect_t *server = (http_redirect_t *)arg; http_redirect_client_t *client; struct sockaddr_in addr; sockaddrlen_t addrlen; sock_t sock; int i, err=-1; char buf1[1024]; do { addrlen = sizeof(addr); sock = accept(server->accept_sock, (struct sockaddr*)&addr, &addrlen); assertb(sock>=0 || sock_wouldblock(server->accept_sock, sock)); debug(DEBUG_INFO, ("http_redirect_select_accept: accepted from %s\n" ,iaddr_fmt(&addr, buf1, sizeof(buf1))) ); client = pool_malloc(server->pool, sizeof(*client)); assertb(client); i = http_redirect_client_init(server, client); assertb(i==0); client->sock = sock; client->addr = addr; i = fdselect_set(server->fdselect, client->sock, FDSELECT_READ, http_redirect_client_select_read, client); assertb(i>=0); err = 0; } while(0); }
dir_t* dir_open(char *path) { dir_t *d=0; int i, err = -1; char *p=0; do { i = strlen(path)+4; p = malloc(i); assertb(p); strncpy(p, path, i); strncat(p, "/*", i); d = calloc(1, sizeof(*d)); assertb(d); d->h = INVALID_HANDLE_VALUE; d->h = FindFirstFile(p, &d->fi); if(d->h == INVALID_HANDLE_VALUE && GetLastError() == ERROR_NO_MORE_FILES) { break; } assertb_syserr(d->h); d->first = 1; err = 0; } while(0); if( p ) { free(p); } if( err ) { dir_close(d); d = 0; } return d; }
console_t console_open() { console_t console = 0; int err=-1; char buf[4096]; int reboot=0; do { console = (console_t)malloc(sizeof(*console)); assertb(console); memset(console, 0, sizeof(*console)); if( 1 ) { console->read_handle = GetStdHandle(STD_INPUT_HANDLE); } else { snprintf(buf, sizeof(buf), "CONIN$"); debug(DEBUG_INFO, ("console_open: CreateFile(path=%s)\n", buf)); console->read_handle = CreateFile(buf, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_SYSTEM, 0 ); } assertb_syserr(console->read_handle != INVALID_HANDLE_VALUE); console->read_pending = 0; console->read_event = CreateEvent(0,0,0,0); assertb(console->read_event); err = 0; break; } while(0); if( err ) { console_close(console); console = 0; } return console; }
/* returns the number of chars in dst */ int http_cgi_dec(char *src, int src_len, char *dst, int dst_len) { char hex[3], *p; char *src_end = src+src_len; char *dst_orig=dst, *dst_end = dst+dst_len; for(; src<src_end && dst<dst_end; src++) { if( *src == '%' ) { src++; assertb(src_end-src>=2); hex[0] = src[0]; hex[1] = src[1]; hex[2] = 0; *dst = (char)(strtoul(hex, &p, 16) & 0xff); dst += 1; src += 2-1; } else { *dst = *src; dst += 1; } } if( dst >= dst_end ) { return 0; } *dst = 0; return dst - dst_orig; }
cfg_enum_t* cfg_enum_open(cfg_t *cfg, cfg_dir_where_t where, char *subdir) { char buf[4096]; cfg_enum_t *e=0; do { if( where == CFG_DIR_NONE ) { e = cfg_enum_open(cfg, CFG_DIR_USER, subdir); if( e ) return e; e = cfg_enum_open(cfg, CFG_DIR_GLOBAL, subdir); if( e ) return e; return 0; } e = (cfg_enum_t*)calloc(1, sizeof(*e)); assertb(e); snprintf(e->path, sizeof(e->path), "%s/%s", cfg_dir(cfg, where, buf, sizeof(buf)), subdir); e->dir = opendir(e->path); } while(0); if( e && !e->dir ) { free(e); e = 0; } return e; }
dir_t* dir_open(char *path) { dir_t *d=0; int err = -1; do { d = calloc(1, sizeof(*d)); assertb(d); d->dir = opendir(path); assertb(d->dir); err = 0; } while(0); if( err ) { dir_close(d); d = 0; } return d; }
int find_keyword(const char *s, unsigned length) { length; for (unsigned i = TOKEN_KEYWORD_FIRST; i != TOKEN_KEYWORD_LAST; ++i) { const char *ts = TOKEN_STRINGS[i]; assertb(ts != NULL); if (0 == strcmp(ts, s)) return (int)i; } return TOKEN_INVALID; }
void http_redirect_client_select_write(fdselect_t *sel, fd_t fd, int state, void *arg) { http_redirect_client_t *client = (http_redirect_client_t*)arg; int i, err=-1; char buf1[1024]; do { if( client->send_len <= 0 ) { i = fread(client->send_buf, 1, sizeof(client->send_buf), client->send_file); if( i == 0 ) { i = http_redirect_client_end_req(client); assertb(i==0); } assertb(i>0); client->send_len = i; client->send_ptr = client->send_buf; } i = send(client->sock, client->send_ptr, client->send_len, 0); assertb(i>0); client->send_len -= i; client->send_ptr += i; debug(DEBUG_INFO, ("http_redirect_client_select_write: addr=%s send=%d\n" ,iaddr_fmt(&client->addr, buf1, sizeof(buf1)) ,i )); err = 0; } while(0); if( err ) { http_redirect_client_free(client); } }
char * pool_memdup(pool_t *pool, const char *str, int len) { char *p=0, *q=0; int err=-1; do { assertb(str); p = (char*)malloc(len); assertb(p); memcpy(p, str, len); q = (char*)pool_add(pool, p, 0, 0); err = 0; } while(0); if( err ) { if( q ) { pool_free(pool, q); } else if ( p ) { free(p); } p = q = 0; } return q; }
int http_redirect_init(http_redirect_t *server, fdselect_t *fdselect, char *root_dir) { int err; do { memset(server, 0, sizeof(*server)); server->fdselect = fdselect; server->pool = pool_new(); assertb(server->pool); server->root_dir = pool_strdup(server->pool, root_dir); err = 0; } while(0); return 0; }
char* http_cgi_enc(char *src, int src_len, char *dst, int dst_len) { char *src_end = src+src_len; char *dst_orig=dst, *dst_end = dst+dst_len; for(; src<src_end && dst>dst_end; src++) { if( isalnum(*src) || *src == '-' || *src == '_' ) { *dst++ = *src; } else { assertb(dst_end-dst>=3); snprintf(dst, 3, "%%%02x", (int)*src); dst += 3; } } if( dst >= dst_end ) { return 0; } return dst_orig; }
int http_header_init(http_header_t *http, pool_t *pool) { int err=-1; memset(http, 0, sizeof(*http)); do { if( !pool ) { http->free_pool = 1; http->pool = pool_new(); assertb(http->pool); } else { http->free_pool = 0; http->pool = pool; } err = 0; } while(0); return err; }
int main(int argc, char **argv) { fdselect_t fdselect; http_redirect_t server_s, *server=&server_s; struct sockaddr_in addr; sockaddrlen_t addrlen; int i, err=-1; char buf[4096]; do { debug_init(DEBUG_INFO, 0, 0); sock_init(); sig_init(); fdselect_init(&fdselect); getcwd(buf, sizeof(buf)); http_redirect_init(server, &fdselect, buf); server->accept_sock = socket(AF_INET, SOCK_STREAM, 0); assertb_sockerr(server->accept_sock>=0); i = 1; setsockopt(server->accept_sock, SOL_SOCKET, SO_REUSEADDR, (const char*)&i, sizeof(i)); addrlen = iaddr_pack(&addr, INADDR_ANY, 8080); i = bind(server->accept_sock, (struct sockaddr*)&addr, addrlen); assertb_sockerr(i==0); i = listen(server->accept_sock, 5); assertb_sockerr(i==0); i = fdselect_set(server->fdselect, server->accept_sock, FDSELECT_READ, http_redirect_select_accept, server); assertb(i>=0); while(!sig_exited) { fdselect_select(&fdselect, 1); } err = 0; } while(0); return err; }
int main(int argc, char **argv) { char *ns, *hostname; sock_t sock; struct sockaddr_in addr; sockaddrlen_t addrlen; char buf_query[4096]; char buf_reply[4096]; char buf_out[4096]; char buf[4096]; dns_rr_t hosts[100]; int i, n, err=-1; int id; dns_t dns_reply; do { debug_init(DEBUG_INFO, 0, 0); sock_init(); if( argc <= 2 ) { fprintf(stderr, "USAGE: %s nameserver hostname\n", argv[0]); break; } ns = argv[1]; hostname = argv[2]; i = dns_resolve_query(buf_query, sizeof(buf_query), hostname, 977); assertb(i>=0); memdump(buf_out, sizeof(buf_out), buf_query, i); fprintf(stderr, "query: len=%d\n%s\n", i, buf_out); /* send the query to ns*/ sock = socket(PF_INET, SOCK_DGRAM, 0); assertb_sockerr(sock>=0); addrlen = iaddr_pack(&addr, inet_resolve(ns), 53); assertb(addrlen>0); n = sendto(sock, buf_query, i, 0, (struct sockaddr*)&addr, addrlen); assertb_sockerr(n==i); /* receive a response */ n = recvfrom(sock, buf_reply, sizeof(buf_reply), 0, (struct sockaddr*)&addr, &addrlen); assertb_sockerr(n>0); debug(DEBUG_INFO, ("recvfrom raw query from %s\n%s\n" , netpkt_ntoa(addr.sin_addr.s_addr, 0) , memdump(buf_out, sizeof(buf_out), buf_reply, n) )); dns_init(&dns_reply, buf_reply, n); dns_pack(&dns_reply, PACK_NET2HOST); debug(DEBUG_INFO, ("dns answer %s\n" ,dns_fmt(&dns_reply, buf, sizeof(buf)))); n = dns_resolve_reply(buf_reply, n, &id, hosts, NELTS(hosts)); for(i=0; i<n; i++) { fprintf(stderr, "hosts[%d]: %s=%s\n", i, hosts[i].name, netpkt_ntoa(hosts[i].rdata.a.addr, 0)); } } while(0); }
int http_get(char *urlstr, http_req_func_t func, void *farg) { url_t url; struct sockaddr_in iaddr; sockaddrlen_t addrlen; int i, err=-1; sock_t sock; int url_parsed=0; char buf[16384], buf1[1024]; size_t len=0; http_header_t http; http_req_t req; int got_header = 0; http_req_error_t req_err = 0; do { memset(&req, 0, sizeof(req)); req.req_url = &url; req.reply_hdr = &http; req_err = HTTP_REQ_ERROR_BAD_URL; i = url_parse(&url, urlstr); assertb(i==0); url_parsed = 1; if( strcasecmp(url.proto, "file") == 0 ) { struct stat st; FILE *f=0; req_err = HTTP_REQ_ERROR_FILE_NOT_FOUND; do { i = stat(url.path, &st); assertb(i==0); http.content_len = st.st_size; req.req_state = HTTP_REQ_BODY; f = fopen(url.path, "r"); assertb(f); while(1) { len = fread(buf, 1, sizeof(buf), f); if( len < 0 ) { req_err = HTTP_REQ_ERROR_INCOMPLETE; break; } if( len <= 0 ) break; err = func(&req, buf, len, farg); if( err ) break; } req_err = 0; err = 0; } while(0); if( f ) { fclose(f); } break; } req_err = HTTP_REQ_ERROR_BAD_URL; assertb( strcasecmp(url.proto, "http") == 0 ); req_err = HTTP_REQ_ERROR_CONNECT; sock = socket(AF_INET, SOCK_STREAM, 0); assertb_sockerr(sock>=0); req.req_state = HTTP_REQ_RESOLVE; i = snprintf(buf, sizeof(buf), "resolving host %s\n", url.host); err = func(&req, buf, i, farg); if( err != 0 ) break; addrlen = iaddr_pack(&iaddr, inet_resolve(url.host), url.port); req.req_state = HTTP_REQ_CONNECT; i = snprintf(buf, sizeof(buf), "connecting to host %s at %s\n" ,url.host ,iaddr_fmt(&iaddr, buf1, sizeof(buf1)) ); err = func(&req, buf, i, farg); if( err != 0 ) break; i = connect(sock, (struct sockaddr*)&iaddr, addrlen); assertb_sockerr(i==0); i = snprintf(buf, sizeof(buf), "GET %s HTTP/1.0\r\n" "Host: %s\r\n" "\r\n" ,url.path_args ,url.host ); req.req_state = HTTP_REQ_SEND; err = func(&req, buf, i, farg); if( err != 0 ) break; i = sock_send_timeout(sock, buf, i, 5000); assertb(i>=0); len = 0; got_header = 0; while(1) { assertb( len < sizeof(buf) ); i = recv(sock, buf+len, sizeof(buf)-len, 0); if( i < 0 ) { warn_sockerr(sock); req_err = HTTP_REQ_ERROR_INCOMPLETE; break; } if( i == 0 ) { req.req_state = HTTP_REQ_EOF; err = func(&req, 0, 0, farg); break; } len += i; if( !got_header ) { http_header_init(&http, 0); i = http_header_parse(&http, buf, len); if( i < 0 ) { req_err = HTTP_REQ_ERROR_BAD_RESPONSE; break; } if( i == 0 ) { continue; } got_header = 1; req.reply_max = http.content_len; req.req_state = HTTP_REQ_HEAD; err = func(&req, buf, http.header_len, farg); if( err != 0 ) { break; } len -= http.header_len; if( len > 0 ) { memmove(buf, buf+http.header_len, len); } } if( got_header ) { req.reply_len += len; req.req_state = HTTP_REQ_BODY; err = func(&req, buf, len, farg); len = 0; if( err ) { break; } } } req_err = 0; } while(0); if( got_header && http.response_code != 200 ) { req_err = HTTP_REQ_ERROR_FILE_NOT_FOUND; } if( req_err ) { req.req_state = HTTP_REQ_ERROR; req.req_error = req_err; err = func(&req, buf, len, farg); } if( url_parsed ) { url_free(&url); } if( got_header ) { http_header_free(&http); } return err; }
void http_redirect_client_select_read(fdselect_t *sel, fd_t fd, int state, void *arg) { http_redirect_client_t *client = (http_redirect_client_t *)arg; http_redirect_t *server = client->server; struct stat st; int i, n, err=-1; char buf[4096]; char buf1[1024]; do { i = client->recv_max - client->recv_len; if( i <= 0 ) { err = 405; /* request too big */ break; } i = recv(client->sock, client->recv_buf+client->recv_len, i, 0); if( i <= 0 ) { if( sock_wouldblock(client->sock, i) ) { /* ignore spurious blocking reads */ err = 0; break; } assertb_sockerr(i); } client->recv_len += i; client->recv_buf[client->recv_len] = 0; debug(DEBUG_INFO, ("http_redirect_client_select_read: addr=%s recv=%d\n" "recv_buf=\n%s\n" ,iaddr_fmt(&client->addr, buf1, sizeof(buf1)) ,i ,client->recv_buf )); i = http_header_parse(&client->http_req, client->recv_buf, client->recv_len); if( i == 0 ) { /* header not complete yet, continue */ err = 0; break; } else if( i < 0 ) { err = -i; break; } /* find a remote server to redirect to */ if( strcmp(req_url->path, "/p2p_router", strlen("/p2p_router"))==0 ) { addrlen = iaddr_pack(&addr, INADDR_ANY, 8969); } else { addrlen = iaddr_pack(&addr, INADDR_ANY, 80); } /* start connecting to remote server */ client->redirect_sock = socket(AF_INET, SOCK_STREAM, 0); assertb_sockerr(client->redirect_sock>=0); i = sock_nonblock(client->redirect_sock, 1); assertb_sockerr(i==0); i = connect(client->redirect_sock, (struct sockaddr*)&addr, addrlen); assertb_sockerr(i==0 || sock_wouldblock(client->redirect_sock, i)); /* stop reading from client, and wait for connection to complete */ fdselect_unset(server->fdselect, client->sock, FDSELECT_READ); fdselect_set(server->fdselect, client->redirect_sock, FDSELECT_READ, http_redirect_client_select_redirect_connect, client); i = snprintf(buf, sizeof(buf), "%s%s", server->root_dir, client->http_req.uri); err = 404; /* file not found */ i = stat(buf, &st); assertb(i==0); client->send_file = fopen(buf, "r"); assertb(client->send_file); debug(DEBUG_INFO, ("http_redirect_client_select_read: sending file=%s\n", buf)); i = snprintf(buf, sizeof(buf), "HTTP/1.0 200 Ok\r\n" "Pragma: no-cache\r\n" "Cache-Control: no-cache\r\n" "Connection: keep-alive\r\n" "Content-Length: %lu\r\n" "Content-Type: text/plain\r\n" "\r\n" ,st.st_size); n = i; i = send(client->sock, buf, n, 0); assertb(i==n); /* stop reading and start writing */ fdselect_unset(server->fdselect, client->sock, FDSELECT_READ); fdselect_set(server->fdselect, client->sock, FDSELECT_WRITE, http_redirect_client_select_write, client); err = 0; } while(0); if( err > 0 ) { i = snprintf(buf, sizeof(buf), "HTTP/1.0 %d\r\n" "Content-Type: text/html; charset=iso-8859-1\r\n" "\r\n" "<HTML><HEAD>\r\n" "<TITLE>HTTP Error %d</TITLE>\r\n" "</HEAD><BODY>\r\n" "<H1>HTTP Error %d</H1>\r\n" "%s<br>\r\n" "<HR>\r\n" "</BODY></HTML>\r\n" , err, err, err , client->http_req.uri); send(client->sock, buf, i, 0); } if( err ) { http_redirect_client_free(client); } }
// track a tcp stream. returns the difference between this packet's // SEQ and the expected next SEQ. int IpConnTrack_track_stream(IpConnTrack *self, IpConn *conn, IpConnTcpQueue *queue, struct netpkt *pkt, int buffer_stream) { netpkt_tcp *tcp; netpkt_udp *udp; tcp_seq_t seq; char *dst, *src; int len, diff=0; do { tcp = pkt->pkt_tcp; udp = pkt->pkt_udp; src = pkt->pkt_msg; len = pkt->pkt_len; diff = 0; if( tcp ) { if( tcp_ack(tcp) ) { queue->ack = ntohl(tcp->ack_seq); } queue->win = ntohs(tcp->window); seq = ntohl(tcp->seq); if( !queue->seq_ok ) { queue->seq_syn = seq; queue->seq = seq; queue->seq_ok = 1; if( tcp_syn(tcp) ) { queue->seq++; } else { conn->conn_pkt_flags |= CONN_PKT_TCP_MISSED_SYN; } } diff = tcp_seq_diff(seq, queue->seq); if( diff > 1 ) { // ignore packets (far) in the future conn->conn_pkt_flags |= CONN_PKT_TCP_FUTURE_SEQ; break; } src += -diff; len -= -diff; if( len <= 0 ) { // ignore past packets break; } queue->seq += len; } else if( udp ) { } if( buffer_stream ) { dst = (char*)array_add(&queue->buf, len); assertb(dst); memcpy(dst, src, len); } } while(0); return diff; }
// returns 0 iff read not complete, >0 bytes read, <0 on error int console_read(console_t console, char *buf, int buflen) { int i, err; DWORD dw=0; int lastError; int n = 0; do { // finish the previous overlapped read assertb( console->read_pending ); if( console->read_result ) { dw = console->read_result; } else { i = GetOverlappedResult(console->read_handle, &console->read_overlap, &dw, FALSE); if( !i && GetLastError() == ERROR_IO_INCOMPLETE ) { n = 0; err = 0; break; } assertb_syserr(i); console->read_pending = 0; } n = 0; while(1) { i = MIN((int)dw, buflen - n); memcpy(buf + n, console->read_buf, i); if( i < dw ) { i = dw - i; console->read_result = 5; memcpy(console->read_buf, console->read_buf + i, i); SetEvent(console->read_event); break; } // start a new overlapped read memset(&console->read_overlap, 0, sizeof(console->read_overlap)); ResetEvent(console->read_event); console->read_overlap.hEvent = console->read_event; console->read_result = 0; dw = sizeof(console->read_buf); debug(DEBUG_INFO, ("console_read reading dw=%ld\n", dw)); i = ReadFile(console->read_handle, console->read_buf, sizeof(console->read_buf), &dw, &console->read_overlap); lastError = GetLastError(); debug(DEBUG_INFO, ("console_read" " i=%d" " dw=%ld" " GetLastError()=%d" " ERROR_IO_PENDING=%d" " IsSet(read_event)=%d" "\n" , i, (long)dw, lastError, ERROR_IO_PENDING , (int)(WaitForSingleObject(console->read_overlap.hEvent, 0) == WAIT_OBJECT_0) )); if( i ) { continue; } else if( lastError == ERROR_IO_PENDING ) { console->read_pending = 1; console->read_result = 0; break; } else { assertb_syserr(0); } } err = 0; } while(0); return err ? err : n; }
http_keyval_t* http_cgi_args(pool_t *pool, char *src, int src_len) { char **pkv=0; char *src_end; char *buf = 0; char *word = 0; http_keyval_t *node=0, *node_first=0; int i; do { if( src_len <= 0 ) { src_len = strlen(src); } src_end = src+src_len; buf = pool_malloc(pool, src_len); assertb(buf); word = src; node = pool_malloc(pool, sizeof(*node)); assertb(node); node_first = node; pkv = &node->key; for(; src<src_end; src++) { if( !(*src == '&' || *src == '=') ) { /* no delimiter yet */ continue; } /* decode key or val */ i = http_cgi_dec(word, src-word, buf, src_len); assertb(i>=0); *pkv = pool_malloc(pool, i+1); memcpy(*pkv, buf, i); (*pkv)[i] = 0; if( *src == '&' ) { /* start new key */ assertb(node); node->next = pool_malloc(pool, sizeof(*node)); node = node->next; pkv = &node->key; } else if ( *src == '=' ) { /* new val for current key */ assertb(node && !node->val); pkv = &node->val; } src++; word = src; } } while(0); if( src < src_end ) { /* error! */ http_keyval_free(pool, node_first); pool_free(pool, buf); return 0; } /* decode key or val */ if( src > word ) { i = http_cgi_dec(word, src-word, buf, src_len); *pkv = pool_malloc(pool, i+1); memcpy(*pkv, buf, i); (*pkv)[i] = 0; } pool_free(pool, buf); return node_first; }
int main(int argc, char **argv) { hash_t h; elt *elts, *p; int nelts = 0; char *c; int i; do { hash_zero(&h); if( argc>1 ) { nelts = strtoul(argv[1], &c, 0); } if( nelts == 0 ) { nelts = 1000; } elts = (elt*)calloc(nelts*sizeof(*elts),1); test_string(nelts); hash_init(&h, hash_hash_int, hash_cmp_int, 0, 0, 1); // put everything in for(i=0, p=elts; i<nelts; i++, p++) { p->in_hash = 1; hash_put(&h, p, p); } verify(&h, elts, nelts, "put"); verify(&h, elts, nelts, "put"); // delete every even element for(i=0, p=elts; i<nelts; i+=2, p+=2) { p->in_hash = 0; hash_free(&h, hash_get(&h, p)); } verify(&h, elts, nelts, "delete even"); // delete every odd element for(i=1, p=elts+1; i<nelts; i+=2, p+=2) { p->in_hash = 0; hash_free(&h, hash_get(&h, p)); } verify(&h, elts, nelts, "delete odd"); // randomly insert and delete stuff for(i=0; i<3*nelts; i++) { int j = (int)(1.0*nelts*rand()/RAND_MAX); p = elts + j; if( (int)(10.0*rand()/RAND_MAX)+1 > 1 ) { p->in_hash = 1; hash_put(&h, p, p); } else { p->in_hash = 0; hash_free(&h, hash_get(&h, p)); } } verify(&h, elts, nelts, "random insert/delete"); hash_clear(&h); /* loop forever looking for memory leak */ if( 0 ) { hash_init(&h, hash_hash_int, hash_cmp_int, 0, 0, 1); for(i=0; ;i++) { hash_node_t *node; hash_remove(&h, (void*)(intptr_t)(i-1)); hash_put(&h, (void*)(intptr_t)i, (void*)(intptr_t)i); node = hash_get(&h, (void*)(intptr_t)(i-1)); assertb(!node); node = hash_get(&h, (void*)(intptr_t)i); assertb(node); assertb((intptr_t)node->node_val == i); } } } while(0); return 0; }
IpConn* IpConnTrack_track_pkt(IpConnTrack *self, struct netpkt *pkt, int track_flags) { IpConnAddr key; IpConn *conn=0; IpConnTcpQueue *queue=0; int tmp_port; //int err=-1; int i; int flags=0, local=0; hash_node_t *node=0; u32 tmp_addr; u32 *addr; netpkt_ip *ip=0; netpkt_tcp *tcp=0; netpkt_udp *udp=0; //netpkt_icmp *icmp=0; ip = pkt->pkt_ip; tcp = pkt->pkt_tcp; udp = pkt->pkt_udp; //icmp = pkt->pkt_icmp; if( !ip || (!tcp && !udp) ) { return 0; } do { /* check if this matches one of my local addresses */ local = 0; for(i=array_count(&self->m_local_addrs), addr=(u32*)array_get(&self->m_local_addrs, 0); i>0; i--, addr++) { if( ip->src == *addr ) { flags |= CONN_PKT_LOCAL_SRC; local = 1; } if( ip->dst == *addr ) { flags |= CONN_PKT_LOCAL_DST; local = 1; } } // ignore non-local packets if( (track_flags & IPCONN_TRACK_LOCAL) && !local ) { break; } /* The canonical hash key in self->conn_hash is client_ip/server_ip/client_port/server_port */ memset(&key, 0, sizeof(key)); /* see if this packet is from server to client. */ flags |= CONN_PKT_FROM_SERVER; key.proto = ip->p; key.client_addr = ip->dst; key.server_addr = ip->src; if( tcp ) { key.client_port = ntohs(tcp->dest); key.server_port = ntohs(tcp->source); } else if( udp ) { key.client_port = ntohs(udp->dest); key.server_port = ntohs(udp->source); } node = hash_get(&self->m_conn_hash, &key); if( node ) { //debug(("track_pkt: packet from server conn=%p\n", node->hash_val)); break; } /* otherwise, this packet is from client to server */ flags &= ~CONN_PKT_FROM_SERVER; flags |= CONN_PKT_FROM_CLIENT; SWAP(key.client_addr, key.server_addr, tmp_addr); SWAP(key.client_port, key.server_port, tmp_port); node = hash_get(&self->m_conn_hash, &key); if( node ) { //debug(("track_pkt: packet from client conn=%p\n", node->hash_val)); break; } // Only start connections on a pure TCP SYN, not a SYN,ACK //if( tcp && (!tcp_syn(tcp) || tcp_ack(tcp)) ) { // break; //} /* doesn't match anything, start a new connection */ flags |= CONN_PKT_FIRST; conn = (IpConn*)malloc(sizeof(*conn)); assertb(conn); IpConn_init(conn); conn->conn_addr = key; conn->conn_state = CONN_STATE_SYN; conn->conn_time_first = mstime(); if( flags & CONN_PKT_LOCAL_DST ) { conn->conn_flags |= CONN_LOCAL_SERVER; } if( flags & CONN_PKT_LOCAL_SRC ) { conn->conn_flags |= CONN_LOCAL_CLIENT; } //debug(("track_pkt: new connection conn=%p\n", conn)); node = hash_put(&self->m_conn_hash, conn, conn); //err = 0; } while(0); if( !node ) { return 0; } conn = (IpConn*)node->node_val; conn->conn_pkt_flags = flags; IpConnTrack_track_state(self, conn, pkt); // track the stream itself if( conn->conn_pkt_flags & CONN_PKT_FROM_SERVER ) { queue = &conn->queue_server; } else if( conn->conn_pkt_flags & CONN_PKT_FROM_CLIENT ) { queue = &conn->queue_client; } if( queue ) { IpConnTrack_track_stream(self, conn, queue, pkt, track_flags & IPCONN_TRACK_BUFFER); } return conn; }