LINUX.ORG.RU

raw socket + vlan header


0

1

надо отправить ethernet кадр с vlan хидером. пакет отправляется, но не могу изменить хидере vlan'a TPid, VID, priority и т.п. как это сделать? код отправки примерно такой:

int s;
s = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
...
struct ifreq ifr;
strncpy(ifr.ifr_name, "eth0", IFNAMSIZ);
ioctl(s, SIOCGIFINDEX, &ifr);
...
struct sockaddr_ll socketAddr;
socketAddr.sll_family   = PF_PACKET;
socketAddr.sll_protocol = htons(ETH_P_ALL);
socketAddr.sll_ifindex  = ifr.ifr_ifindex;
socketAddr.sll_hatype   = ARPHRD_ETHER;
socketAddr.sll_pkttype  = PACKET_OTHERHOST;
socketAddr.sll_halen    = ETH_ALEN;
socketAddr.sll_addr[0]  = dstMac[0];
socketAddr.sll_addr[1]  = dstMac[1];
socketAddr.sll_addr[2]  = dstMac[2];
socketAddr.sll_addr[3]  = dstMac[3];
socketAddr.sll_addr[4]  = dstMac[4];
socketAddr.sll_addr[5]  = dstMac[5];
socketAddr.sll_addr[6]  = 0x00;
socketAddr.sll_addr[7]  = 0x00;
...
struct EthHeader
{
	u_char		dstMac[6];
	u_char		srcMac[6];
	u_int16_t	vlanTpid;
	u_char		vlanUserPriority:3;
	u_char		vlanCfi:1;
	u_int16_t	vlanVid:12;
	u_int16_t	ethertype;
            ...
}__attribute__ ((__packed__));
...
struct EthHeader ethHeader;

memset(ethHeader, 0, sizeof(struct EthHeader));

memcpy(&ethHeader.dstMac,dstMac,ETH_ALEN);
memcpy(&ethHeader.srcMac,srcMac,ETH_ALEN);
ethHeader.vlanTpid = htons(0x8100);
ethHeader.vlanUserPriority = htons(4);
ethHeader.vlanVid = htons(5);
ethHeader.ethertype = htons(SOME_ETHERTYPE);
...
sendto(s, &ethHeader, sizeof(struct EthHeader), 0, (struct sockaddr*)&socketAddr, sizeof(socketAddr));
Пакет отправляется, но поле Tag Protocol ID все равно ставится ETH_P_ALL (0x0003). Если установить
socketAddr.sll_protocol = htons(ETH_P_8021Q);
то Tag Protocol ID выставляется нужный (0x8100) но поля vlan хидера все равно не заполняются моими значениями. Куда рыть? Как vlan заполнить правильно?

у меня предположение, что отправка тегированных пакетов в линуксе возможна только с vlan-интерфейса, созданного при помощи (ip link || vconfig)

nixtrian
()

используй sockaddr_in вместо sockaddr_ll. Структуру заполни нулём. И, да, есть libnet, которая сделает всё это за тебя, если размер не критичен.

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