blob: cd32f71a24fc7460b0b93c707c6a87505a754955 [file] [log] [blame]
developer3abe1ad2022-01-24 11:13:32 +08001#include <sys/ioctl.h>
2#include <sys/socket.h>
3
4#include "atenl.h"
5
6int atenl_eth_init(struct atenl *an)
7{
8 struct sockaddr_ll addr = {};
9 struct ifreq ifr = {};
10 int ret;
11
developer22227f42022-10-07 15:54:07 +080012 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));
developer3abe1ad2022-01-24 11:13:32 +080018 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;
developer22227f42022-10-07 15:54:07 +080026 addr.sll_ifindex = if_nametoindex(an->bridge_name);
developer3abe1ad2022-01-24 11:13:32 +080027
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",
developer22227f42022-10-07 15:54:07 +080042 an->bridge_name, MAC2STR(an->mac_addr));
developer3abe1ad2022-01-24 11:13:32 +080043
44 ret = 0;
45out:
46 return ret;
47}
48
49int atenl_eth_recv(struct atenl *an, struct atenl_data *data)
50{
developer5698c9c2022-05-30 16:40:23 +080051 struct ethhdr *hdr;
52 int len;
developer3abe1ad2022-01-24 11:13:32 +080053
developer5698c9c2022-05-30 16:40:23 +080054 len = recvfrom(an->sock_eth, data->buf, sizeof(data->buf), 0, NULL, NULL);
developer3abe1ad2022-01-24 11:13:32 +080055
developer5698c9c2022-05-30 16:40:23 +080056 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 }
developer3abe1ad2022-01-24 11:13:32 +080066
developer5698c9c2022-05-30 16:40:23 +080067 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;
developer3abe1ad2022-01-24 11:13:32 +080071 }
72
developer5698c9c2022-05-30 16:40:23 +080073 data->len = len;
74
75 return 0;
developer3abe1ad2022-01-24 11:13:32 +080076}
77
78int 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) {
developer5698c9c2022-05-30 16:40:23 +080095 atenl_err("response ethernet length is too long\n");
developer3abe1ad2022-01-24 11:13:32 +080096 return -1;
97 }
98
developer5698c9c2022-05-30 16:40:23 +080099 atenl_dbg_print_data(data->buf, __func__, len);
developer3abe1ad2022-01-24 11:13:32 +0800100
101 addr.sll_family = PF_PACKET;
102 addr.sll_protocol = htons(ETH_P_RACFG);
developer22227f42022-10-07 15:54:07 +0800103 addr.sll_ifindex = if_nametoindex(an->bridge_name);
developer3abe1ad2022-01-24 11:13:32 +0800104 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
developer3abe1ad2022-01-24 11:13:32 +0800117 return 0;
118}