developer | 3abe1ad | 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 | |
| 12 | memcpy(ifr.ifr_name, BRIDGE_NAME, strlen(BRIDGE_NAME)); |
| 13 | ret = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_RACFG)); |
| 14 | if (ret < 0) { |
| 15 | perror("socket"); |
| 16 | goto out; |
| 17 | } |
| 18 | an->sock_eth = ret; |
| 19 | |
| 20 | addr.sll_family = AF_PACKET; |
| 21 | addr.sll_ifindex = if_nametoindex(BRIDGE_NAME); |
| 22 | |
| 23 | ret = bind(an->sock_eth, (struct sockaddr *)&addr, sizeof(addr)); |
| 24 | if (ret < 0) { |
| 25 | perror("bind"); |
| 26 | goto out; |
| 27 | } |
| 28 | |
| 29 | ret = ioctl(an->sock_eth, SIOCGIFHWADDR, &ifr); |
| 30 | if (ret < 0) { |
| 31 | perror("ioctl(SIOCGIFHWADDR)"); |
| 32 | goto out; |
| 33 | } |
| 34 | |
| 35 | memcpy(an->mac_addr, ifr.ifr_hwaddr.sa_data, ETH_ALEN); |
| 36 | atenl_info("Open Ethernet socket success on %s, mac addr = " MACSTR "\n", |
| 37 | BRIDGE_NAME, MAC2STR(an->mac_addr)); |
| 38 | |
| 39 | ret = 0; |
| 40 | out: |
| 41 | return ret; |
| 42 | } |
| 43 | |
| 44 | int atenl_eth_recv(struct atenl *an, struct atenl_data *data) |
| 45 | { |
| 46 | char buf[RACFG_PKT_MAX_SIZE]; |
| 47 | int len = recvfrom(an->sock_eth, buf, sizeof(buf), 0, NULL, NULL); |
| 48 | struct ethhdr *hdr = (struct ethhdr *)buf; |
| 49 | |
| 50 | atenl_dbg("[%d]%s: recv len = %d\n", getpid(), __func__, len); |
| 51 | |
| 52 | if (len >= ETH_HLEN + RACFG_HLEN) { |
| 53 | if (hdr->h_proto == htons(ETH_P_RACFG) && |
| 54 | (ether_addr_equal(an->mac_addr, hdr->h_dest) || |
| 55 | is_broadcast_ether_addr(hdr->h_dest))) { |
| 56 | data->len = len; |
| 57 | memcpy(data->buf, buf, len); |
| 58 | |
| 59 | return 0; |
| 60 | } |
| 61 | } |
| 62 | |
| 63 | atenl_err("%s: packet len is too short\n", __func__); |
| 64 | return -EINVAL; |
| 65 | } |
| 66 | |
| 67 | int atenl_eth_send(struct atenl *an, struct atenl_data *data) |
| 68 | { |
| 69 | struct ethhdr *ehdr = (struct ethhdr *)data->buf; |
| 70 | struct sockaddr_ll addr = {}; |
| 71 | int ret, len = data->len; |
| 72 | |
| 73 | if (an->unicast) |
| 74 | ether_addr_copy(ehdr->h_dest, ehdr->h_source); |
| 75 | else |
| 76 | eth_broadcast_addr(ehdr->h_dest); |
| 77 | |
| 78 | ether_addr_copy(ehdr->h_source, an->mac_addr); |
| 79 | ehdr->h_proto = htons(ETH_P_RACFG); |
| 80 | |
| 81 | if (len < 60) |
| 82 | len = 60; |
| 83 | else if (len > 1514) { |
| 84 | atenl_err("%s: response ethernet length is too long\n", __func__); |
| 85 | return -1; |
| 86 | } |
| 87 | |
| 88 | atenl_dbg_print_data(data, __func__, len); |
| 89 | |
| 90 | addr.sll_family = PF_PACKET; |
| 91 | addr.sll_protocol = htons(ETH_P_RACFG); |
| 92 | addr.sll_ifindex = if_nametoindex(BRIDGE_NAME); |
| 93 | addr.sll_pkttype = PACKET_BROADCAST; |
| 94 | addr.sll_hatype = ARPHRD_ETHER; |
| 95 | addr.sll_halen = ETH_ALEN; |
| 96 | memset(addr.sll_addr, 0, 8); |
| 97 | eth_broadcast_addr(addr.sll_addr); |
| 98 | |
| 99 | ret = sendto(an->sock_eth, data->buf, len, 0, |
| 100 | (struct sockaddr *)&addr, sizeof(addr)); |
| 101 | if (ret < 0) { |
| 102 | perror("sendto"); |
| 103 | return ret; |
| 104 | } |
| 105 | |
| 106 | atenl_dbg("[%d]%s: send length = %d\n", getpid(), __func__, len); |
| 107 | |
| 108 | return 0; |
| 109 | } |