"Das U-Boot" Source Tree
at master 117 lines 2.6 kB view raw
1// SPDX-License-Identifier: GPL-2.0+ 2/* 3 * Copyright (C) 2013 Allied Telesis Labs NZ 4 * Chris Packham, <judge.packham@gmail.com> 5 * 6 * Copyright (C) 2022 YADRO 7 * Viacheslav Mitrofanov <v.v.mitrofanov@yadro.com> 8 */ 9 10/* Simple ping6 implementation */ 11 12#include <net.h> 13#include <net6.h> 14#include "ndisc.h" 15 16static ushort seq_no; 17 18/* the ipv6 address to ping */ 19struct in6_addr net_ping_ip6; 20 21int 22ip6_make_ping(uchar *eth_dst_addr, struct in6_addr *neigh_addr, uchar *pkt) 23{ 24 struct echo_msg *msg; 25 u16 len; 26 u16 csum_p; 27 uchar *pkt_old = pkt; 28 29 len = sizeof(struct echo_msg); 30 31 pkt += net_set_ether(pkt, eth_dst_addr, PROT_IP6); 32 pkt += ip6_add_hdr(pkt, &net_ip6, neigh_addr, PROT_ICMPV6, 33 IPV6_NDISC_HOPLIMIT, len); 34 35 /* ICMPv6 - Echo */ 36 msg = (struct echo_msg *)pkt; 37 msg->icmph.icmp6_type = IPV6_ICMP_ECHO_REQUEST; 38 msg->icmph.icmp6_code = 0; 39 msg->icmph.icmp6_cksum = 0; 40 msg->icmph.icmp6_identifier = 0; 41 msg->icmph.icmp6_sequence = htons(seq_no++); 42 msg->id = msg->icmph.icmp6_identifier; /* these seem redundant */ 43 msg->sequence = msg->icmph.icmp6_sequence; 44 45 /* checksum */ 46 csum_p = csum_partial((u8 *)msg, len, 0); 47 msg->icmph.icmp6_cksum = csum_ipv6_magic(&net_ip6, neigh_addr, len, 48 PROT_ICMPV6, csum_p); 49 50 pkt += len; 51 52 return pkt - pkt_old; 53} 54 55int ping6_send(void) 56{ 57 uchar *pkt; 58 static uchar mac[6]; 59 60 /* always send neighbor solicit */ 61 62 memcpy(mac, net_null_ethaddr, 6); 63 64 net_nd_sol_packet_ip6 = net_ping_ip6; 65 net_nd_packet_mac = mac; 66 67 pkt = net_nd_tx_packet; 68 pkt += ip6_make_ping(mac, &net_ping_ip6, pkt); 69 70 /* size of the waiting packet */ 71 net_nd_tx_packet_size = (pkt - net_nd_tx_packet); 72 73 /* and do the ARP request */ 74 net_nd_try = 1; 75 net_nd_timer_start = get_timer(0); 76 ndisc_request(); 77 return 1; /* waiting */ 78} 79 80static void ping6_timeout(void) 81{ 82 eth_halt(); 83 net_set_state(NETLOOP_FAIL); /* we did not get the reply */ 84} 85 86void ping6_start(void) 87{ 88 printf("Using %s device\n", eth_get_name()); 89 net_set_timeout_handler(10000UL, ping6_timeout); 90 91 ping6_send(); 92} 93 94int ping6_receive(struct ethernet_hdr *et, struct ip6_hdr *ip6, int len) 95{ 96 struct icmp6hdr *icmp = 97 (struct icmp6hdr *)(((uchar *)ip6) + IP6_HDR_SIZE); 98 struct in6_addr src_ip; 99 100 switch (icmp->icmp6_type) { 101 case IPV6_ICMP_ECHO_REPLY: 102 src_ip = ip6->saddr; 103 if (memcmp(&net_ping_ip6, &src_ip, sizeof(struct in6_addr))) 104 return -EINVAL; 105 net_set_state(NETLOOP_SUCCESS); 106 break; 107 case IPV6_ICMP_ECHO_REQUEST: 108 /* ignore for now.... */ 109 debug("Got ICMPv6 ECHO REQUEST from %pI6c\n", &ip6->saddr); 110 return -EINVAL; 111 default: 112 debug("Unexpected ICMPv6 type 0x%x\n", icmp->icmp6_type); 113 return -EINVAL; 114 } 115 116 return 0; 117}