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.1 1995/12/18 03:32:59 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 */
86 struct protent ipxcp_protent = {
87 PPP_IPXCP, ipxcp_init, ipxcp_input, ipxcp_protrej,
88 ipxcp_lowerup, ipxcp_lowerdown, ipxcp_open, ipxcp_close,
89 ipxcp_printpkt, NULL, 0, "IPXCP"
94 * Lengths of configuration options.
98 #define CILEN_COMPLETE 2 /* length of complete option */
99 #define CILEN_NETN 6 /* network number length option */
100 #define CILEN_NODEN 8 /* node number length option */
101 #define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
102 #define CILEN_NAME 3 /* Minimum length of router name */
103 #define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
105 #define CODENAME(x) ((x) == CONFACK ? "ACK" : \
106 (x) == CONFNAK ? "NAK" : "REJ")
108 /* Used in printing the node number */
109 #define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
111 /* Used to generate the proper bit mask */
112 #define BIT(num) (1 << (num))
115 * Make a string representation of a network IP address.
123 sprintf(b, "%lx", ipxaddr);
129 * ipxcp_init - Initialize IPXCP.
135 fsm *f = &ipxcp_fsm[unit];
138 f->protocol = PPP_IPXCP;
139 f->callbacks = &ipxcp_callbacks;
140 fsm_init(&ipxcp_fsm[unit]);
142 memset (wo->name, 0, sizeof (wo->name));
143 memset (wo->our_node, 0, sizeof (wo->our_node));
144 memset (wo->his_node, 0, sizeof (wo->his_node));
147 wo->neg_complete = 1;
153 ao->neg_complete = 1;
156 ao->accept_local = 0;
157 ao->accept_remote = 0;
158 ao->accept_network = 0;
162 * Copy the node number
169 memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
173 * Compare node numbers
177 compare_node (src, dst)
180 return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
184 * Is the node number zero?
192 for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
193 if (node [indx] != 0)
199 * Increment the node number
213 PUTLONG (magic_num, outp);
217 * ipxcp_open - IPXCP is allowed to come up.
223 fsm_open(&ipxcp_fsm[unit]);
227 * ipxcp_close - Take IPXCP down.
230 ipxcp_close(unit, reason)
234 fsm_close(&ipxcp_fsm[unit], reason);
239 * ipxcp_lowerup - The lower layer is up.
245 extern int ipx_enabled;
247 fsm_lowerup(&ipxcp_fsm[unit], ipx_enabled);
252 * ipxcp_lowerdown - The lower layer is down.
255 ipxcp_lowerdown(unit)
258 fsm_lowerdown(&ipxcp_fsm[unit]);
263 * ipxcp_input - Input IPXCP packet.
266 ipxcp_input(unit, p, len)
271 fsm_input(&ipxcp_fsm[unit], p, len);
276 * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
278 * Pretend the lower layer went down, so we shut up.
284 fsm_lowerdown(&ipxcp_fsm[unit]);
289 * ipxcp_resetci - Reset our CI.
298 wo->req_node = wo->neg_node && ao->neg_node;
299 wo->req_nn = wo->neg_nn && ao->neg_nn;
301 if (wo->our_network == 0) {
303 ao->accept_network = 1;
306 * If our node number is zero then change it.
308 if (zero_node (wo->our_node)) {
309 inc_node (wo->our_node);
310 ao->accept_local = 1;
314 * If his node number is zero then change it.
316 if (zero_node (wo->his_node)) {
317 inc_node (wo->his_node);
318 ao->accept_remote = 1;
321 * Unless router protocol is suppressed then assume that we can do RIP.
323 if (! (wo->router & BIT(0)))
324 wo->router |= BIT(2);
326 * Router protocol is only negotiated if requested. Others force the
329 if (wo->router & (BIT(2) | BIT(4)))
332 * Start with these default values
338 * ipxcp_cilen - Return length of our CI.
347 len = go->neg_nn ? CILEN_NETN : 0;
348 len += go->neg_node ? CILEN_NODEN : 0;
349 len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
350 len += go->neg_complete ? CILEN_COMPLETE : 0;
352 * Router protocol 0 is mutually exclusive with the others.
354 if (go->neg_router) {
355 if (go->router & BIT(0))
356 len += CILEN_PROTOCOL;
358 if (go->router & BIT(2))
359 len += CILEN_PROTOCOL;
360 if (go->router & BIT(4))
361 len += CILEN_PROTOCOL;
370 * ipxcp_addci - Add our desired CIs to a packet.
373 ipxcp_addci(f, ucp, lenp)
381 * Add the options to the record.
384 PUTCHAR (IPX_NETWORK_NUMBER, ucp);
385 PUTCHAR (CILEN_NETN, ucp);
386 PUTLONG (go->our_network, ucp);
391 PUTCHAR (IPX_NODE_NUMBER, ucp);
392 PUTCHAR (CILEN_NODEN, ucp);
393 for (indx = 0; indx < sizeof (go->our_node); ++indx)
394 PUTCHAR (go->our_node[indx], ucp);
398 int cilen = strlen (go->name);
400 PUTCHAR (IPX_ROUTER_NAME, ucp);
401 PUTCHAR (CILEN_NAME + cilen - 1, ucp);
402 for (indx = 0; indx < cilen; ++indx)
403 PUTCHAR (go->name [indx], ucp);
406 if (go->neg_router && (go->router & (BIT(0) | BIT(2) | BIT(4)))) {
407 if (go->router & BIT(0)) {
408 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
409 PUTCHAR (CILEN_PROTOCOL, ucp);
412 if (go->router & BIT(2)) {
413 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
414 PUTCHAR (CILEN_PROTOCOL, ucp);
418 if (go->router & BIT(4)) {
419 PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
420 PUTCHAR (CILEN_PROTOCOL, ucp);
426 if (go->neg_complete) {
427 PUTCHAR (IPX_COMPLETE, ucp);
428 PUTCHAR (CILEN_COMPLETE, ucp);
433 * ipxcp_ackci - Ack our CIs.
440 ipxcp_ackci(f, p, len)
446 u_short cilen, citype, cishort;
450 #define ACKCIVOID(opt, neg) \
452 if ((len -= CILEN_VOID) < 0) \
454 GETCHAR(citype, p); \
456 if (cilen != CILEN_VOID || \
461 #define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
463 #define ACKCICHARS(opt, neg, val, cnt) \
465 int indx, count = cnt; \
466 len -= (count + 2); \
469 GETCHAR(citype, p); \
471 if (cilen != (count + 2) || \
474 for (indx = 0; indx < count; ++indx) {\
475 GETCHAR(cichar, p); \
476 if (cichar != ((u_char *) &val)[indx]) \
483 #define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
484 #define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
486 #define ACKCINETWORK(opt, neg, val) \
488 if ((len -= CILEN_NETN) < 0) \
490 GETCHAR(citype, p); \
492 if (cilen != CILEN_NETN || \
495 GETLONG(cilong, p); \
500 #define ACKCIPROTO(opt, neg, val, bit) \
501 if (neg && (val & BIT(bit))) \
505 GETCHAR(citype, p); \
507 if (cilen != CILEN_PROTOCOL || citype != opt) \
512 GETSHORT(cishort, p); \
513 if (cishort != (bit)) \
517 * Process the ACK frame in the order in which the frame was assembled
520 ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
521 ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
522 ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
523 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 0);
524 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 2);
525 ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 4);
526 ACKCICOMPLETE (IPX_COMPLETE, go->neg_complete);
528 * This is the end of the record.
534 * The frame is invalid
536 IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
541 * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
542 * This should not modify any state if the Nak is bad
543 * or if IPXCP is in the OPENED state.
551 ipxcp_nakci(f, p, len)
557 u_char citype, cilen, *next;
560 ipxcp_options no; /* options we've seen Naks for */
561 ipxcp_options try; /* options to request next time */
563 BZERO(&no, sizeof(no));
566 while (len > CILEN_VOID) {
572 next = &p [cilen - CILEN_VOID];
575 case IPX_NETWORK_NUMBER:
576 if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
581 IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
582 if (l && ao->accept_network)
586 case IPX_NODE_NUMBER:
587 if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
591 IPXCPDEBUG((LOG_INFO,
592 "local node number %02X%02X%02X%02X%02X%02X",
595 if (!zero_node (p) && ao->accept_local &&
596 ! compare_node (p, ho->his_node))
597 copy_node (p, try.our_node);
600 /* These have never been sent. Ignore the NAK frame */
601 case IPX_COMPRESSION_PROTOCOL:
604 case IPX_ROUTER_PROTOCOL:
605 if (!go->neg_router || (cilen < CILEN_PROTOCOL))
609 if ((s != 0) && (s != 2) && (s != 4))
612 if (no.router & BIT(s))
615 if (no.router == 0) /* Reset on first NAK only */
618 try.router |= BIT(s);
621 IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
624 /* These, according to the RFC, must never be NAKed. */
625 case IPX_ROUTER_NAME:
629 /* These are for options which we have not seen. */
636 /* If there is still anything left, this packet is bad. */
641 * Do not permit the peer to force a router protocol which we do not
644 try.router &= go->router;
645 if (try.router == 0 && go->router != 0) {
651 * OK, the Nak is good. Now we can update state.
653 if (f->state != OPENED)
659 IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
664 * ipxcp_rejci - Reject some of our CIs.
667 ipxcp_rejci(f, p, len)
673 u_short cilen, citype, cishort;
676 ipxcp_options try; /* options to request next time */
678 #define REJCINETWORK(opt, neg, val) \
681 if ((len -= CILEN_NETN) < 0) \
683 GETCHAR(citype, p); \
685 if (cilen != CILEN_NETN || \
688 GETLONG(cilong, p); \
691 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
694 #define REJCICHARS(opt, neg, val, cnt) \
696 int indx, count = cnt; \
698 len -= (count + 2); \
701 GETCHAR(citype, p); \
703 if (cilen != (count + 2) || \
706 for (indx = 0; indx < count; ++indx) {\
707 GETCHAR(cichar, p); \
708 if (cichar != ((u_char *) &val)[indx]) \
713 IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
716 #define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
717 #define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
719 #define REJCIVOID(opt, neg) \
722 if ((len -= CILEN_VOID) < 0) \
724 GETCHAR(citype, p); \
726 if (cilen != CILEN_VOID || citype != opt) \
728 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
731 #define REJCIPROTO(opt, neg, val, bit) \
732 if (neg && (val & BIT(bit))) \
736 GETCHAR(citype, p); \
738 if (cilen != CILEN_PROTOCOL || citype != opt) \
743 GETSHORT(cishort, p); \
744 if (cishort != (bit)) \
746 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected router proto %d", bit)); \
753 * Any Rejected CIs must be in exactly the same order that we sent.
754 * Check packet length and CI length at each step.
755 * If we find any deviations, then this packet is bad.
760 REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
761 REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
762 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
763 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 2);
764 REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 4);
765 REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
766 REJCIVOID (IPX_COMPLETE, try.neg_complete);
768 * This is the end of the record.
771 if (f->state != OPENED)
777 * The frame is invalid at this point.
779 IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
784 * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
786 * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
787 * appropriately. If reject_if_disagree is non-zero, doesn't return
788 * CONFNAK; returns CONFREJ if it can't return CONFACK.
791 ipxcp_reqci(f, inp, len, reject_if_disagree)
793 u_char *inp; /* Requested CIs */
794 int *len; /* Length of requested CIs */
795 int reject_if_disagree;
798 u_char *cip, *next; /* Pointer to current and next CIs */
799 u_short cilen, citype; /* Parsed len, type */
800 u_short cishort, ts; /* Parsed short value */
801 u_int32_t tl, cinetwork, outnet;/* Parsed address values */
802 int rc = CONFACK; /* Final packet return code */
803 int orc; /* Individual option return code */
804 u_char *p; /* Pointer to next char to parse */
805 u_char *ucp = inp; /* Pointer to current output char */
806 int l = *len; /* Length left */
807 u_char maxslotindex, cflag;
810 * Reset all his options.
812 BZERO(ho, sizeof(*ho));
815 * Process all his options.
819 orc = CONFACK; /* Assume success */
820 cip = p = next; /* Remember begining of CI */
821 if (l < 2 || /* Not enough data for CI header or */
822 p[1] < 2 || /* CI length too small or */
823 p[1] > l) { /* CI length too big? */
824 IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
825 orc = CONFREJ; /* Reject bad CI */
826 cilen = l; /* Reject till end of packet */
827 l = 0; /* Don't loop again */
830 GETCHAR(citype, p); /* Parse CI type */
831 GETCHAR(cilen, p); /* Parse CI length */
832 l -= cilen; /* Adjust remaining length */
833 next += cilen; /* Step to next CI */
835 switch (citype) { /* Check CI type */
837 * The network number must match. Choose the larger of the two.
839 case IPX_NETWORK_NUMBER:
840 IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
842 /* if we wont negotiate the network number or the length is wrong
843 then reject the option */
844 if ( !ao->neg_nn || cilen != CILEN_NETN ) {
848 GETLONG(cinetwork, p);
849 IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
851 /* If the network numbers match then acknowledge them. */
852 if (cinetwork != 0) {
853 ho->his_network = cinetwork;
855 if (wo->our_network == cinetwork)
858 * If the network number is not given or we don't accept their change or
859 * the network number is too small then NAK it.
861 if (! ao->accept_network || cinetwork < wo->our_network) {
862 DECPTR (sizeof (u_int32_t), p);
863 PUTLONG (wo->our_network, p);
869 * The peer sent '0' for the network. Give it ours if we have one.
871 if (go->our_network != 0) {
872 DECPTR (sizeof (u_int32_t), p);
873 PUTLONG (wo->our_network, p);
876 * We don't have one. Reject the value.
883 * The node number is required
885 case IPX_NODE_NUMBER:
886 IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
888 /* if we wont negotiate the node number or the length is wrong
889 then reject the option */
890 if ( cilen != CILEN_NODEN ) {
895 copy_node (p, ho->his_node);
898 * If the remote does not have a number and we do then NAK it with the value
899 * which we have for it. (We never have a default value of zero.)
901 if (zero_node (ho->his_node)) {
903 copy_node (wo->his_node, p);
904 INCPTR (sizeof (wo->his_node), p);
908 * If you have given me the expected network node number then I'll accept
911 if (compare_node (wo->his_node, ho->his_node)) {
914 INCPTR (sizeof (wo->his_node), p);
918 * If his node number is the same as ours then ask him to try the next
921 if (compare_node (ho->his_node, go->our_node)) {
922 inc_node (ho->his_node);
924 copy_node (ho->his_node, p);
925 INCPTR (sizeof (wo->his_node), p);
929 * If we don't accept a new value then NAK it.
931 if (! ao->accept_remote) {
932 copy_node (wo->his_node, p);
933 INCPTR (sizeof (wo->his_node), p);
939 INCPTR (sizeof (wo->his_node), p);
942 * Compression is not desired at this time. It is always rejected.
944 case IPX_COMPRESSION_PROTOCOL:
945 IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
949 * The routing protocol is a bitmask of various types. Any combination
950 * of the values 2 and 4 are permissible. '0' for no routing protocol must
951 * be specified only once.
953 case IPX_ROUTER_PROTOCOL:
954 if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
959 GETSHORT (cishort, p);
960 IPXCPDEBUG((LOG_INFO,
961 "Remote router protocol number %d",
964 if ((cishort == 0 && ho->router != 0) || (ho->router & BIT(0))) {
969 if (cishort != 0 && cishort != 2 && cishort != 4) {
974 if (ho->router & BIT (cishort)) {
979 ho->router |= BIT (cishort);
983 * The router name is advisorary. Just accept it if it is not too large.
985 case IPX_ROUTER_NAME:
986 IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
987 if (cilen >= CILEN_NAME) {
988 int name_size = cilen - CILEN_NAME;
989 if (name_size > sizeof (ho->name))
990 name_size = sizeof (ho->name) - 1;
991 memset (ho->name, 0, sizeof (ho->name));
992 memcpy (ho->name, p, name_size);
993 ho->name [name_size] = '\0';
1001 * This is advisorary.
1004 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1005 if (cilen != CILEN_COMPLETE)
1008 ho->neg_complete = 1;
1013 * All other entries are not known at this time.
1016 IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
1022 IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
1024 if (orc == CONFACK && /* Good CI */
1025 rc != CONFACK) /* but prior CI wasnt? */
1026 continue; /* Don't send this one */
1028 if (orc == CONFNAK) { /* Nak this CI? */
1029 if (reject_if_disagree) /* Getting fed up with sending NAKs? */
1030 orc = CONFREJ; /* Get tough if so */
1031 if (rc == CONFREJ) /* Rejecting prior CI? */
1032 continue; /* Don't send this one */
1033 if (rc == CONFACK) { /* Ack'd all prior CIs? */
1034 rc = CONFNAK; /* Not anymore... */
1035 ucp = inp; /* Backup */
1039 if (orc == CONFREJ && /* Reject this CI */
1040 rc != CONFREJ) { /* but no prior ones? */
1042 ucp = inp; /* Backup */
1045 /* Need to move CI? */
1047 BCOPY(cip, ucp, cilen); /* Move it */
1049 /* Update output pointer */
1054 * If we aren't rejecting this packet, and we want to negotiate
1055 * their address, and they didn't send their address, then we
1056 * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
1057 * input buffer is long enough that we can append the extra
1061 if (rc != CONFREJ && !ho->neg_node &&
1062 wo->req_nn && !reject_if_disagree) {
1064 if (rc == CONFACK) {
1066 wo->req_nn = 0; /* don't ask again */
1067 ucp = inp; /* reset pointer */
1070 if (zero_node (wo->his_node))
1071 inc_node (wo->his_node);
1073 PUTCHAR (IPX_NODE_NUMBER, ucp);
1074 PUTCHAR (CILEN_NODEN, ucp);
1075 copy_node (wo->his_node, ucp);
1076 INCPTR (sizeof (wo->his_node), ucp);
1079 *len = ucp - inp; /* Compute output length */
1080 IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc)));
1081 return (rc); /* Return final code */
1085 * ipxcp_up - IPXCP has come UP.
1087 * Configure the IP network interface appropriately and bring it up.
1096 IPXCPDEBUG((LOG_INFO, "ipxcp: up"));
1099 ho->his_network = wo->his_network;
1102 copy_node (wo->his_node, ho->his_node);
1104 if (!wo->neg_node && !go->neg_node)
1105 copy_node (wo->our_node, go->our_node);
1107 if (zero_node (go->our_node)) {
1108 IPXCPDEBUG((LOG_ERR, "Could not determine local IPX node address"));
1109 ipxcp_close(f->unit, "Could not determine local IPX node address");
1113 go->network = go->our_network;
1114 if (ho->his_network != 0 && ho->his_network > go->network)
1115 go->network = ho->his_network;
1117 if (go->network == 0) {
1118 IPXCPDEBUG((LOG_ERR, "Could not determine network number"));
1119 ipxcp_close (unit, "Could not determine network number");
1123 /* bring the interface up */
1125 IPXCPDEBUG((LOG_WARNING, "sifup failed"));
1126 ipxcp_close(unit, "Interface configuration failed");
1130 /* set the network number for IPX */
1131 if (!sipxfaddr(unit, go->network, go->our_node)) {
1132 IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
1133 ipxcp_close(unit, "Interface configuration failed");
1138 * Execute the ipx-up script, like this:
1139 * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
1142 ipxcp_script (f, "/etc/ppp/ipx-up");
1146 * ipxcp_down - IPXCP has gone DOWN.
1148 * Take the IP network interface down, clear its addresses
1149 * and delete routes through it.
1156 u_int32_t ournn, network;
1158 IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
1160 cipxfaddr (f->unit);
1162 ipxcp_script (f, "/etc/ppp/ipx-down");
1167 * ipxcp_script - Execute a script with arguments
1168 * interface-name tty-name speed local-IPX remote-IPX networks.
1171 ipxcp_script(f, script)
1176 char strspeed[32], strlocal[32], strremote[32];
1177 char strnetwork[32], strpid[32];
1178 char *argv[14], strproto_lcl[32], strproto_rmt[32];
1180 sprintf (strpid, "%d", getpid());
1181 sprintf (strspeed, "%d", baud_rate);
1183 strproto_lcl[0] = '\0';
1184 if (go->neg_router) {
1185 if (go->router & BIT(2))
1186 strcpy (strproto_lcl, "RIP ");
1187 if (go->router & BIT(4))
1188 strcpy (strproto_lcl, "NLSP ");
1191 if (strproto_lcl[0] == '\0')
1192 strcpy (strproto_lcl, "NONE ");
1194 strproto_lcl[strlen (strproto_lcl)-1] = '\0';
1196 strproto_rmt[0] = '\0';
1197 if (ho->neg_router) {
1198 if (ho->router & BIT(2))
1199 strcpy (strproto_rmt, "RIP ");
1200 if (ho->router & BIT(4))
1201 strcpy (strproto_rmt, "NLSP ");
1204 if (strproto_rmt[0] == '\0')
1205 strcpy (strproto_rmt, "NONE ");
1207 strproto_rmt[strlen (strproto_rmt)-1] = '\0';
1209 strcpy (strnetwork, ipx_ntoa (go->network));
1212 "%02X%02X%02X%02X%02X%02X",
1213 NODE(go->our_node));
1216 "%02X%02X%02X%02X%02X%02X",
1217 NODE(ho->his_node));
1223 argv[4] = strnetwork;
1225 argv[6] = strremote;
1226 argv[7] = strproto_lcl;
1227 argv[8] = strproto_rmt;
1229 argv[10] = ho->name;
1233 run_program(script, argv, 0);
1237 * ipxcp_printpkt - print the contents of an IPXCP packet.
1239 char *ipxcp_codenames[] = {
1240 "ConfReq", "ConfAck", "ConfNak", "ConfRej",
1241 "TermReq", "TermAck", "CodeRej"
1245 ipxcp_printpkt(p, plen, printer, arg)
1251 int code, id, len, olen;
1252 u_char *pstart, *optend;
1256 if (plen < HEADERLEN)
1262 if (len < HEADERLEN || len > plen)
1265 if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
1266 printer(arg, " %s", ipxcp_codenames[code-1]);
1268 printer(arg, " code=0x%x", code);
1269 printer(arg, " id=0x%x", id);
1276 /* print option list */
1281 if (olen < CILEN_VOID || olen > len) {
1288 case IPX_NETWORK_NUMBER:
1289 if (olen == CILEN_NETN) {
1292 printer (arg, "network %s", ipx_ntoa (cilong));
1295 case IPX_NODE_NUMBER:
1296 if (olen == CILEN_NODEN) {
1298 printer (arg, "node ");
1299 while (p < optend) {
1301 printer(arg, "%.2x", code);
1305 case IPX_COMPRESSION_PROTOCOL:
1306 if (olen == CILEN_COMPRESS) {
1308 GETSHORT (cishort, p);
1309 printer (arg, "compression %d", cishort);
1312 case IPX_ROUTER_PROTOCOL:
1313 if (olen == CILEN_PROTOCOL) {
1315 GETSHORT (cishort, p);
1316 printer (arg, "router proto %d", cishort);
1319 case IPX_ROUTER_NAME:
1320 if (olen >= CILEN_NAME) {
1322 printer (arg, "router name \"");
1323 while (p < optend) {
1325 if (code >= 0x20 && code < 0x7E)
1326 printer (arg, "%c", code);
1328 printer (arg, " \\%.2x", code);
1330 printer (arg, "\"");
1334 if (olen == CILEN_COMPLETE) {
1336 printer (arg, "complete");
1343 while (p < optend) {
1345 printer(arg, " %.2x", code);
1352 /* print the rest of the bytes in the packet */
1353 for (; len > 0; --len) {
1355 printer(arg, " %.2x", code);
1360 #endif /* ifdef IPX_CHANGE */