X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=net%2Fnet.c;h=5114364edd8b544886ab356efe8d4185cdbc9ce8;hb=a6ab4b5470afadbc0f2a3d70437e3ccb88d8fa5c;hp=1e1d23dafa55fc44944212a1da540a05fbdfee20;hpb=dc557e9a1fe00ca9d884bd88feef5bebf23fede4;p=oweals%2Fu-boot.git diff --git a/net/net.c b/net/net.c index 1e1d23dafa..5114364edd 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,17 +78,28 @@ * - 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_STATUS_LED) +#if defined(CONFIG_CMD_PCAP) +#include +#endif +#if defined(CONFIG_LED_STATUS) #include #include #endif @@ -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) { @@ -318,10 +308,20 @@ U_BOOT_ENV_CALLBACK(dnsip, on_dnsip); */ void net_auto_load(void) { -#if defined(CONFIG_CMD_NFS) - const char *s = getenv("autoload"); +#if defined(CONFIG_CMD_NFS) && !defined(CONFIG_SPL_BUILD) + 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. */ @@ -329,7 +329,7 @@ void net_auto_load(void) return; } #endif - if (getenv_yesno("autoload") == 0) { + if (env_get_yesno("autoload") == 0) { /* * Just use BOOTP/RARP to configure system; * Do not use TFTP 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(); @@ -479,7 +496,7 @@ restart: ping_start(); break; #endif -#if defined(CONFIG_CMD_NFS) +#if defined(CONFIG_CMD_NFS) && !defined(CONFIG_SPL_BUILD) case NFS: nfs_start(); break; @@ -489,7 +506,7 @@ restart: cdp_start(); break; #endif -#if defined(CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) +#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD) case NETCONS: nc_start(); break; @@ -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; @@ -518,15 +540,15 @@ restart: #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ - defined(CONFIG_STATUS_LED) && \ - defined(STATUS_LED_RED) + defined(CONFIG_LED_STATUS) && \ + defined(CONFIG_LED_STATUS_RED) /* * Echo the inverted link state to the fault LED. */ if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) - status_led_set(STATUS_LED_RED, STATUS_LED_OFF); + status_led_set(CONFIG_LED_STATUS_RED, CONFIG_LED_STATUS_OFF); else - status_led_set(STATUS_LED_RED, STATUS_LED_ON); + status_led_set(CONFIG_LED_STATUS_RED, CONFIG_LED_STATUS_ON); #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ #endif /* CONFIG_MII, ... */ #ifdef CONFIG_USB_KEYBOARD @@ -539,9 +561,6 @@ restart: */ for (;;) { WATCHDOG_RESET(); -#ifdef CONFIG_SHOW_ACTIVITY - show_activity(1); -#endif if (arp_timeout_check() > 0) time_start = get_timer(0); @@ -583,16 +602,18 @@ restart: #if defined(CONFIG_MII) || defined(CONFIG_CMD_MII) #if defined(CONFIG_SYS_FAULT_ECHO_LINK_DOWN) && \ - defined(CONFIG_STATUS_LED) && \ - defined(STATUS_LED_RED) + defined(CONFIG_LED_STATUS) && \ + defined(CONFIG_LED_STATUS_RED) /* * Echo the inverted link state to the fault LED. */ if (miiphy_link(eth_get_dev()->name, CONFIG_SYS_FAULT_MII_ADDR)) - status_led_set(STATUS_LED_RED, STATUS_LED_OFF); + status_led_set(CONFIG_LED_STATUS_RED, + CONFIG_LED_STATUS_OFF); else - status_led_set(STATUS_LED_RED, STATUS_LED_ON); + status_led_set(CONFIG_LED_STATUS_RED, + CONFIG_LED_STATUS_ON); #endif /* CONFIG_SYS_FAULT_ECHO_LINK_DOWN, ... */ #endif /* CONFIG_MII, ... */ debug_cond(DEBUG_INT_STATE, "--- net_loop timeout\n"); @@ -614,8 +635,8 @@ restart: if (net_boot_file_size > 0) { printf("Bytes transferred = %d (%x hex)\n", net_boot_file_size, net_boot_file_size); - setenv_hex("filesize", net_boot_file_size); - setenv_hex("fileaddr", load_addr); + env_set_hex("filesize", net_boot_file_size); + env_set_hex("fileaddr", load_addr); } if (protocol != NETCONS) eth_halt(); @@ -633,6 +654,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: @@ -648,6 +670,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; } @@ -666,7 +694,7 @@ int net_start_again(void) unsigned long retrycnt = 0; int ret; - nretry = getenv("netretry"); + nretry = env_get("netretry"); if (nretry) { if (!strcmp(nretry, "yes")) retry_forever = 1; @@ -681,7 +709,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); /* @@ -774,8 +802,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; @@ -797,9 +841,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) { @@ -834,15 +885,7 @@ int net_send_udp_packet(uchar *ether, struct in_addr dest, int dport, int sport, #ifndef CONFIG_NET_MAXDEFRAG #define CONFIG_NET_MAXDEFRAG 16384 #endif -/* - * MAXDEFRAG, above, is chosen in the config file and is real data - * so we need to add the NFS overhead, which is more than TFTP. - * To use sizeof in the internal unnamed structures, we need a real - * instance (can't do "sizeof(struct rpc_t.u.reply))", unfortunately). - * The compiler doesn't complain nor allocates the actual structure - */ -static struct rpc_t rpc_specimen; -#define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG + sizeof(rpc_specimen.u.reply)) +#define IP_PKTSIZE (CONFIG_NET_MAXDEFRAG) #define IP_MAXUDP (IP_PKTSIZE - IP_HDR_SIZE) @@ -1046,6 +1089,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; @@ -1175,9 +1221,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 */ @@ -1218,6 +1261,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); @@ -1264,7 +1310,7 @@ void net_process_received_packet(uchar *in_packet, int len) } #endif -#if defined(CONFIG_NETCONSOLE) && !(CONFIG_SPL_BUILD) +#if defined(CONFIG_NETCONSOLE) && !defined(CONFIG_SPL_BUILD) nc_input_packet((uchar *)ip + IP_UDP_HDR_SIZE, src_ip, ntohs(ip->udp_dst), @@ -1280,6 +1326,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 } } @@ -1319,7 +1370,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; } @@ -1330,6 +1381,7 @@ common: /* Fall through */ case NETCONS: + case FASTBOOT: case TFTPSRV: if (net_ip.s_addr == 0) { puts("*** ERROR: `ipaddr' not set\n"); @@ -1432,7 +1484,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; @@ -1442,7 +1495,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; @@ -1451,6 +1505,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, @@ -1466,10 +1522,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); @@ -1479,16 +1533,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) @@ -1542,7 +1621,7 @@ 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(getenv(var)); + return string_to_vlan(env_get(var)); }