| Daniel Draper 2005-04-14, 2:51 am |
| Hi,
I have written a program to match and log packets in linux using the
libipq interface for netfilter. It works great until it is placed
under load at which time the program hangs, sends cpu load to max and
the machine won't even respond to keyboard strokes leaving me to
physically reboot it.
I have tried commenting out great chunks of my code but seemingly to
no avail. The problem almost seems to not care what my code is doing
only the load on the system or even random.
Has anyone ever encountered this before. The kernel is
2.6.10-1.771_FC2smp (Fedora core 2) and it is on a dual Xeon system.
Any help would be greatly appreciated!
Here is some of the code:
handle = ipq_create_handle(0, PF_INET);
if (!handle)
die(handle);
status = ipq_set_mode(handle, IPQ_COPY_PACKET, MAXBUFF);
if (status < 0)
die(handle);
printf("Starting raptor...\n");
while (1) {
status = ipq_read(handle, buffer, MAXBUFF, 0);
if (status < 0)
die(handle);
/* The gutsy stuff here */
switch (ipq_message_type(buffer)) {
case NLMSG_ERROR:
fprintf(stderr, "An error occurred: %s\n",
(char *)ipq_get_msgerr(buffer));
break;
case IPQM_PACKET: {
ipq_packet_msg_t *p = ipq_get_packet(buffer);
ip = (struct iphdr *)p->payload;
tcp = (struct tcphdr *) (p->payload + (4 * ip->ihl));
/* populate the match structure */
match.src_addr = ip->saddr;
match.dest_addr = ip->daddr;
match.protocol = ip->protocol;
match.odev = p->outdev_name;
match.idev = p->indev_name;
match.bytes = p->data_len;
match.sport = htons(tcp->source);
match.dport = htons(tcp->dest);
/* Run the match */
//tcp_payload = (p->payload + (4 * ip->ihl))+sizeof(struct
tcphdr)+12;
verdict = _match(&match) ? NF_ACCEPT : NF_DROP;
status = ipq_set_verdict(handle, p->packet_id, verdict, 0, NULL);
if (status < 0)
die(handle);
printf(".");
break;
}
}
}
ipq_destroy_handle(handle);
}
int _match(_pkt_match *m) {
int ans = 0;
int up; /* Indicates upstream */
up = !strcmp(m->idev, "eth1");
/* All this does is return true at present */
ans = __match(m, up);
/* Log */
if (ans) {
unsigned int up_bytes = up ? m->bytes : 0;
unsigned int down_bytes = !up ? m->bytes : 0;
/* Log to log tree */
//log_usage(ans, down_bytes, up_bytes);
}
if (m->dport == 8080 || m->sport == 8080)
ans = 1;
return ans;
}
|