// SPDX-License-Identifier: GPL-2.0-only
/**
 * Authors:
 * (C) 2020 Alexander Aring <alex.aring@gmail.com>
 */

#include <net/ipv6.h>
#include <net/rpl.h>

#define IPV6_PFXTAIL_LEN(x) (sizeof(struct in6_addr) - (x))
#define IPV6_RPL_BEST_ADDR_COMPRESSION 15

static void ipv6_rpl_addr_decompress(struct in6_addr *dst,
				     const struct in6_addr *daddr,
				     const void *post, unsigned char pfx)
{
	memcpy(dst, daddr, pfx);
	memcpy(&dst->s6_addr[pfx], post, IPV6_PFXTAIL_LEN(pfx));
}

static void ipv6_rpl_addr_compress(void *dst, const struct in6_addr *addr,
				   unsigned char pfx)
{
	memcpy(dst, &addr->s6_addr[pfx], IPV6_PFXTAIL_LEN(pfx));
}

static void *ipv6_rpl_segdata_pos(const struct ipv6_rpl_sr_hdr *hdr, int i)
{
	return (void *)&hdr->rpl_segdata[i * IPV6_PFXTAIL_LEN(hdr->cmpri)];
}

size_t ipv6_rpl_srh_size(unsigned char n, unsigned char cmpri,
			 unsigned char cmpre)
{
	return sizeof(struct ipv6_rpl_sr_hdr) + (n * IPV6_PFXTAIL_LEN(cmpri)) +
		IPV6_PFXTAIL_LEN(cmpre);
}

void ipv6_rpl_srh_decompress(struct ipv6_rpl_sr_hdr *outhdr,
			     const struct ipv6_rpl_sr_hdr *inhdr,
			     const struct in6_addr *daddr, unsigned char n)
{
	int i;

	outhdr->nexthdr = inhdr->nexthdr;
	outhdr->hdrlen = (((n + 1) * sizeof(struct in6_addr)) >> 3);
	outhdr->pad = 0;
	outhdr->type = inhdr->type;
	outhdr->segments_left = inhdr->segments_left;
	outhdr->cmpri = 0;
	outhdr->cmpre = 0;

	for (i = 0; i < n; i++)
		ipv6_rpl_addr_decompress(&outhdr->rpl_segaddr[i], daddr,
					 ipv6_rpl_segdata_pos(inhdr, i),
					 inhdr->cmpri);

	ipv6_rpl_addr_decompress(&outhdr->rpl_segaddr[n], daddr,
				 ipv6_rpl_segdata_pos(inhdr, n),
				 inhdr->cmpre);
}

static unsigned char ipv6_rpl_srh_calc_cmpri(const struct ipv6_rpl_sr_hdr *inhdr,
					     const struct in6_addr *daddr,
					     unsigned char n)
{
	unsigned char plen;
	int i;

	for (plen = 0; plen < sizeof(*daddr); plen++) {
		for (i = 0; i < n; i++) {
			if (daddr->s6_addr[plen] !=
			    inhdr->rpl_segaddr[i].s6_addr[plen])
				return plen;
		}
	}

	return IPV6_RPL_BEST_ADDR_COMPRESSION;
}

static unsigned char ipv6_rpl_srh_calc_cmpre(const struct in6_addr *daddr,
					     const struct in6_addr *last_segment)
{
	unsigned int plen;

	for (plen = 0; plen < sizeof(*daddr); plen++) {
		if (daddr->s6_addr[plen] != last_segment->s6_addr[plen])
			return plen;
	}

	return IPV6_RPL_BEST_ADDR_COMPRESSION;
}

void ipv6_rpl_srh_compress(struct ipv6_rpl_sr_hdr *outhdr,
			   const struct ipv6_rpl_sr_hdr *inhdr,
			   const struct in6_addr *daddr, unsigned char n)
{
	unsigned char cmpri, cmpre;
	size_t seglen;
	int i;

	cmpri = ipv6_rpl_srh_calc_cmpri(inhdr, daddr, n);
	cmpre = ipv6_rpl_srh_calc_cmpre(daddr, &inhdr->rpl_segaddr[n]);

	outhdr->nexthdr = inhdr->nexthdr;
	seglen = (n * IPV6_PFXTAIL_LEN(cmpri)) + IPV6_PFXTAIL_LEN(cmpre);
	outhdr->hdrlen = seglen >> 3;
	if (seglen & 0x7) {
		outhdr->hdrlen++;
		outhdr->pad = 8 - (seglen & 0x7);
	} else {
		outhdr->pad = 0;
	}
	outhdr->type = inhdr->type;
	outhdr->segments_left = inhdr->segments_left;
	outhdr->cmpri = cmpri;
	outhdr->cmpre = cmpre;

	for (i = 0; i < n; i++)
		ipv6_rpl_addr_compress(ipv6_rpl_segdata_pos(outhdr, i),
				       &inhdr->rpl_segaddr[i], cmpri);

	ipv6_rpl_addr_compress(ipv6_rpl_segdata_pos(outhdr, n),
			       &inhdr->rpl_segaddr[n], cmpre);
}
