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.7 1998/05/13 05:49:18 paulus Exp $";
33 #include <sys/types.h>
34 #include <sys/socket.h>
35 #include <netinet/in.h>
40 #include "pathnames.h"
44 ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */
45 ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
46 ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
47 ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
49 #define wo (&ipxcp_wantoptions[0])
50 #define ao (&ipxcp_allowoptions[0])
51 #define go (&ipxcp_gotoptions[0])
52 #define ho (&ipxcp_hisoptions[0])
55 * Callbacks for fsm code. (CI = Configuration Information)
57 static void ipxcp_resetci __P((fsm *)); /* Reset our CI */
58 static int ipxcp_cilen __P((fsm *)); /* Return length of our CI */
59 static void ipxcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
60 static int ipxcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
61 static int ipxcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
62 static int ipxcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
63 static int ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
64 static void ipxcp_up __P((fsm *)); /* We're UP */
65 static void ipxcp_down __P((fsm *)); /* We're DOWN */
66 static void ipxcp_script __P((fsm *, char *)); /* Run an up/down script */
68 fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */
70 static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
71 ipxcp_resetci, /* Reset our Configuration Information */
72 ipxcp_cilen, /* Length of our Configuration Information */
73 ipxcp_addci, /* Add our Configuration Information */
74 ipxcp_ackci, /* ACK our Configuration Information */
75 ipxcp_nakci, /* NAK our Configuration Information */
76 ipxcp_rejci, /* Reject our Configuration Information */
77 ipxcp_reqci, /* Request peer's Configuration Information */
78 ipxcp_up, /* Called when fsm reaches OPENED state */
79 ipxcp_down, /* Called when fsm leaves OPENED state */
80 NULL, /* Called when we want the lower layer up */
81 NULL, /* Called when we want the lower layer down */
82 NULL, /* Called when Protocol-Reject received */
83 NULL, /* Retransmission is necessary */
84 NULL, /* Called to handle protocol-specific codes */
85 "IPXCP" /* String name of protocol */
89 * Protocol entry points.
92 static void ipxcp_init __P((int));
93 static void ipxcp_open __P((int));
94 static void ipxcp_close __P((int, char *));
95 static void ipxcp_lowerup __P((int));
96 static void ipxcp_lowerdown __P((int));
97 static void ipxcp_input __P((int, u_char *, int));
98 static void ipxcp_protrej __P((int));
99 static int ipxcp_printpkt __P((u_char *, int,
100 void (*) __P((void *, char *, ...)), void *));
102 struct protent ipxcp_protent = {
121 * Lengths of configuration options.
125 #define CILEN_COMPLETE 2 /* length of complete option */
126 #define CILEN_NETN 6 /* network number length option */
127 #define CILEN_NODEN 8 /* node number length option */
128 #define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
129 #define CILEN_NAME 3 /* Minimum length of router name */
130 #define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
132 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
133 (x) == CONFNAK ? "NAK" : "REJ")
135 /* Used in printing the node number */
136 #define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
138 /* Used to generate the proper bit mask */
139 #define BIT(num) (1 << (num))
142 * Convert from internal to external notation
146 to_external(internal)
151 if (internal & IPX_NONE)
160 * Make a string representation of a network IP address.
168 sprintf(b, "%x", ipxaddr);
174 * ipxcp_init - Initialize IPXCP.
180 fsm *f = &ipxcp_fsm[unit];
183 f->protocol = PPP_IPXCP;
184 f->callbacks = &ipxcp_callbacks;
185 fsm_init(&ipxcp_fsm[unit]);
187 memset (wo->name, 0, sizeof (wo->name));
188 memset (wo->our_node, 0, sizeof (wo->our_node));
189 memset (wo->his_node, 0, sizeof (wo->his_node));
192 wo->neg_complete = 1;
198 ao->neg_complete = 1;
201 ao->accept_local = 0;
202 ao->accept_remote = 0;
203 ao->accept_network = 0;
210 * Copy the node number
217 memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
221 * Compare node numbers
225 compare_node (src, dst)
228 return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
232 * Is the node number zero?
240 for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
241 if (node [indx] != 0)
247 * Increment the node number
261 PUTLONG (magic_num, outp);
265 * ipxcp_open - IPXCP is allowed to come up.
271 fsm_open(&ipxcp_fsm[unit]);
275 * ipxcp_close - Take IPXCP down.
278 ipxcp_close(unit, reason)
282 fsm_close(&ipxcp_fsm[unit], reason);
287 * ipxcp_lowerup - The lower layer is up.
293 fsm_lowerup(&ipxcp_fsm[unit]);
298 * ipxcp_lowerdown - The lower layer is down.
301 ipxcp_lowerdown(unit)
304 fsm_lowerdown(&ipxcp_fsm[unit]);
309 * ipxcp_input - Input IPXCP packet.
312 ipxcp_input(unit, p, len)
317 fsm_input(&ipxcp_fsm[unit], p, len);
322 * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
324 * Pretend the lower layer went down, so we shut up.
330 fsm_lowerdown(&ipxcp_fsm[unit]);
335 * ipxcp_resetci - Reset our CI.
341 wo->req_node = wo->neg_node && ao->neg_node;
342 wo->req_nn = wo->neg_nn && ao->neg_nn;
344 if (wo->our_network == 0) {
346 ao->accept_network = 1;
349 * If our node number is zero then change it.
351 if (zero_node (wo->our_node)) {
352 inc_node (wo->our_node);
353 ao->accept_local = 1;
357 * If his node number is zero then change it.
359 if (zero_node (wo->his_node)) {
360 inc_node (wo->his_node);
361 ao->accept_remote = 1;
364 * If no routing agent was specified then we do RIP/SAP according to the
365 * RFC documents. If you have specified something then OK. Otherwise, we
368 if (ao->router == 0) {
369 ao->router |= BIT(RIP_SAP);
370 wo->router |= BIT(RIP_SAP);
373 /* Always specify a routing protocol unless it was REJected. */
376 * Start with these default values
382 * ipxcp_cilen - Return length of our CI.
391 len = go->neg_nn ? CILEN_NETN : 0;
392 len += go->neg_node ? CILEN_NODEN : 0;
393 len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
395 /* RFC says that defaults should not be included. */
396 if (go->neg_router && to_external(go->router) != RIP_SAP)
397 len += CILEN_PROTOCOL;
404 * ipxcp_addci - Add our desired CIs to a packet.
407 ipxcp_addci(f, ucp, lenp)
413 * Add the options to the record.
416 PUTCHAR (IPX_NETWORK_NUMBER, ucp);
417 PUTCHAR (CILEN_NETN, ucp);
418 PUTLONG (go->our_network, ucp);
423 PUTCHAR (IPX_NODE_NUMBER, ucp);
424 PUTCHAR (CILEN_NODEN, ucp);
425 for (indx = 0; indx < sizeof (go->our_node); ++indx)
426 PUTCHAR (go->our_node[indx], ucp);
430 int cilen = strlen (go->name);
432 PUTCHAR (IPX_ROUTER_NAME, ucp);
433 PUTCHAR (CILEN_NAME + cilen - 1, ucp);
434 for (indx = 0; indx < cilen; ++indx)
435 PUTCHAR (go->name [indx], ucp);
438 if (go->neg_router) {
439 short external = to_external (go->router);
440 if (external != RIP_SAP) {
441 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
442 PUTCHAR (CILEN_PROTOCOL, ucp);
443 PUTSHORT (external, ucp);
449 * ipxcp_ackci - Ack our CIs.
456 ipxcp_ackci(f, p, len)
461 u_short cilen, citype, cishort;
465 #define ACKCIVOID(opt, neg) \
467 if ((len -= CILEN_VOID) < 0) \
469 GETCHAR(citype, p); \
471 if (cilen != CILEN_VOID || \
476 #define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
478 #define ACKCICHARS(opt, neg, val, cnt) \
480 int indx, count = cnt; \
481 len -= (count + 2); \
484 GETCHAR(citype, p); \
486 if (cilen != (count + 2) || \
489 for (indx = 0; indx < count; ++indx) {\
490 GETCHAR(cichar, p); \
491 if (cichar != ((u_char *) &val)[indx]) \
498 #define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
499 #define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
501 #define ACKCINETWORK(opt, neg, val) \
503 if ((len -= CILEN_NETN) < 0) \
505 GETCHAR(citype, p); \
507 if (cilen != CILEN_NETN || \
510 GETLONG(cilong, p); \
515 #define ACKCIPROTO(opt, neg, val) \
519 GETCHAR(citype, p); \
521 if (cilen != CILEN_PROTOCOL || citype != opt) \
526 GETSHORT(cishort, p); \
527 if (cishort != to_external (val) || cishort == RIP_SAP) \
531 * Process the ACK frame in the order in which the frame was assembled
534 ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
535 ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
536 ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
537 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
538 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
539 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router);
541 * This is the end of the record.
547 * The frame is invalid
549 IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
554 * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
555 * This should not modify any state if the Nak is bad
556 * or if IPXCP is in the OPENED state.
564 ipxcp_nakci(f, p, len)
569 u_char citype, cilen, *next;
572 ipxcp_options no; /* options we've seen Naks for */
573 ipxcp_options try; /* options to request next time */
575 BZERO(&no, sizeof(no));
578 while (len > CILEN_VOID) {
584 next = &p [cilen - CILEN_VOID];
587 case IPX_NETWORK_NUMBER:
588 if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
593 IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
594 if (l && ao->accept_network)
598 case IPX_NODE_NUMBER:
599 if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
603 IPXCPDEBUG((LOG_INFO,
604 "local node number %02X%02X%02X%02X%02X%02X",
607 if (!zero_node (p) && ao->accept_local &&
608 ! compare_node (p, ho->his_node))
609 copy_node (p, try.our_node);
612 /* This has never been sent. Ignore the NAK frame */
613 case IPX_COMPRESSION_PROTOCOL:
616 case IPX_ROUTER_PROTOCOL:
617 if (!go->neg_router || (cilen < CILEN_PROTOCOL))
621 if (s > 15) /* This is just bad, but ignore for now. */
625 if (no.router & s) /* duplicate NAKs are always bad */
628 if (no.router == 0) /* Reset on first NAK only */
635 IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
638 /* These, according to the RFC, must never be NAKed. */
639 case IPX_ROUTER_NAME:
643 /* These are for options which we have not seen. */
650 /* If there is still anything left, this packet is bad. */
655 * Do not permit the peer to force a router protocol which we do not
656 * support. However, default to the condition that will accept "NONE".
658 try.router &= (ao->router | BIT(IPX_NONE));
659 if (try.router == 0 && ao->router != 0)
660 try.router = BIT(IPX_NONE);
666 * OK, the Nak is good. Now we can update state.
668 if (f->state != OPENED)
674 IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
679 * ipxcp_rejci - Reject some of our CIs.
682 ipxcp_rejci(f, p, len)
687 u_short cilen, citype, cishort;
690 ipxcp_options try; /* options to request next time */
692 #define REJCINETWORK(opt, neg, val) \
693 if (neg && p[0] == opt) { \
694 if ((len -= CILEN_NETN) < 0) \
696 GETCHAR(citype, p); \
698 if (cilen != CILEN_NETN || \
701 GETLONG(cilong, p); \
704 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
708 #define REJCICHARS(opt, neg, val, cnt) \
709 if (neg && p[0] == opt) { \
710 int indx, count = cnt; \
711 len -= (count + 2); \
714 GETCHAR(citype, p); \
716 if (cilen != (count + 2) || \
719 for (indx = 0; indx < count; ++indx) {\
720 GETCHAR(cichar, p); \
721 if (cichar != ((u_char *) &val)[indx]) \
726 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
730 #define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
731 #define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
733 #define REJCIVOID(opt, neg) \
734 if (neg && p[0] == opt) { \
735 if ((len -= CILEN_VOID) < 0) \
737 GETCHAR(citype, p); \
739 if (cilen != CILEN_VOID || citype != opt) \
741 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
745 /* a reject for RIP/SAP is invalid since we don't send it and you can't
746 reject something which is not sent. (You can NAK, but you can't REJ.) */
747 #define REJCIPROTO(opt, neg, val, bit) \
748 if (neg && p[0] == opt) { \
749 if ((len -= CILEN_PROTOCOL) < 0) \
751 GETCHAR(citype, p); \
753 if (cilen != CILEN_PROTOCOL) \
755 GETSHORT(cishort, p); \
756 if (cishort != to_external (val) || cishort == RIP_SAP) \
758 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci short opt %d", opt)); \
762 * Any Rejected CIs must be in exactly the same order that we sent.
763 * Check packet length and CI length at each step.
764 * If we find any deviations, then this packet is bad.
769 REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
770 REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
771 REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
772 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
774 * This is the end of the record.
777 if (f->state != OPENED)
783 * The frame is invalid at this point.
785 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
790 * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
792 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
793 * appropriately. If reject_if_disagree is non-zero, doesn't return
794 * CONFNAK; returns CONFREJ if it can't return CONFACK.
797 ipxcp_reqci(f, inp, len, reject_if_disagree)
799 u_char *inp; /* Requested CIs */
800 int *len; /* Length of requested CIs */
801 int reject_if_disagree;
803 u_char *cip, *next; /* Pointer to current and next CIs */
804 u_short cilen, citype; /* Parsed len, type */
805 u_short cishort; /* Parsed short value */
806 u_int32_t cinetwork; /* Parsed address values */
807 int rc = CONFACK; /* Final packet return code */
808 int orc; /* Individual option return code */
809 u_char *p; /* Pointer to next char to parse */
810 u_char *ucp = inp; /* Pointer to current output char */
811 int l = *len; /* Length left */
814 * Reset all his options.
816 BZERO(ho, sizeof(*ho));
819 * Process all his options.
823 orc = CONFACK; /* Assume success */
824 cip = p = next; /* Remember begining of CI */
825 if (l < 2 || /* Not enough data for CI header or */
826 p[1] < 2 || /* CI length too small or */
827 p[1] > l) { /* CI length too big? */
828 IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
829 orc = CONFREJ; /* Reject bad CI */
830 cilen = l; /* Reject till end of packet */
831 l = 0; /* Don't loop again */
834 GETCHAR(citype, p); /* Parse CI type */
835 GETCHAR(cilen, p); /* Parse CI length */
836 l -= cilen; /* Adjust remaining length */
837 next += cilen; /* Step to next CI */
839 switch (citype) { /* Check CI type */
841 * The network number must match. Choose the larger of the two.
843 case IPX_NETWORK_NUMBER:
844 IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
846 /* if we wont negotiate the network number or the length is wrong
847 then reject the option */
848 if ( !ao->neg_nn || cilen != CILEN_NETN ) {
852 GETLONG(cinetwork, p);
853 IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
855 /* If the network numbers match then acknowledge them. */
856 if (cinetwork != 0) {
857 ho->his_network = cinetwork;
859 if (wo->our_network == cinetwork)
862 * If the network number is not given or we don't accept their change or
863 * the network number is too small then NAK it.
865 if (! ao->accept_network || cinetwork < wo->our_network) {
866 DECPTR (sizeof (u_int32_t), p);
867 PUTLONG (wo->our_network, p);
873 * The peer sent '0' for the network. Give it ours if we have one.
875 if (go->our_network != 0) {
876 DECPTR (sizeof (u_int32_t), p);
877 PUTLONG (wo->our_network, p);
880 * We don't have one. Reject the value.
887 * The node number is required
889 case IPX_NODE_NUMBER:
890 IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
892 /* if we wont negotiate the node number or the length is wrong
893 then reject the option */
894 if ( cilen != CILEN_NODEN ) {
899 copy_node (p, ho->his_node);
902 * If the remote does not have a number and we do then NAK it with the value
903 * which we have for it. (We never have a default value of zero.)
905 if (zero_node (ho->his_node)) {
907 copy_node (wo->his_node, p);
908 INCPTR (sizeof (wo->his_node), p);
912 * If you have given me the expected network node number then I'll accept
915 if (compare_node (wo->his_node, ho->his_node)) {
918 INCPTR (sizeof (wo->his_node), p);
922 * If his node number is the same as ours then ask him to try the next
925 if (compare_node (ho->his_node, go->our_node)) {
926 inc_node (ho->his_node);
928 copy_node (ho->his_node, p);
929 INCPTR (sizeof (wo->his_node), p);
933 * If we don't accept a new value then NAK it.
935 if (! ao->accept_remote) {
936 copy_node (wo->his_node, p);
937 INCPTR (sizeof (wo->his_node), p);
943 INCPTR (sizeof (wo->his_node), p);
946 * Compression is not desired at this time. It is always rejected.
948 case IPX_COMPRESSION_PROTOCOL:
949 IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
953 * The routing protocol is a bitmask of various types. Any combination
954 * of the values RIP_SAP and NLSP are permissible. 'IPX_NONE' for no
955 * routing protocol must be specified only once.
957 case IPX_ROUTER_PROTOCOL:
958 if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
963 GETSHORT (cishort, p);
964 IPXCPDEBUG((LOG_INFO,
965 "Remote router protocol number 0x%04x",
968 if (wo->neg_router == 0) {
970 wo->router = BIT(IPX_NONE);
973 if ((cishort == IPX_NONE && ho->router != 0) ||
974 (ho->router & BIT(IPX_NONE))) {
979 cishort = BIT(cishort);
980 if (ho->router & cishort) {
985 ho->router |= cishort;
988 /* Finally do not allow a router protocol which we do not
991 if ((cishort & (ao->router | BIT(IPX_NONE))) == 0) {
994 if (cishort == BIT(NLSP) &&
995 (ao->router & BIT(RIP_SAP)) &&
1000 protocol = IPX_NONE;
1002 DECPTR (sizeof (u_int16_t), p);
1003 PUTSHORT (protocol, p);
1008 * The router name is advisorary. Just accept it if it is not too large.
1010 case IPX_ROUTER_NAME:
1011 IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
1012 if (cilen >= CILEN_NAME) {
1013 int name_size = cilen - CILEN_NAME;
1014 if (name_size > sizeof (ho->name))
1015 name_size = sizeof (ho->name) - 1;
1016 memset (ho->name, 0, sizeof (ho->name));
1017 memcpy (ho->name, p, name_size);
1018 ho->name [name_size] = '\0';
1026 * This is advisorary.
1029 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1030 if (cilen != CILEN_COMPLETE)
1033 ho->neg_complete = 1;
1038 * All other entries are not known at this time.
1041 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1047 IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
1049 if (orc == CONFACK && /* Good CI */
1050 rc != CONFACK) /* but prior CI wasnt? */
1051 continue; /* Don't send this one */
1053 if (orc == CONFNAK) { /* Nak this CI? */
1054 if (reject_if_disagree) /* Getting fed up with sending NAKs? */
1055 orc = CONFREJ; /* Get tough if so */
1056 if (rc == CONFREJ) /* Rejecting prior CI? */
1057 continue; /* Don't send this one */
1058 if (rc == CONFACK) { /* Ack'd all prior CIs? */
1059 rc = CONFNAK; /* Not anymore... */
1060 ucp = inp; /* Backup */
1064 if (orc == CONFREJ && /* Reject this CI */
1065 rc != CONFREJ) { /* but no prior ones? */
1067 ucp = inp; /* Backup */
1070 /* Need to move CI? */
1072 BCOPY(cip, ucp, cilen); /* Move it */
1074 /* Update output pointer */
1079 * If we aren't rejecting this packet, and we want to negotiate
1080 * their address, and they didn't send their address, then we
1081 * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
1082 * input buffer is long enough that we can append the extra
1086 if (rc != CONFREJ && !ho->neg_node &&
1087 wo->req_nn && !reject_if_disagree) {
1088 if (rc == CONFACK) {
1090 wo->req_nn = 0; /* don't ask again */
1091 ucp = inp; /* reset pointer */
1094 if (zero_node (wo->his_node))
1095 inc_node (wo->his_node);
1097 PUTCHAR (IPX_NODE_NUMBER, ucp);
1098 PUTCHAR (CILEN_NODEN, ucp);
1099 copy_node (wo->his_node, ucp);
1100 INCPTR (sizeof (wo->his_node), ucp);
1103 *len = ucp - inp; /* Compute output length */
1104 IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc)));
1105 return (rc); /* Return final code */
1109 * ipxcp_up - IPXCP has come UP.
1111 * Configure the IP network interface appropriately and bring it up.
1120 IPXCPDEBUG((LOG_INFO, "ipxcp: up"));
1122 /* The default router protocol is RIP/SAP. */
1123 if (ho->router == 0)
1124 ho->router = BIT(RIP_SAP);
1126 if (go->router == 0)
1127 go->router = BIT(RIP_SAP);
1129 /* Fetch the network number */
1131 ho->his_network = wo->his_network;
1134 copy_node (wo->his_node, ho->his_node);
1136 if (!wo->neg_node && !go->neg_node)
1137 copy_node (wo->our_node, go->our_node);
1139 if (zero_node (go->our_node)) {
1140 static char errmsg[] = "Could not determine local IPX node address";
1141 IPXCPDEBUG((LOG_ERR, errmsg));
1142 ipxcp_close(f->unit, errmsg);
1146 go->network = go->our_network;
1147 if (ho->his_network != 0 && ho->his_network > go->network)
1148 go->network = ho->his_network;
1150 if (go->network == 0) {
1151 static char errmsg[] = "Can not determine network number";
1152 IPXCPDEBUG((LOG_ERR, errmsg));
1153 ipxcp_close (unit, errmsg);
1157 /* bring the interface up */
1159 IPXCPDEBUG((LOG_WARNING, "sifup failed"));
1160 ipxcp_close(unit, "Interface configuration failed");
1164 /* set the network number for IPX */
1165 if (!sipxfaddr(unit, go->network, go->our_node)) {
1166 IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
1167 ipxcp_close(unit, "Interface configuration failed");
1172 * Execute the ipx-up script, like this:
1173 * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
1176 ipxcp_script (f, _PATH_IPXUP);
1180 * ipxcp_down - IPXCP has gone DOWN.
1182 * Take the IP network interface down, clear its addresses
1183 * and delete routes through it.
1190 IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
1192 cipxfaddr (f->unit);
1194 ipxcp_script (f, _PATH_IPXDOWN);
1199 * ipxcp_script - Execute a script with arguments
1200 * interface-name tty-name speed local-IPX remote-IPX networks.
1203 ipxcp_script(f, script)
1207 char strspeed[32], strlocal[32], strremote[32];
1208 char strnetwork[32], strpid[32];
1209 char *argv[14], strproto_lcl[32], strproto_rmt[32];
1211 sprintf (strpid, "%d", getpid());
1212 sprintf (strspeed, "%d", baud_rate);
1214 strproto_lcl[0] = '\0';
1215 if (go->neg_router && ((go->router & BIT(IPX_NONE)) == 0)) {
1216 if (go->router & BIT(RIP_SAP))
1217 strcpy (strproto_lcl, "RIP ");
1218 if (go->router & BIT(NLSP))
1219 strcat (strproto_lcl, "NLSP ");
1222 if (strproto_lcl[0] == '\0')
1223 strcpy (strproto_lcl, "NONE ");
1225 strproto_lcl[strlen (strproto_lcl)-1] = '\0';
1227 strproto_rmt[0] = '\0';
1228 if (ho->neg_router && ((ho->router & BIT(IPX_NONE)) == 0)) {
1229 if (ho->router & BIT(RIP_SAP))
1230 strcpy (strproto_rmt, "RIP ");
1231 if (ho->router & BIT(NLSP))
1232 strcat (strproto_rmt, "NLSP ");
1235 if (strproto_rmt[0] == '\0')
1236 strcpy (strproto_rmt, "NONE ");
1238 strproto_rmt[strlen (strproto_rmt)-1] = '\0';
1240 strcpy (strnetwork, ipx_ntoa (go->network));
1243 "%02X%02X%02X%02X%02X%02X",
1244 NODE(go->our_node));
1247 "%02X%02X%02X%02X%02X%02X",
1248 NODE(ho->his_node));
1254 argv[4] = strnetwork;
1256 argv[6] = strremote;
1257 argv[7] = strproto_lcl;
1258 argv[8] = strproto_rmt;
1260 argv[10] = ho->name;
1264 run_program(script, argv, 0);
1268 * ipxcp_printpkt - print the contents of an IPXCP packet.
1270 static char *ipxcp_codenames[] = {
1271 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1272 "TermReq", "TermAck", "CodeRej"
1276 ipxcp_printpkt(p, plen, printer, arg)
1279 void (*printer) __P((void *, char *, ...));
1282 int code, id, len, olen;
1283 u_char *pstart, *optend;
1287 if (plen < HEADERLEN)
1293 if (len < HEADERLEN || len > plen)
1296 if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
1297 printer(arg, " %s", ipxcp_codenames[code-1]);
1299 printer(arg, " code=0x%x", code);
1300 printer(arg, " id=0x%x", id);
1307 /* print option list */
1312 if (olen < CILEN_VOID || olen > len) {
1319 case IPX_NETWORK_NUMBER:
1320 if (olen == CILEN_NETN) {
1323 printer (arg, "network %s", ipx_ntoa (cilong));
1326 case IPX_NODE_NUMBER:
1327 if (olen == CILEN_NODEN) {
1329 printer (arg, "node ");
1330 while (p < optend) {
1332 printer(arg, "%.2x", (int) (unsigned int) (unsigned char) code);
1336 case IPX_COMPRESSION_PROTOCOL:
1337 if (olen == CILEN_COMPRESS) {
1339 GETSHORT (cishort, p);
1340 printer (arg, "compression %d", (int) cishort);
1343 case IPX_ROUTER_PROTOCOL:
1344 if (olen == CILEN_PROTOCOL) {
1346 GETSHORT (cishort, p);
1347 printer (arg, "router proto %d", (int) cishort);
1350 case IPX_ROUTER_NAME:
1351 if (olen >= CILEN_NAME) {
1353 printer (arg, "router name \"");
1354 while (p < optend) {
1356 if (code >= 0x20 && code <= 0x7E)
1357 printer (arg, "%c", (int) (unsigned int) (unsigned char) code);
1359 printer (arg, " \\%.2x", (int) (unsigned int) (unsigned char) code);
1361 printer (arg, "\"");
1365 if (olen == CILEN_COMPLETE) {
1367 printer (arg, "complete");
1374 while (p < optend) {
1376 printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
1384 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1386 print_string(p, len, printer, arg);
1393 /* print the rest of the bytes in the packet */
1394 for (; len > 0; --len) {
1396 printer(arg, " %.2x", (int) (unsigned int) (unsigned char) code);
1401 #endif /* ifdef IPX_CHANGE */