@@ -77,6 +77,7 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
77
77
const int hlen = MCTP_HEADER_MAXLEN + sizeof (struct mctp_hdr );
78
78
int rc , addrlen = msg -> msg_namelen ;
79
79
struct sock * sk = sock -> sk ;
80
+ struct mctp_sock * msk = container_of (sk , struct mctp_sock , sk );
80
81
struct mctp_skb_cb * cb ;
81
82
struct mctp_route * rt ;
82
83
struct sk_buff * skb ;
@@ -100,11 +101,6 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
100
101
if (addr -> smctp_network == MCTP_NET_ANY )
101
102
addr -> smctp_network = mctp_default_net (sock_net (sk ));
102
103
103
- rt = mctp_route_lookup (sock_net (sk ), addr -> smctp_network ,
104
- addr -> smctp_addr .s_addr );
105
- if (!rt )
106
- return - EHOSTUNREACH ;
107
-
108
104
skb = sock_alloc_send_skb (sk , hlen + 1 + len ,
109
105
msg -> msg_flags & MSG_DONTWAIT , & rc );
110
106
if (!skb )
@@ -116,26 +112,53 @@ static int mctp_sendmsg(struct socket *sock, struct msghdr *msg, size_t len)
116
112
* (u8 * )skb_put (skb , 1 ) = addr -> smctp_type ;
117
113
118
114
rc = memcpy_from_msg ((void * )skb_put (skb , len ), msg , len );
119
- if (rc < 0 ) {
120
- kfree_skb (skb );
121
- return rc ;
122
- }
115
+ if (rc < 0 )
116
+ goto err_free ;
123
117
124
118
/* set up cb */
125
119
cb = __mctp_cb (skb );
126
120
cb -> net = addr -> smctp_network ;
127
121
122
+ /* direct addressing */
123
+ if (msk -> addr_ext && addrlen >= sizeof (struct sockaddr_mctp_ext )) {
124
+ DECLARE_SOCKADDR (struct sockaddr_mctp_ext * ,
125
+ extaddr , msg -> msg_name );
126
+
127
+ if (extaddr -> smctp_halen > sizeof (cb -> haddr )) {
128
+ rc = - EINVAL ;
129
+ goto err_free ;
130
+ }
131
+
132
+ cb -> ifindex = extaddr -> smctp_ifindex ;
133
+ cb -> halen = extaddr -> smctp_halen ;
134
+ memcpy (cb -> haddr , extaddr -> smctp_haddr , cb -> halen );
135
+
136
+ rt = NULL ;
137
+ } else {
138
+ rt = mctp_route_lookup (sock_net (sk ), addr -> smctp_network ,
139
+ addr -> smctp_addr .s_addr );
140
+ if (!rt ) {
141
+ rc = - EHOSTUNREACH ;
142
+ goto err_free ;
143
+ }
144
+ }
145
+
128
146
rc = mctp_local_output (sk , rt , skb , addr -> smctp_addr .s_addr ,
129
147
addr -> smctp_tag );
130
148
131
149
return rc ? : len ;
150
+
151
+ err_free :
152
+ kfree_skb (skb );
153
+ return rc ;
132
154
}
133
155
134
156
static int mctp_recvmsg (struct socket * sock , struct msghdr * msg , size_t len ,
135
157
int flags )
136
158
{
137
159
DECLARE_SOCKADDR (struct sockaddr_mctp * , addr , msg -> msg_name );
138
160
struct sock * sk = sock -> sk ;
161
+ struct mctp_sock * msk = container_of (sk , struct mctp_sock , sk );
139
162
struct sk_buff * skb ;
140
163
size_t msglen ;
141
164
u8 type ;
@@ -181,6 +204,16 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
181
204
addr -> smctp_tag = hdr -> flags_seq_tag &
182
205
(MCTP_HDR_TAG_MASK | MCTP_HDR_FLAG_TO );
183
206
msg -> msg_namelen = sizeof (* addr );
207
+
208
+ if (msk -> addr_ext ) {
209
+ DECLARE_SOCKADDR (struct sockaddr_mctp_ext * , ae ,
210
+ msg -> msg_name );
211
+ msg -> msg_namelen = sizeof (* ae );
212
+ ae -> smctp_ifindex = cb -> ifindex ;
213
+ ae -> smctp_halen = cb -> halen ;
214
+ memset (ae -> smctp_haddr , 0x0 , sizeof (ae -> smctp_haddr ));
215
+ memcpy (ae -> smctp_haddr , cb -> haddr , cb -> halen );
216
+ }
184
217
}
185
218
186
219
rc = len ;
@@ -196,12 +229,45 @@ static int mctp_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
196
229
static int mctp_setsockopt (struct socket * sock , int level , int optname ,
197
230
sockptr_t optval , unsigned int optlen )
198
231
{
199
- return - EINVAL ;
232
+ struct mctp_sock * msk = container_of (sock -> sk , struct mctp_sock , sk );
233
+ int val ;
234
+
235
+ if (level != SOL_MCTP )
236
+ return - EINVAL ;
237
+
238
+ if (optname == MCTP_OPT_ADDR_EXT ) {
239
+ if (optlen != sizeof (int ))
240
+ return - EINVAL ;
241
+ if (copy_from_sockptr (& val , optval , sizeof (int )))
242
+ return - EFAULT ;
243
+ msk -> addr_ext = val ;
244
+ return 0 ;
245
+ }
246
+
247
+ return - ENOPROTOOPT ;
200
248
}
201
249
202
250
static int mctp_getsockopt (struct socket * sock , int level , int optname ,
203
251
char __user * optval , int __user * optlen )
204
252
{
253
+ struct mctp_sock * msk = container_of (sock -> sk , struct mctp_sock , sk );
254
+ int len , val ;
255
+
256
+ if (level != SOL_MCTP )
257
+ return - EINVAL ;
258
+
259
+ if (get_user (len , optlen ))
260
+ return - EFAULT ;
261
+
262
+ if (optname == MCTP_OPT_ADDR_EXT ) {
263
+ if (len != sizeof (int ))
264
+ return - EINVAL ;
265
+ val = !!msk -> addr_ext ;
266
+ if (copy_to_user (optval , & val , len ))
267
+ return - EFAULT ;
268
+ return 0 ;
269
+ }
270
+
205
271
return - EINVAL ;
206
272
}
207
273
0 commit comments