X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=net%2Fnet.c;h=ded86e7456715ebfc39ce1f52cdd5fd954870963;hb=a539c8bd7dffa144bdc4826d5858a515f626856f;hp=0b876913e35fe89a74d02e76348fe515cec1a2d9;hpb=bfebc8c965e41d62dc6355d09bdd63ca57011b99;p=oweals%2Fu-boot.git diff --git a/net/net.c b/net/net.c index 0b876913e3..ded86e7456 100644 --- a/net/net.c +++ b/net/net.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0 /* * Copied from Linux Monitor (LiMon) - Networking. * @@ -6,7 +7,6 @@ * Copyright 2000 Roland Borde * Copyright 2000 Paolo Scaffardi * Copyright 2000-2002 Wolfgang Denk, wd@denx.de - * SPDX-License-Identifier: GPL-2.0 */ /* @@ -78,16 +78,27 @@ * - own IP address * We want: - network time * Next step: none + * + * WOL: + * + * Prerequisites: - own ethernet address + * We want: - magic packet or timeout + * Next step: none */ #include #include #include -#include +#include +#include #include #include +#include #include +#if defined(CONFIG_CMD_PCAP) +#include +#endif #if defined(CONFIG_LED_STATUS) #include #include @@ -107,8 +118,9 @@ #if defined(CONFIG_CMD_SNTP) #include "sntp.h" #endif - -DECLARE_GLOBAL_DATA_PTR; +#if defined(CONFIG_CMD_WOL) +#include "wol.h" +#endif /** BOOTP EXTENTIONS **/ @@ -123,10 +135,6 @@ struct in_addr net_dns_server; struct in_addr net_dns_server2; #endif -#ifdef CONFIG_MCAST_TFTP /* Multicast TFTP */ -struct in_addr net_mcast_addr; -#endif - /** END OF BOOTP EXTENTIONS **/ /* Our ethernet address */ @@ -166,6 +174,8 @@ ushort net_native_vlan = 0xFFFF; /* Boot File name */ char net_boot_file_name[1024]; +/* Indicates whether the file name was specified on the command line */ +bool net_boot_file_name_explicit; /* The actual transferred size of the bootfile (in bytes) */ u32 net_boot_file_size; /* Boot file size in blocks as reported by the DHCP server */ @@ -206,26 +216,6 @@ int __maybe_unused net_busy_flag; /**********************************************************************/ -static int on_bootfile(const char *name, const char *value, enum env_op op, - int flags) -{ - if (flags & H_PROGRAMMATIC) - return 0; - - switch (op) { - case env_op_create: - case env_op_overwrite: - copy_filename(net_boot_file_name, value, - sizeof(net_boot_file_name)); - break; - default: - break; - } - - return 0; -} -U_BOOT_ENV_CALLBACK(bootfile, on_bootfile); - static int on_ipaddr(const char *name, const char *value, enum env_op op, int flags) { @@ -322,6 +312,16 @@ void net_auto_load(void) const char *s = env_get("autoload"); if (s != NULL && strcmp(s, "NFS") == 0) { + if (net_check_prereq(NFS)) { +/* We aren't expecting to get a serverip, so just accept the assigned IP */ +#ifdef CONFIG_BOOTP_SERVERIP + net_set_state(NETLOOP_SUCCESS); +#else + printf("Cannot autoload with NFS\n"); + net_set_state(NETLOOP_FAIL); +#endif + return; + } /* * Use NFS to load the bootfile. */ @@ -337,6 +337,16 @@ void net_auto_load(void) net_set_state(NETLOOP_SUCCESS); return; } + if (net_check_prereq(TFTPGET)) { +/* We aren't expecting to get a serverip, so just accept the assigned IP */ +#ifdef CONFIG_BOOTP_SERVERIP + net_set_state(NETLOOP_SUCCESS); +#else + printf("Cannot autoload with TFTPGET\n"); + net_set_state(NETLOOP_FAIL); +#endif + return; + } tftp_start(TFTPGET); } @@ -394,6 +404,7 @@ void net_init(void) int net_loop(enum proto_t protocol) { int ret = -EINVAL; + enum net_loop_state prev_net_state = net_state; net_restarted = 0; net_dev_exists = 0; @@ -431,6 +442,7 @@ restart: case 1: /* network not configured */ eth_halt(); + net_set_state(prev_net_state); return -ENODEV; case 2: @@ -453,6 +465,11 @@ restart: tftp_start_server(); break; #endif +#ifdef CONFIG_UDP_FUNCTION_FASTBOOT + case FASTBOOT: + fastboot_start_server(); + break; +#endif #if defined(CONFIG_CMD_DHCP) case DHCP: bootp_reset(); @@ -508,6 +525,11 @@ restart: case LINKLOCAL: link_local_start(); break; +#endif +#if defined(CONFIG_CMD_WOL) + case WOL: + wol_start(); + break; #endif default: break; @@ -635,6 +657,7 @@ restart: /* Invalidate the last protocol */ eth_set_last_protocol(BOOTP); debug_cond(DEBUG_INT_STATE, "--- net_loop Fail!\n"); + ret = -ENONET; goto done; case NETLOOP_CONTINUE: @@ -650,6 +673,12 @@ done: /* Clear out the handlers */ net_set_udp_handler(NULL); net_set_icmp_handler(NULL); +#endif + net_set_state(prev_net_state); + +#if defined(CONFIG_CMD_PCAP) + if (pcap_active()) + pcap_print_status(); #endif return ret; } @@ -683,7 +712,7 @@ int net_start_again(void) retry_forever = 0; } - if ((!retry_forever) && (net_try_count >= retrycnt)) { + if ((!retry_forever) && (net_try_count > retrycnt)) { eth_halt(); net_set_state(NETLOOP_FAIL); /* @@ -776,8 +805,24 @@ void net_set_timeout_handler(ulong iv, thand_f *f) } } +uchar *net_get_async_tx_pkt_buf(void) +{ + if (arp_is_waiting()) + return arp_tx_packet; /* If we are waiting, we already sent */ + else + return net_tx_packet; +} + int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, int payload_len) +{ + return net_send_ip_packet(ether, dest, dport, sport, payload_len, + IPPROTO_UDP, 0, 0, 0); +} + +int net_send_ip_packet(uchar *ether, struct in_addr dest, int dport, int sport, + int payload_len, int proto, u8 action, u32 tcp_seq_num, + u32 tcp_ack_num) { uchar *pkt; int eth_hdr_size; @@ -799,9 +844,16 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, pkt = (uchar *)net_tx_packet; eth_hdr_size = net_set_ether(pkt, ether, PROT_IP); - pkt += eth_hdr_size; - net_set_udp_header(pkt, dest, dport, sport, payload_len); - pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; + + switch (proto) { + case IPPROTO_UDP: + net_set_udp_header(pkt + eth_hdr_size, dest, dport, sport, + payload_len); + pkt_hdr_size = eth_hdr_size + IP_UDP_HDR_SIZE; + break; + default: + return -EINVAL; + } /* if MAC address was not discovered yet, do an ARP request */ if (memcmp(ether, net_null_ethaddr, 6) == 0) { @@ -1040,6 +1092,9 @@ void net_process_received_packet(uchar *in_packet, int len) debug_cond(DEBUG_NET_PKT, "packet received\n"); +#if defined(CONFIG_CMD_PCAP) + pcap_post(in_packet, len, false); +#endif net_rx_packet = in_packet; net_rx_packet_len = len; et = (struct ethernet_hdr *)in_packet; @@ -1169,9 +1224,6 @@ void net_process_received_packet(uchar *in_packet, int len) dst_ip = net_read_ip(&ip->ip_dst); if (net_ip.s_addr && dst_ip.s_addr != net_ip.s_addr && dst_ip.s_addr != 0xFFFFFFFF) { -#ifdef CONFIG_MCAST_TFTP - if (net_mcast_addr != dst_ip) -#endif return; } /* Read source IP address for later use */ @@ -1212,6 +1264,9 @@ void net_process_received_packet(uchar *in_packet, int len) return; } + if (ntohs(ip->udp_len) < UDP_HDR_SIZE || ntohs(ip->udp_len) > ntohs(ip->ip_len)) + return; + debug_cond(DEBUG_DEV_PKT, "received UDP (to=%pI4, from=%pI4, len=%d)\n", &dst_ip, &src_ip, len); @@ -1274,6 +1329,11 @@ void net_process_received_packet(uchar *in_packet, int len) ntohs(ip->udp_src), ntohs(ip->udp_len) - UDP_HDR_SIZE); break; +#ifdef CONFIG_CMD_WOL + case PROT_WOL: + wol_receive(ip, len); + break; +#endif } } @@ -1313,7 +1373,7 @@ static int net_check_prereq(enum proto_t protocol) /* Fall through */ case TFTPGET: case TFTPPUT: - if (net_server_ip.s_addr == 0) { + if (net_server_ip.s_addr == 0 && !is_serverip_in_cmd()) { puts("*** ERROR: `serverip' not set\n"); return 1; } @@ -1324,6 +1384,7 @@ common: /* Fall through */ case NETCONS: + case FASTBOOT: case TFTPSRV: if (net_ip.s_addr == 0) { puts("*** ERROR: `ipaddr' not set\n"); @@ -1426,7 +1487,8 @@ int net_update_ether(struct ethernet_hdr *et, uchar *addr, uint prot) } } -void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) +void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source, + u16 pkt_len, u8 proto) { struct ip_udp_hdr *ip = (struct ip_udp_hdr *)pkt; @@ -1436,7 +1498,8 @@ void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) /* IP_HDR_SIZE / 4 (not including UDP) */ ip->ip_hl_v = 0x45; ip->ip_tos = 0; - ip->ip_len = htons(IP_HDR_SIZE); + ip->ip_len = htons(pkt_len); + ip->ip_p = proto; ip->ip_id = htons(net_ip_id++); ip->ip_off = htons(IP_FLAGS_DFRAG); /* Don't fragment */ ip->ip_ttl = 255; @@ -1445,6 +1508,8 @@ void net_set_ip_header(uchar *pkt, struct in_addr dest, struct in_addr source) net_copy_ip((void *)&ip->ip_src, &source); /* already in network byte order */ net_copy_ip((void *)&ip->ip_dst, &dest); + + ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); } void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, @@ -1460,10 +1525,8 @@ void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, if (len & 1) pkt[IP_UDP_HDR_SIZE + len] = 0; - net_set_ip_header(pkt, dest, net_ip); - ip->ip_len = htons(IP_UDP_HDR_SIZE + len); - ip->ip_p = IPPROTO_UDP; - ip->ip_sum = compute_ip_checksum(ip, IP_HDR_SIZE); + net_set_ip_header(pkt, dest, net_ip, IP_UDP_HDR_SIZE + len, + IPPROTO_UDP); ip->udp_src = htons(sport); ip->udp_dst = htons(dport); @@ -1473,16 +1536,41 @@ void net_set_udp_header(uchar *pkt, struct in_addr dest, int dport, int sport, void copy_filename(char *dst, const char *src, int size) { - if (*src && (*src == '"')) { + if (src && *src && (*src == '"')) { ++src; --size; } - while ((--size > 0) && *src && (*src != '"')) + while ((--size > 0) && src && *src && (*src != '"')) *dst++ = *src++; *dst = '\0'; } +int is_serverip_in_cmd(void) +{ + return !!strchr(net_boot_file_name, ':'); +} + +int net_parse_bootfile(struct in_addr *ipaddr, char *filename, int max_len) +{ + char *colon; + + if (net_boot_file_name[0] == '\0') + return 0; + + colon = strchr(net_boot_file_name, ':'); + if (colon) { + if (ipaddr) + *ipaddr = string_to_ip(net_boot_file_name); + strncpy(filename, colon + 1, max_len); + } else { + strncpy(filename, net_boot_file_name, max_len); + } + filename[max_len - 1] = '\0'; + + return 1; +} + #if defined(CONFIG_CMD_NFS) || \ defined(CONFIG_CMD_SNTP) || \ defined(CONFIG_CMD_DNS) @@ -1536,7 +1624,19 @@ ushort string_to_vlan(const char *s) return htons(id); } -ushort getenv_vlan(char *var) +ushort env_get_vlan(char *var) { return string_to_vlan(env_get(var)); } + +void eth_parse_enetaddr(const char *addr, uint8_t *enetaddr) +{ + char *end; + int i; + + for (i = 0; i < 6; ++i) { + enetaddr[i] = addr ? simple_strtoul(addr, &end, 16) : 0; + if (addr) + addr = (*end) ? end + 1 : end; + } +}