2525#include <net/genetlink.h>
2626#include <linux/seg6.h>
2727#include <linux/seg6_genl.h>
28+ #ifdef CONFIG_IPV6_SEG6_HMAC
29+ #include <net/seg6_hmac.h>
30+ #endif
2831
2932bool seg6_validate_srh (struct ipv6_sr_hdr * srh , int len )
3033{
@@ -76,11 +79,90 @@ static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = {
7679 [SEG6_ATTR_HMACINFO ] = { .type = NLA_NESTED , },
7780};
7881
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+
79159static int seg6_genl_sethmac (struct sk_buff * skb , struct genl_info * info )
80160{
81161 return - ENOTSUPP ;
82162}
83163
164+ #endif
165+
84166static int seg6_genl_set_tunsrc (struct sk_buff * skb , struct genl_info * info )
85167{
86168 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)
145227 return - ENOMEM ;
146228}
147229
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+
148352static int seg6_genl_dumphmac (struct sk_buff * skb , struct netlink_callback * cb )
149353{
150354 return - ENOTSUPP ;
151355}
152356
357+ #endif
358+
153359static int __net_init seg6_net_init (struct net * net )
154360{
155361 struct seg6_pernet_data * sdata ;
@@ -168,13 +374,21 @@ static int __net_init seg6_net_init(struct net *net)
168374
169375 net -> ipv6 .seg6_data = sdata ;
170376
377+ #ifdef CONFIG_IPV6_SEG6_HMAC
378+ seg6_hmac_net_init (net );
379+ #endif
380+
171381 return 0 ;
172382}
173383
174384static void __net_exit seg6_net_exit (struct net * net )
175385{
176386 struct seg6_pernet_data * sdata = seg6_pernet (net );
177387
388+ #ifdef CONFIG_IPV6_SEG6_HMAC
389+ seg6_hmac_net_exit (net );
390+ #endif
391+
178392 kfree (sdata -> tun_src );
179393 kfree (sdata );
180394}
@@ -193,7 +407,9 @@ static const struct genl_ops seg6_genl_ops[] = {
193407 },
194408 {
195409 .cmd = SEG6_CMD_DUMPHMAC ,
410+ .start = seg6_genl_dumphmac_start ,
196411 .dumpit = seg6_genl_dumphmac ,
412+ .done = seg6_genl_dumphmac_done ,
197413 .policy = seg6_genl_policy ,
198414 .flags = GENL_ADMIN_PERM ,
199415 },
@@ -239,10 +455,20 @@ int __init seg6_init(void)
239455 if (err )
240456 goto out_unregister_pernet ;
241457
458+ #ifdef CONFIG_IPV6_SEG6_HMAC
459+ err = seg6_hmac_init ();
460+ if (err )
461+ goto out_unregister_iptun ;
462+ #endif
463+
242464 pr_info ("Segment Routing with IPv6\n" );
243465
244466out :
245467 return err ;
468+ #ifdef CONFIG_IPV6_SEG6_HMAC
469+ out_unregister_iptun :
470+ seg6_iptunnel_exit ();
471+ #endif
246472out_unregister_pernet :
247473 unregister_pernet_subsys (& ip6_segments_ops );
248474out_unregister_genl :
@@ -252,6 +478,9 @@ int __init seg6_init(void)
252478
253479void seg6_exit (void )
254480{
481+ #ifdef CONFIG_IPV6_SEG6_HMAC
482+ seg6_hmac_exit ();
483+ #endif
255484 seg6_iptunnel_exit ();
256485 unregister_pernet_subsys (& ip6_segments_ops );
257486 genl_unregister_family (& seg6_genl_family );
0 commit comments