From 0fceb64d25ff3d9586549bb43d971c5eef904330 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Mon, 7 Jun 1999 10:23:42 +0200 Subject: Import ax25-apps 0.0.1 from tarball --- ax25ipd/process.c | 338 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 338 insertions(+) create mode 100644 ax25ipd/process.c (limited to 'ax25ipd/process.c') diff --git a/ax25ipd/process.c b/ax25ipd/process.c new file mode 100644 index 0000000..20bae7f --- /dev/null +++ b/ax25ipd/process.c @@ -0,0 +1,338 @@ +/* process.c Handle processing and routing of AX25 frames + * + * Copyright 1991, Michael Westerhof, Sun Microsystems, Inc. + * This software may be freely used, distributed, or modified, providing + * this header is not removed. + * + * This is the only module that knows about the internal structure of + * AX25 frames. + */ + +/* + * Dual port additions by M.Durrant and D.J.Dionne Feb 4, 1995 + */ + +#include "ax25ipd.h" +#include +/* if dual port the upper nibble will have a value of 1 (not 0) */ +#define FROM_PORT2(p) (((*(p+1))&0x10)!=0) +#define FOR_PORT2(p) (addrmatch(p,mycallsign2) || addrmatch(p,myalias2)) +/* ve3djf and ve3pnx addition above */ +#define IS_LAST(p) (((*(p+6))&0x01)!=0) +#define NOT_LAST(p) (((*(p+6))&0x01)==0) +#define REPEATED(p) (((*(p+6))&0x80)!=0) +#define NOTREPEATED(p) (((*(p+6))&0x80)==0) +#define IS_ME(p) (addrmatch(p,mycallsign) || addrmatch(p,myalias) || addrmatch(p,mycallsign2) || addrmatch(p,myalias2) ) +#define NOT_ME(p) (!(addrmatch(p,mycallsign) || addrmatch(p,myalias) || addrmatch(p,mycallsign2) || addrmatch(p,myalias2) ) ) +#define ARE_DIGIS(f) (((*(f+13))&0x01)==0) +#define NO_DIGIS(f) (((*(f+13))&0x01)!=0) +#define SETREPEATED(p) (*(p+6))|=0x80 +#define SETLAST(p) (*(p+6))|=0x01 + +unsigned char bcbuf[256]; /* Must be larger than bc_text!!! */ +int bclen; /* The size of bcbuf */ + +/* + * Initialize the process variables + */ + +void +process_init() +{ + bclen = -1; /* flag that we need to rebuild the bctext */ +} + +/* + * handle a frame given us by the kiss routines. The buf variable is + * a pointer to an AX25 frame. Note that the AX25 frame from kiss does + * not include the CRC bytes. These are computed by this routine, and + * it is expected that the buffer we have has room for the CRC bytes. + * We will either dump this frame, or send it via the IP interface. + * + * If we are in digi mode, we validate in several ways: + * a) we must be the next digi in line to pick up the packet + * b) the next site to get the packet (the next listed digi, or + * the destination if we are the last digi) must be known to + * us via the route table. + * If we pass validation, we then set the digipeated bit for our entry + * in the packet, compute the CRC, and send the packet to the IP + * interface. + * + * If we are in tnc mode, we have less work to do. + * a) the next site to get the packet (the next listed digi, or + * the destination) must be known to us via the route table. + * If we pass validation, we compute the CRC, and send the packet to + * the IP interface. + */ + +void +from_kiss(buf, l) +unsigned char *buf; +int l; +{ + unsigned char *a, *ipaddr; + + if (l<15) { + LOGL2("from_kiss: dumped - length wrong!\n"); + stats.kiss_tooshort++; + return; + } + + if (loglevel>2) + dump_ax25frame("from_kiss: ", buf, l); + + if(digi) { /* if we are in digi mode */ + a = next_addr(buf); + if(NOT_ME(a)){ + stats.kiss_not_for_me++; + LOGL4("from_kiss: (digi) dumped - not for me\n"); + return; + } + if (a==buf) { /* must be a digi */ + stats.kiss_i_am_dest++; + LOGL2("from_kiss: (digi) dumped - I am destination!\n"); + return; + } + SETREPEATED(a); + a = next_addr(buf); /* find who gets it after us */ + } else { /* must be tnc mode */ + a = next_addr(buf); +#ifdef TNC_FILTER + if (IS_ME(a)) { + LOGL2("from_kiss: (tnc) dumped - addressed to self!\n"); + return; + } +#endif + } /* end of tnc mode */ + + /* Lookup the IP address for this route */ + ipaddr = call_to_ip(a); + + if (ipaddr==NULL) { + if (is_call_bcast(a)) { + /* Warning - assuming buffer has room for 2 bytes */ + add_crc(buf, l); l+=2; + send_broadcast(buf, l); + } else { + stats.kiss_no_ip_addr++; + LOGL2("from_kiss: dumped - cannot figure out where to send this!\n"); + } + return; + } else { + /* Warning - assuming buffer has room for 2 bytes */ + add_crc(buf, l); l+=2; + send_ip(buf, l, ipaddr); + } +} + +/* + * handle a frame given us by the IP routines. The buf variable is + * a pointer to an AX25 frame. + * Note that the frame includes the CRC bytes, which we dump ASAP. + * We will either dump this frame, or send it via the KISS interface. + * + * If we are in digi mode, we only validate that: + * a) we must be the next digi in line to pick up the packet + * If we pass validation, we then set the digipeated bit for our entry + * in the packet, and send the packet to the KISS send routine. + * + * If we are in tnc mode, we validate pretty well nothing, just like a + * real TNC... #define FILTER_TNC will change this. + * We simply send the packet to the KISS send routine. + */ + +void +from_ip(buf, l) +unsigned char *buf; +int l; +{ + int port = 0; + unsigned char *a; + + if(!ok_crc(buf, l)){ + stats.ip_failed_crc++; + LOGL2("from_ip: dumped - CRC incorrect!\n"); + return; + } + l = l - 2; /* dump the blasted CRC */ + + if(l<15){ + stats.ip_tooshort++; + LOGL2("from_ip: dumped - length wrong!\n"); + return; + } + + if(loglevel>2)dump_ax25frame("from_ip: ", buf, l); + + if(digi){ /* if we are in digi mode */ + a = next_addr(buf); + if(NOT_ME(a)){ + stats.ip_not_for_me++; + LOGL2("from_ip: (digi) dumped - not for me!\n"); + return; + } + if(a==buf){ /* must be a digi */ + stats.ip_i_am_dest++; + LOGL2("from_ip: (digi) dumped - I am destination!\n"); + return; + } + if(dual_port == 1 && FOR_PORT2(a)){ + port = 0x10; + } + SETREPEATED(a); + } else { /* must be tnc mode */ + a = next_addr(buf); +#ifdef TNC_FILTER + if(NOT_ME(a)){ + LOGL2("from_ip: (tnc) dumped - I am not destination!\n"); + return; + } +#endif + } /* end of tnc mode */ + send_kiss(port, buf, l); +} + +/* + * Send an ID frame out the KISS port. + */ + +void +do_beacon() +{ + int i; + unsigned char *p; + + if(bclen == 0) return; /* nothing to do! */ + + if(bclen < 0) { /* build the id string */ + p = bcbuf; + *p++ = ('I'<<1); + *p++ = ('D'<<1); + *p++ = (' '<<1); + *p++ = (' '<<1); + *p++ = (' '<<1); + *p++ = (' '<<1); + *p++ = '\0' | 0x60; /* SSID, set reserved bits */ + + for(i=0;i<6;i++)*p++=mycallsign[i]; + *p++ = mycallsign[6] | 0x60; /* ensure reserved bits are set */ + SETLAST(bcbuf+7); /* Set the E bit -- last address */ + + *p++ = 0x03; /* Control field -- UI frame */ + + *p++ = 0xf0; /* Protocol ID -- 0xf0 is no protocol */ + + strcpy(p, bc_text); /* add the text field */ + + bclen = 16 + strlen(bc_text); /* adjust the length nicely */ + } + + if(loglevel>2)dump_ax25frame("do_beacon: ", bcbuf, bclen); + stats.kiss_beacon_outs++; + send_kiss(0, bcbuf, bclen); +} + +/* + * return true if the addresses supplied match + * modified for wildcarding by vk5xxx + */ +int +addrmatch(a,b) +unsigned char *a, *b; +{ + if((*a=='\0') || (*b=='\0'))return 0; + + if((*a++^*b++)&0xfe)return 0; /* "K" */ + if((*a++^*b++)&0xfe)return 0; /* "A" */ + if((*a++^*b++)&0xfe)return 0; /* "9" */ + if((*a++^*b++)&0xfe)return 0; /* "W" */ + if((*a++^*b++)&0xfe)return 0; /* "S" */ + if((*a++^*b++)&0xfe)return 0; /* "B" */ + if(((*b++)&0x1e)==0)return 1; /* ssid 0 matches all ssid's */ + if((*a++^*b)&0x1e)return 0; /* ssid */ +/* if((*a++^*b++)&0x1e)return 0; ssid (how it was ...) */ + return 1; +} + +/* + * return pointer to the next station to get this packet + */ +unsigned char * +next_addr(f) +unsigned char *f; +{ + unsigned char *a; + +/* If no digis, return the destination address */ + if(NO_DIGIS(f))return f; + +/* check each digi field. The first one that hasn't seen it is the one */ + a = f + 7; + do { + a += 7; + if(NOTREPEATED(a))return a; + }while(NOT_LAST(a)); + +/* all the digis have seen it. return the destination address */ + return f; +} + +/* + * tack on the CRC for the frame. Note we assume the buffer is long + * enough to have the two bytes tacked on. + */ +void +add_crc(buf, l) +unsigned char *buf; +int l; +{ + unsigned short int u; + + u = compute_crc(buf, l); + buf[l] = u&0xff; /* lsb first */ + buf[l+1] = (u>>8)&0xff; /* msb next */ +} + +/* + * Dump AX25 frame. + */ +void +dump_ax25frame(t, buf, l) +unsigned char *buf; +char *t; +int l; +{ +#ifdef DEBUG + int i; +#endif + unsigned char *a; + + printf("%s AX25: (l=%3d) ", t, l); + + if(l<15){ + printf("Bogus size...\n"); + return; + } + + printf("%s -> ", call_to_a(buf+7)); + printf("%s", call_to_a(buf)); + + if(ARE_DIGIS(buf)){ + printf(" v"); + a = buf+7; + do{ + a+=7; + printf(" %s", call_to_a(a)); + if(REPEATED(a))printf("*"); + }while(NOT_LAST(a)); + } + + printf("\n"); + +#ifdef DEBUG + for(i=0;i