Программирование Raw-сокетов на C.
t0x1n
12.06.06
Сокеты бывают трех типов: 
SOCK_DGRAM датаграмные сокеты - сокеты которые отсылаются в сеть без запроса на соединение (к ним относятся UDP сокеты)
SOCK_STREAM потоковые сокеты - сокеты требующие соединение (TCP сокеты)
SOCK_RAW сырые сокеты - то что хотим, т.е. пишем сокеты с нуля.
В этой статье нас будут интересовать RAW (сырые) сокеты.

В качестве примера я напишу программу которая посылает обычный UDP пакет.
Если вы пользуетесь операционной системой Linux то код программы нужно компилировать с параметром
-D_BSD_SOURCE т.к. мы будет использовать бсдешные сокеты. Также компилировать и запускать 
код программы необходимо с правами root (суперпользователя). Для этого достаточно ввести команду
su root.

Начнем...

Для начало функции нужные нам для работы:

Открытие RAW сокета:
int sock;
sock=socket(PF_INET, SOCKET_RAW, протокол);
Закрытие сокета:
close (sock);
Указание порта отправителя и получателя:
htons(порт);
Указание IP адреса отправителя и получателя:
inet_addr ("IP адрес");

Теперь покажу как устроен заголовок UDP на Си т.к. мы будем писать прогрумму посылающую UDP пакет.
UDP:
uh_sport Порт отправителя
uh_dport Порт получателя
uh_ulen  Длина заголовка
uh_sum   Контрольная сумма

Сообщения об ошибках:
Чтобы в случае ошибки программа нам выдала сообщение о ней 
необходимо написать такую конструкцию:
int sock;
socket(PF_INET, SOCK_RAW, IPPROTO_UDP); //Создаем сокет
if ((sock)<0) //Если sock<0 тогда
{
perror ("socket"); //выдать сообщение об ошибке
} else { //Если нет то
printf ("socket ok"); //Выдать сообщение socket ok
}

А вот код программы посылающий UDP пакет:
#include 
#include 
#include 

main()
{
	int sock;
	sock = socket(PF_INET, SOCK_RAW, IPPROTO_UDP); //Открываем сокет
	if ((sock)<0){
	perror ("socket");
	} else {
	printf ("socket ok\n");
	}
	char buf[9999];

	/* Структуры*/
	struct sockaddr_in sin;
	struct udphdr *udph=(struct udphdr*)buf;
	sin.sin_family = AF_INET;
	sin.sin_addr.s_addr = inet_addr("127.0.0.1"); //IP адрес получателя
	/***********/	

	/*UDP заголовок */
	udph->uh_sport=htons(21); //Порт отправителя
	udph->uh_dport=htons(22); //Порт получателя
	udph->uh_ulen=0; //Длина заголовка
	udph->uh_sum=0; //Контрольная сумма
	/***************/
	
	/*Посылаем пакет*/
	if((sendto(sock, &udph, sizeof(udph), 0, (struct sockaddr*)&sin, sizeof(sin)))<0){
	perror ("sendto");
	} else {
	printf ("sendto ok\n");
	}
	close (sock); //Закрываем сокет
}

Теперь компилируем и запускаем код с правами рута. Чтобы вполне убедиться, что программ работает
можете запустить tcpdump и посмотреть отослался пакет или нет.

[t0x1n@t0x1n~]$ su root
[root@t0x1n~]$ gcc -D_BSD_SOURCE udp.c -udp
[root@t0x1n~]$ ./udp
socket ok
sendto ok
[root@t0x1n~]$

Ну вот думаю и все! Желаю удач в сетевом кодинге :)

ниссан патрол