/* ip_icmp.c 4.24 82/11/03 */
#include "../h/protosw.h"
#include "../net/route.h"
#include "../netinet/in.h"
#include "../netinet/in_systm.h"
#include "../netinet/ip.h"
#include "../netinet/ip_icmp.h"
* ICMP routines: error generation, receive packet processing, and
* routines to turnaround packets back to the originator, and
* host table maintenance routines.
* Generate an error packet of type error
* in response to bad packet ip.
icmp_error(oip
, type
, code
)
register unsigned oiplen
= oip
->ip_hl
<< 2;
register struct icmp
*icp
;
printf("icmp_error(%x, %d, %d)\n", oip
, type
, code
);
* Make sure that the old IP packet had 8 bytes of data to return;
* if not, don't bother. Also don't EVER error if the old
* packet protocol was ICMP.
if (oip
->ip_len
< 8 || oip
->ip_p
== IPPROTO_ICMP
)
* First, formulate icmp message
m
->m_len
= oiplen
+ 8 + ICMP_MINLEN
;
m
->m_off
= MMAXOFF
- m
->m_len
;
icp
= mtod(m
, struct icmp
*);
if (type
== ICMP_PARAMPROB
) {
bcopy((caddr_t
)oip
, (caddr_t
)&icp
->icmp_ip
, oiplen
+ 8);
nip
->ip_len
= htons((u_short
)nip
->ip_len
);
* Now, copy old ip header in front of icmp
* message. This allows us to reuse any source
nip
= mtod(m
, struct ip
*);
bcopy((caddr_t
)oip
, (caddr_t
)nip
, oiplen
);
nip
->ip_len
= m
->m_len
+ oiplen
;
nip
->ip_p
= IPPROTO_ICMP
;
/* icmp_send adds ip header to m_off and m_len, so we deduct here */
static char icmpmap
[] = {
PRC_UNREACH_NET
, PRC_QUENCH
, PRC_REDIRECT_NET
,
-1, -1, PRC_TIMXCEED_INTRANS
,
static struct sockproto icmproto
= { AF_INET
, IPPROTO_ICMP
};
static struct sockaddr_in icmpsrc
= { AF_INET
};
static struct sockaddr_in icmpdst
= { AF_INET
};
* Process a received ICMP message.
register struct icmp
*icp
;
register struct ip
*ip
= mtod(m
, struct ip
*);
int icmplen
= ip
->ip_len
, hlen
= ip
->ip_hl
<< 2, i
, (*ctlfunc
)();
extern u_char ip_protox
[];
* Locate icmp structure in mbuf, and check
* that not corrupted and of at least minimum length.
printf("icmp_input from %x, len %d\n", ip
->ip_src
, icmplen
);
if (icmplen
< ICMP_MINLEN
)
/* need routine to make sure header is in this mbuf here */
icp
= mtod(m
, struct icmp
*);
if (i
!= in_cksum(m
, icmplen
)) {
printf("icmp: cksum %x\n", i
);
* Message type specific processing.
printf("icmp_input, type %d code %d\n", icp
->icmp_type
,
switch (i
= icp
->icmp_type
) {
* Problem with previous datagram; advise
icp
->icmp_ip
.ip_len
= ntohs((u_short
)icp
->icmp_ip
.ip_len
);
if (icmplen
< ICMP_ADVLENMIN
|| icmplen
< ICMP_ADVLEN(icp
))
printf("deliver to protocol %d\n", icp
->icmp_ip
.ip_p
);
if (ctlfunc
= inetsw
[ip_protox
[icp
->icmp_ip
.ip_p
]].pr_ctlinput
)
(*ctlfunc
)(icmpmap
[i
] + icp
->icmp_code
, (caddr_t
)icp
);
icp
->icmp_type
= ICMP_ECHOREPLY
;
if (icmplen
< ICMP_TSLEN
)
icp
->icmp_type
= ICMP_TSTAMPREPLY
;
icp
->icmp_rtime
= iptime();
icp
->icmp_ttime
= icp
->icmp_rtime
; /* bogus, do later! */
/* fill in source address zero fields! */
if (icmplen
< ICMP_ADVLENMIN
|| icmplen
< ICMP_ADVLEN(icp
))
icmpsrc
.sin_addr
= ip
->ip_src
;
icmpdst
.sin_addr
= ip
->ip_dst
;
raw_input(dtom(icp
), &icmproto
, (struct sockaddr
*)&icmpsrc
,
(struct sockaddr
*)&icmpdst
);
* Reflect the ip packet back to the source
* TODO: rearrange ip source routing options.
int generateicmpmsgs
= 1;
* Send an icmp packet back to the ip level,
* after supplying a checksum.
register int hlen
= ip
->ip_hl
<< 2;
register struct icmp
*icp
;
register struct mbuf
*m
= dtom(ip
);
icp
= mtod(m
, struct icmp
*);
icp
->icmp_cksum
= in_cksum(m
, ip
->ip_len
- hlen
);
printf("icmp_send dst %x src %x\n", ip
->ip_dst
, ip
->ip_src
);
(void) ip_output(m
, (struct mbuf
*)0, (struct route
*)0, 0);
t
= (time
.tv_sec
% (24*60*60)) * 1000 + time
.tv_usec
/ 1000;