diff --git a/code/include/linux/nip_addr.h b/code/include/linux/nip_addr.h new file mode 100644 index 0000000000000000000000000000000000000000..c43d217b32fe823e55032239048ad37c9bb2a061 --- /dev/null +++ b/code/include/linux/nip_addr.h @@ -0,0 +1,32 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _NIP_ADDR_H +#define _NIP_ADDR_H + +#include + +#endif /* _NIP_ADDR_H */ diff --git a/code/include/net/nip_addrconf.h b/code/include/net/nip_addrconf.h new file mode 100644 index 0000000000000000000000000000000000000000..d38487d10554f270cdfe766de3e564cf925213b3 --- /dev/null +++ b/code/include/net/nip_addrconf.h @@ -0,0 +1,113 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * Based on include/net/addrconf.h + */ +#ifndef _NIP_ADDRCONF_H +#define _NIP_ADDRCONF_H + +#include +#include + +#include +#include +#include +#include + +#define ADDRCONF_NOTIFY_PRIORITY 0 +#define NIN_ADDR_HSIZE_SHIFT (4) +#define NIN_ADDR_HSIZE (1 << NIN_ADDR_HSIZE_SHIFT) + +int nip_addrconf_add_ifaddr(struct net *net, void __user *arg); +int nip_addrconf_del_ifaddr(struct net *net, void __user *arg); + +int nip_dev_get_saddr(struct net *net, const struct net_device *dev, + const struct nip_addr *daddr, struct nip_addr *saddr); + +int nip_addrconf_init(void); +void nip_addrconf_cleanup(void); + +/** + * __nin_dev_get - get ninet_dev pointer from netdevice + * @dev: network device + * + * Caller must hold rcu_read_lock or RTNL, because this function + * does not take a reference on the ninet_dev. + */ +static inline struct ninet_dev *__nin_dev_get(const struct net_device *dev) +{ + return rcu_dereference_rtnl(dev->nip_ptr); +} + +/** + * nin_dev_get - get ninet_dev pointer from netdevice + * @dev: network device + */ +static inline struct ninet_dev *nin_dev_get(const struct net_device *dev) +{ + struct ninet_dev *idev; + + rcu_read_lock(); + idev = rcu_dereference(dev->nip_ptr); + if (idev) + refcount_inc(&idev->refcnt); + rcu_read_unlock(); + return idev; +} + +static inline struct neigh_parms *__nin_dev_nd_parms_get_rcu( + const struct net_device *dev) +{ + struct ninet_dev *idev = __nin_dev_get(dev); + + return idev ? idev->nd_parms : NULL; +} + +void nin_dev_finish_destroy(struct ninet_dev *idev); + +static inline void nin_dev_put(struct ninet_dev *idev) +{ + if (refcount_dec_and_test(&idev->refcnt)) + nin_dev_finish_destroy(idev); +} + +static inline void nin_dev_put_clear(struct ninet_dev **pidev) +{ + struct ninet_dev *idev = *pidev; + + if (idev) { + nin_dev_put(idev); + *pidev = NULL; + } +} + +static inline void __nin_dev_put(struct ninet_dev *idev) +{ + refcount_dec(&idev->refcnt); +} + +static inline void nin_dev_hold(struct ninet_dev *idev) +{ + refcount_inc(&idev->refcnt); +} + +void ninet_ifa_finish_destroy(struct ninet_ifaddr *ifp); + +static inline void nin_ifa_put(struct ninet_ifaddr *ifp) +{ + if (refcount_dec_and_test(&ifp->refcnt)) + ninet_ifa_finish_destroy(ifp); +} + +static inline void __nin_ifa_put(struct ninet_ifaddr *ifp) +{ + refcount_dec(&ifp->refcnt); +} + +static inline void nin_ifa_hold(struct ninet_ifaddr *ifp) +{ + refcount_inc(&ifp->refcnt); +} + +#endif diff --git a/code/include/uapi/linux/nip_addr.h b/code/include/uapi/linux/nip_addr.h new file mode 100644 index 0000000000000000000000000000000000000000..b58a0883ce273aacea09d3739062d751b876f12f --- /dev/null +++ b/code/include/uapi/linux/nip_addr.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _UAPI_NEWIP_ADDR_H +#define _UAPI_NEWIP_ADDR_H + +#define NIP_ADDR_LEN_1 1 +#define NIP_ADDR_LEN_2 2 +#define NIP_ADDR_LEN_3 3 +#define NIP_ADDR_LEN_4 4 +#define NIP_ADDR_LEN_5 5 + +#define NIP_ADDR_BIT_LEN_8 8 +#define NIP_ADDR_BIT_LEN_16 16 +#define NIP_ADDR_BIT_LEN_24 24 +#define NIP_ADDR_BIT_LEN_40 40 +#define NIP_ADDR_BIT_LEN_MAX 64 + +enum nip_addr_check_value { + ADDR_FIRST_DC = 0xDC, + ADDR_FIRST_F0 = 0xF0, + ADDR_FIRST_F1, + ADDR_FIRST_F2, + ADDR_FIRST_F3, + ADDR_FIRST_F4, + ADDR_FIRST_FF = 0xFF, + ADDR_SECOND_MIN_DD = 0xDD, + ADDR_SECOND_MIN_F1 = 0x14, /* f1 14 00 */ + ADDR_THIRD_MIN_F2 = 0x01, /* f2 00 01 00 00 */ +}; + +enum nip_8bit_addr_index { + NIP_8BIT_ADDR_INDEX_0 = 0, + NIP_8BIT_ADDR_INDEX_1 = 1, + NIP_8BIT_ADDR_INDEX_2 = 2, + NIP_8BIT_ADDR_INDEX_3 = 3, + NIP_8BIT_ADDR_INDEX_4 = 4, + NIP_8BIT_ADDR_INDEX_5 = 5, + NIP_8BIT_ADDR_INDEX_6 = 6, + NIP_8BIT_ADDR_INDEX_7 = 7, + NIP_8BIT_ADDR_INDEX_MAX, +}; + +enum nip_16bit_addr_index { + NIP_16BIT_ADDR_INDEX_0 = 0, + NIP_16BIT_ADDR_INDEX_1 = 1, + NIP_16BIT_ADDR_INDEX_2 = 2, + NIP_16BIT_ADDR_INDEX_3 = 3, + NIP_16BIT_ADDR_INDEX_MAX, +}; + +enum nip_32bit_addr_index { + NIP_32BIT_ADDR_INDEX_0 = 0, + NIP_32BIT_ADDR_INDEX_1 = 1, + NIP_32BIT_ADDR_INDEX_MAX, +}; + +#define nip_addr_field8 v.u.u8 +#define nip_addr_field16 v.u.u16 +#define nip_addr_field32 v.u.u32 + +#pragma pack(1) +struct nip_addr_field { + union { + unsigned char u8[NIP_8BIT_ADDR_INDEX_MAX]; + unsigned short u16[NIP_16BIT_ADDR_INDEX_MAX]; /* big-endian */ + unsigned int u32[NIP_32BIT_ADDR_INDEX_MAX]; /* big-endian */ + } u; +}; + +struct nip_addr { + unsigned char bitlen; + struct nip_addr_field v; +}; +#pragma pack() + +#define POD_SOCKADDR_SIZE 10 + +struct sockaddr_nin { + unsigned short sin_family; /* AF_NINET */ + unsigned short sin_port; /* Transport layer port, big-endian */ + struct nip_addr sin_addr; /* NIP address */ + + /* Pad to size of struct sockaddr + * We don't neet to use this field + * Due to the flexible size of nip_addr, we consider the extreme situation: + * the size of nip_addr is 2 bytes, so we need to add 10 bytes to make sure + * it has the same size as struct sockaddr. And it won't have trouble if you + * increase the length of nip_addr. + */ + unsigned char sin_zero[POD_SOCKADDR_SIZE]; +}; + +extern const struct nip_addr nip_any_addr; +extern const struct nip_addr nip_broadcast_addr_arp; + +int nip_addr_invalid(const struct nip_addr *addr); +int nip_addr_public(const struct nip_addr *addr); +int nip_addr_any(const struct nip_addr *ad); +int get_nip_addr_len(const struct nip_addr *addr); +unsigned char *build_nip_addr(const struct nip_addr *addr, unsigned char *buf); +unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr); + +#endif /* _UAPI_NEWIP_ADDR_H */ + diff --git a/code/net/newip/nip_addr.c b/code/net/newip/nip_addr.c new file mode 100644 index 0000000000000000000000000000000000000000..fb41473f3fcffd83211092efd04c42a302aa9939 --- /dev/null +++ b/code/net/newip/nip_addr.c @@ -0,0 +1,270 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include + +/* This is similar to 0.0.0.0 in IPv4. Does not appear as a real address, + * just a constant used by the native for special processing + */ +const struct nip_addr nip_any_addr = { + .bitlen = NIP_ADDR_BIT_LEN_16, + .nip_addr_field8[0] = 0xFF, /* 0xFF09 addr, big-endian */ + .nip_addr_field8[1] = 0x09, +}; + +const struct nip_addr nip_broadcast_addr_arp = { + .bitlen = NIP_ADDR_BIT_LEN_16, + .nip_addr_field8[0] = 0xFF, /* 0xFF04 addr, big-endian */ + .nip_addr_field8[1] = 0x04, +}; + +/* Short address range: + * 【1-byte】0 ~ 220 + * 00 ~ DC + * + * 【2-byte】221 ~ 5119 + * DD/DE/.../F0 is a 2-byte address descriptor followed by the address value + * DDDD ~ DDFF : 221 ~ 255 + * DE00 ~ DEFF : 256 ~ 511 + * DF00 ~ DFFF : 512 ~ 767 + * ... + * F000 ~ F0FF : 4864 ~ 5119 + * + * 【3-byte】5120 ~ 65535 + * F1 is a 3-byte address descriptor followed by the address value + * F1 1400 ~ F1 FFFF + * + * 【5-byte】65536 ~ 4,294,967,295 + * F2 is a 5-byte address descriptor followed by the address value + * F2 0001 0000 ~ F2 FFFF FFFF + * + * 【7-byte】4,294,967,296 ~ 281,474,976,710,655 + * F3 is a 7-byte address descriptor followed by the address value + * F3 0001 0000 0000 ~ F3 FFFF FFFF FFFF + * + * 【9-byte】281,474,976,710,656 ~ xxxx + * F4 is a 9-byte address descriptor followed by the address value + * F4 0001 0000 0000 0000 ~ F4 FFFF FFFF FFFF FFFF + * + * 0xFF00 - The loopback address + * 0xFF01 - Public address for access authentication + * 0xFF02 - Public address of access authentication + * 0xFF03 - The neighbor found a public address + * 0xFF04 - Address resolution (ARP) + * 0xFF05 - DHCP public address + * 0xFF06 - Public address for minimalist access authentication + * 0xFF07 - Self-organizing protocol public address + * 0xFF08 - The IEEE EUI - 64 addresses + * 0xFF09 - any_addr + */ +int nip_addr_invalid(const struct nip_addr *addr) +{ + unsigned char first_byte, second_byte, third_byte; + int addr_len, i, err; + + first_byte = addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_0]; + second_byte = addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_1]; + third_byte = addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_2]; + addr_len = addr->bitlen / NIP_ADDR_BIT_LEN_8; + + /* The value of the field after the effective length of the short address should be 0 */ + for (i = addr_len; i < NIP_8BIT_ADDR_INDEX_MAX; i++) { + if (addr->nip_addr_field8[i] > 0x00) { + /* newip bitlen error */ + err = 1; + return err; + } + } + + if (first_byte <= ADDR_FIRST_DC && addr_len == NIP_ADDR_LEN_1) { + err = 0; + } else if (first_byte <= ADDR_FIRST_F0 && addr_len == NIP_ADDR_LEN_2) { + if (first_byte > ADDR_FIRST_DC + 1 || + second_byte >= ADDR_SECOND_MIN_DD) { + err = 0; + } else { + /* addr2 is not valid */ + err = 1; + } + } else if (first_byte == ADDR_FIRST_F1 && addr_len == NIP_ADDR_LEN_3) { + if (second_byte >= ADDR_SECOND_MIN_F1) { + err = 0; + } else { + /* addr3 is not valid */ + err = 1; + } + } else if (first_byte == ADDR_FIRST_F2 && addr_len == NIP_ADDR_LEN_5) { + if (second_byte > 0 || third_byte >= ADDR_THIRD_MIN_F2) { + err = 0; + } else { + /* addr5 is not valid */ + err = 1; + } + } else if (first_byte == ADDR_FIRST_FF && addr_len == NIP_ADDR_LEN_2) { + err = 0; + } else { + /* addr check fail */ + err = 1; + } + return err; +} + +/* 0xFF00 - The loopback address + * 0xFF01 - Public address for access authentication + * 0xFF02 - Public address of access authentication + * 0xFF03 - The neighbor found a public address + * 0xFF04 - Address resolution (ARP) + * 0xFF05 - DHCP public address + * 0xFF06 - Public address for minimalist access authentication + * 0xFF07 - Self-organizing protocol public address + * 0xFF08 - The IEEE EUI - 64 addresses + * 0xFF09 - any_addr + */ +int nip_addr_public(const struct nip_addr *addr) +{ + if (addr->bitlen == NIP_ADDR_BIT_LEN_16 && + addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_0] == ADDR_FIRST_FF) + return 1; + else + return 0; +} + +/* judge whether the nip_addr is equal to 0xFF09 */ +int nip_addr_any(const struct nip_addr *ad) +{ + int result = 0; + + if (ad->bitlen == NIP_ADDR_BIT_LEN_16) { + if (ad->nip_addr_field16[0] == nip_any_addr.nip_addr_field16[0] && + ad->nip_addr_field16[1] == nip_any_addr.nip_addr_field16[1]) + result = 1; + } + return result; +} + +int get_nip_addr_len(const struct nip_addr *addr) +{ + int len = 0; + + if (addr->nip_addr_field8[0] <= ADDR_FIRST_DC) + len = NIP_ADDR_LEN_1; + else if ((addr->nip_addr_field8[0] > ADDR_FIRST_DC && + addr->nip_addr_field8[0] <= ADDR_FIRST_F0) || + addr->nip_addr_field8[0] == ADDR_FIRST_FF) + len = NIP_ADDR_LEN_2; + else if (addr->nip_addr_field8[0] == ADDR_FIRST_F1) + len = NIP_ADDR_LEN_3; + else if (addr->nip_addr_field8[0] == ADDR_FIRST_F2) + len = NIP_ADDR_LEN_5; + else + return 0; + return len; +} + +unsigned char *build_nip_addr(const struct nip_addr *addr, unsigned char *buf) +{ + unsigned char *p = buf; + int i; + + if (addr->nip_addr_field8[0] <= ADDR_FIRST_DC) { + *p = addr->nip_addr_field8[0]; + } else if (((addr->nip_addr_field8[0] > ADDR_FIRST_DC) && + (addr->nip_addr_field8[0] <= ADDR_FIRST_F0)) || + (addr->nip_addr_field8[0] == ADDR_FIRST_FF)) { + *p = addr->nip_addr_field8[0]; + p++; + *p = addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_1]; + } else if (addr->nip_addr_field8[0] == ADDR_FIRST_F1) { + for (i = 0; i < NIP_ADDR_LEN_2; i++) { + *p = addr->nip_addr_field8[i]; + p++; + } + *p = addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_2]; + } else if (addr->nip_addr_field8[0] == ADDR_FIRST_F2) { + for (i = 0; i < NIP_ADDR_LEN_4; i++) { + *p = addr->nip_addr_field8[i]; + p++; + } + *p = addr->nip_addr_field8[NIP_8BIT_ADDR_INDEX_4]; + } else { + return 0; + } + + return ++p; +} + +unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr) +{ + unsigned char *p = buf; + int i; + + if (*p <= ADDR_FIRST_DC) { + addr->nip_addr_field8[0] = *p; + p++; + addr->bitlen = NIP_ADDR_BIT_LEN_8; + } else if (*p > ADDR_FIRST_DC && *p <= ADDR_FIRST_F0) { + if (*p > ADDR_FIRST_DC + 1 || *(p + 1) >= ADDR_SECOND_MIN_DD) { + addr->nip_addr_field8[0] = *p; + p++; + addr->nip_addr_field8[1] = *p; + p++; + addr->bitlen = NIP_ADDR_BIT_LEN_16; + } else { + return 0; + } + } else if (*p == ADDR_FIRST_F1) { + if (*(p + 1) >= ADDR_SECOND_MIN_F1) { + for (i = 0; i < NIP_ADDR_LEN_3; i++) { + addr->nip_addr_field8[i] = *p; + p++; + } + addr->bitlen = NIP_ADDR_BIT_LEN_24; + } else { + return 0; + } + } else if (*p == ADDR_FIRST_F2) { + if (*(p + 1) > 0 || *(p + 2) >= ADDR_THIRD_MIN_F2) { /* 偏移2 */ + for (i = 0; i < NIP_ADDR_LEN_5; i++) { + addr->nip_addr_field8[i] = *p; + p++; + } + addr->bitlen = NIP_ADDR_BIT_LEN_40; + } else { + return 0; + } + } else if (*p == ADDR_FIRST_FF) { + addr->nip_addr_field8[0] = *p; + p++; + addr->nip_addr_field8[1] = *p; + p++; + addr->bitlen = NIP_ADDR_BIT_LEN_16; + } else { + return 0; + } + + return p; +} + diff --git a/code/net/newip/nip_addrconf_core.c b/code/net/newip/nip_addrconf_core.c new file mode 100644 index 0000000000000000000000000000000000000000..12d104dde28a2b834dca8c9c66a150fdef00047e --- /dev/null +++ b/code/net/newip/nip_addrconf_core.c @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * NewIP library code, needed by static components when full NewIP support is + * not configured or static. + * + * Based on net/ipv6/addrconf_core.c + */ +#include +#include +#include +#include + +static void nin_dev_finish_destroy_rcu(struct rcu_head *head) +{ + struct ninet_dev *idev = container_of(head, struct ninet_dev, rcu); + + kfree(idev); +} + +void nin_dev_finish_destroy(struct ninet_dev *idev) +{ + struct net_device *dev = idev->dev; + + WARN_ON(!list_empty(&idev->addr_list)); + + dev_put(dev); + if (!idev->dead) { + DEBUG(KERN_WARNING "Freeing alive ninet device.\n"); + return; + } + call_rcu(&idev->rcu, nin_dev_finish_destroy_rcu); +} + diff --git a/code/net/newip/nip_checksum.c b/code/net/newip/nip_checksum.c new file mode 100644 index 0000000000000000000000000000000000000000..437e52bdfb2d5d5ac7bae700a20c7f374d45ae9a --- /dev/null +++ b/code/net/newip/nip_checksum.c @@ -0,0 +1,117 @@ +// SPDX-License-Identifier: BSD-2-Clause +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include +#include "nip_hdr.h" +#include "nip_checksum.h" + +#define USHORT_PAYLOAD 16 +#define NIP_CHECKSUM_UINT8_PAYLOAD 8 +unsigned int _nip_check_sum(unsigned char *data, unsigned short data_len) +{ + unsigned int i = 0, sum = 0; + + while (i + 1 < data_len) { + sum += (data[i] << NIP_CHECKSUM_UINT8_PAYLOAD) + data[i + 1]; + i += 2; /* Offset 2 bytes */ + } + + if (i < (unsigned int)data_len) + sum += (data[i] << NIP_CHECKSUM_UINT8_PAYLOAD); + + return sum; +} + +unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header) +{ + int i, j; + int addr_len; + unsigned char pseudo_header[NIP_HDR_MAX] = {0}; + unsigned short hdr_len = 0; + + addr_len = chksum_header->saddr.bitlen / NIP_ADDR_BIT_LEN_8; + if (addr_len) { + j = 0; + for (i = 0; i < addr_len; i++, j++) + pseudo_header[j] = chksum_header->saddr.nip_addr_field8[i]; + hdr_len += addr_len; + } + + addr_len = chksum_header->daddr.bitlen / NIP_ADDR_BIT_LEN_8; + if (addr_len) { + j = hdr_len; + for (i = 0; i < addr_len; i++, j++) + pseudo_header[j] = chksum_header->daddr.nip_addr_field8[i]; + hdr_len += addr_len; + } + + /* chksum_header->check_len is network order.(big end) */ + *(unsigned short *)(pseudo_header + hdr_len) = chksum_header->check_len; + hdr_len += sizeof(chksum_header->check_len); + *(pseudo_header + hdr_len) = chksum_header->nexthdr; + hdr_len += sizeof(chksum_header->nexthdr); + + return _nip_check_sum(pseudo_header, hdr_len); +} + +/* The checksum is calculated when the packet is received + * Note: + * 1.chksum_header->check_len is network order.(big end) + * 2.check_len is host order. + */ +unsigned short nip_check_sum_parse(unsigned char *data, + unsigned short check_len, + struct nip_pseudo_header *chksum_header) +{ + unsigned int sum = 0; + + sum = _nip_check_sum(data, check_len); + sum += _nip_header_chksum(chksum_header); + + while (sum >> USHORT_PAYLOAD) + sum = (sum >> USHORT_PAYLOAD) + (sum & 0xffff); + return (unsigned short)sum; +} + +/* The checksum is calculated when the packet is sent + * Note: + * 1.chksum_header->check_len is network order.(big end) + * 2.data_len is host order. + */ +unsigned short nip_check_sum_build(unsigned char *data, + unsigned short data_len, + struct nip_pseudo_header *chksum_header) +{ + unsigned int sum = 0; + + sum = _nip_check_sum(data, data_len); + sum += _nip_header_chksum(chksum_header); + + while (sum >> USHORT_PAYLOAD) + sum = (sum >> USHORT_PAYLOAD) + (sum & 0xffff); + return (unsigned short)(~sum); +} + diff --git a/code/net/newip/nip_checksum.h b/code/net/newip/nip_checksum.h new file mode 100644 index 0000000000000000000000000000000000000000..97a359f3ada5ff4d74c8f46d5da389b0dc18d874 --- /dev/null +++ b/code/net/newip/nip_checksum.h @@ -0,0 +1,58 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * + * Redistribution and use in source and binary forms, with or without modification, + * are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this list of + * conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, this list + * of conditions and the following disclaimer in the documentation and/or other materials + * provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, + * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; + * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef _NIP_CHECKSUM_H +#define _NIP_CHECKSUM_H + +#include + +struct nip_pseudo_header { + struct nip_addr saddr; /* Source address, network order.(big end) */ + struct nip_addr daddr; /* Destination address, network order.(big end) */ + unsigned short check_len; /* network order.(big end) */ + unsigned char nexthdr; /* Upper-layer Protocol Type: IPPROTO_UDP */ +}; + +/* The checksum is calculated when the packet is received + * Note: + * 1.chksum_header->check_len is network order.(big end) + * 2.data_len is host order. + */ +unsigned short nip_check_sum_parse(unsigned char *data, + unsigned short check_len, + struct nip_pseudo_header *chksum_header); + +/* The checksum is calculated when the packet is sent + * Note: + * 1.chksum_header->check_len is network order.(big end) + * 2.data_len is host order. + */ +unsigned short nip_check_sum_build(unsigned char *data, + unsigned short data_len, + struct nip_pseudo_header *chksum_header); + +#endif /* _NIP_CHECKSUM_H */ +