[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Re: What's wrong?



On Tue, Jan 05, 1999 at 10:52:24AM +0100, Tibor Koleszar wrote:
> I'm writing an mrtg-like program. It's finished but i dont want to use the
> kernel's ip accounting, so I try to write a RAW SOCKET based traffic
> counter. I've written a small program following by the socket faq and man
> pages, but i think it's reading bad ip headers. Here is the program:

	Well, I have many things to comment about your code:

> extern int errno;
* Please don't define `errno'. Include <errno.h> instead.

> struct ip_pkt {
>  struct iphdr ip;
>  char *buffer;
> } pkt;
* That struct is just 24 bytes: 20 for a `struct iphdr' and 4 for a
  `char *'. Maybe you wanted to use `char buffer[1024]' or something
  like that.
* The size of the IP header in a packet is not always 20 bytes (that
  is, `sizeof(struct iphdr)'; in an IP packet there can be options;
  the correct size of an IP header is `4*ip->ihl' (in bytes).

>    if ((s = socket(AF_INET, SOCK_PACKET, PROTO)) == -1) {
* SOCK_PACKET is obsoleted in linux-2.1 and linux-2.2. You should use
  `socket(PF_PACKET, SOCK_RAW, PROTO)' and, if that fails, use
  your `socket(PF_INET, SOCK_PACKET, PROTO)'.
* SOCK_PACKET (and PF_PACKET) adds a 14-byte header to each packet
  received: the ethernet header.  Thus, you are interpreting an
  ethernet header as an IP packet in your code.

>      read(s, &pkt, sizeof(struct ip_pkt));
* I think you should use `recv' or `recvfrom' instead of `read'.

	In short, I would rewrite all that code this way:

----------------------------------------------------------------------
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/if_ether.h>
#include <netinet/in.h>
#include <netinet/ip.h>

#define PROTO htons(0x0800)

char buffer[65536];

int main(void)
{
	int s;
	struct in_addr in;
	struct iphdr * ip;

	s = socket(PF_PACKET, SOCK_RAW, PROTO);
	if (s == -1) {
		s = socket(PF_INET, SOCK_PACKET, PROTO);
	}
	if (s == -1) {
		perror("socket");
		exit(1);
	}

	while(1) {
		recv(s, buffer, 65536, 0);
		ip = (struct iphdr *)(buffer+sizeof(struct ethhdr));
		in.s_addr = ip->saddr;
		printf("IP Packet from: %s\n", inet_ntoa(in));
	}
}
----------------------------------------------------------------------

-- 
Juan Cespedes


Reply to: