patch-2.0.31 linux/net/core/sock.c

Next file: linux/net/core/sysctl_net_core.c
Previous file: linux/net/core/net_alias.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.0.30/linux/net/core/sock.c linux/net/core/sock.c
@@ -71,6 +71,7 @@
  *		Alan Cox	: 	Generic socket allocation to make hooks
  *					easier (suggested by Craig Metz).
  *		Michael Pall	:	SO_ERROR returns positive errno again
+ *              Elliot Poger    :       Added support for SO_BINDTODEVICE.
  *
  * To Fix:
  *
@@ -128,6 +129,7 @@
 	int valbool;
 	int err;
 	struct linger ling;
+	struct ifreq req;
 
 	/*
 	 *	Options without arguments
@@ -232,7 +234,37 @@
 		case SO_BSDCOMPAT:
 			sk->bsdism = valbool;
 			return 0;
-			
+
+#ifdef CONFIG_NET	
+ 	        case SO_BINDTODEVICE:
+ 			/* Bind this socket to a particular device like "eth0",
+ 			 * as specified in an ifreq structure.  If the device 
+ 			 * is "", socket is NOT bound to a device. */
+ 			if (!valbool) {
+ 				sk->bound_device = NULL;
+ 			} else {
+ 				err=verify_area(VERIFY_READ,optval,sizeof(req));
+ 				if(err)
+ 					return err;
+ 				memcpy_fromfs(&req,optval,sizeof(req));
+
+				/* Remove any cached route for this socket. */
+				if (sk->ip_route_cache) {
+					ip_rt_put(sk->ip_route_cache);
+					sk->ip_route_cache=NULL;
+				}
+
+ 				if (*(req.ifr_name) == '\0') {
+ 					sk->bound_device = NULL;
+ 				} else {
+ 					sk->bound_device = dev_get(req.ifr_name);
+ 					if (sk->bound_device == NULL)
+ 						return -EINVAL;
+ 				}
+ 			}
+  			return 0;
+#endif
+
 		default:
 		  	return(-ENOPROTOOPT);
   	}
@@ -315,6 +347,28 @@
 			val = sk->bsdism;
 			break;
 
+#ifdef CONFIG_NET
+                case SO_BINDTODEVICE:
+		{
+			struct ifreq req;
+
+                        /* Return the bound device (if any) */
+                        err=verify_area(VERIFY_WRITE,optval,sizeof(req));
+                        if(err)
+                                return err;
+
+                        memset((char *) &req, 0, sizeof(req));
+
+                        if (sk->bound_device) {
+                            strncpy(req.ifr_name, sk->bound_device->name, sizeof(req.ifr_name));
+                            (*(struct sockaddr_in *) &req.ifr_addr).sin_family = sk->bound_device->family;
+                            (*(struct sockaddr_in *) &req.ifr_addr).sin_addr.s_addr = sk->bound_device->pa_addr;
+                        }
+                        memcpy_tofs(optval, &req, sizeof(req));
+                        return 0;
+		}
+#endif
+
 		default:
 			return(-ENOPROTOOPT);
 	}
@@ -462,9 +516,9 @@
 			return NULL;
 		}
 		
-		
+
 		mem=sk->wmem_alloc;
-		
+
 		if(!fallback)
 			skb = sock_wmalloc(sk, size, 0, sk->allocation);
 		else

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov