2 * ipxcp.c - PPP IPX Control Protocol.
4 * Copyright (c) 1989 Carnegie Mellon University.
7 * Redistribution and use in source and binary forms are permitted
8 * provided that the above copyright notice and this paragraph are
9 * duplicated in all such forms and that any documentation,
10 * advertising materials, and other materials related to such
11 * distribution and use acknowledge that the software was developed
12 * by Carnegie Mellon University. The name of the
13 * University may not be used to endorse or promote products derived
14 * from this software without specific prior written permission.
15 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
17 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
22 static char rcsid[] = "$Id: ipxcp.c,v 1.6 1998/03/25 03:08:16 paulus Exp $";
32 #include <sys/types.h>
33 #include <sys/socket.h>
34 #include <netinet/in.h>
39 #include "pathnames.h"
42 ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */
43 ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
44 ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
45 ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
47 #define wo (&ipxcp_wantoptions[0])
48 #define ao (&ipxcp_allowoptions[0])
49 #define go (&ipxcp_gotoptions[0])
50 #define ho (&ipxcp_hisoptions[0])
53 * Callbacks for fsm code. (CI = Configuration Information)
55 static void ipxcp_resetci __P((fsm *)); /* Reset our CI */
56 static int ipxcp_cilen __P((fsm *)); /* Return length of our CI */
57 static void ipxcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
58 static int ipxcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
59 static int ipxcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
60 static int ipxcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
61 static int ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
62 static void ipxcp_up __P((fsm *)); /* We're UP */
63 static void ipxcp_down __P((fsm *)); /* We're DOWN */
64 static void ipxcp_script __P((fsm *, char *)); /* Run an up/down script */
66 fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */
68 static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
69 ipxcp_resetci, /* Reset our Configuration Information */
70 ipxcp_cilen, /* Length of our Configuration Information */
71 ipxcp_addci, /* Add our Configuration Information */
72 ipxcp_ackci, /* ACK our Configuration Information */
73 ipxcp_nakci, /* NAK our Configuration Information */
74 ipxcp_rejci, /* Reject our Configuration Information */
75 ipxcp_reqci, /* Request peer's Configuration Information */
76 ipxcp_up, /* Called when fsm reaches OPENED state */
77 ipxcp_down, /* Called when fsm leaves OPENED state */
78 NULL, /* Called when we want the lower layer up */
79 NULL, /* Called when we want the lower layer down */
80 NULL, /* Called when Protocol-Reject received */
81 NULL, /* Retransmission is necessary */
82 NULL, /* Called to handle protocol-specific codes */
83 "IPXCP" /* String name of protocol */
87 * Protocol entry points.
90 static void ipxcp_init __P((int));
91 static void ipxcp_open __P((int));
92 static void ipxcp_close __P((int, char *));
93 static void ipxcp_lowerup __P((int));
94 static void ipxcp_lowerdown __P((int));
95 static void ipxcp_input __P((int, u_char *, int));
96 static void ipxcp_protrej __P((int));
97 static int ipxcp_printpkt __P((u_char *, int,
98 void (*) __P((void *, char *, ...)), void *));
100 struct protent ipxcp_protent = {
119 * Lengths of configuration options.
123 #define CILEN_COMPLETE 2 /* length of complete option */
124 #define CILEN_NETN 6 /* network number length option */
125 #define CILEN_NODEN 8 /* node number length option */
126 #define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
127 #define CILEN_NAME 3 /* Minimum length of router name */
128 #define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
130 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
131 (x) == CONFNAK ? "NAK" : "REJ")
133 /* Used in printing the node number */
134 #define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
136 /* Used to generate the proper bit mask */
137 #define BIT(num) (1 << (num))
140 * Convert from internal to external notation
144 to_external(internal)
149 if (internal & IPX_NONE)
158 * Make a string representation of a network IP address.
166 sprintf(b, "%x", ipxaddr);
172 * ipxcp_init - Initialize IPXCP.
178 fsm *f = &ipxcp_fsm[unit];
181 f->protocol = PPP_IPXCP;
182 f->callbacks = &ipxcp_callbacks;
183 fsm_init(&ipxcp_fsm[unit]);
185 memset (wo->name, 0, sizeof (wo->name));
186 memset (wo->our_node, 0, sizeof (wo->our_node));
187 memset (wo->his_node, 0, sizeof (wo->his_node));
190 wo->neg_complete = 1;
196 ao->neg_complete = 1;
199 ao->accept_local = 0;
200 ao->accept_remote = 0;
201 ao->accept_network = 0;
208 * Copy the node number
215 memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
219 * Compare node numbers
223 compare_node (src, dst)
226 return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
230 * Is the node number zero?
238 for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
239 if (node [indx] != 0)
245 * Increment the node number
259 PUTLONG (magic_num, outp);
263 * ipxcp_open - IPXCP is allowed to come up.
269 fsm_open(&ipxcp_fsm[unit]);
273 * ipxcp_close - Take IPXCP down.
276 ipxcp_close(unit, reason)
280 fsm_close(&ipxcp_fsm[unit], reason);
285 * ipxcp_lowerup - The lower layer is up.
291 fsm_lowerup(&ipxcp_fsm[unit]);
296 * ipxcp_lowerdown - The lower layer is down.
299 ipxcp_lowerdown(unit)
302 fsm_lowerdown(&ipxcp_fsm[unit]);
307 * ipxcp_input - Input IPXCP packet.
310 ipxcp_input(unit, p, len)
315 fsm_input(&ipxcp_fsm[unit], p, len);
320 * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
322 * Pretend the lower layer went down, so we shut up.
328 fsm_lowerdown(&ipxcp_fsm[unit]);
333 * ipxcp_resetci - Reset our CI.
339 wo->req_node = wo->neg_node && ao->neg_node;
340 wo->req_nn = wo->neg_nn && ao->neg_nn;
342 if (wo->our_network == 0) {
344 ao->accept_network = 1;
347 * If our node number is zero then change it.
349 if (zero_node (wo->our_node)) {
350 inc_node (wo->our_node);
351 ao->accept_local = 1;
355 * If his node number is zero then change it.
357 if (zero_node (wo->his_node)) {
358 inc_node (wo->his_node);
359 ao->accept_remote = 1;
362 * If no routing agent was specified then we do RIP/SAP according to the
363 * RFC documents. If you have specified something then OK. Otherwise, we
366 if (ao->router == 0) {
367 ao->router |= BIT(RIP_SAP);
368 wo->router |= BIT(RIP_SAP);
371 /* Always specify a routing protocol unless it was REJected. */
374 * Start with these default values
380 * ipxcp_cilen - Return length of our CI.
389 len = go->neg_nn ? CILEN_NETN : 0;
390 len += go->neg_node ? CILEN_NODEN : 0;
391 len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
393 /* RFC says that defaults should not be included. */
394 if (go->neg_router && to_external(go->router) != RIP_SAP)
395 len += CILEN_PROTOCOL;
402 * ipxcp_addci - Add our desired CIs to a packet.
405 ipxcp_addci(f, ucp, lenp)
411 * Add the options to the record.
414 PUTCHAR (IPX_NETWORK_NUMBER, ucp);
415 PUTCHAR (CILEN_NETN, ucp);
416 PUTLONG (go->our_network, ucp);
421 PUTCHAR (IPX_NODE_NUMBER, ucp);
422 PUTCHAR (CILEN_NODEN, ucp);
423 for (indx = 0; indx < sizeof (go->our_node); ++indx)
424 PUTCHAR (go->our_node[indx], ucp);
428 int cilen = strlen (go->name);
430 PUTCHAR (IPX_ROUTER_NAME, ucp);
431 PUTCHAR (CILEN_NAME + cilen - 1, ucp);
432 for (indx = 0; indx < cilen; ++indx)
433 PUTCHAR (go->name [indx], ucp);
436 if (go->neg_router) {
437 short external = to_external (go->router);
438 if (external != RIP_SAP) {
439 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
440 PUTCHAR (CILEN_PROTOCOL, ucp);
441 PUTSHORT (external, ucp);
447 * ipxcp_ackci - Ack our CIs.
454 ipxcp_ackci(f, p, len)
459 u_short cilen, citype, cishort;
463 #define ACKCIVOID(opt, neg) \
465 if ((len -= CILEN_VOID) < 0) \
467 GETCHAR(citype, p); \
469 if (cilen != CILEN_VOID || \
474 #define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
476 #define ACKCICHARS(opt, neg, val, cnt) \
478 int indx, count = cnt; \
479 len -= (count + 2); \
482 GETCHAR(citype, p); \
484 if (cilen != (count + 2) || \
487 for (indx = 0; indx < count; ++indx) {\
488 GETCHAR(cichar, p); \
489 if (cichar != ((u_char *) &val)[indx]) \
496 #define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
497 #define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
499 #define ACKCINETWORK(opt, neg, val) \
501 if ((len -= CILEN_NETN) < 0) \
503 GETCHAR(citype, p); \
505 if (cilen != CILEN_NETN || \
508 GETLONG(cilong, p); \
513 #define ACKCIPROTO(opt, neg, val) \
517 GETCHAR(citype, p); \
519 if (cilen != CILEN_PROTOCOL || citype != opt) \
524 GETSHORT(cishort, p); \
525 if (cishort != to_external (val) || cishort == RIP_SAP) \
529 * Process the ACK frame in the order in which the frame was assembled
532 ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
533 ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
534 ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
535 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
536 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
537 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
539 * This is the end of the record.
545 * The frame is invalid
547 IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
552 * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
553 * This should not modify any state if the Nak is bad
554 * or if IPXCP is in the OPENED state.
562 ipxcp_nakci(f, p, len)
567 u_char citype, cilen, *next;
570 ipxcp_options no; /* options we've seen Naks for */
571 ipxcp_options try; /* options to request next time */
573 BZERO(&no, sizeof(no));
576 while (len > CILEN_VOID) {
582 next = &p [cilen - CILEN_VOID];
585 case IPX_NETWORK_NUMBER:
586 if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
591 IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
592 if (l && ao->accept_network)
596 case IPX_NODE_NUMBER:
597 if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
601 IPXCPDEBUG((LOG_INFO,
602 "local node number %02X%02X%02X%02X%02X%02X",
605 if (!zero_node (p) && ao->accept_local &&
606 ! compare_node (p, ho->his_node))
607 copy_node (p, try.our_node);
610 /* This has never been sent. Ignore the NAK frame */
611 case IPX_COMPRESSION_PROTOCOL:
614 case IPX_ROUTER_PROTOCOL:
615 if (!go->neg_router || (cilen < CILEN_PROTOCOL))
619 if (s > 15) /* This is just bad, but ignore for now. */
623 if (no.router & s) /* duplicate NAKs are always bad */
626 if (no.router == 0) /* Reset on first NAK only */
633 IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
636 /* These, according to the RFC, must never be NAKed. */
637 case IPX_ROUTER_NAME:
641 /* These are for options which we have not seen. */
648 /* If there is still anything left, this packet is bad. */
653 * Do not permit the peer to force a router protocol which we do not
654 * support. However, default to the condition that will accept "NONE".
656 try.router &= (ao->router | BIT(IPX_NONE));
657 if (try.router == 0 && ao->router != 0)
658 try.router = BIT(IPX_NONE);
664 * OK, the Nak is good. Now we can update state.
666 if (f->state != OPENED)
672 IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
677 * ipxcp_rejci - Reject some of our CIs.
680 ipxcp_rejci(f, p, len)
685 u_short cilen, citype, cishort;
688 ipxcp_options try; /* options to request next time */
690 #define REJCINETWORK(opt, neg, val) \
691 if (neg && p[0] == opt) { \
692 if ((len -= CILEN_NETN) < 0) \
694 GETCHAR(citype, p); \
696 if (cilen != CILEN_NETN || \
699 GETLONG(cilong, p); \
702 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
706 #define REJCICHARS(opt, neg, val, cnt) \
707 if (neg && p[0] == opt) { \
708 int indx, count = cnt; \
709 len -= (count + 2); \
712 GETCHAR(citype, p); \
714 if (cilen != (count + 2) || \
717 for (indx = 0; indx < count; ++indx) {\
718 GETCHAR(cichar, p); \
719 if (cichar != ((u_char *) &val)[indx]) \
724 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
728 #define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
729 #define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
731 #define REJCIVOID(opt, neg) \
732 if (neg && p[0] == opt) { \
733 if ((len -= CILEN_VOID) < 0) \
735 GETCHAR(citype, p); \
737 if (cilen != CILEN_VOID || citype != opt) \
739 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
743 /* a reject for RIP/SAP is invalid since we don't send it and you can't
744 reject something which is not sent. (You can NAK, but you can't REJ.) */
745 #define REJCIPROTO(opt, neg, val, bit) \
746 if (neg && p[0] == opt) { \
747 if ((len -= CILEN_PROTOCOL) < 0) \
749 GETCHAR(citype, p); \
751 if (cilen != CILEN_PROTOCOL) \
753 GETSHORT(cishort, p); \
754 if (cishort != to_external (val) || cishort == RIP_SAP) \
756 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \
760 * Any Rejected CIs must be in exactly the same order that we sent.
761 * Check packet length and CI length at each step.
762 * If we find any deviations, then this packet is bad.
767 REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
768 REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
769 REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
770 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
772 * This is the end of the record.
775 if (f->state != OPENED)
781 * The frame is invalid at this point.
783 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
788 * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
790 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
791 * appropriately. If reject_if_disagree is non-zero, doesn't return
792 * CONFNAK; returns CONFREJ if it can't return CONFACK.
795 ipxcp_reqci(f, inp, len, reject_if_disagree)
797 u_char *inp; /* Requested CIs */
798 int *len; /* Length of requested CIs */
799 int reject_if_disagree;
801 u_char *cip, *next; /* Pointer to current and next CIs */
802 u_short cilen, citype; /* Parsed len, type */
803 u_short cishort; /* Parsed short value */
804 u_int32_t cinetwork; /* Parsed address values */
805 int rc = CONFACK; /* Final packet return code */
806 int orc; /* Individual option return code */
807 u_char *p; /* Pointer to next char to parse */
808 u_char *ucp = inp; /* Pointer to current output char */
809 int l = *len; /* Length left */
812 * Reset all his options.
814 BZERO(ho, sizeof(*ho));
817 * Process all his options.
821 orc = CONFACK; /* Assume success */
822 cip = p = next; /* Remember begining of CI */
823 if (l < 2 || /* Not enough data for CI header or */
824 p[1] < 2 || /* CI length too small or */
825 p[1] > l) { /* CI length too big? */
826 IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
827 orc = CONFREJ; /* Reject bad CI */
828 cilen = l; /* Reject till end of packet */
829 l = 0; /* Don't loop again */
832 GETCHAR(citype, p); /* Parse CI type */
833 GETCHAR(cilen, p); /* Parse CI length */
834 l -= cilen; /* Adjust remaining length */
835 next += cilen; /* Step to next CI */
837 switch (citype) { /* Check CI type */
839 * The network number must match. Choose the larger of the two.
841 case IPX_NETWORK_NUMBER:
842 IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
844 /* if we wont negotiate the network number or the length is wrong
845 then reject the option */
846 if ( !ao->neg_nn || cilen != CILEN_NETN ) {
850 GETLONG(cinetwork, p);
851 IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
853 /* If the network numbers match then acknowledge them. */
854 if (cinetwork != 0) {
855 ho->his_network = cinetwork;
857 if (wo->our_network == cinetwork)
860 * If the network number is not given or we don't accept their change or
861 * the network number is too small then NAK it.
863 if (! ao->accept_network || cinetwork < wo->our_network) {
864 DECPTR (sizeof (u_int32_t), p);
865 PUTLONG (wo->our_network, p);
871 * The peer sent '0' for the network. Give it ours if we have one.
873 if (go->our_network != 0) {
874 DECPTR (sizeof (u_int32_t), p);
875 PUTLONG (wo->our_network, p);
878 * We don't have one. Reject the value.
885 * The node number is required
887 case IPX_NODE_NUMBER:
888 IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
890 /* if we wont negotiate the node number or the length is wrong
891 then reject the option */
892 if ( cilen != CILEN_NODEN ) {
897 copy_node (p, ho->his_node);
900 * If the remote does not have a number and we do then NAK it with the value
901 * which we have for it. (We never have a default value of zero.)
903 if (zero_node (ho->his_node)) {
905 copy_node (wo->his_node, p);
906 INCPTR (sizeof (wo->his_node), p);
910 * If you have given me the expected network node number then I'll accept
913 if (compare_node (wo->his_node, ho->his_node)) {
916 INCPTR (sizeof (wo->his_node), p);
920 * If his node number is the same as ours then ask him to try the next
923 if (compare_node (ho->his_node, go->our_node)) {
924 inc_node (ho->his_node);
926 copy_node (ho->his_node, p);
927 INCPTR (sizeof (wo->his_node), p);
931 * If we don't accept a new value then NAK it.
933 if (! ao->accept_remote) {
934 copy_node (wo->his_node, p);
935 INCPTR (sizeof (wo->his_node), p);
941 INCPTR (sizeof (wo->his_node), p);
944 * Compression is not desired at this time. It is always rejected.
946 case IPX_COMPRESSION_PROTOCOL:
947 IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
951 * The routing protocol is a bitmask of various types. Any combination
952 * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no
953 * routing protocol must be specified only once.
955 case IPX_ROUTER_PROTOCOL:
956 if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
961 GETSHORT (cishort, p);
962 IPXCPDEBUG((LOG_INFO,
963 "Remote router protocol number 0x%04x",
966 if (wo->neg_router == 0) {
968 wo->router = BIT(IPX_NONE);
971 if ((cishort == IPX_NONE && ho->router != 0) ||
972 (ho->router & BIT(IPX_NONE))) {
977 cishort = BIT(cishort);
978 if (ho->router & cishort) {
983 ho->router |= cishort;
986 /* Finally do not allow a router protocol which we do not
989 if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) {
992 if (cishort == BIT(NLSP) &&
993 (ao->router & BIT(RIP_SAP)) &&
1000 DECPTR (sizeof (u_int16_t), p);
1001 PUTSHORT (protocol, p);
1006 * The router name is advisorary. Just accept it if it is not too large.
1008 case IPX_ROUTER_NAME:
1009 IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
1010 if (cilen >= CILEN_NAME) {
1011 int name_size = cilen - CILEN_NAME;
1012 if (name_size > sizeof (ho->name))
1013 name_size = sizeof (ho->name) - 1;
1014 memset (ho->name, 0, sizeof (ho->name));
1015 memcpy (ho->name, p, name_size);
1016 ho->name [name_size] = '\0';
1024 * This is advisorary.
1027 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1028 if (cilen != CILEN_COMPLETE)
1031 ho->neg_complete = 1;
1036 * All other entries are not known at this time.
1039 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1045 IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
1047 if (orc == CONFACK && /* Good CI */
1048 rc != CONFACK) /* but prior CI wasnt? */
1049 continue; /* Don't send this one */
1051 if (orc == CONFNAK) { /* Nak this CI? */
1052 if (reject_if_disagree) /* Getting fed up with sending NAKs? */
1053 orc = CONFREJ; /* Get tough if so */
1054 if (rc == CONFREJ) /* Rejecting prior CI? */
1055 continue; /* Don't send this one */
1056 if (rc == CONFACK) { /* Ack'd all prior CIs? */
1057 rc = CONFNAK; /* Not anymore... */
1058 ucp = inp; /* Backup */
1062 if (orc == CONFREJ && /* Reject this CI */
1063 rc != CONFREJ) { /* but no prior ones? */
1065 ucp = inp; /* Backup */
1068 /* Need to move CI? */
1070 BCOPY(cip, ucp, cilen); /* Move it */
1072 /* Update output pointer */
1077 * If we aren't rejecting this packet, and we want to negotiate
1078 * their address, and they didn't send their address, then we
1079 * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
1080 * input buffer is long enough that we can append the extra
1084 if (rc != CONFREJ && !ho->neg_node &&
1085 wo->req_nn && !reject_if_disagree) {
1086 if (rc == CONFACK) {
1088 wo->req_nn = 0; /* don't ask again */
1089 ucp = inp; /* reset pointer */
1092 if (zero_node (wo->his_node))
1093 inc_node (wo->his_node);
1095 PUTCHAR (IPX_NODE_NUMBER, ucp);
1096 PUTCHAR (CILEN_NODEN, ucp);
1097 copy_node (wo->his_node, ucp);
1098 INCPTR (sizeof (wo->his_node), ucp);
1101 *len = ucp - inp; /* Compute output length */
1102 IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc)));
1103 return (rc); /* Return final code */
1107 * ipxcp_up - IPXCP has come UP.
1109 * Configure the IP network interface appropriately and bring it up.
1118 IPXCPDEBUG((LOG_INFO, "ipxcp: up"));
1120 /* The default router protocol is RIP/SAP. */
1121 if (ho->router == 0)
1122 ho->router = BIT(RIP_SAP);
1124 if (go->router == 0)
1125 go->router = BIT(RIP_SAP);
1127 /* Fetch the network number */
1129 ho->his_network = wo->his_network;
1132 copy_node (wo->his_node, ho->his_node);
1134 if (!wo->neg_node && !go->neg_node)
1135 copy_node (wo->our_node, go->our_node);
1137 if (zero_node (go->our_node)) {
1138 static char errmsg[] = "Could not determine local IPX node address";
1139 IPXCPDEBUG((LOG_ERR, errmsg));
1140 ipxcp_close(f->unit, errmsg);
1144 go->network = go->our_network;
1145 if (ho->his_network != 0 && ho->his_network > go->network)
1146 go->network = ho->his_network;
1148 if (go->network == 0) {
1149 static char errmsg[] = "Can not determine network number";
1150 IPXCPDEBUG((LOG_ERR, errmsg));
1151 ipxcp_close (unit, errmsg);
1155 /* bring the interface up */
1157 IPXCPDEBUG((LOG_WARNING, "sifup failed"));
1158 ipxcp_close(unit, "Interface configuration failed");
1162 /* set the network number for IPX */
1163 if (!sipxfaddr(unit, go->network, go->our_node)) {
1164 IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
1165 ipxcp_close(unit, "Interface configuration failed");
1170 * Execute the ipx-up script, like this:
1171 * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
1174 ipxcp_script (f, _PATH_IPXUP);
1178 * ipxcp_down - IPXCP has gone DOWN.
1180 * Take the IP network interface down, clear its addresses
1181 * and delete routes through it.
1188 IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
1190 cipxfaddr (f->unit);
1192 ipxcp_script (f, _PATH_IPXDOWN);
1197 * ipxcp_script - Execute a script with arguments
1198 * interface-name tty-name speed local-IPX remote-IPX networks.
1201 ipxcp_script(f, script)
1205 char strspeed[32], strlocal[32], strremote[32];
1206 char strnetwork[32], strpid[32];
1207 char *argv[14], strproto_lcl[32], strproto_rmt[32];
1209 sprintf (strpid, "%d", getpid());
1210 sprintf (strspeed, "%d", baud_rate);
1212 strproto_lcl[0] = '\0';
1213 if (go->neg_router && ((go->router & BIT(IPX_NONE)) == 0)) {
1214 if (go->router & BIT(RIP_SAP))
1215 strcpy (strproto_lcl, "RIP ");
1216 if (go->router & BIT(NLSP))
1217 strcat (strproto_lcl, "NLSP ");
1220 if (strproto_lcl[0] == '\0')
1221 strcpy (strproto_lcl, "NONE ");
1223 strproto_lcl[strlen (strproto_lcl)-1] = '\0';
1225 strproto_rmt[0] = '\0';
1226 if (ho->neg_router && ((ho->router & BIT(IPX_NONE)) == 0)) {
1227 if (ho->router & BIT(RIP_SAP))
1228 strcpy (strproto_rmt, "RIP ");
1229 if (ho->router & BIT(NLSP))
1230 strcat (strproto_rmt, "NLSP ");
1233 if (strproto_rmt[0] == '\0')
1234 strcpy (strproto_rmt, "NONE ");
1236 strproto_rmt[strlen (strproto_rmt)-1] = '\0';
1238 strcpy (strnetwork, ipx_ntoa (go->network));
1241 "%02X%02X%02X%02X%02X%02X",
1242 NODE(go->our_node));
1245 "%02X%02X%02X%02X%02X%02X",
1246 NODE(ho->his_node));
1252 argv[4] = strnetwork;
1254 argv[6] = strremote;
1255 argv[7] = strproto_lcl;
1256 argv[8] = strproto_rmt;
1258 argv[10] = ho->name;
1262 run_program(script, argv, 0);
1266 * ipxcp_printpkt - print the contents of an IPXCP packet.
1268 static char *ipxcp_codenames[] = {
1269 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1270 "TermReq", "TermAck", "CodeRej"
1274 ipxcp_printpkt(p, plen, printer, arg)
1277 void (*printer) __P((void *, char *, ...));
1280 int code, id, len, olen;
1281 u_char *pstart, *optend;
1285 if (plen < HEADERLEN)
1291 if (len < HEADERLEN || len > plen)
1294 if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
1295 printer(arg, " %s", ipxcp_codenames[code-1]);
1297 printer(arg, " code=0x%x", code);
1298 printer(arg, " id=0x%x", id);
1305 /* print option list */
1310 if (olen < CILEN_VOID || olen > len) {
1317 case IPX_NETWORK_NUMBER:
1318 if (olen == CILEN_NETN) {
1321 printer (arg, "network %s", ipx_ntoa (cilong));
1324 case IPX_NODE_NUMBER:
1325 if (olen == CILEN_NODEN) {
1327 printer (arg, "node ");
1328 while (p < optend) {
1330 printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code);
1334 case IPX_COMPRESSION_PROTOCOL:
1335 if (olen == CILEN_COMPRESS) {
1337 GETSHORT (cishort, p);
1338 printer (arg, "compression %d", (int) cishort);
1341 case IPX_ROUTER_PROTOCOL:
1342 if (olen == CILEN_PROTOCOL) {
1344 GETSHORT (cishort, p);
1345 printer (arg, "router proto %d", (int) cishort);
1348 case IPX_ROUTER_NAME:
1349 if (olen >= CILEN_NAME) {
1351 printer (arg, "router name \"");
1352 while (p < optend) {
1354 if (code >= 0x20 && code <= 0x7E)
1355 printer (arg, "%c", (int) (unsigned int) (unsigned char) code);
1357 printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code);
1359 printer (arg, "\"");
1363 if (olen == CILEN_COMPLETE) {
1365 printer (arg, "complete");
1372 while (p < optend) {
1374 printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
1382 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1384 print_string(p, len, printer, arg);
1391 /* print the rest of the bytes in the packet */
1392 for (; len > 0; --len) {
1394 printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
1399 #endif /* ifdef IPX_CHANGE */