developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 1 | #include <sys/ioctl.h> |
| 2 | #include <sys/socket.h> |
| 3 | |
| 4 | #include "atenl.h" |
| 5 | |
| 6 | int atenl_eth_init(struct atenl *an) |
| 7 | { |
| 8 | struct sockaddr_ll addr = {}; |
| 9 | struct ifreq ifr = {}; |
| 10 | int ret; |
| 11 | |
developer | 543811b | 2022-10-07 15:54:07 +0800 | [diff] [blame] | 12 | if (!an->bridge_name) { |
| 13 | perror("Bridge name not specified"); |
| 14 | goto out; |
| 15 | } |
| 16 | |
| 17 | memcpy(ifr.ifr_name, an->bridge_name, strlen(an->bridge_name)); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 18 | ret = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RACFG)); |
| 19 | if (ret < 0) { |
| 20 | perror("socket"); |
| 21 | goto out; |
| 22 | } |
| 23 | an->sock_eth = ret; |
| 24 | |
| 25 | addr.sll_family = AF_PACKET; |
developer | 543811b | 2022-10-07 15:54:07 +0800 | [diff] [blame] | 26 | addr.sll_ifindex = if_nametoindex(an->bridge_name); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 27 | |
| 28 | ret = bind(an->sock_eth, (struct sockaddr *)&addr, sizeof(addr)); |
| 29 | if (ret < 0) { |
| 30 | perror("bind"); |
| 31 | goto out; |
| 32 | } |
| 33 | |
| 34 | ret = ioctl(an->sock_eth, SIOCGIFHWADDR, &ifr); |
| 35 | if (ret < 0) { |
| 36 | perror("ioctl(SIOCGIFHWADDR)"); |
| 37 | goto out; |
| 38 | } |
| 39 | |
| 40 | memcpy(an->mac_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); |
| 41 | atenl_info("Open Ethernet socket success on %s, mac addr = " MACSTR "\n", |
developer | 543811b | 2022-10-07 15:54:07 +0800 | [diff] [blame] | 42 | an->bridge_name, MAC2STR(an->mac_addr)); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 43 | |
| 44 | ret = 0; |
| 45 | out: |
| 46 | return ret; |
| 47 | } |
| 48 | |
| 49 | int atenl_eth_recv(struct atenl *an, struct atenl_data *data) |
| 50 | { |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 51 | struct ethhdr *hdr; |
| 52 | int len; |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 53 | |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 54 | len = recvfrom(an->sock_eth, data->buf, sizeof(data->buf), 0, NULL, NULL); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 55 | |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 56 | if (len < ETH_HLEN + RACFG_HLEN) { |
| 57 | atenl_err("packet len is too short: %d\n", len); |
| 58 | return -EINVAL; |
| 59 | } |
| 60 | |
| 61 | hdr = (struct ethhdr *)data->buf; |
| 62 | if (hdr->h_proto != htons(ETH_P_RACFG)) { |
| 63 | atenl_err("invalid protocol type\n"); |
| 64 | return -EINVAL; |
| 65 | } |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 66 | |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 67 | if (!ether_addr_equal(an->mac_addr, hdr->h_dest) && |
| 68 | !is_broadcast_ether_addr(hdr->h_dest)) { |
| 69 | atenl_err("invalid dest MAC\n"); |
| 70 | return -EINVAL; |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 71 | } |
| 72 | |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 73 | data->len = len; |
| 74 | |
| 75 | return 0; |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 76 | } |
| 77 | |
| 78 | int atenl_eth_send(struct atenl *an, struct atenl_data *data) |
| 79 | { |
| 80 | struct ethhdr *ehdr = (struct ethhdr *)data->buf; |
| 81 | struct sockaddr_ll addr = {}; |
| 82 | int ret, len = data->len; |
| 83 | |
| 84 | if (an->unicast) |
| 85 | ether_addr_copy(ehdr->h_dest, ehdr->h_source); |
| 86 | else |
| 87 | eth_broadcast_addr(ehdr->h_dest); |
| 88 | |
| 89 | ether_addr_copy(ehdr->h_source, an->mac_addr); |
| 90 | ehdr->h_proto = htons(ETH_P_RACFG); |
| 91 | |
| 92 | if (len < 60) |
| 93 | len = 60; |
| 94 | else if (len > 1514) { |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 95 | atenl_err("response ethernet length is too long\n"); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 96 | return -1; |
| 97 | } |
| 98 | |
developer | f30d447 | 2022-05-30 16:40:23 +0800 | [diff] [blame] | 99 | atenl_dbg_print_data(data->buf, __func__, len); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 100 | |
| 101 | addr.sll_family = PF_PACKET; |
| 102 | addr.sll_protocol = htons(ETH_P_RACFG); |
developer | 543811b | 2022-10-07 15:54:07 +0800 | [diff] [blame] | 103 | addr.sll_ifindex = if_nametoindex(an->bridge_name); |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 104 | addr.sll_pkttype = PACKET_BROADCAST; |
| 105 | addr.sll_hatype = ARPHRD_ETHER; |
| 106 | addr.sll_halen = ETH_ALEN; |
| 107 | memset(addr.sll_addr, 0, 8); |
| 108 | eth_broadcast_addr(addr.sll_addr); |
| 109 | |
| 110 | ret = sendto(an->sock_eth, data->buf, len, 0, |
| 111 | (struct sockaddr *)&addr, sizeof(addr)); |
| 112 | if (ret < 0) { |
| 113 | perror("sendto"); |
| 114 | return ret; |
| 115 | } |
| 116 | |
developer | 22c7ab6 | 2022-01-24 11:13:32 +0800 | [diff] [blame] | 117 | return 0; |
| 118 | } |