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