| 387 | } |
| 388 | |
| 389 | func (d VirtualTun) pingIPs() { |
| 390 | for _, addr := range d.Conf.CheckAlive { |
| 391 | socket, err := d.Tnet.Dial("ping", addr.String()) |
| 392 | if err != nil { |
| 393 | errorLogger.Printf("Failed to ping %s: %s\n", addr, err.Error()) |
| 394 | continue |
| 395 | } |
| 396 | |
| 397 | data := make([]byte, 16) |
| 398 | _, _ = srand.Read(data) |
| 399 | |
| 400 | requestPing := icmp.Echo{ |
| 401 | Seq: rand.Intn(1 << 16), |
| 402 | Data: data, |
| 403 | } |
| 404 | |
| 405 | var icmpBytes []byte |
| 406 | if addr.Is4() { |
| 407 | icmpBytes, _ = (&icmp.Message{Type: ipv4.ICMPTypeEcho, Code: 0, Body: &requestPing}).Marshal(nil) |
| 408 | } else if addr.Is6() { |
| 409 | icmpBytes, _ = (&icmp.Message{Type: ipv6.ICMPTypeEchoRequest, Code: 0, Body: &requestPing}).Marshal(nil) |
| 410 | } else { |
| 411 | errorLogger.Printf("Failed to ping %s: invalid address: %s\n", addr, addr.String()) |
| 412 | continue |
| 413 | } |
| 414 | |
| 415 | _ = socket.SetReadDeadline(time.Now().Add(time.Duration(d.Conf.CheckAliveInterval) * time.Second)) |
| 416 | _, err = socket.Write(icmpBytes) |
| 417 | if err != nil { |
| 418 | errorLogger.Printf("Failed to ping %s: %s\n", addr, err.Error()) |
| 419 | continue |
| 420 | } |
| 421 | |
| 422 | addr := addr |
| 423 | go func() { |
| 424 | n, err := socket.Read(icmpBytes[:]) |
| 425 | if err != nil { |
| 426 | errorLogger.Printf("Failed to read ping response from %s: %s\n", addr, err.Error()) |
| 427 | return |
| 428 | } |
| 429 | |
| 430 | replyPacket, err := icmp.ParseMessage(1, icmpBytes[:n]) |
| 431 | if err != nil { |
| 432 | errorLogger.Printf("Failed to parse ping response from %s: %s\n", addr, err.Error()) |
| 433 | return |
| 434 | } |
| 435 | |
| 436 | if addr.Is4() { |
| 437 | replyPing, ok := replyPacket.Body.(*icmp.Echo) |
| 438 | if !ok { |
| 439 | errorLogger.Printf("Failed to parse ping response from %s: invalid reply type: %s\n", addr, replyPacket.Type) |
| 440 | return |
| 441 | } |
| 442 | if !bytes.Equal(replyPing.Data, requestPing.Data) || replyPing.Seq != requestPing.Seq { |
| 443 | errorLogger.Printf("Failed to parse ping response from %s: invalid ping reply: %v\n", addr, replyPing) |
| 444 | return |
| 445 | } |
| 446 | } |