/* Generic serial line interface routines * Copyright 1991 Phil Karn, KA9Q */ /* Mods by G1EMM */ #include #include "global.h" #include "config.h" #include "proc.h" #include "iface.h" #include "netuser.h" #include "slhc.h" #include "8250.h" #include "asy.h" #include "ax25.h" #include "kiss.h" #include "pktdrvr.h" #include "ppp.h" #include "slip.h" #include "nrs.h" #include "commands.h" #include "mbuf.h" static int asy_detach __ARGS((struct iface *ifp)); /* Attach a serial interface to the system * argv[0]: hardware type, must be "asy" * argv[1]: I/O address, e.g., "0x3f8" * argv[2]: vector, e.g., "4" * argv[3]: mode, may be: * "slip" (point-to-point SLIP) * "ax25" (AX.25 frame format in SLIP for raw TNC) * "nrs" (NET/ROM format serial protocol) * "ppp" (Point-to-Point Protocol, RFC1171, RFC1172) * argv[4]: interface label, e.g., "sl0" * argv[5]: receiver ring buffer size in bytes * argv[6]: maximum transmission unit, bytes * argv[7]: interface speed, e.g, "9600" * argv[8]: optional flags, * 'c' for cts flow control; * 'r' for RLSD (RS232 pin 8, CD) physical link up/down; * 'v' for Van Jacobson TCP header compression (SLIP only, * use ppp command for VJ compression with PPP); */ int asy_attach(argc,argv,p) int argc; char *argv[]; void *p; { register struct iface *ifp; struct asy *asyp; char *ifn; int dev; int xdev; int trigchar = -1; char cts = FALSE; char rlsd = FALSE; #if defined(SLIP) || defined(AX25) struct slip *sp; #endif #ifdef NRS struct nrs *np; #endif if(if_lookup(argv[4]) != NULLIF){ tprintf("Interface %s already exists\n",argv[4]); return -1; } /* Find unused asy control block */ for(dev=0;dev < ASY_MAX;dev++){ asyp = &Asy[dev]; if(asyp->iface == NULLIF) break; } if(dev >= ASY_MAX){ tprintf("Too many async controllers\n"); return -1; } /* Create interface structure and fill in details */ ifp = (struct iface *)callocw(1,sizeof(struct iface)); ifp->addr = Ip_addr; ifp->name = strdup(argv[4]); ifp->mtu = atoi(argv[6]); ifp->dev = dev; ifp->stop = asy_detach; #ifdef SLIP if(stricmp(argv[3],"SLIP") == 0) { for(xdev = 0;xdev < SLIP_MAX;xdev++){ sp = &Slip[xdev]; if(sp->iface == NULLIF) break; } if(xdev >= SLIP_MAX) { tprintf("Too many slip devices\n"); free(ifp->name); free((char *)ifp); return -1; } setencap(ifp,"SLIP"); ifp->ioctl = asy_ioctl; ifp->raw = slip_raw; ifp->status = slip_status; ifp->flags = 0; ifp->xdev = xdev; sp->iface = ifp; sp->send = asy_send; sp->get = get_asy; sp->type = CL_SERIAL_LINE; trigchar = FR_END; #ifdef VJCOMPRESS if((argc > 8) && (strchr(argv[8],'v') != NULLCHAR)) { sp->escaped |= SLIP_VJCOMPR; sp->slcomp = slhc_init(16,16); } #else sp->slcomp = NULL; #endif /* VJCOMPRESS */ ifp->rxproc = newproc( ifn = if_name( ifp, " rx" ), 256,asy_rx,xdev,NULL,NULL,0); free(ifn); } else #endif #ifdef AX25 if(stricmp(argv[3],"AX25") == 0) { /* Set up a SLIP link to use AX.25 */ for(xdev = 0;xdev < SLIP_MAX;xdev++){ sp = &Slip[xdev]; if(sp->iface == NULLIF) break; } if(xdev >= SLIP_MAX) { tprintf("Too many ax25 devices\n"); free(ifp->name); free((char *)ifp); return -1; } setencap(ifp,"AX25"); ifp->ioctl = kiss_ioctl; ifp->raw = kiss_raw; ifp->status = slip_status; ifp->port = 0; /* G1EMM */ if(ifp->hwaddr == NULLCHAR) ifp->hwaddr = mallocw(AXALEN); memcpy(ifp->hwaddr,Mycall,AXALEN); ifp->xdev = xdev; sp->iface = ifp; sp->send = asy_send; sp->kiss[ifp->port] = ifp; /* G1EMM */ sp->get = get_asy; sp->type = CL_KISS; trigchar = FR_END; ifp->rxproc = newproc( ifn = if_name( ifp, " rx" ), 256,asy_rx,xdev,NULL,NULL,0); free(ifn); } else #endif #ifdef NRS if(stricmp(argv[3],"NRS") == 0) { /* Set up a net/rom serial iface */ for(xdev = 0;xdev < SLIP_MAX;xdev++){ np = &Nrs[xdev]; if(np->iface == NULLIF) break; } if(xdev >= SLIP_MAX) { tprintf("Too many nrs devices\n"); free(ifp->name); free((char *)ifp); return -1; } /* no call supplied? */ setencap(ifp,"AX25"); ifp->ioctl = asy_ioctl; ifp->raw = nrs_raw; /* ifp->status = nrs_status; */ ifp->hwaddr = mallocw(AXALEN); memcpy(ifp->hwaddr,Mycall,AXALEN); ifp->xdev = xdev; np->iface = ifp; np->send = asy_send; np->get = get_asy; trigchar = ETX; ifp->rxproc = newproc( ifn = if_name( ifp, " nrs" ), 256,nrs_recv,xdev,NULL,NULL,0); free(ifn); } else #endif #ifdef PPP if(stricmp(argv[3],"PPP") == 0) { /* Setup for Point-to-Point Protocol */ trigchar = HDLC_FLAG; setencap(ifp,"PPP"); ifp->ioctl = asy_ioctl; ifp->flags = FALSE; /* Initialize parameters for various PPP phases/protocols */ if((argc > 8) && (strchr(argv[8],'r') != NULLCHAR)) rlsd = TRUE; if (ppp_init(ifp) != 0) { tprintf("Cannot allocate PPP control block\n"); free(ifp->name); free((char *)ifp); return -1; } } else #endif /* PPP */ { tprintf("Mode %s unknown for interface %s\n", argv[3],argv[4]); free(ifp->name); free((char *)ifp); return -1; } /* Link in the interface */ ifp->next = Ifaces; Ifaces = ifp; if((argc > 8) && (strchr(argv[8],'c') != NULLCHAR)) cts = TRUE; asy_init(dev,ifp,argv[1],argv[2],(int16)atol(argv[5]), trigchar,cts,rlsd,(int16)atol(argv[7])); return 0; } static int asy_detach(ifp) struct iface *ifp; { asy_stop(ifp); #ifdef SLIP if(stricmp(ifp->iftype->name,"SLIP") == 0) { Slip[ifp->xdev].iface = NULLIF; #ifdef VJCOMPRESS slhc_free( Slip[ifp->xdev].slcomp ); Slip[ifp->xdev].slcomp = NULL; #endif /* VJCOMPRESS */ } else #endif #ifdef AX25 if(stricmp(ifp->iftype->name,"AX25") == 0 && Slip[ifp->xdev].iface == ifp ) { Slip[ifp->xdev].iface = NULLIF; } else #endif #ifdef NRS if(stricmp(ifp->iftype->name,"AX25") == 0 && Nrs[ifp->xdev].iface == ifp ) { Nrs[ifp->xdev].iface = NULLIF; } else #endif #ifdef PPP if(stricmp(ifp->iftype->name,"PPP") == 0) { ppp_free(ifp); } else #endif { tprintf("invalid type %s for interface %s\n", ifp->iftype->name, ifp->name); free(ifp->name); free(ifp); return -1; } return 0; } /* Execute user comm command */ int doasycomm(argc,argv,p) int argc; char *argv[]; void *p; { register struct iface *ifp; register struct asy *ap; int dev; int c; struct mbuf *bp; if((ifp = if_lookup(argv[1])) == NULLIF){ tprintf("Interface %s unknown\n",argv[1]); return 1; } for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++) if(ap->iface == ifp) break; if(dev == ASY_MAX){ tprintf("Interface %s not asy port\n",argv[1]); return 1; } bp = pushdown(NULLBUF,strlen(argv[2]) + 2 ); strcpy(bp->data,argv[2]); strcat(bp->data,"\r"); bp->cnt = strlen(argv[2]) + 1; asy_send(dev,bp); return 0; }