[Python-checkins] CVS: python/dist/src/Modules socketmodule.c,1.133,1.134

Jeremy Hylton jhylton@users.sourceforge.net
Thu, 01 Feb 2001 19:23:11 -0800


Update of /cvsroot/python/python/dist/src/Modules
In directory usw-pr-cvs1:/tmp/cvs-serv30093/Modules

Modified Files:
	socketmodule.c 
Log Message:
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.



Index: socketmodule.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Modules/socketmodule.c,v
retrieving revision 1.133
retrieving revision 1.134
diff -C2 -r1.133 -r1.134
*** socketmodule.c	2001/02/01 23:35:20	1.133
--- socketmodule.c	2001/02/02 03:23:09	1.134
***************
*** 8,12 ****
  Limitations:
  
! - only AF_INET and AF_UNIX address families are supported
  - no read/write operations (use send/recv or makefile instead)
  - additional restrictions apply on Windows
--- 8,13 ----
  Limitations:
  
! - 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
***************
*** 34,37 ****
--- 35,45 ----
  - 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:
***************
*** 147,150 ****
--- 155,164 ----
  #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? */
***************
*** 348,351 ****
--- 362,368 ----
  		struct sockaddr_un un;
  #endif
+ #if defined(linux) && defined(AF_PACKET)
+ 		struct sockaddr_ll ll;
+ #endif		
  	} sock_addr;
  } PySocketSockObject;
***************
*** 551,556 ****
  		return PyString_FromString(a->sun_path);
  	}
! #endif /* AF_UNIX */
  
  	/* More cases here... */
  
--- 568,596 ----
  		return PyString_FromString(a->sun_path);
  	}
! #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... */
  
***************
*** 623,626 ****
--- 663,696 ----
  	}
  
+ #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... */
  
***************
*** 656,659 ****
--- 726,737 ----
  	}
  
+ #if defined(linux) && defined(AF_PACKET)
+ 	case AF_PACKET:
+ 	{
+ 		*len_ret = sizeof (struct sockaddr_ll);
+ 		return 1;
+ 	}
+ #endif
+ 		
  	/* More cases here... */
  
***************
*** 895,899 ****
  \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.";
  
  
--- 973,978 ----
  \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. For raw packet\n\
! sockets the address is a tuple (ifname, proto [,pkttype [,hatype]])";
  
  
***************
*** 2442,2445 ****
--- 2521,2535 ----
  	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 */