25
25
#include <net/genetlink.h>
26
26
#include <linux/seg6.h>
27
27
#include <linux/seg6_genl.h>
28
+ #ifdef CONFIG_IPV6_SEG6_HMAC
29
+ #include <net/seg6_hmac.h>
30
+ #endif
28
31
29
32
bool seg6_validate_srh (struct ipv6_sr_hdr * srh , int len )
30
33
{
@@ -76,11 +79,90 @@ static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = {
76
79
[SEG6_ATTR_HMACINFO ] = { .type = NLA_NESTED , },
77
80
};
78
81
82
+ #ifdef CONFIG_IPV6_SEG6_HMAC
83
+
84
+ static int seg6_genl_sethmac (struct sk_buff * skb , struct genl_info * info )
85
+ {
86
+ struct net * net = genl_info_net (info );
87
+ struct seg6_pernet_data * sdata ;
88
+ struct seg6_hmac_info * hinfo ;
89
+ u32 hmackeyid ;
90
+ char * secret ;
91
+ int err = 0 ;
92
+ u8 algid ;
93
+ u8 slen ;
94
+
95
+ sdata = seg6_pernet (net );
96
+
97
+ if (!info -> attrs [SEG6_ATTR_HMACKEYID ] ||
98
+ !info -> attrs [SEG6_ATTR_SECRETLEN ] ||
99
+ !info -> attrs [SEG6_ATTR_ALGID ])
100
+ return - EINVAL ;
101
+
102
+ hmackeyid = nla_get_u32 (info -> attrs [SEG6_ATTR_HMACKEYID ]);
103
+ slen = nla_get_u8 (info -> attrs [SEG6_ATTR_SECRETLEN ]);
104
+ algid = nla_get_u8 (info -> attrs [SEG6_ATTR_ALGID ]);
105
+
106
+ if (hmackeyid == 0 )
107
+ return - EINVAL ;
108
+
109
+ if (slen > SEG6_HMAC_SECRET_LEN )
110
+ return - EINVAL ;
111
+
112
+ mutex_lock (& sdata -> lock );
113
+ hinfo = seg6_hmac_info_lookup (net , hmackeyid );
114
+
115
+ if (!slen ) {
116
+ if (!hinfo )
117
+ err = - ENOENT ;
118
+
119
+ err = seg6_hmac_info_del (net , hmackeyid );
120
+
121
+ goto out_unlock ;
122
+ }
123
+
124
+ if (!info -> attrs [SEG6_ATTR_SECRET ]) {
125
+ err = - EINVAL ;
126
+ goto out_unlock ;
127
+ }
128
+
129
+ if (hinfo ) {
130
+ err = seg6_hmac_info_del (net , hmackeyid );
131
+ if (err )
132
+ goto out_unlock ;
133
+ }
134
+
135
+ secret = (char * )nla_data (info -> attrs [SEG6_ATTR_SECRET ]);
136
+
137
+ hinfo = kzalloc (sizeof (* hinfo ), GFP_KERNEL );
138
+ if (!hinfo ) {
139
+ err = - ENOMEM ;
140
+ goto out_unlock ;
141
+ }
142
+
143
+ memcpy (hinfo -> secret , secret , slen );
144
+ hinfo -> slen = slen ;
145
+ hinfo -> alg_id = algid ;
146
+ hinfo -> hmackeyid = hmackeyid ;
147
+
148
+ err = seg6_hmac_info_add (net , hmackeyid , hinfo );
149
+ if (err )
150
+ kfree (hinfo );
151
+
152
+ out_unlock :
153
+ mutex_unlock (& sdata -> lock );
154
+ return err ;
155
+ }
156
+
157
+ #else
158
+
79
159
static int seg6_genl_sethmac (struct sk_buff * skb , struct genl_info * info )
80
160
{
81
161
return - ENOTSUPP ;
82
162
}
83
163
164
+ #endif
165
+
84
166
static int seg6_genl_set_tunsrc (struct sk_buff * skb , struct genl_info * info )
85
167
{
86
168
struct net * net = genl_info_net (info );
@@ -145,11 +227,135 @@ static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
145
227
return - ENOMEM ;
146
228
}
147
229
230
+ #ifdef CONFIG_IPV6_SEG6_HMAC
231
+
232
+ static int __seg6_hmac_fill_info (struct seg6_hmac_info * hinfo ,
233
+ struct sk_buff * msg )
234
+ {
235
+ if (nla_put_u32 (msg , SEG6_ATTR_HMACKEYID , hinfo -> hmackeyid ) ||
236
+ nla_put_u8 (msg , SEG6_ATTR_SECRETLEN , hinfo -> slen ) ||
237
+ nla_put (msg , SEG6_ATTR_SECRET , hinfo -> slen , hinfo -> secret ) ||
238
+ nla_put_u8 (msg , SEG6_ATTR_ALGID , hinfo -> alg_id ))
239
+ return -1 ;
240
+
241
+ return 0 ;
242
+ }
243
+
244
+ static int __seg6_genl_dumphmac_element (struct seg6_hmac_info * hinfo ,
245
+ u32 portid , u32 seq , u32 flags ,
246
+ struct sk_buff * skb , u8 cmd )
247
+ {
248
+ void * hdr ;
249
+
250
+ hdr = genlmsg_put (skb , portid , seq , & seg6_genl_family , flags , cmd );
251
+ if (!hdr )
252
+ return - ENOMEM ;
253
+
254
+ if (__seg6_hmac_fill_info (hinfo , skb ) < 0 )
255
+ goto nla_put_failure ;
256
+
257
+ genlmsg_end (skb , hdr );
258
+ return 0 ;
259
+
260
+ nla_put_failure :
261
+ genlmsg_cancel (skb , hdr );
262
+ return - EMSGSIZE ;
263
+ }
264
+
265
+ static int seg6_genl_dumphmac_start (struct netlink_callback * cb )
266
+ {
267
+ struct net * net = sock_net (cb -> skb -> sk );
268
+ struct seg6_pernet_data * sdata ;
269
+ struct rhashtable_iter * iter ;
270
+
271
+ sdata = seg6_pernet (net );
272
+ iter = (struct rhashtable_iter * )cb -> args [0 ];
273
+
274
+ if (!iter ) {
275
+ iter = kmalloc (sizeof (* iter ), GFP_KERNEL );
276
+ if (!iter )
277
+ return - ENOMEM ;
278
+
279
+ cb -> args [0 ] = (long )iter ;
280
+ }
281
+
282
+ rhashtable_walk_enter (& sdata -> hmac_infos , iter );
283
+
284
+ return 0 ;
285
+ }
286
+
287
+ static int seg6_genl_dumphmac_done (struct netlink_callback * cb )
288
+ {
289
+ struct rhashtable_iter * iter = (struct rhashtable_iter * )cb -> args [0 ];
290
+
291
+ rhashtable_walk_exit (iter );
292
+
293
+ kfree (iter );
294
+
295
+ return 0 ;
296
+ }
297
+
298
+ static int seg6_genl_dumphmac (struct sk_buff * skb , struct netlink_callback * cb )
299
+ {
300
+ struct rhashtable_iter * iter = (struct rhashtable_iter * )cb -> args [0 ];
301
+ struct net * net = sock_net (skb -> sk );
302
+ struct seg6_pernet_data * sdata ;
303
+ struct seg6_hmac_info * hinfo ;
304
+ int ret ;
305
+
306
+ sdata = seg6_pernet (net );
307
+
308
+ ret = rhashtable_walk_start (iter );
309
+ if (ret && ret != - EAGAIN )
310
+ goto done ;
311
+
312
+ for (;;) {
313
+ hinfo = rhashtable_walk_next (iter );
314
+
315
+ if (IS_ERR (hinfo )) {
316
+ if (PTR_ERR (hinfo ) == - EAGAIN )
317
+ continue ;
318
+ ret = PTR_ERR (hinfo );
319
+ goto done ;
320
+ } else if (!hinfo ) {
321
+ break ;
322
+ }
323
+
324
+ ret = __seg6_genl_dumphmac_element (hinfo ,
325
+ NETLINK_CB (cb -> skb ).portid ,
326
+ cb -> nlh -> nlmsg_seq ,
327
+ NLM_F_MULTI ,
328
+ skb , SEG6_CMD_DUMPHMAC );
329
+ if (ret )
330
+ goto done ;
331
+ }
332
+
333
+ ret = skb -> len ;
334
+
335
+ done :
336
+ rhashtable_walk_stop (iter );
337
+ return ret ;
338
+ }
339
+
340
+ #else
341
+
342
+ static int seg6_genl_dumphmac_start (struct netlink_callback * cb )
343
+ {
344
+ return 0 ;
345
+ }
346
+
347
+ static int seg6_genl_dumphmac_done (struct netlink_callback * cb )
348
+ {
349
+ return 0 ;
350
+ }
351
+
148
352
static int seg6_genl_dumphmac (struct sk_buff * skb , struct netlink_callback * cb )
149
353
{
150
354
return - ENOTSUPP ;
151
355
}
152
356
357
+ #endif
358
+
153
359
static int __net_init seg6_net_init (struct net * net )
154
360
{
155
361
struct seg6_pernet_data * sdata ;
@@ -168,13 +374,21 @@ static int __net_init seg6_net_init(struct net *net)
168
374
169
375
net -> ipv6 .seg6_data = sdata ;
170
376
377
+ #ifdef CONFIG_IPV6_SEG6_HMAC
378
+ seg6_hmac_net_init (net );
379
+ #endif
380
+
171
381
return 0 ;
172
382
}
173
383
174
384
static void __net_exit seg6_net_exit (struct net * net )
175
385
{
176
386
struct seg6_pernet_data * sdata = seg6_pernet (net );
177
387
388
+ #ifdef CONFIG_IPV6_SEG6_HMAC
389
+ seg6_hmac_net_exit (net );
390
+ #endif
391
+
178
392
kfree (sdata -> tun_src );
179
393
kfree (sdata );
180
394
}
@@ -193,7 +407,9 @@ static const struct genl_ops seg6_genl_ops[] = {
193
407
},
194
408
{
195
409
.cmd = SEG6_CMD_DUMPHMAC ,
410
+ .start = seg6_genl_dumphmac_start ,
196
411
.dumpit = seg6_genl_dumphmac ,
412
+ .done = seg6_genl_dumphmac_done ,
197
413
.policy = seg6_genl_policy ,
198
414
.flags = GENL_ADMIN_PERM ,
199
415
},
@@ -239,10 +455,20 @@ int __init seg6_init(void)
239
455
if (err )
240
456
goto out_unregister_pernet ;
241
457
458
+ #ifdef CONFIG_IPV6_SEG6_HMAC
459
+ err = seg6_hmac_init ();
460
+ if (err )
461
+ goto out_unregister_iptun ;
462
+ #endif
463
+
242
464
pr_info ("Segment Routing with IPv6\n" );
243
465
244
466
out :
245
467
return err ;
468
+ #ifdef CONFIG_IPV6_SEG6_HMAC
469
+ out_unregister_iptun :
470
+ seg6_iptunnel_exit ();
471
+ #endif
246
472
out_unregister_pernet :
247
473
unregister_pernet_subsys (& ip6_segments_ops );
248
474
out_unregister_genl :
@@ -252,6 +478,9 @@ int __init seg6_init(void)
252
478
253
479
void seg6_exit (void )
254
480
{
481
+ #ifdef CONFIG_IPV6_SEG6_HMAC
482
+ seg6_hmac_exit ();
483
+ #endif
255
484
seg6_iptunnel_exit ();
256
485
unregister_pernet_subsys (& ip6_segments_ops );
257
486
genl_unregister_family (& seg6_genl_family );
0 commit comments