Вот собсно raw сокеты в 2-х словах. Код на Дельфи, но винапи он и в Африке винапи. PChar соответственно в си char*. Элементарного типа WSAStartup не касаюсь.
Инициализация
Код:
//декларация обработки ивента
const
WM_ListenSocketEvent = WM_User+1;
....
procedure WMListenSocketEventHandler(var Msg:TMessage);message WM_ListenSocketEvent;
....
function TfrmMain.InitSocket: Boolean;
var
PromiscuousMode: dword;
temp: integer;
BufSize: dword;
begin
result:=false;
// создаем сокет
hSocket := socket(AF_INET, SOCK_RAW, IPPROTO_IP);
if hSocket = INVALID_SOCKET then begin
DeInitSocket(WSAGetLastError);
AddToLog('Raw sockets not supported');
Exit;
end;
FillChar(Addr_in, SizeOf(sockaddr_in), 0);
Addr_in.sin_family:= AF_INET;
// указываем за каким интерфейсом будем следить
Addr_in.sin_addr.s_addr := inet_addr(PChar(Host));
// связываем сокет с локальным адресом
if ScktErrorCheck(bind(hSocket, @Addr_in, SizeOf(sockaddr_in))) = SOCKET_ERROR then exit;
BufSize:=MAX_PACKET_SIZE;
if ScktErrorCheck(SetSockOpt(hSocket, SOL_SOCKET, SO_RCVBUF, PChar(@BufSize), sizeof(BufSize))) = SOCKET_ERROR then exit;
temp:=sizeof(integer);
if ScktErrorCheck(GetSockOpt(hSocket, SOL_SOCKET, SO_RCVBUF, PChar(@BufSize), temp)) = SOCKET_ERROR then exit
else AddToLog('Buffer size = '+IntToHex(BufSize,4));
if ScktErrorCheck(WSAAsyncSelect(hSocket,frmMain.Handle,WM_ListenSocketEvent,FD_READ or FD_CLOSE)) = SOCKET_ERROR then exit;
// Переключаем интерфейс на прием всех пакетов проходящих через интерфейс - promiscuous mode.
PromiscuousMode := 1;
if ScktErrorCheck(ioctlsocket(hSocket, SIO_RCVALL, PromiscuousMode)) = SOCKET_ERROR then exit;
Result := True;
end;
обработчик ивента
Код:
procedure TfrmMain.WMListenSocketEventHandler(var Msg:TMessage);
var
Sock: TSocket;
SockError,PacketSize: integer;
begin
Sock:=TSocket(Msg.WParam);
SockError:=WSAGetSelectError(Msg.lParam);
if SockError <> 0 then begin
CloseSocket(Sock);
Exit;
end;
case WSAGetSelectEvent(Msg.lParam) of
FD_Read: begin
CS.Enter;
PacketSize := recv(hSocket, Packet, MAX_PACKET_SIZE, 0);
// Если есть данные - производим их разбор
ParcePacket(PacketSize);
CS.Leave;
end;
FD_Close: begin
AddToLog('FD_CLOSE');
end;
end;
end;
далее разбор пакета
Код:
if PacketSize <= SizeOf(TIPHeader) then exit;
pIpHdr:=PIPHeader(@Packet[0]);
ipHdrLen:=GetIPHeaderLen(pIpHdr);
pTcpHdr:=PTCPHeader(@Packet[ipHdrLen]);
// определяем тип протокола
if pIpHdr.iph_protocol = IPPROTO_TCP then begin
PacketType := 'TCP';
// Смотрим порт отправителя и получателя
SrcPort := pTcpHdr.sourcePort;
DestPort := pTcpHdr.destinationPort;
end
else exit;
SrcPort := htons(SrcPort);
DestPort := htons(DestPort);
if (SrcPort <> frmMain.FListenPort)and(DestPort <> frmMain.FListenPort) then exit;
// Пишем IP адрес отправителя с портом
AddrSrc.S_addr := pIpHdr.iph_src;
// Пишем IP адрес получателя с портом
AddrDst.S_addr := pIpHdr.iph_dest;
tcpHdrDataOffs:=ipHdrLen + GetTCPDataOffset(@Packet[ipHdrLen]);
PacketFlags:=ntohs(pTcpHdr.flags);
...
в общем на основе структур ip и tcp хедеров разбираем, если что читаем доку "RFC793 - Transmission Control Protocol".
продолжение ниже...