Revision e6d43cfb slirp/ip_icmp.c

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
}

Also available in: Unified diff