diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/sunrpc/xprtsock.c | 66 |
1 files changed, 19 insertions, 47 deletions
diff --git a/net/sunrpc/xprtsock.c b/net/sunrpc/xprtsock.c index 7fdf2bb956a9..fc1e76788120 100644 --- a/net/sunrpc/xprtsock.c +++ b/net/sunrpc/xprtsock.c | |||
@@ -1534,23 +1534,18 @@ static unsigned short xs_next_srcport(struct sock_xprt *transport, unsigned shor | |||
1534 | return xprt_max_resvport; | 1534 | return xprt_max_resvport; |
1535 | return --port; | 1535 | return --port; |
1536 | } | 1536 | } |
1537 | 1537 | static int xs_bind(struct sock_xprt *transport, struct socket *sock) | |
1538 | static int xs_bind4(struct sock_xprt *transport, struct socket *sock) | ||
1539 | { | 1538 | { |
1540 | struct sockaddr_in myaddr = { | 1539 | struct sockaddr_storage myaddr; |
1541 | .sin_family = AF_INET, | ||
1542 | }; | ||
1543 | struct sockaddr_in *sa; | ||
1544 | int err, nloop = 0; | 1540 | int err, nloop = 0; |
1545 | unsigned short port = xs_get_srcport(transport); | 1541 | unsigned short port = xs_get_srcport(transport); |
1546 | unsigned short last; | 1542 | unsigned short last; |
1547 | 1543 | ||
1548 | sa = (struct sockaddr_in *)&transport->srcaddr; | 1544 | memcpy(&myaddr, &transport->srcaddr, transport->xprt.addrlen); |
1549 | myaddr.sin_addr = sa->sin_addr; | ||
1550 | do { | 1545 | do { |
1551 | myaddr.sin_port = htons(port); | 1546 | rpc_set_port((struct sockaddr *)&myaddr, port); |
1552 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1547 | err = kernel_bind(sock, (struct sockaddr *)&myaddr, |
1553 | sizeof(myaddr)); | 1548 | transport->xprt.addrlen); |
1554 | if (port == 0) | 1549 | if (port == 0) |
1555 | break; | 1550 | break; |
1556 | if (err == 0) { | 1551 | if (err == 0) { |
@@ -1562,44 +1557,19 @@ static int xs_bind4(struct sock_xprt *transport, struct socket *sock) | |||
1562 | if (port > last) | 1557 | if (port > last) |
1563 | nloop++; | 1558 | nloop++; |
1564 | } while (err == -EADDRINUSE && nloop != 2); | 1559 | } while (err == -EADDRINUSE && nloop != 2); |
1565 | dprintk("RPC: %s %pI4:%u: %s (%d)\n", | ||
1566 | __func__, &myaddr.sin_addr, | ||
1567 | port, err ? "failed" : "ok", err); | ||
1568 | return err; | ||
1569 | } | ||
1570 | |||
1571 | static int xs_bind6(struct sock_xprt *transport, struct socket *sock) | ||
1572 | { | ||
1573 | struct sockaddr_in6 myaddr = { | ||
1574 | .sin6_family = AF_INET6, | ||
1575 | }; | ||
1576 | struct sockaddr_in6 *sa; | ||
1577 | int err, nloop = 0; | ||
1578 | unsigned short port = xs_get_srcport(transport); | ||
1579 | unsigned short last; | ||
1580 | 1560 | ||
1581 | sa = (struct sockaddr_in6 *)&transport->srcaddr; | 1561 | if (myaddr.ss_family == PF_INET) |
1582 | myaddr.sin6_addr = sa->sin6_addr; | 1562 | dprintk("RPC: %s %pI4:%u: %s (%d)\n", __func__, |
1583 | do { | 1563 | &((struct sockaddr_in *)&myaddr)->sin_addr, |
1584 | myaddr.sin6_port = htons(port); | 1564 | port, err ? "failed" : "ok", err); |
1585 | err = kernel_bind(sock, (struct sockaddr *) &myaddr, | 1565 | else |
1586 | sizeof(myaddr)); | 1566 | dprintk("RPC: %s %pI6:%u: %s (%d)\n", __func__, |
1587 | if (port == 0) | 1567 | &((struct sockaddr_in6 *)&myaddr)->sin6_addr, |
1588 | break; | 1568 | port, err ? "failed" : "ok", err); |
1589 | if (err == 0) { | ||
1590 | transport->srcport = port; | ||
1591 | break; | ||
1592 | } | ||
1593 | last = port; | ||
1594 | port = xs_next_srcport(transport, port); | ||
1595 | if (port > last) | ||
1596 | nloop++; | ||
1597 | } while (err == -EADDRINUSE && nloop != 2); | ||
1598 | dprintk("RPC: xs_bind6 %pI6:%u: %s (%d)\n", | ||
1599 | &myaddr.sin6_addr, port, err ? "failed" : "ok", err); | ||
1600 | return err; | 1569 | return err; |
1601 | } | 1570 | } |
1602 | 1571 | ||
1572 | |||
1603 | #ifdef CONFIG_DEBUG_LOCK_ALLOC | 1573 | #ifdef CONFIG_DEBUG_LOCK_ALLOC |
1604 | static struct lock_class_key xs_key[2]; | 1574 | static struct lock_class_key xs_key[2]; |
1605 | static struct lock_class_key xs_slock_key[2]; | 1575 | static struct lock_class_key xs_slock_key[2]; |
@@ -1643,9 +1613,10 @@ static struct socket *xs_create_sock4(struct rpc_xprt *xprt, | |||
1643 | protocol, -err); | 1613 | protocol, -err); |
1644 | goto out; | 1614 | goto out; |
1645 | } | 1615 | } |
1616 | transport->srcaddr.ss_family = AF_INET; | ||
1646 | xs_reclassify_socket4(sock); | 1617 | xs_reclassify_socket4(sock); |
1647 | 1618 | ||
1648 | if (xs_bind4(transport, sock)) { | 1619 | if (xs_bind(transport, sock)) { |
1649 | sock_release(sock); | 1620 | sock_release(sock); |
1650 | goto out; | 1621 | goto out; |
1651 | } | 1622 | } |
@@ -1667,9 +1638,10 @@ static struct socket *xs_create_sock6(struct rpc_xprt *xprt, | |||
1667 | protocol, -err); | 1638 | protocol, -err); |
1668 | goto out; | 1639 | goto out; |
1669 | } | 1640 | } |
1641 | transport->srcaddr.ss_family = AF_INET6; | ||
1670 | xs_reclassify_socket6(sock); | 1642 | xs_reclassify_socket6(sock); |
1671 | 1643 | ||
1672 | if (xs_bind6(transport, sock)) { | 1644 | if (xs_bind(transport, sock)) { |
1673 | sock_release(sock); | 1645 | sock_release(sock); |
1674 | goto out; | 1646 | goto out; |
1675 | } | 1647 | } |