Hi: Here's a hack I just made up to make DHCP skip tagged packets. In order to do so I've switched from the long-obsolete SOCK_PACKET interface to AF_PACKET+SOCK_RAW.
Obviously you'll need to clean this up. Cheers, -- Email: Herbert Xu <herb...@gondor.apana.org.au> Home Page: http://gondor.apana.org.au/~herbert/ PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt -- diff --git a/common/lpf.c b/common/lpf.c index e5dd1e2..36a14ee 100644 --- a/common/lpf.c +++ b/common/lpf.c @@ -35,6 +35,7 @@ #include <asm/types.h> #include <linux/filter.h> #include <linux/if_ether.h> +#include <linux/if_packet.h> #include <netinet/in_systm.h> #include "includes/netinet/ip.h" #include "includes/netinet/udp.h" @@ -65,11 +66,13 @@ void if_reinitialize_receive (info) int if_register_lpf (info) struct interface_info *info; { + int val; int sock; - struct sockaddr sa; + struct ifreq tmp; + struct sockaddr_ll sa; /* Make an LPF socket. */ - if ((sock = socket(PF_PACKET, SOCK_PACKET, + if ((sock = socket(PF_PACKET, SOCK_RAW, htons((short)ETH_P_ALL))) < 0) { if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || @@ -84,11 +87,20 @@ int if_register_lpf (info) log_fatal ("Open a socket for LPF: %m"); } + val = 1; + setsockopt(sock, SOL_PACKET, PACKET_AUXDATA, &val, sizeof(val)); + + memcpy(&tmp, info->ifp, sizeof(tmp)); + if (ioctl(sock, SIOCGIFINDEX, &tmp) < 0) { + log_fatal("Error getting interface index for \"%s\": %m", + tmp.ifr_name); + } + /* Bind to the interface name */ memset (&sa, 0, sizeof sa); - sa.sa_family = AF_PACKET; - strncpy (sa.sa_data, (const char *)info -> ifp, sizeof sa.sa_data); - if (bind (sock, &sa, sizeof sa)) { + sa.sll_family = AF_PACKET; + sa.sll_ifindex = tmp.ifr_ifindex; + if (bind (sock, (struct sockaddr *)&sa, sizeof sa)) { if (errno == ENOPROTOOPT || errno == EPROTONOSUPPORT || errno == ESOCKTNOSUPPORT || errno == EPFNOSUPPORT || errno == EAFNOSUPPORT || errno == EINVAL) { @@ -294,7 +306,6 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto) double hh [16]; double ih [1536 / sizeof (double)]; unsigned char *buf = (unsigned char *)ih; - struct sockaddr sa; int result; int fudge; @@ -312,21 +323,25 @@ ssize_t send_packet (interface, packet, raw, len, from, to, hto) (unsigned char *)raw, len); memcpy (buf + ibufp, raw, len); - /* For some reason, SOCK_PACKET sockets can't be connected, - so we have to do a sentdo every time. */ - memset (&sa, 0, sizeof sa); - sa.sa_family = AF_PACKET; - strncpy (sa.sa_data, - (const char *)interface -> ifp, sizeof sa.sa_data); - - result = sendto (interface -> wfdesc, - buf + fudge, ibufp + len - fudge, 0, &sa, sizeof sa); + result = send (interface -> wfdesc, + buf + fudge, ibufp + len - fudge, 0); if (result < 0) log_error ("send_packet: %m"); return result; } #endif /* USE_LPF_SEND */ +struct tpacket_auxdata_new +{ + __u32 tp_status; + __u32 tp_len; + __u32 tp_snaplen; + __u16 tp_mac; + __u16 tp_net; + __u16 tp_vlan_tci; + __u16 tp_padding; +}; + #ifdef USE_LPF_RECEIVE ssize_t receive_packet (interface, buf, len, from, hfrom) struct interface_info *interface; @@ -340,11 +355,38 @@ ssize_t receive_packet (interface, buf, len, from, hfrom) unsigned char ibuf [1536]; unsigned bufix = 0; unsigned paylen; - - length = read (interface -> rfdesc, ibuf, sizeof ibuf); + struct cmsghdr *cmsg; + union { + struct cmsghdr cmsg; + char buf[CMSG_SPACE(sizeof(struct tpacket_auxdata_new))]; + } cmsg_buf; + struct msghdr msg = {}; + struct iovec iov; + + iov.iov_base = ibuf; + iov.iov_len = sizeof ibuf; + msg.msg_iov = &iov; + msg.msg_iovlen = 1; + msg.msg_control = &cmsg_buf; + msg.msg_controllen = sizeof cmsg_buf; + + length = recvmsg (interface -> rfdesc, &msg, 0); if (length <= 0) return length; + for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) { + struct tpacket_auxdata_new *aux; + + if (cmsg->cmsg_len < CMSG_LEN(sizeof(struct tpacket_auxdata_new)) || + cmsg->cmsg_level != SOL_PACKET || + cmsg->cmsg_type != PACKET_AUXDATA) + continue; + + aux = (struct tpacket_auxdata_new *)CMSG_DATA(cmsg); + if (aux->tp_vlan_tci != 0) + return 0; + } + bufix = 0; /* Decode the physical header... */ offset = decode_hw_header (interface, ibuf, bufix, hfrom); -- To UNSUBSCRIBE, email to debian-bugs-dist-requ...@lists.debian.org with a subject of "unsubscribe". Trouble? Contact listmas...@lists.debian.org