libax25/0000755000175000017500000000000013517150527010470 5ustar irlirllibax25/ax25io.c0000644000175000017500000003202413517150506011741 0ustar irlirl#include #include #include #include #include #include #include #include #include "config.h" static inline int send_iac_iac(ax25io *p); static inline int send_iac_cmd(ax25io *p, unsigned char cmd, unsigned char opt); static inline int send_linemode(ax25io *p); static ax25io *Iolist; /* --------------------------------------------------------------------- */ #ifdef HAVE_ZLIB_H #include struct compr_s { int z_error; /* "(de)compression error" flag */ unsigned char char_buf; /* temporary character buffer */ z_stream zin; /* decompressor structure */ z_stream zout; /* compressor structure */ }; #endif /* --------------------------------------------------------------------- */ ax25io *axio_init(int in, int out, int paclen, char *eol) { ax25io *new; if ((new = calloc(1, sizeof(ax25io))) == NULL) return NULL; if (paclen > AXBUFLEN) paclen = AXBUFLEN; new->ifd = in; new->ofd = out; new->eolmode = EOLMODE_TEXT; new->paclen = paclen; new->gbuf_usage = 0; strncpy(new->eol, eol, 3); new->eol[3] = 0; new->next = Iolist; Iolist = new; return new; } void axio_end(ax25io *p) { axio_flush(p); #ifdef HAVE_ZLIB_H if (p->zptr) { struct compr_s *z = (struct compr_s *) p->zptr; deflateEnd(&z->zout); inflateEnd(&z->zin); } #endif close(p->ifd); close(p->ofd); p->ifd = -1; p->ofd = -1; } void axio_end_all(void) { ax25io *p = Iolist; while (p != NULL) { if (p->ifd != -1 && p->ofd != -1) axio_end(p); p = p->next; } } /* --------------------------------------------------------------------- */ int axio_compr(ax25io *p, int flag) { #ifdef HAVE_ZLIB_H if (flag) { struct compr_s *z = calloc(1, sizeof(struct compr_s)); if (!z) return -1; p->zptr = z; if (inflateInit(&z->zin) != Z_OK) return -1; if (deflateInit(&z->zout, Z_BEST_COMPRESSION) != Z_OK) return -1; } return 0; #endif /* ax25_errno = AX25IO_NO_Z_SUPPORT; */ return -1; } int axio_paclen(ax25io *p, int paclen) { axio_flush(p); if (paclen > AXBUFLEN) return -1; return p->paclen = paclen; } int axio_eolmode(ax25io *p, int newmode) { int oldmode; oldmode = p->eolmode; p->eolmode = newmode; return oldmode; } int axio_cmpeol(ax25io *p1, ax25io *p2) { return strcmp(p1->eol, p2->eol); } int axio_tnmode(ax25io *p, int newmode) { int oldmode; oldmode = p->telnetmode; p->telnetmode = newmode; return oldmode; } static int flush_obuf(ax25io *p) { int ret, len; if (p->optr == 0) return 0; len = p->optr < p->paclen ? p->optr : p->paclen; if ((ret = write(p->ofd, p->obuf, len)) < 0) return -1; if (ret && ret < p->optr) memmove(p->obuf, &p->obuf[ret], p->optr - ret); p->optr -= ret; return ret; } int axio_flush(ax25io *p) { int flushed = 0; int ret; #ifdef HAVE_ZLIB_H if (p->zptr) { struct compr_s *z = (struct compr_s *) p->zptr; int ret; /* * Fail immediately if there has been an error in * compression or decompression. */ if (z->z_error) { errno = z->z_error; return -1; } /* * No new input, just flush the compression block. */ z->zout.next_in = NULL; z->zout.avail_in = 0; do { /* Adjust the output pointers */ z->zout.next_out = p->obuf + p->optr; z->zout.avail_out = p->paclen - p->optr; ret = deflate(&z->zout, Z_PARTIAL_FLUSH); p->optr = p->paclen - z->zout.avail_out; switch (ret) { case Z_OK: /* All OK */ break; case Z_BUF_ERROR: /* * Progress not possible, it's been * flushed already (I hope). */ break; case Z_STREAM_END: /* What ??? */ errno = z->z_error = ZERR_STREAM_END; return -1; case Z_STREAM_ERROR: /* Something strange */ errno = z->z_error = ZERR_STREAM_ERROR; return -1; default: errno = z->z_error = ZERR_UNKNOWN; return -1; } /* * If output buffer is full, flush it to make room * for more compressed data. */ if (z->zout.avail_out == 0 && flush_obuf(p) < 0) return -1; } while (z->zout.avail_out == 0); } #endif while (p->optr) { /* Return on error or if zero bytes written */ if ((ret = flush_obuf(p)) <= 0) return -1; flushed += ret; } return flushed; } static int rsend(char *c, int len, ax25io *p) { /* Don't go further until there is space */ if (p->paclen <= p->optr) { if (flush_obuf(p) <= 0) return -1; } #ifdef HAVE_ZLIB_H if (p->zptr) { struct compr_s *z = (struct compr_s *) p->zptr; int ret; /* * Fail immediately if there has been an error in * compression or decompression. */ if (z->z_error) { errno = z->z_error; return -1; } /* * One new character to input. */ z->zout.next_in = (unsigned char *) c; z->zout.avail_in = len; /* * Now loop until deflate returns with avail_out != 0 */ do { /* Adjust the output pointers */ z->zout.next_out = p->obuf + p->optr; z->zout.avail_out = p->paclen - p->optr; ret = deflate(&z->zout, Z_NO_FLUSH); p->optr = p->paclen - z->zout.avail_out; switch (ret) { case Z_OK: /* All OK */ break; case Z_STREAM_END: /* What ??? */ errno = z->z_error = ZERR_STREAM_END; return -1; case Z_STREAM_ERROR: /* Something strange */ errno = z->z_error = ZERR_STREAM_ERROR; return -1; case Z_BUF_ERROR: /* Progress not possible (should be) */ errno = z->z_error = ZERR_BUF_ERROR; return -1; default: errno = z->z_error = ZERR_UNKNOWN; return -1; } /* * If the output buffer is full, flush it to make * room for more compressed data. */ if (z->zout.avail_out == 0 && flush_obuf(p) < 0) return -1; } while (z->zout.avail_out == 0); return len; } #endif if (p->optr + len < AXBUFLEN) { memcpy(p->obuf + p->optr, c, len); p->optr += len; } else { errno = EAGAIN; return -1; } if (p->optr >= p->paclen && flush_obuf(p) < 0) return -1; return len; } /* --------------------------------------------------------------------- */ static int recv_ibuf(ax25io *p) { int ret; p->iptr = 0; p->size = 0; if ((ret = read(p->ifd, p->ibuf, AXBUFLEN)) < 0) return -1; if (ret == 0) { errno = 0; return -1; } return p->size = ret; } static int rrecvchar(ax25io *p) { #ifdef HAVE_ZLIB_H if (p->zptr) { struct compr_s *z = (struct compr_s *) p->zptr; int ret; /* * Fail immediately if there has been an error in * compression or decompression. */ if (z->z_error) { errno = z->z_error; return -1; } for (;;) { /* Adjust the input pointers */ z->zin.next_in = p->ibuf + p->iptr; z->zin.avail_in = p->size - p->iptr; /* Room for one output character */ z->zin.next_out = &z->char_buf; z->zin.avail_out = 1; ret = inflate(&z->zin, Z_PARTIAL_FLUSH); p->iptr = p->size - z->zin.avail_in; switch (ret) { case Z_OK: /* * Progress made! Return if there is * something to be returned. */ if (z->zin.avail_out == 0) return z->char_buf; break; case Z_BUF_ERROR: /* * Not enough new data to proceed, * let's hope we'll get some more below. */ break; case Z_STREAM_END: /* What ??? */ errno = z->z_error = ZERR_STREAM_END; return -1; case Z_STREAM_ERROR: /* Something weird */ errno = z->z_error = ZERR_STREAM_ERROR; return -1; case Z_DATA_ERROR: /* Compression protocol error */ errno = z->z_error = ZERR_DATA_ERROR; return -1; case Z_MEM_ERROR: /* Not enough memory */ errno = z->z_error = ZERR_MEM_ERROR; return -1; default: errno = z->z_error = ZERR_UNKNOWN; return -1; } /* * Our only hope is that inflate has consumed all * input and we can get some more. */ if (z->zin.avail_in == 0) { if (recv_ibuf(p) < 0) return -1; } else { /* inflate didn't consume all input ??? */ errno = z->z_error = ZERR_UNKNOWN; return -1; } } /* * We should never fall through here ??? */ errno = z->z_error = ZERR_UNKNOWN; return -1; } #endif if (p->iptr >= p->size && recv_ibuf(p) < 0) return -1; return p->ibuf[p->iptr++]; } /* --------------------------------------------------------------------- */ int axio_putc(int c, ax25io *p) { char cp; if (p->telnetmode && c == IAC) return send_iac_iac(p); if (c == INTERNAL_EOL) { if (p->eolmode == EOLMODE_BINARY) return rsend("\n", 1, p); else return rsend(p->eol, strlen(p->eol), p); } if (p->eolmode == EOLMODE_TEXT && c == '\n') return rsend(p->eol, strlen(p->eol), p); cp = c & 0xff; return rsend(&cp, 1, p); } int axio_getc(ax25io *p) { int c, opt; char *cp; opt = 0; /* silence warning */ if ((c = rrecvchar(p)) == -1) return -1; if (p->telnetmode && c == IAC) { if ((c = rrecvchar(p)) == -1) return -1; if (c > 249 && c < 255 && (opt = rrecvchar(p)) == -1) return -1; switch (c) { case IP: case ABORT: case xEOF: return -1; case SUSP: break; case SB: /* * Start of sub-negotiation. Just ignore everything * until we see a IAC SE (some negotiation...). */ if ((c = rrecvchar(p)) == -1) return -1; if ((opt = rrecvchar(p)) == -1) return -1; while (!(c == IAC && opt == SE)) { c = opt; if ((opt = rrecvchar(p)) == -1) return -1; } break; case WILL: /* * Client is willing to negotiate linemode and * we want it too. Tell the client to go to * local edit mode and also to translate any * signals to telnet commands. Clients answer * is ignored above (rfc1184 says client must obey * ECHO and TRAPSIG). */ if (opt == TELOPT_LINEMODE && p->tn_linemode) { if (send_linemode(p) < 0) return -1; } else { if (send_iac_cmd(p, DONT, opt) < 0) return -1; } axio_flush(p); break; case DO: switch (opt) { case TELOPT_SGA: if (send_iac_cmd(p, WILL, opt) < 0) return -1; axio_flush(p); break; case TELOPT_ECHO: /* * If we want echo then just silently * approve, otherwise deny. */ if (p->tn_echo) break; /* Note fall-through */ default: if (send_iac_cmd(p, WONT, opt) < 0) return -1; axio_flush(p); break; } break; case IAC: /* Escaped IAC */ return IAC; break; case WONT: case DONT: default: break; } return axio_getc(p); } if (c == p->eol[0]) { switch (p->eolmode) { case EOLMODE_BINARY: break; case EOLMODE_TEXT: for (cp = p->eol + 1; *cp; cp++) if (rrecvchar(p) == -1) return -1; c = '\n'; break; case EOLMODE_GW: for (cp = p->eol + 1; *cp; cp++) if (rrecvchar(p) == -1) return -1; c = INTERNAL_EOL; break; } } return c; } /* --------------------------------------------------------------------- */ int axio_gets(char *buf, int buflen, ax25io *p) { int c, len = 0; while (len < (buflen - 1)) { c = axio_getc(p); if (c == -1) { return -len; } /* NUL also interpreted as EOL */ if (c == '\n' || c == '\r' || c == 0) { buf[len] = 0; errno = 0; return len; } buf[len++] = c; } buf[buflen - 1] = 0; errno = 0; return len; } char *axio_getline(ax25io *p) { int ret; ret = axio_gets((char *) p->gbuf + p->gbuf_usage, AXBUFLEN - p->gbuf_usage, p); if (ret > 0 || (ret == 0 && errno == 0)) { p->gbuf_usage = 0; return (char *) p->gbuf; } p->gbuf_usage += ret; return NULL; } int axio_puts(const char *s, ax25io *p) { int count=0; while (*s) if (axio_putc(*s++, p) == -1) { if (errno != EAGAIN) return -1; else break; } else { count++; } return count; } /* --------------------------------------------------------------------- */ static int axio_vprintf(ax25io *p, const char *fmt, va_list args) { static char buf[AXBUFLEN]; int len, i; len = vsprintf(buf, fmt, args); for (i = 0; i < len; i++) if (axio_putc(buf[i], p) == -1) return -1; return len; } int axio_printf(ax25io *p, const char *fmt, ...) { va_list args; int len; va_start(args, fmt); len = axio_vprintf(p, fmt, args); va_end(args); return len; } /* --------------------------------------------------------------------- */ int axio_tn_do_linemode(ax25io *p) { if (send_iac_cmd(p, DO, TELOPT_LINEMODE) < 0) return -1; p->tn_linemode = 1; return 0; } int axio_tn_will_echo(ax25io *p) { if (send_iac_cmd(p, WILL, TELOPT_ECHO) < 0) return -1; p->tn_echo = 1; return 0; } int axio_tn_wont_echo(ax25io *p) { if (send_iac_cmd(p, WONT, TELOPT_ECHO) < 0) return -1; p->tn_echo = 0; return 0; } /* --------------------------------------------------------------------- */ static inline int send_iac_iac(ax25io *p) { unsigned char buf[2] = { IAC, IAC }; return rsend((char *) buf, 2, p); } static inline int send_iac_cmd(ax25io *p, unsigned char cmd, unsigned char opt) { unsigned char buf[3]; buf[0] = IAC; buf[1] = cmd; buf[2] = opt; return rsend((char *)buf, 3, p); } static inline int send_linemode(ax25io *p) { unsigned char buf[7] = { IAC, SB, TELOPT_LINEMODE, LM_MODE, MODE_EDIT | MODE_TRAPSIG, IAC, SE }; return rsend((char *) buf, 7, p); } /* --------------------------------------------------------------------- */ libax25/procutils.c0000644000175000017500000003553013517150506012663 0ustar irlirl#include #include #include #include #include #include /* Needed by nrconfig.h */ #include #include #include "pathnames.h" #define min(a,b) ((a) < (b) ? (a) : (b)) static char *space = " \t\n\r"; /* * Version of atoi() that returns zero if s == NULL. */ static int safe_atoi(const char *s) { return s ? atoi(s) : 0; } /* * Version of atox() that returns zero if s == NULL. */ static unsigned long safe_atox(const char *s) { return s ? strtoul(s, NULL, 16) : 0; } /* * Version of strncpy() that returns NULL if either src or dest is NULL * and also makes sure destination string is always terminated. */ static char *safe_strncpy(char *dest, char *src, int n) { if (!dest || !src) return NULL; dest[n] = 0; return strncpy(dest, src, n); } /* * Our version of strtok(). This one does not touch the original string, * reports the identity of the delimitting character and does not * retain any state info. */ static char *token(char **ptr, const char *delim) { static char buf[256]; char *start; int len; if (!ptr || !*ptr || !delim) return NULL; start = *ptr + strspn(*ptr, delim); len = strcspn(start, delim); *ptr = start + len; if (len == 0) return NULL; len = min(len, sizeof(buf) - 1); memcpy(buf, start, len); buf[len] = 0; return buf; } struct proc_ax25 *read_proc_ax25(void) { FILE *fp; char buffer[256], *cp; struct proc_ax25 *p; struct proc_ax25 *list = NULL; errno = 0; if ((fp = fopen(PROC_AX25_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if ((p = calloc(1, sizeof(struct proc_ax25))) == NULL) break; cp = buffer; p->magic = safe_atox(token(&cp, space)); safe_strncpy(p->dev, token(&cp, space), 13); safe_strncpy(p->src_addr, token(&cp, space), 9); safe_strncpy(p->dest_addr, token(&cp, ", \t\r\n"), 9); p->ndigi = 0; while (*cp == ',' && p->ndigi < 9) { safe_strncpy(p->digi_addr[p->ndigi], token(&cp, ", \t\r\n"), 10); p->ndigi++; } p->st = safe_atoi(token(&cp, space)); p->vs = safe_atoi(token(&cp, space)); p->vr = safe_atoi(token(&cp, space)); p->va = safe_atoi(token(&cp, space)); p->t1timer = safe_atox(token(&cp, space)); p->t1 = safe_atox(token(&cp, space)); p->t2timer = safe_atox(token(&cp, space)); p->t2 = safe_atox(token(&cp, space)); p->t3timer = safe_atox(token(&cp, space)); p->t3 = safe_atox(token(&cp, space)); p->idletimer = safe_atox(token(&cp, space)); p->idle = safe_atox(token(&cp, space)); p->n2count = safe_atoi(token(&cp, space)); p->n2 = safe_atoi(token(&cp, space)); p->rtt = safe_atox(token(&cp, space)); p->window = safe_atoi(token(&cp, space)); p->paclen = safe_atoi(token(&cp, space)); p->sndq = safe_atoi(token(&cp, space)); p->rcvq = safe_atoi(token(&cp, space)); p->inode = safe_atox(token(&cp, space)); p->next = list; list = p; } fclose(fp); return list; } void free_proc_ax25(struct proc_ax25 *ap) { struct proc_ax25 *p; while (ap != NULL) { p = ap->next; free(ap); ap = p; } } struct proc_ax25_route *read_proc_ax25_route(void) { FILE *fp; char buffer[256], *cp; struct proc_ax25_route *new, *tmp, *p; struct proc_ax25_route *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_AX25_ROUTE_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((new = calloc(1, sizeof(struct proc_ax25_route))) == NULL) break; cp = buffer; safe_strncpy(new->call, token(&cp, space), 9); safe_strncpy(new->dev, token(&cp, space), 13); new->cnt = safe_atoi(token(&cp, space)); new->t = safe_atoi(token(&cp, space)); if (list == NULL || new->t > list->t) { tmp = list; list = new; new->next = tmp; } else { for (p = list; p->next != NULL; p = p->next) if (new->t > p->next->t) break; tmp = p->next; p->next = new; new->next = tmp; } } fclose(fp); return list; } void free_proc_ax25_route(struct proc_ax25_route *rp) { struct proc_ax25_route *p; while (rp != NULL) { p = rp->next; free(rp); rp = p; } } struct proc_nr *read_proc_nr(void) { FILE *fp; char buffer[256], *cp; struct proc_nr *p; struct proc_nr *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_NR_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((p = calloc(1, sizeof(struct proc_nr))) == NULL) break; cp = buffer; safe_strncpy(p->user_addr, token(&cp, space), 9); safe_strncpy(p->dest_node, token(&cp, space), 9); safe_strncpy(p->src_node, token(&cp, space), 9); safe_strncpy(p->dev, token(&cp, space), 13); safe_strncpy(p->my_circuit, token(&cp, space), 5); safe_strncpy(p->ur_circuit, token(&cp, space), 5); p->st = safe_atoi(token(&cp, space)); p->vs = safe_atoi(token(&cp, space)); p->vr = safe_atoi(token(&cp, space)); p->va = safe_atoi(token(&cp, space)); p->t1timer = safe_atox(token(&cp, "/")); p->t1 = safe_atox(token(&cp, "/ \t\r\n")); p->t2timer = safe_atox(token(&cp, "/")); p->t2 = safe_atox(token(&cp, "/ \t\r\n")); p->t4timer = safe_atox(token(&cp, "/")); p->t4 = safe_atox(token(&cp, "/ \t\r\n")); p->idletimer = safe_atox(token(&cp, "/")); p->idle = safe_atox(token(&cp, "/ \t\r\n")); p->n2count = safe_atoi(token(&cp, "/")); p->n2 = safe_atoi(token(&cp, "/ \t\r\n")); p->window = safe_atoi(token(&cp, space)); p->sndq = safe_atoi(token(&cp, space)); p->rcvq = safe_atoi(token(&cp, space)); p->inode = safe_atox(token(&cp, space)); p->next = list; list = p; } fclose(fp); return list; } void free_proc_nr(struct proc_nr *np) { struct proc_nr *p; while (np != NULL) { p = np->next; free(np); np = p; } } struct proc_nr_neigh *read_proc_nr_neigh(void) { FILE *fp; char buffer[256], *cp; struct proc_nr_neigh *p; struct proc_nr_neigh *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_NR_NEIGH_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((p = calloc(1, sizeof(struct proc_nr_neigh))) == NULL) break; cp = buffer; p->addr = safe_atoi(token(&cp, space)); safe_strncpy(p->call, token(&cp, space), 9); safe_strncpy(p->dev, token(&cp, space), 13); p->qual = safe_atoi(token(&cp, space)); p->lock = safe_atoi(token(&cp, space)); p->cnt = safe_atoi(token(&cp, space)); p->next = list; list = p; } fclose(fp); return list; } void free_proc_nr_neigh(struct proc_nr_neigh *np) { struct proc_nr_neigh *p; while (np != NULL) { p = np->next; free(np); np = p; } } struct proc_nr_nodes *read_proc_nr_nodes(void) { FILE *fp; char buffer[256], *cp; struct proc_nr_nodes *new, *tmp, *p; struct proc_nr_nodes *list = NULL; char *name; int i = 0; errno = 0; if ((fp = fopen(PROC_NR_NODES_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((new = calloc(1, sizeof(struct proc_nr_nodes))) == NULL) break; cp = buffer; safe_strncpy(new->call, token(&cp, space), 9); safe_strncpy(new->alias, token(&cp, space), 6); new->w = safe_atoi(token(&cp, space)); new->n = safe_atoi(token(&cp, space)); new->qual1 = safe_atoi(token(&cp, space)); new->obs1 = safe_atoi(token(&cp, space)); new->addr1 = safe_atoi(token(&cp, space)); if (new->n > 1) { new->qual2 = safe_atoi(token(&cp, space)); new->obs2 = safe_atoi(token(&cp, space)); new->addr2 = safe_atoi(token(&cp, space)); } if (new->n > 2) { new->qual3 = safe_atoi(token(&cp, space)); new->obs3 = safe_atoi(token(&cp, space)); new->addr3 = safe_atoi(token(&cp, space)); } if (list == NULL || strcmp(new->alias, list->alias) < 0) { tmp = list; list = new; new->next = tmp; } else { for (p = list; p->next != NULL; p = p->next) if (strcmp(new->alias, p->next->alias) < 0) break; tmp = p->next; p->next = new; new->next = tmp; } } /* * Now load the local nodes. */ name = NULL; while ((name = nr_config_get_next(name)) != NULL) { if ((new = calloc(1, sizeof(struct proc_nr_nodes))) == NULL) break; if ((cp = nr_config_get_addr(name)) == NULL) break; safe_strncpy(new->call, cp, 9); if ((cp = nr_config_get_alias(name)) == NULL) break; safe_strncpy(new->alias, cp, 6); new->w = 1; /* local node w */ new->qual1 = 255; /* obviously, local node quality should be set to maximum value */ new->obs1 = 6; /* persist */ /* * n == 0 indicates a local node. */ new->n = 0; if (list == NULL || strcmp(new->alias, list->alias) < 0) { tmp = list; list = new; new->next = tmp; } else { for (p = list; p->next != NULL; p = p->next) if (strcmp(new->alias, p->next->alias) < 0) break; tmp = p->next; p->next = new; new->next = tmp; } } fclose(fp); return list; } void free_proc_nr_nodes(struct proc_nr_nodes *np) { struct proc_nr_nodes *p; while (np != NULL) { p = np->next; free(np); np = p; } } struct proc_rs *read_proc_rs(void) { FILE *fp; char buffer[256]; struct proc_rs *p; struct proc_rs *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_RS_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((p = calloc(1, sizeof(struct proc_rs))) == NULL) break; safe_strncpy(p->dest_addr, strtok(buffer, " \t\n\r"), 10); safe_strncpy(p->dest_call, strtok(NULL, " \t\n\r"), 9); safe_strncpy(p->src_addr, strtok(NULL, " \t\n\r"), 10); safe_strncpy(p->src_call, strtok(NULL, " \t\n\r"), 9); safe_strncpy(p->dev, strtok(NULL, " \t\n\r"), 13); p->lci = safe_atox(strtok(NULL, " \t\n\r")); p->neigh = safe_atoi(strtok(NULL, " \t\n\r")); p->st = safe_atoi(strtok(NULL, " \t\n\r")); p->vs = safe_atoi(strtok(NULL, " \t\n\r")); p->vr = safe_atoi(strtok(NULL, " \t\n\r")); p->va = safe_atoi(strtok(NULL, " \t\n\r")); p->t = safe_atoi(strtok(NULL, " \t\n\r")); p->t1 = safe_atoi(strtok(NULL, " \t\n\r")); p->t2 = safe_atoi(strtok(NULL, " \t\n\r")); p->t3 = safe_atoi(strtok(NULL, " \t\n\r")); p->hb = safe_atoi(strtok(NULL, " \t\n\r")); p->sndq = safe_atoi(strtok(NULL, " \t\n\r")); p->rcvq = safe_atoi(strtok(NULL, " \t\n\r")); p->next = list; list = p; } fclose(fp); return list; } void free_proc_rs(struct proc_rs *ap) { struct proc_rs *p; while (ap != NULL) { p = ap->next; free(ap); ap = p; } } struct proc_rs_neigh *read_proc_rs_neigh(void) { FILE *fp; char buffer[256]; struct proc_rs_neigh *p; struct proc_rs_neigh *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_RS_NEIGH_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((p = calloc(1, sizeof(struct proc_rs_neigh))) == NULL) break; p->addr = safe_atoi(strtok(buffer, " \t\n\r")); safe_strncpy(p->call, strtok(NULL, " \t\n\r"), 9); safe_strncpy(p->dev, strtok(NULL, " \t\n\r"), 13); p->count = safe_atoi(strtok(NULL, " \t\n\r")); p->use = safe_atoi(strtok(NULL, " \t\n\r")); safe_strncpy(p->mode, strtok(NULL, " \t\n\r"), 3); safe_strncpy(p->restart, strtok(NULL, " \t\n\r"), 3); p->t0 = safe_atoi(strtok(NULL, " \t\n\r")); p->tf = safe_atoi(strtok(NULL, " \t\n\r")); p->next = list; list = p; } fclose(fp); return list; } void free_proc_rs_neigh(struct proc_rs_neigh *np) { struct proc_rs_neigh *p; while (np != NULL) { p = np->next; free(np); np = p; } } struct proc_rs_nodes *read_proc_rs_nodes(void) { FILE *fp; char buffer[256]; struct proc_rs_nodes *p; struct proc_rs_nodes *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_RS_NODES_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((p = calloc(1, sizeof(struct proc_rs_nodes))) == NULL) break; safe_strncpy(p->address, strtok(buffer, " \t\n\r"), 10); p->mask = safe_atoi(strtok(NULL, " \t\n\r")); p->n = safe_atoi(strtok(NULL, " \t\n\r")); p->neigh1 = safe_atoi(strtok(NULL, " \t\n\r")); p->neigh2 = safe_atoi(strtok(NULL, " \t\n\r")); p->neigh3 = safe_atoi(strtok(NULL, " \t\n\r")); p->next = list; list = p; } fclose(fp); return list; } void free_proc_rs_nodes(struct proc_rs_nodes *np) { struct proc_rs_nodes *p; while (np != NULL) { p = np->next; free(np); np = p; } } struct proc_rs_route *read_proc_rs_routes(void) { FILE *fp; char buffer[256]; struct proc_rs_route *p; struct proc_rs_route *list = NULL; int i = 0; errno = 0; if ((fp = fopen(PROC_RS_ROUTES_FILE, "r")) == NULL) return NULL; while (fgets(buffer, 256, fp) != NULL) { if (!i++) continue; if ((p = calloc(1, sizeof(struct proc_rs_route))) == NULL) break; p->lci1 = safe_atox(strtok(buffer, " \t\n\r")); safe_strncpy(p->address1, strtok(NULL, " \t\n\r"), 10); safe_strncpy(p->call1, strtok(NULL, " \t\n\r"), 9); p->neigh1 = safe_atoi(strtok(NULL, " \t\n\r")); p->lci2 = safe_atox(strtok(NULL, " \t\n\r")); safe_strncpy(p->address2, strtok(NULL, " \t\n\r"), 10); safe_strncpy(p->call2, strtok(NULL, " \t\n\r"), 9); p->neigh2 = safe_atoi(strtok(NULL, " \t\n\r")); p->next = list; list = p; } fclose(fp); return list; } void free_proc_rs_routes(struct proc_rs_route *np) { struct proc_rs_route *p; while (np != NULL) { p = np->next; free(np); np = p; } } char *get_call(int uid) { FILE *fp; char buf[256]; static char call[10]; int i = 0; errno = 0; if ((fp = fopen(PROC_AX25_CALLS_FILE, "r")) == NULL) return NULL; while (fgets(buf, 256, fp) != NULL) { if (!i++) continue; if (safe_atoi(strtok(buf, " \t\r\n")) == uid) { fclose(fp); safe_strncpy(call, strtok(NULL, " \t\r\n"), 9); return call; } } fclose(fp); return NULL; } struct proc_ax25 *find_link(const char *src, const char *dest, const char *dev) { static struct proc_ax25 a; struct proc_ax25 *p, *list; list = read_proc_ax25(); for (p = list; p != NULL; p = p->next) { if (!strcmp(src, p->src_addr) && !strcmp(dest, p->dest_addr) && !strcmp(dev, p->dev)) { a = *p; a.next = NULL; free_proc_ax25(list); return &a; } } free_proc_ax25(list); return NULL; } struct proc_nr_neigh *find_neigh(int addr, struct proc_nr_neigh *neighs) { static struct proc_nr_neigh n; struct proc_nr_neigh *p, *list; list = neighs ? neighs : read_proc_nr_neigh(); for (p = list; p != NULL; p = p->next) { if (addr == p->addr) { n = *p; n.next = NULL; p = &n; break; } } if (!neighs) free_proc_nr_neigh(list); return p; } struct proc_nr_nodes *find_node(char *addr, struct proc_nr_nodes *nodes) { static struct proc_nr_nodes n; struct proc_nr_nodes *p, *list; list = nodes ? nodes : read_proc_nr_nodes(); for (p = list; p != NULL; p = p->next) { if (!strcasecmp(addr, p->call) || !strcasecmp(addr, p->alias)) { n = *p; n.next = NULL; p = &n; break; } } if (!nodes) free_proc_nr_nodes(list); return p; } libax25/configure.ac0000644000175000017500000000447413517150506012764 0ustar irlirlAC_PREREQ([2.59]) AC_INIT([libax25],[0.0.12-rc5],[linux-hams@vger.kernel.org]) AC_CONFIG_MACRO_DIRS([m4]) AC_CONFIG_SRCDIR(axconfig.c) AM_INIT_AUTOMAKE([foreign no-define 1.7]) AC_CONFIG_HEADERS(config.h) dnl Checks for programs. AC_PROG_CC AC_PROG_GCC_TRADITIONAL LT_INIT dnl Checks for libraries. AC_CHECK_FUNC(setsid,, AC_MSG_ERROR([setsid not found])) AC_CHECK_FUNCS(socket strdup strerror strspn) dnl Checks for header files. AC_HEADER_STDC AC_CHECK_HEADERS(fcntl.h sys/file.h sys/ioctl.h unistd.h) AC_CHECK_HEADER([zlib.h], AC_CHECK_LIB(z, zlibVersion,Z_LIB="-lz",Z_LIB=)) AC_SUBST(Z_LIB, [$Z_LIB]) dnl Checks for working glibc 2.1 headers AC_MSG_CHECKING(for working netax25/ax25.h header file) AC_EGREP_HEADER(ax25_fwd_struct, netax25/ax25.h, has_ax25=yes, has_ax25=no) if test "$has_ax25" = "yes" ; then AC_DEFINE(HAVE_NETAX25_AX25_H, 1, [Define if you have a proper netax25/ax25.h header file]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([AX25_H], [test "$has_ax25" = "yes"]) AC_MSG_CHECKING(for working netrom/netrom.h header file) AC_EGREP_HEADER(unsigned int ndigis, netrom/netrom.h, has_netrom=yes, has_netrom=no) if test "$has_netrom" = "yes" ; then AC_DEFINE(HAVE_NETROM_NETROM_H, 1, [Define if you have a proper netrom/netrom.h header file.]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([NETROM_H], [test "$has_netrom" = "yes"]) AC_MSG_CHECKING(for working netrose/rose.h header file) AC_EGREP_HEADER(rose_facilities_struct, netrose/rose.h, has_rose=yes, has_rose=no) if test "$has_rose" = "yes" ; then AC_DEFINE(HAVE_NETROSE_ROSE_H, 1, [Define if you have a proper netrose/rose.h header file.]) AC_MSG_RESULT(yes) else AC_MSG_RESULT(no) fi AM_CONDITIONAL([ROSE_H], [test "$has_rose" = "yes"]) dnl Checks for typedefs, structures, and compiler characteristics. AC_C_CONST dnl Only use -Wall if we have gcc if test "x$GCC" = "xyes"; then if test -z "`echo "$CFLAGS" | grep "\-Wall" 2> /dev/null`" ; then CFLAGS="$CFLAGS -Wall" fi fi dnl Checks for library functions. basever=$(echo $PACKAGE_VERSION | sed -e 's@-.*$@@') AC_SUBST(BASEVERSION, [$basever]) extraver=$(echo $PACKAGE_VERSION | sed -e 's@@<:@^-@:>@*-@@' -e 's@-@_@') AC_SUBST(EXTRAVERSION, [$extraver]) AM_CONDITIONAL([BUILD_STATIC], [test "$enable_static" = yes]) AC_CONFIG_FILES([Makefile libax25.spec]) AC_OUTPUT libax25/rsports.50000644000175000017500000000241413517150506012270 0ustar irlirl.TH RSPORTS 5 "27 August 1996" Linux "Linux Programmer's Manual" .SH NAME rsports \- Rose port configuration file. .SH DESCRIPTION .LP .B Rsports is an ASCII file that contains information about each of the Rose ports that are to be used. When dealing with a Rose utility such as .B call, it takes an optional argument that is the port name. This port name is a reference to the line within .B rsports, which has the same name. The information on each line contains enough information to bind the command to a particular Rose interface, this binding is done by matching the address on the line in .B rsports with the address of the port set by .B ifconfig or .B rsattach. .LP The .B rsports file may contain comments that begin with a # in the first column, or a port description in the following format, each field being delimited by white space: .sp .RS name address description .RE .sp The field descriptions are: .sp .RS .TP 14 .B name this is the unique Rose port identifier. .TP 14 .B address the address of the Rose interface to bind to. .TP 14 .B description a free format description of this interface, this field extends to the end of the line. It may contain spaces. .RE .SH FILES .LP /etc/ax25/rsports .SH "SEE ALSO" .BR call (1), .BR rose (4), .BR ifconfig (8), .BR rsparms (8). libax25/rose.30000644000175000017500000000174413517150506011527 0ustar irlirl.TH INET 3 "2008-Feb-04" "Linux" "Linux Programmer's Manual" .SH NAME rose_aton, rose_ntoa, rose_cmp \- ROSE Address manipulation routines .SH SYNOPSIS .nf .B #include .sp .BI "int rose_aton(const char *" cp ", char *" inp ");" .sp .BI "char * rose_ntoa(rose_address *" cp ");" .sp .BI "int rose_cmp(rose_address *" a1 ", rose_address *" a2 ");" .fi .SH DESCRIPTION The .BR rose_aton () converts the ROSE address .I cp from an ASCII representation into network format. .PP The .BR rose_ntoa () converts the ROSE address .I cp that is network format to a string that is the ASCII representation of the address. .PP The .BR rose_cmp () compares the two ROSE address .I a1 and .I a2 that are in network format. .SH "RETURN VALUE" The .BR rose_ntoa () and .BR rose_aton () functions return zero if all went OK, -1 if not. .PP The .BR rose_cmp () returns 0 if addresses pointer by .I a1 and .I a2 are identical, 1 otherwise. .SH "SEE ALSO" .BR ax25 "(4), " netrom "(4), " rose "(4)" libax25/netrom/0000755000175000017500000000000013517150506011771 5ustar irlirllibax25/netrom/netrom.h0000644000175000017500000000425513517150506013454 0ustar irlirl/* Copyright (C) 1997 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #ifndef _NETROM_NETROM_H #define _NETROM_NETROM_H 1 #include /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx. */ #define SOL_NETROM 259 /* NetRom control values: */ #define NETROM_T1 1 #define NETROM_T2 2 #define NETROM_N2 3 #define NETROM_PACLEN 5 #define NETROM_T4 6 #define NETROM_IDLE 7 #define NETROM_KILL 99 /* Type of route: */ #define NETROM_NEIGH 0 #define NETROM_NODE 1 struct nr_route_struct { int type; ax25_address callsign; char device[16]; unsigned int quality; char mnemonic[7]; ax25_address neighbour; unsigned int obs_count; unsigned int ndigis; ax25_address digipeaters[AX25_MAX_DIGIS]; }; /* NetRom socket ioctls: */ #define SIOCNRGETPARMS (SIOCPROTOPRIVATE+0) #define SIOCNRSETPARMS (SIOCPROTOPRIVATE+1) #define SIOCNRDECOBS (SIOCPROTOPRIVATE+2) #define SIOCNRRTCTL (SIOCPROTOPRIVATE+3) #define SIOCNRCTLCON (SIOCPROTOPRIVATE+4) /* NetRom parameter structure: */ struct nr_parms_struct { unsigned int quality; unsigned int obs_count; unsigned int ttl; unsigned int timeout; unsigned int ack_delay; unsigned int busy_delay; unsigned int tries; unsigned int window; unsigned int paclen; }; /* NetRom control structure: */ struct nr_ctl_struct { unsigned char index; unsigned char id; unsigned int cmd; unsigned long arg; }; #endif /* netrom/netrom.h */ libax25/nrconfig.c0000644000175000017500000001653413517150506012447 0ustar irlirl#include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" #include #include typedef struct _nrport { struct _nrport *Next; char *Name; char *Call; char *Alias; char *Device; int Paclen; char *Description; } NR_Port; static NR_Port *nr_ports; static NR_Port *nr_port_tail; static int is_same_call(char *call1, char *call2) { if (!call1 || !call2) return 0; for (; *call1 && *call2; call1++, call2++) { if (*call1 == '-' || *call2 == '-') break; if (tolower(*call1 & 0xff) != tolower(*call2 & 0xff)) return 0; } if (!*call1 && !*call2) return 1; if (!*call1 && !strcmp(call2, "-0")) return 1; if (!*call2 && !strcmp(call1, "-0")) return 1; return !strcmp(call1, call2) ? 1 : 0; } static NR_Port *nr_port_ptr(char *name) { NR_Port *p = nr_ports; if (name == NULL) return p; while (p != NULL) { if (p->Name != NULL && strcasecmp(name, p->Name) == 0) return p; p = p->Next; } return NULL; } char *nr_config_get_next(char *name) { NR_Port *p; if (nr_ports == NULL) return NULL; if (name == NULL) return nr_ports->Name; if ((p = nr_port_ptr(name)) == NULL) return NULL; p = p->Next; if (p == NULL) return NULL; return p->Name; } char *nr_config_get_name(char *device) { NR_Port *p = nr_ports; while (p != NULL) { if (p->Device != NULL && strcmp(device, p->Device) == 0) return p->Name; p = p->Next; } return NULL; } char *nr_config_get_addr(char *name) { NR_Port *p = nr_port_ptr(name); if (p == NULL) return NULL; return p->Call; } char *nr_config_get_dev(char *name) { NR_Port *p = nr_port_ptr(name); if (p == NULL) return NULL; return p->Device; } char *nr_config_get_port(ax25_address *callsign) { NR_Port *p = nr_ports; ax25_address addr; while (p != NULL) { if (p->Call != NULL) { ax25_aton_entry(p->Call, (char *)&addr); if (ax25_cmp(callsign, &addr) == 0) return p->Name; } p = p->Next; } return NULL; } char *nr_config_get_alias(char *name) { NR_Port *p = nr_port_ptr(name); if (p == NULL) return NULL; return p->Alias; } int nr_config_get_paclen(char *name) { NR_Port *p = nr_port_ptr(name); if (p == NULL) return 0; return p->Paclen; } char *nr_config_get_desc(char *name) { NR_Port *p = nr_port_ptr(name); if (p == NULL) return NULL; return p->Description; } static int nr_config_init_port(int fd, int lineno, char *line, const char **ifcalls, const char **ifdevs) { NR_Port *p; char *name, *call, *alias, *paclen, *desc; const char *dev = NULL; int found = 0; name = strtok(line, " \t"); call = strtok(NULL, " \t"); alias = strtok(NULL, " \t"); paclen = strtok(NULL, " \t"); desc = strtok(NULL, ""); if (name == NULL || call == NULL || alias == NULL || paclen == NULL || desc == NULL) { fprintf(stderr, "nrconfig: unable to parse line %d of config file\n", lineno); return FALSE; } for (p = nr_ports; p != NULL; p = p->Next) { if (p->Name != NULL && strcasecmp(name, p->Name) == 0) { fprintf(stderr, "nrconfig: duplicate port name %s in line %d of config file\n", name, lineno); return FALSE; } if (p->Call != NULL && is_same_call(call, p->Call)) { fprintf(stderr, "nrconfig: duplicate callsign %s in line %d of config file\n", call, lineno); return FALSE; } if (p->Alias != NULL && strcasecmp(alias, p->Alias) == 0) { fprintf(stderr, "nrconfig: duplicate alias %s in line %d of config file\n", alias, lineno); return FALSE; } } if (atoi(paclen) <= 0) { fprintf(stderr, "nrconfig: invalid packet size %s in line %d of config file\n", paclen, lineno); return FALSE; } strupr(call); strupr(alias); char *cp; if ((cp = strstr(call, "-0")) != NULL) *cp = 0; found = 0; for (;ifcalls && *ifcalls; ++ifcalls, ++ifdevs) { if (strcmp(call, *ifcalls) == 0) { found = 1; dev = *ifdevs; break; } } if (!found) { #if 0 /* None of your business to complain about some port being down... */ fprintf(stderr, "nrconfig: port %s not active\n", name); #endif return FALSE; } if ((p = (NR_Port *)malloc(sizeof(NR_Port))) == NULL) { fprintf(stderr, "nrconfig: out of memory!\n"); return FALSE; } p->Name = strdup(name); p->Call = strdup(call); p->Alias = strdup(alias); p->Device = strdup(dev); p->Paclen = atoi(paclen); p->Description = strdup(desc); if (nr_ports == NULL) nr_ports = p; else nr_port_tail->Next = p; nr_port_tail = p; p->Next = NULL; return TRUE; } int nr_config_load_ports(void) { FILE *fp = NULL; char buffer[256], *s; int fd = -1, lineno = 1, n = 0, i; const char **calllist = NULL; const char **devlist = NULL; const char **pp; int callcount = 0; struct ifreq ifr; /* Reliable listing of all network ports on Linux is only available via reading /proc/net/dev ... */ if ((fd = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "nrconfig: unable to open socket (%s)\n", strerror(errno)); goto cleanup; } if ((fp = fopen("/proc/net/dev", "r"))) { /* Two header lines.. */ s = fgets(buffer, sizeof(buffer), fp); s = fgets(buffer, sizeof(buffer), fp); /* .. then network interface names */ while (!feof(fp)) { if (!fgets(buffer, sizeof(buffer), fp)) break; s = strchr(buffer, ':'); if (s) *s = 0; s = buffer; while (isspace(*s & 0xff)) ++s; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, s, IFNAMSIZ-1); ifr.ifr_name[IFNAMSIZ-1] = 0; if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { fprintf(stderr, "nrconfig: SIOCGIFHWADDR: %s\n", strerror(errno)); return FALSE; } if (ifr.ifr_hwaddr.sa_family != ARPHRD_NETROM) continue; /* store found interface callsigns */ /* ax25_ntoa() returns pointer to static buffer */ s = ax25_ntoa((void*)ifr.ifr_hwaddr.sa_data); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, "nrconfig: SIOCGIFFLAGS: %s\n", strerror(errno)); return FALSE; } if (!(ifr.ifr_flags & IFF_UP)) continue; if ((pp = realloc(calllist, sizeof(char *) * (callcount+2))) == 0) break; calllist = pp; if ((pp = realloc(devlist, sizeof(char *) * (callcount+2))) == 0) break; devlist = pp; if ((calllist[callcount] = strdup(s)) != NULL) { if ((devlist[callcount] = strdup(ifr.ifr_name)) != NULL) { ++callcount; calllist[callcount] = NULL; devlist [callcount] = NULL; } else { free((void*)calllist[callcount]); calllist[callcount] = NULL; devlist[callcount] = NULL; } } } fclose(fp); fp = NULL; } if ((fp = fopen(CONF_NRPORTS_FILE, "r")) == NULL) { fprintf(stderr, "nrconfig: unable to open nrports file %s (%s)\n", CONF_NRPORTS_FILE, strerror(errno)); goto cleanup; } while (fp && fgets(buffer, 255, fp)) { if ((s = strchr(buffer, '\n'))) *s = '\0'; if (strlen(buffer) > 0 && *buffer != '#') if (nr_config_init_port(fd, lineno, buffer, calllist, devlist)) n++; lineno++; } cleanup:; if (fd >= 0) close(fd); if (fp) fclose(fp); for (i = 0; calllist && calllist[i]; ++i) { free((void*)calllist[i]); if (devlist[i] != NULL) free((void*)devlist[i]); } if (calllist) free(calllist); if (devlist) free(devlist); if (nr_ports == NULL) return 0; return n; } libax25/Makefile.am0000644000175000017500000000327413517150506012527 0ustar irlirlACLOCAL_AMFLAGS = -I m4 lib_LTLIBRARIES = libax25.la libax25io.la libax25includedir = $(includedir) libax25ioincludedir = $(includedir) AM_CPPFLAGS = -DAX25_SYSCONFDIR=\""$(sysconfdir)/ax25/"\" \ -DAX25_LOCALSTATEDIR=\""$(localstatedir)/ax25/"\" if !AX25_H USE_LIBAX25_AX25_H = netax25/ax25.h endif if !NETROM_H USE_LIBAX25_NETROM_H = netrom/netrom.h endif if !ROSE_H USE_LIBAX25_ROSE_H = netrose/rose.h endif nobase_libax25include_HEADERS = \ netax25/axlib.h \ netax25/axconfig.h \ netax25/nrconfig.h \ netax25/rsconfig.h \ netax25/daemon.h \ netax25/ttyutils.h \ netax25/procutils.h \ netax25/mheard.h \ $(USE_LIBAX25_AX25_H) \ $(USE_LIBAX25_NETROM_H) \ $(USE_LIBAX25_ROSE_H) nobase_libax25ioinclude_HEADERS = \ netax25/ax25io.h libax25_la_SOURCES = \ axconfig.c \ netax25/axconfig.h \ netax25/axlib.h \ axutils.c \ config.h \ daemon.c \ netax25/daemon.h \ netax25/mheard.h \ nrconfig.c \ netax25/nrconfig.h \ pathnames.h \ procutils.c \ netax25/procutils.h \ rsconfig.c \ netax25/rsconfig.h \ ttyutils.c \ netax25/ttyutils.h \ $(USE_LIBAX25_AX25_H) \ $(USE_LIBAX25_ROSE_H) libax25io_la_SOURCES = \ ax25io.c \ netax25/ax25io.h libax25io_la_LIBADD = @Z_LIB@ dist_man_MANS = ax25.3 rose.3 axports.5 rsports.5 nrports.5 EXTRA_DIST= glibc.patch $(etcfiles) libax25.spec AX25_SYSCONFDIR=@sysconfdir@/ax25/ AX25_LOCALSTATEDIR=@localstatedir@/ax25/ # Needed so that the install is optional etcdir = $(AX25_SYSCONFDIR) etcfiles = axports rsports nrports installconf: $(mkinstalldirs) $(DESTDIR)$(etcdir) @list='$(etcfiles)'; for p in $$list; do \ echo " $(INSTALL_DATA) $$p $(DESTDIR)$(etcdir)/$$p"; \ $(INSTALL_DATA) $$p $(DESTDIR)$(etcdir)/$$p; \ done libax25/ax25.30000644000175000017500000000420513517150506011331 0ustar irlirl.TH INET 3 "2008-Feb-04" "Linux" "Linux Programmer's Manual" .SH NAME .B ax25_aton, ax25_aton_entry, ax25_aton_arglist, .B ax25_ntoa, ax25_cmp, ax25_validate \- AX25 Address manipulation routines .SH SYNOPSIS .nf .B #include .PP .BI "int ax25_aton(const char *" cp ", struct full_sockaddr_ax25 *" fsap ");" .PP .BI "int ax25_aton_arglist(const char **" cp ", struct full_sockaddr_ax25 *" fsap ");" .PP .BI "int ax25_aton_entry(const char *" cp ", char *" axp ");" .PP .BI "char *ax25_ntoa(ax25_address *" axp ");" .PP .BI "int ax25_cmp(ax25_address *" ax1 ", ax25_address *" ax2 ");" .PP .BI "int ax25_validate(char *" axp ");" .PP .BI "char *ax25_config_file(const char *filename);" .fi .SH DESCRIPTION .BR ax25_aton () takes the ASCII string .I cp that is in the format .I callsign .RI [[ V | VIA ] callsign "...]" and stores it in .I fsap in network format. .PP .BR ax25_aton_entry () takes the ASCII string of a callsign .I cp and stores it in network format in .I axp. .PP The .BR ax25_aton_arglist () takes a NULL terminated array of strings .I cp and stores it in .I fsap in network format. .PP The .BR ax25_ntoa () takes a network format address .I axp and returns the ASCII representation. The string is returned in a statically allocated buffer, which subsequent calls will overwrite. .PP The .BR ax25_cmp () function compares the two ax25 addresses, .I ax1 and .IR ax2 , that are in network format and determines wether they are identical, differ only by their SSIDs or are different. .PP The .BR ax25_validate () function checks to see if the address .I axp in network format is a correctly formatted address. .SH "RETURN VALUE" The .BR ax25_aton () and .BR ax25_aton_arglist () functions return -1 if an error occurs otherwise the length of the returned structure. .PP The .BR ax25_aton_entry () function returns -1 if an error occurs otherwise zero. .PP The .BR ax25_cmp () function returns 0 if the two addresses are identical, 1 if they are different or 2 is only the SSIDs are different. .PP The .BR ax25_validate () function returns TRUE if the callsign is valid or FALSE if it is not. .SH "SEE ALSO" .BR ax25 "(4), " netrom "(4), " rose "(4)" libax25/axconfig.c0000644000175000017500000001755013517150506012437 0ustar irlirl#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" typedef struct _axport { struct _axport *Next; char *Name; char *Call; char *Device; int Baud; int Window; int Paclen; char *Description; } AX_Port; static AX_Port *ax25_ports; static AX_Port *ax25_port_tail; static int is_same_call(char *call1, char *call2) { if (!call1 || !call2) return 0; for (; *call1 && *call2; call1++, call2++) { if (*call1 == '-' || *call2 == '-') break; if (tolower(*call1 & 0xff) != tolower(*call2 & 0xff)) return 0; } if (!*call1 && !*call2) return 1; if (!*call1 && !strcmp(call2, "-0")) return 1; if (!*call2 && !strcmp(call1, "-0")) return 1; return !strcmp(call1, call2) ? 1 : 0; } static AX_Port *ax25_port_ptr(char *name) { AX_Port *p = ax25_ports; if (name == NULL) return p; while (p != NULL) { if (p->Name != NULL && strcasecmp(p->Name, name) == 0) return p; if (p->Call != NULL && is_same_call(p->Call, name)) return p; p = p->Next; } return NULL; } char *ax25_config_get_next(char *name) { AX_Port *p; if (ax25_ports == NULL) return NULL; if (name == NULL) return ax25_ports->Name; if ((p = ax25_port_ptr(name)) == NULL) return NULL; p = p->Next; if (p == NULL) return NULL; return p->Name; } char *ax25_config_get_name(char *device) { AX_Port *p = ax25_ports; while (p != NULL) { if (p->Device != NULL) { if (strcmp(p->Device, device) == 0) return p->Name; } p = p->Next; } return NULL; } char *ax25_config_get_addr(char *name) { AX_Port *p = ax25_port_ptr(name); if (p == NULL) return NULL; return p->Call; } char *ax25_config_get_dev(char *name) { AX_Port *p = ax25_port_ptr(name); if (p == NULL) return NULL; return p->Device; } char *ax25_config_get_port(ax25_address *callsign) { AX_Port *p = ax25_ports; ax25_address addr; if (ax25_cmp(callsign, &null_ax25_address) == 0) return "*"; while (p != NULL) { if (p->Call != NULL) { ax25_aton_entry(p->Call, (char *)&addr); if (ax25_cmp(callsign, &addr) == 0) return p->Name; } p = p->Next; } return NULL; } int ax25_config_get_window(char *name) { AX_Port *p = ax25_port_ptr(name); if (p == NULL) return 0; return p->Window; } int ax25_config_get_paclen(char *name) { AX_Port *p = ax25_port_ptr(name); if (p == NULL) return 0; return p->Paclen; } int ax25_config_get_baud(char *name) { AX_Port *p = ax25_port_ptr(name); if (p == NULL) return 0; return p->Baud; } char *ax25_config_get_desc(char *name) { AX_Port *p = ax25_port_ptr(name); if (p == NULL) return NULL; return p->Description; } static int ax25_config_init_port(int fd, int lineno, char *line, const char **ifcalls, const char **ifdevs) { AX_Port *p; char *name, *call, *baud, *paclen, *window, *desc; const char *dev = NULL; int found; name = strtok(line, " \t"); call = strtok(NULL, " \t"); baud = strtok(NULL, " \t"); paclen = strtok(NULL, " \t"); window = strtok(NULL, " \t"); desc = strtok(NULL, ""); if (name == NULL || call == NULL || baud == NULL || paclen == NULL || window == NULL || desc == NULL) { fprintf(stderr, "axconfig: unable to parse line %d of axports file\n", lineno); return FALSE; } for (p = ax25_ports; p != NULL; p = p->Next) { if (p->Name != NULL && strcasecmp(name, p->Name) == 0) { fprintf(stderr, "axconfig: duplicate port name %s in line %d of axports file\n", name, lineno); return FALSE; } if (p->Call != NULL && is_same_call(call, p->Call)) { fprintf(stderr, "axconfig: duplicate callsign %s in line %d of axports file\n", call, lineno); return FALSE; } } if (atoi(baud) < 0) { fprintf(stderr, "axconfig: invalid baud rate setting %s in line %d of axports file\n", baud, lineno); return FALSE; } if (atoi(paclen) <= 0) { fprintf(stderr, "axconfig: invalid packet size setting %s in line %d of axports file\n", paclen, lineno); return FALSE; } if (atoi(window) <= 0) { fprintf(stderr, "axconfig: invalid window size setting %s in line %d of axports file\n", window, lineno); return FALSE; } strupr(call); found = 0; char *cp; if ((cp = strstr(call, "-0")) != NULL) *cp = '\0'; for (;ifcalls && *ifcalls; ++ifcalls, ++ifdevs) { if (strcmp(call, *ifcalls) == 0) { found = 1; dev = *ifdevs; break; } } if (!found) { #if 0 /* None of your business to complain about some port being down... */ fprintf(stderr, "axconfig: port with call '%s' is not active\n", call); #endif return FALSE; } if ((p = (AX_Port *)malloc(sizeof(AX_Port))) == NULL) { fprintf(stderr, "axconfig: out of memory!\n"); return FALSE; } p->Name = strdup(name); p->Call = strdup(call); p->Device = strdup(dev); p->Baud = atoi(baud); p->Window = atoi(window); p->Paclen = atoi(paclen); p->Description = strdup(desc); if (ax25_ports == NULL) ax25_ports = p; else ax25_port_tail->Next = p; ax25_port_tail = p; p->Next = NULL; return TRUE; } int ax25_config_load_ports(void) { FILE *fp = NULL; char buffer[256], *s; int fd = -1, lineno = 1, n = 0, i; const char **calllist = NULL; const char **devlist = NULL; const char **pp; int callcount = 0; struct ifreq ifr; /* Reliable listing of all network ports on Linux is only available via reading /proc/net/dev ... */ if ((fd = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "axconfig: unable to open socket (%s)\n", strerror(errno)); goto cleanup; } if ((fp = fopen("/proc/net/dev", "r"))) { /* Two header lines.. */ s = fgets(buffer, sizeof(buffer), fp); s = fgets(buffer, sizeof(buffer), fp); /* .. then network interface names */ while (!feof(fp)) { if (!fgets(buffer, sizeof(buffer), fp)) break; s = strchr(buffer, ':'); if (s) *s = 0; s = buffer; while (isspace(*s & 0xff)) ++s; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, s, IFNAMSIZ-1); ifr.ifr_name[IFNAMSIZ-1] = 0; if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { fprintf(stderr, "axconfig: SIOCGIFHWADDR: %s\n", strerror(errno)); return FALSE; } if (ifr.ifr_hwaddr.sa_family != ARPHRD_AX25) continue; /* store found interface callsigns */ /* ax25_ntoa() returns pointer to static buffer */ s = ax25_ntoa((void*)ifr.ifr_hwaddr.sa_data); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, "axconfig: SIOCGIFFLAGS: %s\n", strerror(errno)); return FALSE; } if (!(ifr.ifr_flags & IFF_UP)) continue; if ((pp = realloc(calllist, sizeof(char *) * (callcount+2))) == 0) break; calllist = pp; if ((pp = realloc(devlist, sizeof(char *) * (callcount+2))) == 0) break; devlist = pp; if ((calllist[callcount] = strdup(s)) != NULL) { if ((devlist[callcount] = strdup(ifr.ifr_name)) != NULL) { ++callcount; calllist[callcount] = NULL; devlist [callcount] = NULL; } else { free((void*)calllist[callcount]); calllist[callcount] = NULL; } } } fclose(fp); fp = NULL; } if ((fp = fopen(CONF_AXPORTS_FILE, "r")) == NULL) { fprintf(stderr, "axconfig: unable to open axports file %s (%s)\n", CONF_AXPORTS_FILE, strerror(errno)); goto cleanup; } while (fp && fgets(buffer, 255, fp)) { if ((s = strchr(buffer, '\n'))) *s = '\0'; if (strlen(buffer) > 0 && *buffer != '#') if (ax25_config_init_port(fd, lineno, buffer, calllist, devlist)) n++; lineno++; } cleanup:; if (fd >= 0) close(fd); if (fp) fclose(fp); for (i = 0; calllist && calllist[i]; ++i) { free((void*)calllist[i]); if (devlist[i] != NULL) free((void*)devlist[i]); } if (calllist) free(calllist); if (devlist) free(devlist); if (ax25_ports == NULL) return 0; return n; } libax25/INSTALL0000644000175000017500000000107713517150506011523 0ustar irlirlInstallation Instructions for AX.25 Library =========================================== To make this library you will need the following: glibc2.1 (Debian 2.1.1-5 or RedHat glibc-2.1.2-3) A Modern kernel (2.2.x) libtool To build it you type: ./configure make make install If you want to put the files in the "normal" places, type: ./configure --exec_prefix=/usr --sysconfdir=/etc --localstatedir=/var make make install That will put the binaries in /usr/{s}bin and the config files in /etc/ax25 If you want to install the example config files make installconf libax25/nrports.50000644000175000017500000000263213517150506012265 0ustar irlirl.TH NRPORTS 5 "2 August 1996" Linux "Linux Programmer's Manual" .SH NAME nrports \- NET/ROM port configuration file. .SH DESCRIPTION .LP .B Nrports is an ASCII file that contains information about each of the NET/ROM ports that are to be used. When dealing with an NET/ROM utility such as .B call, it takes an optional argument that is the port name. This port name is a reference to the line within .B nrports, which has the same name. The information on each line contains enough information to bind the command to a particular NET/ROM interface, this binding is done by matching the callsign on the line in .B nrports with the callsign of the port set by .B ifconfig. .LP The .B nrports file may contain comments that begin with a # in the first column, or a port description in the following format, each field being delimited by white space: .sp .RS name callsign alias paclen description .RE .sp The field descriptions are: .sp .RS .TP 14 .B name this is the unique NET/ROM port identifier. .TP 14 .B callsign the callsign of the NET/ROM interface to bind to. .TP 14 .B alias this is the alias of the NET/ROM port. .TP 14 .B paclen is the default packet size for this interface. .TP 14 .B description a free format description of this interface, this field extends to the end of the line. It may contain spaces. .RE .SH FILES .LP /etc/ax25/nrports .SH "SEE ALSO" .BR call (1), .BR netrom (4), .BR ifconfig (8), .BR nrparms (8). libax25/rsconfig.c0000644000175000017500000001407513517150506012452 0ustar irlirl#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "pathnames.h" typedef struct _rsport { struct _rsport *Next; char *Name; char *Addr; char *Device; char *Description; } RS_Port; static RS_Port *rs_ports; static RS_Port *rs_port_tail; static RS_Port *rs_port_ptr(char *name) { RS_Port *p = rs_ports; if (name == NULL) return p; while (p != NULL) { if (p->Name != NULL) { if (strcasecmp(name, p->Name) == 0) return p; } p = p->Next; } return NULL; } char *rs_config_get_next(char *name) { RS_Port *p; if (rs_ports == NULL) return NULL; if (name == NULL) return rs_ports->Name; if ((p = rs_port_ptr(name)) == NULL) return NULL; p = p->Next; if (p == NULL) return NULL; return p->Name; } char *rs_config_get_name(char *device) { RS_Port *p = rs_ports; while (p != NULL) { if (p->Device != NULL) { if (strcmp(device, p->Device) == 0) return p->Name; } p = p->Next; } return NULL; } char *rs_config_get_addr(char *name) { RS_Port *p = rs_port_ptr(name); if (p == NULL) return NULL; return p->Addr; } char *rs_config_get_dev(char *name) { RS_Port *p = rs_port_ptr(name); if (p == NULL) return NULL; return p->Device; } char *rs_config_get_port(rose_address *address) { RS_Port *p = rs_ports; rose_address addr; while (p != NULL) { if (p->Addr != NULL) { rose_aton(p->Addr, addr.rose_addr); if (rose_cmp(address, &addr) == 0) return p->Name; } p = p->Next; } return NULL; } char *rs_config_get_desc(char *name) { RS_Port *p = rs_port_ptr(name); if (p == NULL) return NULL; return p->Description; } int rs_config_get_paclen(char *name) { return 128; } static int rs_config_init_port(int fd, int lineno, char *line, const char **ifcalls, const char **ifdevs) { RS_Port *p; char *name, *addr, *desc; const char *dev = NULL; int found = 0; name = strtok(line, " \t"); addr = strtok(NULL, " \t"); desc = strtok(NULL, ""); if (name == NULL || addr == NULL || desc == NULL) { fprintf(stderr, "rsconfig: unable to parse line %d of config file\n", lineno); return FALSE; } for (p = rs_ports; p != NULL; p = p->Next) { if (p->Name != NULL && strcasecmp(name, p->Name) == 0) { fprintf(stderr, "rsconfig: duplicate port name %s in line %d of config file\n", name, lineno); return FALSE; } if (p->Addr != NULL && strcasecmp(addr, p->Addr) == 0) { fprintf(stderr, "rsconfig: duplicate address %s in line %d of config file\n", addr, lineno); return FALSE; } } found = 0; for (;ifcalls && *ifcalls; ++ifcalls, ++ifdevs) { if (strcmp(addr,*ifcalls) == 0) { found = 1; dev = *ifdevs; break; } } if (!found) { #if 0 /* None of your business to complain about some port being down... */ fprintf(stderr, "rsconfig: port %s not active\n", name); #endif return FALSE; } if ((p = (RS_Port *)malloc(sizeof(RS_Port))) == NULL) { fprintf(stderr, "rsconfig: out of memory!\n"); return FALSE; } p->Name = strdup(name); p->Addr = strdup(addr); p->Device = strdup(dev); p->Description = strdup(desc); if (rs_ports == NULL) rs_ports = p; else rs_port_tail->Next = p; rs_port_tail = p; p->Next = NULL; return TRUE; } int rs_config_load_ports(void) { FILE *fp = NULL; char buffer[256], *s; int fd, lineno = 1, n = 0, i; const char **calllist = NULL; const char **devlist = NULL; const char **pp; int callcount = 0; struct ifreq ifr; /* Reliable listing of all network ports on Linux is only available via reading /proc/net/dev ... */ if ((fd = socket(PF_FILE, SOCK_DGRAM, 0)) < 0) { fprintf(stderr, "rsconfig: unable to open socket (%s)\n", strerror(errno)); goto cleanup; } if ((fp = fopen("/proc/net/dev", "r"))) { /* Two header lines.. */ s = fgets(buffer, sizeof(buffer), fp); s = fgets(buffer, sizeof(buffer), fp); /* .. then network interface names */ while (!feof(fp)) { if (!fgets(buffer, sizeof(buffer), fp)) break; s = strchr(buffer, ':'); if (s) *s = 0; s = buffer; while (isspace(*s & 0xff)) ++s; memset(&ifr, 0, sizeof(ifr)); strncpy(ifr.ifr_name, s, IFNAMSIZ-1); ifr.ifr_name[IFNAMSIZ-1] = 0; if (ioctl(fd, SIOCGIFHWADDR, &ifr) < 0) { fprintf(stderr, "rsconfig: SIOCGIFHWADDR: %s\n", strerror(errno)); return FALSE; } if (ifr.ifr_hwaddr.sa_family != ARPHRD_ROSE) continue; /* store found interface callsigns */ /* rose_ntoa() returns pointer to static buffer */ s = rose_ntoa((void*)ifr.ifr_hwaddr.sa_data); if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { fprintf(stderr, "rsconfig: SIOCGIFFLAGS: %s\n", strerror(errno)); return FALSE; } if (!(ifr.ifr_flags & IFF_UP)) continue; if ((pp = realloc(calllist, sizeof(char *) * (callcount+2))) == 0) break; calllist = pp; if ((pp = realloc(devlist, sizeof(char *) * (callcount+2))) == 0) break; devlist = pp; if ((calllist[callcount] = strdup(s)) != NULL) { if ((devlist[callcount] = strdup(ifr.ifr_name)) != NULL) { ++callcount; calllist[callcount] = NULL; devlist [callcount] = NULL; } else { free((void*)calllist[callcount]); } } } fclose(fp); fp = NULL; } if ((fp = fopen(CONF_RSPORTS_FILE, "r")) == NULL) { fprintf(stderr, "rsconfig: unable to open axports file %s (%s)\n", CONF_RSPORTS_FILE, strerror(errno)); goto cleanup; } while (fp && fgets(buffer, 255, fp)) { if ((s = strchr(buffer, '\n'))) *s = '\0'; if (strlen(buffer) > 0 && *buffer != '#') if (rs_config_init_port(fd, lineno, buffer, calllist, devlist)) n++; lineno++; } cleanup:; if (fd >= 0) close(fd); if (fp) fclose(fp); for (i = 0; calllist && calllist[i]; ++i) { free((void*)calllist[i]); if (devlist[i] != NULL) free((void*)devlist[i]); } if (calllist) free(calllist); if (devlist) free(devlist); if (rs_ports == NULL) return 0; return n; } libax25/glibc.patch0000644000175000017500000000522413517150506012571 0ustar irlirl--- netax25/ax25.h.orig Fri Apr 30 13:59:17 1999 +++ netax25/ax25.h Fri Apr 30 14:17:16 1999 @@ -36,6 +36,7 @@ #define AX25_IDLE 9 #define AX25_PACLEN 10 #define AX25_IPMAXQUEUE 11 +#define AX25_IAMDIGI 12 #define AX25_KILL 99 /* AX.25 socket ioctls: */ @@ -48,6 +49,9 @@ #define SIOCAX25SETPARMS (SIOCPROTOPRIVATE+6) #define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7) #define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8) +#define SIOCAX25GETINFO (SIOCPROTOPRIVATE+9) +#define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10) +#define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11) /* unknown: */ #define AX25_NOUID_DEFAULT 0 @@ -101,6 +105,25 @@ ax25_address dest_addr; unsigned int cmd; unsigned long arg; + unsigned char digi_count; + ax25_address digi_addr[AX25_MAX_DIGIS]; + }; + +struct ax25_info_struct + { + unsigned int n2, n2count; + unsigned int t1, t1timer; + unsigned int t2, t2timer; + unsigned int t3, t3timer; + unsigned int idle, idletimer; + unsigned int state; + unsigned int rcv_q, snd_q; + }; + +struct ax25_fwd_struct + { + ax25_address port_from; + ax25_address port_to; }; /* AX.25 route structure: */ --- netrom/netrom.h.orig Fri Apr 30 14:17:53 1999 +++ netrom/netrom.h Fri Apr 30 14:19:52 1999 @@ -29,6 +29,7 @@ #define NETROM_T2 2 #define NETROM_N2 3 #define NETROM_PACLEN 5 +#define NETROM_T4 6 #define NETROM_KILL 99 @@ -45,6 +46,8 @@ char mnemonic[7]; ax25_address neighbour; unsigned int obs_count; + unsigned int ndigis; + ax25_address digipeaters[AX25_MAX_DIGIS]; }; /* NetRom socket ioctls: */ --- netrose/rose.h.orig Fri Apr 30 14:20:41 1999 +++ netrose/rose.h Fri Apr 30 14:24:55 1999 @@ -46,6 +46,7 @@ #define SIOCRSACCEPT (SIOCPROTOPRIVATE + 3) #define SIOCRSCLRRT (SIOCPROTOPRIVATE + 4) #define SIOCRSGL2CALL (SIOCPROTOPRIVATE + 5) +#define SIOCRSGFACILITIES (SIOCPROTOPRIVATE + 6) #define ROSE_DTE_ORIGINATED 0x00 #define ROSE_NUMBER_BUSY 0x01 @@ -73,6 +74,15 @@ ax25_address srose_digi; }; +struct full_sockaddr_rose +{ + sa_family_t srose_family; + rose_address srose_addr; + ax25_address srose_call; + unsigned int srose_ndigis; + ax25_address srose_digis[ROSE_MAX_DIGIS]; +}; + struct rose_route_struct { rose_address address; @@ -87,6 +97,18 @@ { unsigned char cause; unsigned char diagnostic; +}; + +struct rose_facilities_struct +{ + rose_address source_addr, dest_addr; + ax25_address source_call, dest_call; + unsigned char source_ndigis, dest_ndigis; + ax25_address source_digis[ROSE_MAX_DIGIS]; + ax25_address dest_digis[ROSE_MAX_DIGIS]; + unsigned int rand; + rose_address fail_addr; + ax25_address fail_call; }; #endif /* netrose/rose.h */ libax25/axutils.c0000644000175000017500000001270413517150506012326 0ustar irlirl#include #include #include #include #include #include #include #include #include #include ax25_address null_ax25_address = {{0x40, 0x40, 0x40, 0x40, 0x40, 0x40, 0x00}}; /* * Library routine for callsign conversion. */ int ax25_aton_entry(const char *name, char *buf) { int ct = 0; int ssid = 0; const char *p = name; char c; while (ct < 6) { c = toupper(*p); if (c == '-' || c == '\0') break; if (!isalnum(c)) { printf("axutils: invalid symbol in callsign '%s'\n", name); return -1; } buf[ct] = c << 1; p++; ct++; } while (ct < 6) { buf[ct] = ' ' << 1; ct++; } if (*p != '\0') { p++; if (sscanf(p, "%d", &ssid) != 1 || ssid < 0 || ssid > 15) { printf("axutils: SSID must follow '-' and be numeric in the range 0-15 - '%s'\n", name); return -1; } } buf[6] = ((ssid + '0') << 1) & 0x1E; return 0; } int ax25_aton(const char *call, struct full_sockaddr_ax25 *sax) { char *bp, *np; char *addrp; int n = 0; char *tmp = strdup(call); if (tmp == NULL) return -1; bp = tmp; addrp = sax->fsa_ax25.sax25_call.ax25_call; do { /* Fetch one callsign token */ while (*bp != '\0' && isspace(*bp)) bp++; np = bp; while (*np != '\0' && !isspace(*np)) np++; if (*np != '\0') *np++ = '\0'; /* Check for the optional 'via' syntax */ if (n == 1 && (strcasecmp(bp, "V") == 0 || strcasecmp(bp, "VIA") == 0)) { bp = np; continue; } /* Process the token */ if (ax25_aton_entry(bp, addrp) == -1) { free(tmp); return -1; } /* Move along */ bp = np; n++; if (n == 1) addrp = sax->fsa_digipeater[0].ax25_call; /* First digipeater address */ else addrp += sizeof(ax25_address); } while (n <= AX25_MAX_DIGIS && *bp); free(tmp); /* Tidy up */ sax->fsa_ax25.sax25_ndigis = n - 1; sax->fsa_ax25.sax25_family = AF_AX25; return sizeof(struct full_sockaddr_ax25); } int ax25_aton_arglist(const char *call[], struct full_sockaddr_ax25 *sax) { const char *bp; char *addrp; int n = 0; int argp = 0; addrp = sax->fsa_ax25.sax25_call.ax25_call; do { /* Fetch one callsign token */ if ((bp = call[argp++]) == NULL) break; /* Check for the optional 'via' syntax */ if (n == 1 && (strcasecmp(bp, "V") == 0 || strcasecmp(bp, "VIA") == 0)) continue; /* Process the token */ if (ax25_aton_entry(bp, addrp) == -1) return -1; n++; if (n == 1) addrp = sax->fsa_digipeater[0].ax25_call; /* First digipeater address */ else addrp += sizeof(ax25_address); } while (n <= AX25_MAX_DIGIS && call[argp] != NULL); /* Tidy up */ sax->fsa_ax25.sax25_ndigis = n - 1; sax->fsa_ax25.sax25_family = AF_AX25; return sizeof(struct full_sockaddr_ax25); } /* * Library routine for Rose address conversion. */ int rose_aton(const char *addr, char *buf) { int i, n; if (strlen(addr) != 10) { printf("axutils: invalid rose address '%s' length = %zd\n", addr, strlen(addr)); return -1; } if (strspn(addr, "0123456789") != 10) { printf("axutils: invalid characters in address\n"); return -1; } for (n = 0, i = 0; i < 5; i++, n += 2) { buf[i] = (addr[n + 0] - '0') << 4; buf[i] |= (addr[n + 1] - '0') << 0; } return 0; } /* * ax25 -> ascii conversion */ char *ax25_ntoa(const ax25_address *a) { static char buf[11]; char c, *s; int n; for (n = 0, s = buf; n < 6; n++) { c = (a->ax25_call[n] >> 1) & 0x7F; if (c != ' ') *s++ = c; } /* Convention is: -0 suffixes are NOT printed */ if (a->ax25_call[6] & 0x1E) { *s++ = '-'; if ((n = ((a->ax25_call[6] >> 1) & 0x0F)) > 9) { *s++ = '1'; n -= 10; } *s++ = n + '0'; } *s++ = '\0'; return buf; } /* * rose -> ascii conversion */ char *rose_ntoa(const rose_address *a) { static char buf[11]; sprintf(buf, "%02X%02X%02X%02X%02X", a->rose_addr[0] & 0xFF, a->rose_addr[1] & 0xFF, a->rose_addr[2] & 0xFF, a->rose_addr[3] & 0xFF, a->rose_addr[4] & 0xFF); return buf; } /* * Compare two ax.25 addresses */ int ax25_cmp(const ax25_address *a, const ax25_address *b) { if ((a->ax25_call[0] & 0xFE) != (b->ax25_call[0] & 0xFE)) return 1; if ((a->ax25_call[1] & 0xFE) != (b->ax25_call[1] & 0xFE)) return 1; if ((a->ax25_call[2] & 0xFE) != (b->ax25_call[2] & 0xFE)) return 1; if ((a->ax25_call[3] & 0xFE) != (b->ax25_call[3] & 0xFE)) return 1; if ((a->ax25_call[4] & 0xFE) != (b->ax25_call[4] & 0xFE)) return 1; if ((a->ax25_call[5] & 0xFE) != (b->ax25_call[5] & 0xFE)) return 1; if ((a->ax25_call[6] & 0x1E) != (b->ax25_call[6] & 0x1E)) /* SSID without control bit */ return 2; return 0; } /* * Compare two Rose addresses */ int rose_cmp(const rose_address *a, const rose_address *b) { int i; for (i = 0; i < 5; i++) if (a->rose_addr[i] != b->rose_addr[i]) return 1; return 0; } /* * Validate an AX.25 callsign. */ int ax25_validate(const char *call) { char s[7]; int n; for (n = 0; n < 6; n++) { s[n] = (call[n] >> 1) & 0x7F; } s[6] = '\0'; if (strspn(s, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ ") == 6) return TRUE; return FALSE; } /* * Convert a string to upper case */ char *strupr(char *s) { char *p; if (s == NULL) return NULL; for (p = s; *p != '\0'; p++) *p = toupper(*p); return s; } /* * Convert a string to lower case */ char *strlwr(char *s) { char *p; if (s == NULL) return NULL; for (p = s; *p != '\0'; p++) *p = tolower(*p); return s; } libax25/ttyutils.c0000644000175000017500000000510113517150506012527 0ustar irlirl#include #include #include #include #include #include #include #include "pathnames.h" static struct speed_struct { int user_speed; speed_t termios_speed; } speed_table[] = { {300, B300}, {600, B600}, {1200, B1200}, {2400, B2400}, {4800, B4800}, {9600, B9600}, {19200, B19200}, {38400, B38400}, #ifdef B57600 {57600, B57600}, #endif #ifdef B115200 {115200, B115200}, #endif #ifdef B230400 {230400, B230400}, #endif #ifdef B460800 {460800, B460800}, #endif {-1, B0} }; int tty_raw(int fd, int hwflag) { struct termios term; if (tcgetattr(fd, &term) == -1) { perror("tty_raw: tcgetattr"); return FALSE; } term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; term.c_iflag = IGNBRK | IGNPAR; term.c_oflag = 0; term.c_lflag = 0; #ifdef CIBAUD term.c_cflag = (term.c_cflag & (CBAUD | CIBAUD)) | CREAD | CS8 | CLOCAL; #else term.c_cflag = (term.c_cflag & CBAUD) | CREAD | CS8 | CLOCAL; #endif if (hwflag) term.c_cflag |= CRTSCTS; if (tcsetattr(fd, TCSANOW, &term) == -1) { perror("tty_raw: tcsetattr"); return FALSE; } return TRUE; } int tty_speed(int fd, int speed) { struct termios term; struct speed_struct *s; for (s = speed_table; s->user_speed != -1; s++) if (s->user_speed == speed) break; if (s->user_speed == -1) { fprintf(stderr, "tty_speed: invalid speed %d\n", speed); return FALSE; } if (tcgetattr(fd, &term) == -1) { perror("tty_speed: tcgetattr"); return FALSE; } cfsetispeed(&term, s->termios_speed); cfsetospeed(&term, s->termios_speed); if (tcsetattr(fd, TCSANOW, &term) == -1) { perror("tty_speed: tcsetattr"); return FALSE; } return TRUE; } int tty_is_locked(char *tty) { char buffer[50], *s; FILE *fp; int pid = 0; if ((s = strrchr(tty, '/')) != NULL) s++; else s = tty; sprintf(buffer, "%s/LCK..%s", LOCK_SERIAL_DIR, s); if ((fp = fopen(buffer, "r")) == NULL) return FALSE; if (fscanf(fp, "%d", &pid) != 1) { fclose(fp); return FALSE; } fclose(fp); if (kill(pid, 0) == 0) return TRUE; return FALSE; } int tty_lock(char *tty) { char buffer[50], *s; FILE *fp; if ((s = strrchr(tty, '/')) != NULL) s++; else s = tty; sprintf(buffer, "%s/LCK..%s", LOCK_SERIAL_DIR, s); if ((fp = fopen(buffer, "w")) == NULL) return FALSE; fprintf(fp, "%10d\n", getpid()); fclose(fp); return TRUE; } int tty_unlock(char *tty) { char buffer[50], *s; if ((s = strrchr(tty, '/')) != NULL) s++; else s = tty; sprintf(buffer, "%s/LCK..%s", LOCK_SERIAL_DIR, s); return unlink(buffer) == 0; } libax25/netrose/0000755000175000017500000000000013517150506012144 5ustar irlirllibax25/netrose/rose.h0000644000175000017500000000607613517150506013276 0ustar irlirl/* Definitions for Rose packet radio address family. Copyright (C) 1998, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ /* What follows is copied from the 2.1.93 . */ #ifndef _NETROSE_ROSE_H #define _NETROSE_ROSE_H 1 /* Socket level values. */ #define SOL_ROSE 260 /* These are the public elements of the Linux kernel Rose implementation. For kernel AX.25 see the file ax25.h. This file requires ax25.h for the definition of the ax25_address structure. */ #define ROSE_MTU 251 #define ROSE_MAX_DIGIS 6 #define ROSE_DEFER 1 #define ROSE_T1 2 #define ROSE_T2 3 #define ROSE_T3 4 #define ROSE_IDLE 5 #define ROSE_QBITINCL 6 #define ROSE_HOLDBACK 7 #define SIOCRSGCAUSE (SIOCPROTOPRIVATE + 0) #define SIOCRSSCAUSE (SIOCPROTOPRIVATE + 1) #define SIOCRSL2CALL (SIOCPROTOPRIVATE + 2) #define SIOCRSSL2CALL (SIOCPROTOPRIVATE + 2) #define SIOCRSACCEPT (SIOCPROTOPRIVATE + 3) #define SIOCRSCLRRT (SIOCPROTOPRIVATE + 4) #define SIOCRSGL2CALL (SIOCPROTOPRIVATE + 5) #define SIOCRSGFACILITIES (SIOCPROTOPRIVATE + 6) #define ROSE_DTE_ORIGINATED 0x00 #define ROSE_NUMBER_BUSY 0x01 #define ROSE_INVALID_FACILITY 0x03 #define ROSE_NETWORK_CONGESTION 0x05 #define ROSE_OUT_OF_ORDER 0x09 #define ROSE_ACCESS_BARRED 0x0B #define ROSE_NOT_OBTAINABLE 0x0D #define ROSE_REMOTE_PROCEDURE 0x11 #define ROSE_LOCAL_PROCEDURE 0x13 #define ROSE_SHIP_ABSENT 0x39 typedef struct { char rose_addr[5]; } rose_address; struct sockaddr_rose { sa_family_t srose_family; rose_address srose_addr; ax25_address srose_call; int srose_ndigis; ax25_address srose_digi; }; struct full_sockaddr_rose { sa_family_t srose_family; rose_address srose_addr; ax25_address srose_call; unsigned int srose_ndigis; ax25_address srose_digis[ROSE_MAX_DIGIS]; }; struct rose_route_struct { rose_address address; unsigned short int mask; ax25_address neighbour; char device[16]; unsigned char ndigis; ax25_address digipeaters[AX25_MAX_DIGIS]; }; struct rose_cause_struct { unsigned char cause; unsigned char diagnostic; }; struct rose_facilities_struct { rose_address source_addr, dest_addr; ax25_address source_call, dest_call; unsigned char source_ndigis, dest_ndigis; ax25_address source_digis[ROSE_MAX_DIGIS]; ax25_address dest_digis[ROSE_MAX_DIGIS]; unsigned int rand; rose_address fail_addr; ax25_address fail_call; }; #endif /* netrose/rose.h */ libax25/axports0000644000175000017500000000031013517150506012102 0ustar irlirl# /etc/ax25/axports # # The format of this file is: # # name callsign speed paclen window description # #1 OH2BNS-1 1200 255 2 144.675 MHz (1200 bps) #2 OH2BNS-9 38400 255 7 TNOS/Linux (38400 bps) libax25/ChangeLog0000644000175000017500000000605013517150506012240 0ustar irlirllibax25 0.0.12 * Interfaces with a callsign without SSID were not been found anymore after the last patch below. See cvs comment for detail. Affected files: axconfig.c, nrconfig.c and procutils.c. * ax25_ntoa() does no longer print a zero SSID. This avoids addresses like AB3DEF-0 which is general convention anyway. * Lots of small cleanup and fixes to silence warnings and issues raised by modern compilers, code checkers and manual review. * Updated to recent autoconf and automake version to keep the code buildable on modern distributions. * libax25 will again find AX.25 interfaces if if they do not have an IP address assigned. * Add support for building rpm packages. * Slightly modernize the implementation of daemon_start(). * Fix build issues with modern autoconf, automake and GCC. * For the tarball release Regenerate generates files with most recent autoconf and automake. * Improvments to git usage. * Update to work without warnings with latest autotools. * Lots of stylistic cleanups to the code trying to follow the coding style of the kernel. -- Thomas Osterried DL9SAU Wed, 01 Feb 2012 00:10:45 +0100 -- Ralf Baechle DL5RB Sat, 6 Jun 2009 17:00:00 +0100 libax25 0.0.11 * libax25io handles nonblocking io correctly. (PE1RXQ) THIS BREAKS PRACTICLY EVERY APP USING THIS LIBRARY, FIX THEM!!! -- Craig Small Fri, 21 Feb 2003 21:33:48 +1100 libax25 0.0.10 * Fixed byte counting in flush_obuf() (PE1RXQ) * Fixed buffer overflow in flush_obuf() (PE1RXQ) * axio_flush() actually flushes the buffer (PE1RXQ) -- Craig Small Fri, 29 Mar 2002 08:54:20 +1100 libax25 0.0.9 * Updated config.guess and config.sub for hppa * Updated stuff for new libtool -- Craig Small Tue, 28 Aug 2001 10:20:18 +1000 libax25 0.0.8 * Included ax25.h and rose.h for axlib.h Closes Debian bug #64102 -- Craig Small NEVER RELEASED libax25 0.0.7 * Added Tomi's patch to fix glibc 2.0 includes -- Craig Small Mon, 23 Aug 1999 11:23:40 +1000 libax25 0.0.6 * Fixed pathnames.h typo * Fixed instructions -- Craig Small , 19 Jul 1999 libax25 0.0.5 * More patches from Tomi for ax25io stuff * Cleaner way of naming config files * The licence use is now obvious * Added axports, rsports and nrports plus their man pages -- Craig Small , 5 Jul 1999 libax25 0.0.4 * Made some more functions use const args * Split the libaxio library out -- Craig Small , 30 Apr 1999 libax25 0.0.3 * Added Jean-Pauls ROSE patches * Changed all the convert names to ntoa type names * Added Tomi's axio stuff * Started writing ax25.3 and rose.3 -- Craig Small , 20 Apr 1999 libax25 0.0.2 * Initial version from Terry Dawson's code, split from the old ax25-utils package. -- Craig Small , 2 Apr 1999 libax25/COPYING0000644000175000017500000006364213517150506011533 0ustar irlirl GNU LESSER GENERAL PUBLIC LICENSE Version 2.1, February 1999 Copyright (C) 1991, 1999 Free Software Foundation, Inc. 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the Lesser GPL. It also counts as the successor of the GNU Library Public License, version 2, hence the version number 2.1.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Lesser General Public License, applies to some specially designated software packages--typically libraries--of the Free Software Foundation and other authors who decide to use it. You can use it too, but we suggest you first think carefully about whether this license or the ordinary General Public License is the better strategy to use in any particular case, based on the explanations below. When we speak of free software, we are referring to freedom of use, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish); that you receive source code or can get it if you want it; that you can change the software and use pieces of it in new free programs; and that you are informed that you can do these things. To protect your rights, we need to make restrictions that forbid distributors to deny you these rights or to ask you to surrender these rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link other code with the library, you must provide complete object files to the recipients, so that they can relink them with the library after making changes to the library and recompiling it. And you must show them these terms so they know their rights. We protect your rights with a two-step method: (1) we copyright the library, and (2) we offer you this license, which gives you legal permission to copy, distribute and/or modify the library. To protect each distributor, we want to make it very clear that there is no warranty for the free library. Also, if the library is modified by someone else and passed on, the recipients should know that what they have is not the original version, so that the original author's reputation will not be affected by problems that might be introduced by others. Finally, software patents pose a constant threat to the existence of any free program. We wish to make sure that a company cannot effectively restrict the users of a free program by obtaining a restrictive license from a patent holder. Therefore, we insist that any patent license obtained for a version of the library must be consistent with the full freedom of use specified in this license. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License. This license, the GNU Lesser General Public License, applies to certain designated libraries, and is quite different from the ordinary General Public License. We use this license for certain libraries in order to permit linking those libraries into non-free programs. When a program is linked with a library, whether statically or using a shared library, the combination of the two is legally speaking a combined work, a derivative of the original library. The ordinary General Public License therefore permits such linking only if the entire combination fits its criteria of freedom. The Lesser General Public License permits more lax criteria for linking other code with the library. We call this license the "Lesser" General Public License because it does Less to protect the user's freedom than the ordinary General Public License. It also provides other free software developers Less of an advantage over competing non-free programs. These disadvantages are the reason we use the ordinary General Public License for many libraries. However, the Lesser license provides advantages in certain special circumstances. For example, on rare occasions, there may be a special need to encourage the widest possible use of a certain library, so that it becomes a de-facto standard. To achieve this, non-free programs must be allowed to use the library. A more frequent case is that a free library does the same job as widely used non-free libraries. In this case, there is little to gain by limiting the free library to free software only, so we use the Lesser General Public License. In other cases, permission to use a particular library in non-free programs enables a greater number of people to use a large body of free software. For example, permission to use the GNU C Library in non-free programs enables many more people to use the whole GNU operating system, as well as its variant, the GNU/Linux operating system. Although the Lesser General Public License is Less protective of the users' freedom, it does ensure that the user of a program that is linked with the Library has the freedom and the wherewithal to run that program using a modified version of the Library. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, whereas the latter must be combined with the library in order to run. GNU LESSER GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library or other program which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Lesser General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also combine or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Use a suitable shared library mechanism for linking with the Library. A suitable mechanism is one that (1) uses at run time a copy of the library already present on the user's computer system, rather than copying library functions into the executable, and (2) will operate properly with a modified version of the library, if the user installs one, as long as the modified version is interface-compatible with the version that the work was made with. c) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. d) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. e) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the materials to be distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties with this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Lesser General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! libax25/nrports0000644000175000017500000000021313517150506012113 0ustar irlirl# /etc/ax25/nrports # # The format of this file is: # # name callsign alias paclen description # #netrom OH2BNS-10 #LNODE 235 Switch Port libax25/netax25/0000755000175000017500000000000013517150506011753 5ustar irlirllibax25/netax25/axlib.h0000644000175000017500000000727713517150506013240 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * Callsign conversion functions, converts callsigns into network bit * shifted format and vica versa. */ #ifndef _AXLIB_H #define _AXLIB_H #include #include #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif /* * Libax25 version. */ extern char libax25_version[]; /* * The special "null" address, used as the default callsign in routing and * in other places. */ extern ax25_address null_ax25_address; /* * This function converts an ASCII representation of a callsign into network * format. It returns -1 on error, 0 otherwise. */ extern int ax25_aton_entry(const char *, char *); /* * This converts a string with optional digipeaters into a structure understood * by the kernel code. * * The string should be in the format: * * callsign [[V | VIA] callsign ...] * * On error a -1 is returned, otherwise the length of the structure is returned. */ extern int ax25_aton(const char *, struct full_sockaddr_ax25 *); /* * Similar to convert_call above except the callsign(s) are not held in a * string but in a NULL terminated array of pointers to the strings. * On error a -1 is returned, otherwise the length of the structure is returned. */ extern int ax25_aton_arglist(const char ** , struct full_sockaddr_ax25 *); /* * This function converts an ASCII representation of a Rose address into * network format. It returns -1 on error, 0 otherwise. The address must be * ten numbers long. */ extern int rose_aton(const char *, char *); /* * This function returns the textual representation of a callsign in * network format. The data returned is in a statically allocated area, and * subsequent calls will destroy previous callsigns returned. */ extern char *ax25_ntoa(const ax25_address *); /* * This function returns the textual representation of a Rose address in * network format. The data returned is in a statically allocated area, and * subsequent calls will destroy previous callsigns returned. */ extern char *rose_ntoa(const rose_address *); /* * Compares two AX.25 callsigns in network format. Returns a 0 if they are * identical, 1 if they differ, or 2 if only the SSIDs differ. */ extern int ax25_cmp(const ax25_address *, const ax25_address *); /* * Compares two Rose addresses in network format. Returns a 0 if they are * identical, 1 if they differ. */ extern int rose_cmp(const rose_address *, const rose_address *); /* * Validates an AX.25 callsign, returns TRUE if it is valid, or FALSE if it * is not. The callsign should be AX.25 shifted format. */ extern int ax25_validate(const char *); /* * Converts the giver string to upper case. It returns a pointer to the * original string. */ extern char *strupr(char *); /* * Converts the giver string to lower case. It returns a pointer to the * original string. */ extern char *strlwr(char *); #ifdef __cplusplus } #endif #endif libax25/netax25/axconfig.h0000644000175000017500000000573713517150506013736 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * This file contains the definitions of the entry points into the AX.25 * configuration functions. */ #ifndef _AXCONFIG_H #define _AXCONFIG_H #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif /* * This function must be called before using any of the other functions in * this part of the library. It returns the number of active ports, or 0 * on failure. */ extern int ax25_config_load_ports(void); /* * This function allows the enumeration of all the active configured ports. * Passing NULL as the argument returns the first port name in the list, * subsequent calls to this function should be made with the last port name * returned. A NULL return indicates either an error, or the end of the list. */ extern char *ax25_config_get_next(char *); /* * This function maps the device name onto the port name (as used in the axports * file. On error a NULL is returned. */ extern char *ax25_config_get_name(char *); /* * This function maps the port name onto the callsign of the port. On error a * NULL is returned. */ extern char *ax25_config_get_addr(char *); /* * This function maps the port name onto the device name of the port. On error a * NULL is returned. */ extern char *ax25_config_get_dev(char *); /* * This function maps the callsign onto the port name. The callsign should be * in shifted format as per get{peer,sock}name(2). A null_ax25_address will * return a "*" meaning all ports. On error NULL is returned. */ extern char *ax25_config_get_port(ax25_address *); /* * This function takes the port name and returns the default window size. On * error 0 is returned. */ extern int ax25_config_get_window(char *); /* * This function takes the port name and returns the maximum packet length. * On error a 0 is returned. */ extern int ax25_config_get_paclen(char *); /* * This function takes the port name and returns the baud rate. On error a * 0 is returned. */ extern int ax25_config_get_baud(char *); /* * This function takes the port name and returns the description of the port. * On error a NULL is returned. */ extern char *ax25_config_get_desc(char *); #ifdef __cplusplus } #endif #endif libax25/netax25/daemon.h0000644000175000017500000000235513517150506013374 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * Function to convert a running process into a "proper" daemon. */ #ifndef _DAEMON_H #define _DAEMON_H #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif /* * The argument is whether to ignore the death of child processes. The function * return non-zero if all was OK, else zero if there was a problem. */ extern int daemon_start(int); #ifdef __cplusplus } #endif #endif libax25/netax25/ax25io.h0000644000175000017500000000555713517150506013247 0ustar irlirl/* AX25IO - Library for io manuipulation for AX.25 programs * Copyright (C) 1998 Tomi Manninen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ #ifndef _AX25IO_H #define _AX25IO_H #define AXBUFLEN 4096 typedef struct ax25io_s { int ifd; /* stdin socket index */ int ofd; /* stdout socket index */ char eol[4]; /* end-of-line sequence */ int eolmode; /* end-of-line translation on/off */ int telnetmode; /* telnet option negotiation on/off */ int tn_echo; /* will/wont echo */ int tn_linemode; /* will/wont linemode */ int size; /* size of the packet in input buffer */ int paclen; /* paclen */ unsigned char ibuf[AXBUFLEN]; /* input buffer */ unsigned char obuf[AXBUFLEN]; /* output buffer */ unsigned char gbuf[AXBUFLEN]; /* getline buffer */ int gbuf_usage; /* getline buffer usage */ int iptr; /* input pointer */ int optr; /* output pointer */ void *zptr; /* pointer to the compression struct */ struct ax25io_s *next; /* linked list pointer */ } ax25io; #define EOLMODE_TEXT 0 #define EOLMODE_BINARY 1 #define EOLMODE_GW 2 #define AX25_EOL "\r" #define NETROM_EOL AX25_EOL #define ROSE_EOL AX25_EOL #define INET_EOL "\r\n" #define UNSPEC_EOL "\n" #define INTERNAL_EOL 021271 #define ZERR_STREAM_END 1024 #define ZERR_STREAM_ERROR 1025 #define ZERR_DATA_ERROR 1026 #define ZERR_MEM_ERROR 1027 #define ZERR_BUF_ERROR 1028 #define ZERR_UNKNOWN 1029 extern ax25io *axio_init(int, int, int, char *); extern void axio_end(ax25io *); extern void axio_end_all(void); extern int axio_compr(ax25io *, int); extern int axio_paclen(ax25io *, int); extern int axio_eolmode(ax25io *, int); extern int axio_cmpeol(ax25io *, ax25io *); extern int axio_tnmode(ax25io *, int); extern int axio_flush(ax25io *); extern int axio_getc(ax25io *); extern int axio_putc(int, ax25io *); extern char *axio_getline(ax25io *); extern int axio_gets(char *, int, ax25io *); extern int axio_puts(const char *, ax25io *); extern int axio_printf(ax25io *, const char *, ...); extern int axio_tn_do_linemode(ax25io *); extern int axio_tn_will_echo(ax25io *); extern int axio_tn_wont_echo(ax25io *); #endif /* _AX25IO_H */ libax25/netax25/rsconfig.h0000644000175000017500000000507313517150506013743 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * This file contains the definitions of the entry points into the Rose * configuration functions. */ #ifndef _RSCONFIG_H #define _RSCONFIG_H #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif /* * This function must be called before using any of the other functions in * this part of the library. It returns the number of active ports, or 0 * on failure. */ extern int rs_config_load_ports(void); /* * This function allows the enumeration of all the active configured ports. * Passing NULL as the argument returns the first port name in the list, * subsequent calls to this function should be made with the last port name * returned. A NULL return indicates either an error, or the end of the list. */ extern char *rs_config_get_next(char *); /* * This function maps the device name onto the port name (as used in the axports * file. On error a NULL is returned. */ extern char *rs_config_get_name(char *); /* * This function maps the port name onto the address of the port. On error a * NULL is returned. */ extern char *rs_config_get_addr(char *); /* * This function maps the port name onto the device name of the port. On error a * NULL is returned. */ extern char *rs_config_get_dev(char *); /* * This function maps the Rose address in network format onto the port name. * On error, NULL is returned. */ extern char *rs_config_get_port(rose_address *); /* * This function takes the port name and returns the maximum packet length. * On error a 0 is returned. */ extern int rs_config_get_paclen(char *); /* * This function takes the port name and returns the description of the port. * On error a NULL is returned. */ extern char *rs_config_get_desc(char *); #ifdef __cplusplus } #endif #endif libax25/netax25/mheard.h0000644000175000017500000000406313517150506013367 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * This file documents the layout of the mheard file. Since this file is * common to at least two of the AX25 utilities, it is documented here. */ #ifndef MHEARD_H #define MHEARD_H struct mheard_struct { ax25_address from_call; ax25_address to_call; char portname[20]; unsigned int count; unsigned int sframes; unsigned int uframes; unsigned int iframes; unsigned int ndigis; ax25_address digis[8]; time_t first_heard; time_t last_heard; #define MHEARD_TYPE_SABM 0 #define MHEARD_TYPE_SABME 1 #define MHEARD_TYPE_DISC 2 #define MHEARD_TYPE_UA 3 #define MHEARD_TYPE_DM 4 #define MHEARD_TYPE_RR 5 #define MHEARD_TYPE_RNR 6 #define MHEARD_TYPE_REJ 7 #define MHEARD_TYPE_FRMR 8 #define MHEARD_TYPE_I 9 #define MHEARD_TYPE_UI 10 #define MHEARD_TYPE_UNKNOWN 11 unsigned int type; #define MHEARD_MODE_TEXT 0x0001 #define MHEARD_MODE_ARP 0x0002 #define MHEARD_MODE_IP_DG 0x0004 #define MHEARD_MODE_IP_VC 0x0008 #define MHEARD_MODE_NETROM 0x0010 #define MHEARD_MODE_ROSE 0x0020 #define MHEARD_MODE_FLEXNET 0x0040 #define MHEARD_MODE_TEXNET 0x0080 #define MHEARD_MODE_PSATPB 0x0100 #define MHEARD_MODE_PSATFT 0x0200 #define MHEARD_MODE_SEGMENT 0x4000 #define MHEARD_MODE_UNKNOWN 0x8000 unsigned int mode; char spare[128]; }; #endif libax25/netax25/nrconfig.h0000644000175000017500000000533113517150506013733 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * This file contains the definitions of the entry points into the NET/ROM * configuration functions. */ #ifndef _NRCONFIG_H #define _NRCONFIG_H #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif /* * This function must be called before using any of the other functions in * this part of the library. It returns the number of active ports, or 0 * on failure. */ extern int nr_config_load_ports(void); /* * This function allows the enumeration of all the active configured ports. * Passing NULL as the argument returns the first port name in the list, * subsequent calls to this function should be made with the last port name * returned. A NULL return indicates either an error, or the end of the list. */ extern char *nr_config_get_next(char *); /* * This function maps the device name onto the port name (as used in the axports * file. On error a NULL is returned. */ extern char *nr_config_get_name(char *); /* * This function maps the port name onto the callsign of the port. On error a * NULL is returned. */ extern char *nr_config_get_addr(char *); /* * This function maps the port name onto the device name of the port. On error a * NULL is returned. */ extern char *nr_config_get_dev(char *); /* * This function maps the callsign in AX.25 shifted format onto the port name. * On error, NULL is returned. */ extern char *nr_config_get_port(ax25_address *); /* * This function takes the port name and returns the alias of the port. On * error NULL is returned. */ extern char *nr_config_get_alias(char *); /* * This function takes the port name and returns the maximum packet length. * On error a 0 is returned. */ extern int nr_config_get_paclen(char *); /* * This function takes the port name and returns the description of the port. * On error a NULL is returned. */ extern char *nr_config_get_desc(char *); #ifdef __cplusplus } #endif #endif libax25/netax25/ax25.h0000644000175000017500000001131013517150506012677 0ustar irlirl/* Copyright (C) 1997, 1999 Free Software Foundation, Inc. This file is part of the GNU C Library. The GNU C Library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. The GNU C Library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with the GNU C Library; if not, see . */ #ifndef _NETAX25_AX25_H #define _NETAX25_AX25_H 1 #include #include /* Setsockoptions(2) level. Thanks to BSD these must match IPPROTO_xxx. */ #define SOL_AX25 257 /* AX.25 flags: */ #define AX25_WINDOW 1 #define AX25_T1 2 #define AX25_T2 5 #define AX25_T3 4 #define AX25_N2 3 #define AX25_BACKOFF 6 #define AX25_EXTSEQ 7 #define AX25_PIDINCL 8 #define AX25_IDLE 9 #define AX25_PACLEN 10 #define AX25_IPMAXQUEUE 11 #define AX25_IAMDIGI 12 #define AX25_KILL 99 /* AX.25 socket ioctls: */ #define SIOCAX25GETUID (SIOCPROTOPRIVATE) #define SIOCAX25ADDUID (SIOCPROTOPRIVATE+1) #define SIOCAX25DELUID (SIOCPROTOPRIVATE+2) #define SIOCAX25NOUID (SIOCPROTOPRIVATE+3) #define SIOCAX25BPQADDR (SIOCPROTOPRIVATE+4) #define SIOCAX25GETPARMS (SIOCPROTOPRIVATE+5) #define SIOCAX25SETPARMS (SIOCPROTOPRIVATE+6) #define SIOCAX25OPTRT (SIOCPROTOPRIVATE+7) #define SIOCAX25CTLCON (SIOCPROTOPRIVATE+8) #define SIOCAX25GETINFO (SIOCPROTOPRIVATE+9) #define SIOCAX25ADDFWD (SIOCPROTOPRIVATE+10) #define SIOCAX25DELFWD (SIOCPROTOPRIVATE+11) /* unknown: */ #define AX25_NOUID_DEFAULT 0 #define AX25_NOUID_BLOCK 1 #define AX25_SET_RT_IPMODE 2 /* Digipeating flags: */ #define AX25_DIGI_INBAND 0x01 /* Allow digipeating within port */ #define AX25_DIGI_XBAND 0x02 /* Allow digipeating across ports */ /* Maximim number of digipeaters: */ #define AX25_MAX_DIGIS 8 typedef struct { char ax25_call[7]; /* 6 call + SSID (shifted ascii) */ } ax25_address; struct sockaddr_ax25 { sa_family_t sax25_family; ax25_address sax25_call; int sax25_ndigis; }; /* * The sockaddr struct with the digipeater adresses: */ struct full_sockaddr_ax25 { struct sockaddr_ax25 fsa_ax25; ax25_address fsa_digipeater[AX25_MAX_DIGIS]; }; #define sax25_uid sax25_ndigis struct ax25_routes_struct { ax25_address port_addr; ax25_address dest_addr; unsigned char digi_count; ax25_address digi_addr[AX25_MAX_DIGIS]; }; /* The AX.25 ioctl structure: */ struct ax25_ctl_struct { ax25_address port_addr; ax25_address source_addr; ax25_address dest_addr; unsigned int cmd; unsigned long arg; unsigned char digi_count; ax25_address digi_addr[AX25_MAX_DIGIS]; }; struct ax25_info_struct { unsigned int n2, n2count; unsigned int t1, t1timer; unsigned int t2, t2timer; unsigned int t3, t3timer; unsigned int idle, idletimer; unsigned int state; unsigned int rcv_q, snd_q; }; struct ax25_fwd_struct { ax25_address port_from; ax25_address port_to; }; /* AX.25 route structure: */ struct ax25_route_opt_struct { ax25_address port_addr; ax25_address dest_addr; int cmd; int arg; }; /* AX.25 BPQ stuff: */ struct ax25_bpqaddr_struct { char dev[16]; ax25_address addr; }; /* Definitions for the AX.25 `values' fields: */ #define AX25_VALUES_IPDEFMODE 0 /* 'D'=DG 'V'=VC */ #define AX25_VALUES_AXDEFMODE 1 /* 8=Normal 128=Extended Seq Nos */ #define AX25_VALUES_NETROM 2 /* Allow NET/ROM - 0=No 1=Yes */ #define AX25_VALUES_TEXT 3 /* Allow PID=Text - 0=No 1=Yes */ #define AX25_VALUES_BACKOFF 4 /* 'E'=Exponential 'L'=Linear */ #define AX25_VALUES_CONMODE 5 /* Allow connected modes - 0=No 1=Yes */ #define AX25_VALUES_WINDOW 6 /* Default window size for standard AX.25 */ #define AX25_VALUES_EWINDOW 7 /* Default window size for extended AX.25 */ #define AX25_VALUES_T1 8 /* Default T1 timeout value */ #define AX25_VALUES_T2 9 /* Default T2 timeout value */ #define AX25_VALUES_T3 10 /* Default T3 timeout value */ #define AX25_VALUES_N2 11 /* Default N2 value */ #define AX25_VALUES_DIGI 12 /* Digipeat mode */ #define AX25_VALUES_IDLE 13 /* mode vc idle timer */ #define AX25_VALUES_PACLEN 14 /* AX.25 MTU */ #define AX25_VALUES_IPMAXQUEUE 15 /* Maximum number of buffers enqueued */ #define AX25_MAX_VALUES 20 struct ax25_parms_struct { ax25_address port_addr; unsigned short values[AX25_MAX_VALUES]; }; #endif /* netax25/ax25.h */ libax25/netax25/procutils.h0000644000175000017500000001073513517150506014156 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. : * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * Support routines to simplify the reading of the /proc/net/ax25* and * /proc/net/nr* files. */ #ifndef _PROCUTILS_H #define _PROCUTILS_H #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif struct proc_ax25_route { char call[10]; char dev[14]; int cnt; long t; struct proc_ax25_route *next; }; struct proc_ax25 { unsigned long magic; char dev[14]; char src_addr[10]; char dest_addr[10]; char digi_addr[8][11]; int ndigi; unsigned char st; unsigned short vs, vr, va; unsigned long t1timer, t1, t2timer, t2, t3timer, t3; unsigned long idletimer, idle; unsigned char n2count, n2; unsigned long rtt; unsigned char window; unsigned short paclen; unsigned short sndq, rcvq; unsigned long inode; struct proc_ax25 *next; }; struct proc_nr { char user_addr[10], dest_node[10], src_node[10]; char dev[14]; char my_circuit[6], ur_circuit[6]; unsigned char st; unsigned short vs, vr, va; unsigned long t1timer, t1, t2timer, t2, t4timer, t4; unsigned long idletimer, idle; unsigned char n2count, n2; unsigned char window; unsigned short sndq, rcvq; unsigned long inode; struct proc_nr *next; }; struct proc_nr_neigh { int addr; char call[10]; char dev[14]; int qual; int lock; int cnt; struct proc_nr_neigh *next; }; struct proc_nr_nodes { char call[10], alias[7]; unsigned char w, n; unsigned char qual1, qual2, qual3; unsigned char obs1, obs2, obs3; int addr1, addr2, addr3; struct proc_nr_nodes *next; }; struct proc_rs { char dest_addr[11], dest_call[10]; char src_addr[11], src_call[10]; char dev[14]; unsigned short lci; unsigned int neigh; unsigned char st; unsigned short vs, vr, va; unsigned short t, t1, t2, t3; unsigned short hb; unsigned long sndq, rcvq; struct proc_rs *next; }; struct proc_rs_route { unsigned short lci1; char address1[11], call1[10]; unsigned int neigh1; unsigned short lci2; char address2[11], call2[10]; unsigned int neigh2; struct proc_rs_route *next; }; struct proc_rs_neigh { int addr; char call[10]; char dev[14]; unsigned int count; unsigned int use; char mode[4]; char restart[4]; unsigned short t0, tf; struct proc_rs_neigh *next; }; struct proc_rs_nodes { char address[11]; unsigned char mask; unsigned char n; unsigned int neigh1, neigh2, neigh3; struct proc_rs_nodes *next; }; extern struct proc_ax25 *read_proc_ax25(void); extern void free_proc_ax25(struct proc_ax25 *ap); extern struct proc_ax25_route *read_proc_ax25_route(void); extern void free_proc_ax25_route(struct proc_ax25_route *rp); extern struct proc_nr *read_proc_nr(void); extern void free_proc_nr(struct proc_nr *); extern struct proc_nr_neigh *read_proc_nr_neigh(void); extern void free_proc_nr_neigh(struct proc_nr_neigh *np); extern struct proc_nr_nodes *read_proc_nr_nodes(void); extern void free_proc_nr_nodes(struct proc_nr_nodes *np); extern struct proc_rs *read_proc_rs(void); extern void free_proc_rs(struct proc_rs *); extern struct proc_rs_neigh *read_proc_rs_neigh(void); extern void free_proc_rs_neigh(struct proc_rs_neigh *); extern struct proc_rs_nodes *read_proc_rs_nodes(void); extern void free_proc_rs_nodes(struct proc_rs_nodes *); extern struct proc_rs_route *read_proc_rs_routes(void); extern void free_proc_rs_routes(struct proc_rs_route *); extern char *get_call(int uid); extern struct proc_ax25 *find_link(const char *src, const char *dest, const char *dev); extern struct proc_nr_neigh *find_neigh(int addr, struct proc_nr_neigh *neigh); extern struct proc_nr_nodes *find_node(char *addr, struct proc_nr_nodes *nodes); #ifdef _cplusplus } #endif #endif libax25/netax25/ttyutils.h0000644000175000017500000000350413517150506014027 0ustar irlirl/* LIBAX25 - Library for AX.25 programs * Copyright (C) 1997-1999 Jonathan Naylor, Tomi Manninen, Jean-Paul Roubelat * and Alan Cox. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, see * . */ /* * Generic serial port handling functions. */ #ifndef _TTYUTILS_H #define _TTYUTILS_H #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #ifdef __cplusplus extern "C" { #endif /* * Put a given file descriptor into raw mode, if the hwflag is set to TRUE * then hardware handshaking is enabled. Returns TRUE if successful. */ extern int tty_raw(int fd, int hwflag); /* * Set the speed of the given file descriptor. Returns TRUE is it was * successful. */ extern int tty_speed(int fd, int speed); /* * Determines whether a given tty is already open by another process. Returns * TRUE if is already locked, or FALSE if it is free. */ extern int tty_is_locked(char *tty); /* * Creates a lock file for the given tty. It writes the process ID to the * file so take care if doing a fork. Returns TRUE if everything was OK. */ extern int tty_lock(char *tty); /* * Removes the lock file for a given tty. Returns TRUE if successful. */ extern int tty_unlock(char *tty); #ifdef __cplusplus } #endif #endif libax25/pathnames.h0000644000175000017500000000141213517150506012614 0ustar irlirl/* * pathnames.h : Paths that are used by the library */ /* * AX25_SYSCONFDIR is defined in the Makefile!! */ #define CONF_AXPORTS_FILE AX25_SYSCONFDIR"axports" #define CONF_NRPORTS_FILE AX25_SYSCONFDIR"nrports" #define CONF_RSPORTS_FILE AX25_SYSCONFDIR"rsports" #define PROC_AX25_FILE "/proc/net/ax25" #define PROC_AX25_ROUTE_FILE "/proc/net/ax25_route" #define PROC_AX25_CALLS_FILE "/proc/net/ax25_calls" #define PROC_NR_FILE "/proc/net/nr" #define PROC_NR_NEIGH_FILE "/proc/net/nr_neigh" #define PROC_NR_NODES_FILE "/proc/net/nr_nodes" #define PROC_RS_FILE "/proc/net/rose" #define PROC_RS_NEIGH_FILE "/proc/net/rose_neigh" #define PROC_RS_NODES_FILE "/proc/net/rose_nodes" #define PROC_RS_ROUTES_FILE "/proc/net/rose_routes" #define LOCK_SERIAL_DIR "/var/lock" libax25/rsports0000644000175000017500000000015713517150506012127 0ustar irlirl# /etc/ax25/rsports # # The format of this file is: # # name address description # #rose 2080192203 Rose port libax25/axports.50000644000175000017500000000337013517150506012256 0ustar irlirl.TH AXPORTS 5 "2008-Feb-04" Linux "Linux Programmer's Manual" .SH NAME .I /etc/ax25/axports \- AX.25 port configuration file. .SH DESCRIPTION .LP .I axports is an ASCII file that contains information about each of the physical AX.25 ports that are to be used. When dealing with an AX.25 utility such as .BR call , it takes an argument that is the port name. This port name is a reference to the line within .B axports, which has that name as its first argument. The information on each line contains enough information to bind the command to a particular physical AX.25 interface, this binding is done by matching the callsign on the line in .B axports with the callsign of the port set by .B kissattach. .LP The lines within .I axports must either be a comment line, which starts with a # in the first column, or a port description in the following format, each field being delimited by white space: .sp .RS name callsign speed paclen window description .RE .sp The field descriptions are: .sp .RS .TP 14 .B name is the unique identifier of the port. This is the name given as the port argument of many of the AX.25 support programs. This is .I not in any way related to actual device identities, just unique .TP 14 .B callsign the callsign of the physical interface to bind to. .TP 14 .B speed this is the speed of interface, a value of zero means that no speed will be set by kissattach(8). .TP 14 .B paclen is the default maximum packet size for this interface. .TP 14 .B window the default window size for this interface. .TP 14 .B description a free format description of this interface, this field extends to the end of the line. This field may contain spaces. .RE .SH FILES .LP /etc/ax25/axports .SH "SEE ALSO" .BR call (1), .BR ax25 (4), .BR axparms (8), .BR kissattach (8). libax25/AUTHORS0000644000175000017500000000007213517150506011534 0ustar irlirlJonathan Naylor Tomi Manninen Jean-Paul ROUBELAT Alan Cox libax25/libax25.spec.in0000644000175000017500000000346313517150506013222 0ustar irlirlName: libax25 Version: @BASEVERSION@.@EXTRAVERSION@ Release: 1%{?dist} Summary: AX.25 library for hamradio applications License: LGPLv2+ URL: http://www.linux-ax25.org/ Source0: http://www.linux-ax25.org/pub/%{name}/%{name}-@VERSION@.tar.gz BuildRequires: gcc BuildRequires: zlib-devel %description libax25 is a library for ham radio applications that use the AX.25, NETROM or ROSE protocols. Included are routines to do ax25 address parsing, common ax25 application config file parsing, etc. %package devel Summary: Development files for %{name} Requires: %{name} = %{version}-%{release} %description devel The %{name}-devel package contains libraries and header files for developing applications that use %{name}. %package static Summary: Static library files for %{name} Requires: %{name}-static = %{version}-%{release} %description static The %{name}-static package contains the libax25 and libax25io libraries for static linking. You only need these for static linking applications. %prep %setup -q -n %{name}-@VERSION@ %build %configure make %{?_smp_mflags} %install rm -rf $RPM_BUILD_ROOT make DESTDIR=$RPM_BUILD_ROOT install make DESTDIR=$RPM_BUILD_ROOT installconf find $RPM_BUILD_ROOT -name '*.la' -exec rm -f {} ';' %clean rm -rf $RPM_BUILD_ROOT %post -p /sbin/ldconfig %postun -p /sbin/ldconfig %files %doc AUTHORS ChangeLog COPYING README %dir %{_sysconfdir}/ax25 %config(noreplace) %{_sysconfdir}/ax25/axports %config(noreplace) %{_sysconfdir}/ax25/nrports %config(noreplace) %{_sysconfdir}/ax25/rsports %{_libdir}/*.so.* %{_mandir}/man5/*.5* %files devel %{_includedir}/* %{_libdir}/*.so %{_mandir}/man3/*.3* %files static %{_libdir}/*.a %changelog * Sat Jun 27 2009 Ralf Baechle - Initial version libax25/NEWS0000644000175000017500000000012113517150506011156 0ustar irlirlNEWS for ax25-libs ================== This code is alpha, use at your own risk. libax25/daemon.c0000644000175000017500000000245713517150506012104 0ustar irlirl#include #include #include #include #include #include #include #include #include #include #include int daemon_start(int ignsigcld) { /* Code to initialize a daemon process. Taken from _UNIX Network */ /* Programming_ pp.72-85, by W. Richard Stephens, Prentice */ /* Hall PTR, 1990 */ int childpid; /* If started by init, don't bother */ if (getppid() == 1) goto out; /* Ignore the terminal stop signals */ signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); signal(SIGTSTP, SIG_IGN); /* Fork and let parent exit, insures we're not a process group leader */ if ((childpid = fork()) < 0) { return 0; } else if (childpid > 0) { exit(0); } /* * Disassociate from controlling terminal and process group and * ensure the process can't reacquire a new controlling terminal. * We're freshly forked, so setsid can't fail. */ (void) setsid(); out: /* Move the current directory to root, to make sure we aren't on a */ /* mounted filesystem. */ if (chdir("/") < 0) return 0; /* Clear any inherited file mode creation mask. */ umask(0); if (ignsigcld) signal(SIGCHLD, SIG_IGN); /* That's it, we're a "daemon" process now */ return 1; } libax25/README0000644000175000017500000000107213517150506011345 0ustar irlirlAX25 Library ============ This library set is still really under test but is now release for general use. You are supposed to use glibc 2.1 (libc6 unstable libraries) for this package. I have attempted to cater for glibc 2.0 users here. To compile this I used: * A Debian GNU/Linux system * autoconf 2.57 * automake 1.5 * libtool 1.4.3 * libc 2.3.1 * gcc 3.2.3 This library is copyright by the respective authors (see AUTHORS for a list) and licensed under the GNU LGPL (see COPYING for more information). - Craig Small