-# $Id: Makefile.linux,v 1.4 1995/12/11 02:55:14 paulus Exp $
+# $Id: Makefile.linux,v 1.5 1995/12/18 03:32:43 paulus Exp $
CDEF1= -DTERMIOS # Use the termios structure
CDEF2= -DPIDSTRING # I like ascii pid values
CDEF5= -DFNDELAY=O_NDELAY # Old name value
CDEFS= $(CDEF1) $(CDEF2) $(CDEF3) $(CDEF4) $(CDEF5)
-CFLAGS= -O2 -N $(CDEFS)
+CFLAGS= -O2 $(CDEFS)
all: chat
chat: chat.o
- $(CC) -o chat chat.o
+ $(CC) -O2 -o chat chat.o
chat.o: chat.c
$(CC) -c $(CFLAGS) -o chat.o chat.c
.\" -*- nroff -*-
.\" manual page [] for chat 1.8
-.\" $Id: chat.8,v 1.2 1995/06/12 11:24:14 paulus Exp $
+.\" $Id: chat.8,v 1.3 1995/12/18 03:32:45 paulus Exp $
.\" SH section heading
.\" SS subsection heading
.\" LP paragraph
\fIchat\fR program will then log all text received from the modem and
the output strings which it sends to the SYSLOG.
.TP
+.B -V
+Request that the \fIchat\fR script be executed in a stderr verbose
+mode. The \fIchat\fR program will then log all text received from the
+modem and the output strings which it sends to the stderr device. This
+device is usually the local console at the station running the chat or
+pppd program. This option will not work properly if the stderr is
+redirected to the /dev/null locaiton as is the case should pppd be run
+in the 'detached' mode. In that case, use the '-v' option to record
+the session on the SYSLOG device.
+.TP
.B script
If the script is not specified in a file with the \fI-f\fR option then
the script is included as parameters to the \fIchat\fR program.
*
*/
-static char rcsid[] = "$Id: chat.c,v 1.9 1995/06/12 11:24:15 paulus Exp $";
+static char rcsid[] = "$Id: chat.c,v 1.10 1995/12/18 03:32:46 paulus Exp $";
#include <stdio.h>
#include <time.h>
#define DEFAULT_CHAT_TIMEOUT 45
int verbose = 0;
+int Verbose = 0;
int quiet = 0;
int report = 0;
int exit_code = 0;
++verbose;
break;
+ case 'V':
+ ++Verbose;
+ break;
+
case 'f':
if (arg = OPTARG(argc, argv))
{
fprintf (report_fp, "Closing \"%s\".\n", report_file);
}
fclose (report_fp);
- report_fp = (FILE*) NULL;
+ report_fp = (FILE *) NULL;
}
#if defined(get_term_param)
return dup_mem (temp, (size_t) (s1 - temp)); /* may have embedded nuls */
}
+/*
+ * A modified version of 'strtok'. This version skips \ sequences.
+ */
+
+char *expect_strtok (s, term)
+char *s, *term;
+ {
+ static char *str = "";
+ static int escape_flag = 0;
+ char *result;
+/*
+ * If a string was specified then do initial processing.
+ */
+ if (s)
+ {
+ str = s;
+ escape_flag = 0;
+ }
+
+ result = (char *) 0;
+ while (*str)
+ {
+/*
+ * Look for the terminator sequence.
+ * If the escape flag is set then this character is not the terminator.
+ * We assume that term does not contain the backslash character.
+ */
+ if (escape_flag || strchr (term, *str) == (char *) 0)
+ {
+ if (result == (char *) 0)
+ {
+ result = str;
+ }
+
+ if (escape_flag || *str == '\\')
+ {
+ escape_flag = !escape_flag;
+ }
+
+ ++str;
+ continue;
+ }
+/*
+ * This is the terminator. If we have a string then this is the end of the
+ * scan operation.
+ */
+ *str++ = '\0';
+ if (result)
+ {
+ break;
+ }
+ }
+ return (result);
+ }
+
/*
* Process the expect string
*/
-void chat_expect(s)
-register char *s;
+
+void chat_expect (s)
+char *s;
{
+ char *expect;
+ char *reply;
+
if (strcmp(s, "ABORT") == 0)
{
++abort_next;
++timeout_next;
return;
}
-
- while (*s)
+/*
+ * Fetch the expect and reply string.
+ */
+ for (;;)
{
- register char *hyphen;
+ expect = expect_strtok (s, "-");
+ s = (char *) 0;
- for (hyphen = s; *hyphen; ++hyphen)
+ if (expect == (char *) 0)
{
- if (*hyphen == '-')
- {
- if (hyphen == s || hyphen[-1] != '\\')
- {
- break;
- }
- }
+ return;
}
-
- if (*hyphen == '-')
- {
- *hyphen = '\0';
- if (get_string(s))
- {
- return;
- }
- else
- {
- s = hyphen + 1;
-
- for (hyphen = s; *hyphen; ++hyphen)
- {
- if (*hyphen == '-')
- {
- if (hyphen == s || hyphen[-1] != '\\')
- {
- break;
- }
- }
- }
-
- if (*hyphen == '-')
- {
- *hyphen = '\0';
-
- chat_send(s);
- s = hyphen + 1;
- }
- else
- {
- chat_send(s);
- return;
- }
- }
+ reply = expect_strtok (s, "-");
+/*
+ * Handle the expect string. If successful then exit.
+ */
+ if (get_string (expect))
+ {
+ return;
}
- else
+/*
+ * If there is a sub-reply string then send it. Otherwise any condition
+ * is terminal.
+ */
+ if (reply == (char *) 0 || exit_code != 3)
{
- if (get_string(s))
- {
- return;
- }
- else
- {
- if (fail_reason)
- {
- syslog(LOG_INFO, "Failed (%s)", fail_reason);
- }
- else
- {
- syslog(LOG_INFO, "Failed");
- }
-
- terminate(exit_code);
- }
+ break;
}
+
+ chat_send (reply);
+ }
+/*
+ * The expectation did not occur. This is terminal.
+ */
+ if (fail_reason)
+ {
+ syslog(LOG_INFO, "Failed (%s)", fail_reason);
+ }
+ else
+ {
+ syslog(LOG_INFO, "Failed");
}
+ terminate(exit_code);
}
+/*
+ * Translate the input character to the appropriate string for printing
+ * the data.
+ */
+
char *character(c)
int c;
{
}
}
+ if (Verbose) {
+ if (c == '\n') fputc( '\n', stderr );
+ else if (c != '\r') fprintf( stderr, "%s", character(c) );
+ }
+
*s++ = c;
if (s - temp >= len &&
-/* $Id: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp $ */
+/* $Id: if_ppp.h,v 1.4 1995/12/18 03:38:01 paulus Exp $ */
/*
* if_ppp.h - Point-to-Point Protocol definitions.
*/
/*
- * ==PPPVERSION 2.1.3==
+ * ==FILEVERSION 6==
*
* NOTE TO MAINTAINERS:
- * If you modify this file at all, increment the last number above.
- * ppp.c is shipped with a PPP distribution as well as with the kernel;
- * if everyone increases the PPPVERSION number above, then scripts
- * can do the right thing when deciding whether to install a new ppp.c
+ * If you modify this file at all, increment the number above.
+ * if_ppp.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new if_ppp.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
#ifndef _IF_PPP_H_
#define _IF_PPP_H_
+#if defined(__linux__)
+#include <linux/if.h>
+#include <linux/ioctl.h>
+#include <linux/ppp_defs.h>
+#endif
+
/*
* Packet sizes
*/
#define PPP_VERSION "2.2.0"
#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */
#define PROTO_IPX 0x002b /* protocol numbers */
+#define PROTO_DNA_RT 0x0027 /* DNA Routing */
+
/*
* Bit definitions for flags.
};
struct ifpppstatsreq {
- char ifr__name[IFNAMSIZ]; /* Name of the device */
- struct ppp_stats *stats_ptr; /* Pointer to stats buffer */
- struct ppp_stats stats; /* statistic information */
+ struct ifreq b;
+ struct ppp_stats stats; /* statistic information */
};
+struct ifpppcstatsreq {
+ struct ifreq b;
+ struct ppp_comp_stats stats;
+};
+
+#define ifr__name b.ifr_ifrn.ifrn_name
+#define stats_ptr b.ifr_ifru.ifru_data
+
/*
* Ioctl definitions.
*/
#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
-
#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
-#define PPPIOCGTIME _IOR('t', 63, struct ppp_ddinfo) /* Read time info */
+#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0)
-#define SIOCGPPPVER (SIOCDEVPRIVATE + 1)
+#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */
+#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2)
#if !defined(ifr_mtu)
#define ifr_mtu ifr_ifru.ifru_metric
-/* $Id: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp $ */
+/* $Id: if_pppvar.h,v 1.3 1995/12/18 03:38:02 paulus Exp $ */
/*
* if_pppvar.h - private structures and declarations for PPP.
*
*/
/*
- * ==PPPVERSION 2.1.3==
+ * ==FILEVERSION 4==
*
* NOTE TO MAINTAINERS:
- * If you modify this file at all, increment the last number above.
- * ppp.c is shipped with a PPP distribution as well as with the kernel;
- * if everyone increases the PPPVERSION number above, then scripts
- * can do the right thing when deciding whether to install a new ppp.c
+ * If you modify this file at all, increment the number above.
+ * if_pppvar.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new if_pppvar.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
* Buffers for the PPP process have the following structure
*/
-#define RBUFSIZE 2048 /* MUST be a power of 2 and be <= 4095 */
+#define RBUFSIZE 2048 /* MUST be a power of 2 and be <= 4095 */
+
struct ppp_buffer {
int size; /* Size of the buffer area */
int count; /* Count of characters in bufr */
int head; /* index to head of list */
int tail; /* index to tail of list */
- int locked; /* Buffer is being sent */
+ unsigned long locked; /* Buffer is being sent */
int type; /* Type of the buffer */
/* =0, device read buffer */
/* =1, device write buffer */
/* =2, daemon write buffer */
/* =3, daemon read buffer */
unsigned short fcs; /* Frame Check Sequence (CRC) */
+ unsigned char filler[4]; /* Extra space if needed */
};
/* Given a pointer to the ppp_buffer then return base address of buffer */
ext_accm xmit_async_map; /* 1 bit means that given control
character is quoted on output*/
- unsigned long recv_async_map; /* 1 bit means that given control
+ __u32 recv_async_map; /* 1 bit means that given control
character is ignored on input*/
int mtu; /* maximum xmit frame size */
int mru; /* maximum receive frame size */
struct ppp_buffer *s1buf; /* Pointer to daemon buffer */
struct ppp_buffer *s2buf; /* Pointer to device buffer */
- unsigned long last_xmit; /* time of last transmission */
+ __u32 last_xmit; /* time of last transmission */
/* These are pointers to the malloc()ed frame buffers.
These buffers are used while processing a packet. If a packet
struct wait_queue *read_wait; /* queue for writing processes */
/* Statistic information */
- struct pppstat stats; /* statistic information */
- struct ppp_ddinfo ddinfo; /* demand dial information */
+ struct pppstat stats; /* statistic information */
+ struct ppp_idle ddinfo; /* demand dial information */
/* PPP compression protocol information */
u_int sc_bytessent; /* count of octets sent */
--- /dev/null
+/*
+ * ppp-comp.h - Definitions for doing PPP packet compression.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ppp-comp.h,v 1.1 1995/12/18 03:38:10 paulus Exp $
+ */
+
+/*
+ * ==FILEVERSION 4==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, increment the number above.
+ * ppp-comp.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new ppp-comp.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _NET_PPP_COMP_H
+#define _NET_PPP_COMP_H
+
+/*
+ * The following symbols control whether we include code for
+ * various compression methods.
+ */
+
+#ifndef DO_BSD_COMPRESS
+#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */
+#endif
+
+#define DO_PREDICTOR_1 0
+#define DO_PREDICTOR_2 0
+#define DO_DEFLATE 0
+
+/*
+ * Structure giving methods for compression/decompression.
+ */
+
+#ifdef PACKETPTR
+struct compressor {
+ int compress_proto; /* CCP compression protocol number */
+
+ /* Allocate space for a compressor (transmit side) */
+ void *(*comp_alloc) (unsigned char *options, int opt_len);
+
+ /* Free space used by a compressor */
+ void (*comp_free) (void *state);
+
+ /* Initialize a compressor */
+ int (*comp_init) (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int debug);
+
+ /* Reset a compressor */
+ void (*comp_reset) (void *state);
+
+ /* Compress a packet */
+ int (*compress) (void *state, unsigned char *rptr,
+ unsigned char *obuf, int isize, int osize);
+
+ /* Return compression statistics */
+ void (*comp_stat) (void *state, struct compstat *stats);
+
+ /* Allocate space for a decompressor (receive side) */
+ void *(*decomp_alloc) (unsigned char *options, int opt_len);
+
+ /* Free space used by a decompressor */
+ void (*decomp_free) (void *state);
+
+ /* Initialize a decompressor */
+ int (*decomp_init) (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int mru,
+ int debug);
+
+ /* Reset a decompressor */
+ void (*decomp_reset) (void *state);
+
+ /* Decompress a packet. */
+ int (*decompress) (void *state, unsigned char *ibuf, int isize,
+ unsigned char *obuf, int osize);
+
+ /* Update state for an incompressible packet received */
+ void (*incomp) (void *state, unsigned char *ibuf, int icnt);
+
+ /* Return decompression statistics */
+ void (*decomp_stat) (void *state, struct compstat *stats);
+};
+#endif /* PACKETPTR */
+
+/*
+ * Return values for decompress routine.
+ * We need to make these distinctions so that we can disable certain
+ * useful functionality, namely sending a CCP reset-request as a result
+ * of an error detected after decompression. This is to avoid infringing
+ * a patent held by Motorola.
+ * Don't you just lurve software patents.
+ */
+
+#define DECOMP_OK 0 /* everything went OK */
+#define DECOMP_ERROR 1 /* error detected before decomp. */
+#define DECOMP_FATALERROR 2 /* error detected after decomp. */
+
+/*
+ * CCP codes.
+ */
+
+#define CCP_CONFREQ 1
+#define CCP_CONFACK 2
+#define CCP_TERMREQ 5
+#define CCP_TERMACK 6
+#define CCP_RESETREQ 14
+#define CCP_RESETACK 15
+
+/*
+ * Max # bytes for a CCP option
+ */
+
+#define CCP_MAX_OPTION_LENGTH 32
+
+/*
+ * Parts of a CCP packet.
+ */
+
+#define CCP_CODE(dp) ((dp)[0])
+#define CCP_ID(dp) ((dp)[1])
+#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
+#define CCP_HDRLEN 4
+
+#define CCP_OPT_CODE(dp) ((dp)[0])
+#define CCP_OPT_LENGTH(dp) ((dp)[1])
+#define CCP_OPT_MINLEN 2
+
+/*
+ * Definitions for BSD-Compress.
+ */
+
+#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
+#define CILEN_BSD_COMPRESS 3 /* length of config. option */
+
+/* Macros for handling the 3rd byte of the BSD-Compress config option. */
+#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
+#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
+#define BSD_CURRENT_VERSION 1 /* current version number */
+#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
+
+#define BSD_MIN_BITS 9 /* smallest code size supported */
+#define BSD_MAX_BITS 15 /* largest code size supported */
+
+/*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+
+#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
+#define CILEN_PREDICTOR_1 2 /* length of its config option */
+#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
+#define CILEN_PREDICTOR_2 2 /* length of its config option */
+
+#define CI_DEFLATE 24 /* config option for Deflate */
+#define CILEN_DEFLATE 4 /* length of its config option */
+
+#define DEFLATE_MIN_SIZE 8
+#define DEFLATE_MAX_SIZE 15
+#define DEFLATE_METHOD_VAL 8
+#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_METHOD(x) ((x) & 0x0F)
+#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ + DEFLATE_METHOD_VAL)
+#define DEFLATE_CHK_SEQUENCE 0
+
+#endif /* _NET_PPP_COMP_H */
--- /dev/null
+/* $Id: ppp_defs.h,v 1.1 1995/12/18 03:38:15 paulus Exp $ */
+
+/*
+ * ppp_defs.h - PPP definitions.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+/*
+ * ==FILEVERSION 6==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, increment the number above.
+ * ppp_defs.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new ppp_defs.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _PPP_DEFS_H_
+#define _PPP_DEFS_H_
+
+/*
+ * The basic PPP frame.
+ */
+#define PPP_HDRLEN 4 /* octets for standard ppp header */
+#define PPP_FCSLEN 2 /* octets for FCS */
+#define PPP_MRU 1500 /* default MRU = max length of info field */
+
+#define PPP_ADDRESS(p) (((u_char *)(p))[0])
+#define PPP_CONTROL(p) (((u_char *)(p))[1])
+#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
+
+/*
+ * Significant octet values.
+ */
+#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
+#define PPP_UI 0x03 /* Unnumbered Information */
+#define PPP_FLAG 0x7e /* Flag Sequence */
+#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
+#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
+
+/*
+ * Protocol field values.
+ */
+#define PPP_IP 0x21 /* Internet Protocol */
+#define PPP_IPX 0x2b /* IPX protocol */
+#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
+#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
+#define PPP_COMP 0xfd /* compressed packet */
+#define PPP_IPCP 0x8021 /* IP Control Protocol */
+#define PPP_IPXCP 0x802b /* IPX Control Protocol */
+#define PPP_CCP 0x80fd /* Compression Control Protocol */
+#define PPP_LCP 0xc021 /* Link Control Protocol */
+#define PPP_PAP 0xc023 /* Password Authentication Protocol */
+#define PPP_LQR 0xc025 /* Link Quality Report protocol */
+#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
+
+/*
+ * A 32-bit unsigned integral type.
+ */
+#ifndef __BIT_TYPES_DEFINED__
+#ifdef UINT32_T
+typedef UINT32_T u_int32_t;
+#else
+typedef unsigned int u_int32_t;
+#endif
+#endif
+
+/*
+ * Extended asyncmap - allows any character to be escaped.
+ */
+typedef u_int32_t ext_accm[8];
+
+/*
+ * What to do with network protocol (NP) packets.
+ */
+enum NPmode {
+ NPMODE_PASS, /* pass the packet through */
+ NPMODE_DROP, /* silently drop the packet */
+ NPMODE_ERROR, /* return an error */
+ NPMODE_QUEUE /* save it up for later. */
+};
+
+/*
+ * Statistics for LQRP and pppstats
+ */
+struct pppstat {
+ u_int ppp_discards; /* # frames discarded */
+
+ u_int ppp_ibytes; /* bytes received */
+ u_int ppp_ioctects; /* bytes received not in error */
+ u_int ppp_ipackets; /* packets received */
+ u_int ppp_ierrors; /* receive errors */
+ u_int ppp_ilqrs; /* # LQR frames received */
+
+ u_int ppp_obytes; /* raw bytes sent */
+ u_int ppp_ooctects; /* frame bytes sent */
+ u_int ppp_opackets; /* packets sent */
+ u_int ppp_oerrors; /* transmit errors */
+ u_int ppp_olqrs; /* # LQR frames sent */
+};
+
+struct vjstat {
+ u_int vjs_packets; /* outbound packets */
+ u_int vjs_compressed; /* outbound compressed packets */
+ u_int vjs_searches; /* searches for connection state */
+ u_int vjs_misses; /* times couldn't find conn. state */
+ u_int vjs_uncompressedin; /* inbound uncompressed packets */
+ u_int vjs_compressedin; /* inbound compressed packets */
+ u_int vjs_errorin; /* inbound unknown type packets */
+ u_int vjs_tossed; /* inbound packets tossed because of error */
+};
+
+struct compstat {
+ u_int unc_bytes; /* total uncompressed bytes */
+ u_int unc_packets; /* total uncompressed packets */
+ u_int comp_bytes; /* compressed bytes */
+ u_int comp_packets; /* compressed packets */
+ u_int inc_bytes; /* incompressible bytes */
+ u_int inc_packets; /* incompressible packets */
+ /* the compression ratio is defined as in_count / bytes_out */
+ u_int in_count; /* Bytes received */
+ u_int bytes_out; /* Bytes transmitted */
+ double ratio; /* not computed in kernel. */
+};
+
+struct ppp_stats {
+ struct pppstat p; /* basic PPP statistics */
+ struct vjstat vj; /* VJ header compression statistics */
+};
+
+struct ppp_comp_stats {
+ struct compstat c; /* packet compression statistics */
+ struct compstat d; /* packet decompression statistics */
+};
+
+/*
+ * The following structure records the time in seconds since
+ * the last NP packet was sent or received.
+ */
+struct ppp_idle {
+ time_t xmit_idle; /* time since last NP packet sent */
+ time_t recv_idle; /* time since last NP packet received */
+};
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+#endif /* _PPP_DEFS_H_ */
--- /dev/null
+ This archive represents the file called 'ppp-2.2.0d.tar.gz' for
+ Linux only.
+
+The changes from 2.2.0c to 2.2.0d are:
+
+1. Change chat to recognize the ABORT strings if you specify a sub-string.
+
+2. Change the ppp.c file to prevent the symbol table compilation problems.
+
+3. Augment the IP list in the authentication to include a netmask option
+ and to permit a reject as well as the default accept entries.
+
+4. Flushed the tty input buffer prior to starting the connect program.
+ This prevents old modem responses from a previous session to be fed to
+ the current one.
+
+5. Integrated Paul Mackerras' fix for a bug in the CCP which causes
+ the bsd compression to constantly re-negotiate a smaller and smaller
+ code size.
+
+6. Added options to set the Predictor-1 compressor if so desired. Predictor-1
+ is used by Morningstar's PPP package.
+
+7. Add support for Microsoft DNS parameters by Christoper Lameter.
+
+8. Support for the IPX protocol. It originated, and substantially resembles
+ since it started with, the work by G.Cambell@irl.cri.nz. Many thanks to
+ him for starting and getting the initial code to work. The IPX support
+ requires at least the 1.3.43 kernel.
+
+The changes from 2.2.0b to 2.2.0c are:
+
+1. Correct the reference in the ppp.c file for the definition of the
+ symbol table. This is used if you not using modules.
+
+There is still a compile/link problem with the a.out format. The problem
+is not with ppp, but in the module.h header file. If you are using a.out
+and have problems linking with an unresolved 'mod_use_count_' then use
+the following patch on the /usr/include/linux/module.h header file.
+
+ELF does not have this problem. Only a.out will complain.
+
+--- module.h.orig Thu Oct 19 05:32:32 1995
++++ module.h Thu Oct 19 05:33:44 1995
+@@ -90,12 +90,12 @@
+ * define the count variable, and usage macros.
+ */
+
+-extern long mod_use_count_;
+ #if defined(CONFIG_MODVERSIONS) && defined(MODULE) && !defined(__GENKSYMS__)
+ int Using_Versions; /* gcc will handle this global (used as a flag) correctly */
+ #endif
+
+ #ifdef MODULE
++extern long mod_use_count_;
+ #define MOD_INC_USE_COUNT mod_use_count_++
+ #define MOD_DEC_USE_COUNT mod_use_count_--
+ #define MOD_IN_USE (mod_use_count_ != 0)
+
+
+The changes from 2.2.0a to 2.2.0b are:
+
+1. Correct a problem with the 1.3.33+ kernels in that they would cause
+ a SIGSEGV should you run the pppd program with the 'defaultroute'
+ option.
+
+2. Corrections in the ppp.c driver for non-module builds regarding the
+ symbol version informaiton.
+
+3. Removed bad definitions of the MOD_INC_USE_COUNT and MOD_DEC_USE_COUNT
+ from ppp.c.
+
+4. Corrected the cleanup logic for the device. The test for ppp_alive
+ was the wrong sense.
+
+5. Corrected the references in chat scripts for "/usr/lib/ppp" to be
+ "/usr/sbin".
+
+The changes from 2.2.0 and 2.2.0a are:
+
+1. The code files have been moved to the /usr/sbin directory. This should
+ have been done in the 2.2.0 package but something happened and an old
+ Makefile was shipped in its place.
+
+2. The BSD compressor module, bsd_comp, will ONLY compile as a loadable
+ module. This was performed for a few technical reasons and one legal
+ reason. (The legal reason is in the README file here.)
+
+3. The test for the presence of ppp support has been moved to after the
+ decode of the options. It means that the test will no longer use /dev/tty
+ which may not be appropriate at that time.
+
+4. The pppstats program has been changed to work with the driver since the
+ driver will no longer attempt to do a floating point operation. This
+ previously would cause a kernel panic.
+
+ ADDITIONAL INFORMATION
+
+1. This distribution requires either a kernel from the 1.2 series
+which is at or later than 1.2.11 or a kernel from the 1.3 series which
+is at or later 1.3.34. In short, you should use the latest version
+from either release. The difficulties in supporting earlier versions
+as they were being developed were too great. This means that the code
+may or may not work. If it does not then when you ask the answer will
+be the same; UPGRADE to the latest revision of the 1.2 or 1.3 kernels!!
+
+2. Please, please, read the README file in this directory __and__ the
+README.linux file. Pay attention to the fact that you _must_ do the
+command:
+
+make kernel
+
+This does not mean that you need to build the kernel, although you
+will need to do this also, but you must do the command from the ppp
+directory to make any appropriate patches.
+
+3. Do not be concerned should the 'make kernel' say that a file is
+current and not need to be replaced. It only means that the kernel
+already has the proper files. To be honest, it is the reason that
+there is a 'make kernel' -- to cover this condition. I had too many
+people put older drivers into the kernel because they followed the
+wrong set of instructions. Now, for all versions, there is only one
+set of instructions -- "do make kernel".
+
+[Ed.: After I wrote this, I received email from someone who had problems
+which could not be addressed by the standard 'make kernel'. It will not
+be able to make the proper changes if you have not applied the sequence
+against an original then there is a version specific instruction in the
+README.linux file.]
+
--- /dev/null
+/* Because this code is derived from the 4.3BSD compress source:
+ *
+ * Copyright (c) 1985, 1986 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * James A. Woods, derived from original work by Spencer Thomas
+ * and Joseph Orost.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * This version is for use with contigious buffers on Linux-derived systems.
+ *
+ * ==FILEVERSION 5==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, increment the number above.
+ * bsd_comp.c is shipped with a PPP distribution as well as with
+ * the kernel; if everyone increases the FILEVERSION number above,
+ * then scripts can do the right thing when deciding whether to
+ * install a new bsd_comp.c file. Don't change the format of that
+ * line otherwise, so the installation script can recognize it.
+ *
+ * $Id: bsd_comp.c,v 1.2 1995/12/18 03:37:05 paulus Exp $
+ */
+
+#ifndef MODULE
+#error This file must be compiled as a module.
+#endif
+
+#include <linux/module.h>
+
+#include <endian.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/types.h>
+#include <linux/fcntl.h>
+#include <linux/interrupt.h>
+#include <linux/ptrace.h>
+#include <linux/ioport.h>
+#include <linux/in.h>
+#include <linux/malloc.h>
+#include <linux/tty.h>
+#include <linux/errno.h>
+#include <linux/sched.h> /* to get the struct task_struct */
+#include <linux/string.h> /* used in new tty drivers */
+#include <linux/signal.h> /* used in new tty drivers */
+
+#include <asm/system.h>
+#include <asm/bitops.h>
+#include <asm/segment.h>
+
+#include <net/if.h>
+
+#include <linux/if_ether.h>
+#include <linux/netdevice.h>
+#include <linux/skbuff.h>
+#include <linux/inet.h>
+#include <linux/ioctl.h>
+
+#include <linux/ppp_defs.h>
+
+#ifdef NEW_SKBUFF
+#include <linux/netprotocol.h>
+#endif
+
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
+#include <net/if_arp.h>
+
+#undef PACKETPTR
+#define PACKETPTR 1
+#include <linux/ppp-comp.h>
+#undef PACKETPTR
+
+/*
+ * PPP "BSD compress" compression
+ * The differences between this compression and the classic BSD LZW
+ * source are obvious from the requirement that the classic code worked
+ * with files while this handles arbitrarily long streams that
+ * are broken into packets. They are:
+ *
+ * When the code size expands, a block of junk is not emitted by
+ * the compressor and not expected by the decompressor.
+ *
+ * New codes are not necessarily assigned every time an old
+ * code is output by the compressor. This is because a packet
+ * end forces a code to be emitted, but does not imply that a
+ * new sequence has been seen.
+ *
+ * The compression ratio is checked at the first end of a packet
+ * after the appropriate gap. Besides simplifying and speeding
+ * things up, this makes it more likely that the transmitter
+ * and receiver will agree when the dictionary is cleared when
+ * compression is not going well.
+ */
+
+/*
+ * Macros to extract protocol version and number of bits
+ * from the third byte of the BSD Compress CCP configuration option.
+ */
+
+#define BSD_VERSION(x) ((x) >> 5)
+#define BSD_NBITS(x) ((x) & 0x1F)
+
+#define BSD_CURRENT_VERSION 1
+
+/*
+ * A dictionary for doing BSD compress.
+ */
+
+struct bsd_dict {
+ union { /* hash value */
+ unsigned long fcode;
+ struct {
+#ifndef BIG_ENDIAN_BITFIELD /* Little endian order */
+ unsigned short prefix; /* preceding code */
+ unsigned char suffix; /* last character of new code */
+ unsigned char pad;
+#else /* Big endian order */
+ unsigned char pad;
+ unsigned char suffix; /* last character of new code */
+ unsigned short prefix; /* preceding code */
+#endif
+ } hs;
+ } f;
+ unsigned short codem1; /* output of hash table -1 */
+ unsigned short cptr; /* map code to hash table entry */
+};
+
+struct bsd_db {
+ int totlen; /* length of this structure */
+ unsigned int hsize; /* size of the hash table */
+ unsigned char hshift; /* used in hash function */
+ unsigned char n_bits; /* current bits/code */
+ unsigned char maxbits; /* maximum bits/code */
+ unsigned char debug; /* non-zero if debug desired */
+ unsigned char unit; /* ppp unit number */
+ unsigned short seqno; /* sequence # of next packet */
+ unsigned int mru; /* size of receive (decompress) bufr */
+ unsigned int maxmaxcode; /* largest valid code */
+ unsigned int max_ent; /* largest code in use */
+ unsigned int in_count; /* uncompressed bytes, aged */
+ unsigned int bytes_out; /* compressed bytes, aged */
+ unsigned int ratio; /* recent compression ratio */
+ unsigned int checkpoint; /* when to next check the ratio */
+ unsigned int clear_count; /* times dictionary cleared */
+ unsigned int incomp_count; /* incompressible packets */
+ unsigned int incomp_bytes; /* incompressible bytes */
+ unsigned int uncomp_count; /* uncompressed packets */
+ unsigned int uncomp_bytes; /* uncompressed bytes */
+ unsigned int comp_count; /* compressed packets */
+ unsigned int comp_bytes; /* compressed bytes */
+ unsigned short *lens; /* array of lengths of codes */
+ struct bsd_dict *dict; /* dictionary */
+};
+
+#define BSD_OVHD 2 /* BSD compress overhead/packet */
+#define MIN_BSD_BITS 9
+#define BSD_INIT_BITS MIN_BSD_BITS
+#define MAX_BSD_BITS 15
+
+static void bsd_free (void *state);
+static void *bsd_alloc(unsigned char *options, int opt_len, int decomp);
+static void *bsd_comp_alloc (unsigned char *options, int opt_len);
+static void *bsd_decomp_alloc (unsigned char *options, int opt_len);
+
+static int bsd_init (void *db, unsigned char *options,
+ int opt_len, int unit, int debug, int decomp);
+static int bsd_comp_init (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int debug);
+static int bsd_decomp_init (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int mru,
+ int debug);
+
+static void bsd_reset (void *state);
+static void bsd_comp_stats (void *state, struct compstat *stats);
+
+static int bsd_compress (void *state, unsigned char *rptr,
+ unsigned char *obuf, int isize, int osize);
+static void bsd_incomp (void *state, unsigned char *ibuf, int icnt);
+
+static int bsd_decompress (void *state, unsigned char *ibuf, int isize,
+ unsigned char *obuf, int osize);
+
+/* These are in ppp.c */
+extern int ppp_register_compressor (struct compressor *cp);
+extern void ppp_unregister_compressor (struct compressor *cp);
+
+/*
+ * the next two codes should not be changed lightly, as they must not
+ * lie within the contiguous general code space.
+ */
+#define CLEAR 256 /* table clear output code */
+#define FIRST 257 /* first free entry */
+#define LAST 255
+
+#define MAXCODE(b) ((1 << (b)) - 1)
+#define BADCODEM1 MAXCODE(MAX_BSD_BITS);
+
+#define BSD_HASH(prefix,suffix,hshift) ((((unsigned long)(suffix))<<(hshift)) \
+ ^ (unsigned long)(prefix))
+#define BSD_KEY(prefix,suffix) ((((unsigned long)(suffix)) << 16) \
+ + (unsigned long)(prefix))
+
+#define CHECK_GAP 10000 /* Ratio check interval */
+
+#define RATIO_SCALE_LOG 8
+#define RATIO_SCALE (1<<RATIO_SCALE_LOG)
+#define RATIO_MAX (0x7fffffff>>RATIO_SCALE_LOG)
+
+/*
+ * clear the dictionary
+ */
+
+static void
+bsd_clear(struct bsd_db *db)
+{
+ db->clear_count++;
+ db->max_ent = FIRST-1;
+ db->n_bits = BSD_INIT_BITS;
+ db->bytes_out = 0;
+ db->in_count = 0;
+ db->incomp_count = 0;
+ db->ratio = 0;
+ db->checkpoint = CHECK_GAP;
+}
+
+/*
+ * If the dictionary is full, then see if it is time to reset it.
+ *
+ * Compute the compression ratio using fixed-point arithmetic
+ * with 8 fractional bits.
+ *
+ * Since we have an infinite stream instead of a single file,
+ * watch only the local compression ratio.
+ *
+ * Since both peers must reset the dictionary at the same time even in
+ * the absence of CLEAR codes (while packets are incompressible), they
+ * must compute the same ratio.
+ */
+
+static int bsd_check (struct bsd_db *db) /* 1=output CLEAR */
+ {
+ unsigned int new_ratio;
+
+ if (db->in_count >= db->checkpoint)
+ {
+ /* age the ratio by limiting the size of the counts */
+ if (db->in_count >= RATIO_MAX || db->bytes_out >= RATIO_MAX)
+ {
+ db->in_count -= (db->in_count >> 2);
+ db->bytes_out -= (db->bytes_out >> 2);
+ }
+
+ db->checkpoint = db->in_count + CHECK_GAP;
+
+ if (db->max_ent >= db->maxmaxcode)
+ {
+ /* Reset the dictionary only if the ratio is worse,
+ * or if it looks as if it has been poisoned
+ * by incompressible data.
+ *
+ * This does not overflow, because
+ * db->in_count <= RATIO_MAX.
+ */
+
+ new_ratio = db->in_count << RATIO_SCALE_LOG;
+ if (db->bytes_out != 0)
+ {
+ new_ratio /= db->bytes_out;
+ }
+
+ if (new_ratio < db->ratio || new_ratio < 1 * RATIO_SCALE)
+ {
+ bsd_clear (db);
+ return 1;
+ }
+ db->ratio = new_ratio;
+ }
+ }
+ return 0;
+ }
+
+/*
+ * Return statistics.
+ */
+
+static void bsd_comp_stats (void *state, struct compstat *stats)
+ {
+ struct bsd_db *db = (struct bsd_db *) state;
+
+ stats->unc_bytes = db->uncomp_bytes;
+ stats->unc_packets = db->uncomp_count;
+ stats->comp_bytes = db->comp_bytes;
+ stats->comp_packets = db->comp_count;
+ stats->inc_bytes = db->incomp_bytes;
+ stats->inc_packets = db->incomp_count;
+ stats->in_count = db->in_count;
+ stats->bytes_out = db->bytes_out;
+ }
+
+/*
+ * Reset state, as on a CCP ResetReq.
+ */
+
+static void bsd_reset (void *state)
+ {
+ struct bsd_db *db = (struct bsd_db *) state;
+
+ bsd_clear(db);
+
+ db->seqno = 0;
+ db->clear_count = 0;
+ }
+
+/*
+ * Release the compression structure
+ */
+
+static void bsd_free (void *state)
+ {
+ struct bsd_db *db = (struct bsd_db *) state;
+
+ if (db)
+ {
+/*
+ * Release the dictionary
+ */
+ if (db->dict)
+ {
+ vfree (db->dict);
+ db->dict = NULL;
+ }
+/*
+ * Release the string buffer
+ */
+ if (db->lens)
+ {
+ vfree (db->lens);
+ db->lens = NULL;
+ }
+/*
+ * Finally release the structure itself.
+ */
+ kfree (db);
+ MOD_DEC_USE_COUNT;
+ }
+ }
+
+/*
+ * Allocate space for a (de) compressor.
+ */
+
+static void *bsd_alloc (unsigned char *options, int opt_len, int decomp)
+ {
+ int bits;
+ unsigned int hsize, hshift, maxmaxcode;
+ struct bsd_db *db;
+
+ if (opt_len != 3 || options[0] != CI_BSD_COMPRESS || options[1] != 3
+ || BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
+ {
+ return NULL;
+ }
+
+ bits = BSD_NBITS(options[2]);
+
+ switch (bits)
+ {
+ case 9: /* needs 82152 for both directions */
+ case 10: /* needs 84144 */
+ case 11: /* needs 88240 */
+ case 12: /* needs 96432 */
+ hsize = 5003;
+ hshift = 4;
+ break;
+ case 13: /* needs 176784 */
+ hsize = 9001;
+ hshift = 5;
+ break;
+ case 14: /* needs 353744 */
+ hsize = 18013;
+ hshift = 6;
+ break;
+ case 15: /* needs 691440 */
+ hsize = 35023;
+ hshift = 7;
+ break;
+ case 16: /* needs 1366160--far too much, */
+ /* hsize = 69001; */ /* and 69001 is too big for cptr */
+ /* hshift = 8; */ /* in struct bsd_db */
+ /* break; */
+ default:
+ return NULL;
+ }
+/*
+ * Allocate the main control structure for this instance.
+ */
+ maxmaxcode = MAXCODE(bits);
+ db = (struct bsd_db *) kmalloc (sizeof (struct bsd_db),
+ GFP_KERNEL);
+ if (!db)
+ {
+ return NULL;
+ }
+
+ memset (db, 0, sizeof(struct bsd_db));
+/*
+ * Allocate space for the dictionary. This may be more than one page in
+ * length.
+ */
+ db->dict = (struct bsd_dict *) vmalloc (hsize *
+ sizeof (struct bsd_dict));
+ if (!db->dict)
+ {
+ bsd_free (db);
+ return NULL;
+ }
+
+ MOD_INC_USE_COUNT;
+/*
+ * If this is the compression buffer then there is no length data.
+ */
+ if (!decomp)
+ {
+ db->lens = NULL;
+ }
+/*
+ * For decompression, the length information is needed as well.
+ */
+ else
+ {
+ db->lens = (unsigned short *) vmalloc ((maxmaxcode + 1) *
+ sizeof (db->lens[0]));
+ if (!db->lens)
+ {
+ bsd_free (db);
+ return (NULL);
+ }
+ }
+/*
+ * Initialize the data information for the compression code
+ */
+ db->totlen = sizeof (struct bsd_db) +
+ (sizeof (struct bsd_dict) * hsize);
+
+ db->hsize = hsize;
+ db->hshift = hshift;
+ db->maxmaxcode = maxmaxcode;
+ db->maxbits = bits;
+
+ return (void *) db;
+ }
+
+static void *bsd_comp_alloc (unsigned char *options, int opt_len)
+ {
+ return bsd_alloc (options, opt_len, 0);
+ }
+
+static void *bsd_decomp_alloc (unsigned char *options, int opt_len)
+ {
+ return bsd_alloc (options, opt_len, 1);
+ }
+
+/*
+ * Initialize the database.
+ */
+
+static int bsd_init (void *state, unsigned char *options,
+ int opt_len, int unit, int debug, int decomp)
+ {
+ struct bsd_db *db = state;
+ int indx;
+
+ if ((opt_len != 3) || (options[0] != CI_BSD_COMPRESS) || (options[1] != 3)
+ || (BSD_VERSION(options[2]) != BSD_CURRENT_VERSION)
+ || (BSD_NBITS(options[2]) != db->maxbits)
+ || (decomp && db->lens == NULL))
+ {
+ return 0;
+ }
+
+ if (decomp)
+ {
+ indx = LAST;
+ do
+ {
+ db->lens[indx] = 1;
+ }
+ while (indx-- > 0);
+ }
+
+ indx = db->hsize;
+ while (indx-- != 0)
+ {
+ db->dict[indx].codem1 = BADCODEM1;
+ db->dict[indx].cptr = 0;
+ }
+
+ db->unit = unit;
+ db->mru = 0;
+#ifndef DEBUG
+ if (debug)
+#endif
+ db->debug = 1;
+
+ bsd_reset(db);
+
+ return 1;
+ }
+
+static int bsd_comp_init (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int debug)
+ {
+ return bsd_init (state, options, opt_len, unit, debug, 0);
+ }
+
+static int bsd_decomp_init (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int mru,
+ int debug)
+ {
+ return bsd_init (state, options, opt_len, unit, debug, 1);
+ }
+
+/*
+ * Obtain pointers to the various structures in the compression tables
+ */
+
+#define dict_ptrx(p,idx) &(p->dict[idx])
+#define lens_ptrx(p,idx) &(p->lens[idx])
+
+#ifdef DEBUG
+static unsigned short *lens_ptr(struct bsd_db *db, int idx)
+ {
+ if ((unsigned int) idx > (unsigned int) db->maxmaxcode)
+ {
+ printk ("<9>ppp: lens_ptr(%d) > max\n", idx);
+ idx = 0;
+ }
+ return lens_ptrx (db, idx);
+ }
+
+static struct bsd_dict *dict_ptr(struct bsd_db *db, int idx)
+ {
+ if ((unsigned int) idx >= (unsigned int) db->hsize)
+ {
+ printk ("<9>ppp: dict_ptr(%d) > max\n", idx);
+ idx = 0;
+ }
+ return dict_ptrx (db, idx);
+ }
+
+#else
+#define lens_ptr(db,idx) lens_ptrx(db,idx)
+#define dict_ptr(db,idx) dict_ptrx(db,idx)
+#endif
+
+/*
+ * compress a packet
+ *
+ * The result of this function is the size of the compressed
+ * packet. A zero is returned if the packet was not compressed
+ * for some reason, such as the size being larger than uncompressed.
+ *
+ * One change from the BSD compress command is that when the
+ * code size expands, we do not output a bunch of padding.
+ */
+
+static int bsd_compress (void *state, unsigned char *rptr, unsigned char *obuf,
+ int isize, int osize)
+ {
+ struct bsd_db *db;
+ int hshift;
+ unsigned int max_ent;
+ unsigned int n_bits;
+ unsigned int bitno;
+ unsigned long accm;
+ int ent;
+ unsigned long fcode;
+ struct bsd_dict *dictp;
+ unsigned char c;
+ int hval;
+ int disp;
+ int ilen;
+ int mxcode;
+ unsigned char *wptr;
+ int olen;
+
+#define PUTBYTE(v) \
+ { \
+ ++olen; \
+ if (wptr) \
+ { \
+ *wptr++ = (unsigned char) (v); \
+ if (olen >= osize) \
+ { \
+ wptr = NULL; \
+ } \
+ } \
+ }
+
+#define OUTPUT(ent) \
+ { \
+ bitno -= n_bits; \
+ accm |= ((ent) << bitno); \
+ do \
+ { \
+ PUTBYTE(accm >> 24); \
+ accm <<= 8; \
+ bitno += 8; \
+ } \
+ while (bitno <= 24); \
+ }
+
+ /*
+ * If the protocol is not in the range we're interested in,
+ * just return without compressing the packet. If it is,
+ * the protocol becomes the first byte to compress.
+ */
+
+ ent = PPP_PROTOCOL(rptr);
+ if (ent < 0x21 || ent > 0xf9)
+ {
+ return 0;
+ }
+
+ db = (struct bsd_db *) state;
+ hshift = db->hshift;
+ max_ent = db->max_ent;
+ n_bits = db->n_bits;
+ bitno = 32;
+ accm = 0;
+ mxcode = MAXCODE (n_bits);
+
+ /* Initialize the output pointers */
+ wptr = obuf;
+ olen = PPP_HDRLEN + BSD_OVHD;
+
+ if (osize > isize)
+ {
+ osize = isize;
+ }
+
+ /* This is the PPP header information */
+ if (wptr)
+ {
+ *wptr++ = PPP_ADDRESS(rptr);
+ *wptr++ = PPP_CONTROL(rptr);
+ *wptr++ = 0;
+ *wptr++ = PPP_COMP;
+ *wptr++ = db->seqno >> 8;
+ *wptr++ = db->seqno;
+ }
+
+ /* Skip the input header */
+ rptr += PPP_HDRLEN;
+ isize -= PPP_HDRLEN;
+ ilen = ++isize; /* This is off by one, but that is what is in draft! */
+
+ while (--ilen > 0)
+ {
+ c = *rptr++;
+ fcode = BSD_KEY (ent, c);
+ hval = BSD_HASH (ent, c, hshift);
+ dictp = dict_ptr (db, hval);
+
+ /* Validate and then check the entry. */
+ if (dictp->codem1 >= max_ent)
+ {
+ goto nomatch;
+ }
+
+ if (dictp->f.fcode == fcode)
+ {
+ ent = dictp->codem1 + 1;
+ continue; /* found (prefix,suffix) */
+ }
+
+ /* continue probing until a match or invalid entry */
+ disp = (hval == 0) ? 1 : hval;
+
+ do
+ {
+ hval += disp;
+ if (hval >= db->hsize)
+ {
+ hval -= db->hsize;
+ }
+ dictp = dict_ptr (db, hval);
+ if (dictp->codem1 >= max_ent)
+ {
+ goto nomatch;
+ }
+ }
+ while (dictp->f.fcode != fcode);
+
+ ent = dictp->codem1 + 1; /* finally found (prefix,suffix) */
+ continue;
+
+nomatch:
+ OUTPUT(ent); /* output the prefix */
+
+ /* code -> hashtable */
+ if (max_ent < db->maxmaxcode)
+ {
+ struct bsd_dict *dictp2;
+ struct bsd_dict *dictp3;
+ int indx;
+
+ /* expand code size if needed */
+ if (max_ent >= mxcode)
+ {
+ db->n_bits = ++n_bits;
+ mxcode = MAXCODE (n_bits);
+ }
+
+ /* Invalidate old hash table entry using
+ * this code, and then take it over.
+ */
+
+ dictp2 = dict_ptr (db, max_ent + 1);
+ indx = dictp2->cptr;
+ dictp3 = dict_ptr (db, indx);
+
+ if (dictp3->codem1 == max_ent)
+ {
+ dictp3->codem1 = BADCODEM1;
+ }
+
+ dictp2->cptr = hval;
+ dictp->codem1 = max_ent;
+ dictp->f.fcode = fcode;
+ db->max_ent = ++max_ent;
+
+ if (db->lens)
+ {
+ unsigned short *len1 = lens_ptr (db, max_ent);
+ unsigned short *len2 = lens_ptr (db, ent);
+ *len1 = *len2 + 1;
+ }
+ }
+ ent = c;
+ }
+
+ OUTPUT(ent); /* output the last code */
+
+ db->bytes_out += olen; /* Do not count bytes from here */
+ db->uncomp_bytes += isize;
+ db->in_count += isize;
+ ++db->uncomp_count;
+ ++db->seqno;
+
+ if (bitno < 32)
+ {
+ ++db->bytes_out; /* must be set before calling bsd_check */
+ }
+
+ /*
+ * Generate the clear command if needed
+ */
+
+ if (bsd_check(db))
+ {
+ OUTPUT (CLEAR);
+ }
+
+ /*
+ * Pad dribble bits of last code with ones.
+ * Do not emit a completely useless byte of ones.
+ */
+
+ if (bitno != 32)
+ {
+ PUTBYTE((accm | (0xff << (bitno-8))) >> 24);
+ }
+
+ /*
+ * Increase code size if we would have without the packet
+ * boundary because the decompressor will do so.
+ */
+
+ if (max_ent >= mxcode && max_ent < db->maxmaxcode)
+ {
+ db->n_bits++;
+ }
+
+ /* If output length is too large then this is an incomplete frame. */
+ if (wptr == NULL)
+ {
+ ++db->incomp_count;
+ db->incomp_bytes += isize;
+ olen = 0;
+ }
+ else /* Count the number of compressed frames */
+ {
+ ++db->comp_count;
+ db->comp_bytes += olen;
+ }
+
+ /* Return the resulting output length */
+ return olen;
+#undef OUTPUT
+#undef PUTBYTE
+ }
+
+/*
+ * Update the "BSD Compress" dictionary on the receiver for
+ * incompressible data by pretending to compress the incoming data.
+ */
+
+static void bsd_incomp (void *state, unsigned char *ibuf, int icnt)
+ {
+ (void) bsd_compress (state, ibuf, (char *) 0, icnt, 0);
+ }
+
+/*
+ * Decompress "BSD Compress".
+ *
+ * Because of patent problems, we return DECOMP_ERROR for errors
+ * found by inspecting the input data and for system problems, but
+ * DECOMP_FATALERROR for any errors which could possibly be said to
+ * be being detected "after" decompression. For DECOMP_ERROR,
+ * we can issue a CCP reset-request; for DECOMP_FATALERROR, we may be
+ * infringing a patent of Motorola's if we do, so we take CCP down
+ * instead.
+ *
+ * Given that the frame has the correct sequence number and a good FCS,
+ * errors such as invalid codes in the input most likely indicate a
+ * bug, so we return DECOMP_FATALERROR for them in order to turn off
+ * compression, even though they are detected by inspecting the input.
+ */
+
+static int bsd_decompress (void *state, unsigned char *ibuf, int isize,
+ unsigned char *obuf, int osize)
+ {
+ struct bsd_db *db;
+ unsigned int max_ent;
+ unsigned long accm;
+ unsigned int bitno; /* 1st valid bit in accm */
+ unsigned int n_bits;
+ unsigned int tgtbitno; /* bitno when we have a code */
+ struct bsd_dict *dictp;
+ int explen;
+ int seq;
+ unsigned int incode;
+ unsigned int oldcode;
+ unsigned int finchar;
+ unsigned char *p;
+ unsigned char *wptr;
+ int adrs;
+ int ctrl;
+ int ilen;
+ int codelen;
+ int extra;
+
+ db = (struct bsd_db *) state;
+ max_ent = db->max_ent;
+ accm = 0;
+ bitno = 32; /* 1st valid bit in accm */
+ n_bits = db->n_bits;
+ tgtbitno = 32 - n_bits; /* bitno when we have a code */
+
+ /*
+ * Save the address/control from the PPP header
+ * and then get the sequence number.
+ */
+
+ adrs = PPP_ADDRESS (ibuf);
+ ctrl = PPP_CONTROL (ibuf);
+
+ seq = (ibuf[4] << 8) + ibuf[5];
+
+ ibuf += (PPP_HDRLEN + 2);
+ ilen = isize - (PPP_HDRLEN + 2);
+
+ /*
+ * Check the sequence number and give up if it differs from
+ * the value we're expecting.
+ */
+
+ if (seq != db->seqno)
+ {
+ if (db->debug)
+ {
+ printk("bsd_decomp%d: bad sequence # %d, expected %d\n",
+ db->unit, seq, db->seqno - 1);
+ }
+ return DECOMP_ERROR;
+ }
+
+ ++db->seqno;
+ db->bytes_out += ilen;
+
+ /*
+ * Fill in the ppp header, but not the last byte of the protocol
+ * (that comes from the decompressed data).
+ */
+
+ wptr = obuf;
+ *wptr++ = adrs;
+ *wptr++ = ctrl;
+ *wptr++ = 0;
+
+ oldcode = CLEAR;
+ explen = 3;
+
+ /*
+ * Keep the checkpoint correctly so that incompressible packets
+ * clear the dictionary at the proper times.
+ */
+
+ for (;;)
+ {
+ if (ilen-- <= 0)
+ {
+ db->in_count += (explen - 3); /* don't count the header */
+ break;
+ }
+
+ /*
+ * Accumulate bytes until we have a complete code.
+ * Then get the next code, relying on the 32-bit,
+ * unsigned accm to mask the result.
+ */
+
+ bitno -= 8;
+ accm |= *ibuf++ << bitno;
+ if (tgtbitno < bitno)
+ {
+ continue;
+ }
+
+ incode = accm >> tgtbitno;
+ accm <<= n_bits;
+ bitno += n_bits;
+
+ /*
+ * The dictionary must only be cleared at the end of a packet.
+ */
+
+ if (incode == CLEAR)
+ {
+ if (ilen > 0)
+ {
+ if (db->debug)
+ {
+ printk("bsd_decomp%d: bad CLEAR\n", db->unit);
+ }
+ return DECOMP_FATALERROR; /* probably a bug */
+ }
+
+ bsd_clear(db);
+ break;
+ }
+
+ if ((incode > max_ent + 2) || (incode > db->maxmaxcode)
+ || (incode > max_ent && oldcode == CLEAR))
+ {
+ if (db->debug)
+ {
+ printk("bsd_decomp%d: bad code 0x%x oldcode=0x%x ",
+ db->unit, incode, oldcode);
+ printk("max_ent=0x%x explen=%d seqno=%d\n",
+ max_ent, explen, db->seqno);
+ }
+ return DECOMP_FATALERROR; /* probably a bug */
+ }
+
+ /* Special case for KwKwK string. */
+ if (incode > max_ent)
+ {
+ finchar = oldcode;
+ extra = 1;
+ }
+ else
+ {
+ finchar = incode;
+ extra = 0;
+ }
+
+ codelen = *(lens_ptr (db, finchar));
+ explen += codelen + extra;
+ if (explen > osize)
+ {
+ if (db->debug)
+ {
+ printk("bsd_decomp%d: ran out of mru\n", db->unit);
+#ifdef DEBUG
+ printk(" len=%d, finchar=0x%x, codelen=%d, explen=%d\n",
+ ilen, finchar, codelen, explen);
+#endif
+ }
+ return DECOMP_FATALERROR;
+ }
+
+ /*
+ * Decode this code and install it in the decompressed buffer.
+ */
+
+ wptr += codelen;
+ p = wptr;
+ while (finchar > LAST)
+ {
+ struct bsd_dict *dictp2 = dict_ptr (db, finchar);
+
+ dictp = dict_ptr (db, dictp2->cptr);
+#ifdef DEBUG
+ if (--codelen <= 0 || dictp->codem1 != finchar-1)
+ {
+ if (codelen <= 0)
+ {
+ printk("bsd_decomp%d: fell off end of chain ", db->unit);
+ printk("0x%x at 0x%x by 0x%x, max_ent=0x%x\n",
+ incode, finchar, dictp2->cptr, max_ent);
+ }
+ else
+ {
+ if (dictp->codem1 != finchar-1)
+ {
+ printk("bsd_decomp%d: bad code chain 0x%x "
+ "finchar=0x%x ",
+ db->unit, incode, finchar);
+
+ printk("oldcode=0x%x cptr=0x%x codem1=0x%x\n",
+ oldcode, dictp2->cptr, dictp->codem1);
+ }
+ }
+ return DECOMP_FATALERROR;
+ }
+#endif
+ *--p = dictp->f.hs.suffix;
+ finchar = dictp->f.hs.prefix;
+ }
+ *--p = finchar;
+
+#ifdef DEBUG
+ if (--codelen != 0)
+ {
+ printk("bsd_decomp%d: short by %d after code 0x%x, max_ent=0x%x\n",
+ db->unit, codelen, incode, max_ent);
+ }
+#endif
+
+ if (extra) /* the KwKwK case again */
+ {
+ *wptr++ = finchar;
+ }
+
+ /*
+ * If not first code in a packet, and
+ * if not out of code space, then allocate a new code.
+ *
+ * Keep the hash table correct so it can be used
+ * with uncompressed packets.
+ */
+
+ if (oldcode != CLEAR && max_ent < db->maxmaxcode)
+ {
+ struct bsd_dict *dictp2, *dictp3;
+ unsigned short *lens1, *lens2;
+ unsigned long fcode;
+ int hval, disp, indx;
+
+ fcode = BSD_KEY(oldcode,finchar);
+ hval = BSD_HASH(oldcode,finchar,db->hshift);
+ dictp = dict_ptr (db, hval);
+
+ /* look for a free hash table entry */
+ if (dictp->codem1 < max_ent)
+ {
+ disp = (hval == 0) ? 1 : hval;
+ do
+ {
+ hval += disp;
+ if (hval >= db->hsize)
+ {
+ hval -= db->hsize;
+ }
+ dictp = dict_ptr (db, hval);
+ }
+ while (dictp->codem1 < max_ent);
+ }
+
+ /*
+ * Invalidate previous hash table entry
+ * assigned this code, and then take it over
+ */
+
+ dictp2 = dict_ptr (db, max_ent + 1);
+ indx = dictp2->cptr;
+ dictp3 = dict_ptr (db, indx);
+
+ if (dictp3->codem1 == max_ent)
+ {
+ dictp3->codem1 = BADCODEM1;
+ }
+
+ dictp2->cptr = hval;
+ dictp->codem1 = max_ent;
+ dictp->f.fcode = fcode;
+ db->max_ent = ++max_ent;
+
+ /* Update the length of this string. */
+ lens1 = lens_ptr (db, max_ent);
+ lens2 = lens_ptr (db, oldcode);
+ *lens1 = *lens2 + 1;
+
+ /* Expand code size if needed. */
+ if (max_ent >= MAXCODE(n_bits) && max_ent < db->maxmaxcode)
+ {
+ db->n_bits = ++n_bits;
+ tgtbitno = 32-n_bits;
+ }
+ }
+ oldcode = incode;
+ }
+
+ ++db->comp_count;
+ ++db->uncomp_count;
+ db->comp_bytes += isize - BSD_OVHD - PPP_HDRLEN;
+ db->uncomp_bytes += explen;
+
+ if (bsd_check(db))
+ {
+ if (db->debug)
+ {
+ printk("bsd_decomp%d: peer should have cleared dictionary on %d\n",
+ db->unit, db->seqno - 1);
+ }
+ }
+ return explen;
+ }
+
+/*************************************************************
+ * Table of addresses for the BSD compression module
+ *************************************************************/
+
+static struct compressor ppp_bsd_compress = {
+ CI_BSD_COMPRESS, /* compress_proto */
+ bsd_comp_alloc, /* comp_alloc */
+ bsd_free, /* comp_free */
+ bsd_comp_init, /* comp_init */
+ bsd_reset, /* comp_reset */
+ bsd_compress, /* compress */
+ bsd_comp_stats, /* comp_stat */
+ bsd_decomp_alloc, /* decomp_alloc */
+ bsd_free, /* decomp_free */
+ bsd_decomp_init, /* decomp_init */
+ bsd_reset, /* decomp_reset */
+ bsd_decompress, /* decompress */
+ bsd_incomp, /* incomp */
+ bsd_comp_stats /* decomp_stat */
+};
+
+/*************************************************************
+ * Module support routines
+ *************************************************************/
+
+int
+init_module(void)
+{
+ int answer = ppp_register_compressor (&ppp_bsd_compress);
+ if (answer == 0)
+ printk (KERN_INFO "PPP BSD Compression module registered\n");
+ return answer;
+}
+
+void
+cleanup_module(void)
+{
+ ppp_unregister_compressor (&ppp_bsd_compress);
+}
--- /dev/null
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the INET interface module.
+ *
+ * Version: @(#)if.h 1.0.2 04/18/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1982-1988
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_H
+#define _LINUX_IF_H
+
+#include <linux/types.h> /* for "caddr_t" et al */
+#include <linux/socket.h> /* for "struct sockaddr" et al */
+
+/* Standard interface flags. */
+#define IFF_UP 0x1 /* interface is up */
+#define IFF_BROADCAST 0x2 /* broadcast address valid */
+#define IFF_DEBUG 0x4 /* turn on debugging */
+#define IFF_LOOPBACK 0x8 /* is a loopback net */
+#define IFF_POINTOPOINT 0x10 /* interface is has p-p link */
+#define IFF_NOTRAILERS 0x20 /* avoid use of trailers */
+#define IFF_RUNNING 0x40 /* resources allocated */
+#define IFF_NOARP 0x80 /* no ARP protocol */
+#define IFF_PROMISC 0x100 /* receive all packets */
+/* Not supported */
+#define IFF_ALLMULTI 0x200 /* receive all multicast packets*/
+
+#define IFF_MASTER 0x400 /* master of a load balancer */
+#define IFF_SLAVE 0x800 /* slave of a load balancer */
+
+#define IFF_MULTICAST 0x1000 /* Supports multicast */
+
+/*
+ * The ifaddr structure contains information about one address
+ * of an interface. They are maintained by the different address
+ * families, are allocated and attached when an address is set,
+ * and are linked together so all addresses for an interface can
+ * be located.
+ */
+
+struct ifaddr
+{
+ struct sockaddr ifa_addr; /* address of interface */
+ union {
+ struct sockaddr ifu_broadaddr;
+ struct sockaddr ifu_dstaddr;
+ } ifa_ifu;
+ struct iface *ifa_ifp; /* back-pointer to interface */
+ struct ifaddr *ifa_next; /* next address for interface */
+};
+
+#define ifa_broadaddr ifa_ifu.ifu_broadaddr /* broadcast address */
+#define ifa_dstaddr ifa_ifu.ifu_dstaddr /* other end of link */
+
+/*
+ * Device mapping structure. I'd just gone off and designed a
+ * beautiful scheme using only loadable modules with arguments
+ * for driver options and along come the PCMCIA people 8)
+ *
+ * Ah well. The get() side of this is good for WDSETUP, and it'll
+ * be handy for debugging things. The set side is fine for now and
+ * being very small might be worth keeping for clean configuration.
+ */
+
+struct ifmap
+{
+ unsigned long mem_start;
+ unsigned long mem_end;
+ unsigned short base_addr;
+ unsigned char irq;
+ unsigned char dma;
+ unsigned char port;
+ /* 3 bytes spare */
+};
+
+/*
+ * Interface request structure used for socket
+ * ioctl's. All interface ioctl's must have parameter
+ * definitions which begin with ifr_name. The
+ * remainder may be interface specific.
+ */
+
+struct ifreq
+{
+#define IFHWADDRLEN 6
+#define IFNAMSIZ 16
+ union
+ {
+ char ifrn_name[IFNAMSIZ]; /* if name, e.g. "en0" */
+ char ifrn_hwaddr[IFHWADDRLEN]; /* Obsolete */
+ } ifr_ifrn;
+
+ union {
+ struct sockaddr ifru_addr;
+ struct sockaddr ifru_dstaddr;
+ struct sockaddr ifru_broadaddr;
+ struct sockaddr ifru_netmask;
+ struct sockaddr ifru_hwaddr;
+ short ifru_flags;
+ int ifru_metric;
+ int ifru_mtu;
+ struct ifmap ifru_map;
+ char ifru_slave[IFNAMSIZ]; /* Just fits the size */
+ caddr_t ifru_data;
+ } ifr_ifru;
+};
+
+#define ifr_name ifr_ifrn.ifrn_name /* interface name */
+#define old_ifr_hwaddr ifr_ifrn.ifrn_hwaddr /* interface hardware */
+#define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+#define ifr_addr ifr_ifru.ifru_addr /* address */
+#define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
+#define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+#define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
+#define ifr_flags ifr_ifru.ifru_flags /* flags */
+#define ifr_metric ifr_ifru.ifru_metric /* metric */
+#define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+#define ifr_map ifr_ifru.ifru_map /* device map */
+#define ifr_slave ifr_ifru.ifru_slave /* slave device */
+#define ifr_data ifr_ifru.ifru_data /* for use by interface */
+
+/*
+ * Structure used in SIOCGIFCONF request.
+ * Used to retrieve interface configuration
+ * for machine (useful for programs which
+ * must know all networks accessible).
+ */
+
+struct ifconf
+{
+ int ifc_len; /* size of buffer */
+ union
+ {
+ caddr_t ifcu_buf;
+ struct ifreq *ifcu_req;
+ } ifc_ifcu;
+};
+#define ifc_buf ifc_ifcu.ifcu_buf /* buffer address */
+#define ifc_req ifc_ifcu.ifcu_req /* array of structures */
+
+#endif /* _LINUX_IF_H */
--- /dev/null
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the ARP (RFC 826) protocol.
+ *
+ * Version: @(#)if_arp.h 1.0.1 04/16/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
+ * Portions taken from the KA9Q/NOS (v2.00m PA0GRI) source.
+ * Ross Biro, <bir7@leland.Stanford.Edu>
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ * Florian La Roche.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_IF_ARP_H
+#define _LINUX_IF_ARP_H
+
+/* ARP protocol HARDWARE identifiers. */
+#define ARPHRD_NETROM 0 /* from KA9Q: NET/ROM pseudo */
+#define ARPHRD_ETHER 1 /* Ethernet 10Mbps */
+#define ARPHRD_EETHER 2 /* Experimental Ethernet */
+#define ARPHRD_AX25 3 /* AX.25 Level 2 */
+#define ARPHRD_PRONET 4 /* PROnet token ring */
+#define ARPHRD_CHAOS 5 /* Chaosnet */
+#define ARPHRD_IEEE802 6 /* IEEE 802.2 Ethernet/TR/TB */
+#define ARPHRD_ARCNET 7 /* ARCnet */
+#define ARPHRD_APPLETLK 8 /* APPLEtalk */
+/* Dummy types for non ARP hardware */
+#define ARPHRD_SLIP 256
+#define ARPHRD_CSLIP 257
+#define ARPHRD_SLIP6 258
+#define ARPHRD_CSLIP6 259
+#define ARPHRD_RSRVD 260 /* Notional KISS type */
+#define ARPHRD_ADAPT 264
+#define ARPHRD_PPP 512
+#define ARPHRD_TUNNEL 768 /* IPIP tunnel */
+#define ARPHRD_TUNNEL6 769 /* IPIP6 tunnel */
+#define ARPHRD_FRAD 770 /* Frame Relay */
+#define ARPHRD_SKIP 771 /* SKIP vif */
+
+/* ARP protocol opcodes. */
+#define ARPOP_REQUEST 1 /* ARP request */
+#define ARPOP_REPLY 2 /* ARP reply */
+#define ARPOP_RREQUEST 3 /* RARP request */
+#define ARPOP_RREPLY 4 /* RARP reply */
+
+
+/* ARP ioctl request. */
+struct arpreq {
+ struct sockaddr arp_pa; /* protocol address */
+ struct sockaddr arp_ha; /* hardware address */
+ int arp_flags; /* flags */
+ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
+ char arp_dev[16];
+};
+
+struct arpreq_old {
+ struct sockaddr arp_pa; /* protocol address */
+ struct sockaddr arp_ha; /* hardware address */
+ int arp_flags; /* flags */
+ struct sockaddr arp_netmask; /* netmask (only for proxy arps) */
+};
+
+/* ARP Flag values. */
+#define ATF_COM 0x02 /* completed entry (ha valid) */
+#define ATF_PERM 0x04 /* permanent entry */
+#define ATF_PUBL 0x08 /* publish entry */
+#define ATF_USETRAILERS 0x10 /* has requested trailers */
+#define ATF_NETMASK 0x20 /* want to use a netmask (only
+ for proxy entries) */
+
+/*
+ * This structure defines an ethernet arp header.
+ */
+
+struct arphdr
+{
+ unsigned short ar_hrd; /* format of hardware address */
+ unsigned short ar_pro; /* format of protocol address */
+ unsigned char ar_hln; /* length of hardware address */
+ unsigned char ar_pln; /* length of protocol address */
+ unsigned short ar_op; /* ARP opcode (command) */
+
+#if 0
+ /*
+ * Ethernet looks like this : This bit is variable sized however...
+ */
+ unsigned char ar_sha[ETH_ALEN]; /* sender hardware address */
+ unsigned char ar_sip[4]; /* sender IP address */
+ unsigned char ar_tha[ETH_ALEN]; /* target hardware address */
+ unsigned char ar_tip[4]; /* target IP address */
+#endif
+
+};
+
+#endif /* _LINUX_IF_ARP_H */
-/* $Id: if_ppp.h,v 1.3 1995/06/12 11:36:50 paulus Exp $ */
+/* $Id: if_ppp.h,v 1.4 1995/12/18 03:38:01 paulus Exp $ */
/*
* if_ppp.h - Point-to-Point Protocol definitions.
*/
/*
- * ==PPPVERSION 2.1.3==
+ * ==FILEVERSION 6==
*
* NOTE TO MAINTAINERS:
- * If you modify this file at all, increment the last number above.
- * ppp.c is shipped with a PPP distribution as well as with the kernel;
- * if everyone increases the PPPVERSION number above, then scripts
- * can do the right thing when deciding whether to install a new ppp.c
+ * If you modify this file at all, increment the number above.
+ * if_ppp.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new if_ppp.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
#ifndef _IF_PPP_H_
#define _IF_PPP_H_
+#if defined(__linux__)
+#include <linux/if.h>
+#include <linux/ioctl.h>
+#include <linux/ppp_defs.h>
+#endif
+
/*
* Packet sizes
*/
#define PPP_VERSION "2.2.0"
#define PPP_MAGIC 0x5002 /* Magic value for the ppp structure */
#define PROTO_IPX 0x002b /* protocol numbers */
+#define PROTO_DNA_RT 0x0027 /* DNA Routing */
+
/*
* Bit definitions for flags.
};
struct ifpppstatsreq {
- char ifr__name[IFNAMSIZ]; /* Name of the device */
- struct ppp_stats *stats_ptr; /* Pointer to stats buffer */
- struct ppp_stats stats; /* statistic information */
+ struct ifreq b;
+ struct ppp_stats stats; /* statistic information */
};
+struct ifpppcstatsreq {
+ struct ifreq b;
+ struct ppp_comp_stats stats;
+};
+
+#define ifr__name b.ifr_ifrn.ifrn_name
+#define stats_ptr b.ifr_ifru.ifru_data
+
/*
* Ioctl definitions.
*/
#define PPPIOCSCOMPRESS _IOW('t', 77, struct ppp_option_data)
#define PPPIOCGNPMODE _IOWR('t', 76, struct npioctl) /* get NP mode */
#define PPPIOCSNPMODE _IOW('t', 75, struct npioctl) /* set NP mode */
-
#define PPPIOCGDEBUG _IOR('t', 65, int) /* Read debug level */
#define PPPIOCSDEBUG _IOW('t', 64, int) /* Set debug level */
-#define PPPIOCGTIME _IOR('t', 63, struct ppp_ddinfo) /* Read time info */
+#define PPPIOCGIDLE _IOR('t', 63, struct ppp_idle) /* get idle time */
#define SIOCGPPPSTATS (SIOCDEVPRIVATE + 0)
-#define SIOCGPPPVER (SIOCDEVPRIVATE + 1)
+#define SIOCGPPPVER (SIOCDEVPRIVATE + 1) /* NEVER change this!! */
+#define SIOCGPPPCSTATS (SIOCDEVPRIVATE + 2)
#if !defined(ifr_mtu)
#define ifr_mtu ifr_ifru.ifru_metric
-/* $Id: if_pppvar.h,v 1.2 1995/06/12 11:36:51 paulus Exp $ */
+/* $Id: if_pppvar.h,v 1.3 1995/12/18 03:38:02 paulus Exp $ */
/*
* if_pppvar.h - private structures and declarations for PPP.
*
*/
/*
- * ==PPPVERSION 2.1.3==
+ * ==FILEVERSION 4==
*
* NOTE TO MAINTAINERS:
- * If you modify this file at all, increment the last number above.
- * ppp.c is shipped with a PPP distribution as well as with the kernel;
- * if everyone increases the PPPVERSION number above, then scripts
- * can do the right thing when deciding whether to install a new ppp.c
+ * If you modify this file at all, increment the number above.
+ * if_pppvar.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new if_pppvar.h
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
*/
* Buffers for the PPP process have the following structure
*/
-#define RBUFSIZE 2048 /* MUST be a power of 2 and be <= 4095 */
+#define RBUFSIZE 2048 /* MUST be a power of 2 and be <= 4095 */
+
struct ppp_buffer {
int size; /* Size of the buffer area */
int count; /* Count of characters in bufr */
int head; /* index to head of list */
int tail; /* index to tail of list */
- int locked; /* Buffer is being sent */
+ unsigned long locked; /* Buffer is being sent */
int type; /* Type of the buffer */
/* =0, device read buffer */
/* =1, device write buffer */
/* =2, daemon write buffer */
/* =3, daemon read buffer */
unsigned short fcs; /* Frame Check Sequence (CRC) */
+ unsigned char filler[4]; /* Extra space if needed */
};
/* Given a pointer to the ppp_buffer then return base address of buffer */
ext_accm xmit_async_map; /* 1 bit means that given control
character is quoted on output*/
- unsigned long recv_async_map; /* 1 bit means that given control
+ __u32 recv_async_map; /* 1 bit means that given control
character is ignored on input*/
int mtu; /* maximum xmit frame size */
int mru; /* maximum receive frame size */
struct ppp_buffer *s1buf; /* Pointer to daemon buffer */
struct ppp_buffer *s2buf; /* Pointer to device buffer */
- unsigned long last_xmit; /* time of last transmission */
+ __u32 last_xmit; /* time of last transmission */
/* These are pointers to the malloc()ed frame buffers.
These buffers are used while processing a packet. If a packet
struct wait_queue *read_wait; /* queue for writing processes */
/* Statistic information */
- struct pppstat stats; /* statistic information */
- struct ppp_ddinfo ddinfo; /* demand dial information */
+ struct pppstat stats; /* statistic information */
+ struct ppp_idle ddinfo; /* demand dial information */
/* PPP compression protocol information */
u_int sc_bytessent; /* count of octets sent */
--- /dev/null
+#!/bin/sh
+#
+# kinstall.sh -- install updated kernel PPP driver in Linux kernel source
+# Michael Callahan callahan@maths.ox.ac.uk 17 May 1995
+#
+# This script is complicated because we want to avoid installing a driver
+# in a kernel if it won't work in that kernel. This means two things:
+# 1) we check the version of the kernel and refuse to install if the
+# kernel is too old;
+# 2) we check that the files already in the kernel aren't more recent
+# than the one we're about to install.
+# If either 1) or 2) occurs then we exit with an error message and don't
+# touch anything.
+#
+# In addition, we have to edit the Makefile in the drivers/net
+# directory to add support for the ppp-comp compression option.
+#
+# Finally, we have to check that certain include file stubs in
+# /usr/include/net exist, or else pppd won't compile. Phew!
+
+LINUXSRC=/usr/src/linux
+
+if [ $# -gt 1 ]; then
+ echo usage: $0 [linux-source-directory]
+ exit 1
+fi
+
+if [ $# -eq 1 ]; then
+ LINUXSRC=$1
+fi
+
+#
+# Make sure we can find the kernel source
+
+LINUXMK=$LINUXSRC/Makefile
+
+if [ ! -r $LINUXMK -o ! -d $LINUXSRC/drivers ]; then
+ echo There appears to be no kernel source distribution in $LINUXSRC.
+ echo Give the top-level kernel source directory as the argument to
+ echo this script.
+ echo usage: $0 [linux-source-directory]
+ exit 1
+fi
+
+#
+# Check that the kernel source Makefile includes the
+# VERSION, PATCHLEVEL, SUBLEVEL version-numbering scheme
+# introduced in 1.0.1
+if [ `egrep '^VERSION|^PATCHLEVEL|^SUBLEVEL' $LINUXMK | wc -l` -ne 3 ]; then
+ echo You appear to have a very old kernel. You must upgrade.
+ echo It is recommended that you upgrade to the most recent 1.2.X kernel.
+ exit 1
+fi
+
+#
+# Set the VERSION, PATCHLEVEL, SUBLEVEL variables
+VERSION=`egrep '^VERSION' $LINUXMK | sed 's/[^0-9]//g'`
+PATCHLEVEL=`egrep '^PATCHLEVEL' $LINUXMK | sed 's/[^0-9]//g'`
+SUBLEVEL=`egrep '^SUBLEVEL' $LINUXMK | sed 's/[^0-9]//g'`
+
+KERNEL=$VERSION.$PATCHLEVEL.$SUBLEVEL
+
+#
+# Pass judgement on the kernel version
+if [ $VERSION -eq 1 ]; then
+ if [ $PATCHLEVEL -eq 0 -o $PATCHLEVEL -eq 1 -a $SUBLEVEL -lt 14 ]; then
+ echo You appear to be running $KERNEL. There is no support for
+ echo kernels predating 1.1.14. It is recommended that you upgrade
+ echo to the most recent 1.2.X kernel.
+ exit 1
+ fi
+ if [ $PATCHLEVEL -eq 1 ]; then
+ echo You appear to be running $KERNEL. It is recommended that you
+ echo upgrade to the most recent 1.2.X kernel.
+ echo However, installation will proceed.
+ fi
+fi
+
+echo
+echo Installing into kernel version $KERNEL in $LINUXSRC
+echo
+
+#
+# convenience function to exit if the last command failed
+
+function bombiffailed () {
+ STATUS=$?
+ if [ $STATUS -ne 0 ]; then
+ echo "=== kinstall.sh exiting with failure status $STATUS"
+ exit $STATUS
+ fi
+}
+
+#
+# convenience function to compare two files marked with ==FILEVERSION
+# version numbers; returns success if $1 is newer than $2
+
+function newer () {
+ if [ -r $1 ] && f1rev=`fgrep "==FILEVERSION " $1 | sed 's/[^0-9]//g'`; then
+ if [ -r $2 ] && f2rev=`fgrep "==FILEVERSION " $2 | sed 's/[^0-9]//g'`; then
+ if [ "$f1rev" != "" ]; then
+ # return true if f2rev is empty or f1rev => f2rev
+ [ "$f2rev" = "" ] || [ $f1rev -ge $f2rev ]
+ else
+ # f1rev is empty, so false
+ false
+ fi
+ else
+ true # no FILEVERSION in $2, so $1 is newer
+ fi
+ else
+ false # no FILEVERSION in $1, so not newer
+ fi
+}
+
+#
+# Change the USE_SKB_PROTOCOL for correct operation on 1.3.x
+function update_ppp () {
+ mv $LINUXSRC/drivers/net/ppp.c $LINUXSRC/drivers/net/ppp.c.in
+ if [ "$VERSION.$PATCHLEVEL" = "1.3" ]; then
+ sed 's/#define USE_SKB_PROTOCOL 0/#define USE_SKB_PROTOCOL 1/' <$LINUXSRC/drivers/net/ppp.c.in >$LINUXSRC/drivers/net/ppp.c
+ else
+ sed 's/#define USE_SKB_PROTOCOL 1/#define USE_SKB_PROTOCOL 0/' <$LINUXSRC/drivers/net/ppp.c.in >$LINUXSRC/drivers/net/ppp.c
+ fi
+ rm $LINUXSRC/drivers/net/ppp.c.in
+}
+
+#
+# Install the files.
+
+function installfile () {
+ BASE=`basename $1`
+ if newer $1 $BASE; then
+ echo $1 is newer than $BASE, skipping
+ return 0
+ fi
+ BACKUP=`echo $1 | sed 's/.c$/.old.c/;s/.h$/.old.h/'`
+ if [ -f $1 -a $BACKUP != $1 ]; then
+ echo Saving old $1 as `basename $BACKUP`
+ mv $1 $BACKUP
+ bombiffailed
+ fi
+ echo Installing new $1
+ cp $BASE $1
+ bombiffailed
+ touch $1
+ bombiffailed
+ if [ "$2" = "yes" ]; then
+ update_ppp
+ fi
+}
+
+if [ -f $LINUXSRC/drivers/net/ppp.h ]; then
+ echo Moving old $LINUXSRC/drivers/net/ppp.h file out of the way
+ mv $LINUXSRC/drivers/net/ppp.h $LINUXSRC/drivers/net/ppp.old.h
+ bombiffailed
+fi
+
+for FILE in $LINUXSRC/drivers/net/bsd_comp.c \
+ $LINUXSRC/include/linux/if_ppp.h \
+ $LINUXSRC/include/linux/if_pppvar.h \
+ $LINUXSRC/include/linux/ppp-comp.h \
+ $LINUXSRC/include/linux/ppp_defs.h
+ do
+ installfile $FILE no
+done
+
+installfile $LINUXSRC/drivers/net/ppp.c yes
+
+for FILE in if.h if_arp.h route.h
+ do
+ if [ ! -f $LINUXSRC/include/linux/$FILE ]; then
+ echo Installing new $1
+ cp $FILE $LINUXSRC/include/linux/$FILE
+ bombiffailed
+ touch $LINUXSRC/include/linux/$FILE
+ bombiffailed
+ fi
+done
+
+echo -n 'Adding BSD compression module to drivers makefile...'
+NETMK=$LINUXSRC/drivers/net/Makefile
+fgrep bsd_comp.o $NETMK >/dev/null
+if [ ! "$?" = "0" ]; then
+ echo -n '.'
+ rm -f $NETMK.orig $NETMK.rej
+ if [ "$VERSION.$PATCHLEVEL" = "1.2" ]; then
+ (cd $LINUXSRC; patch -p1 -f -F30 -s) <patch-1.2
+ if [ ! "$?" = "0" ]; then
+ touch $NETMK.rej
+ fi
+ else
+ if [ "$VERSION.$PATCHLEVEL" = "1.3" ]; then
+ (cd $LINUXSRC; patch -p1 -f -F30 -s) <patch-1.3
+ if [ ! "$?" = "0" ]; then
+ touch $NETMK.rej
+ fi
+ else
+ touch $NETMK.rej
+ fi
+ fi
+#
+ if [ -e $NETMK.rej ]; then
+ rm -f $NETMK.rej
+ if [ -e $NETMK.orig ]; then
+ mv $NETMK.orig $NETMK
+ fi
+ sed 's/ppp.o$/ppp.o bsd_comp.o/g' <$NETMK >$NETMK.temp
+ bombiffailed
+ echo -n '.'
+ mv $NETMK $NETMK.orig
+ bombiffailed
+ echo -n '.'
+ mv $NETMK.temp $NETMK
+ bombiffailed
+ fi
+#
+ if [ -e $NETMK.orig ]; then
+ mv $NETMK.orig $NETMK.old
+ fi
+else
+ echo -n '(already there--skipping)'
+fi
+echo
+
+#
+# install header stub files in /usr/include/net
+
+for FILE in if_ppp.h \
+ if_pppvar.h \
+ ppp-comp.h \
+ if.h \
+ if_arp.h \
+ route.h \
+ ppp_defs.h
+ do
+ if [ ! -f /usr/include/net/$FILE ]; then
+ echo Installing stub include file in /usr/include/net/$FILE
+ echo "#include <linux/$FILE>" > /usr/include/net/$FILE
+ bombiffailed
+ chown 0:0 /usr/include/net/$FILE
+ bombiffailed
+ chmod 444 /usr/include/net/$FILE
+ bombiffailed
+ touch /usr/include/net/$FILE
+ bombiffailed
+ fi
+done
+
+for FILE in ip.h \
+ tcp.h
+ do
+ if [ ! -f /usr/include/netinet/$FILE ]; then
+ echo Installing stub include file in /usr/include/netinet/$FILE
+ if [ ! -f $LINUXSRC/include/linux/$FILE ]; then
+ echo "#include \"$LINUXSRC/net/inet/$FILE\"" >/usr/include/netinet/$FILE
+ else
+ echo "#include <linux/$FILE>" > /usr/include/netinet/$FILE
+ fi
+ chown 0:0 /usr/include/netinet/$FILE
+ bombiffailed
+ chmod 444 /usr/include/netinet/$FILE
+ bombiffailed
+ touch /usr/include/netinet/$FILE
+ bombiffailed
+ fi
+done
+
+echo "Kernel driver files installation done."
+exit 0
--- /dev/null
+This file is used by the 'make kernel' function. It will apply the patch
+to the drivers/net/Makefile to install the bsd_comp.c file into the list
+of files needed to build the kernel.
+
+This file is for the 1.2 kernel.
+
+--- linux/drivers/net/Makefile.orig Sun Oct 8 17:07:23 1995
++++ linux/drivers/net/Makefile Sun Oct 8 17:10:25 1995
+@@ -85,12 +85,14 @@
+ NETDRV_OBJS := $(NETDRV_OBJS) ppp.o
+ CONFIG_SLHC = CONFIG_SLHC
+ else
+ MODULES := $(MODULES) ppp.o
+ endif
+
++MODULES := $(MODULES) bsd_comp.o
++
+ ifdef CONFIG_SLIP
+ NETDRV_OBJS := $(NETDRV_OBJS) slip.o
+ CONFIG_SLHC = CONFIG_SLHC
+ else
+ MODULES := $(MODULES) slip.o
+ endif
--- /dev/null
+This file is used by the 'make kernel' function. It will apply the patch
+to the drivers/net/Makefile to install the bsd_comp.c file into the list
+of files needed to build the kernel.
+
+This file is for the 1.3 kernel.
+
+--- linux-1.3.32.ORIG/drivers/net/Makefile Fri Sep 8 23:37:24 1995
++++ linux-1.3.32/drivers/net/Makefile Sun Sep 24 19:41:35 1995
+@@ -137,10 +137,14 @@
+ CONFIG_SLHC_MODULE = y
+ M_OBJS += ppp.o
+ endif
+ endif
+
++ifneq ($(CONFIG_PPP),n)
++ M_OBJS += bsd_comp.o
++endif
++
+ ifeq ($(CONFIG_SLIP),y)
+ L_OBJS += slip.o
+ CONFIG_SLHC_BUILTIN = y
+ else
+ ifeq ($(CONFIG_SLIP),m)
--- /dev/null
+/*
+ * ppp-comp.h - Definitions for doing PPP packet compression.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ *
+ * $Id: ppp-comp.h,v 1.1 1995/12/18 03:38:10 paulus Exp $
+ */
+
+/*
+ * ==FILEVERSION 4==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, increment the number above.
+ * ppp-comp.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new ppp-comp.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _NET_PPP_COMP_H
+#define _NET_PPP_COMP_H
+
+/*
+ * The following symbols control whether we include code for
+ * various compression methods.
+ */
+
+#ifndef DO_BSD_COMPRESS
+#define DO_BSD_COMPRESS 1 /* by default, include BSD-Compress */
+#endif
+
+#define DO_PREDICTOR_1 0
+#define DO_PREDICTOR_2 0
+#define DO_DEFLATE 0
+
+/*
+ * Structure giving methods for compression/decompression.
+ */
+
+#ifdef PACKETPTR
+struct compressor {
+ int compress_proto; /* CCP compression protocol number */
+
+ /* Allocate space for a compressor (transmit side) */
+ void *(*comp_alloc) (unsigned char *options, int opt_len);
+
+ /* Free space used by a compressor */
+ void (*comp_free) (void *state);
+
+ /* Initialize a compressor */
+ int (*comp_init) (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int debug);
+
+ /* Reset a compressor */
+ void (*comp_reset) (void *state);
+
+ /* Compress a packet */
+ int (*compress) (void *state, unsigned char *rptr,
+ unsigned char *obuf, int isize, int osize);
+
+ /* Return compression statistics */
+ void (*comp_stat) (void *state, struct compstat *stats);
+
+ /* Allocate space for a decompressor (receive side) */
+ void *(*decomp_alloc) (unsigned char *options, int opt_len);
+
+ /* Free space used by a decompressor */
+ void (*decomp_free) (void *state);
+
+ /* Initialize a decompressor */
+ int (*decomp_init) (void *state, unsigned char *options,
+ int opt_len, int unit, int opthdr, int mru,
+ int debug);
+
+ /* Reset a decompressor */
+ void (*decomp_reset) (void *state);
+
+ /* Decompress a packet. */
+ int (*decompress) (void *state, unsigned char *ibuf, int isize,
+ unsigned char *obuf, int osize);
+
+ /* Update state for an incompressible packet received */
+ void (*incomp) (void *state, unsigned char *ibuf, int icnt);
+
+ /* Return decompression statistics */
+ void (*decomp_stat) (void *state, struct compstat *stats);
+};
+#endif /* PACKETPTR */
+
+/*
+ * Return values for decompress routine.
+ * We need to make these distinctions so that we can disable certain
+ * useful functionality, namely sending a CCP reset-request as a result
+ * of an error detected after decompression. This is to avoid infringing
+ * a patent held by Motorola.
+ * Don't you just lurve software patents.
+ */
+
+#define DECOMP_OK 0 /* everything went OK */
+#define DECOMP_ERROR 1 /* error detected before decomp. */
+#define DECOMP_FATALERROR 2 /* error detected after decomp. */
+
+/*
+ * CCP codes.
+ */
+
+#define CCP_CONFREQ 1
+#define CCP_CONFACK 2
+#define CCP_TERMREQ 5
+#define CCP_TERMACK 6
+#define CCP_RESETREQ 14
+#define CCP_RESETACK 15
+
+/*
+ * Max # bytes for a CCP option
+ */
+
+#define CCP_MAX_OPTION_LENGTH 32
+
+/*
+ * Parts of a CCP packet.
+ */
+
+#define CCP_CODE(dp) ((dp)[0])
+#define CCP_ID(dp) ((dp)[1])
+#define CCP_LENGTH(dp) (((dp)[2] << 8) + (dp)[3])
+#define CCP_HDRLEN 4
+
+#define CCP_OPT_CODE(dp) ((dp)[0])
+#define CCP_OPT_LENGTH(dp) ((dp)[1])
+#define CCP_OPT_MINLEN 2
+
+/*
+ * Definitions for BSD-Compress.
+ */
+
+#define CI_BSD_COMPRESS 21 /* config. option for BSD-Compress */
+#define CILEN_BSD_COMPRESS 3 /* length of config. option */
+
+/* Macros for handling the 3rd byte of the BSD-Compress config option. */
+#define BSD_NBITS(x) ((x) & 0x1F) /* number of bits requested */
+#define BSD_VERSION(x) ((x) >> 5) /* version of option format */
+#define BSD_CURRENT_VERSION 1 /* current version number */
+#define BSD_MAKE_OPT(v, n) (((v) << 5) | (n))
+
+#define BSD_MIN_BITS 9 /* smallest code size supported */
+#define BSD_MAX_BITS 15 /* largest code size supported */
+
+/*
+ * Definitions for other, as yet unsupported, compression methods.
+ */
+
+#define CI_PREDICTOR_1 1 /* config option for Predictor-1 */
+#define CILEN_PREDICTOR_1 2 /* length of its config option */
+#define CI_PREDICTOR_2 2 /* config option for Predictor-2 */
+#define CILEN_PREDICTOR_2 2 /* length of its config option */
+
+#define CI_DEFLATE 24 /* config option for Deflate */
+#define CILEN_DEFLATE 4 /* length of its config option */
+
+#define DEFLATE_MIN_SIZE 8
+#define DEFLATE_MAX_SIZE 15
+#define DEFLATE_METHOD_VAL 8
+#define DEFLATE_SIZE(x) (((x) >> 4) + DEFLATE_MIN_SIZE)
+#define DEFLATE_METHOD(x) ((x) & 0x0F)
+#define DEFLATE_MAKE_OPT(w) ((((w) - DEFLATE_MIN_SIZE) << 4) \
+ + DEFLATE_METHOD_VAL)
+#define DEFLATE_CHK_SEQUENCE 0
+
+#endif /* _NET_PPP_COMP_H */
-/*
- * PPP for Linux
+/* PPP for Linux
+ *
+ * Michael Callahan <callahan@maths.ox.ac.uk>
+ * Al Longyear <longyear@netcom.com>
*
- * ==PPPVERSION 2.1.3==
+ * Dynamic PPP devices by Jim Freeman <jfree@caldera.com>.
+ * ppp_tty_receive ``noisy-raise-bug'' fixed by Ove Ewerlid <ewerlid@syscon.uu.se>
+ *
+ * ==FILEVERSION 8==
*
* NOTE TO MAINTAINERS:
- * If you modify this file at all, increment the last number above.
+ * If you modify this file at all, increment the number above.
* ppp.c is shipped with a PPP distribution as well as with the kernel;
- * if everyone increases the PPPVERSION number above, then scripts
+ * if everyone increases the FILEVERSION number above, then scripts
* can do the right thing when deciding whether to install a new ppp.c
* file. Don't change the format of that line otherwise, so the
* installation script can recognize it.
- *
*/
/*
OPTIMIZE_FLAG_TIME - Number of jiffies to force sending of leading flag
character. This is normally set to ((HZ * 3) / 2).
- This is 1.5 seconds. If not defined then the leading
+ This is 1.5 seconds. If zero then the leading
flag is always sent.
CHECK_CHARACTERS - Enable the checking on all received characters for
8 data bits, no parity. This adds a small amount of
processing for each received character.
-
- PPP_COMPRESS - Enable the PPP compression protocol. This protocol
- is under contention with Motorolla's patent, so use
- with caution.
NEW_SKBUFF - Use NET3.020 sk_buff's
+
+ IPX_CHANGE - Force the use of IPX support into the driver.
+ THIS IS **VERY** ALPHA LEVEL CODE!!!!
*/
/* #define NEW_SKBUFF 1 */
#define OPTIMIZE_FLAG_TIME ((HZ * 3)/2)
+
#define CHECK_CHARACTERS 1
#define PPP_COMPRESS 1
+#define USE_SKB_PROTOCOL 1 /* Set by the installation program! */
-/* $Id: ppp.c,v 1.5 1995/06/12 11:36:53 paulus Exp $
+#ifdef NEW_SKBUFF
+#undef USE_SKB_PROTOCOL
+#define USE_SKB_PROTOCOL 2
+#endif
+
+#ifndef PPP_MAX_DEV
+#define PPP_MAX_DEV 256
+#endif
+
+#undef IPX_CHANGE
+
+#if defined(IPX_CHANGE) || defined(NEW_SKBUFF)
+#define PPP_REQUESTED_HDR_LEN PPP_HARD_HDR_LEN
+#else
+#define PPP_REQUESTED_HDR_LEN 0
+#endif
+
+/* $Id: ppp.c,v 1.6 1995/12/18 03:38:12 paulus Exp $
* Added dynamic allocation of channels to eliminate
* compiled-in limits on the number of channels.
*
* released under the GNU General Public License Version 2.
*/
+#if USE_SKB_PROTOCOL == 0
+#include <linux/config.h> /* still needed for 1.2 */
+#endif
+#include <linux/module.h>
+
+#ifndef MOD_INC_USE_COUNT /* for those 1.2 kernels still out there */
+#undef MOD_DEC_USE_COUNT
+#define MOD_DEC_USE_COUNT do {} while (0)
+#define MOD_INC_USE_COUNT do {} while (0)
+#endif
+
+#include <endian.h>
#include <linux/kernel.h>
#include <linux/sched.h>
#include <linux/types.h>
#include <asm/bitops.h>
#include <asm/segment.h>
#include <net/if.h>
-#include <net/if_arp.h>
-#include <net/if_route.h>
#include <linux/if_ether.h>
#include <linux/netdevice.h>
#include <linux/skbuff.h>
#ifdef NEW_SKBUFF
#include <linux/netprotocol.h>
#else
-#define skb_data(skb) ((unsigned char *) (skb)->data)
-typedef struct sk_buff sk_buff;
+typedef struct sk_buff sk_buff;
+#define skb_data(skb) ((unsigned char *) (skb)->data)
#endif
-#include <ip.h>
-#include <tcp.h>
+#include <netinet/ip.h>
+#include <netinet/tcp.h>
#include <linux/if_arp.h>
#include "slhc.h"
-#include <net/ppp_defs.h>
+#include <linux/ppp_defs.h>
#include <linux/socket.h>
-#include <net/if_ppp.h>
-#include <net/if_pppvar.h>
-
-#ifdef MODULE
-#include <linux/module.h>
-#include <linux/version.h>
-#define STATIC static
-#else
-#define MOD_INC_USE_COUNT while(0) { }
-#define MOD_DEC_USE_COUNT while(0) { }
-#endif /* def MODULE */
+#include <linux/if_ppp.h>
+#include <linux/if_pppvar.h>
-#ifdef PPP_COMPRESS
#undef PACKETPTR
#define PACKETPTR 1
-#include <net/ppp-comp.h>
+#include <linux/ppp-comp.h>
#undef PACKETPTR
#define bsd_decompress (*ppp->sc_rcomp->decompress)
#define bsd_compress (*ppp->sc_xcomp->compress)
-#endif
#ifndef PPP_IPX
#define PPP_IPX 0x2b /* IPX protocol over PPP */
#define PPP_LQR 0xc025 /* Link Quality Reporting Protocol */
#endif
+static int ppp_register_compressor (struct compressor *cp);
+static void ppp_unregister_compressor (struct compressor *cp);
+
/*
* Local functions
*/
+static struct compressor *find_compressor (int type);
static void ppp_init_ctrl_blk (register struct ppp *);
static void ppp_kick_tty (struct ppp *, struct ppp_buffer *bfr);
static int ppp_doframe (struct ppp *);
static struct ppp *ppp_alloc (void);
-static void ppp_print_buffer (const u_char *, u_char *, int);
+static void ppp_print_buffer (const u_char *, const u_char *, int);
extern inline void ppp_stuff_char (struct ppp *ppp,
register struct ppp_buffer *buf,
register u_char chr);
extern inline int lock_buffer (register struct ppp_buffer *buf);
-static void ppp_proto_ccp (struct ppp *ppp, u_char *dp, int len, int rcvd);
static int rcv_proto_ip (struct ppp *, u_short, u_char *, int);
static int rcv_proto_ipx (struct ppp *, u_short, u_char *, int);
static int rcv_proto_vjc_comp (struct ppp *, u_short, u_char *, int);
static int rcv_proto_vjc_uncomp (struct ppp *, u_short, u_char *, int);
static int rcv_proto_unknown (struct ppp *, u_short, u_char *, int);
-static int rcv_proto_ccp (struct ppp *, u_short, u_char *, int);
static int rcv_proto_lqr (struct ppp *, u_short, u_char *, int);
static void ppp_doframe_lower (struct ppp *, u_char *, int);
static int ppp_doframe (struct ppp *);
-/*
- * List of compressors we know about.
- * We leave some space so maybe we can modload compressors.
- */
+extern int ppp_bsd_compressor_init(void);
+static void ppp_proto_ccp (struct ppp *ppp, u_char *dp, int len, int rcvd);
+static int rcv_proto_ccp (struct ppp *, u_short, u_char *, int);
+
+#define ins_char(pbuf,c) (buf_base(pbuf) [(pbuf)->count++] = (u_char)(c))
-#ifdef PPP_COMPRESS
-extern struct compressor ppp_bsd_compress;
+#ifndef OPTIMIZE_FLAG_TIME
+#define OPTIMIZE_FLAG_TIME 0
+#endif
-struct compressor *ppp_compressors[8] = {
- &ppp_bsd_compress,
- NULL
-};
-#endif /* PPP_COMPRESS */
+#ifndef PPP_MAX_DEV
+#define PPP_MAX_DEV 256
+#endif
-#define ins_char(pbuf,c) (buf_base(pbuf) [(pbuf)->count++] = (u_char)(c))
+/*
+ * Parameters which may be changed via insmod.
+ */
+
+static int flag_time = OPTIMIZE_FLAG_TIME;
+static int max_dev = PPP_MAX_DEV;
/*
* The "main" procedure to the ppp device
static int ppp_dev_xmit (sk_buff *, struct device *);
static struct enet_statistics *ppp_dev_stats (struct device *);
+#if USE_SKB_PROTOCOL == 0 /* The 1.2.x kernel is here */
+#define dev_alloc_skb(count) alloc_skb(count, GFP_ATOMIC)
+#define skb_put(skb,count) skb_data(skb)
+#define get_long_user(addr) get_user_long((void *) addr)
+#define get_int_user(addr) ((int) get_user_long((void *) addr))
+#define put_byte_user(val,addr) put_fs_byte(val,((u_char *) (addr)))
+#define put_long_user(val,addr) put_fs_long((val),((void *) (addr)))
+
+static unsigned short ppp_dev_type (sk_buff *, struct device *);
+static int ppp_dev_header (unsigned char *buff, struct device *dev,
+ unsigned short type, void *daddr, void *saddr,
+ unsigned len, struct sk_buff *skb);
+
+#else /* The 1.3.x kernel is here */
+#define get_long_user(addr) get_user(((int *) addr))
+#define get_int_user(addr) ((int) get_user(((int *) addr)))
+#define put_byte_user(val,addr) put_user((val),((u_char *) (addr)))
+#define put_long_user(val,addr) put_user((val),((int *) (addr)))
+
+static int ppp_dev_header (sk_buff *, struct device *, unsigned short,
+ void *, void *, unsigned);
+#endif
+
#ifdef NEW_SKBUFF
static int ppp_dev_input (struct protocol *self, struct protocol *lower,
sk_buff *skb, void *saddr, void *daddr);
int subid, void *saddr, void *daddr, void *opt);
static int ppp_dev_getkey(int protocol, int subid, unsigned char *key);
#else
-static int ppp_dev_header (u_char *, struct device *, unsigned short,
- void *, void *, unsigned, sk_buff *);
static int ppp_dev_rebuild (void *, struct device *, unsigned long,
sk_buff *);
-static unsigned short ppp_dev_type (sk_buff *, struct device *);
#endif
/*
static int ppp_tty_read (struct tty_struct *, struct file *, u_char *,
unsigned int);
-static int ppp_tty_write (struct tty_struct *, struct file *, u_char *,
+static int ppp_tty_write (struct tty_struct *, struct file *, const u_char *,
unsigned int);
static int ppp_tty_ioctl (struct tty_struct *, struct file *, unsigned int,
unsigned long);
static int ppp_tty_open (struct tty_struct *);
static void ppp_tty_close (struct tty_struct *);
static int ppp_tty_room (struct tty_struct *tty);
-static void ppp_tty_receive (struct tty_struct *tty, u_char * cp,
+static void ppp_tty_receive (struct tty_struct *tty, const u_char * cp,
char *fp, int count);
static void ppp_tty_wakeup (struct tty_struct *tty);
-#define PRINTK(p) printk p ;
-#define CHECK_PPP(a) if (!ppp->inuse) { PRINTK ((ppp_warning, __LINE__)) return a;}
-#define CHECK_PPP_VOID() if (!ppp->inuse) { PRINTK ((ppp_warning, __LINE__)) return;}
+#define CHECK_PPP(a) if (!ppp->inuse) { printk (ppp_warning, __LINE__); return a;}
+#define CHECK_PPP_VOID() if (!ppp->inuse) { printk (ppp_warning, __LINE__); return;}
#define in_xmap(ppp,c) (ppp->xmit_async_map[(c) >> 5] & (1 << ((c) & 0x1f)))
#define in_rmap(ppp,c) ((((unsigned int) (u_char) (c)) < 0x20) && \
#define PPP_HARD_HDR_LEN (sizeof (struct ppp_hdr))
-#if 1
typedef struct ppp_ctrl {
struct ppp_ctrl *next; /* Next structure in the list */
char name [8]; /* Name of the device */
#define ctl2dev(ctl) (struct device *) &ctl->dev
#undef PPP_NRUNIT
-#else
-
-#define PPP_NRUNIT 4
-static struct ppp ppp_ctrl[PPP_NRUNIT];
-#undef dev2ppp
-#define dev2ppp(dev) ((struct ppp *) &ppp_ctrl[dev->base_addr])
-#endif
-
/* Buffer types */
#define BUFFER_TYPE_DEV_RD 0 /* ppp read buffer */
#define BUFFER_TYPE_TTY_WR 1 /* tty write buffer */
pfn_proto func;
} ppp_proto_type;
+static
ppp_proto_type proto_list[] = {
{ PPP_IP, rcv_proto_ip },
{ PPP_IPX, rcv_proto_ipx },
{ PPP_VJC_COMP, rcv_proto_vjc_comp },
{ PPP_VJC_UNCOMP, rcv_proto_vjc_uncomp },
- { PPP_LQR, rcv_proto_lqr },
-#ifdef PPP_COMPRESS
+ { PPP_LQR, rcv_proto_lqr },
{ PPP_CCP, rcv_proto_ccp },
-#endif
{ 0, rcv_proto_unknown } /* !!! MUST BE LAST !!! */
};
-/* FCS table from RFC1331 */
+/*
+ * Values for FCS calculations.
+ */
-static unsigned short fcstab[256] =
+#define PPP_INITFCS 0xffff /* Initial FCS value */
+#define PPP_GOODFCS 0xf0b8 /* Good final FCS value */
+#define PPP_FCS(fcs, c) (((fcs) >> 8) ^ ppp_crc16_table[((fcs) ^ (c)) & 0xff])
+
+unsigned short ppp_crc16_table[256] =
{
0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
static struct tty_ldisc ppp_ldisc;
int status;
-#ifdef PPP_NRUNIT
-#define PPP_UNITS3(x) #x
-#define PPP_UNITS2(x) PPP_UNITS3(x)
-#define PPP_UNITS1(x) PPP_UNITS2(x)
-#define PPP_UNITS "(" PPP_UNITS1(PPP_NRUNIT) " devices)"
-#else
-#define PPP_UNITS "(dynamic channel allocation)"
-#endif
printk (KERN_INFO
- "PPP: version %s " PPP_UNITS
+ "PPP: version %s (dynamic channel allocation)"
#ifdef NEW_SKBUFF
" NEW_SKBUFF"
#endif
"\n", szVersion);
-#undef PPP_UNITS
-#undef PPP_UNITS1
-#undef PPP_UNITS2
-#undef PPP_UNITS3
+#ifndef MODULE /* slhc module logic has its own copyright announcment */
printk (KERN_INFO
"TCP compression code copyright 1989 Regents of the "
"University of California\n");
+#endif
-#ifndef PPP_NRUNIT
printk (KERN_INFO
"PPP Dynamic channel allocation code copyright 1995 "
"Caldera, Inc.\n");
-#endif
-
/*
* Register the protocol for the device
*/
proto_ppp.bh_input = ppp_dev_input;
proto_ppp.control_event = default_protocol_control;
proto_ppp.get_binding = ppp_dev_getkey;
- proto_ppp.header_space = 0; /* PPP_HARD_HDR_LEN; */
+ proto_ppp.header_space = PPP_REQUESTED_HDR_LEN;
protocol_register(&proto_ppp);
#endif
dev->default_protocol = &proto_ppp; /* Our protocol layer is PPP */
#else
dev->hard_header = ppp_dev_header;
+#if USE_SKB_PROTOCOL == 0
dev->type_trans = ppp_dev_type;
+#endif
dev->rebuild_header = ppp_dev_rebuild;
- dev->hard_header_len = 0; /* PPP_HARD_HDR_LEN; */
+ dev->hard_header_len = PPP_REQUESTED_HDR_LEN;
#endif
/* device INFO */
dev->pa_addr = 0;
dev->pa_brdaddr = 0;
dev->pa_mask = 0;
- dev->pa_alen = sizeof (unsigned long);
+ dev->pa_alen = 4; /* sizeof (unsigned long) */
return 0;
}
ppp->slcomp = NULL;
ppp->read_wait = NULL;
ppp->write_wait = NULL;
-
-#ifdef OPTIMIZE_FLAG_TIME /* ensure flag will always be sent first time */
- ppp->last_xmit = jiffies - OPTIMIZE_FLAG_TIME;
-#else
- ppp->last_xmit = 0;
-#endif
+ ppp->last_xmit = jiffies - flag_time;
/* clear statistics */
memset (&ppp->stats, '\0', sizeof (struct pppstat));
/* Reset the demand dial information */
- ppp->ddinfo.ip_sjiffies =
- ppp->ddinfo.ip_rjiffies =
- ppp->ddinfo.nip_sjiffies =
- ppp->ddinfo.nip_rjiffies = jiffies;
+ ppp->ddinfo.xmit_idle= /* time since last NP packet sent */
+ ppp->ddinfo.recv_idle=jiffies; /* time since last NP packet received */
-#ifdef PPP_COMPRESS
+ /* PPP compression data */
ppp->sc_xc_state =
ppp->sc_rc_state = NULL;
-#endif /* PPP_COMPRESS */
}
+static struct symbol_table ppp_syms = {
+#include <linux/symtab_begin.h>
+ X(ppp_register_compressor),
+ X(ppp_unregister_compressor),
+ X(ppp_crc16_table),
+#include <linux/symtab_end.h>
+};
+
/* called at boot/load time for each ppp device defined in the kernel */
#ifndef MODULE
if (first_time) {
first_time = 0;
answer = ppp_first_time();
+ if (answer == 0)
+ (void) register_symtab (&ppp_syms);
}
-/*
- * Un-register the devices defined at the start of the system. They will
- * be added when they are needed again. The first device just gets us into
- * this code to register the handlers.
- */
-#if 1
- unregister_netdev (dev);
-#else
- ppp_init_dev (dev);
- ppp_init_ctrl_blk (dev2ppp (dev));
- dev2ppp (dev) -> inuse = 0;
- dev2ppp (dev) -> dev = dev;
-#endif
+ if (answer == 0)
+ answer = -ENODEV;
return answer;
}
#endif
ppp->s2buf = NULL;
ppp->xbuf = NULL;
- ppp->tty->flags &= ~TTY_DO_WRITE_WAKEUP;
+ ppp->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
ppp->flags &= ~SC_XMIT_BUSY;
sti ();
* CCP is down; free (de)compressor state if necessary.
*/
-#ifdef PPP_COMPRESS
static void
ppp_ccp_closed (struct ppp *ppp)
{
- if (ppp->sc_xc_state) {
- (*ppp->sc_xcomp->comp_free) (ppp->sc_xc_state);
- ppp->sc_xc_state = NULL;
- }
+ if (ppp->sc_xc_state) {
+ (*ppp->sc_xcomp->comp_free) (ppp->sc_xc_state);
+ ppp->sc_xc_state = NULL;
+ }
- if (ppp->sc_rc_state) {
- (*ppp->sc_rcomp->decomp_free) (ppp->sc_rc_state);
- ppp->sc_rc_state = NULL;
- }
+ if (ppp->sc_rc_state) {
+ (*ppp->sc_rcomp->decomp_free) (ppp->sc_rc_state);
+ ppp->sc_rc_state = NULL;
+ }
}
-#endif /* PPP_COMPRESS */
/*
* Called to release all of the information in the current PPP structure.
tty = ppp2tty (ppp);
dev = ppp2dev (ppp);
-#ifdef PPP_COMPRESS
ppp_ccp_closed (ppp);
- ppp->sc_xc_state =
- ppp->sc_rc_state = NULL;
-#endif /* PPP_COMPRESS */
if (tty != NULL && tty->disc_data == ppp)
tty->disc_data = NULL; /* Break the tty->ppp link */
{
struct ppp *ppp = tty2ppp (tty);
- if (ppp == NULL || ppp->magic != PPP_MAGIC) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_WARNING
- "ppp: trying to close unopened tty!\n");
- } else {
- CHECK_PPP_VOID();
- if (ppp->flags & SC_DEBUG)
- printk (KERN_INFO "ppp: channel %s closing.\n",
- ppp2dev(ppp) -> name);
- ppp_release (ppp);
- MOD_DEC_USE_COUNT;
+ if (ppp != NULL) {
+ if (ppp->magic != PPP_MAGIC) {
+ if (ppp->flags & SC_DEBUG)
+ printk (KERN_WARNING
+ "ppp: trying to close unopened tty!\n");
+ } else {
+ CHECK_PPP_VOID();
+ if (ppp->flags & SC_DEBUG)
+ printk (KERN_INFO "ppp: channel %s closing.\n",
+ ppp2dev(ppp) -> name);
+ ppp_release (ppp);
+ MOD_DEC_USE_COUNT;
+ }
}
}
/*
* Allocate the structure from the system
*/
- ppp = ppp_alloc ();
+ ppp = ppp_alloc();
if (ppp == NULL) {
if (ppp->flags & SC_DEBUG)
printk (KERN_ERR
if (tty->driver.flush_buffer)
tty->driver.flush_buffer (tty);
/*
- * Allocate space for the default VJ header compression slots (16)
+ * Allocate space for the default VJ header compression slots
*/
ppp->slcomp = slhc_init (16, 16);
if (ppp->slcomp == NULL) {
*/
xbuf = ppp->xbuf;
if (xbuf != NULL) {
- tty->flags &= ~TTY_DO_WRITE_WAKEUP;
+ tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
xbuf->locked = 0;
ppp->xbuf = NULL;
/*
* transmission block.
*/
if (ppp2dev (ppp) -> flags & IFF_UP) {
- ppp2dev (ppp)->tbusy = 0;
+ if (xbuf->type == BUFFER_TYPE_DEV_WR)
+ ppp2dev (ppp)->tbusy = 0;
mark_bh (NET_BH);
- dev_tint (ppp2dev (ppp));
}
/*
* Wake up the transmission queue for all completion events.
/*
* Look at the priorities. Choose a daemon write over the device driver.
*/
+ cli();
xbuf = ppp->s1buf;
ppp->s1buf = NULL;
if (xbuf == NULL) {
xbuf = ppp->s2buf;
ppp->s2buf = NULL;
}
+ sti();
/*
* If there is a pending buffer then transmit it now.
*/
if (xbuf != NULL) {
ppp->flags &= ~SC_XMIT_BUSY;
ppp_kick_tty (ppp, xbuf);
+ return;
}
}
}
struct ppp_buffer *xbuf;
struct ppp *ppp = tty2ppp (tty);
- if (!ppp || ppp->magic != PPP_MAGIC) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG "PPP: write_wakeup called but "
- "couldn't find PPP struct.\n");
+ if (!ppp)
+ return;
+
+ if (ppp->magic != PPP_MAGIC)
return;
- }
/*
* Ensure that there is a transmission pending. Clear the re-entry flag if
* there is no pending buffer. Otherwise, send the buffer.
*/
static void
-ppp_tty_receive (struct tty_struct *tty, u_char * data, char *flags, int count)
+ppp_tty_receive (struct tty_struct *tty, const u_char * data,
+ char *flags, int count)
{
register struct ppp *ppp = tty2ppp (tty);
- register struct ppp_buffer *buf = ppp->rbuf;
+ register struct ppp_buffer *buf = NULL;
u_char chr;
+/*
+ * Fetch the pointer to the buffer. Be careful about race conditions.
+ */
+ if (ppp != NULL)
+ buf = ppp->rbuf;
+
+ if (buf == NULL)
+ return;
/*
* Verify the table pointer and ensure that the line is
* still in PPP discipline.
*/
- if (!ppp || ppp->magic != PPP_MAGIC) {
+ if (ppp->magic != PPP_MAGIC) {
if (ppp->flags & SC_DEBUG)
printk (KERN_DEBUG
"PPP: handler called but couldn't find "
* first FLAG are also tossed by this procedure.
*/
case PPP_FLAG: /* PPP_FLAG: end of frame */
- ppp->stats.ppp_ibytes = ppp->bytes_rcvd;
+ ppp->stats.ppp_ibytes += ppp->rbuf->count;
if (ppp->escape)
ppp->toss |= 0x80;
/*
static int
ppp_rcv_rx (struct ppp *ppp, unsigned short proto, u_char * data, int count)
{
- sk_buff *skb = alloc_skb (count, GFP_ATOMIC);
+ sk_buff *skb = dev_alloc_skb (count);
/*
* Generate a skb buffer for the new frame.
*/
/*
* Move the received data from the input buffer to the skb buffer.
*/
- skb->len = count; /* Store the length */
skb->dev = ppp2dev (ppp); /* We are the device */
-#ifdef NEW_SKBUF
+#if USE_SKB_PROTOCOL == 0
+ skb->len = count;
+#else
skb->protocol = proto;
+ skb->mac.raw = skb_data(skb);
#endif
- memcpy ((u_char *) skb_data(skb), data, count); /* move data */
+ memcpy (skb_put(skb,count), data, count); /* move data */
/*
* Tag the frame and kick it to the proper receive routine
*/
skb->free = 1;
- ppp->ddinfo.ip_rjiffies = jiffies;
+ ppp->ddinfo.recv_idle = jiffies;
netif_rx (skb);
return 1;
}
static int
rcv_proto_ip (struct ppp *ppp, unsigned short proto, u_char * data, int count)
{
- if (ppp2dev (ppp)->flags & IFF_UP) {
- if (count > 0)
- return ppp_rcv_rx (ppp, htons (ETH_P_IP), data, count);
- }
+ if ((ppp2dev (ppp)->flags & IFF_UP) && (count > 0))
+ return ppp_rcv_rx (ppp, htons (ETH_P_IP), data, count);
return 0;
}
static int
rcv_proto_ipx (struct ppp *ppp, unsigned short proto, u_char * data, int count)
{
-#ifdef NEW_SKBUF
- if (ppp2dev (ppp)->flags & IFF_UP) {
- if (count > 0)
- return ppp_rcv_rx (ppp, htons (ETH_P_IPX), data, count);
- } else
+#if defined(NEW_SKBUFF) || defined(IPX_CHANGE)
+ if (((ppp2dev (ppp)->flags & IFF_UP) != 0) && (count > 0))
+ return ppp_rcv_rx (ppp, htons (ETH_P_IPX), data, count);
#endif
return 0;
}
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
- "ppp: successfully queued %d bytes\n",
- len + 2);
+ "ppp: successfully queued %d bytes, flags = %x\n",
+ len + 2, ppp->flags);
- ppp->ddinfo.nip_rjiffies = jiffies;
return 1;
/*
* The buffer is full. Unlock the header
* immediate or the compressors will become confused on the peer.
*/
-#ifdef PPP_COMPRESS
static void ppp_proto_ccp (struct ppp *ppp, u_char *dp, int len, int rcvd)
{
- int slen = CCP_LENGTH(dp);
+ int slen = CCP_LENGTH(dp);
+ u_char *opt = dp + CCP_HDRLEN;
+ int opt_len = slen - CCP_HDRLEN;
+
+ if (slen > len)
+ return;
- if (slen <= len) {
- switch (CCP_CODE(dp)) {
- case CCP_CONFREQ:
- case CCP_TERMREQ:
- case CCP_TERMACK:
+ switch (CCP_CODE(dp)) {
+ case CCP_CONFREQ:
+ case CCP_TERMREQ:
+ case CCP_TERMACK:
/*
* CCP must be going down - disable compression
*/
- if (ppp->flags & SC_CCP_UP) {
- ppp->flags &= ~(SC_CCP_UP |
- SC_COMP_RUN |
- SC_DECOMP_RUN);
- }
- break;
+ if (ppp->flags & SC_CCP_UP) {
+ ppp->flags &= ~(SC_CCP_UP |
+ SC_COMP_RUN |
+ SC_DECOMP_RUN);
+ }
+ break;
- case CCP_CONFACK:
- if (ppp->flags & SC_CCP_OPEN == 0)
- break;
- if (ppp->flags & SC_CCP_UP)
- break;
- if (slen < CCP_HDRLEN + CCP_OPT_MINLEN)
- break;
- if (slen < CCP_OPT_LENGTH (dp + CCP_HDRLEN) +
- CCP_HDRLEN)
- break;
+ case CCP_CONFACK:
+ if ((ppp->flags & SC_CCP_OPEN) == 0)
+ break;
+ if (ppp->flags & SC_CCP_UP)
+ break;
+ if (slen < (CCP_HDRLEN + CCP_OPT_MINLEN))
+ break;
+ if (slen < (CCP_OPT_LENGTH (opt) + CCP_HDRLEN))
+ break;
/*
* we're agreeing to send compressed packets.
*/
- if (!rcvd) {
- if (ppp->sc_xc_state == NULL)
- break;
-
- if ((*ppp->sc_xcomp->comp_init)
- (ppp->sc_xc_state,
- dp + CCP_HDRLEN,
- slen - CCP_HDRLEN,
- ppp2dev (ppp)->base_addr,
- ppp->flags & SC_DEBUG))
- ppp->flags |= SC_COMP_RUN;
+ if (!rcvd) {
+ if (ppp->sc_xc_state == NULL)
break;
- }
+
+ if ((*ppp->sc_xcomp->comp_init)
+ (ppp->sc_xc_state,
+ opt,
+ opt_len,
+ ppp2dev (ppp)->base_addr,
+ 0,
+ ppp->flags))
+ ppp->flags |= SC_COMP_RUN;
+ break;
+ }
/*
* peer is agreeing to send compressed packets.
*/
- if (ppp->sc_rc_state == NULL)
- break;
-
- if ((*ppp->sc_rcomp->decomp_init)
- (ppp->sc_rc_state,
- dp + CCP_HDRLEN,
- slen - CCP_HDRLEN,
- ppp2dev (ppp)->base_addr,
- ppp->mru,
- ppp->flags & SC_DEBUG)) {
- ppp->flags |= SC_DECOMP_RUN;
- ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
- }
+ if (ppp->sc_rc_state == NULL)
break;
+
+ if ((*ppp->sc_rcomp->decomp_init)
+ (ppp->sc_rc_state,
+ opt,
+ opt_len,
+ ppp2dev (ppp)->base_addr,
+ 0,
+ ppp->mru,
+ ppp->flags)) {
+ ppp->flags |= SC_DECOMP_RUN;
+ ppp->flags &= ~(SC_DC_ERROR | SC_DC_FERROR);
+ }
+ break;
/*
* The protocol sequence is complete at this end
*/
- case CCP_RESETACK:
- if (ppp->flags & SC_CCP_UP == 0)
- break;
-
- if (!rcvd) {
- if (ppp->sc_xc_state &&
- (ppp->flags & SC_COMP_RUN))
- (*ppp->sc_xcomp->comp_reset)
- (ppp->sc_xc_state);
- break;
- }
+ case CCP_RESETACK:
+ if ((ppp->flags & SC_CCP_UP) == 0)
+ break;
+ if (!rcvd) {
+ if (ppp->sc_xc_state && (ppp->flags & SC_COMP_RUN))
+ (*ppp->sc_xcomp->comp_reset)(ppp->sc_xc_state);
+ } else {
if (ppp->sc_rc_state && (ppp->flags & SC_DECOMP_RUN)) {
- (*ppp->sc_rcomp->decomp_reset)
- (ppp->sc_rc_state);
+ (*ppp->sc_rcomp->decomp_reset)(ppp->sc_rc_state);
ppp->flags &= ~SC_DC_ERROR;
}
- break;
}
+ break;
}
}
ppp_proto_ccp (ppp, dp, len, 1);
return rcv_proto_unknown (ppp, proto, dp, len);
}
-#endif /* PPP_COMPRESS */
/*
* Handle a LQR packet.
static int
rcv_proto_lqr (struct ppp *ppp, unsigned short proto, u_char * data, int len)
{
+#if 0 /* until support is in the pppd process don't corrupt the reject. */
register u_char *p;
-
if (len > 8) {
if (len < 48)
memset (&data [len], '\0', 48 - len);
len = 68;
}
+#endif
/*
* Pass the frame to the pppd daemon.
*/
/* on entry, a received frame is in ppp->rbuf.bufr
check it and dispose as appropriate */
-static void ppp_doframe_lower (struct ppp *ppp, u_char *data, int len)
+static void ppp_doframe_lower (struct ppp *ppp, u_char *data, int count)
{
- u_short proto;
- int count = len;
+ u_short proto = PPP_PROTOCOL (data);
ppp_proto_type *proto_ptr;
/*
* Ignore empty frames
*/
- if (count <= 0)
+ if (count <= 4)
return;
/*
* Count the frame and print it
++ppp->stats.ppp_ipackets;
if (ppp->flags & SC_LOG_INPKT)
ppp_print_buffer ("receive frame", data, count);
-/*
- * Ignore the leading ADDRESS and CONTROL fields in the frame.
- */
- if ((data[0] == PPP_ALLSTATIONS) && (data[1] == PPP_UI)) {
- data += 2;
- count -= 2;
- }
-/*
- * Obtain the protocol from the frame
- */
- proto = (u_short) *data++;
- if (proto & 1)
- count--;
- else {
- proto = (proto << 8) | (u_short) *data++;
- count -= 2;
- }
/*
* Find the procedure to handle this protocol. The last one is marked
* as a protocol 0 which is the 'catch-all' to feed it to the pppd daemon.
/*
* Update the appropriate statistic counter.
*/
- if ((*proto_ptr->func) (ppp, proto, data, count))
- ppp->stats.ppp_ioctects += len;
+ if ((*proto_ptr->func) (ppp, proto,
+ &data[PPP_HARD_HDR_LEN],
+ count - PPP_HARD_HDR_LEN))
+ ppp->stats.ppp_ioctects += count;
else
++ppp->stats.ppp_discards;
}
{
u_char *data = buf_base (ppp->rbuf);
int count = ppp->rbuf->count;
-#ifdef PPP_COMPRESS
- int proto;
+ int addr, ctrl, proto;
int new_count;
u_char *new_data;
-#endif
/*
* If there is a pending error from the receiver then log it and discard
* the damaged frame.
return 0;
}
count -= 2; /* ignore the fcs characters */
+/*
+ * Ignore the leading ADDRESS and CONTROL fields in the frame.
+ */
+ addr = PPP_ALLSTATIONS;
+ ctrl = PPP_UI;
-#ifdef PPP_COMPRESS
- proto = PPP_PROTOCOL (data);
+ if ((data[0] == PPP_ALLSTATIONS) && (data[1] == PPP_UI)) {
+ data += 2;
+ count -= 2;
+ }
+/*
+ * Obtain the protocol from the frame
+ */
+ proto = (u_short) *data++;
+ if ((proto & 1) == 0) {
+ proto = (proto << 8) | (u_short) *data++;
+ --count;
+ }
+/*
+ * Rewrite the header with the full information. This may encroach upon
+ * the 'filler' area in the buffer header. This is the purpose for the
+ * filler.
+ */
+ *(--data) = proto;
+ *(--data) = proto >> 8;
+ *(--data) = ctrl;
+ *(--data) = addr;
+ count += 3;
/*
* Process the active decompressor.
*/
if ((ppp->sc_rc_state != (void *) 0) &&
- ((ppp->flags & SC_DECOMP_RUN) == 0)) {
+ (ppp->flags & SC_DECOMP_RUN) &&
+ ((ppp->flags & (SC_DC_FERROR | SC_DC_ERROR)) == 0)) {
+ if (proto == PPP_COMP) {
/*
* If the frame is compressed then decompress it.
*/
- if (((ppp->flags & (SC_DC_FERROR | SC_DC_ERROR)) == 0) &&
- (proto == PPP_COMP)) {
new_data = kmalloc (ppp->mru + 4, GFP_ATOMIC);
if (new_data == NULL) {
if (ppp->flags & SC_DEBUG)
count,
new_data,
ppp->mru + 4);
-
switch (new_count) {
default:
ppp_doframe_lower (ppp, new_data, new_count);
return 1;
}
/*
- * The frame is not special. Pass it through the decompressor without
- * actually decompressing the data
+ * The frame is not special. Pass it through the compressor without
+ * actually compressing the data
*/
(*ppp->sc_rcomp->incomp) (ppp->sc_rc_state,
data,
count);
}
-#endif
/*
* Process the uncompressed frame.
*/
#define GETC(c) \
{ \
- c = buf_base (ppp->ubuf) [ppp->ubuf->tail++]; \
- ppp->ubuf->tail &= ppp->ubuf->size; \
+ c = buf_base (ppp->ubuf) [ppp->ubuf->tail++]; \
+ ppp->ubuf->tail &= ppp->ubuf->size; \
}
/*
* Validate the pointer to the PPP structure
*/
- if (!ppp || ppp->magic != PPP_MAGIC) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_tty_read: cannot find ppp channel\n");
+ if (!ppp)
return -EIO;
- }
+
+ if (ppp->magic != PPP_MAGIC)
+ return -EIO;
+
CHECK_PPP (-ENXIO);
if (ppp->flags & SC_DEBUG)
printk (KERN_DEBUG
- "ppp_tty_read: called %x num %u\n",
- (unsigned int) buf,
- nr);
+ "ppp_tty_read: called buf=%p nr=%u\n",
+ buf, nr);
/*
* Acquire the read lock.
*/
for (;;) {
+ ppp = tty2ppp (tty);
+ if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse)
+ return 0;
+
if (set_bit (0, &ppp->ubuf->locked) != 0) {
if (ppp->flags & SC_DEBUG)
printk (KERN_DEBUG
"ppp_tty_read: sleeping(ubuf)\n");
current->timeout = 0;
- current->state = TASK_INTERRUPTIBLE;
+ current->state = TASK_INTERRUPTIBLE;
schedule ();
if (current->signal & ~current->blocked)
return -EINTR;
continue;
}
+/*
+ * Before we attempt to write the frame to the user, ensure that the
+ * user has access to the pages for the total buffer length.
+ */
+ indx = verify_area (VERIFY_WRITE, buf, nr);
+ if (indx != 0)
+ return (indx);
/*
* Fetch the length of the buffer from the first two bytes.
*/
/*
* Reset the time of the last read operation.
*/
- ppp->ddinfo.nip_rjiffies = jiffies;
if (ppp->flags & SC_DEBUG)
printk (KERN_DEBUG "ppp_tty_read: len = %d\n", len);
/*
ppp->stats.ppp_ierrors++;
return -EOVERFLOW;
}
+/*
+ * Before we attempt to write the frame to the user, ensure that the
+ * page tables are proper.
+ */
+ indx = verify_area (VERIFY_WRITE, buf, len + 2);
+ if (indx != 0) {
+ ppp->ubuf->tail += len;
+ ppp->ubuf->tail &= ppp->ubuf->size;
+ clear_bit (0, &ppp->ubuf->locked);
+ return (indx);
+ }
/*
* Fake the insertion of the ADDRESS and CONTROL information because these
* were not saved in the buffer.
*/
- put_fs_byte (PPP_ALLSTATIONS, buf++);
- put_fs_byte (PPP_UI, buf++);
+ put_byte_user (PPP_ALLSTATIONS, buf++);
+ put_byte_user (PPP_UI, buf++);
indx = len;
/*
*/
while (indx-- > 0) {
GETC (c);
- put_fs_byte (c, buf++);
+ put_byte_user (c, buf);
+ ++buf;
}
/*
* Release the lock and return the character count in the buffer area.
if ((buf->count < 0) || (buf->count > 3000))
printk (KERN_DEBUG "ppp_stuff_char: %x %d\n",
(unsigned int) buf->count,
- (unsigned int) buf->count);
+ (unsigned int) chr);
}
/*
* Update the FCS and if the character needs to be escaped, do it.
u_char *data, int count, int non_ip)
{
unsigned short int write_fcs;
+ int address, control;
+ int proto;
/*
* Insert the leading FLAG character
*/
buf->count = 0;
-#ifdef OPTIMIZE_FLAG_TIME
- if (non_ip)
+ if (non_ip || flag_time == 0)
ins_char (buf, PPP_FLAG);
else {
- if (jiffies - ppp->last_xmit > OPTIMIZE_FLAG_TIME)
+ if (jiffies - ppp->last_xmit > flag_time)
ins_char (buf, PPP_FLAG);
}
ppp->last_xmit = jiffies;
-#else
- ins_char (buf, PPP_FLAG);
-#endif
+ buf->fcs = PPP_INITFCS;
+/*
+ * Emit the address/control information if needed
+ */
+ address = PPP_ADDRESS (data);
+ control = PPP_CONTROL (data);
+ proto = PPP_PROTOCOL (data);
+
+ if (address != PPP_ALLSTATIONS ||
+ control != PPP_UI ||
+ (ppp->flags & SC_COMP_AC) == 0) {
+ ppp_stuff_char (ppp, buf, address);
+ ppp_stuff_char (ppp, buf, control);
+ }
+/*
+ * Emit the protocol (compressed if possible)
+ */
+ if ((ppp->flags & SC_COMP_PROT) == 0 || (proto & 0xFF00))
+ ppp_stuff_char (ppp, buf, proto >> 8);
- buf->fcs = PPP_INITFCS;
+ ppp_stuff_char (ppp, buf, proto);
/*
* Insert the data
*/
+ data += 4;
+ count -= 4;
+
while (count-- > 0)
ppp_stuff_char (ppp, buf, *data++);
/*
* 1 if frame must be re-queued for later driver support.
*/
-int
+static int
ppp_dev_xmit_frame (struct ppp *ppp, struct ppp_buffer *buf,
u_char *data, int count)
{
- int address, control;
int proto;
+ int address, control;
u_char *new_data;
int new_count;
/*
* Determine if the frame may be compressed. Attempt to compress the
* frame if possible.
*/
+ proto = PPP_PROTOCOL (data);
address = PPP_ADDRESS (data);
control = PPP_CONTROL (data);
- proto = PPP_PROTOCOL (data);
-#ifdef PPP_COMPRESS
- if ((ppp->flags & SC_COMP_RUN != 0) &&
+ if (((ppp->flags & SC_COMP_RUN) != 0) &&
(ppp->sc_xc_state != (void *) 0) &&
(address == PPP_ALLSTATIONS) &&
(control == PPP_UI) &&
if (new_count > 0) {
++ppp->stats.ppp_opackets;
- ppp->stats.ppp_ooctects += count;
+ ppp->stats.ppp_ooctects += new_count;
ppp_dev_xmit_lower (ppp, buf, new_data,
new_count, 0);
*/
kfree (new_data);
}
-#endif
/*
* The frame may not be compressed. Update the statistics before the
* count field is destroyed. The frame will be transmitted.
*/
++ppp->stats.ppp_opackets;
ppp->stats.ppp_ooctects += count;
-/*
- * Do not compress the protocol id if not possible
- */
- if (!(ppp->flags & SC_COMP_PROT) || (proto & 0xFF00)) {
- --data;
- ++count;
- }
-
- data += 3;
- count -= 3;
-/*
- * Do not compress the address/control if not possible.
- */
- if (address != PPP_ALLSTATIONS ||
- control != PPP_UI ||
- !(ppp->flags & SC_COMP_AC)) {
- *--data = control;
- *--data = address;
- count += 2;
- }
/*
* Go to the escape encoding
*/
/*
* Outbound compression frames
*/
-#ifdef PPP_COMPRESS
- case PPP_COMP:
- ppp_proto_ccp (ppp, data, len, 0);
+ case PPP_CCP:
+ ppp_proto_ccp (ppp,
+ data + PPP_HARD_HDR_LEN,
+ len - PPP_HARD_HDR_LEN,
+ 0);
break;
-#endif
-
/*
* All other frame types
*/
*/
static int
-ppp_tty_write (struct tty_struct *tty, struct file *file, u_char * data,
+ppp_tty_write (struct tty_struct *tty, struct file *file, const u_char * data,
unsigned int count)
{
struct ppp *ppp = tty2ppp (tty);
u_char *new_data;
+ int status;
/*
* Verify the pointer to the PPP data and that the tty is still in PPP mode.
*/
- if (!ppp || ppp->magic != PPP_MAGIC) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_tty_write: cannot find ppp unit\n");
+ if (!ppp)
+ return -EIO;
+
+ if (ppp->magic != PPP_MAGIC)
return -EIO;
- }
CHECK_PPP (-ENXIO);
/*
"from %u to mtu %d\n", count, PPP_MTU);
count = PPP_MTU;
}
+/*
+ * Allocate a buffer for the data and fetch it from the user space.
+ */
+ new_data = kmalloc (count, GFP_KERNEL);
+ if (new_data == NULL) {
+ if (ppp->flags & SC_DEBUG)
+ printk (KERN_ERR
+ "ppp_tty_write: no memory\n");
+ return 0;
+ }
/*
* lock this PPP unit so we will be the only writer;
* sleep if necessary
if (ppp->flags & SC_DEBUG)
printk (KERN_DEBUG "ppp_tty_write: sleeping\n");
interruptible_sleep_on (&ppp->write_wait);
- if (current->signal & ~current->blocked)
+
+ ppp = tty2ppp (tty);
+ if (!ppp || ppp->magic != PPP_MAGIC || !ppp->inuse) {
+ kfree (new_data);
+ return 0;
+ }
+
+ if (current->signal & ~current->blocked) {
+ kfree (new_data);
return -EINTR;
+ }
}
/*
- * Allocate a buffer for the data and fetch it from the user space.
+ * Ensure that the caller's buffer is valid.
*/
- new_data = kmalloc (count, GFP_ATOMIC);
- if (new_data == NULL) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_tty_write: no memory\n");
+ status = verify_area (VERIFY_READ, data, count);
+ if (status != 0) {
+ kfree (new_data);
ppp->tbuf->locked = 0;
- return 0;
+ return status;
}
memcpy_fromfs (new_data, data, count);
* Process the BSD compression IOCTL event for the tty device.
*/
-#ifdef PPP_COMPRESS
static int
ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp)
{
+ struct compressor *cp;
+ struct ppp_option_data data;
int error;
int nb;
+ u_char *ptr;
u_char ccp_option[CCP_MAX_OPTION_LENGTH];
- struct compressor **cp;
/*
- * Validate the range of the ioctl
+ * Fetch the compression parameters
*/
- error = verify_area (VERIFY_READ, odp,
- (unsigned long) (&((struct ppp_option_data *) 0)->length)
- + sizeof (odp->length));
-
+ error = verify_area (VERIFY_READ, odp, sizeof (data));
if (error == 0) {
- nb = (int) get_fs_long (odp->length);
- if ((unsigned long) nb-1 >= (unsigned long) CCP_MAX_OPTION_LENGTH)
+ memcpy_fromfs (&data, odp, sizeof (data));
+ nb = data.length;
+ ptr = data.ptr;
+ if ((unsigned long) nb >= (unsigned long)CCP_MAX_OPTION_LENGTH)
nb = CCP_MAX_OPTION_LENGTH;
-
- error = verify_area (VERIFY_READ, odp, nb);
+
+ error = verify_area (VERIFY_READ, ptr, nb);
}
if (error != 0)
return error;
- memcpy_fromfs (ccp_option, odp, nb);
+ memcpy_fromfs (ccp_option, ptr, nb);
+
if (ccp_option[1] < 2) /* preliminary check on the length byte */
return (-EINVAL);
- for (cp = ppp_compressors; *cp != NULL; ++cp)
- if ((*cp)->compress_proto == ccp_option[0]) {
+ cp = find_compressor ((int) (unsigned) (unsigned char) ccp_option[0]);
+ if (cp != (struct compressor *) 0) {
/*
* Found a handler for the protocol - try to allocate
* a compressor or decompressor.
*/
- error = 0;
- if (odp->transmit) {
- if (ppp->sc_xc_state != NULL)
- (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);
-
- ppp->sc_xcomp = *cp;
- ppp->sc_xc_state = (*cp)->comp_alloc(ccp_option, nb);
-
- if (ppp->sc_xc_state == NULL) {
- if (ppp->flags & SC_DEBUG)
- printk("ppp%ld: comp_alloc failed\n",
- ppp2dev (ppp)->base_addr);
- error = -ENOBUFS;
- }
- ppp->flags &= ~SC_COMP_RUN;
- } else {
- if (ppp->sc_rc_state != NULL)
- (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);
- ppp->sc_rcomp = *cp;
- ppp->sc_rc_state = (*cp)->decomp_alloc(ccp_option, nb);
- if (ppp->sc_rc_state == NULL) {
- if (ppp->flags & SC_DEBUG)
- printk("ppp%ld: decomp_alloc failed\n",
- ppp2dev (ppp)->base_addr);
- error = ENOBUFS;
- }
- ppp->flags &= ~SC_DECOMP_RUN;
+ error = 0;
+ if (data.transmit) {
+ if (ppp->sc_xc_state != NULL)
+ (*ppp->sc_xcomp->comp_free)(ppp->sc_xc_state);
+
+ ppp->sc_xcomp = cp;
+ ppp->sc_xc_state = cp->comp_alloc(ccp_option, nb);
+
+ if (ppp->sc_xc_state == NULL) {
+ if (ppp->flags & SC_DEBUG)
+ printk("ppp%ld: comp_alloc failed\n",
+ ppp2dev (ppp)->base_addr);
+ error = -ENOBUFS;
}
- return (error);
+ ppp->flags &= ~SC_COMP_RUN;
+ } else {
+ if (ppp->sc_rc_state != NULL)
+ (*ppp->sc_rcomp->decomp_free)(ppp->sc_rc_state);
+ ppp->sc_rcomp = cp;
+ ppp->sc_rc_state = cp->decomp_alloc(ccp_option, nb);
+ if (ppp->sc_rc_state == NULL) {
+ if (ppp->flags & SC_DEBUG)
+ printk("ppp%ld: decomp_alloc failed\n",
+ ppp2dev (ppp)->base_addr);
+ error = ENOBUFS;
+ }
+ ppp->flags &= ~SC_DECOMP_RUN;
}
+ return (error);
+ }
if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG "ppp%ld: no compressor for [%x %x %x], %x\n",
- ppp2dev (ppp)->base_addr, ccp_option[0], ccp_option[1],
- ccp_option[2], nb);
+ printk(KERN_DEBUG "ppp%ld: no compressor for [%x %x %x], %x\n",
+ ppp2dev (ppp)->base_addr, ccp_option[0], ccp_option[1],
+ ccp_option[2], nb);
return (-EINVAL); /* no handler found */
}
-#endif /* PPP_COMPRESS */
/*
* Process the IOCTL event for the tty device.
/*
* Verify the status of the PPP device.
*/
- if (!ppp || ppp->magic != PPP_MAGIC) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_tty_ioctl: can't find PPP block from tty!\n");
+ if (!ppp)
return -EBADF;
- }
+
+ if (ppp->magic != PPP_MAGIC)
+ return -EBADF;
+
CHECK_PPP (-ENXIO);
/*
* The user must have an euid of root to do these requests.
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- temp_i = (int) get_fs_long (param3);
+ temp_i = get_int_user ((int *) param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: set mru to %x\n", temp_i);
temp_i |= SC_RCV_B7_1 | SC_RCV_B7_0 |
SC_RCV_ODDP | SC_RCV_EVNP;
#endif
- put_fs_long ((long) temp_i, param3);
+ put_long_user ((long) temp_i, param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_DEBUG
"ppp_tty_ioctl: get flags: addr %lx flags "
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- temp_i = (int) get_fs_long (param3) & SC_MASK;
+ temp_i = get_int_user (param3) & SC_MASK;
temp_i |= (ppp->flags & ~SC_MASK);
-#ifdef PPP_COMPRESS
+
if ((ppp->flags & SC_CCP_OPEN) &&
(temp_i & SC_CCP_OPEN) == 0)
ppp_ccp_closed (ppp);
-#else
- temp_i &= ~SC_CCP_OPEN;
-#endif
+
if ((ppp->flags | temp_i) & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: set flags to %x\n", temp_i);
/*
* Set the compression mode
*/
-#ifdef PPP_COMPRESS
case PPPIOCSCOMPRESS:
error = ppp_set_compression (ppp,
(struct ppp_option_data *) param3);
break;
-#endif
/*
* Retrieve the transmit async map
*/
error = verify_area (VERIFY_WRITE, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- put_fs_long (ppp->xmit_async_map[0], param3);
+ put_long_user (ppp->xmit_async_map[0], param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
- "ppp_tty_ioctl: get asyncmap: addr "
- "%lx asyncmap %lx\n",
- param3, ppp->xmit_async_map[0]);
+ "ppp_tty_ioctl: get asyncmap: addr "
+ "%lx asyncmap %lx\n",
+ param3,
+ (unsigned long) ppp->xmit_async_map[0]);
}
break;
/*
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- ppp->xmit_async_map[0] = get_fs_long (param3);
+ ppp->xmit_async_map[0] = get_long_user (param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: set xmit asyncmap %lx\n",
- ppp->xmit_async_map[0]);
+ (unsigned long) ppp->xmit_async_map[0]);
}
break;
/*
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- ppp->recv_async_map = get_fs_long (param3);
+ ppp->recv_async_map = get_long_user (param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: set rcv asyncmap %lx\n",
- ppp->recv_async_map);
+ (unsigned long) ppp->recv_async_map);
}
break;
/*
error = verify_area (VERIFY_WRITE, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- put_fs_long (ppp2dev (ppp)->base_addr, param3);
+ put_long_user (ppp2dev (ppp)->base_addr, param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: get unit: %ld",
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- temp_i = (int) (get_fs_long (param3) & 0x1F) << 16;
+ temp_i = (get_int_user (param3) & 0x1F) << 16;
temp_i |= (ppp->flags & ~0x1F0000);
if ((ppp->flags | temp_i) & SC_DEBUG)
sizeof (temp_i));
if (error == 0) {
temp_i = (ppp->flags >> 16) & 0x1F;
- put_fs_long ((long) temp_i, param3);
+ put_long_user ((long) temp_i, param3);
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
/*
* Get the times since the last send/receive frame operation
*/
- case PPPIOCGTIME:
+ case PPPIOCGIDLE:
error = verify_area (VERIFY_WRITE, (void *) param3,
- sizeof (struct ppp_ddinfo));
+ sizeof (struct ppp_idle));
if (error == 0) {
- struct ppp_ddinfo cur_ddinfo;
+ struct ppp_idle cur_ddinfo;
unsigned long cur_jiffies = jiffies;
/* change absolute times to relative times. */
- cur_ddinfo.ip_sjiffies = cur_jiffies - ppp->ddinfo.ip_sjiffies;
- cur_ddinfo.ip_rjiffies = cur_jiffies - ppp->ddinfo.ip_rjiffies;
- cur_ddinfo.nip_sjiffies = cur_jiffies - ppp->ddinfo.nip_sjiffies;
- cur_ddinfo.nip_rjiffies = cur_jiffies - ppp->ddinfo.nip_rjiffies;
-
+ cur_ddinfo.xmit_idle = (cur_jiffies - ppp->ddinfo.xmit_idle) / HZ;
+ cur_ddinfo.recv_idle = (cur_jiffies - ppp->ddinfo.recv_idle) / HZ;
memcpy_tofs ((void *) param3, &cur_ddinfo,
- sizeof (struct ppp_ddinfo));
+ sizeof (cur_ddinfo));
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: read demand dial info\n");
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (ppp->xmit_async_map));
if (error == 0) {
- unsigned long temp_tbl[8];
+ __u32 temp_tbl[8];
memcpy_fromfs (temp_tbl, (void *) param3,
sizeof (ppp->xmit_async_map));
error = verify_area (VERIFY_READ, (void *) param3,
sizeof (temp_i));
if (error == 0) {
- temp_i = (int) get_fs_long (param3) + 1;
+ temp_i = get_int_user (param3) + 1;
if (ppp->flags & SC_DEBUG)
printk (KERN_INFO
"ppp_tty_ioctl: set maxcid to %d\n",
/*
* Verify the status of the PPP device.
*/
- if (!ppp || ppp->magic != PPP_MAGIC) {
- if (ppp->flags & SC_DEBUG)
- printk (KERN_ERR
- "ppp_tty_select: can't find PPP block from tty!\n");
+ if (!ppp)
return -EBADF;
- }
+
+ if (ppp->magic != PPP_MAGIC)
+ return -EBADF;
+
CHECK_PPP (0);
/*
* Branch on the type of select mode. A read request must lock the user
*/
static int
-ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr)
+ppp_dev_ioctl_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev)
{
struct ppp_stats *result, temp;
int error;
* Supply the information for the caller. First move the version data
* then move the ppp stats; and finally the vj stats.
*/
- if (error == 0) {
- memset (&temp, 0, sizeof(temp));
+ memset (&temp, 0, sizeof(temp));
+ if (error == 0 && dev->flags & IFF_UP) {
memcpy (&temp.p, &ppp->stats, sizeof (struct pppstat));
-/*
- * Header Compression statistics
- */
if (ppp->slcomp != NULL) {
- temp.vj.vjs_packets = ppp->slcomp->sls_o_nontcp +
- ppp->slcomp->sls_o_tcp;
+ temp.vj.vjs_packets = ppp->slcomp->sls_o_compressed+
+ ppp->slcomp->sls_o_uncompressed;
temp.vj.vjs_compressed = ppp->slcomp->sls_o_compressed;
temp.vj.vjs_searches = ppp->slcomp->sls_o_searches;
temp.vj.vjs_misses = ppp->slcomp->sls_o_misses;
temp.vj.vjs_uncompressedin = ppp->slcomp->sls_i_uncompressed;
temp.vj.vjs_compressedin = ppp->slcomp->sls_i_compressed;
}
+ }
+/*
+ * Move the data to the caller's buffer
+ */
+ if (error == 0)
+ memcpy_tofs (result, &temp, sizeof (temp));
+ return error;
+}
+
+/*
+ * IOCTL to read the compression statistics for the pppstats program.
+ */
+
+static int
+ppp_dev_ioctl_comp_stats (struct ppp *ppp, struct ifreq *ifr, struct device *dev)
+{
+ struct ppp_comp_stats *result, temp;
+ int error;
+/*
+ * Must have write access to the buffer.
+ */
+ result = (struct ppp_comp_stats *) ifr->ifr_ifru.ifru_data;
+ error = verify_area (VERIFY_WRITE,
+ result,
+ sizeof (temp));
/*
- * Frame data compression statistics
+ * Supply the information for the caller.
*/
-#ifdef PPP_COMPRESS
+ memset (&temp, 0, sizeof(temp));
+ if (error == 0 && dev->flags & IFF_UP) {
if (ppp->sc_xc_state != NULL)
(*ppp->sc_xcomp->comp_stat) (ppp->sc_xc_state,
&temp.c);
if (ppp->sc_rc_state != NULL)
(*ppp->sc_rcomp->decomp_stat) (ppp->sc_rc_state,
&temp.d);
-#endif /* PPP_COMPRESS */
-
+ }
/*
* Move the data to the caller's buffer
*/
+ if (error == 0)
memcpy_tofs (result, &temp, sizeof (temp));
- }
return error;
}
*/
switch (cmd) {
case SIOCGPPPSTATS:
- error = ppp_dev_ioctl_stats (ppp, ifr);
+ error = ppp_dev_ioctl_stats (ppp, ifr, dev);
+ break;
+
+ case SIOCGPPPCSTATS:
+ error = ppp_dev_ioctl_comp_stats (ppp, ifr, dev);
break;
case SIOCGPPPVER:
* 1 if frame must be re-queued for later driver support.
*/
-int
+#if defined(IPX_CHANGE)
+#define ppp_dev_xmit_ip1 ppp_dev_xmit_ip
+#endif
+
+static int
ppp_dev_xmit_ip1 (struct device *dev, struct ppp *ppp, u_char *data)
{
int proto = PPP_IP;
len = slhc_compress (ppp->slcomp, data, len,
buf_base (ppp->cbuf) + PPP_HARD_HDR_LEN,
&data,
- !(ppp->flags & SC_NO_TCP_CCID));
+ (ppp->flags & SC_NO_TCP_CCID) == 0);
if (data[0] & SL_TYPE_COMPRESSED_TCP) {
proto = PPP_VJC_COMP;
* by this name.
*/
-int
+#if !defined(IPX_CHANGE)
+static int
ppp_dev_xmit_ip (struct device *dev, struct ppp *ppp, u_char *data)
{
- struct ppp_hdr *hdr;
+ struct ppp_hdr *hdr;
int len;
int answer;
return answer;
}
+#endif /* !defined(IPX_CHANGE) */
/*
* Send an IPX (or any other non-IP) frame to the remote.
* 1 if frame must be re-queued for later driver support.
*/
-int
+#if defined(IPX_CHANGE)
+#define ppp_dev_xmit_ipx1 ppp_dev_xmit_ipx
+#endif
+
+#if defined(NEW_SKBUFF) || defined(IPX_CHANGE)
+static int
ppp_dev_xmit_ipx1 (struct device *dev, struct ppp *ppp,
u_char *data, int len, int proto)
{
* by this name.
*/
-int
+#if !defined(IPX_CHANGE)
+static int
ppp_dev_xmit_ipx (struct device *dev, struct ppp *ppp,
u_char *data, int len, int proto)
{
answer = 1;
else {
memcpy (&hdr[1], data, len);
- answer = (dev, ppp, (u_char *) &hdr[1], len, proto);
+ answer = ppp_dev_xmit_ipx1 (dev, ppp, (u_char *) &hdr[1],
+ len, proto);
kfree (hdr);
}
return answer;
}
+#endif /* !defined(IPX_CHANGE) */
+#endif /* defined(NEW_SKBUFF) || defined(IPX_CHANGE) */
/*
* Send a frame to the remote.
*/
-int
+static int
ppp_dev_xmit (sk_buff *skb, struct device *dev)
{
- int answer;
+ int answer, len;
u_char *data;
struct ppp *ppp = dev2ppp (dev);
struct tty_struct *tty = ppp2tty (ppp);
* Validate the tty linkage
*/
if (ppp->flags & SC_DEBUG)
- printk (KERN_DEBUG "ppp_dev_xmit [%s]: skb %X\n",
- dev->name, (int) skb);
+ printk (KERN_DEBUG "ppp_dev_xmit [%s]: skb %p\n",
+ dev->name, skb);
/*
* Validate the tty interface
*/
/*
* Fetch the pointer to the data
*/
- data = skb_data (skb);
+ len = skb->len;
+ data = skb_data(skb);
/*
* Look at the protocol in the skb to determine the difference between
* an IP frame and an IPX frame.
*/
-#ifdef NEW_SKBUFF
- switch (skb->protocol) {
- case htons (ETH_P_IPX):
- answer = ppp_dev_xmit_ipx (dev, ppp, data, skb->len, PPP_IPX);
+#if defined(NEW_SKBUFF) || defined(IPX_CHANGE)
+ switch (ntohs (skb->protocol)) {
+ case ETH_P_IPX:
+ answer = ppp_dev_xmit_ipx (dev, ppp, data, len, PPP_IPX);
break;
- case htons (ETH_P_IP):
+ case ETH_P_IP:
answer = ppp_dev_xmit_ip (dev, ppp, data);
break;
default: /* All others have no support at this time. */
+#if 1 /* I **REALLY** want to toss this. For the time being, I'll assume
+ that this is IP. However, if you start to see the message below
+ then you should fix the skb->protocol to have the proper values. */
+
+ printk (KERN_ERR
+ "ppp: strange protocol type %x in ppp_dev_xmit\n",
+ skb->protocol);
+ answer = ppp_dev_xmit_ip (dev, ppp, data);
+ break;
+#else /* Shortly, this is what it will be! */
dev_kfree_skb (skb, FREE_WRITE);
return 0;
+#endif /* if 1 */
}
-#else
+#else /* defined(NEW_SKBUFF) || defined(IPX_CHANGE) */
answer = ppp_dev_xmit_ip (dev, ppp, data);
#endif
/*
* This is the end of the transmission. Release the buffer if it was sent.
*/
- if (answer == 0)
+ if (answer == 0) {
dev_kfree_skb (skb, FREE_WRITE);
+ ppp->ddinfo.xmit_idle = jiffies;
+ }
return answer;
}
return &ppp_stats;
}
-#ifdef NEW_SKBUFF
+#if defined(NEW_SKBUFF)
/*
- * The PPP protocol is currently pure IP (no IPX yet). This defines
- * the protocol layer which is blank since the driver does all the
- * cooking.
+ * This defines the protocol layer which is blank since the
+ * driver does all the cooking.
*/
static int ppp_dev_input (struct protocol *self, struct protocol *lower,
#else
+#if USE_SKB_PROTOCOL == 0
/*
* Called to enquire about the type of the frame in the buffer. Return
* ETH_P_IP for an IP frame, ETH_P_IPX for an IPX frame.
{
return (htons (ETH_P_IP));
}
+#endif
-static int
-ppp_dev_header (u_char * buff, struct device *dev, unsigned short type,
- void *daddr, void *saddr, unsigned len, sk_buff *skb)
+#if USE_SKB_PROTOCOL == 0
+static int ppp_dev_header (unsigned char *buff, struct device *dev,
+ unsigned short type, void *daddr, void *saddr,
+ unsigned len, struct sk_buff *skb)
+#else
+static int ppp_dev_header (sk_buff *skb, struct device *dev,
+ unsigned short type, void *daddr,
+ void *saddr, unsigned len)
+#endif
{
return (0);
}
static struct ppp *
ppp_alloc (void)
{
-#if 1
int if_num;
int status;
ppp_ctrl_t *ctl;
if (!set_bit(0, &ppp->inuse))
return (ppp);
ctl = ctl->next;
- if (++if_num == INT_MAX)
+ if (++if_num == max_dev)
return (NULL);
}
/*
status = register_netdev (dev);
if (status == 0) {
- printk ("registered device %s\n", dev->name);
+ printk (KERN_INFO "registered device %s\n", dev->name);
return (ppp);
}
/* This one will forever be busy as it is not initialized */
}
return (NULL);
-#else
- int i;
- for (i = 0; i < PPP_NRUNIT; i++)
- if (!set_bit(0, &ppp_ctrl[i].inuse)) return &ppp_ctrl[i];
-
- return NULL;
-#endif
}
/*
*/
static void
-ppp_print_hex (register u_char * out, u_char * in, int count)
+ppp_print_hex (register u_char * out, const u_char * in, int count)
{
register u_char next_ch;
static char hex[] = "0123456789ABCDEF";
}
static void
-ppp_print_char (register u_char * out, u_char * in, int count)
+ppp_print_char (register u_char * out, const u_char * in, int count)
{
register u_char next_ch;
}
static void
-ppp_print_buffer (const u_char * name, u_char * buf, int count)
+ppp_print_buffer (const u_char * name, const u_char * buf, int count)
{
u_char line[44];
}
}
+/*************************************************************
+ * Compressor module interface
+ *************************************************************/
+
+struct compressor_link {
+ struct compressor_link *next;
+ struct compressor *comp;
+};
+
+static struct compressor_link *ppp_compressors = (struct compressor_link *) 0;
+
+static struct compressor *find_compressor (int type)
+{
+ struct compressor_link *lnk;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ lnk = ppp_compressors;
+ while (lnk != (struct compressor_link *) 0) {
+ if ((int) (unsigned char) lnk->comp->compress_proto == type) {
+ restore_flags(flags);
+ return lnk->comp;
+ }
+ lnk = lnk->next;
+ }
+
+ restore_flags(flags);
+ return (struct compressor *) 0;
+}
+
+static int ppp_register_compressor (struct compressor *cp)
+{
+ struct compressor_link *new;
+ unsigned long flags;
+
+ new = (struct compressor_link *) kmalloc (sizeof (struct compressor_link), GFP_KERNEL);
+
+ if (new == (struct compressor_link *) 0)
+ return 1;
+
+ save_flags(flags);
+ cli();
+
+ if (find_compressor (cp->compress_proto)) {
+ restore_flags(flags);
+ kfree (new);
+ return 0;
+ }
+
+ new->next = ppp_compressors;
+ new->comp = cp;
+ ppp_compressors = new;
+
+ restore_flags(flags);
+ return 0;
+}
+
+static void ppp_unregister_compressor (struct compressor *cp)
+{
+ struct compressor_link *prev = (struct compressor_link *) 0;
+ struct compressor_link *lnk;
+ unsigned long flags;
+
+ save_flags(flags);
+ cli();
+
+ lnk = ppp_compressors;
+ while (lnk != (struct compressor_link *) 0) {
+ if (lnk->comp == cp) {
+ if (prev)
+ prev->next = lnk->next;
+ else
+ ppp_compressors = lnk->next;
+ kfree (lnk);
+ break;
+ }
+ prev = lnk;
+ lnk = lnk->next;
+ }
+ restore_flags(flags);
+}
+
/*************************************************************
* Module support routines
*************************************************************/
#ifdef MODULE
-char kernel_version[] = UTS_RELEASE;
-
int
init_module(void)
{
/* register our line disciplines */
status = ppp_first_time();
- if (status != 0) {
+ if (status != 0)
printk (KERN_INFO
"PPP: ppp_init() failure %d\n", status);
- }
+ else
+ (void) register_symtab (&ppp_syms);
return (status);
}
ppp_ctrl_t *ctl, *next_ctl;
struct device *dev;
struct ppp *ppp;
- int busy_flag = MOD_IN_USE;
+ int busy_flag = 0;
/*
* Ensure that the devices are not in operation.
*/
- if (!busy_flag) {
- ctl = ppp_list;
- while (ctl) {
- ppp = ctl2ppp (ctl);
- if (ppp->inuse && ppp->tty != NULL) {
- busy_flag = 1;
- break;
- }
+ ctl = ppp_list;
+ while (ctl) {
+ ppp = ctl2ppp (ctl);
+ if (ppp->inuse && ppp->tty != NULL) {
+ busy_flag = 1;
+ break;
+ }
- dev = ctl2dev (ctl);
- if (dev->start || dev->flags & IFF_UP) {
- busy_flag = 1;
- break;
- }
- ctl = ctl->next;
+ dev = ctl2dev (ctl);
+ if (dev->start || dev->flags & IFF_UP) {
+ busy_flag = 1;
+ break;
}
+ ctl = ctl->next;
}
+/*
+ * Ensure that there are no compressor modules registered
+ */
+ if (ppp_compressors != NULL)
+ busy_flag = 1;
if (busy_flag) {
printk (KERN_INFO
"(err = %d)\n", status);
else
printk (KERN_INFO
- "PPP: ppp line discipline successfully unregistered\n");
+ "PPP: ppp line discipline successfully unregistered\n");
/*
* De-register the devices so that there is no problem with them
*/
- next = ppp_list;
- while (next) {
- ctl = next;
- ppp = ctl2ppp (ctl);
- dev = ctl2dev (ctl);
-
- ppp_release (ppp);
+ next_ctl = ppp_list;
+ while (next_ctl) {
+ ctl = next_ctl;
+ next_ctl = ctl->next;
+ ppp = ctl2ppp (ctl);
+ dev = ctl2dev (ctl);
+
+ ppp_release (ppp);
unregister_netdev (dev);
-/*
- * Release the storage occupied by the control structures
- */
- next = ctl->next;
kfree (ctl);
}
}
--- /dev/null
+/* $Id: ppp_defs.h,v 1.1 1995/12/18 03:38:15 paulus Exp $ */
+
+/*
+ * ppp_defs.h - PPP definitions.
+ *
+ * Copyright (c) 1994 The Australian National University.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software and its
+ * documentation is hereby granted, provided that the above copyright
+ * notice appears in all copies. This software is provided without any
+ * warranty, express or implied. The Australian National University
+ * makes no representations about the suitability of this software for
+ * any purpose.
+ *
+ * IN NO EVENT SHALL THE AUSTRALIAN NATIONAL UNIVERSITY BE LIABLE TO ANY
+ * PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+ * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
+ * THE AUSTRALIAN NATIONAL UNIVERSITY HAVE BEEN ADVISED OF THE POSSIBILITY
+ * OF SUCH DAMAGE.
+ *
+ * THE AUSTRALIAN NATIONAL UNIVERSITY SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+ * ON AN "AS IS" BASIS, AND THE AUSTRALIAN NATIONAL UNIVERSITY HAS NO
+ * OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
+ * OR MODIFICATIONS.
+ */
+
+/*
+ * ==FILEVERSION 6==
+ *
+ * NOTE TO MAINTAINERS:
+ * If you modify this file at all, increment the number above.
+ * ppp_defs.h is shipped with a PPP distribution as well as with the kernel;
+ * if everyone increases the FILEVERSION number above, then scripts
+ * can do the right thing when deciding whether to install a new ppp_defs.h
+ * file. Don't change the format of that line otherwise, so the
+ * installation script can recognize it.
+ */
+
+#ifndef _PPP_DEFS_H_
+#define _PPP_DEFS_H_
+
+/*
+ * The basic PPP frame.
+ */
+#define PPP_HDRLEN 4 /* octets for standard ppp header */
+#define PPP_FCSLEN 2 /* octets for FCS */
+#define PPP_MRU 1500 /* default MRU = max length of info field */
+
+#define PPP_ADDRESS(p) (((u_char *)(p))[0])
+#define PPP_CONTROL(p) (((u_char *)(p))[1])
+#define PPP_PROTOCOL(p) ((((u_char *)(p))[2] << 8) + ((u_char *)(p))[3])
+
+/*
+ * Significant octet values.
+ */
+#define PPP_ALLSTATIONS 0xff /* All-Stations broadcast address */
+#define PPP_UI 0x03 /* Unnumbered Information */
+#define PPP_FLAG 0x7e /* Flag Sequence */
+#define PPP_ESCAPE 0x7d /* Asynchronous Control Escape */
+#define PPP_TRANS 0x20 /* Asynchronous transparency modifier */
+
+/*
+ * Protocol field values.
+ */
+#define PPP_IP 0x21 /* Internet Protocol */
+#define PPP_IPX 0x2b /* IPX protocol */
+#define PPP_VJC_COMP 0x2d /* VJ compressed TCP */
+#define PPP_VJC_UNCOMP 0x2f /* VJ uncompressed TCP */
+#define PPP_COMP 0xfd /* compressed packet */
+#define PPP_IPCP 0x8021 /* IP Control Protocol */
+#define PPP_IPXCP 0x802b /* IPX Control Protocol */
+#define PPP_CCP 0x80fd /* Compression Control Protocol */
+#define PPP_LCP 0xc021 /* Link Control Protocol */
+#define PPP_PAP 0xc023 /* Password Authentication Protocol */
+#define PPP_LQR 0xc025 /* Link Quality Report protocol */
+#define PPP_CHAP 0xc223 /* Cryptographic Handshake Auth. Protocol */
+
+/*
+ * A 32-bit unsigned integral type.
+ */
+#ifndef __BIT_TYPES_DEFINED__
+#ifdef UINT32_T
+typedef UINT32_T u_int32_t;
+#else
+typedef unsigned int u_int32_t;
+#endif
+#endif
+
+/*
+ * Extended asyncmap - allows any character to be escaped.
+ */
+typedef u_int32_t ext_accm[8];
+
+/*
+ * What to do with network protocol (NP) packets.
+ */
+enum NPmode {
+ NPMODE_PASS, /* pass the packet through */
+ NPMODE_DROP, /* silently drop the packet */
+ NPMODE_ERROR, /* return an error */
+ NPMODE_QUEUE /* save it up for later. */
+};
+
+/*
+ * Statistics for LQRP and pppstats
+ */
+struct pppstat {
+ u_int ppp_discards; /* # frames discarded */
+
+ u_int ppp_ibytes; /* bytes received */
+ u_int ppp_ioctects; /* bytes received not in error */
+ u_int ppp_ipackets; /* packets received */
+ u_int ppp_ierrors; /* receive errors */
+ u_int ppp_ilqrs; /* # LQR frames received */
+
+ u_int ppp_obytes; /* raw bytes sent */
+ u_int ppp_ooctects; /* frame bytes sent */
+ u_int ppp_opackets; /* packets sent */
+ u_int ppp_oerrors; /* transmit errors */
+ u_int ppp_olqrs; /* # LQR frames sent */
+};
+
+struct vjstat {
+ u_int vjs_packets; /* outbound packets */
+ u_int vjs_compressed; /* outbound compressed packets */
+ u_int vjs_searches; /* searches for connection state */
+ u_int vjs_misses; /* times couldn't find conn. state */
+ u_int vjs_uncompressedin; /* inbound uncompressed packets */
+ u_int vjs_compressedin; /* inbound compressed packets */
+ u_int vjs_errorin; /* inbound unknown type packets */
+ u_int vjs_tossed; /* inbound packets tossed because of error */
+};
+
+struct compstat {
+ u_int unc_bytes; /* total uncompressed bytes */
+ u_int unc_packets; /* total uncompressed packets */
+ u_int comp_bytes; /* compressed bytes */
+ u_int comp_packets; /* compressed packets */
+ u_int inc_bytes; /* incompressible bytes */
+ u_int inc_packets; /* incompressible packets */
+ /* the compression ratio is defined as in_count / bytes_out */
+ u_int in_count; /* Bytes received */
+ u_int bytes_out; /* Bytes transmitted */
+ double ratio; /* not computed in kernel. */
+};
+
+struct ppp_stats {
+ struct pppstat p; /* basic PPP statistics */
+ struct vjstat vj; /* VJ header compression statistics */
+};
+
+struct ppp_comp_stats {
+ struct compstat c; /* packet compression statistics */
+ struct compstat d; /* packet decompression statistics */
+};
+
+/*
+ * The following structure records the time in seconds since
+ * the last NP packet was sent or received.
+ */
+struct ppp_idle {
+ time_t xmit_idle; /* time since last NP packet sent */
+ time_t recv_idle; /* time since last NP packet received */
+};
+
+#ifndef __P
+#ifdef __STDC__
+#define __P(x) x
+#else
+#define __P(x) ()
+#endif
+#endif
+
+#endif /* _PPP_DEFS_H_ */
--- /dev/null
+/*
+ * INET An implementation of the TCP/IP protocol suite for the LINUX
+ * operating system. INET is implemented using the BSD Socket
+ * interface as the means of communication with the user level.
+ *
+ * Global definitions for the IP router interface.
+ *
+ * Version: @(#)route.h 1.0.3 05/27/93
+ *
+ * Authors: Original taken from Berkeley UNIX 4.3, (c) UCB 1986-1988
+ * for the purposes of compatibility only.
+ *
+ * Fred N. van Kempen, <waltje@uWalt.NL.Mugnet.ORG>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+#ifndef _LINUX_ROUTE_H
+#define _LINUX_ROUTE_H
+
+#include <linux/if.h>
+
+
+/* This structure gets passed by the SIOCADDRT and SIOCDELRT calls. */
+struct rtentry
+{
+ unsigned long rt_hash; /* hash key for lookups */
+ struct sockaddr rt_dst; /* target address */
+ struct sockaddr rt_gateway; /* gateway addr (RTF_GATEWAY) */
+ struct sockaddr rt_genmask; /* target network mask (IP) */
+ short rt_flags;
+ short rt_refcnt;
+ unsigned long rt_use;
+ struct ifnet *rt_ifp;
+ short rt_metric; /* +1 for binary compatibility! */
+ char *rt_dev; /* forcing the device at add */
+ unsigned long rt_mss; /* per route MTU/Window */
+ unsigned long rt_window; /* Window clamping */
+ unsigned short rt_irtt; /* Initial RTT */
+};
+
+
+#define RTF_UP 0x0001 /* route usable */
+#define RTF_GATEWAY 0x0002 /* destination is a gateway */
+#define RTF_HOST 0x0004 /* host entry (net otherwise) */
+#define RTF_REINSTATE 0x0008 /* reinstate route after tmout */
+#define RTF_DYNAMIC 0x0010 /* created dyn. (by redirect) */
+#define RTF_MODIFIED 0x0020 /* modified dyn. (by redirect) */
+#define RTF_MSS 0x0040 /* specific MSS for this route */
+#define RTF_WINDOW 0x0080 /* per route window clamping */
+#define RTF_IRTT 0x0100 /* Initial round trip time */
+#define RTF_REJECT 0x0200 /* Reject route */
+
+/*
+ * This structure is passed from the kernel to user space by netlink
+ * routing/device announcements
+ */
+
+struct netlink_rtinfo
+{
+ unsigned long rtmsg_type;
+ struct sockaddr rtmsg_dst;
+ struct sockaddr rtmsg_gateway;
+ struct sockaddr rtmsg_genmask;
+ short rtmsg_flags;
+ short rtmsg_metric;
+ char rtmsg_device[16];
+};
+
+#define RTMSG_NEWROUTE 0x01
+#define RTMSG_DELROUTE 0x02
+#define RTMSG_NEWDEVICE 0x11
+#define RTMSG_DELDEVICE 0x12
+
+#endif /* _LINUX_ROUTE_H */
+
#
# pppd makefile for Linux
-# $Id: Makefile.linux,v 1.9 1995/12/11 02:55:25 paulus Exp $
+# $Id: Makefile.linux,v 1.10 1995/12/18 03:32:57 paulus Exp $
#
PPPDSRCS = main.c magic.c fsm.c lcp.c ipcp.c upap.c chap.c md5.c ccp.c \
- auth.c options.c sys-linux.c
+ auth.c options.c sys-linux.c ipxcp.c
HEADERS = callout.h pathnames.h patchlevel.h chap.h md5.h
MANPAGES = pppd.8
PPPDOBJS = main.o magic.o fsm.o lcp.o ipcp.o upap.o chap.o md5.o ccp.o \
- auth.o options.o sys-linux.o
+ auth.o options.o sys-linux.o ipxcp.o
all: pppd
# CC = gcc
# DEBUG_FLAGS = -DDEBUGALL
-COMPILE_FLAGS = -D_linux_=1 -DHAVE_PATHS_H
+COMPILE_FLAGS = -D_linux_=1 -DHAVE_PATHS_H # -DUSE_MS_DNS=1 # -DIPX_CHANGE=1
COPTS = -g # -O2
VER = 0.2.8
LIBS = -lbsd
-CFLAGS = $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
+CFLAGS= $(COPTS) $(DEBUG_FLAGS) $(COMPILE_FLAGS)
SOURCE= RELNOTES Makefile.linux $(PPPDSRCS) $(HEADERS) $(MANPAGES)
install: pppd
--- /dev/null
+/*
+ * ipxcp.c - PPP IPX Control Protocol.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifdef IPX_CHANGE
+#ifndef lint
+static char rcsid[] = "$Id: ipxcp.c,v 1.1 1995/12/18 03:32:59 paulus Exp $";
+#endif
+
+/*
+ * TODO:
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+
+#include "pppd.h"
+#include "fsm.h"
+#include "ipxcp.h"
+#include "pathnames.h"
+
+/* global vars */
+ipxcp_options ipxcp_wantoptions[NUM_PPP]; /* Options that we want to request */
+ipxcp_options ipxcp_gotoptions[NUM_PPP]; /* Options that peer ack'd */
+ipxcp_options ipxcp_allowoptions[NUM_PPP]; /* Options we allow peer to request */
+ipxcp_options ipxcp_hisoptions[NUM_PPP]; /* Options that we ack'd */
+
+#define wo (&ipxcp_wantoptions[0])
+#define ao (&ipxcp_allowoptions[0])
+#define go (&ipxcp_gotoptions[0])
+#define ho (&ipxcp_hisoptions[0])
+
+/*
+ * Callbacks for fsm code. (CI = Configuration Information)
+ */
+static void ipxcp_resetci __P((fsm *)); /* Reset our CI */
+static int ipxcp_cilen __P((fsm *)); /* Return length of our CI */
+static void ipxcp_addci __P((fsm *, u_char *, int *)); /* Add our CI */
+static int ipxcp_ackci __P((fsm *, u_char *, int)); /* Peer ack'd our CI */
+static int ipxcp_nakci __P((fsm *, u_char *, int)); /* Peer nak'd our CI */
+static int ipxcp_rejci __P((fsm *, u_char *, int)); /* Peer rej'd our CI */
+static int ipxcp_reqci __P((fsm *, u_char *, int *, int)); /* Rcv CI */
+static void ipxcp_up __P((fsm *)); /* We're UP */
+static void ipxcp_down __P((fsm *)); /* We're DOWN */
+static void ipxcp_script __P((fsm *, char *)); /* Run an up/down script */
+
+fsm ipxcp_fsm[NUM_PPP]; /* IPXCP fsm structure */
+
+static fsm_callbacks ipxcp_callbacks = { /* IPXCP callback routines */
+ ipxcp_resetci, /* Reset our Configuration Information */
+ ipxcp_cilen, /* Length of our Configuration Information */
+ ipxcp_addci, /* Add our Configuration Information */
+ ipxcp_ackci, /* ACK our Configuration Information */
+ ipxcp_nakci, /* NAK our Configuration Information */
+ ipxcp_rejci, /* Reject our Configuration Information */
+ ipxcp_reqci, /* Request peer's Configuration Information */
+ ipxcp_up, /* Called when fsm reaches OPENED state */
+ ipxcp_down, /* Called when fsm leaves OPENED state */
+ NULL, /* Called when we want the lower layer up */
+ NULL, /* Called when we want the lower layer down */
+ NULL, /* Called when Protocol-Reject received */
+ NULL, /* Retransmission is necessary */
+ NULL, /* Called to handle protocol-specific codes */
+ "IPXCP" /* String name of protocol */
+};
+
+struct protent ipxcp_protent = {
+ PPP_IPXCP, ipxcp_init, ipxcp_input, ipxcp_protrej,
+ ipxcp_lowerup, ipxcp_lowerdown, ipxcp_open, ipxcp_close,
+ ipxcp_printpkt, NULL, 0, "IPXCP"
+};
+
+
+/*
+ * Lengths of configuration options.
+ */
+
+#define CILEN_VOID 2
+#define CILEN_COMPLETE 2 /* length of complete option */
+#define CILEN_NETN 6 /* network number length option */
+#define CILEN_NODEN 8 /* node number length option */
+#define CILEN_PROTOCOL 4 /* Minimum length of routing protocol */
+#define CILEN_NAME 3 /* Minimum length of router name */
+#define CILEN_COMPRESS 4 /* Minimum length of compression protocol */
+
+#define CODENAME(x) ((x) == CONFACK ? "ACK" : \
+ (x) == CONFNAK ? "NAK" : "REJ")
+
+/* Used in printing the node number */
+#define NODE(base) base[0], base[1], base[2], base[3], base[4], base[5]
+
+/* Used to generate the proper bit mask */
+#define BIT(num) (1 << (num))
+
+/*
+ * Make a string representation of a network IP address.
+ */
+
+char *
+ipx_ntoa(ipxaddr)
+u_int32_t ipxaddr;
+{
+ static char b[64];
+ sprintf(b, "%lx", ipxaddr);
+ return b;
+}
+
+
+/*
+ * ipxcp_init - Initialize IPXCP.
+ */
+void
+ipxcp_init(unit)
+ int unit;
+{
+ fsm *f = &ipxcp_fsm[unit];
+
+ f->unit = unit;
+ f->protocol = PPP_IPXCP;
+ f->callbacks = &ipxcp_callbacks;
+ fsm_init(&ipxcp_fsm[unit]);
+
+ memset (wo->name, 0, sizeof (wo->name));
+ memset (wo->our_node, 0, sizeof (wo->our_node));
+ memset (wo->his_node, 0, sizeof (wo->his_node));
+
+ wo->neg_nn = 1;
+ wo->neg_complete = 1;
+ wo->network = 0;
+
+ ao->neg_node = 1;
+ ao->neg_nn = 1;
+ ao->neg_name = 1;
+ ao->neg_complete = 1;
+ ao->neg_router = 1;
+
+ ao->accept_local = 0;
+ ao->accept_remote = 0;
+ ao->accept_network = 0;
+}
+
+/*
+ * Copy the node number
+ */
+
+static void
+copy_node (src, dst)
+u_char *src, *dst;
+{
+ memcpy (dst, src, sizeof (ipxcp_wantoptions[0].our_node));
+}
+
+/*
+ * Compare node numbers
+ */
+
+static int
+compare_node (src, dst)
+u_char *src, *dst;
+{
+ return memcmp (dst, src, sizeof (ipxcp_wantoptions[0].our_node)) == 0;
+}
+
+/*
+ * Is the node number zero?
+ */
+
+static int
+zero_node (node)
+u_char *node;
+{
+ int indx;
+ for (indx = 0; indx < sizeof (ipxcp_wantoptions[0].our_node); ++indx)
+ if (node [indx] != 0)
+ return 0;
+ return 1;
+}
+
+/*
+ * Increment the node number
+ */
+
+static void
+inc_node (node)
+u_char *node;
+{
+ u_char *outp;
+ u_int32_t magic_num;
+
+ outp = node;
+ magic_num = magic();
+ *outp++ = '\0';
+ *outp++ = '\0';
+ PUTLONG (magic_num, outp);
+}
+
+/*
+ * ipxcp_open - IPXCP is allowed to come up.
+ */
+void
+ipxcp_open(unit)
+ int unit;
+{
+ fsm_open(&ipxcp_fsm[unit]);
+}
+
+/*
+ * ipxcp_close - Take IPXCP down.
+ */
+void
+ipxcp_close(unit, reason)
+ int unit;
+ char *reason;
+{
+ fsm_close(&ipxcp_fsm[unit], reason);
+}
+
+
+/*
+ * ipxcp_lowerup - The lower layer is up.
+ */
+void
+ipxcp_lowerup(unit)
+ int unit;
+{
+ extern int ipx_enabled;
+
+ fsm_lowerup(&ipxcp_fsm[unit], ipx_enabled);
+}
+
+
+/*
+ * ipxcp_lowerdown - The lower layer is down.
+ */
+void
+ipxcp_lowerdown(unit)
+ int unit;
+{
+ fsm_lowerdown(&ipxcp_fsm[unit]);
+}
+
+
+/*
+ * ipxcp_input - Input IPXCP packet.
+ */
+void
+ipxcp_input(unit, p, len)
+ int unit;
+ u_char *p;
+ int len;
+{
+ fsm_input(&ipxcp_fsm[unit], p, len);
+}
+
+
+/*
+ * ipxcp_protrej - A Protocol-Reject was received for IPXCP.
+ *
+ * Pretend the lower layer went down, so we shut up.
+ */
+void
+ipxcp_protrej(unit)
+ int unit;
+{
+ fsm_lowerdown(&ipxcp_fsm[unit]);
+}
+
+
+/*
+ * ipxcp_resetci - Reset our CI.
+ */
+static void
+ipxcp_resetci(f)
+ fsm *f;
+{
+ u_int32_t network;
+ int unit = f->unit;
+
+ wo->req_node = wo->neg_node && ao->neg_node;
+ wo->req_nn = wo->neg_nn && ao->neg_nn;
+
+ if (wo->our_network == 0) {
+ wo->neg_node = 1;
+ ao->accept_network = 1;
+ }
+/*
+ * If our node number is zero then change it.
+ */
+ if (zero_node (wo->our_node)) {
+ inc_node (wo->our_node);
+ ao->accept_local = 1;
+ wo->neg_node = 1;
+ }
+/*
+ * If his node number is zero then change it.
+ */
+ if (zero_node (wo->his_node)) {
+ inc_node (wo->his_node);
+ ao->accept_remote = 1;
+ }
+/*
+ * Unless router protocol is suppressed then assume that we can do RIP.
+ */
+ if (! (wo->router & BIT(0)))
+ wo->router |= BIT(2);
+/*
+ * Router protocol is only negotiated if requested. Others force the
+ * negotiation.
+ */
+ if (wo->router & (BIT(2) | BIT(4)))
+ wo->neg_router = 1;
+/*
+ * Start with these default values
+ */
+ *go = *wo;
+}
+
+/*
+ * ipxcp_cilen - Return length of our CI.
+ */
+static int
+ipxcp_cilen(f)
+ fsm *f;
+{
+ int unit = f->unit;
+ int len;
+
+ len = go->neg_nn ? CILEN_NETN : 0;
+ len += go->neg_node ? CILEN_NODEN : 0;
+ len += go->neg_name ? CILEN_NAME + strlen (go->name) - 1 : 0;
+ len += go->neg_complete ? CILEN_COMPLETE : 0;
+/*
+ * Router protocol 0 is mutually exclusive with the others.
+ */
+ if (go->neg_router) {
+ if (go->router & BIT(0))
+ len += CILEN_PROTOCOL;
+ else {
+ if (go->router & BIT(2))
+ len += CILEN_PROTOCOL;
+ if (go->router & BIT(4))
+ len += CILEN_PROTOCOL;
+ }
+ }
+
+ return (len);
+}
+
+
+/*
+ * ipxcp_addci - Add our desired CIs to a packet.
+ */
+static void
+ipxcp_addci(f, ucp, lenp)
+ fsm *f;
+ u_char *ucp;
+ int *lenp;
+{
+ int len = *lenp;
+ int unit = f->unit;
+/*
+ * Add the options to the record.
+ */
+ if (go->neg_nn) {
+ PUTCHAR (IPX_NETWORK_NUMBER, ucp);
+ PUTCHAR (CILEN_NETN, ucp);
+ PUTLONG (go->our_network, ucp);
+ }
+
+ if (go->neg_node) {
+ int indx;
+ PUTCHAR (IPX_NODE_NUMBER, ucp);
+ PUTCHAR (CILEN_NODEN, ucp);
+ for (indx = 0; indx < sizeof (go->our_node); ++indx)
+ PUTCHAR (go->our_node[indx], ucp);
+ }
+
+ if (go->neg_name) {
+ int cilen = strlen (go->name);
+ int indx;
+ PUTCHAR (IPX_ROUTER_NAME, ucp);
+ PUTCHAR (CILEN_NAME + cilen - 1, ucp);
+ for (indx = 0; indx < cilen; ++indx)
+ PUTCHAR (go->name [indx], ucp);
+ }
+
+ if (go->neg_router && (go->router & (BIT(0) | BIT(2) | BIT(4)))) {
+ if (go->router & BIT(0)) {
+ PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
+ PUTCHAR (CILEN_PROTOCOL, ucp);
+ PUTSHORT (0, ucp);
+ } else {
+ if (go->router & BIT(2)) {
+ PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
+ PUTCHAR (CILEN_PROTOCOL, ucp);
+ PUTSHORT (2, ucp);
+ }
+
+ if (go->router & BIT(4)) {
+ PUTCHAR (IPX_ROUTER_PROTOCOL, ucp);
+ PUTCHAR (CILEN_PROTOCOL, ucp);
+ PUTSHORT (4, ucp);
+ }
+ }
+ }
+
+ if (go->neg_complete) {
+ PUTCHAR (IPX_COMPLETE, ucp);
+ PUTCHAR (CILEN_COMPLETE, ucp);
+ }
+}
+
+/*
+ * ipxcp_ackci - Ack our CIs.
+ *
+ * Returns:
+ * 0 - Ack was bad.
+ * 1 - Ack was good.
+ */
+static int
+ipxcp_ackci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ int unit = f->unit;
+ u_short cilen, citype, cishort;
+ u_char cichar;
+ u_int32_t cilong;
+
+#define ACKCIVOID(opt, neg) \
+ if (neg) { \
+ if ((len -= CILEN_VOID) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_VOID || \
+ citype != opt) \
+ break; \
+ }
+
+#define ACKCICOMPLETE(opt,neg) ACKCIVOID(opt, neg)
+
+#define ACKCICHARS(opt, neg, val, cnt) \
+ if (neg) { \
+ int indx, count = cnt; \
+ len -= (count + 2); \
+ if (len < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != (count + 2) || \
+ citype != opt) \
+ break; \
+ for (indx = 0; indx < count; ++indx) {\
+ GETCHAR(cichar, p); \
+ if (cichar != ((u_char *) &val)[indx]) \
+ break; \
+ }\
+ if (indx != count) \
+ break; \
+ }
+
+#define ACKCINODE(opt,neg,val) ACKCICHARS(opt,neg,val,sizeof(val))
+#define ACKCINAME(opt,neg,val) ACKCICHARS(opt,neg,val,strlen(val))
+
+#define ACKCINETWORK(opt, neg, val) \
+ if (neg) { \
+ if ((len -= CILEN_NETN) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_NETN || \
+ citype != opt) \
+ break; \
+ GETLONG(cilong, p); \
+ if (cilong != val) \
+ break; \
+ }
+
+#define ACKCIPROTO(opt, neg, val, bit) \
+ if (neg && (val & BIT(bit))) \
+ { \
+ if (len < 2) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_PROTOCOL || citype != opt) \
+ break; \
+ len -= cilen; \
+ if (len < 0) \
+ break; \
+ GETSHORT(cishort, p); \
+ if (cishort != (bit)) \
+ break; \
+ }
+/*
+ * Process the ACK frame in the order in which the frame was assembled
+ */
+ do {
+ ACKCINETWORK (IPX_NETWORK_NUMBER, go->neg_nn, go->our_network);
+ ACKCINODE (IPX_NODE_NUMBER, go->neg_node, go->our_node);
+ ACKCINAME (IPX_ROUTER_NAME, go->neg_name, go->name);
+ ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 0);
+ ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 2);
+ ACKCIPROTO (IPX_ROUTER_PROTOCOL, go->neg_router, go->router, 4);
+ ACKCICOMPLETE (IPX_COMPLETE, go->neg_complete);
+/*
+ * This is the end of the record.
+ */
+ if (len == 0)
+ return (1);
+ } while (0);
+/*
+ * The frame is invalid
+ */
+ IPXCPDEBUG((LOG_INFO, "ipxcp_ackci: received bad Ack!"));
+ return (0);
+}
+
+/*
+ * ipxcp_nakci - Peer has sent a NAK for some of our CIs.
+ * This should not modify any state if the Nak is bad
+ * or if IPXCP is in the OPENED state.
+ *
+ * Returns:
+ * 0 - Nak was bad.
+ * 1 - Nak was good.
+ */
+
+static int
+ipxcp_nakci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ int unit = f->unit;
+ u_char citype, cilen, *next;
+ u_short s;
+ u_int32_t l;
+ ipxcp_options no; /* options we've seen Naks for */
+ ipxcp_options try; /* options to request next time */
+
+ BZERO(&no, sizeof(no));
+ try = *go;
+
+ while (len > CILEN_VOID) {
+ GETCHAR (citype, p);
+ GETCHAR (cilen, p);
+ len -= cilen;
+ if (len < 0)
+ goto bad;
+ next = &p [cilen - CILEN_VOID];
+
+ switch (citype) {
+ case IPX_NETWORK_NUMBER:
+ if (!go->neg_nn || no.neg_nn || (cilen != CILEN_NETN))
+ goto bad;
+ no.neg_nn = 1;
+
+ GETLONG(l, p);
+ IPXCPDEBUG((LOG_INFO, "local IP address %d", l));
+ if (l && ao->accept_network)
+ try.our_network = l;
+ break;
+
+ case IPX_NODE_NUMBER:
+ if (!go->neg_node || no.neg_node || (cilen != CILEN_NODEN))
+ goto bad;
+ no.neg_node = 1;
+
+ IPXCPDEBUG((LOG_INFO,
+ "local node number %02X%02X%02X%02X%02X%02X",
+ NODE(p)));
+
+ if (!zero_node (p) && ao->accept_local &&
+ ! compare_node (p, ho->his_node))
+ copy_node (p, try.our_node);
+ break;
+
+ /* These have never been sent. Ignore the NAK frame */
+ case IPX_COMPRESSION_PROTOCOL:
+ goto bad;
+
+ case IPX_ROUTER_PROTOCOL:
+ if (!go->neg_router || (cilen < CILEN_PROTOCOL))
+ goto bad;
+
+ GETSHORT (s, p);
+ if ((s != 0) && (s != 2) && (s != 4))
+ goto bad;
+
+ if (no.router & BIT(s))
+ goto bad;
+
+ if (no.router == 0) /* Reset on first NAK only */
+ try.router = 0;
+ no.router |= BIT(s);
+ try.router |= BIT(s);
+ try.neg_router = 1;
+
+ IPXCPDEBUG((LOG_INFO, "Router protocol number %d", s));
+ break;
+
+ /* These, according to the RFC, must never be NAKed. */
+ case IPX_ROUTER_NAME:
+ case IPX_COMPLETE:
+ goto bad;
+
+ /* These are for options which we have not seen. */
+ default:
+ break;
+ }
+ p = next;
+ }
+
+ /* If there is still anything left, this packet is bad. */
+ if (len != 0)
+ goto bad;
+
+ /*
+ * Do not permit the peer to force a router protocol which we do not
+ * support.
+ */
+ try.router &= go->router;
+ if (try.router == 0 && go->router != 0) {
+ try.neg_router = 1;
+ try.router = BIT(0);
+ }
+
+ /*
+ * OK, the Nak is good. Now we can update state.
+ */
+ if (f->state != OPENED)
+ *go = try;
+
+ return 1;
+
+bad:
+ IPXCPDEBUG((LOG_INFO, "ipxcp_nakci: received bad Nak!"));
+ return 0;
+}
+
+/*
+ * ipxcp_rejci - Reject some of our CIs.
+ */
+static int
+ipxcp_rejci(f, p, len)
+ fsm *f;
+ u_char *p;
+ int len;
+{
+ int unit = f->unit;
+ u_short cilen, citype, cishort;
+ u_char cichar;
+ u_int32_t cilong;
+ ipxcp_options try; /* options to request next time */
+
+#define REJCINETWORK(opt, neg, val) \
+ if (neg) { \
+ neg = 0; \
+ if ((len -= CILEN_NETN) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_NETN || \
+ citype != opt) \
+ break; \
+ GETLONG(cilong, p); \
+ if (cilong != val) \
+ break; \
+ IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected long opt %d", opt)); \
+ }
+
+#define REJCICHARS(opt, neg, val, cnt) \
+ if (neg) { \
+ int indx, count = cnt; \
+ neg = 0; \
+ len -= (count + 2); \
+ if (len < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != (count + 2) || \
+ citype != opt) \
+ break; \
+ for (indx = 0; indx < count; ++indx) {\
+ GETCHAR(cichar, p); \
+ if (cichar != ((u_char *) &val)[indx]) \
+ break; \
+ }\
+ if (indx != count) \
+ break; \
+ IPXCPDEBUG((LOG_INFO,"ipxcp_rejci rejected opt %d", opt)); \
+ }
+
+#define REJCINODE(opt,neg,val) REJCICHARS(opt,neg,val,sizeof(val))
+#define REJCINAME(opt,neg,val) REJCICHARS(opt,neg,val,strlen(val))
+
+#define REJCIVOID(opt, neg) \
+ if (neg) { \
+ neg = 0; \
+ if ((len -= CILEN_VOID) < 0) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_VOID || citype != opt) \
+ break; \
+ IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected void opt %d", opt)); \
+ }
+
+#define REJCIPROTO(opt, neg, val, bit) \
+ if (neg && (val & BIT(bit))) \
+ { \
+ if (len < 2) \
+ break; \
+ GETCHAR(citype, p); \
+ GETCHAR(cilen, p); \
+ if (cilen != CILEN_PROTOCOL || citype != opt) \
+ break; \
+ len -= cilen; \
+ if (len < 0) \
+ break; \
+ GETSHORT(cishort, p); \
+ if (cishort != (bit)) \
+ break; \
+ IPXCPDEBUG((LOG_INFO, "ipxcp_rejci rejected router proto %d", bit)); \
+ val &= ~BIT(bit); \
+ if (val == 0) \
+ neg = 0; \
+ }
+
+/*
+ * Any Rejected CIs must be in exactly the same order that we sent.
+ * Check packet length and CI length at each step.
+ * If we find any deviations, then this packet is bad.
+ */
+ try = *go;
+
+ do {
+ REJCINETWORK (IPX_NETWORK_NUMBER, try.neg_nn, try.our_network);
+ REJCINODE (IPX_NODE_NUMBER, try.neg_node, try.our_node);
+ REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 0);
+ REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 2);
+ REJCIPROTO (IPX_ROUTER_PROTOCOL, try.neg_router, try.router, 4);
+ REJCINAME (IPX_ROUTER_NAME, try.neg_name, try.name);
+ REJCIVOID (IPX_COMPLETE, try.neg_complete);
+/*
+ * This is the end of the record.
+ */
+ if (len == 0) {
+ if (f->state != OPENED)
+ *go = try;
+ return (1);
+ }
+ } while (0);
+/*
+ * The frame is invalid at this point.
+ */
+ IPXCPDEBUG((LOG_INFO, "ipxcp_rejci: received bad Reject!"));
+ return 0;
+}
+
+/*
+ * ipxcp_reqci - Check the peer's requested CIs and send appropriate response.
+ *
+ * Returns: CONFACK, CONFNAK or CONFREJ and input packet modified
+ * appropriately. If reject_if_disagree is non-zero, doesn't return
+ * CONFNAK; returns CONFREJ if it can't return CONFACK.
+ */
+static int
+ipxcp_reqci(f, inp, len, reject_if_disagree)
+ fsm *f;
+ u_char *inp; /* Requested CIs */
+ int *len; /* Length of requested CIs */
+ int reject_if_disagree;
+{
+ int unit = f->unit;
+ u_char *cip, *next; /* Pointer to current and next CIs */
+ u_short cilen, citype; /* Parsed len, type */
+ u_short cishort, ts; /* Parsed short value */
+ u_int32_t tl, cinetwork, outnet;/* Parsed address values */
+ int rc = CONFACK; /* Final packet return code */
+ int orc; /* Individual option return code */
+ u_char *p; /* Pointer to next char to parse */
+ u_char *ucp = inp; /* Pointer to current output char */
+ int l = *len; /* Length left */
+ u_char maxslotindex, cflag;
+
+ /*
+ * Reset all his options.
+ */
+ BZERO(ho, sizeof(*ho));
+
+ /*
+ * Process all his options.
+ */
+ next = inp;
+ while (l) {
+ orc = CONFACK; /* Assume success */
+ cip = p = next; /* Remember begining of CI */
+ if (l < 2 || /* Not enough data for CI header or */
+ p[1] < 2 || /* CI length too small or */
+ p[1] > l) { /* CI length too big? */
+ IPXCPDEBUG((LOG_INFO, "ipxcp_reqci: bad CI length!"));
+ orc = CONFREJ; /* Reject bad CI */
+ cilen = l; /* Reject till end of packet */
+ l = 0; /* Don't loop again */
+ goto endswitch;
+ }
+ GETCHAR(citype, p); /* Parse CI type */
+ GETCHAR(cilen, p); /* Parse CI length */
+ l -= cilen; /* Adjust remaining length */
+ next += cilen; /* Step to next CI */
+
+ switch (citype) { /* Check CI type */
+/*
+ * The network number must match. Choose the larger of the two.
+ */
+ case IPX_NETWORK_NUMBER:
+ IPXCPDEBUG((LOG_INFO, "ipxcp: received Network Number request"));
+
+ /* if we wont negotiate the network number or the length is wrong
+ then reject the option */
+ if ( !ao->neg_nn || cilen != CILEN_NETN ) {
+ orc = CONFREJ;
+ break;
+ }
+ GETLONG(cinetwork, p);
+ IPXCPDEBUG((LOG_INFO,"Remote proposed IPX network number is %8Lx",tl));
+
+ /* If the network numbers match then acknowledge them. */
+ if (cinetwork != 0) {
+ ho->his_network = cinetwork;
+ ho->neg_nn = 1;
+ if (wo->our_network == cinetwork)
+ break;
+/*
+ * If the network number is not given or we don't accept their change or
+ * the network number is too small then NAK it.
+ */
+ if (! ao->accept_network || cinetwork < wo->our_network) {
+ DECPTR (sizeof (u_int32_t), p);
+ PUTLONG (wo->our_network, p);
+ orc = CONFNAK;
+ }
+ break;
+ }
+/*
+ * The peer sent '0' for the network. Give it ours if we have one.
+ */
+ if (go->our_network != 0) {
+ DECPTR (sizeof (u_int32_t), p);
+ PUTLONG (wo->our_network, p);
+ orc = CONFNAK;
+/*
+ * We don't have one. Reject the value.
+ */
+ } else
+ orc = CONFREJ;
+
+ break;
+/*
+ * The node number is required
+ */
+ case IPX_NODE_NUMBER:
+ IPXCPDEBUG((LOG_INFO, "ipxcp: received Node Number request"));
+
+ /* if we wont negotiate the node number or the length is wrong
+ then reject the option */
+ if ( cilen != CILEN_NODEN ) {
+ orc = CONFREJ;
+ break;
+ }
+
+ copy_node (p, ho->his_node);
+ ho->neg_node = 1;
+/*
+ * If the remote does not have a number and we do then NAK it with the value
+ * which we have for it. (We never have a default value of zero.)
+ */
+ if (zero_node (ho->his_node)) {
+ orc = CONFNAK;
+ copy_node (wo->his_node, p);
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+ }
+/*
+ * If you have given me the expected network node number then I'll accept
+ * it now.
+ */
+ if (compare_node (wo->his_node, ho->his_node)) {
+ orc = CONFACK;
+ ho->neg_node = 1;
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+ }
+/*
+ * If his node number is the same as ours then ask him to try the next
+ * value.
+ */
+ if (compare_node (ho->his_node, go->our_node)) {
+ inc_node (ho->his_node);
+ orc = CONFNAK;
+ copy_node (ho->his_node, p);
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+ }
+/*
+ * If we don't accept a new value then NAK it.
+ */
+ if (! ao->accept_remote) {
+ copy_node (wo->his_node, p);
+ INCPTR (sizeof (wo->his_node), p);
+ orc = CONFNAK;
+ break;
+ }
+ orc = CONFACK;
+ ho->neg_node = 1;
+ INCPTR (sizeof (wo->his_node), p);
+ break;
+/*
+ * Compression is not desired at this time. It is always rejected.
+ */
+ case IPX_COMPRESSION_PROTOCOL:
+ IPXCPDEBUG((LOG_INFO, "ipxcp: received Compression Protocol request "));
+ orc = CONFREJ;
+ break;
+/*
+ * The routing protocol is a bitmask of various types. Any combination
+ * of the values 2 and 4 are permissible. '0' for no routing protocol must
+ * be specified only once.
+ */
+ case IPX_ROUTER_PROTOCOL:
+ if ( !ao->neg_router || cilen < CILEN_PROTOCOL ) {
+ orc = CONFREJ;
+ break;
+ }
+
+ GETSHORT (cishort, p);
+ IPXCPDEBUG((LOG_INFO,
+ "Remote router protocol number %d",
+ cishort));
+
+ if ((cishort == 0 && ho->router != 0) || (ho->router & BIT(0))) {
+ orc = CONFREJ;
+ break;
+ }
+
+ if (cishort != 0 && cishort != 2 && cishort != 4) {
+ orc = CONFREJ;
+ break;
+ }
+
+ if (ho->router & BIT (cishort)) {
+ orc = CONFREJ;
+ break;
+ }
+
+ ho->router |= BIT (cishort);
+ ho->neg_router = 1;
+ break;
+/*
+ * The router name is advisorary. Just accept it if it is not too large.
+ */
+ case IPX_ROUTER_NAME:
+ IPXCPDEBUG((LOG_INFO, "ipxcp: received Router Name request"));
+ if (cilen >= CILEN_NAME) {
+ int name_size = cilen - CILEN_NAME;
+ if (name_size > sizeof (ho->name))
+ name_size = sizeof (ho->name) - 1;
+ memset (ho->name, 0, sizeof (ho->name));
+ memcpy (ho->name, p, name_size);
+ ho->name [name_size] = '\0';
+ ho->neg_name = 1;
+ orc = CONFACK;
+ break;
+ }
+ orc = CONFREJ;
+ break;
+/*
+ * This is advisorary.
+ */
+ case IPX_COMPLETE:
+ IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
+ if (cilen != CILEN_COMPLETE)
+ orc = CONFREJ;
+ else {
+ ho->neg_complete = 1;
+ orc = CONFACK;
+ }
+ break;
+/*
+ * All other entries are not known at this time.
+ */
+ default:
+ IPXCPDEBUG((LOG_INFO, "ipxcp: received Complete request"));
+ orc = CONFREJ;
+ break;
+ }
+
+endswitch:
+ IPXCPDEBUG((LOG_INFO, " (%s)\n", CODENAME(orc)));
+
+ if (orc == CONFACK && /* Good CI */
+ rc != CONFACK) /* but prior CI wasnt? */
+ continue; /* Don't send this one */
+
+ if (orc == CONFNAK) { /* Nak this CI? */
+ if (reject_if_disagree) /* Getting fed up with sending NAKs? */
+ orc = CONFREJ; /* Get tough if so */
+ if (rc == CONFREJ) /* Rejecting prior CI? */
+ continue; /* Don't send this one */
+ if (rc == CONFACK) { /* Ack'd all prior CIs? */
+ rc = CONFNAK; /* Not anymore... */
+ ucp = inp; /* Backup */
+ }
+ }
+
+ if (orc == CONFREJ && /* Reject this CI */
+ rc != CONFREJ) { /* but no prior ones? */
+ rc = CONFREJ;
+ ucp = inp; /* Backup */
+ }
+
+ /* Need to move CI? */
+ if (ucp != cip)
+ BCOPY(cip, ucp, cilen); /* Move it */
+
+ /* Update output pointer */
+ INCPTR(cilen, ucp);
+ }
+
+ /*
+ * If we aren't rejecting this packet, and we want to negotiate
+ * their address, and they didn't send their address, then we
+ * send a NAK with a IPX_NODE_NUMBER option appended. We assume the
+ * input buffer is long enough that we can append the extra
+ * option safely.
+ */
+
+ if (rc != CONFREJ && !ho->neg_node &&
+ wo->req_nn && !reject_if_disagree) {
+ u_char *ps;
+ if (rc == CONFACK) {
+ rc = CONFNAK;
+ wo->req_nn = 0; /* don't ask again */
+ ucp = inp; /* reset pointer */
+ }
+
+ if (zero_node (wo->his_node))
+ inc_node (wo->his_node);
+
+ PUTCHAR (IPX_NODE_NUMBER, ucp);
+ PUTCHAR (CILEN_NODEN, ucp);
+ copy_node (wo->his_node, ucp);
+ INCPTR (sizeof (wo->his_node), ucp);
+ }
+
+ *len = ucp - inp; /* Compute output length */
+ IPXCPDEBUG((LOG_INFO, "ipxcp: returning Configure-%s", CODENAME(rc)));
+ return (rc); /* Return final code */
+}
+
+/*
+ * ipxcp_up - IPXCP has come UP.
+ *
+ * Configure the IP network interface appropriately and bring it up.
+ */
+
+static void
+ipxcp_up(f)
+ fsm *f;
+{
+ int unit = f->unit;
+
+ IPXCPDEBUG((LOG_INFO, "ipxcp: up"));
+
+ if (!ho->neg_nn)
+ ho->his_network = wo->his_network;
+
+ if (!ho->neg_node)
+ copy_node (wo->his_node, ho->his_node);
+
+ if (!wo->neg_node && !go->neg_node)
+ copy_node (wo->our_node, go->our_node);
+
+ if (zero_node (go->our_node)) {
+ IPXCPDEBUG((LOG_ERR, "Could not determine local IPX node address"));
+ ipxcp_close(f->unit, "Could not determine local IPX node address");
+ return;
+ }
+
+ go->network = go->our_network;
+ if (ho->his_network != 0 && ho->his_network > go->network)
+ go->network = ho->his_network;
+
+ if (go->network == 0) {
+ IPXCPDEBUG((LOG_ERR, "Could not determine network number"));
+ ipxcp_close (unit, "Could not determine network number");
+ return;
+ }
+
+ /* bring the interface up */
+ if (!sifup(unit)) {
+ IPXCPDEBUG((LOG_WARNING, "sifup failed"));
+ ipxcp_close(unit, "Interface configuration failed");
+ return;
+ }
+
+ /* set the network number for IPX */
+ if (!sipxfaddr(unit, go->network, go->our_node)) {
+ IPXCPDEBUG((LOG_WARNING, "sipxfaddr failed"));
+ ipxcp_close(unit, "Interface configuration failed");
+ return;
+ }
+
+ /*
+ * Execute the ipx-up script, like this:
+ * /etc/ppp/ipx-up interface tty speed local-IPX remote-IPX
+ */
+
+ ipxcp_script (f, "/etc/ppp/ipx-up");
+}
+
+/*
+ * ipxcp_down - IPXCP has gone DOWN.
+ *
+ * Take the IP network interface down, clear its addresses
+ * and delete routes through it.
+ */
+
+static void
+ipxcp_down(f)
+ fsm *f;
+{
+ u_int32_t ournn, network;
+
+ IPXCPDEBUG((LOG_INFO, "ipxcp: down"));
+
+ cipxfaddr (f->unit);
+ sifdown(f->unit);
+ ipxcp_script (f, "/etc/ppp/ipx-down");
+}
+
+
+/*
+ * ipxcp_script - Execute a script with arguments
+ * interface-name tty-name speed local-IPX remote-IPX networks.
+ */
+static void
+ipxcp_script(f, script)
+ fsm *f;
+ char *script;
+{
+ int unit = f->unit;
+ char strspeed[32], strlocal[32], strremote[32];
+ char strnetwork[32], strpid[32];
+ char *argv[14], strproto_lcl[32], strproto_rmt[32];
+
+ sprintf (strpid, "%d", getpid());
+ sprintf (strspeed, "%d", baud_rate);
+
+ strproto_lcl[0] = '\0';
+ if (go->neg_router) {
+ if (go->router & BIT(2))
+ strcpy (strproto_lcl, "RIP ");
+ if (go->router & BIT(4))
+ strcpy (strproto_lcl, "NLSP ");
+ }
+
+ if (strproto_lcl[0] == '\0')
+ strcpy (strproto_lcl, "NONE ");
+
+ strproto_lcl[strlen (strproto_lcl)-1] = '\0';
+
+ strproto_rmt[0] = '\0';
+ if (ho->neg_router) {
+ if (ho->router & BIT(2))
+ strcpy (strproto_rmt, "RIP ");
+ if (ho->router & BIT(4))
+ strcpy (strproto_rmt, "NLSP ");
+ }
+
+ if (strproto_rmt[0] == '\0')
+ strcpy (strproto_rmt, "NONE ");
+
+ strproto_rmt[strlen (strproto_rmt)-1] = '\0';
+
+ strcpy (strnetwork, ipx_ntoa (go->network));
+
+ sprintf (strlocal,
+ "%02X%02X%02X%02X%02X%02X",
+ NODE(go->our_node));
+
+ sprintf (strremote,
+ "%02X%02X%02X%02X%02X%02X",
+ NODE(ho->his_node));
+
+ argv[0] = script;
+ argv[1] = ifname;
+ argv[2] = devnam;
+ argv[3] = strspeed;
+ argv[4] = strnetwork;
+ argv[5] = strlocal;
+ argv[6] = strremote;
+ argv[7] = strproto_lcl;
+ argv[8] = strproto_rmt;
+ argv[9] = go->name;
+ argv[10] = ho->name;
+ argv[11] = ipparam;
+ argv[12] = strpid;
+ argv[13] = NULL;
+ run_program(script, argv, 0);
+}
+
+/*
+ * ipxcp_printpkt - print the contents of an IPXCP packet.
+ */
+char *ipxcp_codenames[] = {
+ "ConfReq", "ConfAck", "ConfNak", "ConfRej",
+ "TermReq", "TermAck", "CodeRej"
+};
+
+int
+ipxcp_printpkt(p, plen, printer, arg)
+ u_char *p;
+ int plen;
+ void (*printer)();
+ void *arg;
+{
+ int code, id, len, olen;
+ u_char *pstart, *optend;
+ u_short cishort;
+ u_int32_t cilong;
+
+ if (plen < HEADERLEN)
+ return 0;
+ pstart = p;
+ GETCHAR(code, p);
+ GETCHAR(id, p);
+ GETSHORT(len, p);
+ if (len < HEADERLEN || len > plen)
+ return 0;
+
+ if (code >= 1 && code <= sizeof(ipxcp_codenames) / sizeof(char *))
+ printer(arg, " %s", ipxcp_codenames[code-1]);
+ else
+ printer(arg, " code=0x%x", code);
+ printer(arg, " id=0x%x", id);
+ len -= HEADERLEN;
+ switch (code) {
+ case CONFREQ:
+ case CONFACK:
+ case CONFNAK:
+ case CONFREJ:
+ /* print option list */
+ while (len >= 2) {
+ GETCHAR(code, p);
+ GETCHAR(olen, p);
+ p -= 2;
+ if (olen < CILEN_VOID || olen > len) {
+ break;
+ }
+ printer(arg, " <");
+ len -= olen;
+ optend = p + olen;
+ switch (code) {
+ case IPX_NETWORK_NUMBER:
+ if (olen == CILEN_NETN) {
+ p += CILEN_VOID;
+ GETLONG(cilong, p);
+ printer (arg, "network %s", ipx_ntoa (cilong));
+ }
+ break;
+ case IPX_NODE_NUMBER:
+ if (olen == CILEN_NODEN) {
+ p += CILEN_VOID;
+ printer (arg, "node ");
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, "%.2x", code);
+ }
+ }
+ break;
+ case IPX_COMPRESSION_PROTOCOL:
+ if (olen == CILEN_COMPRESS) {
+ p += CILEN_VOID;
+ GETSHORT (cishort, p);
+ printer (arg, "compression %d", cishort);
+ }
+ break;
+ case IPX_ROUTER_PROTOCOL:
+ if (olen == CILEN_PROTOCOL) {
+ p += CILEN_VOID;
+ GETSHORT (cishort, p);
+ printer (arg, "router proto %d", cishort);
+ }
+ break;
+ case IPX_ROUTER_NAME:
+ if (olen >= CILEN_NAME) {
+ p += CILEN_VOID;
+ printer (arg, "router name \"");
+ while (p < optend) {
+ GETCHAR(code, p);
+ if (code >= 0x20 && code < 0x7E)
+ printer (arg, "%c", code);
+ else
+ printer (arg, " \\%.2x", code);
+ }
+ printer (arg, "\"");
+ }
+ break;
+ case IPX_COMPLETE:
+ if (olen == CILEN_COMPLETE) {
+ p += CILEN_VOID;
+ printer (arg, "complete");
+ }
+ break;
+ default:
+ break;
+ }
+
+ while (p < optend) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+ printer(arg, ">");
+ }
+ break;
+ }
+
+ /* print the rest of the bytes in the packet */
+ for (; len > 0; --len) {
+ GETCHAR(code, p);
+ printer(arg, " %.2x", code);
+ }
+
+ return p - pstart;
+}
+#endif /* ifdef IPX_CHANGE */
--- /dev/null
+/*
+ * ipxcp.h - IPX Control Protocol definitions.
+ *
+ * Copyright (c) 1989 Carnegie Mellon University.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by Carnegie Mellon University. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ *
+ * $Id: ipxcp.h,v 1.1 1995/12/18 03:33:00 paulus Exp $
+ */
+
+/*
+ * Options.
+ */
+#define IPX_NETWORK_NUMBER 1 /* IPX Network Number */
+#define IPX_NODE_NUMBER 2
+#define IPX_COMPRESSION_PROTOCOL 3
+#define IPX_ROUTER_PROTOCOL 4
+#define IPX_ROUTER_NAME 5
+#define IPX_COMPLETE 6
+
+
+typedef struct ipxcp_options {
+ int neg_node : 1; /* Negotiate IPX node number? */
+ int req_node : 1; /* Ask peer to send IPX node number? */
+
+ int neg_nn : 1; /* Negotiate IPX network number? */
+ int req_nn : 1; /* Ask peer to send IPX network number */
+
+ int neg_name : 1; /* Negotiate IPX router name */
+ int neg_complete : 1; /* Negotiate completion */
+ int neg_router : 1; /* Negotiate IPX router number */
+
+ int accept_local : 1; /* accept peer's value for ournode */
+ int accept_remote : 1; /* accept peer's value for hisnode */
+ int accept_network : 1; /* accept network number */
+
+ u_int32_t his_network; /* base network number */
+ u_int32_t our_network; /* our value for network number */
+ u_int32_t network; /* the final network number */
+
+ u_char his_node[6]; /* peer's node number */
+ u_char our_node[6]; /* our node number */
+ u_char name [48]; /* name of the router */
+ int router; /* routing protocol */
+} ipxcp_options;
+
+extern fsm ipxcp_fsm[];
+extern ipxcp_options ipxcp_wantoptions[];
+extern ipxcp_options ipxcp_gotoptions[];
+extern ipxcp_options ipxcp_allowoptions[];
+extern ipxcp_options ipxcp_hisoptions[];
+
+void ipxcp_init __P((int));
+void ipxcp_open __P((int));
+void ipxcp_close __P((int, char *));
+void ipxcp_lowerup __P((int));
+void ipxcp_lowerdown __P((int));
+void ipxcp_input __P((int, u_char *, int));
+void ipxcp_protrej __P((int));
+int ipxcp_printpkt __P((u_char *, int, void (*)(), void *));
+
+extern struct protent ipxcp_protent;