I want to use the new PF_PACKET and SOCK_RAW options to create
a socket that I can send raw ethernet frames on. SOCK_PACKET
was working ok for me, but it's deprecated, evidently, and
it wasn't working on eth8, so I figured it was time to upgrade...
Also, using SIOCGIFINDEX, looking for eth1, gives me '3', when the
only interfaces shown by ifconfig -a are eth0, eth1, and lo (in that order).
Is that correct?
Here is the code that tries to create the socket:
This method seems to work...
int createPacketSocket(const char* dev_name, int ether_type, int dev_idx) {
int s = socket(PF_PACKET, SOCK_RAW, htons(ether_type));
int r; //retval
if (s < 0) {
cerr << "ERROR: socket: " << strerror(errno) << endl;
return s;
}
struct sockaddr_ll myaddr;
// From the man 7 packet man page.
memset(&myaddr, '\0', sizeof(myaddr));
myaddr.sll_family = AF_PACKET;
myaddr.sll_protocol = htons(ether_type);
myaddr.sll_ifindex = dev_idx;
//strcpy(myaddr.sa_data, dev_name);
r = bind(s, (struct sockaddr*)(&myaddr), sizeof(myaddr));
if (r < 0) {
cerr << "ERROR: bind: " << strerror(errno) << endl;
return r;
}
nonblock(s);
return s;
}
sendto gives this error every time: sendto: Invalid argument
To send I use this:
int foo::sendPktTo(int dev_socket, const char* dev, const char* msg,
int msg_len) {
int r = 0;
struct sockaddr from;
memset(&from, 0, sizeof(from));
from.sa_family = AF_INET;
strcpy(from.sa_data, dev);
r = sendto(dev_socket, msg, msg_len, 0, &from, fromlen);
if (r < 0) {
VLOG << "ERROR: foo::sendto: " << strerror(errno) << endl;
}
return r;
}//sendTo
Any help will be greatly appreciated...
Thanks,
Ben
--
Ben Greear (gre...@candelatech.com) http://www.candelatech.com
Author of ScryMUD: scry.wanfear.com 4444 (Released under GPL)
http://scry.wanfear.com http://scry.wanfear.com/~greear
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to majo...@vger.rutgers.edu
Although it is deprecated that would be a bug.
>
> Also, using SIOCGIFINDEX, looking for eth1, gives me '3', when the
> only interfaces shown by ifconfig -a are eth0, eth1, and lo (in that order).
> Is that correct?
Yes, interface indexes count all interfaces. See netdevice(7) for details.
They have nothing to do with the name.
> sendto gives this error every time: sendto: Invalid argument
> To send I use this:
> int foo::sendPktTo(int dev_socket, const char* dev, const char* msg,
> int msg_len) {
> int r = 0;
>
> struct sockaddr from;
> memset(&from, 0, sizeof(from));
> from.sa_family = AF_INET;
SOCK_PACKET obviously does not like AF_INET addresses and tells you that.
Try it with AF_PACKET
> strcpy(from.sa_data, dev);
>
> r = sendto(dev_socket, msg, msg_len, 0, &from, fromlen);
> if (r < 0) {
> VLOG << "ERROR: foo::sendto: " << strerror(errno) << endl;
> }
-Andi
If I have to go back to using the SOCK_PACKET stuff I'll try to
debug this and let you know what I find...
>
> >
> > Also, using SIOCGIFINDEX, looking for eth1, gives me '3', when the
> > only interfaces shown by ifconfig -a are eth0, eth1, and lo (in that order).
> > Is that correct?
>
> Yes, interface indexes count all interfaces. See netdevice(7) for details.
> They have nothing to do with the name.
Out of curiosity, if I manage to remove interface 4 at run-time,
and have bound to index 5 earlier, will I now be bound to the
wrong interface?
> > sendto gives this error every time: sendto: Invalid argument
> > To send I use this:
> > int foo::sendPktTo(int dev_socket, const char* dev, const char* msg,
> > int msg_len) {
> > int r = 0;
> >
> > struct sockaddr from;
> > memset(&from, 0, sizeof(from));
> > from.sa_family = AF_INET;
>
> SOCK_PACKET obviously does not like AF_INET addresses and tells you that.
> Try it with AF_PACKET
Same (wrong) result, unfortunately. The bind system call did not return
< 0, but could I have screwed it up enough that the sendto cannot work?
I've tracked the file descriptor through the code, and it's the same one
I bound earlier...
I'll swap my ethernet interfaces to see if putting it on eth0 instead of
eth8 will make any difference...
Thanks,
Ben
--
Ben Greear (gre...@candelatech.com) http://www.candelatech.com
Author of ScryMUD: scry.wanfear.com 4444 (Released under GPL)
http://scry.wanfear.com http://scry.wanfear.com/~greear
No. They work like pids.
> > > int foo::sendPktTo(int dev_socket, const char* dev, const char* msg,
> > > int msg_len) {
> > > int r = 0;
> > >
> > > struct sockaddr from;
> > > memset(&from, 0, sizeof(from));
> > > from.sa_family = AF_INET;
> >
> > SOCK_PACKET obviously does not like AF_INET addresses and tells you that.
> > Try it with AF_PACKET
>
> Same (wrong) result, unfortunately. The bind system call did not return
> < 0, but could I have screwed it up enough that the sendto cannot work?
[relooking at your original message]
First you pass the wrong address to PF_PACKET sendto() -- it gets a
sockaddr_ll, not a old style spkt address.
It is not clear from your snippet where fromlen comes from, but it is
probably not correctly initialized (it should be sizeof(struct sockaddr_ll)
Also sendto really gets a ``to'' not a ``from'', maybe you should fix
the confusing naming.
-Andi
> First you pass the wrong address to PF_PACKET sendto() -- it gets a
> sockaddr_ll, not a old style spkt address.
> It is not clear from your snippet where fromlen comes from, but it is
> probably not correctly initialized (it should be sizeof(struct sockaddr_ll)
> Also sendto really gets a ``to'' not a ``from'', maybe you should fix
> the confusing naming.
I looked at af_packet.c and figured out that sockaddr_ll was what was needed
(thanks for the well commented code :))
Also, it looks like after I bind, I can pass NULL in to sendto for
the 'to' address.
Right now, it looks like the code is putting it on the right interface
(according to debug I put in the kernel), but I'm still not seeing it on
the wire... I'll keep digging down...
One thing that bothers me a little bit. I have 2 4-port NICs and a
single... The single is the one I'm trying to send messages over.
No matter which slot I put it in (there are only 3 PCI slots in the MB),
that interface shows up as eth8. Is that normal? I thought they probed
based on PCI slots, so that changing the slot would change the ifname it
showed up on...
One final question.. If I create the socket like:
int s = socket(PF_PACKET, SOCK_RAW, htons(ether_type));
bind like this:
struct sockaddr_ll myaddr;
memset(&myaddr, '\0', sizeof(myaddr));
myaddr.sll_family = AF_PACKET;
myaddr.sll_protocol = htons(ether_type);
myaddr.sll_ifindex = dev_idx;
r = bind(s, (struct sockaddr*)(&myaddr), sizeof(myaddr));
and send like this:
r = sendto(dev_socket, msg, msg_len, 0, NULL, 0);
Should I expect to see this method in af_packet.cc called?
static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
struct scm_cookie *scm)
I was expecting to see packet_sendmsg_spkt, but it is using the one above...
Thanks,
Ben
--
Ben Greear (gre...@candelatech.com) http://www.candelatech.com
Author of ScryMUD: scry.wanfear.com 4444 (Released under GPL)
http://scry.wanfear.com http://scry.wanfear.com/~greear
It depends on the driver.
>
> One final question.. If I create the socket like:
> int s = socket(PF_PACKET, SOCK_RAW, htons(ether_type));
>
> bind like this:
> struct sockaddr_ll myaddr;
>
> memset(&myaddr, '\0', sizeof(myaddr));
> myaddr.sll_family = AF_PACKET;
> myaddr.sll_protocol = htons(ether_type);
> myaddr.sll_ifindex = dev_idx;
>
> r = bind(s, (struct sockaddr*)(&myaddr), sizeof(myaddr));
>
> and send like this:
> r = sendto(dev_socket, msg, msg_len, 0, NULL, 0);
>
> Should I expect to see this method in af_packet.cc called?
> static int packet_sendmsg(struct socket *sock, struct msghdr *msg, int len,
> struct scm_cookie *scm)
Yes.
>
> I was expecting to see packet_sendmsg_spkt, but it is using the one above...
This one is called for (PF_INET, SOCK_PACKET) sockets
-Andi