linux/net/llc/llc_pdu.c
<<
>>
Prefs
   1/*
   2 * llc_pdu.c - access to PDU internals
   3 *
   4 * Copyright (c) 1997 by Procom Technology, Inc.
   5 *               2001-2003 by Arnaldo Carvalho de Melo <acme@conectiva.com.br>
   6 *
   7 * This program can be redistributed or modified under the terms of the
   8 * GNU General Public License as published by the Free Software Foundation.
   9 * This program is distributed without any warranty or implied warranty
  10 * of merchantability or fitness for a particular purpose.
  11 *
  12 * See the GNU General Public License for more details.
  13 */
  14
  15#include <linux/netdevice.h>
  16#include <net/llc_pdu.h>
  17
  18static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type);
  19static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu);
  20
  21void llc_pdu_set_cmd_rsp(struct sk_buff *skb, u8 pdu_type)
  22{
  23        llc_pdu_un_hdr(skb)->ssap |= pdu_type;
  24}
  25
  26/**
  27 *      pdu_set_pf_bit - sets poll/final bit in LLC header
  28 *      @pdu_frame: input frame that p/f bit must be set into it.
  29 *      @bit_value: poll/final bit (0 or 1).
  30 *
  31 *      This function sets poll/final bit in LLC header (based on type of PDU).
  32 *      in I or S pdus, p/f bit is right bit of fourth byte in header. in U
  33 *      pdus p/f bit is fifth bit of third byte.
  34 */
  35void llc_pdu_set_pf_bit(struct sk_buff *skb, u8 bit_value)
  36{
  37        u8 pdu_type;
  38        struct llc_pdu_sn *pdu;
  39
  40        llc_pdu_decode_pdu_type(skb, &pdu_type);
  41        pdu = llc_pdu_sn_hdr(skb);
  42
  43        switch (pdu_type) {
  44        case LLC_PDU_TYPE_I:
  45        case LLC_PDU_TYPE_S:
  46                pdu->ctrl_2 = (pdu->ctrl_2 & 0xFE) | bit_value;
  47                break;
  48        case LLC_PDU_TYPE_U:
  49                pdu->ctrl_1 |= (pdu->ctrl_1 & 0xEF) | (bit_value << 4);
  50                break;
  51        }
  52}
  53
  54/**
  55 *      llc_pdu_decode_pf_bit - extracs poll/final bit from LLC header
  56 *      @skb: input skb that p/f bit must be extracted from it
  57 *      @pf_bit: poll/final bit (0 or 1)
  58 *
  59 *      This function extracts poll/final bit from LLC header (based on type of
  60 *      PDU). In I or S pdus, p/f bit is right bit of fourth byte in header. In
  61 *      U pdus p/f bit is fifth bit of third byte.
  62 */
  63void llc_pdu_decode_pf_bit(struct sk_buff *skb, u8 *pf_bit)
  64{
  65        u8 pdu_type;
  66        struct llc_pdu_sn *pdu;
  67
  68        llc_pdu_decode_pdu_type(skb, &pdu_type);
  69        pdu = llc_pdu_sn_hdr(skb);
  70
  71        switch (pdu_type) {
  72        case LLC_PDU_TYPE_I:
  73        case LLC_PDU_TYPE_S:
  74                *pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
  75                break;
  76        case LLC_PDU_TYPE_U:
  77                *pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
  78                break;
  79        }
  80}
  81
  82/**
  83 *      llc_pdu_init_as_disc_cmd - Builds DISC PDU
  84 *      @skb: Address of the skb to build
  85 *      @p_bit: The P bit to set in the PDU
  86 *
  87 *      Builds a pdu frame as a DISC command.
  88 */
  89void llc_pdu_init_as_disc_cmd(struct sk_buff *skb, u8 p_bit)
  90{
  91        struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
  92
  93        pdu->ctrl_1  = LLC_PDU_TYPE_U;
  94        pdu->ctrl_1 |= LLC_2_PDU_CMD_DISC;
  95        pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
  96}
  97
  98/**
  99 *      llc_pdu_init_as_i_cmd - builds I pdu
 100 *      @skb: Address of the skb to build
 101 *      @p_bit: The P bit to set in the PDU
 102 *      @ns: The sequence number of the data PDU
 103 *      @nr: The seq. number of the expected I PDU from the remote
 104 *
 105 *      Builds a pdu frame as an I command.
 106 */
 107void llc_pdu_init_as_i_cmd(struct sk_buff *skb, u8 p_bit, u8 ns, u8 nr)
 108{
 109        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 110
 111        pdu->ctrl_1  = LLC_PDU_TYPE_I;
 112        pdu->ctrl_2  = 0;
 113        pdu->ctrl_2 |= (p_bit & LLC_I_PF_BIT_MASK); /* p/f bit */
 114        pdu->ctrl_1 |= (ns << 1) & 0xFE;   /* set N(S) in bits 2..8 */
 115        pdu->ctrl_2 |= (nr << 1) & 0xFE;   /* set N(R) in bits 10..16 */
 116}
 117
 118/**
 119 *      llc_pdu_init_as_rej_cmd - builds REJ PDU
 120 *      @skb: Address of the skb to build
 121 *      @p_bit: The P bit to set in the PDU
 122 *      @nr: The seq. number of the expected I PDU from the remote
 123 *
 124 *      Builds a pdu frame as a REJ command.
 125 */
 126void llc_pdu_init_as_rej_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
 127{
 128        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 129
 130        pdu->ctrl_1  = LLC_PDU_TYPE_S;
 131        pdu->ctrl_1 |= LLC_2_PDU_CMD_REJ;
 132        pdu->ctrl_2  = 0;
 133        pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
 134        pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
 135        pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
 136}
 137
 138/**
 139 *      llc_pdu_init_as_rnr_cmd - builds RNR pdu
 140 *      @skb: Address of the skb to build
 141 *      @p_bit: The P bit to set in the PDU
 142 *      @nr: The seq. number of the expected I PDU from the remote
 143 *
 144 *      Builds a pdu frame as an RNR command.
 145 */
 146void llc_pdu_init_as_rnr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
 147{
 148        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 149
 150        pdu->ctrl_1  = LLC_PDU_TYPE_S;
 151        pdu->ctrl_1 |= LLC_2_PDU_CMD_RNR;
 152        pdu->ctrl_2  = 0;
 153        pdu->ctrl_2 |= p_bit & LLC_S_PF_BIT_MASK;
 154        pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
 155        pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
 156}
 157
 158/**
 159 *      llc_pdu_init_as_rr_cmd - Builds RR pdu
 160 *      @skb: Address of the skb to build
 161 *      @p_bit: The P bit to set in the PDU
 162 *      @nr: The seq. number of the expected I PDU from the remote
 163 *
 164 *      Builds a pdu frame as an RR command.
 165 */
 166void llc_pdu_init_as_rr_cmd(struct sk_buff *skb, u8 p_bit, u8 nr)
 167{
 168        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 169
 170        pdu->ctrl_1  = LLC_PDU_TYPE_S;
 171        pdu->ctrl_1 |= LLC_2_PDU_CMD_RR;
 172        pdu->ctrl_2  = p_bit & LLC_S_PF_BIT_MASK;
 173        pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
 174        pdu->ctrl_2 |= (nr << 1) & 0xFE; /* set N(R) in bits 10..16 */
 175}
 176
 177/**
 178 *      llc_pdu_init_as_sabme_cmd - builds SABME pdu
 179 *      @skb: Address of the skb to build
 180 *      @p_bit: The P bit to set in the PDU
 181 *
 182 *      Builds a pdu frame as an SABME command.
 183 */
 184void llc_pdu_init_as_sabme_cmd(struct sk_buff *skb, u8 p_bit)
 185{
 186        struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 187
 188        pdu->ctrl_1  = LLC_PDU_TYPE_U;
 189        pdu->ctrl_1 |= LLC_2_PDU_CMD_SABME;
 190        pdu->ctrl_1 |= ((p_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
 191}
 192
 193/**
 194 *      llc_pdu_init_as_dm_rsp - builds DM response pdu
 195 *      @skb: Address of the skb to build
 196 *      @f_bit: The F bit to set in the PDU
 197 *
 198 *      Builds a pdu frame as a DM response.
 199 */
 200void llc_pdu_init_as_dm_rsp(struct sk_buff *skb, u8 f_bit)
 201{
 202        struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 203
 204        pdu->ctrl_1  = LLC_PDU_TYPE_U;
 205        pdu->ctrl_1 |= LLC_2_PDU_RSP_DM;
 206        pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
 207}
 208
 209/**
 210 *      llc_pdu_init_as_frmr_rsp - builds FRMR response PDU
 211 *      @skb: Address of the frame to build
 212 *      @prev_pdu: The rejected PDU frame
 213 *      @f_bit: The F bit to set in the PDU
 214 *      @vs: tx state vari value for the data link conn at the rejecting LLC
 215 *      @vr: rx state var value for the data link conn at the rejecting LLC
 216 *      @vzyxw: completely described in the IEEE Std 802.2 document (Pg 55)
 217 *
 218 *      Builds a pdu frame as a FRMR response.
 219 */
 220void llc_pdu_init_as_frmr_rsp(struct sk_buff *skb, struct llc_pdu_sn *prev_pdu,
 221                              u8 f_bit, u8 vs, u8 vr, u8 vzyxw)
 222{
 223        struct llc_frmr_info *frmr_info;
 224        u8 prev_pf = 0;
 225        u8 *ctrl;
 226        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 227
 228        pdu->ctrl_1  = LLC_PDU_TYPE_U;
 229        pdu->ctrl_1 |= LLC_2_PDU_RSP_FRMR;
 230        pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
 231
 232        frmr_info = (struct llc_frmr_info *)&pdu->ctrl_2;
 233        ctrl = (u8 *)&prev_pdu->ctrl_1;
 234        FRMR_INFO_SET_REJ_CNTRL(frmr_info,ctrl);
 235        FRMR_INFO_SET_Vs(frmr_info, vs);
 236        FRMR_INFO_SET_Vr(frmr_info, vr);
 237        prev_pf = llc_pdu_get_pf_bit(prev_pdu);
 238        FRMR_INFO_SET_C_R_BIT(frmr_info, prev_pf);
 239        FRMR_INFO_SET_INVALID_PDU_CTRL_IND(frmr_info, vzyxw);
 240        FRMR_INFO_SET_INVALID_PDU_INFO_IND(frmr_info, vzyxw);
 241        FRMR_INFO_SET_PDU_INFO_2LONG_IND(frmr_info, vzyxw);
 242        FRMR_INFO_SET_PDU_INVALID_Nr_IND(frmr_info, vzyxw);
 243        FRMR_INFO_SET_PDU_INVALID_Ns_IND(frmr_info, vzyxw);
 244        skb_put(skb, sizeof(struct llc_frmr_info));
 245}
 246
 247/**
 248 *      llc_pdu_init_as_rr_rsp - builds RR response pdu
 249 *      @skb: Address of the skb to build
 250 *      @f_bit: The F bit to set in the PDU
 251 *      @nr: The seq. number of the expected data PDU from the remote
 252 *
 253 *      Builds a pdu frame as an RR response.
 254 */
 255void llc_pdu_init_as_rr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
 256{
 257        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 258
 259        pdu->ctrl_1  = LLC_PDU_TYPE_S;
 260        pdu->ctrl_1 |= LLC_2_PDU_RSP_RR;
 261        pdu->ctrl_2  = 0;
 262        pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
 263        pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
 264        pdu->ctrl_2 |= (nr << 1) & 0xFE;  /* set N(R) in bits 10..16 */
 265}
 266
 267/**
 268 *      llc_pdu_init_as_rej_rsp - builds REJ response pdu
 269 *      @skb: Address of the skb to build
 270 *      @f_bit: The F bit to set in the PDU
 271 *      @nr: The seq. number of the expected data PDU from the remote
 272 *
 273 *      Builds a pdu frame as a REJ response.
 274 */
 275void llc_pdu_init_as_rej_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
 276{
 277        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 278
 279        pdu->ctrl_1  = LLC_PDU_TYPE_S;
 280        pdu->ctrl_1 |= LLC_2_PDU_RSP_REJ;
 281        pdu->ctrl_2  = 0;
 282        pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
 283        pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
 284        pdu->ctrl_2 |= (nr << 1) & 0xFE;  /* set N(R) in bits 10..16 */
 285}
 286
 287/**
 288 *      llc_pdu_init_as_rnr_rsp - builds RNR response pdu
 289 *      @skb: Address of the frame to build
 290 *      @f_bit: The F bit to set in the PDU
 291 *      @nr: The seq. number of the expected data PDU from the remote
 292 *
 293 *      Builds a pdu frame as an RNR response.
 294 */
 295void llc_pdu_init_as_rnr_rsp(struct sk_buff *skb, u8 f_bit, u8 nr)
 296{
 297        struct llc_pdu_sn *pdu = llc_pdu_sn_hdr(skb);
 298
 299        pdu->ctrl_1  = LLC_PDU_TYPE_S;
 300        pdu->ctrl_1 |= LLC_2_PDU_RSP_RNR;
 301        pdu->ctrl_2  = 0;
 302        pdu->ctrl_2 |= f_bit & LLC_S_PF_BIT_MASK;
 303        pdu->ctrl_1 &= 0x0F;    /* setting bits 5..8 to zero(reserved) */
 304        pdu->ctrl_2 |= (nr << 1) & 0xFE;  /* set N(R) in bits 10..16 */
 305}
 306
 307/**
 308 *      llc_pdu_init_as_ua_rsp - builds UA response pdu
 309 *      @skb: Address of the frame to build
 310 *      @f_bit: The F bit to set in the PDU
 311 *
 312 *      Builds a pdu frame as a UA response.
 313 */
 314void llc_pdu_init_as_ua_rsp(struct sk_buff *skb, u8 f_bit)
 315{
 316        struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 317
 318        pdu->ctrl_1  = LLC_PDU_TYPE_U;
 319        pdu->ctrl_1 |= LLC_2_PDU_RSP_UA;
 320        pdu->ctrl_1 |= ((f_bit & 1) << 4) & LLC_U_PF_BIT_MASK;
 321}
 322
 323/**
 324 *      llc_pdu_decode_pdu_type - designates PDU type
 325 *      @skb: input skb that type of it must be designated.
 326 *      @type: type of PDU (output argument).
 327 *
 328 *      This function designates type of PDU (I, S or U).
 329 */
 330static void llc_pdu_decode_pdu_type(struct sk_buff *skb, u8 *type)
 331{
 332        struct llc_pdu_un *pdu = llc_pdu_un_hdr(skb);
 333
 334        if (pdu->ctrl_1 & 1) {
 335                if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
 336                        *type = LLC_PDU_TYPE_U;
 337                else
 338                        *type = LLC_PDU_TYPE_S;
 339        } else
 340                *type = LLC_PDU_TYPE_I;
 341}
 342
 343/**
 344 *      llc_pdu_get_pf_bit - extracts p/f bit of input PDU
 345 *      @pdu: pointer to LLC header.
 346 *
 347 *      This function extracts p/f bit of input PDU. at first examines type of
 348 *      PDU and then extracts p/f bit. Returns the p/f bit.
 349 */
 350static u8 llc_pdu_get_pf_bit(struct llc_pdu_sn *pdu)
 351{
 352        u8 pdu_type;
 353        u8 pf_bit = 0;
 354
 355        if (pdu->ctrl_1 & 1) {
 356                if ((pdu->ctrl_1 & LLC_PDU_TYPE_U) == LLC_PDU_TYPE_U)
 357                        pdu_type = LLC_PDU_TYPE_U;
 358                else
 359                        pdu_type = LLC_PDU_TYPE_S;
 360        } else
 361                pdu_type = LLC_PDU_TYPE_I;
 362        switch (pdu_type) {
 363        case LLC_PDU_TYPE_I:
 364        case LLC_PDU_TYPE_S:
 365                pf_bit = pdu->ctrl_2 & LLC_S_PF_BIT_MASK;
 366                break;
 367        case LLC_PDU_TYPE_U:
 368                pf_bit = (pdu->ctrl_1 & LLC_U_PF_BIT_MASK) >> 4;
 369                break;
 370        }
 371        return pf_bit;
 372}
 373