seg6_local.c 24 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * SR-IPv6 implementation
  4. *
  5. * Authors:
  6. * David Lebrun <david.lebrun@uclouvain.be>
  7. * eBPF support: Mathieu Xhonneux <m.xhonneux@gmail.com>
  8. */
  9. #include <linux/types.h>
  10. #include <linux/skbuff.h>
  11. #include <linux/net.h>
  12. #include <linux/module.h>
  13. #include <net/ip.h>
  14. #include <net/lwtunnel.h>
  15. #include <net/netevent.h>
  16. #include <net/netns/generic.h>
  17. #include <net/ip6_fib.h>
  18. #include <net/route.h>
  19. #include <net/seg6.h>
  20. #include <linux/seg6.h>
  21. #include <linux/seg6_local.h>
  22. #include <net/addrconf.h>
  23. #include <net/ip6_route.h>
  24. #include <net/dst_cache.h>
  25. #include <net/ip_tunnels.h>
  26. #ifdef CONFIG_IPV6_SEG6_HMAC
  27. #include <net/seg6_hmac.h>
  28. #endif
  29. #include <net/seg6_local.h>
  30. #include <linux/etherdevice.h>
  31. #include <linux/bpf.h>
  32. struct seg6_local_lwt;
  33. struct seg6_action_desc {
  34. int action;
  35. unsigned long attrs;
  36. int (*input)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
  37. int static_headroom;
  38. };
  39. struct bpf_lwt_prog {
  40. struct bpf_prog *prog;
  41. char *name;
  42. };
  43. struct seg6_local_lwt {
  44. int action;
  45. struct ipv6_sr_hdr *srh;
  46. int table;
  47. struct in_addr nh4;
  48. struct in6_addr nh6;
  49. int iif;
  50. int oif;
  51. struct bpf_lwt_prog bpf;
  52. int headroom;
  53. struct seg6_action_desc *desc;
  54. };
  55. static struct seg6_local_lwt *seg6_local_lwtunnel(struct lwtunnel_state *lwt)
  56. {
  57. return (struct seg6_local_lwt *)lwt->data;
  58. }
  59. static struct ipv6_sr_hdr *get_srh(struct sk_buff *skb)
  60. {
  61. struct ipv6_sr_hdr *srh;
  62. int len, srhoff = 0;
  63. if (ipv6_find_hdr(skb, &srhoff, IPPROTO_ROUTING, NULL, NULL) < 0)
  64. return NULL;
  65. if (!pskb_may_pull(skb, srhoff + sizeof(*srh)))
  66. return NULL;
  67. srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
  68. len = (srh->hdrlen + 1) << 3;
  69. if (!pskb_may_pull(skb, srhoff + len))
  70. return NULL;
  71. /* note that pskb_may_pull may change pointers in header;
  72. * for this reason it is necessary to reload them when needed.
  73. */
  74. srh = (struct ipv6_sr_hdr *)(skb->data + srhoff);
  75. if (!seg6_validate_srh(srh, len, true))
  76. return NULL;
  77. return srh;
  78. }
  79. static struct ipv6_sr_hdr *get_and_validate_srh(struct sk_buff *skb)
  80. {
  81. struct ipv6_sr_hdr *srh;
  82. srh = get_srh(skb);
  83. if (!srh)
  84. return NULL;
  85. if (srh->segments_left == 0)
  86. return NULL;
  87. #ifdef CONFIG_IPV6_SEG6_HMAC
  88. if (!seg6_hmac_validate_skb(skb))
  89. return NULL;
  90. #endif
  91. return srh;
  92. }
  93. static bool decap_and_validate(struct sk_buff *skb, int proto)
  94. {
  95. struct ipv6_sr_hdr *srh;
  96. unsigned int off = 0;
  97. srh = get_srh(skb);
  98. if (srh && srh->segments_left > 0)
  99. return false;
  100. #ifdef CONFIG_IPV6_SEG6_HMAC
  101. if (srh && !seg6_hmac_validate_skb(skb))
  102. return false;
  103. #endif
  104. if (ipv6_find_hdr(skb, &off, proto, NULL, NULL) < 0)
  105. return false;
  106. if (!pskb_pull(skb, off))
  107. return false;
  108. skb_postpull_rcsum(skb, skb_network_header(skb), off);
  109. skb_reset_network_header(skb);
  110. skb_reset_transport_header(skb);
  111. if (iptunnel_pull_offloads(skb))
  112. return false;
  113. return true;
  114. }
  115. static void advance_nextseg(struct ipv6_sr_hdr *srh, struct in6_addr *daddr)
  116. {
  117. struct in6_addr *addr;
  118. srh->segments_left--;
  119. addr = srh->segments + srh->segments_left;
  120. *daddr = *addr;
  121. }
  122. static int
  123. seg6_lookup_any_nexthop(struct sk_buff *skb, struct in6_addr *nhaddr,
  124. u32 tbl_id, bool local_delivery)
  125. {
  126. struct net *net = dev_net(skb->dev);
  127. struct ipv6hdr *hdr = ipv6_hdr(skb);
  128. int flags = RT6_LOOKUP_F_HAS_SADDR;
  129. struct dst_entry *dst = NULL;
  130. struct rt6_info *rt;
  131. struct flowi6 fl6;
  132. int dev_flags = 0;
  133. fl6.flowi6_iif = skb->dev->ifindex;
  134. fl6.daddr = nhaddr ? *nhaddr : hdr->daddr;
  135. fl6.saddr = hdr->saddr;
  136. fl6.flowlabel = ip6_flowinfo(hdr);
  137. fl6.flowi6_mark = skb->mark;
  138. fl6.flowi6_proto = hdr->nexthdr;
  139. if (nhaddr)
  140. fl6.flowi6_flags = FLOWI_FLAG_KNOWN_NH;
  141. if (!tbl_id) {
  142. dst = ip6_route_input_lookup(net, skb->dev, &fl6, skb, flags);
  143. } else {
  144. struct fib6_table *table;
  145. table = fib6_get_table(net, tbl_id);
  146. if (!table)
  147. goto out;
  148. rt = ip6_pol_route(net, table, 0, &fl6, skb, flags);
  149. dst = &rt->dst;
  150. }
  151. /* we want to discard traffic destined for local packet processing,
  152. * if @local_delivery is set to false.
  153. */
  154. if (!local_delivery)
  155. dev_flags |= IFF_LOOPBACK;
  156. if (dst && (dst->dev->flags & dev_flags) && !dst->error) {
  157. dst_release(dst);
  158. dst = NULL;
  159. }
  160. out:
  161. if (!dst) {
  162. rt = net->ipv6.ip6_blk_hole_entry;
  163. dst = &rt->dst;
  164. dst_hold(dst);
  165. }
  166. skb_dst_drop(skb);
  167. skb_dst_set(skb, dst);
  168. return dst->error;
  169. }
  170. int seg6_lookup_nexthop(struct sk_buff *skb,
  171. struct in6_addr *nhaddr, u32 tbl_id)
  172. {
  173. return seg6_lookup_any_nexthop(skb, nhaddr, tbl_id, false);
  174. }
  175. /* regular endpoint function */
  176. static int input_action_end(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  177. {
  178. struct ipv6_sr_hdr *srh;
  179. srh = get_and_validate_srh(skb);
  180. if (!srh)
  181. goto drop;
  182. advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
  183. seg6_lookup_nexthop(skb, NULL, 0);
  184. return dst_input(skb);
  185. drop:
  186. kfree_skb(skb);
  187. return -EINVAL;
  188. }
  189. /* regular endpoint, and forward to specified nexthop */
  190. static int input_action_end_x(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  191. {
  192. struct ipv6_sr_hdr *srh;
  193. srh = get_and_validate_srh(skb);
  194. if (!srh)
  195. goto drop;
  196. advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
  197. seg6_lookup_nexthop(skb, &slwt->nh6, 0);
  198. return dst_input(skb);
  199. drop:
  200. kfree_skb(skb);
  201. return -EINVAL;
  202. }
  203. static int input_action_end_t(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  204. {
  205. struct ipv6_sr_hdr *srh;
  206. srh = get_and_validate_srh(skb);
  207. if (!srh)
  208. goto drop;
  209. advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
  210. seg6_lookup_nexthop(skb, NULL, slwt->table);
  211. return dst_input(skb);
  212. drop:
  213. kfree_skb(skb);
  214. return -EINVAL;
  215. }
  216. /* decapsulate and forward inner L2 frame on specified interface */
  217. static int input_action_end_dx2(struct sk_buff *skb,
  218. struct seg6_local_lwt *slwt)
  219. {
  220. struct net *net = dev_net(skb->dev);
  221. struct net_device *odev;
  222. struct ethhdr *eth;
  223. if (!decap_and_validate(skb, IPPROTO_ETHERNET))
  224. goto drop;
  225. if (!pskb_may_pull(skb, ETH_HLEN))
  226. goto drop;
  227. skb_reset_mac_header(skb);
  228. eth = (struct ethhdr *)skb->data;
  229. /* To determine the frame's protocol, we assume it is 802.3. This avoids
  230. * a call to eth_type_trans(), which is not really relevant for our
  231. * use case.
  232. */
  233. if (!eth_proto_is_802_3(eth->h_proto))
  234. goto drop;
  235. odev = dev_get_by_index_rcu(net, slwt->oif);
  236. if (!odev)
  237. goto drop;
  238. /* As we accept Ethernet frames, make sure the egress device is of
  239. * the correct type.
  240. */
  241. if (odev->type != ARPHRD_ETHER)
  242. goto drop;
  243. if (!(odev->flags & IFF_UP) || !netif_carrier_ok(odev))
  244. goto drop;
  245. skb_orphan(skb);
  246. if (skb_warn_if_lro(skb))
  247. goto drop;
  248. skb_forward_csum(skb);
  249. if (skb->len - ETH_HLEN > odev->mtu)
  250. goto drop;
  251. skb->dev = odev;
  252. skb->protocol = eth->h_proto;
  253. return dev_queue_xmit(skb);
  254. drop:
  255. kfree_skb(skb);
  256. return -EINVAL;
  257. }
  258. /* decapsulate and forward to specified nexthop */
  259. static int input_action_end_dx6(struct sk_buff *skb,
  260. struct seg6_local_lwt *slwt)
  261. {
  262. struct in6_addr *nhaddr = NULL;
  263. /* this function accepts IPv6 encapsulated packets, with either
  264. * an SRH with SL=0, or no SRH.
  265. */
  266. if (!decap_and_validate(skb, IPPROTO_IPV6))
  267. goto drop;
  268. if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
  269. goto drop;
  270. /* The inner packet is not associated to any local interface,
  271. * so we do not call netif_rx().
  272. *
  273. * If slwt->nh6 is set to ::, then lookup the nexthop for the
  274. * inner packet's DA. Otherwise, use the specified nexthop.
  275. */
  276. if (!ipv6_addr_any(&slwt->nh6))
  277. nhaddr = &slwt->nh6;
  278. skb_set_transport_header(skb, sizeof(struct ipv6hdr));
  279. seg6_lookup_nexthop(skb, nhaddr, 0);
  280. return dst_input(skb);
  281. drop:
  282. kfree_skb(skb);
  283. return -EINVAL;
  284. }
  285. static int input_action_end_dx4(struct sk_buff *skb,
  286. struct seg6_local_lwt *slwt)
  287. {
  288. struct iphdr *iph;
  289. __be32 nhaddr;
  290. int err;
  291. if (!decap_and_validate(skb, IPPROTO_IPIP))
  292. goto drop;
  293. if (!pskb_may_pull(skb, sizeof(struct iphdr)))
  294. goto drop;
  295. skb->protocol = htons(ETH_P_IP);
  296. iph = ip_hdr(skb);
  297. nhaddr = slwt->nh4.s_addr ?: iph->daddr;
  298. skb_dst_drop(skb);
  299. skb_set_transport_header(skb, sizeof(struct iphdr));
  300. err = ip_route_input(skb, nhaddr, iph->saddr, 0, skb->dev);
  301. if (err)
  302. goto drop;
  303. return dst_input(skb);
  304. drop:
  305. kfree_skb(skb);
  306. return -EINVAL;
  307. }
  308. static int input_action_end_dt6(struct sk_buff *skb,
  309. struct seg6_local_lwt *slwt)
  310. {
  311. if (!decap_and_validate(skb, IPPROTO_IPV6))
  312. goto drop;
  313. if (!pskb_may_pull(skb, sizeof(struct ipv6hdr)))
  314. goto drop;
  315. skb_set_transport_header(skb, sizeof(struct ipv6hdr));
  316. seg6_lookup_any_nexthop(skb, NULL, slwt->table, true);
  317. return dst_input(skb);
  318. drop:
  319. kfree_skb(skb);
  320. return -EINVAL;
  321. }
  322. /* push an SRH on top of the current one */
  323. static int input_action_end_b6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  324. {
  325. struct ipv6_sr_hdr *srh;
  326. int err = -EINVAL;
  327. srh = get_and_validate_srh(skb);
  328. if (!srh)
  329. goto drop;
  330. err = seg6_do_srh_inline(skb, slwt->srh);
  331. if (err)
  332. goto drop;
  333. ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
  334. skb_set_transport_header(skb, sizeof(struct ipv6hdr));
  335. seg6_lookup_nexthop(skb, NULL, 0);
  336. return dst_input(skb);
  337. drop:
  338. kfree_skb(skb);
  339. return err;
  340. }
  341. /* encapsulate within an outer IPv6 header and a specified SRH */
  342. static int input_action_end_b6_encap(struct sk_buff *skb,
  343. struct seg6_local_lwt *slwt)
  344. {
  345. struct ipv6_sr_hdr *srh;
  346. int err = -EINVAL;
  347. srh = get_and_validate_srh(skb);
  348. if (!srh)
  349. goto drop;
  350. advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
  351. skb_reset_inner_headers(skb);
  352. skb->encapsulation = 1;
  353. err = seg6_do_srh_encap(skb, slwt->srh, IPPROTO_IPV6);
  354. if (err)
  355. goto drop;
  356. ipv6_hdr(skb)->payload_len = htons(skb->len - sizeof(struct ipv6hdr));
  357. skb_set_transport_header(skb, sizeof(struct ipv6hdr));
  358. seg6_lookup_nexthop(skb, NULL, 0);
  359. return dst_input(skb);
  360. drop:
  361. kfree_skb(skb);
  362. return err;
  363. }
  364. DEFINE_PER_CPU(struct seg6_bpf_srh_state, seg6_bpf_srh_states);
  365. bool seg6_bpf_has_valid_srh(struct sk_buff *skb)
  366. {
  367. struct seg6_bpf_srh_state *srh_state =
  368. this_cpu_ptr(&seg6_bpf_srh_states);
  369. struct ipv6_sr_hdr *srh = srh_state->srh;
  370. if (unlikely(srh == NULL))
  371. return false;
  372. if (unlikely(!srh_state->valid)) {
  373. if ((srh_state->hdrlen & 7) != 0)
  374. return false;
  375. srh->hdrlen = (u8)(srh_state->hdrlen >> 3);
  376. if (!seg6_validate_srh(srh, (srh->hdrlen + 1) << 3, true))
  377. return false;
  378. srh_state->valid = true;
  379. }
  380. return true;
  381. }
  382. static int input_action_end_bpf(struct sk_buff *skb,
  383. struct seg6_local_lwt *slwt)
  384. {
  385. struct seg6_bpf_srh_state *srh_state =
  386. this_cpu_ptr(&seg6_bpf_srh_states);
  387. struct ipv6_sr_hdr *srh;
  388. int ret;
  389. srh = get_and_validate_srh(skb);
  390. if (!srh) {
  391. kfree_skb(skb);
  392. return -EINVAL;
  393. }
  394. advance_nextseg(srh, &ipv6_hdr(skb)->daddr);
  395. /* preempt_disable is needed to protect the per-CPU buffer srh_state,
  396. * which is also accessed by the bpf_lwt_seg6_* helpers
  397. */
  398. preempt_disable();
  399. srh_state->srh = srh;
  400. srh_state->hdrlen = srh->hdrlen << 3;
  401. srh_state->valid = true;
  402. rcu_read_lock();
  403. bpf_compute_data_pointers(skb);
  404. ret = bpf_prog_run_save_cb(slwt->bpf.prog, skb);
  405. rcu_read_unlock();
  406. switch (ret) {
  407. case BPF_OK:
  408. case BPF_REDIRECT:
  409. break;
  410. case BPF_DROP:
  411. goto drop;
  412. default:
  413. pr_warn_once("bpf-seg6local: Illegal return value %u\n", ret);
  414. goto drop;
  415. }
  416. if (srh_state->srh && !seg6_bpf_has_valid_srh(skb))
  417. goto drop;
  418. preempt_enable();
  419. if (ret != BPF_REDIRECT)
  420. seg6_lookup_nexthop(skb, NULL, 0);
  421. return dst_input(skb);
  422. drop:
  423. preempt_enable();
  424. kfree_skb(skb);
  425. return -EINVAL;
  426. }
  427. static struct seg6_action_desc seg6_action_table[] = {
  428. {
  429. .action = SEG6_LOCAL_ACTION_END,
  430. .attrs = 0,
  431. .input = input_action_end,
  432. },
  433. {
  434. .action = SEG6_LOCAL_ACTION_END_X,
  435. .attrs = (1 << SEG6_LOCAL_NH6),
  436. .input = input_action_end_x,
  437. },
  438. {
  439. .action = SEG6_LOCAL_ACTION_END_T,
  440. .attrs = (1 << SEG6_LOCAL_TABLE),
  441. .input = input_action_end_t,
  442. },
  443. {
  444. .action = SEG6_LOCAL_ACTION_END_DX2,
  445. .attrs = (1 << SEG6_LOCAL_OIF),
  446. .input = input_action_end_dx2,
  447. },
  448. {
  449. .action = SEG6_LOCAL_ACTION_END_DX6,
  450. .attrs = (1 << SEG6_LOCAL_NH6),
  451. .input = input_action_end_dx6,
  452. },
  453. {
  454. .action = SEG6_LOCAL_ACTION_END_DX4,
  455. .attrs = (1 << SEG6_LOCAL_NH4),
  456. .input = input_action_end_dx4,
  457. },
  458. {
  459. .action = SEG6_LOCAL_ACTION_END_DT6,
  460. .attrs = (1 << SEG6_LOCAL_TABLE),
  461. .input = input_action_end_dt6,
  462. },
  463. {
  464. .action = SEG6_LOCAL_ACTION_END_B6,
  465. .attrs = (1 << SEG6_LOCAL_SRH),
  466. .input = input_action_end_b6,
  467. },
  468. {
  469. .action = SEG6_LOCAL_ACTION_END_B6_ENCAP,
  470. .attrs = (1 << SEG6_LOCAL_SRH),
  471. .input = input_action_end_b6_encap,
  472. .static_headroom = sizeof(struct ipv6hdr),
  473. },
  474. {
  475. .action = SEG6_LOCAL_ACTION_END_BPF,
  476. .attrs = (1 << SEG6_LOCAL_BPF),
  477. .input = input_action_end_bpf,
  478. },
  479. };
  480. static struct seg6_action_desc *__get_action_desc(int action)
  481. {
  482. struct seg6_action_desc *desc;
  483. int i, count;
  484. count = ARRAY_SIZE(seg6_action_table);
  485. for (i = 0; i < count; i++) {
  486. desc = &seg6_action_table[i];
  487. if (desc->action == action)
  488. return desc;
  489. }
  490. return NULL;
  491. }
  492. static int seg6_local_input(struct sk_buff *skb)
  493. {
  494. struct dst_entry *orig_dst = skb_dst(skb);
  495. struct seg6_action_desc *desc;
  496. struct seg6_local_lwt *slwt;
  497. if (skb->protocol != htons(ETH_P_IPV6)) {
  498. kfree_skb(skb);
  499. return -EINVAL;
  500. }
  501. slwt = seg6_local_lwtunnel(orig_dst->lwtstate);
  502. desc = slwt->desc;
  503. return desc->input(skb, slwt);
  504. }
  505. static const struct nla_policy seg6_local_policy[SEG6_LOCAL_MAX + 1] = {
  506. [SEG6_LOCAL_ACTION] = { .type = NLA_U32 },
  507. [SEG6_LOCAL_SRH] = { .type = NLA_BINARY },
  508. [SEG6_LOCAL_TABLE] = { .type = NLA_U32 },
  509. [SEG6_LOCAL_NH4] = { .type = NLA_BINARY,
  510. .len = sizeof(struct in_addr) },
  511. [SEG6_LOCAL_NH6] = { .type = NLA_BINARY,
  512. .len = sizeof(struct in6_addr) },
  513. [SEG6_LOCAL_IIF] = { .type = NLA_U32 },
  514. [SEG6_LOCAL_OIF] = { .type = NLA_U32 },
  515. [SEG6_LOCAL_BPF] = { .type = NLA_NESTED },
  516. };
  517. static int parse_nla_srh(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  518. {
  519. struct ipv6_sr_hdr *srh;
  520. int len;
  521. srh = nla_data(attrs[SEG6_LOCAL_SRH]);
  522. len = nla_len(attrs[SEG6_LOCAL_SRH]);
  523. /* SRH must contain at least one segment */
  524. if (len < sizeof(*srh) + sizeof(struct in6_addr))
  525. return -EINVAL;
  526. if (!seg6_validate_srh(srh, len, false))
  527. return -EINVAL;
  528. slwt->srh = kmemdup(srh, len, GFP_KERNEL);
  529. if (!slwt->srh)
  530. return -ENOMEM;
  531. slwt->headroom += len;
  532. return 0;
  533. }
  534. static int put_nla_srh(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  535. {
  536. struct ipv6_sr_hdr *srh;
  537. struct nlattr *nla;
  538. int len;
  539. srh = slwt->srh;
  540. len = (srh->hdrlen + 1) << 3;
  541. nla = nla_reserve(skb, SEG6_LOCAL_SRH, len);
  542. if (!nla)
  543. return -EMSGSIZE;
  544. memcpy(nla_data(nla), srh, len);
  545. return 0;
  546. }
  547. static int cmp_nla_srh(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  548. {
  549. int len = (a->srh->hdrlen + 1) << 3;
  550. if (len != ((b->srh->hdrlen + 1) << 3))
  551. return 1;
  552. return memcmp(a->srh, b->srh, len);
  553. }
  554. static int parse_nla_table(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  555. {
  556. slwt->table = nla_get_u32(attrs[SEG6_LOCAL_TABLE]);
  557. return 0;
  558. }
  559. static int put_nla_table(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  560. {
  561. if (nla_put_u32(skb, SEG6_LOCAL_TABLE, slwt->table))
  562. return -EMSGSIZE;
  563. return 0;
  564. }
  565. static int cmp_nla_table(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  566. {
  567. if (a->table != b->table)
  568. return 1;
  569. return 0;
  570. }
  571. static int parse_nla_nh4(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  572. {
  573. memcpy(&slwt->nh4, nla_data(attrs[SEG6_LOCAL_NH4]),
  574. sizeof(struct in_addr));
  575. return 0;
  576. }
  577. static int put_nla_nh4(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  578. {
  579. struct nlattr *nla;
  580. nla = nla_reserve(skb, SEG6_LOCAL_NH4, sizeof(struct in_addr));
  581. if (!nla)
  582. return -EMSGSIZE;
  583. memcpy(nla_data(nla), &slwt->nh4, sizeof(struct in_addr));
  584. return 0;
  585. }
  586. static int cmp_nla_nh4(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  587. {
  588. return memcmp(&a->nh4, &b->nh4, sizeof(struct in_addr));
  589. }
  590. static int parse_nla_nh6(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  591. {
  592. memcpy(&slwt->nh6, nla_data(attrs[SEG6_LOCAL_NH6]),
  593. sizeof(struct in6_addr));
  594. return 0;
  595. }
  596. static int put_nla_nh6(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  597. {
  598. struct nlattr *nla;
  599. nla = nla_reserve(skb, SEG6_LOCAL_NH6, sizeof(struct in6_addr));
  600. if (!nla)
  601. return -EMSGSIZE;
  602. memcpy(nla_data(nla), &slwt->nh6, sizeof(struct in6_addr));
  603. return 0;
  604. }
  605. static int cmp_nla_nh6(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  606. {
  607. return memcmp(&a->nh6, &b->nh6, sizeof(struct in6_addr));
  608. }
  609. static int parse_nla_iif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  610. {
  611. slwt->iif = nla_get_u32(attrs[SEG6_LOCAL_IIF]);
  612. return 0;
  613. }
  614. static int put_nla_iif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  615. {
  616. if (nla_put_u32(skb, SEG6_LOCAL_IIF, slwt->iif))
  617. return -EMSGSIZE;
  618. return 0;
  619. }
  620. static int cmp_nla_iif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  621. {
  622. if (a->iif != b->iif)
  623. return 1;
  624. return 0;
  625. }
  626. static int parse_nla_oif(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  627. {
  628. slwt->oif = nla_get_u32(attrs[SEG6_LOCAL_OIF]);
  629. return 0;
  630. }
  631. static int put_nla_oif(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  632. {
  633. if (nla_put_u32(skb, SEG6_LOCAL_OIF, slwt->oif))
  634. return -EMSGSIZE;
  635. return 0;
  636. }
  637. static int cmp_nla_oif(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  638. {
  639. if (a->oif != b->oif)
  640. return 1;
  641. return 0;
  642. }
  643. #define MAX_PROG_NAME 256
  644. static const struct nla_policy bpf_prog_policy[SEG6_LOCAL_BPF_PROG_MAX + 1] = {
  645. [SEG6_LOCAL_BPF_PROG] = { .type = NLA_U32, },
  646. [SEG6_LOCAL_BPF_PROG_NAME] = { .type = NLA_NUL_STRING,
  647. .len = MAX_PROG_NAME },
  648. };
  649. static int parse_nla_bpf(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  650. {
  651. struct nlattr *tb[SEG6_LOCAL_BPF_PROG_MAX + 1];
  652. struct bpf_prog *p;
  653. int ret;
  654. u32 fd;
  655. ret = nla_parse_nested_deprecated(tb, SEG6_LOCAL_BPF_PROG_MAX,
  656. attrs[SEG6_LOCAL_BPF],
  657. bpf_prog_policy, NULL);
  658. if (ret < 0)
  659. return ret;
  660. if (!tb[SEG6_LOCAL_BPF_PROG] || !tb[SEG6_LOCAL_BPF_PROG_NAME])
  661. return -EINVAL;
  662. slwt->bpf.name = nla_memdup(tb[SEG6_LOCAL_BPF_PROG_NAME], GFP_KERNEL);
  663. if (!slwt->bpf.name)
  664. return -ENOMEM;
  665. fd = nla_get_u32(tb[SEG6_LOCAL_BPF_PROG]);
  666. p = bpf_prog_get_type(fd, BPF_PROG_TYPE_LWT_SEG6LOCAL);
  667. if (IS_ERR(p)) {
  668. kfree(slwt->bpf.name);
  669. return PTR_ERR(p);
  670. }
  671. slwt->bpf.prog = p;
  672. return 0;
  673. }
  674. static int put_nla_bpf(struct sk_buff *skb, struct seg6_local_lwt *slwt)
  675. {
  676. struct nlattr *nest;
  677. if (!slwt->bpf.prog)
  678. return 0;
  679. nest = nla_nest_start_noflag(skb, SEG6_LOCAL_BPF);
  680. if (!nest)
  681. return -EMSGSIZE;
  682. if (nla_put_u32(skb, SEG6_LOCAL_BPF_PROG, slwt->bpf.prog->aux->id))
  683. return -EMSGSIZE;
  684. if (slwt->bpf.name &&
  685. nla_put_string(skb, SEG6_LOCAL_BPF_PROG_NAME, slwt->bpf.name))
  686. return -EMSGSIZE;
  687. return nla_nest_end(skb, nest);
  688. }
  689. static int cmp_nla_bpf(struct seg6_local_lwt *a, struct seg6_local_lwt *b)
  690. {
  691. if (!a->bpf.name && !b->bpf.name)
  692. return 0;
  693. if (!a->bpf.name || !b->bpf.name)
  694. return 1;
  695. return strcmp(a->bpf.name, b->bpf.name);
  696. }
  697. struct seg6_action_param {
  698. int (*parse)(struct nlattr **attrs, struct seg6_local_lwt *slwt);
  699. int (*put)(struct sk_buff *skb, struct seg6_local_lwt *slwt);
  700. int (*cmp)(struct seg6_local_lwt *a, struct seg6_local_lwt *b);
  701. };
  702. static struct seg6_action_param seg6_action_params[SEG6_LOCAL_MAX + 1] = {
  703. [SEG6_LOCAL_SRH] = { .parse = parse_nla_srh,
  704. .put = put_nla_srh,
  705. .cmp = cmp_nla_srh },
  706. [SEG6_LOCAL_TABLE] = { .parse = parse_nla_table,
  707. .put = put_nla_table,
  708. .cmp = cmp_nla_table },
  709. [SEG6_LOCAL_NH4] = { .parse = parse_nla_nh4,
  710. .put = put_nla_nh4,
  711. .cmp = cmp_nla_nh4 },
  712. [SEG6_LOCAL_NH6] = { .parse = parse_nla_nh6,
  713. .put = put_nla_nh6,
  714. .cmp = cmp_nla_nh6 },
  715. [SEG6_LOCAL_IIF] = { .parse = parse_nla_iif,
  716. .put = put_nla_iif,
  717. .cmp = cmp_nla_iif },
  718. [SEG6_LOCAL_OIF] = { .parse = parse_nla_oif,
  719. .put = put_nla_oif,
  720. .cmp = cmp_nla_oif },
  721. [SEG6_LOCAL_BPF] = { .parse = parse_nla_bpf,
  722. .put = put_nla_bpf,
  723. .cmp = cmp_nla_bpf },
  724. };
  725. static int parse_nla_action(struct nlattr **attrs, struct seg6_local_lwt *slwt)
  726. {
  727. struct seg6_action_param *param;
  728. struct seg6_action_desc *desc;
  729. int i, err;
  730. desc = __get_action_desc(slwt->action);
  731. if (!desc)
  732. return -EINVAL;
  733. if (!desc->input)
  734. return -EOPNOTSUPP;
  735. slwt->desc = desc;
  736. slwt->headroom += desc->static_headroom;
  737. for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
  738. if (desc->attrs & (1 << i)) {
  739. if (!attrs[i])
  740. return -EINVAL;
  741. param = &seg6_action_params[i];
  742. err = param->parse(attrs, slwt);
  743. if (err < 0)
  744. return err;
  745. }
  746. }
  747. return 0;
  748. }
  749. static int seg6_local_build_state(struct net *net, struct nlattr *nla,
  750. unsigned int family, const void *cfg,
  751. struct lwtunnel_state **ts,
  752. struct netlink_ext_ack *extack)
  753. {
  754. struct nlattr *tb[SEG6_LOCAL_MAX + 1];
  755. struct lwtunnel_state *newts;
  756. struct seg6_local_lwt *slwt;
  757. int err;
  758. if (family != AF_INET6)
  759. return -EINVAL;
  760. err = nla_parse_nested_deprecated(tb, SEG6_LOCAL_MAX, nla,
  761. seg6_local_policy, extack);
  762. if (err < 0)
  763. return err;
  764. if (!tb[SEG6_LOCAL_ACTION])
  765. return -EINVAL;
  766. newts = lwtunnel_state_alloc(sizeof(*slwt));
  767. if (!newts)
  768. return -ENOMEM;
  769. slwt = seg6_local_lwtunnel(newts);
  770. slwt->action = nla_get_u32(tb[SEG6_LOCAL_ACTION]);
  771. err = parse_nla_action(tb, slwt);
  772. if (err < 0)
  773. goto out_free;
  774. newts->type = LWTUNNEL_ENCAP_SEG6_LOCAL;
  775. newts->flags = LWTUNNEL_STATE_INPUT_REDIRECT;
  776. newts->headroom = slwt->headroom;
  777. *ts = newts;
  778. return 0;
  779. out_free:
  780. kfree(slwt->srh);
  781. kfree(newts);
  782. return err;
  783. }
  784. static void seg6_local_destroy_state(struct lwtunnel_state *lwt)
  785. {
  786. struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
  787. kfree(slwt->srh);
  788. if (slwt->desc->attrs & (1 << SEG6_LOCAL_BPF)) {
  789. kfree(slwt->bpf.name);
  790. bpf_prog_put(slwt->bpf.prog);
  791. }
  792. return;
  793. }
  794. static int seg6_local_fill_encap(struct sk_buff *skb,
  795. struct lwtunnel_state *lwt)
  796. {
  797. struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
  798. struct seg6_action_param *param;
  799. int i, err;
  800. if (nla_put_u32(skb, SEG6_LOCAL_ACTION, slwt->action))
  801. return -EMSGSIZE;
  802. for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
  803. if (slwt->desc->attrs & (1 << i)) {
  804. param = &seg6_action_params[i];
  805. err = param->put(skb, slwt);
  806. if (err < 0)
  807. return err;
  808. }
  809. }
  810. return 0;
  811. }
  812. static int seg6_local_get_encap_size(struct lwtunnel_state *lwt)
  813. {
  814. struct seg6_local_lwt *slwt = seg6_local_lwtunnel(lwt);
  815. unsigned long attrs;
  816. int nlsize;
  817. nlsize = nla_total_size(4); /* action */
  818. attrs = slwt->desc->attrs;
  819. if (attrs & (1 << SEG6_LOCAL_SRH))
  820. nlsize += nla_total_size((slwt->srh->hdrlen + 1) << 3);
  821. if (attrs & (1 << SEG6_LOCAL_TABLE))
  822. nlsize += nla_total_size(4);
  823. if (attrs & (1 << SEG6_LOCAL_NH4))
  824. nlsize += nla_total_size(4);
  825. if (attrs & (1 << SEG6_LOCAL_NH6))
  826. nlsize += nla_total_size(16);
  827. if (attrs & (1 << SEG6_LOCAL_IIF))
  828. nlsize += nla_total_size(4);
  829. if (attrs & (1 << SEG6_LOCAL_OIF))
  830. nlsize += nla_total_size(4);
  831. if (attrs & (1 << SEG6_LOCAL_BPF))
  832. nlsize += nla_total_size(sizeof(struct nlattr)) +
  833. nla_total_size(MAX_PROG_NAME) +
  834. nla_total_size(4);
  835. return nlsize;
  836. }
  837. static int seg6_local_cmp_encap(struct lwtunnel_state *a,
  838. struct lwtunnel_state *b)
  839. {
  840. struct seg6_local_lwt *slwt_a, *slwt_b;
  841. struct seg6_action_param *param;
  842. int i;
  843. slwt_a = seg6_local_lwtunnel(a);
  844. slwt_b = seg6_local_lwtunnel(b);
  845. if (slwt_a->action != slwt_b->action)
  846. return 1;
  847. if (slwt_a->desc->attrs != slwt_b->desc->attrs)
  848. return 1;
  849. for (i = 0; i < SEG6_LOCAL_MAX + 1; i++) {
  850. if (slwt_a->desc->attrs & (1 << i)) {
  851. param = &seg6_action_params[i];
  852. if (param->cmp(slwt_a, slwt_b))
  853. return 1;
  854. }
  855. }
  856. return 0;
  857. }
  858. static const struct lwtunnel_encap_ops seg6_local_ops = {
  859. .build_state = seg6_local_build_state,
  860. .destroy_state = seg6_local_destroy_state,
  861. .input = seg6_local_input,
  862. .fill_encap = seg6_local_fill_encap,
  863. .get_encap_size = seg6_local_get_encap_size,
  864. .cmp_encap = seg6_local_cmp_encap,
  865. .owner = THIS_MODULE,
  866. };
  867. int __init seg6_local_init(void)
  868. {
  869. return lwtunnel_encap_add_ops(&seg6_local_ops,
  870. LWTUNNEL_ENCAP_SEG6_LOCAL);
  871. }
  872. void seg6_local_exit(void)
  873. {
  874. lwtunnel_encap_del_ops(&seg6_local_ops, LWTUNNEL_ENCAP_SEG6_LOCAL);
  875. }