📄 tcp.c
字号:
} else return; } else { struct skbuff *p = rcv->listtail; pakiet = mknew(struct skbuff); pakiet->truesize = skblen; rcv->rmem_alloc += pakiet->truesize; pakiet->len = datalen; pakiet->data = malloc(datalen); if (!pakiet->data) nids_params.no_mem("tcp_queue"); memcpy(pakiet->data, data, datalen); pakiet->fin = (this_tcphdr->th_flags & TH_FIN); pakiet->seq = this_seq; pakiet->urg = (this_tcphdr->th_flags & TH_URG); pakiet->urg_ptr = ntohs(this_tcphdr->th_urp); for (;;) { if (!p || !after(p->seq, this_seq)) break; p = p->prev; } if (!p) { pakiet->prev = 0; pakiet->next = rcv->list; if (rcv->list) rcv->list->prev = pakiet; rcv->list = pakiet; if (!rcv->listtail) rcv->listtail = pakiet; } else { pakiet->next = p->next; p->next = pakiet; pakiet->prev = p; if (pakiet->next) pakiet->next->prev = pakiet; else rcv->listtail = pakiet; } }}static voidprune_queue(struct half_stream * rcv, struct tcphdr * this_tcphdr){ struct skbuff *tmp, *p = rcv->list; nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_BIGQUEUE, ugly_iphdr, this_tcphdr); while (p) { free(p->data); tmp = p->next; free(p); p = tmp; } rcv->list = rcv->listtail = 0; rcv->rmem_alloc = 0;}static voidhandle_ack(struct tcp_stream * a_tcp, struct half_stream * snd, struct half_stream * rcv, u_int acknum){ int ackdiff; ackdiff = acknum - snd->ack_seq; if (ackdiff > 0) { snd->ack_seq = acknum; }}static voidcheck_flags(struct ip * iph, struct tcphdr * th){ u_char flag = *(((u_char *) th) + 13); if (flag & 0x40 || flag & 0x80) nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_BADFLAGS, iph, th);}struct tcp_stream *find_stream(struct tcphdr * this_tcphdr, struct ip * this_iphdr, int *from_client){ struct tuple4 this_addr, reversed; int hash_index; struct tcp_stream *a_tcp; this_addr.source = ntohs(this_tcphdr->th_sport); this_addr.dest = ntohs(this_tcphdr->th_dport); this_addr.saddr = this_iphdr->ip_src.s_addr; this_addr.daddr = this_iphdr->ip_dst.s_addr; hash_index = mk_hash_index(this_addr); for (a_tcp = tcp_stream_table[hash_index]; a_tcp && !b_comp(a_tcp->addr, this_addr); a_tcp = a_tcp->next_node); if (a_tcp) { *from_client = 1; return a_tcp; } reversed.source = ntohs(this_tcphdr->th_dport); reversed.dest = ntohs(this_tcphdr->th_sport); reversed.saddr = this_iphdr->ip_dst.s_addr; reversed.daddr = this_iphdr->ip_src.s_addr; hash_index = mk_hash_index(reversed); for (a_tcp = tcp_stream_table[hash_index]; a_tcp && !b_comp(a_tcp->addr, reversed); a_tcp = a_tcp->next_node); if (a_tcp) { *from_client = 0; return a_tcp; } else return 0;}void clear_stream_buffers(){ int i; struct lurker_node *j; struct tcp_stream *a_tcp; for (i = 0; i < tcp_stream_table_size; i++) { for (a_tcp = tcp_stream_table[i]; a_tcp; a_tcp = a_tcp->next_node) { for (j = a_tcp->listeners; j; j = j->next) { a_tcp->nids_state = NIDS_EXITING; (j->item)(a_tcp, &j->data); } } }} voidprocess_tcp(u_char * data, int skblen){ struct ip *this_iphdr = (struct ip *)data; struct tcphdr *this_tcphdr = (struct tcphdr *)(data + 4 * this_iphdr->ip_hl); int datalen, iplen; int from_client = 1; unsigned int tmp_ts; struct tcp_stream *a_tcp; struct half_stream *snd, *rcv; ugly_iphdr = this_iphdr; iplen = ntohs(this_iphdr->ip_len); if (iplen - 4 * this_iphdr->ip_hl <sizeof(struct tcphdr)) { nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr, this_tcphdr); return; } // ktos sie bawi datalen = iplen - 4 * this_iphdr->ip_hl - 4 * this_tcphdr->th_off; if (datalen < 0) { nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr, this_tcphdr); return; } // ktos sie bawi if ((this_iphdr->ip_src.s_addr | this_iphdr->ip_dst.s_addr) == 0) { nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr, this_tcphdr); return; } if (!(this_tcphdr->th_flags & TH_ACK)) detect_scan(this_iphdr); if (!nids_params.n_tcp_streams) return; if (my_tcp_check(this_tcphdr, iplen - 4 * this_iphdr->ip_hl, this_iphdr->ip_src.s_addr, this_iphdr->ip_dst.s_addr)) { nids_params.syslog(NIDS_WARN_TCP, NIDS_WARN_TCP_HDR, this_iphdr, this_tcphdr); return; } check_flags(this_iphdr, this_tcphdr); if (!(a_tcp = find_stream(this_tcphdr, this_iphdr, &from_client))) { if ((this_tcphdr->th_flags & TH_SYN) && !(this_tcphdr->th_flags & TH_ACK) && !(this_tcphdr->th_flags & TH_RST)) add_new_tcp(this_tcphdr, this_iphdr); return; } if (from_client) { snd = &a_tcp->client; rcv = &a_tcp->server; } else { rcv = &a_tcp->client; snd = &a_tcp->server; } if ((this_tcphdr->th_flags & TH_SYN)) { if (from_client || a_tcp->client.state != TCP_SYN_SENT || a_tcp->server.state != TCP_CLOSE || !(this_tcphdr->th_flags & TH_ACK)) return; if (a_tcp->client.seq != ntohl(this_tcphdr->th_ack)) return; a_tcp->server.state = TCP_SYN_RECV; a_tcp->server.seq = ntohl(this_tcphdr->th_seq) + 1; a_tcp->server.first_data_seq = a_tcp->server.seq; a_tcp->server.ack_seq = ntohl(this_tcphdr->th_ack); a_tcp->server.window = ntohs(this_tcphdr->th_win); if (a_tcp->client.ts_on) { a_tcp->server.ts_on = get_ts(this_tcphdr, &a_tcp->server.curr_ts); if (!a_tcp->server.ts_on) a_tcp->client.ts_on = 0; } else a_tcp->server.ts_on = 0; return; } if (!before(ntohl(this_tcphdr->th_seq), rcv->ack_seq + rcv->window) || before(ntohl(this_tcphdr->th_seq) + datalen, rcv->ack_seq)) return; if ((this_tcphdr->th_flags & TH_RST)) { if (a_tcp->nids_state == NIDS_DATA) { struct lurker_node *i; a_tcp->nids_state = NIDS_RESET; for (i = a_tcp->listeners; i; i = i->next) (i->item) (a_tcp, &i->data); } free_tcp(a_tcp); return; } /* PAWS check */ if (rcv->ts_on && get_ts(this_tcphdr, &tmp_ts) && before(tmp_ts, snd->curr_ts)) return; if ((this_tcphdr->th_flags & TH_ACK)) { if (from_client && a_tcp->client.state == TCP_SYN_SENT && a_tcp->server.state == TCP_SYN_RECV) { if (ntohl(this_tcphdr->th_ack) == a_tcp->server.seq) { a_tcp->client.state = TCP_ESTABLISHED; a_tcp->client.ack_seq = ntohl(this_tcphdr->th_ack); { struct proc_node *i; struct lurker_node *j; void *data; a_tcp->server.state = TCP_ESTABLISHED; a_tcp->nids_state = NIDS_JUST_EST; for (i = tcp_procs; i; i = i->next) { char whatto = 0; char cc = a_tcp->client.collect; char sc = a_tcp->server.collect; char ccu = a_tcp->client.collect_urg; char scu = a_tcp->server.collect_urg; (i->item) (a_tcp, &data); if (cc < a_tcp->client.collect) whatto |= COLLECT_cc; if (ccu < a_tcp->client.collect_urg) whatto |= COLLECT_ccu; if (sc < a_tcp->server.collect) whatto |= COLLECT_sc; if (scu < a_tcp->server.collect_urg) whatto |= COLLECT_scu; if (nids_params.one_loop_less) { if (a_tcp->client.collect >=2) { a_tcp->client.collect=cc; whatto&=~COLLECT_cc; } if (a_tcp->server.collect >=2 ) { a_tcp->server.collect=sc; whatto&=~COLLECT_sc; } } if (whatto) { j = mknew(struct lurker_node); j->item = i->item; j->data = data; j->whatto = whatto; j->next = a_tcp->listeners; a_tcp->listeners = j; } } if (!a_tcp->listeners) { free_tcp(a_tcp); return; } a_tcp->nids_state = NIDS_DATA; } } // return; } } if ((this_tcphdr->th_flags & TH_ACK)) { handle_ack(a_tcp, snd, rcv, ntohl(this_tcphdr->th_ack)); if (rcv->state == FIN_SENT) rcv->state = FIN_CONFIRMED; if (rcv->state == FIN_CONFIRMED && snd->state == FIN_CONFIRMED) { struct lurker_node *i; a_tcp->nids_state = NIDS_CLOSE; for (i = a_tcp->listeners; i; i = i->next) (i->item) (a_tcp, &i->data); free_tcp(a_tcp); return; } } if (datalen + (this_tcphdr->th_flags & TH_FIN) > 0) tcp_queue(a_tcp, this_tcphdr, snd, rcv, (char *) (this_tcphdr) + 4 * this_tcphdr->th_off, datalen, skblen); snd->window = ntohs(this_tcphdr->th_win); if (rcv->rmem_alloc > 65535) prune_queue(rcv, this_tcphdr); if (!a_tcp->listeners) free_tcp(a_tcp);}voidnids_discard(struct tcp_stream * a_tcp, int num){ if (num < a_tcp->read) a_tcp->read = num;}voidnids_register_tcp(void (*x)){ struct proc_node *i; i = mknew(struct proc_node); i->item = x; i->next = tcp_procs; tcp_procs = i;}inttcp_init(int size){ int i; if (!nids_params.n_tcp_streams) return 0; tcp_stream_table_size = nids_params.n_tcp_streams; tcp_stream_table = malloc(tcp_stream_table_size * sizeof(char *)); if (!tcp_stream_table) nids_params.no_mem("tcp_init"); memset(tcp_stream_table, 0, tcp_stream_table_size * sizeof(char *)); max_stream = 3 * tcp_stream_table_size / 4; streams_pool = (struct tcp_stream *) malloc((max_stream + 1) * sizeof(struct tcp_stream)); if (!streams_pool) nids_params.no_mem("tcp_init"); for (i = 0; i < max_stream; i++) streams_pool[i].next_free = &(streams_pool[i + 1]); streams_pool[max_stream].next_free = 0; free_streams = streams_pool; init_hash(); return 0;}#if HAVE_ICMPHDR#define STRUCT_ICMP struct icmphdr#define ICMP_CODE code#define ICMP_TYPE type#else#define STRUCT_ICMP struct icmp#define ICMP_CODE icmp_code#define ICMP_TYPE icmp_type#endif#ifndef ICMP_DEST_UNREACH#define ICMP_DEST_UNREACH ICMP_UNREACH#define ICMP_PROT_UNREACH ICMP_UNREACH_PROTOCOL#define ICMP_PORT_UNREACH ICMP_UNREACH_PORT#define NR_ICMP_UNREACH ICMP_MAXTYPE#endif voidprocess_icmp(u_char * data){ struct ip *iph = (struct ip *) data; struct ip *orig_ip; STRUCT_ICMP *pkt; struct tcphdr *th; struct half_stream *hlf; int match_addr; struct tcp_stream *a_tcp; struct lurker_node *i; int from_client; int len = ntohs(iph->ip_len) - (iph->ip_hl << 2); if (len < sizeof(STRUCT_ICMP)) return; pkt = (STRUCT_ICMP *) (data + (iph->ip_hl << 2)); if (ip_compute_csum((char *) pkt, len)) return; if (pkt->ICMP_TYPE != ICMP_DEST_UNREACH) return; len -= 8; // sizeof(struct icmp) is not what we want here if (len < sizeof(struct ip)) return; orig_ip = (struct ip *) (((char *) pkt) + 8); len -= orig_ip->ip_hl << 2; if (len < 8) return; if ((pkt->ICMP_CODE & 15) == ICMP_PROT_UNREACH || (pkt->ICMP_CODE & 15) == ICMP_PORT_UNREACH) match_addr = 1; else match_addr = 0; if (pkt->ICMP_CODE > NR_ICMP_UNREACH) return; if (match_addr && (iph->ip_src.s_addr != orig_ip->ip_dst.s_addr)) return; if (orig_ip->ip_p != IPPROTO_TCP) return; th = (struct tcphdr *) (((char *) orig_ip) + (orig_ip->ip_hl << 2)); if (!(a_tcp = find_stream(th, orig_ip, &from_client))) return; if (a_tcp->addr.dest == iph->ip_dst.s_addr) hlf = &a_tcp->server; else hlf = &a_tcp->client; if (hlf->state != TCP_SYN_SENT && hlf->state != TCP_SYN_RECV) return; a_tcp->nids_state = NIDS_RESET; for (i = a_tcp->listeners; i; i = i->next) (i->item) (a_tcp, &i->data); free_tcp(a_tcp);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -