Path: isy!liuida!sunic!news.funet.fi!fuug!mcsun!uunet!bonnie.concordia.ca!ccu.umanitoba.ca!access.usask.ca!alberta!cpsc.ucalgary.ca!xenlink!deraadt From: deraadt@xenlink.cuc.ab.ca (Theo de Raadt) Newsgroups: alt.sources Subject: SunOS AX25 device driver Keywords: AX25 KA9Q device driver Message-ID: Date: 10 Feb 92 10:20:56 GMT Sender: news@xenlink.uucp Followup-To: alt.sources.d Organization: Xenlink Lines: 1840 Nntp-Posting-Host: xenlink [ This device driver for the SunOS kernel allows the kernel network layer to send IP packets inside AX25 (using a TNC on a serial port), exactly like KA9Q NOS does. The AX25 device appears exactly (ok, minus possible bugs :-) like any other network device does to the kernel, so you can use any old regular SunOS TCP/IP programs (ftp, telnet, etc). (Tested on Sun3/60 and Sun4/260, SunOS4.1.1.) VERSION 1.0 deraadt@lego.cuc.ab.ca ] Actually, mail to me at deraadt@xenlink.cuc.ab.ca. Other mail paths are broken. 'Makefile' <<'END_OF_FILE' XCFLAGS= -g XBIN= ax25ether ax25 X Xall: $(BIN) X Xclean: X $(RM) *.o *~ $(BIN) END_OF_FILE if test 73 -ne `wc -c <'Makefile'`; then echo shar: \"'Makefile'\" unpacked with wrong size! fi # end of 'Makefile' fi if test -f 'README' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'README'\" else echo shar: Extracting \"'README'\" \(3792 characters\) sed "s/^X//" >'README' <<'END_OF_FILE' XSTATUS: XTested on a Sun3/60 and a Sun4/260 running SunOS4.1.1, using a PacComm XTiny-2 TNC, and talking with other NOS sites in Calgary, Alberta. X XINSTALL: X0. Substitute the name 'KERNEL_CONFIG_FILE' in the following steps with the X kernel configuration file for your new kernel (If in doubt, make a copy X of GENERIC, and use it). X Also, substitute 'sun3' with whatever the command 'arch -k' says X your kernel architecture is. X X1. First, you need to add the device driver to the kernel. Add this line to X /usr/sys/sun3/conf/KERNEL_CONFIG_FILE. X pseudo-device ax1 init ax_attach X ^ this number determines how many TNCs you can hook up. X X2. splice these sections in the appropriate (fairly obvious) places in X /usr/sys/sun/str_conf.c X #include "ax.h" X X #if NAX > 0 X extern struct streamtab axinfo; X #endif X X #if NAX > 0 X { "ax25", &axinfo }, X #endif X X3. add this line to /usr/sys/conf.common/files.cmn X os/tty_ax.c optional ax X X4. Install the needed files in the kernel sys tree X # cp tty_ax.c /usr/sys/os X # cp if_ax.h /usr/include/sys X # cp if_ax.h /usr/sys/sys X X5. Build the kernel X # cd /usr/sys/sun3/conf X # config KERNEL_CONFIG_FILE X # cd ../KERNEL_CONFIG_FILE X # make X # mv /vmunix /vmunix.save X # cp vmunix /vmunix X X6. Reboot your machine to start up the new kernel. X X7. Now, build the two user level programs: ax25ether and ax25, and give X it a try. X # make X X8. Put your hostname in /etc/hosts with the correct IP address. X 44.135.145.28 ve6uug-0 X X9. Ensure that the netmask for network #44 is correct. Ussually it should X be 0xffffff00. Put that in /etc/netmasks, like this. X 44 255.255.255.0 X (If you are running YP, you may need to rebuild the databases. X # (cd /var/yp; make) X ) X X10. Ensure your TNC is in KISS mode, with the proper KISS timing parameters X already set. Now we can start up the interface. X X # ./ax25 -v ve6uug-0 ve6uug-0 /dev/ttyb X popping module: ttcompat X popping module: ldterm X pushing module: ax25 X network device: ax0 X addresses: ax25 ac.8a.6c.aa.aa.8e.60 'VE6UUG-0' = ether 99:da:55:b5:d6:70 X execute: ifconfig ax0 ve6uug-0 netmask + broadcast + up X Setting netmask of ax0 to 255.255.255.0 X X The first instance of your callsign is resolved according to /etc/hosts X to generate an IP address. The second instance of your callsign determines X what your AX25 hardware address is, which is what other parties use to X actually send a packet to your hardware. X X11. Check to see if the interface has come up. X # netstat -in X Name Mtu Net/Dest Address Ipkts Ierrs Opkts Oerrs Collis Queue X le0 1500 136.159.222.0 136.159.222.1 3871 0 1847 0 0 0 X lo0 1536 127.0.0.0 127.0.0.1 339 0 339 0 0 0 X ax0 1000 44.135.145.0 44.135.145.28 0 0 0 0 0 0 X X12. Try to talk to a few other hosts, ie. telnet, finger, etc. X XBUGS: XGenerally, etherfind seems to work, but only on the second and successive Xattempts. The first attempt fails with an NIOCBIND error. No idea why. X XPackets with digipeater addresses in their header are dropped on the floor Ximmediately. Proper digipeater support cannot be easily added. (My opinion: Xdigipeating is a dumb idea). X XDTR behaviour: M_HANGUP and M_UNHANGUP streams messages are not handled Xcorrectly. Currently, it's best to your TNC's DTR line. X XOTHER NOTES: XThe kernel ARP routines can only deal with 6 byte ethernet addresses. A Xbizzare encoding scheme is used to encode AX25 7-byte addresses into these X6-byte addresses. When AX25 addresses are converted, the resulting ethernet Xaddresses always have their upper byte set to 0x99. The program ax25ether Xwill convert between AX25 addresses and ethernet addresses as shown using Xthe arp command. END_OF_FILE if test 3792 -ne `wc -c <'README'`; then echo shar: \"'README'\" unpacked with wrong size! fi # end of 'README' fi if test -f 'ax25.8' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ax25.8'\" else echo shar: Extracting \"'ax25.8'\" \(3814 characters\) sed "s/^X//" >'ax25.8' <<'END_OF_FILE' X.\" manual page v0.1 for ax25 pl-0 X.\" SH section heading X.\" SS subsection heading X.\" LP paragraph X.\" IP indented paragraph X.\" TP hanging label X.TH AX25 8 X.SH NAME Xax25 \- AX25/IP ifconfig Utility X.SH SYNOPSIS X.B ax25 X[ X.I \-v X] X.I X.I X.I X.SH DESCRIPTION X.LP XAmateur packet radio enthusiasts nowadays send IP packets over radio Xlinks. Hanging off a serial port on their computer, TNC modems are Xused to provide CSMA-like behaviour so that the single radio channel Xcan be shared between multiple stations (somewhat like how ethernet Xworks). Packet radio is a broadcast medium, hence the TNC is Xresponsible for sharing the bandwidth with other TNC's. The computer Xtalking to the TNC must use a protocol called KISS (a simple Xderivative of SLIP encoding) to send/receive packets to/from the TNC. X.LP XAX25 packets vary in length. The packet header at the start of the Xpacket has four parts: X.TP X1. XA (guaranteed to be) unique source address. X.TP X2. XA destination addresses. X.TP X3. XAn AX25 packet type field. In our case it is always set to XUI, to indicate that this is an AX25 datagram. X.TP X4. XA small number, choosing between various higher level Xprotocols, called the protocol ID. X.LP XThe addresses found in the header are a simple 7-byte encoding of the XHAM radio call sign and substation ID. These addresses are used just Xlike ethernet hardware addresses are, to provide a unique name for Xeach station. The protocol ID can choose between many protocols but Xusers of IP-over-AX25 under Unix are really only concerned with two XAX25 sub-protocols: ARP and IP. X.LP XAX25 packets (received via KISS encoding from the TNC) which are found Xto contain ARP or IP datagrams are decoded and handed off to the Xkernel networking code. Similarily, the network code gives outbound Xdatagrams to the AX25 device driver, where the reverse process occurs: Xthey are encapsulated in AX25 packets and, after KISS encoding, sent Xoff to the TNC for transmission. X.LP XBoth incoming and outgoing ARP datagrams require special handling. XThe Unix kernel's internal ARP cache contains translations between X4-byte IP addresses and 6-byte ethernet addresses. It's convenient to Xnot rewrite the kernel's ARP implementation, so an encoding scheme was Xdeveloped which converts 7-byte AX25 addresses to/from 6-byte ethernet Xaddresses. This is too twisted to describe here, so refer to the Xdevice driver source. X.LP X.SH OPTIONS XYou must be root to run this. It's a good idea to start it from X/etc/rc.local in the background. X.TP X.B \-v XPrint out more information while setting up the link. X.TP X.B XThis provides the IP address for the network port. This name gets passed Xto ifconfig(8), so it can be a name out of the hosts(5) database. X.TP X.B XThis is your HAM call sign, with your substation ID. X.TP X.B XCommunicate over the named device at 9600 baud. X.LP X.SH EXAMPLE X.IP Xax25 44.135.145.28 ve6uug-0 /dev/ttyb X\".SH FILES X.SH SEE ALSO XMike Chepponis (K3MC), Phil Karn (KA9Q). X.I The KISS TNC: A simple Host\-to\-TNC communications protocol. X.LP XPacComm. X.I Operating Manual for PacComm Packet Controllers, pg. 31. X.TP X.B RFC1055 XRomkey, J. X.I A Nonstandard for Transmission of IP Datagrams Over Serial Lines: SLIP X.LP XThe README file supplied with this AX25 package. X.LP X\".SH DIAGNOSTICS X\".SH NOTES X.SH BUGS XEtherfind doesn't work as expected the first time you run it! X.LP XTNC's that toggle DTR for each packet can cause problems because Xstreams M_HANGUP and M_UNHANGUP messages are treated incorrectly. If Xyou see console messages about M_HANGUP and M_UNHANGUP, cutting the XDTR line will solve the problem. X.LP X.SH AUTHORS XTheo de Raadt \ [kernel hack] X.LP XWilliam Graham (VE6UUG) \ [HAM] X.LP END_OF_FILE if test 3814 -ne `wc -c <'ax25.8'`; then echo shar: \"'ax25.8'\" unpacked with wrong size! fi # end of 'ax25.8' fi if test -f 'ax25.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ax25.c'\" else echo shar: Extracting \"'ax25.c'\" \(3577 characters\) sed "s/^X//" >'ax25.c' <<'END_OF_FILE' X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X Xu_char ax25broadcastaddr[7] = { X 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 X}; Xstatic struct ether_addr etherbroadcastaddr = { X 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, X}; X Xint Xmain(argc, argv) Xchar **argv; X{ X struct termios tios; X u_char ax25[7]; X struct ether_addr eth; X char cmd[128], name[64]; X u_char *cp, c; X int verbose = 0; X int unit = 777; X int fd, i; X X if(argc<4) { X printf("usage: %s [-v] inet-addr ham-call-sign tty\n", *argv); X exit(0); X } X X if( !strcmp(argv[1], "-v") ) { X verbose = 1; X argv++; X } X X fd = open(argv[3], O_RDWR); X if(fd == -1) { X perror("open"); X exit(1); X } X X while(1) { X if(verbose) X if(ioctl(fd, I_LOOK, name) != -1) X printf("popping module: %s\n", name); X if(ioctl(fd, I_POP, 0) == -1) X break; X } X X if( ioctl(fd, TCGETS, &tios) <0) { X perror("ioctl TCGETS"); X exit(1); X } X X tios.c_cflag = CRTSCTS | B9600; X tios.c_cflag |= CS8|CREAD|HUPCL; X tios.c_iflag = IGNBRK; X if( ioctl(fd, TCSETS, &tios) <0) { X perror("ioctl TCSETS"); X exit(1); X } X X if(verbose) X printf("pushing module: ax25\n"); X if( ioctl(fd, I_PUSH, "ax25") == -1) { X perror("ioctl I_PUSH"); X exit(1); X } X X if( ioctl(fd, AXIOGUNIT, &unit) != -1) { X if(verbose) X printf("network device: ax%d\n", unit); X } else { X perror("ioctl AXIOGUNIT"); X exit(1); X } X X /* X * convert the HAM call sign to an ax25_addr X */ X i = 0; X bzero((caddr_t)ax25, sizeof(ax25)); X for(cp=(u_char *)argv[2]; *cp && (i<6); cp++) { X if(*cp=='-') { X cp++; X break; X } X c = islower(*cp) ? toupper(*cp) : *cp; X ax25[i++] = (u_char)(c << 1); X } X while(i<6) X ax25[i++] = (u_char)(' ' << 1); X while(*cp=='-') X cp++; X if(*cp) X ax25[6] = (u_char)(*cp << 1); X X ax_ax2ether(ax25, ð); X if( ioctl(fd, AXIOSHADDR, ð) == -1) { X perror("ioctl AXIOSHADDR"); X exit(1); X } X X sprintf(cmd, "ifconfig ax%d %s netmask + broadcast + up", X unit, argv[1]); X if(verbose) X printf("execute: %s\n", cmd); X system(cmd); X X while(sigpause(0)!=-1) X ; X return 0; X} X X X/* X * convert an ax25 address to an ether_addr X */ Xax_ax2ether(axhp, ethp) Xu_char *axhp; Xstruct ether_addr *ethp; X{ X u_char c; X int i; X X printf("addresses: ax25 "); X for(i=0; i<6; i++) X printf("%02x.", axhp[i]); X printf("%02x '", axhp[6]); X X for(i=0; i<(7-1); i++) X printf("%c", axhp[i]>>1); X printf("-%c' = ether ", axhp[6]>>1); X X if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr, X sizeof(ax25broadcastaddr)) ) { X bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp, X sizeof(struct ether_addr)); X goto done; X } X X ethp->ether_addr_octet[0] = 0x99; X c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc); X c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03); X ethp->ether_addr_octet[1] = c; X c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0); X c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f); X ethp->ether_addr_octet[2] = c; X c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0); X c |= ((((axhp[3]>>1) - ' ') ) & 0x3f); X ethp->ether_addr_octet[3] = c; X c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc); X c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03); X ethp->ether_addr_octet[4] = c; X c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0); X c |= ((((axhp[6]>>1) - '0') ) & 0x0f); X ethp->ether_addr_octet[5] = c; X Xdone: X for(i=0; iether_addr_octet[i]); X printf("%02x\n", ethp->ether_addr_octet[5]); X return 0; X} X END_OF_FILE if test 3577 -ne `wc -c <'ax25.c'`; then echo shar: \"'ax25.c'\" unpacked with wrong size! fi # end of 'ax25.c' fi if test -f 'ax25ether.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'ax25ether.c'\" else echo shar: Extracting \"'ax25ether.c'\" \(4192 characters\) sed "s/^X//" >'ax25ether.c' <<'END_OF_FILE' X#include X#include X#include X#include X#include X#include X#include X Xu_char ax25broadcastaddr[7] = { X 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 X}; Xstatic struct ether_addr etherbroadcastaddr = { X 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, X}; Xstatic struct ether_addr ethernulladdr; X X/* X * convert an ax25 address to an ether_addr X */ Xax_ax2ether(axhp, ethp) Xu_char *axhp; Xstruct ether_addr *ethp; X{ X u_char c; X int i; X X for(i=0; i<6; i++) X printf("%02x.", axhp[i]); X printf("%02x '", axhp[6]); X X for(i=0; i<(7-1); i++) X printf("%c", axhp[i]>>1); X printf("-%c' == ", axhp[6]>>1); X X if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr, X sizeof(ax25broadcastaddr)) ) { X bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp, X sizeof(struct ether_addr)); X goto done; X } X X ethp->ether_addr_octet[0] = 0x99; X c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc); X c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03); X ethp->ether_addr_octet[1] = c; X c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0); X c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f); X ethp->ether_addr_octet[2] = c; X c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0); X c |= ((((axhp[3]>>1) - ' ') ) & 0x3f); X ethp->ether_addr_octet[3] = c; X c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc); X c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03); X ethp->ether_addr_octet[4] = c; X c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0); X c |= ((((axhp[6]>>1) - '0') ) & 0x0f); X ethp->ether_addr_octet[5] = c; X Xdone: X for(i=0; iether_addr_octet[i]); X printf("%02x\n", ethp->ether_addr_octet[5]); X return 0; X} X X/* X * convert an ether_addr to an ax25 address X */ Xax_ether2ax(ethp, axhp) Xstruct ether_addr *ethp; Xu_char *axhp; X{ X u_char c; X int i; X X for(i=0; iether_addr_octet[i]); X printf("%02x == ", ethp->ether_addr_octet[5]); X X if( !bcmp((caddr_t)ethp, (caddr_t)ðernulladdr, X sizeof(struct ether_addr))) { X printf("nothing\n"); X return; X } X if( !bcmp((caddr_t)ethp, (caddr_t)ðerbroadcastaddr, X sizeof(struct ether_addr))) { X axhp[0] = 'Q' << 1; X axhp[1] = 'S' << 1; X axhp[2] = 'T' << 1; X axhp[3] = ' ' << 1; X axhp[4] = ' ' << 1; X axhp[5] = ' ' << 1; X axhp[6] = '0' << 1; X goto done; X } X X c = ethp->ether_addr_octet[0]; X if(c != 0x99) { X printf("[NO MAPPING]\n"); X for(i=0; i<7; i++) X axhp[i] = (i+1) << 1; X return; X } X c = (ethp->ether_addr_octet[1] >> 2) & 0x3f; X axhp[0] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[1] << 4) & 0x30; X c |= (ethp->ether_addr_octet[2] >> 4) & 0x0f; X axhp[1] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[2] << 2) & 0x3c; X c |= (ethp->ether_addr_octet[3] >> 6) & 0x03; X axhp[2] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[3] ) & 0x3f; X axhp[3] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[4] >> 2) & 0x3f; X axhp[4] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[4] << 4) & 0x30; X c |= (ethp->ether_addr_octet[5] >> 4) & 0x0f; X axhp[5] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[5] ) & 0x0f; X axhp[6] = (u_char)((c + '0') << 1); X Xdone: X for(i=0; i<6; i++) X printf("%02x.", axhp[i]); X printf("%02x '", axhp[6]); X X for(i=0; i<6; i++) X printf("%c", (axhp[i]>>1) & 0x7f ); X printf("-%c'\n", (axhp[6]>>1) & 0x7f ); X} X Xmain(argc, argv) Xchar **argv; X{ X u_char ax25[7]; X struct ether_addr eth; X u_char *cp, c; X int i; X X if(argc<3) { X fprintf(stderr, "usage: %s af addr\n", argv[0]); X fprintf(stderr, "\taf=ax25, ether\n"); X exit(0); X } X X if( !strcmp(argv[1], "ax25")) { X i = 0; X bzero((caddr_t)ax25, sizeof(ax25)); X for(cp=(u_char *)argv[2]; *cp && (i<6); cp++) { X if(*cp=='-') { X cp++; X break; X } X c = islower(*cp) ? toupper(*cp) : *cp; X ax25[i++] = (u_char)(c << 1); X } X while(i<6) X ax25[i++] = (u_char)(' ' << 1); X while(*cp=='-') X cp++; X if(*cp) X ax25[6] = (u_char)(*cp << 1); X ax_ax2ether(ax25, ð); X X } else if( !strcmp(argv[1], "ether")) { X bcopy((caddr_t)ether_aton(argv[2]), (caddr_t)ð, X sizeof(struct ether_addr)); X ax_ether2ax(ð, ax25); X } else X printf("what?\n"); X return 0; X} END_OF_FILE if test 4192 -ne `wc -c <'ax25ether.c'`; then echo shar: \"'ax25ether.c'\" unpacked with wrong size! fi # end of 'ax25ether.c' fi if test -f 'if_ax.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'if_ax.h'\" else echo shar: Extracting \"'if_ax.h'\" \(1890 characters\) sed "s/^X//" >'if_ax.h' <<'END_OF_FILE' X#ifndef _if_ax_h_ X#define _if_ax_h_ X X#define AXIOGUNIT _IOR(x, 111, int) /* get unit number */ X#define AXIOSHADDR _IOW(x, 112, struct ether_addr) /* set ether_addr */ X X#define AXSTREAMNAME "ax25" /* streams module name */ X#define AXIFNAME "ax" /* interface name */ X#define AX25MTU 1000 /* max ax25 packet size */ X X/* An ax25 address is encoded as a struct ether_addr so that it can fit X * in the arp tables. X * X * encoding format in struct ether_addr X * ________ ______ ______ ______ ______ ______ ______ _____ X * | 8 | 6 | 6 | 6 | 6 | 6 | 6 | 4 | X * |________|______|______|______|______|______|______|_____| X * X * The upper byte of ether_addr is set to 0x99. X * X * The next 6 6-bit fields are each filled with an ax25_addr.aa_c[] entry, X * shifted back to normal ASCII, and then offset from ASCII space X * (ie. aa_c[0] - ' '). X * X * The sid has values ASCII '0' -> ASCII '0'+15. ASCII '0' is subtraced and X * the low 4 bits of the ether_addr are set from that. X */ X X/* screw digipeaters */ Xstruct ax25_hdr { X u_char ah_dst[7], ah_src[7]; X u_char ah_cmd; X u_char ah_pid; X}; X X/* X * AX25 commands. All others are tossed. X */ X#define AX25CMD_UI 0x03 /* AX25 datagram */ X X/* X * AX25 Protocol IDs. All others are tossed. X */ X#define AX25PID_IP 0xcc /* ARPA IP */ X#define AX25PID_ARP 0xcd /* ARPA ARP */ X X/* X * AX25 ARP address types. X */ X#define AX25_HARDTYPE 0x0003 X#define AX25_IPTYPE ((short)AX25PID_IP) X X/* X * KISS framing. This is SLIP. X */ X#define KISS_END 0xc0 X#define KISS_ESC 0xdb X#define KISS_TEND 0xdc X#define KISS_TESC 0xdd X X/* X * KISS commands - first data byte inside the KISS packet. X */ X#define KISS_DATA 0x00 X#define KISS_TXDELAY 0x01 X#define KISS_PERSISTANCE 0x02 X#define KISS_SLOTTIME 0x03 X#define KISS_TXTAIL 0x04 X#define KISS_FULLDUPLEX 0x05 X#define KISS_HARDWARE 0x06 X#define KISS_QUIT 0xff X X#endif /* _if_ax_h_ */ END_OF_FILE if test 1890 -ne `wc -c <'if_ax.h'`; then echo shar: \"'if_ax.h'\" unpacked with wrong size! fi # end of 'if_ax.h' fi if test -f 'tty_ax.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'tty_ax.c'\" else echo shar: Extracting \"'tty_ax.c'\" \(23598 characters\) sed "s/^X//" >'tty_ax.c' <<'END_OF_FILE' X/* X * KISS+AX25 IP streams module for sunos 4.x X * X * Copyright 1991, 1992 by Theo de Raadt X * X * Theo de Raadt X * Thanks to William Graham for AX25 specs. X * X * Streams ideas ripped off from PPP and SLIP implimentations for X * Sunos by Brad Clements and Rayan Zachariassen respectively. X */ X#undef DEBUG X#undef DEBUG2 X#define AX_NIT X X#include "ax.h" X#if NAX > 0 X X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X#include X X#include X X#include X#include X#include X#include X X#include X X#include X#include X#include X X#ifdef AX_NIT Xstatic struct ether_header nitheader = { {{1}}, {{2}}, ETHERTYPE_IP }; Xstatic struct nit_if nif = {(caddr_t)&nitheader, sizeof(nitheader), 0, 0}; X Xstatic struct ether_header nitheader_arp = { {{1}}, {{2}}, ETHERTYPE_ARP }; Xstatic struct nit_if nif_arp = {(caddr_t)&nitheader_arp, sizeof(nitheader_arp), 0, 0}; X#endif X Xint ax_attach(); Xstatic int ax_open(), ax_close(), ax_rput(), ax_wput(), ax_wsrv(); Xstatic int ax_ioctl(), ax_output(); Xstatic struct mbuf *ax_btom(); X Xstatic struct module_info minfo = { X 0xabce, AXSTREAMNAME, 0, INFPSZ, 16384, 4096 X}; X Xstatic struct qinit r_init = { X ax_rput, NULL, ax_open, ax_close, NULL, &minfo, NULL X}; X Xstatic struct qinit w_init = { X ax_wput, ax_wsrv, ax_open, ax_close, NULL, &minfo, NULL X}; X Xstruct streamtab axinfo = { X &r_init, &w_init, NULL, NULL, NULL X}; X Xstatic struct axpriv { X struct arpcom arpcom; X queue_t *q; X u_char *buf; X u_char *dp; X u_int inlen; X u_char gotesc, toobig; X} axpriv[NAX]; X Xstatic u_char ax25broadcastaddr[7] = { X 'Q'<<1, 'S'<<1, 'T'<<1, ' '<<1, ' '<<1, ' '<<1, '0'<<1 X}; Xstatic struct ether_addr ethernulladdr; X Xint Xax_attach(unit) Xint unit; X{ X register struct ifnet *ifp = &axpriv[unit].arpcom.ac_if; X X ifp->if_name = AXIFNAME; X ifp->if_mtu = AX25MTU; X ifp->if_flags = IFF_BROADCAST; X ifp->if_unit = unit; X ifp->if_ioctl = ax_ioctl; X ifp->if_output = ax_output; X ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; X if_attach(ifp); X return 0; X} X Xstatic int Xax_open(q, dev, flag, sflag) Xqueue_t *q; Xdev_t dev; Xint flag, sflag; X{ X struct axpriv *axp; X int unit, s; X X if( !suser()) { X u.u_error = EPERM; X return OPENFAIL; X } X X s = splstr(); X for( unit=0; unitbuf) X continue; X if(axp->arpcom.ac_if.if_mtu == 0) X ax_attach(unit); X axp->arpcom.ac_if.if_flags |= IFF_RUNNING; X axp->buf = (u_char *)kmem_alloc(AX25MTU); X axp->dp = axp->buf + sizeof(struct ifnet *); X axp->inlen = 0; X axp->q = WR(q); X WR(q)->q_ptr = q->q_ptr = (caddr_t)axp; X (void) splx(s); X log(LOG_INFO, "ax%d: coming up\n", unit); X return unit; X } X splx(s); X log(LOG_INFO, "ax%d: no more devices available\n", NAX); X return OPENFAIL; X} X Xstatic int Xax_close(q, flag) Xqueue_t *q; Xint flag; X{ X struct axpriv *axp; X int s; X X s = splimp(); X axp = (struct axpriv *)q->q_ptr; X if(axp) { X log(LOG_INFO, "ax%d: going down\n", axp->arpcom.ac_if.if_unit); X if_down(&axp->arpcom.ac_if); X axp->arpcom.ac_if.if_flags &= ~(IFF_UP|IFF_RUNNING); X if(axp->buf) X kmem_free(axp->buf, AX25MTU); X axp->buf = NULL; X axp->q = NULL; X } X (void) splx(s); X} X Xstatic int Xax_wput(q, mp) Xqueue_t *q; Xmblk_t *mp; X{ X struct axpriv *axp; X char ax25[7]; X struct iocblk *iocp; X X switch(mp->b_datap->db_type) { X case M_FLUSH: X if(*mp->b_rptr & FLUSHW) X flushq(q, FLUSHDATA); X putnext(q, mp); X break; X case M_DATA: X putq(q, mp); X break; X case M_IOCTL: X iocp = (struct iocblk *)mp->b_rptr; X axp = (struct axpriv *)q->q_ptr; X switch(iocp->ioc_cmd) { X case AXIOSHADDR: X bcopy((caddr_t)mp->b_cont->b_rptr, X (caddr_t)&axp->arpcom.ac_enaddr, X sizeof(struct ether_addr)); X mp->b_datap->db_type = M_IOCACK; X iocp->ioc_rval = iocp->ioc_count = iocp->ioc_error = 0; X qreply(q, mp); X log(LOG_INFO, "ax%d: ether %2x:%2x:%2x:%2x:%2x:%2x ax25 ", X axp->arpcom.ac_if.if_unit, X axp->arpcom.ac_enaddr.ether_addr_octet[0], X axp->arpcom.ac_enaddr.ether_addr_octet[1], X axp->arpcom.ac_enaddr.ether_addr_octet[2], X axp->arpcom.ac_enaddr.ether_addr_octet[3], X axp->arpcom.ac_enaddr.ether_addr_octet[4], X axp->arpcom.ac_enaddr.ether_addr_octet[5]); X ax_ether2ax(&axp->arpcom.ac_enaddr, ax25); X print_ax25addr(ax25); X printf("\n"); X return; X case AXIOGUNIT: X iocp->ioc_rval = 0; X if( mp->b_cont = allocb(sizeof(int), BPRI_MED) ) { X u_char *cp = mp->b_cont->b_wptr; X X mp->b_datap->db_type = M_IOCACK; X *((int *)cp) = axp->arpcom.ac_if.if_unit; X mp->b_cont->b_wptr += sizeof(int); X iocp->ioc_count = sizeof(int); X iocp->ioc_error = 0; X qreply(q, mp); X break; X } X iocp->ioc_error = ENOSR; X mp->b_datap->db_type = M_IOCNAK; X qreply(q, mp); X return; X default: X log(LOG_INFO, "ax%d: unknown ioc %8x\n", X axp->arpcom.ac_if.if_unit, iocp->ioc_cmd); X putnext(q, mp); X return; X } X break; X default: X putnext(q, mp); X } X} X Xstatic int Xax_rput(q, mp) Xqueue_t *q; Xmblk_t *mp; X{ X struct axpriv *axp = (struct axpriv *)q->q_ptr; X struct ifnet *ifp; X register u_char c, *rp; X register mblk_t *bp; X struct mbuf *m; X int proto, forus, s; X X if( axp==NULL ) { X log(LOG_INFO, "ax_rput: axp is NULL\n"); X freemsg(mp); X return; X } X if( axp->buf==NULL ) { X log(LOG_INFO, "ax_rput: axp->buf is NULL\n"); X freemsg(mp); X return; X } X X ifp = &axp->arpcom.ac_if; X switch(mp->b_datap->db_type) { X case M_DATA: X break; X case M_FLUSH: X if(*mp->b_rptr & FLUSHR) X flushq(q, FLUSHDATA); X putnext(q, mp); X return; X case M_UNHANGUP: X log(LOG_INFO, "ax%d: M_UNHANGUP\n", ifp->if_unit); X axp->q = WR(q); /* hook us up again */ X putnext(q, mp); X putctl1(q->q_next, M_PCSIG, SIGURG); X return; X case M_HANGUP: X log(LOG_INFO, "ax%d: M_HANGUP\n", ifp->if_unit); X s = splstr(); X axp->q = NULL; /* cause ax_output to return ENETDOWN */ X (void) splx(s); X putnext(q, mp); X return; X case M_BREAK: X case M_IOCACK: X putnext(q, mp); X return; X default: X log(LOG_INFO, "ax%d: rput streams message type %d discarded\n", X ifp->if_unit, mp->b_datap->db_type); X putnext(q, mp); X return; X } X X /* X * Perform the KISS protocol on the streams message, and add the bytes X * to a packet reconstruction buffer. When a complete AX25 packet has X * been collected, strip the AX25 layer and provide the IP (or ARP) packet X * inside to the networking code. X */ X for( bp=mp; bp; bp=bp->b_cont) { X rp = bp->b_rptr; X while( rp < bp->b_wptr) { X c = *rp++; X /*printf("K %2x\n", c);*/ X if(axp->gotesc) { X axp->gotesc = 0; X if(c==KISS_TEND) X c = KISS_END; X else if(c==KISS_TESC) X c = KISS_ESC; X#ifdef DEBUG X else X log(LOG_INFO, "ax%d: kiss ESC error (c=%d)\n", X ifp->if_unit, c); X#endif X } else if(c==KISS_END) { X if(axp->toobig) { X axp->toobig = 0; X /*printf("ax%d: packet toobig\n", X ifp->if_unit);*/ X axp->inlen = 0; X continue; X } X if(axp->inlen==0) X continue; X X /* X * buf contains KISS_DATA followed by an AX25 X * packet. Extract the IP packet lurking inside X * AX25 packet.. X */ X m = ax_btom(axp, &proto, &forus); X axp->dp = axp->buf + sizeof(struct ifnet *); X ifp->if_ipackets++; X axp->inlen = 0; X if(!m) { X ifp->if_ierrors++; X continue; X } X X switch(proto) { X case AX25PID_IP: X#ifdef AX_NIT X if(ifp->if_flags & IFF_PROMISC) { X struct mbuf *nm = m; X int len = 0; X X do { X len += nm->m_len; X } while( nm=nm->m_next ); X len -= sizeof(struct ifnet *); X m->m_off += sizeof(struct ifnet *); X nif.nif_bodylen = len; X snit_intr(&axp->arpcom, m, &nif); X m->m_off -= sizeof(struct ifnet *); X } X#endif X if(!forus) { X m_freem(m); X break; X } X s = splimp(); X if( IF_QFULL(&ipintrq) ) { X IF_DROP(&ipintrq); X ifp->if_ierrors++; X m_freem(m); X (void) splx(s); X } else { X IF_ENQUEUE(&ipintrq, m); X schednetisr(NETISR_IP); X (void) splx(s); X#ifdef DEBUG X log(LOG_INFO, "handing off to IP\n"); X#endif X } X break; X case AX25PID_ARP: X#ifdef AX_NIT X if(ifp->if_flags & IFF_PROMISC) { X struct mbuf *nm = m; X int len = 0; X X do { X len += nm->m_len; X } while( nm=nm->m_next ); X len -= sizeof(struct ifnet *); X m->m_off += sizeof(struct ifnet *); X nif_arp.nif_bodylen = len; X snit_intr(&axp->arpcom, m, &nif_arp); X m->m_off -= sizeof(struct ifnet *); X } X#endif X if(!forus) { X m_freem(m); X break; X } X#ifdef DEBUG X printf("[INCOMING ethernet arp packet]"); X ax25_arpdebug(m); X#endif X arpinput(&axp->arpcom, m); X break; X default: X#ifdef DEBUG2 X printf("ax%d: unknown protocol %d\n", X ifp->if_unit, X proto); X#endif X m_freem(m); X break; X } X continue; X } else if(c==KISS_ESC) { X axp->gotesc = 1; X continue; X } X if(++axp->inlen > AX25MTU) { X if(axp->toobig) X continue; X axp->toobig = 1; X ifp->if_ierrors++; X axp->dp = axp->buf + sizeof(struct ifnet *); X continue; X } else X *axp->dp++ = c; X } X bp->b_rptr = rp; X } X freemsg(mp); X return; X} X X Xstatic struct mbuf * Xax_btom(axp, protop, forusp) Xstruct axpriv *axp; Xint *protop, *forusp; X{ X struct ax25_hdr *ax; X struct mbuf *m, **mp, *top = NULL; X struct ifnet *ifp; X struct ether_addr oureth; X int len, count; X caddr_t cp; X X ax = (struct ax25_hdr *)(axp->buf + sizeof(struct ifnet *) + 1); X X /* X * digipeaters are not supported (they could be supported - could X * correct the AX25 packet's fields, KISS encode it, and send a X * message downstream to the TNC.) X * X * The IP packet must come in an AX25 UI frame. X */ X if(ax->ah_cmd != AX25CMD_UI) { X#ifdef DEBUG2 X printf("ax%d: ax25 frame not UI, cmd=%2x\n", X axp->arpcom.ac_if.if_unit, ax->ah_cmd); X#endif X return NULL; X } X X#ifdef DEBUG2 X printf("ax%d: ", axp->arpcom.ac_if.if_unit); X print_ax25addr(ax->ah_src); X printf("->"); X print_ax25addr(ax->ah_dst); X printf(" [%d]\n", axp->inlen - sizeof(struct ax25_hdr) - 1); X#endif X X /* X * is this packet to us? X */ X *forusp = 1; X ax_ax2ether(ax->ah_dst, &oureth); X if( bcmp((caddr_t)&oureth, (caddr_t)&axp->arpcom.ac_enaddr, X sizeof oureth) && X bcmp((caddr_t)ax25broadcastaddr, (caddr_t)&axp->arpcom.ac_enaddr, X sizeof oureth)) { X *forusp = 0; X } X X /* X * packet not for us, and not promisc mode --> can out. X */ X if( !(axp->arpcom.ac_if.if_flags & IFF_PROMISC) && *forusp==0) X return NULL; X X /* X * check acceptable protocols X */ X switch(ax->ah_pid) { X case AX25PID_IP: X case AX25PID_ARP: X break; X default: X#ifdef DEBUG2 X printf("ax%d: packet discarded - protocol %d\n", X axp->arpcom.ac_if.if_unit, ax->ah_pid); X#endif X return NULL; X } X X *protop = (int)(ax->ah_pid); X ifp = &axp->arpcom.ac_if; X cp = (caddr_t)(axp->buf + sizeof(struct ifnet *) + 1 + sizeof(struct ax25_hdr)); X mp = ⊤ X len = axp->inlen - 1 - sizeof(struct ax25_hdr); X while(len>0) { X MGET(m, M_DONTWAIT, MT_DATA); X if(m == NULL) { X if(top) X m_freem(top); X return NULL; X } X *mp = m; X if(ifp) { X m->m_off += sizeof(ifp); X count = MIN(len, MLEN - sizeof(ifp)); X bcopy(cp, mtod(m, caddr_t), count); X m->m_len = count; X m->m_off -= sizeof(ifp); X m->m_len += sizeof(ifp); X *mtod(m, struct ifnet **) = ifp; X ifp = NULL; X } else { X count = MIN(len, MLEN); X bcopy(cp, mtod(m, caddr_t), count); X m->m_len = count; X } X cp += count; X len -= count; X mp = &m->m_next; X } X if(ax->ah_pid== AX25PID_ARP) { X top->m_off += sizeof(ifp); /* XXX ax_ax2etherarp() weak */ X ax_ax2etherarp(top); X top->m_off -= sizeof(ifp); X } X X return top; X} X X Xstatic int Xax_wsrv(q) Xqueue_t *q; X{ X register mblk_t *mp; X X while( mp=getq(q) ) { X if( !canput(q->q_next)) { X putbq(q, mp); X return; X } X putnext(q, mp); X } X} X X/* %%% ifconfig ether #:#:#:#:#:# not working */ Xstatic int Xax_ioctl(ifp, cmd, data) Xstruct ifnet *ifp; Xint cmd; Xcaddr_t data; X{ X register struct ifaddr *ifa = (struct ifaddr *)data; X register struct ifreq *ifr = (struct ifreq *)data; X int error = 0, s; X X if(ifa==NULL) X return EFAULT; X s = splimp(); X switch(cmd) { X case SIOCSIFFLAGS: X if(!data) /* IFF_PROMISC change */ X break; X if(!suser()) { X error = EPERM; X break; X } X ifp->if_flags &= IFF_CANTCHANGE; X ifp->if_flags |= (ifr->ifr_flags & ~IFF_CANTCHANGE); X break; X case SIOCGIFFLAGS: X ifr->ifr_flags = ifp->if_flags; X break; X case SIOCSIFADDR: X switch(ifa->ifa_addr.sa_family) { X case AF_INET: X ((struct arpcom *)ifp)->ac_ipaddr = IA_SIN(ifa)->sin_addr; X ifp->if_flags |= IFF_UP; X break; X default: X error = EAFNOSUPPORT; X break; X } X break; X case SIOCSIFBRDADDR: X if(ifa->ifa_addr.sa_family != AF_INET) X error = EAFNOSUPPORT; X break; X case SIOCSIFNETMASK: X if(ifa->ifa_addr.sa_family != AF_INET) X error = EAFNOSUPPORT; X break; X default: X error = EINVAL; X } X (void) splx(s); X return error; X} X Xstatic int Xax_output(ifp, m0, dst) Xstruct ifnet *ifp; Xstruct mbuf *m0; Xstruct sockaddr *dst; X{ X struct axpriv *axp; X struct ax25_hdr ax25; X struct ether_header *eth; X struct mbuf *m = m0; X int i, len, s, n; X struct in_addr idst; X u_char *cp, *cp2; X mblk_t *mp; X X axp = &axpriv[ifp->if_unit]; X if(axp->q == NULL) X return ENETDOWN; X X /* printf("ax%d: trying to send packet\n", ifp->if_unit); */ X X switch(dst->sa_family) { X case AF_INET: X#ifdef AX_NIT X if(axp->arpcom.ac_if.if_flags & IFF_PROMISC) { X struct mbuf *nm = m0; X int len = 0; X X do { X len += nm->m_len; X } while( nm=nm->m_next ); X nif.nif_bodylen = len; X snit_intr(&axp->arpcom, m0, &nif); X } X X#endif X idst = ((struct sockaddr_in *)dst)->sin_addr; X ((struct arpcom *)ifp)->ac_lastip = idst; X m = m0; X if( !arpresolve((struct arpcom *)ifp, m)) { X return 0; X } X#ifdef DEBUG2 X len = 0; X for(m=m0; m; m=m->m_next) { X cp = mtod(m, u_char *); X n = m->m_len; X while(n-->0) { X if( !(len++ % 16) ) X printf("\n\t"); X printf("%2x ", *cp++); X } X } X if( len % 16 ) X printf("\n"); X#endif X ax25.ah_pid = AX25PID_IP; X ax_ether2ax(&((struct arpcom *)ifp)->ac_enaddr, ax25.ah_src); X ax_ether2ax(&((struct arpcom *)ifp)->ac_lastarp, ax25.ah_dst); X#ifdef DEBUG2 X printf("ax%d: sending to ", ifp->if_unit); X print_ax25addr(ax25.ah_dst); X printf("\n"); X#endif X break; X case AF_UNSPEC: X eth = (struct ether_header *)dst->sa_data; X switch(eth->ether_type) { X case ETHERTYPE_ARP: X case ETHERTYPE_REVARP: X#ifdef AX_NIT X if(axp->arpcom.ac_if.if_flags & IFF_PROMISC) { X struct mbuf *nm = m0; X int len = 0; X X do { X len += nm->m_len; X } while( nm=nm->m_next ); X nif_arp.nif_bodylen = len; X snit_intr(&axp->arpcom, m0, &nif_arp); X } X X#endif X#ifdef DEBUG2 X printf("AF_UNSPEC: ARP\n"); X printf("[ethernet arp packet]"); X len = 0; X for(m=m0; m; m=m->m_next) { X cp = mtod(m, u_char *); X n = m->m_len; X while(n-->0) { X if( !(len++ % 16) ) X printf("\n\t"); X printf("%2x ", *cp++); X } X } X if( len % 16 ) X printf("\n"); X#endif X X ax_ether2axarp(m0); X ax25.ah_pid = AX25PID_ARP; X ax_ether2ax(&((struct arpcom *)ifp)->ac_enaddr, ax25.ah_src); X ax_ether2ax(ð->ether_dhost, ax25.ah_dst); X#ifdef DEBUG2 X printf("[AX25 arp packet]"); X#endif X break; X default: X printf("AF_UNSPEC: unknown ether_type %4x", X ntohs(eth->ether_type)); X ax25.ah_pid = AX25PID_IP; /* wrong */ X ax_ether2ax(ð->ether_shost, ax25.ah_src); X ax_ether2ax(ð->ether_dhost, ax25.ah_dst); X break; X } X X#ifdef DEBUG2 X len = 0; X for(m=m0; m; m=m->m_next) { X cp = mtod(m, u_char *); X n = m->m_len; X while(n-->0) { X if( !(len++ % 16) ) X printf("\n\t"); X printf("%2x ", *cp++); X } X } X if( len % 16 ) X printf("\n"); X#endif X X break; X default: X log(LOG_INFO, "ax%d: cannot handle af%d\n", ifp->if_unit, X dst->sa_family); X m_freem(m0); X return EAFNOSUPPORT; X } X X ax25.ah_cmd = AX25CMD_UI; X ax25.ah_src[6] |= 0x01; /* %%% set low bit on src */ X X /* X * run through the ax25_hdr and the packet buffer counting X * how much space we need for KISS encoding. X */ X len = 2; /* KISS_END, KISS_DATA */ X for(i=0, cp=(u_char *)&ax25; i< sizeof(ax25); i++, cp++) { X len++; X if(*cp==KISS_END || *cp==KISS_ESC) X len++; X } X for(m=m0; m; m=m->m_next) { X cp = mtod(m, u_char *); X for(i=0; i< m->m_len; i++, cp++) { X len++; X if(*cp==KISS_END || *cp==KISS_ESC) X len++; X } X } X len++; /* KISS_END */ X X if( !(mp = allocb(len, BPRI_MED)) ) { X log(LOG_INFO, "ax%d: ax_output cannot allocb %d bytes\n", X ifp->if_unit, len); X m_freem(m0); X return ENOSR; X } X X#ifdef DEBUG2 X cp2 = mp->b_wptr; X#endif X X /* X * KISS-format the ax25 header and data into mp. X */ X *mp->b_wptr++ = KISS_END; X *mp->b_wptr++ = KISS_DATA; X for(i=0, cp=(u_char *)&ax25; ib_wptr++ = KISS_ESC; X *mp->b_wptr++ = KISS_TEND; X break; X case KISS_ESC: X *mp->b_wptr++ = KISS_ESC; X *mp->b_wptr++ = KISS_TESC; X break; X default: X *mp->b_wptr++ = *cp; X break; X } X } X for(m=m0; m; m=m->m_next) { X cp = mtod(m, u_char *); X for(i=0; i< m->m_len; i++, cp++) { X switch(*cp) { X case KISS_END: X *mp->b_wptr++ = KISS_ESC; X *mp->b_wptr++ = KISS_TEND; X break; X case KISS_ESC: X *mp->b_wptr++ = KISS_ESC; X *mp->b_wptr++ = KISS_TESC; X break; X default: X *mp->b_wptr++ = *cp; X break; X } X } X } X *mp->b_wptr++ = KISS_END; /* superfluous, really */ X X#ifdef DEBUG2 X printf("actual serial output:\n"); X while(cp2 < mp->b_wptr) X printf("%2x ", *cp2++); X printf("\n"); X#endif X X s = splstr(); X if(axp->q) X putq(axp->q, mp); X else X freemsg(mp); X (void) splx(s); X m_freem(m0); X return 0; X} X X/* X * convert an ethernet ARP packet to an AX25 ARP packet. The AX25 frame X * header is not included. X */ Xax_ether2axarp(m) Xstruct mbuf *m; X{ X struct arphdr *arp = mtod(m, struct arphdr *); X struct ether_addr eth1, eth2; X struct in_addr in1, in2; X caddr_t cp; X X arp->ar_hrd = AX25_HARDTYPE; X arp->ar_pro = AX25_IPTYPE; X arp->ar_hln = 7; X X cp = ((caddr_t)arp) + sizeof(struct arphdr); X bcopy(cp, (caddr_t)ð1, sizeof(struct ether_addr)); X cp += sizeof(struct ether_addr); X bcopy(cp, (caddr_t)&in1, sizeof(struct in_addr)); X cp += sizeof(struct in_addr); X bcopy(cp, (caddr_t)ð2, sizeof(struct ether_addr)); X cp += sizeof(struct ether_addr); X bcopy(cp, (caddr_t)&in2, sizeof(struct in_addr)); X X cp = ((caddr_t)arp) + sizeof(struct arphdr); X ax_ether2ax(ð1, (u_char *)cp); X cp += 7; X bcopy((caddr_t)&in1, cp, sizeof(struct in_addr)); X cp += sizeof(struct in_addr); X ax_ether2ax(ð2, (u_char *)cp); X cp += 7; X bcopy((caddr_t)&in2, cp, sizeof(struct in_addr)); X X m->m_len += 2; X return 0; X} X X/* X * convert an AX25 ARP packet to an ethernet ARP packet. The AX25 frame X * is assumed to have been already stripped off. X */ Xax_ax2etherarp(m) Xstruct mbuf *m; X{ X struct arphdr *arp = mtod(m, struct arphdr *); X u_char axa1[7], axa2[7]; X struct in_addr in1, in2; X caddr_t cp; X X#ifdef DEBUG2 X printf("[INCOMING AX25 arp packet]"); X ax25_arpdebug(m); X#endif X X arp->ar_hrd = ARPHRD_ETHER; X arp->ar_pro = ETHERTYPE_IP; X arp->ar_hln = sizeof(struct ether_addr); X X cp = ((caddr_t)arp) + sizeof(struct arphdr); X bcopy(cp, (caddr_t)axa1, 7); X cp += 7; X bcopy(cp, (caddr_t)&in1, sizeof(struct in_addr)); X cp += sizeof(struct in_addr); X bcopy(cp, (caddr_t)axa2, 7); X cp += 7; X bcopy(cp, (caddr_t)&in2, sizeof(struct in_addr)); X X cp = ((caddr_t)arp) + sizeof(struct arphdr); X ax_ax2ether(axa1, (struct ether_addr *)cp); X cp += sizeof(struct ether_addr); X bcopy((caddr_t)&in1, cp, sizeof(struct in_addr)); X cp += sizeof(struct in_addr); X ax_ax2ether(axa2, (struct ether_addr *)cp); X cp += sizeof(struct ether_addr); X bcopy((caddr_t)&in2, cp, sizeof(struct in_addr)); X X m->m_len -= 2; X return 0; X} X X/* X * convert an ax25_addr to an ether_addr X */ Xax_ax2ether(axhp, ethp) Xu_char *axhp; Xstruct ether_addr *ethp; X{ X u_char c; X int i; X X#ifdef DEBUG2 X for(i=0; i<6; i++) X printf("%2x.", axhp[i]); X printf("%2x '", axhp[6]); X X for(i=0; i<(7-1); i++) X printf("%c", (axhp[i]>>1) & 0x7f ); X printf("-%c' == ", (axhp[6]&0x7f)>>1 & 0x7f ); X#endif X X if( !bcmp((caddr_t)axhp, (caddr_t)ax25broadcastaddr, X sizeof(ax25broadcastaddr)) ) { X bcopy((caddr_t)ðerbroadcastaddr, (caddr_t)ethp, X sizeof(struct ether_addr)); X goto done; X } X X ethp->ether_addr_octet[0] = 0x99; X c = ((((axhp[0]>>1) - ' ') << 2) & 0xfc); X c |= ((((axhp[1]>>1) - ' ') >> 4) & 0x03); X ethp->ether_addr_octet[1] = c; X c = ((((axhp[1]>>1) - ' ') << 4) & 0xf0); X c |= ((((axhp[2]>>1) - ' ') >> 2) & 0x0f); X ethp->ether_addr_octet[2] = c; X c = ((((axhp[2]>>1) - ' ') << 6) & 0xc0); X c |= ((((axhp[3]>>1) - ' ') ) & 0x3f); X ethp->ether_addr_octet[3] = c; X c = ((((axhp[4]>>1) - ' ') << 2) & 0xfc); X c |= ((((axhp[5]>>1) - ' ') >> 4) & 0x03); X ethp->ether_addr_octet[4] = c; X c = ((((axhp[5]>>1) - ' ') << 4) & 0xf0); X c |= (((((axhp[6]&0x7f)>>1) - '0') ) & 0x0f); X ethp->ether_addr_octet[5] = c; X Xdone: X#ifdef DEBUG2 X for(i=0; iether_addr_octet[i]); X printf("%2x\n", ethp->ether_addr_octet[5]); X#endif X return 0; X} X X/* X * convert an ether_addr to an ax25_addr X */ Xax_ether2ax(ethp, axhp) Xstruct ether_addr *ethp; Xu_char *axhp; X{ X u_char c; X int i; X X#ifdef DEBUG2 X for(i=0; iether_addr_octet[i]); X printf("%2x == ", ethp->ether_addr_octet[5]); X#endif X X if( !bcmp((caddr_t)ethp, (caddr_t)ðernulladdr, X sizeof(struct ether_addr))) { X#ifdef DEBUG2 X printf("nothing\n"); X#endif X for(i=0; i<7; i++) X axhp[i] = (u_char)0; X return; X } X if( !bcmp((caddr_t)ethp, (caddr_t)ðerbroadcastaddr, X sizeof(struct ether_addr))) { X bcopy((caddr_t)ax25broadcastaddr, (caddr_t)axhp, X sizeof(ax25broadcastaddr)); X goto done; X } X c = ethp->ether_addr_octet[0]; X if(c != 0x99) { X#ifdef DEBUG2 X printf("[NO MAPPING]\n"); X#endif X for(i=0; i<7; i++) X axhp[i] = (u_char)0; X return; X } X c = (ethp->ether_addr_octet[1] >> 2) & 0x3f; X axhp[0] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[1] << 4) & 0x30; X c |= (ethp->ether_addr_octet[2] >> 4) & 0x0f; X axhp[1] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[2] << 2) & 0x3c; X c |= (ethp->ether_addr_octet[3] >> 6) & 0x03; X axhp[2] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[3] ) & 0x3f; X axhp[3] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[4] >> 2) & 0x3f; X axhp[4] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[4] << 4) & 0x30; X c |= (ethp->ether_addr_octet[5] >> 4) & 0x0f; X axhp[5] = (u_char)((c + ' ') << 1); X c = (ethp->ether_addr_octet[5] ) & 0x0f; X axhp[6] = (u_char)((c + '0') << 1); X Xdone: X#ifdef DEBUG2 X for(i=0; i<6; i++) X printf("%2x.", axhp[i]); X printf("%2x '", axhp[6]); X X for(i=0; i<6; i++) X printf("%c", (axhp[i] >> 1) & 0x7f ); X printf("-%c'\n", ((axhp[6] & 0x7f) >> 1) & 0x7f ); X#endif X return; X} X Xprint_ax25addr(axhp) Xu_char *axhp; X{ X int i; X X#ifdef DEBUG2 X for(i=0; i<6; i++) X printf("%2x.", axhp[i]); X printf("%2x", axhp[6]); X#endif X X printf("("); X for(i=0; i<6; i++) X printf("%c", (axhp[i]>>1) & 0x7f ); X printf("-%c)", ((axhp[6]&0x7f)>>1) & 0x7f ); X} X Xax25_arpdebug(m0) Xstruct mbuf *m0; X{ X struct mbuf *m; X int len, n; X u_char *cp; X X len = 0; X for(m=m0; m; m=m->m_next) { X printf("*"); X cp = mtod(m, u_char *); X n = m->m_len; X while(n-->0) { X if( !(len++ % 16) ) X printf("\n\t"); X printf("%2x ", *cp++); X } X } X if( len % 16 ) X printf("\n"); X} X X X#endif /* !(NAX > 0) */ X END_OF_FILE if test 23598 -ne `wc -c <'tty_ax.c'`; then echo shar: \"'tty_ax.c'\" unpacked with wrong size! fi # end of 'tty_ax.c' fi echo shar: End of shell archive. exit 0 -- SunOS 4.0.3: /usr/include/vm/as.h, Line 44 | Theo de Raadt SunOS 4.1.1: /usr/include/vm/as.h, Line 49 | deraadt@cpsc.ucalgary.ca Is it a typo? Should the '_' be an 's'?? :-) | deraadt@cpsc.ucalgary.ca