/* SCTP kernel implementation1* Copyright (c) 2003 International Business Machines, Corp.2*3* This file is part of the SCTP kernel implementation4*5* These functions manipulate sctp SSN tracker.6*7* This SCTP implementation is free software;8* you can redistribute it and/or modify it under the terms of9* the GNU General Public License as published by10* the Free Software Foundation; either version 2, or (at your option)11* any later version.12*13* This SCTP implementation is distributed in the hope that it14* will be useful, but WITHOUT ANY WARRANTY; without even the implied15* ************************16* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.17* See the GNU General Public License for more details.18*19* You should have received a copy of the GNU General Public License20* along with GNU CC; see the file COPYING. If not, write to21* the Free Software Foundation, 59 Temple Place - Suite 330,22* Boston, MA 02111-1307, USA.23*24* Please send any bug reports or fixes you make to the25* email address(es):26* lksctp developers <[email protected]>27*28* Or submit a bug report through the following website:29* http://www.sf.net/projects/lksctp30*31* Written or modified by:32* Jon Grimm <[email protected]>33*34* Any bugs reported given to us we will try to fix... any fixes shared will35* be incorporated into the next SCTP release.36*/3738#include <linux/types.h>39#include <linux/slab.h>40#include <net/sctp/sctp.h>41#include <net/sctp/sm.h>4243#define MAX_KMALLOC_SIZE 1310724445static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,46__u16 out);4748/* Storage size needed for map includes 2 headers and then the49* specific needs of in or out streams.50*/51static inline size_t sctp_ssnmap_size(__u16 in, __u16 out)52{53return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16);54}555657/* Create a new sctp_ssnmap.58* Allocate room to store at least 'len' contiguous TSNs.59*/60struct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out,61gfp_t gfp)62{63struct sctp_ssnmap *retval;64int size;6566size = sctp_ssnmap_size(in, out);67if (size <= MAX_KMALLOC_SIZE)68retval = kmalloc(size, gfp);69else70retval = (struct sctp_ssnmap *)71__get_free_pages(gfp, get_order(size));72if (!retval)73goto fail;7475if (!sctp_ssnmap_init(retval, in, out))76goto fail_map;7778retval->malloced = 1;79SCTP_DBG_OBJCNT_INC(ssnmap);8081return retval;8283fail_map:84if (size <= MAX_KMALLOC_SIZE)85kfree(retval);86else87free_pages((unsigned long)retval, get_order(size));88fail:89return NULL;90}919293/* Initialize a block of memory as a ssnmap. */94static struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in,95__u16 out)96{97memset(map, 0x00, sctp_ssnmap_size(in, out));9899/* Start 'in' stream just after the map header. */100map->in.ssn = (__u16 *)&map[1];101map->in.len = in;102103/* Start 'out' stream just after 'in'. */104map->out.ssn = &map->in.ssn[in];105map->out.len = out;106107return map;108}109110/* Clear out the ssnmap streams. */111void sctp_ssnmap_clear(struct sctp_ssnmap *map)112{113size_t size;114115size = (map->in.len + map->out.len) * sizeof(__u16);116memset(map->in.ssn, 0x00, size);117}118119/* Dispose of a ssnmap. */120void sctp_ssnmap_free(struct sctp_ssnmap *map)121{122if (map && map->malloced) {123int size;124125size = sctp_ssnmap_size(map->in.len, map->out.len);126if (size <= MAX_KMALLOC_SIZE)127kfree(map);128else129free_pages((unsigned long)map, get_order(size));130SCTP_DBG_OBJCNT_DEC(ssnmap);131}132}133134135