cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rpl.c (3270B)


      1// SPDX-License-Identifier: GPL-2.0-only
      2/*
      3 * Authors:
      4 * (C) 2020 Alexander Aring <alex.aring@gmail.com>
      5 */
      6
      7#include <net/ipv6.h>
      8#include <net/rpl.h>
      9
     10#define IPV6_PFXTAIL_LEN(x) (sizeof(struct in6_addr) - (x))
     11#define IPV6_RPL_BEST_ADDR_COMPRESSION 15
     12
     13static void ipv6_rpl_addr_decompress(struct in6_addr *dst,
     14				     const struct in6_addr *daddr,
     15				     const void *post, unsigned char pfx)
     16{
     17	memcpy(dst, daddr, pfx);
     18	memcpy(&dst->s6_addr[pfx], post, IPV6_PFXTAIL_LEN(pfx));
     19}
     20
     21static void ipv6_rpl_addr_compress(void *dst, const struct in6_addr *addr,
     22				   unsigned char pfx)
     23{
     24	memcpy(dst, &addr->s6_addr[pfx], IPV6_PFXTAIL_LEN(pfx));
     25}
     26
     27static void *ipv6_rpl_segdata_pos(const struct ipv6_rpl_sr_hdr *hdr, int i)
     28{
     29	return (void *)&hdr->rpl_segdata[i * IPV6_PFXTAIL_LEN(hdr->cmpri)];
     30}
     31
     32size_t ipv6_rpl_srh_size(unsigned char n, unsigned char cmpri,
     33			 unsigned char cmpre)
     34{
     35	return (n * IPV6_PFXTAIL_LEN(cmpri)) + IPV6_PFXTAIL_LEN(cmpre);
     36}
     37
     38void ipv6_rpl_srh_decompress(struct ipv6_rpl_sr_hdr *outhdr,
     39			     const struct ipv6_rpl_sr_hdr *inhdr,
     40			     const struct in6_addr *daddr, unsigned char n)
     41{
     42	int i;
     43
     44	outhdr->nexthdr = inhdr->nexthdr;
     45	outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
     46	outhdr->pad = 0;
     47	outhdr->type = inhdr->type;
     48	outhdr->segments_left = inhdr->segments_left;
     49	outhdr->cmpri = 0;
     50	outhdr->cmpre = 0;
     51
     52	for (i = 0; i < n; i++)
     53		ipv6_rpl_addr_decompress(&outhdr->rpl_segaddr[i], daddr,
     54					 ipv6_rpl_segdata_pos(inhdr, i),
     55					 inhdr->cmpri);
     56
     57	ipv6_rpl_addr_decompress(&outhdr->rpl_segaddr[n], daddr,
     58				 ipv6_rpl_segdata_pos(inhdr, n),
     59				 inhdr->cmpre);
     60}
     61
     62static unsigned char ipv6_rpl_srh_calc_cmpri(const struct ipv6_rpl_sr_hdr *inhdr,
     63					     const struct in6_addr *daddr,
     64					     unsigned char n)
     65{
     66	unsigned char plen;
     67	int i;
     68
     69	for (plen = 0; plen < sizeof(*daddr); plen++) {
     70		for (i = 0; i < n; i++) {
     71			if (daddr->s6_addr[plen] !=
     72			    inhdr->rpl_segaddr[i].s6_addr[plen])
     73				return plen;
     74		}
     75	}
     76
     77	return IPV6_RPL_BEST_ADDR_COMPRESSION;
     78}
     79
     80static unsigned char ipv6_rpl_srh_calc_cmpre(const struct in6_addr *daddr,
     81					     const struct in6_addr *last_segment)
     82{
     83	unsigned int plen;
     84
     85	for (plen = 0; plen < sizeof(*daddr); plen++) {
     86		if (daddr->s6_addr[plen] != last_segment->s6_addr[plen])
     87			return plen;
     88	}
     89
     90	return IPV6_RPL_BEST_ADDR_COMPRESSION;
     91}
     92
     93void ipv6_rpl_srh_compress(struct ipv6_rpl_sr_hdr *outhdr,
     94			   const struct ipv6_rpl_sr_hdr *inhdr,
     95			   const struct in6_addr *daddr, unsigned char n)
     96{
     97	unsigned char cmpri, cmpre;
     98	size_t seglen;
     99	int i;
    100
    101	cmpri = ipv6_rpl_srh_calc_cmpri(inhdr, daddr, n);
    102	cmpre = ipv6_rpl_srh_calc_cmpre(daddr, &inhdr->rpl_segaddr[n]);
    103
    104	outhdr->nexthdr = inhdr->nexthdr;
    105	seglen = (n * IPV6_PFXTAIL_LEN(cmpri)) + IPV6_PFXTAIL_LEN(cmpre);
    106	outhdr->hdrlen = seglen >> 3;
    107	if (seglen & 0x7) {
    108		outhdr->hdrlen++;
    109		outhdr->pad = 8 - (seglen & 0x7);
    110	} else {
    111		outhdr->pad = 0;
    112	}
    113	outhdr->type = inhdr->type;
    114	outhdr->segments_left = inhdr->segments_left;
    115	outhdr->cmpri = cmpri;
    116	outhdr->cmpre = cmpre;
    117
    118	for (i = 0; i < n; i++)
    119		ipv6_rpl_addr_compress(ipv6_rpl_segdata_pos(outhdr, i),
    120				       &inhdr->rpl_segaddr[i], cmpri);
    121
    122	ipv6_rpl_addr_compress(ipv6_rpl_segdata_pos(outhdr, n),
    123			       &inhdr->rpl_segaddr[n], cmpre);
    124}