URL: https://www.opennet.me/cgi-bin/openforum/vsluhboard.cgi
Форум: vsluhforumID9
Нить номер: 2762
[ Назад ]

Исходное сообщение
"Проблемы с raw sockets под FreeBSD 5.1"

Отправлено Tsr , 07-Апр-04 15:16 
Доброе время суток!
Не подскажет ли всезнающий олл, как разобраться с сабжем:

при работе с raw socket если во фрагменте:
<cut>
sockd = socket(AF_INET,SOCK_RAW,IPPROTO_RAW);

char on = 1;
setsockopt(sockd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(on));

<cut>
переменная on != 0
при вызове sendto выдается ошибка "неверный аргумент", хотя sockd открылся нормально.
иначе формируется пакет с IP-заголовком, отличным от моего.
Как побороть сие безобразие.

С уважением, Андрей.


Содержание

Сообщения в этом обсуждении
"Проблемы с raw sockets под FreeBSD 5.1"
Отправлено 3bepb , 08-Апр-04 08:56 
У меня тоже такая проблема была. Я сильно не разбирался но если правильно составить ip заголовок то всё должно заработать видимо ядро его проверяет.
Для примера:
#include <stdio.h>
#include <ctype.h>
#include <errno.h>
#include <netdb.h>
#include <stdlib.h>
#include <string.h>
#include <netinet/in_systm.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netinet/ip.h>
#include <netinet/tcp.h>

#define PORT 40

int send_packet(int sock_, struct sockaddr_in sin_, char *buff_);
u_short checksum(u_short *addr, int len);

int main(int argc, char *argv[])
{
  int i, sock, on = 1;
  struct sockaddr_in sin;
  struct _pseudoheader {
    struct in_addr src_addr;
    struct in_addr dst_addr;
    u_char zero;
    u_char protocol;
    u_char length;
  } pseudoheader;
  struct in_addr src, dst;
  struct ip *iph;
  struct tcphdr *tcp;
  u_char *buf = (char *)malloc(sizeof(struct ip) + sizeof(struct tcphdr));
  u_char *pseudo = (char *)malloc(sizeof(struct _pseudoheader) +
  sizeof(struct tcphdr));

  if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_RAW)) < 0) {
    printf("socket\n");
    exit(1);
  }

  if (setsockopt(sock, 0, 2, &on, sizeof(on)) < 0) {
    printf("setsockopt\n");
    exit(1);
  }
  
  iph = (struct ip *)buf;
  tcp = (struct tcphdr *)(buf + sizeof(struct ip));

  inet_aton("10.16.17.23",&src);
  inet_aton("10.16.17.1",&dst);

  pseudoheader.src_addr = src;
  pseudoheader.dst_addr = dst;
  pseudoheader.zero = 0;
  pseudoheader.protocol = IPPROTO_TCP;
  pseudoheader.length = htons(sizeof(struct tcphdr));

  memcpy(pseudo,&pseudoheader,sizeof(struct _pseudoheader));
  memcpy(pseudo + sizeof(struct _pseudoheader),buf + sizeof(struct ip),
sizeof(struct tcphdr));

  iph->ip_hl = 5;
  iph->ip_v  = 4;
  iph->ip_tos = 0;
  iph->ip_len = ntohs(sizeof(struct ip) + sizeof(struct tcphdr));
  iph->ip_id  = rand();
  iph->ip_off = htons(IP_DF);
  iph->ip_ttl = 64;
  iph->ip_p = IPPROTO_TCP;
  iph->ip_sum = 0;
  iph->ip_src = src;
  iph->ip_dst = dst;
  
  tcp->th_sport = htons(rand());
  tcp->th_dport = htons(PORT);
  tcp->th_seq   = ntohl(rand());
  tcp->th_ack   = rand();
  tcp->th_off   = 5;
  tcp->th_flags = TH_SYN;
  tcp->th_win   = htons(512);
  tcp->th_sum   = checksum((u_short *)pseudo,sizeof(struct _pseudoheader) +
sizeof(struct tcphdr));
  tcp->th_urp   = 0;

  sin.sin_family = AF_INET;
  sin.sin_port = htons(PORT);
  sin.sin_addr = dst;

  send_packet(sock,sin,buf);

  free(buf);  
  free(pseudo);
  return 0;
}

int send_packet(int sock_, struct sockaddr_in sin_, char *buff_)
{
  int err;

  if((err = sendto(sock_, buff_, (size_t)(sizeof(struct ip) +
sizeof(struct tcphdr)), 0, (struct sockaddr *)&sin_, sizeof(sin_))) < 0) {
    printf("sendto %d\n",err);
  }
  
  printf("packet send...\n");

  return err;
}

u_short checksum(u_short *addr, int len)
{
  u_short *w = addr;
  int i = len;
  int sum = 0;
  u_short answer;
  
  while(i > 0) {
    sum += *w++;
    i -= 2;
  }
  if(i == 1) sum += *(u_char *)w;
  sum = (sum >> 16) + (sum & 0xffff);
  sum = sum + (sum >> 16);
  
  return (~sum);  
}
  
Код я писал в OpenBSD.