Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2230865

Browse files
committed
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.
1 parent 042f313 commit 2230865

1 file changed

Lines changed: 93 additions & 3 deletions

File tree

Modules/socketmodule.c

Lines changed: 93 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ This module provides an interface to Berkeley socket IPC.
77
88
Limitations:
99
10-
- only AF_INET and AF_UNIX address families are supported
10+
- only AF_INET and AF_UNIX address families are supported in a
11+
portable manner, though AF_PACKET is supported under Linux.
1112
- no read/write operations (use send/recv or makefile instead)
1213
- additional restrictions apply on Windows
1314
@@ -33,6 +34,13 @@ Module interface:
3334
(including the dd.dd.dd.dd notation) and port is in host byte order
3435
- where a hostname is returned, the dd.dd.dd.dd notation is used
3536
- a UNIX domain socket address is a string specifying the pathname
37+
- an AF_PACKET socket address is a tuple containing a string
38+
specifying the ethernet interface and an integer specifying
39+
the Ethernet protocol number to be received. For example:
40+
("eth0",0x1234). Optional 3rd and 4th elements in the tuple
41+
specify packet-type and ha-type -- these are ignored by
42+
networking code, but accepted since they are returned by the
43+
getsockname() method.
3644
3745
Socket methods:
3846
@@ -146,6 +154,12 @@ Socket methods:
146154
#undef AF_UNIX
147155
#endif
148156

157+
#if defined(linux) && defined(AF_PACKET)
158+
#include <sys/ioctl.h>
159+
#include <net/if.h>
160+
#include <netpacket/packet.h>
161+
#endif
162+
149163
#ifndef O_NDELAY
150164
#define O_NDELAY O_NONBLOCK /* For QNX only? */
151165
#endif
@@ -347,6 +361,9 @@ typedef struct {
347361
#ifdef AF_UNIX
348362
struct sockaddr_un un;
349363
#endif
364+
#if defined(linux) && defined(AF_PACKET)
365+
struct sockaddr_ll ll;
366+
#endif
350367
} sock_addr;
351368
} PySocketSockObject;
352369

@@ -550,8 +567,31 @@ makesockaddr(struct sockaddr *addr, int addrlen)
550567
struct sockaddr_un *a = (struct sockaddr_un *) addr;
551568
return PyString_FromString(a->sun_path);
552569
}
553-
#endif /* AF_UNIX */
570+
#endif
554571

572+
#if defined(linux) && defined(AF_PACKET)
573+
case AF_PACKET:
574+
{
575+
struct sockaddr_ll *a = (struct sockaddr_ll *)addr;
576+
char *ifname = "";
577+
struct ifreq ifr;
578+
int s;
579+
/* need a socket on which we can do an ioctl to look
580+
* up interface name from index, but only if index is
581+
* non-zero.
582+
*/
583+
if (a->sll_ifindex
584+
&& ((s = socket(AF_PACKET, SOCK_RAW, 0)) >= 0)) {
585+
ifr.ifr_ifindex = a->sll_ifindex;
586+
if (ioctl(s, SIOCGIFNAME, &ifr) == 0)
587+
ifname = ifr.ifr_name;
588+
close(s);
589+
}
590+
return Py_BuildValue("shbh", ifname, ntohs(a->sll_protocol),
591+
a->sll_pkttype, a->sll_hatype);
592+
}
593+
#endif
594+
555595
/* More cases here... */
556596

557597
default:
@@ -622,6 +662,36 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args, struct sockaddr **addr_ret
622662
return 1;
623663
}
624664

665+
#if defined(linux) && defined(AF_PACKET)
666+
case AF_PACKET:
667+
{
668+
struct sockaddr_ll* addr;
669+
struct ifreq ifr;
670+
char *interfaceName;
671+
int protoNumber;
672+
int hatype = 0;
673+
int pkttype = 0;
674+
675+
if (!PyArg_ParseTuple(args, "si|ii", &interfaceName,
676+
&protoNumber, &pkttype, &hatype))
677+
return 0;
678+
strncpy(ifr.ifr_name, interfaceName, sizeof(ifr.ifr_name));
679+
ifr.ifr_name[(sizeof(ifr.ifr_name))-1] = '\0';
680+
if (ioctl(s->sock_fd, SIOCGIFINDEX, &ifr))
681+
return 0;
682+
addr = &(s->sock_addr.ll);
683+
addr->sll_family = AF_PACKET;
684+
addr->sll_protocol = htons((short)protoNumber);
685+
addr->sll_ifindex = ifr.ifr_ifindex;
686+
addr->sll_pkttype = pkttype;
687+
addr->sll_hatype = hatype;
688+
*addr_ret = (struct sockaddr *) addr;
689+
*len_ret = sizeof *addr;
690+
return 1;
691+
}
692+
#endif
693+
694+
625695
/* More cases here... */
626696

627697
default:
@@ -655,6 +725,14 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)
655725
return 1;
656726
}
657727

728+
#if defined(linux) && defined(AF_PACKET)
729+
case AF_PACKET:
730+
{
731+
*len_ret = sizeof (struct sockaddr_ll);
732+
return 1;
733+
}
734+
#endif
735+
658736
/* More cases here... */
659737

660738
default:
@@ -894,7 +972,8 @@ static char bind_doc[] =
894972
"bind(address)\n\
895973
\n\
896974
Bind the socket to a local address. For IP sockets, the address is a\n\
897-
pair (host, port); the host must refer to the local host.";
975+
pair (host, port); the host must refer to the local host. For raw packet\n\
976+
sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])";
898977

899978

900979
/* s.close() method.
@@ -2441,6 +2520,17 @@ init_socket(void)
24412520
#ifdef AF_ROSE
24422521
insint(d, "AF_ROSE", AF_ROSE); /* Amateur Radio X.25 PLP */
24432522
#endif
2523+
#if defined(linux) && defined(AF_PACKET)
2524+
insint(d, "AF_PACKET", AF_PACKET);
2525+
insint(d, "PF_PACKET", PF_PACKET);
2526+
insint(d, "PACKET_HOST", PACKET_HOST);
2527+
insint(d, "PACKET_BROADCAST", PACKET_BROADCAST);
2528+
insint(d, "PACKET_MULTICAST", PACKET_MULTICAST);
2529+
insint(d, "PACKET_OTHERHOST", PACKET_OTHERHOST);
2530+
insint(d, "PACKET_OUTGOING", PACKET_OUTGOING);
2531+
insint(d, "PACKET_LOOPBACK", PACKET_LOOPBACK);
2532+
insint(d, "PACKET_FASTROUTE", PACKET_FASTROUTE);
2533+
#endif
24442534

24452535
/* Socket types */
24462536
insint(d, "SOCK_STREAM", SOCK_STREAM);

0 commit comments

Comments
 (0)