oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 1 | /* www.mycal.com |
| 2 | *--------------------------------------------------------------------------- |
| 3 | *lcp.c - Link Configuration Protocol Handler. - - |
| 4 | *--------------------------------------------------------------------------- |
| 5 | *Version - 0.1 Original Version June 3, 2000 - |
| 6 | * |
| 7 | *--------------------------------------------------------------------------- |
| 8 | *- Copyright (C) 2000, Mycal Labs www.mycal.com - - |
| 9 | *--------------------------------------------------------------------------- |
| 10 | * |
| 11 | * |
| 12 | */ |
| 13 | /* |
| 14 | * Copyright (c) 2003, Mike Johnson, Mycal Labs, www.mycal.net |
| 15 | * All rights reserved. |
| 16 | * |
| 17 | * Redistribution and use in source and binary forms, with or without |
| 18 | * modification, are permitted provided that the following conditions |
| 19 | * are met: |
| 20 | * 1. Redistributions of source code must retain the above copyright |
| 21 | * notice, this list of conditions and the following disclaimer. |
| 22 | * 2. Redistributions in binary form must reproduce the above copyright |
| 23 | * notice, this list of conditions and the following disclaimer in the |
| 24 | * documentation and/or other materials provided with the distribution. |
| 25 | * 3. All advertising materials mentioning features or use of this software |
| 26 | * must display the following acknowledgement: |
| 27 | * This product includes software developed by Mike Johnson/Mycal Labs |
| 28 | * www.mycal.net. |
| 29 | * 4. The name of the author may not be used to endorse or promote |
| 30 | * products derived from this software without specific prior |
| 31 | * written permission. |
| 32 | * |
| 33 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS |
| 34 | * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| 35 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
| 36 | * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
| 37 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| 38 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| 39 | * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| 40 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| 41 | * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| 42 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| 43 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| 44 | * |
| 45 | * This file is part of the Mycal Modified uIP TCP/IP stack. |
| 46 | * |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 47 | * $Id: lcp.c,v 1.3 2005/01/26 23:36:22 oliverschmidt Exp $ |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 48 | * |
| 49 | */ |
| 50 | |
| 51 | /* */ |
| 52 | /* include files */ |
| 53 | /* */ |
| 54 | |
| 55 | #include "ppp-conf.h" |
| 56 | |
| 57 | /*#include "time.h"*/ |
| 58 | #include "ppp.h" |
| 59 | #include "ahdlc.h" |
| 60 | #include "lcp.h" |
| 61 | |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 62 | #if 0 |
oliverschmidt | acc6395 | 2004-08-29 15:11:45 +0000 | [diff] [blame] | 63 | #define DEBUG1(x) |
| 64 | #define DEBUG2(x) |
| 65 | #else |
| 66 | #include <stdio.h> |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 67 | #define DEBUG1(x) debug_printf x |
| 68 | #define DEBUG2(x) debug_printf x |
oliverschmidt | acc6395 | 2004-08-29 15:11:45 +0000 | [diff] [blame] | 69 | #endif |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 70 | |
| 71 | #define TIMER_expire() |
| 72 | #define TIMER_set() |
| 73 | #define TIMER_timeout(x) 1 |
| 74 | |
| 75 | /*u8_t tflag; |
| 76 | u8_t *lcp_buffer; |
| 77 | u16_t lcp_tx_time; |
| 78 | u8_t lcp_retry; |
| 79 | u16_t lcp_timeout=5;*/ |
| 80 | |
| 81 | u8_t lcp_state; |
| 82 | u16_t ppp_tx_mru = 0; |
| 83 | |
| 84 | /* We need this when we neg our direction. |
| 85 | u8_t lcp_tx_options; */ |
| 86 | |
| 87 | /* |
| 88 | * Define the supported paramets for this module here. |
| 89 | */ |
| 90 | u8_t lcplist[] = { |
| 91 | LPC_MAGICNUMBER, |
| 92 | LPC_PFC, |
| 93 | LPC_ACFC, |
| 94 | LPC_AUTH, |
| 95 | LPC_ACCM, |
| 96 | LPC_MRU, |
| 97 | 0}; |
| 98 | |
| 99 | /*---------------------------------------------------------------------------*/ |
| 100 | /* lcp_init() - Initialize the LCP engine to startup values */ |
| 101 | /*---------------------------------------------------------------------------*/ |
| 102 | void |
| 103 | lcp_init(void) |
| 104 | { |
| 105 | lcp_state = 0; |
| 106 | ppp_retry = 0; |
| 107 | TIMER_expire(); |
| 108 | } |
| 109 | /*---------------------------------------------------------------------------*/ |
| 110 | /* lcp_rx() - Receive an LCP packet and process it. |
| 111 | * This routine receives a LCP packet in buffer of length count. |
| 112 | * Process it here, support for CONF_REQ, CONF_ACK, CONF_NACK, CONF_REJ or |
| 113 | * TERM_REQ. |
| 114 | */ |
| 115 | /*---------------------------------------------------------------------------*/ |
| 116 | void |
| 117 | lcp_rx(u8_t *buffer, u16_t count) |
| 118 | { |
| 119 | u8_t *bptr = buffer, *tptr; |
| 120 | u8_t error = 0; |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 121 | u8_t id; |
| 122 | u16_t len, j; |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 123 | |
| 124 | switch(*bptr++) { |
| 125 | case CONF_REQ: /* config request */ |
| 126 | /* parce request and see if we can ACK it */ |
| 127 | id = *bptr++; |
| 128 | len = (*bptr++ << 8); |
| 129 | len |= *bptr++; |
| 130 | /*len -= 2;*/ |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 131 | DEBUG1(("received [LCP Config Request id %u\n",id)); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 132 | if(scan_packet((u16_t)LCP, lcplist, buffer, bptr, (u16_t)(len-4))) { |
| 133 | /* must do the -4 here, !scan packet */ |
| 134 | |
| 135 | DEBUG1((" options were rejected\n")); |
| 136 | } else { |
| 137 | /* lets try to implement what peer wants */ |
| 138 | tptr = bptr = buffer; |
| 139 | bptr += 4; /* skip code, id, len */ |
| 140 | error = 0; |
| 141 | /* first scan for unknown values */ |
| 142 | while(bptr < buffer+len) { |
| 143 | switch(*bptr++) { |
| 144 | case LPC_MRU: /* mru */ |
| 145 | j = *bptr++; |
| 146 | j -= 2; |
| 147 | if(j == 2) { |
| 148 | ppp_tx_mru = ((*bptr++<<8) || (*bptr++)); |
| 149 | DEBUG1(("<mru %d> ",ppp_tx_mru)); |
| 150 | } else { |
| 151 | DEBUG1(("<mru ??> ")); |
| 152 | } |
| 153 | break; |
| 154 | case LPC_ACCM: /* */ |
| 155 | bptr++; /* skip length */ |
| 156 | j = *bptr++; |
| 157 | j += *bptr++; |
| 158 | j += *bptr++; |
| 159 | j += *bptr++; |
| 160 | if((j==0) || (j==0x3fc)) { |
| 161 | // ok |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 162 | DEBUG1(("<asyncmap 0x%04x>",j)); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 163 | } else { |
| 164 | /* |
| 165 | * fail we only support default or all zeros |
| 166 | */ |
| 167 | DEBUG1(("We only support default or all zeros for ACCM ")); |
| 168 | error = 1; |
| 169 | *tptr++ = LPC_ACCM; |
| 170 | *tptr++ = 0x6; |
| 171 | *tptr++ = 0; |
| 172 | *tptr++ = 0; |
| 173 | *tptr++ = 0; |
| 174 | *tptr++ = 0; |
| 175 | } |
| 176 | break; |
| 177 | case LPC_AUTH: |
| 178 | bptr++; |
| 179 | if((*bptr++==0xc0) && (*bptr++==0x23)) { |
| 180 | DEBUG1(("<auth pap> ")); |
| 181 | /* negotiate PAP */ |
| 182 | lcp_state |= LCP_RX_AUTH; |
| 183 | } else { |
| 184 | /* we only support PAP */ |
| 185 | DEBUG1(("<auth ??>")); |
| 186 | error = 1; |
| 187 | *tptr++ = LPC_AUTH; |
| 188 | *tptr++ = 0x4; |
| 189 | *tptr++ = 0xc0; |
| 190 | *tptr++ = 0x23; |
| 191 | } |
| 192 | break; |
| 193 | case LPC_MAGICNUMBER: |
| 194 | DEBUG1(("<magic > ")); |
| 195 | /* |
| 196 | * Compair incoming number to our number (not implemented) |
| 197 | */ |
| 198 | bptr++; /* for now just dump */ |
| 199 | bptr++; |
| 200 | bptr++; |
| 201 | bptr++; |
| 202 | bptr++; |
| 203 | break; |
| 204 | case LPC_PFC: |
| 205 | bptr++; |
| 206 | DEBUG1(("<pcomp> ")); |
| 207 | /*tflag|=PPP_PFC;*/ |
| 208 | break; |
| 209 | case LPC_ACFC: |
| 210 | bptr++; |
| 211 | DEBUG1(("<accomp> ")); |
| 212 | /*tflag|=PPP_ACFC;*/ |
| 213 | break; |
| 214 | |
| 215 | } |
| 216 | } |
| 217 | /* Error? if we we need to send a config Reject ++++ this is good for a subroutine */ |
| 218 | if(error) { |
| 219 | /* write the config NAK packet we've built above, take on the header */ |
| 220 | bptr = buffer; |
| 221 | *bptr++ = CONF_NAK; /* Write Conf_rej */ |
| 222 | *bptr++;/*tptr++;*/ /* skip over ID */ |
| 223 | |
| 224 | /* Write new length */ |
| 225 | *bptr++ = 0; |
| 226 | *bptr = tptr - buffer; |
| 227 | |
| 228 | /* write the reject frame */ |
| 229 | DEBUG1(("\nWriting NAK frame \n")); |
| 230 | // Send packet ahdlc_txz(procol,header,data,headerlen,datalen); |
| 231 | ahdlc_tx(LCP, 0, buffer, 0, (u16_t)(tptr-buffer)); |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 232 | DEBUG1(("- end NAK Write frame\n")); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 233 | |
| 234 | } else { |
| 235 | /* |
| 236 | * If we get here then we are OK, lets send an ACK and tell the rest |
| 237 | * of our modules our negotiated config. |
| 238 | */ |
| 239 | DEBUG1(("\nSend ACK!\n")); |
| 240 | bptr = buffer; |
| 241 | *bptr++ = CONF_ACK; /* Write Conf_ACK */ |
| 242 | bptr++; /* Skip ID (send same one) */ |
| 243 | /* |
| 244 | * Set stuff |
| 245 | */ |
| 246 | /*ppp_flags|=tflag;*/ |
| 247 | /* DEBUG2("SET- stuff -- are we up? c=%d dif=%d \n", count, (u16_t)(bptr-buffer)); */ |
| 248 | |
| 249 | /* write the ACK frame */ |
| 250 | DEBUG2(("Writing ACK frame \n")); |
| 251 | /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ |
| 252 | ahdlc_tx(LCP, 0, buffer, 0, count /*bptr-buffer*/); |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 253 | DEBUG2(("- end ACK Write frame\n")); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 254 | |
| 255 | /* expire the timer to make things happen after a state change */ |
| 256 | /*timer_expire();*/ |
| 257 | |
| 258 | } |
| 259 | } |
| 260 | break; |
| 261 | case CONF_ACK: /* config Ack Anytime we do an ack reset the timer to force send. */ |
| 262 | DEBUG1(("LCP-ACK - ")); |
| 263 | /* check that ID matches one sent */ |
| 264 | if(*bptr++ == ppp_id) { |
| 265 | /* Change state to PPP up. */ |
| 266 | DEBUG1((">>>>>>>> good ACK id up!\n",ppp_id)); |
| 267 | /* copy negotiated values over */ |
| 268 | |
| 269 | lcp_state |= LCP_TX_UP; |
| 270 | |
| 271 | /* expire the timer to make things happen after a state change */ |
| 272 | TIMER_expire(); |
| 273 | } |
| 274 | else |
| 275 | DEBUG1(("*************++++++++++ bad id %d\n",ppp_id)); |
| 276 | break; |
| 277 | case CONF_NAK: /* Config Nack */ |
| 278 | DEBUG1(("LCP-CONF NAK\n")); |
| 279 | ppp_id++; |
| 280 | break; |
| 281 | case CONF_REJ: /* Config Reject */ |
| 282 | DEBUG1(("LCP-CONF REJ\n")); |
| 283 | ppp_id++; |
| 284 | break; |
| 285 | case TERM_REQ: /* Terminate Request */ |
| 286 | DEBUG1(("LCP-TERM-REQ -")); |
| 287 | bptr = buffer; |
| 288 | *bptr++ = TERM_ACK; /* Write TERM_ACK */ |
| 289 | /* write the reject frame */ |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 290 | DEBUG1(("Writing TERM_ACK frame \n")); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 291 | /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ |
| 292 | ahdlc_tx(LCP, 0, buffer, 0, count); |
| 293 | lcp_state &= ~LCP_TX_UP; |
| 294 | lcp_state |= LCP_TERM_PEER; |
| 295 | break; |
| 296 | case TERM_ACK: |
| 297 | DEBUG1(("LCP-TERM ACK\n")); |
| 298 | break; |
| 299 | default: |
| 300 | break; |
| 301 | } |
| 302 | } |
| 303 | /*---------------------------------------------------------------------------*/ |
| 304 | /* lcp_task(buffer) - This routine see if a lcp request needs to be sent |
| 305 | * out. It uses the passed buffer to form the packet. This formed LCP |
| 306 | * request is what we negotiate for sending options on the link. |
| 307 | * |
| 308 | * Currently we negotiate : Magic Number Only, but this will change. |
| 309 | */ |
| 310 | /*---------------------------------------------------------------------------*/ |
| 311 | void |
| 312 | lcp_task(u8_t *buffer) |
| 313 | { |
| 314 | u8_t *bptr; |
| 315 | u16_t t; |
| 316 | LCPPKT *pkt; |
| 317 | |
| 318 | /* lcp tx not up and hasn't timed out then lets see if we need to send a request */ |
| 319 | if(!(lcp_state & LCP_TX_UP) && !(lcp_state & LCP_TX_TIMEOUT)) { |
| 320 | /* Check if we have a request pending */ |
| 321 | /*t=get_seconds()-lcp_tx_time;*/ |
| 322 | if(1 == TIMER_timeout(LCP_TX_TIMEOUT)) { |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 323 | DEBUG1(("\nSending LCP request packet - ")); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 324 | /* |
| 325 | * No pending request, lets build one |
| 326 | */ |
| 327 | pkt = (LCPPKT *)buffer; |
| 328 | |
| 329 | /* Configure-Request only here, write id */ |
| 330 | pkt->code = CONF_REQ; |
| 331 | pkt->id = ppp_id; |
| 332 | |
| 333 | bptr = pkt->data; |
| 334 | |
| 335 | /* Write options */ |
| 336 | |
| 337 | /* Write magic number */ |
| 338 | DEBUG1(("LPC_MAGICNUMBER -")); |
| 339 | *bptr++ = LPC_MAGICNUMBER; |
| 340 | *bptr++ = 0x6; |
| 341 | *bptr++ = 0; |
| 342 | *bptr++ = 0; |
| 343 | *bptr++ = 0; |
| 344 | *bptr++ = 0; |
| 345 | |
| 346 | /* ACCM */ |
| 347 | #if 0 |
| 348 | if((lcp_tx_options & LCP_OPT_ACCM) & 0) { |
| 349 | *bptr++ = LPC_ACCM; |
| 350 | *bptr++ = 0x6; |
| 351 | *bptr++ = 0; |
| 352 | *bptr++ = 0; |
| 353 | *bptr++ = 0; |
| 354 | *bptr++ = 0; |
| 355 | } |
| 356 | /* |
| 357 | * Authentication protocol |
| 358 | */ |
| 359 | if((lcp_tx_options & LCP_OPT_AUTH) && 0) { |
| 360 | /* |
| 361 | * If turned on, we only negotiate PAP |
| 362 | */ |
| 363 | *bptr++ = LPC_AUTH; |
| 364 | *bptr++ = 0x4; |
| 365 | *bptr++ = 0xc0; |
| 366 | *bptr++ = 0x23; |
| 367 | } |
| 368 | /* |
| 369 | * PFC |
| 370 | */ |
| 371 | if((lcp_tx_options & LCP_OPT_PFC) && 0) { |
| 372 | /* |
| 373 | * If turned on, we only negotiate PAP |
| 374 | */ |
| 375 | *bptr++ = LPC_PFC; |
| 376 | *bptr++ = 0x2; |
| 377 | } |
| 378 | /* |
| 379 | * ACFC |
| 380 | */ |
| 381 | if((lcp_tx_options & LCP_OPT_ACFC) && 0) { |
| 382 | /* |
| 383 | * If turned on, we only negotiate PAP |
| 384 | */ |
| 385 | *bptr++ = LPC_ACFC; |
| 386 | *bptr++ = 0x2; |
| 387 | } |
| 388 | #endif |
| 389 | /* Write length */ |
| 390 | t = bptr - buffer; |
| 391 | pkt->len = htons(t); /* length here - code and ID + */ |
| 392 | |
oliverschmidt | 85729cb | 2005-01-26 23:36:22 +0000 | [diff] [blame] | 393 | DEBUG1((" len %d\n",t)); |
oliverschmidt | 3396e9a | 2004-08-20 12:29:54 +0000 | [diff] [blame] | 394 | |
| 395 | /* Send packet */ |
| 396 | /* Send packet ahdlc_txz(procol,header,data,headerlen,datalen); */ |
| 397 | ahdlc_tx(LCP, 0, buffer, 0, t); |
| 398 | |
| 399 | /* Set timer */ |
| 400 | TIMER_set(); |
| 401 | /*lcp_tx_time=get_seconds();*/ |
| 402 | /* Inc retry */ |
| 403 | ppp_retry++; |
| 404 | /* |
| 405 | * Have we timed out? |
| 406 | */ |
| 407 | if(ppp_retry > LCP_RETRY_COUNT) { |
| 408 | lcp_state &= LCP_TX_TIMEOUT; |
| 409 | } |
| 410 | } |
| 411 | } |
| 412 | } |
| 413 | /*---------------------------------------------------------------------------*/ |