160c778b25972e095df8981dd41e99d161e8738f9Vlad Yasevich/* SCTP kernel implementation 21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Copyright (c) 2003 International Business Machines, Corp. 31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 460c778b25972e095df8981dd41e99d161e8738f9Vlad Yasevich * This file is part of the SCTP kernel implementation 51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * These functions manipulate sctp SSN tracker. 71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 860c778b25972e095df8981dd41e99d161e8738f9Vlad Yasevich * This SCTP implementation is free software; 91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * you can redistribute it and/or modify it under the terms of 101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the GNU General Public License as published by 111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * the Free Software Foundation; either version 2, or (at your option) 121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * any later version. 131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 1460c778b25972e095df8981dd41e99d161e8738f9Vlad Yasevich * This SCTP implementation is distributed in the hope that it 151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * will be useful, but WITHOUT ANY WARRANTY; without even the implied 161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * ************************ 171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * See the GNU General Public License for more details. 191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * You should have received a copy of the GNU General Public License 214b2f13a25133b115eb56771bd4a8e71a82aea968Jeff Kirsher * along with GNU CC; see the file COPYING. If not, see 224b2f13a25133b115eb56771bd4a8e71a82aea968Jeff Kirsher * <http://www.gnu.org/licenses/>. 231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Please send any bug reports or fixes you make to the 251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * email address(es): 2691705c61b52029ab5da67a15a23eef08667bf40eDaniel Borkmann * lksctp developers <linux-sctp@vger.kernel.org> 271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * 281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Written or modified by: 291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Jon Grimm <jgrimm@us.ibm.com> 301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/types.h> 335a0e3ad6af8660be21ca98a971cd00f331318c05Tejun Heo#include <linux/slab.h> 341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sctp/sctp.h> 351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <net/sctp/sm.h> 361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, 381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u16 out); 391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Storage size needed for map includes 2 headers and then the 411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * specific needs of in or out streams. 421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline size_t sctp_ssnmap_size(__u16 in, __u16 out) 441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return sizeof(struct sctp_ssnmap) + (in + out) * sizeof(__u16); 461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Create a new sctp_ssnmap. 501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * Allocate room to store at least 'len' contiguous TSNs. 511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */ 523182cd84f0e132558bbe106c070405ae49f1f0e3Alexey Dobriyanstruct sctp_ssnmap *sctp_ssnmap_new(__u16 in, __u16 out, 53dd0fc66fb33cd610bc1a5db8a5e232d34879b4d7Al Viro gfp_t gfp) 541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds struct sctp_ssnmap *retval; 561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds int size; 571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = sctp_ssnmap_size(in, out); 593f736868b47687d1336fe88185560b22bb92021eCong Wang if (size <= KMALLOC_MAX_SIZE) 601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = kmalloc(size, gfp); 611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds retval = (struct sctp_ssnmap *) 631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __get_free_pages(gfp, get_order(size)); 641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!retval) 651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail; 661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds if (!sctp_ssnmap_init(retval, in, out)) 681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds goto fail_map; 691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds SCTP_DBG_OBJCNT_INC(ssnmap); 711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return retval; 731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail_map: 753f736868b47687d1336fe88185560b22bb92021eCong Wang if (size <= KMALLOC_MAX_SIZE) 761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds kfree(retval); 771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds else 781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds free_pages((unsigned long)retval, get_order(size)); 791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsfail: 801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return NULL; 811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Initialize a block of memory as a ssnmap. */ 851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sctp_ssnmap *sctp_ssnmap_init(struct sctp_ssnmap *map, __u16 in, 861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds __u16 out) 871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(map, 0x00, sctp_ssnmap_size(in, out)); 891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start 'in' stream just after the map header. */ 911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map->in.ssn = (__u16 *)&map[1]; 921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map->in.len = in; 931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds /* Start 'out' stream just after 'in'. */ 951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map->out.ssn = &map->in.ssn[in]; 961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds map->out.len = out; 971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds return map; 991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Clear out the ssnmap streams. */ 1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sctp_ssnmap_clear(struct sctp_ssnmap *map) 1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size_t size; 1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds size = (map->in.len + map->out.len) * sizeof(__u16); 1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds memset(map->in.ssn, 0x00, size); 1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds 1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Dispose of a ssnmap. */ 1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsvoid sctp_ssnmap_free(struct sctp_ssnmap *map) 1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{ 113542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann int size; 114542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann 115542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann if (unlikely(!map)) 116542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann return; 117542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann 118542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann size = sctp_ssnmap_size(map->in.len, map->out.len); 119542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann if (size <= KMALLOC_MAX_SIZE) 120542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann kfree(map); 121542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann else 122542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann free_pages((unsigned long)map, get_order(size)); 123542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann 124542c2d832087aa78566be49aa4284779a0a687b3Daniel Borkmann SCTP_DBG_OBJCNT_DEC(ssnmap); 1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds} 126