📄 ip.c
字号:
#include "tcpip.h"/* Decode Stuff */struct proto ipv4_p=init_proto2("ip", ipv4_decode, ipv4_dprint, ip_match, ip_commit);struct proto_req ipv4_r[]={ proto_request("ethernet", __constant_htons(0x0800)), proto_request("sll", __constant_htons(0x0800)), proto_request("linux", __constant_htons(0x0800)), proto_request("__pcap_dlt", 12), /* DLT_RAW */ null_request()};/* Token bucket for ip/ipfrag alerts */struct tokenbucket ip_tb={ .cost=(RATE_SEC/1), /* 1 alert per second */ .burst=(RATE_SEC/1)*10, /* a burst of 10 alerts per second */};/* Generator */struct generator ip_gen=init_generator("sig.ip", NULL);struct generator dip_gen=init_generator("decode.ip", &ip_tb);/* Print out an IPv4 header */int ipv4_dprint(struct layer *l, char *buf, int buflen){ struct in_addr s, d; char sip[32], dip[32]; char end[32]; struct pkt_iphdr *iph=l->h.ip; s.s_addr=iph->saddr; d.s_addr=iph->daddr; strncpy(sip, inet_ntoa(s), 32); strncpy(dip, inet_ntoa(d), 32); if ( iph->frag_off & htons(IP_MF|IP_OFFMASK) ) { snprintf(end, sizeof(end), "(frag %u:%u@%u%s)", ntohs(iph->id), ntohs(iph->tot_len)-(iph->ihl<<2), (ntohs(iph->frag_off)&IP_OFFMASK)<<3, (ntohs(iph->frag_off)&IP_MF) ? "+" : ""); }else if ( l->flags & FLAG_IP_REASM ) { snprintf(end, sizeof(end), "(reasm %u:%u@0)", ntohs(iph->id), ntohs(iph->tot_len)-(iph->ihl<<2)); }else{ snprintf(end, sizeof(end), "len=%u", ntohs(iph->tot_len)); } return snprintf(buf, buflen, "%s > %s ttl=%u proto=%u %s%s", sip,dip,iph->ttl,iph->protocol,end, (l->flags&FLAG_IP_CSUM) ? "" : " !!bad_csum!!");}static inline u_int32_t ip_csum(struct pkt_iphdr *iph){ u_int16_t *tmp=(u_int16_t *)iph; u_int16_t csum; u_int32_t sum=0; int i; for(i=0; i<iph->ihl<<1; i++) { sum+=tmp[i]; if(sum & 0x80000000) { sum = (sum & 0xffff) + (sum >> 16); } } while(sum >> 16) sum = (sum & 0xffff) + (sum >> 16); csum=(~sum) & 0xffff; return csum ? 0 : FLAG_IP_CSUM;}/* Decode an IPv4 packet */void ipv4_decode(struct packet *p){ struct proto_child *pc; int my_layer=p->llen; struct layer *l=&p->layer[my_layer]; int ks=0; /* Check it meets minimum size of packet */ if ( l->h.raw+sizeof(struct pkt_iphdr) > p->end ) { return; } /* Check to see if the whole datagram is here */ if ( l->h.raw+ntohs(l->h.ip->tot_len) > p->end ) { l->flags|=FLAG_IP_DTRUNC; } /* Check the header length isn't bogus, encapsulated * protocols can't overlap the header! */ if ( l->h.ip->ihl<5 ) { static struct alert a=init_alert( "Invalid IP header length", 1, 0, 5); alert(&dip_gen, p, &a); return; } /* We only accept IPv4 */ if ( l->h.ip->version!=4 ) { static struct alert a=init_alert( "IP version != 4", 2, 0, 5); alert(&dip_gen, p, &a); return; } /* The total length can't be less than the header length. */ if ( ntohs(l->h.ip->tot_len) < (l->h.ip->ihl<<2) ) { static struct alert a=init_alert( "IP datagram reported smaller than header", 3, 0, 5); alert(&dip_gen, p, &a); return; } /* We don't really need to check the checksum because you * can't use bad IP header checksums to exploit anything, no * routers will actually pass them on. Though you could * generate attacks locally or it could be a genuine error. * either way, its only 20 bytes! :) */ l->flags|=ip_csum(l->h.ip); /* Use the ihl header field to decode the packet */ if ( (p->layer[p->llen+1].h.raw= l->h.raw+(l->h.ip->ihl<<2)) > p->end ) return; /* We now know we have valid data */ p->llen++; /* Perform IP de-fragmentation */ if ( use_ipfrag && (l->h.ip->frag_off & ipfmask) ) { ks=ipfrag_process(p, my_layer); } /* Only decode fragments with offset 0, ie: * those containing the next header */ if ( l->h.ip->frag_off & __constant_htons(IP_OFFMASK) ) goto nodecode; /* Don't decode too far */ if ( p->llen >= PKT_LAYERS ) goto finish; /* Find a relevent protocol handler to * decode our encapsulated content */ for(pc=l->proto->children; pc; pc=pc->next) { if ( l->h.ip->protocol == pc->id ) { p->layer[p->llen].flags=0; p->layer[p->llen].session=NULL; p->layer[p->llen].proto=pc->proto; pc->proto->decode(p); goto finish; } }nodecode: if ( p->layer[p->llen].h.raw<p->end ) p->layer[p->llen++].proto=NULL; dispatch(p);finish: if ( ks ) ipq_kill(l->session);}/* =================================================== * PACKET MATCHING STUFF BEYOND THIS POINT * =================================================== */struct sig_node ip_root;void ip_match(struct packet *p, unsigned int l){ detect_set(&cur_alert, &alert_depth); detect(ip_root.child, p, l); if ( cur_alert ) { alert(&ip_gen, p, cur_alert); return; }}int ip_commit(struct rule *r){ struct criteria *c; struct sig_node *x; struct matcher *m; struct alert *a; unsigned int i; /* Can't handle this case */ if ( r->num_criteria==0 ) return 0; if ( !(x=calloc(r->num_criteria, sizeof(*x))) ) return 0; /* Copy the alert data */ if ( !(a=calloc(1, sizeof(*a))) ) { free(x); return 0; } memcpy(a, &r->alert, sizeof(*a)); /* Build an array of all the nodes we want to add */ for(c=r->criteria,i=0; c; c=c->next,i++) { char *key; if ( !strcmp(c->crit, "src") ) { key="ip_src"; }else if ( !strcmp(c->crit, "dst") ) { key="ip_dst"; }else if ( !strcmp(c->crit, "sport") ) { key="ip_sport"; }else if ( !strcmp(c->crit, "dport") ) { key="ip_dport"; }else key=c->crit; if ( !(m=matcher_find(key)) ) { mesg(M_ERR,"ip_commit: cannot find '%s' matcher", key); detect_free_sig(x, i); return 0; } x[i].match=m; x[i].n=c->negate; x[i].cost=m->cost; if ( !(x[i].m=m->validate(c->args, &x[i].p, c->modifier, &x[i].cost)) ) { detect_free_sig(x, i); return 0; } } return detect_add_sig(x, r->num_criteria, &ip_root, a);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -