aboutsummaryrefslogtreecommitdiffstats
path: root/net/ipv6
diff options
context:
space:
mode:
Diffstat (limited to 'net/ipv6')
-rw-r--r--net/ipv6/ip6_fib.c9
-rw-r--r--net/ipv6/ip6_flowlabel.c24
-rw-r--r--net/ipv6/ndisc.c1
-rw-r--r--net/ipv6/netfilter/Kconfig2
-rw-r--r--net/ipv6/netfilter/ip6_queue.c7
-rw-r--r--net/ipv6/netfilter/ip6_tables.c47
-rw-r--r--net/ipv6/netfilter/ip6t_ah.c7
-rw-r--r--net/ipv6/netfilter/ip6t_frag.c7
-rw-r--r--net/ipv6/netfilter/ip6t_hbh.c7
-rw-r--r--net/ipv6/netfilter/ip6t_rt.c7
-rw-r--r--net/ipv6/raw.c17
-rw-r--r--net/ipv6/sit.c1
-rw-r--r--net/ipv6/xfrm6_tunnel.c4
13 files changed, 91 insertions, 49 deletions
diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c
index 8fcae7a6510b..f98ca30d7c1f 100644
--- a/net/ipv6/ip6_fib.c
+++ b/net/ipv6/ip6_fib.c
@@ -169,7 +169,6 @@ static __inline__ void rt6_release(struct rt6_info *rt)
169 169
170static struct fib6_table fib6_main_tbl = { 170static struct fib6_table fib6_main_tbl = {
171 .tb6_id = RT6_TABLE_MAIN, 171 .tb6_id = RT6_TABLE_MAIN,
172 .tb6_lock = RW_LOCK_UNLOCKED,
173 .tb6_root = { 172 .tb6_root = {
174 .leaf = &ip6_null_entry, 173 .leaf = &ip6_null_entry,
175 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, 174 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -187,6 +186,12 @@ static void fib6_link_table(struct fib6_table *tb)
187{ 186{
188 unsigned int h; 187 unsigned int h;
189 188
189 /*
190 * Initialize table lock at a single place to give lockdep a key,
191 * tables aren't visible prior to being linked to the list.
192 */
193 rwlock_init(&tb->tb6_lock);
194
190 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1); 195 h = tb->tb6_id & (FIB_TABLE_HASHSZ - 1);
191 196
192 /* 197 /*
@@ -199,7 +204,6 @@ static void fib6_link_table(struct fib6_table *tb)
199#ifdef CONFIG_IPV6_MULTIPLE_TABLES 204#ifdef CONFIG_IPV6_MULTIPLE_TABLES
200static struct fib6_table fib6_local_tbl = { 205static struct fib6_table fib6_local_tbl = {
201 .tb6_id = RT6_TABLE_LOCAL, 206 .tb6_id = RT6_TABLE_LOCAL,
202 .tb6_lock = RW_LOCK_UNLOCKED,
203 .tb6_root = { 207 .tb6_root = {
204 .leaf = &ip6_null_entry, 208 .leaf = &ip6_null_entry,
205 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO, 209 .fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO,
@@ -213,7 +217,6 @@ static struct fib6_table *fib6_alloc_table(u32 id)
213 table = kzalloc(sizeof(*table), GFP_ATOMIC); 217 table = kzalloc(sizeof(*table), GFP_ATOMIC);
214 if (table != NULL) { 218 if (table != NULL) {
215 table->tb6_id = id; 219 table->tb6_id = id;
216 table->tb6_lock = RW_LOCK_UNLOCKED;
217 table->tb6_root.leaf = &ip6_null_entry; 220 table->tb6_root.leaf = &ip6_null_entry;
218 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO; 221 table->tb6_root.fn_flags = RTN_ROOT | RTN_TL_ROOT | RTN_RTINFO;
219 } 222 }
diff --git a/net/ipv6/ip6_flowlabel.c b/net/ipv6/ip6_flowlabel.c
index 1d672b0547f2..6d4533b58dca 100644
--- a/net/ipv6/ip6_flowlabel.c
+++ b/net/ipv6/ip6_flowlabel.c
@@ -330,8 +330,10 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int *
330 fl->share = freq->flr_share; 330 fl->share = freq->flr_share;
331 addr_type = ipv6_addr_type(&freq->flr_dst); 331 addr_type = ipv6_addr_type(&freq->flr_dst);
332 if ((addr_type&IPV6_ADDR_MAPPED) 332 if ((addr_type&IPV6_ADDR_MAPPED)
333 || addr_type == IPV6_ADDR_ANY) 333 || addr_type == IPV6_ADDR_ANY) {
334 err = -EINVAL;
334 goto done; 335 goto done;
336 }
335 ipv6_addr_copy(&fl->dst, &freq->flr_dst); 337 ipv6_addr_copy(&fl->dst, &freq->flr_dst);
336 atomic_set(&fl->users, 1); 338 atomic_set(&fl->users, 1);
337 switch (fl->share) { 339 switch (fl->share) {
@@ -587,6 +589,8 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo
587 while (!fl) { 589 while (!fl) {
588 if (++state->bucket <= FL_HASH_MASK) 590 if (++state->bucket <= FL_HASH_MASK)
589 fl = fl_ht[state->bucket]; 591 fl = fl_ht[state->bucket];
592 else
593 break;
590 } 594 }
591 return fl; 595 return fl;
592} 596}
@@ -623,9 +627,13 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v)
623 read_unlock_bh(&ip6_fl_lock); 627 read_unlock_bh(&ip6_fl_lock);
624} 628}
625 629
626static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) 630static int ip6fl_seq_show(struct seq_file *seq, void *v)
627{ 631{
628 while(fl) { 632 if (v == SEQ_START_TOKEN)
633 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
634 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
635 else {
636 struct ip6_flowlabel *fl = v;
629 seq_printf(seq, 637 seq_printf(seq,
630 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n", 638 "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n",
631 (unsigned)ntohl(fl->label), 639 (unsigned)ntohl(fl->label),
@@ -636,17 +644,7 @@ static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl)
636 (long)(fl->expires - jiffies)/HZ, 644 (long)(fl->expires - jiffies)/HZ,
637 NIP6(fl->dst), 645 NIP6(fl->dst),
638 fl->opt ? fl->opt->opt_nflen : 0); 646 fl->opt ? fl->opt->opt_nflen : 0);
639 fl = fl->next;
640 } 647 }
641}
642
643static int ip6fl_seq_show(struct seq_file *seq, void *v)
644{
645 if (v == SEQ_START_TOKEN)
646 seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n",
647 "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt");
648 else
649 ip6fl_fl_seq_show(seq, v);
650 return 0; 648 return 0;
651} 649}
652 650
diff --git a/net/ipv6/ndisc.c b/net/ipv6/ndisc.c
index 41a8a5f06602..73eb8c33e9f0 100644
--- a/net/ipv6/ndisc.c
+++ b/net/ipv6/ndisc.c
@@ -1742,6 +1742,7 @@ int __init ndisc_init(struct net_proto_family *ops)
1742 1742
1743void ndisc_cleanup(void) 1743void ndisc_cleanup(void)
1744{ 1744{
1745 unregister_netdevice_notifier(&ndisc_netdev_notifier);
1745#ifdef CONFIG_SYSCTL 1746#ifdef CONFIG_SYSCTL
1746 neigh_sysctl_unregister(&nd_tbl.parms); 1747 neigh_sysctl_unregister(&nd_tbl.parms);
1747#endif 1748#endif
diff --git a/net/ipv6/netfilter/Kconfig b/net/ipv6/netfilter/Kconfig
index 4bc4e5b33794..d7c45a9c15fe 100644
--- a/net/ipv6/netfilter/Kconfig
+++ b/net/ipv6/netfilter/Kconfig
@@ -40,7 +40,7 @@ config IP6_NF_QUEUE
40 To compile it as a module, choose M here. If unsure, say N. 40 To compile it as a module, choose M here. If unsure, say N.
41 41
42config IP6_NF_IPTABLES 42config IP6_NF_IPTABLES
43 tristate "IP6 tables support (required for filtering/masq/NAT)" 43 tristate "IP6 tables support (required for filtering)"
44 depends on NETFILTER_XTABLES 44 depends on NETFILTER_XTABLES
45 help 45 help
46 ip6tables is a general, extensible packet identification framework. 46 ip6tables is a general, extensible packet identification framework.
diff --git a/net/ipv6/netfilter/ip6_queue.c b/net/ipv6/netfilter/ip6_queue.c
index 9510c24ca8d2..9fec832ee08b 100644
--- a/net/ipv6/netfilter/ip6_queue.c
+++ b/net/ipv6/netfilter/ip6_queue.c
@@ -349,9 +349,10 @@ ipq_mangle_ipv6(ipq_verdict_msg_t *v, struct ipq_queue_entry *e)
349 if (v->data_len < sizeof(*user_iph)) 349 if (v->data_len < sizeof(*user_iph))
350 return 0; 350 return 0;
351 diff = v->data_len - e->skb->len; 351 diff = v->data_len - e->skb->len;
352 if (diff < 0) 352 if (diff < 0) {
353 skb_trim(e->skb, v->data_len); 353 if (pskb_trim(e->skb, v->data_len))
354 else if (diff > 0) { 354 return -ENOMEM;
355 } else if (diff > 0) {
355 if (v->data_len > 0xFFFF) 356 if (v->data_len > 0xFFFF)
356 return -EINVAL; 357 return -EINVAL;
357 if (diff > skb_tailroom(e->skb)) { 358 if (diff > skb_tailroom(e->skb)) {
diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c
index 4ab368fa0b8f..204e02162d49 100644
--- a/net/ipv6/netfilter/ip6_tables.c
+++ b/net/ipv6/netfilter/ip6_tables.c
@@ -111,7 +111,7 @@ ip6_packet_match(const struct sk_buff *skb,
111 const char *outdev, 111 const char *outdev,
112 const struct ip6t_ip6 *ip6info, 112 const struct ip6t_ip6 *ip6info,
113 unsigned int *protoff, 113 unsigned int *protoff,
114 int *fragoff) 114 int *fragoff, int *hotdrop)
115{ 115{
116 size_t i; 116 size_t i;
117 unsigned long ret; 117 unsigned long ret;
@@ -169,9 +169,11 @@ ip6_packet_match(const struct sk_buff *skb,
169 unsigned short _frag_off; 169 unsigned short _frag_off;
170 170
171 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off); 171 protohdr = ipv6_find_hdr(skb, protoff, -1, &_frag_off);
172 if (protohdr < 0) 172 if (protohdr < 0) {
173 if (_frag_off == 0)
174 *hotdrop = 1;
173 return 0; 175 return 0;
174 176 }
175 *fragoff = _frag_off; 177 *fragoff = _frag_off;
176 178
177 dprintf("Packet protocol %hi ?= %s%hi.\n", 179 dprintf("Packet protocol %hi ?= %s%hi.\n",
@@ -290,7 +292,7 @@ ip6t_do_table(struct sk_buff **pskb,
290 IP_NF_ASSERT(e); 292 IP_NF_ASSERT(e);
291 IP_NF_ASSERT(back); 293 IP_NF_ASSERT(back);
292 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6, 294 if (ip6_packet_match(*pskb, indev, outdev, &e->ipv6,
293 &protoff, &offset)) { 295 &protoff, &offset, &hotdrop)) {
294 struct ip6t_entry_target *t; 296 struct ip6t_entry_target *t;
295 297
296 if (IP6T_MATCH_ITERATE(e, do_match, 298 if (IP6T_MATCH_ITERATE(e, do_match,
@@ -584,12 +586,19 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size,
584 return -EINVAL; 586 return -EINVAL;
585 } 587 }
586 588
589 if (e->target_offset + sizeof(struct ip6t_entry_target) >
590 e->next_offset)
591 return -EINVAL;
592
587 j = 0; 593 j = 0;
588 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); 594 ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j);
589 if (ret != 0) 595 if (ret != 0)
590 goto cleanup_matches; 596 goto cleanup_matches;
591 597
592 t = ip6t_get_target(e); 598 t = ip6t_get_target(e);
599 ret = -EINVAL;
600 if (e->target_offset + t->u.target_size > e->next_offset)
601 goto cleanup_matches;
593 target = try_then_request_module(xt_find_target(AF_INET6, 602 target = try_then_request_module(xt_find_target(AF_INET6,
594 t->u.user.name, 603 t->u.user.name,
595 t->u.user.revision), 604 t->u.user.revision),
@@ -749,19 +758,17 @@ translate_table(const char *name,
749 } 758 }
750 } 759 }
751 760
752 if (!mark_source_chains(newinfo, valid_hooks, entry0))
753 return -ELOOP;
754
755 /* Finally, each sanity check must pass */ 761 /* Finally, each sanity check must pass */
756 i = 0; 762 i = 0;
757 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, 763 ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size,
758 check_entry, name, size, &i); 764 check_entry, name, size, &i);
759 765
760 if (ret != 0) { 766 if (ret != 0)
761 IP6T_ENTRY_ITERATE(entry0, newinfo->size, 767 goto cleanup;
762 cleanup_entry, &i); 768
763 return ret; 769 ret = -ELOOP;
764 } 770 if (!mark_source_chains(newinfo, valid_hooks, entry0))
771 goto cleanup;
765 772
766 /* And one copy for every other CPU */ 773 /* And one copy for every other CPU */
767 for_each_possible_cpu(i) { 774 for_each_possible_cpu(i) {
@@ -769,6 +776,9 @@ translate_table(const char *name,
769 memcpy(newinfo->entries[i], entry0, newinfo->size); 776 memcpy(newinfo->entries[i], entry0, newinfo->size);
770 } 777 }
771 778
779 return 0;
780cleanup:
781 IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i);
772 return ret; 782 return ret;
773} 783}
774 784
@@ -1438,6 +1448,9 @@ static void __exit ip6_tables_fini(void)
1438 * If target header is found, its offset is set in *offset and return protocol 1448 * If target header is found, its offset is set in *offset and return protocol
1439 * number. Otherwise, return -1. 1449 * number. Otherwise, return -1.
1440 * 1450 *
1451 * If the first fragment doesn't contain the final protocol header or
1452 * NEXTHDR_NONE it is considered invalid.
1453 *
1441 * Note that non-1st fragment is special case that "the protocol number 1454 * Note that non-1st fragment is special case that "the protocol number
1442 * of last header" is "next header" field in Fragment header. In this case, 1455 * of last header" is "next header" field in Fragment header. In this case,
1443 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff 1456 * *offset is meaningless and fragment offset is stored in *fragoff if fragoff
@@ -1461,12 +1474,12 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
1461 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) { 1474 if ((!ipv6_ext_hdr(nexthdr)) || nexthdr == NEXTHDR_NONE) {
1462 if (target < 0) 1475 if (target < 0)
1463 break; 1476 break;
1464 return -1; 1477 return -ENOENT;
1465 } 1478 }
1466 1479
1467 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr); 1480 hp = skb_header_pointer(skb, start, sizeof(_hdr), &_hdr);
1468 if (hp == NULL) 1481 if (hp == NULL)
1469 return -1; 1482 return -EBADMSG;
1470 if (nexthdr == NEXTHDR_FRAGMENT) { 1483 if (nexthdr == NEXTHDR_FRAGMENT) {
1471 unsigned short _frag_off, *fp; 1484 unsigned short _frag_off, *fp;
1472 fp = skb_header_pointer(skb, 1485 fp = skb_header_pointer(skb,
@@ -1475,18 +1488,18 @@ int ipv6_find_hdr(const struct sk_buff *skb, unsigned int *offset,
1475 sizeof(_frag_off), 1488 sizeof(_frag_off),
1476 &_frag_off); 1489 &_frag_off);
1477 if (fp == NULL) 1490 if (fp == NULL)
1478 return -1; 1491 return -EBADMSG;
1479 1492
1480 _frag_off = ntohs(*fp) & ~0x7; 1493 _frag_off = ntohs(*fp) & ~0x7;
1481 if (_frag_off) { 1494 if (_frag_off) {
1482 if (target < 0 && 1495 if (target < 0 &&
1483 ((!ipv6_ext_hdr(hp->nexthdr)) || 1496 ((!ipv6_ext_hdr(hp->nexthdr)) ||
1484 nexthdr == NEXTHDR_NONE)) { 1497 hp->nexthdr == NEXTHDR_NONE)) {
1485 if (fragoff) 1498 if (fragoff)
1486 *fragoff = _frag_off; 1499 *fragoff = _frag_off;
1487 return hp->nexthdr; 1500 return hp->nexthdr;
1488 } 1501 }
1489 return -1; 1502 return -ENOENT;
1490 } 1503 }
1491 hdrlen = 8; 1504 hdrlen = 8;
1492 } else if (nexthdr == NEXTHDR_AUTH) 1505 } else if (nexthdr == NEXTHDR_AUTH)
diff --git a/net/ipv6/netfilter/ip6t_ah.c b/net/ipv6/netfilter/ip6t_ah.c
index ec1b1608156c..46486645eb75 100644
--- a/net/ipv6/netfilter/ip6t_ah.c
+++ b/net/ipv6/netfilter/ip6t_ah.c
@@ -54,9 +54,14 @@ match(const struct sk_buff *skb,
54 const struct ip6t_ah *ahinfo = matchinfo; 54 const struct ip6t_ah *ahinfo = matchinfo;
55 unsigned int ptr; 55 unsigned int ptr;
56 unsigned int hdrlen = 0; 56 unsigned int hdrlen = 0;
57 int err;
57 58
58 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL) < 0) 59 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_AUTH, NULL);
60 if (err < 0) {
61 if (err != -ENOENT)
62 *hotdrop = 1;
59 return 0; 63 return 0;
64 }
60 65
61 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah); 66 ah = skb_header_pointer(skb, ptr, sizeof(_ah), &_ah);
62 if (ah == NULL) { 67 if (ah == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_frag.c b/net/ipv6/netfilter/ip6t_frag.c
index 78d9c8b9e28a..cd22eaaccdca 100644
--- a/net/ipv6/netfilter/ip6t_frag.c
+++ b/net/ipv6/netfilter/ip6t_frag.c
@@ -52,9 +52,14 @@ match(const struct sk_buff *skb,
52 struct frag_hdr _frag, *fh; 52 struct frag_hdr _frag, *fh;
53 const struct ip6t_frag *fraginfo = matchinfo; 53 const struct ip6t_frag *fraginfo = matchinfo;
54 unsigned int ptr; 54 unsigned int ptr;
55 int err;
55 56
56 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL) < 0) 57 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL);
58 if (err < 0) {
59 if (err != -ENOENT)
60 *hotdrop = 1;
57 return 0; 61 return 0;
62 }
58 63
59 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag); 64 fh = skb_header_pointer(skb, ptr, sizeof(_frag), &_frag);
60 if (fh == NULL) { 65 if (fh == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_hbh.c b/net/ipv6/netfilter/ip6t_hbh.c
index d32a205e3af2..3f25babe0440 100644
--- a/net/ipv6/netfilter/ip6t_hbh.c
+++ b/net/ipv6/netfilter/ip6t_hbh.c
@@ -65,9 +65,14 @@ match(const struct sk_buff *skb,
65 u8 _opttype, *tp = NULL; 65 u8 _opttype, *tp = NULL;
66 u8 _optlen, *lp = NULL; 66 u8 _optlen, *lp = NULL;
67 unsigned int optlen; 67 unsigned int optlen;
68 int err;
68 69
69 if (ipv6_find_hdr(skb, &ptr, match->data, NULL) < 0) 70 err = ipv6_find_hdr(skb, &ptr, match->data, NULL);
71 if (err < 0) {
72 if (err != -ENOENT)
73 *hotdrop = 1;
70 return 0; 74 return 0;
75 }
71 76
72 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh); 77 oh = skb_header_pointer(skb, ptr, sizeof(_optsh), &_optsh);
73 if (oh == NULL) { 78 if (oh == NULL) {
diff --git a/net/ipv6/netfilter/ip6t_rt.c b/net/ipv6/netfilter/ip6t_rt.c
index bcb2e168a5bc..54d7d14134fd 100644
--- a/net/ipv6/netfilter/ip6t_rt.c
+++ b/net/ipv6/netfilter/ip6t_rt.c
@@ -58,9 +58,14 @@ match(const struct sk_buff *skb,
58 unsigned int hdrlen = 0; 58 unsigned int hdrlen = 0;
59 unsigned int ret = 0; 59 unsigned int ret = 0;
60 struct in6_addr *ap, _addr; 60 struct in6_addr *ap, _addr;
61 int err;
61 62
62 if (ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL) < 0) 63 err = ipv6_find_hdr(skb, &ptr, NEXTHDR_ROUTING, NULL);
64 if (err < 0) {
65 if (err != -ENOENT)
66 *hotdrop = 1;
63 return 0; 67 return 0;
68 }
64 69
65 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route); 70 rh = skb_header_pointer(skb, ptr, sizeof(_route), &_route);
66 if (rh == NULL) { 71 if (rh == NULL) {
diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c
index d09329ca3267..d6dedc4aec77 100644
--- a/net/ipv6/raw.c
+++ b/net/ipv6/raw.c
@@ -604,7 +604,7 @@ error:
604 return err; 604 return err;
605} 605}
606 606
607static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) 607static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
608{ 608{
609 struct iovec *iov; 609 struct iovec *iov;
610 u8 __user *type = NULL; 610 u8 __user *type = NULL;
@@ -616,7 +616,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
616 int i; 616 int i;
617 617
618 if (!msg->msg_iov) 618 if (!msg->msg_iov)
619 return; 619 return 0;
620 620
621 for (i = 0; i < msg->msg_iovlen; i++) { 621 for (i = 0; i < msg->msg_iovlen; i++) {
622 iov = &msg->msg_iov[i]; 622 iov = &msg->msg_iov[i];
@@ -638,8 +638,9 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
638 code = iov->iov_base; 638 code = iov->iov_base;
639 639
640 if (type && code) { 640 if (type && code) {
641 get_user(fl->fl_icmp_type, type); 641 if (get_user(fl->fl_icmp_type, type) ||
642 get_user(fl->fl_icmp_code, code); 642 get_user(fl->fl_icmp_code, code))
643 return -EFAULT;
643 probed = 1; 644 probed = 1;
644 } 645 }
645 break; 646 break;
@@ -650,7 +651,8 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
650 /* check if type field is readable or not. */ 651 /* check if type field is readable or not. */
651 if (iov->iov_len > 2 - len) { 652 if (iov->iov_len > 2 - len) {
652 u8 __user *p = iov->iov_base; 653 u8 __user *p = iov->iov_base;
653 get_user(fl->fl_mh_type, &p[2 - len]); 654 if (get_user(fl->fl_mh_type, &p[2 - len]))
655 return -EFAULT;
654 probed = 1; 656 probed = 1;
655 } else 657 } else
656 len += iov->iov_len; 658 len += iov->iov_len;
@@ -664,6 +666,7 @@ static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg)
664 if (probed) 666 if (probed)
665 break; 667 break;
666 } 668 }
669 return 0;
667} 670}
668 671
669static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, 672static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
@@ -787,7 +790,9 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk,
787 opt = ipv6_fixup_options(&opt_space, opt); 790 opt = ipv6_fixup_options(&opt_space, opt);
788 791
789 fl.proto = proto; 792 fl.proto = proto;
790 rawv6_probe_proto_opt(&fl, msg); 793 err = rawv6_probe_proto_opt(&fl, msg);
794 if (err)
795 goto out;
791 796
792 ipv6_addr_copy(&fl.fl6_dst, daddr); 797 ipv6_addr_copy(&fl.fl6_dst, daddr);
793 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) 798 if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr))
diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c
index b481a4d780c2..be699f85b2c7 100644
--- a/net/ipv6/sit.c
+++ b/net/ipv6/sit.c
@@ -854,3 +854,4 @@ int __init sit_init(void)
854module_init(sit_init); 854module_init(sit_init);
855module_exit(sit_cleanup); 855module_exit(sit_cleanup);
856MODULE_LICENSE("GPL"); 856MODULE_LICENSE("GPL");
857MODULE_ALIAS("sit0");
diff --git a/net/ipv6/xfrm6_tunnel.c b/net/ipv6/xfrm6_tunnel.c
index 7af227bb1551..7931e4f898d4 100644
--- a/net/ipv6/xfrm6_tunnel.c
+++ b/net/ipv6/xfrm6_tunnel.c
@@ -135,7 +135,7 @@ u32 xfrm6_tunnel_spi_lookup(xfrm_address_t *saddr)
135 x6spi = __xfrm6_tunnel_spi_lookup(saddr); 135 x6spi = __xfrm6_tunnel_spi_lookup(saddr);
136 spi = x6spi ? x6spi->spi : 0; 136 spi = x6spi ? x6spi->spi : 0;
137 read_unlock_bh(&xfrm6_tunnel_spi_lock); 137 read_unlock_bh(&xfrm6_tunnel_spi_lock);
138 return spi; 138 return htonl(spi);
139} 139}
140 140
141EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup); 141EXPORT_SYMBOL(xfrm6_tunnel_spi_lookup);
@@ -210,7 +210,7 @@ u32 xfrm6_tunnel_alloc_spi(xfrm_address_t *saddr)
210 spi = __xfrm6_tunnel_alloc_spi(saddr); 210 spi = __xfrm6_tunnel_alloc_spi(saddr);
211 write_unlock_bh(&xfrm6_tunnel_spi_lock); 211 write_unlock_bh(&xfrm6_tunnel_spi_lock);
212 212
213 return spi; 213 return htonl(spi);
214} 214}
215 215
216EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi); 216EXPORT_SYMBOL(xfrm6_tunnel_alloc_spi);