root/net/802/llc.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. llc_rx_adm
  2. llc_rx_setup
  3. llc_rx_reset
  4. llc_rx_d_conn
  5. llc_rx_error
  6. llc_rx_nr_shared
  7. llc_rx_normal

   1 /*
   2  *      802.2 Class 2 LLC service.
   3  */
   4  
   5  
   6 int llc_rx_adm(struct sock *sk,struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
   7 {
   8         if(type==CMD)
   9         {
  10                 if(cmd==DISC)
  11                         send_response(sk,DM|pf);
  12                 else if(cmd==SABM)
  13                 {
  14                         if(sk->state!=TCP_LISTEN)
  15                                 send_response(sk. DM|pf);
  16                         else
  17                         {
  18                                 sk=ll_rx_accept(sk);
  19                                 if(sk!=NULL)
  20                                 {
  21                                         send_response(sk, UA|pf);
  22                                         sk->llc.vs=0;
  23                                         sk->llc.vr=0;
  24                                         sk->llc.p_flag=0;
  25                                         sk->llc.remote_busy=0;
  26                                         llc_state(sk,LLC_NORMAL);
  27                                 }
  28                         }       
  29                 }
  30                 else if(pf)
  31                         send_response(sk, DM|PF);
  32         }
  33         return 0;
  34 }
  35 
  36 int llc_rx_setup(struct sock *sk, struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
  37 {
  38         if(type==CMD)
  39         {
  40                 if(cmd==SABM)
  41                 {
  42                         sk->llc.vs=0;
  43                         sk->llc.vr=0;
  44                         send_response(sk, UA|pf);
  45                 }
  46                 if(cmd==DISC)
  47                 {
  48                         send_response(sk, DM|pf);
  49                         llc_error(sk,ECONNRESET);
  50                         llc_state(sk, LLC_ADM);
  51                 }
  52         }
  53         else
  54         {
  55                 if(cmd==UA && pf==sk->llc.p_flag)
  56                 {
  57                         del_timer(&sk->llc.t1);
  58                         sk->llc.vs=0;
  59                         llc_update_p_flag(sk,pf);
  60                         llc_state(sk,LLC_NORMAL);
  61                 }
  62                 if(cmd==DM)
  63                 {
  64                         llc_error(sk, ECONNRESET);
  65                         llc_state(sk, LLC_ADM);
  66                 }
  67         }
  68 }
  69 
  70 int llc_rx_reset(struct sock *sk, struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         if(type==CMD)
  73         {
  74                 if(cmd==SABM)
  75                 {
  76                         sk->llc.vr=0;
  77                         sk->llc.vs=0;
  78                         send_response(sk, UA|pf);
  79                 }
  80                 else if(cmd==DISC)
  81                 {
  82                         if(sk->llc.cause_flag==1)
  83                                 llc_shutdown(sk,SHUTDOWN_MASK);
  84                         else
  85                                 llc_eror(sk, ECONNREFUSED);
  86                         send_response(sk, DM|pf);
  87                         llc_state(sk, LLC_ADM);
  88                 }
  89         }
  90         else
  91         {
  92                 if(cmd==UA)
  93                 {
  94                         if(sk->llc.p_flag==pf)
  95                         {
  96                                 del_timer(&sk->llc.t1);
  97                                 sk->llc.vs=0;
  98                                 sk->llc.vr=0;
  99                                 llc_update_p_flag(sk,pf);
 100                                 llc_confirm_reset(sk, sk->llc.cause_flag);
 101                                 sk->llc.remote_busy=0;
 102                                 llc_state(sk, LLC_NORMAL);
 103                         }
 104                 }
 105                 if(cmd==DM)
 106                 {       /* Should check cause_flag */
 107                         llc_shutdown(sk, SHUTDOWN_MASK);
 108                         llc_state(sk, LLC_ADM);
 109                 }
 110         }
 111         return 0;
 112 }
 113 
 114 int llc_rx_d_conn(struct sock *sk, struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
 115 {
 116         if(type==CMD)
 117         {
 118                 if(cmd==SABM)
 119                 {
 120                         llc_error(sk, ECONNRESET);
 121                         llc_state(sk, ADM);
 122                 }
 123                 else if(cmd==DISC)
 124                 {
 125                         send_response(UA|pf);
 126                         llc_state(sk, LLC_D_CONN);
 127                 }
 128                 else if(pf)
 129                         send_response(sk, DM|PF);
 130         }
 131         else
 132         {
 133                 if(cmd==UA && pf==sk->llc.p_flag)
 134                 {
 135                         del_timer(&sk->llc.t1);
 136                         llc_state(sk, ADM);
 137                         llc_confirm_reset(sk, sk->llc.cause_flag);
 138                 }
 139                 if(cmd==DM)
 140                 {
 141                         del_timer(&sk->llc.t1);
 142                         /*if(sk->llc.cause_flag)*/
 143                         llc_shutdown(sk, SHUTDOWN_MASK);        
 144                 }
 145                 
 146         }
 147         return 0;
 148 }
 149 
 150 int llc_rx_error(struct sock *sk, struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
 151 {
 152         if(type==CMD)
 153         {
 154                 if(cmd==SABM)
 155                 {
 156                         sk->llc.vs=0;
 157                         sk->llc.vr=0;
 158                         send_response(sk, UA|pf);
 159                         llc_error(sk,ECONNRESET);
 160                         sk->llc.p_flag=0;
 161                         sk->llc.remote_busy=0;
 162                         llc_state(sk, LLC_NORMAL);
 163                 }
 164                 else if(cmd==DISC)
 165                 {
 166                         send_response(sk, UA|pf);
 167                         llc_shutdown(sk, SHUTDOWN_MASK);
 168                         llc_state(sk, LLC_ADM);
 169                 }
 170                 else
 171                         llc_resend_frmr_rsp(sk,pf);
 172         }
 173         else
 174         {
 175                 if(cmd==DM)
 176                 {
 177                         llc_error(sk, ECONNRESET);
 178                         del_timer(&sk->llc.t1);
 179                         llc_state(sk, LLC_ADM);
 180                 }
 181                 if(cmd==FRMR)
 182                 {
 183                         send_command(sk, SABM);
 184                         sk->llc.p_flag=pf;
 185                         llc_start_t1();
 186                         sk->llc.retry_count=0;
 187                         sk->llc.cause_flag=0;
 188                         llc_error(sk, EPROTO);
 189                         llc_state(sk, LLC_RESET);
 190                 }
 191         }
 192 }
 193 
 194 
 195 /*
 196  *      Subroutine for handling the shared cases of the data modes.
 197  */
 198  
 199 int llc_rx_nr_shared(struct sock *sk, struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
 200 {
 201         if(type==CMD)
 202         {
 203                 if(cmd==SABM)
 204                 {
 205                         /*
 206                          *      Optional reset processing. We decline resets.
 207                          */
 208                         send_response(sk,DM|pf);
 209                         llc_error(sk, ECONNRESET);
 210                         llc_state(sk, LLC_ADM);
 211                 }
 212                 else if(cmd==DISC)
 213                 {
 214                         send_response(sk,UA|pf);
 215                         llc_state(sk, LLC_ADM);
 216                         llc_shutdown(sk, SHUTDOWN_MASK);
 217                 }
 218                 /*
 219                  *      We only ever use windows of 7, so there is no illegal NR/NS value
 220                  *      otherwise we would FRMR here and go to ERROR state
 221                  */
 222                 else if(cmd==ILLEGAL)
 223                 {
 224                         llc_send_frmr_response(sk, ILLEGAL_TYPE,pf);
 225                         llc_state(sk, LLC_ERROR);
 226                         llc_error(sk, EPROTO);
 227                 }
 228                 else
 229                         /*
 230                          *      Not covered by general rule
 231                          */
 232                         return 0;
 233         }
 234         else
 235         {
 236                 /*
 237                  *      We close on errors
 238                  */
 239                 if(cmd==FRMR)
 240                 {
 241                         send_command(sk, DM|pf);
 242                         sk->llc.p_flag=pf;
 243                         llc_start_t1(sk);
 244                         llc_error(sk, EPROTO);
 245                         sk->llc.cause_flag=0;
 246                         llc_state(sk, LLC_D_CONN):
 247                 }
 248                 else if(cmd==DM)
 249                 {
 250                         llc_state(sk, LLC_ADM);
 251                         llc_error(sk, ECONNREFUSED);
 252                 }
 253                 /*
 254                  *      We always use a window of 7 so can't get I resp
 255                  *      with invalid NS,  or any resp with invalid NR. If
 256                  *      we add this they do the same as..
 257                  */
 258                 else if(cmd==UA)
 259                 {
 260                         llc_send_frmr_response(sk, UNEXPECTED_CONTROL, pf);
 261                         llc_state(sk, LLC_ERROR);
 262                         llc_error(sk, EPROTO);
 263                 }
 264                 else if(pf==1 && sk->llc.p_flag==0)
 265                 {
 266                         llc_send_frmr_response(sk, UNEXPECTED_RESPONSE, pf);
 267                         llc_state(sk, LLC_ERROR);
 268                         llc_error(sk, EPROTO);
 269                 }
 270                 else if(cmd==ILLEGAL)
 271                 {
 272                         llc_send_frmr_response(sk, ILLEGAL_TYPE,pf);
 273                         llc_state(sk, LLC_ERROR);
 274                         llc_error(sk, EPROTO);
 275                 }
 276                 else
 277                         /*
 278                          *      Not covered by general rule
 279                          */
 280                         return 0
 281         }
 282         /*
 283          *      Processed.
 284          */
 285         return 1;
 286 }
 287 
 288 int llc_rx_normal(struct sock *sk, struct sk_buff *skb, int type, int cmd, int pf, int nr, int ns)
     /* [previous][next][first][last][top][bottom][index][help] */
 289 {
 290         if(llc_rx_nr_shared(sk, skb, type, cmd, pf, nr, ns))
 291                 return 0;
 292         if(cmd==I)
 293         {
 294                 if(llc_invalid_ns(sk,ns))
 295                 {
 296                         if((type==RESP && sk->llc.p_flag==pf)||(type==CMD && pf==0 && sk->llc.p_flag==0))
 297                         {
 298                                 llc_command(sk, REJ|PF);
 299                                 llc_ack_frames(sk,nr);  /* Ack frames and update N(R) */
 300                                 sk->llc.p_flag=PF;
 301                                 llc_state(sk, LLC_REJECT);
 302                                 sk->llc.retry_count=0;
 303                                 llc_start_t1(sk);
 304                                 sk->llc.remote_busy=0;
 305                         }
 306                         else if((type==CMD && !pf && sk->llc.p_flag==1) || (type==RESP && !pf && sk->llc.p_flag==1))
 307                         {
 308                                 if(type==CMD)
 309                                         llc_response(sk, REJ);
 310                                 else
 311                                         llc_command(sk, REJ);
 312                                 llc_ack_frames(sk,nr);
 313                                 sk->llc.retry_count=0;
 314                                 llc_state(sk, LLC_REJECT);
 315                                 llc_start_t1(sk);
 316                         }
 317                         else if(pf && type==CMD)
 318                         {
 319                                 llc_response(sk, REJ|PF);
 320                                 llc_ack_frames(sk,nr);
 321                                 sk->llc.retry_count=0;
 322                                 llc_start_t1(sk);
 323                         }
 324                 }
 325                 else
 326                 {
 327                         /*
 328                          *      Valid I frame cases
 329                          */
 330                          
 331                          if(sk->llc.p_flag==pf && !(type==CMD && pf))
 332                          {
 333                                 sk->llc.vr=(sk->llc.vr+1)&7;
 334                                 llc_queue_rr_cmd(sk, PF);
 335                                 sk->llc.retry_count=0;
 336                                 llc_start_t1(sk);
 337                                 sk->llc.p_flag=1;
 338                                 llc_ack_frames(sk,nr);
 339                                 sk->llc.remote_busy=0;
 340                          }
 341                          else if(sk->ppc.p_flag!=pf)
 342                          {
 343                                 sk->llc.vr=(sk->llc.vr+1)&7;
 344                                 if(type==CMD)
 345                                         llc_queue_rr_resp(sk, 0);
 346                                 else
 347                                         llc_queue_rr_cmd(sk, 0);
 348                                 if(sk->llc.nr!=nr)
 349                                 {
 350                                         llc_ack_frames(sk,nr);
 351                                         llc_reset_t1(sk);
 352                                 }
 353                          }
 354                          else if(pf)
 355                          {
 356                                 sk->llc.vr=(sk->llc.vr+1)&7;
 357                                 llc_queue_rr_resp(sk,PF);
 358                                 if(sk->llc.nr!=nr)
 359                                 {
 360                                         llc_ack_frames(sk,nr);
 361                                         llc_reset_t1(sk);
 362                                 }
 363                          }
 364                          llc_queue_data(sk,skb);
 365                          return 1;
 366                 }
 367         }
 368         else if(cmd==RR||cmd==RNR)
 369         {
 370                 if(type==CMD || (type==RESP && (!pf || pf==1 && sk->llc.p_flag==1)))
 371                 {
 372                         llc_update_p_flag(sk,pf);
 373                         if(sk->llc.nr!=nr)
 374                         {
 375                                 llc_ack_frames(sk,nr);
 376                                 llc_reset_t1(sk);
 377                         }
 378                         if(cmd==RR)
 379                                 sk->llc.remote_busy=0;
 380                         else
 381                         {       sk->llc.remote_busy=1;
 382                                         if(!llc_t1_running(sk))
 383                                         llc_start_t1(sk);
 384                         }
 385                 }
 386                 else if(type==cmd && pf)
 387                 {
 388                         if(cmd==RR)
 389                                 llc_queue_rr_resp(sk,PF);
 390                         else
 391                         {
 392                                 send_response(sk, RR|PF);
 393                                 if(!llc_t1_running(sk))
 394                                         llc_start_t1(sk);
 395                         }
 396                         if(sk->llc.nr!=nr)
 397                         {
 398                                 llc_ack_frames(sk,nr);
 399                                 llc_reset_t1(sk);
 400                         }
 401                         if(cmd==RR)
 402                                 sk->llc.remote_busy=0;
 403                         else
 404                                 sk->llc.remote_busy=1;
 405                 }
 406         }
 407         else if(cmd==REJ)
 408         {
 409                 
 410         }
 411 }
 412                         

/* [previous][next][first][last][top][bottom][index][help] */