X-Git-Url: http://git.ozlabs.org/?p=ppp.git;a=blobdiff_plain;f=pppd%2Fipxcp.c;h=9de3462f61d8e2c2ebc270000707ffa9e17481d2;hp=a347518b9ebb9b9563a8d0e4833704cebc2bdbb8;hb=96dad36e1d37716004171559280613739e7df29e;hpb=df61cf799017d2e36315a493e996e2a34ba9a973 diff --git a/pppd/ipxcp.c b/pppd/ipxcp.c index a347518..9de3462 100644 --- a/pppd/ipxcp.c +++ b/pppd/ipxcp.c @@ -19,7 +19,7 @@ #ifdef IPX_CHANGE #ifndef lint -static char rcsid[] = "$Id: ipxcp.c,v 1.3 1996/09/14 05:15:20 paulus Exp $"; +static char rcsid[] = "$Id: ipxcp.c,v 1.5 1997/03/04 03:39:32 paulus Exp $"; #endif /* @@ -115,7 +115,6 @@ struct protent ipxcp_protent = { NULL }; - /* * Lengths of configuration options. */ @@ -137,6 +136,24 @@ struct protent ipxcp_protent = { /* Used to generate the proper bit mask */ #define BIT(num) (1 << (num)) +/* + * Convert from internal to external notation + */ + +static short int +to_external(internal) +short int internal; +{ + short int external; + + if (internal & IPX_NONE) + external = IPX_NONE; + else + external = RIP_SAP; + + return external; +} + /* * Make a string representation of a network IP address. */ @@ -182,6 +199,9 @@ ipxcp_init(unit) ao->accept_local = 0; ao->accept_remote = 0; ao->accept_network = 0; + + wo->tried_rip = 0; + wo->tried_nlsp = 0; } /* @@ -342,16 +362,17 @@ ipxcp_resetci(f) ao->accept_remote = 1; } /* - * Unless router protocol is suppressed then assume that we can do RIP. - */ - if (! (wo->router & BIT(0))) - wo->router |= BIT(2); -/* - * Router protocol is only negotiated if requested. Others force the - * negotiation. + * If no routing agent was specified then we do RIP/SAP according to the + * RFC documents. If you have specified something then OK. Otherwise, we + * do RIP/SAP. */ - if (wo->router & (BIT(2) | BIT(4))) - wo->neg_router = 1; + if (ao->router == 0) { + ao->router |= BIT(RIP_SAP); + wo->router |= BIT(RIP_SAP); + } + + /* Always specify a routing protocol unless it was REJected. */ + wo->neg_router = 1; /* * Start with these default values */ @@ -361,6 +382,7 @@ ipxcp_resetci(f) /* * ipxcp_cilen - Return length of our CI. */ + static int ipxcp_cilen(f) fsm *f; @@ -371,20 +393,10 @@ ipxcp_cilen(f) len = go->neg_nn ? CILEN_NETN : 0; len += go->neg_node ? CILEN_NODEN : 0; len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0; - len += go->neg_complete ? CILEN_COMPLETE : 0; -/* - * Router protocol 0 is mutually exclusive with the others. - */ - if (go->neg_router) { - if (go->router & BIT(0)) - len += CILEN_PROTOCOL; - else { - if (go->router & BIT(2)) - len += CILEN_PROTOCOL; - if (go->router & BIT(4)) - len += CILEN_PROTOCOL; - } - } + + /* RFC says that defaults should not be included. */ + if (go->neg_router && to_external(go->router) != RIP_SAP) + len += CILEN_PROTOCOL; return (len); } @@ -427,30 +439,14 @@ ipxcp_addci(f, ucp, lenp) PUTCHAR (go->name [indx], ucp); } - if (go->neg_router && (go->router & (BIT(0) | BIT(2) | BIT(4)))) { - if (go->router & BIT(0)) { + if (go->neg_router) { + short external = to_external (go->router); + if (external != RIP_SAP) { PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); - PUTCHAR (CILEN_PROTOCOL, ucp); - PUTSHORT (0, ucp); - } else { - if (go->router & BIT(2)) { - PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); - PUTCHAR (CILEN_PROTOCOL, ucp); - PUTSHORT (2, ucp); - } - - if (go->router & BIT(4)) { - PUTCHAR (IPX_ROUTER_PROTOCOL, ucp); - PUTCHAR (CILEN_PROTOCOL, ucp); - PUTSHORT (4, ucp); - } + PUTCHAR (CILEN_PROTOCOL, ucp); + PUTSHORT (external, ucp); } } - - if (go->neg_complete) { - PUTCHAR (IPX_COMPLETE, ucp); - PUTCHAR (CILEN_COMPLETE, ucp); - } } /* @@ -521,9 +517,8 @@ ipxcp_ackci(f, p, len) break; \ } -#define ACKCIPROTO(opt, neg, val, bit) \ - if (neg && (val & BIT(bit))) \ - { \ +#define ACKCIPROTO(opt, neg, val) \ + if (neg) { \ if (len < 2) \ break; \ GETCHAR(citype, p); \ @@ -534,7 +529,7 @@ ipxcp_ackci(f, p, len) if (len < 0) \ break; \ GETSHORT(cishort, p); \ - if (cishort != (bit)) \ + if (cishort != to_external (val) || cishort == RIP_SAP) \ break; \ } /* @@ -544,10 +539,9 @@ ipxcp_ackci(f, p, len) ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network); ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node); ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name); - ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 0); - ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 2); - ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 4); - ACKCICOMPLETE (IPX_COMPLETE, go->neg_complete); + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); + ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router); /* * This is the end of the record. */ @@ -621,7 +615,7 @@ ipxcp_nakci(f, p, len) copy_node (p, try.our_node); break; - /* These have never been sent. Ignore the NAK frame */ + /* This has never been sent. Ignore the NAK frame */ case IPX_COMPRESSION_PROTOCOL: goto bad; @@ -630,16 +624,18 @@ ipxcp_nakci(f, p, len) goto bad; GETSHORT (s, p); - if ((s != 0) && (s != 2) && (s != 4)) - goto bad; + if (s > 15) /* This is just bad, but ignore for now. */ + break; - if (no.router & BIT(s)) + s = BIT(s); + if (no.router & s) /* duplicate NAKs are always bad */ goto bad; if (no.router == 0) /* Reset on first NAK only */ try.router = 0; - no.router |= BIT(s); - try.router |= BIT(s); + + no.router |= s; + try.router |= s; try.neg_router = 1; IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s)); @@ -663,13 +659,14 @@ ipxcp_nakci(f, p, len) /* * Do not permit the peer to force a router protocol which we do not - * support. + * support. However, default to the condition that will accept "NONE". */ - try.router &= go->router; - if (try.router == 0 && go->router != 0) { + try.router &= (ao->router | BIT(IPX_NONE)); + if (try.router == 0 && ao->router != 0) + try.router = BIT(IPX_NONE); + + if (try.router != 0) try.neg_router = 1; - try.router = BIT(0); - } /* * OK, the Nak is good. Now we can update state. @@ -700,8 +697,7 @@ ipxcp_rejci(f, p, len) ipxcp_options try; /* options to request next time */ #define REJCINETWORK(opt, neg, val) \ - if (neg) { \ - neg = 0; \ + if (neg && p[0] == opt) { \ if ((len -= CILEN_NETN) < 0) \ break; \ GETCHAR(citype, p); \ @@ -713,12 +709,12 @@ ipxcp_rejci(f, p, len) if (cilong != val) \ break; \ IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \ + neg = 0; \ } #define REJCICHARS(opt, neg, val, cnt) \ - if (neg) { \ + if (neg && p[0] == opt) { \ int indx, count = cnt; \ - neg = 0; \ len -= (count + 2); \ if (len < 0) \ break; \ @@ -735,14 +731,14 @@ ipxcp_rejci(f, p, len) if (indx != count) \ break; \ IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \ + neg = 0; \ } #define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val)) #define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val)) #define REJCIVOID(opt, neg) \ - if (neg) { \ - neg = 0; \ + if (neg && p[0] == opt) { \ if ((len -= CILEN_VOID) < 0) \ break; \ GETCHAR(citype, p); \ @@ -750,29 +746,25 @@ ipxcp_rejci(f, p, len) if (cilen != CILEN_VOID || citype != opt) \ break; \ IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \ + neg = 0; \ } +/* a reject for RIP/SAP is invalid since we don't send it and you can't + reject something which is not sent. (You can NAK, but you can't REJ.) */ #define REJCIPROTO(opt, neg, val, bit) \ - if (neg && (val & BIT(bit))) \ - { \ - if (len < 2) \ + if (neg && p[0] == opt) { \ + if ((len -= CILEN_PROTOCOL) < 0) \ break; \ GETCHAR(citype, p); \ GETCHAR(cilen, p); \ - if (cilen != CILEN_PROTOCOL || citype != opt) \ - break; \ - len -= cilen; \ - if (len < 0) \ + if (cilen != CILEN_PROTOCOL) \ break; \ GETSHORT(cishort, p); \ - if (cishort != (bit)) \ + if (cishort != to_external (val) || cishort == RIP_SAP) \ break; \ - IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected router proto %d", bit)); \ - val &= ~BIT(bit); \ - if (val == 0) \ - neg = 0; \ - } - + IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \ + neg = 0; \ + } /* * Any Rejected CIs must be in exactly the same order that we sent. * Check packet length and CI length at each step. @@ -783,11 +775,8 @@ ipxcp_rejci(f, p, len) do { REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network); REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node); - REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0); - REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 2); - REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 4); REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name); - REJCIVOID (IPX_COMPLETE, try.neg_complete); + REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0); /* * This is the end of the record. */ @@ -971,8 +960,8 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) break; /* * The routing protocol is a bitmask of various types. Any combination - * of the values 2 and 4 are permissible. '0' for no routing protocol must - * be specified only once. + * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no + * routing protocol must be specified only once. */ case IPX_ROUTER_PROTOCOL: if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) { @@ -982,26 +971,47 @@ ipxcp_reqci(f, inp, len, reject_if_disagree) GETSHORT (cishort, p); IPXCPDEBUG((LOG_INFO, - "Remote router protocol number %d", + "Remote router protocol number 0x%04x", cishort)); - if ((cishort == 0 && ho->router != 0) || (ho->router & BIT(0))) { - orc = CONFREJ; - break; + if (wo->neg_router == 0) { + wo->neg_router = 1; + wo->router = BIT(IPX_NONE); } - if (cishort != 0 && cishort != 2 && cishort != 4) { + if ((cishort == IPX_NONE && ho->router != 0) || + (ho->router & BIT(IPX_NONE))) { orc = CONFREJ; break; } - if (ho->router & BIT (cishort)) { + cishort = BIT(cishort); + if (ho->router & cishort) { orc = CONFREJ; break; } - ho->router |= BIT (cishort); + ho->router |= cishort; ho->neg_router = 1; + + /* Finally do not allow a router protocol which we do not + support. */ + + if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) { + int protocol; + + if (cishort == BIT(NLSP) && + (ao->router & BIT(RIP_SAP)) && + !wo->tried_rip) { + protocol = RIP_SAP; + wo->tried_rip = 1; + } else + protocol = IPX_NONE; + + DECPTR (sizeof (u_int16_t), p); + PUTSHORT (protocol, p); + orc = CONFNAK; + } break; /* * The router name is advisorary. Just accept it if it is not too large. @@ -1119,6 +1129,14 @@ ipxcp_up(f) IPXCPDEBUG((LOG_INFO, "ipxcp: up")); + /* The default router protocol is RIP/SAP. */ + if (ho->router == 0) + ho->router = BIT(RIP_SAP); + + if (go->router == 0) + go->router = BIT(RIP_SAP); + + /* Fetch the network number */ if (!ho->neg_nn) ho->his_network = wo->his_network; @@ -1129,8 +1147,9 @@ ipxcp_up(f) copy_node (wo->our_node, go->our_node); if (zero_node (go->our_node)) { - IPXCPDEBUG((LOG_ERR, "Could not determine local IPX node address")); - ipxcp_close(f->unit, "Could not determine local IPX node address"); + static char errmsg[] = "Could not determine local IPX node address"; + IPXCPDEBUG((LOG_ERR, errmsg)); + ipxcp_close(f->unit, errmsg); return; } @@ -1139,8 +1158,9 @@ ipxcp_up(f) go->network = ho->his_network; if (go->network == 0) { - IPXCPDEBUG((LOG_ERR, "Could not determine network number")); - ipxcp_close (unit, "Could not determine network number"); + static char errmsg[] = "Can not determine network number"; + IPXCPDEBUG((LOG_ERR, errmsg)); + ipxcp_close (unit, errmsg); return; } @@ -1163,7 +1183,7 @@ ipxcp_up(f) * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX */ - ipxcp_script (f, "/etc/ppp/ipx-up"); + ipxcp_script (f, _PATH_IPXUP); } /* @@ -1183,7 +1203,7 @@ ipxcp_down(f) cipxfaddr (f->unit); sifdown(f->unit); - ipxcp_script (f, "/etc/ppp/ipx-down"); + ipxcp_script (f, _PATH_IPXDOWN); } @@ -1205,11 +1225,11 @@ ipxcp_script(f, script) sprintf (strspeed, "%d", baud_rate); strproto_lcl[0] = '\0'; - if (go->neg_router) { - if (go->router & BIT(2)) + if (go->neg_router && ((go->router & BIT(IPX_NONE)) == 0)) { + if (go->router & BIT(RIP_SAP)) strcpy (strproto_lcl, "RIP "); - if (go->router & BIT(4)) - strcpy (strproto_lcl, "NLSP "); + if (go->router & BIT(NLSP)) + strcat (strproto_lcl, "NLSP "); } if (strproto_lcl[0] == '\0') @@ -1218,11 +1238,11 @@ ipxcp_script(f, script) strproto_lcl[strlen (strproto_lcl)-1] = '\0'; strproto_rmt[0] = '\0'; - if (ho->neg_router) { - if (ho->router & BIT(2)) + if (ho->neg_router && ((ho->router & BIT(IPX_NONE)) == 0)) { + if (ho->router & BIT(RIP_SAP)) strcpy (strproto_rmt, "RIP "); - if (ho->router & BIT(4)) - strcpy (strproto_rmt, "NLSP "); + if (ho->router & BIT(NLSP)) + strcat (strproto_rmt, "NLSP "); } if (strproto_rmt[0] == '\0') @@ -1311,52 +1331,52 @@ ipxcp_printpkt(p, plen, printer, arg) switch (code) { case IPX_NETWORK_NUMBER: if (olen == CILEN_NETN) { - p += CILEN_VOID; + p += 2; GETLONG(cilong, p); printer (arg, "network %s", ipx_ntoa (cilong)); } break; case IPX_NODE_NUMBER: if (olen == CILEN_NODEN) { - p += CILEN_VOID; + p += 2; printer (arg, "node "); while (p < optend) { GETCHAR(code, p); - printer(arg, "%.2x", code); + printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code); } } break; case IPX_COMPRESSION_PROTOCOL: if (olen == CILEN_COMPRESS) { - p += CILEN_VOID; + p += 2; GETSHORT (cishort, p); - printer (arg, "compression %d", cishort); + printer (arg, "compression %d", (int) cishort); } break; case IPX_ROUTER_PROTOCOL: if (olen == CILEN_PROTOCOL) { - p += CILEN_VOID; + p += 2; GETSHORT (cishort, p); - printer (arg, "router proto %d", cishort); + printer (arg, "router proto %d", (int) cishort); } break; case IPX_ROUTER_NAME: if (olen >= CILEN_NAME) { - p += CILEN_VOID; + p += 2; printer (arg, "router name \""); while (p < optend) { GETCHAR(code, p); - if (code >= 0x20 && code < 0x7E) - printer (arg, "%c", code); + if (code >= 0x20 && code <= 0x7E) + printer (arg, "%c", (int) (unsigned int) (unsigned char) code); else - printer (arg, " \\%.2x", code); + printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code); } printer (arg, "\""); } break; case IPX_COMPLETE: if (olen == CILEN_COMPLETE) { - p += CILEN_VOID; + p += 2; printer (arg, "complete"); } break; @@ -1366,7 +1386,7 @@ ipxcp_printpkt(p, plen, printer, arg) while (p < optend) { GETCHAR(code, p); - printer(arg, " %.2x", code); + printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code); } printer(arg, ">"); } @@ -1386,7 +1406,7 @@ ipxcp_printpkt(p, plen, printer, arg) /* print the rest of the bytes in the packet */ for (; len > 0; --len) { GETCHAR(code, p); - printer(arg, " %.2x", code); + printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code); } return p - pstart;