summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJeremy Hylton <jeremy@alum.mit.edu>2001-02-02 03:23:09 (GMT)
committerJeremy Hylton <jeremy@alum.mit.edu>2001-02-02 03:23:09 (GMT)
commit2230865043111f2926b8ff5d06608cec5058e74e (patch)
tree4aa5f0a309e32a718240266deb822176683b03f1
parent042f3137bafe310321caeb064a7fc7db1cea05bd (diff)
downloadcpython-2230865043111f2926b8ff5d06608cec5058e74e.zip
cpython-2230865043111f2926b8ff5d06608cec5058e74e.tar.gz
cpython-2230865043111f2926b8ff5d06608cec5058e74e.tar.bz2
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.
-rw-r--r--Modules/socketmodule.c96
1 files changed, 93 insertions, 3 deletions
diff --git a/Modules/socketmodule.c b/Modules/socketmodule.c
index 9b6300c..ca123ad 100644
--- a/Modules/socketmodule.c
+++ b/Modules/socketmodule.c
@@ -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);