patch-2.1.28 linux/net/ipv4/raw.c
Next file: linux/net/ipv4/tcp.c
Previous file: linux/net/ipv4/proc.c
Back to the patch index
Back to the overall index
- Lines: 196
- Date:
Mon Mar 3 09:37:44 1997
- Orig file:
v2.1.27/linux/net/ipv4/raw.c
- Orig date:
Sat Jan 25 13:46:14 1997
diff -u --recursive --new-file v2.1.27/linux/net/ipv4/raw.c linux/net/ipv4/raw.c
@@ -30,6 +30,7 @@
* Alan Cox : Beginnings of mrouted support.
* Alan Cox : Added IP_HDRINCL option.
* Alan Cox : Skip broadcast check if BSDism set.
+ * David S. Miller : New socket lookup architecture.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
@@ -58,12 +59,89 @@
#include <net/sock.h>
#include <net/icmp.h>
#include <net/udp.h>
+#include <net/raw.h>
#include <net/checksum.h>
#ifdef CONFIG_IP_MROUTE
struct sock *mroute_socket=NULL;
#endif
+struct sock *raw_v4_htable[RAWV4_HTABLE_SIZE];
+
+static void raw_v4_hash(struct sock *sk)
+{
+ struct sock **skp;
+ int num = sk->num;
+
+ num &= (RAWV4_HTABLE_SIZE - 1);
+ skp = &raw_v4_htable[num];
+ SOCKHASH_LOCK();
+ sk->next = *skp;
+ *skp = sk;
+ sk->hashent = num;
+ SOCKHASH_UNLOCK();
+}
+
+static void raw_v4_unhash(struct sock *sk)
+{
+ struct sock **skp;
+ int num = sk->num;
+
+ num &= (RAWV4_HTABLE_SIZE - 1);
+ skp = &raw_v4_htable[num];
+
+ SOCKHASH_LOCK();
+ while(*skp != NULL) {
+ if(*skp == sk) {
+ *skp = sk->next;
+ break;
+ }
+ skp = &((*skp)->next);
+ }
+ SOCKHASH_UNLOCK();
+}
+
+static void raw_v4_rehash(struct sock *sk)
+{
+ struct sock **skp;
+ int num = sk->num;
+ int oldnum = sk->hashent;
+
+ num &= (RAWV4_HTABLE_SIZE - 1);
+ skp = &raw_v4_htable[oldnum];
+
+ SOCKHASH_LOCK();
+ while(*skp != NULL) {
+ if(*skp == sk) {
+ *skp = sk->next;
+ break;
+ }
+ skp = &((*skp)->next);
+ }
+ sk->next = raw_v4_htable[num];
+ raw_v4_htable[num] = sk;
+ sk->hashent = num;
+ SOCKHASH_UNLOCK();
+}
+
+/* Grumble... icmp and ip_input want to get at this... */
+struct sock *raw_v4_lookup(struct sock *sk, unsigned short num,
+ unsigned long raddr, unsigned long laddr)
+{
+ struct sock *s = sk;
+
+ SOCKHASH_LOCK();
+ for(s = sk; s; s = s->next) {
+ if((s->num == num) &&
+ !(s->dead && (s->state == TCP_CLOSE)) &&
+ !(s->daddr && s->daddr != raddr) &&
+ !(s->rcv_saddr && s->rcv_saddr != laddr))
+ break; /* gotcha */
+ }
+ SOCKHASH_UNLOCK();
+ return s;
+}
+
/*
* Raw_err does not currently get called by the icmp module - FIXME:
*/
@@ -339,12 +417,30 @@
destroy_sock(sk);
}
-
-static int raw_init(struct sock *sk)
+/* This gets rid of all the nasties in af_inet. -DaveM */
+static int raw_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
{
- return(0);
-}
+ struct sockaddr_in *addr = (struct sockaddr_in *) uaddr;
+ int chk_addr_ret;
+ if((sk->state != TCP_CLOSE) || (addr_len < sizeof(struct sockaddr_in)))
+ return -EINVAL;
+ chk_addr_ret = __ip_chk_addr(addr->sin_addr.s_addr);
+ if(addr->sin_addr.s_addr != 0 && chk_addr_ret != IS_MYADDR &&
+ chk_addr_ret != IS_MULTICAST && chk_addr_ret != IS_BROADCAST) {
+#ifdef CONFIG_IP_TRANSPARENT_PROXY
+ /* Superuser may bind to any address to allow transparent proxying. */
+ if(!suser())
+#endif
+ return -EADDRNOTAVAIL;
+ }
+ sk->rcv_saddr = sk->saddr = addr->sin_addr.s_addr;
+ if(chk_addr_ret == IS_MULTICAST || chk_addr_ret == IS_BROADCAST)
+ sk->saddr = 0; /* Use device */
+ dst_release(sk->dst_cache);
+ sk->dst_cache = NULL;
+ return 0;
+}
/*
* This should be easy, if there is something there
@@ -406,30 +502,37 @@
struct proto raw_prot = {
- raw_close,
- udp_connect,
- NULL,
- NULL,
- NULL,
- NULL,
- datagram_poll,
-#ifdef CONFIG_IP_MROUTE
- ipmr_ioctl,
+ (struct sock *)&raw_prot, /* sklist_next */
+ (struct sock *)&raw_prot, /* sklist_prev */
+ raw_close, /* close */
+ udp_connect, /* connect */
+ NULL, /* accept */
+ NULL, /* retransmit */
+ NULL, /* write_wakeup */
+ NULL, /* read_wakeup */
+ datagram_poll, /* poll */
+#ifdef CONFIG_IP_MROUTE
+ ipmr_ioctl, /* ioctl */
#else
- NULL,
-#endif
- raw_init,
- NULL,
- NULL,
- ip_setsockopt,
- ip_getsockopt,
- raw_sendmsg,
- raw_recvmsg,
- NULL, /* No special bind */
- raw_rcv_skb,
- 128,
- 0,
- "RAW",
- 0, 0,
- NULL
+ NULL, /* ioctl */
+#endif
+ NULL, /* init */
+ NULL, /* destroy */
+ NULL, /* shutdown */
+ ip_setsockopt, /* setsockopt */
+ ip_getsockopt, /* getsockopt */
+ raw_sendmsg, /* sendmsg */
+ raw_recvmsg, /* recvmsg */
+ raw_bind, /* bind */
+ raw_rcv_skb, /* backlog_rcv */
+ raw_v4_hash, /* hash */
+ raw_v4_unhash, /* unhash */
+ raw_v4_rehash, /* rehash */
+ NULL, /* good_socknum */
+ NULL, /* verify_bind */
+ 128, /* max_header */
+ 0, /* retransmits */
+ "RAW", /* name */
+ 0, /* inuse */
+ 0 /* highestinuse */
};
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov