ppplcp.c
上传用户:hepax88
上传日期:2007-01-03
资源大小:1101k
文件大小:27k
源码类别:

TCP/IP协议栈

开发平台:

Visual C++

  1. /*
  2.  *  PPPLCP.C -- negotiate data link options
  3.  *
  4.  * This implementation of PPP is declared to be in the public domain.
  5.  *
  6.  * Jan 91 Bill_Simpson@um.cc.umich.edu
  7.  * Computer Systems Consulting Services
  8.  *
  9.  * Acknowledgements and correction history may be found in PPP.C
  10.  */
  11. #include <stdio.h>
  12. #include "global.h"
  13. #include "mbuf.h"
  14. #include "iface.h"
  15. #include "socket.h"
  16. #include "ppp.h"
  17. #include "pppfsm.h"
  18. #include "ppplcp.h"
  19. #include "ppppap.h"
  20. #include "cmdparse.h"
  21. #include "devparam.h"
  22. #include "trace.h"
  23. /* These defaults are defined in the PPP RFCs, and must not be changed */
  24. static struct lcp_value_s lcp_default = {
  25. FALSE, /* no need to negotiate defaults */
  26. LCP_MRU_DEFAULT,
  27. LCP_ACCM_DEFAULT,
  28. 0, /* no authentication */
  29. 0, /* no encryption */
  30. 0L, /* no magic number */
  31. 0L, /* no reporting period */
  32. };
  33. /* for test purposes, accept anything we understand in the NAK */
  34. static uint16 lcp_negotiate = LCP_N_MRU | LCP_N_ACCM | LCP_N_AUTHENT
  35. | LCP_N_PFC | LCP_N_ACFC | LCP_N_MAGIC;
  36. static byte_t option_length[] = {
  37.  0, /* unused */
  38.  4, /* MRU */
  39.  6, /* ACCM */
  40.  4, /* authentication */
  41.  4, /* encryption */
  42.  6, /* magic number */
  43.  6, /* monitor reporting period */
  44.  2, /* Protocol compression */
  45.  2 /* Address/Control compression */
  46. };
  47. static int dolcp_local(int argc, char *argv[], void *p);
  48. static int dolcp_open(int argc, char *argv[], void *p);
  49. static int dolcp_remote(int argc, char *argv[], void *p);
  50. static int dolcp_accm(int argc, char *argv[], void *p);
  51. static int dolcp_acfc(int argc, char *argv[], void *p);
  52. static int dolcp_auth(int argc, char *argv[], void *p);
  53. static int dolcp_magic(int argc, char *argv[], void *p);
  54. static int dolcp_mru(int argc, char *argv[], void *p);
  55. static int dolcp_pfc(int argc, char *argv[], void *p);
  56. static int dolcp_default(int argc, char *argv[], void *p);
  57. static void lcp_option(struct mbuf **bpp,
  58. struct lcp_value_s *value_p,
  59. byte_t o_type,
  60. byte_t o_length,
  61. struct mbuf **copy_bpp );
  62. static void lcp_makeoptions(struct mbuf **bpp,
  63. struct lcp_value_s *value_p,
  64. uint16 negotiating);
  65. static struct mbuf *lcp_makereq(struct fsm_s *fsm_p);
  66. static int lcp_check(struct mbuf **bpp,
  67. struct lcp_s *lcp_p,
  68. struct lcp_side_s *side_p,
  69. struct option_hdr *option_p,
  70. int request);
  71. static int lcp_request(struct fsm_s *fsm_p,
  72. struct config_hdr *config,
  73. struct mbuf **data);
  74. static int lcp_ack(struct fsm_s *fsm_p,
  75. struct config_hdr *ackcnf,
  76. struct mbuf **data);
  77. static int lcp_nak(struct fsm_s *fsm_p,
  78. struct config_hdr *nakcnf,
  79. struct mbuf **data);
  80. static int lcp_reject(struct fsm_s *fsm_p,
  81. struct config_hdr *rejcnf,
  82. struct mbuf **data);
  83. static void lcp_reset(struct fsm_s *fsm_p);
  84. static void lcp_starting(struct fsm_s *fsm_p);
  85. static void lcp_stopping(struct fsm_s *fsm_p);
  86. static void lcp_closing(struct fsm_s *fsm_p);
  87. static void lcp_opening(struct fsm_s *fsm_p);
  88. static void lcp_free(struct fsm_s *fsm_p);
  89. static struct fsm_constant_s lcp_constants = {
  90. "Lcp",
  91. PPP_LCP_PROTOCOL,
  92. 0x0FFE, /* codes 1-11 recognized */
  93. Lcp,
  94. LCP_REQ_TRY,
  95. LCP_NAK_TRY,
  96. LCP_TERM_TRY,
  97. LCP_TIMEOUT * 1000L,
  98. lcp_free,
  99. lcp_reset,
  100. lcp_starting,
  101. lcp_opening,
  102. lcp_closing,
  103. lcp_stopping,
  104. lcp_makereq,
  105. lcp_request,
  106. lcp_ack,
  107. lcp_nak,
  108. lcp_reject
  109. };
  110. /************************************************************************/
  111. /* "ppp <iface> lcp" subcommands */
  112. static struct cmds Lcpcmds[] = {
  113. "close", doppp_close, 0, 0, NULL,
  114. "listen", doppp_passive, 0, 0, NULL,
  115. "local", dolcp_local, 0, 0, NULL,
  116. "open", dolcp_open, 0, 0, NULL,
  117. "remote", dolcp_remote, 0, 0, NULL,
  118. "timeout", doppp_timeout, 0, 0, NULL,
  119. "try", doppp_try, 0, 0, NULL,
  120. NULL,
  121. };
  122. /* "ppp <iface> lcp [local | remote]" subcommands */
  123. static struct cmds Lcpside_cmds[] = {
  124. "accm", dolcp_accm, 0, 0, NULL,
  125. "acfc", dolcp_acfc, 0, 0, NULL,
  126. "authenticate", dolcp_auth, 0, 0, NULL,
  127. "magic", dolcp_magic, 0, 0, NULL,
  128. "mru", dolcp_mru, 0, 0, NULL,
  129. "pfc", dolcp_pfc, 0, 0, NULL,
  130. "default", dolcp_default, 0, 0, NULL,
  131. NULL,
  132. };
  133. int
  134. doppp_lcp(argc,argv,p)
  135. int argc;
  136. char *argv[];
  137. void *p;
  138. {
  139. register struct iface *ifp = p;
  140. register struct ppp_s *ppp_p = ifp->edv;
  141. return subcmd(Lcpcmds, argc, argv, &(ppp_p->fsm[Lcp]));
  142. }
  143. static int
  144. dolcp_local(argc,argv,p)
  145. int argc;
  146. char *argv[];
  147. void *p;
  148. {
  149. struct fsm_s *fsm_p = p;
  150. struct lcp_s *lcp_p = fsm_p->pdv;
  151. return subcmd(Lcpside_cmds, argc, argv, &(lcp_p->local));
  152. }
  153. static int
  154. dolcp_open(argc,argv,p)
  155. int argc;
  156. char *argv[];
  157. void *p;
  158. {
  159. struct fsm_s *fsm_p = p;
  160. doppp_active( argc, argv, p );
  161. if ( fsm_p->ppp_p->phase >= pppLCP ) {
  162. fsm_start( fsm_p );
  163. }
  164. return 0;
  165. }
  166. static int
  167. dolcp_remote(argc,argv,p)
  168. int argc;
  169. char *argv[];
  170. void *p;
  171. {
  172. struct fsm_s *fsm_p = p;
  173. struct lcp_s *lcp_p = fsm_p->pdv;
  174. return subcmd(Lcpside_cmds, argc, argv, &(lcp_p->remote));
  175. }
  176. /************************************************************************/
  177. static int
  178. dolcp_accm(argc,argv,p)
  179. int argc;
  180. char *argv[];
  181. void *p;
  182. {
  183. struct lcp_side_s *side_p = p;
  184. if (argc < 2) {
  185. printf("0x%08lxn",side_p->want.accm);
  186. } else if (stricmp(argv[1],"allow") == 0) {
  187. return bit16cmd(&(side_p->will_negotiate),LCP_N_ACCM,
  188. "Allow ACCM", --argc, &argv[1] );
  189. } else {
  190. side_p->want.accm = strtoul(argv[1], NULL, 0);
  191. if ( side_p->want.accm != LCP_ACCM_DEFAULT )
  192. side_p->want.negotiate |= LCP_N_ACCM;
  193. else
  194. side_p->want.negotiate &= ~LCP_N_ACCM;
  195. }
  196. return 0;
  197. }
  198. static int
  199. dolcp_acfc(argc,argv,p)
  200. int argc;
  201. char *argv[];
  202. void *p;
  203. {
  204. struct lcp_side_s *side_p = p;
  205. if (stricmp(argv[1],"allow") == 0) {
  206. return bit16cmd(&(side_p->will_negotiate),LCP_N_ACFC,
  207. "Allow Address/Control Field Compression", --argc, &argv[1] );
  208. }
  209. return bit16cmd( &(side_p->want.negotiate), LCP_N_ACFC,
  210. "Address/Control Field Compression", argc, argv );
  211. }
  212. static int
  213. dolcp_auth(argc,argv,p)
  214. int argc;
  215. char *argv[];
  216. void *p;
  217. {
  218. struct lcp_side_s *side_p = p;
  219. if (argc < 2) {
  220. if ( side_p->want.negotiate & LCP_N_AUTHENT ) {
  221. switch ( side_p->want.authentication ) {
  222. case PPP_PAP_PROTOCOL:
  223. printf("Papn");
  224. break;
  225. default:
  226. printf("0x%04xn", side_p->want.authentication);
  227. break;
  228. };
  229. } else {
  230. printf("Nonen");
  231. }
  232. } else if (stricmp(argv[1],"allow") == 0) {
  233. return bit16cmd(&(side_p->will_negotiate),LCP_N_AUTHENT,
  234. "Allow Authentication", --argc, &argv[1] );
  235. } else if (stricmp(argv[1],"pap") == 0) {
  236. side_p->want.negotiate |= LCP_N_AUTHENT;
  237. side_p->want.authentication = PPP_PAP_PROTOCOL;
  238. } else if (stricmp(argv[1],"none") == 0) {
  239. side_p->want.negotiate &= ~LCP_N_AUTHENT;
  240. } else {
  241. printf("allow pap nonen");
  242. return 1;
  243. }
  244. return 0;
  245. }
  246. static int
  247. dolcp_magic(argc,argv,p)
  248. int argc;
  249. char *argv[];
  250. void *p;
  251. {
  252. struct lcp_side_s *side_p = p;
  253. int result = 0;
  254. if (argc < 2) {
  255. printf("%dn",side_p->want.magic_number);
  256. } else if (stricmp(argv[1],"allow") == 0) {
  257. return bit16cmd(&(side_p->will_negotiate),LCP_N_MAGIC,
  258. "Allow Magic Number", --argc, &argv[1] );
  259. } else {
  260. register int32 x = strtoul(argv[1], NULL, 0);
  261. if ( !x ) {
  262. int test;
  263. /* Check for keyword */
  264. result = setbool( &test, "Magic Number", argc, argv );
  265. if ( test ) {
  266. /* Make a non-zero random number */
  267. x = rdclock() << ((rdclock() & 0xf)+8);
  268. }
  269. }
  270. if ( x ) {
  271. side_p->want.negotiate |= LCP_N_MAGIC;
  272. } else {
  273. side_p->want.negotiate &= ~LCP_N_MAGIC;
  274. }
  275. side_p->want.magic_number = x;
  276. }
  277. return result;
  278. }
  279. static int
  280. dolcp_mru(argc,argv,p)
  281. int argc;
  282. char *argv[];
  283. void *p;
  284. {
  285. struct lcp_side_s *side_p = p;
  286. if (argc < 2) {
  287. printf("%dn",side_p->want.mru);
  288. } else if (stricmp(argv[1],"allow") == 0) {
  289. return bit16cmd(&(side_p->will_negotiate),LCP_N_MRU,
  290. "Allow MRU", --argc, &argv[1] );
  291. } else {
  292. register int x = (int)strtol( argv[1], NULL, 0 );
  293. if (x < LCP_MRU_LO || x > LCP_MRU_HI) {
  294. printf("MRU %s (%d) out of range %d thru %dn",
  295. argv[1], x, LCP_MRU_LO, LCP_MRU_HI);
  296. return -1;
  297. } else if ( x != LCP_MRU_DEFAULT ) {
  298. side_p->want.negotiate |= LCP_N_MRU;
  299. } else {
  300. side_p->want.negotiate &= ~LCP_N_MRU;
  301. }
  302. side_p->want.mru = x;
  303. }
  304. return 0;
  305. }
  306. static int
  307. dolcp_pfc(argc,argv,p)
  308. int argc;
  309. char *argv[];
  310. void *p;
  311. {
  312. struct lcp_side_s *side_p = p;
  313. if (stricmp(argv[1],"allow") == 0) {
  314. return bit16cmd(&(side_p->will_negotiate),LCP_N_PFC,
  315. "Allow Protocol Field Compression", --argc, &argv[1] );
  316. }
  317. return bit16cmd( &(side_p->want.negotiate), LCP_N_PFC,
  318. "Protocol Field Compression", argc, argv );
  319. }
  320. static int
  321. dolcp_default(argc,argv,p)
  322. int argc;
  323. char *argv[];
  324. void *p;
  325. {
  326. struct lcp_side_s *side_p = p;
  327. ASSIGN( side_p->want, lcp_default );
  328. return 0;
  329. }
  330. /************************************************************************/
  331. /* E V E N T   P R O C E S S I N G */
  332. /************************************************************************/
  333. static void
  334. lcp_option( bpp, value_p, o_type, o_length, copy_bpp )
  335. struct mbuf **bpp;
  336. struct lcp_value_s *value_p;
  337. byte_t o_type;
  338. byte_t o_length;
  339. struct mbuf **copy_bpp;
  340. {
  341. struct mbuf *bp;
  342. register uint8 *cp;
  343. register int toss = o_length - OPTION_HDR_LEN;
  344. if ((bp = alloc_mbuf(o_length)) == NULL) {
  345. return;
  346. }
  347. cp = bp->data;
  348. *cp++ = o_type;
  349. *cp++ = o_length;
  350. switch ( o_type ) {
  351. case LCP_MRU:
  352. put16(cp, value_p->mru);
  353. toss -= 2;
  354. #ifdef PPP_DEBUG_OPTIONS
  355. if (PPPtrace & PPP_DEBUG_OPTIONS)
  356. trace_log(PPPiface, "    making MRU: %d", value_p->mru);
  357. #endif
  358. break;
  359. case LCP_ACCM:
  360. put32(cp, value_p->accm);
  361. toss -= 4;
  362. #ifdef PPP_DEBUG_OPTIONS
  363. if (PPPtrace & PPP_DEBUG_OPTIONS)
  364. trace_log(PPPiface, "    making ACCM: 0x%08lx", value_p->accm);
  365. #endif
  366. break;
  367. case LCP_AUTHENT:
  368. put16(cp, value_p->authentication);
  369. toss -= 2;
  370. #ifdef PPP_DEBUG_OPTIONS
  371. if (PPPtrace & PPP_DEBUG_OPTIONS)
  372. trace_log(PPPiface, "    making Auth Protocol: 0x%04x",
  373. value_p->authentication);
  374. #endif
  375. break;
  376. case LCP_MAGIC:
  377. put32(cp, value_p->magic_number);
  378. toss -= 4;
  379. #ifdef PPP_DEBUG_OPTIONS
  380. if (PPPtrace & PPP_DEBUG_OPTIONS)
  381. trace_log(PPPiface, "    making Magic Number: 0x%08lx",
  382. value_p->magic_number);
  383. #endif
  384. break;
  385. case LCP_PFC:
  386. #ifdef PPP_DEBUG_OPTIONS
  387. if (PPPtrace & PPP_DEBUG_OPTIONS)
  388. trace_log(PPPiface, "    making Protocol compression");
  389. #endif
  390. break;
  391. case LCP_ACFC:
  392. #ifdef PPP_DEBUG_OPTIONS
  393. if (PPPtrace & PPP_DEBUG_OPTIONS)
  394. trace_log(PPPiface, "    making Addr/Ctl compression");
  395. #endif
  396. break;
  397. case LCP_ENCRYPT: /* not implemented */
  398. case LCP_QUALITY: /* not implemented */
  399. default:
  400. #ifdef PPP_DEBUG_OPTIONS
  401. if (PPPtrace & PPP_DEBUG_OPTIONS)
  402. trace_log(PPPiface, "    making unimplemented type %d", o_type);
  403. #endif
  404. break;
  405. };
  406. while ( toss-- > 0 ) {
  407. *cp++ = pullchar(copy_bpp);
  408. }
  409. bp->cnt += o_length;
  410. append(bpp, &bp);
  411. }
  412. /************************************************************************/
  413. /* Build a list of options */
  414. static void
  415. lcp_makeoptions(bpp, value_p, negotiating)
  416. struct mbuf **bpp;
  417. struct lcp_value_s *value_p;
  418. uint16 negotiating;
  419. {
  420. register int o_type;
  421. PPP_DEBUG_ROUTINES("lcp_makeoptions()");
  422. for ( o_type = 1; o_type <= LCP_OPTION_LIMIT; o_type++ ) {
  423. if (negotiating & (1 << o_type)) {
  424. lcp_option( bpp, value_p,
  425. o_type, option_length[ o_type ], NULL);
  426. }
  427. }
  428. }
  429. /************************************************************************/
  430. /* Build a request to send to remote host */
  431. static struct mbuf *
  432. lcp_makereq(fsm_p)
  433. struct fsm_s *fsm_p;
  434. {
  435. struct lcp_s *lcp_p = fsm_p->pdv;
  436. struct mbuf *req_bp = NULL;
  437. PPP_DEBUG_ROUTINES("lcp_makereq()");
  438. lcp_makeoptions( &req_bp, &(lcp_p->local.work),
  439. lcp_p->local.work.negotiate );
  440. return(req_bp);
  441. }
  442. /************************************************************************/
  443. /* Check the options, updating the working values.
  444.  * Returns -1 if ran out of data, ACK/NAK/REJ as appropriate.
  445.  */
  446. static int
  447. lcp_check( bpp, lcp_p, side_p, option_p, request )
  448. struct mbuf **bpp;
  449. struct lcp_s *lcp_p;
  450. struct lcp_side_s *side_p;
  451. struct option_hdr *option_p;
  452. int request;
  453. {
  454. int toss = option_p->len - OPTION_HDR_LEN;
  455. int option_result = CONFIG_ACK; /* Assume good values */
  456. switch(option_p->type) {
  457. case LCP_MRU:
  458. side_p->work.mru = pull16(bpp);
  459. toss -= 2;
  460. #ifdef PPP_DEBUG_OPTIONS
  461. if (PPPtrace & PPP_DEBUG_OPTIONS)
  462. trace_log(PPPiface, "    checking MRU: %d", side_p->work.mru);
  463. #endif
  464. /* Check if new value is appropriate */
  465. if (side_p->work.mru < LCP_MRU_LO) {
  466. side_p->work.mru = LCP_MRU_LO;
  467. option_result = CONFIG_NAK;
  468. } else if (side_p->work.mru > LCP_MRU_HI) {
  469. side_p->work.mru = LCP_MRU_HI;
  470. option_result = CONFIG_NAK;
  471. }
  472. if ( request && (side_p->want.negotiate & LCP_N_MRU)
  473.   && side_p->work.mru > side_p->want.mru ) {
  474. side_p->work.mru = side_p->want.mru;
  475. option_result = side_p->want.mru;
  476. }
  477. break;
  478. case LCP_ACCM:
  479. side_p->work.accm = pull32(bpp);
  480. toss -= 4;
  481. #ifdef PPP_DEBUG_OPTIONS
  482. if (PPPtrace & PPP_DEBUG_OPTIONS)
  483. trace_log(PPPiface, "    checking ACCM: 0x%08lx", side_p->work.accm);
  484. #endif
  485. /* Remote host may ask to escape more control  */
  486. /* characters than we require, but must escape */
  487. /* at least the control chars that we require. */
  488. if ( (!request || (side_p->want.negotiate & LCP_N_ACCM))
  489.   && side_p->work.accm !=
  490.        (side_p->work.accm | side_p->want.accm) ) {
  491. side_p->work.accm |= side_p->want.accm;
  492. option_result = CONFIG_NAK;
  493. }
  494. break;
  495. case LCP_AUTHENT:
  496. side_p->work.authentication = pull16(bpp);
  497. toss -= 2;
  498. #ifdef PPP_DEBUG_OPTIONS
  499. if (PPPtrace & PPP_DEBUG_OPTIONS)
  500. trace_log(PPPiface, "    checking Auth Protocol: 0x%04x",
  501. side_p->work.authentication);
  502. #endif
  503. /* Check if new value is appropriate */
  504. switch ( side_p->work.authentication ) {
  505. case PPP_PAP_PROTOCOL:
  506. /* Yes */
  507. break;
  508. default:
  509. side_p->work.authentication = PPP_PAP_PROTOCOL;
  510. option_result = CONFIG_NAK;
  511. break;
  512. };
  513. break;
  514. case LCP_MAGIC:
  515. side_p->work.magic_number = pull32(bpp);
  516. toss -= 4;
  517. #ifdef PPP_DEBUG_OPTIONS
  518. if (PPPtrace & PPP_DEBUG_OPTIONS)
  519. trace_log(PPPiface, "    checking Magic Number: 0x%08lx",
  520. side_p->work.magic_number);
  521. #endif
  522. /* Ensure that magic numbers are different */
  523. if (side_p->work.magic_number == 0L
  524.  || lcp_p->remote.work.magic_number == lcp_p->local.work.magic_number) {
  525. side_p->work.magic_number += rdclock();
  526. option_result = CONFIG_NAK;
  527. }
  528. break;
  529. case LCP_PFC:
  530. #ifdef PPP_DEBUG_OPTIONS
  531. if (PPPtrace & PPP_DEBUG_OPTIONS)
  532. trace_log(PPPiface, "    checking Protocol compression");
  533. #endif
  534. break;
  535. case LCP_ACFC:
  536. #ifdef PPP_DEBUG_OPTIONS
  537. if (PPPtrace & PPP_DEBUG_OPTIONS)
  538. trace_log(PPPiface, "    checking Addr/Ctl compression");
  539. #endif
  540. break;
  541. case LCP_ENCRYPT: /* not implemented */
  542. case LCP_QUALITY: /* not implemented */
  543. default:
  544. option_result = CONFIG_REJ;
  545. break;
  546. };
  547. if (option_p->type > LCP_OPTION_LIMIT
  548.  || !(side_p->will_negotiate & (1 << option_p->type))) {
  549. option_result = CONFIG_REJ;
  550. }
  551. if ( toss < 0 )
  552. return -1;
  553. if ( !request  &&  toss > 0 ) {
  554. /* toss extra bytes in option */
  555. while( toss-- > 0 ) {
  556. if ( pullchar(bpp) == -1 )
  557. return -1;
  558. }
  559. }
  560. return (option_result);
  561. }
  562. /************************************************************************/
  563. /* Check Link Control options requested by the remote host */
  564. static int
  565. lcp_request(fsm_p, config, data)
  566. struct fsm_s *fsm_p;
  567. struct config_hdr *config;
  568. struct mbuf **data;
  569. {
  570. struct lcp_s *lcp_p = fsm_p->pdv;
  571. int32 signed_length = config->len;
  572. struct mbuf *reply_bp = NULL; /* reply packet */
  573. int reply_result = CONFIG_ACK; /* reply to request */
  574. uint16 desired; /* desired to negotiate */
  575. struct option_hdr option; /* option header storage */
  576. int option_result; /* option reply */
  577. PPP_DEBUG_ROUTINES("lcp_request()");
  578. lcp_p->remote.work.negotiate = FALSE; /* clear flags */
  579. /* Process options requested by remote host */
  580. while (signed_length > 0  &&  ntohopt(&option, data) != -1) {
  581. if ((signed_length -= option.len) < 0) {
  582. PPP_DEBUG_CHECKS("LCP REQ: bad header length");
  583. free_p(data);
  584. free_p(&reply_bp);
  585. return -1;
  586. }
  587. if ( ( option_result = lcp_check( data, lcp_p,
  588. &(lcp_p->remote), &option, TRUE ) ) == -1 ) {
  589. PPP_DEBUG_CHECKS("LCP REQ: ran out of data");
  590. free_p(data);
  591. free_p(&reply_bp);
  592. return -1;
  593. }
  594. #ifdef PPP_DEBUG_OPTIONS
  595. if (PPPtrace & PPP_DEBUG_OPTIONS) {
  596. trace_log(PPPiface, "LCP REQ: result %s, option %d, length %d",
  597. fsmCodes[option_result],
  598. option.type,
  599. option.len);
  600. }
  601. #endif
  602. if ( option_result < reply_result ) {
  603. continue;
  604. } else if ( option_result > reply_result ) {
  605. /* Discard current list of replies */
  606. free_p(&reply_bp);
  607. reply_bp = NULL;
  608. reply_result = option_result;
  609. }
  610. /* remember that we processed option */
  611. if ( option_result != CONFIG_REJ
  612.   && option.type <= LCP_OPTION_LIMIT ) {
  613. lcp_p->remote.work.negotiate |= (1 << option.type);
  614. }
  615. /* Add option response to the return list */
  616. lcp_option( &reply_bp, &(lcp_p->remote.work),
  617. option.type, option.len, data );
  618. }
  619. /* Now check for any missing options which are desired */
  620. if ( fsm_p->retry_nak > 0
  621.  &&  (desired = lcp_p->remote.want.negotiate
  622.        & ~lcp_p->remote.work.negotiate) != 0 ) {
  623. switch ( reply_result ) {
  624. case CONFIG_ACK:
  625. free_p(&reply_bp);
  626. reply_bp = NULL;
  627. reply_result = CONFIG_NAK;
  628. /* fallthru */
  629. case CONFIG_NAK:
  630. lcp_makeoptions( &reply_bp, &(lcp_p->remote.want),
  631. desired );
  632. fsm_p->retry_nak--;
  633. break;
  634. case CONFIG_REJ:
  635. /* do nothing */
  636. break;
  637. };
  638. } else if ( reply_result == CONFIG_NAK ) {
  639. /* if too many NAKs, reject instead */
  640. if ( fsm_p->retry_nak > 0 )
  641. fsm_p->retry_nak--;
  642. else
  643. reply_result = CONFIG_REJ;
  644. }
  645. /* Send ACK/NAK/REJ to remote host */
  646. fsm_send(fsm_p, reply_result, config->id, &reply_bp);
  647. free_p(data);
  648. return (reply_result != CONFIG_ACK);
  649. }
  650. /************************************************************************/
  651. /* Process configuration ACK sent by remote host */
  652. static int
  653. lcp_ack(
  654. struct fsm_s *fsm_p,
  655. struct config_hdr *config,
  656. struct mbuf **data
  657. ){
  658. struct mbuf *req_bp;
  659. int error = FALSE;
  660. PPP_DEBUG_ROUTINES("lcp_ack()");
  661. /* ID field must match last request we sent */
  662. if (config->id != fsm_p->lastid) {
  663. PPP_DEBUG_CHECKS("LCP ACK: wrong ID");
  664. free_p(data);
  665. return -1;
  666. }
  667. /* Get a copy of last request we sent */
  668. req_bp = lcp_makereq(fsm_p);
  669. /* Overall buffer length should match */
  670. if (config->len != len_p(req_bp)) {
  671. PPP_DEBUG_CHECKS("LCP ACK: buffer length mismatch");
  672. error = TRUE;
  673. } else {
  674. register int req_char;
  675. register int ack_char;
  676. /* Each byte should match */
  677. while ((req_char = pullchar(&req_bp)) != -1) {
  678. if ((ack_char = pullchar(data)) == -1
  679.  || ack_char != req_char ) {
  680. PPP_DEBUG_CHECKS("LCP ACK: data mismatch");
  681. /*trace_log(PPPiface, "req=%02X, ack=%02X", req_char, ack_char);*/
  682. error = TRUE;
  683. break;
  684. }
  685. }
  686. }
  687. free_p(&req_bp);
  688. free_p(data);
  689. if (error) {
  690. return -1;
  691. }
  692. PPP_DEBUG_CHECKS("LCP ACK: valid");
  693. return 0;
  694. }
  695. /************************************************************************/
  696. /* Process configuration NAK sent by remote host */
  697. static int
  698. lcp_nak(
  699. struct fsm_s *fsm_p,
  700. struct config_hdr *config,
  701. struct mbuf **data
  702. ){
  703. struct lcp_s *lcp_p = fsm_p->pdv;
  704. struct lcp_side_s *local_p = &(lcp_p->local);
  705. int32 signed_length = config->len;
  706. struct option_hdr option;
  707. int last_option = 0;
  708. int result;
  709. PPP_DEBUG_ROUTINES("lcp_nak()");
  710. /* ID field must match last request we sent */
  711. if (config->id != fsm_p->lastid) {
  712. PPP_DEBUG_CHECKS("LCP NAK: wrong ID");
  713. free_p(data);
  714. return -1;
  715. }
  716. /* First, process in order.  Then, process extra "important" options */
  717. while (signed_length > 0  &&  ntohopt(&option, data) != -1) {
  718. if ((signed_length -= option.len) < 0) {
  719. PPP_DEBUG_CHECKS("LCP NAK: bad header length");
  720. free_p(data);
  721. return -1;
  722. }
  723. if ( option.type > LCP_OPTION_LIMIT ) {
  724. PPP_DEBUG_CHECKS("LCP NAK: option out of range");
  725. } else if ( option.type < last_option
  726.   || !(local_p->work.negotiate & (1 << option.type)) ) {
  727. if (local_p->work.negotiate & (1 << option.type)) {
  728. PPP_DEBUG_CHECKS("LCP NAK: option out of order");
  729. free_p(data);
  730. return -1; /* was requested */
  731. }
  732. local_p->work.negotiate |= (1 << option.type);
  733. last_option = LCP_OPTION_LIMIT + 1;
  734. } else {
  735. last_option = option.type;
  736. }
  737. if ( ( result = lcp_check( data, lcp_p,
  738. local_p, &option, FALSE ) ) == -1 ) {
  739. PPP_DEBUG_CHECKS("LCP NAK: ran out of data");
  740. free_p(data);
  741. return -1;
  742. }
  743. /* update the negotiation status */
  744. if ( result == CONFIG_REJ
  745.   && option.type <= LCP_OPTION_LIMIT ) {
  746. local_p->work.negotiate &= ~(1 << option.type);
  747. }
  748. }
  749. PPP_DEBUG_CHECKS("LCP NAK: valid");
  750. free_p(data);
  751. return 0;
  752. }
  753. /************************************************************************/
  754. /* Process configuration reject sent by remote host */
  755. static int
  756. lcp_reject(
  757. struct fsm_s *fsm_p,
  758. struct config_hdr *config,
  759. struct mbuf **data
  760. ){
  761. struct lcp_s *lcp_p = fsm_p->pdv;
  762. struct lcp_side_s *local_p = &(lcp_p->local);
  763. int32 signed_length = config->len;
  764. struct option_hdr option;
  765. int last_option = 0;
  766. PPP_DEBUG_ROUTINES("lcp_reject()");
  767. /* ID field must match last request we sent */
  768. if (config->id != fsm_p->lastid) {
  769. PPP_DEBUG_CHECKS("LCP REJ: wrong ID");
  770. free_p(data);
  771. return -1;
  772. }
  773. /* Process in order, checking for errors */
  774. while (signed_length > 0  &&  ntohopt(&option, data) != -1) {
  775. register int k;
  776. if ((signed_length -= option.len) < 0) {
  777. PPP_DEBUG_CHECKS("LCP REJ: bad header length");
  778. free_p(data);
  779. return -1;
  780. }
  781. if ( option.type > LCP_OPTION_LIMIT ) {
  782. PPP_DEBUG_CHECKS("LCP REJ: option out of range");
  783. } else if ( option.type < last_option
  784.  || !(local_p->work.negotiate & (1 << option.type))) {
  785. PPP_DEBUG_CHECKS("LCP REJ: option out of order");
  786. free_p(data);
  787. return -1;
  788. }
  789. for ( k = option.len - OPTION_HDR_LEN; k-- > 0; ) {
  790. if ( pullchar(data) == -1 ) {
  791. PPP_DEBUG_CHECKS("LCP REJ: ran out of data");
  792. free_p(data);
  793. return -1;
  794. }
  795. }
  796. last_option = option.type;
  797. if ( option.type <= LCP_OPTION_LIMIT ) {
  798. local_p->work.negotiate &= ~(1 << option.type);
  799. }
  800. }
  801. PPP_DEBUG_CHECKS("LCP REJ: valid");
  802. free_p(data);
  803. return 0;
  804. }
  805. /************************************************************************/
  806. /* I N I T I A L I Z A T I O N */
  807. /************************************************************************/
  808. /* Check for PPP Network-Layer Protocol Phase */
  809. void
  810. ppp_ready(ppp_p)
  811. struct ppp_s *ppp_p;
  812. {
  813. if ( !(ppp_p->flags & (PPP_AP_LOCAL | PPP_AP_REMOTE)) ) {
  814. /* no pending authentication */
  815. ppp_p->phase = pppREADY;
  816. ppp_p->upsince = secclock();
  817. fsm_start( &(ppp_p->fsm[IPcp]) );
  818. }
  819. }
  820. /****************************************************************************/
  821. /* Reset configuration options before request */
  822. static void
  823. lcp_reset(fsm_p)
  824. struct fsm_s *fsm_p;
  825. {
  826. struct lcp_s *lcp_p =  fsm_p->pdv;
  827. PPP_DEBUG_ROUTINES("lcp_reset()");
  828. if ( lcp_p->local.want.negotiate & LCP_N_MAGIC ) {
  829. lcp_p->local.want.magic_number += rdclock();
  830. }
  831. ASSIGN( lcp_p->local.work, lcp_p->local.want );
  832. lcp_p->local.will_negotiate |= lcp_p->local.want.negotiate;
  833. lcp_p->remote.work.negotiate = FALSE;
  834. lcp_p->remote.will_negotiate |= lcp_p->remote.want.negotiate;
  835. }
  836. /************************************************************************/
  837. /* Prepare to begin configuration exchange */
  838. static void
  839. lcp_starting(fsm_p)
  840. struct fsm_s *fsm_p;
  841. {
  842. PPP_DEBUG_ROUTINES("lcp_starting()");
  843. fsm_p->ppp_p->phase = pppLCP;
  844. }
  845. /************************************************************************/
  846. /* After termination */
  847. static void
  848. lcp_stopping(fsm_p)
  849. struct fsm_s *fsm_p;
  850. {
  851. struct iface *ifp = fsm_p->ppp_p->iface;
  852. PPP_DEBUG_ROUTINES("lcp_stopping()");
  853. /* Tell the dialer to shut down */
  854. if ( ifp->supv != NULL )
  855. alert( ifp->supv, EABORT );
  856. /* Now, tell the device to go down.
  857.  * In turn, it should tell our IO status
  858.  * when it has gone down.
  859.  */
  860. ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  861. }
  862. /************************************************************************/
  863. /* Close higher levels in preparation for link shutdown */
  864. static void
  865. lcp_closing(fsm_p)
  866. struct fsm_s *fsm_p;
  867. {
  868. struct ppp_s *ppp_p = fsm_p->ppp_p;
  869. ppp_p->phase = pppTERMINATE;
  870. fsm_down( &(ppp_p->fsm[IPcp]) );
  871. pap_down( &(ppp_p->fsm[Pap]) );
  872. }
  873. #ifdef TURBOC_SWITCH_BUG
  874. #pragma option -G-
  875. #endif
  876. /************************************************************************/
  877. /* configuration negotiation complete */
  878. static void
  879. lcp_opening(fsm_p)
  880. struct fsm_s *fsm_p;
  881. {
  882. struct lcp_s *lcp_p =  fsm_p->pdv;
  883. struct iface *ifp =  fsm_p->ppp_p->iface;
  884. if (ifp->mtu != lcp_p->remote.work.mru) {
  885. /* Set new Max Transmission Unit for outgoing packets */
  886. ifp->mtu = lcp_p->remote.work.mru;
  887. if (PPPtrace > 1)
  888. trace_log(PPPiface,"    Set new MTU for outgoing packets: %d",
  889. ifp->mtu);
  890. }
  891. /* check for authentication */
  892. fsm_p->ppp_p->phase = pppAP;
  893. fsm_p->ppp_p->flags &= ~(PPP_AP_LOCAL | PPP_AP_REMOTE);
  894. free(fsm_p->ppp_p->peername);
  895. fsm_p->ppp_p->peername = NULL;
  896. if (lcp_p->local.work.negotiate & LCP_N_AUTHENT) {
  897. switch (lcp_p->local.work.authentication) {
  898. case PPP_PAP_PROTOCOL:
  899. pap_local(fsm_p->ppp_p);
  900. break;
  901. };
  902. }
  903. if (lcp_p->remote.work.negotiate & LCP_N_AUTHENT) {
  904. switch (lcp_p->remote.work.authentication) {
  905. case PPP_PAP_PROTOCOL:
  906. pap_remote(fsm_p->ppp_p);
  907. break;
  908. };
  909. }
  910. /* re-check for authentication */
  911. ppp_ready(fsm_p->ppp_p);
  912. }
  913. #ifdef TURBOC_SWITCH_BUG
  914. #pragma option -G
  915. #endif
  916. /************************************************************************/
  917. static void
  918. lcp_free(fsm_p)
  919. struct fsm_s *fsm_p;
  920. {
  921. /* nothing to do */
  922. }
  923. /* Initialize configuration structure */
  924. void
  925. lcp_init(ppp_p)
  926. struct ppp_s *ppp_p;
  927. {
  928. struct fsm_s *fsm_p = &(ppp_p->fsm[Lcp]);
  929. struct lcp_s *lcp_p;
  930. PPPtrace = ppp_p->trace;
  931. PPPiface = ppp_p->iface;
  932. PPP_DEBUG_ROUTINES("lcp_init()");
  933. fsm_p->ppp_p = ppp_p;
  934. fsm_p->pdc = &lcp_constants;
  935. fsm_p->pdv =
  936. lcp_p = callocw(1,sizeof(struct lcp_s));
  937. /* Set option parameters to first request defaults */
  938. ASSIGN( lcp_p->local.want, lcp_default );
  939. lcp_p->local.will_negotiate = lcp_negotiate;
  940. ASSIGN( lcp_p->remote.want, lcp_default );
  941. ASSIGN( lcp_p->remote.work, lcp_default );
  942. lcp_p->remote.will_negotiate = lcp_negotiate;
  943. fsm_init(fsm_p);
  944. }