1 // SPDX-License-Identifier: GPL-2.0-or-later 1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 2 /* 3 * SR-IPv6 implementation 3 * SR-IPv6 implementation 4 * 4 * 5 * Author: 5 * Author: 6 * David Lebrun <david.lebrun@uclouvain.be> 6 * David Lebrun <david.lebrun@uclouvain.be> 7 */ 7 */ 8 8 9 #include <linux/errno.h> 9 #include <linux/errno.h> 10 #include <linux/types.h> 10 #include <linux/types.h> 11 #include <linux/socket.h> 11 #include <linux/socket.h> 12 #include <linux/net.h> 12 #include <linux/net.h> 13 #include <linux/in6.h> 13 #include <linux/in6.h> 14 #include <linux/slab.h> 14 #include <linux/slab.h> 15 #include <linux/rhashtable.h> 15 #include <linux/rhashtable.h> 16 16 17 #include <net/ipv6.h> 17 #include <net/ipv6.h> 18 #include <net/protocol.h> 18 #include <net/protocol.h> 19 19 20 #include <net/seg6.h> 20 #include <net/seg6.h> 21 #include <net/genetlink.h> 21 #include <net/genetlink.h> 22 #include <linux/seg6.h> 22 #include <linux/seg6.h> 23 #include <linux/seg6_genl.h> 23 #include <linux/seg6_genl.h> >> 24 #ifdef CONFIG_IPV6_SEG6_HMAC 24 #include <net/seg6_hmac.h> 25 #include <net/seg6_hmac.h> >> 26 #endif 25 27 26 bool seg6_validate_srh(struct ipv6_sr_hdr *srh !! 28 bool seg6_validate_srh(struct ipv6_sr_hdr *srh, int len) 27 { 29 { 28 unsigned int tlv_offset; << 29 int max_last_entry; << 30 int trailing; 30 int trailing; >> 31 unsigned int tlv_offset; 31 32 32 if (srh->type != IPV6_SRCRT_TYPE_4) 33 if (srh->type != IPV6_SRCRT_TYPE_4) 33 return false; 34 return false; 34 35 35 if (((srh->hdrlen + 1) << 3) != len) 36 if (((srh->hdrlen + 1) << 3) != len) 36 return false; 37 return false; 37 38 38 if (!reduced && srh->segments_left > s !! 39 if (srh->segments_left > srh->first_segment) 39 return false; 40 return false; 40 } else { << 41 max_last_entry = (srh->hdrlen << 42 << 43 if (srh->first_segment > max_l << 44 return false; << 45 << 46 if (srh->segments_left > srh-> << 47 return false; << 48 } << 49 41 50 tlv_offset = sizeof(*srh) + ((srh->fir 42 tlv_offset = sizeof(*srh) + ((srh->first_segment + 1) << 4); 51 43 52 trailing = len - tlv_offset; 44 trailing = len - tlv_offset; 53 if (trailing < 0) 45 if (trailing < 0) 54 return false; 46 return false; 55 47 56 while (trailing) { 48 while (trailing) { 57 struct sr6_tlv *tlv; 49 struct sr6_tlv *tlv; 58 unsigned int tlv_len; 50 unsigned int tlv_len; 59 51 60 if (trailing < sizeof(*tlv)) 52 if (trailing < sizeof(*tlv)) 61 return false; 53 return false; 62 54 63 tlv = (struct sr6_tlv *)((unsi 55 tlv = (struct sr6_tlv *)((unsigned char *)srh + tlv_offset); 64 tlv_len = sizeof(*tlv) + tlv-> 56 tlv_len = sizeof(*tlv) + tlv->len; 65 57 66 trailing -= tlv_len; 58 trailing -= tlv_len; 67 if (trailing < 0) 59 if (trailing < 0) 68 return false; 60 return false; 69 61 70 tlv_offset += tlv_len; 62 tlv_offset += tlv_len; 71 } 63 } 72 64 73 return true; 65 return true; 74 } 66 } 75 67 76 struct ipv6_sr_hdr *seg6_get_srh(struct sk_buf << 77 { << 78 struct ipv6_sr_hdr *srh; << 79 int len, srhoff = 0; << 80 << 81 if (ipv6_find_hdr(skb, &srhoff, IPPROT << 82 return NULL; << 83 << 84 if (!pskb_may_pull(skb, srhoff + sizeo << 85 return NULL; << 86 << 87 srh = (struct ipv6_sr_hdr *)(skb->data << 88 << 89 len = (srh->hdrlen + 1) << 3; << 90 << 91 if (!pskb_may_pull(skb, srhoff + len)) << 92 return NULL; << 93 << 94 /* note that pskb_may_pull may change << 95 * for this reason it is necessary to << 96 */ << 97 srh = (struct ipv6_sr_hdr *)(skb->data << 98 << 99 if (!seg6_validate_srh(srh, len, true) << 100 return NULL; << 101 << 102 return srh; << 103 } << 104 << 105 /* Determine if an ICMP invoking packet contai << 106 * header. If it does, extract the offset to << 107 * address, which is in the first segment addr << 108 */ << 109 void seg6_icmp_srh(struct sk_buff *skb, struct << 110 { << 111 __u16 network_header = skb->network_he << 112 struct ipv6_sr_hdr *srh; << 113 << 114 /* Update network header to point to t << 115 * inside the ICMP packet, so we can u << 116 * helper. << 117 */ << 118 skb_reset_network_header(skb); << 119 << 120 srh = seg6_get_srh(skb, 0); << 121 if (!srh) << 122 goto out; << 123 << 124 if (srh->type != IPV6_SRCRT_TYPE_4) << 125 goto out; << 126 << 127 opt->flags |= IP6SKB_SEG6; << 128 opt->srhoff = (unsigned char *)srh - s << 129 << 130 out: << 131 /* Restore the network header back to << 132 skb->network_header = network_header; << 133 } << 134 << 135 static struct genl_family seg6_genl_family; 68 static struct genl_family seg6_genl_family; 136 69 137 static const struct nla_policy seg6_genl_polic 70 static const struct nla_policy seg6_genl_policy[SEG6_ATTR_MAX + 1] = { 138 [SEG6_ATTR_DST] 71 [SEG6_ATTR_DST] = { .type = NLA_BINARY, 139 .len = sizeof(struct in6_addr) 72 .len = sizeof(struct in6_addr) }, 140 [SEG6_ATTR_DSTLEN] 73 [SEG6_ATTR_DSTLEN] = { .type = NLA_S32, }, 141 [SEG6_ATTR_HMACKEYID] = { .t 74 [SEG6_ATTR_HMACKEYID] = { .type = NLA_U32, }, 142 [SEG6_ATTR_SECRET] 75 [SEG6_ATTR_SECRET] = { .type = NLA_BINARY, }, 143 [SEG6_ATTR_SECRETLEN] = { .t 76 [SEG6_ATTR_SECRETLEN] = { .type = NLA_U8, }, 144 [SEG6_ATTR_ALGID] 77 [SEG6_ATTR_ALGID] = { .type = NLA_U8, }, 145 [SEG6_ATTR_HMACINFO] = { .t 78 [SEG6_ATTR_HMACINFO] = { .type = NLA_NESTED, }, 146 }; 79 }; 147 80 148 #ifdef CONFIG_IPV6_SEG6_HMAC 81 #ifdef CONFIG_IPV6_SEG6_HMAC 149 82 150 static int seg6_genl_sethmac(struct sk_buff *s 83 static int seg6_genl_sethmac(struct sk_buff *skb, struct genl_info *info) 151 { 84 { 152 struct net *net = genl_info_net(info); 85 struct net *net = genl_info_net(info); 153 struct seg6_pernet_data *sdata; 86 struct seg6_pernet_data *sdata; 154 struct seg6_hmac_info *hinfo; 87 struct seg6_hmac_info *hinfo; 155 u32 hmackeyid; 88 u32 hmackeyid; 156 char *secret; 89 char *secret; 157 int err = 0; 90 int err = 0; 158 u8 algid; 91 u8 algid; 159 u8 slen; 92 u8 slen; 160 93 161 sdata = seg6_pernet(net); 94 sdata = seg6_pernet(net); 162 95 163 if (!info->attrs[SEG6_ATTR_HMACKEYID] 96 if (!info->attrs[SEG6_ATTR_HMACKEYID] || 164 !info->attrs[SEG6_ATTR_SECRETLEN] 97 !info->attrs[SEG6_ATTR_SECRETLEN] || 165 !info->attrs[SEG6_ATTR_ALGID]) 98 !info->attrs[SEG6_ATTR_ALGID]) 166 return -EINVAL; 99 return -EINVAL; 167 100 168 hmackeyid = nla_get_u32(info->attrs[SE 101 hmackeyid = nla_get_u32(info->attrs[SEG6_ATTR_HMACKEYID]); 169 slen = nla_get_u8(info->attrs[SEG6_ATT 102 slen = nla_get_u8(info->attrs[SEG6_ATTR_SECRETLEN]); 170 algid = nla_get_u8(info->attrs[SEG6_AT 103 algid = nla_get_u8(info->attrs[SEG6_ATTR_ALGID]); 171 104 172 if (hmackeyid == 0) 105 if (hmackeyid == 0) 173 return -EINVAL; 106 return -EINVAL; 174 107 175 if (slen > SEG6_HMAC_SECRET_LEN) 108 if (slen > SEG6_HMAC_SECRET_LEN) 176 return -EINVAL; 109 return -EINVAL; 177 110 178 mutex_lock(&sdata->lock); 111 mutex_lock(&sdata->lock); 179 hinfo = seg6_hmac_info_lookup(net, hma 112 hinfo = seg6_hmac_info_lookup(net, hmackeyid); 180 113 181 if (!slen) { 114 if (!slen) { >> 115 if (!hinfo) >> 116 err = -ENOENT; >> 117 182 err = seg6_hmac_info_del(net, 118 err = seg6_hmac_info_del(net, hmackeyid); 183 119 184 goto out_unlock; 120 goto out_unlock; 185 } 121 } 186 122 187 if (!info->attrs[SEG6_ATTR_SECRET]) { 123 if (!info->attrs[SEG6_ATTR_SECRET]) { 188 err = -EINVAL; 124 err = -EINVAL; 189 goto out_unlock; 125 goto out_unlock; 190 } 126 } 191 127 192 if (slen > nla_len(info->attrs[SEG6_AT << 193 err = -EINVAL; << 194 goto out_unlock; << 195 } << 196 << 197 if (hinfo) { 128 if (hinfo) { 198 err = seg6_hmac_info_del(net, 129 err = seg6_hmac_info_del(net, hmackeyid); 199 if (err) 130 if (err) 200 goto out_unlock; 131 goto out_unlock; 201 } 132 } 202 133 203 secret = (char *)nla_data(info->attrs[ 134 secret = (char *)nla_data(info->attrs[SEG6_ATTR_SECRET]); 204 135 205 hinfo = kzalloc(sizeof(*hinfo), GFP_KE 136 hinfo = kzalloc(sizeof(*hinfo), GFP_KERNEL); 206 if (!hinfo) { 137 if (!hinfo) { 207 err = -ENOMEM; 138 err = -ENOMEM; 208 goto out_unlock; 139 goto out_unlock; 209 } 140 } 210 141 211 memcpy(hinfo->secret, secret, slen); 142 memcpy(hinfo->secret, secret, slen); 212 hinfo->slen = slen; 143 hinfo->slen = slen; 213 hinfo->alg_id = algid; 144 hinfo->alg_id = algid; 214 hinfo->hmackeyid = hmackeyid; 145 hinfo->hmackeyid = hmackeyid; 215 146 216 err = seg6_hmac_info_add(net, hmackeyi 147 err = seg6_hmac_info_add(net, hmackeyid, hinfo); 217 if (err) 148 if (err) 218 kfree(hinfo); 149 kfree(hinfo); 219 150 220 out_unlock: 151 out_unlock: 221 mutex_unlock(&sdata->lock); 152 mutex_unlock(&sdata->lock); 222 return err; 153 return err; 223 } 154 } 224 155 225 #else 156 #else 226 157 227 static int seg6_genl_sethmac(struct sk_buff *s 158 static int seg6_genl_sethmac(struct sk_buff *skb, struct genl_info *info) 228 { 159 { 229 return -ENOTSUPP; 160 return -ENOTSUPP; 230 } 161 } 231 162 232 #endif 163 #endif 233 164 234 static int seg6_genl_set_tunsrc(struct sk_buff 165 static int seg6_genl_set_tunsrc(struct sk_buff *skb, struct genl_info *info) 235 { 166 { 236 struct net *net = genl_info_net(info); 167 struct net *net = genl_info_net(info); 237 struct in6_addr *val, *t_old, *t_new; 168 struct in6_addr *val, *t_old, *t_new; 238 struct seg6_pernet_data *sdata; 169 struct seg6_pernet_data *sdata; 239 170 240 sdata = seg6_pernet(net); 171 sdata = seg6_pernet(net); 241 172 242 if (!info->attrs[SEG6_ATTR_DST]) 173 if (!info->attrs[SEG6_ATTR_DST]) 243 return -EINVAL; 174 return -EINVAL; 244 175 245 val = nla_data(info->attrs[SEG6_ATTR_D 176 val = nla_data(info->attrs[SEG6_ATTR_DST]); 246 t_new = kmemdup(val, sizeof(*val), GFP 177 t_new = kmemdup(val, sizeof(*val), GFP_KERNEL); 247 if (!t_new) 178 if (!t_new) 248 return -ENOMEM; 179 return -ENOMEM; 249 180 250 mutex_lock(&sdata->lock); 181 mutex_lock(&sdata->lock); 251 182 252 t_old = sdata->tun_src; 183 t_old = sdata->tun_src; 253 rcu_assign_pointer(sdata->tun_src, t_n 184 rcu_assign_pointer(sdata->tun_src, t_new); 254 185 255 mutex_unlock(&sdata->lock); 186 mutex_unlock(&sdata->lock); 256 187 257 synchronize_net(); 188 synchronize_net(); 258 kfree(t_old); 189 kfree(t_old); 259 190 260 return 0; 191 return 0; 261 } 192 } 262 193 263 static int seg6_genl_get_tunsrc(struct sk_buff 194 static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info) 264 { 195 { 265 struct net *net = genl_info_net(info); 196 struct net *net = genl_info_net(info); 266 struct in6_addr *tun_src; 197 struct in6_addr *tun_src; 267 struct sk_buff *msg; 198 struct sk_buff *msg; 268 void *hdr; 199 void *hdr; 269 200 270 msg = genlmsg_new(NLMSG_DEFAULT_SIZE, 201 msg = genlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); 271 if (!msg) 202 if (!msg) 272 return -ENOMEM; 203 return -ENOMEM; 273 204 274 hdr = genlmsg_put(msg, info->snd_porti 205 hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq, 275 &seg6_genl_family, 0 206 &seg6_genl_family, 0, SEG6_CMD_GET_TUNSRC); 276 if (!hdr) 207 if (!hdr) 277 goto free_msg; 208 goto free_msg; 278 209 279 rcu_read_lock(); 210 rcu_read_lock(); 280 tun_src = rcu_dereference(seg6_pernet( 211 tun_src = rcu_dereference(seg6_pernet(net)->tun_src); 281 212 282 if (nla_put(msg, SEG6_ATTR_DST, sizeof 213 if (nla_put(msg, SEG6_ATTR_DST, sizeof(struct in6_addr), tun_src)) 283 goto nla_put_failure; 214 goto nla_put_failure; 284 215 285 rcu_read_unlock(); 216 rcu_read_unlock(); 286 217 287 genlmsg_end(msg, hdr); 218 genlmsg_end(msg, hdr); 288 return genlmsg_reply(msg, info); 219 return genlmsg_reply(msg, info); 289 220 290 nla_put_failure: 221 nla_put_failure: 291 rcu_read_unlock(); 222 rcu_read_unlock(); 292 free_msg: 223 free_msg: 293 nlmsg_free(msg); 224 nlmsg_free(msg); 294 return -ENOMEM; 225 return -ENOMEM; 295 } 226 } 296 227 297 #ifdef CONFIG_IPV6_SEG6_HMAC 228 #ifdef CONFIG_IPV6_SEG6_HMAC 298 229 299 static int __seg6_hmac_fill_info(struct seg6_h 230 static int __seg6_hmac_fill_info(struct seg6_hmac_info *hinfo, 300 struct sk_buf 231 struct sk_buff *msg) 301 { 232 { 302 if (nla_put_u32(msg, SEG6_ATTR_HMACKEY 233 if (nla_put_u32(msg, SEG6_ATTR_HMACKEYID, hinfo->hmackeyid) || 303 nla_put_u8(msg, SEG6_ATTR_SECRETLE 234 nla_put_u8(msg, SEG6_ATTR_SECRETLEN, hinfo->slen) || 304 nla_put(msg, SEG6_ATTR_SECRET, hin 235 nla_put(msg, SEG6_ATTR_SECRET, hinfo->slen, hinfo->secret) || 305 nla_put_u8(msg, SEG6_ATTR_ALGID, h 236 nla_put_u8(msg, SEG6_ATTR_ALGID, hinfo->alg_id)) 306 return -1; 237 return -1; 307 238 308 return 0; 239 return 0; 309 } 240 } 310 241 311 static int __seg6_genl_dumphmac_element(struct 242 static int __seg6_genl_dumphmac_element(struct seg6_hmac_info *hinfo, 312 u32 po 243 u32 portid, u32 seq, u32 flags, 313 struct 244 struct sk_buff *skb, u8 cmd) 314 { 245 { 315 void *hdr; 246 void *hdr; 316 247 317 hdr = genlmsg_put(skb, portid, seq, &s 248 hdr = genlmsg_put(skb, portid, seq, &seg6_genl_family, flags, cmd); 318 if (!hdr) 249 if (!hdr) 319 return -ENOMEM; 250 return -ENOMEM; 320 251 321 if (__seg6_hmac_fill_info(hinfo, skb) 252 if (__seg6_hmac_fill_info(hinfo, skb) < 0) 322 goto nla_put_failure; 253 goto nla_put_failure; 323 254 324 genlmsg_end(skb, hdr); 255 genlmsg_end(skb, hdr); 325 return 0; 256 return 0; 326 257 327 nla_put_failure: 258 nla_put_failure: 328 genlmsg_cancel(skb, hdr); 259 genlmsg_cancel(skb, hdr); 329 return -EMSGSIZE; 260 return -EMSGSIZE; 330 } 261 } 331 262 332 static int seg6_genl_dumphmac_start(struct net 263 static int seg6_genl_dumphmac_start(struct netlink_callback *cb) 333 { 264 { 334 struct net *net = sock_net(cb->skb->sk 265 struct net *net = sock_net(cb->skb->sk); 335 struct seg6_pernet_data *sdata; 266 struct seg6_pernet_data *sdata; 336 struct rhashtable_iter *iter; 267 struct rhashtable_iter *iter; 337 268 338 sdata = seg6_pernet(net); 269 sdata = seg6_pernet(net); 339 iter = (struct rhashtable_iter *)cb->a 270 iter = (struct rhashtable_iter *)cb->args[0]; 340 271 341 if (!iter) { 272 if (!iter) { 342 iter = kmalloc(sizeof(*iter), 273 iter = kmalloc(sizeof(*iter), GFP_KERNEL); 343 if (!iter) 274 if (!iter) 344 return -ENOMEM; 275 return -ENOMEM; 345 276 346 cb->args[0] = (long)iter; 277 cb->args[0] = (long)iter; 347 } 278 } 348 279 349 rhashtable_walk_enter(&sdata->hmac_inf 280 rhashtable_walk_enter(&sdata->hmac_infos, iter); 350 281 351 return 0; 282 return 0; 352 } 283 } 353 284 354 static int seg6_genl_dumphmac_done(struct netl 285 static int seg6_genl_dumphmac_done(struct netlink_callback *cb) 355 { 286 { 356 struct rhashtable_iter *iter = (struct 287 struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0]; 357 288 358 rhashtable_walk_exit(iter); 289 rhashtable_walk_exit(iter); 359 290 360 kfree(iter); 291 kfree(iter); 361 292 362 return 0; 293 return 0; 363 } 294 } 364 295 365 static int seg6_genl_dumphmac(struct sk_buff * 296 static int seg6_genl_dumphmac(struct sk_buff *skb, struct netlink_callback *cb) 366 { 297 { 367 struct rhashtable_iter *iter = (struct 298 struct rhashtable_iter *iter = (struct rhashtable_iter *)cb->args[0]; 368 struct seg6_hmac_info *hinfo; 299 struct seg6_hmac_info *hinfo; 369 int ret; 300 int ret; 370 301 371 rhashtable_walk_start(iter); 302 rhashtable_walk_start(iter); 372 303 373 for (;;) { 304 for (;;) { 374 hinfo = rhashtable_walk_next(i 305 hinfo = rhashtable_walk_next(iter); 375 306 376 if (IS_ERR(hinfo)) { 307 if (IS_ERR(hinfo)) { 377 if (PTR_ERR(hinfo) == 308 if (PTR_ERR(hinfo) == -EAGAIN) 378 continue; 309 continue; 379 ret = PTR_ERR(hinfo); 310 ret = PTR_ERR(hinfo); 380 goto done; 311 goto done; 381 } else if (!hinfo) { 312 } else if (!hinfo) { 382 break; 313 break; 383 } 314 } 384 315 385 ret = __seg6_genl_dumphmac_ele 316 ret = __seg6_genl_dumphmac_element(hinfo, 386 317 NETLINK_CB(cb->skb).portid, 387 318 cb->nlh->nlmsg_seq, 388 319 NLM_F_MULTI, 389 320 skb, SEG6_CMD_DUMPHMAC); 390 if (ret) 321 if (ret) 391 goto done; 322 goto done; 392 } 323 } 393 324 394 ret = skb->len; 325 ret = skb->len; 395 326 396 done: 327 done: 397 rhashtable_walk_stop(iter); 328 rhashtable_walk_stop(iter); 398 return ret; 329 return ret; 399 } 330 } 400 331 401 #else 332 #else 402 333 403 static int seg6_genl_dumphmac_start(struct net 334 static int seg6_genl_dumphmac_start(struct netlink_callback *cb) 404 { 335 { 405 return 0; 336 return 0; 406 } 337 } 407 338 408 static int seg6_genl_dumphmac_done(struct netl 339 static int seg6_genl_dumphmac_done(struct netlink_callback *cb) 409 { 340 { 410 return 0; 341 return 0; 411 } 342 } 412 343 413 static int seg6_genl_dumphmac(struct sk_buff * 344 static int seg6_genl_dumphmac(struct sk_buff *skb, struct netlink_callback *cb) 414 { 345 { 415 return -ENOTSUPP; 346 return -ENOTSUPP; 416 } 347 } 417 348 418 #endif 349 #endif 419 350 420 static int __net_init seg6_net_init(struct net 351 static int __net_init seg6_net_init(struct net *net) 421 { 352 { 422 struct seg6_pernet_data *sdata; 353 struct seg6_pernet_data *sdata; 423 354 424 sdata = kzalloc(sizeof(*sdata), GFP_KE 355 sdata = kzalloc(sizeof(*sdata), GFP_KERNEL); 425 if (!sdata) 356 if (!sdata) 426 return -ENOMEM; 357 return -ENOMEM; 427 358 428 mutex_init(&sdata->lock); 359 mutex_init(&sdata->lock); 429 360 430 sdata->tun_src = kzalloc(sizeof(*sdata 361 sdata->tun_src = kzalloc(sizeof(*sdata->tun_src), GFP_KERNEL); 431 if (!sdata->tun_src) { 362 if (!sdata->tun_src) { 432 kfree(sdata); 363 kfree(sdata); 433 return -ENOMEM; 364 return -ENOMEM; 434 } 365 } 435 366 436 net->ipv6.seg6_data = sdata; 367 net->ipv6.seg6_data = sdata; 437 368 438 if (seg6_hmac_net_init(net)) { !! 369 #ifdef CONFIG_IPV6_SEG6_HMAC 439 kfree(rcu_dereference_raw(sdat !! 370 seg6_hmac_net_init(net); 440 kfree(sdata); !! 371 #endif 441 return -ENOMEM; << 442 } << 443 372 444 return 0; 373 return 0; 445 } 374 } 446 375 447 static void __net_exit seg6_net_exit(struct ne 376 static void __net_exit seg6_net_exit(struct net *net) 448 { 377 { 449 struct seg6_pernet_data *sdata = seg6_ 378 struct seg6_pernet_data *sdata = seg6_pernet(net); 450 379 >> 380 #ifdef CONFIG_IPV6_SEG6_HMAC 451 seg6_hmac_net_exit(net); 381 seg6_hmac_net_exit(net); >> 382 #endif 452 383 453 kfree(rcu_dereference_raw(sdata->tun_s !! 384 kfree(sdata->tun_src); 454 kfree(sdata); 385 kfree(sdata); 455 } 386 } 456 387 457 static struct pernet_operations ip6_segments_o 388 static struct pernet_operations ip6_segments_ops = { 458 .init = seg6_net_init, 389 .init = seg6_net_init, 459 .exit = seg6_net_exit, 390 .exit = seg6_net_exit, 460 }; 391 }; 461 392 462 static const struct genl_ops seg6_genl_ops[] = 393 static const struct genl_ops seg6_genl_ops[] = { 463 { 394 { 464 .cmd = SEG6_CMD_SETHMAC, 395 .cmd = SEG6_CMD_SETHMAC, 465 .validate = GENL_DONT_VALIDATE 396 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 466 .doit = seg6_genl_sethmac, 397 .doit = seg6_genl_sethmac, 467 .flags = GENL_ADMIN_PERM, 398 .flags = GENL_ADMIN_PERM, 468 }, 399 }, 469 { 400 { 470 .cmd = SEG6_CMD_DUMPHMAC, 401 .cmd = SEG6_CMD_DUMPHMAC, 471 .validate = GENL_DONT_VALIDATE 402 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 472 .start = seg6_genl_dumphmac_s 403 .start = seg6_genl_dumphmac_start, 473 .dumpit = seg6_genl_dumphmac, 404 .dumpit = seg6_genl_dumphmac, 474 .done = seg6_genl_dumphmac_d 405 .done = seg6_genl_dumphmac_done, 475 .flags = GENL_ADMIN_PERM, 406 .flags = GENL_ADMIN_PERM, 476 }, 407 }, 477 { 408 { 478 .cmd = SEG6_CMD_SET_TUNSRC, 409 .cmd = SEG6_CMD_SET_TUNSRC, 479 .validate = GENL_DONT_VALIDATE 410 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 480 .doit = seg6_genl_set_tunsrc 411 .doit = seg6_genl_set_tunsrc, 481 .flags = GENL_ADMIN_PERM, 412 .flags = GENL_ADMIN_PERM, 482 }, 413 }, 483 { 414 { 484 .cmd = SEG6_CMD_GET_TUNSRC, 415 .cmd = SEG6_CMD_GET_TUNSRC, 485 .validate = GENL_DONT_VALIDATE 416 .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, 486 .doit = seg6_genl_get_tunsrc 417 .doit = seg6_genl_get_tunsrc, 487 .flags = GENL_ADMIN_PERM, 418 .flags = GENL_ADMIN_PERM, 488 }, 419 }, 489 }; 420 }; 490 421 491 static struct genl_family seg6_genl_family __r 422 static struct genl_family seg6_genl_family __ro_after_init = { 492 .hdrsize = 0, 423 .hdrsize = 0, 493 .name = SEG6_GENL_NAME, 424 .name = SEG6_GENL_NAME, 494 .version = SEG6_GENL_VERSION, 425 .version = SEG6_GENL_VERSION, 495 .maxattr = SEG6_ATTR_MAX, 426 .maxattr = SEG6_ATTR_MAX, 496 .policy = seg6_genl_policy, 427 .policy = seg6_genl_policy, 497 .netnsok = true, 428 .netnsok = true, 498 .parallel_ops = true, 429 .parallel_ops = true, 499 .ops = seg6_genl_ops, 430 .ops = seg6_genl_ops, 500 .n_ops = ARRAY_SIZE(seg6_genl 431 .n_ops = ARRAY_SIZE(seg6_genl_ops), 501 .resv_start_op = SEG6_CMD_GET_TUNSRC << 502 .module = THIS_MODULE, 432 .module = THIS_MODULE, 503 }; 433 }; 504 434 505 int __init seg6_init(void) 435 int __init seg6_init(void) 506 { 436 { 507 int err; !! 437 int err = -ENOMEM; 508 438 509 err = register_pernet_subsys(&ip6_segm !! 439 err = genl_register_family(&seg6_genl_family); 510 if (err) 440 if (err) 511 goto out; 441 goto out; 512 442 513 err = genl_register_family(&seg6_genl_ !! 443 err = register_pernet_subsys(&ip6_segments_ops); 514 if (err) 444 if (err) 515 goto out_unregister_pernet; !! 445 goto out_unregister_genl; 516 446 >> 447 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL 517 err = seg6_iptunnel_init(); 448 err = seg6_iptunnel_init(); 518 if (err) 449 if (err) 519 goto out_unregister_genl; !! 450 goto out_unregister_pernet; 520 451 521 err = seg6_local_init(); 452 err = seg6_local_init(); 522 if (err) 453 if (err) 523 goto out_unregister_iptun; !! 454 goto out_unregister_pernet; >> 455 #endif 524 456 >> 457 #ifdef CONFIG_IPV6_SEG6_HMAC 525 err = seg6_hmac_init(); 458 err = seg6_hmac_init(); 526 if (err) 459 if (err) 527 goto out_unregister_seg6; !! 460 goto out_unregister_iptun; >> 461 #endif 528 462 529 pr_info("Segment Routing with IPv6\n") 463 pr_info("Segment Routing with IPv6\n"); 530 464 531 out: 465 out: 532 return err; 466 return err; 533 out_unregister_seg6: !! 467 #ifdef CONFIG_IPV6_SEG6_HMAC 534 seg6_local_exit(); << 535 out_unregister_iptun: 468 out_unregister_iptun: >> 469 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL >> 470 seg6_local_exit(); 536 seg6_iptunnel_exit(); 471 seg6_iptunnel_exit(); 537 out_unregister_genl: !! 472 #endif 538 genl_unregister_family(&seg6_genl_fami !! 473 #endif >> 474 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL 539 out_unregister_pernet: 475 out_unregister_pernet: 540 unregister_pernet_subsys(&ip6_segments 476 unregister_pernet_subsys(&ip6_segments_ops); >> 477 #endif >> 478 out_unregister_genl: >> 479 genl_unregister_family(&seg6_genl_family); 541 goto out; 480 goto out; 542 } 481 } 543 482 544 void seg6_exit(void) 483 void seg6_exit(void) 545 { 484 { >> 485 #ifdef CONFIG_IPV6_SEG6_HMAC 546 seg6_hmac_exit(); 486 seg6_hmac_exit(); 547 seg6_local_exit(); !! 487 #endif >> 488 #ifdef CONFIG_IPV6_SEG6_LWTUNNEL 548 seg6_iptunnel_exit(); 489 seg6_iptunnel_exit(); 549 genl_unregister_family(&seg6_genl_fami !! 490 #endif 550 unregister_pernet_subsys(&ip6_segments 491 unregister_pernet_subsys(&ip6_segments_ops); >> 492 genl_unregister_family(&seg6_genl_family); 551 } 493 } 552 494
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.