]>
git.ipfire.org Git - people/ms/rstp.git/blob - packet.c
1 /*****************************************************************************
2 Copyright (c) 2006 EMC Corporation.
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the Free
6 Software Foundation; either version 2 of the License, or (at your option)
9 This program is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 You should have received a copy of the GNU General Public License along with
15 this program; if not, write to the Free Software Foundation, Inc., 59
16 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 The full GNU General Public License is included in this distribution in the
21 Authors: Srinivas Aji <Aji_Srinivas@emc.com>
22 Stephen Hemminger <shemminger@linux-foundation.org>
24 ******************************************************************************/
27 #include "epoll_loop.h"
28 #include "netif_utils.h"
29 #include "bridge_ctl.h"
37 #include <sys/socket.h>
38 #include <sys/ioctl.h>
40 #include <netinet/in.h>
43 #include <linux/if_ether.h>
44 #include <linux/if_packet.h>
45 #include <linux/filter.h>
52 * To send/receive Spanning Tree packets we use PF_PACKET because
53 * it allows the filtering we want but gives raw data
55 void packet_send(struct epoll_event_handler
*h
, unsigned char *data
, int len
)
59 if (fcntl(h
->fd
, F_SETFL
, 0) < 0)
60 ERROR("Error unsetting O_NONBLOCK: %m");
62 l
= send(h
->fd
, data
, len
, 0);
64 ERROR("send failed: %m");
66 ERROR("short write in sendto: %d instead of %d", l
, len
);
68 if (fcntl(h
->fd
, F_SETFL
, O_NONBLOCK
) < 0)
69 ERROR("Error setting O_NONBLOCK: %m");
72 void packet_rcv_handler(uint32_t events
, struct epoll_event_handler
*h
)
75 unsigned char buf
[2048];
77 cc
= recv(h
->fd
, &buf
, sizeof(buf
), 0);
79 ERROR("read failed: %m");
84 printf("Src %02x:%02x:%02x:%02x:%02x:%02x\n",
85 buf
[0], buf
[1], buf
[2], buf
[3], buf
[4], buf
[5]);
88 for (i
= 0; i
< cc
; i
+= 16) {
89 for (j
= 0; j
< 16 && i
+ j
< cc
; j
++)
90 printf(" %02x", buf
[i
+ j
]);
97 bridge_bpdu_rcv(h
->arg
, buf
, cc
);
100 /* Berkeley Packet filter code to filter out spanning tree packets.
103 static struct sock_filter stp_filter
[] = {
104 { 0x28, 0, 0, 0x0000000c },
105 { 0x25, 3, 0, 0x000005dc },
106 { 0x30, 0, 0, 0x0000000e },
107 { 0x15, 0, 1, 0x00000042 },
108 { 0x6, 0, 0, 0x00000060 },
109 { 0x6, 0, 0, 0x00000000 },
113 * Open up a raw packet socket to catch all 802.2 packets on a device
114 * and install a packet filter to only see STP (SAP 42)
116 int packet_sock_create(struct epoll_event_handler
*h
, int if_index
,
120 struct sockaddr_ll sll
= {
121 .sll_family
= AF_PACKET
,
122 .sll_ifindex
= if_index
,
124 struct sock_fprog prog
= {
125 .len
= sizeof(stp_filter
) / sizeof(stp_filter
[0]),
126 .filter
= stp_filter
,
129 s
= socket(PF_PACKET
, SOCK_PACKET
, htons(ETH_P_802_2
));
131 ERROR("socket failed: %m");
135 if (bind(s
, (struct sockaddr
*) &sll
, sizeof(sll
)) < 0)
136 ERROR("bind failed: %m");
138 else if (setsockopt(s
, SOL_SOCKET
, SO_ATTACH_FILTER
, &prog
, sizeof(prog
)) < 0)
139 ERROR("setsockopt packet filter failed: %m");
141 else if (fcntl(s
, F_SETFL
, O_NONBLOCK
) < 0)
142 ERROR("fcntl set nonblock failed: %m");
147 h
->handler
= packet_rcv_handler
;
149 if (add_epoll(h
) == 0)
157 void packet_sock_delete(struct epoll_event_handler
*h
)