Revision e6d43cfb
b/slirp/ip_icmp.c | ||
---|---|---|
60 | 60 |
/* ADDR MASK REPLY (18) */ 0 |
61 | 61 |
}; |
62 | 62 |
|
63 |
void icmp_init(Slirp *slirp) |
|
64 |
{ |
|
65 |
slirp->icmp.so_next = slirp->icmp.so_prev = &slirp->icmp; |
|
66 |
slirp->icmp_last_so = &slirp->icmp; |
|
67 |
} |
|
68 |
|
|
69 |
static int icmp_send(struct socket *so, struct mbuf *m, int hlen) |
|
70 |
{ |
|
71 |
struct ip *ip = mtod(m, struct ip *); |
|
72 |
struct sockaddr_in addr; |
|
73 |
|
|
74 |
so->s = qemu_socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP); |
|
75 |
if (so->s == -1) { |
|
76 |
return -1; |
|
77 |
} |
|
78 |
|
|
79 |
so->so_m = m; |
|
80 |
so->so_faddr = ip->ip_dst; |
|
81 |
so->so_laddr = ip->ip_src; |
|
82 |
so->so_iptos = ip->ip_tos; |
|
83 |
so->so_type = IPPROTO_ICMP; |
|
84 |
so->so_state = SS_ISFCONNECTED; |
|
85 |
so->so_expire = curtime + SO_EXPIRE; |
|
86 |
|
|
87 |
addr.sin_family = AF_INET; |
|
88 |
addr.sin_addr = so->so_faddr; |
|
89 |
|
|
90 |
insque(so, &so->slirp->icmp); |
|
91 |
|
|
92 |
if (sendto(so->s, m->m_data + hlen, m->m_len - hlen, 0, |
|
93 |
(struct sockaddr *)&addr, sizeof(addr)) == -1) { |
|
94 |
DEBUG_MISC((dfd, "icmp_input icmp sendto tx errno = %d-%s\n", |
|
95 |
errno, strerror(errno))); |
|
96 |
icmp_error(m, ICMP_UNREACH, ICMP_UNREACH_NET, 0, strerror(errno)); |
|
97 |
icmp_detach(so); |
|
98 |
} |
|
99 |
|
|
100 |
return 0; |
|
101 |
} |
|
102 |
|
|
103 |
void icmp_detach(struct socket *so) |
|
104 |
{ |
|
105 |
closesocket(so->s); |
|
106 |
sofree(so); |
|
107 |
} |
|
108 |
|
|
63 | 109 |
/* |
64 | 110 |
* Process a received ICMP message. |
65 | 111 |
*/ |
... | ... | |
97 | 143 |
DEBUG_ARG("icmp_type = %d", icp->icmp_type); |
98 | 144 |
switch (icp->icmp_type) { |
99 | 145 |
case ICMP_ECHO: |
100 |
icp->icmp_type = ICMP_ECHOREPLY; |
|
101 | 146 |
ip->ip_len += hlen; /* since ip_input subtracts this */ |
102 | 147 |
if (ip->ip_dst.s_addr == slirp->vhost_addr.s_addr) { |
103 | 148 |
icmp_reflect(m); |
... | ... | |
107 | 152 |
struct socket *so; |
108 | 153 |
struct sockaddr_in addr; |
109 | 154 |
if ((so = socreate(slirp)) == NULL) goto freeit; |
155 |
if (icmp_send(so, m, hlen) == 0) { |
|
156 |
return; |
|
157 |
} |
|
110 | 158 |
if(udp_attach(so) == -1) { |
111 | 159 |
DEBUG_MISC((dfd,"icmp_input udp_attach errno = %d-%s\n", |
112 | 160 |
errno,strerror(errno))); |
... | ... | |
321 | 369 |
m->m_len -= hlen; |
322 | 370 |
icp = mtod(m, struct icmp *); |
323 | 371 |
|
372 |
icp->icmp_type = ICMP_ECHOREPLY; |
|
324 | 373 |
icp->icmp_cksum = 0; |
325 | 374 |
icp->icmp_cksum = cksum(m, ip->ip_len - hlen); |
326 | 375 |
|
... | ... | |
351 | 400 |
|
352 | 401 |
(void ) ip_output((struct socket *)NULL, m); |
353 | 402 |
} |
403 |
|
|
404 |
void icmp_receive(struct socket *so) |
|
405 |
{ |
|
406 |
struct mbuf *m = so->so_m; |
|
407 |
struct ip *ip = mtod(m, struct ip *); |
|
408 |
int hlen = ip->ip_hl << 2; |
|
409 |
u_char error_code; |
|
410 |
struct icmp *icp; |
|
411 |
int id, len; |
|
412 |
|
|
413 |
m->m_data += hlen; |
|
414 |
m->m_len -= hlen; |
|
415 |
icp = mtod(m, struct icmp *); |
|
416 |
|
|
417 |
id = icp->icmp_id; |
|
418 |
len = recv(so->s, icp, m->m_len, 0); |
|
419 |
icp->icmp_id = id; |
|
420 |
|
|
421 |
m->m_data -= hlen; |
|
422 |
m->m_len += hlen; |
|
423 |
|
|
424 |
if (len == -1 || len == 0) { |
|
425 |
if (errno == ENETUNREACH) { |
|
426 |
error_code = ICMP_UNREACH_NET; |
|
427 |
} else { |
|
428 |
error_code = ICMP_UNREACH_HOST; |
|
429 |
} |
|
430 |
DEBUG_MISC((dfd, " udp icmp rx errno = %d-%s\n", errno, |
|
431 |
strerror(errno))); |
|
432 |
icmp_error(so->so_m, ICMP_UNREACH, error_code, 0, strerror(errno)); |
|
433 |
} else { |
|
434 |
icmp_reflect(so->so_m); |
|
435 |
so->so_m = NULL; /* Don't m_free() it again! */ |
|
436 |
} |
|
437 |
icmp_detach(so); |
|
438 |
} |
b/slirp/ip_icmp.h | ||
---|---|---|
153 | 153 |
(type) == ICMP_IREQ || (type) == ICMP_IREQREPLY || \ |
154 | 154 |
(type) == ICMP_MASKREQ || (type) == ICMP_MASKREPLY) |
155 | 155 |
|
156 |
void icmp_init(Slirp *slirp); |
|
156 | 157 |
void icmp_input(struct mbuf *, int); |
157 | 158 |
void icmp_error(struct mbuf *msrc, u_char type, u_char code, int minsize, |
158 | 159 |
const char *message); |
159 | 160 |
void icmp_reflect(struct mbuf *); |
161 |
void icmp_receive(struct socket *so); |
|
162 |
void icmp_detach(struct socket *so); |
|
160 | 163 |
|
161 | 164 |
#endif |
b/slirp/ip_input.c | ||
---|---|---|
58 | 58 |
slirp->ipq.ip_link.next = slirp->ipq.ip_link.prev = &slirp->ipq.ip_link; |
59 | 59 |
udp_init(slirp); |
60 | 60 |
tcp_init(slirp); |
61 |
icmp_init(slirp); |
|
61 | 62 |
} |
62 | 63 |
|
63 | 64 |
/* |
b/slirp/misc.c | ||
---|---|---|
407 | 407 |
inet_ntoa(dst_addr), ntohs(dst_port), |
408 | 408 |
so->so_rcv.sb_cc, so->so_snd.sb_cc); |
409 | 409 |
} |
410 |
|
|
411 |
for (so = slirp->icmp.so_next; so != &slirp->icmp; so = so->so_next) { |
|
412 |
n = snprintf(buf, sizeof(buf), " ICMP[%d sec]", |
|
413 |
(so->so_expire - curtime) / 1000); |
|
414 |
src.sin_addr = so->so_laddr; |
|
415 |
dst_addr = so->so_faddr; |
|
416 |
memset(&buf[n], ' ', 19 - n); |
|
417 |
buf[19] = 0; |
|
418 |
monitor_printf(mon, "%s %3d %15s - ", buf, so->s, |
|
419 |
src.sin_addr.s_addr ? inet_ntoa(src.sin_addr) : "*"); |
|
420 |
monitor_printf(mon, "%15s - %5d %5d\n", inet_ntoa(dst_addr), |
|
421 |
so->so_rcv.sb_cc, so->so_snd.sb_cc); |
|
422 |
} |
|
410 | 423 |
} |
b/slirp/slirp.c | ||
---|---|---|
373 | 373 |
UPD_NFDS(so->s); |
374 | 374 |
} |
375 | 375 |
} |
376 |
|
|
377 |
/* |
|
378 |
* ICMP sockets |
|
379 |
*/ |
|
380 |
for (so = slirp->icmp.so_next; so != &slirp->icmp; |
|
381 |
so = so_next) { |
|
382 |
so_next = so->so_next; |
|
383 |
|
|
384 |
/* |
|
385 |
* See if it's timed out |
|
386 |
*/ |
|
387 |
if (so->so_expire) { |
|
388 |
if (so->so_expire <= curtime) { |
|
389 |
icmp_detach(so); |
|
390 |
continue; |
|
391 |
} else { |
|
392 |
do_slowtimo = 1; /* Let socket expire */ |
|
393 |
} |
|
394 |
} |
|
395 |
|
|
396 |
if (so->so_state & SS_ISFCONNECTED) { |
|
397 |
FD_SET(so->s, readfds); |
|
398 |
UPD_NFDS(so->s); |
|
399 |
} |
|
400 |
} |
|
376 | 401 |
} |
377 | 402 |
|
378 | 403 |
*pnfds = nfds; |
... | ... | |
542 | 567 |
sorecvfrom(so); |
543 | 568 |
} |
544 | 569 |
} |
570 |
|
|
571 |
/* |
|
572 |
* Check incoming ICMP relies. |
|
573 |
*/ |
|
574 |
for (so = slirp->icmp.so_next; so != &slirp->icmp; |
|
575 |
so = so_next) { |
|
576 |
so_next = so->so_next; |
|
577 |
|
|
578 |
if (so->s != -1 && FD_ISSET(so->s, readfds)) { |
|
579 |
icmp_receive(so); |
|
580 |
} |
|
581 |
} |
|
545 | 582 |
} |
546 | 583 |
|
547 | 584 |
/* |
b/slirp/slirp.h | ||
---|---|---|
152 | 152 |
#include "tcp_var.h" |
153 | 153 |
#include "tcpip.h" |
154 | 154 |
#include "udp.h" |
155 |
#include "ip_icmp.h" |
|
155 | 156 |
#include "mbuf.h" |
156 | 157 |
#include "sbuf.h" |
157 | 158 |
#include "socket.h" |
... | ... | |
218 | 219 |
struct socket udb; |
219 | 220 |
struct socket *udp_last_so; |
220 | 221 |
|
222 |
/* icmp states */ |
|
223 |
struct socket icmp; |
|
224 |
struct socket *icmp_last_so; |
|
225 |
|
|
221 | 226 |
/* tftp states */ |
222 | 227 |
char *tftp_prefix; |
223 | 228 |
struct tftp_session tftp_sessions[TFTP_SESSIONS_MAX]; |
b/slirp/socket.c | ||
---|---|---|
71 | 71 |
slirp->tcp_last_so = &slirp->tcb; |
72 | 72 |
} else if (so == slirp->udp_last_so) { |
73 | 73 |
slirp->udp_last_so = &slirp->udb; |
74 |
} else if (so == slirp->icmp_last_so) { |
|
75 |
slirp->icmp_last_so = &slirp->icmp; |
|
74 | 76 |
} |
75 | 77 |
m_free(so->so_m); |
76 | 78 |
|
Also available in: Unified diff