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.3 1996/09/14 05:15:20 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 = {
120 * Lengths of configuration options.
124 #define CILEN_COMPLETE 2 /* length of complete option */
125 #define CILEN_NETN 6 /* network number length option */
126 #define CILEN_NODEN 8 /* node number length option */
127 #define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
128 #define CILEN_NAME 3 /* Minimum length of router name */
129 #define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
131 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
132 (x) == CONFNAK ? "NAK" : "REJ")
134 /* Used in printing the node number */
135 #define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
137 /* Used to generate the proper bit mask */
138 #define BIT(num) (1 << (num))
141 * Make a string representation of a network IP address.
149 sprintf(b, "%lx", ipxaddr);
155 * ipxcp_init - Initialize IPXCP.
161 fsm *f = &ipxcp_fsm[unit];
164 f->protocol = PPP_IPXCP;
165 f->callbacks = &ipxcp_callbacks;
166 fsm_init(&ipxcp_fsm[unit]);
168 memset (wo->name, 0, sizeof (wo->name));
169 memset (wo->our_node, 0, sizeof (wo->our_node));
170 memset (wo->his_node, 0, sizeof (wo->his_node));
173 wo->neg_complete = 1;
179 ao->neg_complete = 1;
182 ao->accept_local = 0;
183 ao->accept_remote = 0;
184 ao->accept_network = 0;
188 * Copy the node number
195 memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
199 * Compare node numbers
203 compare_node (src, dst)
206 return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
210 * Is the node number zero?
218 for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
219 if (node [indx] != 0)
225 * Increment the node number
239 PUTLONG (magic_num, outp);
243 * ipxcp_open - IPXCP is allowed to come up.
249 fsm_open(&ipxcp_fsm[unit]);
253 * ipxcp_close - Take IPXCP down.
256 ipxcp_close(unit, reason)
260 fsm_close(&ipxcp_fsm[unit], reason);
265 * ipxcp_lowerup - The lower layer is up.
271 fsm_lowerup(&ipxcp_fsm[unit]);
276 * ipxcp_lowerdown - The lower layer is down.
279 ipxcp_lowerdown(unit)
282 fsm_lowerdown(&ipxcp_fsm[unit]);
287 * ipxcp_input - Input IPXCP packet.
290 ipxcp_input(unit, p, len)
295 fsm_input(&ipxcp_fsm[unit], p, len);
300 * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
302 * Pretend the lower layer went down, so we shut up.
308 fsm_lowerdown(&ipxcp_fsm[unit]);
313 * ipxcp_resetci - Reset our CI.
322 wo->req_node = wo->neg_node && ao->neg_node;
323 wo->req_nn = wo->neg_nn && ao->neg_nn;
325 if (wo->our_network == 0) {
327 ao->accept_network = 1;
330 * If our node number is zero then change it.
332 if (zero_node (wo->our_node)) {
333 inc_node (wo->our_node);
334 ao->accept_local = 1;
338 * If his node number is zero then change it.
340 if (zero_node (wo->his_node)) {
341 inc_node (wo->his_node);
342 ao->accept_remote = 1;
345 * Unless router protocol is suppressed then assume that we can do RIP.
347 if (! (wo->router & BIT(0)))
348 wo->router |= BIT(2);
350 * Router protocol is only negotiated if requested. Others force the
353 if (wo->router & (BIT(2) | BIT(4)))
356 * Start with these default values
362 * ipxcp_cilen - Return length of our CI.
371 len = go->neg_nn ? CILEN_NETN : 0;
372 len += go->neg_node ? CILEN_NODEN : 0;
373 len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
374 len += go->neg_complete ? CILEN_COMPLETE : 0;
376 * Router protocol 0 is mutually exclusive with the others.
378 if (go->neg_router) {
379 if (go->router & BIT(0))
380 len += CILEN_PROTOCOL;
382 if (go->router & BIT(2))
383 len += CILEN_PROTOCOL;
384 if (go->router & BIT(4))
385 len += CILEN_PROTOCOL;
394 * ipxcp_addci - Add our desired CIs to a packet.
397 ipxcp_addci(f, ucp, lenp)
405 * Add the options to the record.
408 PUTCHAR (IPX_NETWORK_NUMBER, ucp);
409 PUTCHAR (CILEN_NETN, ucp);
410 PUTLONG (go->our_network, ucp);
415 PUTCHAR (IPX_NODE_NUMBER, ucp);
416 PUTCHAR (CILEN_NODEN, ucp);
417 for (indx = 0; indx < sizeof (go->our_node); ++indx)
418 PUTCHAR (go->our_node[indx], ucp);
422 int cilen = strlen (go->name);
424 PUTCHAR (IPX_ROUTER_NAME, ucp);
425 PUTCHAR (CILEN_NAME + cilen - 1, ucp);
426 for (indx = 0; indx < cilen; ++indx)
427 PUTCHAR (go->name [indx], ucp);
430 if (go->neg_router && (go->router & (BIT(0) | BIT(2) | BIT(4)))) {
431 if (go->router & BIT(0)) {
432 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
433 PUTCHAR (CILEN_PROTOCOL, ucp);
436 if (go->router & BIT(2)) {
437 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
438 PUTCHAR (CILEN_PROTOCOL, ucp);
442 if (go->router & BIT(4)) {
443 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
444 PUTCHAR (CILEN_PROTOCOL, ucp);
450 if (go->neg_complete) {
451 PUTCHAR (IPX_COMPLETE, ucp);
452 PUTCHAR (CILEN_COMPLETE, ucp);
457 * ipxcp_ackci - Ack our CIs.
464 ipxcp_ackci(f, p, len)
470 u_short cilen, citype, cishort;
474 #define ACKCIVOID(opt, neg) \
476 if ((len -= CILEN_VOID) < 0) \
478 GETCHAR(citype, p); \
480 if (cilen != CILEN_VOID || \
485 #define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
487 #define ACKCICHARS(opt, neg, val, cnt) \
489 int indx, count = cnt; \
490 len -= (count + 2); \
493 GETCHAR(citype, p); \
495 if (cilen != (count + 2) || \
498 for (indx = 0; indx < count; ++indx) {\
499 GETCHAR(cichar, p); \
500 if (cichar != ((u_char *) &val)[indx]) \
507 #define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
508 #define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
510 #define ACKCINETWORK(opt, neg, val) \
512 if ((len -= CILEN_NETN) < 0) \
514 GETCHAR(citype, p); \
516 if (cilen != CILEN_NETN || \
519 GETLONG(cilong, p); \
524 #define ACKCIPROTO(opt, neg, val, bit) \
525 if (neg && (val & BIT(bit))) \
529 GETCHAR(citype, p); \
531 if (cilen != CILEN_PROTOCOL || citype != opt) \
536 GETSHORT(cishort, p); \
537 if (cishort != (bit)) \
541 * Process the ACK frame in the order in which the frame was assembled
544 ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
545 ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
546 ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
547 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 0);
548 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 2);
549 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 4);
550 ACKCICOMPLETE (IPX_COMPLETE, go->neg_complete);
552 * This is the end of the record.
558 * The frame is invalid
560 IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
565 * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
566 * This should not modify any state if the Nak is bad
567 * or if IPXCP is in the OPENED state.
575 ipxcp_nakci(f, p, len)
581 u_char citype, cilen, *next;
584 ipxcp_options no; /* options we've seen Naks for */
585 ipxcp_options try; /* options to request next time */
587 BZERO(&no, sizeof(no));
590 while (len > CILEN_VOID) {
596 next = &p [cilen - CILEN_VOID];
599 case IPX_NETWORK_NUMBER:
600 if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
605 IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
606 if (l && ao->accept_network)
610 case IPX_NODE_NUMBER:
611 if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
615 IPXCPDEBUG((LOG_INFO,
616 "local node number %02X%02X%02X%02X%02X%02X",
619 if (!zero_node (p) && ao->accept_local &&
620 ! compare_node (p, ho->his_node))
621 copy_node (p, try.our_node);
624 /* These have never been sent. Ignore the NAK frame */
625 case IPX_COMPRESSION_PROTOCOL:
628 case IPX_ROUTER_PROTOCOL:
629 if (!go->neg_router || (cilen < CILEN_PROTOCOL))
633 if ((s != 0) && (s != 2) && (s != 4))
636 if (no.router & BIT(s))
639 if (no.router == 0) /* Reset on first NAK only */
642 try.router |= BIT(s);
645 IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
648 /* These, according to the RFC, must never be NAKed. */
649 case IPX_ROUTER_NAME:
653 /* These are for options which we have not seen. */
660 /* If there is still anything left, this packet is bad. */
665 * Do not permit the peer to force a router protocol which we do not
668 try.router &= go->router;
669 if (try.router == 0 && go->router != 0) {
675 * OK, the Nak is good. Now we can update state.
677 if (f->state != OPENED)
683 IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
688 * ipxcp_rejci - Reject some of our CIs.
691 ipxcp_rejci(f, p, len)
697 u_short cilen, citype, cishort;
700 ipxcp_options try; /* options to request next time */
702 #define REJCINETWORK(opt, neg, val) \
705 if ((len -= CILEN_NETN) < 0) \
707 GETCHAR(citype, p); \
709 if (cilen != CILEN_NETN || \
712 GETLONG(cilong, p); \
715 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
718 #define REJCICHARS(opt, neg, val, cnt) \
720 int indx, count = cnt; \
722 len -= (count + 2); \
725 GETCHAR(citype, p); \
727 if (cilen != (count + 2) || \
730 for (indx = 0; indx < count; ++indx) {\
731 GETCHAR(cichar, p); \
732 if (cichar != ((u_char *) &val)[indx]) \
737 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
740 #define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
741 #define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
743 #define REJCIVOID(opt, neg) \
746 if ((len -= CILEN_VOID) < 0) \
748 GETCHAR(citype, p); \
750 if (cilen != CILEN_VOID || citype != opt) \
752 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
755 #define REJCIPROTO(opt, neg, val, bit) \
756 if (neg && (val & BIT(bit))) \
760 GETCHAR(citype, p); \
762 if (cilen != CILEN_PROTOCOL || citype != opt) \
767 GETSHORT(cishort, p); \
768 if (cishort != (bit)) \
770 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected router proto %d", bit)); \
777 * Any Rejected CIs must be in exactly the same order that we sent.
778 * Check packet length and CI length at each step.
779 * If we find any deviations, then this packet is bad.
784 REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
785 REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
786 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
787 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 2);
788 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 4);
789 REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
790 REJCIVOID (IPX_COMPLETE, try.neg_complete);
792 * This is the end of the record.
795 if (f->state != OPENED)
801 * The frame is invalid at this point.
803 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
808 * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
810 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
811 * appropriately. If reject_if_disagree is non-zero, doesn't return
812 * CONFNAK; returns CONFREJ if it can't return CONFACK.
815 ipxcp_reqci(f, inp, len, reject_if_disagree)
817 u_char *inp; /* Requested CIs */
818 int *len; /* Length of requested CIs */
819 int reject_if_disagree;
822 u_char *cip, *next; /* Pointer to current and next CIs */
823 u_short cilen, citype; /* Parsed len, type */
824 u_short cishort, ts; /* Parsed short value */
825 u_int32_t tl, cinetwork, outnet;/* Parsed address values */
826 int rc = CONFACK; /* Final packet return code */
827 int orc; /* Individual option return code */
828 u_char *p; /* Pointer to next char to parse */
829 u_char *ucp = inp; /* Pointer to current output char */
830 int l = *len; /* Length left */
831 u_char maxslotindex, cflag;
834 * Reset all his options.
836 BZERO(ho, sizeof(*ho));
839 * Process all his options.
843 orc = CONFACK; /* Assume success */
844 cip = p = next; /* Remember begining of CI */
845 if (l < 2 || /* Not enough data for CI header or */
846 p[1] < 2 || /* CI length too small or */
847 p[1] > l) { /* CI length too big? */
848 IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
849 orc = CONFREJ; /* Reject bad CI */
850 cilen = l; /* Reject till end of packet */
851 l = 0; /* Don't loop again */
854 GETCHAR(citype, p); /* Parse CI type */
855 GETCHAR(cilen, p); /* Parse CI length */
856 l -= cilen; /* Adjust remaining length */
857 next += cilen; /* Step to next CI */
859 switch (citype) { /* Check CI type */
861 * The network number must match. Choose the larger of the two.
863 case IPX_NETWORK_NUMBER:
864 IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
866 /* if we wont negotiate the network number or the length is wrong
867 then reject the option */
868 if ( !ao->neg_nn || cilen != CILEN_NETN ) {
872 GETLONG(cinetwork, p);
873 IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
875 /* If the network numbers match then acknowledge them. */
876 if (cinetwork != 0) {
877 ho->his_network = cinetwork;
879 if (wo->our_network == cinetwork)
882 * If the network number is not given or we don't accept their change or
883 * the network number is too small then NAK it.
885 if (! ao->accept_network || cinetwork < wo->our_network) {
886 DECPTR (sizeof (u_int32_t), p);
887 PUTLONG (wo->our_network, p);
893 * The peer sent '0' for the network. Give it ours if we have one.
895 if (go->our_network != 0) {
896 DECPTR (sizeof (u_int32_t), p);
897 PUTLONG (wo->our_network, p);
900 * We don't have one. Reject the value.
907 * The node number is required
909 case IPX_NODE_NUMBER:
910 IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
912 /* if we wont negotiate the node number or the length is wrong
913 then reject the option */
914 if ( cilen != CILEN_NODEN ) {
919 copy_node (p, ho->his_node);
922 * If the remote does not have a number and we do then NAK it with the value
923 * which we have for it. (We never have a default value of zero.)
925 if (zero_node (ho->his_node)) {
927 copy_node (wo->his_node, p);
928 INCPTR (sizeof (wo->his_node), p);
932 * If you have given me the expected network node number then I'll accept
935 if (compare_node (wo->his_node, ho->his_node)) {
938 INCPTR (sizeof (wo->his_node), p);
942 * If his node number is the same as ours then ask him to try the next
945 if (compare_node (ho->his_node, go->our_node)) {
946 inc_node (ho->his_node);
948 copy_node (ho->his_node, p);
949 INCPTR (sizeof (wo->his_node), p);
953 * If we don't accept a new value then NAK it.
955 if (! ao->accept_remote) {
956 copy_node (wo->his_node, p);
957 INCPTR (sizeof (wo->his_node), p);
963 INCPTR (sizeof (wo->his_node), p);
966 * Compression is not desired at this time. It is always rejected.
968 case IPX_COMPRESSION_PROTOCOL:
969 IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
973 * The routing protocol is a bitmask of various types. Any combination
974 * of the values 2 and 4 are permissible. '0' for no routing protocol must
975 * be specified only once.
977 case IPX_ROUTER_PROTOCOL:
978 if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
983 GETSHORT (cishort, p);
984 IPXCPDEBUG((LOG_INFO,
985 "Remote router protocol number %d",
988 if ((cishort == 0 && ho->router != 0) || (ho->router & BIT(0))) {
993 if (cishort != 0 && cishort != 2 && cishort != 4) {
998 if (ho->router & BIT (cishort)) {
1003 ho->router |= BIT (cishort);
1007 * The router name is advisorary. Just accept it if it is not too large.
1009 case IPX_ROUTER_NAME:
1010 IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
1011 if (cilen >= CILEN_NAME) {
1012 int name_size = cilen - CILEN_NAME;
1013 if (name_size > sizeof (ho->name))
1014 name_size = sizeof (ho->name) - 1;
1015 memset (ho->name, 0, sizeof (ho->name));
1016 memcpy (ho->name, p, name_size);
1017 ho->name [name_size] = '\0';
1025 * This is advisorary.
1028 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1029 if (cilen != CILEN_COMPLETE)
1032 ho->neg_complete = 1;
1037 * All other entries are not known at this time.
1040 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1046 IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
1048 if (orc == CONFACK && /* Good CI */
1049 rc != CONFACK) /* but prior CI wasnt? */
1050 continue; /* Don't send this one */
1052 if (orc == CONFNAK) { /* Nak this CI? */
1053 if (reject_if_disagree) /* Getting fed up with sending NAKs? */
1054 orc = CONFREJ; /* Get tough if so */
1055 if (rc == CONFREJ) /* Rejecting prior CI? */
1056 continue; /* Don't send this one */
1057 if (rc == CONFACK) { /* Ack'd all prior CIs? */
1058 rc = CONFNAK; /* Not anymore... */
1059 ucp = inp; /* Backup */
1063 if (orc == CONFREJ && /* Reject this CI */
1064 rc != CONFREJ) { /* but no prior ones? */
1066 ucp = inp; /* Backup */
1069 /* Need to move CI? */
1071 BCOPY(cip, ucp, cilen); /* Move it */
1073 /* Update output pointer */
1078 * If we aren't rejecting this packet, and we want to negotiate
1079 * their address, and they didn't send their address, then we
1080 * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
1081 * input buffer is long enough that we can append the extra
1085 if (rc != CONFREJ && !ho->neg_node &&
1086 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"));
1123 ho->his_network = wo->his_network;
1126 copy_node (wo->his_node, ho->his_node);
1128 if (!wo->neg_node && !go->neg_node)
1129 copy_node (wo->our_node, go->our_node);
1131 if (zero_node (go->our_node)) {
1132 IPXCPDEBUG((LOG_ERR, "Could not determine local IPX node address"));
1133 ipxcp_close(f->unit, "Could not determine local IPX node address");
1137 go->network = go->our_network;
1138 if (ho->his_network != 0 && ho->his_network > go->network)
1139 go->network = ho->his_network;
1141 if (go->network == 0) {
1142 IPXCPDEBUG((LOG_ERR, "Could not determine network number"));
1143 ipxcp_close (unit, "Could not determine network number");
1147 /* bring the interface up */
1149 IPXCPDEBUG((LOG_WARNING, "sifup failed"));
1150 ipxcp_close(unit, "Interface configuration failed");
1154 /* set the network number for IPX */
1155 if (!sipxfaddr(unit, go->network, go->our_node)) {
1156 IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
1157 ipxcp_close(unit, "Interface configuration failed");
1162 * Execute the ipx-up script, like this:
1163 * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
1166 ipxcp_script (f, "/etc/ppp/ipx-up");
1170 * ipxcp_down - IPXCP has gone DOWN.
1172 * Take the IP network interface down, clear its addresses
1173 * and delete routes through it.
1180 u_int32_t ournn, network;
1182 IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
1184 cipxfaddr (f->unit);
1186 ipxcp_script (f, "/etc/ppp/ipx-down");
1191 * ipxcp_script - Execute a script with arguments
1192 * interface-name tty-name speed local-IPX remote-IPX networks.
1195 ipxcp_script(f, script)
1200 char strspeed[32], strlocal[32], strremote[32];
1201 char strnetwork[32], strpid[32];
1202 char *argv[14], strproto_lcl[32], strproto_rmt[32];
1204 sprintf (strpid, "%d", getpid());
1205 sprintf (strspeed, "%d", baud_rate);
1207 strproto_lcl[0] = '\0';
1208 if (go->neg_router) {
1209 if (go->router & BIT(2))
1210 strcpy (strproto_lcl, "RIP ");
1211 if (go->router & BIT(4))
1212 strcpy (strproto_lcl, "NLSP ");
1215 if (strproto_lcl[0] == '\0')
1216 strcpy (strproto_lcl, "NONE ");
1218 strproto_lcl[strlen (strproto_lcl)-1] = '\0';
1220 strproto_rmt[0] = '\0';
1221 if (ho->neg_router) {
1222 if (ho->router & BIT(2))
1223 strcpy (strproto_rmt, "RIP ");
1224 if (ho->router & BIT(4))
1225 strcpy (strproto_rmt, "NLSP ");
1228 if (strproto_rmt[0] == '\0')
1229 strcpy (strproto_rmt, "NONE ");
1231 strproto_rmt[strlen (strproto_rmt)-1] = '\0';
1233 strcpy (strnetwork, ipx_ntoa (go->network));
1236 "%02X%02X%02X%02X%02X%02X",
1237 NODE(go->our_node));
1240 "%02X%02X%02X%02X%02X%02X",
1241 NODE(ho->his_node));
1247 argv[4] = strnetwork;
1249 argv[6] = strremote;
1250 argv[7] = strproto_lcl;
1251 argv[8] = strproto_rmt;
1253 argv[10] = ho->name;
1257 run_program(script, argv, 0);
1261 * ipxcp_printpkt - print the contents of an IPXCP packet.
1263 static char *ipxcp_codenames[] = {
1264 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1265 "TermReq", "TermAck", "CodeRej"
1269 ipxcp_printpkt(p, plen, printer, arg)
1272 void (*printer) __P((void *, char *, ...));
1275 int code, id, len, olen;
1276 u_char *pstart, *optend;
1280 if (plen < HEADERLEN)
1286 if (len < HEADERLEN || len > plen)
1289 if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
1290 printer(arg, " %s", ipxcp_codenames[code-1]);
1292 printer(arg, " code=0x%x", code);
1293 printer(arg, " id=0x%x", id);
1300 /* print option list */
1305 if (olen < CILEN_VOID || olen > len) {
1312 case IPX_NETWORK_NUMBER:
1313 if (olen == CILEN_NETN) {
1316 printer (arg, "network %s", ipx_ntoa (cilong));
1319 case IPX_NODE_NUMBER:
1320 if (olen == CILEN_NODEN) {
1322 printer (arg, "node ");
1323 while (p < optend) {
1325 printer(arg, "%.2x", code);
1329 case IPX_COMPRESSION_PROTOCOL:
1330 if (olen == CILEN_COMPRESS) {
1332 GETSHORT (cishort, p);
1333 printer (arg, "compression %d", cishort);
1336 case IPX_ROUTER_PROTOCOL:
1337 if (olen == CILEN_PROTOCOL) {
1339 GETSHORT (cishort, p);
1340 printer (arg, "router proto %d", cishort);
1343 case IPX_ROUTER_NAME:
1344 if (olen >= CILEN_NAME) {
1346 printer (arg, "router name \"");
1347 while (p < optend) {
1349 if (code >= 0x20 && code < 0x7E)
1350 printer (arg, "%c", code);
1352 printer (arg, " \\%.2x", code);
1354 printer (arg, "\"");
1358 if (olen == CILEN_COMPLETE) {
1360 printer (arg, "complete");
1367 while (p < optend) {
1369 printer(arg, " %.2x", code);
1377 if (len > 0 && *p >= ' ' && *p < 0x7f) {
1379 print_string(p, len, printer, arg);
1386 /* print the rest of the bytes in the packet */
1387 for (; len > 0; --len) {
1389 printer(arg, " %.2x", code);
1394 #endif /* ifdef IPX_CHANGE */