mirror of
https://github.com/openharmony/kernel_linux_common_modules.git
synced 2026-08-27 09:41:18 -04:00
NewIP code security issue remediation
1.Resolved read out of bounds caused by skb_len flip 2.Resolve the getsockopt TCP_MD5SIG null pointer reference problem 3.Resolve the NEWIP null pointer reference problem Signed-off-by: liangbotong <liangbotong@huawei.com>
This commit is contained in:
@@ -403,21 +403,26 @@ unsigned char *build_nip_addr(const struct nip_addr *addr, unsigned char *buf)
|
||||
return p;
|
||||
}
|
||||
|
||||
unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr)
|
||||
unsigned char *decode_nip_addr(struct nip_buff *nbuf, struct nip_addr *addr)
|
||||
{
|
||||
int i;
|
||||
int ret;
|
||||
int addr_len;
|
||||
unsigned char *p = buf;
|
||||
|
||||
addr->NIP_ADDR_FIELD8[0] = *p;
|
||||
if (nbuf->remaining_len < sizeof(unsigned char))
|
||||
return 0;
|
||||
|
||||
addr->NIP_ADDR_FIELD8[0] = *nbuf->data;
|
||||
addr_len = get_nip_addr_len(addr);
|
||||
if (addr_len == 0)
|
||||
return 0;
|
||||
|
||||
if (nbuf->remaining_len < addr_len)
|
||||
return 0;
|
||||
|
||||
for (i = 0; i < addr_len; i++) {
|
||||
addr->NIP_ADDR_FIELD8[i] = *p;
|
||||
p++;
|
||||
addr->NIP_ADDR_FIELD8[i] = *nbuf->data;
|
||||
nip_buff_pull(nbuf, sizeof(unsigned char));
|
||||
}
|
||||
addr->bitlen = addr_len * NIP_ADDR_BIT_LEN_8;
|
||||
|
||||
@@ -425,6 +430,6 @@ unsigned char *decode_nip_addr(unsigned char *buf, struct nip_addr *addr)
|
||||
if (ret)
|
||||
return 0;
|
||||
|
||||
return p;
|
||||
return nbuf->data;
|
||||
}
|
||||
|
||||
|
||||
@@ -109,12 +109,26 @@ enum nip_index {
|
||||
extern const struct nip_addr nip_any_addr;
|
||||
extern const struct nip_addr nip_broadcast_addr_arp;
|
||||
|
||||
struct nip_buff {
|
||||
unsigned char *data;
|
||||
unsigned int remaining_len;
|
||||
};
|
||||
|
||||
static inline void nip_buff_pull(struct nip_buff *nbuf, unsigned int len)
|
||||
{
|
||||
if (len > nbuf->remaining_len)
|
||||
return;
|
||||
|
||||
nbuf->data += len;
|
||||
nbuf->remaining_len -= len;
|
||||
}
|
||||
|
||||
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 *addr);
|
||||
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);
|
||||
unsigned char *decode_nip_addr(struct nip_buff *nbuf, struct nip_addr *addr);
|
||||
int is_nip_local_addr(const struct nip_addr *addr);
|
||||
|
||||
#endif /* _UAPI_NEWIP_ADDR_H */
|
||||
|
||||
@@ -38,7 +38,7 @@ unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header)
|
||||
unsigned short hdr_len = 0;
|
||||
|
||||
addr_len = chksum_header->saddr.bitlen / NIP_ADDR_BIT_LEN_8;
|
||||
if (addr_len) {
|
||||
if (addr_len && addr_len < NIP_HDR_MAX) {
|
||||
j = 0;
|
||||
for (i = 0; i < addr_len; i++, j++)
|
||||
pseudo_header[j] = chksum_header->saddr.NIP_ADDR_FIELD8[i];
|
||||
@@ -46,7 +46,7 @@ unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header)
|
||||
}
|
||||
|
||||
addr_len = chksum_header->daddr.bitlen / NIP_ADDR_BIT_LEN_8;
|
||||
if (addr_len) {
|
||||
if (addr_len && addr_len < NIP_HDR_MAX) {
|
||||
j = hdr_len;
|
||||
for (i = 0; i < addr_len; i++, j++)
|
||||
pseudo_header[j] = chksum_header->daddr.NIP_ADDR_FIELD8[i];
|
||||
@@ -54,10 +54,15 @@ unsigned int _nip_header_chksum(struct nip_pseudo_header *chksum_header)
|
||||
}
|
||||
|
||||
/* 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);
|
||||
if (hdr_len < NIP_HDR_MAX) {
|
||||
*(unsigned short *)(pseudo_header + hdr_len) = chksum_header->check_len;
|
||||
hdr_len += sizeof(chksum_header->check_len);
|
||||
}
|
||||
|
||||
if (hdr_len < NIP_HDR_MAX) {
|
||||
*(pseudo_header + hdr_len) = chksum_header->nexthdr;
|
||||
hdr_len += sizeof(chksum_header->nexthdr);
|
||||
}
|
||||
|
||||
return _nip_check_sum(pseudo_header, hdr_len);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@
|
||||
*/
|
||||
#define NIP_HDR_MAX 24
|
||||
#define NIP_UDP_HDR_LEN 8
|
||||
#define NIP_MIN_MTU (NIP_HDR_MAX + NIP_UDP_HDR_LEN)
|
||||
#define NIP_TCP_HDR_LEN 20
|
||||
#define NIP_MIN_MTU (NIP_HDR_MAX + NIP_TCP_HDR_LEN)
|
||||
#define NIP_BYTE_ALIGNMENT 2
|
||||
|
||||
#define NIP_BITMAP_HAVE_MORE_BIT 0x01
|
||||
|
||||
@@ -12,81 +12,98 @@
|
||||
#include "nip_hdr.h"
|
||||
|
||||
/* Must carry the current field */
|
||||
static int _get_nip_hdr_bitmap(unsigned char *buf,
|
||||
static int _get_nip_hdr_bitmap(struct nip_buff *nbuf,
|
||||
unsigned char bitmap[],
|
||||
unsigned char bitmap_index_max)
|
||||
{
|
||||
int i = 0;
|
||||
unsigned char *p = buf;
|
||||
|
||||
if (*p & NIP_BITMAP_INVALID_SET)
|
||||
if (nbuf->remaining_len < sizeof(unsigned char))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
if (*nbuf->data & NIP_BITMAP_INVALID_SET)
|
||||
return -NIP_HDR_BITMAP_INVALID;
|
||||
|
||||
do {
|
||||
if (i >= bitmap_index_max)
|
||||
return -NIP_HDR_BITMAP_NUM_OUT_RANGE;
|
||||
|
||||
bitmap[i] = *p;
|
||||
p++;
|
||||
if (nbuf->remaining_len < sizeof(unsigned char))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
bitmap[i] = *nbuf->data;
|
||||
nip_buff_pull(nbuf, sizeof(unsigned char));
|
||||
} while (bitmap[i++] & NIP_BITMAP_HAVE_MORE_BIT);
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/* Must carry the current field */
|
||||
static int _get_nip_hdr_ttl(const unsigned char *buf,
|
||||
static int _get_nip_hdr_ttl(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
if (!(bitmap & NIP_BITMAP_INCLUDE_TTL))
|
||||
return -NIP_HDR_NO_TTL;
|
||||
|
||||
niph->ttl = *buf;
|
||||
niph->include_ttl = 1;
|
||||
if (nbuf->remaining_len < sizeof(niph->ttl))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
return sizeof(niph->ttl);
|
||||
niph->ttl = *nbuf->data;
|
||||
niph->include_ttl = 1;
|
||||
nip_buff_pull(nbuf, sizeof(niph->ttl));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Optional fields */
|
||||
/* Communication between devices of the same version may not carry packet Header length,
|
||||
* but communication between devices of different versions must carry packet header length
|
||||
*/
|
||||
static int _get_nip_hdr_len(const unsigned char *buf,
|
||||
static int _get_nip_hdr_len(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
if (!(bitmap & NIP_BITMAP_INCLUDE_HDR_LEN))
|
||||
return 0;
|
||||
|
||||
if (nbuf->remaining_len < sizeof(niph->hdr_len))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
/* Total_len is a network sequence and cannot be
|
||||
* compared directly with the local sequence
|
||||
*/
|
||||
niph->hdr_len = *buf;
|
||||
niph->hdr_len = *nbuf->data;
|
||||
niph->include_hdr_len = 1;
|
||||
nip_buff_pull(nbuf, sizeof(niph->hdr_len));
|
||||
|
||||
if (niph->include_total_len && niph->hdr_len >= niph->rcv_buf_len)
|
||||
return -NIP_HDR_LEN_OUT_RANGE;
|
||||
|
||||
return sizeof(niph->hdr_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Must carry the current field */
|
||||
static int _get_nip_hdr_nexthdr(const unsigned char *buf,
|
||||
static int _get_nip_hdr_nexthdr(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
if (!(bitmap & NIP_BITMAP_INCLUDE_NEXT_HDR))
|
||||
return -NIP_HDR_NO_NEXT_HDR;
|
||||
|
||||
niph->nexthdr = *buf;
|
||||
niph->include_nexthdr = 1;
|
||||
if (nbuf->remaining_len < sizeof(niph->nexthdr))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
return sizeof(niph->nexthdr);
|
||||
niph->nexthdr = *nbuf->data;
|
||||
niph->include_nexthdr = 1;
|
||||
nip_buff_pull(nbuf, sizeof(niph->nexthdr));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Must carry the current field */
|
||||
/* Note: niph->saddr is network order.(big end) */
|
||||
static int _get_nip_hdr_daddr(unsigned char *buf,
|
||||
static int _get_nip_hdr_daddr(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
@@ -95,7 +112,7 @@ static int _get_nip_hdr_daddr(unsigned char *buf,
|
||||
if (!(bitmap & NIP_BITMAP_INCLUDE_DADDR))
|
||||
return -NIP_HDR_NO_DADDR;
|
||||
|
||||
p = decode_nip_addr(buf, &niph->daddr);
|
||||
p = decode_nip_addr(nbuf, &niph->daddr);
|
||||
if (!p)
|
||||
return -NIP_HDR_DECAP_DADDR_ERR;
|
||||
|
||||
@@ -103,12 +120,12 @@ static int _get_nip_hdr_daddr(unsigned char *buf,
|
||||
return -NIP_HDR_DADDR_INVALID;
|
||||
|
||||
niph->include_daddr = 1;
|
||||
return (niph->daddr.bitlen / NIP_ADDR_BIT_LEN_8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Optional fields */
|
||||
/* Note: niph->daddr is network order.(big end) */
|
||||
static int _get_nip_hdr_saddr(unsigned char *buf,
|
||||
static int _get_nip_hdr_saddr(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
@@ -117,7 +134,7 @@ static int _get_nip_hdr_saddr(unsigned char *buf,
|
||||
if (!(bitmap & NIP_BITMAP_INCLUDE_SADDR))
|
||||
return 0;
|
||||
|
||||
p = decode_nip_addr(buf, &niph->saddr);
|
||||
p = decode_nip_addr(nbuf, &niph->saddr);
|
||||
if (!p)
|
||||
return -NIP_HDR_DECAP_SADDR_ERR;
|
||||
|
||||
@@ -125,84 +142,80 @@ static int _get_nip_hdr_saddr(unsigned char *buf,
|
||||
return -NIP_HDR_SADDR_INVALID;
|
||||
|
||||
niph->include_saddr = 1;
|
||||
return (niph->saddr.bitlen / NIP_ADDR_BIT_LEN_8);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Optional fields: tcp/arp need, udp needless */
|
||||
/* Note: niph->total_len is network order.(big end), need change to host order */
|
||||
static int _get_nip_total_len(unsigned char *buf,
|
||||
static int _get_nip_total_len(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
if (!(bitmap & NIP_BITMAP_INCLUDE_TOTAL_LEN))
|
||||
return 0;
|
||||
|
||||
if (nbuf->remaining_len < sizeof(niph->total_len))
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
/* Total_len is a network sequence and cannot be
|
||||
* compared directly with the local sequence
|
||||
*/
|
||||
niph->total_len = *((unsigned short *)buf);
|
||||
niph->total_len = *((unsigned short *)nbuf->data);
|
||||
niph->include_total_len = 1;
|
||||
nip_buff_pull(nbuf, sizeof(niph->total_len));
|
||||
|
||||
return sizeof(niph->total_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _nip_hdr_bitmap0_parse(unsigned char *buf,
|
||||
static int _nip_hdr_bitmap0_parse(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
int len;
|
||||
int len_total = 0;
|
||||
int err;
|
||||
|
||||
len = _get_nip_hdr_ttl(buf, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_ttl(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
/* Optional fields */
|
||||
len = _get_nip_total_len(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_total_len(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
len = _get_nip_hdr_nexthdr(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_nexthdr(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
len = _get_nip_hdr_daddr(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_daddr(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
len = _get_nip_hdr_saddr(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_saddr(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return len_total;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _nip_hdr_bitmap1_parse(unsigned char *buf,
|
||||
static int _nip_hdr_bitmap1_parse(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
int len;
|
||||
int len_total = 0;
|
||||
int err;
|
||||
|
||||
/* If add new field needs to be modified with the macro definition */
|
||||
if (bitmap & NIP_INVALID_BITMAP_2)
|
||||
niph->include_unknown_bit = 1;
|
||||
|
||||
/* Optional fields */
|
||||
len = _get_nip_hdr_len(buf + len_total, bitmap, niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
len_total += len;
|
||||
err = _get_nip_hdr_len(nbuf, bitmap, niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return len_total;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _nip_hdr_unknown_bit_check(unsigned char *buf,
|
||||
static int _nip_hdr_unknown_bit_check(struct nip_buff *nbuf,
|
||||
unsigned char bitmap,
|
||||
struct nip_hdr_decap *niph)
|
||||
{
|
||||
@@ -211,7 +224,7 @@ static int _nip_hdr_unknown_bit_check(unsigned char *buf,
|
||||
}
|
||||
|
||||
#define FACTORY_NUM_MAX 3
|
||||
static int (*hdr_parse_factory[FACTORY_NUM_MAX])(unsigned char *,
|
||||
static int (*hdr_parse_factory[FACTORY_NUM_MAX])(struct nip_buff *,
|
||||
unsigned char,
|
||||
struct nip_hdr_decap *) = {
|
||||
_nip_hdr_bitmap0_parse,
|
||||
@@ -242,33 +255,37 @@ int nip_hdr_parse(unsigned char *rcv_buf, unsigned int buf_len, struct nip_hdr_d
|
||||
{
|
||||
int i = 0;
|
||||
int ret;
|
||||
unsigned char *buf = rcv_buf;
|
||||
unsigned char bitmap[BITMAP_MAX] = {0};
|
||||
int num = _get_nip_hdr_bitmap(buf, bitmap, BITMAP_MAX);
|
||||
int num;
|
||||
struct nip_buff nbuf;
|
||||
|
||||
if (num <= 0 || !rcv_buf)
|
||||
nbuf.data = rcv_buf;
|
||||
if (!nbuf.data)
|
||||
return 0;
|
||||
|
||||
nbuf.remaining_len = buf_len;
|
||||
num = _get_nip_hdr_bitmap(&nbuf, bitmap, BITMAP_MAX);
|
||||
if (num <= 0)
|
||||
return num;
|
||||
|
||||
niph->hdr_real_len = num * sizeof(bitmap[0]);
|
||||
buf += niph->hdr_real_len;
|
||||
|
||||
niph->rcv_buf_len = buf_len;
|
||||
while (i < num) {
|
||||
int len;
|
||||
int err;
|
||||
|
||||
if (i >= FACTORY_NUM_MAX)
|
||||
break;
|
||||
len = hdr_parse_factory[i](buf, bitmap[i], niph);
|
||||
if (len < 0)
|
||||
return len;
|
||||
|
||||
buf += len;
|
||||
niph->hdr_real_len += len;
|
||||
if (niph->hdr_real_len >= buf_len)
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
err = hdr_parse_factory[i](&nbuf, bitmap[i], niph);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
if (buf_len < nbuf.remaining_len)
|
||||
return -NIP_HDR_RCV_BUF_READ_OUT_RANGE;
|
||||
|
||||
niph->hdr_real_len = buf_len - nbuf.remaining_len;
|
||||
ret = nip_hdr_check(niph);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
@@ -128,6 +128,15 @@ static inline void _nip_hdr_encap_comm_bitmap(struct nip_hdr_encap *head)
|
||||
|
||||
void nip_hdr_udp_encap(struct nip_hdr_encap *head)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
len = get_nip_hdr_len(NIP_HDR_UDP, &head->saddr, &head->daddr);
|
||||
if (len == 0 || len > NIP_HDR_MAX)
|
||||
return;
|
||||
|
||||
/* Encapsulate the bitmap into the newIP packet header BUF */
|
||||
#if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1)
|
||||
_nip_hdr_encap_udp_bitmap(head);
|
||||
@@ -146,6 +155,15 @@ void nip_hdr_udp_encap(struct nip_hdr_encap *head)
|
||||
/* need update total len after this func, call nip_update_total_len */
|
||||
void nip_hdr_comm_encap(struct nip_hdr_encap *head)
|
||||
{
|
||||
int len;
|
||||
|
||||
if (!head)
|
||||
return;
|
||||
|
||||
len = get_nip_hdr_len(NIP_HDR_COMM, &head->saddr, &head->daddr);
|
||||
if (len == 0 || len > NIP_HDR_MAX)
|
||||
return;
|
||||
|
||||
/* Encapsulate the bitmap into the newIP packet header BUF */
|
||||
#if (NEWIP_BYTE_ALIGNMENT_ENABLE == 1)
|
||||
_nip_hdr_encap_comm_bitmap(head);
|
||||
|
||||
@@ -195,15 +195,15 @@ static ssize_t bt_io_file_read(struct file *filp,
|
||||
btdev_dbg_err("%s invalid skb", cdev_name(vnet));
|
||||
return -EINVAL;
|
||||
}
|
||||
out_sz = skb->len - MACADDR_LEN;
|
||||
if (unlikely(out_sz > size)) {
|
||||
out_sz = skb->len > MACADDR_LEN ? (skb->len - MACADDR_LEN) : 0;
|
||||
if (unlikely(out_sz > size) || unlikely(out_sz == 0)) {
|
||||
/* Obtain the skb pointer from the ring buf and ask whether the user-state buf
|
||||
* length can store data in the skb. If the user-state buf length is not enough,
|
||||
* the skb cannot be released at this time, because the skb is still unchained
|
||||
* on the ring buf.
|
||||
*/
|
||||
btdev_dbg_err("%s usr-buf too small, skb-len=%ld, usr-buf-len=%ld",
|
||||
cdev_name(vnet), (long)out_sz, (long)size);
|
||||
btdev_dbg_err("%s usr-buf too small, skb-len=%ld, usr-buf-len=%ld, skb-len=%u",
|
||||
cdev_name(vnet), (long)out_sz, (long)size, skb->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -854,8 +854,10 @@ static int bt_ring_is_full(const struct bt_ring *ring)
|
||||
static void bt_ring_produce(struct bt_ring *ring, void *data)
|
||||
{
|
||||
smp_mb(); // Make sure the read and write order is correct
|
||||
ring->data[ring->head] = data;
|
||||
ring->head = (ring->head + 1) % ring->size;
|
||||
if (likely(ring->head < ring->size)) {
|
||||
ring->data[ring->head] = data;
|
||||
ring->head = (ring->head + 1) % ring->size;
|
||||
}
|
||||
smp_wmb(); // Make sure the write order is correct
|
||||
}
|
||||
|
||||
@@ -863,7 +865,7 @@ static void *bt_ring_current(struct bt_ring *ring)
|
||||
{
|
||||
void *data = NULL;
|
||||
|
||||
if (unlikely(!ring))
|
||||
if (unlikely(!ring) || unlikely(ring->tail > ring->size))
|
||||
return data;
|
||||
|
||||
data = ring->data[ring->tail];
|
||||
|
||||
@@ -221,6 +221,9 @@ static inline const char *bt_virnet_get_ndev_name(const struct bt_virnet *vn)
|
||||
|
||||
static inline const char *bt_virnet_get_state_rep(const struct bt_virnet *vn)
|
||||
{
|
||||
if (unlikely(vn->state > BT_VIRNET_STAET_NUM))
|
||||
return g_bt_virnet_state_rep[BT_VIRNET_STATE_DELETED];
|
||||
|
||||
return g_bt_virnet_state_rep[vn->state];
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,9 @@
|
||||
*/
|
||||
void nip_ninet_ehashfn(const struct sock *sk, u32 *ret)
|
||||
{
|
||||
if (!sk || !ret)
|
||||
return;
|
||||
|
||||
*ret = ninet_ehashfn(sock_net(sk), &sk->SK_NIP_RCV_SADDR,
|
||||
sk->sk_num, &sk->SK_NIP_DADDR, sk->sk_dport);
|
||||
}
|
||||
|
||||
@@ -163,6 +163,12 @@ static inline struct tcp_nip_request_sock *tcp_nip_rsk(const struct request_sock
|
||||
return (struct tcp_nip_request_sock *)req;
|
||||
}
|
||||
|
||||
static inline void tcp_nip_modify_send_head(struct sock *sk, const struct sk_buff *skb)
|
||||
{
|
||||
if (tcp_skb_is_last(sk, skb))
|
||||
sk->sk_send_head = NULL;
|
||||
}
|
||||
|
||||
/* connect */
|
||||
int __tcp_nip_connect(struct sock *sk);
|
||||
int _tcp_nip_conn_request(struct request_sock_ops *rsk_ops,
|
||||
|
||||
+22
-2
@@ -45,9 +45,16 @@
|
||||
int nip_icmp_rcv(struct sk_buff *skb)
|
||||
{
|
||||
int ret = 0;
|
||||
struct nip_icmp_hdr *hdr = nip_icmp_header(skb);
|
||||
u8 type = hdr->nip_icmp_type;
|
||||
struct nip_icmp_hdr *hdr;
|
||||
u8 type;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct nip_icmp_hdr))) {
|
||||
nip_dbg("invalid ICMP packet");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdr = nip_icmp_header(skb);
|
||||
type = hdr->nip_icmp_type;
|
||||
nip_dbg("rcv newip icmp packet. type=%u", type);
|
||||
switch (type) {
|
||||
case NIP_ARP_NS:
|
||||
@@ -60,7 +67,20 @@ int nip_icmp_rcv(struct sk_buff *skb)
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void nip_icmp_early_demux(struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_icmp_err_handler(struct sk_buff *skb,
|
||||
struct ninet_skb_parm *opt,
|
||||
u8 type, u8 code,
|
||||
int offset, __be32 info)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct ninet_protocol nip_icmp_protocol = {
|
||||
.early_demux = nip_icmp_early_demux,
|
||||
.err_handler = nip_icmp_err_handler,
|
||||
.handler = nip_icmp_rcv,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
@@ -241,7 +241,8 @@ static void ninet_unhash2(struct inet_hashinfo *h, struct sock *sk)
|
||||
|
||||
spin_lock(&ilb2->lock);
|
||||
hlist_del_init_rcu(&inet_csk(sk)->icsk_listen_portaddr_node);
|
||||
ilb2->count--;
|
||||
if (ilb2->count)
|
||||
ilb2->count--;
|
||||
spin_unlock(&ilb2->lock);
|
||||
}
|
||||
|
||||
@@ -254,7 +255,8 @@ static void __ninet_unhash(struct sock *sk, struct inet_listen_hashbucket *ilb)
|
||||
struct inet_hashinfo *hashinfo = sk->sk_prot->h.hashinfo;
|
||||
|
||||
ninet_unhash2(hashinfo, sk);
|
||||
ilb->count--;
|
||||
if (ilb->count)
|
||||
ilb->count--;
|
||||
}
|
||||
__sk_nulls_del_node_init_rcu(sk);
|
||||
sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
|
||||
@@ -311,10 +313,9 @@ struct sock *__ninet_lookup_established(struct net *net,
|
||||
const struct hlist_nulls_node *node;
|
||||
|
||||
const __portpair ports = INET_COMBINED_PORTS(sport, hnum);
|
||||
|
||||
/* mask ensures that the hash index is valid without memory overruns */
|
||||
unsigned int hash = ninet_ehashfn(net, daddr, hnum, saddr, sport);
|
||||
unsigned int slot = hash & hashinfo->ehash_mask;
|
||||
|
||||
struct inet_ehash_bucket *head = &hashinfo->ehash[slot];
|
||||
|
||||
begin:
|
||||
@@ -434,7 +435,7 @@ struct sock *ninet_lookup_listener(struct net *net,
|
||||
saddr, sport, &nip_any_addr, hnum,
|
||||
dif, sdif);
|
||||
done:
|
||||
if (IS_ERR(result))
|
||||
if (IS_ERR_OR_NULL(result))
|
||||
return NULL;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -88,6 +88,7 @@ struct nip_fib_node *nip_fib_locate(struct hlist_head *nip_tb_head,
|
||||
struct hlist_head *h;
|
||||
unsigned int hash;
|
||||
|
||||
/* hash calc ensures that the hash index is valid without memory overruns */
|
||||
hash = ninet_route_hash(daddr);
|
||||
h = &nip_tb_head[hash];
|
||||
|
||||
@@ -97,6 +98,7 @@ struct nip_fib_node *nip_fib_locate(struct hlist_head *nip_tb_head,
|
||||
}
|
||||
|
||||
/* find default route */
|
||||
/* hash calc ensures that the hash index is valid without memory overruns */
|
||||
hash = ninet_route_hash(&nip_any_addr);
|
||||
h = &nip_tb_head[hash];
|
||||
|
||||
@@ -139,6 +141,7 @@ int nip_fib_add(struct nip_fib_table *table, struct nip_rt_info *rt)
|
||||
char dst[NIP_ADDR_BIT_LEN_MAX] = {0};
|
||||
char gateway[NIP_ADDR_BIT_LEN_MAX] = {0};
|
||||
|
||||
/* hash calc ensures that the hash index is valid without memory overruns */
|
||||
hash = ninet_route_hash(&rt->rt_dst);
|
||||
h = &table->nip_tb_head[hash];
|
||||
|
||||
|
||||
+1
-1
@@ -101,7 +101,7 @@ int nip_rcv(struct sk_buff *skb, struct net_device *dev,
|
||||
|
||||
memset(nipcb(skb), 0, sizeof(struct ninet_skb_parm));
|
||||
offset = nip_hdr_parse(skb->data, skb->len, &niph);
|
||||
if (offset <= 0) {
|
||||
if (offset <= 0 || offset > skb->len) {
|
||||
nip_dbg("check in failure, errcode=%d, Drop a packet (nexthdr=%u, hdr_len=%u)",
|
||||
offset, niph.nexthdr, niph.hdr_len);
|
||||
goto drop;
|
||||
|
||||
+6
-3
@@ -54,15 +54,18 @@ void update_memory_rate(const char *upper_fun)
|
||||
struct sysinfo mem_info;
|
||||
unsigned long total;
|
||||
unsigned long free;
|
||||
unsigned long used;
|
||||
unsigned int uint_kb;
|
||||
|
||||
si_meminfo(&mem_info);
|
||||
uint_kb = mem_info.mem_unit / NIP_BIT_TO_BYTE;
|
||||
total = (unsigned long)mem_info.totalram * uint_kb;
|
||||
free = (unsigned long)mem_info.freeram * uint_kb;
|
||||
used = total - free;
|
||||
nip_dbg("%s call cur-func mem total: %ld KB, mem used: %ld KB", upper_fun, total, used);
|
||||
if (total > free)
|
||||
nip_dbg("%s call cur-func mem total: %ld KB, mem used: %ld KB",
|
||||
upper_fun, total, total - free);
|
||||
else
|
||||
nip_dbg("%s call cur-func mem total: %ld KB, mem free: %ld KB",
|
||||
upper_fun, total, free);
|
||||
}
|
||||
|
||||
int nip_output(struct net *net, struct sock *sk, struct sk_buff *skb)
|
||||
|
||||
+57
-6
@@ -87,11 +87,16 @@ static void nndisc_error_report(struct neighbour *neigh, struct sk_buff *skb)
|
||||
kfree_skb(skb);
|
||||
}
|
||||
|
||||
static void nndisc_generic_error_report(struct neighbour *neigh, struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct neigh_ops nndisc_generic_ops = {
|
||||
.family = AF_NINET,
|
||||
.solicit = nndisc_solicit,
|
||||
.output = neigh_resolve_output,
|
||||
.connected_output = neigh_connected_output,
|
||||
.error_report = nndisc_generic_error_report,
|
||||
};
|
||||
|
||||
static const struct neigh_ops nndisc_hh_ops = {
|
||||
@@ -121,6 +126,15 @@ static const struct neigh_ops nndisc_direct_ops = {
|
||||
#define NIP_NEIGH_GC_THRESH_2 512
|
||||
#define NIP_NEIGH_GC_THRESH_3 1024
|
||||
|
||||
static void nndisc_proxy_redo(struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static int nndisc_is_multicast(const void *pkey)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct neigh_table nnd_tbl = {
|
||||
.family = AF_NINET,
|
||||
.key_len = sizeof(struct nip_addr),
|
||||
@@ -128,6 +142,8 @@ struct neigh_table nnd_tbl = {
|
||||
.hash = nndisc_hash,
|
||||
.key_eq = nndisc_key_eq,
|
||||
.constructor = nndisc_constructor,
|
||||
.proxy_redo = nndisc_proxy_redo,
|
||||
.is_multicast = nndisc_is_multicast,
|
||||
.id = "nndisc_cache",
|
||||
.parms = {
|
||||
.tbl = &nnd_tbl,
|
||||
@@ -495,16 +511,27 @@ out:
|
||||
|
||||
int nndisc_rcv_ns(struct sk_buff *skb)
|
||||
{
|
||||
struct nnd_msg *msg = (struct nnd_msg *)skb_transport_header(skb);
|
||||
u_char *p = msg->data;
|
||||
struct nnd_msg *msg;
|
||||
u_char *p;
|
||||
u_char *lladdr;
|
||||
struct nip_addr addr = {0};
|
||||
struct neighbour *neigh;
|
||||
struct ethhdr *eth;
|
||||
struct net_device *dev = skb->dev;
|
||||
int err = 0;
|
||||
struct nip_buff nbuf;
|
||||
|
||||
p = decode_nip_addr(p, &addr);
|
||||
if (!pskb_may_pull(skb, sizeof(struct nnd_msg))) {
|
||||
nip_dbg("invalid ns packet");
|
||||
err = -EFAULT;
|
||||
goto out;
|
||||
}
|
||||
|
||||
msg = (struct nnd_msg *)skb->data;
|
||||
nbuf.data = msg->data;
|
||||
nbuf.remaining_len = skb->len - sizeof(struct nip_icmp_hdr);
|
||||
|
||||
p = decode_nip_addr(&nbuf, &addr);
|
||||
if (!p) {
|
||||
nip_dbg("failure when decode source address");
|
||||
err = -EFAULT;
|
||||
@@ -526,7 +553,7 @@ int nndisc_rcv_ns(struct sk_buff *skb)
|
||||
lladdr = eth->h_source;
|
||||
|
||||
/* checksum parse */
|
||||
if (!nip_get_nndisc_rcv_checksum(skb, p)) {
|
||||
if (!nip_get_nndisc_rcv_checksum(skb, nbuf.data)) {
|
||||
nip_dbg("ns ICMP checksum failed, drop the packet");
|
||||
err = -EINVAL;
|
||||
goto out;
|
||||
@@ -546,16 +573,40 @@ out:
|
||||
|
||||
int nndisc_rcv_na(struct sk_buff *skb)
|
||||
{
|
||||
struct nnd_msg *msg = (struct nnd_msg *)skb_transport_header(skb);
|
||||
u_char *p = msg->data;
|
||||
struct nnd_msg *msg;
|
||||
u_char *p;
|
||||
u_char len;
|
||||
u8 lladdr[ALIGN(MAX_ADDR_LEN, sizeof(unsigned long))];
|
||||
struct net_device *dev = skb->dev;
|
||||
struct neighbour *neigh;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct nnd_msg))) {
|
||||
nip_dbg("invalid na packet");
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msg = (struct nnd_msg *)skb->data;
|
||||
p = msg->data;
|
||||
if (skb->len - sizeof(struct nip_icmp_hdr) < sizeof(unsigned char)) {
|
||||
nip_dbg("invalid msg data");
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
len = *p;
|
||||
if (len > MAX_ADDR_LEN) {
|
||||
nip_dbg("invalid length, drop the packet(len=%u)", len);
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
p++;
|
||||
memset(lladdr, 0, ALIGN(MAX_ADDR_LEN, sizeof(unsigned long)));
|
||||
if (skb->len - sizeof(struct nip_icmp_hdr) - sizeof(unsigned char) < len) {
|
||||
nip_dbg("invalid msg data");
|
||||
kfree_skb(skb);
|
||||
return -EINVAL;
|
||||
}
|
||||
memcpy(lladdr, p, len);
|
||||
|
||||
if (!nip_get_nndisc_rcv_checksum(skb, p + len)) {
|
||||
|
||||
+299
-42
@@ -400,6 +400,7 @@
|
||||
#include <net/nip_route.h>
|
||||
#include <linux/nip.h>
|
||||
#include "nip_checksum.h"
|
||||
#include "nip_hdr.h"
|
||||
#include "tcp_nip_parameter.h"
|
||||
|
||||
#define tcp_header_length(th) ((th)->doff << 2)
|
||||
@@ -449,9 +450,14 @@ bool nip_get_tcp_input_checksum(struct sk_buff *skb)
|
||||
|
||||
static int tcp_nip_close_state(struct sock *sk)
|
||||
{
|
||||
int next = (int)new_state[sk->sk_state];
|
||||
int ns = next & TCP_STATE_MASK;
|
||||
int next;
|
||||
int ns;
|
||||
|
||||
if (sk->sk_state >= TCP_MAX_STATES)
|
||||
return TCP_ACTION_FIN;
|
||||
|
||||
next = (int)new_state[sk->sk_state];
|
||||
ns = next & TCP_STATE_MASK;
|
||||
tcp_set_state(sk, ns);
|
||||
|
||||
return next & TCP_ACTION_FIN;
|
||||
@@ -787,29 +793,69 @@ static void tcp_nip_reqsk_destructor(struct request_sock *req)
|
||||
;
|
||||
}
|
||||
|
||||
static void tcp_nip_reqsk_send_ack(const struct sock *sk, struct sk_buff *skb,
|
||||
struct request_sock *req)
|
||||
{
|
||||
}
|
||||
|
||||
static void tcp_nip_reqsk_send_reset(const struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static void tcp_nip_reqsk_syn_ack_timeout(const struct request_sock *req)
|
||||
{
|
||||
}
|
||||
|
||||
struct request_sock_ops tcp_nip_request_sock_ops __read_mostly = {
|
||||
.family = AF_NINET,
|
||||
.obj_size = sizeof(struct tcp_nip_request_sock),
|
||||
.rtx_syn_ack = tcp_nip_rtx_synack,
|
||||
.send_ack = NULL,
|
||||
.destructor = tcp_nip_reqsk_destructor,
|
||||
.send_reset = NULL,
|
||||
.syn_ack_timeout = NULL,
|
||||
.family = AF_NINET,
|
||||
.obj_size = sizeof(struct tcp_nip_request_sock),
|
||||
.rtx_syn_ack = tcp_nip_rtx_synack,
|
||||
.send_ack = tcp_nip_reqsk_send_ack,
|
||||
.destructor = tcp_nip_reqsk_destructor,
|
||||
.send_reset = tcp_nip_reqsk_send_reset,
|
||||
.syn_ack_timeout = tcp_nip_reqsk_syn_ack_timeout,
|
||||
};
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
static int nip_calc_md5_hash(char *location, const struct tcp_md5sig_key *md5,
|
||||
const struct sock *sk, const struct sk_buff *skb)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static struct tcp_md5sig_key *nip_req_md5_lookup(const struct sock *sk,
|
||||
const struct sock *addr_sk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef CONFIG_SYN_COOKIES
|
||||
static __u32 nip_cookie_init_seq(const struct sk_buff *skb, __u16 *mss)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
static u32 tcp_nip_init_ts_off(const struct net *net, const struct sk_buff *skb)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct tcp_request_sock_ops tcp_request_sock_newip_ops = {
|
||||
.mss_clamp = TCP_BASE_MSS,
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
.req_md5_lookup = NULL,
|
||||
.calc_md5_hash = NULL,
|
||||
.req_md5_lookup = nip_req_md5_lookup,
|
||||
.calc_md5_hash = nip_calc_md5_hash,
|
||||
#endif
|
||||
.init_req = tcp_nip_init_req,
|
||||
#ifdef CONFIG_SYN_COOKIES
|
||||
.cookie_init_seq = NULL,
|
||||
.cookie_init_seq = nip_cookie_init_seq,
|
||||
#endif
|
||||
.route_req = tcp_nip_route_req,
|
||||
.init_seq = tcp_nip_init_sequence,
|
||||
.send_synack = tcp_nip_send_synack,
|
||||
.init_ts_off = tcp_nip_init_ts_off,
|
||||
};
|
||||
|
||||
/* Function
|
||||
@@ -935,21 +981,37 @@ put_and_exit:
|
||||
goto out;
|
||||
}
|
||||
|
||||
static const struct inet_connection_sock_af_ops newip_specific = {
|
||||
.queue_xmit = tcp_nip_queue_xmit,
|
||||
.send_check = NULL,
|
||||
.rebuild_header = NULL,
|
||||
.sk_rx_dst_set = ninet_sk_rx_dst_set,
|
||||
.conn_request = tcp_nip_conn_request,
|
||||
.syn_recv_sock = tcp_nip_syn_recv_sock,
|
||||
.net_header_len = 0,
|
||||
.net_frag_header_len = 0,
|
||||
.setsockopt = nip_setsockopt,
|
||||
.getsockopt = nip_getsockopt,
|
||||
.addr2sockaddr = NULL,
|
||||
.sockaddr_len = sizeof(struct sockaddr_nin),
|
||||
static void tcp_nip_send_check(struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
.mtu_reduced = NULL,
|
||||
static int tcp_nip_rebuild_header(struct sock *sk)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void nip_addr2sockaddr(struct sock *sk, struct sockaddr *addr)
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_mtu_reduced(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct inet_connection_sock_af_ops newip_specific = {
|
||||
.queue_xmit = tcp_nip_queue_xmit,
|
||||
.send_check = tcp_nip_send_check,
|
||||
.rebuild_header = tcp_nip_rebuild_header,
|
||||
.sk_rx_dst_set = ninet_sk_rx_dst_set,
|
||||
.conn_request = tcp_nip_conn_request,
|
||||
.syn_recv_sock = tcp_nip_syn_recv_sock,
|
||||
.net_header_len = 0,
|
||||
.net_frag_header_len = 0,
|
||||
.setsockopt = nip_setsockopt,
|
||||
.getsockopt = nip_getsockopt,
|
||||
.addr2sockaddr = nip_addr2sockaddr,
|
||||
.sockaddr_len = sizeof(struct sockaddr_nin),
|
||||
.mtu_reduced = nip_mtu_reduced,
|
||||
};
|
||||
|
||||
#if IS_ENABLED(CONFIG_NEWIP_FAST_KEEPALIVE)
|
||||
@@ -1135,6 +1197,162 @@ static void tcp_sock_priv_init(struct sock *sk)
|
||||
_tcp_sock_priv_init(sk);
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_init(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_release(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
static u32 nip_icsk_ca_ssthresh(struct sock *sk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_cong_avoid(struct sock *sk, u32 ack, u32 acked)
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_set_state(struct sock *sk, u8 new_state)
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_cwnd_event(struct sock *sk, enum tcp_ca_event ev)
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_in_ack_event(struct sock *sk, u32 flags)
|
||||
{
|
||||
}
|
||||
|
||||
static u32 nip_icsk_ca_undo_cwnd(struct sock *sk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_pkts_acked(struct sock *sk, const struct ack_sample *sample)
|
||||
{
|
||||
}
|
||||
|
||||
static u32 nip_icsk_ca_min_tso_segs(struct sock *sk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 nip_icsk_ca_sndbuf_expand(struct sock *sk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nip_icsk_ca_cong_control(struct sock *sk, const struct rate_sample *rs)
|
||||
{
|
||||
}
|
||||
|
||||
static size_t nip_icsk_ca_get_info(struct sock *sk, u32 ext, int *attr,
|
||||
union tcp_cc_info *info)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nip_icsk_ulp_init(struct sock *sk)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void nip_icsk_ulp_update(struct sock *sk, struct proto *p,
|
||||
void (*write_space)(struct sock *sk))
|
||||
{
|
||||
}
|
||||
|
||||
static void nip_icsk_ulp_release(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
static int nip_icsk_ulp_get_info(const struct sock *sk, struct sk_buff *skb)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static size_t nip_icsk_ulp_get_info_size(const struct sock *sk)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nip_icsk_ulp_clone(const struct request_sock *req, struct sock *newsk,
|
||||
const gfp_t priority)
|
||||
{
|
||||
}
|
||||
|
||||
static struct module nip_owner;
|
||||
|
||||
struct tcp_ulp_ops nip_icsk_ulp_ops = {
|
||||
.init = nip_icsk_ulp_init,
|
||||
.update = nip_icsk_ulp_update,
|
||||
.release = nip_icsk_ulp_release,
|
||||
.get_info = nip_icsk_ulp_get_info,
|
||||
.get_info_size = nip_icsk_ulp_get_info_size,
|
||||
.clone = nip_icsk_ulp_clone,
|
||||
.owner = &nip_owner,
|
||||
};
|
||||
|
||||
struct tcp_congestion_ops nip_icsk_ca_ops = {
|
||||
.init = nip_icsk_ca_init,
|
||||
.release = nip_icsk_ca_release,
|
||||
.ssthresh = nip_icsk_ca_ssthresh,
|
||||
.cong_avoid = nip_icsk_ca_cong_avoid,
|
||||
.set_state = nip_icsk_ca_set_state,
|
||||
.cwnd_event = nip_icsk_ca_cwnd_event,
|
||||
.in_ack_event = nip_icsk_ca_in_ack_event,
|
||||
.undo_cwnd = nip_icsk_ca_undo_cwnd,
|
||||
.pkts_acked = nip_icsk_ca_pkts_acked,
|
||||
.min_tso_segs = nip_icsk_ca_min_tso_segs,
|
||||
.sndbuf_expand = nip_icsk_ca_sndbuf_expand,
|
||||
.cong_control = nip_icsk_ca_cong_control,
|
||||
.get_info = nip_icsk_ca_get_info,
|
||||
};
|
||||
|
||||
static void nip_icsk_clean_acked(struct sock *sk, u32 acked_seq)
|
||||
{
|
||||
}
|
||||
|
||||
static void inet_connection_sock_pre_init(struct inet_connection_sock *icsk)
|
||||
{
|
||||
icsk->icsk_ca_ops = &nip_icsk_ca_ops;
|
||||
icsk->icsk_ulp_ops = &nip_icsk_ulp_ops;
|
||||
icsk->icsk_clean_acked = nip_icsk_clean_acked;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
struct tcp_md5sig_key *nip_md5_lookup(const struct sock *sk,
|
||||
const struct sock *addr_sk)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nip_md5_parse(struct sock *sk, int optname, sockptr_t optval,
|
||||
int optlen)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
const struct tcp_sock_af_ops nip_af_specific = {
|
||||
.md5_lookup = nip_md5_lookup,
|
||||
.calc_md5_hash = nip_calc_md5_hash,
|
||||
.md5_parse = nip_md5_parse,
|
||||
};
|
||||
|
||||
struct tcp_md5sig_info __rcu nip_md5sig_info;
|
||||
#endif
|
||||
|
||||
static void tcp_sock_pre_init(struct tcp_sock *tp)
|
||||
{
|
||||
#ifdef CONFIG_TCP_MD5SIG
|
||||
tp->af_specific = &nip_af_specific;
|
||||
tp->md5sig_info = &nip_md5sig_info;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Function
|
||||
* Example Initialize sock information in TCP
|
||||
* Parameter
|
||||
@@ -1153,6 +1371,8 @@ static int tcp_nip_init_sock(struct sock *sk)
|
||||
tcp_nip_init_xmit_timers(sk);
|
||||
INIT_LIST_HEAD(&tp->tsq_node);
|
||||
|
||||
inet_connection_sock_pre_init(icsk);
|
||||
tcp_sock_pre_init(tp);
|
||||
icsk->icsk_rto = get_nip_rto() == 0 ? TCP_TIMEOUT_INIT : (HZ / get_nip_rto());
|
||||
icsk->icsk_rto_min = TCP_RTO_MIN;
|
||||
icsk->icsk_delack_max = TCP_DELACK_MAX;
|
||||
@@ -1206,13 +1426,15 @@ static unsigned int tcp_xmit_size_goal(struct sock *sk, u32 mss_now,
|
||||
int large_allowed)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
u32 new_size_goal, size_goal;
|
||||
u32 new_size_goal = NIP_MIN_MTU;
|
||||
u32 size_goal;
|
||||
|
||||
if (!large_allowed || !mss_now)
|
||||
return mss_now;
|
||||
|
||||
/* Note : tcp_tso_autosize() will eventually split this later */
|
||||
new_size_goal = sk->sk_gso_max_size - 1 - MAX_TCP_HEADER;
|
||||
if (sk->sk_gso_max_size > MAX_TCP_HEADER + 1)
|
||||
new_size_goal = sk->sk_gso_max_size - 1 - MAX_TCP_HEADER;
|
||||
new_size_goal = tcp_bound_to_half_wnd(tp, new_size_goal);
|
||||
|
||||
/* We try hard to avoid divides here */
|
||||
@@ -1352,6 +1574,7 @@ out:
|
||||
|
||||
do_fault:
|
||||
if (!skb->len) {
|
||||
tcp_nip_modify_send_head(sk, skb);
|
||||
tcp_unlink_write_queue(skb, sk);
|
||||
sk_wmem_free_skb(sk, skb);
|
||||
}
|
||||
@@ -1703,6 +1926,26 @@ static bool tcp_nip_add_backlog(struct sock *sk, struct sk_buff *skb)
|
||||
return false;
|
||||
}
|
||||
|
||||
static int nip_skb_precheck(struct sk_buff *skb)
|
||||
{
|
||||
if (!pskb_may_pull(skb, sizeof(struct tcphdr))) {
|
||||
nip_dbg("invalid tcp packet length, drop the packet(skb->len=%u)", skb->len);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (skb->pkt_type != PACKET_HOST) {
|
||||
nip_dbg("unknown pkt-type(%u), drop skb", skb->pkt_type);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!nip_get_tcp_input_checksum(skb)) {
|
||||
nip_dbg("checksum fail, drop skb");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Function
|
||||
* TCP is the gateway from the network layer to the transport layer
|
||||
* and receives data packets from the network layer
|
||||
@@ -1713,19 +1956,12 @@ static int tcp_nip_rcv(struct sk_buff *skb)
|
||||
{
|
||||
const struct tcphdr *th;
|
||||
bool refcounted;
|
||||
struct sock *sk;
|
||||
struct sock *sk = NULL;
|
||||
int ret;
|
||||
int dif = skb->skb_iif;
|
||||
|
||||
if (skb->pkt_type != PACKET_HOST) {
|
||||
nip_dbg("unknown pkt-type(%u), drop skb", skb->pkt_type);
|
||||
if (nip_skb_precheck(skb))
|
||||
goto discard_it;
|
||||
}
|
||||
|
||||
if (!nip_get_tcp_input_checksum(skb)) {
|
||||
nip_dbg("checksum fail, drop skb");
|
||||
goto discard_it;
|
||||
}
|
||||
|
||||
th = (const struct tcphdr *)skb->data;
|
||||
|
||||
@@ -1733,6 +1969,8 @@ static int tcp_nip_rcv(struct sk_buff *skb)
|
||||
nip_dbg("non-four byte alignment, drop skb");
|
||||
goto discard_it;
|
||||
}
|
||||
if (!pskb_may_pull(skb, th->doff * 4))
|
||||
goto discard_it;
|
||||
|
||||
sk = __ninet_lookup_skb(&tcp_hashinfo, skb, __tcp_hdrlen(th),
|
||||
th->source, th->dest, dif, &refcounted);
|
||||
@@ -1814,7 +2052,7 @@ put_and_return:
|
||||
|
||||
no_tcp_socket:
|
||||
tcp_nip_send_reset(NULL, skb);
|
||||
goto discard_it;
|
||||
|
||||
discard_it:
|
||||
kfree_skb(skb);
|
||||
return 0;
|
||||
@@ -1997,10 +2235,22 @@ struct sock *ninet_csk_accept(struct sock *sk, int flags, int *err, bool kern)
|
||||
return newsk;
|
||||
}
|
||||
|
||||
static int tcp_nip_sendpage(struct sock *sk, struct page *page, int offset, size_t size,
|
||||
int flags)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int tcp_nip_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
struct proto tcp_nip_prot = {
|
||||
.name = "NIP_TCP",
|
||||
.owner = THIS_MODULE,
|
||||
.close = tcp_nip_close,
|
||||
.pre_connect = tcp_nip_pre_connect,
|
||||
.connect = tcp_nip_connect,
|
||||
.disconnect = tcp_nip_disconnect,
|
||||
.accept = ninet_csk_accept,
|
||||
@@ -2013,7 +2263,7 @@ struct proto tcp_nip_prot = {
|
||||
.keepalive = tcp_set_keepalive,
|
||||
.recvmsg = tcp_nip_recvmsg,
|
||||
.sendmsg = tcp_nip_sendmsg,
|
||||
.sendpage = NULL,
|
||||
.sendpage = tcp_nip_sendpage,
|
||||
.backlog_rcv = tcp_nip_do_rcv,
|
||||
.release_cb = tcp_nip_release_cb,
|
||||
.hash = ninet_hash,
|
||||
@@ -2033,10 +2283,17 @@ struct proto tcp_nip_prot = {
|
||||
.no_autobind = true,
|
||||
};
|
||||
|
||||
static void tcp_nip_err_handler(struct sk_buff *skb,
|
||||
struct ninet_skb_parm *opt,
|
||||
u8 type, u8 code, int offset, __be32 info)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct ninet_protocol tcp_nip_protocol = {
|
||||
.early_demux = tcp_nip_early_demux,
|
||||
.handler = tcp_nip_rcv,
|
||||
.flags = 0,
|
||||
.early_demux = tcp_nip_early_demux,
|
||||
.handler = tcp_nip_rcv,
|
||||
.err_handler = tcp_nip_err_handler,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
static struct inet_protosw tcp_nip_protosw = {
|
||||
|
||||
+69
-6
@@ -817,6 +817,7 @@ static int tcp_nip_clean_rtx_queue(struct sock *sk, ktime_t *skb_snd_tstamp)
|
||||
if (*skb_snd_tstamp == 0)
|
||||
*skb_snd_tstamp = skb->tstamp;
|
||||
|
||||
tcp_nip_modify_send_head(sk, skb);
|
||||
tcp_unlink_write_queue(skb, sk);
|
||||
sk_wmem_free_skb(sk, skb);
|
||||
}
|
||||
@@ -1379,7 +1380,8 @@ static void tcp_nip_dup_ack_retrans(struct sock *sk, const struct sk_buff *skb,
|
||||
*/
|
||||
int mss = tcp_nip_current_mss(sk);
|
||||
struct tcphdr *th = (struct tcphdr *)skb->data;
|
||||
u16 discard_num = htons(th->urg_ptr);
|
||||
u16 discard_num = htons(th->urg_ptr) > PKT_DISCARD_MAX ?
|
||||
0 : htons(th->urg_ptr);
|
||||
u32 last_nip_ssthresh = ntp->nip_ssthresh;
|
||||
|
||||
if (tp->selective_acks[0].end_seq)
|
||||
@@ -1567,7 +1569,56 @@ static void tcp_nip_ack_calc_ssthresh(struct sock *sk, u32 ack, int icsk_rto_las
|
||||
}
|
||||
}
|
||||
|
||||
static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb)
|
||||
static bool __tcp_nip_oow_rate_limited(struct net *net, int mib_idx, u32 *last_oow_ack_time)
|
||||
{
|
||||
if (*last_oow_ack_time) {
|
||||
s32 elapsed = (s32)(tcp_jiffies32 - *last_oow_ack_time);
|
||||
|
||||
if (elapsed >= 0 &&
|
||||
elapsed < READ_ONCE(net->ipv4.sysctl_tcp_invalid_ratelimit)) {
|
||||
NET_INC_STATS(net, mib_idx);
|
||||
return true; /* rate-limited: don't send yet! */
|
||||
}
|
||||
}
|
||||
|
||||
*last_oow_ack_time = tcp_jiffies32;
|
||||
|
||||
return false; /* not rate-limited: go ahead, send dupack now! */
|
||||
}
|
||||
|
||||
static void tcp_nip_send_challenge_ack(struct sock *sk, const struct sk_buff *skb)
|
||||
{
|
||||
/* unprotected vars, we dont care of overwrites */
|
||||
static u32 nip_challenge_timestamp;
|
||||
static unsigned int nip_challenge_count;
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct net *net = sock_net(sk);
|
||||
u32 count, now;
|
||||
|
||||
/* First check our per-socket dupack rate limit. */
|
||||
if (__tcp_nip_oow_rate_limited(net,
|
||||
LINUX_MIB_TCPACKSKIPPEDCHALLENGE,
|
||||
&tp->last_oow_ack_time))
|
||||
return;
|
||||
|
||||
/* Then check host-wide RFC 5961 rate limit. */
|
||||
now = jiffies / HZ;
|
||||
if (now != READ_ONCE(nip_challenge_timestamp)) {
|
||||
u32 ack_limit = READ_ONCE(net->ipv4.sysctl_tcp_challenge_ack_limit);
|
||||
u32 half = (ack_limit + 1) >> 1;
|
||||
|
||||
WRITE_ONCE(nip_challenge_timestamp, now);
|
||||
WRITE_ONCE(nip_challenge_count, half + prandom_u32_max(ack_limit));
|
||||
}
|
||||
count = READ_ONCE(nip_challenge_count);
|
||||
if (count > 0) {
|
||||
WRITE_ONCE(nip_challenge_count, count - 1);
|
||||
NET_INC_STATS(net, LINUX_MIB_TCPCHALLENGEACK);
|
||||
tcp_nip_send_ack(sk);
|
||||
}
|
||||
}
|
||||
|
||||
static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb, int flag)
|
||||
{
|
||||
struct tcp_sock *tp = tcp_sk(sk);
|
||||
struct tcp_nip_common *ntp = &tcp_nip_sk(sk)->common;
|
||||
@@ -1578,8 +1629,15 @@ static int tcp_nip_ack(struct sock *sk, const struct sk_buff *skb)
|
||||
int prior_packets = tp->packets_out;
|
||||
ktime_t skb_snd_tstamp = 0;
|
||||
|
||||
if (before(ack, prior_snd_una))
|
||||
if (before(ack, prior_snd_una)) {
|
||||
if (before(ack, prior_snd_una - tp->max_window)) {
|
||||
if (!(flag & FLAG_NO_CHALLENGE_ACK))
|
||||
tcp_nip_send_challenge_ack(sk, skb);
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (after(ack, tp->snd_nxt))
|
||||
return -1;
|
||||
|
||||
@@ -1730,10 +1788,13 @@ void tcp_nip_rcv_established(struct sock *sk, struct sk_buff *skb,
|
||||
if (unlikely(!rcu_access_pointer(sk->sk_rx_dst)))
|
||||
inet_csk(sk)->icsk_af_ops->sk_rx_dst_set(sk, skb);
|
||||
|
||||
if (skb->len < (th->doff << 2))
|
||||
return;
|
||||
|
||||
if (!tcp_nip_validate_incoming(sk, skb, th, 1))
|
||||
return;
|
||||
|
||||
if (tcp_nip_ack(sk, skb) < 0)
|
||||
if (tcp_nip_ack(sk, skb, FLAG_SLOWPATH | FLAG_UPDATE_TS_RECENT) < 0)
|
||||
goto discard;
|
||||
|
||||
tcp_nip_data_queue(sk, skb);
|
||||
@@ -1863,7 +1924,7 @@ static int tcp_nip_rcv_synsent_state_process(struct sock *sk, struct sk_buff *sk
|
||||
|
||||
tcp_init_wl(tp, TCP_SKB_CB(skb)->seq);
|
||||
|
||||
tcp_nip_ack(sk, skb);
|
||||
tcp_nip_ack(sk, skb, FLAG_SLOWPATH);
|
||||
tp->out_of_order_queue = RB_ROOT;
|
||||
/* The next data number expected to be accepted is +1 */
|
||||
tp->rcv_nxt = TCP_SKB_CB(skb)->seq + 1;
|
||||
@@ -1992,7 +2053,9 @@ int tcp_nip_rcv_state_process(struct sock *sk, struct sk_buff *skb)
|
||||
if (!tcp_nip_validate_incoming(sk, skb, th, 0))
|
||||
return 0;
|
||||
|
||||
acceptable = tcp_nip_ack(sk, skb);
|
||||
acceptable = tcp_nip_ack(sk, skb, FLAG_SLOWPATH |
|
||||
FLAG_UPDATE_TS_RECENT |
|
||||
FLAG_NO_CHALLENGE_ACK) > 0;
|
||||
/* If the third handshake ACK is invalid, 1 is returned
|
||||
* and the SKB is discarded in tcp_nip_rcv
|
||||
*/
|
||||
|
||||
+76
-27
@@ -231,6 +231,7 @@ struct sock *__nip_udp_lib_lookup(struct net *net,
|
||||
struct udp_hslot *hslot2;
|
||||
struct sock *result;
|
||||
|
||||
/* mask ensures that the hash index is valid without memory overruns */
|
||||
hash2 = nip_udp_portaddr_hash(net, daddr, hnum);
|
||||
slot2 = hash2 & udptable->mask;
|
||||
hslot2 = &udptable->hash2[slot2];
|
||||
@@ -243,6 +244,7 @@ struct sock *__nip_udp_lib_lookup(struct net *net,
|
||||
goto done;
|
||||
|
||||
/* Lookup wildcard sockets */
|
||||
/* mask ensures that the hash index is valid without memory overruns */
|
||||
hash2 = nip_udp_portaddr_hash(net, &nip_any_addr, hnum);
|
||||
slot2 = hash2 & udptable->mask;
|
||||
hslot2 = &udptable->hash2[slot2];
|
||||
@@ -362,13 +364,27 @@ bool nip_get_udp_input_checksum(struct sk_buff *skb)
|
||||
int nip_udp_input(struct sk_buff *skb)
|
||||
{
|
||||
struct sock *sk;
|
||||
int rc = 0;
|
||||
struct udphdr *udphead = udp_hdr(skb);
|
||||
int rc = -EINVAL;
|
||||
struct udphdr *udphead;
|
||||
|
||||
if (!pskb_may_pull(skb, sizeof(struct udphdr))) {
|
||||
nip_dbg("invalid skb length, drop the packet(skb->len=%u)", skb->len);
|
||||
kfree_skb(skb);
|
||||
goto end;
|
||||
}
|
||||
|
||||
udphead = udp_hdr(skb);
|
||||
if (ntohs(udphead->len) < sizeof(struct udphdr) ||
|
||||
ntohs(udphead->len) > skb->len) {
|
||||
nip_dbg("invalid udp packet length, drop the packet(udphead->len=%u)",
|
||||
ntohs(udphead->len));
|
||||
kfree_skb(skb);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!nip_get_udp_input_checksum(skb)) {
|
||||
nip_dbg("checksum failed, drop the packet");
|
||||
kfree_skb(skb);
|
||||
rc = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -378,7 +394,6 @@ int nip_udp_input(struct sk_buff *skb)
|
||||
nip_dbg("dport not match, drop the packet. sport=%u, dport=%u, data_len=%u",
|
||||
ntohs(udphead->source), ntohs(udphead->dest), ntohs(udphead->len));
|
||||
kfree_skb(skb);
|
||||
rc = -1;
|
||||
goto end;
|
||||
}
|
||||
|
||||
@@ -481,34 +496,68 @@ int nip_udp_getsockopt(struct sock *sk, int level,
|
||||
return nip_getsockopt(sk, level, optname, optval, optlen);
|
||||
}
|
||||
|
||||
int nip_udp_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int nip_udp_pre_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
int nip_udp_sendpage(struct sock *sk, struct page *page, int offset,
|
||||
size_t size, int flags)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
void nip_udp_datagram_release_cb(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
void udp_nip_rehash(struct sock *sk)
|
||||
{
|
||||
}
|
||||
|
||||
void nip_udp_early_demux(struct sk_buff *skb)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct ninet_protocol nip_udp_protocol = {
|
||||
.handler = nip_udp_input,
|
||||
.err_handler = nip_udp_err,
|
||||
.flags = 0,
|
||||
.handler = nip_udp_input,
|
||||
.err_handler = nip_udp_err,
|
||||
.early_demux = nip_udp_early_demux,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
/* Newip Udp related operations */
|
||||
struct proto nip_udp_prot = {
|
||||
.name = "nip_udp",
|
||||
.owner = THIS_MODULE,
|
||||
.close = udp_lib_close,
|
||||
.disconnect = udp_disconnect,
|
||||
.ioctl = udp_ioctl,
|
||||
.init = udp_init_sock,
|
||||
.destroy = nip_udp_destroy_sock,
|
||||
.setsockopt = nip_udp_setsockopt,
|
||||
.getsockopt = nip_udp_getsockopt,
|
||||
.sendmsg = nip_udp_output,
|
||||
.recvmsg = nip_udp_recvmsg,
|
||||
.backlog_rcv = __nip_udp_queue_rcv_skb,
|
||||
.hash = udp_lib_hash,
|
||||
.unhash = udp_lib_unhash,
|
||||
.get_port = nip_udp_get_port,
|
||||
.memory_allocated = &udp_memory_allocated,
|
||||
.sysctl_mem = sysctl_udp_mem,
|
||||
.obj_size = sizeof(struct nip_udp_sock),
|
||||
.h.udp_table = &udp_table,
|
||||
.diag_destroy = udp_abort,
|
||||
.name = "nip_udp",
|
||||
.owner = THIS_MODULE,
|
||||
.close = udp_lib_close,
|
||||
.pre_connect = nip_udp_pre_connect,
|
||||
.connect = nip_udp_datagram_connect,
|
||||
.disconnect = udp_disconnect,
|
||||
.ioctl = udp_ioctl,
|
||||
.init = udp_init_sock,
|
||||
.destroy = nip_udp_destroy_sock,
|
||||
.setsockopt = nip_udp_setsockopt,
|
||||
.getsockopt = nip_udp_getsockopt,
|
||||
.sendmsg = nip_udp_output,
|
||||
.recvmsg = nip_udp_recvmsg,
|
||||
.sendpage = nip_udp_sendpage,
|
||||
.release_cb = nip_udp_datagram_release_cb,
|
||||
.backlog_rcv = __nip_udp_queue_rcv_skb,
|
||||
.hash = udp_lib_hash,
|
||||
.unhash = udp_lib_unhash,
|
||||
.rehash = udp_nip_rehash,
|
||||
.get_port = nip_udp_get_port,
|
||||
.memory_allocated = &udp_memory_allocated,
|
||||
.sysctl_mem = sysctl_udp_mem,
|
||||
.obj_size = sizeof(struct nip_udp_sock),
|
||||
.h.udp_table = &udp_table,
|
||||
.diag_destroy = udp_abort,
|
||||
};
|
||||
|
||||
/* Example Create newip socket information */
|
||||
|
||||
Reference in New Issue
Block a user