LINUX.ORG.RU

Отправка пакетов СОКЕТами не доходит до интерфейса eth0. Wireshark видит их только на any-интерфейсе


0

0

Создание сокета происходит вот так:
argv[1]=IP;
argv[2]=Interface name;

	unsigned char dst_mac[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};
	int sock=socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	struct ifreq ifr;
	strncpy((char*)ifr.ifr_name, argv[2], IFNAMSIZ);
	if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) {
		perror("getting device index number");
		return 1;
	}
	printf("Interface index=%d\n",ifr.ifr_ifindex);
	if(ioctl(sock, SIOCGIFHWADDR, &ifr)<0){
		perror("getting device addr");
		return 1;
	}
	memcpy(scr_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
	printf("MAC=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",scr_mac[0],scr_mac[1],scr_mac[2],scr_mac[3],scr_mac[4],scr_mac[5]);
	struct sockaddr_in sa_in;
	if(ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
		perror("ioctl SIOCGIFADDR");
		return -1;
	}
	memset((void *)&sa_in, 0, sizeof(struct sockaddr_in));
	memcpy((void *)&sa_in, (void *)&ifr.ifr_addr, sizeof(struct sockaddr));
	    //memcpy((void *)&ifp->ip, (void *)&s.sin_addr.s_addr, sizeof(__u32));
	printf("Interface addr=%x\n",ntohl(sa_in.sin_addr.s_addr));

	struct sockaddr_ll sall;
	  memset(&sall,0,sizeof(sall));
	  sall.sll_family=AF_PACKET;
	  sall.sll_ifindex=ifr.ifr_ifindex;
	  sall.sll_protocol=htons(ETH_P_ALL);
	  sall.sll_halen = ETH_ALEN;
	  memcpy(sall.sll_addr, scr_mac, ETH_ALEN);

	if(bind(sock,(struct sockaddr *)&sall,sizeof(sall))<0) {
		perror("bind");
		exit(1);
	}
Заполнение Ethernet, IP, UDP заголовков производится вручную и корректно.
На одной машине установлена fedora 10 rus, ядро 2.6.27.41, интерфейсы eth0,lo - всё работает правильно.
На другой машине установлена openSuse 11.1, ядра есть разные 2.6.27.7, 2.6.27.41, 2.6.31.3, интерфейсы eth0, eth1, eth2, lo.
eth1,eth2 вроде работают правильно, а вот при посылке пакета на интерфейс eth0 пакеты не отправляются, хотя sendto возвращает правильное число отправленных байт (1052 bytes).
Wireshark видит эти призрачные пакеты только в Any-интерфейсе, соответственно с приписанными заголовками «Linux cooked capture».

На неверно работающей машине iptables -L:
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
Моя программа выводит что для интерфейсов lo/eth0/eth1/eth2:Interface index= 1/4/2/3 соответственно.
ЗЫ:Простите за «многа букаф»)

>Any-интерфейсе
anykey на клавиатуре нажми три раза и всё заработает.

dimon555 ★★★★★
()
Ответ на: комментарий от true_admin

Та не - пинг идёт)
Причём я не «куда-то» отправляю, а в первом случае - с машины А на машину Б. Всё в порядке, с обоих сторон wireshark видит пакеты.
А во втором случае с машины Б на машину А - не отправляется.
Фаервола нема, мистика какая-то...
Добавлю ifconfig неправильно работающей машины «Б»:

eth0      Link encap:Ethernet  HWaddr хх:хх:хх:хх:хх:хх
          inet addr:192.168.0.130  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::f6ce:46ff:fe99:547b/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:25380 errors:0 dropped:0 overruns:0 frame:0
          TX packets:939 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2532789 (2.4 Mb)  TX bytes:81623 (79.7 Kb)
          Interrupt:17

eth1      Link encap:Ethernet  HWaddr уу:уу:уу:уу:уу:уу
          inet addr:192.168.10.1  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::1aa9:5ff:fee9:9bb8/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9500  Metric:1
          RX packets:28 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5000412 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:6427 (6.2 Kb)  TX bytes:2375359437 (2265.3 Mb)
          Interrupt:219

eth2      Link encap:Ethernet  HWaddr zz:zz:zz:zz:zz:zz
          inet addr:192.168.10.2  Bcast:192.168.10.255  Mask:255.255.255.0
          inet6 addr: fe80::1aa9:5ff:fee9:9bbc/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:9500  Metric:1
          RX packets:5000398 errors:0 dropped:0 overruns:0 frame:0
          TX packets:43 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:2465365669 (2351.1 Mb)  TX bytes:7171 (7.0 Kb)
          Interrupt:211

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:52 errors:0 dropped:0 overruns:0 frame:0
          TX packets:52 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:3296 (3.2 Kb)  TX bytes:3296 (3.2 Kb)

SaintSatanist
() автор топика

Как формируется пакет, может выложите куда-нибудь весь исходник. Какая сетёвка eth0?

mky ★★★★★
()
Ответ на: комментарий от true_admin

ну так он же написал что они видны, только не там где нужно.

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от mky

может выложите куда-нибудь весь исходник.

++

Какая сетёвка eth0?

при чём тут сетевая?! Думаешь проблема железа?!

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от Boy_from_Jungle

там где MTU большой, там всё впорядке)
Кстати если кто знает как поставить MTU порядка 30кбайт, буду благодарен.

SaintSatanist
() автор топика
Ответ на: комментарий от mky

Пакет формируется нормально, поскольку на 3х из 4х сетевух всё работает и сниферится верно. Сетевая NC105i PCIe Gigabit Server Adapter, драйвер ядра tg3.

SaintSatanist
() автор топика
Ответ на: комментарий от goose

route:

Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
192.168.0.0     *               255.255.255.0   U     0      0        0 eth0
192.168.10.0    *               255.255.255.0   U     0      0        0 eth1
192.168.10.0    *               255.255.255.0   U     0      0        0 eth2
link-local      *               255.255.0.0     U     0      0        0 eth1
loopback        *               255.0.0.0       U     0      0        0 lo
default         192.168.0.2     0.0.0.0         UG    0      0        0 eth0 

SaintSatanist
() автор топика
Ответ на: комментарий от SaintSatanist

Кстати если кто знает как поставить MTU порядка 30кбайт, буду благодарен.


А что не получается?! Если не изменяет склероз, то макс. МТЮ равен 65536 байт

Boy_from_Jungle ★★★★
()
Ответ на: комментарий от mky

Собственно плевалка UDP-фрэймами.

//Цопирайт хумэна http://www.linux.org.ru/people/SaintSatanist/profile
//Использование этих исходников пиндосами преследуется всеми медведами Сибири

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <linux/if_ether.h>
#include <linux/if_packet.h>
#include <linux/ip.h>
#include <linux/sockios.h>
#include <linux/udp.h>
#include <net/if.h>
#include <netinet/in.h>
#include <sys/socket.h>

u_int16_t csum(u_int16_t *buffer, int size){//для IP и ICMP
	unsigned long cksum=0;
	while(size > 1) { cksum+=*buffer++; size -= 2; }
	if(size) cksum += *(u_int8_t *)buffer;
	cksum = (cksum >> 16) + (cksum & 0xffff);
	cksum += (cksum >>16);
return (u_int16_t)(~cksum);
}

int main(int argc, char* argv[]) {
	printf("Version2010.06.04_16:18:10\n");
	unsigned char scr_mac[6] = {0x00,0x1D, 0x60, 0x79, 0xBB, 0x69};
	unsigned char dst_mac[6] = {0xFF,0xFF, 0xFF, 0xFF, 0xFF, 0xFF};

	if (argc!=3) {
			printf("Команда требует два аргумента\n");
			return 0;
		}
	//argv[1]="192.168.0.XXX";
	//argv[2]="eth0";
	int sock=socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	
	struct ifreq ifr;	
	strncpy((char*)ifr.ifr_name, argv[2], IFNAMSIZ);	
	if (ioctl(sock, SIOGIFINDEX, &ifr) < 0) {
			perror("getting device index number");
			return 1;
	}
	printf("Interface index=%d\n",ifr.ifr_ifindex);
	if(ioctl(sock, SIOCGIFHWADDR, &ifr)<0){
		perror("getting device addr");
		return 1;
	}
	memcpy(scr_mac,ifr.ifr_hwaddr.sa_data,ETH_ALEN);
	printf("MAC=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",scr_mac[0],scr_mac[1],scr_mac[2],scr_mac[3],scr_mac[4],scr_mac[5]);
	struct sockaddr_in sa_in;
	if(ioctl(sock, SIOCGIFADDR, &ifr) < 0) {
		perror("ioctl SIOCGIFADDR");
		return -1;
	}
	memset((void *)&sa_in, 0, sizeof(struct sockaddr_in));
	memcpy((void *)&sa_in, (void *)&ifr.ifr_addr, sizeof(struct sockaddr));

	printf("Interface IP addr=%x\n",ntohl(sa_in.sin_addr.s_addr));
	struct sockaddr_ll sall;
	  memset(&sall,0,sizeof(sall));
	  sall.sll_family=AF_PACKET;
	  sall.sll_ifindex=ifr.ifr_ifindex;
	  sall.sll_protocol=htons(ETH_P_ALL);
	  sall.sll_halen = ETH_ALEN;
	  memcpy(sall.sll_addr, scr_mac, ETH_ALEN);

	if(bind(sock,(struct sockaddr *)&sall,sizeof(sall))<0) {
		perror("bind");
		exit(1);
	}

	int MSG_SIZE=9410;
	int HEADERS_SIZE=sizeof(struct ethhdr) + sizeof(struct iphdr)+sizeof(struct udphdr);
	int BUFSIZE=MSG_SIZE+ HEADERS_SIZE;

	unsigned char data[BUFSIZE];
	struct ethhdr *ethr = (struct ethhdr *) data;
	struct arp_hdr *arp = (struct arp_hdr *)(data + sizeof(struct ethhdr));
	struct iphdr *ip = (struct iphdr *)(data + sizeof(struct ethhdr));
	struct udphdr *udp = (struct udphdr *)(data + sizeof(struct ethhdr) + sizeof(struct iphdr));
	//заполняем Ethernet заголовок
	memcpy(ethr->h_source, scr_mac, ETH_ALEN);
	memcpy(ethr->h_dest, dst_mac, ETH_ALEN);
	ethr->h_proto=htons(ETH_P_IP);
	//заполняем UDP
	udp->source=htons(3426);
	udp->dest=htons(3426);
	udp->len=htons(MSG_SIZE+8);
	udp->check=0;//Убираем проверку, для оптимизации производительности
	//заполняем инэт-протокол
	ip->ihl = 5;//длина заголовка ИП (dword)
	ip->version = 4;  //версия
	ip->tos = 0;			//тип сервиса
	ip->tot_len = htons(ip->ihl*4+ntohs(udp->len));
	ip->id = htons(25276);
	ip->frag_off = 0;
	ip->ttl = 55;
	ip->protocol = 0x11;
	ip->saddr=sa_in.sin_addr.s_addr;
	ip->daddr=inet_addr(argv[1]);
	ip->check = 0;
	ip->check = csum((unsigned short *)ip,sizeof(struct iphdr));
	int n=1,i,reclen;

	printf("Ready to start\n");
	for(i=1;i<MSG_SIZE/10;i++) sprintf(data+HEADERS_SIZE+i*10,"0x%.8x",i);
	unsigned char message[11];
	reclen=HEADERS_SIZE+MSG_SIZE;
	i=0;
	while(i<10){//10 - количество пакетов. Можно поставить мильён)
			sprintf(message,"0x%.8x",i);
			memcpy((void *)(data+HEADERS_SIZE), (void *)message, 10);
			n=send(sock, data, reclen, 0);
			if(n<0)printf("-");
			/*//Раскомментировать для проверки отправляемых данных
			else {
				printf("\nДлина=%d",n);
				for(n=0;n<BUFSIZE;n++){
					if(n%8==0)printf(" ");
					if(n%16==0)printf("\n");
					printf("%.2X ",(u_int8_t)data[n]);
				}
			}
			*/
			i++;
		}

	printf("\nSended.\n");
	return 0;
} 

SaintSatanist
() автор топика
Ответ на: комментарий от Boy_from_Jungle

MTU

Ну сам попробуй))
Если устанавливать командой «ifconfig eth1 mtu 30000», то оно скажет «SIOCSIFMTU: Недопустимый аргумент»

SaintSatanist
() автор топика
Ответ на: комментарий от SaintSatanist

Читал по диагонали, но

reclen=HEADERS_SIZE+MSG_SIZE;

MSG_SIZE=9410;

Вы пытаетесь через SOCK_RAW отправить пакет, больше чем MTU?

mky ★★★★★
()
Ответ на: комментарий от mky

Не пытаюсь) MSG_SIZE был изначально 1410, когда я растянул MTU до 9500, тогда и сделал соответствующий MSG_SIZE.
Кстати, пару раз я наткнулся на замеченное вами несоответствие, но в данном случае send() возвращает отрицательное значение, что выводит на ошибку сразу.

SaintSatanist
() автор топика
Ответ на: комментарий от SaintSatanist

Сегодня:

поставил на машине Б, eth0 в неразборчивый режим. Отправил по eth0 пакеты - wireshark их увидел, хотя слушал интерфейс eth1. Сделал тоже самое, назначив сниффер на eth0, он видит весь трафик, кроме того, что я отправляю (как и раньше). Итак, какого хрена пакеты попадают на другую сетевуху (eth1), когда я включаю promisc на eth0???
Программа-плевалка правильно выводит MAC и IP адреса - они соответствуют назначенному интерфейсу, судя по ifconfig.

SaintSatanist
() автор топика
Ответ на: комментарий от Boy_from_Jungle

Ещё один, блин)
Я же сказал - send() возвращает отрицательное значение при попытке превышения MTU. И загляните в первый пост «вот при посылке пакета на интерфейс eth0 пакеты не отправляются, хотя sendto возвращает правильное число отправленных байт (1052 bytes).»
Проблема была как до изменения MTU, так и после.

SaintSatanist
() автор топика
Ответ на: комментарий от SaintSatanist

Я стал именно по этой причине спрашивать, то у вас sendto возвращает 1052, то размер сообщения 9410, а то 1410. Потом ещё выяснится, что iptables то отключены, то включены, хотя они не должны влиять на SOCK_RAW.

Покажите вывод: «ip addr», «ip route», «ip rule».

Какой командой вы переводите eth0 в promiscuous mode? Что будет, если запустить два wireshark, на eth0 и на eth1? Или такое можно только с tcpdump?

Может поставить на сокет опцию SO_DONTROUTE...

mky ★★★★★
()
Ответ на: комментарий от mky

iptables выключены постоянно

ip addr:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
    inet 127.0.0.2/8 brd 127.255.255.255 scope host secondary lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 18:a9:05:e9:9b:b8 brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.1/24 brd 192.168.10.255 scope global eth1
    inet6 fe80::1aa9:5ff:fee9:9bb8/64 scope link
       valid_lft forever preferred_lft forever
3: eth2: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 18:a9:05:e9:9b:bc brd ff:ff:ff:ff:ff:ff
    inet 192.168.10.2/24 brd 192.168.10.255 scope global eth2
    inet6 fe80::1aa9:5ff:fee9:9bbc/64 scope link
       valid_lft forever preferred_lft forever
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether f4:ce:46:99:54:7b brd ff:ff:ff:ff:ff:ff
    inet 192.168.0.130/24 brd 192.168.0.255 scope global eth0
    inet6 fe80::f6ce:46ff:fe99:547b/64 scope link
       valid_lft forever preferred_lft forever
ip route:
192.168.0.0/24 dev eth0  proto kernel  scope link  src 192.168.0.130
192.168.10.0/24 dev eth1  proto kernel  scope link  src 192.168.10.1
192.168.10.0/24 dev eth2  proto kernel  scope link  src 192.168.10.2
169.254.0.0/16 dev eth0  scope link
127.0.0.0/8 dev lo  scope link
default via 192.168.0.2 dev eth0
ip rule:
0:      from all lookup local
32766:  from all lookup main
32767:  from all lookup default
Неразборчивый режим включаю командой ifconfig eth0 promisc.
Как поставить на сокет SO_DONTROUTE? setsockopt? перед bind-ом писать?

SaintSatanist
() автор топика
Ответ на: комментарий от mky

«Что будет, если запустить два wireshark, на eth0 и на eth1?»
Запустил. После отправки 100 пакетов по eth0, wireshark0 их не увидел, wireshark1 увидел. Это при том, что promisc выключен на всех интерфейсах. Потом отправил ещё 100 пакетов по етх0, wireshark1 увидел только 20 из них. После дальнейших отправок он не видел ничего.

Принял 120 пакетов и всё. wireshark0 моих пакетов не увидел, но стабильно сниферил сетевой трафик.

И вот, что я не сказал ещё - eth1 и eth2 постоянно соединены между собой оптоволокном.

(под wiresharkХ я подразумеваю wireshark ethХ:capturing)

SaintSatanist
() автор топика
Ответ на: комментарий от SaintSatanist

Да, использовать setsockopt(), вроде после bind'а.

А у вас eth1 и eth2 специально так сконфигурированы, что у них адреса из одной подсетки и два маршрута в одну сеть через разные интерфейсы?

И, сам то пакеты уходят куда надо или нет? То есть, если с другой машины дампить, то пакеты через какую сетёвку идут?

Так не знаю, куда копать, вроде всё выглядит нормальным.

mky ★★★★★
()
Ответ на: комментарий от mky

Не увидел последнее сообщение. То есть eth1 и eth2 это петля. А пинг то нормально работает и его пакеты через wireshark видны? Можно попробовать сделать «strace ping - I eth0 192.168.0.XXX» и в вашей программе воспроизвести последовательность syscall'ов.

mky ★★★★★
()
Ответ на: комментарий от mky

ух-ты. Я думал что strace не выполняет, а только выводит последовательность системных вызовов и ввёл «strace poweroff» =)))

SaintSatanist
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.