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