Commit 0788f64b authored by David S. Miller's avatar David S. Miller

Merge nuts.ninka.net:/home/davem/src/BK/network-2.5

into nuts.ninka.net:/home/davem/src/BK/net-2.5
parents ca377000 7669c7cc
......@@ -2073,7 +2073,8 @@ ppp_ccp_peek(struct ppp *ppp, struct sk_buff *skb, int inbound)
case CCP_CONFACK:
if ((ppp->flags & (SC_CCP_OPEN | SC_CCP_UP)) != SC_CCP_OPEN)
break;
if (!pskb_may_pull(skb, len = CCP_LENGTH(dp)) + 2)
len = CCP_LENGTH(dp);
if (!pskb_may_pull(skb, len + 2))
return; /* too short */
dp += CCP_HDRLEN;
len -= CCP_HDRLEN;
......
......@@ -605,7 +605,18 @@ int __init tun_init(void)
void tun_cleanup(void)
{
struct net_device *dev, *nxt;
misc_deregister(&tun_miscdev);
rtnl_lock();
for (dev = dev_base; dev; dev = nxt) {
nxt = dev->next;
if (dev->init == tun_net_init)
unregister_netdevice(dev);
}
rtnl_unlock();
}
module_init(tun_init);
......
......@@ -185,10 +185,9 @@ struct compressor {
#define DEFLATE_MIN_SIZE 9
#define DEFLATE_MAX_SIZE 15
#define DEFLATE_METHOD_VAL 8
#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
#define DEFLATE_SIZE(x) (((x) >> 4) + 8)
#define DEFLATE_METHOD(x) ((x) & 0x0F)
#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ DEFLATE_METHOD_VAL)
#define DEFLATE_MAKE_OPT(w) ((((w) - 8) << 4) + DEFLATE_METHOD_VAL)
#define DEFLATE_CHK_SEQUENCE 0
/*
......
......@@ -37,6 +37,7 @@ struct xfrm_selector
__u16 dport_mask;
__u16 sport;
__u16 sport_mask;
__u16 family;
__u8 prefixlen_d;
__u8 prefixlen_s;
__u8 proto;
......@@ -125,6 +126,7 @@ enum
struct xfrm_user_tmpl {
struct xfrm_id id;
__u16 family;
xfrm_address_t saddr;
__u32 reqid;
__u8 mode;
......@@ -189,7 +191,6 @@ struct xfrm_userpolicy_info {
struct xfrm_lifetime_cur curlft;
__u32 priority;
__u32 index;
__u16 family;
__u8 dir;
__u8 action;
#define XFRM_POLICY_ALLOW 0
......
......@@ -353,9 +353,7 @@ extern int ip6_push_pending_frames(struct sock *sk);
extern void ip6_flush_pending_frames(struct sock *sk);
extern int ip6_dst_lookup(struct sock *sk,
struct dst_entry **dst,
struct flowi *fl);
extern struct dst_entry * ip6_dst_lookup(struct sock *sk, struct flowi *fl);
/*
* skb processing functions
......
......@@ -279,6 +279,7 @@ static struct xfrm_state *ipcomp_tunnel_create(struct xfrm_state *x)
t->props.family = AF_INET;
t->props.mode = 1;
t->props.saddr.a4 = x->props.saddr.a4;
t->props.flags = x->props.flags;
t->type = xfrm_get_type(IPPROTO_IPIP, t->props.family);
if (t->type == NULL)
......
......@@ -27,6 +27,20 @@ static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff
IP_ECN_set_ce(inner_iph);
}
static int xfrm4_parse_spi(struct sk_buff *skb, u8 nexthdr, u32 *spi, u32 *seq)
{
switch (nexthdr) {
case IPPROTO_IPIP:
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
return -EINVAL;
*spi = skb->nh.iph->saddr;
*seq = 0;
return 0;
}
return xfrm_parse_spi(skb, nexthdr, spi, seq);
}
int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
{
int err;
......@@ -36,7 +50,7 @@ int xfrm4_rcv_encap(struct sk_buff *skb, __u16 encap_type)
int xfrm_nr = 0;
int decaps = 0;
if ((err = xfrm_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
if ((err = xfrm4_parse_spi(skb, skb->nh.iph->protocol, &spi, &seq)) != 0)
goto drop;
do {
......
......@@ -83,31 +83,8 @@ static int ipip_output(struct sk_buff *skb)
return err;
}
static inline void ipip_ecn_decapsulate(struct iphdr *outer_iph, struct sk_buff *skb)
{
struct iphdr *inner_iph = skb->nh.iph;
if (INET_ECN_is_ce(outer_iph->tos) &&
INET_ECN_is_not_ce(inner_iph->tos))
IP_ECN_set_ce(inner_iph);
}
static int ipip_xfrm_rcv(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_buff *skb)
{
struct iphdr *outer_iph = skb->nh.iph;
if (!pskb_may_pull(skb, sizeof(struct iphdr)))
return -EINVAL;
skb->mac.raw = skb->nh.raw;
skb->nh.raw = skb->data;
memset(&(IPCB(skb)->opt), 0, sizeof(struct ip_options));
dst_release(skb->dst);
skb->dst = NULL;
skb->protocol = htons(ETH_P_IP);
skb->pkt_type = PACKET_HOST;
ipip_ecn_decapsulate(outer_iph, skb);
netif_rx(skb);
return 0;
}
......@@ -149,46 +126,12 @@ int xfrm4_tunnel_deregister(struct xfrm_tunnel *handler)
static int ipip_rcv(struct sk_buff *skb)
{
struct xfrm_tunnel *handler = ipip_handler;
struct xfrm_state *x = NULL;
int err;
/* Tunnel devices take precedence. */
if (handler) {
err = handler->handler(skb);
if (!err)
goto out;
}
if (handler && handler->handler(skb) == 0)
return 0;
x = xfrm_state_lookup((xfrm_address_t *)&skb->nh.iph->daddr,
skb->nh.iph->saddr,
IPPROTO_IPIP, AF_INET);
if (!x)
goto drop;
spin_lock(&x->lock);
if (unlikely(x->km.state != XFRM_STATE_VALID))
goto drop_unlock;
err = ipip_xfrm_rcv(x, NULL, skb);
if (err)
goto drop_unlock;
x->curlft.bytes += skb->len;
x->curlft.packets++;
spin_unlock(&x->lock);
xfrm_state_put(x);
out:
return err;
drop_unlock:
spin_unlock(&x->lock);
xfrm_state_put(x);
drop:
err = NET_RX_DROP;
kfree_skb(skb);
goto out;
return xfrm4_rcv_encap(skb, 0);
}
static void ipip_err(struct sk_buff *skb, u32 info)
......
......@@ -265,13 +265,12 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
* There is offset of AH before IPv6 header after the process.
*/
struct ipv6hdr *iph = skb->nh.ipv6h;
struct ipv6_auth_hdr *ah;
struct ah_data *ahp;
unsigned char *tmp_hdr = NULL;
u16 hdr_len = skb->data - skb->nh.raw;
u16 hdr_len;
u16 ah_hlen;
u16 cleared_hlen = hdr_len;
u16 cleared_hlen;
u16 nh_offset = 0;
u8 nexthdr = 0;
u8 *prevhdr;
......@@ -279,6 +278,14 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
if (!pskb_may_pull(skb, sizeof(struct ip_auth_hdr)))
goto out;
/* We are going to _remove_ AH header to keep sockets happy,
* so... Later this can change. */
if (skb_cloned(skb) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto out;
hdr_len = skb->data - skb->nh.raw;
cleared_hlen = hdr_len;
ah = (struct ipv6_auth_hdr*)skb->data;
ahp = x->data;
nexthdr = ah->nexthdr;
......@@ -297,27 +304,22 @@ int ah6_input(struct xfrm_state *x, struct xfrm_decap_state *decap, struct sk_bu
if (!pskb_may_pull(skb, ah_hlen))
goto out;
/* We are going to _remove_ AH header to keep sockets happy,
* so... Later this can change. */
if (skb_cloned(skb) &&
pskb_expand_head(skb, 0, 0, GFP_ATOMIC))
goto out;
tmp_hdr = kmalloc(cleared_hlen, GFP_ATOMIC);
if (!tmp_hdr)
goto out;
memcpy(tmp_hdr, skb->nh.raw, cleared_hlen);
ipv6_clear_mutable_options(skb, &nh_offset, XFRM_POLICY_IN);
iph->priority = 0;
iph->flow_lbl[0] = 0;
iph->flow_lbl[1] = 0;
iph->flow_lbl[2] = 0;
iph->hop_limit = 0;
skb->nh.ipv6h->priority = 0;
skb->nh.ipv6h->flow_lbl[0] = 0;
skb->nh.ipv6h->flow_lbl[1] = 0;
skb->nh.ipv6h->flow_lbl[2] = 0;
skb->nh.ipv6h->hop_limit = 0;
{
u8 auth_data[ahp->icv_trunc_len];
memcpy(auth_data, ah->auth_data, ahp->icv_trunc_len);
memset(ah->auth_data, 0, ahp->icv_trunc_len);
skb_push(skb, skb->data - skb->nh.raw);
ahp->icv(ahp, skb, ah->auth_data);
if (memcmp(ah->auth_data, auth_data, ahp->icv_trunc_len)) {
......
......@@ -355,8 +355,8 @@ void icmpv6_send(struct sk_buff *skb, int type, int code, __u32 info,
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl);
if (err) goto out;
dst = ip6_dst_lookup(sk, &fl);
if (dst->error) goto out;
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
......@@ -434,9 +434,9 @@ static void icmpv6_echo_reply(struct sk_buff *skb)
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl);
dst = ip6_dst_lookup(sk, &fl);
if (err) goto out;
if (dst->error) goto out;
if (hlimit < 0) {
if (ipv6_addr_is_multicast(&fl.fl6_dst))
......
......@@ -209,11 +209,6 @@ int ip6_xmit(struct sock *sk, struct sk_buff *skb, struct flowi *fl,
int seg_len = skb->len;
int hlimit;
u32 mtu;
int err = 0;
if ((err = xfrm_lookup(&skb->dst, fl, sk, 0)) < 0) {
return err;
}
if (opt) {
int head_room;
......@@ -1141,72 +1136,73 @@ static int ip6_fragment(struct sk_buff *skb, int (*output)(struct sk_buff*))
return err;
}
int ip6_dst_lookup(struct sock *sk, struct dst_entry **dst, struct flowi *fl)
struct dst_entry *ip6_dst_lookup(struct sock *sk, struct flowi *fl)
{
struct ipv6_pinfo *np = inet6_sk(sk);
struct dst_entry *dst = NULL;
int err = 0;
*dst = __sk_dst_check(sk, np->dst_cookie);
if (*dst) {
struct rt6_info *rt = (struct rt6_info*)*dst;
/* Yes, checking route validity in not connected
case is not very simple. Take into account,
that we do not support routing by source, TOS,
and MSG_DONTROUTE --ANK (980726)
1. If route was host route, check that
cached destination is current.
If it is network route, we still may
check its validity using saved pointer
to the last used address: daddr_cache.
We do not want to save whole address now,
(because main consumer of this service
is tcp, which has not this problem),
so that the last trick works only on connected
sockets.
2. oif also should be the same.
*/
if (((rt->rt6i_dst.plen != 128 ||
ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
&& (np->daddr_cache == NULL ||
ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
|| (fl->oif && fl->oif != (*dst)->dev->ifindex)) {
*dst = NULL;
} else
dst_hold(*dst);
if (sk) {
struct ipv6_pinfo *np = inet6_sk(sk);
dst = __sk_dst_check(sk, np->dst_cookie);
if (dst) {
struct rt6_info *rt = (struct rt6_info*)dst;
/* Yes, checking route validity in not connected
case is not very simple. Take into account,
that we do not support routing by source, TOS,
and MSG_DONTROUTE --ANK (980726)
1. If route was host route, check that
cached destination is current.
If it is network route, we still may
check its validity using saved pointer
to the last used address: daddr_cache.
We do not want to save whole address now,
(because main consumer of this service
is tcp, which has not this problem),
so that the last trick works only on connected
sockets.
2. oif also should be the same.
*/
if (((rt->rt6i_dst.plen != 128 ||
ipv6_addr_cmp(&fl->fl6_dst, &rt->rt6i_dst.addr))
&& (np->daddr_cache == NULL ||
ipv6_addr_cmp(&fl->fl6_dst, np->daddr_cache)))
|| (fl->oif && fl->oif != dst->dev->ifindex)) {
dst = NULL;
} else
dst_hold(dst);
}
}
if (*dst == NULL)
*dst = ip6_route_output(sk, fl);
if (dst == NULL)
dst = ip6_route_output(sk, fl);
if ((*dst)->error) {
IP6_INC_STATS(Ip6OutNoRoutes);
dst_release(*dst);
return -ENETUNREACH;
}
if (dst->error)
return dst;
if (ipv6_addr_any(&fl->fl6_src)) {
err = ipv6_get_saddr(*dst, &fl->fl6_dst, &fl->fl6_src);
err = ipv6_get_saddr(dst, &fl->fl6_dst, &fl->fl6_src);
if (err) {
#if IP6_DEBUG >= 2
printk(KERN_DEBUG "ip6_build_xmit: "
"no available source address\n");
#endif
return err;
dst->error = err;
return dst;
}
}
if (*dst) {
if ((err = xfrm_lookup(dst, fl, sk, 0)) < 0) {
dst_release(*dst);
return -ENETUNREACH;
if (dst) {
if ((err = xfrm_lookup(&dst, fl, sk, 0)) < 0) {
dst->error = -ENETUNREACH;
}
}
return 0;
return dst;
}
int ip6_append_data(struct sock *sk, int getfrag(void *from, char *to, int offset, int len, int odd, struct sk_buff *skb),
......
......@@ -621,6 +621,14 @@ merge_options(struct sock *sk, __u8 encap_limit,
return opt;
}
static int
ip6ip6_getfrag(void *from, char *to, int offset, int len, int odd,
struct sk_buff *skb)
{
memcpy(to, (char *) from + offset, len);
return 0;
}
/**
* ip6ip6_tnl_addr_conflict - compare packet addresses to tunnel's own
* @t: the outgoing tunnel device
......@@ -755,9 +763,9 @@ int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
}
if (skb->len > mtu) {
icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu, dev);
goto tx_err_opt_release;
goto tx_err_dst_release;
}
err = ip6_append_data(sk, ip_generic_getfrag, skb->nh.raw, skb->len, 0,
err = ip6_append_data(sk, ip6ip6_getfrag, skb->nh.raw, skb->len, 0,
t->parms.hop_limit, opt, &fl,
(struct rt6_info *)dst, MSG_DONTWAIT);
......@@ -785,7 +793,6 @@ int ip6ip6_tnl_xmit(struct sk_buff *skb, struct net_device *dev)
return 0;
tx_err_dst_release:
dst_release(dst);
tx_err_opt_release:
if (opt && opt != orig_opt)
sock_kfree_s(sk, opt, opt->tot_len);
tx_err_free_fl_lbl:
......
......@@ -658,8 +658,8 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
dst = ip6_dst_lookup(sk, &fl);
if ((err = dst->error))
goto out;
if (hlimit < 0) {
......
......@@ -663,7 +663,7 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
dst = ip6_route_output(sk, &fl);
dst = ip6_dst_lookup(sk, &fl);
if ((err = dst->error) != 0) {
dst_release(dst);
......@@ -691,6 +691,8 @@ static int tcp_v6_connect(struct sock *sk, struct sockaddr *uaddr,
tp->ext_header_len = 0;
if (np->opt)
tp->ext_header_len = np->opt->opt_flen + np->opt->opt_nflen;
tp->ext2_header_len = dst->header_len;
tp->mss_clamp = IPV6_MIN_MTU - sizeof(struct tcphdr) - sizeof(struct ipv6hdr);
inet->dport = usin->sin6_port;
......@@ -788,7 +790,7 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
fl.fl_ip_dport = inet->dport;
fl.fl_ip_sport = inet->sport;
dst = ip6_route_output(sk, &fl);
dst = ip6_dst_lookup(sk, &fl);
} else
dst_hold(dst);
......@@ -889,7 +891,7 @@ static int tcp_v6_send_synack(struct sock *sk, struct open_request *req,
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
dst = ip6_route_output(sk, &fl);
dst = ip6_dst_lookup(sk, &fl);
if (dst->error)
goto done;
}
......@@ -1018,7 +1020,7 @@ static void tcp_v6_send_reset(struct sk_buff *skb)
fl.fl_ip_sport = t1->source;
/* sk = NULL, but it is safe for now. RST socket required. */
buff->dst = ip6_route_output(NULL, &fl);
buff->dst = ip6_dst_lookup(NULL, &fl);
if (buff->dst->error == 0) {
ip6_xmit(NULL, buff, &fl, NULL, 0);
......@@ -1081,7 +1083,7 @@ static void tcp_v6_send_ack(struct sk_buff *skb, u32 seq, u32 ack, u32 win, u32
fl.fl_ip_dport = t1->dest;
fl.fl_ip_sport = t1->source;
buff->dst = ip6_route_output(NULL, &fl);
buff->dst = ip6_dst_lookup(NULL, &fl);
if (buff->dst->error == 0) {
ip6_xmit(NULL, buff, &fl, NULL, 0);
......@@ -1329,7 +1331,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
fl.fl_ip_dport = req->rmt_port;
fl.fl_ip_sport = inet_sk(sk)->sport;
dst = ip6_route_output(sk, &fl);
dst = ip6_dst_lookup(sk, &fl);
}
if (dst->error)
......@@ -1401,6 +1403,7 @@ static struct sock * tcp_v6_syn_recv_sock(struct sock *sk, struct sk_buff *skb,
if (newnp->opt)
newtp->ext_header_len = newnp->opt->opt_nflen +
newnp->opt->opt_flen;
newtp->ext2_header_len = dst->header_len;
tcp_sync_mss(newsk, dst_pmtu(dst));
newtp->advmss = dst_metric(dst, RTAX_ADVMSS);
......@@ -1727,7 +1730,7 @@ static int tcp_v6_rebuild_header(struct sock *sk)
ipv6_addr_copy(&fl.fl6_dst, rt0->addr);
}
dst = ip6_route_output(sk, &fl);
dst = ip6_dst_lookup(sk, &fl);
if (dst->error) {
err = dst->error;
......@@ -1770,7 +1773,7 @@ static int tcp_v6_xmit(struct sk_buff *skb, int ipfragok)
dst = __sk_dst_check(sk, np->dst_cookie);
if (dst == NULL) {
dst = ip6_route_output(sk, &fl);
dst = ip6_dst_lookup(sk, &fl);
if (dst->error) {
sk->sk_err_soft = -dst->error;
......
......@@ -811,8 +811,10 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
* The socket lock must be held while it's corked.
*/
lock_sock(sk);
if (likely(up->pending))
if (likely(up->pending)) {
dst = NULL;
goto do_append_data;
}
release_sock(sk);
}
ulen += sizeof(struct udphdr);
......@@ -928,8 +930,8 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
if (!fl.oif && ipv6_addr_is_multicast(&fl.fl6_dst))
fl.oif = np->mcast_oif;
err = ip6_dst_lookup(sk, &dst, &fl);
if (err)
dst = ip6_dst_lookup(sk, &fl);
if ((err = dst->error))
goto out;
if (hlimit < 0) {
......@@ -968,9 +970,10 @@ static int udpv6_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg
else if (!corkreq)
err = udp_v6_push_pending_frames(sk, up);
ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
if (dst)
ip6_dst_store(sk, dst,
!ipv6_addr_cmp(&fl.fl6_dst, &np->daddr) ?
&np->daddr : NULL);
if (err > 0)
err = np->recverr ? net_xmit_errno(err) : 0;
release_sock(sk);
......
......@@ -482,10 +482,8 @@ EXPORT_SYMBOL(sysctl_tcp_tw_recycle);
EXPORT_SYMBOL(sysctl_max_syn_backlog);
#endif
#endif
#if defined (CONFIG_IPV6_MODULE) || defined (CONFIG_IP_SCTP_MODULE) || defined (CONFIG_IPV6_TUNNEL_MODULE)
EXPORT_SYMBOL(ip_generic_getfrag);
#endif
EXPORT_SYMBOL(tcp_read_sock);
......
......@@ -527,7 +527,7 @@ static int verify_newpolicy_info(struct xfrm_userpolicy_info *p)
return -EINVAL;
};
switch (p->family) {
switch (p->sel.family) {
case AF_INET:
break;
......@@ -594,7 +594,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy
memcpy(&xp->lft, &p->lft, sizeof(xp->lft));
xp->action = p->action;
xp->flags = p->flags;
xp->family = p->family;
xp->family = p->sel.family;
/* XXX xp->share = p->share; */
}
......@@ -605,7 +605,7 @@ static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_i
memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
p->priority = xp->priority;
p->index = xp->index;
p->family = xp->family;
p->sel.family = xp->family;
p->dir = dir;
p->action = xp->action;
p->flags = xp->flags;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment