SF patch 101137 from Grant Edwards

Adds support for raw packets (AF_PACKET) under Linux.  I haven't
tested this code thoroughly; it compiles and the basic calls all work
without crashing.  Not sure what to actually do with raw sockets though.

Not sure what other platforms this might be useful for.
This commit is contained in:
Jeremy Hylton 2001-02-02 03:23:09 +00:00
parent 042f3137ba
commit 2230865043
1 changed files with 93 additions and 3 deletions

View File

@ -7,7 +7,8 @@ This module provides an interface to Berkeley socket IPC.
Limitations:
- only AF_INET and AF_UNIX address families are supported
- only AF_INET and AF_UNIX address families are supported in a
portable manner, though AF_PACKET is supported under Linux.
- no read/write operations (use send/recv or makefile instead)
- additional restrictions apply on Windows
@ -33,6 +34,13 @@ Module interface:
(including the dd.dd.dd.dd notation) and port is in host byte order
- where a hostname is returned, the dd.dd.dd.dd notation is used
- a UNIX domain socket address is a string specifying the pathname
- an AF_PACKET socket address is a tuple containing a string
specifying the ethernet interface and an integer specifying
the Ethernet protocol number to be received. For example:
("eth0",0x1234). Optional 3rd and 4th elements in the tuple
specify packet-type and ha-type -- these are ignored by
networking code, but accepted since they are returned by the
getsockname() method.
Socket methods:
@ -146,6 +154,12 @@ Socket methods:
#undef AF_UNIX
#endif
#if defined(linux) && defined(AF_PACKET)
#include <sys/ioctl.h>
#include <net/if.h>
#include <netpacket/packet.h>
#endif
#ifndef O_NDELAY
#define O_NDELAY O_NONBLOCK /* For QNX only? */
#endif
@ -347,6 +361,9 @@ typedef struct {
#ifdef AF_UNIX
struct sockaddr_un un;
#endif
#if defined(linux) && defined(AF_PACKET)
struct sockaddr_ll ll;
#endif
} sock_addr;
} PySocketSockObject;
@ -550,8 +567,31 @@ makesockaddr(struct sockaddr *addr, int addrlen)
struct sockaddr_un *a = (struct sockaddr_un *) addr;
return PyString_FromString(a->sun_path);
}
#endif /* AF_UNIX */
#endif
#if defined(linux) && defined(AF_PACKET)
case AF_PACKET:
{
struct sockaddr_ll *a = (struct sockaddr_ll *)addr;
char *ifname = "";
struct ifreq ifr;
int s;
/* need a socket on which we can do an ioctl to look
* up interface name from index, but only if index is
* non-zero.
*/
if (a->sll_ifindex
&& ((s = socket(AF_PACKET, SOCK_RAW, 0)) >= 0)) {
ifr.ifr_ifindex = a->sll_ifindex;
if (ioctl(s, SIOCGIFNAME, &ifr) == 0)
ifname = ifr.ifr_name;
close(s);
}
return Py_BuildValue("shbh", ifname, ntohs(a->sll_protocol),
a->sll_pkttype, a->sll_hatype);
}
#endif
/* More cases here... */
default:
@ -622,6 +662,36 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, struct sockaddr **addr_ret
return 1;
}
#if defined(linux) && defined(AF_PACKET)
case AF_PACKET:
{
struct sockaddr_ll* addr;
struct ifreq ifr;
char *interfaceName;
int protoNumber;
int hatype = 0;
int pkttype = 0;
if (!PyArg_ParseTuple(args, "si|ii", &interfaceName,
&protoNumber, &pkttype, &hatype))
return 0;
strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr))
return 0;
addr = &(s->sock_addr.ll);
addr->sll_family = AF_PACKET;
addr->sll_protocol = htons((short)protoNumber);
addr->sll_ifindex = ifr.ifr_ifindex;
addr->sll_pkttype = pkttype;
addr->sll_hatype = hatype;
*addr_ret = (struct sockaddr *) addr;
*len_ret = sizeof *addr;
return 1;
}
#endif
/* More cases here... */
default:
@ -655,6 +725,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
return 1;
}
#if defined(linux) && defined(AF_PACKET)
case AF_PACKET:
{
*len_ret = sizeof (struct sockaddr_ll);
return 1;
}
#endif
/* More cases here... */
default:
@ -894,7 +972,8 @@ static char bind_doc[] =
"bind(address)\n\
\n\
Bind the socket to a local address. For IP sockets, the address is a\n\
pair (host, port); the host must refer to the local host.";
pair (host, port); the host must refer to the local host. For raw packet\n\
sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])";
/* s.close() method.
@ -2441,6 +2520,17 @@ init_socket(void)
#ifdef AF_ROSE
insint(d, "AF_ROSE", AF_ROSE); /* Amateur Radio X.25 PLP */
#endif
#if defined(linux) && defined(AF_PACKET)
insint(d, "AF_PACKET", AF_PACKET);
insint(d, "PF_PACKET", PF_PACKET);
insint(d, "PACKET_HOST", PACKET_HOST);
insint(d, "PACKET_BROADCAST", PACKET_BROADCAST);
insint(d, "PACKET_MULTICAST", PACKET_MULTICAST);
insint(d, "PACKET_OTHERHOST", PACKET_OTHERHOST);
insint(d, "PACKET_OUTGOING", PACKET_OUTGOING);
insint(d, "PACKET_LOOPBACK", PACKET_LOOPBACK);
insint(d, "PACKET_FASTROUTE", PACKET_FASTROUTE);
#endif
/* Socket types */
insint(d, "SOCK_STREAM", SOCK_STREAM);