Logo Search packages:      
Sourcecode: isdnutils version File versions  Download package

ctrltimru.c

/*
 * ISDN TimRu-Control
 *
 * Copyright 1998 by Christian A. Lademann (cal@zls.de)
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2, or (at your option)
 * any later version.
 *
 * This program 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 *
 */

#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
#include <unistd.h>
#include <time.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <linux/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include "config.h"
#ifdef HAVE_TIMRU
#include <linux/isdn_timru.h>
#include <linux/isdn_budget.h>
#endif

#include "isdnctrl.h"
#include "ctrlconf.h"

#ifdef HAVE_TIMRU
/* TimRu - Erweiterung */
/*
06.06.97:cal:turnaround_rule(): bei nicht-umkehrbarer Regel mit 0 zurueckkehren
10.06.97:cal:hdl_timeout_rule(): memset(&timru, 0, ...)
12.06.97:cal:commandline-parsing kompatibel zur Hauptschleife, damit mehrere
      Kommandos hintereinander angegeben werden koennen; id und cmdptr werden
      an die betreffenden Funktionen uebergeben.
26.06.97:cal:neben "*" auch "any" als Wildcard-Angabe und neben "!" auch "not"
      als Negations-Angabe zulassen; bei "bringup" jetzt auch hup-timeout als
      initial-timeout einlesen.
09.06.98:cal:Mini-Glibc-Patch von Andreas Steffan <deas@uni-hamburg.de> eing.
*/

char  *timru_protfam_kt [] =  { "ip", "ipx", "ppp", "*", "any", "\0" };
int   timru_protfam_nt [] =   { ISDN_TIMRU_PROTFAM_IP,
                          ISDN_TIMRU_PROTFAM_IPX,
                          ISDN_TIMRU_PROTFAM_PPP,
                          ISDN_TIMRU_PROTFAM_WILDCARD,
                          ISDN_TIMRU_PROTFAM_WILDCARD,
                          -1 };

char  *timru_ip_kt [] = { "icmp", "tcp", "udp", "*", "any", "\0" };
int   timru_ip_nt [] =  { ISDN_TIMRU_IP_ICMP,
                          ISDN_TIMRU_IP_TCP,
                          ISDN_TIMRU_IP_UDP,
                          ISDN_TIMRU_IP_WILDCARD,
                          ISDN_TIMRU_IP_WILDCARD,
                          -1 };

char  *timru_ppp_kt [] =      { "ipcp", "ipxcp", "ccp", "lcp", "pap", "lqr", 
                          "chap", "*", "any", "\0" };
int   timru_ppp_nt [] = { ISDN_TIMRU_PPP_IPCP,
                          ISDN_TIMRU_PPP_IPXCP,
                          ISDN_TIMRU_PPP_CCP,
                          ISDN_TIMRU_PPP_LCP,
                          ISDN_TIMRU_PPP_PAP,
                          ISDN_TIMRU_PPP_LQR,
                          ISDN_TIMRU_PPP_CHAP,
                          ISDN_TIMRU_PPP_WILDCARD,
                          ISDN_TIMRU_PPP_WILDCARD,
                          -1 };


char  *timru_ruletype_kt [] = { "bringup", "keepup_in", "keepup_out", "\0" };
int   timru_ruletype_nt [] =  { ISDN_TIMRU_BRINGUP,
                          ISDN_TIMRU_KEEPUP_IN,
                          ISDN_TIMRU_KEEPUP_OUT,
                          -1 };

#define     MIN_IP_PORT 0
#define     MAX_IP_PORT 0xffff

#define     MIN_ICMP_TYPE     0
#define     MAX_ICMP_TYPE     0xff

int   flush_timeout_rules(int, char *, int, int, int, char *[]);
int   output_rule_header(int, int);
int   output_timeout_rules(int, char *, int, int, char *[]);
int   output_timeout_rule(isdn_ioctl_timeout_rule *);
int   read_icmp_type(char *, __u8 *, __u8 *);
int   read_ip_addr(char *, struct in_addr *, struct in_addr *);
int   read_ip_port(char *, char *, __u16 *, __u16 *);
int   set_default_timeout(int, char *, int, int, char *[]);
int   turnaround_rule(isdn_ioctl_timeout_rule *);
int   write_icmp_type(char *, __u8, __u8);
int   write_ip_addr(char *, struct in_addr, struct in_addr);
int   write_ip_port(char *, __u16, __u16);


int
read_ip_addr(char *s, struct in_addr *a, struct in_addr *m) {
      char        host [256],
                  mask [16];
      int         a1, a2, a3, a4;
      struct hostent    *he;
      struct netent     *ne;


      if(!strcmp(s, "*") || !strcmp(s, "any")) {
            a->s_addr = (__u32)htonl(0);
            m->s_addr = (__u32)htonl(0);

            return(0);
      }

      if(strchr(s, '/')) {
            strcpy(host, strtok(s, "/"));
            strcpy(mask, strtok(NULL, "/"));
      } else {
            strcpy(host, s);
            strcpy(mask, "0");
      }

      if(! strcmp(host, "0"))
            a->s_addr = (__u32)htonl(0x00000000);
      else if(sscanf(host, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) == 4)
            a->s_addr = (__u32)htonl((((a1&0xff)<<24)|((a2&0xff)<<16)|((a3&0xff)<<8)|(a4&0xff)));
      else if((ne = getnetbyname(s)) && ne->n_addrtype == AF_INET)
            a->s_addr = (__u32)htonl(ne->n_net);
      else if((he = gethostbyname(s)) && he->h_addrtype == AF_INET)
            memcpy(a, he->h_addr_list [0], sizeof(struct in_addr));
      else
            return(-1);

      if(sscanf(mask, "%d.%d.%d.%d", &a1, &a2, &a3, &a4) == 4)
            m->s_addr = (__u32)htonl((((a1&0xff)<<24)|((a2&0xff)<<16)|((a3&0xff)<<8)|(a4&0xff)));
      else if(sscanf(mask, "%d", &a1) == 1) {
            int   i;

            m->s_addr = (__u32)htonl(0);

            for(i = a1; i > 0; i--)
                  m->s_addr |= 1 << (32 - i);

            m->s_addr = (__u32)htonl(m->s_addr);
      } else
            return(-1);

      return(0);
}


int
write_ip_addr(char *s, struct in_addr a, struct in_addr m) {
      int   a1, a2, a3, a4, m1, m2, m3, m4,
            i, mbits, in_mask;


      if(a.s_addr == (__u32)ntohl(0))
            sprintf(s, "0");
      else {
            a1 = (ntohl(a.s_addr) >> 24) & 0xff;
            a2 = (ntohl(a.s_addr) >> 16) & 0xff;
            a3 = (ntohl(a.s_addr) >> 8) & 0xff;
            a4 = ntohl(a.s_addr) & 0xff;

            sprintf(s, "%d.%d.%d.%d", a1, a2, a3, a4);
      }

      mbits = 0;
      in_mask = 1;
      for(i = 31; i >= 0; i--) {
            if((((1 << i) & ntohl(m.s_addr)) != 0) == (in_mask != 0)) {
                  if(in_mask)
                        mbits++;
            } else {
                  if(in_mask)
                        in_mask = 0;
                  else
                        break;
            }
      }

      if(i < 0)
            sprintf(s, "%s/%d", s, mbits);
      else {
            m1 = (ntohl(m.s_addr) >> 24) & 0xff;
            m2 = (ntohl(m.s_addr) >> 16) & 0xff;
            m3 = (ntohl(m.s_addr) >> 8) & 0xff;
            m4 = ntohl(m.s_addr) & 0xff;

            sprintf(s, "%s/%d.%d.%d.%d", s, m1, m2, m3, m4);
      }

      return(0);
}


int
read_ip_port(char *s, char *proto, __u16 *from, __u16 *to) {
      int         f, t, n;
      char        *q;
      struct servent    *service;


      if(!strcmp(s, "*") || !strcmp(s, "any")) {
            f = MIN_IP_PORT;
            t = MAX_IP_PORT;
      } else {
            if(proto && (service = getservbyname(s, proto))) /* specific port by name */
                  f = t = ntohs(service->s_port);
            else
                  if((q = strchr(s, '-'))) {    /* port range */
                        if(q - s == 0)    /* -to: empty from */
                              f = MIN_IP_PORT;
                        else {
                              if(sscanf(s, "%i%n", &f, &n) <= 0 || n != q - s)
                                    return(-1);
                        }
                  
                        if(! *(q + 1))    /* from-: empty to */
                              t = MAX_IP_PORT;
                        else {
                              if(sscanf(q + 1, "%i%n", &t, &n) <= 0 || n != strlen(q + 1))
                                    return(-1);
                        }
                  } else {    /* specific port */
                        if(sscanf(s, "%i%n", &f, &n) > 0 || n == strlen(s))
                              t = f;
                        else
                              return(-1);
                  }
      }

      if(f < MIN_IP_PORT || f > MAX_IP_PORT || t < MIN_IP_PORT || t > MAX_IP_PORT)
            return(-1);

      *from = (__u16)htons(f);
      *to = (__u16)htons(t);

      return(0);
}


int
write_ip_port(char *s, __u16 from, __u16 to) {
      if(ntohs(from) == MIN_IP_PORT && ntohs(to) == MAX_IP_PORT)
            sprintf(s, "*");
      else if(from == to)
            sprintf(s, "%d", ntohs(from));
      else
            sprintf(s, "%d-%d", ntohs(from), ntohs(to));

      return(0);
}


int
read_icmp_type(char *s, __u8 *from, __u8 *to) {
      int         f, t, n;
      char        *q;


      if(!strcmp(s, "*") || !strcmp(s, "any")) {
            f = MIN_ICMP_TYPE;
            t = MAX_ICMP_TYPE;
      } else {
            if((q = strchr(s, '-'))) {    /* port range */
                  if(q - s == 0)    /* -to: empty from */
                        f = MIN_ICMP_TYPE;
                  else {
                        if(sscanf(s, "%i%n", &f, &n) <= 0 || n != q - s)
                              return(-1);
                  }
                  
                  if(! *(q + 1))    /* from-: empty to */
                        t = MAX_ICMP_TYPE;
                  else {
                        if(sscanf(q + 1, "%i%n", &t, &n) <= 0 || n != strlen(q + 1))
                              return(-1);
                  }
            } else {    /* specific port */
                  if(sscanf(s, "%i%n", &f, &n) > 0 || n == strlen(s))
                        t = f;
                  else
                        return(-1);
            }
      }

      if(f < MIN_ICMP_TYPE || f > MAX_ICMP_TYPE || t < MIN_ICMP_TYPE || t > MAX_ICMP_TYPE)
            return(-1);

      *from = (__u8)f;
      *to = (__u8)t;

      return(0);
}


int
write_icmp_type(char *s, __u8 from, __u8 to) {
      if(from == MIN_ICMP_TYPE && to == MAX_ICMP_TYPE)
            sprintf(s, "*");
      else if(from == to)
            sprintf(s, "%d", from);
      else
            sprintf(s, "%d-%d", from, to);

      return(0);
}


#define     SHIFT_ARGS(msg)   { \
      if(++argp >= argc) { \
            fprintf(stderr, "rule-parser: out of arguments"); \
            if(strlen(msg)) \
                  fprintf(stderr, " looking for %s", (msg)); \
            fprintf(stderr, "\n"); \
            return(-1); \
      } else { \
            ++args_used; \
      } \
}


#define     UNSHIFT_ARGS(i) { \
      if(argp > (i)) { \
            argp -= (i); \
            args_used -= (i); \
      } \
}


#define     PARSER_ERROR(msg) { \
      fprintf(stderr, "rule-parser: parse-error"); \
      if(strlen(msg)) \
            fprintf(stderr, ": %s", (msg)); \
      fprintf(stderr, "\n"); \
      return(-1); \
}

#define max(a, b) ((a) > (b) ? (a) : (b))


int
hdl_timeout_rule(int fd, char *id, int cmd, int argc, char *argv []) {
      isdn_ioctl_timeout_rule timru;
      int               ioctl_fcn,
                        n_protfam, n_prot,
                        ioret, n,
                        other_type = -1,
                        argp = 0,
                        args_used = 0;
      char        k_protfam [16], k_prot [16];


      memset(&timru, 0, sizeof(isdn_ioctl_timeout_rule));

      /* cmd */
      switch(cmd) {
      case ADDRULE:
            ioctl_fcn = IIOCNETARU;
            timru.where = 1;
            break;

      case INSRULE:
            ioctl_fcn = IIOCNETARU;
            timru.where = 0;
            break;

      case DELRULE:
            ioctl_fcn = IIOCNETDRU;
            break;

      case DEFAULT:
            return(args_used + set_default_timeout(fd, id, argp, argc, argv));
            break;

      case SHOWRULES:
            return(args_used + output_timeout_rules(fd, id, argp, argc, argv));
            break;

      case FLUSHRULES:
            return(args_used + flush_timeout_rules(fd, id, 0, argp, argc, argv));
            break;

      case FLUSHALLRULES:
            return(args_used + flush_timeout_rules(fd, id, 1, argp, argc, argv));
            break;

      default:
            PARSER_ERROR("unknown command");
      }

      /* interface */
      strncpy(timru.name, id, sizeof(timru.name) - 1);

      /* rule-type */
      /* SHIFT_ARGS("rule-type"); */
      if(! strcmp(argv [argp], "bringup")) {
            timru.rule.type = ISDN_TIMRU_BRINGUP;
      } else if(! strcmp(argv [argp], "keepup")) {
            /* keepup-type */
            SHIFT_ARGS("keepup-type");
            if(! strcmp(argv [argp], "in"))
                  timru.rule.type = ISDN_TIMRU_KEEPUP_IN;
            else if(! strcmp(argv [argp], "out"))
                  timru.rule.type = ISDN_TIMRU_KEEPUP_OUT;
            else if(! strcmp(argv [argp], "both")) {
                  timru.rule.type = ISDN_TIMRU_KEEPUP_IN;
                  other_type = ISDN_TIMRU_KEEPUP_OUT;
            } else
                  PARSER_ERROR("wrong keepup-type");
      } else
            PARSER_ERROR("wrong rule-type");

      /* hup-timeout */
      SHIFT_ARGS("hup-timeout");
      if(sscanf(argv [argp], "%i%n", &timru.rule.timeout, &n) <= 0 || n != strlen(argv [argp]))
            PARSER_ERROR("wrong timeout");

      /* neg */
      SHIFT_ARGS("rule-parameter");
      if(! strcmp(argv [argp], "!") || ! strcmp(argv [argp], "not")) {
            timru.rule.neg = 1;
            SHIFT_ARGS("rule-parameter");
      } else
            timru.rule.neg = 0;

      /* rule */
      if(strchr(argv [argp], '/')) {
            if(sscanf(argv [argp], "%[a-z0-9*]/%[a-z0-9*]", k_protfam, k_prot) != 2)
                  PARSER_ERROR("wrong protocol specification");
      } else {
            if(! strcmp(argv [argp], "any")) {
                  strcpy(k_protfam, "any");
                  strcpy(k_prot, "any");
            } else
                  PARSER_ERROR("wrong protocol specification");
      }

      if((n_protfam = key2num(k_protfam, timru_protfam_kt, timru_protfam_nt)) < 0)
            PARSER_ERROR("wrong protocol-family");

      timru.rule.protfam = n_protfam;

      switch(timru.rule.protfam) {
      case ISDN_TIMRU_PROTFAM_IP:
            if((n_prot = key2num(k_prot, timru_ip_kt, timru_ip_nt)) < 0)
                  PARSER_ERROR("wrong ip-protocol");

            timru.rule.rule.ip.protocol = n_prot;

            /* src-addr */
            SHIFT_ARGS("source-address");
            if(read_ip_addr(argv [argp], &timru.rule.rule.ip.saddr, &timru.rule.rule.ip.smask) < 0)
                  PARSER_ERROR("wrong source-address");

            switch(timru.rule.rule.ip.protocol) {
            case ISDN_TIMRU_IP_ICMP:
                  /* port-range */
                  SHIFT_ARGS("icmp-type(s)");
                  if(read_icmp_type(argv [argp], &timru.rule.rule.ip.pt.type.from, &timru.rule.rule.ip.pt.type.to) < 0)
                        PARSER_ERROR("wrong icmp-type(s)");
                  break;

            case ISDN_TIMRU_IP_TCP:
            case ISDN_TIMRU_IP_UDP:
                  /* service-range */
                  SHIFT_ARGS("source port-number(s)");
                  if(read_ip_port(argv [argp], k_prot, &timru.rule.rule.ip.pt.port.s_from, &timru.rule.rule.ip.pt.port.s_to) < 0)
                        PARSER_ERROR("wrong source port-number(s)");
                  break;
            }

            /* dst-addr */
            SHIFT_ARGS("destination-address");
            if(read_ip_addr(argv [argp], &timru.rule.rule.ip.daddr, &timru.rule.rule.ip.dmask) < 0)
                  PARSER_ERROR("wrong destination-address");

            switch(timru.rule.rule.ip.protocol) {
            case ISDN_TIMRU_IP_TCP:
            case ISDN_TIMRU_IP_UDP:
                  /* service-range */
                  SHIFT_ARGS("destination port-number(s)");
                  if(read_ip_port(argv [argp], k_prot, &timru.rule.rule.ip.pt.port.d_from, &timru.rule.rule.ip.pt.port.d_to) < 0)
                        PARSER_ERROR("wrong destination port-number(s)");
                  break;
            }

            break;
      
      case ISDN_TIMRU_PROTFAM_PPP:
            if((n_prot = key2num(k_prot, timru_ppp_kt, timru_ppp_nt)) < 0)
                  PARSER_ERROR("wrong ppp-protocol");

            timru.rule.rule.ppp.protocol = n_prot;
            break;
      }

      if((ioret = ioctl(fd, ioctl_fcn, &timru)) < 0) {
            perror("ioctl failed.");
            return(ioret);
      }

      if(other_type >= 0) {
            if(turnaround_rule(&timru) < 0)
                  return(-1);

            timru.rule.type = other_type;

            if((ioret = ioctl(fd, ioctl_fcn, &timru)) < 0) {
                  perror("ioctl failed.");
                  return(ioret);
            }
      }

      return(args_used);
}


int
turnaround_rule(isdn_ioctl_timeout_rule *timru) {
      isdn_ioctl_timeout_rule timbuf;

      memcpy((char *)&timbuf, (char *)timru, sizeof(isdn_ioctl_timeout_rule));
      switch(timru->rule.protfam) {
      case ISDN_TIMRU_PROTFAM_IP:
            memcpy((char *)&timru->rule.rule.ip.saddr, (char *)&timbuf.rule.rule.ip.daddr, sizeof(timbuf.rule.rule.ip.daddr));
            memcpy((char *)&timru->rule.rule.ip.smask, (char *)&timbuf.rule.rule.ip.dmask, sizeof(timbuf.rule.rule.ip.dmask));
            memcpy((char *)&timru->rule.rule.ip.daddr, (char *)&timbuf.rule.rule.ip.saddr, sizeof(timbuf.rule.rule.ip.saddr));
            memcpy((char *)&timru->rule.rule.ip.dmask, (char *)&timbuf.rule.rule.ip.smask, sizeof(timbuf.rule.rule.ip.smask));

            switch(timru->rule.rule.ip.protocol) {
            case ISDN_TIMRU_IP_TCP:
            case ISDN_TIMRU_IP_UDP:
                  timru->rule.rule.ip.pt.port.s_from = timbuf.rule.rule.ip.pt.port.d_from;
                  timru->rule.rule.ip.pt.port.s_to = timbuf.rule.rule.ip.pt.port.d_to;
                  timru->rule.rule.ip.pt.port.d_from = timbuf.rule.rule.ip.pt.port.s_from;
                  timru->rule.rule.ip.pt.port.d_to = timbuf.rule.rule.ip.pt.port.s_to;
                  break;
            }
            break;
      }
      return(0);
}


int
output_timeout_rules(int fd, char *id, int firstarg, int argc, char *argv []) {
      isdn_ioctl_timeout_rule timru;
      int               i, j, k,
                        header_printed;


      /* interface */
      strncpy(timru.name, id, sizeof(timru.name) - 1);

      printf("Timeout rules for interface %s:\n", timru.name);

      for(i = 0; i < ISDN_TIMRU_NUM_CHECK; i++) {
            timru.where = -1;
            timru.type = i;

            if(ioctl(fd, IIOCNETGRU, &timru) == 0) {
                  switch(i) {
                  case ISDN_TIMRU_BRINGUP:
                        printf("Default bringup policy: ");
                        if(timru.defval == 0)
                              printf("false\n");
                        else
                              printf("true, initial timeout is %d sec.\n", timru.defval);
                        break;

                  case ISDN_TIMRU_KEEPUP_IN:
                        printf("Default huptimeout for incoming packets: %d sec.\n", timru.defval);
                        break;

                  case ISDN_TIMRU_KEEPUP_OUT:
                        printf("Default huptimeout for outgoing packets: %d sec.\n", timru.defval);
                        printf("\nCurrent huptimeout: %d sec.\n", timru.index);
                        printf("Time until hangup: %d sec.\n", max(0, timru.index - timru.protfam));
                        break;
                  }
            }
      }

      for(i = 0; i < ISDN_TIMRU_NUM_CHECK; i++) {
            header_printed = 0;
            for(j = 0; j < ISDN_TIMRU_NUM_PROTFAM; j++) {
                  k = 0;
                  header_printed = 0;
                  while(1) {
                        timru.type = i;
                        timru.protfam = j;
                        timru.index = k;
                        timru.where = 0;

                        if(ioctl(fd, IIOCNETGRU, &timru) == 0) {
                              if(! header_printed) {
                                    output_rule_header(i, j);
                                    header_printed = 1;
                              }
                              output_timeout_rule(&timru);
                        } else
                              break;

                        k++;
                  }
            }
      }

      return(0);
}


int
output_timeout_rule(isdn_ioctl_timeout_rule *timru) {
      char  str [80];

      /* rule-nr */
      printf("%d-%d-%-d ", timru->type, timru->protfam, timru->index);

      /* rule-type */
      printf("%s ", num2key(timru->rule.type, timru_ruletype_kt, timru_ruletype_nt));
      
      /* timeout */
      if(timru->rule.type != ISDN_TIMRU_BRINGUP)
            printf("%d ", timru->rule.timeout);

      /* neg */
      printf("%s", (timru->rule.neg ? "!" : ""));

      /* protocol */
      printf("%s", num2key(timru->rule.protfam, timru_protfam_kt, timru_protfam_nt));
      switch(timru->rule.protfam) {
      case ISDN_TIMRU_PROTFAM_IP:
            /* protocol */
            printf("/%s ", num2key(timru->rule.rule.ip.protocol, timru_ip_kt, timru_ip_nt));

            /* src addr */
            write_ip_addr(str, timru->rule.rule.ip.saddr, timru->rule.rule.ip.smask);
            printf("%s ", str);

            /* src port/type */
            strcpy(str, "\0");
            switch(timru->rule.rule.ip.protocol) {
            case ISDN_TIMRU_IP_ICMP:
                  write_icmp_type(str, timru->rule.rule.ip.pt.type.from, timru->rule.rule.ip.pt.type.to);
                  printf("%s ", str);
                  break;
            
            case ISDN_TIMRU_IP_TCP:
            case ISDN_TIMRU_IP_UDP:
                  write_ip_port(str, timru->rule.rule.ip.pt.port.s_from, timru->rule.rule.ip.pt.port.s_to);
                  printf("%s ", str);
                  break;
            }

            /* dst addr */
            write_ip_addr(str, timru->rule.rule.ip.daddr, timru->rule.rule.ip.dmask);
            printf("%s ", str);

            /* dst port */
            strcpy(str, "\0");
            switch(timru->rule.rule.ip.protocol) {
            case ISDN_TIMRU_IP_TCP:
            case ISDN_TIMRU_IP_UDP:
                  write_ip_port(str, timru->rule.rule.ip.pt.port.d_from, timru->rule.rule.ip.pt.port.d_to);
                  printf("%s ", str);
                  break;
            }
            break;

      case ISDN_TIMRU_PROTFAM_PPP:
            printf("/%s", num2key(timru->rule.rule.ppp.protocol, timru_ppp_kt, timru_ppp_nt));
            break;

      default:
            printf(" ");
            break;
      }

      printf("\n");

      return(0);
}


int
output_rule_header(int rule_type, int protfam) {
      printf("\n");
      switch(rule_type) {
      case ISDN_TIMRU_BRINGUP:      printf("Bringup-rules for outgoing "); break;
      case ISDN_TIMRU_KEEPUP_IN:    printf("Keepup-rules for incoming "); break;
      case ISDN_TIMRU_KEEPUP_OUT:   printf("Keepup-rules for outgoing "); break;
      }
      printf("%s-packets:\n", num2key(protfam, timru_protfam_kt, timru_protfam_nt));

      return(0);
}


int
flush_timeout_rules(int fd, char *id, int all, int firstarg, int argc, char *argv []) {
      isdn_ioctl_timeout_rule timru;
      int               i, j, first, last,
                        argp = firstarg,
                        args_used = 0;
      char              name [9];


      /* interface */
      strncpy(name, id, sizeof(name) - 1);

      if(all) {
            first = 0;
            last = ISDN_TIMRU_NUM_CHECK - 1;
      } else {
            /* rule-type */
            SHIFT_ARGS("rule-type");
            if(! strcmp(argv [argp], "bringup")) {
                  first = last = ISDN_TIMRU_BRINGUP;
            } else if(! strcmp(argv [argp], "keepup")) {
                  /* keepup-type */
                  SHIFT_ARGS("keepup-type");
                  if(! strcmp(argv [argp], "in"))
                        first = last = ISDN_TIMRU_KEEPUP_IN;
                  else if(! strcmp(argv [argp], "out"))
                        first = last = ISDN_TIMRU_KEEPUP_OUT;
                  else if(! strcmp(argv [argp], "both")) {
                        first = ISDN_TIMRU_KEEPUP_IN;
                        last = ISDN_TIMRU_KEEPUP_OUT;
                  } else
                        PARSER_ERROR("wrong keepup-type");
            } else
                  PARSER_ERROR("wrong rule-type");
      }

      for(i = first; i <= last; i++) {
            for(j = 0; j < ISDN_TIMRU_NUM_PROTFAM; j++) {
                  while(1) {
                        strcpy(timru.name, name);
                        timru.where = 0;
                        timru.type = i;
                        timru.protfam = j;
                        timru.index = 0;

                        if(ioctl(fd, IIOCNETGRU, &timru) < 0)
                              break;

                        if(ioctl(fd, IIOCNETDRU, &timru) < 0)
                              break;
                  }
            }
      }

      return(args_used);
}


int
set_default_timeout(int fd, char *id, int firstarg, int argc, char *argv []) {
      isdn_ioctl_timeout_rule timru;
      int               n, ret, other_type = -1,
                        argp = firstarg,
                        args_used = 0;


      /* set defaults */
      timru.where = -1;

      /* interface */
      strncpy(timru.name, id, sizeof(timru.name) - 1);

      /* rule-type */
      SHIFT_ARGS("rule-type");
      if(! strcmp(argv [argp], "bringup")) {
            timru.type = ISDN_TIMRU_BRINGUP;
      } else if(! strcmp(argv [argp], "keepup")) {
            /* keepup-type */
            SHIFT_ARGS("keepup-type");
            if(! strcmp(argv [argp], "in"))
                  timru.type = ISDN_TIMRU_KEEPUP_IN;
            else if(! strcmp(argv [argp], "out"))
                  timru.type = ISDN_TIMRU_KEEPUP_OUT;
            else if(! strcmp(argv [argp], "both")) {
                  timru.type = ISDN_TIMRU_KEEPUP_IN;
                  other_type = ISDN_TIMRU_KEEPUP_OUT;
            } else
                  PARSER_ERROR("wrong keepup-type");
      } else
            PARSER_ERROR("wrong rule-type");

      /* default value */
      SHIFT_ARGS("default-value");
      if(sscanf(argv [argp], "%i%n", &timru.defval, &n) <= 0 || n != strlen(argv [argp]))
            PARSER_ERROR("wrong default-value");

      if((ret = ioctl(fd, IIOCNETARU, &timru)) < 0)
            return(ret);

      if(other_type >= 0) {
            timru.type = other_type;
            if((ret = ioctl(fd, IIOCNETARU, &timru)) < 0)
                  return(ret);
      }

      return(args_used);
}


char *
defs_timru(char *id) {
      static char r [1024];
      char  *p = r;

      p += sprintf(p, "addrule %s keepup in 0 ppp/lcp\n", id);

      return(r);
}


/* Budget-Erweiterung */
/*
??.07.97:cal:DAY: (60 * HOUR) --> (24 * HOUR)
04.11.97:cal:div. Formatierungen
*/

int output_budgets(int, char *, int, int, int, char *[]);
int read_budget_time(char *, time_t *);
char *write_budget_time(time_t);
char *output_time(time_t *);

#define     MINUTE      60
#define     HOUR  (60 * MINUTE)
#define     DAY   (24 * HOUR)
#define     WEEK  (7 * DAY)
#define     MONTH (30 * DAY)
#define     YEAR  (365 * DAY)


int
hdl_budget(int fd, char *id, int cmd, int argc, char *argv []) {
      isdn_ioctl_budget budget;
      int               ioret, n,
                        argp = 0,
                        args_used = 0;
      time_t            t;


      memset(&budget, 0, sizeof(isdn_ioctl_budget));

      /* cmd */
      switch(cmd) {
      case SHOWBUDGETS:
      case SAVEBUDGETS:
            return(args_used + output_budgets(fd, id, cmd, argp, argc, argv));
            break;

      case BUDGET:
            /* interface */
            strncpy(budget.name, id, sizeof(budget.name) - 1);

            /* budget-type */
            SHIFT_ARGS("rule-type");
            if(! strcmp(argv [argp], "dial"))
                  budget.budget = ISDN_BUDGET_DIAL;
            else if(! strcmp(argv [argp], "charge"))
                  budget.budget = ISDN_BUDGET_CHARGE;
            else if(! strcmp(argv [argp], "online"))
                  budget.budget = ISDN_BUDGET_ONLINE;
            else
                  PARSER_ERROR("wrong budget-type");

            budget.command = ISDN_BUDGET_GET_BUDGET;
            if((ioret = ioctl(fd, IIOCNETBUD, &budget)) < 0) {
                  perror("ioctl failed.");
                  return(ioret);
            }

            /* amount */
            SHIFT_ARGS("amount");
            if(!strcmp(argv [argp], "off")) {
                  budget.amount = -1;
                  budget.period = (time_t)0;
            } else {
                  /* amount */
                  if(read_budget_time(argv [argp], &t) < 0)
                        PARSER_ERROR("wrong amount");
                  budget.amount = t;

                  /* period */
                  SHIFT_ARGS("period");
                  if(read_budget_time(argv [argp], &budget.period) < 0)
                        PARSER_ERROR("wrong period");

                  budget.used = 0;
                  budget.period_started = (time_t)0;
            }

            budget.command = ISDN_BUDGET_SET_BUDGET;
            if((ioret = ioctl(fd, IIOCNETBUD, &budget)) < 0) {
                  perror("ioctl failed.");
                  return(ioret);
            }

            return(args_used);
            break;

      case RESTOREBUDGETS:
            /* interface */
            strncpy(budget.name, id, sizeof(budget.name) - 1);

            while(argp + 1 < argc) {
                  SHIFT_ARGS("saved-budget");
                  if(sscanf(argv [argp], "%d:%d:%ld:%d:%ld%n",
                        &budget.budget, &budget.amount, (long *)&budget.period,
                        &budget.used, (long *)&budget.period_started, &n) != 5 ||
                        n != strlen(argv [argp])) {

                        UNSHIFT_ARGS(1);
                        break;
                  } else {
                        budget.command = ISDN_BUDGET_SET_BUDGET;
                        if((ioret = ioctl(fd, IIOCNETBUD, &budget)) < 0) {
                              perror("ioctl failed.");
                              return(ioret);
                        }
                  }
            }

            return(args_used);
            break;

      default:
            PARSER_ERROR("unknown command");
      }
}


int
read_budget_time(char *str, time_t *period) {
      char  *s = str, base [10], comma [2];
      int   e, n, amount;
      time_t      total = 0;

      while(*s) {
            memset(base, 0, sizeof(base));

            if((e = sscanf(s, "%i%n%[a-zA-Z]%n", &amount, &n, base, &n)) > 0) {
                  s += n;

                  if(*s && sscanf(s, "%[,]%n", comma, &n) > 0)
                        s += n;

                  if(e == 1 || !strcmp(base, "s") || !strcmp(base, "sec"))
                        total += amount;
                  else if(!strcmp(base, "m") || !strcmp(base, "min"))
                        total += (amount * MINUTE);
                  else if(!strcmp(base, "h") || !strcmp(base, "hour"))
                        total += (amount * HOUR);
                  else if(!strcmp(base, "d") || !strcmp(base, "day"))
                        total += (amount * DAY);
                  else if(!strcmp(base, "w") || !strcmp(base, "week"))
                        total += (amount * WEEK);
                  else if(!strcmp(base, "M") || !strcmp(base, "month"))
                        total += (amount * MONTH);
                  else if(!strcmp(base, "y") || !strcmp(base, "year"))
                        total += (amount * YEAR);
                  else
                        return(-1);
            } else
                  return(-1);
      }

      *period = total;
                        
      return(0);
}


char *
write_budget_time(time_t period) {
      static char str [64];
      time_t            rest = period;


      memset(str, 0, sizeof(str));

      if(rest >= YEAR) {
            sprintf(str, "%ldy", rest / YEAR);
            rest %= YEAR;
      }

      if(rest >= MONTH) {
            sprintf(str, "%s%ldM", str, rest / MONTH);
            rest %= MONTH;
      }

      if(rest >= WEEK) {
            sprintf(str, "%s%ldw", str, rest / WEEK);
            rest %= WEEK;
      }

      if(rest >= DAY) {
            sprintf(str, "%s%ldd", str, rest / DAY);
            rest %= DAY;
      }

      if(rest >= HOUR) {
            sprintf(str, "%s%ldh", str, rest / HOUR);
            rest %= HOUR;
      }

      if(rest >= MINUTE) {
            sprintf(str, "%s%ldm", str, rest / MINUTE);
            rest %= MINUTE;
      }

      if(rest > 0 || period == 0)
            sprintf(str, "%s%lds", str, rest);

      return(str);
}


char *
output_time(time_t *t) {
      static char str [64];
      struct tm   *u;


      memset(str, 0, sizeof(str));

      if((u = localtime(t)))
            sprintf(str, "%02d.%02d.%04d, %02d:%02d:%02d",
                  u->tm_mday, u->tm_mon + 1, u->tm_year + 1900,
                  u->tm_hour, u->tm_min, u->tm_sec);

      return(str);
}


int
output_budgets(int fd, char *id, int cmd, int firstarg, int argc, char *argv []) {
      isdn_ioctl_budget budget;
      int               i;


      /* interface */
      strncpy(budget.name, id, sizeof(budget.name) - 1);

      switch(cmd) {
      case SHOWBUDGETS:
            printf("Budgets for interface %s:\n", budget.name);

            printf("\n");
            printf("TYPE    AMOUNT     PERIOD     USED       SINCE\n");

            for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
                  budget.command = ISDN_BUDGET_GET_BUDGET;
                  budget.budget = i;

                  if(ioctl(fd, IIOCNETBUD, &budget) == 0) {
                        switch(i) {
                        case ISDN_BUDGET_DIAL:
                              printf("%-6.6s  ", "dial");
                              if(budget.amount < 0)
                                    printf("off\n");
                              else
                                    printf("%-10d %-10.10s %-10d %s\n",
                                          budget.amount, write_budget_time(budget.period), budget.used,
                                          output_time(&budget.period_started));
                              break;

                        case ISDN_BUDGET_CHARGE:
                              printf("%-6.6s  ", "charge");
                              if(budget.amount < 0)
                                    printf("off\n");
                              else
                                    printf("%-10d %-10.10s %-10d %s\n",
                                          budget.amount, write_budget_time(budget.period), budget.used,
                                          output_time(&budget.period_started));
                              break;

                        case ISDN_BUDGET_ONLINE:
                              printf("%-6.6s  ", "online");
                              if(budget.amount < 0)
                                    printf("off\n");
                              else {
                                    printf("%-10.10s ", write_budget_time(budget.amount));
                                    printf("%-10.10s ", write_budget_time(budget.period));
                                    printf("%-10.10s %s\n", write_budget_time(budget.used),
                                          output_time(&budget.period_started));
                              }
                              break;
                        }
                  } else {
                        perror("ioctl failed");
                  }
            }
            break;

      case SAVEBUDGETS:
            for(i = 0; i < ISDN_BUDGET_NUM_BUDGET; i++) {
                  budget.command = ISDN_BUDGET_GET_BUDGET;
                  budget.budget = i;

                  if(ioctl(fd, IIOCNETBUD, &budget) == 0) {
                        if(i > 0)
                              printf(" ");

                        printf("%d:%d:%ld:%d:%ld",
                              i, budget.amount, budget.period,
                              budget.used, budget.period_started);
                  } else {
                        perror("ioctl failed");
                  }
            }
            printf("\n");
      }

      return(0);
}


char *
defs_budget(char *id) {
      static char r [1024];
      char  *p = r;

      p += sprintf(p, "budget %s dial 10 1min\n", id);
      p += sprintf(p, "budget %s charge 100 1day\n", id);
      p += sprintf(p, "budget %s online 8hour 1day\n", id);

      return(r);
}
#endif

Generated by  Doxygen 1.6.0   Back to index