diff options
-rw-r--r-- | include/linux/sunrpc/svc_xprt.h | 51 | ||||
-rw-r--r-- | include/linux/sunrpc/svcsock.h | 4 | ||||
-rw-r--r-- | net/sunrpc/svc_xprt.c | 31 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 56 |
4 files changed, 110 insertions, 32 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h index 6a8445b9dfd9..09de12b63c1d 100644 --- a/include/linux/sunrpc/svc_xprt.h +++ b/include/linux/sunrpc/svc_xprt.h | |||
@@ -61,6 +61,10 @@ struct svc_xprt { | |||
61 | void *xpt_auth_cache;/* auth cache */ | 61 | void *xpt_auth_cache;/* auth cache */ |
62 | struct list_head xpt_deferred; /* deferred requests that need | 62 | struct list_head xpt_deferred; /* deferred requests that need |
63 | * to be revisted */ | 63 | * to be revisted */ |
64 | struct sockaddr_storage xpt_local; /* local address */ | ||
65 | size_t xpt_locallen; /* length of address */ | ||
66 | struct sockaddr_storage xpt_remote; /* remote peer's address */ | ||
67 | size_t xpt_remotelen; /* length of address */ | ||
64 | }; | 68 | }; |
65 | 69 | ||
66 | int svc_reg_xprt_class(struct svc_xprt_class *); | 70 | int svc_reg_xprt_class(struct svc_xprt_class *); |
@@ -70,9 +74,56 @@ void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *, | |||
70 | int svc_create_xprt(struct svc_serv *, char *, unsigned short, int); | 74 | int svc_create_xprt(struct svc_serv *, char *, unsigned short, int); |
71 | void svc_xprt_received(struct svc_xprt *); | 75 | void svc_xprt_received(struct svc_xprt *); |
72 | void svc_xprt_put(struct svc_xprt *xprt); | 76 | void svc_xprt_put(struct svc_xprt *xprt); |
77 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt); | ||
73 | static inline void svc_xprt_get(struct svc_xprt *xprt) | 78 | static inline void svc_xprt_get(struct svc_xprt *xprt) |
74 | { | 79 | { |
75 | kref_get(&xprt->xpt_ref); | 80 | kref_get(&xprt->xpt_ref); |
76 | } | 81 | } |
82 | static inline void svc_xprt_set_local(struct svc_xprt *xprt, | ||
83 | struct sockaddr *sa, int salen) | ||
84 | { | ||
85 | memcpy(&xprt->xpt_local, sa, salen); | ||
86 | xprt->xpt_locallen = salen; | ||
87 | } | ||
88 | static inline void svc_xprt_set_remote(struct svc_xprt *xprt, | ||
89 | struct sockaddr *sa, int salen) | ||
90 | { | ||
91 | memcpy(&xprt->xpt_remote, sa, salen); | ||
92 | xprt->xpt_remotelen = salen; | ||
93 | } | ||
94 | static inline unsigned short svc_addr_port(struct sockaddr *sa) | ||
95 | { | ||
96 | unsigned short ret = 0; | ||
97 | switch (sa->sa_family) { | ||
98 | case AF_INET: | ||
99 | ret = ntohs(((struct sockaddr_in *)sa)->sin_port); | ||
100 | break; | ||
101 | case AF_INET6: | ||
102 | ret = ntohs(((struct sockaddr_in6 *)sa)->sin6_port); | ||
103 | break; | ||
104 | } | ||
105 | return ret; | ||
106 | } | ||
107 | |||
108 | static inline size_t svc_addr_len(struct sockaddr *sa) | ||
109 | { | ||
110 | switch (sa->sa_family) { | ||
111 | case AF_INET: | ||
112 | return sizeof(struct sockaddr_in); | ||
113 | case AF_INET6: | ||
114 | return sizeof(struct sockaddr_in6); | ||
115 | } | ||
116 | return -EAFNOSUPPORT; | ||
117 | } | ||
118 | |||
119 | static inline unsigned short svc_xprt_local_port(struct svc_xprt *xprt) | ||
120 | { | ||
121 | return svc_addr_port((struct sockaddr *)&xprt->xpt_local); | ||
122 | } | ||
123 | |||
124 | static inline unsigned short svc_xprt_remote_port(struct svc_xprt *xprt) | ||
125 | { | ||
126 | return svc_addr_port((struct sockaddr *)&xprt->xpt_remote); | ||
127 | } | ||
77 | 128 | ||
78 | #endif /* SUNRPC_SVC_XPRT_H */ | 129 | #endif /* SUNRPC_SVC_XPRT_H */ |
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 96a229e6b9c9..206f092ad4c7 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h | |||
@@ -28,10 +28,6 @@ struct svc_sock { | |||
28 | /* private TCP part */ | 28 | /* private TCP part */ |
29 | int sk_reclen; /* length of record */ | 29 | int sk_reclen; /* length of record */ |
30 | int sk_tcplen; /* current read length */ | 30 | int sk_tcplen; /* current read length */ |
31 | |||
32 | struct sockaddr_storage sk_local; /* local address */ | ||
33 | struct sockaddr_storage sk_remote; /* remote peer's address */ | ||
34 | int sk_remotelen; /* length of address */ | ||
35 | }; | 31 | }; |
36 | 32 | ||
37 | /* | 33 | /* |
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c index 023aeb0ecfa9..eb650af50c49 100644 --- a/net/sunrpc/svc_xprt.c +++ b/net/sunrpc/svc_xprt.c | |||
@@ -125,7 +125,6 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, | |||
125 | spin_unlock(&svc_xprt_class_lock); | 125 | spin_unlock(&svc_xprt_class_lock); |
126 | if (try_module_get(xcl->xcl_owner)) { | 126 | if (try_module_get(xcl->xcl_owner)) { |
127 | struct svc_xprt *newxprt; | 127 | struct svc_xprt *newxprt; |
128 | ret = 0; | ||
129 | newxprt = xcl->xcl_ops->xpo_create | 128 | newxprt = xcl->xcl_ops->xpo_create |
130 | (serv, | 129 | (serv, |
131 | (struct sockaddr *)&sin, sizeof(sin), | 130 | (struct sockaddr *)&sin, sizeof(sin), |
@@ -133,7 +132,8 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, | |||
133 | if (IS_ERR(newxprt)) { | 132 | if (IS_ERR(newxprt)) { |
134 | module_put(xcl->xcl_owner); | 133 | module_put(xcl->xcl_owner); |
135 | ret = PTR_ERR(newxprt); | 134 | ret = PTR_ERR(newxprt); |
136 | } | 135 | } else |
136 | ret = svc_xprt_local_port(newxprt); | ||
137 | } | 137 | } |
138 | goto out; | 138 | goto out; |
139 | } | 139 | } |
@@ -144,3 +144,30 @@ int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port, | |||
144 | return ret; | 144 | return ret; |
145 | } | 145 | } |
146 | EXPORT_SYMBOL_GPL(svc_create_xprt); | 146 | EXPORT_SYMBOL_GPL(svc_create_xprt); |
147 | |||
148 | /* | ||
149 | * Copy the local and remote xprt addresses to the rqstp structure | ||
150 | */ | ||
151 | void svc_xprt_copy_addrs(struct svc_rqst *rqstp, struct svc_xprt *xprt) | ||
152 | { | ||
153 | struct sockaddr *sin; | ||
154 | |||
155 | memcpy(&rqstp->rq_addr, &xprt->xpt_remote, xprt->xpt_remotelen); | ||
156 | rqstp->rq_addrlen = xprt->xpt_remotelen; | ||
157 | |||
158 | /* | ||
159 | * Destination address in request is needed for binding the | ||
160 | * source address in RPC replies/callbacks later. | ||
161 | */ | ||
162 | sin = (struct sockaddr *)&xprt->xpt_local; | ||
163 | switch (sin->sa_family) { | ||
164 | case AF_INET: | ||
165 | rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr; | ||
166 | break; | ||
167 | case AF_INET6: | ||
168 | rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr; | ||
169 | break; | ||
170 | } | ||
171 | } | ||
172 | EXPORT_SYMBOL_GPL(svc_xprt_copy_addrs); | ||
173 | |||
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 9d0a9e6c0e10..9564d2e9520e 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -623,33 +623,13 @@ svc_recvfrom(struct svc_rqst *rqstp, struct kvec *iov, int nr, int buflen) | |||
623 | struct msghdr msg = { | 623 | struct msghdr msg = { |
624 | .msg_flags = MSG_DONTWAIT, | 624 | .msg_flags = MSG_DONTWAIT, |
625 | }; | 625 | }; |
626 | struct sockaddr *sin; | ||
627 | int len; | 626 | int len; |
628 | 627 | ||
629 | len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, | 628 | len = kernel_recvmsg(svsk->sk_sock, &msg, iov, nr, buflen, |
630 | msg.msg_flags); | 629 | msg.msg_flags); |
631 | 630 | ||
632 | /* sock_recvmsg doesn't fill in the name/namelen, so we must.. | ||
633 | */ | ||
634 | memcpy(&rqstp->rq_addr, &svsk->sk_remote, svsk->sk_remotelen); | ||
635 | rqstp->rq_addrlen = svsk->sk_remotelen; | ||
636 | |||
637 | /* Destination address in request is needed for binding the | ||
638 | * source address in RPC callbacks later. | ||
639 | */ | ||
640 | sin = (struct sockaddr *)&svsk->sk_local; | ||
641 | switch (sin->sa_family) { | ||
642 | case AF_INET: | ||
643 | rqstp->rq_daddr.addr = ((struct sockaddr_in *)sin)->sin_addr; | ||
644 | break; | ||
645 | case AF_INET6: | ||
646 | rqstp->rq_daddr.addr6 = ((struct sockaddr_in6 *)sin)->sin6_addr; | ||
647 | break; | ||
648 | } | ||
649 | |||
650 | dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", | 631 | dprintk("svc: socket %p recvfrom(%p, %Zu) = %d\n", |
651 | svsk, iov[0].iov_base, iov[0].iov_len, len); | 632 | svsk, iov[0].iov_base, iov[0].iov_len, len); |
652 | |||
653 | return len; | 633 | return len; |
654 | } | 634 | } |
655 | 635 | ||
@@ -719,8 +699,15 @@ svc_write_space(struct sock *sk) | |||
719 | } | 699 | } |
720 | } | 700 | } |
721 | 701 | ||
722 | static inline void svc_udp_get_dest_address(struct svc_rqst *rqstp, | 702 | /* |
723 | struct cmsghdr *cmh) | 703 | * Copy the UDP datagram's destination address to the rqstp structure. |
704 | * The 'destination' address in this case is the address to which the | ||
705 | * peer sent the datagram, i.e. our local address. For multihomed | ||
706 | * hosts, this can change from msg to msg. Note that only the IP | ||
707 | * address changes, the port number should remain the same. | ||
708 | */ | ||
709 | static void svc_udp_get_dest_address(struct svc_rqst *rqstp, | ||
710 | struct cmsghdr *cmh) | ||
724 | { | 711 | { |
725 | switch (rqstp->rq_sock->sk_sk->sk_family) { | 712 | switch (rqstp->rq_sock->sk_sk->sk_family) { |
726 | case AF_INET: { | 713 | case AF_INET: { |
@@ -787,7 +774,10 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
787 | svc_xprt_received(&svsk->sk_xprt); | 774 | svc_xprt_received(&svsk->sk_xprt); |
788 | return -EAGAIN; | 775 | return -EAGAIN; |
789 | } | 776 | } |
790 | rqstp->rq_addrlen = sizeof(rqstp->rq_addr); | 777 | len = svc_addr_len(svc_addr(rqstp)); |
778 | if (len < 0) | ||
779 | return len; | ||
780 | rqstp->rq_addrlen = len; | ||
791 | if (skb->tstamp.tv64 == 0) { | 781 | if (skb->tstamp.tv64 == 0) { |
792 | skb->tstamp = ktime_get_real(); | 782 | skb->tstamp = ktime_get_real(); |
793 | /* Don't enable netstamp, sunrpc doesn't | 783 | /* Don't enable netstamp, sunrpc doesn't |
@@ -1097,14 +1087,13 @@ static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) | |||
1097 | if (!(newsvsk = svc_setup_socket(serv, newsock, &err, | 1087 | if (!(newsvsk = svc_setup_socket(serv, newsock, &err, |
1098 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) | 1088 | (SVC_SOCK_ANONYMOUS | SVC_SOCK_TEMPORARY)))) |
1099 | goto failed; | 1089 | goto failed; |
1100 | memcpy(&newsvsk->sk_remote, sin, slen); | 1090 | svc_xprt_set_remote(&newsvsk->sk_xprt, sin, slen); |
1101 | newsvsk->sk_remotelen = slen; | ||
1102 | err = kernel_getsockname(newsock, sin, &slen); | 1091 | err = kernel_getsockname(newsock, sin, &slen); |
1103 | if (unlikely(err < 0)) { | 1092 | if (unlikely(err < 0)) { |
1104 | dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err); | 1093 | dprintk("svc_tcp_accept: kernel_getsockname error %d\n", -err); |
1105 | slen = offsetof(struct sockaddr, sa_data); | 1094 | slen = offsetof(struct sockaddr, sa_data); |
1106 | } | 1095 | } |
1107 | memcpy(&newsvsk->sk_local, sin, slen); | 1096 | svc_xprt_set_local(&newsvsk->sk_xprt, sin, slen); |
1108 | 1097 | ||
1109 | if (serv->sv_stats) | 1098 | if (serv->sv_stats) |
1110 | serv->sv_stats->nettcpconn++; | 1099 | serv->sv_stats->nettcpconn++; |
@@ -1245,6 +1234,7 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp) | |||
1245 | svsk->sk_reclen = 0; | 1234 | svsk->sk_reclen = 0; |
1246 | svsk->sk_tcplen = 0; | 1235 | svsk->sk_tcplen = 0; |
1247 | 1236 | ||
1237 | svc_xprt_copy_addrs(rqstp, &svsk->sk_xprt); | ||
1248 | svc_xprt_received(&svsk->sk_xprt); | 1238 | svc_xprt_received(&svsk->sk_xprt); |
1249 | if (serv->sv_stats) | 1239 | if (serv->sv_stats) |
1250 | serv->sv_stats->nettcpcnt++; | 1240 | serv->sv_stats->nettcpcnt++; |
@@ -1805,6 +1795,11 @@ int svc_addsock(struct svc_serv *serv, | |||
1805 | else { | 1795 | else { |
1806 | svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS); | 1796 | svsk = svc_setup_socket(serv, so, &err, SVC_SOCK_DEFAULTS); |
1807 | if (svsk) { | 1797 | if (svsk) { |
1798 | struct sockaddr_storage addr; | ||
1799 | struct sockaddr *sin = (struct sockaddr *)&addr; | ||
1800 | int salen; | ||
1801 | if (kernel_getsockname(svsk->sk_sock, sin, &salen) == 0) | ||
1802 | svc_xprt_set_local(&svsk->sk_xprt, sin, salen); | ||
1808 | svc_xprt_received(&svsk->sk_xprt); | 1803 | svc_xprt_received(&svsk->sk_xprt); |
1809 | err = 0; | 1804 | err = 0; |
1810 | } | 1805 | } |
@@ -1831,6 +1826,9 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1831 | int error; | 1826 | int error; |
1832 | int type; | 1827 | int type; |
1833 | char buf[RPC_MAX_ADDRBUFLEN]; | 1828 | char buf[RPC_MAX_ADDRBUFLEN]; |
1829 | struct sockaddr_storage addr; | ||
1830 | struct sockaddr *newsin = (struct sockaddr *)&addr; | ||
1831 | int newlen; | ||
1834 | 1832 | ||
1835 | dprintk("svc: svc_create_socket(%s, %d, %s)\n", | 1833 | dprintk("svc: svc_create_socket(%s, %d, %s)\n", |
1836 | serv->sv_program->pg_name, protocol, | 1834 | serv->sv_program->pg_name, protocol, |
@@ -1855,12 +1853,18 @@ static struct svc_xprt *svc_create_socket(struct svc_serv *serv, | |||
1855 | if (error < 0) | 1853 | if (error < 0) |
1856 | goto bummer; | 1854 | goto bummer; |
1857 | 1855 | ||
1856 | newlen = len; | ||
1857 | error = kernel_getsockname(sock, newsin, &newlen); | ||
1858 | if (error < 0) | ||
1859 | goto bummer; | ||
1860 | |||
1858 | if (protocol == IPPROTO_TCP) { | 1861 | if (protocol == IPPROTO_TCP) { |
1859 | if ((error = kernel_listen(sock, 64)) < 0) | 1862 | if ((error = kernel_listen(sock, 64)) < 0) |
1860 | goto bummer; | 1863 | goto bummer; |
1861 | } | 1864 | } |
1862 | 1865 | ||
1863 | if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { | 1866 | if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { |
1867 | svc_xprt_set_local(&svsk->sk_xprt, newsin, newlen); | ||
1864 | svc_xprt_received(&svsk->sk_xprt); | 1868 | svc_xprt_received(&svsk->sk_xprt); |
1865 | return (struct svc_xprt *)svsk; | 1869 | return (struct svc_xprt *)svsk; |
1866 | } | 1870 | } |