Re: EAGAIN and Linux 2.6 IPsec patch
Herbert Xu <[email protected]> Tue, 30 Sep 2003 21:34:24 +1000
| Newsgroups | gmane.linux.network.general,gmane.network.freeswan.devel |
|---|---|
| Message-ID | <[email protected]> |
--mYCpIKhGyMATD0i+
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
On Mon, Sep 29, 2003 at 09:25:04AM -0400, D. Hugh Redelmeier wrote:
>
> Here's an extract from an strace of a ping to a new IP address, with
> OE on 2.6. Note: no packet has been sent
>
> socket(PF_INET, SOCK_RAW, IPPROTO_ICMP) = 3
> socket(PF_INET, SOCK_DGRAM, IPPROTO_IP) = 4
> connect(4, {sin_family=AF_INET, sin_port=htons(1025), sin_addr=inet_addr("216.239.41.99")}}, 16) = -1 EAGAIN (Resource temporarily unavailable)
>
> To me, this EAGAIN is very odd. Notice that the program is not yet
> attempting to send a packet. (Will this generate an ACQUIRE?)
OK, this looks like a bug that is independent of the packet queueing issue.
TCP/UDP connects do a route/IPSEC lookup to determine information
about the connection. The IPSEC lookup can fail with EAGAIN if the
policy is in place without any SAs.
Since connect already has an O_NONBLOCK bit we should make it try
harder if it is clear.
The following (untested) patch tries to do that.
Cheers,
--
Debian GNU/Linux 3.0 is out! ( http://www.debian.org/ )
Email: Herbert Xu ~{PmV>HI~} <[email protected]>
Home Page: http://gondor.apana.org.au/~herbert/
PGP Key: http://gondor.apana.org.au/~herbert/pubkey.txt
--mYCpIKhGyMATD0i+
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=p
Index: kernel-source-2.5/include/net/ipv6.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/ipv6.h,v
retrieving revision 1.1.1.10
diff -u -r1.1.1.10 ipv6.h
--- kernel-source-2.5/include/net/ipv6.h 27 Sep 2003 00:02:02 -0000 1.1.1.10
+++ kernel-source-2.5/include/net/ipv6.h 30 Sep 2003 11:29:14 -0000
@@ -355,7 +355,7 @@
extern int ip6_dst_lookup(struct sock *sk,
struct dst_entry **dst,
- struct flowi *fl);
+ struct flowi *fl, int block);
/*
* skb processing functions
Index: kernel-source-2.5/include/net/route.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/route.h,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 route.h
--- kernel-source-2.5/include/net/route.h 17 Jun 2003 04:19:37 -0000 1.1.1.5
+++ kernel-source-2.5/include/net/route.h 30 Sep 2003 11:26:58 -0000
@@ -148,7 +148,8 @@
static inline int ip_route_connect(struct rtable **rp, u32 dst,
u32 src, u32 tos, int oif, u8 protocol,
- u16 sport, u16 dport, struct sock *sk)
+ u16 sport, u16 dport, struct sock *sk,
+ int block)
{
struct flowi fl = { .oif = oif,
.nl_u = { .ip4_u = { .daddr = dst,
@@ -169,7 +170,7 @@
ip_rt_put(*rp);
*rp = NULL;
}
- return ip_route_output_flow(rp, &fl, sk, 0);
+ return ip_route_output_flow(rp, &fl, sk, block);
}
static inline int ip_route_newports(struct rtable **rp, u16 sport, u16 dport,
Index: kernel-source-2.5/include/net/sock.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/sock.h,v
retrieving revision 1.1.1.9
diff -u -r1.1.1.9 sock.h
--- kernel-source-2.5/include/net/sock.h 2 Jul 2003 20:51:53 -0000 1.1.1.9
+++ kernel-source-2.5/include/net/sock.h 30 Sep 2003 10:40:14 -0000
@@ -402,7 +402,7 @@
long timeout);
int (*connect)(struct sock *sk,
struct sockaddr *uaddr,
- int addr_len);
+ int addr_len, int flags);
int (*disconnect)(struct sock *sk, int flags);
struct sock * (*accept) (struct sock *sk, int flags, int *err);
Index: kernel-source-2.5/include/net/tcp.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/tcp.h,v
retrieving revision 1.1.1.9
diff -u -r1.1.1.9 tcp.h
--- kernel-source-2.5/include/net/tcp.h 11 Jul 2003 10:53:05 -0000 1.1.1.9
+++ kernel-source-2.5/include/net/tcp.h 30 Sep 2003 11:11:02 -0000
@@ -852,7 +852,7 @@
extern int tcp_v4_connect(struct sock *sk,
struct sockaddr *uaddr,
- int addr_len);
+ int addr_len, int flags);
extern int tcp_connect(struct sock *sk);
Index: kernel-source-2.5/include/net/transp_v6.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/transp_v6.h,v
retrieving revision 1.1.1.3
diff -u -r1.1.1.3 transp_v6.h
--- kernel-source-2.5/include/net/transp_v6.h 27 May 2003 08:38:39 -0000 1.1.1.3
+++ kernel-source-2.5/include/net/transp_v6.h 30 Sep 2003 11:16:35 -0000
@@ -28,7 +28,7 @@
extern int udpv6_connect(struct sock *sk,
struct sockaddr *uaddr,
- int addr_len);
+ int addr_len, int flags);
extern int datagram_recv_ctl(struct sock *sk,
struct msghdr *msg,
Index: kernel-source-2.5/include/net/udp.h
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/include/net/udp.h,v
retrieving revision 1.1.1.5
diff -u -r1.1.1.5 udp.h
--- kernel-source-2.5/include/net/udp.h 17 Jun 2003 04:20:20 -0000 1.1.1.5
+++ kernel-source-2.5/include/net/udp.h 30 Sep 2003 10:47:09 -0000
@@ -65,7 +65,7 @@
extern void udp_err(struct sk_buff *, u32);
extern int udp_connect(struct sock *sk,
- struct sockaddr *usin, int addr_len);
+ struct sockaddr *usin, int addr_len, int flags);
extern int udp_sendmsg(struct kiocb *iocb, struct sock *sk,
struct msghdr *msg, int len);
Index: kernel-source-2.5/net/ipv4/af_inet.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/af_inet.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 af_inet.c
--- kernel-source-2.5/net/ipv4/af_inet.c 27 Sep 2003 00:02:03 -0000 1.1.1.11
+++ kernel-source-2.5/net/ipv4/af_inet.c 30 Sep 2003 10:41:56 -0000
@@ -558,7 +558,7 @@
if (!inet_sk(sk)->num && inet_autobind(sk))
return -EAGAIN;
- return sk->sk_prot->connect(sk, (struct sockaddr *)uaddr, addr_len);
+ return sk->sk_prot->connect(sk, uaddr, addr_len, flags);
}
static long inet_wait_for_connect(struct sock *sk, long timeo)
@@ -619,7 +619,7 @@
if (sk->sk_state != TCP_CLOSE)
goto out;
- err = sk->sk_prot->connect(sk, uaddr, addr_len);
+ err = sk->sk_prot->connect(sk, uaddr, addr_len, flags);
if (err < 0)
goto out;
Index: kernel-source-2.5/net/ipv4/tcp_ipv4.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/tcp_ipv4.c,v
retrieving revision 1.1.1.12
diff -u -r1.1.1.12 tcp_ipv4.c
--- kernel-source-2.5/net/ipv4/tcp_ipv4.c 28 Sep 2003 04:44:22 -0000 1.1.1.12
+++ kernel-source-2.5/net/ipv4/tcp_ipv4.c 30 Sep 2003 11:27:42 -0000
@@ -747,7 +747,8 @@
}
/* This will initiate an outgoing connection. */
-int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int tcp_v4_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len,
+ int flags)
{
struct inet_opt *inet = inet_sk(sk);
struct tcp_opt *tp = tcp_sk(sk);
@@ -773,7 +774,8 @@
tmp = ip_route_connect(&rt, nexthop, inet->saddr,
RT_CONN_FLAGS(sk), sk->sk_bound_dev_if,
IPPROTO_TCP,
- inet->sport, usin->sin_port, sk);
+ inet->sport, usin->sin_port, sk,
+ !(flags&O_NONBLOCK));
if (tmp < 0)
return tmp;
@@ -1878,7 +1880,7 @@
RT_TOS(inet->tos) | sk->sk_localroute,
sk->sk_bound_dev_if,
IPPROTO_TCP,
- inet->sport, inet->dport, sk);
+ inet->sport, inet->dport, sk, 0);
if (err)
return err;
Index: kernel-source-2.5/net/ipv4/udp.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv4/udp.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 udp.c
--- kernel-source-2.5/net/ipv4/udp.c 28 Sep 2003 04:44:22 -0000 1.1.1.13
+++ kernel-source-2.5/net/ipv4/udp.c 30 Sep 2003 11:28:29 -0000
@@ -856,7 +856,8 @@
return -EAGAIN;
}
-int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int udp_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len,
+ int flags)
{
struct inet_opt *inet = inet_sk(sk);
struct sockaddr_in *usin = (struct sockaddr_in *) uaddr;
@@ -885,7 +886,8 @@
err = ip_route_connect(&rt, usin->sin_addr.s_addr, saddr,
RT_CONN_FLAGS(sk), oif,
IPPROTO_UDP,
- inet->sport, usin->sin_port, sk);
+ inet->sport, usin->sin_port, sk,
+ !(flags&O_NONBLOCK));
if (err)
return err;
if ((rt->rt_flags & RTCF_BROADCAST) && !sock_flag(sk, SOCK_BROADCAST)) {
Index: kernel-source-2.5/net/ipv6/icmp.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/icmp.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 icmp.c
--- kernel-source-2.5/net/ipv6/icmp.c 27 Sep 2003 00:02:03 -0000 1.1.1.11
+++ kernel-source-2.5/net/ipv6/icmp.c 30 Sep 2003 11:00:06 -0000
@@ -366,7 +366,7 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, 0);
if (err)
goto out;
@@ -449,7 +449,7 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, 0);
if (err)
goto out;
Index: kernel-source-2.5/net/ipv6/ip6_output.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/ip6_output.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 ip6_output.c
--- kernel-source-2.5/net/ipv6/ip6_output.c 27 Sep 2003 00:02:03 -0000 1.1.1.13
+++ kernel-source-2.5/net/ipv6/ip6_output.c 30 Sep 2003 11:29:43 -0000
@@ -1136,7 +1136,8 @@
return err;
}
-int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
+int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl,
+ int block)
{
int err = 0;
@@ -1193,7 +1194,7 @@
goto out_err_release;
}
}
- if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
+ if ((err = xfrm_lookup(dst, fl, sk, block)) < 0) {
err = -ENETUNREACH;
goto out_err_release;
}
Index: kernel-source-2.5/net/ipv6/raw.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/raw.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 raw.c
--- kernel-source-2.5/net/ipv6/raw.c 28 Sep 2003 04:44:23 -0000 1.1.1.11
+++ kernel-source-2.5/net/ipv6/raw.c 30 Sep 2003 11:01:15 -0000
@@ -658,7 +658,7 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, !(msg->msg_flags&MSG_DONTWAIT));
if (err)
goto out;
Index: kernel-source-2.5/net/ipv6/tcp_ipv6.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/tcp_ipv6.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 tcp_ipv6.c
--- kernel-source-2.5/net/ipv6/tcp_ipv6.c 28 Sep 2003 04:44:23 -0000 1.1.1.13
+++ kernel-source-2.5/net/ipv6/tcp_ipv6.c 30 Sep 2003 11:31:23 -0000
@@ -537,7 +537,7 @@
}
static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
- int addr_len)
+ int addr_len, int flags)
{
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
struct inet_opt *inet = inet_sk(sk);
@@ -630,7 +630,8 @@
tp->af_specific = &ipv6_mapped;
sk->sk_backlog_rcv = tcp_v4_do_rcv;
- err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin));
+ err = tcp_v4_connect(sk, (struct sockaddr *)&sin, sizeof(sin),
+ flags);
if (err) {
tp->ext_header_len = exthdrlen;
@@ -663,7 +664,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, !(flags & O_NONBLOCK));
if (err)
goto failure;
@@ -783,7 +784,7 @@
fl.fl_ip_dport = inet->dport;
fl.fl_ip_sport = inet->sport;
- if ((err = ip6_dst_lookup(sk, &dst, &fl))) {
+ if ((err = ip6_dst_lookup(sk, &dst, &fl, 0))) {
sk->sk_err_soft = -err;
goto out;
}
@@ -885,7 +886,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, 0);
if (err)
goto done;
}
@@ -1014,7 +1015,7 @@
fl.fl_ip_sport = t1->source;
/* sk = NULL, but it is safe for now. RST socket required. */
- if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+ if (!ip6_dst_lookup(NULL, &buff->dst, &fl, 0)) {
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TcpOutSegs);
TCP_INC_STATS_BH(TcpOutRsts);
@@ -1075,7 +1076,7 @@
fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source;
- if (!ip6_dst_lookup(NULL, &buff->dst, &fl)) {
+ if (!ip6_dst_lookup(NULL, &buff->dst, &fl, 0)) {
ip6_xmit(NULL, buff, &fl, NULL, 0);
TCP_INC_STATS_BH(TcpOutSegs);
return;
@@ -1321,7 +1322,7 @@
fl.fl_ip_dport = req->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
- if (ip6_dst_lookup(sk, &dst, &fl))
+ if (ip6_dst_lookup(sk, &dst, &fl, 0))
goto out;
}
@@ -1718,7 +1719,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, 0);
if (err) {
sk->sk_route_caps = 0;
@@ -1760,7 +1761,7 @@
dst = __sk_dst_check(sk, np->dst_cookie);
if (dst == NULL) {
- int err = ip6_dst_lookup(sk, &dst, &fl);
+ int err = ip6_dst_lookup(sk, &dst, &fl, 0);
if (err) {
sk->sk_err_soft = -err;
Index: kernel-source-2.5/net/ipv6/udp.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/ipv6/udp.c,v
retrieving revision 1.1.1.11
diff -u -r1.1.1.11 udp.c
--- kernel-source-2.5/net/ipv6/udp.c 28 Sep 2003 04:44:23 -0000 1.1.1.11
+++ kernel-source-2.5/net/ipv6/udp.c 30 Sep 2003 10:52:04 -0000
@@ -201,7 +201,8 @@
*
*/
-int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int udpv6_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len,
+ int flags)
{
struct sockaddr_in6 *usin = (struct sockaddr_in6 *) uaddr;
struct inet_opt *inet = inet_sk(sk);
@@ -216,7 +217,7 @@
if (usin->sin6_family == AF_INET) {
if (__ipv6_only_sock(sk))
return -EAFNOSUPPORT;
- err = udp_connect(sk, uaddr, addr_len);
+ err = udp_connect(sk, uaddr, addr_len, flags);
goto ipv4_connected;
}
@@ -259,7 +260,8 @@
sin.sin_addr.s_addr = daddr->s6_addr32[3];
sin.sin_port = usin->sin6_port;
- err = udp_connect(sk, (struct sockaddr*) &sin, sizeof(sin));
+ err = udp_connect(sk, (struct sockaddr*) &sin, sizeof(sin),
+ flags);
ipv4_connected:
if (err)
@@ -330,7 +332,7 @@
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, !(flags&O_NONBLOCK));
if (err)
goto out;
@@ -921,7 +923,7 @@
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
- err = ip6_dst_lookup(sk, &dst, &fl);
+ err = ip6_dst_lookup(sk, &dst, &fl, !(msg->msg_flags&MSG_DONTWAIT));
if (err)
goto out;
Index: kernel-source-2.5/net/sctp/socket.c
===================================================================
RCS file: /home/gondolin/herbert/src/CVS/debian/kernel-source-2.5/net/sctp/socket.c,v
retrieving revision 1.1.1.13
diff -u -r1.1.1.13 socket.c
--- kernel-source-2.5/net/sctp/socket.c 27 Sep 2003 00:02:03 -0000 1.1.1.13
+++ kernel-source-2.5/net/sctp/socket.c 30 Sep 2003 10:40:58 -0000
@@ -1868,7 +1868,7 @@
* len: the size of the address.
*/
SCTP_STATIC int sctp_connect(struct sock *sk, struct sockaddr *uaddr,
- int addr_len)
+ int addr_len, int flags)
{
struct sctp_opt *sp;
struct sctp_endpoint *ep;
--mYCpIKhGyMATD0i+--
-
To unsubscribe from this list: send the line "unsubscribe linux-net" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html