patch-2.1.30 linux/net/ipv6/icmp.c
Next file: linux/net/ipv6/ip6_fib.c
Previous file: linux/net/ipv6/exthdrs.c
Back to the patch index
Back to the overall index
- Lines: 481
- Date:
Thu Mar 20 18:17:14 1997
- Orig file:
v2.1.29/linux/net/ipv6/icmp.c
- Orig date:
Tue Mar 4 10:25:27 1997
diff -u --recursive --new-file v2.1.29/linux/net/ipv6/icmp.c linux/net/ipv6/icmp.c
@@ -5,6 +5,8 @@
* Authors:
* Pedro Roque <roque@di.fc.ul.pt>
*
+ * $Id: icmp.c,v 1.8 1997/03/18 18:24:30 davem Exp $
+ *
* Based on net/ipv4/icmp.c
*
* RFC 1885
@@ -28,17 +30,9 @@
#include <linux/socket.h>
#include <linux/in.h>
#include <linux/kernel.h>
-#include <linux/major.h>
#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/string.h>
#include <linux/sockios.h>
#include <linux/net.h>
-#include <linux/fcntl.h>
-#include <linux/mm.h>
-#include <linux/interrupt.h>
-#include <linux/proc_fs.h>
-#include <linux/stat.h>
#include <linux/skbuff.h>
#include <linux/inet.h>
@@ -49,15 +43,13 @@
#include <net/sock.h>
#include <net/ipv6.h>
+#include <net/checksum.h>
#include <net/protocol.h>
-#include <net/route.h>
-#include <net/ndisc.h>
#include <net/raw.h>
-#include <net/inet_common.h>
+#include <net/rawv6.h>
#include <net/transp_v6.h>
-#include <net/ipv6_route.h>
+#include <net/ip6_route.h>
#include <net/addrconf.h>
-#include <net/rawv6.h>
#include <asm/uaccess.h>
#include <asm/system.h>
@@ -88,7 +80,7 @@
struct icmpv6_msg {
- struct icmpv6hdr icmph;
+ struct icmp6hdr icmph;
__u8 *data;
struct in6_addr *daddr;
int len;
@@ -106,7 +98,7 @@
char *buff, unsigned int offset, unsigned int len)
{
struct icmpv6_msg *msg = (struct icmpv6_msg *) data;
- struct icmpv6hdr *icmph;
+ struct icmp6hdr *icmph;
__u32 csum;
/*
@@ -115,26 +107,25 @@
* on an echo reply. (those are the rules on RFC 1883)
*/
- if (offset)
- {
+ if (offset) {
csum = csum_partial_copy((void *) msg->data +
- offset - sizeof(struct icmpv6hdr),
+ offset - sizeof(struct icmp6hdr),
buff, len, msg->csum);
msg->csum = csum;
return 0;
}
csum = csum_partial_copy((void *) &msg->icmph, buff,
- sizeof(struct icmpv6hdr), msg->csum);
+ sizeof(struct icmp6hdr), msg->csum);
csum = csum_partial_copy((void *) msg->data,
- buff + sizeof(struct icmpv6hdr),
- len - sizeof(struct icmpv6hdr), csum);
+ buff + sizeof(struct icmp6hdr),
+ len - sizeof(struct icmp6hdr), csum);
- icmph = (struct icmpv6hdr *) buff;
+ icmph = (struct icmp6hdr *) buff;
- icmph->checksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
- IPPROTO_ICMPV6, csum);
+ icmph->icmp6_cksum = csum_ipv6_magic(saddr, msg->daddr, msg->len,
+ IPPROTO_ICMPV6, csum);
return 0;
}
@@ -163,6 +154,7 @@
struct in6_addr *saddr = NULL;
struct device *src_dev = NULL;
struct icmpv6_msg msg;
+ struct flowi fl;
int addr_type = 0;
int optlen;
int len;
@@ -171,9 +163,8 @@
* sanity check pointer in case of parameter problem
*/
- if (type == ICMPV6_PARAMETER_PROB &&
- (info > (skb->tail - ((unsigned char *) hdr))))
- {
+ if (type == ICMPV6_PARAMPROB &&
+ (info > (skb->tail - ((unsigned char *) hdr)))) {
printk(KERN_DEBUG "icmpv6_send: bug! pointer > skb\n");
return;
}
@@ -188,23 +179,18 @@
addr_type = ipv6_addr_type(&hdr->daddr);
if (ipv6_chk_addr(&hdr->daddr))
- {
saddr = &hdr->daddr;
- }
/*
* Dest addr check
*/
- if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST))
- {
+ if ((addr_type & IPV6_ADDR_MULTICAST || skb->pkt_type != PACKET_HOST)) {
if (type != ICMPV6_PKT_TOOBIG &&
- !(type == ICMPV6_PARAMETER_PROB &&
+ !(type == ICMPV6_PARAMPROB &&
code == ICMPV6_UNK_OPTION &&
(opt_unrec(skb, info))))
- {
return;
- }
saddr = NULL;
}
@@ -216,16 +202,13 @@
*/
if (addr_type & IPV6_ADDR_LINKLOCAL)
- {
src_dev = skb->dev;
- }
/*
* Must not send if we know that source is Anycast also.
* for now we don't know that.
*/
- if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST))
- {
+ if ((addr_type == IPV6_ADDR_ANY) || (addr_type & IPV6_ADDR_MULTICAST)) {
printk(KERN_DEBUG "icmpv6_send: addr_any/mcast source\n");
return;
}
@@ -235,9 +218,9 @@
* getfrag_t callback.
*/
- msg.icmph.type = type;
- msg.icmph.code = code;
- msg.icmph.checksum = 0;
+ msg.icmph.icmp6_type = type;
+ msg.icmph.icmp6_code = code;
+ msg.icmph.icmp6_cksum = 0;
msg.icmph.icmp6_pointer = htonl(info);
msg.data = skb->nh.raw;
@@ -252,31 +235,37 @@
optlen = 0;
len = min(skb->tail - ((unsigned char *) hdr),
- 576 - sizeof(struct ipv6hdr) - sizeof(struct icmpv6hdr)
+ 576 - sizeof(struct ipv6hdr) - sizeof(struct icmp6hdr)
- optlen);
- if (len < 0)
- {
+ if (len < 0) {
printk(KERN_DEBUG "icmp: len problem\n");
return;
}
- len += sizeof(struct icmpv6hdr);
+ len += sizeof(struct icmp6hdr);
msg.len = len;
+ fl.proto = IPPROTO_ICMPV6;
+ fl.nl_u.ip6_u.daddr = &hdr->saddr;
+ fl.nl_u.ip6_u.saddr = saddr;
+ fl.dev = src_dev;
+ fl.uli_u.icmpt.type = type;
+ fl.uli_u.icmpt.code = code;
- ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len,
- saddr, src_dev, NULL, IPPROTO_ICMPV6, 0, 1);
+ ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
+ MSG_DONTWAIT);
}
static void icmpv6_echo_reply(struct sk_buff *skb)
{
struct sock *sk = icmpv6_socket->sk;
struct ipv6hdr *hdr = skb->nh.ipv6h;
- struct icmpv6hdr *icmph = (struct icmpv6hdr *) skb->h.raw;
+ struct icmp6hdr *icmph = (struct icmp6hdr *) skb->h.raw;
struct in6_addr *saddr;
struct icmpv6_msg msg;
+ struct flowi fl;
unsigned char *data;
int len;
@@ -288,11 +277,11 @@
saddr = NULL;
len = skb->tail - data;
- len += sizeof(struct icmpv6hdr);
+ len += sizeof(struct icmp6hdr);
- msg.icmph.type = ICMPV6_ECHO_REPLY;
- msg.icmph.code = 0;
- msg.icmph.checksum = 0;
+ msg.icmph.icmp6_type = ICMPV6_ECHO_REPLY;
+ msg.icmph.icmp6_code = 0;
+ msg.icmph.icmp6_cksum = 0;
msg.icmph.icmp6_identifier = icmph->icmp6_identifier;
msg.icmph.icmp6_sequence = icmph->icmp6_sequence;
@@ -300,9 +289,16 @@
msg.csum = 0;
msg.len = len;
msg.daddr = &hdr->saddr;
-
- ipv6_build_xmit(sk, icmpv6_getfrag, &msg, &hdr->saddr, len, saddr,
- skb->dev, NULL, IPPROTO_ICMPV6, 0, 1);
+
+ fl.proto = IPPROTO_ICMPV6;
+ fl.nl_u.ip6_u.daddr = &hdr->saddr;
+ fl.nl_u.ip6_u.saddr = saddr;
+ fl.dev = skb->dev;
+ fl.uli_u.icmpt.type = ICMPV6_ECHO_REPLY;
+ fl.uli_u.icmpt.code = 0;
+
+ ip6_build_xmit(sk, icmpv6_getfrag, &msg, &fl, len, NULL, -1,
+ MSG_DONTWAIT);
}
static __inline__ int ipv6_ext_hdr(u8 nexthdr)
@@ -339,19 +335,24 @@
pbuff = (char *) (hdr + 1);
len -= sizeof(struct ipv6hdr);
- while (ipv6_ext_hdr(nexthdr))
- {
+ while (ipv6_ext_hdr(nexthdr)) {
int hdrlen;
if (nexthdr == NEXTHDR_NONE)
return;
nexthdr = *pbuff;
+
+ /* Header length is size in 8-octet units, not
+ * including the first 8 octets.
+ */
hdrlen = *(pbuff+1);
+ hdrlen = (hdrlen + 1) << 3;
- if (((hdrlen + 1) << 3) > len)
+ if (hdrlen > len)
return;
+ /* Now this is right. */
pbuff += hdrlen;
len -= hdrlen;
}
@@ -360,16 +361,13 @@
for (ipprot = (struct inet6_protocol *) inet6_protos[hash];
ipprot != NULL;
- ipprot=(struct inet6_protocol *)ipprot->next)
- {
+ ipprot=(struct inet6_protocol *)ipprot->next) {
if (ipprot->protocol != nexthdr)
continue;
if (ipprot->err_handler)
- {
ipprot->err_handler(type, code, pbuff, info,
saddr, daddr, ipprot);
- }
return;
}
@@ -378,16 +376,12 @@
sk = raw_v6_htable[hash];
if (sk == NULL)
- {
return;
- }
while((sk = raw_v6_lookup(sk, nexthdr, daddr, saddr))) {
rawv6_err(sk, type, code, pbuff, saddr, daddr);
sk = sk->next;
}
-
- return;
}
/*
@@ -400,32 +394,29 @@
int redo, struct inet6_protocol *protocol)
{
struct ipv6hdr *orig_hdr;
- struct icmpv6hdr *hdr = (struct icmpv6hdr *) skb->h.raw;
+ struct icmp6hdr *hdr = (struct icmp6hdr *) skb->h.raw;
int ulen;
- /* perform checksum */
-
-
+ /* Perform checksum. */
switch (skb->ip_summed) {
case CHECKSUM_NONE:
skb->csum = csum_partial((char *)hdr, len, 0);
case CHECKSUM_HW:
if (csum_ipv6_magic(saddr, daddr, len, IPPROTO_ICMPV6,
- skb->csum))
- {
+ skb->csum)) {
printk(KERN_DEBUG "icmpv6 checksum failed\n");
goto discard_it;
}
default:
/* CHECKSUM_UNNECESSARY */
- }
+ };
/*
* length of original packet carried in skb
*/
ulen = skb->tail - (unsigned char *) (hdr + 1);
- switch (hdr->type) {
+ switch (hdr->icmp6_type) {
case ICMPV6_ECHO_REQUEST:
icmpv6_echo_reply(skb);
@@ -438,20 +429,19 @@
case ICMPV6_PKT_TOOBIG:
orig_hdr = (struct ipv6hdr *) (hdr + 1);
if (ulen >= sizeof(struct ipv6hdr))
- {
- rt6_handle_pmtu(&orig_hdr->daddr,
- ntohl(hdr->icmp6_mtu));
- }
+ rt6_pmtu_discovery(&orig_hdr->daddr, dev,
+ ntohl(hdr->icmp6_mtu));
/*
- * Drop through to notify
+ * Drop through to notify
*/
case ICMPV6_DEST_UNREACH:
- case ICMPV6_TIME_EXCEEDED:
- case ICMPV6_PARAMETER_PROB:
+ case ICMPV6_TIME_EXCEED:
+ case ICMPV6_PARAMPROB:
- icmpv6_notify(hdr->type, hdr->code, (char *) (hdr + 1), ulen,
+ icmpv6_notify(hdr->icmp6_type, hdr->icmp6_code,
+ (char *) (hdr + 1), ulen,
saddr, daddr, protocol);
break;
@@ -463,32 +453,35 @@
ndisc_rcv(skb, dev, saddr, daddr, opt, len);
break;
- case ICMPV6_MEMBERSHIP_QUERY:
- case ICMPV6_MEMBERSHIP_REPORT:
- case ICMPV6_MEMBERSHIP_REDUCTION:
- /* forward the packet to the igmp module */
+ case ICMPV6_MGM_QUERY:
+ igmp6_event_query(skb, hdr, len);
+ break;
+
+ case ICMPV6_MGM_REPORT:
+ igmp6_event_report(skb, hdr, len);
+ break;
+
+ case ICMPV6_MGM_REDUCTION:
break;
default:
printk(KERN_DEBUG "icmpv6: msg of unkown type\n");
/* informational */
- if (hdr->type & 0x80)
- {
+ if (hdr->icmp6_type & 0x80)
goto discard_it;
- }
/*
* error of unkown type.
* must pass to upper level
*/
- icmpv6_notify(hdr->type, hdr->code, (char *) (hdr + 1), ulen,
+ icmpv6_notify(hdr->icmp6_type, hdr->icmp6_code,
+ (char *) (hdr + 1), ulen,
saddr, daddr, protocol);
- }
-
- discard_it:
+ };
+discard_it:
kfree_skb(skb, FREE_READ);
return 0;
}
@@ -509,7 +502,7 @@
if((err=ops->create(icmpv6_socket, IPPROTO_ICMPV6))<0)
printk(KERN_DEBUG
- "Failed to create the ICMP control socket.\n");
+ "Failed to create the ICMP6 control socket.\n");
MOD_DEC_USE_COUNT;
@@ -518,6 +511,9 @@
sk->num = 256; /* Don't receive any data */
inet6_add_protocol(&icmpv6_protocol);
+
+ ndisc_init(ops);
+ igmp6_init(ops);
}
static struct icmp6_err {
@@ -539,8 +535,7 @@
switch (type) {
case ICMPV6_DEST_UNREACH:
- if (code <= ICMPV6_PORT_UNREACH)
- {
+ if (code <= ICMPV6_PORT_UNREACH) {
*err = tab_unreach[code].err;
fatal = tab_unreach[code].fatal;
}
@@ -550,7 +545,7 @@
*err = EMSGSIZE;
break;
- case ICMPV6_PARAMETER_PROB:
+ case ICMPV6_PARAMPROB:
*err = EPROTO;
fatal = 1;
break;
@@ -558,9 +553,3 @@
return fatal;
}
-
-/*
- * Local variables:
- * compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/include -Wall -Wstrict-prototypes -O2 -fomit-frame-pointer -fno-strength-reduce -pipe -m486 -DCPU=486 -DMODULE -DMODVERSIONS -include /usr/src/linux/include/linux/modversions.h -c -o icmp.o icmp.c"
- * End:
- */
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov