/* net/rom user command processing */ #include #include "global.h" #include "mbuf.h" #include "ax25.h" #include "netrom.h" #include "timer.h" #include "iface.h" #include "lapb.h" #include "cmdparse.h" /*#include */ static int dointerface(), dobcnodes(), donodetimer(), donrroute(), doobsotimer(), donodefilter() ; static struct cmds nrcmds[] = { "bcnodes", dobcnodes, 2, "netrom bcnodes ", NULLCHAR, "interface", dointerface, 4, "netrom interface ", NULLCHAR, "nodefilter", donodefilter, 0, NULLCHAR, NULLCHAR, "nodetimer", donodetimer, 0, NULLCHAR, NULLCHAR, "obsotimer", doobsotimer, 0, NULLCHAR, NULLCHAR, "route", donrroute, 0, NULLCHAR, NULLCHAR, NULLCHAR, NULLFP, 0, "netrom subcommands: bcnodes interface nodetimer nodefilter obsotimer route", NULLCHAR } ; static struct timer nodetimer ; /* timer for nodes broadcasts */ static struct timer obsotimer ; /* timer for aging routes */ /* Command multiplexer */ donetrom(argc,argv) int argc ; char *argv[] ; { return subcmd(nrcmds,argc,argv) ; } static int dorouteadd(), doroutedrop(), doroutedump(), dorouteinfo() ; static struct cmds routecmds[] = { "add", dorouteadd, 6, "netrom route add ", "add failed", "drop", doroutedrop, 4, "netrom route drop ", "drop failed", "info", dorouteinfo, 2, "netrom route info ", NULLCHAR, NULLCHAR, NULLFP, 0, "netrom route subcommands: add drop info", NULLCHAR } ; /* Route command multiplexer */ static donrroute(argc, argv) int argc ; char *argv[] ; { if (argc < 2) { doroutedump() ; return 0 ; } return subcmd(routecmds,argc,argv) ; } /* Dump a list of known routes */ static doroutedump() { register struct nrroute_tab *rp ; register int i, column ; char buf[16] ; char *cp ; column = 1 ; for (i = 0 ; i < NRNUMCHAINS ; i++) for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) { strcpy(buf,rp->alias) ; /* remove trailing spaces */ if ((cp = index(buf,' ')) == NULLCHAR) cp = &buf[strlen(buf)] ; if (cp != buf) /* don't include colon for null alias */ *cp++ = ':' ; pax25(cp,&rp->call) ; printf("%-16s ",buf) ; if (column++ == 4) { printf("\n") ; column = 1 ; } } if (column != 1) printf("\n") ; return 0 ; } /* print detailed information on an individual route */ dorouteinfo(argc,argv) int argc ; char *argv[] ; { register struct nrroute_tab *rp ; register struct nr_bind *bp ; register struct nrnbr_tab *np ; struct ax25_addr dest ; char neighbor[60] ; if (setcall(&dest,argv[1]) == -1) { printf ("bad destination name\n") ; return -1 ; } if ((rp = find_nrroute(&dest)) == NULLNRRTAB) { printf("no such route\n") ; return -1 ; } for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) { np = bp->via ; psax25(neighbor,np->call) ; printf("%1s %3d %3d %-8s %s\n", (bp->flags & NRB_PERMANENT ? "P" : " "), bp->quality,bp->obsocnt, nrifaces[np->interface].interface->name, neighbor) ; } return 0 ; } /* convert a null-terminated alias name to a blank-filled, upcased */ /* version. Return -1 on failure. */ static int putalias(to,from) register char *to, *from ; { int len, i ; if ((len = strlen(from)) > ALEN) { printf ("alias too long - six characters max\n") ; return -1 ; } for (i = 0 ; i < ALEN ; i++) { if (i < len) { if (islower(*from)) *to++ = toupper(*from++) ; else *to++ = *from++ ; } else *to++ = ' ' ; } *to = '\0' ; return 0 ; } /* Add a route */ dorouteadd(argc, argv) int argc ; char *argv[] ; { char alias[7] ; struct ax25_addr dest ; unsigned quality ; char neighbor[AXALEN * 3] ; register int i ; int naddr ; /* format alias (putalias prints error message if necessary) */ if (putalias(alias,argv[1]) == -1) return -1 ; /* format destination callsign */ if (setcall(&dest,argv[2]) == -1) { printf("bad destination callsign\n") ; return -1 ; } /* find interface */ for (i = 0 ; i < nr_numiface ; i++) if (!strcmp(nrifaces[i].interface->name,argv[3])) break ; if (i == nr_numiface) { printf("Interface \"%s\" not found\n",argv[3]) ; return -1 ; } /* get and check quality value */ if ((quality = atoi(argv[4])) > 255) { printf("maximum route quality is 255\n") ; return -1 ; } /* make sure no more than 2 digis */ naddr = argc - 5 ; if (naddr > 3) { printf("no more than 2 digipeaters for a net/rom neighbor\n") ; return -1 ; } /* format neighbor address string */ setpath(neighbor,&argv[5],naddr) ; return nr_routeadd(alias,&dest,i,quality,neighbor,1) ; } /* drop a route */ static doroutedrop(argc,argv) int argc ; char *argv[] ; { struct ax25_addr dest, neighbor ; register int i ; /* format destination and neighbor callsigns */ if (setcall(&dest,argv[1]) == -1) { printf("bad destination callsign\n") ; return -1 ; } if (setcall(&neighbor,argv[2]) == -1) { printf("bad neighbor callsign\n") ; return -1 ; } /* find interface */ for (i = 0 ; i < nr_numiface ; i++) if (!strcmp(nrifaces[i].interface->name,argv[3])) break ; if (i == nr_numiface) { printf("Interface \"%s\" not found\n",argv[3]) ; return -1 ; } return nr_routedrop(&dest,&neighbor,i) ; } /* make an interface available to net/rom */ int dointerface(argc,argv) int argc ; char *argv[] ; { register char *sp, *dp ; int i, len ; register struct interface *ifp ; extern struct interface *ifaces ; if (nr_interface == NULLIF) { printf("Attach netrom interface first\n") ; return 1 ; } if (nr_numiface >= NRNUMIFACE) { printf("Only %d net/rom interfaces available\n",NRNUMIFACE) ; return 1 ; } for(ifp=ifaces;ifp != NULLIF;ifp = ifp->next){ if(strcmp(argv[1],ifp->name) == 0) break; } if(ifp == NULLIF){ printf("Interface \"%s\" unknown\n",argv[1]); return 1; } if (!(ifp->flags != CONNECT_MODE)) { /* DG2KK: was: IF_AX25 */ printf("Must be an ax.25 interface\n") ; return 1 ; } for (i = 0 ; i < nr_numiface ; i++) if (nrifaces[i].interface == ifp) { printf("Interface \"%s\" is already registered\n",argv[1]) ; return 1 ; } nrifaces[nr_numiface].interface = ifp ; if (putalias(nrifaces[nr_numiface].alias,argv[2]) == -1) return 1 ; if ((nrifaces[nr_numiface].quality = atoi(argv[3])) > 255) { printf("Quality cannot be greater than 255\n") ; return 1 ; } nr_numiface++ ; /* accept this interface */ return 0 ; } /* Broadcast nodes list on named interface. */ int dobcnodes(argc,argv) int argc ; char *argv[] ; { register int i ; for (i = 0 ; i < nr_numiface ; i++) if (!strcmp(nrifaces[i].interface->name,argv[1])) break ; if (i == nr_numiface) { printf("Interface \"%s\" not found\n",argv[1]) ; return 1 ; } nr_bcnodes(i) ; } #define TICKSPERSEC (1000 / MSPTICK) /* Ticks per second */ /* Set outbound node broadcast interval */ static int donodetimer(argc,argv) int argc; char *argv[]; { int donodetick(); if(argc < 2){ printf("%d/%d\n",(nodetimer.start - nodetimer.count)/TICKSPERSEC, nodetimer.start/TICKSPERSEC); return 0; } stop_timer(&nodetimer) ; /* in case it's already running */ nodetimer.func = (void (*)())donodetick;/* what to call on timeout */ nodetimer.arg = NULLCHAR; /* dummy value */ nodetimer.start = atoi(argv[1])*TICKSPERSEC; /* set timer duration */ start_timer(&nodetimer); /* and fire it up */ return 0; } static int donodetick() { register int i ; for (i = 0 ; i < nr_numiface ; i++) nr_bcnodes(i) ; /* Restart timer */ start_timer(&nodetimer) ; } /* Set timer for aging routes */ static int doobsotimer(argc,argv) int argc; char *argv[]; { extern int doobsotick(); if(argc < 2){ printf("%d/%d\n",(obsotimer.start - obsotimer.count)/TICKSPERSEC, obsotimer.start/TICKSPERSEC); return 0; } stop_timer(&obsotimer) ; /* just in case it's already running */ obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */ obsotimer.arg = NULLCHAR; /* dummy value */ obsotimer.start = atoi(argv[1])*TICKSPERSEC; /* set timer duration */ start_timer(&obsotimer); /* and fire it up */ return 0; } /* Go through the routing table, reducing the obsolescence count of * non-permanent routes, and purging them if the count reaches 0 */ static int doobsotick() { register struct nrnbr_tab *np ; register struct nrroute_tab *rp, *rpnext ; register struct nr_bind *bp, *bpnext ; struct ax25_addr neighbor ; int i ; for (i = 0 ; i < NRNUMCHAINS ; i++) { for (rp = nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) { rpnext = rp->next ; /* save in case we free this route */ for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) { bpnext = bp->next ; /* in case we free this binding */ if (bp->flags & NRB_PERMANENT) /* don't age these */ continue ; if (--bp->obsocnt == 0) { /* time's up! */ if (bp->next != NULLNRBIND) bp->next->prev = bp->prev ; if (bp->prev != NULLNRBIND) bp->prev->next = bp->next ; else rp->routes = bp->next ; rp->num_routes-- ; /* one less binding */ np = bp->via ; /* find the neighbor */ free(bp) ; /* now we can free the bind */ /* Check to see if we can free the neighbor */ if (--np->refcnt == 0) { if (np->next != NULLNTAB) np->next->prev = np->prev ; if (np->prev != NULLNTAB) np->prev->next = np->next ; else { memcpy(neighbor.call,np->call,ALEN) ; neighbor.ssid = np->call[ALEN] ; nrnbr_tab[nrhash(&neighbor)] = np->next ; } free(np) ; /* free the storage */ } } } if (rp->num_routes == 0) { /* did we free them all? */ if (rp->next != NULLNRRTAB) rp->next->prev = rp->prev ; if (rp->prev != NULLNRRTAB) rp->prev->next = rp->next ; else nrroute_tab[i] = rp->next ; free(rp) ; } } } start_timer(&obsotimer) ; } static int donfadd(), donfdrop(), donfmode() ; static struct cmds nfcmds[] = { "add", donfadd, 3, "netrom nodefilter add ", "add failed", "drop", donfdrop, 3, "netrom nodefilter drop ", "drop failed", "mode", donfmode, 0, NULLCHAR, NULLCHAR, NULLCHAR, NULLFP, 0, "nodefilter subcommands: add drop mode", NULLCHAR } ; /* nodefilter command multiplexer */ static donodefilter(argc,argv) int argc ; char *argv[] ; { if (argc < 2) { donfdump() ; return 0 ; } return subcmd(nfcmds,argc,argv) ; } /* display a list of pairs from the filter * list. */ static donfdump() { int i, column = 1 ; struct nrnf_tab *fp ; char buf[16] ; for (i = 0 ; i < NRNUMCHAINS ; i++) for (fp = nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) { pax25(buf,&fp->neighbor) ; printf("%-7s %-8s ", buf,nrifaces[fp->interface].interface->name) ; if (column++ == 4) { printf("\n") ; column = 1 ; } } if (column != 1) printf("\n") ; return 0 ; } /* add an entry to the filter table */ static donfadd(argc,argv) int argc ; char *argv[] ; { struct ax25_addr neighbor ; register int i ; /* format callsign */ if (setcall(&neighbor,argv[1]) == -1) { printf("bad neighbor callsign\n") ; return -1 ; } /* find interface */ for (i = 0 ; i < nr_numiface ; i++) if (!strcmp(nrifaces[i].interface->name,argv[2])) break ; if (i == nr_numiface) { printf("Interface \"%s\" not found\n",argv[2]) ; return -1 ; } return nr_nfadd(&neighbor,i) ; } /* drop an entry from the filter table */ static donfdrop(argc,argv) int argc ; char *argv[] ; { struct ax25_addr neighbor ; register int i ; /* format neighbor callsign */ if (setcall(&neighbor,argv[1]) == -1) { printf("bad neighbor callsign\n") ; return -1 ; } /* find interface */ for (i = 0 ; i < nr_numiface ; i++) if (!strcmp(nrifaces[i].interface->name,argv[2])) break ; if (i == nr_numiface) { printf("Interface \"%s\" not found\n",argv[2]) ; return -1 ; } return nr_nfdrop(&neighbor,i) ; } /* nodefilter mode subcommand */ static donfmode(argc,argv) int argc ; char *argv[] ; { if (argc < 2) { printf("filter mode is ") ; switch (nr_nfmode) { case NRNF_NOFILTER: printf("none\n") ; break ; case NRNF_ACCEPT: printf("accept\n") ; break ; case NRNF_REJECT: printf("reject\n") ; break ; default: printf("some strange, unknown value\n") ; } return 0 ; } switch (argv[1][0]) { case 'n': case 'N': nr_nfmode = NRNF_NOFILTER ; break ; case 'a': case 'A': nr_nfmode = NRNF_ACCEPT ; break ; case 'r': case 'R': nr_nfmode = NRNF_REJECT ; break ; default: printf("modes are: none accept reject\n") ; return -1 ; } return 0 ; }