Annotation of embedaddon/coova-chilli/src/main-query.c, revision 1.1.1.1

1.1       misho       1: /* 
                      2:  * chilli - ChilliSpot.org. A Wireless LAN Access Point Controller.
                      3:  * Copyright (C) 2006 PicoPoint B.V.
                      4:  * Copyright (c) 2006-2007 David Bird <david@coova.com>
                      5:  *
                      6:  * The contents of this file may be used under the terms of the GNU
                      7:  * General Public License Version 2, provided that the above copyright
                      8:  * notice and this permission notice is included in all copies or
                      9:  * substantial portions of the software.
                     10:  * 
                     11:  */
                     12: 
                     13: #include "system.h"
                     14: #include "syserr.h"
                     15: #include "cmdline.h"
                     16: #include "dhcp.h"
                     17: #include "radius.h"
                     18: #include "radius_chillispot.h"
                     19: #include "radius_wispr.h"
                     20: #include "redir.h"
                     21: #include "chilli.h"
                     22: #include "options.h"
                     23: #include "cmdsock.h"
                     24: 
                     25: static int usage(char *program) {
                     26:   fprintf(stderr, "Usage: %s [ -s <socket> ] <command> [<argument>]\n", program);
                     27:   fprintf(stderr, "  socket = full path to UNIX domain socket (e.g. /var/run/chilli.sock)\n");
                     28:   /*  fprintf(stderr, "           TCP socket port, or ip:port, to bind to (e.g. 1999)\n"); */
                     29:   return 1;
                     30: }
                     31: 
                     32: typedef struct _cmd_info {
                     33:   int type;
                     34:   char *command;
                     35:   char *desc;
                     36: } cmd_info;
                     37: 
                     38: static cmd_info commands[] = {
                     39:   { CMDSOCK_LIST,          "list",          NULL },
                     40:   { CMDSOCK_ROUTE,         "route",         NULL },
                     41:   { CMDSOCK_DHCP_LIST,     "dhcp-list",     NULL },
                     42:   { CMDSOCK_DHCP_RELEASE,  "dhcp-release",  NULL },
                     43:   { CMDSOCK_AUTHORIZE,     "authorize",     NULL },
                     44:   { CMDSOCK_DHCP_RELEASE,  "logout",        NULL },
                     45:   { CMDSOCK_DHCP_RELEASE,  "logoff",        NULL },
                     46:   { CMDSOCK_DHCP_DROP,     "drop",          NULL },
                     47:   { CMDSOCK_DHCP_DROP,     "block",         NULL },
                     48:   { 0, NULL, NULL }
                     49: };
                     50: 
                     51: int main(int argc, char **argv) {
                     52:   /*
                     53:    *   chilli_query [ -s <unix-socket> ] <command> [<argument>]
                     54:    *   (or maybe this should get the unix-socket from the config file)
                     55:    */
                     56: 
                     57:   char *cmdsock = DEFCMDSOCK;
                     58:   int s, len;
                     59:   struct sockaddr_un remote;
                     60:   struct cmdsock_request request;
                     61:   char line[1024], *cmd;
                     62:   int argidx = 1;
                     63: 
                     64:   if (argc < 2) return usage(argv[0]);
                     65: 
                     66:   if (*argv[argidx] == '/') {
                     67:     /* for backward support, ignore a unix-socket given as first arg */
                     68:     if (argc < 3) return usage(argv[0]);
                     69:     cmdsock = argv[argidx++];
                     70:   } 
                     71:   
                     72:   memset(&request,0,sizeof(request));
                     73: 
                     74:   while (argidx < argc && *argv[argidx] == '-') {
                     75:     if (!strcmp(argv[argidx], "-s")) {
                     76:       argidx++;
                     77:       if (argidx >= argc) return usage(argv[0]);
                     78:       cmdsock = argv[argidx++];
                     79:     } else if (!strcmp(argv[argidx], "-json")) {
                     80:       request.options |= CMDSOCK_OPT_JSON;
                     81:       argidx++;
                     82:     }
                     83:   }
                     84: 
                     85:   if (argidx >= argc) return usage(argv[0]);
                     86: 
                     87:   cmd = argv[argidx++];
                     88:   for (s = 0; commands[s].command; s++) {
                     89:     if (!strcmp(cmd, commands[s].command)) {
                     90:       request.type = commands[s].type;
                     91:       switch(request.type) {
                     92:       case CMDSOCK_AUTHORIZE:
                     93:        {
                     94:          struct arguments {
                     95:            char *name;
                     96:            int type;    /* 0=string, 1=integer, 2=ip */
                     97:            int length;
                     98:            void *field;
                     99:            char *desc;
                    100:            char *flag;
                    101:            char flagbit;
                    102:          } args[] = {
                    103:            { "ip", 2, 
                    104:              sizeof(request.data.sess.ip),
                    105:              &request.data.sess.ip,
                    106:              "IP of client to authorize",0,0 },
                    107:            { "sessionid", 0, 
                    108:              sizeof(request.data.sess.sessionid),
                    109:              request.data.sess.sessionid,
                    110:              "Session-id to authorize",0,0 },
                    111:            { "username", 0, 
                    112:              sizeof(request.data.sess.username),
                    113:              request.data.sess.username,
                    114:              "Username to use in RADIUS Accounting",0,0 },
                    115:            { "sessiontimeout", 1, 
                    116:              sizeof(request.data.sess.params.sessiontimeout),
                    117:              &request.data.sess.params.sessiontimeout,
                    118:              "Max session time (in seconds)",0,0 },
                    119:            { "maxoctets", 1, 
                    120:              sizeof(request.data.sess.params.maxtotaloctets),
                    121:              &request.data.sess.params.maxtotaloctets,
                    122:              "Max up/down octets (bytes)",0,0 },
                    123:            { "maxbwup", 1, 
                    124:              sizeof(request.data.sess.params.bandwidthmaxup),
                    125:              &request.data.sess.params.bandwidthmaxup,
                    126:              "Max bandwidth up",0,0 },
                    127:            { "maxbwdown", 1, 
                    128:              sizeof(request.data.sess.params.bandwidthmaxdown),
                    129:              &request.data.sess.params.bandwidthmaxdown,
                    130:              "Max bandwidth down",0,0 },
                    131:            { "splash", 0, 
                    132:              sizeof(request.data.sess.params.url),
                    133:              &request.data.sess.params.url,
                    134:              "Set splash page",
                    135:              &request.data.sess.params.flags, REQUIRE_UAM_SPLASH },
                    136:            { "routeidx", 1, 
                    137:              sizeof(request.data.sess.params.routeidx),
                    138:              &request.data.sess.params.routeidx,
                    139:              "Route interface index",  0, 0 },
                    140:            /* more... */
                    141:          };
                    142:          int count = sizeof(args)/sizeof(struct arguments);
                    143:          int pos = argidx;
                    144:          argc -= argidx;
                    145:          while(argc > 0) {
                    146:            int i;
                    147: 
                    148:            for (i=0; i<count; i++) {
                    149: 
                    150:              if (!strcmp(argv[pos],args[i].name)) {
                    151: 
                    152:                if (argc == 1) {
                    153:                  fprintf(stderr, "Argument %s requires a value\n", argv[pos]);
                    154:                  return usage(argv[0]);
                    155:                }
                    156:          
                    157:                if (args[i].flag) {
                    158:                  *(args[i].flag) |=args[i].flagbit;
                    159:                }
                    160: 
                    161:                switch(args[i].type) {
                    162:                case 0:
                    163:                  strncpy(((char *)args[i].field), argv[pos+1], args[i].length-1);
                    164:                  break;
                    165:                case 1:
                    166:                  switch(args[i].length) {
                    167:                  case 1:
                    168:                    *((uint8_t *)args[i].field) = (uint8_t)atoi(argv[pos+1]);
                    169:                    break;
                    170:                  case 2:
                    171:                    *((uint16_t *)args[i].field) = (uint16_t)atoi(argv[pos+1]);
                    172:                    break;
                    173:                  case 4:
                    174:                    *((uint32_t *)args[i].field) = (uint32_t)atoi(argv[pos+1]);
                    175:                    break;
                    176:                  }
                    177:                  break;
                    178:                case 2:
                    179:                  if (!inet_aton(argv[pos+1], ((struct in_addr *)args[i].field))) {
                    180:                    fprintf(stderr, "Invalid IP Address: %s\n", argv[pos+1]);
                    181:                    return usage(argv[0]);
                    182:                  }
                    183:                  break;
                    184:                }
                    185:                break;
                    186:              }
                    187:            }
                    188: 
                    189:            if (i == count) {
                    190:              fprintf(stderr, "Unknown argument: %s\n", argv[pos]);
                    191:              fprintf(stderr, "Use:\n");
                    192:              for (i=0; i<count; i++) {
                    193:                fprintf(stderr, "  %-15s<value>  - type: %-6s - %s\n", 
                    194:                        args[i].name, 
                    195:                        args[i].type == 0 ? "string" :
                    196:                        args[i].type == 1 ? "long" :
                    197:                        args[i].type == 2 ? "int" :
                    198:                        args[i].type == 3 ? "ip" :
                    199:                        "unknown", args[i].desc);
                    200:              }
                    201:              fprintf(stderr, "The ip and/or sessionid is required.\n");
                    202:              return usage(argv[0]);
                    203:            }
                    204: 
                    205:            argc -= 2;
                    206:            pos += 2;
                    207:          }
                    208:        }
                    209:        break;
                    210:       case CMDSOCK_DHCP_DROP:
                    211:       case CMDSOCK_DHCP_RELEASE:
                    212:        {
                    213:          unsigned int temp[PKT_ETH_ALEN];
                    214:          char macstr[RADIUS_ATTR_VLEN];
                    215:          int macstrlen;
                    216:          int i;
                    217: 
                    218:          if (argc < argidx+1) {
                    219:            fprintf(stderr, "%s requires a MAC address argument\n", cmd);
                    220:            return usage(argv[0]);
                    221:          }
                    222:          
                    223:          if ((macstrlen = strlen(argv[argidx])) >= (RADIUS_ATTR_VLEN-1)) {
                    224:            fprintf(stderr, "%s: bad MAC address\n", argv[argidx]);
                    225:            return -1;
                    226:          }
                    227: 
                    228:          memcpy(macstr, argv[argidx], macstrlen);
                    229:          macstr[macstrlen] = 0;
                    230: 
                    231:          for (i=0; i<macstrlen; i++) 
                    232:            if (!isxdigit(macstr[i])) 
                    233:              macstr[i] = 0x20;
                    234: 
                    235:          if (sscanf(macstr, "%2x %2x %2x %2x %2x %2x", 
                    236:                     &temp[0], &temp[1], &temp[2], 
                    237:                     &temp[3], &temp[4], &temp[5]) != 6) {
                    238:            fprintf(stderr, "%s: bad MAC address\n", argv[argidx]);
                    239:            return -1;
                    240:          }
                    241: 
                    242:          for (i = 0; i < PKT_ETH_ALEN; i++) 
                    243:            request.data.mac[i] = temp[i];
                    244: 
                    245:          /* do another switch to pick up param configs for authorize */
                    246:        }
                    247:        break;
                    248:       case CMDSOCK_ROUTE:
                    249:        {
                    250:          unsigned int temp[PKT_ETH_ALEN];
                    251:          char macstr[RADIUS_ATTR_VLEN];
                    252:          int macstrlen;
                    253:          int routeidx;
                    254:          int i;
                    255: 
                    256:          if (argc < argidx + 2) {
                    257:            break;
                    258:          }
                    259:          
                    260:          if ((macstrlen = strlen(argv[argidx])) >= (RADIUS_ATTR_VLEN-1)) {
                    261:            fprintf(stderr, "%s: bad MAC address\n", argv[argidx]);
                    262:            break;
                    263:          }
                    264: 
                    265:          memcpy(macstr, argv[argidx], macstrlen);
                    266:          macstr[macstrlen] = 0;
                    267: 
                    268:          for (i=0; i<macstrlen; i++) 
                    269:            if (!isxdigit(macstr[i])) 
                    270:              macstr[i] = 0x20;
                    271: 
                    272:          if (sscanf(macstr, "%2x %2x %2x %2x %2x %2x", 
                    273:                     &temp[0], &temp[1], &temp[2], 
                    274:                     &temp[3], &temp[4], &temp[5]) != 6) {
                    275:            fprintf(stderr, "%s: bad MAC address\n", argv[argidx]);
                    276:            break;
                    277:          }
                    278: 
                    279:          for (i = 0; i < PKT_ETH_ALEN; i++) 
                    280:            request.data.mac[i] = temp[i];
                    281: 
                    282:          argidx++;
                    283:          request.data.sess.params.routeidx = atoi(argv[argidx]);
                    284: 
                    285:          request.type = CMDSOCK_ROUTE_SET;
                    286: 
                    287:          /* do another switch to pick up param configs for authorize */
                    288:        }
                    289:        break;
                    290:       }
                    291:       break;
                    292:     }
                    293:   }
                    294: 
                    295:   if (!commands[s].command) {
                    296:     fprintf(stderr,"unknown command: %s\n",cmd);
                    297:     exit(1);
                    298:   }
                    299: 
                    300:   if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
                    301:     perror("socket");
                    302:     exit(1);
                    303:   }
                    304: 
                    305:   remote.sun_family = AF_UNIX;
                    306:   strcpy(remote.sun_path, cmdsock);
                    307:   len = strlen(remote.sun_path) + sizeof(remote.sun_family);
                    308:   if (connect(s, (struct sockaddr *)&remote, len) == -1) {
                    309:     perror("connect");
                    310:     exit(1);
                    311:   }
                    312:   
                    313:   if (write(s, &request, sizeof(request)) != sizeof(request)) {
                    314:     perror("write");
                    315:     exit(1);
                    316:   }
                    317: 
                    318:   while((len = read(s, line, sizeof(line)-1)) > 0) 
                    319:     write(1, line, len);
                    320: 
                    321:   if (len < 0) 
                    322:     perror("read");
                    323: 
                    324:   shutdown(s,2);
                    325:   close(s);
                    326:   
                    327:   return 0;
                    328: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>