ppp/ppp-2.4.2-pppoatm.patch

1246 lines
34 KiB
Diff

--- ppp-2.4.2/configure.atm1 2002-11-09 11:24:41.000000000 +0000
+++ ppp-2.4.2/configure 2004-10-04 12:11:55.000000000 +0100
@@ -141,7 +141,7 @@ if [ -d "$ksrc" ]; then
rm -f Makedefs.com
ln -s $ksrc/Makedefs$compiletype Makedefs.com
echo " $ksrc/Makedefs$compiletype -> Makedefs.com"
- for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/rp-pppoe pppd/plugins/radius; do
+ for dir in pppd pppstats chat pppdump pppd/plugins pppd/plugins/rp-pppoe pppd/plugins/radius pppd/plugins/pppoatm; do
rm -f $dir/Makefile
if [ -f $dir/Makefile.$makext ]; then
ln -s Makefile.$makext $dir/Makefile
--- ppp-2.4.2/pppd/plugins/Makefile.linux.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/Makefile.linux 2004-10-04 12:11:55.000000000 +0100
@@ -4,7 +4,7 @@ CFLAGS = $(COPTS) -I.. -I../../include -
LDFLAGS = -shared
INSTALL = install -o root
-SUBDIRS := rp-pppoe
+SUBDIRS := rp-pppoe pppoatm
# Uncomment the next line to include the radius authentication plugin
# SUBDIRS += radius
PLUGINS := minconn.so passprompt.so passwordfd.so
--- ppp-2.4.2/pppd/plugins/pppoatm/ans.c.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/ans.c 2004-10-04 12:11:55.000000000 +0100
@@ -0,0 +1,262 @@
+/* ans.c - Interface for text2atm and atm2text to ANS */
+
+/* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */
+
+
+/*
+ * This stuff is a temporary hack to avoid using gethostbyname_nsap and such
+ * without doing the "full upgrade" to getaddrinfo/getnameinfo. This also
+ * serves as an exercise for me to get all the details right before I propose
+ * a patch that would eventually end up in libc (and that should therefore be
+ * as stable as possible).
+ */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+
+#include "atm.h"
+#include "atmres.h"
+
+
+#define MAX_ANSWER 2048
+#define MAX_NAME 1024
+
+#define MAX_LINE 2048 /* in /etc/e164_cc */
+#define E164_CC_DEFAULT_LEN 2
+#define E164_CC_FILE "/etc/e164_cc"
+
+#define GET16(pos) (((pos)[0] << 8) | (pos)[1])
+
+
+static int ans(const char *text,int wanted,void *result,int res_len)
+{
+ unsigned char answer[MAX_ANSWER];
+ unsigned char name[MAX_NAME];
+ unsigned char *pos,*data,*found;
+ int answer_len,name_len,data_len,found_len;
+ int questions,answers;
+
+ found_len = 0; /* gcc wants it */
+ if ((answer_len = res_search(text,C_IN,wanted,answer,MAX_ANSWER)) < 0)
+ return TRY_OTHER;
+ /*
+ * Response header: id, flags, #queries, #answers, #authority,
+ * #additional (all 16 bits)
+ */
+ pos = answer+12;
+ if (answer[3] & 15) return TRY_OTHER; /* rcode != 0 */
+ questions = GET16(answer+4);
+ if (questions != 1) return TRY_OTHER; /* trouble ... */
+ answers = GET16(answer+6);
+ if (answers < 1) return TRY_OTHER;
+ /*
+ * Query: name, type (16), class (16)
+ */
+ if ((name_len = dn_expand(answer,answer+answer_len,pos,name,MAX_NAME)) < 0)
+ return TRY_OTHER;
+ pos += name_len;
+ if (GET16(pos) != wanted || GET16(pos+2) != C_IN) return TRY_OTHER;
+ pos += 4;
+ /*
+ * Iterate over answers until we find something we like, giving priority
+ * to ATMA_AESA (until signaling is fixed to work with E.164 too)
+ */
+ found = NULL;
+ while (answers--) {
+ /*
+ * RR: name, type (16), class (16), TTL (32), resource_len (16),
+ * resource_data ...
+ */
+ if ((name_len = dn_expand(answer,answer+answer_len,pos,name,MAX_NAME))
+ < 0) return TRY_OTHER;
+ pos += name_len;
+ data_len = GET16(pos+8);
+ data = pos+10;
+ pos = data+data_len;
+ if (GET16(data-10) != wanted || GET16(data-8) != C_IN || !--data_len)
+ continue;
+ switch (wanted) {
+ case T_NSAP:
+ data_len++;
+ if (data_len != ATM_ESA_LEN) continue;
+ memcpy(((struct sockaddr_atmsvc *) result)->
+ sas_addr.prv,data,ATM_ESA_LEN);
+ return 0;
+ case T_ATMA:
+ switch (*data++) {
+ case ATMA_AESA:
+ if (data_len != ATM_ESA_LEN) continue;
+ memcpy(((struct sockaddr_atmsvc *) result)->
+ sas_addr.prv,data,ATM_ESA_LEN);
+ return 0;
+ case ATMA_E164:
+ if (data_len > ATM_E164_LEN) continue;
+ if (!found) {
+ found = data;
+ found_len = data_len;
+ }
+ break;
+ default:
+ continue;
+ }
+ case T_PTR:
+ if (dn_expand(answer,answer+answer_len,data,result,
+ res_len) < 0) return FATAL;
+ return 0;
+ default:
+ continue;
+ }
+ }
+ if (!found) return TRY_OTHER;
+ memcpy(((struct sockaddr_atmsvc *) result)->sas_addr.pub,found,
+ found_len);
+ ((struct sockaddr_atmsvc *) result)->sas_addr.pub[found_len] = 0;
+ return 0;
+}
+
+
+int ans_byname(const char *text,struct sockaddr_atmsvc *addr,int length,
+ int flags)
+{
+ if (!(flags & T2A_SVC) || length != sizeof(*addr)) return TRY_OTHER;
+ memset(addr,0,sizeof(*addr));
+ addr->sas_family = AF_ATMSVC;
+ if (!ans(text,T_ATMA,addr,length)) return 0;
+ return ans(text,T_NSAP,addr,length);
+}
+
+
+static int encode_nsap(char *buf,const unsigned char *addr)
+{
+ static int fmt_dcc[] = { 2,12,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
+ 4,2,0 };
+ static int fmt_e164[] = { 2,12,1,1,1,1,1,1,1,1,16,2,0 };
+ int *fmt;
+ int pos,i,j;
+
+ switch (*addr) {
+ case ATM_AFI_DCC:
+ case ATM_AFI_ICD:
+ case ATM_AFI_LOCAL:
+ case ATM_AFI_DCC_GROUP:
+ case ATM_AFI_ICD_GROUP:
+ case ATM_AFI_LOCAL_GROUP:
+ fmt = fmt_dcc;
+ break;
+ case ATM_AFI_E164:
+ case ATM_AFI_E164_GROUP:
+ fmt = fmt_e164;
+ break;
+ default:
+ return TRY_OTHER;
+ }
+ pos = 2*ATM_ESA_LEN;
+ for (i = 0; fmt[i]; i++) {
+ pos -= fmt[i];
+ for (j = 0; j < fmt[i]; j++)
+ sprintf(buf++,"%x",
+ (addr[(pos+j) >> 1] >> 4*(1-((pos+j) & 1))) & 0xf);
+ *buf++ = '.';
+ }
+ strcpy(buf,"AESA.ATMA.INT.");
+ return 0;
+}
+
+
+static int encode_nsap_new(char *buf,const unsigned char *addr)
+{
+ int i;
+ int digit;
+
+ for (i = 20; i; ) {
+ i--;
+ digit = addr[i] & 0x0F;
+ *(buf++) = digit + (digit >= 10 ? '7' : '0');
+ *(buf++) = '.';
+ digit = ((unsigned char) (addr[i])) >> 4;
+ *(buf++) = digit + (digit >= 10 ? '7' : '0');
+ *(buf++) = '.';
+ }
+ strcpy (buf, "NSAP.INT.");
+ return 0;
+}
+
+
+static int cc_len(int p0,int p1)
+{
+ static char *cc_table = NULL;
+ FILE *file;
+ char buffer[MAX_LINE];
+ char *here;
+ int cc;
+
+ if (!cc_table) {
+ if (!(cc_table = malloc(100))) {
+ perror("malloc");
+ return E164_CC_DEFAULT_LEN;
+ }
+ memset(cc_table,E164_CC_DEFAULT_LEN,100);
+ if (!(file = fopen(E164_CC_FILE,"r")))
+ perror(E164_CC_FILE);
+ else {
+ while (fgets(buffer,MAX_LINE,file)) {
+ here = strchr(buffer,'#');
+ if (here) *here = 0;
+ if (sscanf(buffer,"%d",&cc) == 1) {
+ if (cc < 10) cc_table[cc] = 1;
+ else if (cc < 100) cc_table[cc] = 2;
+ else cc_table[cc/10] = 3;
+ }
+ }
+ fclose(file);
+ }
+ }
+ if (cc_table[p0] == 1) return 1;
+ return cc_table[p0*10+p1];
+}
+
+
+static int encode_e164(char *buf,const char *addr)
+{
+ const char *prefix,*here;
+
+ prefix = addr+cc_len(addr[0]-48,addr[1]-48);
+ here = strchr(addr,0);
+ while (here > prefix) {
+ *buf++ = *--here;
+ *buf++ = '.';
+ }
+ while (here > addr) *buf++ = *addr++;
+ strcpy(buf,".E164.ATMA.INT.");
+ return 0;
+}
+
+
+int ans_byaddr(char *buffer,int length,const struct sockaddr_atmsvc *addr,
+ int flags)
+{
+ char tmp[MAX_NAME]; /* could be smaller ... */
+ int res;
+
+ if (addr->sas_addr.prv) {
+ res = encode_nsap(tmp,addr->sas_addr.prv);
+ if (!res && !ans(tmp,T_PTR,buffer,length)) return 0;
+ res = encode_nsap_new(tmp,addr->sas_addr.prv);
+ if (res < 0) return res;
+ return ans(tmp,T_PTR,buffer,length);
+ } else {
+ res = encode_e164(tmp,addr->sas_addr.pub);
+ if (res < 0) return res;
+ return ans(tmp,T_PTR,buffer,length);
+ }
+}
--- ppp-2.4.2/pppd/plugins/pppoatm/Makefile.linux.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/Makefile.linux 2004-10-05 17:32:17.462042440 +0100
@@ -0,0 +1,41 @@
+CC = gcc
+COPTS = -O2 -g
+CFLAGS = $(COPTS) -I../.. -I../../../include -fPIC
+LDFLAGS = -shared
+INSTALL = install -o root
+
+#***********************************************************************
+
+PLUGIN := pppoatm.so
+PLUGIN_OBJS := pppoatm.o
+
+#*******
+# Do we have the ATM libraries installed? Set HAVE_LIBATM to use them,
+# or leave it unset to build the few routines we actually _use_ into
+# the plugin directly.
+#
+#HAVE_LIBATM=yes
+
+ifdef HAVE_LIBATM
+LIBS := -latm
+else
+CFLAGS += -I.
+PLUGIN_OBJS += text2qos.o text2atm.o misc.o ans.o
+LIBS := -lresolv
+endif
+
+#*********
+all: $(PLUGIN)
+
+$(PLUGIN): $(PLUGIN_OBJS)
+ $(CC) $(CFLAGS) -o $@ -shared $^ $(LIBS)
+
+install: all
+ $(INSTALL) -d -m 755 $(LIBDIR)
+ $(INSTALL) -c -m 4550 $(PLUGIN) $(LIBDIR)
+
+clean:
+ rm -f *.o *.so
+
+%.o: %.c
+ $(CC) $(CFLAGS) -c -o $@ $<
--- ppp-2.4.2/pppd/plugins/pppoatm/text2atm.c.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/text2atm.c 2004-10-04 12:11:55.000000000 +0100
@@ -0,0 +1,249 @@
+/* text2atm.c - Converts textual representation of ATM address to binary
+ encoding */
+
+/* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <limits.h>
+
+#include "atm.h"
+#include "atmsap.h"
+#include "atmres.h"
+
+
+static int try_pvc(const char *text,struct sockaddr_atmpvc *addr,int flags)
+{
+ int part[3];
+ int i;
+
+ part[0] = part[1] = part[2] = 0;
+ i = 0;
+ while (1) {
+ if (!*text) return FATAL; /* empty or ends with a dot */
+ if (i == 3) return TRY_OTHER; /* too long */
+ if (isdigit(*text)) {
+ if (*text == '0' && isdigit(text[1])) return TRY_OTHER;
+ /* no leading zeroes */
+ do {
+ if (part[i] > INT_MAX/10) return TRY_OTHER;/* number too big */
+ part[i] = part[i]*10+*text++-'0';
+ }
+ while (isdigit(*text));
+ i++;
+ if (!*text) break;
+ if (*text++ != '.') return TRY_OTHER; /* non-PVC character */
+ continue;
+ }
+ if (*text == '*') {
+ if (!(flags & T2A_WILDCARD)) return FATAL; /* not allowed */
+ part[i++] = ATM_ITF_ANY; /* all *_ANY have the same value */
+ }
+ else {
+ if (*text != '?') return TRY_OTHER; /* invalid character */
+ if (!(flags & T2A_UNSPEC)) return FATAL; /* not allowed */
+ part[i++] = ATM_VPI_UNSPEC; /* all *_UNSPEC have the same
+ value */
+ }
+ if (!*++text) break;
+ if (*text++ != '.') return FATAL; /* dot required */
+ }
+ if (i < 2) return TRY_OTHER; /* no dots */
+ if (i == 2) {
+ part[2] = part[1];
+ part[1] = part[0];
+ part[0] = 0; /* default interface */
+ }
+ if (part[0] > SHRT_MAX || part[2] > ATM_MAX_VCI)
+ return TRY_OTHER; /* too big */
+ if (part[1] > (flags & T2A_NNI ? ATM_MAX_VPI_NNI : ATM_MAX_VPI))
+ return TRY_OTHER; /* too big */
+ if (part[0] == ATM_VPI_UNSPEC) return FATAL; /* bad */
+ addr->sap_family = AF_ATMPVC;
+ addr->sap_addr.itf = part[0];
+ addr->sap_addr.vpi = part[1];
+ addr->sap_addr.vci = part[2];
+ return 0;
+}
+
+
+static int do_try_nsap(const char *text,struct sockaddr_atmsvc *addr,int flags)
+{
+ const char *walk;
+ int count,pos,dot;
+ int offset,len;
+ char value;
+
+ count = dot = 0;
+ for (walk = text; *walk; walk++)
+ if (isdigit(*walk)) {
+ if (count++ == 15) break;
+ dot = 1;
+ }
+ else if (*text != '.') break;
+ else if (!dot) return FATAL; /* two dots in a row */
+ else dot = 0;
+ if (*walk != ':') {
+ pos = 0;
+ offset = 0;
+ }
+ else {
+ if (!dot || *text == '0') return FATAL;
+ addr->sas_addr.prv[0] = ATM_AFI_E164;
+ addr->sas_addr.prv[1] = 0;
+ memset(addr->sas_addr.prv+1,0,8);
+ for (pos = 18-count-1; *text; text++) {
+ if (*text == '.') continue;
+ if (*text == ':') break;
+ else {
+ if (pos & 1) addr->sas_addr.prv[pos >> 1] |= *text-'0';
+ else addr->sas_addr.prv[pos >> 1] = (*text-'0') << 4;
+ pos++;
+ }
+ }
+ addr->sas_addr.prv[8] |= 0xf;
+ text++;
+ pos++;
+ offset = 72;
+ }
+ for (dot = 0; *text; text++)
+ if (isxdigit(*text)) {
+ if (pos == ATM_ESA_LEN*2) return TRY_OTHER; /* too long */
+ value = isdigit(*text) ? *text-'0' : (islower(*text) ?
+ toupper(*text) : *text)-'A'+10;
+ if (pos & 1) addr->sas_addr.prv[pos >> 1] |= value;
+ else addr->sas_addr.prv[pos >> 1] = value << 4;
+ pos++;
+ dot = 1;
+ }
+ else
+ if (*text == '/' && (flags & T2A_WILDCARD)) break;
+ else if (*text != '.') return TRY_OTHER;
+ else {
+ if (!dot) return FATAL; /* two dots in a row */
+ dot = 0;
+ }
+ if (!dot) return FATAL;
+ if (pos > 1 && !*addr->sas_addr.prv)
+ return TRY_OTHER; /* no leading zeroes */
+ if (!*text)
+ return pos != ATM_ESA_LEN*2 ? TRY_OTHER : ATM_ESA_LEN*2;
+ /* handle bad length */
+ len = 0;
+ while (*++text) {
+ if (!isdigit(*text)) return -1; /* non-digit in length */
+ if (len >= pos*4) return -1; /* too long */
+ len = len*10+*text-'0';
+ }
+ if (len > 7 && addr->sas_addr.prv[0] != ATM_AFI_E164) offset = 72;
+ if (len < offset) return FATAL;
+ return len > pos*4 ? TRY_OTHER : len;
+}
+
+
+static int try_nsap(const char *text,struct sockaddr_atmsvc *addr,int flags)
+{
+ int result;
+
+ result = do_try_nsap(text,addr,flags);
+ if (result < 0) return result;
+ addr->sas_family = AF_ATMSVC;
+ *addr->sas_addr.pub = 0;
+ return result;
+}
+
+
+static int try_e164(const char *text,struct sockaddr_atmsvc *addr,int flags)
+{
+ int i,dot,result;
+
+ if (*text == ':' || *text == '+') text++;
+ for (i = dot = 0; *text; text++)
+ if (isdigit(*text)) {
+ if (i == ATM_E164_LEN) return TRY_OTHER; /* too long */
+ addr->sas_addr.pub[i++] = *text;
+ dot = 1;
+ }
+ else if (*text != '.') break;
+ else {
+ if (!dot) return TRY_OTHER; /* two dots in a row */
+ dot = 0;
+ }
+ if (!dot) return TRY_OTHER;
+ addr->sas_addr.pub[i] = 0;
+ *addr->sas_addr.prv = 0;
+ result = 0;
+ if (*text) {
+ if (*text++ != '+') return TRY_OTHER;
+ else {
+ result = do_try_nsap(text,addr,flags);
+ if (result < 0) return FATAL;
+ }
+ }
+ addr->sas_family = AF_ATMSVC;
+ return result;
+}
+
+
+static int search(FILE *file,const char *text,struct sockaddr *addr,int length,
+ int flags)
+{
+ char line[MAX_ATM_NAME_LEN+1];
+ const char *here;
+ int result;
+
+ while (fgets(line,MAX_ATM_NAME_LEN,file)) {
+ if (!strtok(line,"\t\n ")) continue;
+ while ((here = strtok(NULL,"\t\n ")))
+ if (!strcasecmp(here,text)) {
+ here = strtok(line,"\t\n ");
+ result = text2atm(here,addr,length,flags);
+ if (result >= 0) return result;
+ }
+ }
+ return TRY_OTHER;
+}
+
+
+static int try_name(const char *text,struct sockaddr *addr,int length,
+ int flags)
+{
+ FILE *file;
+ int result;
+
+ if (!(file = fopen(HOSTS_ATM,"r"))) return TRY_OTHER;
+ result = search(file,text,addr,length,flags);
+ (void) fclose(file);
+ return result;
+}
+
+
+int text2atm(const char *text,struct sockaddr *addr,int length,int flags)
+{
+ int result;
+
+ if (!*text) return -1;
+ if (!(flags & (T2A_PVC | T2A_SVC))) flags |= T2A_PVC | T2A_SVC;
+ if (length < sizeof(struct sockaddr_atmpvc)) return -1;
+ if (flags & T2A_PVC) {
+ result = try_pvc(text,(struct sockaddr_atmpvc *) addr,flags);
+ if (result != TRY_OTHER) return result;
+ }
+ if ((flags & T2A_SVC) && length >= sizeof(struct sockaddr_atmsvc)) {
+ result = try_nsap(text,(struct sockaddr_atmsvc *) addr,flags);
+ if (result != TRY_OTHER) return result;
+ result = try_e164(text,(struct sockaddr_atmsvc *) addr,flags);
+ if (result != TRY_OTHER) return result;
+ }
+ if (!(flags & T2A_NAME)) return -1;
+ result = try_name(text,addr,length,flags & ~T2A_NAME);
+ if (result == TRY_OTHER && !(flags & T2A_LOCAL))
+ result = ans_byname(text,(struct sockaddr_atmsvc *) addr,length,flags);
+ if (result != TRY_OTHER) return result;
+ return -1;
+}
--- ppp-2.4.2/pppd/plugins/pppoatm/text2qos.c.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/text2qos.c 2004-10-04 12:11:55.000000000 +0100
@@ -0,0 +1,180 @@
+/* text2qos.c - Converts textual representation of QOS parameters to binary
+ encoding */
+
+/* Written 1996-2000 by Werner Almesberger, EPFL-LRC/ICA */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+
+#include "atm.h"
+
+
+#define fetch __atmlib_fetch
+
+
+#define RATE_ERROR -2
+
+
+int __t2q_get_rate(const char **text,int up)
+{
+ const char mult[] = "kKmMgGg";
+ const char *multiplier;
+ char *end;
+ unsigned int rate,fract;
+ int power;
+
+ if (!strncmp(*text,"max",3)) {
+ *text += 3;
+ return ATM_MAX_PCR;
+ }
+ rate = strtoul(*text,&end,10);
+ power = fract = 0;
+ if (*end == '.')
+ for (end++; *end && isdigit(*end); end++) {
+ fract = fract*10+*end-48;
+ if (--power == -9) break;
+ }
+ multiplier = NULL;
+ if (*end && (multiplier = strchr(mult,*end))) {
+ while (multiplier >= mult) {
+ if (rate > UINT_MAX/1000) return RATE_ERROR;
+ rate *= 1000;
+ power += 3;
+ multiplier -= 2;
+ }
+ end++;
+ }
+ while (power && fract)
+ if (power < 0) {
+ fract /= 10;
+ power++;
+ }
+ else {
+ fract *= 10;
+ power--;
+ }
+ rate += fract;
+ if (strlen(end) < 3) {
+ if (multiplier) return RATE_ERROR;
+ }
+ else if (!strncmp(end,"cps",3)) end += 3;
+ else if (!strncmp(end,"bps",3)) {
+ rate = (rate+(up ? 8*ATM_CELL_PAYLOAD-1 : 0))/8/
+ ATM_CELL_PAYLOAD;
+ end += 3;
+ }
+ else if (multiplier) return RATE_ERROR;
+ if (rate > INT_MAX) return RATE_ERROR;
+ *text = end;
+ return rate;
+}
+
+
+static int params(const char **text,struct atm_trafprm *a,
+ struct atm_trafprm *b)
+{
+ int value;
+ char *end;
+
+ if (*(*text)++ != ':') return -1;
+ while (1) {
+ if (!**text) return -1;
+ switch (fetch(text,"max_pcr=","pcr=","min_pcr=","max_sdu=","sdu=",
+ NULL)) {
+ case 0:
+ if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
+ if (a) a->max_pcr = value;
+ if (b) b->max_pcr = value;
+ break;
+ case 1:
+ if ((value = __t2q_get_rate(text,0)) == RATE_ERROR) return -1;
+ if (a) a->pcr = value;
+ if (b) b->pcr = value;
+ break;
+ case 2:
+ if ((value = __t2q_get_rate(text,1)) == RATE_ERROR) return -1;
+ if (value == ATM_MAX_PCR) return -1;
+ if (a) a->min_pcr = value;
+ if (b) b->min_pcr = value;
+ break;
+ case 3:
+ case 4:
+ value = strtol(*text,&end,10);
+ if (value < 0) return -1;
+ *text = end;
+ if (a) a->max_sdu = value;
+ if (b) b->max_sdu = value;
+ break;
+ default:
+ return 0;
+ }
+ if (!**text) break;
+ if (*(*text)++ != ',') return -1;
+ }
+ return 0;
+}
+
+
+int text2qos(const char *text,struct atm_qos *qos,int flags)
+{
+ int traffic_class,aal;
+
+ traffic_class = ATM_NONE;
+ aal = ATM_NO_AAL;
+ do {
+ static const unsigned char aal_number[] = { ATM_AAL0, ATM_AAL5 };
+ int item;
+
+ item = fetch(&text,"!none","ubr","cbr","vbr","abr","aal0","aal5",NULL);
+ switch (item) {
+ case 1:
+ case 2:
+ /* we don't support VBR yet */
+ case 4:
+ traffic_class = item;
+ break;
+ case 5:
+ case 6:
+ aal = aal_number[item-5];
+ break;
+ default:
+ return -1;
+ }
+ }
+ while (*text == ',' ? text++ : 0);
+ if (!traffic_class) return -1;
+ if (qos && !(flags & T2Q_DEFAULTS)) memset(qos,0,sizeof(*qos));
+ if (qos) qos->txtp.traffic_class = qos->rxtp.traffic_class = traffic_class;
+ if (qos && aal) qos->aal = aal;
+ if (!*text) return 0;
+ if (params(&text,qos ? &qos->txtp : NULL,qos ? &qos->rxtp : NULL))
+ return -1;
+ if (!*text) return 0;
+ switch (fetch(&text,"tx","rx",NULL)) {
+ case 0:
+ if (!fetch(&text,":none",NULL)) {
+ if (qos) qos->txtp.traffic_class = ATM_NONE;
+ if (*text == ',') text++;
+ break;
+ }
+ if (params(&text,qos ? &qos->txtp : NULL,NULL)) return -1;
+ break;
+ case 1:
+ text -= 2;
+ break;
+ default:
+ return -1;
+ }
+ if (!*text) return 0;
+ if (fetch(&text,"rx",NULL)) return -1;
+ if (!fetch(&text,":none",NULL) && qos) qos->rxtp.traffic_class = ATM_NONE;
+ else if (params(&text,qos ? &qos->rxtp : NULL,NULL)) return -1;
+ return *text ? -1 : 0;
+}
--- ppp-2.4.2/pppd/plugins/pppoatm/atm.h.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/atm.h 2004-10-05 17:25:10.825900992 +0100
@@ -0,0 +1,108 @@
+/* atm.h - Functions useful for ATM applications */
+
+/* Written 1995-2000 by Werner Almesberger, EPFL-LRC/ICA */
+
+
+#ifndef _ATM_H
+#define _ATM_H
+
+#include <stdint.h>
+#include <sys/socket.h>
+#include <linux/atm.h>
+
+
+/*
+ * For versions of glibc < 2.1
+ */
+
+#ifndef AF_ATMPVC
+#define AF_ATMPVC 8
+#endif
+
+#ifndef AF_ATMSVC
+#define AF_ATMSVC 20
+#endif
+
+#ifndef PF_ATMPVC
+#define PF_ATMPVC AF_ATMPVC
+#endif
+
+#ifndef PF_ATMSVC
+#define PF_ATMSVC AF_ATMSVC
+#endif
+
+#ifndef SOL_ATM
+#define SOL_ATM 264
+#endif
+
+#ifndef SOL_AAL
+#define SOL_AAL 265
+#endif
+
+
+#define HOSTS_ATM "/etc/hosts.atm"
+
+/* text2atm flags */
+#define T2A_PVC 1 /* address is PVC */
+#define T2A_SVC 2 /* address is SVC */
+#define T2A_UNSPEC 4 /* allow unspecified parts in PVC address */
+#define T2A_WILDCARD 8 /* allow wildcards in PVC or SVC address */
+#define T2A_NNI 16 /* allow NNI VPI range (PVC) */
+#define T2A_NAME 32 /* allow name resolution */
+#define T2A_REMOTE 64 /* OBSOLETE */
+#define T2A_LOCAL 128 /* don't use ANS */
+
+/* atm2text flags */
+#define A2T_PRETTY 1 /* add syntactic sugar */
+#define A2T_NAME 2 /* attempt name lookup */
+#define A2T_REMOTE 4 /* OBSOLETE */
+#define A2T_LOCAL 8 /* don't use ANS */
+
+/* atm_equal flags */
+#define AXE_WILDCARD 1 /* allow wildcard match */
+#define AXE_PRVOPT 2 /* private part of SVC address is optional */
+
+/* text2qos flags */
+#define T2Q_DEFAULTS 1 /* structure contains default values */
+
+/* text2sap flags */
+#define T2S_NAME 1 /* attempt name lookup */
+#define T2S_LOCAL 2 /* we may support NIS or such in the future */
+
+/* sap2text flags */
+#define S2T_NAME 1 /* attempt name lookup */
+#define S2T_LOCAL 2 /* we may support NIS or such in the future */
+
+/* sap_equal flags */
+#define SXE_COMPATIBLE 1 /* check for compatibility instead of identity*/
+#define SXE_NEGOTIATION 2 /* allow negotiation; requires SXE_COMPATIBLE;
+ assumes "a" defines the available
+ capabilities */
+#define SXE_RESULT 4 /* return selected SAP */
+
+#define MAX_ATM_ADDR_LEN (2*ATM_ESA_LEN+ATM_E164_LEN+5)
+ /* 4 dots, 1 plus */
+#define MAX_ATM_NAME_LEN 256 /* wild guess */
+#define MAX_ATM_QOS_LEN 116 /* 5+4+2*(3+3*(7+9)+2)+1 */
+#define MAX_ATM_SAP_LEN 255 /* BHLI(27)+1+3*BLLI(L2=33,L3=41,+1)+2 */
+
+
+int text2atm(const char *text,struct sockaddr *addr,int length,int flags);
+int atm2text(char *buffer,int length,const struct sockaddr *addr,int flags);
+int atm_equal(const struct sockaddr *a,const struct sockaddr *b,int len,
+ int flags);
+
+int sdu2cell(int s,int sizes,const int *sdu_size,int *num_sdu);
+
+int text2qos(const char *text,struct atm_qos *qos,int flags);
+int qos2text(char *buffer,int length,const struct atm_qos *qos,int flags);
+int qos_equal(const struct atm_qos *a,const struct atm_qos *b);
+
+int text2sap(const char *text,struct atm_sap *sap,int flags);
+int sap2text(char *buffer,int length,const struct atm_sap *sap,int flags);
+int sap_equal(const struct atm_sap *a,const struct atm_sap *b,int flags,...);
+
+int __t2q_get_rate(const char **text,int up);
+int __atmlib_fetch(const char **pos,...); /* internal use only */
+
+#endif
--- ppp-2.4.2/pppd/plugins/pppoatm/pppoatm.c.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/pppoatm.c 2004-10-04 12:11:55.000000000 +0100
@@ -0,0 +1,224 @@
+/* pppoatm.c - pppd plugin to implement PPPoATM protocol.
+ *
+ * Copyright 2000 Mitchell Blank Jr.
+ * Based in part on work from Jens Axboe and Paul Mackerras.
+ * Updated to ppp-2.4.1 by Bernhard Kaindl
+ *
+ * Updated to ppp-2.4.2 by David Woodhouse 2004.
+ * - disconnect method added
+ * - remove_options() abuse removed.
+ *
+ * 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.
+ */
+#include <unistd.h>
+#include <string.h>
+#include <stdlib.h>
+#include "pppd.h"
+#include "pathnames.h"
+#include "fsm.h" /* Needed for lcp.h to include cleanly */
+#include "lcp.h"
+#include <atm.h>
+#include <linux/atmdev.h>
+#include <linux/atmppp.h>
+#include <sys/stat.h>
+#include <net/if.h>
+#include <sys/ioctl.h>
+
+const char pppd_version[] = VERSION;
+
+static struct sockaddr_atmpvc pvcaddr;
+static char *qosstr = NULL;
+static bool llc_encaps = 0;
+static bool vc_encaps = 0;
+static int device_got_set = 0;
+static int pppoatm_max_mtu, pppoatm_max_mru;
+static int setdevname_pppoatm(const char *cp, const char **argv, int doit);
+struct channel pppoa_channel;
+static int pppoa_fd = -1;
+
+static option_t pppoa_options[] = {
+ { "device name", o_wild, (void *) &setdevname_pppoatm,
+ "ATM service provider IDs: VPI.VCI",
+ OPT_DEVNAM | OPT_PRIVFIX | OPT_NOARG | OPT_A2STRVAL | OPT_STATIC,
+ devnam},
+ { "llc-encaps", o_bool, &llc_encaps,
+ "use LLC encapsulation for PPPoATM", 1},
+ { "vc-encaps", o_bool, &vc_encaps,
+ "use VC multiplexing for PPPoATM (default)", 1},
+ { "qos", o_string, &qosstr,
+ "set QoS for PPPoATM connection", 1},
+ { NULL }
+};
+
+/* returns:
+ * -1 if there's a problem with setting the device
+ * 0 if we can't parse "cp" as a valid name of a device
+ * 1 if "cp" is a reasonable thing to name a device
+ * Note that we don't actually open the device at this point
+ * We do need to fill in:
+ * devnam: a string representation of the device
+ * devstat: a stat structure of the device. In this case
+ * we're not opening a device, so we just make sure
+ * to set up S_ISCHR(devstat.st_mode) != 1, so we
+ * don't get confused that we're on stdin.
+ */
+int (*old_setdevname_hook)(const char* cp) = NULL;
+static int setdevname_pppoatm(const char *cp, const char **argv, int doit)
+{
+ struct sockaddr_atmpvc addr;
+ extern struct stat devstat;
+ if (device_got_set)
+ return 0;
+ //info("PPPoATM setdevname_pppoatm: '%s'", cp);
+ memset(&addr, 0, sizeof addr);
+ if (text2atm(cp, (struct sockaddr *) &addr, sizeof(addr),
+ T2A_PVC | T2A_NAME) < 0) {
+ if(doit)
+ info("atm does not recognize: %s", cp);
+ return 0;
+ }
+ if (!doit) return 1;
+ //if (!dev_set_ok()) return -1;
+ memcpy(&pvcaddr, &addr, sizeof pvcaddr);
+ strlcpy(devnam, cp, sizeof devnam);
+ devstat.st_mode = S_IFSOCK;
+ if (the_channel != &pppoa_channel) {
+ the_channel = &pppoa_channel;
+ lcp_wantoptions[0].neg_accompression = 0;
+ lcp_allowoptions[0].neg_accompression = 0;
+ lcp_wantoptions[0].neg_asyncmap = 0;
+ lcp_allowoptions[0].neg_asyncmap = 0;
+ lcp_wantoptions[0].neg_pcompression = 0;
+ }
+ info("PPPoATM setdevname_pppoatm - SUCCESS:%s", cp);
+ device_got_set = 1;
+ return 1;
+}
+
+#define pppoatm_overhead() (llc_encaps ? 6 : 2)
+
+static void no_device_given_pppoatm(void)
+{
+ fatal("No vpi.vci specified");
+}
+
+static void set_line_discipline_pppoatm(int fd)
+{
+ struct atm_backend_ppp be;
+ be.backend_num = ATM_BACKEND_PPP;
+ if (!llc_encaps)
+ be.encaps = PPPOATM_ENCAPS_VC;
+ else if (!vc_encaps)
+ be.encaps = PPPOATM_ENCAPS_LLC;
+ else
+ be.encaps = PPPOATM_ENCAPS_AUTODETECT;
+ if (ioctl(fd, ATM_SETBACKEND, &be) < 0)
+ fatal("ioctl(ATM_SETBACKEND): %m");
+}
+
+#if 0
+static void reset_line_discipline_pppoatm(int fd)
+{
+ atm_backend_t be = ATM_BACKEND_RAW;
+ /* 2.4 doesn't support this yet */
+ (void) ioctl(fd, ATM_SETBACKEND, &be);
+}
+#endif
+
+static int connect_pppoatm(void)
+{
+ int fd;
+ struct atm_qos qos;
+
+ system ("/sbin/modprobe pppoatm");
+
+ if (!device_got_set)
+ no_device_given_pppoatm();
+ fd = socket(AF_ATMPVC, SOCK_DGRAM, 0);
+ if (fd < 0)
+ fatal("failed to create socket: %m");
+ memset(&qos, 0, sizeof qos);
+ qos.txtp.traffic_class = qos.rxtp.traffic_class = ATM_UBR;
+ /* TODO: support simplified QoS setting */
+ if (qosstr != NULL)
+ if (text2qos(qosstr, &qos, 0))
+ fatal("Can't parse QoS: \"%s\"");
+ qos.txtp.max_sdu = lcp_allowoptions[0].mru + pppoatm_overhead();
+ qos.rxtp.max_sdu = lcp_wantoptions[0].mru + pppoatm_overhead();
+ qos.aal = ATM_AAL5;
+ if (setsockopt(fd, SOL_ATM, SO_ATMQOS, &qos, sizeof(qos)) < 0)
+ fatal("setsockopt(SO_ATMQOS): %m");
+ /* TODO: accept on SVCs... */
+ if (connect(fd, (struct sockaddr *) &pvcaddr,
+ sizeof(struct sockaddr_atmpvc)))
+ fatal("connect(%s): %m", devnam);
+ pppoatm_max_mtu = lcp_allowoptions[0].mru;
+ pppoatm_max_mru = lcp_wantoptions[0].mru;
+ set_line_discipline_pppoatm(fd);
+ strlcpy(ppp_devnam, devnam, sizeof(ppp_devnam));
+ pppoa_fd = fd;
+ return fd;
+}
+
+static void disconnect_pppoatm(void)
+{
+ close(pppoa_fd);
+}
+
+static void send_config_pppoa(int mtu,
+ u_int32_t asyncmap,
+ int pcomp,
+ int accomp)
+{
+ int sock;
+ struct ifreq ifr;
+ if (mtu > pppoatm_max_mtu)
+ error("Couldn't increase MTU to %d", mtu);
+ sock = socket(AF_INET, SOCK_DGRAM, 0);
+ if (sock < 0)
+ fatal("Couldn't create IP socket: %m");
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ ifr.ifr_mtu = mtu;
+ if (ioctl(sock, SIOCSIFMTU, (caddr_t) &ifr) < 0)
+ fatal("ioctl(SIOCSIFMTU): %m");
+ (void) close (sock);
+}
+
+static void recv_config_pppoa(int mru,
+ u_int32_t asyncmap,
+ int pcomp,
+ int accomp)
+{
+ if (mru > pppoatm_max_mru)
+ error("Couldn't increase MRU to %d", mru);
+}
+
+void plugin_init(void)
+{
+#if defined(__linux__)
+ extern int new_style_driver; /* From sys-linux.c */
+ if (!ppp_available() && !new_style_driver)
+ fatal("Kernel doesn't support ppp_generic - "
+ "needed for PPPoATM");
+#else
+ fatal("No PPPoATM support on this OS");
+#endif
+ info("PPPoATM plugin_init");
+ add_options(pppoa_options);
+}
+struct channel pppoa_channel = {
+ options: pppoa_options,
+ process_extra_options: NULL,
+ check_options: NULL,
+ connect: &connect_pppoatm,
+ disconnect: &disconnect_pppoatm,
+ establish_ppp: &generic_establish_ppp,
+ disestablish_ppp: &generic_disestablish_ppp,
+ send_config: &send_config_pppoa,
+ recv_config: &recv_config_pppoa,
+ close: NULL,
+ cleanup: NULL
+};
--- ppp-2.4.2/pppd/plugins/pppoatm/atmsap.h.atm1 2004-10-05 17:35:56.772702152 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/atmsap.h 2004-10-05 17:25:10.826900840 +0100
@@ -0,0 +1,45 @@
+/* atmsap.h - ATM Service Access Point addressing definitions */
+
+/* Written 1996-1998 by Werner Almesberger, EPFL LRC/ICA */
+
+
+#ifndef _ATMSAP_H
+#define _ATMSAP_H
+
+#include <stdint.h>
+#include <linux/atmsap.h>
+
+
+/*
+ * Selected ISO/IEC TR 9577 Network Layer Protocol Identifiers (NLPID)
+ */
+
+#define NLPID_IEEE802_1_SNAP 0x80 /* IEEE 802.1 SNAP */
+
+/*
+ * Selected Organizationally Unique Identifiers (OUIs)
+ */
+
+#define ATM_FORUM_OUI "\x00\xA0\x3E" /* ATM Forum */
+#define EPFL_OUI "\x00\x60\xD7" /* EPF Lausanne, CH */
+
+/*
+ * Selected vendor-specific application identifiers (for B-HLI). Such an
+ * identifier consists of three bytes containing the OUI, followed by four
+ * bytes assigned by the organization owning the OUI.
+ */
+
+#define ANS_HLT_VS_ID ATM_FORUM_OUI "\x00\x00\x00\x01"
+ /* ATM Name System, af-saa-0069.000 */
+#define VOD_HLT_VS_ID ATM_FORUM_OUI "\x00\x00\x00\x02"
+ /* VoD, af-saa-0049.001 */
+#define AREQUIPA_HLT_VS_ID EPFL_OUI "\x01\x00\x00\x01" /* Arequipa */
+#define TTCP_HLT_VS_ID EPFL_OUI "\x01\x00\x00\x03" /* ttcp_atm */
+
+
+/* Mapping of "well-known" TCP, UDP, etc. port numbers to ATM BHLIs.
+ btd-saa-api-bhli-01.02 */
+
+void atm_tcpip_port_mapping(char *vs_id,uint8_t protocol,uint16_t port);
+
+#endif
--- ppp-2.4.2/pppd/plugins/pppoatm/atmres.h.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/atmres.h 2004-10-04 12:11:55.000000000 +0100
@@ -0,0 +1,36 @@
+/* atmres.h - Common definitions and prototypes for resolver functions */
+
+/* Written 1996,1998 by Werner Almesberger, EPFL-LRC/ICA */
+
+
+#ifndef _ATMRES_H
+#define _ATMRES_H
+
+#include <arpa/nameser.h>
+#include <linux/atm.h>
+
+
+/* Some #defines that may be needed if ANS isn't installed on that system */
+
+#ifndef T_ATMA
+#define T_ATMA 34
+#endif
+#ifndef ATMA_AESA
+#define ATMA_AESA 0
+#endif
+#ifndef ATMA_E164
+#define ATMA_E164 1
+#endif
+
+/* Return codes for text2atm and atm2text */
+
+#define TRY_OTHER -2
+#define FATAL -1 /* must be -1 */
+
+
+int ans_byname(const char *text,struct sockaddr_atmsvc *addr,int length,
+ int flags);
+int ans_byaddr(char *buffer,int length,const struct sockaddr_atmsvc *addr,
+ int flags);
+
+#endif
--- ppp-2.4.2/pppd/plugins/pppoatm/misc.c.atm1 2004-10-04 12:11:55.000000000 +0100
+++ ppp-2.4.2/pppd/plugins/pppoatm/misc.c 2004-10-04 12:11:55.000000000 +0100
@@ -0,0 +1,51 @@
+/* misc.c - Miscellaneous library functions */
+
+/* Written 1997-2000 by Werner Almesberger, EPFL-ICA/ICA */
+
+#if HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h> /* for htons */
+
+#include <atm.h>
+#include <atmsap.h>
+
+
+int __atmlib_fetch(const char **pos,...)
+{
+ const char *value;
+ int ref_len,best_len,len;
+ int i,best;
+ va_list ap;
+
+ va_start(ap,pos);
+ ref_len = strlen(*pos);
+ best_len = 0;
+ best = -1;
+ for (i = 0; (value = va_arg(ap,const char *)); i++) {
+ len = strlen(value);
+ if (*value != '!' && len <= ref_len && len > best_len &&
+ !strncasecmp(*pos,value,len)) {
+ best = i;
+ best_len = len;
+ }
+ }
+ va_end(ap);
+ if (best > -1) (*pos) += best_len;
+ return best;
+}
+
+
+void atm_tcpip_port_mapping(char *vs_id,uint8_t protocol,uint16_t port)
+{
+ memcpy(vs_id,ATM_FORUM_OUI "\x01",4);
+ vs_id[4] = protocol; /* e.g. IP_TCP or IP_UDP; from netinet/protocols.h */
+ vs_id[5] = (htons(port) >> 8) & 255;
+ vs_id[6] = htons(port) & 255;
+}