aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/ipv6/seg6_local.c211
1 files changed, 193 insertions, 18 deletions
diff --git a/net/ipv6/seg6_local.c b/net/ipv6/seg6_local.c
index 53615d7e0723..ab1fc1b17ddf 100644
--- a/net/ipv6/seg6_local.c
+++ b/net/ipv6/seg6_local.c
@@ -104,6 +104,181 @@ static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = {
104 [SEG6_LOCAL_OIF] = { .type = NLA_U32 }, 104 [SEG6_LOCAL_OIF] = { .type = NLA_U32 },
105}; 105};
106 106
107static int parse_nla_srh(struct nlattr **attrs, struct seg6_local_lwt *slwt)
108{
109 struct ipv6_sr_hdr *srh;
110 int len;
111
112 srh = nla_data(attrs[SEG6_LOCAL_SRH]);
113 len = nla_len(attrs[SEG6_LOCAL_SRH]);
114
115 /* SRH must contain at least one segment */
116 if (len < sizeof(*srh) + sizeof(struct in6_addr))
117 return -EINVAL;
118
119 if (!seg6_validate_srh(srh, len))
120 return -EINVAL;
121
122 slwt->srh = kmalloc(len, GFP_KERNEL);
123 if (!slwt->srh)
124 return -ENOMEM;
125
126 memcpy(slwt->srh, srh, len);
127
128 slwt->headroom += len;
129
130 return 0;
131}
132
133static int put_nla_srh(struct sk_buff *skb, struct seg6_local_lwt *slwt)
134{
135 struct ipv6_sr_hdr *srh;
136 struct nlattr *nla;
137 int len;
138
139 srh = slwt->srh;
140 len = (srh->hdrlen + 1) << 3;
141
142 nla = nla_reserve(skb, SEG6_LOCAL_SRH, len);
143 if (!nla)
144 return -EMSGSIZE;
145
146 memcpy(nla_data(nla), srh, len);
147
148 return 0;
149}
150
151static int cmp_nla_srh(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
152{
153 int len = (a->srh->hdrlen + 1) << 3;
154
155 if (len != ((b->srh->hdrlen + 1) << 3))
156 return 1;
157
158 return memcmp(a->srh, b->srh, len);
159}
160
161static int parse_nla_table(struct nlattr **attrs, struct seg6_local_lwt *slwt)
162{
163 slwt->table = nla_get_u32(attrs[SEG6_LOCAL_TABLE]);
164
165 return 0;
166}
167
168static int put_nla_table(struct sk_buff *skb, struct seg6_local_lwt *slwt)
169{
170 if (nla_put_u32(skb, SEG6_LOCAL_TABLE, slwt->table))
171 return -EMSGSIZE;
172
173 return 0;
174}
175
176static int cmp_nla_table(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
177{
178 if (a->table != b->table)
179 return 1;
180
181 return 0;
182}
183
184static int parse_nla_nh4(struct nlattr **attrs, struct seg6_local_lwt *slwt)
185{
186 memcpy(&slwt->nh4, nla_data(attrs[SEG6_LOCAL_NH4]),
187 sizeof(struct in_addr));
188
189 return 0;
190}
191
192static int put_nla_nh4(struct sk_buff *skb, struct seg6_local_lwt *slwt)
193{
194 struct nlattr *nla;
195
196 nla = nla_reserve(skb, SEG6_LOCAL_NH4, sizeof(struct in_addr));
197 if (!nla)
198 return -EMSGSIZE;
199
200 memcpy(nla_data(nla), &slwt->nh4, sizeof(struct in_addr));
201
202 return 0;
203}
204
205static int cmp_nla_nh4(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
206{
207 return memcmp(&a->nh4, &b->nh4, sizeof(struct in_addr));
208}
209
210static int parse_nla_nh6(struct nlattr **attrs, struct seg6_local_lwt *slwt)
211{
212 memcpy(&slwt->nh6, nla_data(attrs[SEG6_LOCAL_NH6]),
213 sizeof(struct in6_addr));
214
215 return 0;
216}
217
218static int put_nla_nh6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
219{
220 struct nlattr *nla;
221
222 nla = nla_reserve(skb, SEG6_LOCAL_NH6, sizeof(struct in6_addr));
223 if (!nla)
224 return -EMSGSIZE;
225
226 memcpy(nla_data(nla), &slwt->nh6, sizeof(struct in6_addr));
227
228 return 0;
229}
230
231static int cmp_nla_nh6(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
232{
233 return memcmp(&a->nh6, &b->nh6, sizeof(struct in6_addr));
234}
235
236static int parse_nla_iif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
237{
238 slwt->iif = nla_get_u32(attrs[SEG6_LOCAL_IIF]);
239
240 return 0;
241}
242
243static int put_nla_iif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
244{
245 if (nla_put_u32(skb, SEG6_LOCAL_IIF, slwt->iif))
246 return -EMSGSIZE;
247
248 return 0;
249}
250
251static int cmp_nla_iif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
252{
253 if (a->iif != b->iif)
254 return 1;
255
256 return 0;
257}
258
259static int parse_nla_oif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
260{
261 slwt->oif = nla_get_u32(attrs[SEG6_LOCAL_OIF]);
262
263 return 0;
264}
265
266static int put_nla_oif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
267{
268 if (nla_put_u32(skb, SEG6_LOCAL_OIF, slwt->oif))
269 return -EMSGSIZE;
270
271 return 0;
272}
273
274static int cmp_nla_oif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
275{
276 if (a->oif != b->oif)
277 return 1;
278
279 return 0;
280}
281
107struct seg6_action_param { 282struct seg6_action_param {
108 int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt); 283 int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt);
109 int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt); 284 int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
@@ -111,29 +286,29 @@ struct seg6_action_param {
111}; 286};
112 287
113static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = { 288static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = {
114 [SEG6_LOCAL_SRH] = { .parse = NULL, 289 [SEG6_LOCAL_SRH] = { .parse = parse_nla_srh,
115 .put = NULL, 290 .put = put_nla_srh,
116 .cmp = NULL }, 291 .cmp = cmp_nla_srh },
117 292
118 [SEG6_LOCAL_TABLE] = { .parse = NULL, 293 [SEG6_LOCAL_TABLE] = { .parse = parse_nla_table,
119 .put = NULL, 294 .put = put_nla_table,
120 .cmp = NULL }, 295 .cmp = cmp_nla_table },
121 296
122 [SEG6_LOCAL_NH4] = { .parse = NULL, 297 [SEG6_LOCAL_NH4] = { .parse = parse_nla_nh4,
123 .put = NULL, 298 .put = put_nla_nh4,
124 .cmp = NULL }, 299 .cmp = cmp_nla_nh4 },
125 300
126 [SEG6_LOCAL_NH6] = { .parse = NULL, 301 [SEG6_LOCAL_NH6] = { .parse = parse_nla_nh6,
127 .put = NULL, 302 .put = put_nla_nh6,
128 .cmp = NULL }, 303 .cmp = cmp_nla_nh6 },
129 304
130 [SEG6_LOCAL_IIF] = { .parse = NULL, 305 [SEG6_LOCAL_IIF] = { .parse = parse_nla_iif,
131 .put = NULL, 306 .put = put_nla_iif,
132 .cmp = NULL }, 307 .cmp = cmp_nla_iif },
133 308
134 [SEG6_LOCAL_OIF] = { .parse = NULL, 309 [SEG6_LOCAL_OIF] = { .parse = parse_nla_oif,
135 .put = NULL, 310 .put = put_nla_oif,
136 .cmp = NULL }, 311 .cmp = cmp_nla_oif },
137}; 312};
138 313
139static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt) 314static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)