Netdev List
 help / color / mirror / Atom feed
* Re: [PATCH] driver:net:stmmac: Disable DMA store and forward mode if platform data force_sf_dma_mode is negative.
From: Giuseppe CAVALLARO @ 2013-08-19  7:45 UTC (permalink / raw)
  To: Sonic Zhang; +Cc: netdev, adi-buildroot-devel, Sonic Zhang
In-Reply-To: <CAJxxZ0PZUYeFnfnHVNaVi=wx_YDiTmsUNCfNyR27=jSuBH+tzg@mail.gmail.com>

On 8/19/2013 9:31 AM, Sonic Zhang wrote:
> Hi Giuseppe,
>
> On Mon, Aug 19, 2013 at 2:03 PM, Giuseppe CAVALLARO
> <peppe.cavallaro@st.com> wrote:
>> Hello Sonic
>>
>>
>> On 8/15/2013 9:37 AM, Sonic Zhang wrote:
>>>
>>> From: Sonic Zhang <sonic.zhang@analog.com>
>>>
>>> Some synopsys ip implementation doesn't support DMA store and forward
>>> mode,
>>> such as BF60x. So, define force_sf_dma_mode negative to use DMA thresholds
>>> only.
>>
>>
>> I think that you should not pass the force_sf_dma_mode platform field
>> at all (and it doesn't make sense to force it as negative).
>> To use the threshold you should reset tx_coe. In fact, your HW cannot
>> perform the Hw csum if SF is not available.
>> Note that, the HW cap register (if available) can override (set/reset)
>>   tx_coe.
>
> Even if I reset tx_coe, the SF mode is still set to RX DMA in current
> stmmac_dma_operation_mode(). SF mode is not supported in both RX DMA
> and TX DMA in Blackfin MAC.

yes this is true. the SF is always set for the RX path because I have
never had and known HW w/o RX csum (since the 209).

So I think the code could be improved to disable/enable the SF also for
the RX path.

>>
>> I tested, long time ago, this scenario on old mac w/o HW cap register
>> and w/o SF.
>
> Blackfin synopsys MAC IP has the HW cap register with tx_coe set to 1,
> but the HW tx_coe doesn't really work. I have the other patch to
> disable HW tx_coe in board file and override the HW cap register.

AFAIK the HW shouldn't be able to perform the csum in HW w/o SF.

Maybe, an easy way could be to use a new field to force the threshold
mode. This should also remove the csum in HW (IMO) and program the
DMA operation register.

Regards
Peppe

>
> Regards,
>
> Sonic
>
>>
>> let me know if it is ok
>>
>> I have just noticed that the no_csum_insertion could be removed and I'll
>> provide a patch for it.
>>
>
>

^ permalink raw reply

* Re: 3.11-rc6 genetlink locking fix offends lockdep
From: Johannes Berg @ 2013-08-19  8:00 UTC (permalink / raw)
  To: Hugh Dickins
  Cc: Linus Torvalds, Greg KH, David S. Miller, Otcheretianski, Andrei,
	linux-kernel@vger.kernel.org, netdev@vger.kernel.org,
	stable@vger.kernel.org, Pravin B Shelar, Thomas Graf
In-Reply-To: <alpine.LNX.2.00.1308182143370.906@eggly.anvils>


> 3.11-rc6's commit 58ad436fcf49 ("genetlink: fix family dump race")
> gives me the lockdep trace below at startup.

Hmm. Yes, I see now how this happens, not sure why I didn't run into it.

The problem is that genl_family_rcv_msg() is called with the genl_lock
held, and then calls netlink_dump_start() with it held, creating a
genl_lock->cb_mutex dependency, but obviously the dump continuation is
the other way around.

We could use the semaphore instead, I believe, but I don't really
understand the mutex vs. semaphore well enough to be sure that's
correct.

johannes


diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index f85f8a2..6cfa646 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -792,7 +792,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
 	bool need_locking = chains_to_skip || fams_to_skip;
 
 	if (need_locking)
-		genl_lock();
+		down_read(&cb_lock);
 
 	for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
 		n = 0;
@@ -815,7 +815,7 @@ errout:
 	cb->args[1] = n;
 
 	if (need_locking)
-		genl_unlock();
+		up_read(&cb_lock);
 
 	return skb->len;
 }

^ permalink raw reply related

* Re: NAT stops forwarding ACKs after PMTU discovery
From: Corey Hickey @ 2013-08-19  8:43 UTC (permalink / raw)
  To: Eric Dumazet; +Cc: Jozsef Kadlecsik, Linux Netdev List, netfilter-devel
In-Reply-To: <1376870592.4226.27.camel@edumazet-glaptop>

On 2013-08-18 17:03, Eric Dumazet wrote:
> On Sun, 2013-08-18 at 17:00 -0700, Eric Dumazet wrote:
> 
>> Code like this seems very suspect to me :
>>
>> before(sack, receiver->td_end + 1)
>>
> 
> My suggestion would be to try :
> 
> diff --git a/net/netfilter/nf_conntrack_proto_tcp.c b/net/netfilter/nf_conntrack_proto_tcp.c

[...]

Thanks for all your suggestions--I really wasn't expecting so much on a
weekend. Here's all the data I have for tonight.


I tried the linux-next kernel, then linux-next with your patch applied.
Neither of them fix the problem, unfortunately. I have taken tcpdumps
for a working SSH and a failing SSH.

http://fatooh.org/files/tmp/linux-next-patch1.tar.bz2

[localhost]
sudo tcpdump -ni br0 -s 0 -w /tmp/local.pcap 'host 10.15.24.13 or icmp'

[router eth0]
tcpdump -ni eth0 -s 0 -w /tmp/eth0.pcap \
    'host 10.15.24.13 or (icmp and host not 69.78.33.132)'
* the exclusion here is just to remove some unrelated clutter

[router tun0]
tcpdump -ni tun0 -s 0 -w /tmp/tun0.pcap -s 0 'host 10.15.24.13 or icmp'

[remote]
tcpdump -ni eth0 -s 0 -w remote.pcap 'host 192.168.61.56'


Some notes:

1. I tested the new kernels only on the Linux router, assuming that is
where it was intended.

2. I take back what I wrote earlier about every connection that involves
PMTU discovery failed; I may have been observing this wrong. For now,
the situation is that some connections stop forwarding packets from the
remote host immediately after the retransmit, while other work fine.

3. From local.pcap, you can see that my localhost doesn't actually
transmit a large packet, yet the router's eth0 sees a large packet come
in. I think this is due to TSO, but I'm not completely sure.

4. For some reason, I cannot reproduce this when SSHing to a host at
work that is running Debian sid with 3.10-1-amd64, but I can reproduce
it when SSHing to hosts running Centos 6.4 with
2.6.32-358.6.1.el6.x86_64 (which surely has a ton of patches applied,
for whatever that's worth).

5. I have only a vague understanding of SACK; I will be reading up on
this soon. I will also look into packetdrill for reproducing the
problem, if the SSH results aren't good enough.

6. If I reduce the MTU on localhost to match the path MTU, the problem
does go away.

Thanks again for all the help,
Corey

^ permalink raw reply

* [PATCH net-next] myri10ge: Add support for ndo_busy_poll
From: Hyong-Youb Kim @ 2013-08-19  9:02 UTC (permalink / raw)
  To: David S. Miller; +Cc: netdev, Hyong-Youb Kim

Add the ndo_busy_poll handler. Use skb_mark_napi_id to mark receive
packets with the napi id. For each slice, use per-slice spinlock and
state variable to ensure that only one handler processes receive
pacekts.

Locking, statistics counters, and the ndo_busy_poll handler follow
those in the ixgbe driver. So, credit goes to that driver's authors.

Signed-off-by: Hyong-Youb Kim <hykim@myri.com>
---
 drivers/net/ethernet/myricom/myri10ge/myri10ge.c |  200 +++++++++++++++++++++-
 1 files changed, 198 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
index 66c0400..3bb14e7 100644
--- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
+++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c
@@ -74,6 +74,7 @@
 #ifdef CONFIG_MTRR
 #include <asm/mtrr.h>
 #endif
+#include <net/busy_poll.h>
 
 #include "myri10ge_mcp.h"
 #include "myri10ge_mcp_gen_header.h"
@@ -194,6 +195,21 @@ struct myri10ge_slice_state {
 	int cpu;
 	__be32 __iomem *dca_tag;
 #endif
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	unsigned int state;
+#define SLICE_STATE_IDLE	0
+#define SLICE_STATE_NAPI	1	/* NAPI owns this slice */
+#define SLICE_STATE_POLL	2	/* poll owns this slice */
+#define SLICE_LOCKED (SLICE_STATE_NAPI | SLICE_STATE_POLL)
+#define SLICE_STATE_NAPI_YIELD	4	/* NAPI yielded this slice */
+#define SLICE_STATE_POLL_YIELD	8	/* poll yielded this slice */
+#define SLICE_USER_PEND (SLICE_STATE_POLL | SLICE_STATE_POLL_YIELD)
+	spinlock_t lock;
+	unsigned long lock_napi_yield;
+	unsigned long lock_poll_yield;
+	unsigned long busy_poll_miss;
+	unsigned long busy_poll_cnt;
+#endif /* CONFIG_NET_RX_BUSY_POLL */
 	char irq_desc[32];
 };
 
@@ -909,6 +925,92 @@ abort:
 	return status;
 }
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static inline void myri10ge_ss_init_lock(struct myri10ge_slice_state *ss)
+{
+	spin_lock_init(&ss->lock);
+	ss->state = SLICE_STATE_IDLE;
+}
+
+static inline bool myri10ge_ss_lock_napi(struct myri10ge_slice_state *ss)
+{
+	int rc = true;
+	spin_lock(&ss->lock);
+	if ((ss->state & SLICE_LOCKED)) {
+		WARN_ON((ss->state & SLICE_STATE_NAPI));
+		ss->state |= SLICE_STATE_NAPI_YIELD;
+		rc = false;
+		ss->lock_napi_yield++;
+	} else
+		ss->state = SLICE_STATE_NAPI;
+	spin_unlock(&ss->lock);
+	return rc;
+}
+
+static inline void myri10ge_ss_unlock_napi(struct myri10ge_slice_state *ss)
+{
+	spin_lock(&ss->lock);
+	WARN_ON((ss->state & (SLICE_STATE_POLL | SLICE_STATE_NAPI_YIELD)));
+	ss->state = SLICE_STATE_IDLE;
+	spin_unlock(&ss->lock);
+}
+
+static inline bool myri10ge_ss_lock_poll(struct myri10ge_slice_state *ss)
+{
+	int rc = true;
+	spin_lock_bh(&ss->lock);
+	if ((ss->state & SLICE_LOCKED)) {
+		ss->state |= SLICE_STATE_POLL_YIELD;
+		rc = false;
+		ss->lock_poll_yield++;
+	} else
+		ss->state |= SLICE_STATE_POLL;
+	spin_unlock_bh(&ss->lock);
+	return rc;
+}
+
+static inline void myri10ge_ss_unlock_poll(struct myri10ge_slice_state *ss)
+{
+	spin_lock_bh(&ss->lock);
+	WARN_ON((ss->state & SLICE_STATE_NAPI));
+	ss->state = SLICE_STATE_IDLE;
+	spin_unlock_bh(&ss->lock);
+}
+
+static inline bool myri10ge_ss_busy_polling(struct myri10ge_slice_state *ss)
+{
+	WARN_ON(!(ss->state & SLICE_LOCKED));
+	return (ss->state & SLICE_USER_PEND);
+}
+#else /* CONFIG_NET_RX_BUSY_POLL */
+static inline void myri10ge_ss_init_lock(struct myri10ge_slice_state *ss)
+{
+}
+
+static inline bool myri10ge_ss_lock_napi(struct myri10ge_slice_state *ss)
+{
+	return false;
+}
+
+static inline void myri10ge_ss_unlock_napi(struct myri10ge_slice_state *ss)
+{
+}
+
+static inline bool myri10ge_ss_lock_poll(struct myri10ge_slice_state *ss)
+{
+	return false;
+}
+
+static inline void myri10ge_ss_unlock_poll(struct myri10ge_slice_state *ss)
+{
+}
+
+static inline bool myri10ge_ss_busy_polling(struct myri10ge_slice_state *ss)
+{
+	return false;
+}
+#endif
+
 static int myri10ge_reset(struct myri10ge_priv *mgp)
 {
 	struct myri10ge_cmd cmd;
@@ -1300,6 +1402,8 @@ myri10ge_vlan_rx(struct net_device *dev, void *addr, struct sk_buff *skb)
 	}
 }
 
+#define MYRI10GE_HLEN 64 /* Bytes to copy from page to skb linear memory */
+
 static inline int
 myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
 {
@@ -1311,6 +1415,7 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
 	struct pci_dev *pdev = mgp->pdev;
 	struct net_device *dev = mgp->dev;
 	u8 *va;
+	bool polling;
 
 	if (len <= mgp->small_bytes) {
 		rx = &ss->rx_small;
@@ -1325,7 +1430,15 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
 	va = page_address(rx->info[idx].page) + rx->info[idx].page_offset;
 	prefetch(va);
 
-	skb = napi_get_frags(&ss->napi);
+	/* When busy polling in user context, allocate skb and copy headers to
+	 * skb's linear memory ourselves.  When not busy polling, use the napi
+	 * gro api.
+	 */
+	polling = myri10ge_ss_busy_polling(ss);
+	if (polling)
+		skb = netdev_alloc_skb(dev, MYRI10GE_HLEN + 16);
+	else
+		skb = napi_get_frags(&ss->napi);
 	if (unlikely(skb == NULL)) {
 		ss->stats.rx_dropped++;
 		for (i = 0, remainder = len; remainder > 0; i++) {
@@ -1364,8 +1477,29 @@ myri10ge_rx_done(struct myri10ge_slice_state *ss, int len, __wsum csum)
 	}
 	myri10ge_vlan_rx(mgp->dev, va, skb);
 	skb_record_rx_queue(skb, ss - &mgp->ss[0]);
+	skb_mark_napi_id(skb, &ss->napi);
 
-	napi_gro_frags(&ss->napi);
+	if (polling) {
+		int hlen;
+		
+		/* myri10ge_vlan_rx might have moved the header, so compute
+		 * length and address again.
+		 */
+		hlen = MYRI10GE_HLEN > skb->len ? skb->len : MYRI10GE_HLEN;
+		va = page_address(skb_frag_page(&rx_frags[0])) +
+			rx_frags[0].page_offset;
+		/* Copy header into the skb linear memory */
+		skb_copy_to_linear_data(skb, va, hlen);
+		rx_frags[0].page_offset += hlen;
+		rx_frags[0].size -= hlen;
+		skb->data_len -= hlen;
+		skb->tail += hlen;
+		skb->protocol = eth_type_trans(skb, dev);
+		netif_receive_skb(skb);
+	}
+	else
+		napi_gro_frags(&ss->napi);
+	
 	return 1;
 }
 
@@ -1524,10 +1658,14 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
 	if (ss->mgp->dca_enabled)
 		myri10ge_update_dca(ss);
 #endif
+	/* Try later if the busy_poll handler is running. */
+	if (!myri10ge_ss_lock_napi(ss))
+		return budget;
 
 	/* process as many rx events as NAPI will allow */
 	work_done = myri10ge_clean_rx_done(ss, budget);
 
+	myri10ge_ss_unlock_napi(ss);
 	if (work_done < budget) {
 		napi_complete(napi);
 		put_be32(htonl(3), ss->irq_claim);
@@ -1535,6 +1673,34 @@ static int myri10ge_poll(struct napi_struct *napi, int budget)
 	return work_done;
 }
 
+#ifdef CONFIG_NET_RX_BUSY_POLL
+static int myri10ge_busy_poll(struct napi_struct *napi)
+{
+	struct myri10ge_slice_state *ss =
+	    container_of(napi, struct myri10ge_slice_state, napi);
+	struct myri10ge_priv *mgp = ss->mgp;
+	int work_done;
+
+	/* Poll only when the link is up */
+	if (mgp->link_state != MXGEFW_LINK_UP)
+		return LL_FLUSH_FAILED;
+
+	if (!myri10ge_ss_lock_poll(ss))
+		return LL_FLUSH_BUSY;
+
+	/* Process a small number of packets */
+	work_done = myri10ge_clean_rx_done(ss, 4);
+	if (work_done)
+		ss->busy_poll_cnt += work_done;
+	else
+		ss->busy_poll_miss++;
+	
+	myri10ge_ss_unlock_poll(ss);
+
+	return work_done;
+}
+#endif /* CONFIG_NET_RX_BUSY_POLL */
+
 static irqreturn_t myri10ge_intr(int irq, void *arg)
 {
 	struct myri10ge_slice_state *ss = arg;
@@ -1742,6 +1908,10 @@ static const char myri10ge_gstrings_slice_stats[][ETH_GSTRING_LEN] = {
 	"tx_pkt_start", "tx_pkt_done", "tx_req", "tx_done",
 	"rx_small_cnt", "rx_big_cnt",
 	"wake_queue", "stop_queue", "tx_linearized",
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	"rx_lock_napi_yield", "rx_lock_poll_yield", "rx_busy_poll_miss",
+	"rx_busy_poll_cnt",
+#endif
 };
 
 #define MYRI10GE_NET_STATS_LEN      21
@@ -1842,6 +2012,12 @@ myri10ge_get_ethtool_stats(struct net_device *netdev,
 		data[i++] = (unsigned int)ss->tx.wake_queue;
 		data[i++] = (unsigned int)ss->tx.stop_queue;
 		data[i++] = (unsigned int)ss->tx.linearized;
+#ifdef CONFIG_NET_RX_BUSY_POLL
+		data[i++] = ss->lock_napi_yield;
+		data[i++] = ss->lock_poll_yield;
+		data[i++] = ss->busy_poll_miss;
+		data[i++] = ss->busy_poll_cnt;
+#endif
 	}
 }
 
@@ -2405,6 +2581,9 @@ static int myri10ge_open(struct net_device *dev)
 			goto abort_with_rings;
 		}
 
+		/* Initialize the slice spinlock and state used for polling */
+		myri10ge_ss_init_lock(ss);
+		
 		/* must happen prior to any irq */
 		napi_enable(&(ss)->napi);
 	}
@@ -2481,9 +2660,19 @@ static int myri10ge_close(struct net_device *dev)
 
 	del_timer_sync(&mgp->watchdog_timer);
 	mgp->running = MYRI10GE_ETH_STOPPING;
+	local_bh_disable(); /* myri10ge_ss_lock_napi needs bh disabled */
 	for (i = 0; i < mgp->num_slices; i++) {
 		napi_disable(&mgp->ss[i].napi);
+		/* Lock the slice to prevent the busy_poll handler from
+		 * accessing it.  Later when we bring the NIC up, myri10ge_open
+		 * resets the slice including this lock.
+		 */
+		while (!myri10ge_ss_lock_napi(&mgp->ss[i])) {
+			pr_info("Slice %d locked\n", i);
+			mdelay(1);
+		}
 	}
+	local_bh_enable();
 	netif_carrier_off(dev);
 
 	netif_tx_stop_all_queues(dev);
@@ -3569,8 +3758,11 @@ static void myri10ge_free_slices(struct myri10ge_priv *mgp)
 					  ss->fw_stats, ss->fw_stats_bus);
 			ss->fw_stats = NULL;
 		}
+		napi_hash_del(&ss->napi);
 		netif_napi_del(&ss->napi);
 	}
+	/* Wait till napi structs are no longer used, and then free ss. */
+	synchronize_rcu();
 	kfree(mgp->ss);
 	mgp->ss = NULL;
 }
@@ -3606,6 +3798,7 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
 		ss->dev = mgp->dev;
 		netif_napi_add(ss->dev, &ss->napi, myri10ge_poll,
 			       myri10ge_napi_weight);
+		napi_hash_add(&ss->napi);
 	}
 	return 0;
 abort:
@@ -3748,6 +3941,9 @@ static const struct net_device_ops myri10ge_netdev_ops = {
 	.ndo_change_mtu		= myri10ge_change_mtu,
 	.ndo_set_rx_mode	= myri10ge_set_multicast_list,
 	.ndo_set_mac_address	= myri10ge_set_mac_address,
+#ifdef CONFIG_NET_RX_BUSY_POLL
+	.ndo_busy_poll		= myri10ge_busy_poll,
+#endif
 };
 
 static int myri10ge_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
-- 
1.7.1

^ permalink raw reply related

* [ PATCH net-next ] xfrm: remove irrelevant comment in xfrm_input().
From: Rami Rosen @ 2013-08-19 12:47 UTC (permalink / raw)
  To: steffen.klassert; +Cc: davem, netdev, Rami Rosen

This patch removes a comment in xfrm_input() which became irrelevant
due to commit 2774c13, "xfrm: Handle blackhole route creation via afinfo".
That commit removed returning -EREMOTE in the xfrm_lookup() method when the 
packet should be discarded  and also removed the correspoinding -EREMOTE 
handlers. This was replaced by calling the make_blackhole() method. Therefore
the comment about -EREMOTE is not relevant anymore.

Signed-off-by: Rami Rosen <ramirose@gmail.com>
---
 net/xfrm/xfrm_policy.c | 2 --
 1 file changed, 2 deletions(-)

diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index d8da6b8..3d65c6e 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2132,8 +2132,6 @@ restart:
 		 * have the xfrm_state's. We need to wait for KM to
 		 * negotiate new SA's or bail out with error.*/
 		if (net->xfrm.sysctl_larval_drop) {
-			/* EREMOTE tells the caller to generate
-			 * a one-shot blackhole route. */
 			dst_release(dst);
 			xfrm_pols_put(pols, drop_pols);
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES);
-- 
1.8.1.4

^ permalink raw reply related

* [PATCH] net: cpsw: Add support for wake-on-lan for cpsw
From: ujhelyi.m @ 2013-08-19 10:13 UTC (permalink / raw)
  To: davem, mugunthanvnm, netdev; +Cc: linux-kernel, Matus Ujhelyi

From: Matus Ujhelyi <ujhelyi.m@gmail.com>

Signed-off-by: Matus Ujhelyi <ujhelyi.m@gmail.com>
---
 drivers/net/ethernet/ti/cpsw.c |   25 +++++++++++++++++++++++++
 1 file changed, 25 insertions(+)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 22a7a43..f59302e 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1416,6 +1416,29 @@ static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
 		return -EOPNOTSUPP;
 }
 
+static void
+cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	int slave_no = cpsw_slave_index(priv);
+	wol->supported = 0;
+	wol->wolopts = 0;
+	if (priv->slaves[slave_no].phy)
+		phy_ethtool_get_wol(priv->slaves[slave_no].phy, wol);
+
+}
+
+static int
+cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	int slave_no = cpsw_slave_index(priv);
+	if (priv->slaves[slave_no].phy)
+		return phy_ethtool_set_wol(priv->slaves[slave_no].phy, wol);
+	else
+		return -EOPNOTSUPP;
+}
+
 static const struct ethtool_ops cpsw_ethtool_ops = {
 	.get_drvinfo	= cpsw_get_drvinfo,
 	.get_msglevel	= cpsw_get_msglevel,
@@ -1426,6 +1449,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
 	.set_settings	= cpsw_set_settings,
 	.get_coalesce	= cpsw_get_coalesce,
 	.set_coalesce	= cpsw_set_coalesce,
+	.get_wol        = cpsw_get_wol,
+	.set_wol        = cpsw_set_wol,
 };
 
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
-- 
1.7.9.5

^ permalink raw reply related

* [Patch net-next v3 2/9] net: rename '%pIS' to '%pIA' for union inet_addr
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Daniel Borkmann, Joe Perches, linux-kernel,
	Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

The "%pIS" specifier is for struct Sockaddr, since now we have union
inet_addr, rename it to '%pIA' so that it can accept union inet_addr*.
But struct sockaddr * can still safely passed to
'%pIA', since it is a union of it.

Cc: Daniel Borkmann <dborkman@redhat.com>
Cc: Joe Perches <joe@perches.com>
Cc: linux-kernel@vger.kernel.org
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 Documentation/printk-formats.txt |   20 ++++++++++----------
 drivers/net/netconsole.c         |   10 ++--------
 lib/vsprintf.c                   |   29 +++++++++++++----------------
 net/core/netpoll.c               |   10 ++--------
 net/sctp/associola.c             |    6 +++---
 net/sctp/protocol.c              |    6 +++---
 net/sctp/sm_sideeffect.c         |    2 +-
 net/sctp/socket.c                |    4 ++--
 8 files changed, 36 insertions(+), 51 deletions(-)

diff --git a/Documentation/printk-formats.txt b/Documentation/printk-formats.txt
index 3e8cb73..3521cc9 100644
--- a/Documentation/printk-formats.txt
+++ b/Documentation/printk-formats.txt
@@ -123,15 +123,15 @@ IPv6 addresses:
 
 IPv4/IPv6 addresses (generic, with port, flowinfo, scope):
 
-	%pIS	1.2.3.4		or 0001:0002:0003:0004:0005:0006:0007:0008
-	%piS	001.002.003.004	or 00010002000300040005000600070008
-	%pISc	1.2.3.4		or 1:2:3:4:5:6:7:8
-	%pISpc	1.2.3.4:12345	or [1:2:3:4:5:6:7:8]:12345
-	%p[Ii]S[pfschnbl]
+	%pIA	1.2.3.4		or 0001:0002:0003:0004:0005:0006:0007:0008
+	%piA	001.002.003.004	or 00010002000300040005000600070008
+	%pIAc	1.2.3.4		or 1:2:3:4:5:6:7:8
+	%pIApc	1.2.3.4:12345	or [1:2:3:4:5:6:7:8]:12345
+	%p[Ii]A[pfschnbl]
 
 	For printing an IP address without the need to distinguish whether it's
-	of type AF_INET or AF_INET6, a pointer to a valid 'struct sockaddr',
-	specified through 'IS' or 'iS', can be passed to this format specifier.
+	of type AF_INET or AF_INET6, a pointer to a valid 'union inet_addr',
+	specified through 'IA' or 'iA', can be passed to this format specifier.
 
 	The additional 'p', 'f', and 's' specifiers are used to specify port
 	(IPv4, IPv6), flowinfo (IPv6) and scope (IPv6). Ports have a ':' prefix,
@@ -149,9 +149,9 @@ IPv4/IPv6 addresses (generic, with port, flowinfo, scope):
 
 	Further examples:
 
-	%pISfc		1.2.3.4		or [1:2:3:4:5:6:7:8]/123456789
-	%pISsc		1.2.3.4		or [1:2:3:4:5:6:7:8]%1234567890
-	%pISpfc		1.2.3.4:12345	or [1:2:3:4:5:6:7:8]:12345/123456789
+	%pIAfc		1.2.3.4		or [1:2:3:4:5:6:7:8]/123456789
+	%pIAsc		1.2.3.4		or [1:2:3:4:5:6:7:8]%1234567890
+	%pIApfc		1.2.3.4:12345	or [1:2:3:4:5:6:7:8]:12345/123456789
 
 UUID/GUID addresses:
 
diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index e4eac0c..28234f8 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -270,18 +270,12 @@ static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
 
 static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
 {
-	if (nt->np.ipv6)
-		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.sin6.sin6_addr);
-	else
-		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip.sin.sin_addr.s_addr);
+	return snprintf(buf, PAGE_SIZE, "%pIA\n", &nt->np.local_ip);
 }
 
 static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
 {
-	if (nt->np.ipv6)
-		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.sin6.sin6_addr);
-	else
-		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip.sin.sin_addr.s_addr);
+	return snprintf(buf, PAGE_SIZE, "%pIA\n", &nt->np.remote_ip);
 }
 
 static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
diff --git a/lib/vsprintf.c b/lib/vsprintf.c
index 739a363..49618d0 100644
--- a/lib/vsprintf.c
+++ b/lib/vsprintf.c
@@ -27,6 +27,7 @@
 #include <linux/uaccess.h>
 #include <linux/ioport.h>
 #include <net/addrconf.h>
+#include <net/inet_addr.h>
 
 #include <asm/page.h>		/* for PAGE_SIZE */
 #include <asm/sections.h>	/* for dereference_function_descriptor() */
@@ -1104,14 +1105,14 @@ int kptr_restrict __read_mostly;
  * - 'I' [46] for IPv4/IPv6 addresses printed in the usual way
  *       IPv4 uses dot-separated decimal without leading 0's (1.2.3.4)
  *       IPv6 uses colon separated network-order 16 bit hex with leading 0's
- *       [S][pfs]
- *       Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
+ *       [A][pfs]
+ *       Generic IPv4/IPv6 address (union inet_addr *) that falls back to
  *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
  * - 'i' [46] for 'raw' IPv4/IPv6 addresses
  *       IPv6 omits the colons (01020304...0f)
  *       IPv4 uses dot-separated decimal with leading 0's (010.123.045.006)
- *       [S][pfs]
- *       Generic IPv4/IPv6 address (struct sockaddr *) that falls back to
+ *       [A][pfs]
+ *       Generic IPv4/IPv6 address (union inet_addr *) that falls back to
  *       [4] or [6] and is able to print port [p], flowinfo [f], scope [s]
  * - '[Ii][4S][hnbl]' IPv4 addresses in host, network, big or little endian order
  * - 'I[6S]c' for IPv6 addresses printed as specified by
@@ -1196,18 +1197,14 @@ char *pointer(const char *fmt, char *buf, char *end, void *ptr,
 			return ip6_addr_string(buf, end, ptr, spec, fmt);
 		case '4':
 			return ip4_addr_string(buf, end, ptr, spec, fmt);
-		case 'S': {
-			const union {
-				struct sockaddr		raw;
-				struct sockaddr_in	v4;
-				struct sockaddr_in6	v6;
-			} *sa = ptr;
-
-			switch (sa->raw.sa_family) {
+		case 'A': {
+			const union inet_addr *sa = ptr;
+
+			switch (sa->sa.sa_family) {
 			case AF_INET:
-				return ip4_addr_string_sa(buf, end, &sa->v4, spec, fmt);
+				return ip4_addr_string_sa(buf, end, &sa->sin, spec, fmt);
 			case AF_INET6:
-				return ip6_addr_string_sa(buf, end, &sa->v6, spec, fmt);
+				return ip6_addr_string_sa(buf, end, &sa->sin6, spec, fmt);
 			default:
 				return string(buf, end, "(invalid address)", spec);
 			}}
@@ -1488,8 +1485,8 @@ qualifier:
  * %pI6 print an IPv6 address with colons
  * %pi6 print an IPv6 address without colons
  * %pI6c print an IPv6 address as specified by RFC 5952
- * %pIS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address
- * %piS depending on sa_family of 'struct sockaddr *' print IPv4/IPv6 address
+ * %pIA depending on sa_family of 'union inet_addr *' print IPv4/IPv6 address
+ * %piA depending on sa_family of 'union inet_addr *' print IPv4/IPv6 address
  * %pU[bBlL] print a UUID/GUID in big or little endian using lower or upper
  *   case.
  * %*ph[CDN] a variable-length hex string with a separator (supports up to 64
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index dd38553..9a45c54 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -900,16 +900,10 @@ out:
 void netpoll_print_options(struct netpoll *np)
 {
 	np_info(np, "local port %d\n", np->local_port);
-	if (np->ipv6)
-		np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.sin6.sin6_addr);
-	else
-		np_info(np, "local IPv4 address %pI4\n", &np->local_ip.sin.sin_addr.s_addr);
+	np_info(np, "local IP address %pIA\n", &np->local_ip);
 	np_info(np, "interface '%s'\n", np->dev_name);
 	np_info(np, "remote port %d\n", np->remote_port);
-	if (np->ipv6)
-		np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.sin6.sin6_addr);
-	else
-		np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.sin.sin_addr.s_addr);
+	np_info(np, "remote IP address %pIA\n", &np->remote_ip);
 	np_info(np, "remote ethernet address %pM\n", np->remote_mac);
 }
 EXPORT_SYMBOL(netpoll_print_options);
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index cef5099..a514612 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -534,7 +534,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
 	struct list_head	*pos;
 	struct sctp_transport	*transport;
 
-	pr_debug("%s: association:%p addr:%pISpc\n",
+	pr_debug("%s: association:%p addr:%pIApc\n",
 		 __func__, asoc, &peer->ipaddr.sa);
 
 	/* If we are to remove the current retran_path, update it
@@ -631,7 +631,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 	/* AF_INET and AF_INET6 share common port field. */
 	port = ntohs(addr->v4.sin_port);
 
-	pr_debug("%s: association:%p addr:%pISpc state:%d\n", __func__,
+	pr_debug("%s: association:%p addr:%pIApc state:%d\n", __func__,
 		 asoc, &addr->sa, peer_state);
 
 	/* Set the port if it has not been set yet.  */
@@ -1341,7 +1341,7 @@ void sctp_assoc_update_retran_path(struct sctp_association *asoc)
 	else
 		t = asoc->peer.retran_path;
 
-	pr_debug("%s: association:%p addr:%pISpc\n", __func__, asoc,
+	pr_debug("%s: association:%p addr:%pIApc\n", __func__, asoc,
 		 &t->ipaddr.sa);
 }
 
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 5e17092..0680be7 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -598,7 +598,7 @@ static void sctp_addr_wq_timeout_handler(unsigned long arg)
 	spin_lock_bh(&net->sctp.addr_wq_lock);
 
 	list_for_each_entry_safe(addrw, temp, &net->sctp.addr_waitq, list) {
-		pr_debug("%s: the first ent in wq:%p is addr:%pISc for cmd:%d at "
+		pr_debug("%s: the first ent in wq:%p is addr:%pIAc for cmd:%d at "
 			 "entry:%p\n", __func__, &net->sctp.addr_waitq, &addrw->a.sa,
 			 addrw->state, addrw);
 
@@ -703,7 +703,7 @@ void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cm
 	addrw = sctp_addr_wq_lookup(net, addr);
 	if (addrw) {
 		if (addrw->state != cmd) {
-			pr_debug("%s: offsets existing entry for %d, addr:%pISc "
+			pr_debug("%s: offsets existing entry for %d, addr:%pIAc "
 				 "in wq:%p\n", __func__, addrw->state, &addrw->a.sa,
 				 &net->sctp.addr_waitq);
 
@@ -723,7 +723,7 @@ void sctp_addr_wq_mgmt(struct net *net, struct sctp_sockaddr_entry *addr, int cm
 	addrw->state = cmd;
 	list_add_tail(&addrw->list, &net->sctp.addr_waitq);
 
-	pr_debug("%s: add new entry for cmd:%d, addr:%pISc in wq:%p\n",
+	pr_debug("%s: add new entry for cmd:%d, addr:%pIAc in wq:%p\n",
 		 __func__, addrw->state, &addrw->a.sa, &net->sctp.addr_waitq);
 
 	if (!timer_pending(&net->sctp.addr_wq_timer)) {
diff --git a/net/sctp/sm_sideeffect.c b/net/sctp/sm_sideeffect.c
index 666c668..638c63c 100644
--- a/net/sctp/sm_sideeffect.c
+++ b/net/sctp/sm_sideeffect.c
@@ -514,7 +514,7 @@ static void sctp_do_8_2_transport_strike(sctp_cmd_seq_t *commands,
 
 	if (transport->state != SCTP_INACTIVE &&
 	    (transport->error_count > transport->pathmaxrxt)) {
-		pr_debug("%s: association:%p transport addr:%pISpc failed\n",
+		pr_debug("%s: association:%p transport addr:%pIApc failed\n",
 			 __func__, asoc, &transport->ipaddr.sa);
 
 		sctp_assoc_control_transport(asoc, transport,
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index d5d5882..dba117a 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -343,7 +343,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 
 	snum = ntohs(addr->v4.sin_port);
 
-	pr_debug("%s: sk:%p, new addr:%pISc, port:%d, new port:%d, len:%d\n",
+	pr_debug("%s: sk:%p, new addr:%pIAc, port:%d, new port:%d, len:%d\n",
 		 __func__, sk, &addr->sa, bp->port, snum, len);
 
 	/* PF specific bind() address verification. */
@@ -797,7 +797,7 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 				asoc->asconf_addr_del_pending->v6.sin6_addr = sin6->sin6_addr;
 			}
 
-			pr_debug("%s: keep the last address asoc:%p %pISc at %p\n",
+			pr_debug("%s: keep the last address asoc:%p %pIAc at %p\n",
 				 __func__, asoc, &asoc->asconf_addr_del_pending->sa,
 				 asoc->asconf_addr_del_pending);
 
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 7/9] fs: use generic union inet_addr and helper functions
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Steve French, Christine Caulfield,
	David Teigland, Trond Myklebust, linux-cifs, linux-kernel,
	cluster-devel, linux-nfs, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

nfs and cifs define some helper functions for sockaddr,
they can use the generic functions for union inet_addr/struct sockaddr
too.

Since some dlm code needs to compare ->sin_port, introduce a
generic function inet_addr_equal_strict() for it.

Cc: Steve French <sfrench@samba.org>
Cc: Christine Caulfield <ccaulfie@redhat.com>
Cc: David Teigland <teigland@redhat.com>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: linux-cifs@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
Cc: cluster-devel@redhat.com
Cc: linux-nfs@vger.kernel.org
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 fs/cifs/connect.c          |   54 +++++---------------
 fs/dlm/lowcomms.c          |   24 ++-------
 fs/nfs/client.c            |  113 +-------------------------------------------
 fs/nfs/nfs4client.c        |    2 +-
 fs/nfs/nfs4filelayoutdev.c |   37 ++-------------
 fs/nfs/super.c             |   31 +-----------
 include/net/inet_addr.h    |    8 +++
 net/core/utils.c           |   23 +++++++++
 8 files changed, 60 insertions(+), 232 deletions(-)

diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index d67c550..081cb6c 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -40,6 +40,7 @@
 #include <linux/module.h>
 #include <keys/user-type.h>
 #include <net/ipv6.h>
+#include <net/inet_addr.h>
 #include <linux/parser.h>
 
 #include "cifspdu.h"
@@ -1900,17 +1901,9 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
 {
 	switch (srcaddr->sa_family) {
 	case AF_UNSPEC:
-		return (rhs->sa_family == AF_UNSPEC);
-	case AF_INET: {
-		struct sockaddr_in *saddr4 = (struct sockaddr_in *)srcaddr;
-		struct sockaddr_in *vaddr4 = (struct sockaddr_in *)rhs;
-		return (saddr4->sin_addr.s_addr == vaddr4->sin_addr.s_addr);
-	}
-	case AF_INET6: {
-		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
-		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
-		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
-	}
+	case AF_INET:
+	case AF_INET6:
+		return sockaddr_equal(srcaddr, rhs);
 	default:
 		WARN_ON(1);
 		return false; /* don't expect to be here */
@@ -1925,16 +1918,13 @@ srcip_matches(struct sockaddr *srcaddr, struct sockaddr *rhs)
 static bool
 match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
 {
-	__be16 port, *sport;
+	unsigned short port, sport;
 
 	switch (addr->sa_family) {
 	case AF_INET:
-		sport = &((struct sockaddr_in *) &server->dstaddr)->sin_port;
-		port = ((struct sockaddr_in *) addr)->sin_port;
-		break;
 	case AF_INET6:
-		sport = &((struct sockaddr_in6 *) &server->dstaddr)->sin6_port;
-		port = ((struct sockaddr_in6 *) addr)->sin6_port;
+		sport = sockaddr_get_port((struct sockaddr *)&server->dstaddr);
+		port = sockaddr_get_port(addr);
 		break;
 	default:
 		WARN_ON(1);
@@ -1942,14 +1932,14 @@ match_port(struct TCP_Server_Info *server, struct sockaddr *addr)
 	}
 
 	if (!port) {
-		port = htons(CIFS_PORT);
-		if (port == *sport)
+		port = CIFS_PORT;
+		if (port == sport)
 			return true;
 
-		port = htons(RFC1001_PORT);
+		port = RFC1001_PORT;
 	}
 
-	return port == *sport;
+	return port == sport;
 }
 
 static bool
@@ -1957,27 +1947,11 @@ match_address(struct TCP_Server_Info *server, struct sockaddr *addr,
 	      struct sockaddr *srcaddr)
 {
 	switch (addr->sa_family) {
-	case AF_INET: {
-		struct sockaddr_in *addr4 = (struct sockaddr_in *)addr;
-		struct sockaddr_in *srv_addr4 =
-					(struct sockaddr_in *)&server->dstaddr;
-
-		if (addr4->sin_addr.s_addr != srv_addr4->sin_addr.s_addr)
-			return false;
-		break;
-	}
-	case AF_INET6: {
-		struct sockaddr_in6 *addr6 = (struct sockaddr_in6 *)addr;
-		struct sockaddr_in6 *srv_addr6 =
-					(struct sockaddr_in6 *)&server->dstaddr;
-
-		if (!ipv6_addr_equal(&addr6->sin6_addr,
-				     &srv_addr6->sin6_addr))
-			return false;
-		if (addr6->sin6_scope_id != srv_addr6->sin6_scope_id)
+	case AF_INET:
+	case AF_INET6:
+		if (!sockaddr_equal(addr, (struct sockaddr *)&server->dstaddr))
 			return false;
 		break;
-	}
 	default:
 		WARN_ON(1);
 		return false; /* don't expect to be here */
diff --git a/fs/dlm/lowcomms.c b/fs/dlm/lowcomms.c
index d90909e..c051237 100644
--- a/fs/dlm/lowcomms.c
+++ b/fs/dlm/lowcomms.c
@@ -54,6 +54,7 @@
 #include <linux/slab.h>
 #include <net/sctp/sctp.h>
 #include <net/ipv6.h>
+#include <net/inet_addr.h>
 
 #include "dlm_internal.h"
 #include "lowcomms.h"
@@ -286,28 +287,13 @@ static struct dlm_node_addr *find_node_addr(int nodeid)
 static int addr_compare(struct sockaddr_storage *x, struct sockaddr_storage *y)
 {
 	switch (x->ss_family) {
-	case AF_INET: {
-		struct sockaddr_in *sinx = (struct sockaddr_in *)x;
-		struct sockaddr_in *siny = (struct sockaddr_in *)y;
-		if (sinx->sin_addr.s_addr != siny->sin_addr.s_addr)
-			return 0;
-		if (sinx->sin_port != siny->sin_port)
-			return 0;
-		break;
-	}
-	case AF_INET6: {
-		struct sockaddr_in6 *sinx = (struct sockaddr_in6 *)x;
-		struct sockaddr_in6 *siny = (struct sockaddr_in6 *)y;
-		if (!ipv6_addr_equal(&sinx->sin6_addr, &siny->sin6_addr))
-			return 0;
-		if (sinx->sin6_port != siny->sin6_port)
-			return 0;
-		break;
-	}
+	case AF_INET:
+	case AF_INET6:
+		return inet_addr_equal_strict((union inet_addr *)x,
+					      (union inet_addr *)y);
 	default:
 		return 0;
 	}
-	return 1;
 }
 
 static int nodeid_to_addr(int nodeid, struct sockaddr_storage *sas_out,
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index 340b1ef..708dc96 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -38,6 +38,7 @@
 #include <linux/slab.h>
 #include <linux/idr.h>
 #include <net/ipv6.h>
+#include <net/inet_addr.h>
 #include <linux/nfs_xdr.h>
 #include <linux/sunrpc/bc_xprt.h>
 #include <linux/nsproxy.h>
@@ -283,116 +284,6 @@ void nfs_put_client(struct nfs_client *clp)
 }
 EXPORT_SYMBOL_GPL(nfs_put_client);
 
-#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
-/*
- * Test if two ip6 socket addresses refer to the same socket by
- * comparing relevant fields. The padding bytes specifically, are not
- * compared. sin6_flowinfo is not compared because it only affects QoS
- * and sin6_scope_id is only compared if the address is "link local"
- * because "link local" addresses need only be unique to a specific
- * link. Conversely, ordinary unicast addresses might have different
- * sin6_scope_id.
- *
- * The caller should ensure both socket addresses are AF_INET6.
- */
-static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
-				      const struct sockaddr *sa2)
-{
-	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
-	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
-
-	if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
-		return 0;
-	else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		return sin1->sin6_scope_id == sin2->sin6_scope_id;
-
-	return 1;
-}
-#else	/* !defined(CONFIG_IPV6) && !defined(CONFIG_IPV6_MODULE) */
-static int nfs_sockaddr_match_ipaddr6(const struct sockaddr *sa1,
-				      const struct sockaddr *sa2)
-{
-	return 0;
-}
-#endif
-
-/*
- * Test if two ip4 socket addresses refer to the same socket, by
- * comparing relevant fields. The padding bytes specifically, are
- * not compared.
- *
- * The caller should ensure both socket addresses are AF_INET.
- */
-static int nfs_sockaddr_match_ipaddr4(const struct sockaddr *sa1,
-				      const struct sockaddr *sa2)
-{
-	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
-	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
-
-	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
-}
-
-static int nfs_sockaddr_cmp_ip6(const struct sockaddr *sa1,
-				const struct sockaddr *sa2)
-{
-	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sa1;
-	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sa2;
-
-	return nfs_sockaddr_match_ipaddr6(sa1, sa2) &&
-		(sin1->sin6_port == sin2->sin6_port);
-}
-
-static int nfs_sockaddr_cmp_ip4(const struct sockaddr *sa1,
-				const struct sockaddr *sa2)
-{
-	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sa1;
-	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sa2;
-
-	return nfs_sockaddr_match_ipaddr4(sa1, sa2) &&
-		(sin1->sin_port == sin2->sin_port);
-}
-
-#if defined(CONFIG_NFS_V4_1)
-/*
- * Test if two socket addresses represent the same actual socket,
- * by comparing (only) relevant fields, excluding the port number.
- */
-int nfs_sockaddr_match_ipaddr(const struct sockaddr *sa1,
-			      const struct sockaddr *sa2)
-{
-	if (sa1->sa_family != sa2->sa_family)
-		return 0;
-
-	switch (sa1->sa_family) {
-	case AF_INET:
-		return nfs_sockaddr_match_ipaddr4(sa1, sa2);
-	case AF_INET6:
-		return nfs_sockaddr_match_ipaddr6(sa1, sa2);
-	}
-	return 0;
-}
-EXPORT_SYMBOL_GPL(nfs_sockaddr_match_ipaddr);
-#endif /* CONFIG_NFS_V4_1 */
-
-/*
- * Test if two socket addresses represent the same actual socket,
- * by comparing (only) relevant fields, including the port number.
- */
-static int nfs_sockaddr_cmp(const struct sockaddr *sa1,
-			    const struct sockaddr *sa2)
-{
-	if (sa1->sa_family != sa2->sa_family)
-		return 0;
-
-	switch (sa1->sa_family) {
-	case AF_INET:
-		return nfs_sockaddr_cmp_ip4(sa1, sa2);
-	case AF_INET6:
-		return nfs_sockaddr_cmp_ip6(sa1, sa2);
-	}
-	return 0;
-}
-
 /*
  * Find an nfs_client on the list that matches the initialisation data
  * that is supplied.
@@ -419,7 +310,7 @@ static struct nfs_client *nfs_match_client(const struct nfs_client_initdata *dat
 		if (clp->cl_minorversion != data->minorversion)
 			continue;
 		/* Match the full socket address */
-		if (!nfs_sockaddr_cmp(sap, clap))
+		if (!sockaddr_equal_strict(sap, clap))
 			continue;
 
 		atomic_inc(&clp->cl_count);
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index 90dce91..383b97a 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -552,7 +552,7 @@ static bool nfs4_cb_match_client(const struct sockaddr *addr,
 		return false;
 
 	/* Match only the IP address, not the port number */
-	if (!nfs_sockaddr_match_ipaddr(addr, clap))
+	if (!sockaddr_equal(addr, clap))
 		return false;
 
 	return true;
diff --git a/fs/nfs/nfs4filelayoutdev.c b/fs/nfs/nfs4filelayoutdev.c
index 95604f6..955494cb 100644
--- a/fs/nfs/nfs4filelayoutdev.c
+++ b/fs/nfs/nfs4filelayoutdev.c
@@ -32,6 +32,7 @@
 #include <linux/vmalloc.h>
 #include <linux/module.h>
 #include <linux/sunrpc/addr.h>
+#include <net/inet_addr.h>
 
 #include "internal.h"
 #include "nfs4session.h"
@@ -74,44 +75,14 @@ print_ds(struct nfs4_pnfs_ds *ds)
 static bool
 same_sockaddr(struct sockaddr *addr1, struct sockaddr *addr2)
 {
-	struct sockaddr_in *a, *b;
-	struct sockaddr_in6 *a6, *b6;
-
-	if (addr1->sa_family != addr2->sa_family)
-		return false;
-
-	switch (addr1->sa_family) {
-	case AF_INET:
-		a = (struct sockaddr_in *)addr1;
-		b = (struct sockaddr_in *)addr2;
-
-		if (a->sin_addr.s_addr == b->sin_addr.s_addr &&
-		    a->sin_port == b->sin_port)
-			return true;
-		break;
-
-	case AF_INET6:
-		a6 = (struct sockaddr_in6 *)addr1;
-		b6 = (struct sockaddr_in6 *)addr2;
-
-		/* LINKLOCAL addresses must have matching scope_id */
-		if (ipv6_addr_scope(&a6->sin6_addr) ==
-		    IPV6_ADDR_SCOPE_LINKLOCAL &&
-		    a6->sin6_scope_id != b6->sin6_scope_id)
-			return false;
-
-		if (ipv6_addr_equal(&a6->sin6_addr, &b6->sin6_addr) &&
-		    a6->sin6_port == b6->sin6_port)
-			return true;
-		break;
-
-	default:
+	if (addr1->sa_family != AF_INET && addr1->sa_family != AF_INET6) {
 		dprintk("%s: unhandled address family: %u\n",
 			__func__, addr1->sa_family);
 		return false;
 	}
 
-	return false;
+	return inet_addr_equal_strict((union inet_addr *)addr1,
+				      (union inet_addr *)addr2);
 }
 
 static bool
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index ac7c359..0744abb 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -49,6 +49,7 @@
 #include <linux/in6.h>
 #include <linux/slab.h>
 #include <net/ipv6.h>
+#include <net/inet_addr.h>
 #include <linux/netdevice.h>
 #include <linux/nfs_xdr.h>
 #include <linux/magic.h>
@@ -2335,34 +2336,8 @@ static int nfs_compare_super_address(struct nfs_server *server1,
 
 	sap1 = (struct sockaddr *)&server1->nfs_client->cl_addr;
 	sap2 = (struct sockaddr *)&server2->nfs_client->cl_addr;
-
-	if (sap1->sa_family != sap2->sa_family)
-		return 0;
-
-	switch (sap1->sa_family) {
-	case AF_INET: {
-		struct sockaddr_in *sin1 = (struct sockaddr_in *)sap1;
-		struct sockaddr_in *sin2 = (struct sockaddr_in *)sap2;
-		if (sin1->sin_addr.s_addr != sin2->sin_addr.s_addr)
-			return 0;
-		if (sin1->sin_port != sin2->sin_port)
-			return 0;
-		break;
-	}
-	case AF_INET6: {
-		struct sockaddr_in6 *sin1 = (struct sockaddr_in6 *)sap1;
-		struct sockaddr_in6 *sin2 = (struct sockaddr_in6 *)sap2;
-		if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
-			return 0;
-		if (sin1->sin6_port != sin2->sin6_port)
-			return 0;
-		break;
-	}
-	default:
-		return 0;
-	}
-
-	return 1;
+	return inet_addr_equal_strict((union inet_addr *)sap1,
+				      (union inet_addr *)sap2);
 }
 
 static int nfs_compare_super(struct super_block *sb, void *data)
diff --git a/include/net/inet_addr.h b/include/net/inet_addr.h
index 44179c8..f317f0f 100644
--- a/include/net/inet_addr.h
+++ b/include/net/inet_addr.h
@@ -122,6 +122,7 @@ void inet_addr_set_port(union inet_addr *sap,
 }
 
 bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b);
+bool inet_addr_equal_strict(const union inet_addr *a, const union inet_addr *b);
 int simple_inet_pton(const char *str, union inet_addr *addr);
 
 static inline bool sockaddr_equal(const struct sockaddr *sap1,
@@ -131,6 +132,13 @@ static inline bool sockaddr_equal(const struct sockaddr *sap1,
 			       (const union inet_addr *)sap2);
 }
 
+static inline int sockaddr_equal_strict(const struct sockaddr *sa1,
+					const struct sockaddr *sa2)
+{
+	return inet_addr_equal_strict((union inet_addr *)sa1,
+				      (union inet_addr *)sa2);
+}
+
 static inline bool sockaddr_copy(struct sockaddr *dst,
 				 const struct sockaddr *src)
 {
diff --git a/net/core/utils.c b/net/core/utils.c
index 837bb18..489bc8d 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -380,6 +380,8 @@ bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
 {
 	if (a->sa.sa_family != b->sa.sa_family)
 		return false;
+	if (a->sa.sa_family == AF_UNSPEC)
+		return true;
 	else if (a->sa.sa_family == AF_INET6) {
 		if (!ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr))
 			return false;
@@ -399,3 +401,24 @@ bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
 }
 #endif
 EXPORT_SYMBOL(inet_addr_equal);
+
+/*
+ * Unlike inet_addr_equal(), this function compares ->sin_port too.
+ */
+bool inet_addr_equal_strict(const union inet_addr *a, const union inet_addr *b)
+{
+	if (inet_addr_equal(a, b)) {
+		switch (a->sa.sa_family) {
+#if IS_ENABLED(CONFIG_IPV6)
+		case AF_INET6:
+			return a->sin6.sin6_port == b->sin6.sin6_port;
+#endif
+		case AF_INET:
+			return a->sin.sin_port == b->sin.sin_port;
+		default:
+			return true;
+		}
+	} else
+		return false;
+}
+EXPORT_SYMBOL(inet_addr_equal_strict);
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 9/9] selinux: use generic union inet_addr
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, James Morris, Stephen Smalley, Eric Paris,
	Paul Moore, linux-kernel, linux-security-module, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

selinux has some similar definition like union inet_addr,
it can re-use the generic union inet_addr too.

Cc: James Morris <james.l.morris@oracle.com>
Cc: Stephen Smalley <sds@tycho.nsa.gov>
Cc: Eric Paris <eparis@parisplace.org>
Cc: Paul Moore <pmoore@redhat.com>
Cc: linux-kernel@vger.kernel.org
Cc: linux-security-module@vger.kernel.org
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 include/linux/lsm_audit.h          |   19 +-----
 security/lsm_audit.c               |   58 ++++++++--------
 security/selinux/hooks.c           |  130 +++++++++++++++++-------------------
 security/selinux/include/netnode.h |    4 +-
 security/selinux/include/objsec.h  |    7 +--
 security/selinux/netnode.c         |  102 ++++++++--------------------
 security/smack/smack_lsm.c         |   19 +++---
 7 files changed, 138 insertions(+), 201 deletions(-)

diff --git a/include/linux/lsm_audit.h b/include/linux/lsm_audit.h
index 1cc89e9..48cab1e 100644
--- a/include/linux/lsm_audit.h
+++ b/include/linux/lsm_audit.h
@@ -21,23 +21,13 @@
 #include <linux/path.h>
 #include <linux/key.h>
 #include <linux/skbuff.h>
+#include <net/inet_addr.h>
 
 struct lsm_network_audit {
 	int netif;
 	struct sock *sk;
-	u16 family;
-	__be16 dport;
-	__be16 sport;
-	union {
-		struct {
-			__be32 daddr;
-			__be32 saddr;
-		} v4;
-		struct {
-			struct in6_addr daddr;
-			struct in6_addr saddr;
-		} v6;
-	} fam;
+	union inet_addr saddr;
+	union inet_addr daddr;
 };
 
 /* Auxiliary data to use in generating the audit record. */
@@ -83,9 +73,6 @@ struct common_audit_data {
 	}; /* per LSM data pointer union */
 };
 
-#define v4info fam.v4
-#define v6info fam.v6
-
 int ipv4_skb_to_auditdata(struct sk_buff *skb,
 		struct common_audit_data *ad, u8 *proto);
 
diff --git a/security/lsm_audit.c b/security/lsm_audit.c
index 8d8d97d..244c2a1 100644
--- a/security/lsm_audit.c
+++ b/security/lsm_audit.c
@@ -49,8 +49,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
 	if (ih == NULL)
 		return -EINVAL;
 
-	ad->u.net->v4info.saddr = ih->saddr;
-	ad->u.net->v4info.daddr = ih->daddr;
+	ad->u.net->saddr.sin.sin_addr.s_addr = ih->saddr;
+	ad->u.net->daddr.sin.sin_addr.s_addr = ih->daddr;
 
 	if (proto)
 		*proto = ih->protocol;
@@ -64,8 +64,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
 		if (th == NULL)
 			break;
 
-		ad->u.net->sport = th->source;
-		ad->u.net->dport = th->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(th->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(th->dest));
 		break;
 	}
 	case IPPROTO_UDP: {
@@ -73,8 +73,8 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
 		if (uh == NULL)
 			break;
 
-		ad->u.net->sport = uh->source;
-		ad->u.net->dport = uh->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(uh->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(uh->dest));
 		break;
 	}
 	case IPPROTO_DCCP: {
@@ -82,16 +82,16 @@ int ipv4_skb_to_auditdata(struct sk_buff *skb,
 		if (dh == NULL)
 			break;
 
-		ad->u.net->sport = dh->dccph_sport;
-		ad->u.net->dport = dh->dccph_dport;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(dh->dccph_sport));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(dh->dccph_dport));
 		break;
 	}
 	case IPPROTO_SCTP: {
 		struct sctphdr *sh = sctp_hdr(skb);
 		if (sh == NULL)
 			break;
-		ad->u.net->sport = sh->source;
-		ad->u.net->dport = sh->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(sh->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(sh->dest));
 		break;
 	}
 	default:
@@ -119,8 +119,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
 	ip6 = ipv6_hdr(skb);
 	if (ip6 == NULL)
 		return -EINVAL;
-	ad->u.net->v6info.saddr = ip6->saddr;
-	ad->u.net->v6info.daddr = ip6->daddr;
+	ad->u.net->saddr.sin6.sin6_addr = ip6->saddr;
+	ad->u.net->daddr.sin6.sin6_addr = ip6->daddr;
 	ret = 0;
 	/* IPv6 can have several extension header before the Transport header
 	 * skip them */
@@ -140,8 +140,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
 		if (th == NULL)
 			break;
 
-		ad->u.net->sport = th->source;
-		ad->u.net->dport = th->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(th->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(th->dest));
 		break;
 	}
 	case IPPROTO_UDP: {
@@ -151,8 +151,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
 		if (uh == NULL)
 			break;
 
-		ad->u.net->sport = uh->source;
-		ad->u.net->dport = uh->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(uh->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(uh->dest));
 		break;
 	}
 	case IPPROTO_DCCP: {
@@ -162,8 +162,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
 		if (dh == NULL)
 			break;
 
-		ad->u.net->sport = dh->dccph_sport;
-		ad->u.net->dport = dh->dccph_dport;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(dh->dccph_sport));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(dh->dccph_dport));
 		break;
 	}
 	case IPPROTO_SCTP: {
@@ -172,8 +172,8 @@ int ipv6_skb_to_auditdata(struct sk_buff *skb,
 		sh = skb_header_pointer(skb, offset, sizeof(_sctph), &_sctph);
 		if (sh == NULL)
 			break;
-		ad->u.net->sport = sh->source;
-		ad->u.net->dport = sh->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(sh->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(sh->dest));
 		break;
 	}
 	default:
@@ -333,21 +333,21 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 			}
 		}
 
-		switch (a->u.net->family) {
+		switch (a->u.net->saddr.sa.sa_family) {
 		case AF_INET:
-			print_ipv4_addr(ab, a->u.net->v4info.saddr,
-					a->u.net->sport,
+			print_ipv4_addr(ab, a->u.net->saddr.sin.sin_addr.s_addr,
+					a->u.net->saddr.sin.sin_port,
 					"saddr", "src");
-			print_ipv4_addr(ab, a->u.net->v4info.daddr,
-					a->u.net->dport,
+			print_ipv4_addr(ab, a->u.net->daddr.sin.sin_addr.s_addr,
+					a->u.net->daddr.sin.sin_port,
 					"daddr", "dest");
 			break;
 		case AF_INET6:
-			print_ipv6_addr(ab, &a->u.net->v6info.saddr,
-					a->u.net->sport,
+			print_ipv6_addr(ab, &a->u.net->saddr.sin6.sin6_addr,
+					a->u.net->saddr.sin.sin_port,
 					"saddr", "src");
-			print_ipv6_addr(ab, &a->u.net->v6info.daddr,
-					a->u.net->dport,
+			print_ipv6_addr(ab, &a->u.net->daddr.sin6.sin6_addr,
+					a->u.net->daddr.sin.sin_port,
 					"daddr", "dest");
 			break;
 		}
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index c956390..f9959c0 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -3595,8 +3595,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
 	if (ihlen < sizeof(_iph))
 		goto out;
 
-	ad->u.net->v4info.saddr = ih->saddr;
-	ad->u.net->v4info.daddr = ih->daddr;
+	ad->u.net->saddr.sin.sin_addr.s_addr = ih->saddr;
+	ad->u.net->daddr.sin.sin_addr.s_addr = ih->daddr;
 	ret = 0;
 
 	if (proto)
@@ -3614,8 +3614,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
 		if (th == NULL)
 			break;
 
-		ad->u.net->sport = th->source;
-		ad->u.net->dport = th->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(th->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(th->dest));
 		break;
 	}
 
@@ -3630,8 +3630,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
 		if (uh == NULL)
 			break;
 
-		ad->u.net->sport = uh->source;
-		ad->u.net->dport = uh->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(uh->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(uh->dest));
 		break;
 	}
 
@@ -3646,8 +3646,8 @@ static int selinux_parse_skb_ipv4(struct sk_buff *skb,
 		if (dh == NULL)
 			break;
 
-		ad->u.net->sport = dh->dccph_sport;
-		ad->u.net->dport = dh->dccph_dport;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(dh->dccph_sport));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(dh->dccph_dport));
 		break;
 	}
 
@@ -3674,8 +3674,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
 	if (ip6 == NULL)
 		goto out;
 
-	ad->u.net->v6info.saddr = ip6->saddr;
-	ad->u.net->v6info.daddr = ip6->daddr;
+	ad->u.net->saddr.sin6.sin6_addr = ip6->saddr;
+	ad->u.net->daddr.sin6.sin6_addr = ip6->daddr;
 	ret = 0;
 
 	nexthdr = ip6->nexthdr;
@@ -3695,8 +3695,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
 		if (th == NULL)
 			break;
 
-		ad->u.net->sport = th->source;
-		ad->u.net->dport = th->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(th->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(th->dest));
 		break;
 	}
 
@@ -3707,8 +3707,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
 		if (uh == NULL)
 			break;
 
-		ad->u.net->sport = uh->source;
-		ad->u.net->dport = uh->dest;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(uh->source));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(uh->dest));
 		break;
 	}
 
@@ -3719,8 +3719,8 @@ static int selinux_parse_skb_ipv6(struct sk_buff *skb,
 		if (dh == NULL)
 			break;
 
-		ad->u.net->sport = dh->dccph_sport;
-		ad->u.net->dport = dh->dccph_dport;
+		inet_addr_set_port(&ad->u.net->saddr, ntohs(dh->dccph_sport));
+		inet_addr_set_port(&ad->u.net->daddr, ntohs(dh->dccph_dport));
 		break;
 	}
 
@@ -3735,18 +3735,17 @@ out:
 #endif /* IPV6 */
 
 static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
-			     char **_addrp, int src, u8 *proto)
+			     union inet_addr **_addrp, int src, u8 *proto)
 {
-	char *addrp;
+	union inet_addr *addrp;
 	int ret;
+	sa_family_t family = src ? ad->u.net->saddr.sa.sa_family : ad->u.net->daddr.sa.sa_family;
 
-	switch (ad->u.net->family) {
+	switch (family) {
 	case PF_INET:
 		ret = selinux_parse_skb_ipv4(skb, ad, proto);
 		if (ret)
 			goto parse_error;
-		addrp = (char *)(src ? &ad->u.net->v4info.saddr :
-				       &ad->u.net->v4info.daddr);
 		goto okay;
 
 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
@@ -3754,13 +3753,11 @@ static int selinux_parse_skb(struct sk_buff *skb, struct common_audit_data *ad,
 		ret = selinux_parse_skb_ipv6(skb, ad, proto);
 		if (ret)
 			goto parse_error;
-		addrp = (char *)(src ? &ad->u.net->v6info.saddr :
-				       &ad->u.net->v6info.daddr);
 		goto okay;
 #endif	/* IPV6 */
 	default:
 		addrp = NULL;
-		goto okay;
+		goto save;
 	}
 
 parse_error:
@@ -3770,6 +3767,8 @@ parse_error:
 	return ret;
 
 okay:
+	addrp = src ? &ad->u.net->saddr : &ad->u.net->daddr;
+save:
 	if (_addrp)
 		*_addrp = addrp;
 	return 0;
@@ -3912,25 +3911,15 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 	 */
 	family = sk->sk_family;
 	if (family == PF_INET || family == PF_INET6) {
-		char *addrp;
+		union inet_addr *addrp = (union inet_addr *)address;
 		struct sk_security_struct *sksec = sk->sk_security;
 		struct common_audit_data ad;
 		struct lsm_network_audit net = {0,};
-		struct sockaddr_in *addr4 = NULL;
-		struct sockaddr_in6 *addr6 = NULL;
 		unsigned short snum;
 		u32 sid, node_perm;
 
-		if (family == PF_INET) {
-			addr4 = (struct sockaddr_in *)address;
-			snum = ntohs(addr4->sin_port);
-			addrp = (char *)&addr4->sin_addr.s_addr;
-		} else {
-			addr6 = (struct sockaddr_in6 *)address;
-			snum = ntohs(addr6->sin6_port);
-			addrp = (char *)&addr6->sin6_addr.s6_addr;
-		}
-
+		addrp->sa.sa_family = family;
+		snum = inet_addr_get_port(addrp);
 		if (snum) {
 			int low, high;
 
@@ -3943,8 +3932,9 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 					goto out;
 				ad.type = LSM_AUDIT_DATA_NET;
 				ad.u.net = &net;
-				ad.u.net->sport = htons(snum);
-				ad.u.net->family = family;
+				inet_addr_set_port(&ad.u.net->saddr, snum);
+				ad.u.net->saddr.sa.sa_family = family;
+				ad.u.net->daddr.sa.sa_family = family;
 				err = avc_has_perm(sksec->sid, sid,
 						   sksec->sclass,
 						   SOCKET__NAME_BIND, &ad);
@@ -3971,19 +3961,17 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
 			break;
 		}
 
-		err = sel_netnode_sid(addrp, family, &sid);
+		err = sel_netnode_sid(addrp, &sid);
 		if (err)
 			goto out;
 
 		ad.type = LSM_AUDIT_DATA_NET;
 		ad.u.net = &net;
-		ad.u.net->sport = htons(snum);
-		ad.u.net->family = family;
+		inet_addr_set_port(&ad.u.net->saddr, snum);
+		ad.u.net->saddr.sa.sa_family = family;
+		ad.u.net->daddr.sa.sa_family = family;
 
-		if (family == PF_INET)
-			ad.u.net->v4info.saddr = addr4->sin_addr.s_addr;
-		else
-			ad.u.net->v6info.saddr = addr6->sin6_addr;
+		ad.u.net->saddr = *addrp;
 
 		err = avc_has_perm(sksec->sid, sid,
 				   sksec->sclass, node_perm, &ad);
@@ -4011,22 +3999,18 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
 	    sksec->sclass == SECCLASS_DCCP_SOCKET) {
 		struct common_audit_data ad;
 		struct lsm_network_audit net = {0,};
-		struct sockaddr_in *addr4 = NULL;
-		struct sockaddr_in6 *addr6 = NULL;
+		union inet_addr *addrp = (union inet_addr *)address;
 		unsigned short snum;
 		u32 sid, perm;
 
 		if (sk->sk_family == PF_INET) {
-			addr4 = (struct sockaddr_in *)address;
 			if (addrlen < sizeof(struct sockaddr_in))
 				return -EINVAL;
-			snum = ntohs(addr4->sin_port);
 		} else {
-			addr6 = (struct sockaddr_in6 *)address;
 			if (addrlen < SIN6_LEN_RFC2133)
 				return -EINVAL;
-			snum = ntohs(addr6->sin6_port);
 		}
+		snum = inet_addr_get_port(addrp);
 
 		err = sel_netport_sid(sk->sk_protocol, snum, &sid);
 		if (err)
@@ -4037,8 +4021,9 @@ static int selinux_socket_connect(struct socket *sock, struct sockaddr *address,
 
 		ad.type = LSM_AUDIT_DATA_NET;
 		ad.u.net = &net;
-		ad.u.net->dport = htons(snum);
-		ad.u.net->family = sk->sk_family;
+		inet_addr_set_port(&ad.u.net->daddr, snum);
+		ad.u.net->saddr.sa.sa_family = sk->sk_family;
+		ad.u.net->daddr.sa.sa_family = sk->sk_family;
 		err = avc_has_perm(sksec->sid, sid, sksec->sclass, perm, &ad);
 		if (err)
 			goto out;
@@ -4169,7 +4154,7 @@ static int selinux_socket_unix_may_send(struct socket *sock,
 			    &ad);
 }
 
-static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
+static int selinux_inet_sys_rcv_skb(int ifindex, union inet_addr *addrp,
 				    u32 peer_sid,
 				    struct common_audit_data *ad)
 {
@@ -4185,7 +4170,7 @@ static int selinux_inet_sys_rcv_skb(int ifindex, char *addrp, u16 family,
 	if (err)
 		return err;
 
-	err = sel_netnode_sid(addrp, family, &node_sid);
+	err = sel_netnode_sid(addrp, &node_sid);
 	if (err)
 		return err;
 	return avc_has_perm(peer_sid, node_sid,
@@ -4200,12 +4185,13 @@ static int selinux_sock_rcv_skb_compat(struct sock *sk, struct sk_buff *skb,
 	u32 sk_sid = sksec->sid;
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
-	char *addrp;
+	union inet_addr *addrp;
 
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->netif = skb->skb_iif;
-	ad.u.net->family = family;
+	ad.u.net->saddr.sa.sa_family = family;
+	ad.u.net->daddr.sa.sa_family = family;
 	err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
 	if (err)
 		return err;
@@ -4233,7 +4219,7 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	u32 sk_sid = sksec->sid;
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
-	char *addrp;
+	union inet_addr *addrp;
 	u8 secmark_active;
 	u8 peerlbl_active;
 
@@ -4259,7 +4245,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->netif = skb->skb_iif;
-	ad.u.net->family = family;
+	ad.u.net->saddr.sa.sa_family = family;
+	ad.u.net->daddr.sa.sa_family = family;
 	err = selinux_parse_skb(skb, &ad, &addrp, 1, NULL);
 	if (err)
 		return err;
@@ -4270,7 +4257,8 @@ static int selinux_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 		err = selinux_skb_peerlbl_sid(skb, family, &peer_sid);
 		if (err)
 			return err;
-		err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp, family,
+		addrp->sa.sa_family = family;
+		err = selinux_inet_sys_rcv_skb(skb->skb_iif, addrp,
 					       peer_sid, &ad);
 		if (err) {
 			selinux_netlbl_err(skb, err, 0);
@@ -4621,7 +4609,7 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
 				       u16 family)
 {
 	int err;
-	char *addrp;
+	union inet_addr *addrp;
 	u32 peer_sid;
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
@@ -4644,12 +4632,14 @@ static unsigned int selinux_ip_forward(struct sk_buff *skb, int ifindex,
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->netif = ifindex;
-	ad.u.net->family = family;
+	ad.u.net->saddr.sa.sa_family = family;
+	ad.u.net->daddr.sa.sa_family = family;
 	if (selinux_parse_skb(skb, &ad, &addrp, 1, NULL) != 0)
 		return NF_DROP;
 
 	if (peerlbl_active) {
-		err = selinux_inet_sys_rcv_skb(ifindex, addrp, family,
+		addrp->sa.sa_family = family;
+		err = selinux_inet_sys_rcv_skb(ifindex, addrp,
 					       peer_sid, &ad);
 		if (err) {
 			selinux_netlbl_err(skb, err, 1);
@@ -4732,7 +4722,7 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 	struct sk_security_struct *sksec;
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
-	char *addrp;
+	union inet_addr *addrp;
 	u8 proto;
 
 	if (sk == NULL)
@@ -4742,7 +4732,8 @@ static unsigned int selinux_ip_postroute_compat(struct sk_buff *skb,
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->netif = ifindex;
-	ad.u.net->family = family;
+	ad.u.net->saddr.sa.sa_family = family;
+	ad.u.net->daddr.sa.sa_family = family;
 	if (selinux_parse_skb(skb, &ad, &addrp, 0, &proto))
 		return NF_DROP;
 
@@ -4765,7 +4756,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 	struct sock *sk;
 	struct common_audit_data ad;
 	struct lsm_network_audit net = {0,};
-	char *addrp;
+	union inet_addr *addrp;
 	u8 secmark_active;
 	u8 peerlbl_active;
 
@@ -4813,7 +4804,8 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 	ad.type = LSM_AUDIT_DATA_NET;
 	ad.u.net = &net;
 	ad.u.net->netif = ifindex;
-	ad.u.net->family = family;
+	ad.u.net->saddr.sa.sa_family = family;
+	ad.u.net->daddr.sa.sa_family = family;
 	if (selinux_parse_skb(skb, &ad, &addrp, 0, NULL))
 		return NF_DROP;
 
@@ -4832,7 +4824,7 @@ static unsigned int selinux_ip_postroute(struct sk_buff *skb, int ifindex,
 				 SECCLASS_NETIF, NETIF__EGRESS, &ad))
 			return NF_DROP_ERR(-ECONNREFUSED);
 
-		if (sel_netnode_sid(addrp, family, &node_sid))
+		if (sel_netnode_sid(addrp, &node_sid))
 			return NF_DROP;
 		if (avc_has_perm(peer_sid, node_sid,
 				 SECCLASS_NODE, NODE__SENDTO, &ad))
diff --git a/security/selinux/include/netnode.h b/security/selinux/include/netnode.h
index df7a5ed..f32c909 100644
--- a/security/selinux/include/netnode.h
+++ b/security/selinux/include/netnode.h
@@ -27,6 +27,8 @@
 #ifndef _SELINUX_NETNODE_H
 #define _SELINUX_NETNODE_H
 
-int sel_netnode_sid(void *addr, u16 family, u32 *sid);
+#include <net/inet_addr.h>
+
+int sel_netnode_sid(union inet_addr *addr, u32 *sid);
 
 #endif
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index aa47bca..a46caaf 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -24,6 +24,7 @@
 #include <linux/binfmts.h>
 #include <linux/in.h>
 #include <linux/spinlock.h>
+#include <net/inet_addr.h>
 #include "flask.h"
 #include "avc.h"
 
@@ -80,12 +81,8 @@ struct netif_security_struct {
 };
 
 struct netnode_security_struct {
-	union {
-		__be32 ipv4;		/* IPv4 node address */
-		struct in6_addr ipv6;	/* IPv6 node address */
-	} addr;
+	union inet_addr addr;
 	u32 sid;			/* SID for this node */
-	u16 family;			/* address family */
 };
 
 struct netport_security_struct {
diff --git a/security/selinux/netnode.c b/security/selinux/netnode.c
index c5454c0..713f14e 100644
--- a/security/selinux/netnode.c
+++ b/security/selinux/netnode.c
@@ -68,79 +68,49 @@ static LIST_HEAD(sel_netnode_list);
 static DEFINE_SPINLOCK(sel_netnode_lock);
 static struct sel_netnode_bkt sel_netnode_hash[SEL_NETNODE_HASH_SIZE];
 
-/**
- * sel_netnode_hashfn_ipv4 - IPv4 hashing function for the node table
- * @addr: IPv4 address
- *
- * Description:
- * This is the IPv4 hashing function for the node interface table, it returns
- * the bucket number for the given IP address.
- *
- */
-static unsigned int sel_netnode_hashfn_ipv4(__be32 addr)
-{
-	/* at some point we should determine if the mismatch in byte order
-	 * affects the hash function dramatically */
-	return (addr & (SEL_NETNODE_HASH_SIZE - 1));
-}
 
 /**
- * sel_netnode_hashfn_ipv6 - IPv6 hashing function for the node table
- * @addr: IPv6 address
+ * sel_netnode_hashfn - IPv4/IPv6 hashing function for the node table
+ * @addr: generic IP address
  *
  * Description:
- * This is the IPv6 hashing function for the node interface table, it returns
+ * This is the IP hashing function for the node interface table, it returns
  * the bucket number for the given IP address.
  *
  */
-static unsigned int sel_netnode_hashfn_ipv6(const struct in6_addr *addr)
+static unsigned int sel_netnode_hashfn(const union inet_addr *addr)
 {
-	/* just hash the least significant 32 bits to keep things fast (they
-	 * are the most likely to be different anyway), we can revisit this
-	 * later if needed */
-	return (addr->s6_addr32[3] & (SEL_NETNODE_HASH_SIZE - 1));
+	if (addr->sa.sa_family == PF_INET)
+		/* at some point we should determine if the mismatch in byte order
+		 * affects the hash function dramatically */
+		return (addr->sin.sin_addr.s_addr & (SEL_NETNODE_HASH_SIZE - 1));
+	else if (addr->sa.sa_family == PF_INET6)
+		/* just hash the least significant 32 bits to keep things fast (they
+		 * are the most likely to be different anyway), we can revisit this
+		 * later if needed */
+		return (addr->sin6.sin6_addr.s6_addr32[3] & (SEL_NETNODE_HASH_SIZE - 1));
+	else
+		BUG();
 }
 
 /**
  * sel_netnode_find - Search for a node record
  * @addr: IP address
- * @family: address family
  *
  * Description:
  * Search the network node table and return the record matching @addr.  If an
  * entry can not be found in the table return NULL.
  *
  */
-static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
+static struct sel_netnode *sel_netnode_find(const union inet_addr *addr)
 {
 	unsigned int idx;
 	struct sel_netnode *node;
 
-	switch (family) {
-	case PF_INET:
-		idx = sel_netnode_hashfn_ipv4(*(__be32 *)addr);
-		break;
-	case PF_INET6:
-		idx = sel_netnode_hashfn_ipv6(addr);
-		break;
-	default:
-		BUG();
-		return NULL;
-	}
-
+	idx = sel_netnode_hashfn(addr);
 	list_for_each_entry_rcu(node, &sel_netnode_hash[idx].list, list)
-		if (node->nsec.family == family)
-			switch (family) {
-			case PF_INET:
-				if (node->nsec.addr.ipv4 == *(__be32 *)addr)
-					return node;
-				break;
-			case PF_INET6:
-				if (ipv6_addr_equal(&node->nsec.addr.ipv6,
-						    addr))
-					return node;
-				break;
-			}
+		if (inet_addr_equal(&node->nsec.addr, addr))
+			return node;
 
 	return NULL;
 }
@@ -156,18 +126,9 @@ static struct sel_netnode *sel_netnode_find(const void *addr, u16 family)
 static void sel_netnode_insert(struct sel_netnode *node)
 {
 	unsigned int idx;
+	union inet_addr *addr = &node->nsec.addr;
 
-	switch (node->nsec.family) {
-	case PF_INET:
-		idx = sel_netnode_hashfn_ipv4(node->nsec.addr.ipv4);
-		break;
-	case PF_INET6:
-		idx = sel_netnode_hashfn_ipv6(&node->nsec.addr.ipv6);
-		break;
-	default:
-		BUG();
-	}
-
+	idx = sel_netnode_hashfn(addr);
 	/* we need to impose a limit on the growth of the hash table so check
 	 * this bucket to make sure it is within the specified bounds */
 	list_add_rcu(&node->list, &sel_netnode_hash[idx].list);
@@ -186,7 +147,6 @@ static void sel_netnode_insert(struct sel_netnode *node)
 /**
  * sel_netnode_sid_slow - Lookup the SID of a network address using the policy
  * @addr: the IP address
- * @family: the address family
  * @sid: node SID
  *
  * Description:
@@ -196,14 +156,14 @@ static void sel_netnode_insert(struct sel_netnode *node)
  * failure.
  *
  */
-static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
+static int sel_netnode_sid_slow(union inet_addr *addr, u32 *sid)
 {
 	int ret = -ENOMEM;
 	struct sel_netnode *node;
 	struct sel_netnode *new = NULL;
 
 	spin_lock_bh(&sel_netnode_lock);
-	node = sel_netnode_find(addr, family);
+	node = sel_netnode_find(addr);
 	if (node != NULL) {
 		*sid = node->nsec.sid;
 		spin_unlock_bh(&sel_netnode_lock);
@@ -212,16 +172,16 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
 	new = kzalloc(sizeof(*new), GFP_ATOMIC);
 	if (new == NULL)
 		goto out;
-	switch (family) {
+	switch (addr->sa.sa_family) {
 	case PF_INET:
 		ret = security_node_sid(PF_INET,
 					addr, sizeof(struct in_addr), sid);
-		new->nsec.addr.ipv4 = *(__be32 *)addr;
+		new->nsec.addr = *addr;
 		break;
 	case PF_INET6:
 		ret = security_node_sid(PF_INET6,
 					addr, sizeof(struct in6_addr), sid);
-		new->nsec.addr.ipv6 = *(struct in6_addr *)addr;
+		new->nsec.addr = *addr;
 		break;
 	default:
 		BUG();
@@ -229,7 +189,6 @@ static int sel_netnode_sid_slow(void *addr, u16 family, u32 *sid)
 	if (ret != 0)
 		goto out;
 
-	new->nsec.family = family;
 	new->nsec.sid = *sid;
 	sel_netnode_insert(new);
 
@@ -246,8 +205,7 @@ out:
 
 /**
  * sel_netnode_sid - Lookup the SID of a network address
- * @addr: the IP address
- * @family: the address family
+ * @addr: the generic IP address
  * @sid: node SID
  *
  * Description:
@@ -258,12 +216,12 @@ out:
  * on failure.
  *
  */
-int sel_netnode_sid(void *addr, u16 family, u32 *sid)
+int sel_netnode_sid(union inet_addr *addr, u32 *sid)
 {
 	struct sel_netnode *node;
 
 	rcu_read_lock();
-	node = sel_netnode_find(addr, family);
+	node = sel_netnode_find(addr);
 	if (node != NULL) {
 		*sid = node->nsec.sid;
 		rcu_read_unlock();
@@ -271,7 +229,7 @@ int sel_netnode_sid(void *addr, u16 family, u32 *sid)
 	}
 	rcu_read_unlock();
 
-	return sel_netnode_sid_slow(addr, family, sid);
+	return sel_netnode_sid_slow(addr, sid);
 }
 
 /**
diff --git a/security/smack/smack_lsm.c b/security/smack/smack_lsm.c
index eefbd10..9a80923 100644
--- a/security/smack/smack_lsm.c
+++ b/security/smack/smack_lsm.c
@@ -1900,9 +1900,7 @@ static int smack_netlabel_send(struct sock *sk, struct sockaddr_in *sap)
 		struct lsm_network_audit net;
 
 		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-		ad.a.u.net->family = sap->sin_family;
-		ad.a.u.net->dport = sap->sin_port;
-		ad.a.u.net->v4info.daddr = sap->sin_addr.s_addr;
+		ad.a.u.net->daddr = (union inet_addr )*sap;
 #endif
 		sk_lbl = SMACK_UNLABELED_SOCKET;
 		skp = ssp->smk_out;
@@ -2055,12 +2053,13 @@ auditout:
 
 #ifdef CONFIG_AUDIT
 	smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-	ad.a.u.net->family = sk->sk_family;
-	ad.a.u.net->dport = port;
+	inet_addr_set_port(&ad.a.u.net->daddr, port);
+	ad.a.u.net->saddr.sa.sa_family = sk->sk_family;
+	ad.a.u.net->daddr.sa.sa_family = sk->sk_family;
 	if (act == SMK_RECEIVING)
-		ad.a.u.net->v6info.saddr = address->sin6_addr;
+		ad.a.u.net->saddr.sin6.sin6_addr = address->sin6_addr;
 	else
-		ad.a.u.net->v6info.daddr = address->sin6_addr;
+		ad.a.u.net->daddr.sin6.sin6_addr = address->sin6_addr;
 #endif
 	return smk_access(skp, object, MAY_WRITE, &ad);
 }
@@ -3202,7 +3201,8 @@ static int smack_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
 
 #ifdef CONFIG_AUDIT
 		smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-		ad.a.u.net->family = sk->sk_family;
+		ad.a.u.net->saddr.sa.sa_family = sk->sk_family;
+		ad.a.u.net->daddr.sa.sa_family = sk->sk_family;
 		ad.a.u.net->netif = skb->skb_iif;
 		ipv4_skb_to_auditdata(skb, &ad.a, NULL);
 #endif
@@ -3384,7 +3384,8 @@ static int smack_inet_conn_request(struct sock *sk, struct sk_buff *skb,
 
 #ifdef CONFIG_AUDIT
 	smk_ad_init_net(&ad, __func__, LSM_AUDIT_DATA_NET, &net);
-	ad.a.u.net->family = family;
+	ad.a.u.net->saddr.sa.sa_family = family;
+	ad.a.u.net->daddr.sa.sa_family = family;
 	ad.a.u.net->netif = skb->skb_iif;
 	ipv4_skb_to_auditdata(skb, &ad.a, NULL);
 #endif
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 0/9] net: introduce generic type and helpers for IP address
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang

From: Cong Wang <amwang@redhat.com>

As IPv6 becomes popular, more and more subsystems begin to support IPv6,
therefore we need a generic IP address type, in case of duplicates.
Also we will also need some helpers to compare, print, check the generic
IP address.

This patchset introduce a new type union inet_addr as a union of IPv4
and IPv6 address, and struct in_addr_gen for inetpeer and bridge mdb,
plus some helper functions that will be used by existing code and
in the future VXLAN module.

However, due to ABI limit, we still can't convert union nf_inet_addr
to union inet_addr.

Signed-off-by: Cong Wang <amwang@redhat.com>

v2 -> v3:
* introduce sockaddr_*() helper functions as well
* split the first patch into two
* rebase on to the latest net-next

v1 -> v2:
* introduce another generic IP address type, struct in_addr_gen
* convert bridge multicast code too
* complete the smack part

RFC -> v1:
* rebase these patches on top of Daniel's
* rename inet_pton() to simple_inet_pton()
* fix the simple_inet_pton() API
* make inet_addr_equal() non-inline
* add two more patches

Cong Wang (9):
  net: introduce generic union inet_addr
  net: rename '%pIS' to '%pIA' for union inet_addr
  net: introduce generic simple_inet_pton()
  inetpeer: use generic struct in_addr_gen
  bridge: use generic struct in_addr_gen
  sunrpc: use generic union inet_addr
  fs: use generic union inet_addr and help functions
  sctp: use generic union inet_addr
  selinux: use generic union inet_addr

 Documentation/printk-formats.txt   |   20 ++--
 drivers/net/netconsole.c           |   22 ++--
 fs/cifs/connect.c                  |   54 ++------
 fs/dlm/lowcomms.c                  |   24 +---
 fs/lockd/clntlock.c                |    2 +-
 fs/lockd/host.c                    |    8 +-
 fs/lockd/mon.c                     |    2 +-
 fs/lockd/svcsubs.c                 |    2 +-
 fs/nfs/client.c                    |  113 +-----------------
 fs/nfs/nfs4client.c                |    2 +-
 fs/nfs/nfs4filelayoutdev.c         |   37 +-----
 fs/nfs/nfs4namespace.c             |    2 +-
 fs/nfs/super.c                     |   37 +-----
 fs/nfsd/nfs4state.c                |    6 +-
 fs/nfsd/nfscache.c                 |    8 +-
 include/linux/lsm_audit.h          |   19 +---
 include/linux/netpoll.h            |    9 +--
 include/linux/sunrpc/addr.h        |  131 +-------------------
 include/net/inet_addr.h            |  160 ++++++++++++++++++++++++
 include/net/inetpeer.h             |   25 +---
 include/net/sctp/sctp.h            |   22 ++--
 include/net/sctp/sm.h              |    4 +-
 include/net/sctp/structs.h         |  132 +++++++++-----------
 lib/vsprintf.c                     |   29 ++---
 net/bridge/br_mdb.c                |   53 ++++----
 net/bridge/br_multicast.c          |   65 ++++------
 net/bridge/br_private.h            |    9 +-
 net/core/netpoll.c                 |   86 +++++--------
 net/core/utils.c                   |   84 +++++++++++++
 net/ipv4/inetpeer.c                |   33 +++--
 net/ipv4/tcp_metrics.c             |   74 +++++-------
 net/sctp/associola.c               |   32 +++---
 net/sctp/bind_addr.c               |   61 +++------
 net/sctp/endpointola.c             |   12 +-
 net/sctp/input.c                   |   56 ++++----
 net/sctp/ipv6.c                    |  240 ++++++++++++++++--------------------
 net/sctp/outqueue.c                |    4 +-
 net/sctp/proc.c                    |   10 +-
 net/sctp/protocol.c                |  204 ++++++++++++-------------------
 net/sctp/sm_make_chunk.c           |   54 ++++----
 net/sctp/sm_sideeffect.c           |    2 +-
 net/sctp/sm_statefuns.c            |   23 +---
 net/sctp/socket.c                  |  130 +++++++++++---------
 net/sctp/transport.c               |   12 +-
 net/sctp/ulpevent.c                |    2 +-
 net/sunrpc/clnt.c                  |    2 +-
 net/sunrpc/rpcb_clnt.c             |    2 +-
 net/sunrpc/xprtrdma/transport.c    |    4 +-
 net/sunrpc/xprtsock.c              |    8 +-
 security/lsm_audit.c               |   58 +++++-----
 security/selinux/hooks.c           |  130 +++++++++----------
 security/selinux/include/netnode.h |    4 +-
 security/selinux/include/objsec.h  |    7 +-
 security/selinux/netnode.c         |  102 +++++-----------
 security/smack/smack_lsm.c         |   19 ++--
 55 files changed, 1063 insertions(+), 1389 deletions(-)
 create mode 100644 include/net/inet_addr.h

-- 
1.7.7.6

^ permalink raw reply

* [Patch net-next v3 1/9] net: introduce generic union inet_addr
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

Introduce a generic IP address type, union inet_addr, so that
subsystems don't have to use their own definitions. Because
netpoll already defines union inet_addr, just move it to global.
Some of the helper functions will be used by VXLAN IPv6 code too.

Signed-off-by: Cong Wang <amwang@redhat.com>
---
 drivers/net/netconsole.c |   20 +++++++++------
 include/linux/netpoll.h  |    9 +------
 include/net/inet_addr.h  |   62 ++++++++++++++++++++++++++++++++++++++++++++++
 net/core/netpoll.c       |   50 +++++++++++++++++++-----------------
 4 files changed, 101 insertions(+), 40 deletions(-)
 create mode 100644 include/net/inet_addr.h

diff --git a/drivers/net/netconsole.c b/drivers/net/netconsole.c
index 4822aaf..e4eac0c 100644
--- a/drivers/net/netconsole.c
+++ b/drivers/net/netconsole.c
@@ -271,17 +271,17 @@ static ssize_t show_remote_port(struct netconsole_target *nt, char *buf)
 static ssize_t show_local_ip(struct netconsole_target *nt, char *buf)
 {
 	if (nt->np.ipv6)
-		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.in6);
+		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.local_ip.sin6.sin6_addr);
 	else
-		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip);
+		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.local_ip.sin.sin_addr.s_addr);
 }
 
 static ssize_t show_remote_ip(struct netconsole_target *nt, char *buf)
 {
 	if (nt->np.ipv6)
-		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.in6);
+		return snprintf(buf, PAGE_SIZE, "%pI6c\n", &nt->np.remote_ip.sin6.sin6_addr);
 	else
-		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip);
+		return snprintf(buf, PAGE_SIZE, "%pI4\n", &nt->np.remote_ip.sin.sin_addr.s_addr);
 }
 
 static ssize_t show_local_mac(struct netconsole_target *nt, char *buf)
@@ -419,17 +419,19 @@ static ssize_t store_local_ip(struct netconsole_target *nt,
 
 	if (strnchr(buf, count, ':')) {
 		const char *end;
-		if (in6_pton(buf, count, nt->np.local_ip.in6.s6_addr, -1, &end) > 0) {
+		if (in6_pton(buf, count, nt->np.local_ip.sin6.sin6_addr.s6_addr, -1, &end) > 0) {
 			if (*end && *end != '\n') {
 				printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end);
 				return -EINVAL;
 			}
+			nt->np.local_ip.sa.sa_family = AF_INET6;
 			nt->np.ipv6 = true;
 		} else
 			return -EINVAL;
 	} else {
 		if (!nt->np.ipv6) {
-			nt->np.local_ip.ip = in_aton(buf);
+			nt->np.local_ip.sin.sin_addr.s_addr = in_aton(buf);
+			nt->np.local_ip.sa.sa_family = AF_INET;
 		} else
 			return -EINVAL;
 	}
@@ -450,17 +452,19 @@ static ssize_t store_remote_ip(struct netconsole_target *nt,
 
 	if (strnchr(buf, count, ':')) {
 		const char *end;
-		if (in6_pton(buf, count, nt->np.remote_ip.in6.s6_addr, -1, &end) > 0) {
+		if (in6_pton(buf, count, nt->np.remote_ip.sin6.sin6_addr.s6_addr, -1, &end) > 0) {
 			if (*end && *end != '\n') {
 				printk(KERN_ERR "netconsole: invalid IPv6 address at: <%c>\n", *end);
 				return -EINVAL;
 			}
+			nt->np.remote_ip.sa.sa_family = AF_INET6;
 			nt->np.ipv6 = true;
 		} else
 			return -EINVAL;
 	} else {
 		if (!nt->np.ipv6) {
-			nt->np.remote_ip.ip = in_aton(buf);
+			nt->np.remote_ip.sin.sin_addr.s_addr = in_aton(buf);
+			nt->np.remote_ip.sa.sa_family = AF_INET;
 		} else
 			return -EINVAL;
 	}
diff --git a/include/linux/netpoll.h b/include/linux/netpoll.h
index f3c7c24..3884834 100644
--- a/include/linux/netpoll.h
+++ b/include/linux/netpoll.h
@@ -11,14 +11,7 @@
 #include <linux/interrupt.h>
 #include <linux/rcupdate.h>
 #include <linux/list.h>
-
-union inet_addr {
-	__u32		all[4];
-	__be32		ip;
-	__be32		ip6[4];
-	struct in_addr	in;
-	struct in6_addr	in6;
-};
+#include <net/inet_addr.h>
 
 struct netpoll {
 	struct net_device *dev;
diff --git a/include/net/inet_addr.h b/include/net/inet_addr.h
new file mode 100644
index 0000000..66a16fe
--- /dev/null
+++ b/include/net/inet_addr.h
@@ -0,0 +1,62 @@
+#ifndef _INET_ADDR_H
+#define _INET_ADDR_H
+
+#include <linux/in.h>
+#include <linux/in6.h>
+#include <linux/socket.h>
+#include <net/addrconf.h>
+
+union inet_addr {
+	struct sockaddr_in sin;
+	struct sockaddr_in6 sin6;
+	struct sockaddr sa;
+};
+
+#if IS_ENABLED(CONFIG_IPV6)
+static inline
+bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
+{
+	if (a->sa.sa_family != b->sa.sa_family)
+		return false;
+	if (a->sa.sa_family == AF_INET6)
+		return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr);
+	else
+		return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
+}
+
+static inline bool inet_addr_any(const union inet_addr *ipa)
+{
+	if (ipa->sa.sa_family == AF_INET6)
+		return ipv6_addr_any(&ipa->sin6.sin6_addr);
+	else
+		return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
+}
+
+static inline bool inet_addr_multicast(const union inet_addr *ipa)
+{
+	if (ipa->sa.sa_family == AF_INET6)
+		return ipv6_addr_is_multicast(&ipa->sin6.sin6_addr);
+	else
+		return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr));
+}
+
+#else /* !CONFIG_IPV6 */
+
+static inline
+bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
+{
+	return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
+}
+
+static inline bool inet_addr_any(const union inet_addr *ipa)
+{
+	return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
+}
+
+static inline bool inet_addr_multicast(const union inet_addr *ipa)
+{
+	return IN_MULTICAST(ntohl(ipa->sin.sin_addr.s_addr));
+}
+#endif
+
+#endif
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 2c637e9..dd38553 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -456,8 +456,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 
 	if (np->ipv6) {
 		udph->check = 0;
-		udph->check = csum_ipv6_magic(&np->local_ip.in6,
-					      &np->remote_ip.in6,
+		udph->check = csum_ipv6_magic(&np->local_ip.sin6.sin6_addr,
+					      &np->remote_ip.sin6.sin6_addr,
 					      udp_len, IPPROTO_UDP,
 					      csum_partial(udph, udp_len, 0));
 		if (udph->check == 0)
@@ -476,16 +476,16 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 		ip6h->payload_len = htons(sizeof(struct udphdr) + len);
 		ip6h->nexthdr = IPPROTO_UDP;
 		ip6h->hop_limit = 32;
-		ip6h->saddr = np->local_ip.in6;
-		ip6h->daddr = np->remote_ip.in6;
+		ip6h->saddr = np->local_ip.sin6.sin6_addr;
+		ip6h->daddr = np->remote_ip.sin6.sin6_addr;
 
 		eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
 		skb_reset_mac_header(skb);
 		skb->protocol = eth->h_proto = htons(ETH_P_IPV6);
 	} else {
 		udph->check = 0;
-		udph->check = csum_tcpudp_magic(np->local_ip.ip,
-						np->remote_ip.ip,
+		udph->check = csum_tcpudp_magic(np->local_ip.sin.sin_addr.s_addr,
+						np->remote_ip.sin.sin_addr.s_addr,
 						udp_len, IPPROTO_UDP,
 						csum_partial(udph, udp_len, 0));
 		if (udph->check == 0)
@@ -504,8 +504,8 @@ void netpoll_send_udp(struct netpoll *np, const char *msg, int len)
 		iph->ttl      = 64;
 		iph->protocol = IPPROTO_UDP;
 		iph->check    = 0;
-		put_unaligned(np->local_ip.ip, &(iph->saddr));
-		put_unaligned(np->remote_ip.ip, &(iph->daddr));
+		put_unaligned(np->local_ip.sin.sin_addr.s_addr, &(iph->saddr));
+		put_unaligned(np->remote_ip.sin.sin_addr.s_addr, &(iph->daddr));
 		iph->check    = ip_fast_csum((unsigned char *)iph, iph->ihl);
 
 		eth = (struct ethhdr *) skb_push(skb, ETH_HLEN);
@@ -589,7 +589,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
 
 		spin_lock_irqsave(&npinfo->rx_lock, flags);
 		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
-			if (tip != np->local_ip.ip)
+			if (tip != np->local_ip.sin.sin_addr.s_addr)
 				continue;
 
 			hlen = LL_RESERVED_SPACE(np->dev);
@@ -677,7 +677,7 @@ static void netpoll_neigh_reply(struct sk_buff *skb, struct netpoll_info *npinfo
 
 		spin_lock_irqsave(&npinfo->rx_lock, flags);
 		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
-			if (!ipv6_addr_equal(daddr, &np->local_ip.in6))
+			if (!ipv6_addr_equal(daddr, &np->local_ip.sin6.sin6_addr))
 				continue;
 
 			hlen = LL_RESERVED_SPACE(np->dev);
@@ -827,9 +827,11 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 		if (checksum_udp(skb, uh, ulen, iph->saddr, iph->daddr))
 			goto out;
 		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
-			if (np->local_ip.ip && np->local_ip.ip != iph->daddr)
+			__be32 daddr = np->local_ip.sin.sin_addr.s_addr;
+			__be32 saddr = np->remote_ip.sin.sin_addr.s_addr;
+			if (daddr && daddr != iph->daddr)
 				continue;
-			if (np->remote_ip.ip && np->remote_ip.ip != iph->saddr)
+			if (saddr && saddr != iph->saddr)
 				continue;
 			if (np->local_port && np->local_port != ntohs(uh->dest))
 				continue;
@@ -865,9 +867,9 @@ int __netpoll_rx(struct sk_buff *skb, struct netpoll_info *npinfo)
 		if (udp6_csum_init(skb, uh, IPPROTO_UDP))
 			goto out;
 		list_for_each_entry_safe(np, tmp, &npinfo->rx_np, rx) {
-			if (!ipv6_addr_equal(&np->local_ip.in6, &ip6h->daddr))
+			if (!ipv6_addr_equal(&np->local_ip.sin6.sin6_addr, &ip6h->daddr))
 				continue;
-			if (!ipv6_addr_equal(&np->remote_ip.in6, &ip6h->saddr))
+			if (!ipv6_addr_equal(&np->remote_ip.sin6.sin6_addr, &ip6h->saddr))
 				continue;
 			if (np->local_port && np->local_port != ntohs(uh->dest))
 				continue;
@@ -899,15 +901,15 @@ void netpoll_print_options(struct netpoll *np)
 {
 	np_info(np, "local port %d\n", np->local_port);
 	if (np->ipv6)
-		np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.in6);
+		np_info(np, "local IPv6 address %pI6c\n", &np->local_ip.sin6.sin6_addr);
 	else
-		np_info(np, "local IPv4 address %pI4\n", &np->local_ip.ip);
+		np_info(np, "local IPv4 address %pI4\n", &np->local_ip.sin.sin_addr.s_addr);
 	np_info(np, "interface '%s'\n", np->dev_name);
 	np_info(np, "remote port %d\n", np->remote_port);
 	if (np->ipv6)
-		np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.in6);
+		np_info(np, "remote IPv6 address %pI6c\n", &np->remote_ip.sin6.sin6_addr);
 	else
-		np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.ip);
+		np_info(np, "remote IPv4 address %pI4\n", &np->remote_ip.sin.sin_addr.s_addr);
 	np_info(np, "remote ethernet address %pM\n", np->remote_mac);
 }
 EXPORT_SYMBOL(netpoll_print_options);
@@ -921,7 +923,7 @@ static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
 		if (!*end)
 			return 0;
 	}
-	if (in6_pton(str, -1, addr->in6.s6_addr, -1, &end) > 0) {
+	if (in6_pton(str, -1, addr->sin6.sin6_addr.s6_addr, -1, &end) > 0) {
 #if IS_ENABLED(CONFIG_IPV6)
 		if (!*end)
 			return 1;
@@ -1140,7 +1142,7 @@ int netpoll_setup(struct netpoll *np)
 		rtnl_lock();
 	}
 
-	if (!np->local_ip.ip) {
+	if (!np->local_ip.sin.sin_addr.s_addr) {
 		if (!np->ipv6) {
 			in_dev = __in_dev_get_rtnl(ndev);
 
@@ -1151,8 +1153,8 @@ int netpoll_setup(struct netpoll *np)
 				goto put;
 			}
 
-			np->local_ip.ip = in_dev->ifa_list->ifa_local;
-			np_info(np, "local IP %pI4\n", &np->local_ip.ip);
+			np->local_ip.sin.sin_addr.s_addr = in_dev->ifa_list->ifa_local;
+			np_info(np, "local IP %pI4\n", &np->local_ip.sin.sin_addr.s_addr);
 		} else {
 #if IS_ENABLED(CONFIG_IPV6)
 			struct inet6_dev *idev;
@@ -1166,7 +1168,7 @@ int netpoll_setup(struct netpoll *np)
 				list_for_each_entry(ifp, &idev->addr_list, if_list) {
 					if (ipv6_addr_type(&ifp->addr) & IPV6_ADDR_LINKLOCAL)
 						continue;
-					np->local_ip.in6 = ifp->addr;
+					np->local_ip.sin6.sin6_addr = ifp->addr;
 					err = 0;
 					break;
 				}
@@ -1177,7 +1179,7 @@ int netpoll_setup(struct netpoll *np)
 				       np->dev_name);
 				goto put;
 			} else
-				np_info(np, "local IPv6 %pI6c\n", &np->local_ip.in6);
+				np_info(np, "local IPv6 %pI6c\n", &np->local_ip.sin6.sin6_addr);
 #else
 			np_err(np, "IPv6 is not supported %s, aborting\n",
 			       np->dev_name);
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 3/9] net: introduce generic simple_inet_pton()
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Ben Hutchings, Stephen Hemminger, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

simple_inet_pton() is a simple implementation of inet_pton()
in kernel, the original code is already in netpoll, so just move
it to global.

Cc: Ben Hutchings <bhutchings@solarflare.com>
Cc: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 include/net/inet_addr.h |    3 +++
 net/core/netpoll.c      |   36 ++++++++----------------------------
 net/core/utils.c        |   36 ++++++++++++++++++++++++++++++++++++
 3 files changed, 47 insertions(+), 28 deletions(-)

diff --git a/include/net/inet_addr.h b/include/net/inet_addr.h
index 66a16fe..7289aed 100644
--- a/include/net/inet_addr.h
+++ b/include/net/inet_addr.h
@@ -4,6 +4,7 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <linux/socket.h>
+#include <linux/inet.h>
 #include <net/addrconf.h>
 
 union inet_addr {
@@ -59,4 +60,6 @@ static inline bool inet_addr_multicast(const union inet_addr *ipa)
 }
 #endif
 
+int simple_inet_pton(const char *str, union inet_addr *addr);
+
 #endif
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index 9a45c54..5b1d0c8 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -908,30 +908,10 @@ void netpoll_print_options(struct netpoll *np)
 }
 EXPORT_SYMBOL(netpoll_print_options);
 
-static int netpoll_parse_ip_addr(const char *str, union inet_addr *addr)
-{
-	const char *end;
-
-	if (!strchr(str, ':') &&
-	    in4_pton(str, -1, (void *)addr, -1, &end) > 0) {
-		if (!*end)
-			return 0;
-	}
-	if (in6_pton(str, -1, addr->sin6.sin6_addr.s6_addr, -1, &end) > 0) {
-#if IS_ENABLED(CONFIG_IPV6)
-		if (!*end)
-			return 1;
-#else
-		return -1;
-#endif
-	}
-	return -1;
-}
-
 int netpoll_parse_options(struct netpoll *np, char *opt)
 {
 	char *cur=opt, *delim;
-	int ipv6;
+	int ret;
 
 	if (*cur != '@') {
 		if ((delim = strchr(cur, '@')) == NULL)
@@ -947,11 +927,11 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
 		if ((delim = strchr(cur, '/')) == NULL)
 			goto parse_failed;
 		*delim = 0;
-		ipv6 = netpoll_parse_ip_addr(cur, &np->local_ip);
-		if (ipv6 < 0)
+		ret = simple_inet_pton(cur, &np->local_ip);
+		if (ret < 0)
 			goto parse_failed;
 		else
-			np->ipv6 = (bool)ipv6;
+			np->ipv6 = np->local_ip.sa.sa_family == AF_INET6;
 		cur = delim;
 	}
 	cur++;
@@ -983,13 +963,13 @@ int netpoll_parse_options(struct netpoll *np, char *opt)
 	if ((delim = strchr(cur, '/')) == NULL)
 		goto parse_failed;
 	*delim = 0;
-	ipv6 = netpoll_parse_ip_addr(cur, &np->remote_ip);
-	if (ipv6 < 0)
+	ret = simple_inet_pton(cur, &np->remote_ip);
+	if (ret < 0)
 		goto parse_failed;
-	else if (np->ipv6 != (bool)ipv6)
+	else if (np->ipv6 != (np->local_ip.sa.sa_family == AF_INET6))
 		goto parse_failed;
 	else
-		np->ipv6 = (bool)ipv6;
+		np->ipv6 = np->local_ip.sa.sa_family == AF_INET6;
 	cur = delim + 1;
 
 	if (*cur != 0) {
diff --git a/net/core/utils.c b/net/core/utils.c
index aa88e23..22dd621 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -29,6 +29,7 @@
 
 #include <net/sock.h>
 #include <net/net_ratelimit.h>
+#include <net/inet_addr.h>
 
 #include <asm/byteorder.h>
 #include <asm/uaccess.h>
@@ -338,3 +339,38 @@ void inet_proto_csum_replace16(__sum16 *sum, struct sk_buff *skb,
 				  csum_unfold(*sum)));
 }
 EXPORT_SYMBOL(inet_proto_csum_replace16);
+
+/**
+ * simple_inet_pton - a simple implementation of inet_pton()
+ * @str: the start of the IPv4 or IPv6 address string
+ * @addr: a pointer to union inet_addr
+ *
+ * Return zero on success, callers should check addr->sa.sa_family
+ * to know if the address is IPv4 or IPv6; return negative when
+ * any error occurs.
+ *
+ */
+int simple_inet_pton(const char *str, union inet_addr *addr)
+{
+	const char *end;
+
+	if (!strchr(str, ':') &&
+	    in4_pton(str, -1, (void *)addr, -1, &end) > 0) {
+		if (!*end) {
+			addr->sa.sa_family = AF_INET;
+			return 0;
+		}
+	}
+	if (in6_pton(str, -1, addr->sin6.sin6_addr.s6_addr, -1, &end) > 0) {
+#if IS_ENABLED(CONFIG_IPV6)
+		if (!*end) {
+			addr->sa.sa_family = AF_INET6;
+			return 0;
+		}
+#else
+		return -EAFNOSUPPORT;
+#endif
+	}
+	return -EINVAL;
+}
+EXPORT_SYMBOL(simple_inet_pton);
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 4/9] inetpeer: use generic struct in_addr_gen
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Eric Dumazet, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

Similar definition of struct inetpeer_addr is used by bridge multciast
code too, therefore it makes sense to introduce a generic struct
in_addr_gen, so that code can be shared.

There is no more overhead for inet_peer structs now.

Cc: Eric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 include/net/inet_addr.h |   22 ++++++++++++++
 include/net/inetpeer.h  |   25 ++++-----------
 net/ipv4/inetpeer.c     |   33 +++++++++++++-------
 net/ipv4/tcp_metrics.c  |   74 ++++++++++++++++++----------------------------
 4 files changed, 79 insertions(+), 75 deletions(-)

diff --git a/include/net/inet_addr.h b/include/net/inet_addr.h
index 7289aed..ee80df4 100644
--- a/include/net/inet_addr.h
+++ b/include/net/inet_addr.h
@@ -13,6 +13,28 @@ union inet_addr {
 	struct sockaddr sa;
 };
 
+/* a simpler definition of generic inet addr, without additional
+ * information for IPv6 address.
+ */
+struct in_addr_gen {
+	union {
+		struct in_addr	in_addr;
+		struct in6_addr	in6_addr;
+	};
+	unsigned short int	family;
+};
+
+static inline
+bool in_addr_gen_equal(const struct in_addr_gen *a, const struct in_addr_gen *b)
+{
+	if (a->family != b->family)
+		return false;
+	if (a->family == AF_INET6)
+		return ipv6_addr_equal(&a->in6_addr, &b->in6_addr);
+	else
+		return a->in_addr.s_addr == b->in_addr.s_addr;
+}
+
 #if IS_ENABLED(CONFIG_IPV6)
 static inline
 bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
diff --git a/include/net/inetpeer.h b/include/net/inetpeer.h
index 53f464d..9574843 100644
--- a/include/net/inetpeer.h
+++ b/include/net/inetpeer.h
@@ -13,24 +13,13 @@
 #include <linux/spinlock.h>
 #include <linux/rtnetlink.h>
 #include <net/ipv6.h>
+#include <net/inet_addr.h>
 #include <linux/atomic.h>
 
-struct inetpeer_addr_base {
-	union {
-		__be32			a4;
-		__be32			a6[4];
-	};
-};
-
-struct inetpeer_addr {
-	struct inetpeer_addr_base	addr;
-	__u16				family;
-};
-
 struct inet_peer {
 	/* group together avl_left,avl_right,v4daddr to speedup lookups */
 	struct inet_peer __rcu	*avl_left, *avl_right;
-	struct inetpeer_addr	daddr;
+	struct in_addr_gen	daddr;
 	__u32			avl_height;
 
 	u32			metrics[RTAX_MAX];
@@ -133,16 +122,16 @@ static inline bool inet_metrics_new(const struct inet_peer *p)
 
 /* can be called with or without local BH being disabled */
 struct inet_peer *inet_getpeer(struct inet_peer_base *base,
-			       const struct inetpeer_addr *daddr,
+			       const struct in_addr_gen *daddr,
 			       int create);
 
 static inline struct inet_peer *inet_getpeer_v4(struct inet_peer_base *base,
 						__be32 v4daddr,
 						int create)
 {
-	struct inetpeer_addr daddr;
+	struct in_addr_gen daddr;
 
-	daddr.addr.a4 = v4daddr;
+	daddr.in_addr.s_addr = v4daddr;
 	daddr.family = AF_INET;
 	return inet_getpeer(base, &daddr, create);
 }
@@ -151,9 +140,9 @@ static inline struct inet_peer *inet_getpeer_v6(struct inet_peer_base *base,
 						const struct in6_addr *v6daddr,
 						int create)
 {
-	struct inetpeer_addr daddr;
+	struct in_addr_gen daddr;
 
-	*(struct in6_addr *)daddr.addr.a6 = *v6daddr;
+	daddr.in6_addr = *v6daddr;
 	daddr.family = AF_INET6;
 	return inet_getpeer(base, &daddr, create);
 }
diff --git a/net/ipv4/inetpeer.c b/net/ipv4/inetpeer.c
index 000e3d2..70ffc9e 100644
--- a/net/ipv4/inetpeer.c
+++ b/net/ipv4/inetpeer.c
@@ -197,17 +197,26 @@ void __init inet_initpeers(void)
 	INIT_DEFERRABLE_WORK(&gc_work, inetpeer_gc_worker);
 }
 
-static int addr_compare(const struct inetpeer_addr *a,
-			const struct inetpeer_addr *b)
+static int addr_compare(const struct in_addr_gen *a,
+			const struct in_addr_gen *b)
 {
-	int i, n = (a->family == AF_INET ? 1 : 4);
+	int i;
 
-	for (i = 0; i < n; i++) {
-		if (a->addr.a6[i] == b->addr.a6[i])
-			continue;
-		if ((__force u32)a->addr.a6[i] < (__force u32)b->addr.a6[i])
+	if (a->family == AF_INET) {
+		if (a->in_addr.s_addr == b->in_addr.s_addr)
+			return 0;
+		if ((__force u32)a->in_addr.s_addr <
+		    (__force u32)b->in_addr.s_addr)
 			return -1;
-		return 1;
+	} else {
+		for (i = 0; i < 4; i++) {
+			if (a->in6_addr.s6_addr32[i] == b->in6_addr.s6_addr32[i])
+				continue;
+			if ((__force u32)a->in6_addr.s6_addr32[i] <
+			    (__force u32)b->in6_addr.s6_addr32[i])
+				return -1;
+			return 1;
+		}
 	}
 
 	return 0;
@@ -248,7 +257,7 @@ static int addr_compare(const struct inetpeer_addr *a,
  * But every pointer we follow is guaranteed to be valid thanks to RCU.
  * We exit from this function if number of links exceeds PEER_MAXDEPTH
  */
-static struct inet_peer *lookup_rcu(const struct inetpeer_addr *daddr,
+static struct inet_peer *lookup_rcu(const struct in_addr_gen *daddr,
 				    struct inet_peer_base *base)
 {
 	struct inet_peer *u = rcu_dereference(base->root);
@@ -457,7 +466,7 @@ static int inet_peer_gc(struct inet_peer_base *base,
 }
 
 struct inet_peer *inet_getpeer(struct inet_peer_base *base,
-			       const struct inetpeer_addr *daddr,
+			       const struct in_addr_gen *daddr,
 			       int create)
 {
 	struct inet_peer __rcu **stack[PEER_MAXDEPTH], ***stackptr;
@@ -506,8 +515,8 @@ relookup:
 		atomic_set(&p->rid, 0);
 		atomic_set(&p->ip_id_count,
 				(daddr->family == AF_INET) ?
-					secure_ip_id(daddr->addr.a4) :
-					secure_ipv6_id(daddr->addr.a6));
+					secure_ip_id(daddr->in_addr.s_addr) :
+					secure_ipv6_id(daddr->in6_addr.s6_addr32));
 		p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
 		p->rate_tokens = 0;
 		/* 60*HZ is arbitrary, but chosen enough high so that the first
diff --git a/net/ipv4/tcp_metrics.c b/net/ipv4/tcp_metrics.c
index f6a005c..3bb3789 100644
--- a/net/ipv4/tcp_metrics.c
+++ b/net/ipv4/tcp_metrics.c
@@ -31,7 +31,7 @@ struct tcp_fastopen_metrics {
 
 struct tcp_metrics_block {
 	struct tcp_metrics_block __rcu	*tcpm_next;
-	struct inetpeer_addr		tcpm_addr;
+	struct in_addr_gen		tcpm_addr;
 	unsigned long			tcpm_stamp;
 	u32				tcpm_ts;
 	u32				tcpm_ts_stamp;
@@ -74,22 +74,6 @@ static void tcp_metric_set_msecs(struct tcp_metrics_block *tm,
 	tm->tcpm_vals[idx] = jiffies_to_msecs(val);
 }
 
-static bool addr_same(const struct inetpeer_addr *a,
-		      const struct inetpeer_addr *b)
-{
-	const struct in6_addr *a6, *b6;
-
-	if (a->family != b->family)
-		return false;
-	if (a->family == AF_INET)
-		return a->addr.a4 == b->addr.a4;
-
-	a6 = (const struct in6_addr *) &a->addr.a6[0];
-	b6 = (const struct in6_addr *) &b->addr.a6[0];
-
-	return ipv6_addr_equal(a6, b6);
-}
-
 struct tcpm_hash_bucket {
 	struct tcp_metrics_block __rcu	*chain;
 };
@@ -131,7 +115,7 @@ static void tcpm_suck_dst(struct tcp_metrics_block *tm, struct dst_entry *dst,
 }
 
 static struct tcp_metrics_block *tcpm_new(struct dst_entry *dst,
-					  struct inetpeer_addr *addr,
+					  struct in_addr_gen *addr,
 					  unsigned int hash,
 					  bool reclaim)
 {
@@ -189,7 +173,7 @@ static struct tcp_metrics_block *tcp_get_encode(struct tcp_metrics_block *tm, in
 	return NULL;
 }
 
-static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *addr,
+static struct tcp_metrics_block *__tcp_get_metrics(const struct in_addr_gen *addr,
 						   struct net *net, unsigned int hash)
 {
 	struct tcp_metrics_block *tm;
@@ -197,7 +181,7 @@ static struct tcp_metrics_block *__tcp_get_metrics(const struct inetpeer_addr *a
 
 	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
 	     tm = rcu_dereference(tm->tcpm_next)) {
-		if (addr_same(&tm->tcpm_addr, addr))
+		if (in_addr_gen_equal(&tm->tcpm_addr, addr))
 			break;
 		depth++;
 	}
@@ -208,18 +192,18 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
 						       struct dst_entry *dst)
 {
 	struct tcp_metrics_block *tm;
-	struct inetpeer_addr addr;
+	struct in_addr_gen addr;
 	unsigned int hash;
 	struct net *net;
 
 	addr.family = req->rsk_ops->family;
 	switch (addr.family) {
 	case AF_INET:
-		addr.addr.a4 = inet_rsk(req)->rmt_addr;
-		hash = (__force unsigned int) addr.addr.a4;
+		addr.in_addr.s_addr = inet_rsk(req)->rmt_addr;
+		hash = (__force unsigned int) addr.in_addr.s_addr;
 		break;
 	case AF_INET6:
-		*(struct in6_addr *)addr.addr.a6 = inet6_rsk(req)->rmt_addr;
+		addr.in6_addr = inet6_rsk(req)->rmt_addr;
 		hash = ipv6_addr_hash(&inet6_rsk(req)->rmt_addr);
 		break;
 	default:
@@ -231,7 +215,7 @@ static struct tcp_metrics_block *__tcp_get_metrics_req(struct request_sock *req,
 
 	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
 	     tm = rcu_dereference(tm->tcpm_next)) {
-		if (addr_same(&tm->tcpm_addr, &addr))
+		if (in_addr_gen_equal(&tm->tcpm_addr, &addr))
 			break;
 	}
 	tcpm_check_stamp(tm, dst);
@@ -242,19 +226,19 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock
 {
 	struct inet6_timewait_sock *tw6;
 	struct tcp_metrics_block *tm;
-	struct inetpeer_addr addr;
+	struct in_addr_gen addr;
 	unsigned int hash;
 	struct net *net;
 
 	addr.family = tw->tw_family;
 	switch (addr.family) {
 	case AF_INET:
-		addr.addr.a4 = tw->tw_daddr;
-		hash = (__force unsigned int) addr.addr.a4;
+		addr.in_addr.s_addr = tw->tw_daddr;
+		hash = (__force unsigned int) addr.in_addr.s_addr;
 		break;
 	case AF_INET6:
 		tw6 = inet6_twsk((struct sock *)tw);
-		*(struct in6_addr *)addr.addr.a6 = tw6->tw_v6_daddr;
+		addr.in6_addr = tw6->tw_v6_daddr;
 		hash = ipv6_addr_hash(&tw6->tw_v6_daddr);
 		break;
 	default:
@@ -266,7 +250,7 @@ static struct tcp_metrics_block *__tcp_get_metrics_tw(struct inet_timewait_sock
 
 	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
 	     tm = rcu_dereference(tm->tcpm_next)) {
-		if (addr_same(&tm->tcpm_addr, &addr))
+		if (in_addr_gen_equal(&tm->tcpm_addr, &addr))
 			break;
 	}
 	return tm;
@@ -277,7 +261,7 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
 						 bool create)
 {
 	struct tcp_metrics_block *tm;
-	struct inetpeer_addr addr;
+	struct in_addr_gen addr;
 	unsigned int hash;
 	struct net *net;
 	bool reclaim;
@@ -285,11 +269,11 @@ static struct tcp_metrics_block *tcp_get_metrics(struct sock *sk,
 	addr.family = sk->sk_family;
 	switch (addr.family) {
 	case AF_INET:
-		addr.addr.a4 = inet_sk(sk)->inet_daddr;
-		hash = (__force unsigned int) addr.addr.a4;
+		addr.in_addr.s_addr = inet_sk(sk)->inet_daddr;
+		hash = (__force unsigned int) addr.in_addr.s_addr;
 		break;
 	case AF_INET6:
-		*(struct in6_addr *)addr.addr.a6 = inet6_sk(sk)->daddr;
+		addr.in6_addr = inet6_sk(sk)->daddr;
 		hash = ipv6_addr_hash(&inet6_sk(sk)->daddr);
 		break;
 	default:
@@ -725,12 +709,12 @@ static int tcp_metrics_fill_info(struct sk_buff *msg,
 	switch (tm->tcpm_addr.family) {
 	case AF_INET:
 		if (nla_put_be32(msg, TCP_METRICS_ATTR_ADDR_IPV4,
-				tm->tcpm_addr.addr.a4) < 0)
+				tm->tcpm_addr.in_addr.s_addr) < 0)
 			goto nla_put_failure;
 		break;
 	case AF_INET6:
 		if (nla_put(msg, TCP_METRICS_ATTR_ADDR_IPV6, 16,
-			    tm->tcpm_addr.addr.a6) < 0)
+			    tm->tcpm_addr.in6_addr.s6_addr32) < 0)
 			goto nla_put_failure;
 		break;
 	default:
@@ -853,7 +837,7 @@ done:
 	return skb->len;
 }
 
-static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
+static int parse_nl_addr(struct genl_info *info, struct in_addr_gen *addr,
 			 unsigned int *hash, int optional)
 {
 	struct nlattr *a;
@@ -861,8 +845,8 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
 	a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV4];
 	if (a) {
 		addr->family = AF_INET;
-		addr->addr.a4 = nla_get_be32(a);
-		*hash = (__force unsigned int) addr->addr.a4;
+		addr->in_addr.s_addr = nla_get_be32(a);
+		*hash = (__force unsigned int) addr->in_addr.s_addr;
 		return 0;
 	}
 	a = info->attrs[TCP_METRICS_ATTR_ADDR_IPV6];
@@ -870,8 +854,8 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
 		if (nla_len(a) != sizeof(struct in6_addr))
 			return -EINVAL;
 		addr->family = AF_INET6;
-		memcpy(addr->addr.a6, nla_data(a), sizeof(addr->addr.a6));
-		*hash = ipv6_addr_hash((struct in6_addr *) addr->addr.a6);
+		memcpy(&addr->in6_addr, nla_data(a), sizeof(addr->in6_addr));
+		*hash = ipv6_addr_hash(&addr->in6_addr);
 		return 0;
 	}
 	return optional ? 1 : -EAFNOSUPPORT;
@@ -880,7 +864,7 @@ static int parse_nl_addr(struct genl_info *info, struct inetpeer_addr *addr,
 static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
 {
 	struct tcp_metrics_block *tm;
-	struct inetpeer_addr addr;
+	struct in_addr_gen addr;
 	unsigned int hash;
 	struct sk_buff *msg;
 	struct net *net = genl_info_net(info);
@@ -905,7 +889,7 @@ static int tcp_metrics_nl_cmd_get(struct sk_buff *skb, struct genl_info *info)
 	rcu_read_lock();
 	for (tm = rcu_dereference(net->ipv4.tcp_metrics_hash[hash].chain); tm;
 	     tm = rcu_dereference(tm->tcpm_next)) {
-		if (addr_same(&tm->tcpm_addr, &addr)) {
+		if (in_addr_gen_equal(&tm->tcpm_addr, &addr)) {
 			ret = tcp_metrics_fill_info(msg, tm);
 			break;
 		}
@@ -960,7 +944,7 @@ static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info)
 	struct tcpm_hash_bucket *hb;
 	struct tcp_metrics_block *tm;
 	struct tcp_metrics_block __rcu **pp;
-	struct inetpeer_addr addr;
+	struct in_addr_gen addr;
 	unsigned int hash;
 	struct net *net = genl_info_net(info);
 	int ret;
@@ -977,7 +961,7 @@ static int tcp_metrics_nl_cmd_del(struct sk_buff *skb, struct genl_info *info)
 	spin_lock_bh(&tcp_metrics_lock);
 	for (tm = deref_locked_genl(*pp); tm;
 	     pp = &tm->tcpm_next, tm = deref_locked_genl(*pp)) {
-		if (addr_same(&tm->tcpm_addr, &addr)) {
+		if (in_addr_gen_equal(&tm->tcpm_addr, &addr)) {
 			*pp = tm->tcpm_next;
 			break;
 		}
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 5/9] bridge: use generic struct in_addr_gen
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev; +Cc: David S. Miller, Stephen Hemminger, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

Cc: Stephen Hemminger <stephen@networkplumber.org>
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 net/bridge/br_mdb.c       |   53 ++++++++++++++++++------------------
 net/bridge/br_multicast.c |   65 +++++++++++++++++++-------------------------
 net/bridge/br_private.h   |    9 +-----
 3 files changed, 57 insertions(+), 70 deletions(-)

diff --git a/net/bridge/br_mdb.c b/net/bridge/br_mdb.c
index e4d5cd4..55d6b59 100644
--- a/net/bridge/br_mdb.c
+++ b/net/bridge/br_mdb.c
@@ -13,6 +13,29 @@
 
 #include "br_private.h"
 
+static void br_ip_to_entry(struct br_mdb_entry *entry, struct br_ip *ip)
+{
+	if (ip->ip.family == AF_INET) {
+		entry->addr.proto = htons(ETH_P_IP);
+		entry->addr.u.ip4 = ip->ip.in_addr.s_addr;
+	} else {
+		entry->addr.proto = htons(ETH_P_IPV6);
+		entry->addr.u.ip6 = ip->ip.in6_addr;
+	}
+}
+
+static void br_entry_to_ip(struct br_ip *ip, struct br_mdb_entry *entry)
+{
+	__be16 proto = entry->addr.proto;
+	if (proto == htons(ETH_P_IP)) {
+		ip->ip.family = AF_INET;
+		ip->ip.in_addr.s_addr = entry->addr.u.ip4;
+	} else {
+		ip->ip.family = AF_INET6;
+		ip->ip.in6_addr = entry->addr.u.ip6;
+	}
+}
+
 static int br_rports_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
 			       struct net_device *dev)
 {
@@ -84,13 +107,7 @@ static int br_mdb_fill_info(struct sk_buff *skb, struct netlink_callback *cb,
 					memset(&e, 0, sizeof(e));
 					e.ifindex = port->dev->ifindex;
 					e.state = p->state;
-					if (p->addr.proto == htons(ETH_P_IP))
-						e.addr.u.ip4 = p->addr.u.ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-					if (p->addr.proto == htons(ETH_P_IPV6))
-						e.addr.u.ip6 = p->addr.u.ip6;
-#endif
-					e.addr.proto = p->addr.proto;
+					br_ip_to_entry(&e, &p->addr);
 					if (nla_put(skb, MDBA_MDB_ENTRY_INFO, sizeof(e), &e)) {
 						nla_nest_cancel(skb, nest2);
 						err = -EMSGSIZE;
@@ -234,11 +251,7 @@ void br_mdb_notify(struct net_device *dev, struct net_bridge_port *port,
 
 	memset(&entry, 0, sizeof(entry));
 	entry.ifindex = port->dev->ifindex;
-	entry.addr.proto = group->proto;
-	entry.addr.u.ip4 = group->u.ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-	entry.addr.u.ip6 = group->u.ip6;
-#endif
+	br_ip_to_entry(&entry, group);
 	__br_mdb_notify(dev, &entry, type);
 }
 
@@ -369,13 +382,7 @@ static int __br_mdb_add(struct net *net, struct net_bridge *br,
 	if (!p || p->br != br || p->state == BR_STATE_DISABLED)
 		return -EINVAL;
 
-	ip.proto = entry->addr.proto;
-	if (ip.proto == htons(ETH_P_IP))
-		ip.u.ip4 = entry->addr.u.ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-	else
-		ip.u.ip6 = entry->addr.u.ip6;
-#endif
+	br_entry_to_ip(&ip, entry);
 
 	spin_lock_bh(&br->multicast_lock);
 	ret = br_mdb_add_group(br, p, &ip, entry->state);
@@ -418,13 +425,7 @@ static int __br_mdb_del(struct net_bridge *br, struct br_mdb_entry *entry)
 	if (timer_pending(&br->multicast_querier_timer))
 		return -EBUSY;
 
-	ip.proto = entry->addr.proto;
-	if (ip.proto == htons(ETH_P_IP))
-		ip.u.ip4 = entry->addr.u.ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-	else
-		ip.u.ip6 = entry->addr.u.ip6;
-#endif
+	br_entry_to_ip(&ip, entry);
 
 	spin_lock_bh(&br->multicast_lock);
 	mdb = mlock_dereference(br->mdb, br);
diff --git a/net/bridge/br_multicast.c b/net/bridge/br_multicast.c
index 08e576a..6d7c407 100644
--- a/net/bridge/br_multicast.c
+++ b/net/bridge/br_multicast.c
@@ -38,19 +38,9 @@ unsigned int br_mdb_rehash_seq;
 
 static inline int br_ip_equal(const struct br_ip *a, const struct br_ip *b)
 {
-	if (a->proto != b->proto)
-		return 0;
 	if (a->vid != b->vid)
 		return 0;
-	switch (a->proto) {
-	case htons(ETH_P_IP):
-		return a->u.ip4 == b->u.ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-	case htons(ETH_P_IPV6):
-		return ipv6_addr_equal(&a->u.ip6, &b->u.ip6);
-#endif
-	}
-	return 0;
+	return in_addr_gen_equal(&a->ip, &b->ip);
 }
 
 static inline int __br_ip4_hash(struct net_bridge_mdb_htable *mdb, __be32 ip,
@@ -72,12 +62,12 @@ static inline int __br_ip6_hash(struct net_bridge_mdb_htable *mdb,
 static inline int br_ip_hash(struct net_bridge_mdb_htable *mdb,
 			     struct br_ip *ip)
 {
-	switch (ip->proto) {
+	switch (ip->ip.family) {
 	case htons(ETH_P_IP):
-		return __br_ip4_hash(mdb, ip->u.ip4, ip->vid);
+		return __br_ip4_hash(mdb, ip->ip.in_addr.s_addr, ip->vid);
 #if IS_ENABLED(CONFIG_IPV6)
 	case htons(ETH_P_IPV6):
-		return __br_ip6_hash(mdb, &ip->u.ip6, ip->vid);
+		return __br_ip6_hash(mdb, &ip->ip.in6_addr, ip->vid);
 #endif
 	}
 	return 0;
@@ -110,8 +100,8 @@ static struct net_bridge_mdb_entry *br_mdb_ip4_get(
 {
 	struct br_ip br_dst;
 
-	br_dst.u.ip4 = dst;
-	br_dst.proto = htons(ETH_P_IP);
+	br_dst.ip.in_addr.s_addr = dst;
+	br_dst.ip.family = AF_INET;
 	br_dst.vid = vid;
 
 	return br_mdb_ip_get(mdb, &br_dst);
@@ -124,8 +114,8 @@ static struct net_bridge_mdb_entry *br_mdb_ip6_get(
 {
 	struct br_ip br_dst;
 
-	br_dst.u.ip6 = *dst;
-	br_dst.proto = htons(ETH_P_IPV6);
+	br_dst.ip.in6_addr = *dst;
+	br_dst.ip.family = AF_INET6;
 	br_dst.vid = vid;
 
 	return br_mdb_ip_get(mdb, &br_dst);
@@ -144,16 +134,17 @@ struct net_bridge_mdb_entry *br_mdb_get(struct net_bridge *br,
 	if (BR_INPUT_SKB_CB(skb)->igmp)
 		return NULL;
 
-	ip.proto = skb->protocol;
 	ip.vid = vid;
 
 	switch (skb->protocol) {
 	case htons(ETH_P_IP):
-		ip.u.ip4 = ip_hdr(skb)->daddr;
+		ip.ip.family = AF_INET;
+		ip.ip.in_addr.s_addr = ip_hdr(skb)->daddr;
 		break;
 #if IS_ENABLED(CONFIG_IPV6)
 	case htons(ETH_P_IPV6):
-		ip.u.ip6 = ipv6_hdr(skb)->daddr;
+		ip.ip.family = AF_INET6;
+		ip.ip.in6_addr = ipv6_hdr(skb)->daddr;
 		break;
 #endif
 	default:
@@ -495,12 +486,12 @@ out:
 static struct sk_buff *br_multicast_alloc_query(struct net_bridge *br,
 						struct br_ip *addr)
 {
-	switch (addr->proto) {
-	case htons(ETH_P_IP):
-		return br_ip4_multicast_alloc_query(br, addr->u.ip4);
+	switch (addr->ip.family) {
+	case AF_INET:
+		return br_ip4_multicast_alloc_query(br, addr->ip.in_addr.s_addr);
 #if IS_ENABLED(CONFIG_IPV6)
-	case htons(ETH_P_IPV6):
-		return br_ip6_multicast_alloc_query(br, &addr->u.ip6);
+	case AF_INET6:
+		return br_ip6_multicast_alloc_query(br, &addr->ip.in6_addr);
 #endif
 	}
 	return NULL;
@@ -708,8 +699,8 @@ static int br_ip4_multicast_add_group(struct net_bridge *br,
 	if (ipv4_is_local_multicast(group))
 		return 0;
 
-	br_group.u.ip4 = group;
-	br_group.proto = htons(ETH_P_IP);
+	br_group.ip.in_addr.s_addr = group;
+	br_group.ip.family = AF_INET;
 	br_group.vid = vid;
 
 	return br_multicast_add_group(br, port, &br_group);
@@ -726,8 +717,8 @@ static int br_ip6_multicast_add_group(struct net_bridge *br,
 	if (!ipv6_is_transient_multicast(group))
 		return 0;
 
-	br_group.u.ip6 = *group;
-	br_group.proto = htons(ETH_P_IPV6);
+	br_group.ip.in6_addr = *group;
+	br_group.ip.family = AF_INET6;
 	br_group.vid = vid;
 
 	return br_multicast_add_group(br, port, &br_group);
@@ -799,13 +790,13 @@ static void br_multicast_send_query(struct net_bridge *br,
 	    timer_pending(&br->multicast_querier_timer))
 		return;
 
-	memset(&br_group.u, 0, sizeof(br_group.u));
+	memset(&br_group.ip, 0, sizeof(br_group.ip));
 
-	br_group.proto = htons(ETH_P_IP);
+	br_group.ip.family = AF_INET;
 	__br_multicast_send_query(br, port, &br_group);
 
 #if IS_ENABLED(CONFIG_IPV6)
-	br_group.proto = htons(ETH_P_IPV6);
+	br_group.ip.family = AF_INET6;
 	__br_multicast_send_query(br, port, &br_group);
 #endif
 
@@ -1338,8 +1329,8 @@ static void br_ip4_multicast_leave_group(struct net_bridge *br,
 	if (ipv4_is_local_multicast(group))
 		return;
 
-	br_group.u.ip4 = group;
-	br_group.proto = htons(ETH_P_IP);
+	br_group.ip.in_addr.s_addr = group;
+	br_group.ip.family = AF_INET;
 	br_group.vid = vid;
 
 	br_multicast_leave_group(br, port, &br_group);
@@ -1356,8 +1347,8 @@ static void br_ip6_multicast_leave_group(struct net_bridge *br,
 	if (!ipv6_is_transient_multicast(group))
 		return;
 
-	br_group.u.ip6 = *group;
-	br_group.proto = htons(ETH_P_IPV6);
+	br_group.ip.in6_addr = *group;
+	br_group.ip.family = AF_INET6;
 	br_group.vid = vid;
 
 	br_multicast_leave_group(br, port, &br_group);
diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h
index d41283c..4a5a52a 100644
--- a/net/bridge/br_private.h
+++ b/net/bridge/br_private.h
@@ -19,6 +19,7 @@
 #include <linux/u64_stats_sync.h>
 #include <net/route.h>
 #include <linux/if_vlan.h>
+#include <net/inet_addr.h>
 
 #define BR_HASH_BITS 8
 #define BR_HASH_SIZE (1 << BR_HASH_BITS)
@@ -56,13 +57,7 @@ struct mac_addr
 
 struct br_ip
 {
-	union {
-		__be32	ip4;
-#if IS_ENABLED(CONFIG_IPV6)
-		struct in6_addr ip6;
-#endif
-	} u;
-	__be16		proto;
+	struct in_addr_gen ip;
 	__u16		vid;
 };
 
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 6/9] sunrpc: use generic union inet_addr
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Jeff Layton, Trond Myklebust, J. Bruce Fields,
	linux-nfs, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

sunrpc defines some helper functions for sockaddr, actually they
can re-use the generic functions for union inet_addr too.

Cc: Jeff Layton <jlayton@redhat.com>
Cc: Trond Myklebust <Trond.Myklebust@netapp.com>
Cc: "J. Bruce Fields" <bfields@fieldses.org>
Cc: linux-nfs@vger.kernel.org
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 fs/lockd/clntlock.c             |    2 +-
 fs/lockd/host.c                 |    8 +-
 fs/lockd/mon.c                  |    2 +-
 fs/lockd/svcsubs.c              |    2 +-
 fs/nfs/nfs4namespace.c          |    2 +-
 fs/nfs/super.c                  |    6 +-
 fs/nfsd/nfs4state.c             |    6 +-
 fs/nfsd/nfscache.c              |    8 +-
 include/linux/sunrpc/addr.h     |  131 +--------------------------------------
 include/net/inet_addr.h         |   99 ++++++++++++++++++++++++-----
 net/core/utils.c                |   25 ++++++++
 net/sunrpc/clnt.c               |    2 +-
 net/sunrpc/rpcb_clnt.c          |    2 +-
 net/sunrpc/xprtrdma/transport.c |    4 +-
 net/sunrpc/xprtsock.c           |    8 +-
 15 files changed, 134 insertions(+), 173 deletions(-)

diff --git a/fs/lockd/clntlock.c b/fs/lockd/clntlock.c
index 41e491b..289444e 100644
--- a/fs/lockd/clntlock.c
+++ b/fs/lockd/clntlock.c
@@ -184,7 +184,7 @@ __be32 nlmclnt_grant(const struct sockaddr *addr, const struct nlm_lock *lock)
 		 */
 		if (fl_blocked->fl_u.nfs_fl.owner->pid != lock->svid)
 			continue;
-		if (!rpc_cmp_addr(nlm_addr(block->b_host), addr))
+		if (!sockaddr_equal(nlm_addr(block->b_host), addr))
 			continue;
 		if (nfs_compare_fh(NFS_FH(file_inode(fl_blocked->fl_file)) ,fh) != 0)
 			continue;
diff --git a/fs/lockd/host.c b/fs/lockd/host.c
index 969d589..155c720 100644
--- a/fs/lockd/host.c
+++ b/fs/lockd/host.c
@@ -134,7 +134,7 @@ static struct nlm_host *nlm_alloc_host(struct nlm_lookup_host_info *ni,
 
 	memcpy(nlm_addr(host), ni->sap, ni->salen);
 	host->h_addrlen    = ni->salen;
-	rpc_set_port(nlm_addr(host), 0);
+	sockaddr_set_port(nlm_addr(host), 0);
 	host->h_srcaddrlen = 0;
 
 	host->h_rpcclnt    = NULL;
@@ -240,7 +240,7 @@ struct nlm_host *nlmclnt_lookup_host(const struct sockaddr *sap,
 	hlist_for_each_entry(host, chain, h_hash) {
 		if (host->net != net)
 			continue;
-		if (!rpc_cmp_addr(nlm_addr(host), sap))
+		if (!sockaddr_equal(nlm_addr(host), sap))
 			continue;
 
 		/* Same address. Share an NSM handle if we already have one */
@@ -352,7 +352,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
 	hlist_for_each_entry(host, chain, h_hash) {
 		if (host->net != net)
 			continue;
-		if (!rpc_cmp_addr(nlm_addr(host), ni.sap))
+		if (!sockaddr_equal(nlm_addr(host), ni.sap))
 			continue;
 
 		/* Same address. Share an NSM handle if we already have one */
@@ -363,7 +363,7 @@ struct nlm_host *nlmsvc_lookup_host(const struct svc_rqst *rqstp,
 			continue;
 		if (host->h_version != ni.version)
 			continue;
-		if (!rpc_cmp_addr(nlm_srcaddr(host), src_sap))
+		if (!sockaddr_equal(nlm_srcaddr(host), src_sap))
 			continue;
 
 		/* Move to head of hash chain. */
diff --git a/fs/lockd/mon.c b/fs/lockd/mon.c
index 1812f02..d36d65a 100644
--- a/fs/lockd/mon.c
+++ b/fs/lockd/mon.c
@@ -270,7 +270,7 @@ static struct nsm_handle *nsm_lookup_addr(const struct sockaddr *sap)
 	struct nsm_handle *nsm;
 
 	list_for_each_entry(nsm, &nsm_handles, sm_link)
-		if (rpc_cmp_addr(nsm_addr(nsm), sap))
+		if (sockaddr_equal(nsm_addr(nsm), sap))
 			return nsm;
 	return NULL;
 }
diff --git a/fs/lockd/svcsubs.c b/fs/lockd/svcsubs.c
index dc5c759..a9f4a6f 100644
--- a/fs/lockd/svcsubs.c
+++ b/fs/lockd/svcsubs.c
@@ -431,7 +431,7 @@ EXPORT_SYMBOL_GPL(nlmsvc_unlock_all_by_sb);
 static int
 nlmsvc_match_ip(void *datap, struct nlm_host *host)
 {
-	return rpc_cmp_addr(nlm_srcaddr(host), datap);
+	return sockaddr_equal(nlm_srcaddr(host), datap);
 }
 
 /**
diff --git a/fs/nfs/nfs4namespace.c b/fs/nfs/nfs4namespace.c
index cdb0b41..79767fc 100644
--- a/fs/nfs/nfs4namespace.c
+++ b/fs/nfs/nfs4namespace.c
@@ -243,7 +243,7 @@ static struct vfsmount *try_location(struct nfs_clone_mount *mountdata,
 		if (mountdata->addrlen == 0)
 			continue;
 
-		rpc_set_port(mountdata->addr, NFS_PORT);
+		sockaddr_set_port(mountdata->addr, NFS_PORT);
 
 		memcpy(page2, buf->data, buf->len);
 		page2[buf->len] = '\0';
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index f6db66d..ac7c359 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -978,7 +978,7 @@ static void nfs_set_port(struct sockaddr *sap, int *port,
 	if (*port == NFS_UNSPEC_PORT)
 		*port = default_port;
 
-	rpc_set_port(sap, *port);
+	sockaddr_set_port(sap, *port);
 }
 
 /*
@@ -2133,8 +2133,8 @@ nfs_compare_remount_data(struct nfs_server *nfss,
 	    data->timeo != (10U * nfss->client->cl_timeout->to_initval / HZ) ||
 	    data->nfs_server.port != nfss->port ||
 	    data->nfs_server.addrlen != nfss->nfs_client->cl_addrlen ||
-	    !rpc_cmp_addr((struct sockaddr *)&data->nfs_server.address,
-			  (struct sockaddr *)&nfss->nfs_client->cl_addr))
+	    !sockaddr_equal((struct sockaddr *)&data->nfs_server.address,
+			    (struct sockaddr *)&nfss->nfs_client->cl_addr))
 		return -EINVAL;
 
 	return 0;
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 43f4229..92689bf 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -1009,7 +1009,7 @@ static void init_session(struct svc_rqst *rqstp, struct nfsd4_session *new, stru
 		 * the rpc client not to require an address in the
 		 * future:
 		 */
-		rpc_copy_addr((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
+		sockaddr_copy((struct sockaddr *)&clp->cl_cb_conn.cb_addr, sa);
 		clp->cl_cb_conn.cb_addrlen = svc_addr_len(sa);
 	}
 }
@@ -1362,7 +1362,7 @@ static struct nfs4_client *create_client(struct xdr_netobj name,
 	clear_bit(0, &clp->cl_cb_slot_busy);
 	rpc_init_wait_queue(&clp->cl_cb_waitq, "Backchannel slot table");
 	copy_verf(clp, verf);
-	rpc_copy_addr((struct sockaddr *) &clp->cl_addr, sa);
+	sockaddr_copy((struct sockaddr *) &clp->cl_addr, sa);
 	gen_confirm(clp);
 	clp->cl_cb_session = NULL;
 	clp->net = net;
@@ -1939,7 +1939,7 @@ nfsd4_create_session(struct svc_rqst *rqstp,
 	} else if (unconf) {
 		struct nfs4_client *old;
 		if (!same_creds(&unconf->cl_cred, &rqstp->rq_cred) ||
-		    !rpc_cmp_addr(sa, (struct sockaddr *) &unconf->cl_addr)) {
+		    !sockaddr_equal(sa, (struct sockaddr *) &unconf->cl_addr)) {
 			status = nfserr_clid_inuse;
 			goto out_free_conn;
 		}
diff --git a/fs/nfsd/nfscache.c b/fs/nfsd/nfscache.c
index e76244e..e2561d6 100644
--- a/fs/nfsd/nfscache.c
+++ b/fs/nfsd/nfscache.c
@@ -318,8 +318,8 @@ nfsd_cache_match(struct svc_rqst *rqstp, __wsum csum, struct svc_cacherep *rp)
 	if (rqstp->rq_xid != rp->c_xid || rqstp->rq_proc != rp->c_proc ||
 	    rqstp->rq_prot != rp->c_prot || rqstp->rq_vers != rp->c_vers ||
 	    rqstp->rq_arg.len != rp->c_len ||
-	    !rpc_cmp_addr(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) ||
-	    rpc_get_port(svc_addr(rqstp)) != rpc_get_port((struct sockaddr *)&rp->c_addr))
+	    !sockaddr_equal(svc_addr(rqstp), (struct sockaddr *)&rp->c_addr) ||
+	    sockaddr_get_port(svc_addr(rqstp)) != sockaddr_get_port((struct sockaddr *)&rp->c_addr))
 		return false;
 
 	/* compare checksum of NFS data */
@@ -446,8 +446,8 @@ search_cache:
 	rp->c_state = RC_INPROG;
 	rp->c_xid = xid;
 	rp->c_proc = proc;
-	rpc_copy_addr((struct sockaddr *)&rp->c_addr, svc_addr(rqstp));
-	rpc_set_port((struct sockaddr *)&rp->c_addr, rpc_get_port(svc_addr(rqstp)));
+	sockaddr_equal((struct sockaddr *)&rp->c_addr, svc_addr(rqstp));
+	sockaddr_set_port((struct sockaddr *)&rp->c_addr, sockaddr_get_port(svc_addr(rqstp)));
 	rp->c_prot = proto;
 	rp->c_vers = vers;
 	rp->c_len = rqstp->rq_arg.len;
diff --git a/include/linux/sunrpc/addr.h b/include/linux/sunrpc/addr.h
index 07d8e53..002be97 100644
--- a/include/linux/sunrpc/addr.h
+++ b/include/linux/sunrpc/addr.h
@@ -11,6 +11,7 @@
 #include <linux/in.h>
 #include <linux/in6.h>
 #include <net/ipv6.h>
+#include <net/inet_addr.h>
 
 size_t		rpc_ntop(const struct sockaddr *, char *, const size_t);
 size_t		rpc_pton(struct net *, const char *, const size_t,
@@ -19,139 +20,9 @@ char *		rpc_sockaddr2uaddr(const struct sockaddr *, gfp_t);
 size_t		rpc_uaddr2sockaddr(struct net *, const char *, const size_t,
 				   struct sockaddr *, const size_t);
 
-static inline unsigned short rpc_get_port(const struct sockaddr *sap)
-{
-	switch (sap->sa_family) {
-	case AF_INET:
-		return ntohs(((struct sockaddr_in *)sap)->sin_port);
-	case AF_INET6:
-		return ntohs(((struct sockaddr_in6 *)sap)->sin6_port);
-	}
-	return 0;
-}
-
-static inline void rpc_set_port(struct sockaddr *sap,
-				const unsigned short port)
-{
-	switch (sap->sa_family) {
-	case AF_INET:
-		((struct sockaddr_in *)sap)->sin_port = htons(port);
-		break;
-	case AF_INET6:
-		((struct sockaddr_in6 *)sap)->sin6_port = htons(port);
-		break;
-	}
-}
-
 #define IPV6_SCOPE_DELIMITER		'%'
 #define IPV6_SCOPE_ID_LEN		sizeof("%nnnnnnnnnn")
 
-static inline bool __rpc_cmp_addr4(const struct sockaddr *sap1,
-				   const struct sockaddr *sap2)
-{
-	const struct sockaddr_in *sin1 = (const struct sockaddr_in *)sap1;
-	const struct sockaddr_in *sin2 = (const struct sockaddr_in *)sap2;
-
-	return sin1->sin_addr.s_addr == sin2->sin_addr.s_addr;
-}
-
-static inline bool __rpc_copy_addr4(struct sockaddr *dst,
-				    const struct sockaddr *src)
-{
-	const struct sockaddr_in *ssin = (struct sockaddr_in *) src;
-	struct sockaddr_in *dsin = (struct sockaddr_in *) dst;
-
-	dsin->sin_family = ssin->sin_family;
-	dsin->sin_addr.s_addr = ssin->sin_addr.s_addr;
-	return true;
-}
-
-#if IS_ENABLED(CONFIG_IPV6)
-static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
-				   const struct sockaddr *sap2)
-{
-	const struct sockaddr_in6 *sin1 = (const struct sockaddr_in6 *)sap1;
-	const struct sockaddr_in6 *sin2 = (const struct sockaddr_in6 *)sap2;
-
-	if (!ipv6_addr_equal(&sin1->sin6_addr, &sin2->sin6_addr))
-		return false;
-	else if (ipv6_addr_type(&sin1->sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		return sin1->sin6_scope_id == sin2->sin6_scope_id;
-
-	return true;
-}
-
-static inline bool __rpc_copy_addr6(struct sockaddr *dst,
-				    const struct sockaddr *src)
-{
-	const struct sockaddr_in6 *ssin6 = (const struct sockaddr_in6 *) src;
-	struct sockaddr_in6 *dsin6 = (struct sockaddr_in6 *) dst;
-
-	dsin6->sin6_family = ssin6->sin6_family;
-	dsin6->sin6_addr = ssin6->sin6_addr;
-	dsin6->sin6_scope_id = ssin6->sin6_scope_id;
-	return true;
-}
-#else	/* !(IS_ENABLED(CONFIG_IPV6) */
-static inline bool __rpc_cmp_addr6(const struct sockaddr *sap1,
-				   const struct sockaddr *sap2)
-{
-	return false;
-}
-
-static inline bool __rpc_copy_addr6(struct sockaddr *dst,
-				    const struct sockaddr *src)
-{
-	return false;
-}
-#endif	/* !(IS_ENABLED(CONFIG_IPV6) */
-
-/**
- * rpc_cmp_addr - compare the address portion of two sockaddrs.
- * @sap1: first sockaddr
- * @sap2: second sockaddr
- *
- * Just compares the family and address portion. Ignores port, but
- * compares the scope if it's a link-local address.
- *
- * Returns true if the addrs are equal, false if they aren't.
- */
-static inline bool rpc_cmp_addr(const struct sockaddr *sap1,
-				const struct sockaddr *sap2)
-{
-	if (sap1->sa_family == sap2->sa_family) {
-		switch (sap1->sa_family) {
-		case AF_INET:
-			return __rpc_cmp_addr4(sap1, sap2);
-		case AF_INET6:
-			return __rpc_cmp_addr6(sap1, sap2);
-		}
-	}
-	return false;
-}
-
-/**
- * rpc_copy_addr - copy the address portion of one sockaddr to another
- * @dst: destination sockaddr
- * @src: source sockaddr
- *
- * Just copies the address portion and family. Ignores port, scope, etc.
- * Caller is responsible for making certain that dst is large enough to hold
- * the address in src. Returns true if address family is supported. Returns
- * false otherwise.
- */
-static inline bool rpc_copy_addr(struct sockaddr *dst,
-				 const struct sockaddr *src)
-{
-	switch (src->sa_family) {
-	case AF_INET:
-		return __rpc_copy_addr4(dst, src);
-	case AF_INET6:
-		return __rpc_copy_addr6(dst, src);
-	}
-	return false;
-}
-
 /**
  * rpc_get_scope_id - return scopeid for a given sockaddr
  * @sa: sockaddr to get scopeid from
diff --git a/include/net/inet_addr.h b/include/net/inet_addr.h
index ee80df4..44179c8 100644
--- a/include/net/inet_addr.h
+++ b/include/net/inet_addr.h
@@ -36,17 +36,6 @@ bool in_addr_gen_equal(const struct in_addr_gen *a, const struct in_addr_gen *b)
 }
 
 #if IS_ENABLED(CONFIG_IPV6)
-static inline
-bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
-{
-	if (a->sa.sa_family != b->sa.sa_family)
-		return false;
-	if (a->sa.sa_family == AF_INET6)
-		return ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr);
-	else
-		return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
-}
-
 static inline bool inet_addr_any(const union inet_addr *ipa)
 {
 	if (ipa->sa.sa_family == AF_INET6)
@@ -65,12 +54,6 @@ static inline bool inet_addr_multicast(const union inet_addr *ipa)
 
 #else /* !CONFIG_IPV6 */
 
-static inline
-bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
-{
-	return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
-}
-
 static inline bool inet_addr_any(const union inet_addr *ipa)
 {
 	return ipa->sin.sin_addr.s_addr == htonl(INADDR_ANY);
@@ -82,6 +65,88 @@ static inline bool inet_addr_multicast(const union inet_addr *ipa)
 }
 #endif
 
+/**
+ * inet_addr_copy - copy the address portion of one inet_addr to another
+ * @dst: destination sockaddr
+ * @src: source sockaddr
+ *
+ * Just copies the address portion and family. Ignores port, scope, etc.
+ * Caller is responsible for making certain that dst is large enough to hold
+ * the address in src. Returns true if address family is supported. Returns
+ * false otherwise.
+ */
+static inline bool inet_addr_copy(union inet_addr *dst,
+				  const union inet_addr *src)
+{
+	dst->sa.sa_family = src->sa.sa_family;
+
+	switch (src->sa.sa_family) {
+	case AF_INET:
+		dst->sin.sin_addr.s_addr = src->sin.sin_addr.s_addr;
+		return true;
+#if IS_ENABLED(CONFIG_IPV6)
+	case AF_INET6:
+		dst->sin6.sin6_addr = src->sin6.sin6_addr;
+		dst->sin6.sin6_scope_id = src->sin6.sin6_scope_id;
+		return true;
+#endif
+	}
+
+	return false;
+}
+
+static inline
+unsigned short inet_addr_get_port(const union inet_addr *sap)
+{
+	switch (sap->sa.sa_family) {
+	case AF_INET:
+		return ntohs(sap->sin.sin_port);
+	case AF_INET6:
+		return ntohs(sap->sin6.sin6_port);
+	}
+	return 0;
+}
+
+static inline
+void inet_addr_set_port(union inet_addr *sap,
+			const unsigned short port)
+{
+	switch (sap->sa.sa_family) {
+	case AF_INET:
+		sap->sin.sin_port = htons(port);
+		break;
+	case AF_INET6:
+		sap->sin6.sin6_port = htons(port);
+		break;
+	}
+}
+
+bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b);
 int simple_inet_pton(const char *str, union inet_addr *addr);
 
+static inline bool sockaddr_equal(const struct sockaddr *sap1,
+				  const struct sockaddr *sap2)
+{
+	return inet_addr_equal((const union inet_addr *)sap1,
+			       (const union inet_addr *)sap2);
+}
+
+static inline bool sockaddr_copy(struct sockaddr *dst,
+				 const struct sockaddr *src)
+{
+	return inet_addr_copy((union inet_addr *)dst,
+			      (const union inet_addr *)src);
+}
+
+static inline unsigned short sockaddr_get_port(const struct sockaddr *sap)
+{
+	return inet_addr_get_port((const union inet_addr *)sap);
+}
+
+static inline void sockaddr_set_port(struct sockaddr *sap,
+				const unsigned short port)
+{
+	inet_addr_set_port((union inet_addr *)sap, port);
+}
+
 #endif
diff --git a/net/core/utils.c b/net/core/utils.c
index 22dd621..837bb18 100644
--- a/net/core/utils.c
+++ b/net/core/utils.c
@@ -374,3 +374,28 @@ int simple_inet_pton(const char *str, union inet_addr *addr)
 	return -EINVAL;
 }
 EXPORT_SYMBOL(simple_inet_pton);
+
+#if IS_ENABLED(CONFIG_IPV6)
+bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
+{
+	if (a->sa.sa_family != b->sa.sa_family)
+		return false;
+	else if (a->sa.sa_family == AF_INET6) {
+		if (!ipv6_addr_equal(&a->sin6.sin6_addr, &b->sin6.sin6_addr))
+			return false;
+		else if (__ipv6_addr_needs_scope_id(__ipv6_addr_type(&a->sin6.sin6_addr)))
+			return a->sin6.sin6_scope_id == b->sin6.sin6_scope_id;
+		else
+			return true;
+	} else
+		return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
+}
+#else
+bool inet_addr_equal(const union inet_addr *a, const union inet_addr *b)
+{
+	if (a->sa.sa_family == AF_UNSPEC)
+		return a->sa.sa_family == b->sa.sa_family;
+	return a->sin.sin_addr.s_addr == b->sin.sin_addr.s_addr;
+}
+#endif
+EXPORT_SYMBOL(inet_addr_equal);
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index ecbc4e3..49fe013 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -1137,7 +1137,7 @@ int rpc_localaddr(struct rpc_clnt *clnt, struct sockaddr *buf, size_t buflen)
 	net = get_net(xprt->xprt_net);
 	rcu_read_unlock();
 
-	rpc_set_port(sap, 0);
+	sockaddr_set_port(sap, 0);
 	err = rpc_sockname(net, sap, salen, buf, buflen);
 	put_net(net);
 	if (err != 0)
diff --git a/net/sunrpc/rpcb_clnt.c b/net/sunrpc/rpcb_clnt.c
index 1891a10..8078161 100644
--- a/net/sunrpc/rpcb_clnt.c
+++ b/net/sunrpc/rpcb_clnt.c
@@ -971,7 +971,7 @@ static int rpcb_dec_getaddr(struct rpc_rqst *req, struct xdr_stream *xdr,
 	if (rpc_uaddr2sockaddr(req->rq_xprt->xprt_net, (char *)p, len,
 				sap, sizeof(address)) == 0)
 		goto out_fail;
-	rpcb->r_port = rpc_get_port(sap);
+	rpcb->r_port = sockaddr_get_port(sap);
 
 	return 0;
 
diff --git a/net/sunrpc/xprtrdma/transport.c b/net/sunrpc/xprtrdma/transport.c
index 285dc08..aa09a36 100644
--- a/net/sunrpc/xprtrdma/transport.c
+++ b/net/sunrpc/xprtrdma/transport.c
@@ -162,7 +162,7 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt)
 	(void)rpc_ntop(sap, buf, sizeof(buf));
 	xprt->address_strings[RPC_DISPLAY_ADDR] = kstrdup(buf, GFP_KERNEL);
 
-	snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap));
+	snprintf(buf, sizeof(buf), "%u", sockaddr_get_port(sap));
 	xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL);
 
 	xprt->address_strings[RPC_DISPLAY_PROTO] = "rdma";
@@ -170,7 +170,7 @@ xprt_rdma_format_addresses(struct rpc_xprt *xprt)
 	snprintf(buf, sizeof(buf), "%08x", ntohl(sin->sin_addr.s_addr));
 	xprt->address_strings[RPC_DISPLAY_HEX_ADDR] = kstrdup(buf, GFP_KERNEL);
 
-	snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap));
+	snprintf(buf, sizeof(buf), "%4hx", sockaddr_get_port(sap));
 	xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);
 
 	/* netid */
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c
index d6656d7..5922c8b 100644
--- a/net/sunrpc/xprtsock.c
+++ b/net/sunrpc/xprtsock.c
@@ -333,10 +333,10 @@ static void xs_format_common_peer_ports(struct rpc_xprt *xprt)
 	struct sockaddr *sap = xs_addr(xprt);
 	char buf[128];
 
-	snprintf(buf, sizeof(buf), "%u", rpc_get_port(sap));
+	snprintf(buf, sizeof(buf), "%u", sockaddr_get_port(sap));
 	xprt->address_strings[RPC_DISPLAY_PORT] = kstrdup(buf, GFP_KERNEL);
 
-	snprintf(buf, sizeof(buf), "%4hx", rpc_get_port(sap));
+	snprintf(buf, sizeof(buf), "%4hx", sockaddr_get_port(sap));
 	xprt->address_strings[RPC_DISPLAY_HEX_PORT] = kstrdup(buf, GFP_KERNEL);
 }
 
@@ -1674,7 +1674,7 @@ static void xs_set_port(struct rpc_xprt *xprt, unsigned short port)
 {
 	dprintk("RPC:       setting port for xprt %p to %u\n", xprt, port);
 
-	rpc_set_port(xs_addr(xprt), port);
+	sockaddr_set_port(xs_addr(xprt), port);
 	xs_update_peer_port(xprt);
 }
 
@@ -1706,7 +1706,7 @@ static int xs_bind(struct sock_xprt *transport, struct socket *sock)
 
 	memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen);
 	do {
-		rpc_set_port((struct sockaddr *)&myaddr, port);
+		sockaddr_set_port((struct sockaddr *)&myaddr, port);
 		err = kernel_bind(sock, (struct sockaddr *)&myaddr,
 				transport->xprt.addrlen);
 		if (port == 0)
-- 
1.7.7.6

^ permalink raw reply related

* [Patch net-next v3 8/9] sctp: use generic union inet_addr
From: Cong Wang @ 2013-08-19 10:14 UTC (permalink / raw)
  To: netdev
  Cc: David S. Miller, Daniel Borkmann, Vlad Yasevich, Neil Horman,
	linux-sctp, Cong Wang
In-Reply-To: <1376907278-26377-1-git-send-email-amwang@redhat.com>

From: Cong Wang <amwang@redhat.com>

sctp has its own union sctp_addr which is nearly same
with the generic union inet_addr, so just convert it
to the generic one.

Sorry for the big patch, it is not easy to split it. Most
of the patch simply does s/union sctp_addr/union inet_addr/
and some adjustments for the fields.

The address family specific ops, ->cmp_addr(), ->is_any() etc.,
are removed, since we have generic helpers, they are unnecessary.

Cc: Daniel Borkmann <dborkman@redhat.com>
Cc: Vlad Yasevich <vyasevich@gmail.com>
Cc: Neil Horman <nhorman@tuxdriver.com>
Cc: linux-sctp@vger.kernel.org
Signed-off-by: Cong Wang <amwang@redhat.com>
---
 include/net/sctp/sctp.h    |   22 ++--
 include/net/sctp/sm.h      |    4 +-
 include/net/sctp/structs.h |  132 +++++++++++-------------
 net/sctp/associola.c       |   26 +++---
 net/sctp/bind_addr.c       |   61 ++++--------
 net/sctp/endpointola.c     |   12 +-
 net/sctp/input.c           |   56 +++++-----
 net/sctp/ipv6.c            |  240 +++++++++++++++++++-------------------------
 net/sctp/outqueue.c        |    4 +-
 net/sctp/proc.c            |   10 +-
 net/sctp/protocol.c        |  198 ++++++++++++++----------------------
 net/sctp/sm_make_chunk.c   |   54 +++++-----
 net/sctp/sm_statefuns.c    |   23 ++---
 net/sctp/socket.c          |  126 +++++++++++++-----------
 net/sctp/transport.c       |   12 +-
 net/sctp/ulpevent.c        |    2 +-
 16 files changed, 437 insertions(+), 545 deletions(-)

diff --git a/include/net/sctp/sctp.h b/include/net/sctp/sctp.h
index 3794c5a..0472336 100644
--- a/include/net/sctp/sctp.h
+++ b/include/net/sctp/sctp.h
@@ -584,22 +584,22 @@ static inline int __sctp_sstate(const struct sock *sk, sctp_sock_state_t state)
 }
 
 /* Map v4-mapped v6 address back to v4 address */
-static inline void sctp_v6_map_v4(union sctp_addr *addr)
+static inline void sctp_v6_map_v4(union inet_addr *addr)
 {
-	addr->v4.sin_family = AF_INET;
-	addr->v4.sin_port = addr->v6.sin6_port;
-	addr->v4.sin_addr.s_addr = addr->v6.sin6_addr.s6_addr32[3];
+	addr->sin.sin_family = AF_INET;
+	addr->sin.sin_port = addr->sin6.sin6_port;
+	addr->sin.sin_addr.s_addr = addr->sin6.sin6_addr.s6_addr32[3];
 }
 
 /* Map v4 address to v4-mapped v6 address */
-static inline void sctp_v4_map_v6(union sctp_addr *addr)
+static inline void sctp_v4_map_v6(union inet_addr *addr)
 {
-	addr->v6.sin6_family = AF_INET6;
-	addr->v6.sin6_port = addr->v4.sin_port;
-	addr->v6.sin6_addr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
-	addr->v6.sin6_addr.s6_addr32[0] = 0;
-	addr->v6.sin6_addr.s6_addr32[1] = 0;
-	addr->v6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
+	addr->sin6.sin6_family = AF_INET6;
+	addr->sin6.sin6_port = addr->sin.sin_port;
+	addr->sin6.sin6_addr.s6_addr32[3] = addr->sin.sin_addr.s_addr;
+	addr->sin6.sin6_addr.s6_addr32[0] = 0;
+	addr->sin6.sin6_addr.s6_addr32[1] = 0;
+	addr->sin6.sin6_addr.s6_addr32[2] = htonl(0x0000ffff);
 }
 
 /* The cookie is always 0 since this is how it's used in the
diff --git a/include/net/sctp/sm.h b/include/net/sctp/sm.h
index 4ef75af..63ed797 100644
--- a/include/net/sctp/sm.h
+++ b/include/net/sctp/sm.h
@@ -244,11 +244,11 @@ struct sctp_chunk *sctp_make_op_error(const struct sctp_association *,
 				 size_t reserve_tail);
 
 struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *,
-					      union sctp_addr *,
+					      union inet_addr *,
 					      struct sockaddr *,
 					      int, __be16);
 struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
-					     union sctp_addr *addr);
+					     union inet_addr *addr);
 int sctp_verify_asconf(const struct sctp_association *asoc,
 		       struct sctp_paramhdr *param_hdr, void *chunk_end,
 		       struct sctp_paramhdr **errp);
diff --git a/include/net/sctp/structs.h b/include/net/sctp/structs.h
index 422db6c..8dfaa39 100644
--- a/include/net/sctp/structs.h
+++ b/include/net/sctp/structs.h
@@ -59,15 +59,7 @@
 #include <linux/workqueue.h>	/* We need tq_struct.	 */
 #include <linux/sctp.h>		/* We need sctp* header structs.  */
 #include <net/sctp/auth.h>	/* We need auth specific structs */
-
-/* A convenience structure for handling sockaddr structures.
- * We should wean ourselves off this.
- */
-union sctp_addr {
-	struct sockaddr_in v4;
-	struct sockaddr_in6 v6;
-	struct sockaddr sa;
-};
+#include <net/inet_addr.h>
 
 /* Forward declarations for data structures. */
 struct sctp_globals;
@@ -290,7 +282,7 @@ struct sctp_cookie {
 	__u32 initial_tsn;
 
 	/* This holds the originating address of the INIT packet.  */
-	union sctp_addr peer_addr;
+	union inet_addr peer_addr;
 
 	/* IG Section 2.35.3 
 	 * Include the source port of the INIT-ACK
@@ -366,7 +358,7 @@ union sctp_params {
  */
 typedef struct sctp_sender_hb_info {
 	struct sctp_paramhdr param_hdr;
-	union sctp_addr daddr;
+	union inet_addr daddr;
 	unsigned long sent_at;
 	__u64 hb_nonce;
 } __packed sctp_sender_hb_info_t;
@@ -447,7 +439,7 @@ struct sctp_af {
 					 char __user *optval,
 					 int __user *optlen);
 	void		(*get_dst)	(struct sctp_transport *t,
-					 union sctp_addr *saddr,
+					 union inet_addr *saddr,
 					 struct flowi *fl,
 					 struct sock *sk);
 	void		(*get_saddr)	(struct sctp_sock *sk,
@@ -455,36 +447,32 @@ struct sctp_af {
 					 struct flowi *fl);
 	void		(*copy_addrlist) (struct list_head *,
 					  struct net_device *);
-	int		(*cmp_addr)	(const union sctp_addr *addr1,
-					 const union sctp_addr *addr2);
-	void		(*addr_copy)	(union sctp_addr *dst,
-					 union sctp_addr *src);
-	void		(*from_skb)	(union sctp_addr *,
+	bool		(*cmp_addr)	(const union inet_addr *addr1,
+					 const union inet_addr *addr2);
+	void		(*addr_copy)	(union inet_addr *dst,
+					 union inet_addr *src);
+	void		(*from_skb)	(union inet_addr *,
 					 struct sk_buff *skb,
 					 int saddr);
-	void		(*from_sk)	(union sctp_addr *,
+	void		(*from_sk)	(union inet_addr *,
 					 struct sock *sk);
-	void		(*to_sk_saddr)	(union sctp_addr *,
+	void		(*to_sk_saddr)	(union inet_addr *,
 					 struct sock *sk);
-	void		(*to_sk_daddr)	(union sctp_addr *,
+	void		(*to_sk_daddr)	(union inet_addr *,
 					 struct sock *sk);
-	void		(*from_addr_param) (union sctp_addr *,
+	void		(*from_addr_param) (union inet_addr *,
 					    union sctp_addr_param *,
 					    __be16 port, int iif);
-	int		(*to_addr_param) (const union sctp_addr *,
+	int		(*to_addr_param) (const union inet_addr *,
 					  union sctp_addr_param *); 
-	int		(*addr_valid)	(union sctp_addr *,
+	int		(*addr_valid)	(union inet_addr *,
 					 struct sctp_sock *,
 					 const struct sk_buff *);
-	sctp_scope_t	(*scope) (union sctp_addr *);
-	void		(*inaddr_any)	(union sctp_addr *, __be16);
-	int		(*is_any)	(const union sctp_addr *);
-	int		(*available)	(union sctp_addr *,
+	sctp_scope_t	(*scope) (union inet_addr *);
+	int		(*available)	(union inet_addr *,
 					 struct sctp_sock *);
 	int		(*skb_iif)	(const struct sk_buff *sk);
 	int		(*is_ce)	(const struct sk_buff *sk);
-	void		(*seq_dump_addr)(struct seq_file *seq,
-					 union sctp_addr *addr);
 	void		(*ecn_capable)(struct sock *sk);
 	__u16		net_header_len;
 	int		sockaddr_len;
@@ -500,15 +488,15 @@ struct sctp_pf {
 	void (*event_msgname)(struct sctp_ulpevent *, char *, int *);
 	void (*skb_msgname)  (struct sk_buff *, char *, int *);
 	int  (*af_supported) (sa_family_t, struct sctp_sock *);
-	int  (*cmp_addr) (const union sctp_addr *,
-			  const union sctp_addr *,
+	int  (*cmp_addr) (const union inet_addr *,
+			  const union inet_addr *,
 			  struct sctp_sock *);
-	int  (*bind_verify) (struct sctp_sock *, union sctp_addr *);
-	int  (*send_verify) (struct sctp_sock *, union sctp_addr *);
+	int  (*bind_verify) (struct sctp_sock *, union inet_addr *);
+	int  (*send_verify) (struct sctp_sock *, union inet_addr *);
 	int  (*supported_addrs)(const struct sctp_sock *, __be16 *);
 	struct sock *(*create_accept_sk) (struct sock *sk,
 					  struct sctp_association *asoc);
-	void (*addr_v4map) (struct sctp_sock *, union sctp_addr *);
+	void (*addr_v4map) (struct sctp_sock *, union inet_addr *);
 	struct sctp_af *af;
 };
 
@@ -607,9 +595,9 @@ struct sctp_chunk {
 	unsigned long sent_at;
 
 	/* What is the origin IP address for this chunk?  */
-	union sctp_addr source;
+	union inet_addr source;
 	/* Destination address for this chunk. */
-	union sctp_addr dest;
+	union inet_addr dest;
 
 	/* For outbound message, track all fragments for SEND_FAILED. */
 	struct sctp_datamsg *msg;
@@ -655,9 +643,9 @@ void  *sctp_addto_chunk_fixed(struct sctp_chunk *, int len, const void *data);
 struct sctp_chunk *sctp_chunkify(struct sk_buff *,
 				 const struct sctp_association *,
 				 struct sock *);
-void sctp_init_addrs(struct sctp_chunk *, union sctp_addr *,
-		     union sctp_addr *);
-const union sctp_addr *sctp_source(const struct sctp_chunk *chunk);
+void sctp_init_addrs(struct sctp_chunk *, union inet_addr *,
+		     union inet_addr *);
+const union inet_addr *sctp_source(const struct sctp_chunk *chunk);
 
 enum {
 	SCTP_ADDR_NEW,		/* new address added to assoc/ep */
@@ -669,7 +657,7 @@ enum {
 struct sctp_sockaddr_entry {
 	struct list_head list;
 	struct rcu_head	rcu;
-	union sctp_addr a;
+	union inet_addr a;
 	__u8 state;
 	__u8 valid;
 };
@@ -728,7 +716,7 @@ static inline int sctp_packet_empty(struct sctp_packet *packet)
 }
 
 /* This represents a remote transport address.
- * For local transport addresses, we just use union sctp_addr.
+ * For local transport addresses, we just use union inet_addr.
  *
  * RFC2960 Section 1.4 Key Terms
  *
@@ -781,7 +769,7 @@ struct sctp_transport {
 	struct flowi fl;
 
 	/* This is the peer's IP address and port. */
-	union sctp_addr ipaddr;
+	union inet_addr ipaddr;
 
 	/* These are the functions we call to handle LLP stuff.	 */
 	struct sctp_af *af_specific;
@@ -830,7 +818,7 @@ struct sctp_transport {
 	/* Destination */
 	struct dst_entry *dst;
 	/* Source address. */
-	union sctp_addr saddr;
+	union inet_addr saddr;
 
 	/* Heartbeat interval: The endpoint sends out a Heartbeat chunk to
 	 * the destination address every heartbeat interval.
@@ -943,11 +931,11 @@ struct sctp_transport {
 	struct rcu_head rcu;
 };
 
-struct sctp_transport *sctp_transport_new(struct net *, const union sctp_addr *,
+struct sctp_transport *sctp_transport_new(struct net *, const union inet_addr *,
 					  gfp_t);
 void sctp_transport_set_owner(struct sctp_transport *,
 			      struct sctp_association *);
-void sctp_transport_route(struct sctp_transport *, union sctp_addr *,
+void sctp_transport_route(struct sctp_transport *, union inet_addr *,
 			  struct sctp_sock *);
 void sctp_transport_pmtu(struct sctp_transport *, struct sock *sk);
 void sctp_transport_free(struct sctp_transport *);
@@ -1098,17 +1086,17 @@ int sctp_bind_addr_copy(struct net *net, struct sctp_bind_addr *dest,
 int sctp_bind_addr_dup(struct sctp_bind_addr *dest,
 			const struct sctp_bind_addr *src,
 			gfp_t gfp);
-int sctp_add_bind_addr(struct sctp_bind_addr *, union sctp_addr *,
+int sctp_add_bind_addr(struct sctp_bind_addr *, union inet_addr *,
 		       __u8 addr_state, gfp_t gfp);
-int sctp_del_bind_addr(struct sctp_bind_addr *, union sctp_addr *);
-int sctp_bind_addr_match(struct sctp_bind_addr *, const union sctp_addr *,
+int sctp_del_bind_addr(struct sctp_bind_addr *, union inet_addr *);
+int sctp_bind_addr_match(struct sctp_bind_addr *, const union inet_addr *,
 			 struct sctp_sock *);
-int sctp_bind_addr_conflict(struct sctp_bind_addr *, const union sctp_addr *,
+int sctp_bind_addr_conflict(struct sctp_bind_addr *, const union inet_addr *,
 			 struct sctp_sock *, struct sctp_sock *);
 int sctp_bind_addr_state(const struct sctp_bind_addr *bp,
-			 const union sctp_addr *addr);
-union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
-					const union sctp_addr	*addrs,
+			 const union inet_addr *addr);
+union inet_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
+					const union inet_addr	*addrs,
 					int			addrcnt,
 					struct sctp_sock	*opt);
 union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
@@ -1117,10 +1105,10 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
 int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw, int len,
 			   __u16 port, gfp_t gfp);
 
-sctp_scope_t sctp_scope(const union sctp_addr *);
-int sctp_in_scope(struct net *net, const union sctp_addr *addr, const sctp_scope_t scope);
-int sctp_is_any(struct sock *sk, const union sctp_addr *addr);
-int sctp_addr_is_valid(const union sctp_addr *addr);
+sctp_scope_t sctp_scope(const union inet_addr *);
+int sctp_in_scope(struct net *net, const union inet_addr *addr, const sctp_scope_t scope);
+int sctp_is_any(struct sock *sk, const union inet_addr *addr);
+int sctp_addr_is_valid(const union inet_addr *addr);
 int sctp_is_ep_boundall(struct sock *sk);
 
 
@@ -1266,20 +1254,20 @@ void sctp_endpoint_hold(struct sctp_endpoint *);
 void sctp_endpoint_add_asoc(struct sctp_endpoint *, struct sctp_association *);
 struct sctp_association *sctp_endpoint_lookup_assoc(
 	const struct sctp_endpoint *ep,
-	const union sctp_addr *paddr,
+	const union inet_addr *paddr,
 	struct sctp_transport **);
 int sctp_endpoint_is_peeled_off(struct sctp_endpoint *,
-				const union sctp_addr *);
+				const union inet_addr *);
 struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *,
-					struct net *, const union sctp_addr *);
-int sctp_has_association(struct net *net, const union sctp_addr *laddr,
-			 const union sctp_addr *paddr);
+					struct net *, const union inet_addr *);
+int sctp_has_association(struct net *net, const union inet_addr *laddr,
+			 const union inet_addr *paddr);
 
 int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
 		     sctp_cid_t, sctp_init_chunk_t *peer_init,
 		     struct sctp_chunk *chunk, struct sctp_chunk **err_chunk);
 int sctp_process_init(struct sctp_association *, struct sctp_chunk *chunk,
-		      const union sctp_addr *peer,
+		      const union inet_addr *peer,
 		      sctp_init_chunk_t *init, gfp_t gfp);
 __u32 sctp_generate_tag(const struct sctp_endpoint *);
 __u32 sctp_generate_tsn(const struct sctp_endpoint *);
@@ -1419,7 +1407,7 @@ struct sctp_association {
 		/* Cache the primary path address here, when we
 		 * need a an address for msg_name.
 		 */
-		union sctp_addr primary_addr;
+		union inet_addr primary_addr;
 
 		/* active_path
 		 *   The path that we are currently using to
@@ -1820,7 +1808,7 @@ struct sctp_association {
 	 * after reaching 4294967295.
 	 */
 	__u32 addip_serial;
-	union sctp_addr *asconf_addr_del_pending;
+	union inet_addr *asconf_addr_del_pending;
 	int src_out_of_asoc_ok;
 	struct sctp_transport *new_transport;
 
@@ -1879,15 +1867,15 @@ struct sctp_transport *sctp_assoc_choose_alter_transport(
 	struct sctp_association *, struct sctp_transport *);
 void sctp_assoc_update_retran_path(struct sctp_association *);
 struct sctp_transport *sctp_assoc_lookup_paddr(const struct sctp_association *,
-					  const union sctp_addr *);
+					  const union inet_addr *);
 int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
-			    const union sctp_addr *laddr);
+			    const union inet_addr *laddr);
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *,
-				     const union sctp_addr *address,
+				     const union inet_addr *address,
 				     const gfp_t gfp,
 				     const int peer_state);
 void sctp_assoc_del_peer(struct sctp_association *asoc,
-			 const union sctp_addr *addr);
+			 const union inet_addr *addr);
 void sctp_assoc_rm_peer(struct sctp_association *asoc,
 			 struct sctp_transport *peer);
 void sctp_assoc_control_transport(struct sctp_association *,
@@ -1896,8 +1884,8 @@ void sctp_assoc_control_transport(struct sctp_association *,
 struct sctp_transport *sctp_assoc_lookup_tsn(struct sctp_association *, __u32);
 struct sctp_transport *sctp_assoc_is_match(struct sctp_association *,
 					   struct net *,
-					   const union sctp_addr *,
-					   const union sctp_addr *);
+					   const union inet_addr *,
+					   const union inet_addr *);
 void sctp_assoc_migrate(struct sctp_association *, struct sock *);
 void sctp_assoc_update(struct sctp_association *old,
 		       struct sctp_association *new);
@@ -1923,8 +1911,8 @@ struct sctp_chunk *sctp_assoc_lookup_asconf_ack(
 					__be32 serial);
 void sctp_asconf_queue_teardown(struct sctp_association *asoc);
 
-int sctp_cmp_addr_exact(const union sctp_addr *ss1,
-			const union sctp_addr *ss2);
+int sctp_cmp_addr_exact(const union inet_addr *ss1,
+			const union inet_addr *ss2);
 struct sctp_chunk *sctp_get_ecne_prepend(struct sctp_association *asoc);
 
 /* A convenience structure to parse out SCTP specific CMSGs. */
diff --git a/net/sctp/associola.c b/net/sctp/associola.c
index a514612..ed0a9a7 100644
--- a/net/sctp/associola.c
+++ b/net/sctp/associola.c
@@ -487,7 +487,7 @@ void sctp_assoc_set_primary(struct sctp_association *asoc,
 
 	/* Set a default msg_name for events. */
 	memcpy(&asoc->peer.primary_addr, &transport->ipaddr,
-	       sizeof(union sctp_addr));
+	       sizeof(union inet_addr));
 
 	/* If the primary path is changing, assume that the
 	 * user wants to use this new path.
@@ -617,7 +617,7 @@ void sctp_assoc_rm_peer(struct sctp_association *asoc,
 
 /* Add a transport address to an association.  */
 struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
-					   const union sctp_addr *addr,
+					   const union inet_addr *addr,
 					   const gfp_t gfp,
 					   const int peer_state)
 {
@@ -629,7 +629,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 	sp = sctp_sk(asoc->base.sk);
 
 	/* AF_INET and AF_INET6 share common port field. */
-	port = ntohs(addr->v4.sin_port);
+	port = ntohs(addr->sin.sin_port);
 
 	pr_debug("%s: association:%p addr:%pIApc state:%d\n", __func__,
 		 asoc, &addr->sa, peer_state);
@@ -761,7 +761,7 @@ struct sctp_transport *sctp_assoc_add_peer(struct sctp_association *asoc,
 
 /* Delete a transport address from an association.  */
 void sctp_assoc_del_peer(struct sctp_association *asoc,
-			 const union sctp_addr *addr)
+			 const union inet_addr *addr)
 {
 	struct list_head	*pos;
 	struct list_head	*temp;
@@ -780,7 +780,7 @@ void sctp_assoc_del_peer(struct sctp_association *asoc,
 /* Lookup a transport by address. */
 struct sctp_transport *sctp_assoc_lookup_paddr(
 					const struct sctp_association *asoc,
-					const union sctp_addr *address)
+					const union inet_addr *address)
 {
 	struct sctp_transport *t;
 
@@ -977,8 +977,8 @@ __u32 sctp_association_get_next_tsn(struct sctp_association *asoc)
 /* Compare two addresses to see if they match.  Wildcard addresses
  * only match themselves.
  */
-int sctp_cmp_addr_exact(const union sctp_addr *ss1,
-			const union sctp_addr *ss2)
+int sctp_cmp_addr_exact(const union inet_addr *ss1,
+			const union inet_addr *ss2)
 {
 	struct sctp_af *af;
 
@@ -1069,13 +1069,13 @@ out:
 /* Is this the association we are looking for? */
 struct sctp_transport *sctp_assoc_is_match(struct sctp_association *asoc,
 					   struct net *net,
-					   const union sctp_addr *laddr,
-					   const union sctp_addr *paddr)
+					   const union inet_addr *laddr,
+					   const union inet_addr *paddr)
 {
 	struct sctp_transport *transport;
 
-	if ((htons(asoc->base.bind_addr.port) == laddr->v4.sin_port) &&
-	    (htons(asoc->peer.port) == paddr->v4.sin_port) &&
+	if ((htons(asoc->base.bind_addr.port) == laddr->sin.sin_port) &&
+	    (htons(asoc->peer.port) == paddr->sin.sin_port) &&
 	    net_eq(sock_net(asoc->base.sk), net)) {
 		transport = sctp_assoc_lookup_paddr(asoc, paddr);
 		if (!transport)
@@ -1551,11 +1551,11 @@ int sctp_assoc_set_bind_addr_from_cookie(struct sctp_association *asoc,
 
 /* Lookup laddr in the bind address list of an association. */
 int sctp_assoc_lookup_laddr(struct sctp_association *asoc,
-			    const union sctp_addr *laddr)
+			    const union inet_addr *laddr)
 {
 	int found = 0;
 
-	if ((asoc->base.bind_addr.port == ntohs(laddr->v4.sin_port)) &&
+	if ((asoc->base.bind_addr.port == ntohs(laddr->sin.sin_port)) &&
 	    sctp_bind_addr_match(&asoc->base.bind_addr, laddr,
 				 sctp_sk(asoc->base.sk)))
 		found = 1;
diff --git a/net/sctp/bind_addr.c b/net/sctp/bind_addr.c
index 077bb07..03d8f85 100644
--- a/net/sctp/bind_addr.c
+++ b/net/sctp/bind_addr.c
@@ -47,7 +47,7 @@
 
 /* Forward declarations for internal helpers. */
 static int sctp_copy_one_addr(struct net *, struct sctp_bind_addr *,
-			      union sctp_addr *, sctp_scope_t scope, gfp_t gfp,
+			      union inet_addr *, sctp_scope_t scope, gfp_t gfp,
 			      int flags);
 static void sctp_bind_addr_clean(struct sctp_bind_addr *);
 
@@ -150,7 +150,7 @@ void sctp_bind_addr_free(struct sctp_bind_addr *bp)
 }
 
 /* Add an address to the bind address list in the SCTP_bind_addr structure. */
-int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
+int sctp_add_bind_addr(struct sctp_bind_addr *bp, union inet_addr *new,
 		       __u8 addr_state, gfp_t gfp)
 {
 	struct sctp_sockaddr_entry *addr;
@@ -165,8 +165,8 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
 	/* Fix up the port if it has not yet been set.
 	 * Both v4 and v6 have the port at the same offset.
 	 */
-	if (!addr->a.v4.sin_port)
-		addr->a.v4.sin_port = htons(bp->port);
+	if (!addr->a.sin.sin_port)
+		addr->a.sin.sin_port = htons(bp->port);
 
 	addr->state = addr_state;
 	addr->valid = 1;
@@ -185,7 +185,7 @@ int sctp_add_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *new,
 /* Delete an address from the bind address list in the SCTP_bind_addr
  * structure.
  */
-int sctp_del_bind_addr(struct sctp_bind_addr *bp, union sctp_addr *del_addr)
+int sctp_del_bind_addr(struct sctp_bind_addr *bp, union inet_addr *del_addr)
 {
 	struct sctp_sockaddr_entry *addr, *temp;
 	int found = 0;
@@ -253,7 +253,7 @@ union sctp_params sctp_bind_addrs_to_raw(const struct sctp_bind_addr *bp,
 	addrparms = retval;
 
 	list_for_each_entry(addr, &bp->address_list, list) {
-		af = sctp_get_af_specific(addr->a.v4.sin_family);
+		af = sctp_get_af_specific(addr->a.sin.sin_family);
 		len = af->to_addr_param(&addr->a, &rawaddr);
 		memcpy(addrparms.v, &rawaddr, len);
 		addrparms.v += len;
@@ -274,7 +274,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
 {
 	union sctp_addr_param *rawaddr;
 	struct sctp_paramhdr *param;
-	union sctp_addr addr;
+	union inet_addr addr;
 	int retval = 0;
 	int len;
 	struct sctp_af *af;
@@ -313,7 +313,7 @@ int sctp_raw_to_bind_addrs(struct sctp_bind_addr *bp, __u8 *raw_addr_list,
 
 /* Does this contain a specified address?  Allow wildcarding. */
 int sctp_bind_addr_match(struct sctp_bind_addr *bp,
-			 const union sctp_addr *addr,
+			 const union inet_addr *addr,
 			 struct sctp_sock *opt)
 {
 	struct sctp_sockaddr_entry *laddr;
@@ -337,7 +337,7 @@ int sctp_bind_addr_match(struct sctp_bind_addr *bp,
  * the bp.
  */
 int sctp_bind_addr_conflict(struct sctp_bind_addr *bp,
-			    const union sctp_addr *addr,
+			    const union inet_addr *addr,
 			    struct sctp_sock *bp_sp,
 			    struct sctp_sock *addr_sp)
 {
@@ -372,7 +372,7 @@ int sctp_bind_addr_conflict(struct sctp_bind_addr *bp,
 
 /* Get the state of the entry in the bind_addr_list */
 int sctp_bind_addr_state(const struct sctp_bind_addr *bp,
-			 const union sctp_addr *addr)
+			 const union inet_addr *addr)
 {
 	struct sctp_sockaddr_entry *laddr;
 	struct sctp_af *af;
@@ -399,13 +399,13 @@ int sctp_bind_addr_state(const struct sctp_bind_addr *bp,
 /* Find the first address in the bind address list that is not present in
  * the addrs packed array.
  */
-union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
-					const union sctp_addr	*addrs,
+union inet_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
+					const union inet_addr	*addrs,
 					int			addrcnt,
 					struct sctp_sock	*opt)
 {
 	struct sctp_sockaddr_entry	*laddr;
-	union sctp_addr			*addr;
+	union inet_addr			*addr;
 	void 				*addr_buf;
 	struct sctp_af			*af;
 	int				i;
@@ -415,10 +415,10 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
 	 * can't change.
 	 */
 	list_for_each_entry(laddr, &bp->address_list, list) {
-		addr_buf = (union sctp_addr *)addrs;
+		addr_buf = (union inet_addr *)addrs;
 		for (i = 0; i < addrcnt; i++) {
 			addr = addr_buf;
-			af = sctp_get_af_specific(addr->v4.sin_family);
+			af = sctp_get_af_specific(addr->sin.sin_family);
 			if (!af)
 				break;
 
@@ -436,13 +436,13 @@ union sctp_addr *sctp_find_unmatch_addr(struct sctp_bind_addr	*bp,
 
 /* Copy out addresses from the global local address list. */
 static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
-			      union sctp_addr *addr,
+			      union inet_addr *addr,
 			      sctp_scope_t scope, gfp_t gfp,
 			      int flags)
 {
 	int error = 0;
 
-	if (sctp_is_any(NULL, addr)) {
+	if (inet_addr_any(addr)) {
 		error = sctp_copy_local_addr_list(net, dest, scope, gfp, flags);
 	} else if (sctp_in_scope(net, addr, scope)) {
 		/* Now that the address is in scope, check to see if
@@ -461,27 +461,8 @@ static int sctp_copy_one_addr(struct net *net, struct sctp_bind_addr *dest,
 	return error;
 }
 
-/* Is this a wildcard address?  */
-int sctp_is_any(struct sock *sk, const union sctp_addr *addr)
-{
-	unsigned short fam = 0;
-	struct sctp_af *af;
-
-	/* Try to get the right address family */
-	if (addr->sa.sa_family != AF_UNSPEC)
-		fam = addr->sa.sa_family;
-	else if (sk)
-		fam = sk->sk_family;
-
-	af = sctp_get_af_specific(fam);
-	if (!af)
-		return 0;
-
-	return af->is_any(addr);
-}
-
 /* Is 'addr' valid for 'scope'?  */
-int sctp_in_scope(struct net *net, const union sctp_addr *addr, sctp_scope_t scope)
+int sctp_in_scope(struct net *net, const union inet_addr *addr, sctp_scope_t scope)
 {
 	sctp_scope_t addr_scope = sctp_scope(addr);
 
@@ -530,7 +511,7 @@ int sctp_is_ep_boundall(struct sock *sk)
 	if (sctp_list_single_entry(&bp->address_list)) {
 		addr = list_entry(bp->address_list.next,
 				  struct sctp_sockaddr_entry, list);
-		if (sctp_is_any(sk, &addr->a))
+		if (inet_addr_any(&addr->a))
 			return 1;
 	}
 	return 0;
@@ -541,7 +522,7 @@ int sctp_is_ep_boundall(struct sock *sk)
  ********************************************************************/
 
 /* What is the scope of 'addr'?  */
-sctp_scope_t sctp_scope(const union sctp_addr *addr)
+sctp_scope_t sctp_scope(const union inet_addr *addr)
 {
 	struct sctp_af *af;
 
@@ -549,5 +530,5 @@ sctp_scope_t sctp_scope(const union sctp_addr *addr)
 	if (!af)
 		return SCTP_SCOPE_UNUSABLE;
 
-	return af->scope((union sctp_addr *)addr);
+	return af->scope((union inet_addr *)addr);
 }
diff --git a/net/sctp/endpointola.c b/net/sctp/endpointola.c
index 09b8daa..3b19e06 100644
--- a/net/sctp/endpointola.c
+++ b/net/sctp/endpointola.c
@@ -299,11 +299,11 @@ void sctp_endpoint_put(struct sctp_endpoint *ep)
 /* Is this the endpoint we are looking for?  */
 struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
 					       struct net *net,
-					       const union sctp_addr *laddr)
+					       const union inet_addr *laddr)
 {
 	struct sctp_endpoint *retval = NULL;
 
-	if ((htons(ep->base.bind_addr.port) == laddr->v4.sin_port) &&
+	if ((htons(ep->base.bind_addr.port) == laddr->sin.sin_port) &&
 	    net_eq(sock_net(ep->base.sk), net)) {
 		if (sctp_bind_addr_match(&ep->base.bind_addr, laddr,
 					 sctp_sk(ep->base.sk)))
@@ -319,7 +319,7 @@ struct sctp_endpoint *sctp_endpoint_is_match(struct sctp_endpoint *ep,
  */
 static struct sctp_association *__sctp_endpoint_lookup_assoc(
 	const struct sctp_endpoint *ep,
-	const union sctp_addr *paddr,
+	const union inet_addr *paddr,
 	struct sctp_transport **transport)
 {
 	struct sctp_association *asoc = NULL;
@@ -338,7 +338,7 @@ static struct sctp_association *__sctp_endpoint_lookup_assoc(
 	if (!ep->base.bind_addr.port)
 		goto out;
 
-	rport = ntohs(paddr->v4.sin_port);
+	rport = ntohs(paddr->sin.sin_port);
 
 	hash = sctp_assoc_hashfn(sock_net(ep->base.sk), ep->base.bind_addr.port,
 				 rport);
@@ -364,7 +364,7 @@ out:
 /* Lookup association on an endpoint based on a peer address.  BH-safe.  */
 struct sctp_association *sctp_endpoint_lookup_assoc(
 	const struct sctp_endpoint *ep,
-	const union sctp_addr *paddr,
+	const union inet_addr *paddr,
 	struct sctp_transport **transport)
 {
 	struct sctp_association *asoc;
@@ -380,7 +380,7 @@ struct sctp_association *sctp_endpoint_lookup_assoc(
  * given peer address.
  */
 int sctp_endpoint_is_peeled_off(struct sctp_endpoint *ep,
-				const union sctp_addr *paddr)
+				const union inet_addr *paddr)
 {
 	struct sctp_sockaddr_entry *addr;
 	struct sctp_bind_addr *bp;
diff --git a/net/sctp/input.c b/net/sctp/input.c
index 5f20686..2a8bae9 100644
--- a/net/sctp/input.c
+++ b/net/sctp/input.c
@@ -62,15 +62,15 @@
 static int sctp_rcv_ootb(struct sk_buff *);
 static struct sctp_association *__sctp_rcv_lookup(struct net *net,
 				      struct sk_buff *skb,
-				      const union sctp_addr *paddr,
-				      const union sctp_addr *laddr,
+				      const union inet_addr *paddr,
+				      const union inet_addr *laddr,
 				      struct sctp_transport **transportp);
 static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
-						const union sctp_addr *laddr);
+						const union inet_addr *laddr);
 static struct sctp_association *__sctp_lookup_association(
 					struct net *net,
-					const union sctp_addr *local,
-					const union sctp_addr *peer,
+					const union inet_addr *local,
+					const union inet_addr *peer,
 					struct sctp_transport **pt);
 
 static int sctp_add_backlog(struct sock *sk, struct sk_buff *skb);
@@ -114,8 +114,8 @@ int sctp_rcv(struct sk_buff *skb)
 	struct sctp_transport *transport = NULL;
 	struct sctp_chunk *chunk;
 	struct sctphdr *sh;
-	union sctp_addr src;
-	union sctp_addr dest;
+	union inet_addr src;
+	union inet_addr dest;
 	int family;
 	struct sctp_af *af;
 	struct net *net = dev_net(skb->dev);
@@ -470,8 +470,8 @@ struct sock *sctp_err_lookup(struct net *net, int family, struct sk_buff *skb,
 			     struct sctp_association **app,
 			     struct sctp_transport **tpp)
 {
-	union sctp_addr saddr;
-	union sctp_addr daddr;
+	union inet_addr saddr;
+	union inet_addr daddr;
 	struct sctp_af *af;
 	struct sock *sk = NULL;
 	struct sctp_association *asoc;
@@ -765,14 +765,14 @@ void sctp_unhash_endpoint(struct sctp_endpoint *ep)
 
 /* Look up an endpoint. */
 static struct sctp_endpoint *__sctp_rcv_lookup_endpoint(struct net *net,
-						const union sctp_addr *laddr)
+						const union inet_addr *laddr)
 {
 	struct sctp_hashbucket *head;
 	struct sctp_ep_common *epb;
 	struct sctp_endpoint *ep;
 	int hash;
 
-	hash = sctp_ep_hashfn(net, ntohs(laddr->v4.sin_port));
+	hash = sctp_ep_hashfn(net, ntohs(laddr->sin.sin_port));
 	head = &sctp_ep_hashtable[hash];
 	read_lock(&head->lock);
 	sctp_for_each_hentry(epb, &head->chain) {
@@ -853,8 +853,8 @@ void sctp_unhash_established(struct sctp_association *asoc)
 /* Look up an association. */
 static struct sctp_association *__sctp_lookup_association(
 					struct net *net,
-					const union sctp_addr *local,
-					const union sctp_addr *peer,
+					const union inet_addr *local,
+					const union inet_addr *peer,
 					struct sctp_transport **pt)
 {
 	struct sctp_hashbucket *head;
@@ -866,8 +866,8 @@ static struct sctp_association *__sctp_lookup_association(
 	/* Optimize here for direct hit, only listening connections can
 	 * have wildcards anyways.
 	 */
-	hash = sctp_assoc_hashfn(net, ntohs(local->v4.sin_port),
-				 ntohs(peer->v4.sin_port));
+	hash = sctp_assoc_hashfn(net, ntohs(local->sin.sin_port),
+				 ntohs(peer->sin.sin_port));
 	head = &sctp_assoc_hashtable[hash];
 	read_lock(&head->lock);
 	sctp_for_each_hentry(epb, &head->chain) {
@@ -891,8 +891,8 @@ hit:
 /* Look up an association. BH-safe. */
 static
 struct sctp_association *sctp_lookup_association(struct net *net,
-						 const union sctp_addr *laddr,
-						 const union sctp_addr *paddr,
+						 const union inet_addr *laddr,
+						 const union inet_addr *paddr,
 						 struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc;
@@ -906,8 +906,8 @@ struct sctp_association *sctp_lookup_association(struct net *net,
 
 /* Is there an association matching the given local and peer addresses? */
 int sctp_has_association(struct net *net,
-			 const union sctp_addr *laddr,
-			 const union sctp_addr *paddr)
+			 const union inet_addr *laddr,
+			 const union inet_addr *paddr)
 {
 	struct sctp_association *asoc;
 	struct sctp_transport *transport;
@@ -940,11 +940,11 @@ int sctp_has_association(struct net *net,
  */
 static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
 	struct sk_buff *skb,
-	const union sctp_addr *laddr, struct sctp_transport **transportp)
+	const union inet_addr *laddr, struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc;
-	union sctp_addr addr;
-	union sctp_addr *paddr = &addr;
+	union inet_addr addr;
+	union inet_addr *paddr = &addr;
 	struct sctphdr *sh = sctp_hdr(skb);
 	union sctp_params params;
 	sctp_init_chunk_t *init;
@@ -1004,14 +1004,14 @@ static struct sctp_association *__sctp_rcv_init_lookup(struct net *net,
 static struct sctp_association *__sctp_rcv_asconf_lookup(
 					struct net *net,
 					sctp_chunkhdr_t *ch,
-					const union sctp_addr *laddr,
+					const union inet_addr *laddr,
 					__be16 peer_port,
 					struct sctp_transport **transportp)
 {
 	sctp_addip_chunk_t *asconf = (struct sctp_addip_chunk *)ch;
 	struct sctp_af *af;
 	union sctp_addr_param *param;
-	union sctp_addr paddr;
+	union inet_addr paddr;
 
 	/* Skip over the ADDIP header and find the Address parameter */
 	param = (union sctp_addr_param *)(asconf + 1);
@@ -1037,7 +1037,7 @@ static struct sctp_association *__sctp_rcv_asconf_lookup(
 */
 static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
 				      struct sk_buff *skb,
-				      const union sctp_addr *laddr,
+				      const union inet_addr *laddr,
 				      struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc = NULL;
@@ -1104,7 +1104,7 @@ static struct sctp_association *__sctp_rcv_walk_lookup(struct net *net,
  */
 static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
 				      struct sk_buff *skb,
-				      const union sctp_addr *laddr,
+				      const union inet_addr *laddr,
 				      struct sctp_transport **transportp)
 {
 	sctp_chunkhdr_t *ch;
@@ -1138,8 +1138,8 @@ static struct sctp_association *__sctp_rcv_lookup_harder(struct net *net,
 /* Lookup an association for an inbound skb. */
 static struct sctp_association *__sctp_rcv_lookup(struct net *net,
 				      struct sk_buff *skb,
-				      const union sctp_addr *paddr,
-				      const union sctp_addr *laddr,
+				      const union inet_addr *paddr,
+				      const union inet_addr *laddr,
 				      struct sctp_transport **transportp)
 {
 	struct sctp_association *asoc;
diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c
index da613ce..2e1262b 100644
--- a/net/sctp/ipv6.c
+++ b/net/sctp/ipv6.c
@@ -74,12 +74,12 @@
 
 #include <asm/uaccess.h>
 
-static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
-					 union sctp_addr *s2);
-static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr,
+static inline int sctp_v6_addr_match_len(union inet_addr *s1,
+					 union inet_addr *s2);
+static void sctp_v6_to_addr(union inet_addr *addr, struct in6_addr *saddr,
 			      __be16 port);
-static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
-			    const union sctp_addr *addr2);
+static bool sctp_v6_cmp_addr(const union inet_addr *addr1,
+			     const union inet_addr *addr2);
 
 /* Event handler for inet6 address addition/deletion events.
  * The sctp_local_addr_list needs to be protocted by a spin lock since
@@ -100,10 +100,10 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 	case NETDEV_UP:
 		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
 		if (addr) {
-			addr->a.v6.sin6_family = AF_INET6;
-			addr->a.v6.sin6_port = 0;
-			addr->a.v6.sin6_addr = ifa->addr;
-			addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
+			addr->a.sin6.sin6_family = AF_INET6;
+			addr->a.sin6.sin6_port = 0;
+			addr->a.sin6.sin6_addr = ifa->addr;
+			addr->a.sin6.sin6_scope_id = ifa->idev->dev->ifindex;
 			addr->valid = 1;
 			spin_lock_bh(&net->sctp.local_addr_lock);
 			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
@@ -116,7 +116,7 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 		list_for_each_entry_safe(addr, temp,
 					&net->sctp.local_addr_list, list) {
 			if (addr->a.sa.sa_family == AF_INET6 &&
-					ipv6_addr_equal(&addr->a.v6.sin6_addr,
+					ipv6_addr_equal(&addr->a.sin6.sin6_addr,
 						&ifa->addr)) {
 				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
 				found = 1;
@@ -218,13 +218,13 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
 	/* Fill in the dest address from the route entry passed with the skb
 	 * and the source address from the transport.
 	 */
-	fl6.daddr = transport->ipaddr.v6.sin6_addr;
-	fl6.saddr = transport->saddr.v6.sin6_addr;
+	fl6.daddr = transport->ipaddr.sin6.sin6_addr;
+	fl6.saddr = transport->saddr.sin6.sin6_addr;
 
 	fl6.flowlabel = np->flow_label;
 	IP6_ECN_flow_xmit(sk, fl6.flowlabel);
 	if (ipv6_addr_type(&fl6.saddr) & IPV6_ADDR_LINKLOCAL)
-		fl6.flowi6_oif = transport->saddr.v6.sin6_scope_id;
+		fl6.flowi6_oif = transport->saddr.sin6.sin6_scope_id;
 	else
 		fl6.flowi6_oif = sk->sk_bound_dev_if;
 
@@ -247,7 +247,7 @@ static int sctp_v6_xmit(struct sk_buff *skb, struct sctp_transport *transport)
 /* Returns the dst cache entry for the given source and destination ip
  * addresses.
  */
-static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
+static void sctp_v6_get_dst(struct sctp_transport *t, union inet_addr *saddr,
 			    struct flowi *fl, struct sock *sk)
 {
 	struct sctp_association *asoc = t->asoc;
@@ -255,19 +255,19 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 	struct flowi6 *fl6 = &fl->u.ip6;
 	struct sctp_bind_addr *bp;
 	struct sctp_sockaddr_entry *laddr;
-	union sctp_addr *baddr = NULL;
-	union sctp_addr *daddr = &t->ipaddr;
-	union sctp_addr dst_saddr;
+	union inet_addr *baddr = NULL;
+	union inet_addr *daddr = &t->ipaddr;
+	union inet_addr dst_saddr;
 	__u8 matchlen = 0;
 	__u8 bmatchlen;
 	sctp_scope_t scope;
 
 	memset(fl6, 0, sizeof(struct flowi6));
-	fl6->daddr = daddr->v6.sin6_addr;
-	fl6->fl6_dport = daddr->v6.sin6_port;
+	fl6->daddr = daddr->sin6.sin6_addr;
+	fl6->fl6_dport = daddr->sin6.sin6_port;
 	fl6->flowi6_proto = IPPROTO_SCTP;
-	if (ipv6_addr_type(&daddr->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
-		fl6->flowi6_oif = daddr->v6.sin6_scope_id;
+	if (ipv6_addr_type(&daddr->sin6.sin6_addr) & IPV6_ADDR_LINKLOCAL)
+		fl6->flowi6_oif = daddr->sin6.sin6_scope_id;
 
 	pr_debug("%s: dst=%pI6 ", __func__, &fl6->daddr);
 
@@ -275,8 +275,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 		fl6->fl6_sport = htons(asoc->base.bind_addr.port);
 
 	if (saddr) {
-		fl6->saddr = saddr->v6.sin6_addr;
-		fl6->fl6_sport = saddr->v6.sin6_port;
+		fl6->saddr = saddr->sin6.sin6_addr;
+		fl6->fl6_sport = saddr->sin6.sin6_port;
 
 		pr_debug("src=%pI6 - ", &fl6->saddr);
 	}
@@ -334,8 +334,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 	}
 	rcu_read_unlock();
 	if (baddr) {
-		fl6->saddr = baddr->v6.sin6_addr;
-		fl6->fl6_sport = baddr->v6.sin6_port;
+		fl6->saddr = baddr->sin6.sin6_addr;
+		fl6->fl6_sport = baddr->sin6.sin6_port;
 		dst = ip6_dst_lookup_flow(sk, fl6, NULL, false);
 	}
 
@@ -358,10 +358,10 @@ out:
 /* Returns the number of consecutive initial bits that match in the 2 ipv6
  * addresses.
  */
-static inline int sctp_v6_addr_match_len(union sctp_addr *s1,
-					 union sctp_addr *s2)
+static inline int sctp_v6_addr_match_len(union inet_addr *s1,
+					 union inet_addr *s2)
 {
-	return ipv6_addr_diff(&s1->v6.sin6_addr, &s2->v6.sin6_addr);
+	return ipv6_addr_diff(&s1->sin6.sin6_addr, &s2->sin6.sin6_addr);
 }
 
 /* Fills in the source address(saddr) based on the destination address(daddr)
@@ -372,13 +372,13 @@ static void sctp_v6_get_saddr(struct sctp_sock *sk,
 			      struct flowi *fl)
 {
 	struct flowi6 *fl6 = &fl->u.ip6;
-	union sctp_addr *saddr = &t->saddr;
+	union inet_addr *saddr = &t->saddr;
 
 	pr_debug("%s: asoc:%p dst:%p\n", __func__, t->asoc, t->dst);
 
 	if (t->dst) {
-		saddr->v6.sin6_family = AF_INET6;
-		saddr->v6.sin6_addr = fl6->saddr;
+		saddr->sin6.sin6_family = AF_INET6;
+		saddr->sin6.sin6_addr = fl6->saddr;
 	}
 }
 
@@ -401,10 +401,10 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
 		/* Add the address to the local list.  */
 		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 		if (addr) {
-			addr->a.v6.sin6_family = AF_INET6;
-			addr->a.v6.sin6_port = 0;
-			addr->a.v6.sin6_addr = ifp->addr;
-			addr->a.v6.sin6_scope_id = dev->ifindex;
+			addr->a.sin6.sin6_family = AF_INET6;
+			addr->a.sin6.sin6_port = 0;
+			addr->a.sin6.sin6_addr = ifp->addr;
+			addr->a.sin6.sin6_scope_id = dev->ifindex;
 			addr->valid = 1;
 			INIT_LIST_HEAD(&addr->list);
 			list_add_tail(&addr->list, addrlist);
@@ -416,155 +416,132 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
 }
 
 /* Initialize a sockaddr_storage from in incoming skb. */
-static void sctp_v6_from_skb(union sctp_addr *addr,struct sk_buff *skb,
+static void sctp_v6_from_skb(union inet_addr *addr,struct sk_buff *skb,
 			     int is_saddr)
 {
 	__be16 *port;
 	struct sctphdr *sh;
 
-	port = &addr->v6.sin6_port;
-	addr->v6.sin6_family = AF_INET6;
-	addr->v6.sin6_flowinfo = 0; /* FIXME */
-	addr->v6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif;
+	port = &addr->sin6.sin6_port;
+	addr->sin6.sin6_family = AF_INET6;
+	addr->sin6.sin6_flowinfo = 0; /* FIXME */
+	addr->sin6.sin6_scope_id = ((struct inet6_skb_parm *)skb->cb)->iif;
 
 	sh = sctp_hdr(skb);
 	if (is_saddr) {
 		*port  = sh->source;
-		addr->v6.sin6_addr = ipv6_hdr(skb)->saddr;
+		addr->sin6.sin6_addr = ipv6_hdr(skb)->saddr;
 	} else {
 		*port = sh->dest;
-		addr->v6.sin6_addr = ipv6_hdr(skb)->daddr;
+		addr->sin6.sin6_addr = ipv6_hdr(skb)->daddr;
 	}
 }
 
-/* Initialize an sctp_addr from a socket. */
-static void sctp_v6_from_sk(union sctp_addr *addr, struct sock *sk)
+/* Initialize an inet_addr from a socket. */
+static void sctp_v6_from_sk(union inet_addr *addr, struct sock *sk)
 {
-	addr->v6.sin6_family = AF_INET6;
-	addr->v6.sin6_port = 0;
-	addr->v6.sin6_addr = inet6_sk(sk)->rcv_saddr;
+	addr->sin6.sin6_family = AF_INET6;
+	addr->sin6.sin6_port = 0;
+	addr->sin6.sin6_addr = inet6_sk(sk)->rcv_saddr;
 }
 
-/* Initialize sk->sk_rcv_saddr from sctp_addr. */
-static void sctp_v6_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
+/* Initialize sk->sk_rcv_saddr from inet_addr. */
+static void sctp_v6_to_sk_saddr(union inet_addr *addr, struct sock *sk)
 {
 	if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
 		inet6_sk(sk)->rcv_saddr.s6_addr32[0] = 0;
 		inet6_sk(sk)->rcv_saddr.s6_addr32[1] = 0;
 		inet6_sk(sk)->rcv_saddr.s6_addr32[2] = htonl(0x0000ffff);
 		inet6_sk(sk)->rcv_saddr.s6_addr32[3] =
-			addr->v4.sin_addr.s_addr;
+			addr->sin.sin_addr.s_addr;
 	} else {
-		inet6_sk(sk)->rcv_saddr = addr->v6.sin6_addr;
+		inet6_sk(sk)->rcv_saddr = addr->sin6.sin6_addr;
 	}
 }
 
-/* Initialize sk->sk_daddr from sctp_addr. */
-static void sctp_v6_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
+/* Initialize sk->sk_daddr from inet_addr. */
+static void sctp_v6_to_sk_daddr(union inet_addr *addr, struct sock *sk)
 {
 	if (addr->sa.sa_family == AF_INET && sctp_sk(sk)->v4mapped) {
 		inet6_sk(sk)->daddr.s6_addr32[0] = 0;
 		inet6_sk(sk)->daddr.s6_addr32[1] = 0;
 		inet6_sk(sk)->daddr.s6_addr32[2] = htonl(0x0000ffff);
-		inet6_sk(sk)->daddr.s6_addr32[3] = addr->v4.sin_addr.s_addr;
+		inet6_sk(sk)->daddr.s6_addr32[3] = addr->sin.sin_addr.s_addr;
 	} else {
-		inet6_sk(sk)->daddr = addr->v6.sin6_addr;
+		inet6_sk(sk)->daddr = addr->sin6.sin6_addr;
 	}
 }
 
-/* Initialize a sctp_addr from an address parameter. */
-static void sctp_v6_from_addr_param(union sctp_addr *addr,
+/* Initialize a inet_addr from an address parameter. */
+static void sctp_v6_from_addr_param(union inet_addr *addr,
 				    union sctp_addr_param *param,
 				    __be16 port, int iif)
 {
-	addr->v6.sin6_family = AF_INET6;
-	addr->v6.sin6_port = port;
-	addr->v6.sin6_flowinfo = 0; /* BUG */
-	addr->v6.sin6_addr = param->v6.addr;
-	addr->v6.sin6_scope_id = iif;
+	addr->sin6.sin6_family = AF_INET6;
+	addr->sin6.sin6_port = port;
+	addr->sin6.sin6_flowinfo = 0; /* BUG */
+	addr->sin6.sin6_addr = param->v6.addr;
+	addr->sin6.sin6_scope_id = iif;
 }
 
-/* Initialize an address parameter from a sctp_addr and return the length
+/* Initialize an address parameter from a inet_addr and return the length
  * of the address parameter.
  */
-static int sctp_v6_to_addr_param(const union sctp_addr *addr,
+static int sctp_v6_to_addr_param(const union inet_addr *addr,
 				 union sctp_addr_param *param)
 {
 	int length = sizeof(sctp_ipv6addr_param_t);
 
 	param->v6.param_hdr.type = SCTP_PARAM_IPV6_ADDRESS;
 	param->v6.param_hdr.length = htons(length);
-	param->v6.addr = addr->v6.sin6_addr;
+	param->v6.addr = addr->sin6.sin6_addr;
 
 	return length;
 }
 
-/* Initialize a sctp_addr from struct in6_addr. */
-static void sctp_v6_to_addr(union sctp_addr *addr, struct in6_addr *saddr,
+/* Initialize a inet_addr from struct in6_addr. */
+static void sctp_v6_to_addr(union inet_addr *addr, struct in6_addr *saddr,
 			      __be16 port)
 {
 	addr->sa.sa_family = AF_INET6;
-	addr->v6.sin6_port = port;
-	addr->v6.sin6_addr = *saddr;
+	addr->sin6.sin6_port = port;
+	addr->sin6.sin6_addr = *saddr;
 }
 
 /* Compare addresses exactly.
  * v4-mapped-v6 is also in consideration.
  */
-static int sctp_v6_cmp_addr(const union sctp_addr *addr1,
-			    const union sctp_addr *addr2)
+static bool sctp_v6_cmp_addr(const union inet_addr *addr1,
+			     const union inet_addr *addr2)
 {
 	if (addr1->sa.sa_family != addr2->sa.sa_family) {
 		if (addr1->sa.sa_family == AF_INET &&
 		    addr2->sa.sa_family == AF_INET6 &&
-		    ipv6_addr_v4mapped(&addr2->v6.sin6_addr)) {
-			if (addr2->v6.sin6_port == addr1->v4.sin_port &&
-			    addr2->v6.sin6_addr.s6_addr32[3] ==
-			    addr1->v4.sin_addr.s_addr)
+		    ipv6_addr_v4mapped(&addr2->sin6.sin6_addr)) {
+			if (addr2->sin6.sin6_port == addr1->sin.sin_port &&
+			    addr2->sin6.sin6_addr.s6_addr32[3] ==
+			    addr1->sin.sin_addr.s_addr)
 				return 1;
 		}
 		if (addr2->sa.sa_family == AF_INET &&
 		    addr1->sa.sa_family == AF_INET6 &&
-		    ipv6_addr_v4mapped(&addr1->v6.sin6_addr)) {
-			if (addr1->v6.sin6_port == addr2->v4.sin_port &&
-			    addr1->v6.sin6_addr.s6_addr32[3] ==
-			    addr2->v4.sin_addr.s_addr)
+		    ipv6_addr_v4mapped(&addr1->sin6.sin6_addr)) {
+			if (addr1->sin6.sin6_port == addr2->sin.sin_port &&
+			    addr1->sin6.sin6_addr.s6_addr32[3] ==
+			    addr2->sin.sin_addr.s_addr)
 				return 1;
 		}
 		return 0;
 	}
-	if (!ipv6_addr_equal(&addr1->v6.sin6_addr, &addr2->v6.sin6_addr))
-		return 0;
-	/* If this is a linklocal address, compare the scope_id. */
-	if (ipv6_addr_type(&addr1->v6.sin6_addr) & IPV6_ADDR_LINKLOCAL) {
-		if (addr1->v6.sin6_scope_id && addr2->v6.sin6_scope_id &&
-		    (addr1->v6.sin6_scope_id != addr2->v6.sin6_scope_id)) {
-			return 0;
-		}
-	}
-
-	return 1;
-}
 
-/* Initialize addr struct to INADDR_ANY. */
-static void sctp_v6_inaddr_any(union sctp_addr *addr, __be16 port)
-{
-	memset(addr, 0x00, sizeof(union sctp_addr));
-	addr->v6.sin6_family = AF_INET6;
-	addr->v6.sin6_port = port;
-}
-
-/* Is this a wildcard address? */
-static int sctp_v6_is_any(const union sctp_addr *addr)
-{
-	return ipv6_addr_any(&addr->v6.sin6_addr);
+	return inet_addr_equal(addr1, addr2);
 }
 
 /* Should this be available for binding?   */
-static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v6_available(union inet_addr *addr, struct sctp_sock *sp)
 {
 	int type;
-	const struct in6_addr *in6 = (const struct in6_addr *)&addr->v6.sin6_addr;
+	const struct in6_addr *in6 = (const struct in6_addr *)&addr->sin6.sin6_addr;
 
 	type = ipv6_addr_type(in6);
 	if (IPV6_ADDR_ANY == type)
@@ -590,11 +567,11 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp)
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v6_addr_valid(union sctp_addr *addr,
+static int sctp_v6_addr_valid(union inet_addr *addr,
 			      struct sctp_sock *sp,
 			      const struct sk_buff *skb)
 {
-	int ret = ipv6_addr_type(&addr->v6.sin6_addr);
+	int ret = ipv6_addr_type(&addr->sin6.sin6_addr);
 
 	/* Support v4-mapped-v6 address. */
 	if (ret == IPV6_ADDR_MAPPED) {
@@ -617,7 +594,7 @@ static int sctp_v6_addr_valid(union sctp_addr *addr,
 }
 
 /* What is the scope of 'addr'?  */
-static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
+static sctp_scope_t sctp_v6_scope(union inet_addr *addr)
 {
 	int v6scope;
 	sctp_scope_t retval;
@@ -626,7 +603,7 @@ static sctp_scope_t sctp_v6_scope(union sctp_addr *addr)
 	 * See IFA_* in <net/if_inet6.h>.  Map to a generic SCTP scope.
 	 */
 
-	v6scope = ipv6_addr_scope(&addr->v6.sin6_addr);
+	v6scope = ipv6_addr_scope(&addr->sin6.sin6_addr);
 	switch (v6scope) {
 	case IFA_HOST:
 		retval = SCTP_SCOPE_LOOPBACK;
@@ -688,7 +665,7 @@ out:
 }
 
 /* Map v4 address to mapped v6 address */
-static void sctp_v6_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr)
+static void sctp_v6_addr_v4map(struct sctp_sock *sp, union inet_addr *addr)
 {
 	if (sp->v4mapped && AF_INET == addr->sa.sa_family)
 		sctp_v4_map_v6(addr);
@@ -707,12 +684,6 @@ static int sctp_v6_is_ce(const struct sk_buff *skb)
 	return *((__u32 *)(ipv6_hdr(skb))) & htonl(1 << 20);
 }
 
-/* Dump the v6 addr to the seq file. */
-static void sctp_v6_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
-{
-	seq_printf(seq, "%pI6 ", &addr->v6.sin6_addr);
-}
-
 static void sctp_v6_ecn_capable(struct sock *sk)
 {
 	inet6_sk(sk)->tclass |= INET_ECN_ECT_0;
@@ -737,7 +708,7 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
 	struct sockaddr_in6 *sin6, *sin6from;
 
 	if (msgname) {
-		union sctp_addr *addr;
+		union inet_addr *addr;
 		struct sctp_association *asoc;
 
 		asoc = event->asoc;
@@ -753,13 +724,13 @@ static void sctp_inet6_event_msgname(struct sctp_ulpevent *event,
 		/* Map ipv4 address into v4-mapped-on-v6 address.  */
 		if (sctp_sk(asoc->base.sk)->v4mapped &&
 		    AF_INET == addr->sa.sa_family) {
-			sctp_v4_map_v6((union sctp_addr *)sin6);
+			sctp_v4_map_v6((union inet_addr *)sin6);
 			sin6->sin6_addr.s6_addr32[3] =
-				addr->v4.sin_addr.s_addr;
+				addr->sin.sin_addr.s_addr;
 			return;
 		}
 
-		sin6from = &asoc->peer.primary_addr.v6;
+		sin6from = &asoc->peer.primary_addr.sin6;
 		sin6->sin6_addr = sin6from->sin6_addr;
 		if (ipv6_addr_type(&sin6->sin6_addr) & IPV6_ADDR_LINKLOCAL)
 			sin6->sin6_scope_id = sin6from->sin6_scope_id;
@@ -782,7 +753,7 @@ static void sctp_inet6_skb_msgname(struct sk_buff *skb, char *msgname,
 		/* Map ipv4 address into v4-mapped-on-v6 address. */
 		if (sctp_sk(skb->sk)->v4mapped &&
 		    ip_hdr(skb)->version == 4) {
-			sctp_v4_map_v6((union sctp_addr *)sin6);
+			sctp_v4_map_v6((union inet_addr *)sin6);
 			sin6->sin6_addr.s6_addr32[3] = ip_hdr(skb)->saddr;
 			return;
 		}
@@ -815,8 +786,8 @@ static int sctp_inet6_af_supported(sa_family_t family, struct sctp_sock *sp)
  * of indirection lets us choose whether a PF_INET6 should
  * disallow any v4 addresses if we so choose.
  */
-static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
-			       const union sctp_addr *addr2,
+static int sctp_inet6_cmp_addr(const union inet_addr *addr1,
+			       const union inet_addr *addr2,
 			       struct sctp_sock *opt)
 {
 	struct sctp_af *af1, *af2;
@@ -833,7 +804,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
 		return 0;
 
 	/* Today, wildcard AF_INET/AF_INET6. */
-	if (sctp_is_any(sk, addr1) || sctp_is_any(sk, addr2))
+	if (inet_addr_any(addr1) || inet_addr_any(addr2))
 		return 1;
 
 	if (addr1->sa.sa_family != addr2->sa.sa_family)
@@ -845,7 +816,7 @@ static int sctp_inet6_cmp_addr(const union sctp_addr *addr1,
 /* Verify that the provided sockaddr looks bindable.   Common verification,
  * has already been taken care of.
  */
-static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet6_bind_verify(struct sctp_sock *opt, union inet_addr *addr)
 {
 	struct sctp_af *af;
 
@@ -853,18 +824,18 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
 	if (addr->sa.sa_family != AF_INET6)
 		af = sctp_get_af_specific(addr->sa.sa_family);
 	else {
-		int type = ipv6_addr_type(&addr->v6.sin6_addr);
+		int type = ipv6_addr_type(&addr->sin6.sin6_addr);
 		struct net_device *dev;
 
 		if (type & IPV6_ADDR_LINKLOCAL) {
 			struct net *net;
-			if (!addr->v6.sin6_scope_id)
+			if (!addr->sin6.sin6_scope_id)
 				return 0;
 			net = sock_net(&opt->inet.sk);
 			rcu_read_lock();
-			dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
+			dev = dev_get_by_index_rcu(net, addr->sin6.sin6_scope_id);
 			if (!dev ||
-			    !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) {
+			    !ipv6_chk_addr(net, &addr->sin6.sin6_addr, dev, 0)) {
 				rcu_read_unlock();
 				return 0;
 			}
@@ -882,7 +853,7 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
 /* Verify that the provided sockaddr looks sendable.   Common verification,
  * has already been taken care of.
  */
-static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet6_send_verify(struct sctp_sock *opt, union inet_addr *addr)
 {
 	struct sctp_af *af = NULL;
 
@@ -890,15 +861,15 @@ static int sctp_inet6_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
 	if (addr->sa.sa_family != AF_INET6)
 		af = sctp_get_af_specific(addr->sa.sa_family);
 	else {
-		int type = ipv6_addr_type(&addr->v6.sin6_addr);
+		int type = ipv6_addr_type(&addr->sin6.sin6_addr);
 		struct net_device *dev;
 
 		if (type & IPV6_ADDR_LINKLOCAL) {
-			if (!addr->v6.sin6_scope_id)
+			if (!addr->sin6.sin6_scope_id)
 				return 0;
 			rcu_read_lock();
 			dev = dev_get_by_index_rcu(sock_net(&opt->inet.sk),
-						   addr->v6.sin6_scope_id);
+						   addr->sin6.sin6_scope_id);
 			rcu_read_unlock();
 			if (!dev)
 				return 0;
@@ -995,12 +966,9 @@ static struct sctp_af sctp_af_inet6 = {
 	.cmp_addr	   = sctp_v6_cmp_addr,
 	.scope		   = sctp_v6_scope,
 	.addr_valid	   = sctp_v6_addr_valid,
-	.inaddr_any	   = sctp_v6_inaddr_any,
-	.is_any		   = sctp_v6_is_any,
 	.available	   = sctp_v6_available,
 	.skb_iif	   = sctp_v6_skb_iif,
 	.is_ce		   = sctp_v6_is_ce,
-	.seq_dump_addr	   = sctp_v6_seq_dump_addr,
 	.ecn_capable	   = sctp_v6_ecn_capable,
 	.net_header_len	   = sizeof(struct ipv6hdr),
 	.sockaddr_len	   = sizeof(struct sockaddr_in6),
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 94df758..57583a2 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -57,7 +57,7 @@ static int sctp_acked(struct sctp_sackhdr *sack, __u32 tsn);
 static void sctp_check_transmitted(struct sctp_outq *q,
 				   struct list_head *transmitted_queue,
 				   struct sctp_transport *transport,
-				   union sctp_addr *saddr,
+				   union inet_addr *saddr,
 				   struct sctp_sackhdr *sack,
 				   __u32 *highest_new_tsn);
 
@@ -1315,7 +1315,7 @@ int sctp_outq_is_empty(const struct sctp_outq *q)
 static void sctp_check_transmitted(struct sctp_outq *q,
 				   struct list_head *transmitted_queue,
 				   struct sctp_transport *transport,
-				   union sctp_addr *saddr,
+				   union inet_addr *saddr,
 				   struct sctp_sackhdr *sack,
 				   __u32 *highest_new_tsn_in_sack)
 {
diff --git a/net/sctp/proc.c b/net/sctp/proc.c
index 0c06421..e216ee0 100644
--- a/net/sctp/proc.c
+++ b/net/sctp/proc.c
@@ -124,7 +124,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
 	struct sctp_association *asoc;
 	struct sctp_sockaddr_entry *laddr;
 	struct sctp_transport *peer;
-	union sctp_addr *addr, *primary = NULL;
+	union inet_addr *addr, *primary = NULL;
 	struct sctp_af *af;
 
 	if (epb->type == SCTP_EP_TYPE_ASSOCIATION) {
@@ -149,7 +149,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
 		if (primary && af->cmp_addr(addr, primary)) {
 			seq_printf(seq, "*");
 		}
-		af->seq_dump_addr(seq, addr);
+		seq_printf(seq, "%pIA ", &addr);
 	}
 	rcu_read_unlock();
 }
@@ -158,7 +158,7 @@ static void sctp_seq_dump_local_addrs(struct seq_file *seq, struct sctp_ep_commo
 static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_association *assoc)
 {
 	struct sctp_transport *transport;
-	union sctp_addr *addr, *primary;
+	union inet_addr *addr, *primary;
 	struct sctp_af *af;
 
 	primary = &assoc->peer.primary_addr;
@@ -173,7 +173,7 @@ static void sctp_seq_dump_remote_addrs(struct seq_file *seq, struct sctp_associa
 		if (af->cmp_addr(addr, primary)) {
 			seq_printf(seq, "*");
 		}
-		af->seq_dump_addr(seq, addr);
+		seq_printf(seq, "%pIA ", addr);
 	}
 	rcu_read_unlock();
 }
@@ -462,7 +462,7 @@ static int sctp_remaddr_seq_show(struct seq_file *seq, void *v)
 			/*
 			 * The remote address (ADDR)
 			 */
-			tsp->af_specific->seq_dump_addr(seq, &tsp->ipaddr);
+			seq_printf(seq, "%pIA ", &tsp->ipaddr);
 			seq_printf(seq, " ");
 
 			/*
diff --git a/net/sctp/protocol.c b/net/sctp/protocol.c
index 0680be7..82aab6b 100644
--- a/net/sctp/protocol.c
+++ b/net/sctp/protocol.c
@@ -149,9 +149,9 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
 		/* Add the address to the local list.  */
 		addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
 		if (addr) {
-			addr->a.v4.sin_family = AF_INET;
-			addr->a.v4.sin_port = 0;
-			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
+			addr->a.sa.sa_family = AF_INET;
+			addr->a.sin.sin_port = 0;
+			addr->a.sin.sin_addr.s_addr = ifa->ifa_local;
 			addr->valid = 1;
 			INIT_LIST_HEAD(&addr->list);
 			list_add_tail(&addr->list, addrlist);
@@ -227,16 +227,16 @@ end_copy:
 	return error;
 }
 
-/* Initialize a sctp_addr from in incoming skb.  */
-static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
+/* Initialize a inet_addr from in incoming skb.  */
+static void sctp_v4_from_skb(union inet_addr *addr, struct sk_buff *skb,
 			     int is_saddr)
 {
 	void *from;
 	__be16 *port;
 	struct sctphdr *sh;
 
-	port = &addr->v4.sin_port;
-	addr->v4.sin_family = AF_INET;
+	port = &addr->sin.sin_port;
+	addr->sa.sa_family = AF_INET;
 
 	sh = sctp_hdr(skb);
 	if (is_saddr) {
@@ -246,89 +246,61 @@ static void sctp_v4_from_skb(union sctp_addr *addr, struct sk_buff *skb,
 		*port = sh->dest;
 		from = &ip_hdr(skb)->daddr;
 	}
-	memcpy(&addr->v4.sin_addr.s_addr, from, sizeof(struct in_addr));
+	memcpy(&addr->sin.sin_addr.s_addr, from, sizeof(struct in_addr));
 }
 
-/* Initialize an sctp_addr from a socket. */
-static void sctp_v4_from_sk(union sctp_addr *addr, struct sock *sk)
+/* Initialize an inet_addr from a socket. */
+static void sctp_v4_from_sk(union inet_addr *addr, struct sock *sk)
 {
-	addr->v4.sin_family = AF_INET;
-	addr->v4.sin_port = 0;
-	addr->v4.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr;
+	addr->sa.sa_family = AF_INET;
+	addr->sin.sin_port = 0;
+	addr->sin.sin_addr.s_addr = inet_sk(sk)->inet_rcv_saddr;
 }
 
-/* Initialize sk->sk_rcv_saddr from sctp_addr. */
-static void sctp_v4_to_sk_saddr(union sctp_addr *addr, struct sock *sk)
+/* Initialize sk->sk_rcv_saddr from inet_addr. */
+static void sctp_v4_to_sk_saddr(union inet_addr *addr, struct sock *sk)
 {
-	inet_sk(sk)->inet_rcv_saddr = addr->v4.sin_addr.s_addr;
+	inet_sk(sk)->inet_rcv_saddr = addr->sin.sin_addr.s_addr;
 }
 
-/* Initialize sk->sk_daddr from sctp_addr. */
-static void sctp_v4_to_sk_daddr(union sctp_addr *addr, struct sock *sk)
+/* Initialize sk->sk_daddr from inet_addr. */
+static void sctp_v4_to_sk_daddr(union inet_addr *addr, struct sock *sk)
 {
-	inet_sk(sk)->inet_daddr = addr->v4.sin_addr.s_addr;
+	inet_sk(sk)->inet_daddr = addr->sin.sin_addr.s_addr;
 }
 
-/* Initialize a sctp_addr from an address parameter. */
-static void sctp_v4_from_addr_param(union sctp_addr *addr,
+/* Initialize a inet_addr from an address parameter. */
+static void sctp_v4_from_addr_param(union inet_addr *addr,
 				    union sctp_addr_param *param,
 				    __be16 port, int iif)
 {
-	addr->v4.sin_family = AF_INET;
-	addr->v4.sin_port = port;
-	addr->v4.sin_addr.s_addr = param->v4.addr.s_addr;
+	addr->sa.sa_family = AF_INET;
+	addr->sin.sin_port = port;
+	addr->sin.sin_addr.s_addr = param->v4.addr.s_addr;
 }
 
-/* Initialize an address parameter from a sctp_addr and return the length
+/* Initialize an address parameter from a inet_addr and return the length
  * of the address parameter.
  */
-static int sctp_v4_to_addr_param(const union sctp_addr *addr,
+static int sctp_v4_to_addr_param(const union inet_addr *addr,
 				 union sctp_addr_param *param)
 {
 	int length = sizeof(sctp_ipv4addr_param_t);
 
 	param->v4.param_hdr.type = SCTP_PARAM_IPV4_ADDRESS;
 	param->v4.param_hdr.length = htons(length);
-	param->v4.addr.s_addr = addr->v4.sin_addr.s_addr;
+	param->v4.addr.s_addr = addr->sin.sin_addr.s_addr;
 
 	return length;
 }
 
-/* Initialize a sctp_addr from a dst_entry. */
-static void sctp_v4_dst_saddr(union sctp_addr *saddr, struct flowi4 *fl4,
+/* Initialize a inet_addr from a dst_entry. */
+static void sctp_v4_dst_saddr(union inet_addr *saddr, struct flowi4 *fl4,
 			      __be16 port)
 {
-	saddr->v4.sin_family = AF_INET;
-	saddr->v4.sin_port = port;
-	saddr->v4.sin_addr.s_addr = fl4->saddr;
-}
-
-/* Compare two addresses exactly. */
-static int sctp_v4_cmp_addr(const union sctp_addr *addr1,
-			    const union sctp_addr *addr2)
-{
-	if (addr1->sa.sa_family != addr2->sa.sa_family)
-		return 0;
-	if (addr1->v4.sin_port != addr2->v4.sin_port)
-		return 0;
-	if (addr1->v4.sin_addr.s_addr != addr2->v4.sin_addr.s_addr)
-		return 0;
-
-	return 1;
-}
-
-/* Initialize addr struct to INADDR_ANY. */
-static void sctp_v4_inaddr_any(union sctp_addr *addr, __be16 port)
-{
-	addr->v4.sin_family = AF_INET;
-	addr->v4.sin_addr.s_addr = htonl(INADDR_ANY);
-	addr->v4.sin_port = port;
-}
-
-/* Is this a wildcard address? */
-static int sctp_v4_is_any(const union sctp_addr *addr)
-{
-	return htonl(INADDR_ANY) == addr->v4.sin_addr.s_addr;
+	saddr->sin.sin_family = AF_INET;
+	saddr->sin.sin_port = port;
+	saddr->sin.sin_addr.s_addr = fl4->saddr;
 }
 
 /* This function checks if the address is a valid address to be used for
@@ -338,7 +310,7 @@ static int sctp_v4_is_any(const union sctp_addr *addr)
  * Return 0 - If the address is a non-unicast or an illegal address.
  * Return 1 - If the address is a unicast.
  */
-static int sctp_v4_addr_valid(union sctp_addr *addr,
+static int sctp_v4_addr_valid(union inet_addr *addr,
 			      struct sctp_sock *sp,
 			      const struct sk_buff *skb)
 {
@@ -347,7 +319,7 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
 		return 0;
 
 	/* Is this a non-unicast address or a unusable SCTP address? */
-	if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr))
+	if (IS_IPV4_UNUSABLE_ADDRESS(addr->sin.sin_addr.s_addr))
 		return 0;
 
 	/* Is this a broadcast address? */
@@ -358,13 +330,13 @@ static int sctp_v4_addr_valid(union sctp_addr *addr,
 }
 
 /* Should this be available for binding?   */
-static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
+static int sctp_v4_available(union inet_addr *addr, struct sctp_sock *sp)
 {
 	struct net *net = sock_net(&sp->inet.sk);
-	int ret = inet_addr_type(net, addr->v4.sin_addr.s_addr);
+	int ret = inet_addr_type(net, addr->sin.sin_addr.s_addr);
 
 
-	if (addr->v4.sin_addr.s_addr != htonl(INADDR_ANY) &&
+	if (addr->sin.sin_addr.s_addr != htonl(INADDR_ANY) &&
 	   ret != RTN_LOCAL &&
 	   !sp->inet.freebind &&
 	   !sysctl_ip_nonlocal_bind)
@@ -393,20 +365,20 @@ static int sctp_v4_available(union sctp_addr *addr, struct sctp_sock *sp)
  * IPv4 scoping can be controlled through sysctl option
  * net.sctp.addr_scope_policy
  */
-static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
+static sctp_scope_t sctp_v4_scope(union inet_addr *addr)
 {
 	sctp_scope_t retval;
 
 	/* Check for unusable SCTP addresses. */
-	if (IS_IPV4_UNUSABLE_ADDRESS(addr->v4.sin_addr.s_addr)) {
+	if (IS_IPV4_UNUSABLE_ADDRESS(addr->sin.sin_addr.s_addr)) {
 		retval =  SCTP_SCOPE_UNUSABLE;
-	} else if (ipv4_is_loopback(addr->v4.sin_addr.s_addr)) {
+	} else if (ipv4_is_loopback(addr->sin.sin_addr.s_addr)) {
 		retval = SCTP_SCOPE_LOOPBACK;
-	} else if (ipv4_is_linklocal_169(addr->v4.sin_addr.s_addr)) {
+	} else if (ipv4_is_linklocal_169(addr->sin.sin_addr.s_addr)) {
 		retval = SCTP_SCOPE_LINK;
-	} else if (ipv4_is_private_10(addr->v4.sin_addr.s_addr) ||
-		   ipv4_is_private_172(addr->v4.sin_addr.s_addr) ||
-		   ipv4_is_private_192(addr->v4.sin_addr.s_addr)) {
+	} else if (ipv4_is_private_10(addr->sin.sin_addr.s_addr) ||
+		   ipv4_is_private_172(addr->sin.sin_addr.s_addr) ||
+		   ipv4_is_private_192(addr->sin.sin_addr.s_addr)) {
 		retval = SCTP_SCOPE_PRIVATE;
 	} else {
 		retval = SCTP_SCOPE_GLOBAL;
@@ -419,7 +391,7 @@ static sctp_scope_t sctp_v4_scope(union sctp_addr *addr)
  * addresses. If an association is passed, trys to get a dst entry with a
  * source address that matches an address in the bind address list.
  */
-static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
+static void sctp_v4_get_dst(struct sctp_transport *t, union inet_addr *saddr,
 				struct flowi *fl, struct sock *sk)
 {
 	struct sctp_association *asoc = t->asoc;
@@ -428,12 +400,12 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 	struct sctp_bind_addr *bp;
 	struct sctp_sockaddr_entry *laddr;
 	struct dst_entry *dst = NULL;
-	union sctp_addr *daddr = &t->ipaddr;
-	union sctp_addr dst_saddr;
+	union inet_addr *daddr = &t->ipaddr;
+	union inet_addr dst_saddr;
 
 	memset(fl4, 0x0, sizeof(struct flowi4));
-	fl4->daddr  = daddr->v4.sin_addr.s_addr;
-	fl4->fl4_dport = daddr->v4.sin_port;
+	fl4->daddr  = daddr->sin.sin_addr.s_addr;
+	fl4->fl4_dport = daddr->sin.sin_port;
 	fl4->flowi4_proto = IPPROTO_SCTP;
 	if (asoc) {
 		fl4->flowi4_tos = RT_CONN_FLAGS(asoc->base.sk);
@@ -441,8 +413,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 		fl4->fl4_sport = htons(asoc->base.bind_addr.port);
 	}
 	if (saddr) {
-		fl4->saddr = saddr->v4.sin_addr.s_addr;
-		fl4->fl4_sport = saddr->v4.sin_port;
+		fl4->saddr = saddr->sin.sin_addr.s_addr;
+		fl4->fl4_sport = saddr->sin.sin_port;
 	}
 
 	pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
@@ -471,7 +443,7 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 			    (laddr->state != SCTP_ADDR_SRC &&
 			    !asoc->src_out_of_asoc_ok))
 				continue;
-			if (sctp_v4_cmp_addr(&dst_saddr, &laddr->a))
+			if (inet_addr_equal_strict(&dst_saddr, &laddr->a))
 				goto out_unlock;
 		}
 		rcu_read_unlock();
@@ -492,8 +464,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 			continue;
 		if ((laddr->state == SCTP_ADDR_SRC) &&
 		    (AF_INET == laddr->a.sa.sa_family)) {
-			fl4->saddr = laddr->a.v4.sin_addr.s_addr;
-			fl4->fl4_sport = laddr->a.v4.sin_port;
+			fl4->saddr = laddr->a.sin.sin_addr.s_addr;
+			fl4->fl4_sport = laddr->a.sin.sin_port;
 			rt = ip_route_output_key(sock_net(sk), fl4);
 			if (!IS_ERR(rt)) {
 				dst = &rt->dst;
@@ -520,12 +492,12 @@ static void sctp_v4_get_saddr(struct sctp_sock *sk,
 			      struct sctp_transport *t,
 			      struct flowi *fl)
 {
-	union sctp_addr *saddr = &t->saddr;
+	union inet_addr *saddr = &t->saddr;
 	struct rtable *rt = (struct rtable *)t->dst;
 
 	if (rt) {
-		saddr->v4.sin_family = AF_INET;
-		saddr->v4.sin_addr.s_addr = fl->u.ip4.saddr;
+		saddr->sa.sa_family = AF_INET;
+		saddr->sin.sin_addr.s_addr = fl->u.ip4.saddr;
 	}
 }
 
@@ -559,7 +531,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk,
 
 	newinet = inet_sk(newsk);
 
-	newinet->inet_daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr;
+	newinet->inet_daddr = asoc->peer.primary_addr.sin.sin_addr.s_addr;
 
 	sk_refcnt_debug_inc(newsk);
 
@@ -573,17 +545,11 @@ out:
 }
 
 /* Map address, empty for v4 family */
-static void sctp_v4_addr_v4map(struct sctp_sock *sp, union sctp_addr *addr)
+static void sctp_v4_addr_v4map(struct sctp_sock *sp, union inet_addr *addr)
 {
 	/* Empty */
 }
 
-/* Dump the v4 addr to the seq file. */
-static void sctp_v4_seq_dump_addr(struct seq_file *seq, union sctp_addr *addr)
-{
-	seq_printf(seq, "%pI4 ", &addr->v4.sin_addr);
-}
-
 static void sctp_v4_ecn_capable(struct sock *sk)
 {
 	INET_ECN_xmit(sk);
@@ -608,11 +574,11 @@ static void sctp_addr_wq_timeout_handler(unsigned long arg)
 		if (addrw->a.sa.sa_family == AF_INET6) {
 			struct in6_addr *in6;
 
-			if (ipv6_addr_type(&addrw->a.v6.sin6_addr) &
+			if (ipv6_addr_type(&addrw->a.sin6.sin6_addr) &
 			    IPV6_ADDR_LINKLOCAL)
 				goto free_next;
 
-			in6 = (struct in6_addr *)&addrw->a.v6.sin6_addr;
+			in6 = (struct in6_addr *)&addrw->a.sin6.sin6_addr;
 			if (ipv6_chk_addr(net, in6, NULL, 0) == 0 &&
 			    addrw->state == SCTP_ADDR_NEW) {
 				unsigned long timeo_val;
@@ -672,17 +638,8 @@ static struct sctp_sockaddr_entry *sctp_addr_wq_lookup(struct net *net,
 	struct sctp_sockaddr_entry *addrw;
 
 	list_for_each_entry(addrw, &net->sctp.addr_waitq, list) {
-		if (addrw->a.sa.sa_family != addr->a.sa.sa_family)
-			continue;
-		if (addrw->a.sa.sa_family == AF_INET) {
-			if (addrw->a.v4.sin_addr.s_addr ==
-			    addr->a.v4.sin_addr.s_addr)
-				return addrw;
-		} else if (addrw->a.sa.sa_family == AF_INET6) {
-			if (ipv6_addr_equal(&addrw->a.v6.sin6_addr,
-			    &addr->a.v6.sin6_addr))
-				return addrw;
-		}
+		if (inet_addr_equal(&addrw->a, &addr->a))
+			return addrw;
 	}
 	return NULL;
 }
@@ -753,9 +710,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 	case NETDEV_UP:
 		addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
 		if (addr) {
-			addr->a.v4.sin_family = AF_INET;
-			addr->a.v4.sin_port = 0;
-			addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
+			addr->a.sa.sa_family = AF_INET;
+			addr->a.sin.sin_port = 0;
+			addr->a.sin.sin_addr.s_addr = ifa->ifa_local;
 			addr->valid = 1;
 			spin_lock_bh(&net->sctp.local_addr_lock);
 			list_add_tail_rcu(&addr->list, &net->sctp.local_addr_list);
@@ -768,7 +725,7 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 		list_for_each_entry_safe(addr, temp,
 					&net->sctp.local_addr_list, list) {
 			if (addr->a.sa.sa_family == AF_INET &&
-					addr->a.v4.sin_addr.s_addr ==
+					addr->a.sin.sin_addr.s_addr ==
 					ifa->ifa_local) {
 				sctp_addr_wq_mgmt(net, addr, SCTP_ADDR_DEL);
 				found = 1;
@@ -875,7 +832,7 @@ static void sctp_inet_event_msgname(struct sctp_ulpevent *event, char *msgname,
 		asoc = event->asoc;
 		sctp_inet_msgname(msgname, addr_len);
 		sin = (struct sockaddr_in *)msgname;
-		sinfrom = &asoc->peer.primary_addr.v4;
+		sinfrom = &asoc->peer.primary_addr.sin;
 		sin->sin_port = htons(asoc->peer.port);
 		sin->sin_addr.s_addr = sinfrom->sin_addr.s_addr;
 	}
@@ -902,17 +859,17 @@ static int sctp_inet_af_supported(sa_family_t family, struct sctp_sock *sp)
 }
 
 /* Address matching with wildcards allowed. */
-static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
-			      const union sctp_addr *addr2,
+static int sctp_inet_cmp_addr(const union inet_addr *addr1,
+			      const union inet_addr *addr2,
 			      struct sctp_sock *opt)
 {
 	/* PF_INET only supports AF_INET addresses. */
 	if (addr1->sa.sa_family != addr2->sa.sa_family)
 		return 0;
-	if (htonl(INADDR_ANY) == addr1->v4.sin_addr.s_addr ||
-	    htonl(INADDR_ANY) == addr2->v4.sin_addr.s_addr)
+	if (htonl(INADDR_ANY) == addr1->sin.sin_addr.s_addr ||
+	    htonl(INADDR_ANY) == addr2->sin.sin_addr.s_addr)
 		return 1;
-	if (addr1->v4.sin_addr.s_addr == addr2->v4.sin_addr.s_addr)
+	if (addr1->sin.sin_addr.s_addr == addr2->sin.sin_addr.s_addr)
 		return 1;
 
 	return 0;
@@ -921,7 +878,7 @@ static int sctp_inet_cmp_addr(const union sctp_addr *addr1,
 /* Verify that provided sockaddr looks bindable.  Common verification has
  * already been taken care of.
  */
-static int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet_bind_verify(struct sctp_sock *opt, union inet_addr *addr)
 {
 	return sctp_v4_available(addr, opt);
 }
@@ -929,7 +886,7 @@ static int sctp_inet_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
 /* Verify that sockaddr looks sendable.  Common verification has already
  * been taken care of.
  */
-static int sctp_inet_send_verify(struct sctp_sock *opt, union sctp_addr *addr)
+static int sctp_inet_send_verify(struct sctp_sock *opt, union inet_addr *addr)
 {
 	return 1;
 }
@@ -1048,15 +1005,12 @@ static struct sctp_af sctp_af_inet = {
 	.to_sk_daddr	   = sctp_v4_to_sk_daddr,
 	.from_addr_param   = sctp_v4_from_addr_param,
 	.to_addr_param	   = sctp_v4_to_addr_param,
-	.cmp_addr	   = sctp_v4_cmp_addr,
+	.cmp_addr	   = inet_addr_equal_strict,
 	.addr_valid	   = sctp_v4_addr_valid,
-	.inaddr_any	   = sctp_v4_inaddr_any,
-	.is_any		   = sctp_v4_is_any,
 	.available	   = sctp_v4_available,
 	.scope		   = sctp_v4_scope,
 	.skb_iif	   = sctp_v4_skb_iif,
 	.is_ce		   = sctp_v4_is_ce,
-	.seq_dump_addr	   = sctp_v4_seq_dump_addr,
 	.ecn_capable	   = sctp_v4_ecn_capable,
 	.net_header_len	   = sizeof(struct iphdr),
 	.sockaddr_len	   = sizeof(struct sockaddr_in),
diff --git a/net/sctp/sm_make_chunk.c b/net/sctp/sm_make_chunk.c
index 01e9783..883a9ce 100644
--- a/net/sctp/sm_make_chunk.c
+++ b/net/sctp/sm_make_chunk.c
@@ -75,7 +75,7 @@ static sctp_cookie_param_t *sctp_pack_cookie(const struct sctp_endpoint *ep,
 					const __u8 *raw_addrs, int addrs_len);
 static int sctp_process_param(struct sctp_association *asoc,
 			      union sctp_params param,
-			      const union sctp_addr *peer_addr,
+			      const union inet_addr *peer_addr,
 			      gfp_t gfp);
 static void *sctp_addto_param(struct sctp_chunk *chunk, int len,
 			      const void *data);
@@ -1349,15 +1349,15 @@ nodata:
 }
 
 /* Set chunk->source and dest based on the IP header in chunk->skb.  */
-void sctp_init_addrs(struct sctp_chunk *chunk, union sctp_addr *src,
-		     union sctp_addr *dest)
+void sctp_init_addrs(struct sctp_chunk *chunk, union inet_addr *src,
+		     union inet_addr *dest)
 {
-	memcpy(&chunk->source, src, sizeof(union sctp_addr));
-	memcpy(&chunk->dest, dest, sizeof(union sctp_addr));
+	memcpy(&chunk->source, src, sizeof(union inet_addr));
+	memcpy(&chunk->dest, dest, sizeof(union inet_addr));
 }
 
 /* Extract the source address from a chunk.  */
-const union sctp_addr *sctp_source(const struct sctp_chunk *chunk)
+const union inet_addr *sctp_source(const struct sctp_chunk *chunk)
 {
 	/* If we have a known transport, use that.  */
 	if (chunk->transport) {
@@ -1774,7 +1774,7 @@ no_hmac:
 		goto fail;
 	}
 
-	if (chunk->sctp_hdr->source != bear_cookie->peer_addr.v4.sin_port ||
+	if (chunk->sctp_hdr->source != bear_cookie->peer_addr.sin.sin_port ||
 	    ntohs(chunk->sctp_hdr->dest) != bear_cookie->my_port) {
 		*error = -SCTP_IERROR_BAD_PORTS;
 		goto fail;
@@ -2302,7 +2302,7 @@ int sctp_verify_init(struct net *net, const struct sctp_association *asoc,
  * FIXME:  This is an association method.
  */
 int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
-		      const union sctp_addr *peer_addr,
+		      const union inet_addr *peer_addr,
 		      sctp_init_chunk_t *peer_init, gfp_t gfp)
 {
 	struct net *net = sock_net(asoc->base.sk);
@@ -2310,7 +2310,7 @@ int sctp_process_init(struct sctp_association *asoc, struct sctp_chunk *chunk,
 	struct sctp_transport *transport;
 	struct list_head *pos, *temp;
 	struct sctp_af *af;
-	union sctp_addr addr;
+	union inet_addr addr;
 	char *cookie;
 	int src_match = 0;
 
@@ -2499,11 +2499,11 @@ nomem:
  */
 static int sctp_process_param(struct sctp_association *asoc,
 			      union sctp_params param,
-			      const union sctp_addr *peer_addr,
+			      const union inet_addr *peer_addr,
 			      gfp_t gfp)
 {
 	struct net *net = sock_net(asoc->base.sk);
-	union sctp_addr addr;
+	union inet_addr addr;
 	int i;
 	__u16 sat;
 	int retval = 1;
@@ -2750,7 +2750,7 @@ __u32 sctp_generate_tsn(const struct sctp_endpoint *ep)
  * Address Parameter and other parameter will not be wrapped in this function
  */
 static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
-					   union sctp_addr *addr,
+					   union inet_addr *addr,
 					   int vparam_len)
 {
 	sctp_addiphdr_t asconf;
@@ -2758,7 +2758,7 @@ static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
 	int length = sizeof(asconf) + vparam_len;
 	union sctp_addr_param addrparam;
 	int addrlen;
-	struct sctp_af *af = sctp_get_af_specific(addr->v4.sin_family);
+	struct sctp_af *af = sctp_get_af_specific(addr->sin.sin_family);
 
 	addrlen = af->to_addr_param(addr, &addrparam);
 	if (!addrlen)
@@ -2805,7 +2805,7 @@ static struct sctp_chunk *sctp_make_asconf(struct sctp_association *asoc,
  *
  */
 struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
-					      union sctp_addr	      *laddr,
+					      union inet_addr	      *laddr,
 					      struct sockaddr	      *addrs,
 					      int		      addrcnt,
 					      __be16		      flags)
@@ -2813,7 +2813,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 	sctp_addip_param_t	param;
 	struct sctp_chunk	*retval;
 	union sctp_addr_param	addr_param;
-	union sctp_addr		*addr;
+	union inet_addr		*addr;
 	void			*addr_buf;
 	struct sctp_af		*af;
 	int			paramlen = sizeof(param);
@@ -2826,7 +2826,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 	addr_buf = addrs;
 	for (i = 0; i < addrcnt; i++) {
 		addr = addr_buf;
-		af = sctp_get_af_specific(addr->v4.sin_family);
+		af = sctp_get_af_specific(addr->sin.sin_family);
 		addr_param_len = af->to_addr_param(addr, &addr_param);
 
 		totallen += paramlen;
@@ -2854,7 +2854,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 	addr_buf = addrs;
 	for (i = 0; i < addrcnt; i++) {
 		addr = addr_buf;
-		af = sctp_get_af_specific(addr->v4.sin_family);
+		af = sctp_get_af_specific(addr->sin.sin_family);
 		addr_param_len = af->to_addr_param(addr, &addr_param);
 		param.param_hdr.type = flags;
 		param.param_hdr.length = htons(paramlen + addr_param_len);
@@ -2867,7 +2867,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
 	}
 	if (flags == SCTP_PARAM_ADD_IP && del_pickup) {
 		addr = asoc->asconf_addr_del_pending;
-		af = sctp_get_af_specific(addr->v4.sin_family);
+		af = sctp_get_af_specific(addr->sin.sin_family);
 		addr_param_len = af->to_addr_param(addr, &addr_param);
 		param.param_hdr.type = SCTP_PARAM_DEL_IP;
 		param.param_hdr.length = htons(paramlen + addr_param_len);
@@ -2894,14 +2894,14 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
  * Create an ASCONF chunk with Set Primary IP address parameter.
  */
 struct sctp_chunk *sctp_make_asconf_set_prim(struct sctp_association *asoc,
-					     union sctp_addr *addr)
+					     union inet_addr *addr)
 {
 	sctp_addip_param_t	param;
 	struct sctp_chunk 	*retval;
 	int 			len = sizeof(param);
 	union sctp_addr_param	addrparam;
 	int			addrlen;
-	struct sctp_af		*af = sctp_get_af_specific(addr->v4.sin_family);
+	struct sctp_af		*af = sctp_get_af_specific(addr->sin.sin_family);
 
 	addrlen = af->to_addr_param(addr, &addrparam);
 	if (!addrlen)
@@ -3010,7 +3010,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 {
 	struct sctp_transport *peer;
 	struct sctp_af *af;
-	union sctp_addr	addr;
+	union inet_addr	addr;
 	union sctp_addr_param *addr_param;
 
 	addr_param = (void *)asconf_param + sizeof(sctp_addip_param_t);
@@ -3044,7 +3044,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 	 * (note: wildcard is permitted and requires special handling so
 	 *  make sure we check for that)
 	 */
-	if (!af->is_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb))
+	if (!inet_addr_any(&addr) && !af->addr_valid(&addr, NULL, asconf->skb))
 		return SCTP_ERROR_DNS_FAILED;
 
 	switch (asconf_param->param_hdr.type) {
@@ -3053,7 +3053,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 		 * If the address 0.0.0.0 or ::0 is provided, the source
 		 * address of the packet MUST be added.
 		 */
-		if (af->is_any(&addr))
+		if (inet_addr_any(&addr))
 			memcpy(&addr, &asconf->source, sizeof(addr));
 
 		/* ADDIP 4.3 D9) If an endpoint receives an ADD IP address
@@ -3096,7 +3096,7 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 		 * addresses of the peer except	the source address of the
 		 * packet MUST be deleted.
 		 */
-		if (af->is_any(&addr)) {
+		if (inet_addr_any(&addr)) {
 			sctp_assoc_set_primary(asoc, asconf->transport);
 			sctp_assoc_del_nonprimary_peers(asoc,
 							asconf->transport);
@@ -3109,8 +3109,8 @@ static __be16 sctp_process_asconf_param(struct sctp_association *asoc,
 		 * MAY mark the source address of the packet as its
 		 * primary.
 		 */
-		if (af->is_any(&addr))
-			memcpy(&addr.v4, sctp_source(asconf), sizeof(addr));
+		if (inet_addr_any(&addr))
+			memcpy(&addr.sin, sctp_source(asconf), sizeof(addr));
 
 		peer = sctp_assoc_lookup_paddr(asoc, &addr);
 		if (!peer)
@@ -3264,7 +3264,7 @@ static void sctp_asconf_param_success(struct sctp_association *asoc,
 				     sctp_addip_param_t *asconf_param)
 {
 	struct sctp_af *af;
-	union sctp_addr	addr;
+	union inet_addr	addr;
 	struct sctp_bind_addr *bp = &asoc->base.bind_addr;
 	union sctp_addr_param *addr_param;
 	struct sctp_transport *transport;
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index dfe3f36..ee975a3 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1124,7 +1124,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(struct net *net,
 					sctp_cmd_seq_t *commands)
 {
 	struct sctp_chunk *chunk = arg;
-	union sctp_addr from_addr;
+	union inet_addr from_addr;
 	struct sctp_transport *link;
 	sctp_sender_hb_info_t *hbinfo;
 	unsigned long max_interval;
@@ -1150,17 +1150,8 @@ sctp_disposition_t sctp_sf_backbeat_8_3(struct net *net,
 
 	/* This should never happen, but lets log it if so.  */
 	if (unlikely(!link)) {
-		if (from_addr.sa.sa_family == AF_INET6) {
-			net_warn_ratelimited("%s association %p could not find address %pI6\n",
-					     __func__,
-					     asoc,
-					     &from_addr.v6.sin6_addr);
-		} else {
-			net_warn_ratelimited("%s association %p could not find address %pI4\n",
-					     __func__,
-					     asoc,
-					     &from_addr.v4.sin_addr.s_addr);
-		}
+		net_warn_ratelimited("%s association %p could not find address %pIA\n",
+				     __func__, asoc, &from_addr);
 		return SCTP_DISPOSITION_DISCARD;
 	}
 
@@ -1193,7 +1184,7 @@ sctp_disposition_t sctp_sf_backbeat_8_3(struct net *net,
 /* Helper function to send out an abort for the restart
  * condition.
  */
-static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
+static int sctp_sf_send_restart_abort(struct net *net, union inet_addr *ssa,
 				      struct sctp_chunk *init,
 				      sctp_cmd_seq_t *commands)
 {
@@ -1203,7 +1194,7 @@ static int sctp_sf_send_restart_abort(struct net *net, union sctp_addr *ssa,
 	struct sctp_errhdr *errhdr;
 	struct sctp_endpoint *ep;
 	char buffer[sizeof(struct sctp_errhdr)+sizeof(union sctp_addr_param)];
-	struct sctp_af *af = sctp_get_af_specific(ssa->v4.sin_family);
+	struct sctp_af *af = sctp_get_af_specific(ssa->sin.sin_family);
 
 	/* Build the error on the stack.   We are way to malloc crazy
 	 * throughout the code today.
@@ -1243,7 +1234,7 @@ out:
 }
 
 static bool list_has_sctp_addr(const struct list_head *list,
-			       union sctp_addr *ipaddr)
+			       union inet_addr *ipaddr)
 {
 	struct sctp_transport *addr;
 
@@ -6041,7 +6032,7 @@ static struct sctp_packet *sctp_ootb_pkt_new(struct net *net,
 	/* Cache a route for the transport with the chunk's destination as
 	 * the source address.
 	 */
-	sctp_transport_route(transport, (union sctp_addr *)&chunk->dest,
+	sctp_transport_route(transport, (union inet_addr *)&chunk->dest,
 			     sctp_sk(net->sctp.ctl_sock));
 
 	packet = sctp_packet_init(&transport->packet, transport, sport, dport);
diff --git a/net/sctp/socket.c b/net/sctp/socket.c
index dba117a..6e74dac 100644
--- a/net/sctp/socket.c
+++ b/net/sctp/socket.c
@@ -89,14 +89,14 @@ static int sctp_wait_for_accept(struct sock *sk, long timeo);
 static void sctp_wait_for_close(struct sock *sk, long timeo);
 static void sctp_destruct_sock(struct sock *sk);
 static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
-					union sctp_addr *addr, int len);
+					union inet_addr *addr, int len);
 static int sctp_bindx_add(struct sock *, struct sockaddr *, int);
 static int sctp_bindx_rem(struct sock *, struct sockaddr *, int);
 static int sctp_send_asconf_add_ip(struct sock *, struct sockaddr *, int);
 static int sctp_send_asconf_del_ip(struct sock *, struct sockaddr *, int);
 static int sctp_send_asconf(struct sctp_association *asoc,
 			    struct sctp_chunk *chunk);
-static int sctp_do_bind(struct sock *, union sctp_addr *, int);
+static int sctp_do_bind(struct sock *, union inet_addr *, int);
 static int sctp_autobind(struct sock *sk);
 static void sctp_sock_migrate(struct sock *, struct sock *,
 			      struct sctp_association *, sctp_socket_type_t);
@@ -173,7 +173,7 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
 }
 
 /* Verify that this is a valid address. */
-static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
+static inline int sctp_verify_addr(struct sock *sk, union inet_addr *addr,
 				   int len)
 {
 	struct sctp_af *af;
@@ -240,7 +240,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
 {
 	struct sctp_association *addr_asoc = NULL, *id_asoc = NULL;
 	struct sctp_transport *transport;
-	union sctp_addr *laddr = (union sctp_addr *)addr;
+	union inet_addr *laddr = (union inet_addr *)addr;
 
 	addr_asoc = sctp_endpoint_lookup_assoc(sctp_sk(sk)->ep,
 					       laddr,
@@ -254,7 +254,7 @@ static struct sctp_transport *sctp_addr_id2transport(struct sock *sk,
 		return NULL;
 
 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
-						(union sctp_addr *)addr);
+						(union inet_addr *)addr);
 
 	return transport;
 }
@@ -280,7 +280,7 @@ static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
 
 	/* Disallow binding twice. */
 	if (!sctp_sk(sk)->ep->base.bind_addr.port)
-		retval = sctp_do_bind(sk, (union sctp_addr *)addr,
+		retval = sctp_do_bind(sk, (union inet_addr *)addr,
 				      addr_len);
 	else
 		retval = -EINVAL;
@@ -290,11 +290,11 @@ static int sctp_bind(struct sock *sk, struct sockaddr *addr, int addr_len)
 	return retval;
 }
 
-static long sctp_get_port_local(struct sock *, union sctp_addr *);
+static long sctp_get_port_local(struct sock *, union inet_addr *);
 
 /* Verify this is a valid sockaddr. */
 static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
-					union sctp_addr *addr, int len)
+					union inet_addr *addr, int len)
 {
 	struct sctp_af *af;
 
@@ -304,7 +304,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
 
 	/* V4 mapped address are really of AF_INET family */
 	if (addr->sa.sa_family == AF_INET6 &&
-	    ipv6_addr_v4mapped(&addr->v6.sin6_addr)) {
+	    ipv6_addr_v4mapped(&addr->sin6.sin6_addr)) {
 		if (!opt->pf->af_supported(AF_INET, opt))
 			return NULL;
 	} else {
@@ -323,7 +323,7 @@ static struct sctp_af *sctp_sockaddr_af(struct sctp_sock *opt,
 }
 
 /* Bind a local address either to an endpoint or to an association.  */
-static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
+static int sctp_do_bind(struct sock *sk, union inet_addr *addr, int len)
 {
 	struct net *net = sock_net(sk);
 	struct sctp_sock *sp = sctp_sk(sk);
@@ -341,7 +341,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 		return -EINVAL;
 	}
 
-	snum = ntohs(addr->v4.sin_port);
+	snum = ntohs(addr->sin.sin_port);
 
 	pr_debug("%s: sk:%p, new addr:%pIAc, port:%d, new port:%d, len:%d\n",
 		 __func__, sk, &addr->sa, bp->port, snum, len);
@@ -378,7 +378,7 @@ static int sctp_do_bind(struct sock *sk, union sctp_addr *addr, int len)
 	 * The function sctp_get_port_local() does duplicate address
 	 * detection.
 	 */
-	addr->v4.sin_port = htons(snum);
+	addr->sin.sin_port = htons(snum);
 	if ((ret = sctp_get_port_local(sk, addr))) {
 		return -EADDRINUSE;
 	}
@@ -472,7 +472,7 @@ static int sctp_bindx_add(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 			goto err_bindx_add;
 		}
 
-		retval = sctp_do_bind(sk, (union sctp_addr *)sa_addr,
+		retval = sctp_do_bind(sk, (union inet_addr *)sa_addr,
 				      af->sockaddr_len);
 
 		addr_buf += af->sockaddr_len;
@@ -510,8 +510,8 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
 	struct sctp_bind_addr		*bp;
 	struct sctp_chunk		*chunk;
 	struct sctp_sockaddr_entry	*laddr;
-	union sctp_addr			*addr;
-	union sctp_addr			saveaddr;
+	union inet_addr			*addr;
+	union inet_addr			saveaddr;
 	void				*addr_buf;
 	struct sctp_af			*af;
 	struct list_head		*p;
@@ -545,7 +545,7 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
 			addr = addr_buf;
-			af = sctp_get_af_specific(addr->v4.sin_family);
+			af = sctp_get_af_specific(addr->sin.sin_family);
 			if (!af) {
 				retval = -EINVAL;
 				goto out;
@@ -578,7 +578,7 @@ static int sctp_send_asconf_add_ip(struct sock		*sk,
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
 			addr = addr_buf;
-			af = sctp_get_af_specific(addr->v4.sin_family);
+			af = sctp_get_af_specific(addr->sin.sin_family);
 			memcpy(&saveaddr, addr, af->sockaddr_len);
 			retval = sctp_add_bind_addr(bp, &saveaddr,
 						    SCTP_ADDR_NEW, GFP_ATOMIC);
@@ -631,7 +631,7 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 	struct sctp_bind_addr *bp = &ep->base.bind_addr;
 	int retval = 0;
 	void *addr_buf;
-	union sctp_addr *sa_addr;
+	union inet_addr *sa_addr;
 	struct sctp_af *af;
 
 	pr_debug("%s: sk:%p, addrs:%p, addrcnt:%d\n",
@@ -661,14 +661,14 @@ static int sctp_bindx_rem(struct sock *sk, struct sockaddr *addrs, int addrcnt)
 			goto err_bindx_rem;
 		}
 
-		if (sa_addr->v4.sin_port &&
-		    sa_addr->v4.sin_port != htons(bp->port)) {
+		if (sa_addr->sin.sin_port &&
+		    sa_addr->sin.sin_port != htons(bp->port)) {
 			retval = -EINVAL;
 			goto err_bindx_rem;
 		}
 
-		if (!sa_addr->v4.sin_port)
-			sa_addr->v4.sin_port = htons(bp->port);
+		if (!sa_addr->sin.sin_port)
+			sa_addr->sin.sin_port = htons(bp->port);
 
 		/* FIXME - There is probably a need to check if sk->sk_saddr and
 		 * sk->sk_rcv_addr are currently set to one of the addresses to
@@ -713,7 +713,7 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 	struct sctp_transport	*transport;
 	struct sctp_bind_addr	*bp;
 	struct sctp_chunk	*chunk;
-	union sctp_addr		*laddr;
+	union inet_addr		*laddr;
 	void			*addr_buf;
 	struct sctp_af		*af;
 	struct sctp_sockaddr_entry *saddr;
@@ -750,7 +750,7 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
 			laddr = addr_buf;
-			af = sctp_get_af_specific(laddr->v4.sin_family);
+			af = sctp_get_af_specific(laddr->sin.sin_family);
 			if (!af) {
 				retval = -EINVAL;
 				goto out;
@@ -770,31 +770,31 @@ static int sctp_send_asconf_del_ip(struct sock		*sk,
 		 * association.
 		 */
 		bp = &asoc->base.bind_addr;
-		laddr = sctp_find_unmatch_addr(bp, (union sctp_addr *)addrs,
+		laddr = sctp_find_unmatch_addr(bp, (union inet_addr *)addrs,
 					       addrcnt, sp);
 		if ((laddr == NULL) && (addrcnt == 1)) {
 			if (asoc->asconf_addr_del_pending)
 				continue;
 			asoc->asconf_addr_del_pending =
-			    kzalloc(sizeof(union sctp_addr), GFP_ATOMIC);
+			    kzalloc(sizeof(union inet_addr), GFP_ATOMIC);
 			if (asoc->asconf_addr_del_pending == NULL) {
 				retval = -ENOMEM;
 				goto out;
 			}
 			asoc->asconf_addr_del_pending->sa.sa_family =
 				    addrs->sa_family;
-			asoc->asconf_addr_del_pending->v4.sin_port =
+			asoc->asconf_addr_del_pending->sin.sin_port =
 				    htons(bp->port);
 			if (addrs->sa_family == AF_INET) {
 				struct sockaddr_in *sin;
 
 				sin = (struct sockaddr_in *)addrs;
-				asoc->asconf_addr_del_pending->v4.sin_addr.s_addr = sin->sin_addr.s_addr;
+				asoc->asconf_addr_del_pending->sin.sin_addr.s_addr = sin->sin_addr.s_addr;
 			} else if (addrs->sa_family == AF_INET6) {
 				struct sockaddr_in6 *sin6;
 
 				sin6 = (struct sockaddr_in6 *)addrs;
-				asoc->asconf_addr_del_pending->v6.sin6_addr = sin6->sin6_addr;
+				asoc->asconf_addr_del_pending->sin6.sin6_addr = sin6->sin6_addr;
 			}
 
 			pr_debug("%s: keep the last address asoc:%p %pIAc at %p\n",
@@ -824,7 +824,7 @@ skip_mkasconf:
 		addr_buf = addrs;
 		for (i = 0; i < addrcnt; i++) {
 			laddr = addr_buf;
-			af = sctp_get_af_specific(laddr->v4.sin_family);
+			af = sctp_get_af_specific(laddr->sin.sin_family);
 			list_for_each_entry(saddr, &bp->address_list, list) {
 				if (sctp_cmp_addr_exact(&saddr->a, laddr))
 					saddr->state = SCTP_ADDR_DEL;
@@ -856,12 +856,12 @@ out:
 int sctp_asconf_mgmt(struct sctp_sock *sp, struct sctp_sockaddr_entry *addrw)
 {
 	struct sock *sk = sctp_opt2sk(sp);
-	union sctp_addr *addr;
+	union inet_addr *addr;
 	struct sctp_af *af;
 
 	/* It is safe to write port space in caller. */
 	addr = &addrw->a;
-	addr->v4.sin_port = htons(sp->ep->base.bind_addr.port);
+	addr->sin.sin_port = htons(sp->ep->base.bind_addr.port);
 	af = sctp_get_af_specific(addr->sa.sa_family);
 	if (!af)
 		return -EINVAL;
@@ -1048,14 +1048,14 @@ static int __sctp_connect(struct sock* sk,
 	struct sctp_association *asoc = NULL;
 	struct sctp_association *asoc2;
 	struct sctp_transport *transport;
-	union sctp_addr to;
+	union inet_addr to;
 	struct sctp_af *af;
 	sctp_scope_t scope;
 	long timeo;
 	int err = 0;
 	int addrcnt = 0;
 	int walk_size = 0;
-	union sctp_addr *sa_addr = NULL;
+	union inet_addr *sa_addr = NULL;
 	void *addr_buf;
 	unsigned short port;
 	unsigned int f_flags = 0;
@@ -1093,7 +1093,7 @@ static int __sctp_connect(struct sock* sk,
 			goto out_free;
 		}
 
-		port = ntohs(sa_addr->v4.sin_port);
+		port = ntohs(sa_addr->sin.sin_port);
 
 		/* Save current address so we can work with it */
 		memcpy(&to, sa_addr, af->sockaddr_len);
@@ -1569,7 +1569,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 	struct sctp_association *new_asoc=NULL, *asoc=NULL;
 	struct sctp_transport *transport, *chunk_tp;
 	struct sctp_chunk *chunk;
-	union sctp_addr to;
+	union inet_addr to;
 	struct sockaddr *msg_name = NULL;
 	struct sctp_sndrcvinfo default_sinfo;
 	struct sctp_sndrcvinfo *sinfo;
@@ -1611,7 +1611,7 @@ static int sctp_sendmsg(struct kiocb *iocb, struct sock *sk,
 	if (!sctp_style(sk, UDP_HIGH_BANDWIDTH) && msg->msg_name) {
 		int msg_namelen = msg->msg_namelen;
 
-		err = sctp_verify_addr(sk, (union sctp_addr *)msg->msg_name,
+		err = sctp_verify_addr(sk, (union inet_addr *)msg->msg_name,
 				       msg_namelen);
 		if (err)
 			return err;
@@ -2477,7 +2477,7 @@ static int sctp_setsockopt_peer_addr_params(struct sock *sk,
 	/* If an address other than INADDR_ANY is specified, and
 	 * no transport is found, then the request is invalid.
 	 */
-	if (!sctp_is_any(sk, ( union sctp_addr *)&params.spp_address)) {
+	if (!inet_addr_any((union inet_addr *)&params.spp_address)) {
 		trans = sctp_addr_id2transport(sk, &params.spp_address,
 					       params.spp_assoc_id);
 		if (!trans)
@@ -3059,15 +3059,15 @@ static int sctp_setsockopt_peer_primary_addr(struct sock *sk, char __user *optva
 	if (!af)
 		return -EINVAL;
 
-	if (!af->addr_valid((union sctp_addr *)&prim.sspp_addr, sp, NULL))
+	if (!af->addr_valid((union inet_addr *)&prim.sspp_addr, sp, NULL))
 		return -EADDRNOTAVAIL;
 
-	if (!sctp_assoc_lookup_laddr(asoc, (union sctp_addr *)&prim.sspp_addr))
+	if (!sctp_assoc_lookup_laddr(asoc, (union inet_addr *)&prim.sspp_addr))
 		return -EADDRNOTAVAIL;
 
 	/* Create an ASCONF chunk with SET_PRIMARY parameter	*/
 	chunk = sctp_make_asconf_set_prim(asoc,
-					  (union sctp_addr *)&prim.sspp_addr);
+					  (union inet_addr *)&prim.sspp_addr);
 	if (!chunk)
 		return -ENOMEM;
 
@@ -3496,7 +3496,7 @@ static int sctp_setsockopt_paddr_thresholds(struct sock *sk,
 		return -EFAULT;
 
 
-	if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) {
+	if (inet_addr_any((const union inet_addr *)&val.spt_address)) {
 		asoc = sctp_id2assoc(sk, val.spt_assoc_id);
 		if (!asoc)
 			return -ENOENT;
@@ -4094,7 +4094,7 @@ static int sctp_getsockopt_sctp_status(struct sock *sk, int len,
 			transport->af_specific->sockaddr_len);
 	/* Map ipv4 address into v4-mapped-on-v6 address.  */
 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
-		(union sctp_addr *)&status.sstat_primary.spinfo_address);
+		(union inet_addr *)&status.sstat_primary.spinfo_address);
 	status.sstat_primary.spinfo_state = transport->state;
 	status.sstat_primary.spinfo_cwnd = transport->cwnd;
 	status.sstat_primary.spinfo_srtt = transport->srtt;
@@ -4449,7 +4449,7 @@ static int sctp_getsockopt_peer_addr_params(struct sock *sk, int len,
 	/* If an address other than INADDR_ANY is specified, and
 	 * no transport is found, then the request is invalid.
 	 */
-	if (!sctp_is_any(sk, ( union sctp_addr *)&params.spp_address)) {
+	if (!inet_addr_any((union inet_addr *)&params.spp_address)) {
 		trans = sctp_addr_id2transport(sk, &params.spp_address,
 					       params.spp_assoc_id);
 		if (!trans) {
@@ -4633,7 +4633,7 @@ static int sctp_getsockopt_peer_addrs(struct sock *sk, int len,
 	struct sctp_getaddrs getaddrs;
 	struct sctp_transport *from;
 	void __user *to;
-	union sctp_addr temp;
+	union inet_addr temp;
 	struct sctp_sock *sp = sctp_sk(sk);
 	int addrlen;
 	size_t space_left;
@@ -4680,7 +4680,7 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
 			    size_t space_left, int *bytes_copied)
 {
 	struct sctp_sockaddr_entry *addr;
-	union sctp_addr temp;
+	union inet_addr temp;
 	int cnt = 0;
 	int addrlen;
 	struct net *net = sock_net(sk);
@@ -4698,8 +4698,8 @@ static int sctp_copy_laddrs(struct sock *sk, __u16 port, void *to,
 		    (AF_INET == addr->a.sa.sa_family))
 			continue;
 		memcpy(&temp, &addr->a, sizeof(temp));
-		if (!temp.v4.sin_port)
-			temp.v4.sin_port = htons(port);
+		if (!temp.sin.sin_port)
+			temp.sin.sin_port = htons(port);
 
 		sctp_get_pf_specific(sk->sk_family)->addr_v4map(sctp_sk(sk),
 								&temp);
@@ -4730,7 +4730,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
 	struct sctp_getaddrs getaddrs;
 	struct sctp_sockaddr_entry *addr;
 	void __user *to;
-	union sctp_addr temp;
+	union inet_addr temp;
 	struct sctp_sock *sp = sctp_sk(sk);
 	int addrlen;
 	int err = 0;
@@ -4773,7 +4773,7 @@ static int sctp_getsockopt_local_addrs(struct sock *sk, int len,
 	if (sctp_list_single_entry(&bp->address_list)) {
 		addr = list_entry(bp->address_list.next,
 				  struct sctp_sockaddr_entry, list);
-		if (sctp_is_any(sk, &addr->a)) {
+		if (inet_addr_any(&addr->a)) {
 			cnt = sctp_copy_laddrs(sk, bp->port, addrs,
 						space_left, &bytes_copied);
 			if (cnt < 0) {
@@ -4852,7 +4852,7 @@ static int sctp_getsockopt_primary_addr(struct sock *sk, int len,
 		asoc->peer.primary_path->af_specific->sockaddr_len);
 
 	sctp_get_pf_specific(sk->sk_family)->addr_v4map(sp,
-			(union sctp_addr *)&prim.ssp_addr);
+			(union inet_addr *)&prim.ssp_addr);
 
 	if (put_user(len, optlen))
 		return -EFAULT;
@@ -5605,7 +5605,7 @@ static int sctp_getsockopt_paddr_thresholds(struct sock *sk,
 	if (copy_from_user(&val, (struct sctp_paddrthlds __user *)optval, len))
 		return -EFAULT;
 
-	if (sctp_is_any(sk, (const union sctp_addr *)&val.spt_address)) {
+	if (inet_addr_any((const union inet_addr *)&val.spt_address)) {
 		asoc = sctp_id2assoc(sk, val.spt_assoc_id);
 		if (!asoc)
 			return -ENOENT;
@@ -5869,14 +5869,14 @@ static void sctp_unhash(struct sock *sk)
 static struct sctp_bind_bucket *sctp_bucket_create(
 	struct sctp_bind_hashbucket *head, struct net *, unsigned short snum);
 
-static long sctp_get_port_local(struct sock *sk, union sctp_addr *addr)
+static long sctp_get_port_local(struct sock *sk, union inet_addr *addr)
 {
 	struct sctp_bind_hashbucket *head; /* hash list */
 	struct sctp_bind_bucket *pp;
 	unsigned short snum;
 	int ret;
 
-	snum = ntohs(addr->v4.sin_port);
+	snum = ntohs(addr->sin.sin_port);
 
 	pr_debug("%s: begins, snum:%d\n", __func__, snum);
 
@@ -6023,12 +6023,12 @@ fail:
  */
 static int sctp_get_port(struct sock *sk, unsigned short snum)
 {
-	union sctp_addr addr;
+	union inet_addr addr;
 	struct sctp_af *af = sctp_sk(sk)->pf->af;
 
 	/* Set up a dummy address struct from the sk. */
 	af->from_sk(&addr, sk);
-	addr.v4.sin_port = htons(snum);
+	addr.sin.sin_port = htons(snum);
 
 	/* Note: sk->sk_num gets filled in if ephemeral port request. */
 	return !!sctp_get_port_local(sk, &addr);
@@ -6264,6 +6264,16 @@ void sctp_put_port(struct sock *sk)
 	sctp_local_bh_enable();
 }
 
+static void sctp_inaddr_any(union inet_addr *addr, sa_family_t family, __be16 port)
+{
+	memset(addr, 0x00, sizeof(union inet_addr));
+	addr->sa.sa_family = family;
+	if (family == AF_INET)
+		addr->sin.sin_port = port;
+	else
+		addr->sin6.sin6_port = port;
+}
+
 /*
  * The system picks an ephemeral port and choose an address set equivalent
  * to binding with a wildcard address.
@@ -6272,7 +6282,7 @@ void sctp_put_port(struct sock *sk)
  */
 static int sctp_autobind(struct sock *sk)
 {
-	union sctp_addr autoaddr;
+	union inet_addr autoaddr;
 	struct sctp_af *af;
 	__be16 port;
 
@@ -6280,7 +6290,7 @@ static int sctp_autobind(struct sock *sk)
 	af = sctp_sk(sk)->pf->af;
 
 	port = htons(inet_sk(sk)->inet_num);
-	af->inaddr_any(&autoaddr, port);
+	sctp_inaddr_any(&autoaddr, af->sa_family, port);
 
 	return sctp_do_bind(sk, &autoaddr, af->sockaddr_len);
 }
diff --git a/net/sctp/transport.c b/net/sctp/transport.c
index e332efb..aeaec64 100644
--- a/net/sctp/transport.c
+++ b/net/sctp/transport.c
@@ -9,7 +9,7 @@
  *
  * This module provides the abstraction for an SCTP tranport representing
  * a remote transport address.  For local transport addresses, we just use
- * union sctp_addr.
+ * union inet_addr.
  *
  * This SCTP implementation is free software;
  * you can redistribute it and/or modify it under the terms of
@@ -55,13 +55,13 @@
 /* Initialize a new transport from provided memory.  */
 static struct sctp_transport *sctp_transport_init(struct net *net,
 						  struct sctp_transport *peer,
-						  const union sctp_addr *addr,
+						  const union inet_addr *addr,
 						  gfp_t gfp)
 {
 	/* Copy in the address.  */
 	peer->ipaddr = *addr;
 	peer->af_specific = sctp_get_af_specific(addr->sa.sa_family);
-	memset(&peer->saddr, 0, sizeof(union sctp_addr));
+	memset(&peer->saddr, 0, sizeof(union inet_addr));
 
 	peer->sack_generation = 0;
 
@@ -105,7 +105,7 @@ static struct sctp_transport *sctp_transport_init(struct net *net,
 
 /* Allocate and initialize a new transport.  */
 struct sctp_transport *sctp_transport_new(struct net *net,
-					  const union sctp_addr *addr,
+					  const union inet_addr *addr,
 					  gfp_t gfp)
 {
 	struct sctp_transport *transport;
@@ -267,7 +267,7 @@ void sctp_transport_update_pmtu(struct sock *sk, struct sctp_transport *t, u32 p
  * address.
  */
 void sctp_transport_route(struct sctp_transport *transport,
-			  union sctp_addr *saddr, struct sctp_sock *opt)
+			  union inet_addr *saddr, struct sctp_sock *opt)
 {
 	struct sctp_association *asoc = transport->asoc;
 	struct sctp_af *af = transport->af_specific;
@@ -275,7 +275,7 @@ void sctp_transport_route(struct sctp_transport *transport,
 	af->get_dst(transport, saddr, &transport->fl, sctp_opt2sk(opt));
 
 	if (saddr)
-		memcpy(&transport->saddr, saddr, sizeof(union sctp_addr));
+		memcpy(&transport->saddr, saddr, sizeof(union inet_addr));
 	else
 		af->get_saddr(opt, transport, &transport->fl);
 
diff --git a/net/sctp/ulpevent.c b/net/sctp/ulpevent.c
index 81089ed..d81b983 100644
--- a/net/sctp/ulpevent.c
+++ b/net/sctp/ulpevent.c
@@ -344,7 +344,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_peer_addr_change(
 	/* Map ipv4 address into v4-mapped-on-v6 address.  */
 	sctp_get_pf_specific(asoc->base.sk->sk_family)->addr_v4map(
 					sctp_sk(asoc->base.sk),
-					(union sctp_addr *)&spc->spc_aaddr);
+					(union inet_addr *)&spc->spc_aaddr);
 
 	return event;
 
-- 
1.7.7.6

^ permalink raw reply related

* Re: [PATCH] net: cpsw: Add support for wake-on-lan for cpsw
From: Mugunthan V N @ 2013-08-19 10:25 UTC (permalink / raw)
  To: ujhelyi.m; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1376907191-25491-1-git-send-email-ujhelyi.m@gmail.com>

On Monday 19 August 2013 03:43 PM, ujhelyi.m@gmail.com wrote:
> From: Matus Ujhelyi <ujhelyi.m@gmail.com>
>
> Signed-off-by: Matus Ujhelyi <ujhelyi.m@gmail.com>
> ---
Please add some commit description.

Regards
Mugunthan V N

^ permalink raw reply

* Re: [PATCH] driver:net:stmmac: Disable DMA store and forward mode if platform data force_sf_dma_mode is negative.
From: Sonic Zhang @ 2013-08-19 10:51 UTC (permalink / raw)
  To: Giuseppe CAVALLARO; +Cc: netdev, adi-buildroot-devel, Sonic Zhang
In-Reply-To: <5211CD14.3080808@st.com>

Hi Giuseppe,

On Mon, Aug 19, 2013 at 3:45 PM, Giuseppe CAVALLARO
<peppe.cavallaro@st.com> wrote:
> On 8/19/2013 9:31 AM, Sonic Zhang wrote:
>>
>> Hi Giuseppe,
>>
>> On Mon, Aug 19, 2013 at 2:03 PM, Giuseppe CAVALLARO
>> <peppe.cavallaro@st.com> wrote:
>>>
>>> Hello Sonic
>>>
>>>
>>> On 8/15/2013 9:37 AM, Sonic Zhang wrote:
>>>>
>>>>
>>>> From: Sonic Zhang <sonic.zhang@analog.com>
>>>>
>>>> Some synopsys ip implementation doesn't support DMA store and forward
>>>> mode,
>>>> such as BF60x. So, define force_sf_dma_mode negative to use DMA
>>>> thresholds
>>>> only.
>>>
>>>
>>>
>>> I think that you should not pass the force_sf_dma_mode platform field
>>> at all (and it doesn't make sense to force it as negative).
>>> To use the threshold you should reset tx_coe. In fact, your HW cannot
>>> perform the Hw csum if SF is not available.
>>> Note that, the HW cap register (if available) can override (set/reset)
>>>   tx_coe.
>>
>>
>> Even if I reset tx_coe, the SF mode is still set to RX DMA in current
>> stmmac_dma_operation_mode(). SF mode is not supported in both RX DMA
>> and TX DMA in Blackfin MAC.
>
>
> yes this is true. the SF is always set for the RX path because I have
> never had and known HW w/o RX csum (since the 209).
>
> So I think the code could be improved to disable/enable the SF also for
> the RX path.
>
>
>>>
>>> I tested, long time ago, this scenario on old mac w/o HW cap register
>>> and w/o SF.
>>
>>
>> Blackfin synopsys MAC IP has the HW cap register with tx_coe set to 1,
>> but the HW tx_coe doesn't really work. I have the other patch to
>> disable HW tx_coe in board file and override the HW cap register.
>
>
> AFAIK the HW shouldn't be able to perform the csum in HW w/o SF.
>
> Maybe, an easy way could be to use a new field to force the threshold
> mode. This should also remove the csum in HW (IMO) and program the
> DMA operation register.
>

The problem is that HW RX csum works perfectly on Blackfin MAC
although the SF mode is not supported in RX DMA. I may need 2 platform
fields to force RX DMA threshold and disable HW tx_coe. One field
doesn't cover both cases well.

Which 2 fields do you prefer?

Thanks

Sonic

^ permalink raw reply

* [PATCH] ipv6: handle Redirect ICMP Message with no Redirected Header option
From: Duan Jiong @ 2013-08-19 10:54 UTC (permalink / raw)
  To: davem; +Cc: netdev

From: Duan Jiong <duanj.fnst@cn.fujitsu.com>

rfc 4861 says the Redirected Header option is optional, so
the kernel should not drop the Redirect Message that has no
Redirected Header option. In this patch, the function
ip6_redirect_no_header() is introduced to deal with that
condition.

Signed-off-by: Duan Jiong <duanj.fnst@cn.fujitsu.com>
---
 include/net/ip6_route.h |    1 +
 net/ipv6/ndisc.c        |    4 +++-
 net/ipv6/route.c        |   21 +++++++++++++++++++++
 3 files changed, 25 insertions(+), 1 deletions(-)

diff --git a/include/net/ip6_route.h b/include/net/ip6_route.h
index 260f83f..7966f54 100644
--- a/include/net/ip6_route.h
+++ b/include/net/ip6_route.h
@@ -135,6 +135,7 @@ extern void ip6_update_pmtu(struct sk_buff *skb, struct net *net, __be32 mtu,
 extern void ip6_sk_update_pmtu(struct sk_buff *skb, struct sock *sk,
 			       __be32 mtu);
 extern void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark);
+extern void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, u32 mark);
 extern void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk);
 
 struct netlink_callback;
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 79aa965..04d31c2 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1369,8 +1369,10 @@ static void ndisc_redirect_rcv(struct sk_buff *skb)
 	if (!ndisc_parse_options(msg->opt, ndoptlen, &ndopts))
 		return;
 
-	if (!ndopts.nd_opts_rh)
+	if (!ndopts.nd_opts_rh) {
+		ip6_redirect_no_header(skb, dev_net(skb->dev), 0, 0);
 		return;
+	}
 
 	hdr = (u8 *)ndopts.nd_opts_rh;
 	hdr += 8;
diff --git a/net/ipv6/route.c b/net/ipv6/route.c
index b70f897..9934b87 100644
--- a/net/ipv6/route.c
+++ b/net/ipv6/route.c
@@ -1178,6 +1178,27 @@ void ip6_redirect(struct sk_buff *skb, struct net *net, int oif, u32 mark)
 }
 EXPORT_SYMBOL_GPL(ip6_redirect);
 
+void ip6_redirect_no_header(struct sk_buff *skb, struct net *net, int oif, u32 mark)
+{
+	const struct ipv6hdr *iph = (struct ipv6hdr *) skb_network_header(skb);
+	struct rd_msg *msg = (struct rd_msg *)skb_transport_header(skb);
+	struct dst_entry *dst;
+	struct flowi6 fl6;
+
+	memset(&fl6, 0, sizeof(fl6));
+	fl6.flowi6_oif = oif;
+	fl6.flowi6_mark = mark;
+	fl6.flowi6_flags = 0;
+	fl6.daddr = msg->dest;
+	fl6.saddr = iph->daddr;
+
+	dst = ip6_route_output(net, NULL, &fl6);
+	if (!dst->error)
+		rt6_do_redirect(dst, NULL, skb);
+	dst_release(dst);
+}
+EXPORT_SYMBOL_GPL(ip6_redirect_no_header);
+
 void ip6_sk_redirect(struct sk_buff *skb, struct sock *sk)
 {
 	ip6_redirect(skb, sock_net(sk), sk->sk_bound_dev_if, sk->sk_mark);
-- 
1.7.3.1

^ permalink raw reply related

* Re: 3.11-rc6 genetlink locking fix offends lockdep
From: Ding Tianhong @ 2013-08-19 11:00 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Hugh Dickins, Linus Torvalds, Greg KH, David S. Miller,
	Otcheretianski, Andrei, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org, stable@vger.kernel.org, Pravin B Shelar,
	Thomas Graf
In-Reply-To: <1376899214.14734.6.camel@jlt4.sipsolutions.net>

On 2013/8/19 16:00, Johannes Berg wrote:
> 
>> 3.11-rc6's commit 58ad436fcf49 ("genetlink: fix family dump race")
>> gives me the lockdep trace below at startup.
> 
> Hmm. Yes, I see now how this happens, not sure why I didn't run into it.
> 
> The problem is that genl_family_rcv_msg() is called with the genl_lock
> held, and then calls netlink_dump_start() with it held, creating a
> genl_lock->cb_mutex dependency, but obviously the dump continuation is
> the other way around.
> 
> We could use the semaphore instead, I believe, but I don't really
> understand the mutex vs. semaphore well enough to be sure that's
> correct.
> 
> johannes
> 
it is useless, the logic need to modify or otherwise it will still call lockdep trace.
maybe i could send a patch for it, if you wish.

> 
> diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
> index f85f8a2..6cfa646 100644
> --- a/net/netlink/genetlink.c
> +++ b/net/netlink/genetlink.c
> @@ -792,7 +792,7 @@ static int ctrl_dumpfamily(struct sk_buff *skb, struct netlink_callback *cb)
>  	bool need_locking = chains_to_skip || fams_to_skip;
>  
>  	if (need_locking)
> -		genl_lock();
> +		down_read(&cb_lock);
>  
>  	for (i = chains_to_skip; i < GENL_FAM_TAB_SIZE; i++) {
>  		n = 0;
> @@ -815,7 +815,7 @@ errout:
>  	cb->args[1] = n;
>  
>  	if (need_locking)
> -		genl_unlock();
> +		up_read(&cb_lock);
>  
>  	return skb->len;
>  }
> 
> 
> --
> To unsubscribe from this list: send the line "unsubscribe netdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> 
> .
> 

^ permalink raw reply

* [PATCHv2] net: cpsw: Add support for wake-on-lan for cpsw
From: ujhelyi.m @ 2013-08-19 11:05 UTC (permalink / raw)
  To: davem, mugunthanvnm, netdev; +Cc: linux-kernel, Matus Ujhelyi

From: Matus Ujhelyi <ujhelyi.m@gmail.com>

Some phy's can be configured to enable wake on lan (e.g. at803x or marvell 88E1318S).
There is no way how to enable wol on CPSW with such connected phys. This patch
adds this support. It is provided by calling the phy's related code.

Tested on board with at8030x connected phy. Wol interrupt line is
connected to GPIO0 on am335x.

Signed-off-by: Matus Ujhelyi <ujhelyi.m@gmail.com>
---
 drivers/net/ethernet/ti/cpsw.c |   23 +++++++++++++++++++++++
 1 file changed, 23 insertions(+)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 22a7a43..fe8d973 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1416,6 +1416,27 @@ static int cpsw_set_settings(struct net_device *ndev, struct ethtool_cmd *ecmd)
 		return -EOPNOTSUPP;
 }
 
+static void cpsw_get_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	int slave_no = cpsw_slave_index(priv);
+	wol->supported = 0;
+	wol->wolopts = 0;
+	if (priv->slaves[slave_no].phy)
+		phy_ethtool_get_wol(priv->slaves[slave_no].phy, wol);
+
+}
+
+static int cpsw_set_wol(struct net_device *ndev, struct ethtool_wolinfo *wol)
+{
+	struct cpsw_priv *priv = netdev_priv(ndev);
+	int slave_no = cpsw_slave_index(priv);
+	if (priv->slaves[slave_no].phy)
+		return phy_ethtool_set_wol(priv->slaves[slave_no].phy, wol);
+	else
+		return -EOPNOTSUPP;
+}
+
 static const struct ethtool_ops cpsw_ethtool_ops = {
 	.get_drvinfo	= cpsw_get_drvinfo,
 	.get_msglevel	= cpsw_get_msglevel,
@@ -1426,6 +1447,8 @@ static const struct ethtool_ops cpsw_ethtool_ops = {
 	.set_settings	= cpsw_set_settings,
 	.get_coalesce	= cpsw_get_coalesce,
 	.set_coalesce	= cpsw_set_coalesce,
+	.get_wol        = cpsw_get_wol,
+	.set_wol        = cpsw_set_wol,
 };
 
 static void cpsw_slave_init(struct cpsw_slave *slave, struct cpsw_priv *priv,
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH 0/7] replace devm_request_and_ioremap by devm_ioremap_resource
From: Julia Lawall @ 2013-08-19 11:20 UTC (permalink / raw)
  To: linux-fbdev
  Cc: kernel-janitors, linux-serial, linux-kernel, linux-tegra,
	linux-pci, linux-arm-kernel, netdev, linux-mmc

devm_request_and_ioremap has been replaced by devm_ioremap_resource, which
gives more informative error return code information.  This patch series
removes the remaining uses of devm_request_and_ioremap.

This patch series was generated using the semantic patch
scripts/coccinelle/api/devm_ioremap_resource.cocci from the Linux kernel
source tree.  Manual modifications have been made to move associated calls
to platform_get_resource closer to the resulting call to
devm_ioremap_resource and to remove the associated error handling code.

^ permalink raw reply

* [PATCH 5/7] bcm63xx_enet: replace devm_request_and_ioremap by devm_ioremap_resource
From: Julia Lawall @ 2013-08-19 11:20 UTC (permalink / raw)
  To: netdev; +Cc: kernel-janitors, linux-kernel
In-Reply-To: <1376911241-27720-1-git-send-email-Julia.Lawall@lip6.fr>

From: Julia Lawall <Julia.Lawall@lip6.fr>

Use devm_ioremap_resource instead of devm_request_and_ioremap.

This was done using the semantic patch
scripts/coccinelle/api/devm_ioremap_resource.cocci

The relevant call to platform_get_resource was manually moved down to the
call to devm_ioremap_resource.

Signed-off-by: Julia Lawall <Julia.Lawall@lip6.fr>

---
 drivers/net/ethernet/broadcom/bcm63xx_enet.c |   10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/broadcom/bcm63xx_enet.c b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
index b1bcd4b..89ff09e 100644
--- a/drivers/net/ethernet/broadcom/bcm63xx_enet.c
+++ b/drivers/net/ethernet/broadcom/bcm63xx_enet.c
@@ -1747,11 +1747,10 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	if (!bcm_enet_shared_base[0])
 		return -ENODEV;
 
-	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
 	res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
 	res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
-	if (!res_mem || !res_irq || !res_irq_rx || !res_irq_tx)
+	if (!res_irq || !res_irq_rx || !res_irq_tx)
 		return -ENODEV;
 
 	ret = 0;
@@ -1767,9 +1766,10 @@ static int bcm_enet_probe(struct platform_device *pdev)
 	if (ret)
 		goto out;
 
-	priv->base = devm_request_and_ioremap(&pdev->dev, res_mem);
-	if (priv->base == NULL) {
-		ret = -ENOMEM;
+	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	priv->base = devm_ioremap_resource(&pdev->dev, res_mem);
+	if (IS_ERR(priv->base)) {
+		ret = PTR_ERR(priv->base);
 		goto out;
 	}
 

^ permalink raw reply related

* Re: 3.11-rc6 genetlink locking fix offends lockdep
From: Johannes Berg @ 2013-08-19 11:22 UTC (permalink / raw)
  To: Ding Tianhong
  Cc: Hugh Dickins, Linus Torvalds, Greg KH, David S. Miller,
	Otcheretianski, Andrei, linux-kernel@vger.kernel.org,
	netdev@vger.kernel.org, stable@vger.kernel.org, Pravin B Shelar,
	Thomas Graf
In-Reply-To: <5211FAB3.7080400@huawei.com>

On Mon, 2013-08-19 at 19:00 +0800, Ding Tianhong wrote:
> On 2013/8/19 16:00, Johannes Berg wrote:
> > 
> >> 3.11-rc6's commit 58ad436fcf49 ("genetlink: fix family dump race")
> >> gives me the lockdep trace below at startup.
> > 
> > Hmm. Yes, I see now how this happens, not sure why I didn't run into it.
> > 
> > The problem is that genl_family_rcv_msg() is called with the genl_lock
> > held, and then calls netlink_dump_start() with it held, creating a
> > genl_lock->cb_mutex dependency, but obviously the dump continuation is
> > the other way around.
> > 
> > We could use the semaphore instead, I believe, but I don't really
> > understand the mutex vs. semaphore well enough to be sure that's
> > correct.
> > 
> > johannes
> > 
> it is useless, the logic need to modify or otherwise it will still call lockdep trace.

I don't believe so, the semaphore and cb_mutex don't have a dependency
yet, afaict.

> maybe i could send a patch for it, if you wish.

What do you mean?

johannes

^ permalink raw reply

* Re: [PATCHv2] net: cpsw: Add support for wake-on-lan for cpsw
From: Mugunthan V N @ 2013-08-19 11:39 UTC (permalink / raw)
  To: ujhelyi.m; +Cc: davem, netdev, linux-kernel
In-Reply-To: <1376910358-19882-1-git-send-email-ujhelyi.m@gmail.com>

On Monday 19 August 2013 04:35 PM, ujhelyi.m@gmail.com wrote:
> From: Matus Ujhelyi <ujhelyi.m@gmail.com>
>
> Some phy's can be configured to enable wake on lan (e.g. at803x or marvell 88E1318S).
> There is no way how to enable wol on CPSW with such connected phys. This patch
> adds this support. It is provided by calling the phy's related code.
>
> Tested on board with at8030x connected phy. Wol interrupt line is
> connected to GPIO0 on am335x.
>
> Signed-off-by: Matus Ujhelyi <ujhelyi.m@gmail.com>
Looks good to me.
Acked-by: Mugunthan V N <mugunthanvnm@gmail.com>

Regards
Mugunthan V N

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox