patch-1.3.38 linux/net/ipv4/packet.c
Next file: linux/net/ipv4/rarp.c
Previous file: linux/net/ipv4/ipmr.c
Back to the patch index
Back to the overall index
- Lines: 289
- Date:
Mon Nov 6 12:59:01 1995
- Orig file:
v1.3.37/linux/net/ipv4/packet.c
- Orig date:
Mon Oct 23 18:02:23 1995
diff -u --recursive --new-file v1.3.37/linux/net/ipv4/packet.c linux/net/ipv4/packet.c
@@ -198,37 +198,6 @@
return(len);
}
-static int packet_sendto(struct sock *sk, const unsigned char *from, int len,
- int noblock, unsigned flags, struct sockaddr_in *usin,
- int addr_len)
-{
- struct iovec iov;
- struct msghdr msg;
-
- iov.iov_base = (void *)from;
- iov.iov_len = len;
-
- msg.msg_name = (void *)usin;
- msg.msg_namelen = addr_len;
- msg.msg_accrights = NULL;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- return packet_sendmsg(sk, &msg, len, noblock, flags);
-}
-
-
-/*
- * A write to a SOCK_PACKET can't actually do anything useful and will
- * always fail but we include it for completeness and future expansion.
- */
-
-static int packet_write(struct sock *sk, const unsigned char *buff,
- int len, int noblock, unsigned flags)
-{
- return(packet_sendto(sk, buff, len, noblock, flags, NULL, 0));
-}
-
/*
* Close a SOCK_PACKET socket. This is fairly simple. We immediately go
* to 'closed' state and remove our protocol entry in the device list.
@@ -238,27 +207,45 @@
static void packet_close(struct sock *sk, int timeout)
{
+ /*
+ * Stop more data and kill the socket off.
+ */
+
sk->inuse = 1;
sk->state = TCP_CLOSE;
- dev_remove_pack((struct packet_type *)sk->pair);
- kfree_s((void *)sk->pair, sizeof(struct packet_type));
- sk->pair = NULL;
+
+ /*
+ * Unhook the notifier
+ */
+
+ unregister_netdevice_notifier(&sk->protinfo.af_packet.notifier);
+
+ if(sk->protinfo.af_packet.prot_hook)
+ {
+ /*
+ * Remove the protocol hook
+ */
+
+ dev_remove_pack((struct packet_type *)sk->protinfo.af_packet.prot_hook);
+
+ /*
+ * Dispose of litter carefully.
+ */
+
+ kfree_s((void *)sk->protinfo.af_packet.prot_hook, sizeof(struct packet_type));
+ sk->protinfo.af_packet.prot_hook = NULL;
+ }
+
release_sock(sk);
}
/*
- * Create a packet of type SOCK_PACKET. We do one slightly irregular
- * thing here that wants tidying up. We borrow the 'pair' pointer in
- * the socket object so we can find the packet_type entry in the
- * device list. The reverse is easy as we use the data field of the
- * packet type to point to our socket.
+ * Attach a packer hook to a device.
*/
-static int packet_init(struct sock *sk)
+int packet_attach(struct sock *sk)
{
- struct packet_type *p;
-
- p = (struct packet_type *) kmalloc(sizeof(*p), GFP_KERNEL);
+ struct packet_type *p = (struct packet_type *) kmalloc(sizeof(*p), GFP_KERNEL);
if (p == NULL)
return(-ENOMEM);
@@ -272,7 +259,113 @@
* We need to remember this somewhere.
*/
- sk->pair = (struct sock *)p;
+ sk->protinfo.af_packet.prot_hook = p;
+ return 0;
+}
+
+/*
+ * Bind a packet socket to a device
+ */
+
+static int packet_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+{
+ char dev[15];
+
+ /*
+ * Check legality
+ */
+
+ if(addr_len!=sizeof(struct sockaddr))
+ return -EINVAL;
+ strncpy(dev,uaddr->sa_data,14);
+ dev[14]=0;
+
+ /*
+ * Lock the device chain while we sanity check
+ * the bind request.
+ */
+
+ dev_lock_list();
+ if((sk->protinfo.af_packet.bound_dev=dev_get(dev))==NULL)
+ {
+ dev_unlock_list();
+ return -ENODEV;
+ }
+ if(!(sk->protinfo.af_packet.bound_dev->flags&IFF_UP))
+ {
+ dev_unlock_list();
+ return -ENETDOWN;
+ }
+
+ /*
+ * Perform the request.
+ */
+
+ memcpy(sk->protinfo.af_packet.device_name,dev,15);
+ if(sk->protinfo.af_packet.prot_hook)
+ dev_remove_pack(sk->protinfo.af_packet.prot_hook);
+ else
+ {
+ int err=packet_attach(sk);
+ if(err)
+ {
+ dev_unlock_list();
+ return err;
+ }
+ }
+ sk->protinfo.af_packet.prot_hook->dev=sk->protinfo.af_packet.bound_dev;
+ dev_add_pack(sk->protinfo.af_packet.prot_hook);
+ /*
+ * Now the notifier is set up right this lot is safe.
+ */
+ dev_unlock_list();
+ return 0;
+}
+
+/*
+ * This hook is called when a device goes up or down so that
+ * SOCK_PACKET sockets can come unbound properly.
+ */
+
+static int packet_unbind(struct notifier_block *this, unsigned long msg, void *data)
+{
+ struct inet_packet_opt *ipo=(struct inet_packet_opt *)this;
+ if(msg==NETDEV_DOWN && data==ipo->bound_dev)
+ {
+ /*
+ * Our device has gone down.
+ */
+ ipo->bound_dev=NULL;
+ dev_remove_pack(ipo->prot_hook);
+ kfree(ipo->prot_hook);
+ ipo->prot_hook=NULL;
+ }
+ return NOTIFY_DONE;
+}
+
+
+/*
+ * Create a packet of type SOCK_PACKET.
+ */
+
+static int packet_init(struct sock *sk)
+{
+ /*
+ * Attach a protocol block
+ */
+
+ int err=packet_attach(sk);
+ if(err)
+ return err;
+
+ /*
+ * Set up the per socket notifier.
+ */
+
+ sk->protinfo.af_packet.notifier.notifier_call=packet_unbind;
+ sk->protinfo.af_packet.notifier.priority=0;
+
+ register_netdevice_notifier(&sk->protinfo.af_packet.notifier);
return(0);
}
@@ -295,6 +388,13 @@
return(0);
/*
+ * If there is no protocol hook then the device is down.
+ */
+
+ if(sk->protinfo.af_packet.prot_hook==NULL)
+ return -ENETDOWN;
+
+ /*
* If the address length field is there to be filled in, we fill
* it in now.
*/
@@ -354,40 +454,6 @@
return(copied);
}
-static int packet_recvfrom(struct sock *sk, unsigned char *ubuf, int size, int noblock, unsigned flags,
- struct sockaddr_in *sa, int *addr_len)
-{
- struct iovec iov;
- struct msghdr msg;
-
- iov.iov_base = ubuf;
- iov.iov_len = size;
-
- msg.msg_name = (void *)sa;
- msg.msg_namelen = 0;
- if (addr_len)
- msg.msg_namelen = *addr_len;
- msg.msg_accrights = NULL;
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
-
- return packet_recvmsg(sk, &msg, size, noblock, flags, addr_len);
-}
-
-
-
-/*
- * A packet read can succeed and is just the same as a recvfrom but without the
- * addresses being recorded.
- */
-
-int packet_read(struct sock *sk, unsigned char *buff,
- int len, int noblock, unsigned flags)
-{
- return(packet_recvfrom(sk, buff, len, noblock, flags, NULL, NULL));
-}
-
-
/*
* This structure declares to the lower layer socket subsystem currently
* incorrectly embedded in the IP code how to behave. This interface needs
@@ -397,10 +463,6 @@
struct proto packet_prot =
{
packet_close,
- packet_read,
- packet_write,
- packet_sendto,
- packet_recvfrom,
ip_build_header, /* Not actually used */
NULL,
NULL,
@@ -417,8 +479,11 @@
NULL,
packet_sendmsg, /* Sendmsg */
packet_recvmsg, /* Recvmsg */
+ packet_bind, /* Bind */
128,
0,
"PACKET",
0, 0
};
+
+
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this