-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathavb_util.c
executable file
·162 lines (144 loc) · 4.12 KB
/
avb_util.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "avb_util.h"
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,10,0)
#include <net/sock.h>
#endif
void avb_log(int level, char *fmt, ...)
{
va_list args;
va_start(args, fmt);
switch (level) {
case AVB_KERN_EMERG:
vprintk(fmt, args);
break;
case AVB_KERN_ALERT:
vprintk(fmt, args);
break;
case AVB_KERN_CRIT:
vprintk(fmt, args);
break;
case AVB_KERN_ERR:
vprintk(fmt, args);
break;
case AVB_KERN_WARN:
vprintk(fmt, args);
break;
case AVB_KERN_NOT:
vprintk(fmt, args);
break;
#ifdef AVB_DEBUG
case AVB_KERN_INFO:
vprintk(fmt, args);
break;
case AVB_KERN_DEBUG:
vprintk(fmt, args);
break;
#else
default:
break;
#endif
}
va_end(args);
}
bool avb_socket_init(const char *ifname, struct socketdata *sd, int rx_timeout)
{
int err = 0;
struct net_device *dev = NULL;
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
struct timeval ts_opts;
#else
struct __kernel_old_timeval ts_opts;
#endif
ts_opts.tv_sec = (rx_timeout / 1000);
ts_opts.tv_usec = (rx_timeout % 1000);
avb_log(AVB_KERN_INFO, KERN_INFO "avb_socket_init");
dev = dev_get_by_name_rcu(&init_net, ifname);
if (!dev) {
avb_log(AVB_KERN_ERR,
KERN_ERR "avb_socket_init device %s not found\n", ifname);
return false;
}
if ((err = sock_create_kern(&init_net, AF_PACKET, SOCK_RAW,
htons(sd->type), &sd->sock)) != 0) {
avb_log(AVB_KERN_ERR,
KERN_ERR "avb_socket_init Socket creation fails %d \n",
err);
return false;
}
memcpy(&sd->srcmac[0], dev->dev_addr, 6);
sd->if_idx = dev->ifindex;
rtnl_lock();
dev_set_promiscuity(dev, 1);
rtnl_unlock();
if ((err =
#if LINUX_VERSION_CODE < KERNEL_VERSION(5,10,0)
kernel_setsockopt(
sd->sock, SOL_SOCKET,
#if LINUX_VERSION_CODE >= KERNEL_VERSION(5,1,0)
SO_RCVTIMEO_OLD,
#else
SO_RCVTIMEO,
#endif
(void *)&ts_opts, sizeof(ts_opts))) != 0) {
#else
sock_setsockopt(
sd->sock, SOL_SOCKET, SO_RCVTIMEO_OLD,
KERNEL_SOCKPTR(&ts_opts), sizeof(ts_opts))) != 0) {
#endif
avb_log(AVB_KERN_WARN,
KERN_WARNING "avb_msrp_init set rx timeout fails with error %d\n",
err);
return false;
}
/* Index of the network device */
sd->tx_sock_address.sll_family = AF_PACKET;
sd->tx_sock_address.sll_protocol = htons(sd->type);
sd->tx_sock_address.sll_ifindex = sd->if_idx;
/* Address length*/
sd->tx_sock_address.sll_halen = ETH_ALEN;
/* Destination MAC */
sd->tx_sock_address.sll_addr[0] = sd->destmac[0];
sd->tx_sock_address.sll_addr[1] = sd->destmac[1];
sd->tx_sock_address.sll_addr[2] = sd->destmac[2];
sd->tx_sock_address.sll_addr[3] = sd->destmac[3];
sd->tx_sock_address.sll_addr[4] = sd->destmac[4];
sd->tx_sock_address.sll_addr[5] = sd->destmac[5];
/* Set the message header */
sd->tx_msg_hdr.msg_control = NULL;
sd->tx_msg_hdr.msg_controllen = 0;
sd->tx_msg_hdr.msg_flags = 0;
sd->tx_msg_hdr.msg_name = &sd->tx_sock_address;
sd->tx_msg_hdr.msg_namelen = sizeof(struct sockaddr_ll);
sd->tx_msg_hdr.msg_iocb = NULL;
/* Index of the network device */
sd->rx_sock_address.sll_family = AF_PACKET;
sd->rx_sock_address.sll_protocol = htons(sd->type);
sd->rx_sock_address.sll_ifindex = sd->if_idx;
/* Address length*/
sd->rx_sock_address.sll_halen = ETH_ALEN;
/* Destination MAC */
sd->rx_sock_address.sll_addr[0] = sd->destmac[0];
sd->rx_sock_address.sll_addr[1] = sd->destmac[1];
sd->rx_sock_address.sll_addr[2] = sd->destmac[2];
sd->rx_sock_address.sll_addr[3] = sd->destmac[3];
sd->rx_sock_address.sll_addr[4] = sd->destmac[4];
sd->rx_sock_address.sll_addr[5] = sd->destmac[5];
/* Set the message header */
sd->rx_msg_hdr.msg_control = NULL;
sd->rx_msg_hdr.msg_controllen = 0;
sd->rx_msg_hdr.msg_flags = 0;
sd->rx_msg_hdr.msg_name = &sd->rx_sock_address;
sd->rx_msg_hdr.msg_namelen = sizeof(struct sockaddr_ll);
sd->rx_msg_hdr.msg_iocb = NULL;
sd->rx_iov.iov_base = sd->rx_buf;
sd->rx_iov.iov_len = AVB_MAX_ETH_FRAME_SIZE;
iov_iter_init(&sd->rx_msg_hdr.msg_iter, READ, &sd->rx_iov, 1,
AVB_MAX_ETH_FRAME_SIZE);
if ((err = kernel_bind(sd->sock,
(struct sockaddr *)&sd->rx_sock_address,
sizeof(sd->rx_sock_address))) != 0) {
avb_log(AVB_KERN_WARN,
KERN_WARNING "avb socket binding fails %d\n", err);
return false;
}
return true;
}